@goodfellow-cms/registry 0.3.0 → 0.5.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 CHANGED
@@ -97,6 +97,10 @@ export default defineConfig({
97
97
  });
98
98
  ```
99
99
 
100
+ ### Making it easy to find
101
+
102
+ Call the registry's repository `goodfellow-blocks-<name>` and give it the `goodfellow-blocks` topic on GitHub or GitLab, so searching either finds it, as `goodfellow-plugin-<name>` and `goodfellow-theme-<name>` do for plugins and themes. You can also ask for it to be listed in [shadcn's directory of registries](https://ui.shadcn.com/docs/directory). This registry is the exception, since it's released with Goodfellow.
103
+
100
104
  ## Working on this registry
101
105
 
102
106
  - `registry.json` lists the blocks, whose files are in `site/blocks/installed/`, laid out as they'll be in a site.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodfellow-cms/registry",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Goodfellow's block registry: blocks built with shadcn/ui, which sites install from the admin panel.",
5
5
  "keywords": [
6
6
  "goodfellow",
@@ -28,6 +28,8 @@
28
28
  "./package.json": "./package.json"
29
29
  },
30
30
  "devDependencies": {
31
+ "@goodfellow-cms/core": "0.5.0",
32
+ "@goodfellow-cms/react": "0.5.0",
31
33
  "@puckeditor/core": "0.23.0",
32
34
  "@types/react": "^19.2.0",
33
35
  "@types/react-dom": "^19.2.0",
@@ -37,12 +39,10 @@
37
39
  "lucide-react": "1.52.0",
38
40
  "radix-ui": "1.7.0",
39
41
  "react": "19.3.0",
40
- "react-dom": "19.3.0",
41
- "@goodfellow-cms/core": "0.3.0",
42
- "@goodfellow-cms/react": "0.3.0"
42
+ "react-dom": "19.3.0"
43
43
  },
44
44
  "engines": {
45
- "node": ">=22"
45
+ "node": "^22.23.4 || ^24.22.1 || >=26.12.1"
46
46
  },
47
47
  "publishConfig": {
48
48
  "access": "public"
@@ -8,12 +8,12 @@
8
8
  {
9
9
  "path": "blocks/installed/custom-html/block.tsx",
10
10
  "type": "registry:block",
11
- "content": "import { classNameField, sanitizeHtml } from \"@goodfellow-cms/react\";\nimport type { ComponentConfig } from \"@puckeditor/core\";\nimport { HtmlPreview } from \"./html-preview\";\nimport { HtmlWithScripts } from \"./html-scripts\";\n\nexport interface CustomHtmlProps {\n html: string;\n sanitize: boolean;\n className: string;\n}\n\n/**\n * HTML written by hand, such as a widget's embed code. It's made safe by\n * default: scripts, styles, frames, forms and inline styles are left out. Used\n * as it's written, it runs on the site, but in the editor only inside a\n * sandboxed frame, where it can't reach the admin panel. Its scripts run\n * whenever its page is shown, also after moving to it on a Next.js site.\n */\nconst CustomHtml: ComponentConfig<CustomHtmlProps> = {\n label: \"Custom HTML\",\n fields: {\n html: { type: \"textarea\", label: \"HTML\" },\n sanitize: {\n type: \"radio\",\n label: \"Make it safe\",\n options: [\n { label: \"Yes: leave out scripts, styles and frames\", value: true },\n { label: \"No: use it exactly as written\", value: false },\n ],\n },\n className: classNameField,\n },\n defaultProps: { html: \"<p>Your HTML goes here.</p>\", sanitize: true, className: \"\" },\n render: ({ html, sanitize, className, puck }) => {\n if (!sanitize && puck.isEditing) return <HtmlPreview html={html} className={className} />;\n // Only HTML with scripts needs the browser's help, which loads React on the page.\n if (!sanitize && /<script[\\s>]/i.test(html)) return <HtmlWithScripts html={html} className={className} />;\n return (\n <div\n className={className || undefined}\n // biome-ignore lint/security/noDangerouslySetInnerHtml: sanitized unless the editor chose to use it as written\n dangerouslySetInnerHTML={{ __html: sanitize ? sanitizeHtml(html) : html }}\n />\n );\n },\n};\n\nexport default CustomHtml;\n"
11
+ "content": "import { classNameField, sanitizeHtml } from \"@goodfellow-cms/react\";\nimport type { ComponentConfig } from \"@puckeditor/core\";\nimport { HtmlPreview } from \"./html-preview\";\nimport { HtmlWithScripts } from \"./html-scripts\";\n\nexport interface CustomHtmlProps {\n html: string;\n sanitize: boolean;\n className: string;\n}\n\n/**\n * HTML written by hand, such as a widget's embed code. It's made safe by\n * default: scripts, styles, frames, forms and inline styles are left out. Used\n * as it's written, it runs on the site, but in the editor it's only shown,\n * inside a sandboxed frame, where it can't reach the admin panel, and its\n * scripts don't run. On the site they run whenever its page is shown, also\n * after moving to it on a Next.js site.\n */\nconst CustomHtml: ComponentConfig<CustomHtmlProps> = {\n label: \"Custom HTML\",\n fields: {\n html: { type: \"textarea\", label: \"HTML\" },\n sanitize: {\n type: \"radio\",\n label: \"Make it safe\",\n options: [\n { label: \"Yes: leave out scripts, styles and frames\", value: true },\n { label: \"No: use it exactly as written\", value: false },\n ],\n },\n className: classNameField,\n },\n defaultProps: { html: \"<p>Your HTML goes here.</p>\", sanitize: true, className: \"\" },\n render: ({ html, sanitize, className, puck }) => {\n if (!sanitize && puck.isEditing) return <HtmlPreview html={html} className={className} />;\n // Only HTML with scripts needs the browser's help, which loads React on the page.\n if (!sanitize && /<script[\\s>]/i.test(html)) return <HtmlWithScripts html={html} className={className} />;\n return (\n <div\n className={className || undefined}\n // biome-ignore lint/security/noDangerouslySetInnerHtml: sanitized unless the editor chose to use it as written\n dangerouslySetInnerHTML={{ __html: sanitize ? sanitizeHtml(html) : html }}\n />\n );\n },\n};\n\nexport default CustomHtml;\n"
12
12
  },
13
13
  {
14
14
  "path": "blocks/installed/custom-html/html-preview.tsx",
15
15
  "type": "registry:component",
16
- "content": "\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\n\n/** Tells the editor how tall the HTML is, so the frame fits it. */\nconst REPORT_HEIGHT =\n \"<script>new ResizeObserver(function(){parent.postMessage({goodfellowHtmlHeight:document.documentElement.scrollHeight},'*')}).observe(document.documentElement)</script>\";\n\n/**\n * Shows HTML as it was written, in the editor only: inside a frame sandboxed\n * without `allow-same-origin`, so its scripts run on their own and can't reach\n * the admin panel or the editor's sign-in. It has the page's styles.\n */\nexport function HtmlPreview({ html, className }: { html: string; className: string }) {\n const frame = useRef<HTMLIFrameElement>(null);\n const [height, setHeight] = useState(120);\n const [styles, setStyles] = useState(\"\");\n\n useEffect(() => {\n const document = frame.current?.ownerDocument;\n const view = document?.defaultView;\n if (!document || !view) return;\n setStyles(\n [...document.querySelectorAll('link[rel=\"stylesheet\"], style')].map((element) => element.outerHTML).join(\"\"),\n );\n const onMessage = (event: MessageEvent) => {\n const reported = (event.data as { goodfellowHtmlHeight?: unknown } | null)?.goodfellowHtmlHeight;\n if (event.source === frame.current?.contentWindow && typeof reported === \"number\") setHeight(Math.ceil(reported));\n };\n view.addEventListener(\"message\", onMessage);\n return () => view.removeEventListener(\"message\", onMessage);\n }, []);\n\n return (\n <iframe\n ref={frame}\n title=\"Custom HTML\"\n sandbox=\"allow-scripts\"\n srcDoc={`<!doctype html><html><head><meta charset=\"utf-8\">${styles}</head><body style=\"margin:0\">${html}${REPORT_HEIGHT}</body></html>`}\n className={className || undefined}\n style={{ display: \"block\", width: \"100%\", height, border: 0 }}\n />\n );\n}\n"
16
+ "content": "\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\n\n/**\n * Shows HTML as it was written, in the editor only: inside a frame sandboxed\n * with nothing allowed, so it can't reach the admin panel or the editor's\n * sign-in. Its scripts don't run there, since the editor runs only its own\n * scripts; they run on the published site. It has the page's styles, and\n * can be made taller by dragging its corner.\n */\nexport function HtmlPreview({ html, className }: { html: string; className: string }) {\n const frame = useRef<HTMLIFrameElement>(null);\n const [styles, setStyles] = useState(\"\");\n\n useEffect(() => {\n const document = frame.current?.ownerDocument;\n if (!document) return;\n setStyles(\n [...document.querySelectorAll('link[rel=\"stylesheet\"], style')].map((element) => element.outerHTML).join(\"\"),\n );\n }, []);\n\n return (\n <div className={className || undefined}>\n <div style={{ height: 240, resize: \"vertical\", overflow: \"hidden\" }}>\n <iframe\n ref={frame}\n title=\"Custom HTML\"\n sandbox=\"\"\n srcDoc={`<!doctype html><html><head><meta charset=\"utf-8\">${styles}</head><body style=\"margin:0\">${html}</body></html>`}\n style={{ display: \"block\", width: \"100%\", height: \"100%\", border: 0 }}\n />\n </div>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n Scripts don't run in the editor. They run on the published site.\n </p>\n </div>\n );\n}\n"
17
17
  },
