The Web Component Manifest
Any Web Component is or aims to be:
- an HTML tag
- a CSS encapsulated environment
- a JS business logic unit
As HTML tag, a custom Web Component has attributes
and properties
. Moreover a pair attribute
and property
can be coupled by reflecting changes: a change on the former is mirrored on the latter, and viceversa.
Basics
The Configurator layout section queries the Web Components to discover their metadata and their properties/attributes using a static getter promise called a Manifest.
The __manifest
static getter must return a JavaScript object containing information on the component metadata, properties and attributes, and API mocks.
You can use the JSON schema to get information on the supported properties and to check your components manifests.
As an example, consider the following custom button component
import { LitElement } from 'lit'
class MyButton extends LitElement {
static get __manifest() {
return import('./manifest').then(({default: manifest}) => manifest)
}
@property() hidden?: boolean
}
The component exposes the static getter __manifest
thus instructing the Configurator preview section with the following manifest
import type { Manifest } from '@micro-lc/compose-toolkit'
const manifest = {
label: 'My awesome button',
properties: {
hidden: {
type: 'boolean'
}
}
}
export default manifest
Attribute and properties
The component attributes and properties can be described using the properties
key of the manifest, which should be an object mapping the component properties to a JSON schema.
Properties types can be almost anything that JSON schema provides:
boolean
string
number
object
array
- a
oneOf
array of primitives
For each of these, the Configurator layout will provide a consistent form input to edit the property.
Trivially, primitive types boolean
, string
, and number
are simple to edit from a form input.
Complex properties such as objects and arrays are also handled in a no-code
fashion so far the manifest is precise in describing their nested properties.
The most basic visualization for an object
without a schema is an IDE-like editor, with basic JSON validation capabilities. Likewise an array has a no-code
item selector, which again, without schema will spawn an IDE-like editor for each one of its items.
The owner/developer of custom Web Components can enforce no-code
configurability by nesting the component manifest.
For instance:
import { LitElement } from 'lit'
interface Action {
type: 'http-request' | 'file-upload'
url: string
}
class MyButton extends LitElement {
static get __manifest() {
return import('./manifest').then(({default: manifest}) => manifest)
}
@property() action?: Action
}
can be described by the following manifest
import type { Manifest } from '@micro-lc/compose-toolkit'
const manifest: Manifest = {
properties: {
action: {
type: 'object',
properties: {
type: {type: 'string', enum: ['http-request', 'file-upload']},
url: {type: 'string'}
}
}
}
}
export default manifest
Despite the action
being an object, the Configurator layout section will spawn a modal (which can have potentially infinite levels of nesting) to configure type
as a string with at most 2 fixed values and url
as a string.
Mia's Configuration Advanced
The Web Component manifest is a superset of a compliant draft-07 JSON schema. The Configurator guarantees to display a no-code
comfortable version of each property.
Beside this specification, Configurator can enforce some extra logic using a special property, available to any Web Component property or nested property: __mia_configuration
.
Let's consider a custom button
import { LitElement } from 'lit'
class MyButton extends LitElement {
static get __manifest() {
return import('./manifest').then(({default: manifest}) => manifest)
}
@property() hidden?: boolean
}
with manifest
import type { Manifest } from '@micro-lc/compose-toolkit'
const manifest = {
properties: {
hidden: {
type: 'boolean'
__mia_configuration: {
// mia specific configurations
}
}
}
}
export default manifest
The __mia_configuration
object targets the following use cases:
deprecated
▶️ mark a property for deprecationlabel
▶️ The label to show on the form input/editor used to configure the given property. This label supports i18n by supporting both astring
and a dictionary where the key is the language 2 letters code and the translation.description
▶️ helpful when the property configuration is complicated or nested: provides a description tooltip to help the user.docLink
▶️ replaces thedescription
tooltip with a link to external documentationoneOfGuard
▶️ see refoneOfDefault
▶️ allows to select adefault
branch of a JSON schemaoneOf
section.priority
▶️ groups properties in 3 levels inside the Configurator layout section form. Helpful when multiple personas are interacting with the configuration by highlighting those properties which are most likely to be tuned.attribute
▶️ instructs the Configurator layout section that the property is mirrored by an HTML attribute (NOT USED ATM).schema-hint
▶️ Configurator layout section knows some often used property schemas and provides labels to select them instead of writing the whole property JSON schema.shared-key
▶️ Configurator allows to share JSON schema definitions by resolving in-place their references.enumLabels
▶️ provides the capability to i18n-ify string enums
Summarizing the __mia_configuration
property must comply with the following type:
/**
* This interface was referenced by `MiaSchema`'s JSON-Schema
* via the `definition` "__mia_configuration".
*/
export interface MiaConfiguration {
deprecated?:
| boolean
| {
since?: string
description?: LocalizedText
[k: string]: unknown
}
label?: LocalizedText
description?: LocalizedText
docLink?: string
oneOfGuard?: string
oneOfDefault?: number
priority?: "high" | "medium" | "low"
attribute?: boolean | string
"schema-hint"?:
| "localized-text"
| "dynamic-icon"
| "on-off-toggle"
| "color"
| "event"
| "mia/endpoints"
| "mia/endpoints/crud"
| "mia/endpoints/crud-and-generate-data-schema"
| "micro-lc/applications"
"shared-key"?: "back-kit/data-schema" | string
enumLabels?: {
[k: string]: LocalizedText
}
}
The oneOfGuard
key
Suppose your property is a JSON oneOf
an there's a guard key which allows to distinguish non-overlapping types. For instance:
import type { Manifest } from '@micro-lc/compose-toolkit'
const manifest = {
properties: {
action: {
type: 'object',
oneOf: [
{
properties: {
type: {const: 'http-post'},
url: {type: 'string'},
payload: {type: 'string'}
}
},
{
properties: {
type: {const: 'event'},
payload: {type: 'object'}
}
}
]
__mia_configuration: {
oneOfGuard: 'type'
}
}
}
}
export default manifest
By using oneOfGuard
set to type
Configurator layout section is able to provide a no-code
configuration to the property action
by requesting the user to select a type
between http-post
and event
and then the rest of the object.
If the user selects http-post
then 2 string input will appear in order to configure url
and payload
, otherwise an IDE-like editor will allow to type directly the payload
property since no schema was provided.
The schema-hint
key
Configurator provides some types that are well known and often used in order to avoid writing down a repeating JSON schema multiple times.
- A
localized-text
hints for a string or a dictionary of translations - A
dynamic-icon
is a property that complies with the@micro-lc/iconic
icon interface - An
on-off-toggle
is a number, either0
and1
which will be rendered as a boolean toggle - A
color
spawns a color picker - An
event
expects an object with at least 2 properties:- a
label
which must be astring
- and a
payload
which must be anobject
- a
- A
mia/endpoints
spawns a selection with a fixed list of options which are Mia Platform's Console currently available http endpoints. - A
mia/endpoints/crud
is the list ofmia/endpoints
coming from aCRUD Service
microservice. - A
mia/endpoints/data-source
is the list ofmia/endpoints
coming from aCRUD Service
microservice, a Mongo View, a Fast Data projection, or a Fast Data Single View. - A
micro-lc/applications
is the list of currently configured applications in the Configurator initial section.
The shared-key
key
JSON schema supports referencing of property definitions. Despite not being a fixed pattern there's a recommendation for draft-07 which suggests to use the key definitions
at the first level of your JSON configuration. In the most recent drafts it will be substituted by the $defs
keyword.
The following example shows how it works:
{
"definitions": {
"propertyUsedMultipleTimes": {
// property schema
}
},
"type": "object",
"properties": {
"first": {
"$ref": "#/definitions/propertyUsedMultipleTimes"
},
"second": {
"$ref": "#/definitions/propertyUsedMultipleTimes"
}
}
}
The shared-key
property suggests to the Configurator how to group properties using JSON definitions
(refer to the dedicated documentation for more information).