
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
@autoviews/core
Advanced tools
AutoViews
is a set of utilities and abstractions which provides functionality to automatically build UI on top of JSONSchema
.
To build UI automatically AutoViews
uses some abstractions:
JSONSchema
, data
, optional UISchema
as prop and ComponentsRepo
as components
property in context
and renders accordinglystring
, object
and others, even custom data types) and optionally with theirs predicate
's, which are boolean returning functions that defines ability of this component to render this JSONSchema
node.JSON
that describes specific rules to render that specific JSONSchema
node:
ComponentsRepo
should be chosen to get component,UIHints
to applyEach component which is depends on state or other variables could decide which UISchema
to use for render or return custom render result.
To address specific JSONSchema
node UISchema
uses JSONPointer as key and ComponentOptions as value to tell which component and it's setting to use, or what UIHints
have to be applied.
AutoView
is component that will automatically render data
which is validated with given JSONSchema
with components registered in ComponentsRepo
and pathed through RepositoryProvider
.
To choose what specific component to be used and what UIHints
have to be considered AutoView
uses UISchema
object and utilities.
ComponentsRepo
is class which accepts string name
and optional getType
function as constructor parameter.
ComponentsRepo
instance should be provided to the AutoView
context.
import {
RepositoryProvider,
AutoView,
CoreSchemaMetaSchema,
UISchema
} from '@autoviews/core';
<RepositoryProvider components={repoInstance}>
<AutoView {...props} />
</RepositoryProvider>;
getType
getType
allows you to define how to calculate data type for the JSONSchema
nodes. Return value is string
. This string used to register component records.
By default it is type
field. However you might find it useful for enum
, because in JSONSchema
enum type is string
. This example resolves this problem:
const repo = new ComponentsRepo('myRepo', node =>
'enum' in node ? 'enum' : node.type
);
repo.register('enum', {name: 'select', component: SelectComponent});
However, as mentioned, you can return any string
value.
For example, if your JSONSchema
has own type system, you can return somethings like
const repo = new ComponentsRepo('myRepo', node => node.myCustomType);
repo.register('user', {name: 'user-card', component: UserCardComponent});
Once you did instance, you can assign component records to data types
const repo = new ComponentsRepo('editComponents');
repo.register('number', {name: 'number-input', component: NumberInput});
Note: it is not possible to register()
component record with existing name
value, .register()
will throw an error in this case.
You can have as many component records assigned to certain data type as you want.
If you need more then one, you may want to add predicate
function during registering:
const hasMinMax = node =>
node.hasOwnProperty('minimum') && node.hasOwnProperty('maximum');
repo.register('number', {
name: 'slider',
component: Slider,
predicate: hasMinMax
});
repo.getMatched({type: 'number', minimum: 0, maximum: 10});
Will return array of available component records in registration order
[
{name: 'number-input', component: NumberInput},
{name: 'slider', predicate: hasMinMax, component: SliderInput}
];
By default AutoView
will pick last component record in getMatched
array, unless there is other component specified in UISchema
.
It is possible to clone repository with all records with clone
method.
const edit = new ComponentsRepo('edit');
repo.register('number', {name: 'number-input', component: NumberInput});
const form = edit.clone('form');
repo.register('object', {name: 'myForm', component: Form});
clone
also allows to override getType
const edit = new ComponentsRepo('edit', node => node.type);
const form = edit.clone('form', node => node.customTypeField);
You can wrap all or some components into the wrappers
const edit = new ComponentsRepo('edit');
repo.register('number', {name: 'number-input', component: NumberInput});
repo.register('string', {name: 'text-input', component: TextInput});
repo.addWrapper((item, props) => (
<div data-automation-id={`${props.pointer}#TEST`}>
<h3>{props.schema.title}</h3>
{item}
</div>
));
example above will wrap all components in repository, however it is possible to specify which components you want to wrap with include
and exclude
rules.
Both include
and exclude
are optional arrays of components names, used in register
function.
This will wrap only number-input
component.
repo.addWrapper(
(item, props) => (
<div data-automation-id={`${props.pointer}#TEST`}>
<h3>{props.schema.title}</h3>
{item}
</div>
),
{
include: ['number-input']
}
);
This will wrap all components except number-input
repo.addWrapper(
(item, props) => (
<div data-automation-id={`${props.pointer}#TEST`}>
<h3>{props.schema.title}</h3>
{item}
</div>
),
{
exclude: ['number-input']
}
);
You can remove previously registered component record by calling .remove(componentName)
repo.register('string', {name: 'string-component', component: SomeComponent});
//...
repo.remove('string-component');
You can replace component record with another one:
repo.register('number', {
name: 'number-input',
component: OldComponent
});
repo.replace('MyNumberComponent', oldRecord => ({
...oldRecord,
name: 'new-number-input',
component: NewComponent
}));
Yes, you're right, name could be changed as well. Basically that means that the new component record will have same index (order) as old one.
You can replace many existing component records with another one. It might be useful if you want to replace original components with higher order component.
Same as addWrapper
this method allows you to define include
and exclude
options.
Both include
and exclude
are optional arrays of components names, used in register
function.
repo.replaceAll(
record => {
const OriginalComponent = record.component;
return {
...record,
component: props => <OriginalComponent {...doSomethingWithProps(props)} />
};
},
{
include: ['number-input', 'text-input']
}
);
Components in ComponentsRepo
may have AutoViewProps
props interface which has optional onChange?: AutoEventHandler
and onClick?: AutoEventHandler
.
AutoEventHandler
is object with next type:
type AutoEventHandler = (
e: React.SyntheticEvent<HTMLElement>,
autoEvent: AutoEvent
) => void;
where AutoEvent
is something very special:
interface AutoEvent {
schemaPointer: string;
pointer: string;
patch?: Operation[];
}
This events may have JSONPatch operations on given data, which should be handled by application that uses AutoView
.
This library provides handy event handlers creators for each JSONPatch
operation.
UISchema
is an object that contains information about how to render JSONSchema
.
There is a corresponding type UISchema
.
Here we create a new UISchema
and assign our editComponents
repository to the UISchema
.
Example is valid for geo schema
repo.register('string', {name: 'input', component: TextInput}
repo.register('string', {name: 'coordinateInput', component: CoordinateInput}
const uiSchema = createUISchema({
editComponents: { // key is repository `name`.
'/properties/longitude', {name: 'coordinateInput'},
'/properties/latitude', {name: 'coordinateInput'},
}
});
// ...
<RepositoryProvider components={repo}>
<AutoView
{...props}
uiSchema={uiSchema}
/>
</RepositoryProvider>
So with the appropriate JSONSchema
and data
properties the AutoView
component will render assigned components from the UIHints
at the given JSONPointer
's
Component may take some options.
When choosing specific component to render certain data type in UISchema
you may also set it's options
.
const overrides = createUISchema({
viewComponents: {
'': {name: 'uppercasable', options: {uppercase: true}}
}
});
const {select} = clientRenderer.render(
<RepositoryProvider components={repo}>
<AutoView
schema={schema}
data="foo"
uiSchema={overrides}
/>
</RepositoryProvider>
);
In this case component that is registered in viewComponents
components repository by string
type with name uppercasable
should get options
and accordingly to value of option name uppercase
make data: string = 'foo'
prop — uppercased in render result.
UISchema
contains not only rules for one or multiple ComponentsRepo
but also keeps list of UIHints
which are specific rules for data type. Thus, components which are implementing certain type of data may consider that UIHints
.
Same as for ComponentsRepo
overrides, UIHints
uses JSONPointer
s.
At the following example we have special UIHints
for root JSONSchema
which says what order should it have.
Each component that assigned to type object
in repo may consider order
and hidden
hint and render result accordingly.
This repo contains AutoFields
component which take into consideration order
and hidden
and will consider other object related UIHints
.
const schema: CoreSchemaMetaSchema = {
type: 'object',
properties: {
first: {type: 'string'},
second: {type: 'string'},
third: {type: 'string'},
fourth: {type: 'string'},
fifth: {type: 'string'},
sixth: {type: 'string'}
}
};
const ObjectFields = props => (
<fieldset>
<AutoFields {...props} />
</fieldset>
);
const repo = new ComponentsRepo('editComponents');
repo.register('string', {name: 'input', component: TextInput}
repo.register('object', {name: 'fields', component: ObjectFields}
const uiSchema = createUISchema({}, {
'': {
order: ['second', 'third', 'first'],
hidden: ['fourth', 'sixth']
}
});
// ...
<RepositoryProvider components={repo}>
<AutoView
schema={schema}
uiSchema={uiSchema}
data={{
first: '',
second: '',
third: '',
fourth: '',
fifth: '',
sixth: ''
}}
/>
</RepositoryProvider>
So this example will render data
fields with input
in order which is defined in UIHints
.
There are functions to change UISchema
type values in an immutable way:
Adding/changing UIHints
:
const emptyUISchema = createUISchema();
const uiSchemaWithHints = setUIHints(
'/path/in/data',
{order: ['second', 'third', 'first']},
emptyUISchema
);
Retrieving UIHints
:
const hints = getUIHints('/path/in/data', uiSchemaWithHints);
Removing UIHints
:
const uiSchemaWithoutHints = unsetUIHints('/path/in/data', uiSchemaWithHints);
Adding/changing component options:
const emptyUISchema = createUISchema();
const uiSchemaWithComponent = setComponent(
'repositoryName',
'/path/in/data',
{name: 'uppercasable', options: {uppercase: true}},
original
);
Retrieving component options;
const componentOptions = getComponent(
'repositoryName',
'/path/in/data',
uiSchemaWithComponent
);
Removing component:
const uiSchemaWithoutComponent = unsetComponent(
'repositoryName',
'/path/in/data',
uiSchemaWithComponent
);
FAQs
TODO
The npm package @autoviews/core receives a total of 19 weekly downloads. As such, @autoviews/core popularity was classified as not popular.
We found that @autoviews/core demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.