plentico / plenti

Static Site Generator with Go backend and Svelte frontend
https://plenti.co
Apache License 2.0
1k stars 48 forks source link

User defined schema types (custom field widgets) #219

Closed jimafisk closed 1 year ago

jimafisk commented 2 years ago

We have a variety of standard fields to choose from when defining the input widgets for the CMS editor via a _schema.json file (https://github.com/plentico/plenti/issues/204). It would be great if a user could extend the CMS by defining their own type without having to eject core to do it. For example, maybe the user wants a color picker, they could add a new svelte component for this and then reference it in their _schema.json.

This isn't a high priority and probably won't be worked on in the short term, but thought it was something that folks will eventually ask for so figured I'd add a ticket for it now.

jimafisk commented 1 year ago

I've been working on implementing this, two small challenges have arose:

Firstly, with the use of dynamic imports FieldWidget = (await import('./fields/date.svelte')).default and dynamic Svelte components <svelte:component this={FieldWidget}>, we should no longer have to use static imports:

Example static imports ```svelte ```

However, the Svelte compiler does not convert paths for ESM (it does not change extensions from .svelte to .js or create paths that can be resolved from other files). So things like svelte/internal don't automatically get converted to ../../../web_modules/svelte/internal/index.mjs that the browser can read.

We could:

A) leave unused static imports, but this would require you to import your new field widget in your app somewhere (also in an unused place) for Gopack to pick up on it.

B) Modifying our build so Gopack manually runs on these, which would allow you to simply create new core/cms/fields/my_new_widget.svelte files in your project to add custom widgets


Secondly, transitions break when nesting dynamic components: https://github.com/sveltejs/svelte/issues/1568#issuecomment-1441014492. This impacts expanding the accordion widget for components.

jimafisk commented 1 year ago

A basic implementation for custom FieldWidgets / user defined schema should be available in v0.6.2.

You can add custom field widgets by creating a layouts/_fields folder and adding a custom svelte file.

For example layouts/_fields/color_picker.svelte with contents like:

<script>
  export let field, label, showMediaModal, changingMedia, localMediaList, parentKeys, schema;
</script>

<div class="color-picker">
  <input type="color" id="picker" bind:value={field} />
  <label for="picker">Select Color</label>
</div>

Then reference it in a _schema.json file for a content type or component:

{
    "name": {
        "type": "color_picker",
        "options": []
    }
}

In the future I'll clean up some console errors, and potentially make the location configurable in plenti.json.