18
18
  {
19
19
  "path": "blocks/installed/custom-html/html-scripts.tsx",
@@ -24,7 +24,7 @@
24
24
  "meta": {
25
25
  "goodfellow": {
26
26
  "category": "Advanced",
27
- "version": "0.3.0"
27
+ "version": "0.5.0"
28
28
  }
29
29
  },
30
30
  "dependencies": []
package/r/registry.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "goodfellow": {
22
22
  "category": "Page sections",
23
23
  "recommended": true,
24
- "version": "0.3.0"
24
+ "version": "0.5.0"
25
25
  }
26
26
  },
27
27
  "dependencies": []
@@ -45,7 +45,7 @@
45
45
  "goodfellow": {
46
46
  "category": "Page sections",
47
47
  "recommended": true,
48
- "version": "0.3.0"
48
+ "version": "0.5.0"
49
49
  }
50
50
  },
51
51
  "dependencies": []
@@ -69,7 +69,7 @@
69
69
  "goodfellow": {
70
70
  "category": "Page sections",
71
71
  "recommended": true,
72
- "version": "0.3.0"
72
+ "version": "0.5.0"
73
73
  }
74
74
  },
75
75
  "dependencies": []
@@ -92,7 +92,7 @@
92
92
  "goodfellow": {
93
93
  "category": "Page sections",
94
94
  "recommended": true,
95
- "version": "0.3.0"
95
+ "version": "0.5.0"
96
96
  }
