@glennjong/pixel-window 0.1.1 → 0.1.2

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,60 @@
1
+ # @glennjong/pixel-window
2
+
3
+ 像素風格的 React 視窗元件庫,支援可自訂邊框、顏色與拖曳、縮放。
4
+
5
+ ## 安裝
6
+
7
+ ```bash
8
+ yarn add @glennjong/pixel-window
9
+ # 或
10
+ npm install @glennjong/pixel-window
11
+ ```
12
+
13
+ ## 使用方式
14
+
15
+ ```tsx
16
+ import { PixelWindow, FreePixelWindow } from '@glennjong/pixel-window';
17
+
18
+ function App() {
19
+ return (
20
+ <>
21
+ <PixelWindow pixel={24} stroke="#000" frame="#F0F0F0" background="#F0F0F0">
22
+ <div>內容</div>
23
+ </PixelWindow>
24
+ <FreePixelWindow name="demo" pixel={24} stroke="#000" frame="#F0F0F0" background="#F0F0F0">
25
+ <div>可拖曳視窗</div>
26
+ </FreePixelWindow>
27
+ </>
28
+ );
29
+ }
30
+ ```
31
+
32
+ ## API
33
+
34
+ ### `<PixelWindow />`
35
+ | Prop | Type | Default | 說明 |
36
+ |--------------|----------|-----------|--------------|
37
+ | pixel | number | 160 | 邊框像素大小 |
38
+ | stroke | string | #000 | 邊框顏色 |
39
+ | frame | string | #333 | 框色 |
40
+ | background | string | #DDD | 背景色 |
41
+ | style | object | | 內容區樣式 |
42
+ | children | ReactNode| | 內容 |
43
+
44
+ ### `<FreePixelWindow />`
45
+ | Prop | Type | Default | 說明 |
46
+ |--------------|----------|-----------|------------------|
47
+ | name | string | | 唯一名稱(儲存位置/大小) |
48
+ | pixel | number | 16 | 邊框像素大小 |
49
+ | stroke | string | #000 | 邊框顏色 |
50
+ | frame | string | #333 | 框色 |
51
+ | background | string | #DDD | 背景色 |
52
+ | position | object | {x:100,y:100}| 初始位置 |
53
+ | minWidth | number | 120 | 最小寬度 |
54
+ | minHeight | number | 100 | 最小高度 |
55
+ | style | object | | 內容區樣式 |
56
+ | children | ReactNode| | 內容 |
57
+
58
+ ## 授權
59
+
60
+ MIT License
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/frame.ts","../src/index.tsx"],"sourcesContent":["export * from './index';\nexport * from './frame';\n","export function getFrame({ size, stroke, frame, background }: { size: number; stroke: string; frame: string; background: string }): string {\n\tconst height = size; // Assuming square frames\n\tconst svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{{size}}\" height=\"{{height}}\" viewBox=\"0 0 12 12\"><path fill=\"{{stroke}}\" d=\"M2 0h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9zM1 1h1v1H1z\"/><path fill=\"{{frame}}\" d=\"M2 1h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{stroke}}\" d=\"M10 1h1v1h-1zM0 2h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 2h1v1H1zm1 0h1v1H2z\"/><path fill=\"{{stroke}}\" d=\"M3 2h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{frame}}\" d=\"M9 2h1v1H9zm1 0h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 2h1v1h-1zM0 3h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 3h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 3h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 3h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 3h1v1h-1zM0 4h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 4h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 4h1v1H2zm1 0h1v1H3z\"/><path fill=\"{{background}}\" d=\"M4 4h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7z\"/><path fill=\"{{stroke}}\" d=\"M8 4h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 4h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 4h1v1h-1zM0 5h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 5h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 5h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 5h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 5h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 5h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 5h1v1h-1zM0 6h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 6h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 6h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 6h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 6h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 6h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 6h1v1h-1zM0 7h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 7h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 7h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 7h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 7h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 7h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 7h1v1h-1zM0 8h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 8h1v1H1zm1 0h1v1H2z\"/><path fill=\"{{stroke}}\" d=\"M3 8h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{frame}}\" d=\"M9 8h1v1H9zm1 0h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 8h1v1h-1zM0 9h1v1H0zm1 0h1v1H1z\"/><path fill=\"{{frame}}\" d=\"M2 9h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{stroke}}\" d=\"M10 9h1v1h-1zm-9 1h1v1H1zm1 0h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9zm1 0h1v1h-1zm-8 1h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/></svg>'\n\t\t.replace(/\\{\\{size\\}\\}/g, size.toString())\n\t\t.replace(/\\{\\{height\\}\\}/g, height.toString())\n\t\t.replace(/\\{\\{stroke\\}\\}/g, stroke)\n\t\t.replace(/\\{\\{frame\\}\\}/g, frame)\n\t\t.replace(/\\{\\{background\\}\\}/g, background);\n\n\t// Encode SVG to Base64 safely\n\tconst encodedSvg = encodeURIComponent(svg)\n\t\t.replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)));\n\n\treturn `data:image/svg+xml;base64,${btoa(encodedSvg)}`;\n}\n\nfunction getCheckbox({ size, color }: { size: number; color: string }) {\n\tconst svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{{width}}\" height=\"{{height}}\" viewBox=\"0 0 12 6\"><rect width=\"1\" height=\"1\" x=\"1\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"4\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"7\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"8\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"9\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"10\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"1\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"4\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"7\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"8\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"9\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"10\" y=\"5\" fill=\"{{color}}\"></rect></svg>'\n\t\t.replace(/\\{\\{width\\}\\}/g, (size*2).toString())\n\t\t.replace(/\\{\\{height\\}\\}/g, size.toString())\n\t\t.replace(/\\{\\{color\\}\\}/g, color)\n \n\tconst encodedSvg = encodeURIComponent(svg)\n\t\t.replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)))\n\t\t.replace(/#/g, '%23');\n\n\treturn `data:image/svg+xml;base64,${btoa(encodedSvg)}`;\n\n}\n\nexport const frame = getFrame({\n\tsize: 160,\n\tstroke: '#000',\n\tframe: '#333',\n\tbackground: '#DDD',\n});\n\nexport const checkbox = getCheckbox({\n\tsize: 12,\n\tcolor: '#000',\n});\nexport const checkboxLight = getCheckbox({\n\tsize: 12,\n\tcolor: '#000',\n});\n","import { getFrame } from './frame';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport const PixelWindow = ({\n\tstyle = {},\n\tstroke = '#000',\n\tframe = '#333',\n\tbackground = '#DDD',\n\tpixel = 160,\n\tchildren,\n}: {\n\tstyle?: React.CSSProperties,\n\tpixel?: number,\n\tstroke?: string\n\tframe?: string\n\tbackground?: string\n\tchildren: ReactNode;\n}) => {\n\n\tconst pixelFrame = getFrame({\n\t\tsize: pixel,\n\t\tstroke,\n\t\tframe,\n\t\tbackground,\n\t});\n\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"window\"\n\t\t\tstyle={{\n\t\t\t\twidth: '100%',\n\t\t\t\theight: '100%',\n\t\t\t\tborderImage: `url(${pixelFrame})`,\n\t\t\t\tborderImageSlice: '49% 49% fill',\n\t\t\t\tborderImageWidth: `${pixel}px`,\n\t\t\t}}\n\t\t>\n\t\t\t<div style={{ padding: `${pixel}px`}}>\n\t\t\t\t<div\n\t\t\t\t\tstyle={{ boxSizing: 'border-box', ...style }}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport const FreePixelWindow = ({\n\tname,\n\tchildren,\n\tpixel = 16,\n\tstroke = '#000',\n\tframe = '#333',\n\tbackground = '#DDD',\n\tposition: initialPosition = { x: 100, y: 100 },\n\tstyle,\n\tminWidth = 120,\n\tminHeight = 100,\n}: {\n\tname?: string;\n\tchildren: ReactNode;\n\tpixel?: number;\n\tstroke?: string;\n\tframe?: string;\n\tbackground?: string;\n\tposition?: { x: number; y: number };\n\tstyle?: React.CSSProperties;\n\tminWidth?: number;\n\tminHeight?: number;\n}) => {\n\n\tconst [position, setPosition] = useState(() => {\n\t\tif (name) {\n\t\t\tconst savedPosition = localStorage.getItem(`${name}-position`);\n\t\t\treturn savedPosition ? JSON.parse(savedPosition) : initialPosition;\n\t\t}\n\t\treturn initialPosition;\n\t});\n\n\tconst [size, setSize] = useState(() => {\n\t\tconst savedSize = localStorage.getItem(`${name}-size`);\n\t\treturn savedSize ? JSON.parse(savedSize) : { width: 300, height: 200 };\n\t});\n\n\tconst [isDragging, setIsDragging] = useState(false);\n\tconst [isResizing, setIsResizing] = useState(false);\n\tconst [dragStart, setDragStart] = useState({ x: 0, y: 0 });\n\tconst [resizeStart, setResizeStart] = useState({ width: 0, height: 0, mouseX: 0, mouseY: 0 });\n\n\tuseEffect(() => {\n\t\tif (name) {\n\t\t\tlocalStorage.setItem(`${name}-position`, JSON.stringify(position));\n\t\t\tlocalStorage.setItem(`${name}-size`, JSON.stringify(size));\n\n\t\t}\n\t}, [name, position, size]);\n\n\tconst handleMouseMove = useCallback((e: MouseEvent) => {\n\t\tif (isDragging) {\n\t\t\tsetPosition({\n\t\t\t\tx: e.clientX - dragStart.x,\n\t\t\t\ty: e.clientY - dragStart.y,\n\t\t\t});\n\t\t} else if (isResizing) {\n\t\t\tconst deltaX = e.clientX - resizeStart.mouseX;\n\t\t\tconst deltaY = e.clientY - resizeStart.mouseY;\n\n\t\t\tsetSize({\n\t\t\t\twidth: Math.max(resizeStart.width + deltaX, minWidth),\n\t\t\t\theight: Math.max(resizeStart.height + deltaY, minHeight),\n\t\t\t});\n\t\t}\n\t}, [isDragging, isResizing, dragStart, resizeStart, minWidth, minHeight]);\n\n\tconst handleMouseUp = useCallback(() => {\n\t\tsetIsDragging(false);\n\t\tsetIsResizing(false);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (isDragging || isResizing) {\n\t\t\twindow.addEventListener('mousemove', handleMouseMove);\n\t\t\twindow.addEventListener('mouseup', handleMouseUp);\n\t\t} else {\n\t\t\twindow.removeEventListener('mousemove', handleMouseMove);\n\t\t\twindow.removeEventListener('mouseup', handleMouseUp);\n\t\t}\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('mousemove', handleMouseMove);\n\t\t\twindow.removeEventListener('mouseup', handleMouseUp);\n\t\t};\n\t}, [isDragging, isResizing, handleMouseMove, handleMouseUp]);\n\n\tconst handleMouseDown = (e: React.MouseEvent) => {\n\t\tsetIsDragging(true);\n\t\tsetDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });\n\t};\n\n\tconst handleResizeStart = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tsetIsResizing(true);\n\t\tsetResizeStart({\n\t\t\twidth: size.width,\n\t\t\theight: size.height,\n\t\t\tmouseX: e.clientX,\n\t\t\tmouseY: e.clientY,\n\t\t});\n\t};\n\n\tconst pixelFrame = getFrame({\n\t\tsize: pixel,\n\t\tstroke,\n\t\tframe,\n\t\tbackground,\n\t});\n\n\treturn createPortal(\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: 'absolute',\n\t\t\t\toverflow: 'hidden',\n\t\t\t\tresize: 'none',\n\t\t\t\ttop: position.y,\n\t\t\t\tleft: position.x,\n\t\t\t\twidth: size.width,\n\t\t\t\theight: size.height,\n\t\t\t\tborderImage: `url(${pixelFrame})`,\n\t\t\t\tborderImageSlice: '49% 49% fill',\n\t\t\t\tborderImageWidth: `${pixel}px`,\n\t\t\t}}\n\t\t\tonMouseUp={handleMouseUp}\n\t\t>\n\t\t\t<div \n\t\t\t\tonMouseDown={handleMouseDown}\n\t\t\t\tonMouseUp={handleMouseUp}\n\t\t\t\tstyle={{\n\t\t\t\t\theight: `${pixel}px`,\n\t\t\t\t\tcursor: \"grab\",\n\t\t\t\t\tuserSelect: \"none\"\n\t\t\t\t}}\n\t\t\t></div>\n\t\t\t<div style={{\n\t\t\t\tpadding: `${pixel}px`,\n\t\t\t\tpaddingTop: 0,\n\t\t\t\t...style\n\t\t\t}}>{children}</div>\n\t\t\t<div\n\t\t\t\tonMouseDown={handleResizeStart}\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\twidth: `${pixel}px`,\n\t\t\t\t\theight: `${pixel}px`,\n\t\t\t\t\tcursor: 'se-resize',\n\t\t\t\t\tbottom: 0,\n\t\t\t\t\tright: 0,\n\t\t\t\t}}\n\t\t\t></div>\n\t\t</div>,\n\t\tdocument.body\n\t);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,SAAS,SAAS,EAAE,MAAM,QAAQ,OAAAA,QAAO,WAAW,GAAgF;AAC1I,QAAM,SAAS;AACf,QAAM,MAAM,0vFACV,QAAQ,iBAAiB,KAAK,SAAS,CAAC,EACxC,QAAQ,mBAAmB,OAAO,SAAS,CAAC,EAC5C,QAAQ,mBAAmB,MAAM,EACjC,QAAQ,kBAAkBA,MAAK,EAC/B,QAAQ,uBAAuB,UAAU;AAG3C,QAAM,aAAa,mBAAmB,GAAG,EACvC,QAAQ,mBAAmB,CAAC,GAAG,OAAO,OAAO,aAAa,SAAS,IAAI,EAAE,CAAC,CAAC;AAE7E,SAAO,6BAA6B,KAAK,UAAU,CAAC;AACrD;AAEA,SAAS,YAAY,EAAE,MAAM,MAAM,GAAoC;AACtE,QAAM,MAAM,40EACV,QAAQ,mBAAmB,OAAK,GAAG,SAAS,CAAC,EAC7C,QAAQ,mBAAmB,KAAK,SAAS,CAAC,EAC1C,QAAQ,kBAAkB,KAAK;AAEjC,QAAM,aAAa,mBAAmB,GAAG,EACvC,QAAQ,mBAAmB,CAAC,GAAG,OAAO,OAAO,aAAa,SAAS,IAAI,EAAE,CAAC,CAAC,EAC3E,QAAQ,MAAM,KAAK;AAErB,SAAO,6BAA6B,KAAK,UAAU,CAAC;AAErD;AAEO,IAAM,QAAQ,SAAS;AAAA,EAC7B,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,YAAY;AACb,CAAC;AAEM,IAAM,WAAW,YAAY;AAAA,EACnC,MAAM;AAAA,EACN,OAAO;AACR,CAAC;AACM,IAAM,gBAAgB,YAAY;AAAA,EACxC,MAAM;AAAA,EACN,OAAO;AACR,CAAC;;;AC3CD,mBAAiE;AACjE,uBAA6B;AAsCzB;AApCG,IAAM,cAAc,CAAC;AAAA,EAC3B,QAAQ,CAAC;AAAA,EACT,SAAS;AAAA,EACT,OAAAC,SAAQ;AAAA,EACR,aAAa;AAAA,EACb,QAAQ;AAAA,EACR;AACD,MAOM;AAEL,QAAM,aAAa,SAAS;AAAA,IAC3B,MAAM;AAAA,IACN;AAAA,IACA,OAAAA;AAAA,IACA;AAAA,EACD,CAAC;AAGD,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,OAAO;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,aAAa,OAAO,UAAU;AAAA,QAC9B,kBAAkB;AAAA,QAClB,kBAAkB,GAAG,KAAK;AAAA,MAC3B;AAAA,MAEA,sDAAC,SAAI,OAAO,EAAE,SAAS,GAAG,KAAK,KAAI,GAClC;AAAA,QAAC;AAAA;AAAA,UACA,OAAO,EAAE,WAAW,cAAc,GAAG,MAAM;AAAA,UAE1C;AAAA;AAAA,MACF,GACD;AAAA;AAAA,EACD;AAEF;AAEO,IAAM,kBAAkB,CAAC;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,OAAAA,SAAQ;AAAA,EACR,aAAa;AAAA,EACb,UAAU,kBAAkB,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,EAC7C;AAAA,EACA,WAAW;AAAA,EACX,YAAY;AACb,MAWM;AAEL,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAS,MAAM;AAC9C,QAAI,MAAM;AACT,YAAM,gBAAgB,aAAa,QAAQ,GAAG,IAAI,WAAW;AAC7D,aAAO,gBAAgB,KAAK,MAAM,aAAa,IAAI;AAAA,IACpD;AACA,WAAO;AAAA,EACR,CAAC;AAED,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,MAAM;AACtC,UAAM,YAAY,aAAa,QAAQ,GAAG,IAAI,OAAO;AACrD,WAAO,YAAY,KAAK,MAAM,SAAS,IAAI,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,EACtE,CAAC;AAED,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAS,KAAK;AAClD,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAS,KAAK;AAClD,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAS,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AACzD,QAAM,CAAC,aAAa,cAAc,QAAI,uBAAS,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EAAE,CAAC;AAE5F,8BAAU,MAAM;AACf,QAAI,MAAM;AACT,mBAAa,QAAQ,GAAG,IAAI,aAAa,KAAK,UAAU,QAAQ,CAAC;AACjE,mBAAa,QAAQ,GAAG,IAAI,SAAS,KAAK,UAAU,IAAI,CAAC;AAAA,IAE1D;AAAA,EACD,GAAG,CAAC,MAAM,UAAU,IAAI,CAAC;AAEzB,QAAM,sBAAkB,0BAAY,CAAC,MAAkB;AACtD,QAAI,YAAY;AACf,kBAAY;AAAA,QACX,GAAG,EAAE,UAAU,UAAU;AAAA,QACzB,GAAG,EAAE,UAAU,UAAU;AAAA,MAC1B,CAAC;AAAA,IACF,WAAW,YAAY;AACtB,YAAM,SAAS,EAAE,UAAU,YAAY;AACvC,YAAM,SAAS,EAAE,UAAU,YAAY;AAEvC,cAAQ;AAAA,QACP,OAAO,KAAK,IAAI,YAAY,QAAQ,QAAQ,QAAQ;AAAA,QACpD,QAAQ,KAAK,IAAI,YAAY,SAAS,QAAQ,SAAS;AAAA,MACxD,CAAC;AAAA,IACF;AAAA,EACD,GAAG,CAAC,YAAY,YAAY,WAAW,aAAa,UAAU,SAAS,CAAC;AAExE,QAAM,oBAAgB,0BAAY,MAAM;AACvC,kBAAc,KAAK;AACnB,kBAAc,KAAK;AAAA,EACpB,GAAG,CAAC,CAAC;AAEL,8BAAU,MAAM;AACf,QAAI,cAAc,YAAY;AAC7B,aAAO,iBAAiB,aAAa,eAAe;AACpD,aAAO,iBAAiB,WAAW,aAAa;AAAA,IACjD,OAAO;AACN,aAAO,oBAAoB,aAAa,eAAe;AACvD,aAAO,oBAAoB,WAAW,aAAa;AAAA,IACpD;AAEA,WAAO,MAAM;AACZ,aAAO,oBAAoB,aAAa,eAAe;AACvD,aAAO,oBAAoB,WAAW,aAAa;AAAA,IACpD;AAAA,EACD,GAAG,CAAC,YAAY,YAAY,iBAAiB,aAAa,CAAC;AAE3D,QAAM,kBAAkB,CAAC,MAAwB;AAChD,kBAAc,IAAI;AAClB,iBAAa,EAAE,GAAG,EAAE,UAAU,SAAS,GAAG,GAAG,EAAE,UAAU,SAAS,EAAE,CAAC;AAAA,EACtE;AAEA,QAAM,oBAAoB,CAAC,MAAwB;AAClD,MAAE,gBAAgB;AAClB,kBAAc,IAAI;AAClB,mBAAe;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,QAAQ,EAAE;AAAA,MACV,QAAQ,EAAE;AAAA,IACX,CAAC;AAAA,EACF;AAEA,QAAM,aAAa,SAAS;AAAA,IAC3B,MAAM;AAAA,IACN;AAAA,IACA,OAAAA;AAAA,IACA;AAAA,EACD,CAAC;AAED,aAAO;AAAA,IACN;AAAA,MAAC;AAAA;AAAA,QACA,OAAO;AAAA,UACN,UAAU;AAAA,UACV,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,KAAK,SAAS;AAAA,UACd,MAAM,SAAS;AAAA,UACf,OAAO,KAAK;AAAA,UACZ,QAAQ,KAAK;AAAA,UACb,aAAa,OAAO,UAAU;AAAA,UAC9B,kBAAkB;AAAA,UAClB,kBAAkB,GAAG,KAAK;AAAA,QAC3B;AAAA,QACA,WAAW;AAAA,QAEX;AAAA;AAAA,YAAC;AAAA;AAAA,cACA,aAAa;AAAA,cACb,WAAW;AAAA,cACX,OAAO;AAAA,gBACN,QAAQ,GAAG,KAAK;AAAA,gBAChB,QAAQ;AAAA,gBACR,YAAY;AAAA,cACb;AAAA;AAAA,UACA;AAAA,UACD,4CAAC,SAAI,OAAO;AAAA,YACX,SAAS,GAAG,KAAK;AAAA,YACjB,YAAY;AAAA,YACZ,GAAG;AAAA,UACJ,GAAI,UAAS;AAAA,UACb;AAAA,YAAC;AAAA;AAAA,cACA,aAAa;AAAA,cACb,OAAO;AAAA,gBACN,UAAU;AAAA,gBACV,OAAO,GAAG,KAAK;AAAA,gBACf,QAAQ,GAAG,KAAK;AAAA,gBAChB,QAAQ;AAAA,gBACR,QAAQ;AAAA,gBACR,OAAO;AAAA,cACR;AAAA;AAAA,UACA;AAAA;AAAA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,EACV;AACD;","names":["frame","frame"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/frame.ts","../src/index.tsx"],"sourcesContent":["export * from './index';\nexport * from './frame';\n","export function getFrame({ size, stroke, frame, background }: { size: number; stroke: string; frame: string; background: string }): string {\n const height = size; // Assuming square frames\n const svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{{size}}\" height=\"{{height}}\" viewBox=\"0 0 12 12\"><path fill=\"{{stroke}}\" d=\"M2 0h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9zM1 1h1v1H1z\"/><path fill=\"{{frame}}\" d=\"M2 1h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{stroke}}\" d=\"M10 1h1v1h-1zM0 2h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 2h1v1H1zm1 0h1v1H2z\"/><path fill=\"{{stroke}}\" d=\"M3 2h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{frame}}\" d=\"M9 2h1v1H9zm1 0h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 2h1v1h-1zM0 3h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 3h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 3h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 3h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 3h1v1h-1zM0 4h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 4h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 4h1v1H2zm1 0h1v1H3z\"/><path fill=\"{{background}}\" d=\"M4 4h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7z\"/><path fill=\"{{stroke}}\" d=\"M8 4h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 4h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 4h1v1h-1zM0 5h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 5h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 5h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 5h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 5h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 5h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 5h1v1h-1zM0 6h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 6h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 6h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 6h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 6h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 6h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 6h1v1h-1zM0 7h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 7h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 7h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 7h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 7h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 7h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 7h1v1h-1zM0 8h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 8h1v1H1zm1 0h1v1H2z\"/><path fill=\"{{stroke}}\" d=\"M3 8h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{frame}}\" d=\"M9 8h1v1H9zm1 0h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 8h1v1h-1zM0 9h1v1H0zm1 0h1v1H1z\"/><path fill=\"{{frame}}\" d=\"M2 9h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{stroke}}\" d=\"M10 9h1v1h-1zm-9 1h1v1H1zm1 0h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9zm1 0h1v1h-1zm-8 1h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/></svg>'\n .replace(/\\{\\{size\\}\\}/g, size.toString())\n .replace(/\\{\\{height\\}\\}/g, height.toString())\n .replace(/\\{\\{stroke\\}\\}/g, stroke)\n .replace(/\\{\\{frame\\}\\}/g, frame)\n .replace(/\\{\\{background\\}\\}/g, background);\n\n // Encode SVG to Base64 safely\n const encodedSvg = encodeURIComponent(svg)\n .replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)));\n\n return `data:image/svg+xml;base64,${btoa(encodedSvg)}`;\n}\n\nfunction getCheckbox({ size, color }: { size: number; color: string }) {\n const svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{{width}}\" height=\"{{height}}\" viewBox=\"0 0 12 6\"><rect width=\"1\" height=\"1\" x=\"1\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"4\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"7\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"8\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"9\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"10\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"1\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"4\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"7\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"8\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"9\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"10\" y=\"5\" fill=\"{{color}}\"></rect></svg>'\n .replace(/\\{\\{width\\}\\}/g, (size*2).toString())\n .replace(/\\{\\{height\\}\\}/g, size.toString())\n .replace(/\\{\\{color\\}\\}/g, color)\n \n const encodedSvg = encodeURIComponent(svg)\n .replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)))\n .replace(/#/g, '%23');\n\n return `data:image/svg+xml;base64,${btoa(encodedSvg)}`;\n\n}\n\nexport const frame = getFrame({\n size: 160,\n stroke: '#000',\n frame: '#333',\n background: '#DDD',\n});\n\nexport const checkbox = getCheckbox({\n size: 12,\n color: '#000',\n});\nexport const checkboxLight = getCheckbox({\n size: 12,\n color: '#000',\n});\n","import { getFrame } from './frame';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport const PixelWindow = ({\n style = {},\n stroke = '#000',\n frame = '#333',\n background = '#DDD',\n pixel = 160,\n children,\n}: {\n style?: React.CSSProperties,\n pixel?: number,\n stroke?: string\n frame?: string\n background?: string\n children: ReactNode;\n}) => {\n\n const pixelFrame = getFrame({\n size: pixel,\n stroke,\n frame,\n background,\n });\n\n\n return (\n <div\n className=\"window\"\n style={{\n width: '100%',\n height: '100%',\n borderImage: `url(${pixelFrame})`,\n borderImageSlice: '49% 49% fill',\n borderImageWidth: `${pixel}px`,\n }}\n >\n <div style={{ padding: `${pixel}px`}}>\n <div\n style={{ boxSizing: 'border-box', ...style }}\n >\n {children}\n </div>\n </div>\n </div>\n );\n};\n\nexport const FreePixelWindow = ({\n name,\n children,\n pixel = 16,\n stroke = '#000',\n frame = '#333',\n background = '#DDD',\n position: initialPosition = { x: 100, y: 100 },\n style,\n minWidth = 120,\n minHeight = 100,\n}: {\n name?: string;\n children: ReactNode;\n pixel?: number;\n stroke?: string;\n frame?: string;\n background?: string;\n position?: { x: number; y: number };\n style?: React.CSSProperties;\n minWidth?: number;\n minHeight?: number;\n}) => {\n\n const [position, setPosition] = useState(() => {\n if (name) {\n const savedPosition = localStorage.getItem(`${name}-position`);\n return savedPosition ? JSON.parse(savedPosition) : initialPosition;\n }\n return initialPosition;\n });\n\n const [size, setSize] = useState(() => {\n const savedSize = localStorage.getItem(`${name}-size`);\n return savedSize ? JSON.parse(savedSize) : { width: 300, height: 200 };\n });\n\n const [isDragging, setIsDragging] = useState(false);\n const [isResizing, setIsResizing] = useState(false);\n const [dragStart, setDragStart] = useState({ x: 0, y: 0 });\n const [resizeStart, setResizeStart] = useState({ width: 0, height: 0, mouseX: 0, mouseY: 0 });\n\n useEffect(() => {\n if (name) {\n localStorage.setItem(`${name}-position`, JSON.stringify(position));\n localStorage.setItem(`${name}-size`, JSON.stringify(size));\n\n }\n }, [name, position, size]);\n\n const handleMouseMove = useCallback((e: MouseEvent) => {\n if (isDragging) {\n setPosition({\n x: e.clientX - dragStart.x,\n y: e.clientY - dragStart.y,\n });\n } else if (isResizing) {\n const deltaX = e.clientX - resizeStart.mouseX;\n const deltaY = e.clientY - resizeStart.mouseY;\n\n setSize({\n width: Math.max(resizeStart.width + deltaX, minWidth),\n height: Math.max(resizeStart.height + deltaY, minHeight),\n });\n }\n }, [isDragging, isResizing, dragStart, resizeStart, minWidth, minHeight]);\n\n const handleMouseUp = useCallback(() => {\n setIsDragging(false);\n setIsResizing(false);\n }, []);\n\n useEffect(() => {\n if (isDragging || isResizing) {\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n } else {\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n }\n\n return () => {\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n }, [isDragging, isResizing, handleMouseMove, handleMouseUp]);\n\n const handleMouseDown = (e: React.MouseEvent) => {\n setIsDragging(true);\n setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });\n };\n\n const handleResizeStart = (e: React.MouseEvent) => {\n e.stopPropagation();\n setIsResizing(true);\n setResizeStart({\n width: size.width,\n height: size.height,\n mouseX: e.clientX,\n mouseY: e.clientY,\n });\n };\n\n const pixelFrame = getFrame({\n size: pixel,\n stroke,\n frame,\n background,\n });\n\n return createPortal(\n <div\n style={{\n position: 'absolute',\n overflow: 'hidden',\n resize: 'none',\n top: position.y,\n left: position.x,\n width: size.width,\n height: size.height,\n borderImage: `url(${pixelFrame})`,\n borderImageSlice: '49% 49% fill',\n borderImageWidth: `${pixel}px`,\n }}\n onMouseUp={handleMouseUp}\n >\n <div \n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n style={{\n height: `${pixel}px`,\n cursor: \"grab\",\n userSelect: \"none\"\n }}\n ></div>\n <div style={{\n padding: `${pixel}px`,\n paddingTop: 0,\n ...style\n }}>{children}</div>\n <div\n onMouseDown={handleResizeStart}\n style={{\n position: 'absolute',\n width: `${pixel}px`,\n height: `${pixel}px`,\n cursor: 'se-resize',\n bottom: 0,\n right: 0,\n }}\n ></div>\n </div>,\n document.body\n );\n};\n"],"mappings":"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","names":["frame","frame"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/frame.ts","../src/index.tsx"],"sourcesContent":["export function getFrame({ size, stroke, frame, background }: { size: number; stroke: string; frame: string; background: string }): string {\n\tconst height = size; // Assuming square frames\n\tconst svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{{size}}\" height=\"{{height}}\" viewBox=\"0 0 12 12\"><path fill=\"{{stroke}}\" d=\"M2 0h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9zM1 1h1v1H1z\"/><path fill=\"{{frame}}\" d=\"M2 1h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{stroke}}\" d=\"M10 1h1v1h-1zM0 2h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 2h1v1H1zm1 0h1v1H2z\"/><path fill=\"{{stroke}}\" d=\"M3 2h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{frame}}\" d=\"M9 2h1v1H9zm1 0h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 2h1v1h-1zM0 3h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 3h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 3h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 3h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 3h1v1h-1zM0 4h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 4h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 4h1v1H2zm1 0h1v1H3z\"/><path fill=\"{{background}}\" d=\"M4 4h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7z\"/><path fill=\"{{stroke}}\" d=\"M8 4h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 4h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 4h1v1h-1zM0 5h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 5h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 5h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 5h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 5h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 5h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 5h1v1h-1zM0 6h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 6h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 6h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 6h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 6h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 6h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 6h1v1h-1zM0 7h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 7h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 7h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 7h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 7h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 7h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 7h1v1h-1zM0 8h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 8h1v1H1zm1 0h1v1H2z\"/><path fill=\"{{stroke}}\" d=\"M3 8h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{frame}}\" d=\"M9 8h1v1H9zm1 0h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 8h1v1h-1zM0 9h1v1H0zm1 0h1v1H1z\"/><path fill=\"{{frame}}\" d=\"M2 9h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{stroke}}\" d=\"M10 9h1v1h-1zm-9 1h1v1H1zm1 0h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9zm1 0h1v1h-1zm-8 1h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/></svg>'\n\t\t.replace(/\\{\\{size\\}\\}/g, size.toString())\n\t\t.replace(/\\{\\{height\\}\\}/g, height.toString())\n\t\t.replace(/\\{\\{stroke\\}\\}/g, stroke)\n\t\t.replace(/\\{\\{frame\\}\\}/g, frame)\n\t\t.replace(/\\{\\{background\\}\\}/g, background);\n\n\t// Encode SVG to Base64 safely\n\tconst encodedSvg = encodeURIComponent(svg)\n\t\t.replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)));\n\n\treturn `data:image/svg+xml;base64,${btoa(encodedSvg)}`;\n}\n\nfunction getCheckbox({ size, color }: { size: number; color: string }) {\n\tconst svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{{width}}\" height=\"{{height}}\" viewBox=\"0 0 12 6\"><rect width=\"1\" height=\"1\" x=\"1\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"4\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"7\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"8\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"9\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"10\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"1\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"4\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"7\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"8\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"9\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"10\" y=\"5\" fill=\"{{color}}\"></rect></svg>'\n\t\t.replace(/\\{\\{width\\}\\}/g, (size*2).toString())\n\t\t.replace(/\\{\\{height\\}\\}/g, size.toString())\n\t\t.replace(/\\{\\{color\\}\\}/g, color)\n \n\tconst encodedSvg = encodeURIComponent(svg)\n\t\t.replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)))\n\t\t.replace(/#/g, '%23');\n\n\treturn `data:image/svg+xml;base64,${btoa(encodedSvg)}`;\n\n}\n\nexport const frame = getFrame({\n\tsize: 160,\n\tstroke: '#000',\n\tframe: '#333',\n\tbackground: '#DDD',\n});\n\nexport const checkbox = getCheckbox({\n\tsize: 12,\n\tcolor: '#000',\n});\nexport const checkboxLight = getCheckbox({\n\tsize: 12,\n\tcolor: '#000',\n});\n","import { getFrame } from './frame';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport const PixelWindow = ({\n\tstyle = {},\n\tstroke = '#000',\n\tframe = '#333',\n\tbackground = '#DDD',\n\tpixel = 160,\n\tchildren,\n}: {\n\tstyle?: React.CSSProperties,\n\tpixel?: number,\n\tstroke?: string\n\tframe?: string\n\tbackground?: string\n\tchildren: ReactNode;\n}) => {\n\n\tconst pixelFrame = getFrame({\n\t\tsize: pixel,\n\t\tstroke,\n\t\tframe,\n\t\tbackground,\n\t});\n\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"window\"\n\t\t\tstyle={{\n\t\t\t\twidth: '100%',\n\t\t\t\theight: '100%',\n\t\t\t\tborderImage: `url(${pixelFrame})`,\n\t\t\t\tborderImageSlice: '49% 49% fill',\n\t\t\t\tborderImageWidth: `${pixel}px`,\n\t\t\t}}\n\t\t>\n\t\t\t<div style={{ padding: `${pixel}px`}}>\n\t\t\t\t<div\n\t\t\t\t\tstyle={{ boxSizing: 'border-box', ...style }}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport const FreePixelWindow = ({\n\tname,\n\tchildren,\n\tpixel = 16,\n\tstroke = '#000',\n\tframe = '#333',\n\tbackground = '#DDD',\n\tposition: initialPosition = { x: 100, y: 100 },\n\tstyle,\n\tminWidth = 120,\n\tminHeight = 100,\n}: {\n\tname?: string;\n\tchildren: ReactNode;\n\tpixel?: number;\n\tstroke?: string;\n\tframe?: string;\n\tbackground?: string;\n\tposition?: { x: number; y: number };\n\tstyle?: React.CSSProperties;\n\tminWidth?: number;\n\tminHeight?: number;\n}) => {\n\n\tconst [position, setPosition] = useState(() => {\n\t\tif (name) {\n\t\t\tconst savedPosition = localStorage.getItem(`${name}-position`);\n\t\t\treturn savedPosition ? JSON.parse(savedPosition) : initialPosition;\n\t\t}\n\t\treturn initialPosition;\n\t});\n\n\tconst [size, setSize] = useState(() => {\n\t\tconst savedSize = localStorage.getItem(`${name}-size`);\n\t\treturn savedSize ? JSON.parse(savedSize) : { width: 300, height: 200 };\n\t});\n\n\tconst [isDragging, setIsDragging] = useState(false);\n\tconst [isResizing, setIsResizing] = useState(false);\n\tconst [dragStart, setDragStart] = useState({ x: 0, y: 0 });\n\tconst [resizeStart, setResizeStart] = useState({ width: 0, height: 0, mouseX: 0, mouseY: 0 });\n\n\tuseEffect(() => {\n\t\tif (name) {\n\t\t\tlocalStorage.setItem(`${name}-position`, JSON.stringify(position));\n\t\t\tlocalStorage.setItem(`${name}-size`, JSON.stringify(size));\n\n\t\t}\n\t}, [name, position, size]);\n\n\tconst handleMouseMove = useCallback((e: MouseEvent) => {\n\t\tif (isDragging) {\n\t\t\tsetPosition({\n\t\t\t\tx: e.clientX - dragStart.x,\n\t\t\t\ty: e.clientY - dragStart.y,\n\t\t\t});\n\t\t} else if (isResizing) {\n\t\t\tconst deltaX = e.clientX - resizeStart.mouseX;\n\t\t\tconst deltaY = e.clientY - resizeStart.mouseY;\n\n\t\t\tsetSize({\n\t\t\t\twidth: Math.max(resizeStart.width + deltaX, minWidth),\n\t\t\t\theight: Math.max(resizeStart.height + deltaY, minHeight),\n\t\t\t});\n\t\t}\n\t}, [isDragging, isResizing, dragStart, resizeStart, minWidth, minHeight]);\n\n\tconst handleMouseUp = useCallback(() => {\n\t\tsetIsDragging(false);\n\t\tsetIsResizing(false);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (isDragging || isResizing) {\n\t\t\twindow.addEventListener('mousemove', handleMouseMove);\n\t\t\twindow.addEventListener('mouseup', handleMouseUp);\n\t\t} else {\n\t\t\twindow.removeEventListener('mousemove', handleMouseMove);\n\t\t\twindow.removeEventListener('mouseup', handleMouseUp);\n\t\t}\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('mousemove', handleMouseMove);\n\t\t\twindow.removeEventListener('mouseup', handleMouseUp);\n\t\t};\n\t}, [isDragging, isResizing, handleMouseMove, handleMouseUp]);\n\n\tconst handleMouseDown = (e: React.MouseEvent) => {\n\t\tsetIsDragging(true);\n\t\tsetDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });\n\t};\n\n\tconst handleResizeStart = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t\tsetIsResizing(true);\n\t\tsetResizeStart({\n\t\t\twidth: size.width,\n\t\t\theight: size.height,\n\t\t\tmouseX: e.clientX,\n\t\t\tmouseY: e.clientY,\n\t\t});\n\t};\n\n\tconst pixelFrame = getFrame({\n\t\tsize: pixel,\n\t\tstroke,\n\t\tframe,\n\t\tbackground,\n\t});\n\n\treturn createPortal(\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: 'absolute',\n\t\t\t\toverflow: 'hidden',\n\t\t\t\tresize: 'none',\n\t\t\t\ttop: position.y,\n\t\t\t\tleft: position.x,\n\t\t\t\twidth: size.width,\n\t\t\t\theight: size.height,\n\t\t\t\tborderImage: `url(${pixelFrame})`,\n\t\t\t\tborderImageSlice: '49% 49% fill',\n\t\t\t\tborderImageWidth: `${pixel}px`,\n\t\t\t}}\n\t\t\tonMouseUp={handleMouseUp}\n\t\t>\n\t\t\t<div \n\t\t\t\tonMouseDown={handleMouseDown}\n\t\t\t\tonMouseUp={handleMouseUp}\n\t\t\t\tstyle={{\n\t\t\t\t\theight: `${pixel}px`,\n\t\t\t\t\tcursor: \"grab\",\n\t\t\t\t\tuserSelect: \"none\"\n\t\t\t\t}}\n\t\t\t></div>\n\t\t\t<div style={{\n\t\t\t\tpadding: `${pixel}px`,\n\t\t\t\tpaddingTop: 0,\n\t\t\t\t...style\n\t\t\t}}>{children}</div>\n\t\t\t<div\n\t\t\t\tonMouseDown={handleResizeStart}\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\twidth: `${pixel}px`,\n\t\t\t\t\theight: `${pixel}px`,\n\t\t\t\t\tcursor: 'se-resize',\n\t\t\t\t\tbottom: 0,\n\t\t\t\t\tright: 0,\n\t\t\t\t}}\n\t\t\t></div>\n\t\t</div>,\n\t\tdocument.body\n\t);\n};\n"],"mappings":"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","names":["frame","frame"]}
1
+ {"version":3,"sources":["../src/frame.ts","../src/index.tsx"],"sourcesContent":["export function getFrame({ size, stroke, frame, background }: { size: number; stroke: string; frame: string; background: string }): string {\n const height = size; // Assuming square frames\n const svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{{size}}\" height=\"{{height}}\" viewBox=\"0 0 12 12\"><path fill=\"{{stroke}}\" d=\"M2 0h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9zM1 1h1v1H1z\"/><path fill=\"{{frame}}\" d=\"M2 1h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{stroke}}\" d=\"M10 1h1v1h-1zM0 2h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 2h1v1H1zm1 0h1v1H2z\"/><path fill=\"{{stroke}}\" d=\"M3 2h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{frame}}\" d=\"M9 2h1v1H9zm1 0h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 2h1v1h-1zM0 3h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 3h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 3h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 3h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 3h1v1h-1zM0 4h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 4h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 4h1v1H2zm1 0h1v1H3z\"/><path fill=\"{{background}}\" d=\"M4 4h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7z\"/><path fill=\"{{stroke}}\" d=\"M8 4h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 4h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 4h1v1h-1zM0 5h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 5h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 5h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 5h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 5h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 5h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 5h1v1h-1zM0 6h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 6h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 6h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 6h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 6h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 6h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 6h1v1h-1zM0 7h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 7h1v1H1z\"/><path fill=\"{{stroke}}\" d=\"M2 7h1v1H2z\"/><path fill=\"{{background}}\" d=\"M3 7h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{stroke}}\" d=\"M9 7h1v1H9z\"/><path fill=\"{{frame}}\" d=\"M10 7h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 7h1v1h-1zM0 8h1v1H0z\"/><path fill=\"{{frame}}\" d=\"M1 8h1v1H1zm1 0h1v1H2z\"/><path fill=\"{{stroke}}\" d=\"M3 8h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8z\"/><path fill=\"{{frame}}\" d=\"M9 8h1v1H9zm1 0h1v1h-1z\"/><path fill=\"{{stroke}}\" d=\"M11 8h1v1h-1zM0 9h1v1H0zm1 0h1v1H1z\"/><path fill=\"{{frame}}\" d=\"M2 9h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/><path fill=\"{{stroke}}\" d=\"M10 9h1v1h-1zm-9 1h1v1H1zm1 0h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9zm1 0h1v1h-1zm-8 1h1v1H2zm1 0h1v1H3zm1 0h1v1H4zm1 0h1v1H5zm1 0h1v1H6zm1 0h1v1H7zm1 0h1v1H8zm1 0h1v1H9z\"/></svg>'\n .replace(/\\{\\{size\\}\\}/g, size.toString())\n .replace(/\\{\\{height\\}\\}/g, height.toString())\n .replace(/\\{\\{stroke\\}\\}/g, stroke)\n .replace(/\\{\\{frame\\}\\}/g, frame)\n .replace(/\\{\\{background\\}\\}/g, background);\n\n // Encode SVG to Base64 safely\n const encodedSvg = encodeURIComponent(svg)\n .replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)));\n\n return `data:image/svg+xml;base64,${btoa(encodedSvg)}`;\n}\n\nfunction getCheckbox({ size, color }: { size: number; color: string }) {\n const svg = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"{{width}}\" height=\"{{height}}\" viewBox=\"0 0 12 6\"><rect width=\"1\" height=\"1\" x=\"1\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"4\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"7\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"8\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"9\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"10\" y=\"0\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"1\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"2\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"3\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"0\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"5\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"6\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"11\" y=\"4\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"1\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"2\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"3\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"4\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"7\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"8\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"9\" y=\"5\" fill=\"{{color}}\"></rect><rect width=\"1\" height=\"1\" x=\"10\" y=\"5\" fill=\"{{color}}\"></rect></svg>'\n .replace(/\\{\\{width\\}\\}/g, (size*2).toString())\n .replace(/\\{\\{height\\}\\}/g, size.toString())\n .replace(/\\{\\{color\\}\\}/g, color)\n \n const encodedSvg = encodeURIComponent(svg)\n .replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)))\n .replace(/#/g, '%23');\n\n return `data:image/svg+xml;base64,${btoa(encodedSvg)}`;\n\n}\n\nexport const frame = getFrame({\n size: 160,\n stroke: '#000',\n frame: '#333',\n background: '#DDD',\n});\n\nexport const checkbox = getCheckbox({\n size: 12,\n color: '#000',\n});\nexport const checkboxLight = getCheckbox({\n size: 12,\n color: '#000',\n});\n","import { getFrame } from './frame';\nimport { useCallback, useEffect, useState, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport const PixelWindow = ({\n style = {},\n stroke = '#000',\n frame = '#333',\n background = '#DDD',\n pixel = 160,\n children,\n}: {\n style?: React.CSSProperties,\n pixel?: number,\n stroke?: string\n frame?: string\n background?: string\n children: ReactNode;\n}) => {\n\n const pixelFrame = getFrame({\n size: pixel,\n stroke,\n frame,\n background,\n });\n\n\n return (\n <div\n className=\"window\"\n style={{\n width: '100%',\n height: '100%',\n borderImage: `url(${pixelFrame})`,\n borderImageSlice: '49% 49% fill',\n borderImageWidth: `${pixel}px`,\n }}\n >\n <div style={{ padding: `${pixel}px`}}>\n <div\n style={{ boxSizing: 'border-box', ...style }}\n >\n {children}\n </div>\n </div>\n </div>\n );\n};\n\nexport const FreePixelWindow = ({\n name,\n children,\n pixel = 16,\n stroke = '#000',\n frame = '#333',\n background = '#DDD',\n position: initialPosition = { x: 100, y: 100 },\n style,\n minWidth = 120,\n minHeight = 100,\n}: {\n name?: string;\n children: ReactNode;\n pixel?: number;\n stroke?: string;\n frame?: string;\n background?: string;\n position?: { x: number; y: number };\n style?: React.CSSProperties;\n minWidth?: number;\n minHeight?: number;\n}) => {\n\n const [position, setPosition] = useState(() => {\n if (name) {\n const savedPosition = localStorage.getItem(`${name}-position`);\n return savedPosition ? JSON.parse(savedPosition) : initialPosition;\n }\n return initialPosition;\n });\n\n const [size, setSize] = useState(() => {\n const savedSize = localStorage.getItem(`${name}-size`);\n return savedSize ? JSON.parse(savedSize) : { width: 300, height: 200 };\n });\n\n const [isDragging, setIsDragging] = useState(false);\n const [isResizing, setIsResizing] = useState(false);\n const [dragStart, setDragStart] = useState({ x: 0, y: 0 });\n const [resizeStart, setResizeStart] = useState({ width: 0, height: 0, mouseX: 0, mouseY: 0 });\n\n useEffect(() => {\n if (name) {\n localStorage.setItem(`${name}-position`, JSON.stringify(position));\n localStorage.setItem(`${name}-size`, JSON.stringify(size));\n\n }\n }, [name, position, size]);\n\n const handleMouseMove = useCallback((e: MouseEvent) => {\n if (isDragging) {\n setPosition({\n x: e.clientX - dragStart.x,\n y: e.clientY - dragStart.y,\n });\n } else if (isResizing) {\n const deltaX = e.clientX - resizeStart.mouseX;\n const deltaY = e.clientY - resizeStart.mouseY;\n\n setSize({\n width: Math.max(resizeStart.width + deltaX, minWidth),\n height: Math.max(resizeStart.height + deltaY, minHeight),\n });\n }\n }, [isDragging, isResizing, dragStart, resizeStart, minWidth, minHeight]);\n\n const handleMouseUp = useCallback(() => {\n setIsDragging(false);\n setIsResizing(false);\n }, []);\n\n useEffect(() => {\n if (isDragging || isResizing) {\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n } else {\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n }\n\n return () => {\n window.removeEventListener('mousemove', handleMouseMove);\n window.removeEventListener('mouseup', handleMouseUp);\n };\n }, [isDragging, isResizing, handleMouseMove, handleMouseUp]);\n\n const handleMouseDown = (e: React.MouseEvent) => {\n setIsDragging(true);\n setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });\n };\n\n const handleResizeStart = (e: React.MouseEvent) => {\n e.stopPropagation();\n setIsResizing(true);\n setResizeStart({\n width: size.width,\n height: size.height,\n mouseX: e.clientX,\n mouseY: e.clientY,\n });\n };\n\n const pixelFrame = getFrame({\n size: pixel,\n stroke,\n frame,\n background,\n });\n\n return createPortal(\n <div\n style={{\n position: 'absolute',\n overflow: 'hidden',\n resize: 'none',\n top: position.y,\n left: position.x,\n width: size.width,\n height: size.height,\n borderImage: `url(${pixelFrame})`,\n borderImageSlice: '49% 49% fill',\n borderImageWidth: `${pixel}px`,\n }}\n onMouseUp={handleMouseUp}\n >\n <div \n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n style={{\n height: `${pixel}px`,\n cursor: \"grab\",\n userSelect: \"none\"\n }}\n ></div>\n <div style={{\n padding: `${pixel}px`,\n paddingTop: 0,\n ...style\n }}>{children}</div>\n <div\n onMouseDown={handleResizeStart}\n style={{\n position: 'absolute',\n width: `${pixel}px`,\n height: `${pixel}px`,\n cursor: 'se-resize',\n bottom: 0,\n right: 0,\n }}\n ></div>\n </div>,\n document.body\n );\n};\n"],"mappings":"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","names":["frame","frame"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glennjong/pixel-window",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "main": "dist/index.cjs.js",
5
5
  "module": "dist/index.esm.js",
6
6
  "types": "dist/index.d.ts",