Skip to content
Twilight React Playground
ثيم رائدaren

DevSchema types

typeAdvanced

The simplified shape of twilight.json settings and components that virtual:twilight/schema exports and DevSettingsWidget draws.

import { DevSchema, DevSchemaField, DevSchemaComponent, DevSchemaOption, DevFieldKind } from '@salla.sa/twilight-theme-engine/dev';

In plain words

twilight.json describes each setting in the dashboard's vocabulary: a type and a format per field. The dev server turns that into a simpler list the dev widget can draw: for each field, which control to show (kind), its label and its default value.

These types describe that list. They are TypeScript shapes only, removed when the theme builds. You meet them when you type a schema by hand, as the dev widget's live demo does.

Signature

type DevFieldKind = 'toggle' | 'select' | 'text' | 'readonly';

interface DevSchemaOption { label: string; value: string }

interface DevSchemaField {
  id: string;                  // the twilight.json id, also the override key
  label: string;               // the entry's label, else its id
  kind: DevFieldKind;
  default: unknown;            // null for readonly fields
  options?: DevSchemaOption[]; // select only
  note?: string;               // readonly only: why, e.g. 'remote (products)'
}

interface DevSchemaComponent {
  path: string;                // 'home.brands'; falls back to the component's key
  title: string;               // title.en, else title.ar, else path
  fields: DevSchemaField[];
}

interface DevSchema {
  settings: DevSchemaField[];
  components: DevSchemaComponent[];
  settingsDefaults: Record<string, unknown>;                   // editable settings only
  componentDefaults: Record<string, Record<string, unknown>>;  // by component path
}

Example

app/dev/sample-schema.ts
import type { DevSchema } from '@salla.sa/twilight-theme-engine/dev';

// What the dev server builds from:
//   { "id": "footer_is_dark", "type": "boolean", "format": "switch", "label": "Dark footer", "value": false }
//   { "id": "brands", "type": "items", "format": "dropdown-list", "label": "Brands", "source": "brands" }
export const sampleSchema: DevSchema = {
  settings: [
    { id: 'footer_is_dark', label: 'Dark footer', kind: 'toggle', default: false },
    {
      id: 'brands',
      label: 'Brands',
      kind: 'readonly',
      default: null,
      note: 'remote (brands)',
    },
  ],
  components: [],
  settingsDefaults: { footer_is_dark: false },
  componentDefaults: {},
};

How it behaves

  • type: boolean becomes toggle, with value as the default when it is a boolean, else false.

  • type: items with format: dropdown-list and inline options becomes select; its default is the first of value, then selected, then the first option. Without inline options it is readonly with the note remote (<source>).

  • type: string with format text, textarea, image, icon or line becomes text, with value as the default when it is a string, else ''.

  • type: static is skipped. Anything else (collection, variable-list, number, an unknown type) is readonly with the note <type>/<format>. Entries without an id, and components without path or key, are dropped.

  • virtual:twilight/schema has the same shape, declared separately in the engine's dist/ambient/virtual-modules.d.ts, which a theme lists under files in tsconfig.json (as packages/theme-custom/tsconfig.json does).

Gotchas

  • The function that builds a DevSchema from twilight.json is not exported, and neither is the empty schema. A schema made outside the dev server has to be written by hand, and nothing checks it against your manifest.

  • In a production build virtual:twilight/schema is { settings: [], components: [], settingsDefaults: {}, componentDefaults: {} }, whatever your manifest holds. Code that reads it for anything other than the widget sees nothing once built.

Related

Source and docs