@blocklet/pages-kit-block-studio 0.1.4 → 0.1.5

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.
@@ -1,9 +1,20 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MEDIA_KIT_RESOURCE_TYPE = exports.MEDIA_KIT_DID = exports.PAGES_KIT_BLOCK_STUDIO_RESOURCE_TYPE = exports.PAGES_KIT_BLOCK_STUDIO_DID = exports.PAGES_KIT_RESOURCE_TYPE = exports.PAGES_KIT_DID = void 0;
6
+ exports.DEFAULT_BLOCK_ENTRY_FILES_PATTERN = exports.NANOID_LENGTH = exports.PREVIEW_IMAGE_DIR = exports.METADATA_FILE_NAME = exports.libDir = exports.NEW_BLOCK_TEMPLATE_METADATA_PATH = exports.NEW_BLOCK_TEMPLATE_PATH = exports.MEDIA_KIT_RESOURCE_TYPE = exports.MEDIA_KIT_DID = exports.PAGES_KIT_BLOCK_STUDIO_RESOURCE_TYPE = exports.PAGES_KIT_BLOCK_STUDIO_DID = exports.PAGES_KIT_RESOURCE_TYPE = exports.PAGES_KIT_DID = void 0;
7
+ const path_1 = __importDefault(require("path"));
4
8
  exports.PAGES_KIT_DID = 'z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o';
5
9
  exports.PAGES_KIT_RESOURCE_TYPE = 'page';
6
10
  exports.PAGES_KIT_BLOCK_STUDIO_DID = 'z2qa7rr3eUyVnWp2PCxEVARuUfLFh6cE5V2xV';
7
11
  exports.PAGES_KIT_BLOCK_STUDIO_RESOURCE_TYPE = 'page';
8
12
  exports.MEDIA_KIT_DID = 'z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9';
9
13
  exports.MEDIA_KIT_RESOURCE_TYPE = 'imgpack';