97
97
  },
98
98
  "dependencies": []
@@ -119,7 +119,7 @@
119
119
  "meta": {
120
120
  "goodfellow": {
121
121
  "category": "Page sections",
122
- "version": "0.3.0"
122
+ "version": "0.5.0"
123
123
  }
124
124
  }
125
125
  },
@@ -144,7 +144,7 @@
144
144
  "goodfellow": {
145
145
  "category": "Page sections",
146
146
  "recommended": true,
147
- "version": "0.3.0"
147
+ "version": "0.5.0"
148
148
  }
149
149
  }
150
150
  },
@@ -170,7 +170,7 @@
170
170
  "meta": {
171
171
  "goodfellow": {
172
172
  "category": "Advanced",
173
- "version": "0.3.0"
173
+ "version": "0.5.0"
174
174
  }
175
175
  },
176
176
  "dependencies": []
@@ -197,7 +197,7 @@
197
197
  "goodfellow": {
198
198
  "category": "Interactive",
199
199
  "recommended": true,
200
- "version": "0.3.0"
200
+ "version": "0.5.0"
201
201
  }
202
202
  },
203
203
  "dependencies": []
@@ -224,7 +224,7 @@
224
224
  "goodfellow": {
225
225
  "category": "Interactive",
226
226
  "recommended": true,
227
- "version": "0.3.0"
227
+ "version": "0.5.0"
228
228
  }
