Field Kit

Nesta página

O tipo de campo json do EmDash armazena dados estruturados arbitrários, editados por padrão através de um input de texto de linha única que aceita JSON bruto. Field Kit é um plugin oficial que fornece quatro widgets componíveis para campos json, configurados inteiramente através de options de seed para que os construtores de sites possam usá-los apenas com o esquema de seed.

Instalação

Instale o pacote do npm:

npm i @emdash-cms/plugin-field-kit

A seguinte configuração registra o plugin:

import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { fieldKitPlugin } from "@emdash-cms/plugin-field-kit";

export default defineConfig({
	integrations: [
		emdash({
			plugins: [fieldKitPlugin()],
		}),
	],
});

Anexe um widget a qualquer campo json definindo widget como field-kit:<name>. A seguinte definição de campo usa o widget list:

{
	"slug": "ingredients",
	"type": "json",
	"widget": "field-kit:list",
	"options": { "fields": [...] }
}

Widgets

WidgetUsoValor armazenado
object-formFormulário inline para objetos JSON simples{ key: value, ... }
listEditor de array ordenado com adicionar / remover / reordenar[{ ... }, ...]
gridMatriz de linhas × colunas{ rowKey: { colKey: value } }
tagsInput de chip/tag de forma livre["tag1", "tag2"]

Se um widget estiver faltando suas options necessárias (por exemplo, fields para object-form/list, ou rows/columns para grid), o editor renderiza um aviso inline “Widget mal configurado” em vez de um input quebrado — útil ao iterar em esquemas de seed.

object-form

Renderiza um grupo de subcampos tipados que são armazenados como um único objeto JSON. Bom para dados estruturados de forma fixa como informações nutricionais ou de contato. A seguinte definição de campo configura um objeto nutricional:

{
	"slug": "nutrition",
	"type": "json",
	"widget": "field-kit:object-form",
	"options": {
		"collapsed": false,
		"fields": [
			{ "key": "calories", "label": "Calories", "type": "number", "suffix": "kcal" },
			{ "key": "protein", "label": "Protein", "type": "number", "suffix": "g" },
			{ "key": "fat", "label": "Fat", "type": "number", "suffix": "g" },
			{ "key": "carbs", "label": "Carbs", "type": "number", "suffix": "g" }
		]
	}
}

Valor armazenado: { "calories": 250, "protein": 12.5, "fat": 8, "carbs": 30 }.

OpçãoTipoPadrãoDescrição
fieldsSubFieldDef[](obrigatório)Definições de subcampos — veja Subcampos.
collapsedbooleanfalseRenderizar o grupo recolhido por padrão.
helpTextstringTexto de ajuda exibido abaixo do widget.

list

Um editor de array ordenado com controles de adicionar, remover e reordenar. Cada linha é um objeto JSON cuja forma é definida por fields. O cabeçalho da linha mostra um resumo renderizado a partir de um template estilo Mustache. A seguinte definição de campo configura uma lista de ingredientes:

{
	"slug": "ingredients",
	"type": "json",
	"widget": "field-kit:list",
	"options": {
		"itemLabel": "Ingredient",
		"min": 1,
		"max": 50,
		"sortable": true,
		"summary": "{{name}} — {{amount}}",
		"fields": [
			{ "key": "name", "label": "Name", "type": "text", "required": true },
			{ "key": "amount", "label": "Amount", "type": "text" },
			{ "key": "optional", "label": "Optional", "type": "boolean" }
		]
	}
}

O valor armazenado é um array de objetos de linha:

[
	{ "name": "Flour", "amount": "500g", "optional": false },
	{ "name": "Butter", "amount": "200g", "optional": false }
]
OpçãoTipoPadrãoDescrição
fieldsSubFieldDef[](obrigatório)Definições de subcampos para cada linha.
itemLabelstring"Item"Label singular para uma linha (usado no botão “Adicionar” e títulos de linha de fallback).
minnumberNúmero mínimo de itens. Abaixo disso, o botão remover se esconde.
maxnumberNúmero máximo de itens. Nesta contagem, o botão adicionar se esconde.
sortablebooleantrueMostrar botões de reordenar para cima/baixo.
summarystringTemplate Mustache renderizado como o título de linha recolhida. Veja Templates de resumo.
helpTextstringTexto de ajuda exibido abaixo do widget.

grid

Uma matriz bidimensional de linhas × colunas. Cada célula pode ser um alternador, input de texto, input numérico ou seleção. Útil para matrizes como disponibilidade sazonal, tabelas de preços ou comparações de recursos. A seguinte definição de campo configura uma grade de disponibilidade sazonal:

