measuredco / puck Goto Github PK
View Code? Open in Web Editor NEWThe visual editor for React
Home Page: https://puckeditor.com
License: MIT License
The visual editor for React
Home Page: https://puckeditor.com
License: MIT License
Users may wish to preview their page for different viewport sizes without leaving Puck.
Viewport previews are typically done by resizing an iframe containing the content. However, Puck doesn't currently use frames because of their historical performance issues and the challenges supporting a robust drag-and-drop interface.
We're looking for alternative solutions. Please use this thread to propose ideas and discuss!
i have a Component with props as
{
name: string;
price: {"total": number; "string": number}
}
@chrisvxd
how can i define the config for the price prop for puck editor. i see we added support for "custom" type but not sure if this can be done with it .
The last few days have been a blast - we've gone from 8 stars on Tuesday morning to 2.1k and counting on Thursday.
We've been thinking a lot about the best way to engage with you all.
Currently we're considering:
Are there any things we're missing, or anything you'd like us to consider? Free-form responses welcome.
If a component definition exists in the content, but it doesn't exist in the puck config, puck should gracefully fail.
<Render>
should render nothing
<Puck>
should render a warning
The code generated by the generator doesn't get built on publish, which makes it easy to publish code that will fail when the user tries to build it. We should build all recipes as generated by the generator as part of a GitHub workflow for PRs, failing if any build fails.
To test generators, we need to:
Example: #46
I am trying to make an email template editor using Puck and React Email. However, Puck is adding a few extra elements between the root element and the component (see screenshot) which is causing styles such as:
#my-email-container {
display: flex;
flex-flow: column;
align-items: center;
}
to not work as expected.
Example code:
const config = {
root: {
render({ children }) {
return <div className="my-email-container">{children}</div>;
},
},
components: {
Button: {
fields: { ... },
render({ content, url, bgColor }) {
return (
<Button
pX={20}
pY={12}
href={url}
style={{ background: bgColor, color: "#000" }}
>
{content}
</Button>
);
},
},
},
};
const initialData = {
root: {
title: "Title",
},
content: [],
};
export default function EmailEditorPage() {
return (
<Puck
config={config}
data={initialData}
/>
);
}
This is because puck may sometimes be used for non-page content, such as sections within a page.
We need a hosted demo that showcases how puck can integrate with different component libraries.
demo
to /apps
.demo
with one or more component libraries@monospaced suggested we could look into making the config more modular.
Some thoughts:
This doesn't necessarily require a first-party API, and may be more "recipe" based.
Users shouldn't have to worry about configuring CSS. We should inline it, if possible.
Amazing project! I'm very excited at the prospect of software creators and designers in particular being able to use a component library directly in this highly intuitive manner. Well done!
I'm curious what the path might look like in supporting preact, specifically for deno/fresh?
Great concept, well executed — thanks for putting this out there!
When navigating a large collection of components, it would be useful to have them grouped into some form of hierarchy (rather than a single list) so they could be found more easily.
Once we've published the core and puck packages, we should ensure we're installing these into generated projects.
In the puck config
How can I create a new field type and it's editor?
The current plugin system doesn't seem to support this, only allowing us to reimplement the whole sidebar editing?
We don't currently publish GitHub releases. We should.
Our release process currently goes:
yarn release
. This bumps all monorepo packages and updates the changeling.release:
commit and publishes all packagesThere are 2 options that come to mind:
If going with automation (my preferred option), we should update the CI that runs on step 5 to create the release via an API and update it with the changelog for that release.
yarn release
. We could either parse these back out of the CHANGELOG, or consider a separate CHANGELOG
directory (but retain a CHANGELOG.md
in here containing all releases. I think I prefer the former.After adding some elements the previous ones lose the hover border and actions:
Source: https://news.ycombinator.com/item?id=37392861
Sometimes a user might need to rename or remove a property provided to a component. For example, remaining description
to subtitle
.
The user currently has two options:
render
function.These solutions either require repetitive work, or require the user to republish each page manually.
Add a first-party mechanism for transforming data on a per-component basis.
This would probably live under a separate package (/packages/transform
or /packages/migrate
) and provide a user with a mechanism to 1) patch their data on the fly in a standardised manor and 2) batch transform their puck data consistently to adhere to the new props.
import { createTransform } from "@measured/puck-transform";
const transform = createTransform({
HeadingBlock: ({ subtitle, ...props }) => {
return {
...props,
description: subtitle,
};
},
});
// Pull from backend
const data = {
type: "HeadingBlock",
props: {
subtitle: "Hello, world",
},
};
export default () => <Puck data={transform(data)} config={config} />;
// Example data
const allData = [
{
path: "/",
data: {
root: {},
content: [
{
type: "HeadingBlock",
props: {
subtitle: "Hello, world",
},
},
],
},
},
];
// Run the transformer
const patchedData = allData.map((page) => ({
...page,
data: transform(page.data),
}));
// Write to your db
const save = () => {};
save(patchedData);
My component have a prop tags of array type but values as string for it ``tags: string[]` . how can i define Field config for this prop, seems like it's currently not supported.
Would be great if subitems (like the features inside of a featureList) could be reordered via drag and drop. (Even if it's only sorting the list in the righthand sidebar.) As I understand it, the only way now to reorder sub items is to delete them and re-enter each one.
Using a magic _data
prop with an external adaptor doesn't work for children of an array
field type
Large tracker for lots of features:
group
input typestitle
etcsetData
prop to allow plugins to override the dataplugin-heading-analyzer
)I followed the intrusions and created a new app using
npx create-puck-app my-app
Running yarn dev
and accessing http://localhost:3000 throws 404. Looking at app/[...puckPath]/page.tsx
it looks like it throws a 404 when database.json is not found. I tried creating an empty file but the same issue persists. What should go in this file when bootstrapping the editor for the first time?
Hi!
I'm running into a few errors when trying to build the next app:
The first one is a type error in ./app/[...puckPath]/page.tsx
:
Type error: Cannot find module '@measured/puck/types/Config' or its corresponding type declarations.
3 | import resolvePuckPath from "./resolve-puck-path";
4 | import { Metadata } from "next";
> 5 | import { Data } from "@measured/puck/types/Config";
| ^
6 |
7 | export async function generateMetadata({
8 | params,
I think this can be fixed by changing:
import { Data } from "@measured/puck/types/Config";
// to ->
import { Data } from "@measured/puck";
and changing line 27 from:
return {
title: data?.page?.title, // Property 'page' does not exist on type 'Data'
};
// to ->
return {
title: data?.root?.title,
};
This gets me further into the build process, but it errors out on the Collecting page data
step:
pnpm run build
> [email protected] build /Users/maantje/programmeren/Full webapps/test_app_puck_v2
> next build
- info Creating an optimized production build
- info Compiled successfully
- info Linting and checking validity of types
- info Collecting page data
[ ] - info Generating static pages (0/3)TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11576:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
cause: AggregateError
at internalConnectMultiple (node:net:1111:18)
at afterConnectMultiple (node:net:1663:5)
at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
code: 'ECONNREFUSED',
[errors]: [ [Error], [Error] ]
}
}
TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11576:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
cause: AggregateError
at internalConnectMultiple (node:net:1111:18)
at afterConnectMultiple (node:net:1663:5)
at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
code: 'ECONNREFUSED',
[errors]: [ [Error], [Error] ]
}
}
Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11576:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
- info Generating static pages (3/3)
> Export encountered errors on following paths:
/page: /
I also tried with yarn, which gave me the same results.
npx create-puck-app
and use default optionsnpm run dev
or yarn dev
/
page and give it a title and heading with random wordsnpm run build
or yarn build
I found this(https://stackoverflow.com/questions/74165121/next-js-fetch-request-gives-error-typeerror-fetch-failed) which can maybe help, but I didn't really figure it out. I think it has something to do with the fetch to localhost:3000 in ./app/[...puckPath]/page.tsx
.
edit: just occurred to me that this should probably be 2 different issues
react-beautiful-dnd is somewhat dated and hasn't kept pace with React releases:
@measured
npm scopeI tried using the demo in Vite but I am stuck on "Failed to resolve import "@measured/puck/components/Puck""
This file doesn't exist on the NPM package's dist folder, what am I missing?
Is there a way to share state between components in the config? Other than abusing dom tricks? Or is the state of each component isolated?
From my understanding, it would likely be the latter, and that makes more sense for what Puck is trying to achieve, but for my use case I would be hoping that there might be a way to share state. Global states would work as well.
The code in /recipes
and /packages/create-puck-app/templates
is currently duplicated. We should reconcile these to prevent users from committing changes to the wrong directory. See #120 for example.
Suggest we should add a script that either:
The work is already well underway in #37. Issue for tracking.
Right now, some packages may not be correctly built for distribution. Known issues:
plugin-heading-analyzer
- does not currently compile from TS into JSAt it's core, puck is a mechanism to build visual editors into existing applications.
We could also consider making a standalone application framework, puck-app
, that wraps Next.js, includes a database configuration and authentication via something like auth0. This will provide OOTB support for basic marketing sites with no dynamic content.
i.e.
yarn create puck-app
Spits out
puck.config.ts
package.json
- contains scripts like
eject
- eject from Puck to a standalone Next.js applicationeslint
etcQuestions / notes
--
This might be better as a generator, but I thought this could be a clean way to hide away all the noise from the end user.
It seems that this is the way that tooling is going.
It would be nice to be able to add sub objects pretty much exactly the way arrayFields
currently behaves just without the 'add item' UI!
For example in the demo site we have full blocks like Hero
which only have some theme/config options but we also have components like H1
on the page at the same time.
The Hero
likely contains a H1 and it would be nice to be able to edit the H1 as a dedicated object.
This will enable components to toggle their behaviour depending on the context that they're rendered in
Hi!
What an amazing project! I was trying to get it to work locally but it seems like the recipe doesn't work on my machine. I get this error when I run it:
> npx create-puck-app my-app
node:internal/errors:496
ErrorCaptureStackTrace(err);
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'glob' imported from /Users/maantje/.npm/_npx/039b3c3c47fc2298/node_modules/create-puck-app/index.js
at new NodeError (node:internal/errors:405:5)
at packageResolve (node:internal/modules/esm/resolve:781:9)
at moduleResolve (node:internal/modules/esm/resolve:830:20)
at defaultResolve (node:internal/modules/esm/resolve:1035:11)
at DefaultModuleLoader.resolve (node:internal/modules/esm/loader:251:12)
at DefaultModuleLoader.getModuleJob (node:internal/modules/esm/loader:140:32)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:33)
at link (node:internal/modules/esm/module_job:75:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
Node.js v20.4.0
I'm using Node v20.4.0, I also tried with pnpm and got the same error. I sadly don't know enough about npm to fix this.
Current the puck Editor renders the Components List by map Object.keys(config.components)
. it will be great if we can have ability to control the order of rendering this List.
Let's use this issue to crib out structure for a proper docs site
Currently, we have no way to create groups of fields. #62 adds object
support, and spun out this discussion.
Inline fieldsets at the top-level (with headings) are something I've considered as a way to break the form up into separate areas of related fields. It strikes me that the Heading scenario here might also work with an inline Heading fieldset.
Add renderFields
method
Example adding a Style fieldset to Heading
export const Heading: ComponentConfig<HeadingProps> = {
renderFields: () => {
return <>
<Field name="text" />
<Field name="level" />
<Fieldset title="Style">
<Field name="size" />
<Field name="align" />
<Field name="padding" />
</Fieldset>
</>
},
fields: {
text: { type: "text" },
size: {
type: "select",
options: sizeOptions,
},
level: {
type: "select",
options: levelOptions,
},
align: {
type: "radio",
options: [
{ label: "Left", value: "left" },
{ label: "Center", value: "center" },
{ label: "Right", value: "right" },
],
},
padding: { type: "text" },
},
}
Change fields
API or add new fieldsets
API
export const Heading: ComponentConfig<HeadingProps> = {
fieldsets: [
{
title: "",
fields: {
text: { type: "text" },
level: {
type: "select",
options: levelOptions,
},
},
},
{
title: "Style",
fields: {
size: {
type: "select",
options: sizeOptions,
},
align: {
type: "radio",
options: [
{ label: "Left", value: "left" },
{ label: "Center", value: "center" },
{ label: "Right", value: "right" },
],
},
padding: { type: "text" },
},
},
],
Something else; could be some combination of the above or another proposal.
Related #62
Unclear how this would work, as image uploads are largely a user-land problem and it's unclear how much value a generic solution would provide.
Suggestions:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.