229
229
  },
230
230
  "dependencies": []
@@ -250,7 +250,7 @@
250
250
  "meta": {
251
251
  "goodfellow": {
252
252
  "category": "Interactive",
253
- "version": "0.3.0"
253
+ "version": "0.5.0"
254
254
  }
255
255
  },
256
256
  "dependencies": []
@@ -19,7 +19,7 @@
19
19
  "goodfellow": {
20
20
  "category": "Page sections",
21
21
  "recommended": true,
22
- "version": "0.3.0"
22
+ "version": "0.5.0"
23
23
  }
24
24
  },
25
25
  "dependencies": []
@@ -19,7 +19,7 @@
19
19
  "goodfellow": {
20
20
  "category": "Page sections",
21
21
  "recommended": true,
22
- "version": "0.3.0"
22
+ "version": "0.5.0"
23
23
  }
24
24
  },
25
25
  "dependencies": []
@@ -22,7 +22,7 @@
22
22
  "meta": {
23
23
  "goodfellow": {
24
24
  "category": "Interactive",
25
- "version": "0.3.0"
25
+ "version": "0.5.0"
26
26
  }
27
27
  },
28
28
  "dependencies": []
package/r/shadcn-faq.json CHANGED
@@ -23,7 +23,7 @@
23
23
  "goodfellow": {
24
24
  "category": "Interactive",
25
25
  "recommended": true,
26
- "version": "0.3.0"
26
+ "version": "0.5.0"
27
27
  }
28
28
  },
29
29
  "dependencies": []
@@ -18,7 +18,7 @@
18
18
  "goodfellow": {
19
19
  "category": "Page sections",
20
20
  "recommended": true,
21
- "version": "0.3.0"
21
+ "version": "0.5.0"
22
22
  }
23
23
  },
24
24
  "dependencies": []
@@ -21,7 +21,7 @@
21
21
  "goodfellow": {
22
22
  "category": "Page sections",
23
23
  "recommended": true,
24
- "version": "0.3.0"
24
+ "version": "0.5.0"
25
25
  }
26
26
  }
27
27
  }
@@ -22,7 +22,7 @@
22
22
  "meta": {
23
23
  "goodfellow": {
24
24
  "category": "Page sections",
25
- "version": "0.3.0"
25
+ "version": "0.5.0"
26
26
  }
27
27
  }
28
28
  }
@@ -23,7 +23,7 @@
23
23
  "goodfellow": {
24
24
  "category": "Interactive",
25
25
  "recommended": true,
26
- "version": "0.3.0"
26
+ "version": "0.5.0"
27
27
  }
28
28
  },
29
29
  "dependencies": []
@@ -18,7 +18,7 @@
18
18
  "goodfellow": {
19
19
  "category": "Page sections",
20
20
  "recommended": true,
21
- "version": "0.3.0"
21
+ "version": "0.5.0"
22
22
  }
23
23
  },
24
24
  "dependencies": []