{
	"slug": "availability",
	"type": "json",
	"widget": "field-kit:grid",
	"options": {
		"cell": "toggle",
		"rows": [
			{ "key": "berries", "label": "Berries" },
			{ "key": "stoneFruit", "label": "Stone fruit" },
			{ "key": "citrus", "label": "Citrus" }
		],
		"columns": [
			{ "key": "spring", "label": "Spring" },
			{ "key": "summer", "label": "Summer" },
			{ "key": "autumn", "label": "Autumn" },
			{ "key": "winter", "label": "Winter" }
		]
	}
}

O valor armazenado é um objeto indexado por linha, depois por coluna:

{
	"berries": { "spring": false, "summer": true, "autumn": false, "winter": false },
	"stoneFruit": { "spring": false, "summer": true, "autumn": true, "winter": false },
	"citrus": { "spring": false, "summer": false, "autumn": true, "winter": true }
}
OpçãoTipoPadrãoDescrição
rowsGridAxisDef[](obrigatório)Definições de linhas: { key, label, image? }.
columnsGridAxisDef[](obrigatório)Definições de colunas: { key, label, image? }.
cell"toggle" | "text" | "number" | "select""toggle"Tipo de input de célula, aplicado uniformemente a cada célula.
cellOptionsstring[] | Array<{ label, value }>[]Obrigatório quando cell é "select".
helpTextstringTexto de ajuda exibido abaixo do widget.

tags

Um input estilo chip para arrays de strings. Suporta uma lista fixa de suggestions, valores personalizados de forma livre (alternáveis), transformações de maiúsculas/minúsculas e um max opcional. A seguinte definição de campo configura um input de tags de palavras-chave:

{
	"slug": "keywords",
	"type": "json",
	"widget": "field-kit:tags",
	"options": {
		"placeholder": "Add a keyword…",
		"max": 10,
		"transform": "lowercase",
		"allowCustom": true,
		"suggestions": ["vegan", "vegetarian", "gluten-free", "dairy-free", "nut-free"]
	}
}

Valor armazenado: ["vegan", "gluten-free"].

Pressione Enter ou , para confirmar uma tag. Backspace em um input vazio remove a última tag. Tags duplicadas são ignoradas silenciosamente.

OpçãoTipoPadrãoDescrição
placeholderstring"Add..."Placeholder de input exibido quando não há tags presentes.
maxnumberNúmero máximo de tags. O input se esconde no limite.
suggestionsstring[][]Sugestões de autocomplete exibidas via <datalist>.
allowCustombooleantrueQuando false, apenas valores de suggestions podem ser adicionados.
transform"none" | "lowercase" | "uppercase" | "trim""none"Normalizar tags à medida que são adicionadas.
helpTextstringTexto de ajuda exibido abaixo do widget.

Subcampos

object-form e list aceitam um array options.fields de definições de subcampos tipados. Cada entrada tem uma key (a chave do objeto JSON em que escreve), um label, um type e extras específicos do tipo.

Tipo de subcampoRenderizado comoExtras notáveis
textInput de linha únicaplaceholder
textareaInput multilinharows (padrão 3), placeholder
numberInput numéricomin, max, step, prefix, suffix, placeholder
booleanInterruptor de alternância
selectMenu suspensooptions: string[] | Array<{ label, value }>, placeholder
dateInput de data
colorSeletor de cor nativo emparelhado com um input de texto hexadecimal
urlInput de URL (HTML5 type="url")placeholder

Propriedades comuns em cada subcampo: required, helpText, defaultValue.

Templates de resumo

O widget list renderiza cada linha recolhida usando um template estilo Mustache em options.summary. {{key}} é substituído pelo valor da linha para essa chave (convertido para string). Valores falsy retornam para "{itemLabel} {n}". O seguinte template combina duas chaves:

"summary": "{{name}} — {{amount}}"

Renderiza linhas como Flour — 500g. O template é substituição de string simples — sem HTML, sem expressões aninhadas.

Durabilidade de dados

Os widgets do Field Kit armazenam JSON simples na coluna existente do campo, usando apenas essa coluna. Se você remover @emdash-cms/plugin-field-kit da sua configuração, os dados permanecem válidos — o campo reverte para o input de texto json padrão.

Isso se aplica mesmo quando você muda a forma do widget: chaves desconhecidas em objetos armazenados são preservadas na próxima gravação, para que você possa evoluir um esquema sem perder dados capturados sob um conjunto de campos mais antigo.

Veja também