14
+ exports.NEW_BLOCK_TEMPLATE_PATH = path_1.default.join(__dirname, 'new-block-template', 'index.tsx');
15
+ exports.NEW_BLOCK_TEMPLATE_METADATA_PATH = path_1.default.join(__dirname, 'new-block-template', '@metadata.json');
16
+ exports.libDir = 'lib';
17
+ exports.METADATA_FILE_NAME = '@metadata.json';
18
+ exports.PREVIEW_IMAGE_DIR = '@preview-images';
19
+ exports.NANOID_LENGTH = 16;
20
+ exports.DEFAULT_BLOCK_ENTRY_FILES_PATTERN = 'src/**/index.{ts,tsx,html}';
@@ -0,0 +1,59 @@
1
+ {
2
+ "properties": {
3
+ "gs1rn5jmxfvpxptx": {
4
+ "index": 0,
5
+ "data": {
6
+ "id": "gs1rn5jmxfvpxptx",
7
+ "key": "title",
8
+ "locales": {
9
+ "zh": {
10
+ "name": "Title"
11
+ }
12
+ }
13
+ }
14
+ },
15
+ "9ajrz12ik7esfk1z": {
16
+ "index": 1,
17
+ "data": {
18
+ "id": "9ajrz12ik7esfk1z",
19
+ "key": "description",
20
+ "locales": {
21
+ "zh": {
22
+ "name": "Description",
23
+ "defaultValue": "Welcome to Pages Kit Block Studio"
24
+ }
25
+ }
26
+ }
27
+ },
28
+ "3ckcfvf6b7zyskk8": {
29
+ "index": 2,
30
+ "data": {
31
+ "id": "3ckcfvf6b7zyskk8",
32
+ "key": "logo",
33
+ "type": "url",
34
+ "locales": {
35
+ "zh": {
36
+ "defaultValue": {
37
+ "url": "/.well-known/service/blocklet/logo?imageFilter=convert&f=png&h=80",
38
+ "mediaKitUrl": "/.well-known/service/blocklet/logo?imageFilter=convert&f=png&h=80"
39
+ },
40
+ "name": "Logo"
41
+ }
42
+ }
43
+ }
44
+ },
45
+ "x3lqht8ikble1itx": {
46
+ "index": 3,
47
+ "data": {
48
+ "id": "x3lqht8ikble1itx",
49
+ "key": "copyright",
50
+ "locales": {
51
+ "zh": {
52
+ "defaultValue": "Powered by Pages Kit Block Studio"
53
+ }
54
+ },
55
+ "visible": false
56
+ }
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,89 @@
1
+ import React from 'react';
2
+
3
+ export interface HelloWorldProps {
4
+ title?: string;
5
+ logo?: string | { url: string };
6
+ description?: string;
7
+ copyright?: string;
8
+ }
9
+
10
+ // default export
11
+ export default function HelloWorld({ title = 'Hello World', logo, description, copyright }: HelloWorldProps) {
12
+ return (
13
+ <div
14
+ style={{
15
+ display: 'flex',
16
+ flexDirection: 'column',
17
+ alignItems: 'center',
18
+ padding: '16px 0',
19
+ }}>
20
+ {title && <h1>{title}</h1>}
21
+ {logo && (
22
+ <img
23
+ src={typeof logo === 'object' ? logo.url : logo}
24
+ alt="logo"
25
+ style={{
26
+ margin: '16px 0',
27
+ maxWidth: '200px',
28
+ }}
29
+ />
30
+ )}
31
+ {description && (
32
+ <div
33
+ style={{
34
+ color: '#666',
35
+ marginTop: '8px',
36
+ }}>
37
+ {description}
38
+ </div>
39
+ )}
40
+ {copyright && (
41
+ <div
42
+ style={{
43
+ color: '#999',
44
+ fontSize: '12px',
45
+ marginTop: '16px',
46
+ }}>
47
+ {copyright}
48
+ </div>
49
+ )}
50
+ </div>
51
+ );
52
+ }
53
+
54
+ // export edit component
55
+ export const EditComponent: React.FC<HelloWorldProps & { onChange?: (value: HelloWorldProps) => void }> = ({
56
+ onChange,
57
+ ...props
58
+ }) => {
59
+ return (
60
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
61
+ <div
62
+ style={{
63
+ fontSize: '14px',
64
+ fontWeight: 500,
65
+ color: '#333',
66
+ padding: '8px 0',
67
+ borderBottom: '1px solid #eee',
68
+ }}>
69
+ Footer Parameters
70
+ </div>
71
+ <input
72
+ id="copyright-input"
73
+ type="text"
74
+ style={{
75
+ width: '100%',
76
+ padding: '8px 12px',
77
+ border: '1px solid #ddd',
78
+ borderRadius: '4px',
79
+ fontSize: '14px',
80
+ transition: 'border-color 0.3s',
81
+ outline: 'none',
82
+ }}
83
+ value={props.copyright || ''}
84
+ onChange={(e) => onChange?.({ copyright: e.target.value })}
85
+ placeholder="Please Input Copyright"
86
+ />
87
+ </div>
88
+ );
89
+ };
@@ -17,6 +17,7 @@ const express_1 = require("express");
17
17
  const fs_1 = __importDefault(require("fs"));
18
18
  const lodash_1 = require("lodash");
19
19
  const path_1 = __importDefault(require("path"));
20
+ const constants_1 = require("../constants");
20
21
  const helper_1 = require("../utils/helper");
21
22
  exports.initBlockStudioRouter = (0, express_1.Router)();
22
23
  const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.svg'];
@@ -89,6 +90,47 @@ exports.initBlockStudioRouter.post('/', (req, res) => __awaiter(void 0, void 0,
89
90
  return res.status(500).json({ error: 'Failed to write file' });
90
91
  }
91
92
  }));
93
+ exports.initBlockStudioRouter.post('/create', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
94
+ if (!helper_1.isDev) {
95
+ return res.status(403).json({ error: 'Only available in development mode' });
96
+ }
97
+ const { name, description } = req.body;
98
+ if (!name) {
99
+ return res.status(400).json({ error: 'Name is required' });
100
+ }
101
+ try {
102
+ const pattern = (0, helper_1.getBlockEntryFilesPattern)();
103
+ const baseDir = path_1.default.dirname(pattern.replace(/\*\*?/g, ''));
104
+ const blockDir = path_1.default.join(baseDir, name);
105
+ const metadataPath = path_1.default.join(blockDir, constants_1.METADATA_FILE_NAME);
106
+ const indexPath = path_1.default.join(blockDir, 'index.tsx');
107
+ // Check if block already exists
108
+ if (fs_1.default.existsSync(blockDir)) {
109
+ return res.status(409).json({ error: 'Block already exists' });
110
+ }
111
+ // Create block directory
112
+ fs_1.default.mkdirSync(blockDir, { recursive: true });
113
+ // Initialize metadata
114
+ let metadata = (0, helper_1.initializeMetadata)(metadataPath);
115
+ metadata.name = name;
116
+ metadata.description = description || '';
117
+ metadata.createdAt = new Date().toISOString();
118
+ metadata.updatedAt = new Date().toISOString();
119
+ // get template metadata from @metadata.json
120
+ const metadataContent = fs_1.default.readFileSync(constants_1.NEW_BLOCK_TEMPLATE_METADATA_PATH, 'utf-8');
121
+ metadata = Object.assign(Object.assign({}, metadata), (0, helper_1.safeParse)(metadataContent));
122
+ // Write metadata file
123
+ fs_1.default.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
124
+ // Copy template file to index.tsx
125
+ const templateContent = fs_1.default.readFileSync(constants_1.NEW_BLOCK_TEMPLATE_PATH, 'utf-8');
126
+ fs_1.default.writeFileSync(indexPath, templateContent);
127
+ return res.json({ success: true, metadata });
128
+ }
129
+ catch (error) {
130
+ console.error('Failed to create block:', error);
131
+ return res.status(500).json({ error: 'Failed to create block' });
132
+ }
133
+ }));
92
134
  exports.initBlockStudioRouter.get('/all', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
93
135
  const { withBlockletData = true } = req.query;
94
136
  const allBlocks = yield (0, helper_1.findComponentFiles)();
@@ -196,11 +196,33 @@ function generateComponent(content, _isDev = true) {
196
196
  if (_isDev) {
197
197
  // do something
198
198
  }
199
- return `import { createElement } from 'react';
199
+ return `import { createElement, useEffect, useRef } from 'react';
200
200
 
201
201
  export default function HtmlPreview() {
202
+ const iframeRef = useRef(null);
203
+
204
+ useEffect(() => {
205
+ const iframe = iframeRef.current;
206
+ if (!iframe) return;
207
+
208
+ const resizeObserver = new ResizeObserver(() => {
209
+ const doc = iframe.contentDocument;
210
+ if (!doc) return;
211
+
212
+ const height = doc.documentElement.scrollHeight;
213
+ iframe.style.height = height + 'px';
214
+ });
215
+
216
+ iframe.addEventListener('load', () => {
217
+ resizeObserver.observe(iframe.contentDocument.documentElement);
218
+ });
219
+
220
+ return () => resizeObserver.disconnect();
221
+ }, []);
222
+
202
223
  return createElement('iframe', {
203
- style: { border: 'none', width: '100%', height: '100%' },
224
+ ref: iframeRef,
225
+ style: { border: 'none', width: '100%', minHeight: '50px' },
204
226
  sandbox: 'allow-scripts',
205
227
  title: 'Preview ${name}',
206
228
  srcDoc: ${htmlContent}