Skip to content
Snippets Groups Projects
Commit 4fb9af89 authored by David Sehnal's avatar David Sehnal
Browse files

tables

parent a81464dd
Branches
Tags
No related merge requests found
...@@ -69,6 +69,27 @@ describe('table', () => { ...@@ -69,6 +69,27 @@ describe('table', () => {
expect(t.n.toArray()).toEqual(['row1', 'row2']); expect(t.n.toArray()).toEqual(['row1', 'row2']);
}); });
it('ofArrays', () => {
const t = Table.ofArrays<typeof schema>(schema, {
x: [10, -1],
n: ['row1', 'row2'],
});
expect(t.x.toArray()).toEqual([10, -1]);
expect(t.n.toArray()).toEqual(['row1', 'row2']);
});
it('pickColumns', () => {
const t = Table.ofColumns<typeof schema>({
x: Column.ofArray({ array: [10, -1], type: Column.Type.int }),
n: Column.ofArray({ array: ['row1', 'row2'], type: Column.Type.str }),
});
const s = { x: Column.Type.int };
const picked = Table.pickColumns(s, t);
expect(picked._columns).toEqual(['x']);
expect(picked._rowCount).toEqual(2);
expect(picked.x.toArray()).toEqual([10, -1]);
});
it('sort', () => { it('sort', () => {
const t = Table.ofColumns<typeof schema>({ const t = Table.ofColumns<typeof schema>({
x: Column.ofArray({ array: [10, -1], type: Column.Type.int }), x: Column.ofArray({ array: [10, -1], type: Column.Type.int }),
......
...@@ -17,18 +17,24 @@ interface Column<T> { ...@@ -17,18 +17,24 @@ interface Column<T> {
} }
namespace Column { namespace Column {
export type Type = typeof Type.str | typeof Type.int | typeof Type.float | Type.Vector | Type.Matrix export type Type<T = any> = Type.Str | Type.Int | Type.Float | Type.Vector | Type.Matrix | Type.Aliased<T>
export namespace Type { export namespace Type {
export const str = { T: '' as string, kind: 'str' as 'str' }; export type Str = { T: string, kind: 'str' }
export const int = { T: 0 as number, kind: 'int' as 'int' }; export type Int = { T: number, kind: 'int' }
export const float = { T: 0 as number, kind: 'float' as 'float' }; export type Float = { T: number, kind: 'float' }
export type Vector = { T: number[], dim: number, kind: 'vector' }; export type Vector = { T: number[], dim: number, kind: 'vector' };
export type Matrix = { T: number[][], rows: number, cols: number, kind: 'matrix' }; export type Matrix = { T: number[][], rows: number, cols: number, kind: 'matrix' };
export type Aliased<T> = { T: T } & { kind: 'str' | 'int' | 'float' }
export const str: Str = { T: '', kind: 'str' };
export const int: Int = { T: 0, kind: 'int' };
export const float: Float = { T: 0, kind: 'float' };
export function vector(dim: number): Vector { return { T: [] as number[], dim, kind: 'vector' }; } export function vector(dim: number): Vector { return { T: [] as number[], dim, kind: 'vector' }; }
export function matrix(rows: number, cols: number): Matrix { return { T: [] as number[][], rows, cols, kind: 'matrix' }; } export function matrix(rows: number, cols: number): Matrix { return { T: [] as number[][], rows, cols, kind: 'matrix' }; }
export function aliased<T>(t: Type): Aliased<T> { return t as any as Aliased<T>; }
} }
export interface ToArrayParams { export interface ToArrayParams {
......
...@@ -9,10 +9,21 @@ import { sortArray } from './sort' ...@@ -9,10 +9,21 @@ import { sortArray } from './sort'
type Table<Schema extends Table.Schema> = { readonly _rowCount: number, readonly _columns: ReadonlyArray<string> } & Table.Columns<Schema> type Table<Schema extends Table.Schema> = { readonly _rowCount: number, readonly _columns: ReadonlyArray<string> } & Table.Columns<Schema>
/** An immutable table */
namespace Table { namespace Table {
export type Schema = { [field: string]: Column.Type } export type Schema = { [field: string]: Column.Type }
export type Columns<S extends Schema> = { [C in keyof S]: Column<S[C]['T']> } export type Columns<S extends Schema> = { [C in keyof S]: Column<S[C]['T']> }
export type Row<S extends Schema> = { [C in keyof S]: S[C]['T'] } export type Row<S extends Schema> = { [C in keyof S]: S[C]['T'] }
export type Arrays<S extends Schema> = { [C in keyof S]: ArrayLike<S[C]['T']> }
export function pickColumns<S extends Schema, T extends S>(schema: S, table: Table<T>): Table<S> {
const ret = Object.create(null);
const keys = Object.keys(schema);
ret._rowCount = table._rowCount;
ret._columns = keys;
for (const k of keys) ret[k] = table[k];
return ret;
}
export function ofColumns<S extends Schema, R extends Table<S> = Table<S>>(columns: Columns<S>): R { export function ofColumns<S extends Schema, R extends Table<S> = Table<S>>(columns: Columns<S>): R {
const _columns = Object.keys(columns); const _columns = Object.keys(columns);
...@@ -26,7 +37,7 @@ namespace Table { ...@@ -26,7 +37,7 @@ namespace Table {
const columns = Object.keys(schema); const columns = Object.keys(schema);
ret._rowCount = rowCount; ret._rowCount = rowCount;
ret._columns = columns; ret._columns = columns;
for (const k of Object.keys(schema)) { for (const k of columns) {
(ret as any)[k] = Column.ofLambda({ (ret as any)[k] = Column.ofLambda({
rowCount, rowCount,
type: schema[k], type: schema[k],
...@@ -37,6 +48,17 @@ namespace Table { ...@@ -37,6 +48,17 @@ namespace Table {
return ret as R; return ret as R;
} }
export function ofArrays<S extends Schema, R extends Table<S> = Table<S>>(schema: Schema, arrays: Arrays<S>): R {
const ret = Object.create(null);
const columns = Object.keys(schema);
ret._rowCount = arrays[columns[0]].length;
ret._columns = columns;
for (const k of Object.keys(schema)) {
(ret as any)[k] = Column.ofArray({ array: arrays[k], type: schema[k] })
}
return ret as R;
}
/** Sort and return a new table */ /** Sort and return a new table */
export function sort<T extends Table<S>, S extends Schema>(table: T, cmp: (i: number, j: number) => number) { export function sort<T extends Table<S>, S extends Schema>(table: T, cmp: (i: number, j: number) => number) {
const indices = new Int32Array(table._rowCount); const indices = new Int32Array(table._rowCount);
......
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
*/ */
import Column from '../../../mol-base/collections/column' import Column from '../../../mol-base/collections/column'
import { Shape as mmCIF } from '../../../mol-io/reader/cif/schema/mmcif' import Table from '../../../mol-base/collections/table'
import { Schema as mmCIF } from '../../../mol-io/reader/cif/schema/mmcif'
export interface ElementSymbol extends String { '@type': 'element-symbol' } export interface ElementSymbol extends String { '@type': 'element-symbol' }
export function ElementSymbol(s: string): ElementSymbol { export function ElementSymbol(s: string): ElementSymbol {
...@@ -13,50 +14,55 @@ export function ElementSymbol(s: string): ElementSymbol { ...@@ -13,50 +14,55 @@ export function ElementSymbol(s: string): ElementSymbol {
return s.toUpperCase() as any; return s.toUpperCase() as any;
} }
type Key = { key: Column<number> } export const AtomsSchema = {
type_symbol: Column.Type.aliased<ElementSymbol>(mmCIF.atom_site.type_symbol),
type _Atoms = Pick<mmCIF['atom_site'], label_atom_id: mmCIF.atom_site.label_atom_id,
| 'type_symbol' auth_atom_id: mmCIF.atom_site.auth_atom_id,
| 'label_atom_id' label_alt_id: mmCIF.atom_site.label_alt_id,
| 'auth_atom_id' pdbx_formal_charge: mmCIF.atom_site.pdbx_formal_charge,
| 'label_alt_id' occupancy: mmCIF.atom_site.occupancy,
| 'pdbx_formal_charge' B_iso_or_equiv: mmCIF.atom_site.B_iso_or_equiv,
| 'occupancy'
| 'B_iso_or_equiv'> key: Column.Type.int,
& Key source_row: Column.Type.int,
export interface Atoms extends _Atoms { };
source_row: Column<number>
} export interface Atoms extends Table<typeof AtomsSchema> { }
export const ResiduesSchema = {
group_PDB: mmCIF.atom_site.group_PDB,
label_comp_id: mmCIF.atom_site.label_comp_id,
auth_comp_id: mmCIF.atom_site.auth_comp_id,
label_seq_id: mmCIF.atom_site.label_seq_id,
auth_seq_id: mmCIF.atom_site.auth_seq_id,
pdbx_PDB_ins_code: mmCIF.atom_site.pdbx_PDB_ins_code,
type _Residues = Pick<mmCIF['atom_site'], key: Column.Type.int
| 'group_PDB' };
| 'label_comp_id'
| 'auth_comp_id' export interface Residues extends Table<typeof AtomsSchema> { }
| 'label_seq_id'
| 'auth_seq_id' export const ChainsSchema = {
| 'pdbx_PDB_ins_code'> label_asym_id: mmCIF.atom_site.label_asym_id,
& Key auth_asym_id: mmCIF.atom_site.auth_asym_id,
export interface Residues extends _Residues { } auth_comp_id: mmCIF.atom_site.auth_comp_id,
label_entity_id: mmCIF.atom_site.label_entity_id,
type _Chains = Pick<mmCIF['atom_site'], pdbx_PDB_model_num: mmCIF.atom_site.pdbx_PDB_model_num,
| 'label_asym_id'
| 'auth_asym_id' key: Column.Type.int,
| 'auth_comp_id' entityIndex: Column.Type.int
| 'label_entity_id'
| 'pdbx_PDB_model_num'>
& Key
export interface Chains extends _Chains {
enityDataIndex: Column<number>
} }
type _EntityData = mmCIF['entity'] export interface Chains extends Table<typeof ChainsSchema> { }
export interface EntityData extends _EntityData { }
export const EntitySchema = mmCIF['entity']
export interface Entities extends Table<typeof EntitySchema> { }
export interface Macromolecule { export interface Macromolecule {
atoms: Atoms, atoms: Atoms,
residues: Residues, residues: Residues,
chains: Chains, chains: Chains,
entityData: EntityData entities: Entities
} }
export default Macromolecule export default Macromolecule
\ No newline at end of file
...@@ -21,7 +21,7 @@ const testBlock = Data.Block({ ...@@ -21,7 +21,7 @@ const testBlock = Data.Block({
}, 'test'); }, 'test');
namespace TestSchema { namespace TestSchema {
export const atoms = { x: Schema.Field.int(), name: Schema.Field.str() } export const atoms = { x: Schema.Types.int, name: Schema.Types.str }
export const schema = { atoms } export const schema = { atoms }
} }
......
...@@ -6,59 +6,46 @@ ...@@ -6,59 +6,46 @@
import * as Data from './data-model' import * as Data from './data-model'
import Column, { createAndFillArray } from '../../../mol-base/collections/column' import Column, { createAndFillArray } from '../../../mol-base/collections/column'
import Table from '../../../mol-base/collections/table'
/**
* A schema defines the shape of categories and fields.
*
* @example:
* const atom_site = {
* '@alias': '_atom_site',
* label_atom_id: Field.str(),
* Cartn_x: Field.float(),
* Cartn_y: Field.float(),
* Cartn_z: Field.float(),
* }
*
* const mmCIF = { atom_site };
*/
//////////////////////////////////////////////
export function toTypedFrame<Schema extends FrameSchema, Frame extends TypedFrame<Schema> = TypedFrame<Schema>>(schema: Schema, frame: Data.Frame): Frame { export function toTypedFrame<Schema extends FrameSchema, Frame extends TypedFrame<Schema> = TypedFrame<Schema>>(schema: Schema, frame: Data.Frame): Frame {
return createTypedFrame(schema, frame) as Frame; return createTypedFrame(schema, frame) as Frame;
} }
export function toTypedCategory<Schema extends CategorySchema>(schema: Schema, category: Data.Category): TypedCategory<Schema> { export function toTable<Schema extends Table.Schema, R extends Table<Schema> = Table<Schema>>(schema: Schema, category: Data.Category): R {
return new _TypedCategory(category, schema, true) as TypedCategory<any>; return new _TypedCategory(category, schema, true) as any;
} }
export type FrameSchema = { [category: string]: CategorySchema } export const Types = Column.Type
export type TypedFrameShape<Schema extends FrameSchema> = { [C in keyof Schema]: TypedCategoryShape<Schema[C]> }
export type FrameSchema = { [category: string]: Table.Schema }
export type TypedFrame<Schema extends FrameSchema> = { export type TypedFrame<Schema extends FrameSchema> = {
readonly _header?: string, readonly _header?: string,
readonly _frame: Data.Frame readonly _frame: Data.Frame
} & { [C in keyof Schema]: TypedCategory<Schema[C]> } } & { [C in keyof Schema]: Table<Schema[C]> }
export type CategorySchema = { [field: string]: Field.Schema<any> } type ColumnCtor = (field: Data.Field, category: Data.Category, key: string) => Column<any>
export type TypedCategoryShape<Schema extends CategorySchema> = { [F in keyof Schema]: Column<Schema[F]['T']> }
export type TypedCategory<Schema extends CategorySchema> = {
readonly _rowCount: number,
readonly _isDefined: boolean,
readonly _category: Data.Category
} & { [F in keyof Schema]: Column<Schema[F]['T']> }
export namespace Field { function getColumnCtor(t: Column.Type): ColumnCtor {
export interface Schema<T> { T: T, ctor: (field: Data.Field, category: Data.Category, key: string) => Column<T>, undefinedField: (c: number) => Data.Field, alias?: string }; switch (t.kind) {
export interface Spec { undefinedField?: (c: number) => Data.Field, alias?: string } case 'str': return (f, c, k) => createColumn(Column.Type.str, f, f.str, f.toStringArray);
case 'int': return (f, c, k) => createColumn(Column.Type.int, f, f.int, f.toIntArray);
case 'float': return (f, c, k) => createColumn(Column.Type.float, f, f.float, f.toFloatArray);
case 'vector': return (f, c, k) => {
const dim = t.dim;
const value = (row: number) => Data.getVector(c, k, dim, row);
return createColumn(t, f, value, params => createAndFillArray(f.rowCount, value, params));
}
case 'matrix': return (f, c, k) => {
const rows = t.rows, cols = t.cols;
const value = (row: number) => Data.getMatrix(c, k, rows, cols, row);
return createColumn(t, f, value, params => createAndFillArray(f.rowCount, value, params));
}
}
}
export function alias(name: string): Schema<any> { return { alias: name } as any; }
export function str(spec?: Spec) { return createSchema(spec, Str); }
export function int(spec?: Spec) { return createSchema(spec, Int); }
export function float(spec?: Spec) { return createSchema(spec, Float); }
export function vector(rows: number, spec?: Spec) { return createSchema(spec, Vector(rows)); }
export function matrix(rows: number, cols: number, spec?: Spec) { return createSchema(spec, Matrix(rows, cols)); }
function create<T>(type: Column.Type, field: Data.Field, value: (row: number) => T, toArray: Column<T>['toArray']): Column<T> { function createColumn<T>(type: Column.Type, field: Data.Field, value: (row: number) => T, toArray: Column<T>['toArray']): Column<T> {
return { return {
'@type': type, '@type': type,
'@array': field['@array'], '@array': field['@array'],
...@@ -71,30 +58,6 @@ export namespace Field { ...@@ -71,30 +58,6 @@ export namespace Field {
}; };
} }
function Str(field: Data.Field) { return create(Column.Type.str, field, field.str, field.toStringArray); }
function Int(field: Data.Field) { return create(Column.Type.int, field, field.int, field.toIntArray); }
function Float(field: Data.Field) { return create(Column.Type.float, field, field.float, field.toFloatArray); }
function Vector(rows: number) {
return function(field: Data.Field, category: Data.Category, key: string) {
const value = (row: number) => Data.getVector(category, key, rows, row);
return create(Column.Type.vector(rows), field, value, params => createAndFillArray(field.rowCount, value, params));
}
}
function Matrix(rows: number, cols: number) {
return function(field: Data.Field, category: Data.Category, key: string) {
const value = (row: number) => Data.getMatrix(category, key, rows, cols, row);
return create(Column.Type.matrix(rows, cols), field, value, params => createAndFillArray(field.rowCount, value, params));
}
}
// spec argument is to allow for specialised implementation for undefined fields
function createSchema<T>(spec: Spec | undefined, ctor: (field: Data.Field, category: Data.Category, key: string) => Column<T>): Schema<T> {
return { T: 0 as any, ctor, undefinedField: (spec && spec.undefinedField) || Data.DefaultUndefinedField, alias: spec && spec.alias };
}
}
class _TypedFrame implements TypedFrame<any> { // tslint:disable-line:class-name class _TypedFrame implements TypedFrame<any> { // tslint:disable-line:class-name
header = this._frame.header; header = this._frame.header;
constructor(public _frame: Data.Frame, schema: FrameSchema) { constructor(public _frame: Data.Frame, schema: FrameSchema) {
...@@ -104,19 +67,21 @@ class _TypedFrame implements TypedFrame<any> { // tslint:disable-line:class-name ...@@ -104,19 +67,21 @@ class _TypedFrame implements TypedFrame<any> { // tslint:disable-line:class-name
} }
} }
class _TypedCategory implements TypedCategory<any> { // tslint:disable-line:class-name class _TypedCategory implements Table<any> { // tslint:disable-line:class-name
_rowCount = this._category.rowCount; _rowCount = this._category.rowCount;
constructor(public _category: Data.Category, schema: CategorySchema, public _isDefined: boolean) { _columns: ReadonlyArray<string>;
const fieldKeys = Object.keys(schema).filter(k => k !== '@alias'); constructor(public _category: Data.Category, schema: Table.Schema, public _isDefined: boolean) {
const fieldKeys = Object.keys(schema);
this._columns = fieldKeys;
const cache = Object.create(null); const cache = Object.create(null);
for (const k of fieldKeys) { for (const k of fieldKeys) {
const s = schema[k]; const cType = schema[k];
const ctor = getColumnCtor(cType);
Object.defineProperty(this, k, { Object.defineProperty(this, k, {
get: function() { get: function() {
if (cache[k]) return cache[k]; if (cache[k]) return cache[k];
const name = s.alias || k; const field = _category.getField(k);
const field = _category.getField(name) || s.undefinedField(_category.rowCount); cache[k] = !!field ? ctor(field, _category, k) : Column.Undefined(_category.rowCount, cType);
cache[k] = s.ctor(field, _category, name);
return cache[k]; return cache[k];
}, },
enumerable: true, enumerable: true,
...@@ -130,9 +95,7 @@ function createTypedFrame(schema: FrameSchema, frame: Data.Frame): any { ...@@ -130,9 +95,7 @@ function createTypedFrame(schema: FrameSchema, frame: Data.Frame): any {
return new _TypedFrame(frame, schema); return new _TypedFrame(frame, schema);
} }
function createTypedCategory(key: string, schema: CategorySchema, frame: Data.Frame) { function createTypedCategory(key: string, schema: Table.Schema, frame: Data.Frame) {
const alias = (schema['@alias'] && schema['@alias'].alias) || key; const cat = frame.categories[key[0] === '_' ? key : '_' + key];
const name = alias[0] === '_' ? alias : '_' + alias;
const cat = frame.categories[name];
return new _TypedCategory(cat || Data.Category.Empty, schema, !!cat); return new _TypedCategory(cat || Data.Category.Empty, schema, !!cat);
} }
\ No newline at end of file
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
import { Field, TypedFrame } from '../schema' import { Types, TypedFrame } from '../schema'
const str = Field.str() const str = Types.str
const float = Field.float() const float = Types.float
const datablock = { const datablock = {
id: str, id: str,
...@@ -58,7 +58,7 @@ const item_units_conversion = { ...@@ -58,7 +58,7 @@ const item_units_conversion = {
// TODO save frame dic schema // TODO save frame dic schema
const dic = { export const Schema = {
datablock, datablock,
dictionary, dictionary,
dictionary_history, dictionary_history,
...@@ -69,5 +69,7 @@ const dic = { ...@@ -69,5 +69,7 @@ const dic = {
item_units_conversion item_units_conversion
} }
type dic = TypedFrame<typeof dic> export interface Frame extends TypedFrame<typeof Schema> { }
export default dic
// type dic = TypedFrame<typeof dic>
//export default dic
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
*/ */
import { Field, TypedFrame, TypedFrameShape } from '../schema' import { Types, TypedFrame } from '../schema'
const str = Field.str(); const str = Types.str;
const int = Field.int(); const int = Types.int;
const float = Field.float(); const float = Types.float;
const entry = { const entry = {
id: str id: str
...@@ -18,7 +18,7 @@ type EntityType = 'polymer' | 'non-polymer' | 'water' ...@@ -18,7 +18,7 @@ type EntityType = 'polymer' | 'non-polymer' | 'water'
const entity = { const entity = {
id: str, id: str,
type: str as Field.Schema<EntityType>, type: Types.aliased<EntityType>(str),
src_method: str, src_method: str,
pdbx_description: str, pdbx_description: str,
formula_weight: float, formula_weight: float,
...@@ -48,8 +48,8 @@ const cell = { ...@@ -48,8 +48,8 @@ const cell = {
const symmetry = { const symmetry = {
entry_id: str, entry_id: str,
space_group_name_HM: Field.str({ alias: 'space_group_name_H-M' }), 'space_group_name_H-M': str,
pdbx_full_space_group_name_HM: Field.str({ alias: 'pdbx_full_space_group_name_H-M' }), 'pdbx_full_space_group_name_H': str,
cell_setting: str, cell_setting: str,
Int_Tables_number: int, Int_Tables_number: int,
space_group_name_Hall: str space_group_name_Hall: str
...@@ -117,7 +117,7 @@ type BondValueOrder = ...@@ -117,7 +117,7 @@ type BondValueOrder =
const struct_conn = { const struct_conn = {
id: str, id: str,
conn_type_id: str as Field.Schema<StructConnTypeId>, conn_type_id: Types.aliased<StructConnTypeId>(str),
pdbx_PDB_id: str, pdbx_PDB_id: str,
ptnr1_label_asym_id: str, ptnr1_label_asym_id: str,
ptnr1_label_comp_id: str, ptnr1_label_comp_id: str,
...@@ -148,11 +148,11 @@ const struct_conn = { ...@@ -148,11 +148,11 @@ const struct_conn = {
pdbx_ptnr3_PDB_ins_code: str, pdbx_ptnr3_PDB_ins_code: str,
details: str, details: str,
pdbx_dist_value: float, pdbx_dist_value: float,
pdbx_value_order: str as Field.Schema<BondValueOrder> pdbx_value_order: Types.aliased<BondValueOrder>(str)
} }
const struct_conn_type = { const struct_conn_type = {
id: str as Field.Schema<StructConnTypeId>, id: Types.aliased<StructConnTypeId>(str),
criteria: str, criteria: str,
reference: str reference: str
} }
...@@ -161,10 +161,10 @@ const chem_comp_bond = { ...@@ -161,10 +161,10 @@ const chem_comp_bond = {
comp_id: str, comp_id: str,
pdbx_stereo_config: str, pdbx_stereo_config: str,
pdbx_ordinal: int, pdbx_ordinal: int,
pdbx_aromatic_flag: str as Field.Schema<'Y' | 'N'>, pdbx_aromatic_flag: Types.aliased<'Y' | 'N'>(str),
atom_id_1: str, atom_id_1: str,
atom_id_2: str, atom_id_2: str,
value_order: str as Field.Schema<BondValueOrder> value_order: Types.aliased<BondValueOrder>(str)
} }
const pdbx_struct_assembly = { const pdbx_struct_assembly = {
...@@ -186,8 +186,8 @@ const pdbx_struct_oper_list = { ...@@ -186,8 +186,8 @@ const pdbx_struct_oper_list = {
type: str, type: str,
name: str, name: str,
symmetry_operation: str, symmetry_operation: str,
matrix: Field.matrix(3, 3), matrix: Types.matrix(3, 3),
vector: Field.vector(3) vector: Types.vector(3)
} }
const pdbx_struct_mod_residue = { const pdbx_struct_mod_residue = {
...@@ -246,4 +246,3 @@ export const Schema = { ...@@ -246,4 +246,3 @@ export const Schema = {
}; };
export interface Frame extends TypedFrame<typeof Schema> { } export interface Frame extends TypedFrame<typeof Schema> { }
\ No newline at end of file
export interface Shape extends TypedFrameShape<typeof Schema> { }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment