diff --git a/src/mol-plugin/context.ts b/src/mol-plugin/context.ts
index 3a80ae51ce42397b2371fd339113f6816ae21469..a3026c18863f27dd8298ed78f30ce74d331c725e 100644
--- a/src/mol-plugin/context.ts
+++ b/src/mol-plugin/context.ts
@@ -19,6 +19,10 @@ import { Representation } from 'mol-repr/representation';
 import { CreateStructureFromPDBe } from './state/actions/basic';
 import { LogEntry } from 'mol-util/log-entry';
 import { TaskManager } from './util/task-manager';
+import { StructureRepresentationRegistry } from 'mol-repr/structure/registry';
+import { ColorTheme } from 'mol-theme/color';
+import { SizeTheme } from 'mol-theme/size';
+import { ThemeRegistryContext } from 'mol-theme/theme';
 
 export class PluginContext {
     private disposed = false;
@@ -49,6 +53,11 @@ export class PluginContext {
         task: this.tasks.events
     };
 
+    readonly structureReprensentation = {
+        registry: new StructureRepresentationRegistry(),
+        themeCtx: { colorThemeRegistry: new ColorTheme.Registry(), sizeThemeRegistry: new SizeTheme.Registry() } as ThemeRegistryContext
+    }
+
     readonly behaviors = {
         // state: {
         //     data: this.state.dataState.behaviors,
diff --git a/src/mol-plugin/spec.ts b/src/mol-plugin/spec.ts
index 69a6e8683f174e4023d9ba8281072565f518ae7b..2d297190919b18a67f4e76b2fb16880b7f0feefb 100644
--- a/src/mol-plugin/spec.ts
+++ b/src/mol-plugin/spec.ts
@@ -4,8 +4,34 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-interface PluginSpec {
+import { StateAction } from 'mol-state/action';
+import { Transformer } from 'mol-state';
+import { StateTransformParameters } from './ui/state/parameters';
+
+export { PluginSpec }
 
+interface PluginSpec {
+    actions: PluginSpec.Action[],
+    behaviors: PluginSpec.Behavior[]
 }
 
-export { PluginSpec }
\ No newline at end of file
+namespace PluginSpec {
+    export interface Action {
+        action: StateAction | Transformer,
+        customControl?: StateTransformParameters.Class,
+        autoUpdate?: boolean
+    }
+
+    export function Action(action: StateAction | Transformer, params?: { customControl?: StateTransformParameters.Class, autoUpdate?: boolean }): Action {
+        return { action, customControl: params && params.customControl, autoUpdate: params && params.autoUpdate };
+    }
+
+    export interface Behavior {
+        transformer: Transformer,
+        defaultParams?: any
+    }
+
+    export function Behavior<T extends Transformer>(transformer: T, defaultParams?: Transformer.Params<T>): Behavior {
+        return { transformer, defaultParams };
+    }
+}
\ No newline at end of file
diff --git a/src/mol-plugin/state/actions/basic.ts b/src/mol-plugin/state/actions/basic.ts
index 4fdbf9adbd4f7c697c51677371c10583446576b6..b8acbafe85cc39c3dec72a9fc35368f2c7ca6b77 100644
--- a/src/mol-plugin/state/actions/basic.ts
+++ b/src/mol-plugin/state/actions/basic.ts
@@ -9,6 +9,7 @@ import { PluginStateObject } from '../objects';
 import { StateTransforms } from '../transforms';
 import { ParamDefinition as PD } from 'mol-util/param-definition';
 import { StateSelection } from 'mol-state/state/selection';
+import { CartoonParams } from 'mol-repr/structure/representation/cartoon';
 
 export const CreateStructureFromPDBe = StateAction.create<PluginStateObject.Root, void, { id: string }>({
     from: [PluginStateObject.Root],
@@ -45,7 +46,12 @@ export const CreateStructureFromPDBe = StateAction.create<PluginStateObject.Root
             .apply(StateTransforms.Model.CreateModelFromTrajectory, { modelIndex: 0 })
             .apply(StateTransforms.Model.CreateStructureAssembly)
             // .apply(StateTransforms.Model.CreateStructureSelection, { query, label: 'ALA residues' })
-            .apply(StateTransforms.Visuals.CreateStructureRepresentation)
+            .apply(StateTransforms.Visuals.CreateStructureRepresentation, {
+                type: {
+                    name: 'cartoon',
+                    params: PD.getDefaultValues(CartoonParams)
+                }
+            })
             .getTree();
 
         return state.update(newTree);
diff --git a/src/mol-plugin/state/transforms/visuals.ts b/src/mol-plugin/state/transforms/visuals.ts
index 3c76a56f5d2c3f49b30cdab808c6f6c44f40a2e3..6bc0aa12e53040daca08c7f2309635f0c94ebd60 100644
--- a/src/mol-plugin/state/transforms/visuals.ts
+++ b/src/mol-plugin/state/transforms/visuals.ts
@@ -9,31 +9,45 @@ import { Task } from 'mol-task';
 import { PluginStateTransform } from '../objects';
 import { PluginStateObject as SO } from '../objects';
 import { PluginContext } from 'mol-plugin/context';
-import { ColorTheme } from 'mol-theme/color';
-import { SizeTheme } from 'mol-theme/size';
-import { RepresentationRegistry } from 'mol-repr/representation';
-
-const colorThemeRegistry = new ColorTheme.Registry()
-const sizeThemeRegistry = new SizeTheme.Registry()
-const representationRegistry = new RepresentationRegistry()
+import { ParamDefinition as PD } from 'mol-util/param-definition';
 
 export { CreateStructureRepresentation }
-namespace CreateStructureRepresentation { export interface Params { } }
+namespace CreateStructureRepresentation {
+    export interface Params {
+        type: { name: string, params: any /** todo is there "common type" */ }
+    }
+}
 const CreateStructureRepresentation = PluginStateTransform.Create<SO.Molecule.Structure, SO.Molecule.Representation3D, CreateStructureRepresentation.Params>({
     name: 'create-structure-representation',
     display: { name: 'Create 3D Representation' },
     from: [SO.Molecule.Structure],
     to: [SO.Molecule.Representation3D],
+    params: {
+        default: (a, ctx: PluginContext) => ({
+            type: {
+                name: ctx.structureReprensentation.registry.default.name,
+                params: PD.getDefaultValues(ctx.structureReprensentation.registry.default.provider.getParams(ctx.structureReprensentation.themeCtx, a.data))
+            }
+        }),
+        definition: (a, ctx: PluginContext) => ({
+            type: PD.Mapped('Type', '',
+                ctx.structureReprensentation.registry.default.name,
+                ctx.structureReprensentation.registry.types,
+                name => ctx.structureReprensentation.registry.get(name)!.getParams(ctx.structureReprensentation.themeCtx, a.data))
+        })
+    },
     apply({ a, params }, plugin: PluginContext) {
         return Task.create('Structure Representation', async ctx => {
-            const repr = representationRegistry.create('cartoon', { colorThemeRegistry, sizeThemeRegistry }, a.data)
-            await repr.createOrUpdate({ webgl: plugin.canvas3d.webgl, colorThemeRegistry, sizeThemeRegistry }, {}, {}, a.data).runInContext(ctx);
-            return new SO.Molecule.Representation3D(repr);
+            const repr = plugin.structureReprensentation.registry.create(params.type.name, plugin.structureReprensentation.themeCtx, a.data)
+            await repr.createOrUpdate({ webgl: plugin.canvas3d.webgl, ...plugin.structureReprensentation.themeCtx }, params.type.params || {}, {}, a.data).runInContext(ctx);
+            return new SO.Molecule.Representation3D(repr, { label: params.type.name });
         });
     },
-    update({ a, b }, plugin: PluginContext) {
+    update({ a, b, oldParams, newParams }, plugin: PluginContext) {
         return Task.create('Structure Representation', async ctx => {
-            await b.data.createOrUpdate({ webgl: plugin.canvas3d.webgl, colorThemeRegistry, sizeThemeRegistry }, b.data.props, {}, a.data).runInContext(ctx);
+            if (newParams.type.name !== oldParams.type.name) return Transformer.UpdateResult.Recreate;
+
+            await b.data.createOrUpdate({ webgl: plugin.canvas3d.webgl, ...plugin.structureReprensentation.themeCtx }, { ...b.data.props, ...newParams.type.params }, {}, a.data).runInContext(ctx);
             return Transformer.UpdateResult.Updated;
         });
     }
diff --git a/src/mol-plugin/ui/controls/parameters.tsx b/src/mol-plugin/ui/controls/parameters.tsx
index c9071c0103ebe26ff2a99a78763329f1fada56f0..43feabf3c2a4cab7a5f681bc76cd2ac547672749 100644
--- a/src/mol-plugin/ui/controls/parameters.tsx
+++ b/src/mol-plugin/ui/controls/parameters.tsx
@@ -19,14 +19,18 @@ export interface ParameterControlsProps<P extends PD.Params = PD.Params> {
 export class ParameterControls<P extends PD.Params> extends React.PureComponent<ParameterControlsProps<P>, {}> {
     render() {
         const common = {
-            changes: this.props.onChange,
+            onChange: this.props.onChange,
             isEnabled: this.props.isEnabled,
             onEnter: this.props.onEnter,
         }
         const params = this.props.params;
         const values = this.props.values;
         return <div style={{ width: '100%' }}>
-            {Object.keys(params).map(key => <ParamWrapper control={controlFor(params[key])} param={params[key]} key={key} {...common} name={key} value={values[key]} />)}
+            {Object.keys(params).map(key => {
+                const param = params[key];
+                if (param.type === 'mapped') return <MappedControl param={param} key={key} {...common} name={key} value={values[key]} />
+                return <ParamWrapper control={controlFor(param)} param={param} key={key} {...common} name={key} value={values[key]} />
+            })}
         </div>;
     }
 }
@@ -36,22 +40,27 @@ function controlFor(param: PD.Any): ValueControl {
         case 'boolean': return BoolControl;
         case 'number': return NumberControl;
         case 'range': return NumberControl;
-        case 'multi-select': throw new Error('nyi');
-        case 'color': throw new Error('nyi');
+        case 'multi-select': return MultiSelectControl;
+        case 'color': return ColorControl;
         case 'select': return SelectControl;
         case 'text': return TextControl;
+        case 'interval': return IntervalControl;
+        case 'group': return GroupControl;
+        case 'mapped': throw Error('Must be handled separately');
     }
-    throw new Error('not supporter');
+    throw new Error('not supported');
 }
 
-type ParamWrapperProps = { name: string, value: any, param: PD.Base<any>, changes: ParamOnChange, control: ValueControl, onEnter?: () => void, isEnabled?: boolean }
+type MappedWrapperProps = { name: string, value: PD.Mapped<any>['defaultValue'], param: PD.Mapped<any>, onChange: ParamOnChange, onEnter?: () => void, isEnabled?: boolean }
+
+type ParamWrapperProps = { name: string, value: any, param: PD.Base<any>, onChange: ParamOnChange, control: ValueControl, onEnter?: () => void, isEnabled?: boolean }
 export type ParamOnChange = (params: { param: PD.Base<any>, name: string, value: any }) => void
 type ValueControlProps<P extends PD.Base<any> = PD.Base<any>> = { value: any, param: P, isEnabled?: boolean, onChange: (v: any) => void, onEnter?: () => void }
 type ValueControl = React.ComponentClass<ValueControlProps<any>>
 
 export class ParamWrapper extends React.PureComponent<ParamWrapperProps> {
     onChange = (value: any) => {
-        this.props.changes({ param: this.props.param, name: this.props.name, value });
+        this.props.onChange({ param: this.props.param, name: this.props.name, value });
     }
 
     render() {
@@ -124,7 +133,84 @@ export class SelectControl extends React.PureComponent<ValueControlProps<PD.Sele
 
     render() {
         return <select value={this.props.value || ''} onChange={this.onChange}>
-            {this.props.param.options.map(([value, label]) => <option key={label} value={value}>{label}</option>)}
+            {this.props.param.options.map(([value, label]) => <option key={value} value={value}>{label}</option>)}
         </select>;
     }
+}
+
+
+export class MultiSelectControl extends React.PureComponent<ValueControlProps<PD.MultiSelect<any>>> {
+    // onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
+    //     this.setState({ value: e.target.value });
+    //     this.props.onChange(e.target.value);
+    // }
+
+    render() {
+        return <span>multiselect TODO</span>;
+        // return <select value={this.props.value || ''} onChange={this.onChange}>
+        //     {this.props.param.options.map(([value, label]) => <option key={label} value={value}>{label}</option>)}
+        // </select>;
+    }
+}
+
+export class IntervalControl extends React.PureComponent<ValueControlProps<PD.Interval>> {
+    // onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
+    //     this.setState({ value: e.target.value });
+    //     this.props.onChange(e.target.value);
+    // }
+
+    render() {
+        return <span>interval TODO</span>;
+    }
+}
+
+export class ColorControl extends React.PureComponent<ValueControlProps<PD.Color>> {
+    // onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
+    //     this.setState({ value: e.target.value });
+    //     this.props.onChange(e.target.value);
+    // }
+
+    render() {
+        return <span>color TODO</span>;
+    }
+}
+
+export class GroupControl extends React.PureComponent<ValueControlProps<PD.Group<any>>> {
+    // onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
+    //     this.setState({ value: e.target.value });
+    //     this.props.onChange(e.target.value);
+    // }
+
+    render() {
+        return <span>group TODO</span>;
+    }
+}
+
+export class MappedControl extends React.PureComponent<MappedWrapperProps> {
+    change(value: PD.Mapped<any>['defaultValue'] ) {
+        this.props.onChange({ name: this.props.name, param: this.props.param, value });
+    }
+
+    onChangeName: ParamOnChange = e => {
+        this.change({ name: e.value, params: PD.getDefaultValues(this.props.param.map(e.value)) });
+    }
+
+    onChangeParam: ParamOnChange = e => {
+        const value: PD.Mapped<any>['defaultValue'] = this.props.value;
+        this.change({ name: value.name, params: { ...value.params, [e.name]: e.value } });
+    }
+
+    render() {
+        const value: PD.Mapped<any>['defaultValue'] = this.props.value;
+        const params = this.props.param.map(value.name);
+
+        return <div>
+            <ParamWrapper control={SelectControl} param={this.props.param.select}
+                isEnabled={this.props.isEnabled} onChange={this.onChangeName} onEnter={this.props.onEnter}
+                name={'name'} value={value.name} />
+            <div style={{ borderLeft: '5px solid #777', paddingLeft: '5px' }}>
+                <ParameterControls params={params} onChange={this.onChangeParam} values={value.params} onEnter={this.props.onEnter} isEnabled={this.props.isEnabled} />
+            </div>
+        </div>
+    }
 }
\ No newline at end of file
diff --git a/src/mol-repr/representation.ts b/src/mol-repr/representation.ts
index 948d6a033b88614a89252f1cfa74296ba277dc0d..8f8efdefcc1561d4cb3e8a0c1d154dfeccf95451 100644
--- a/src/mol-repr/representation.ts
+++ b/src/mol-repr/representation.ts
@@ -29,12 +29,19 @@ export type RepresentationParamsGetter<D, P extends PD.Params> = (ctx: ThemeRegi
 export interface RepresentationProvider<D, P extends PD.Params> {
     readonly factory: (getParams: RepresentationParamsGetter<D, P>) => Representation<D, P>
     readonly getParams: (ctx: ThemeRegistryContext, data: D) => P
+    // TODO
+    // readonly defaultParams: PD.Values<P>
 }
 
 export class RepresentationRegistry<D> {
     private _list: { name: string, provider: RepresentationProvider<D, any> }[] = []
     private _map = new Map<string, RepresentationProvider<D, any>>()
 
+    get default() { return this._list[0]; }
+    get types(): [string, string][] {
+        return this._list.map(e => [e.name, e.name] as [string, string]);
+    }
+
     constructor() {};
 
     add<P extends PD.Params>(name: string, factory: RepresentationProvider<D, P>['factory'], getParams: RepresentationProvider<D, P>['getParams']) {
@@ -70,9 +77,9 @@ interface Representation<D, P extends PD.Params = {}> {
     readonly label: string
     readonly updated: BehaviorSubject<number>
     readonly renderObjects: ReadonlyArray<RenderObject>
-    readonly props: Readonly<PD.DefaultValues<P>>
+    readonly props: Readonly<PD.Values<P>>
     readonly params: Readonly<P>
-    createOrUpdate: (ctx: RepresentationContext, props?: Partial<PD.DefaultValues<P>>, themeProps?: ThemeProps, data?: D) => Task<void>
+    createOrUpdate: (ctx: RepresentationContext, props?: Partial<PD.Values<P>>, themeProps?: ThemeProps, data?: D) => Task<void>
     getLoci: (pickingId: PickingId) => Loci
     mark: (loci: Loci, action: MarkerAction) => boolean
     destroy: () => void
@@ -93,7 +100,7 @@ namespace Representation {
         const updated = new BehaviorSubject(0)
 
         let currentParams: P
-        let currentProps: PD.DefaultValues<P>
+        let currentProps: PD.Values<P>
         let currentData: D
 
         const reprMap: { [k: number]: string } = {}
@@ -174,7 +181,7 @@ export interface VisualContext {
 
 export interface Visual<D, P extends PD.Params> {
     readonly renderObject: RenderObject | undefined
-    createOrUpdate: (ctx: VisualContext, theme: Theme, props?: Partial<PD.DefaultValues<P>>, data?: D) => Promise<void>
+    createOrUpdate: (ctx: VisualContext, theme: Theme, props?: Partial<PD.Values<P>>, data?: D) => Promise<void>
     getLoci: (pickingId: PickingId) => Loci
     mark: (loci: Loci, action: MarkerAction) => boolean
     destroy: () => void
diff --git a/src/mol-repr/shape/representation.ts b/src/mol-repr/shape/representation.ts
index b48f16439458b61a9de504fc2f085099be570e3c..9e283591f388d0c63167f22bbc9c4ce69e61dd5e 100644
--- a/src/mol-repr/shape/representation.ts
+++ b/src/mol-repr/shape/representation.ts
@@ -35,10 +35,10 @@ export function ShapeRepresentation<P extends ShapeParams>(): ShapeRepresentatio
     const renderObjects: RenderObject[] = []
     let _renderObject: MeshRenderObject | undefined
     let _shape: Shape
-    let currentProps: PD.DefaultValues<P> = PD.getDefaultValues(ShapeParams) as PD.DefaultValues<P>
+    let currentProps: PD.Values<P> = PD.getDefaultValues(ShapeParams) as PD.Values<P>
     let currentParams: P
 
-    function createOrUpdate(ctx: RepresentationContext, props: Partial<PD.DefaultValues<P>> = {}, themeProps: ThemeProps = {}, shape?: Shape) {
+    function createOrUpdate(ctx: RepresentationContext, props: Partial<PD.Values<P>> = {}, themeProps: ThemeProps = {}, shape?: Shape) {
         currentProps = Object.assign({}, currentProps, props)
         if (shape) _shape = shape
 
diff --git a/src/mol-repr/structure/complex-representation.ts b/src/mol-repr/structure/complex-representation.ts
index 7486dd23f89ba5a64c144a0ac68ccc0279a2f559..bf0350bcb4cd31af3d41620e441ae19716f2f4e8 100644
--- a/src/mol-repr/structure/complex-representation.ts
+++ b/src/mol-repr/structure/complex-representation.ts
@@ -23,10 +23,10 @@ export function ComplexRepresentation<P extends StructureParams>(label: string,
 
     let _structure: Structure
     let _params: P
-    let _props: PD.DefaultValues<P>
+    let _props: PD.Values<P>
     let _theme: Theme
 
-    function createOrUpdate(ctx: RepresentationContext, props: Partial<PD.DefaultValues<P>> = {}, themeProps: ThemeProps = {}, structure?: Structure) {
+    function createOrUpdate(ctx: RepresentationContext, props: Partial<PD.Values<P>> = {}, themeProps: ThemeProps = {}, structure?: Structure) {
         if (structure && structure !== _structure) {
             _params = getParams(ctx, structure)
             _structure = structure
diff --git a/src/mol-repr/structure/complex-visual.ts b/src/mol-repr/structure/complex-visual.ts
index e8f9944a290266f1b18274333fa32226d7500d70..9d27d8bca1a1aadf810da95155f7e1a016c88d87 100644
--- a/src/mol-repr/structure/complex-visual.ts
+++ b/src/mol-repr/structure/complex-visual.ts
@@ -37,18 +37,18 @@ type ComplexParams = typeof ComplexParams
 type ComplexRenderObject = MeshRenderObject | LinesRenderObject | PointsRenderObject | DirectVolumeRenderObject
 
 interface ComplexVisualBuilder<P extends ComplexParams, G extends Geometry> {
-    defaultProps: PD.DefaultValues<P>
-    createGeometry(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.DefaultValues<P>, geometry?: G): Promise<G>
+    defaultProps: PD.Values<P>
+    createGeometry(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<P>, geometry?: G): Promise<G>
     createLocationIterator(structure: Structure): LocationIterator
     getLoci(pickingId: PickingId, structure: Structure, id: number): Loci
     mark(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean): boolean,
-    setUpdateState(state: VisualUpdateState, newProps: PD.DefaultValues<P>, currentProps: PD.DefaultValues<P>, newTheme: Theme, currentTheme: Theme): void
+    setUpdateState(state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme): void
 }
 
 interface ComplexVisualGeometryBuilder<P extends ComplexParams, G extends Geometry> extends ComplexVisualBuilder<P, G> {
     createEmptyGeometry(geometry?: G): G
-    createRenderObject(ctx: VisualContext, structure: Structure, geometry: Geometry, locationIt: LocationIterator, theme: Theme, currentProps: PD.DefaultValues<P>): Promise<ComplexRenderObject>
-    updateValues(values: RenderableValues, newProps: PD.DefaultValues<P>): void
+    createRenderObject(ctx: VisualContext, structure: Structure, geometry: Geometry, locationIt: LocationIterator, theme: Theme, currentProps: PD.Values<P>): Promise<ComplexRenderObject>
+    updateValues(values: RenderableValues, newProps: PD.Values<P>): void
 }
 
 export function ComplexVisual<P extends ComplexParams>(builder: ComplexVisualGeometryBuilder<P, Geometry>): ComplexVisual<P> {
@@ -57,14 +57,14 @@ export function ComplexVisual<P extends ComplexParams>(builder: ComplexVisualGeo
     const updateState = VisualUpdateState.create()
 
     let renderObject: ComplexRenderObject | undefined
-    let currentProps: PD.DefaultValues<P>
+    let currentProps: PD.Values<P>
     let currentTheme: Theme
     let geometry: Geometry
     let currentStructure: Structure
     let locationIt: LocationIterator
     let conformationHash: number
 
-    async function create(ctx: VisualContext, structure: Structure, theme: Theme, props: Partial<PD.DefaultValues<P>> = {}) {
+    async function create(ctx: VisualContext, structure: Structure, theme: Theme, props: Partial<PD.Values<P>> = {}) {
         currentProps = Object.assign({}, defaultProps, props)
         currentTheme = theme
         currentStructure = structure
@@ -76,7 +76,7 @@ export function ComplexVisual<P extends ComplexParams>(builder: ComplexVisualGeo
         renderObject = await createRenderObject(ctx, structure, geometry, locationIt, theme, currentProps)
     }
 
-    async function update(ctx: VisualContext, theme: Theme, props: Partial<PD.DefaultValues<P>>) {
+    async function update(ctx: VisualContext, theme: Theme, props: Partial<PD.Values<P>>) {
         const newProps = Object.assign({}, currentProps, props, { structure: currentStructure })
 
         if (!renderObject) return false
@@ -123,7 +123,7 @@ export function ComplexVisual<P extends ComplexParams>(builder: ComplexVisualGeo
 
     return {
         get renderObject () { return renderObject },
-        async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<PD.DefaultValues<P>> = {}, structure?: Structure) {
+        async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<PD.Values<P>> = {}, structure?: Structure) {
             if (!structure && !currentStructure) {
                 throw new Error('missing structure')
             } else if (structure && (!currentStructure || !renderObject)) {
@@ -182,7 +182,7 @@ export interface ComplexMeshVisualBuilder<P extends ComplexMeshParams> extends C
 export function ComplexMeshVisual<P extends ComplexMeshParams>(builder: ComplexMeshVisualBuilder<P>): ComplexVisual<P> {
     return ComplexVisual({
         ...builder,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<P>, currentProps: PD.DefaultValues<P>, newTheme: Theme, currentTheme: Theme) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme) => {
             builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme)
             if (SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true
         },
diff --git a/src/mol-repr/structure/units-representation.ts b/src/mol-repr/structure/units-representation.ts
index 44897ad4feca3d32df5d78966e3438023d7ddf0e..c91a664a6a3529dea3b4b11df46ed38f33ef810c 100644
--- a/src/mol-repr/structure/units-representation.ts
+++ b/src/mol-repr/structure/units-representation.ts
@@ -34,10 +34,10 @@ export function UnitsRepresentation<P extends UnitsParams>(label: string, getPar
     let _structure: Structure
     let _groups: ReadonlyArray<Unit.SymmetryGroup>
     let _params: P
-    let _props: PD.DefaultValues<P>
+    let _props: PD.Values<P>
     let _theme: Theme
 
-    function createOrUpdate(ctx: RepresentationContext, props: Partial<PD.DefaultValues<P>> = {}, themeProps: ThemeProps = {}, structure?: Structure) {
+    function createOrUpdate(ctx: RepresentationContext, props: Partial<PD.Values<P>> = {}, themeProps: ThemeProps = {}, structure?: Structure) {
         if (structure && structure !== _structure) {
             _params = getParams(ctx, structure)
             if (!_props) _props = PD.getDefaultValues(_params)
diff --git a/src/mol-repr/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts
index 6656c585bd2d94b81f8e6e33c7a67428389782fe..ebfb6ab0461e97fd449b9c69dda6095ec83f18a4 100644
--- a/src/mol-repr/structure/units-visual.ts
+++ b/src/mol-repr/structure/units-visual.ts
@@ -44,18 +44,18 @@ function sameGroupConformation(groupA: Unit.SymmetryGroup, groupB: Unit.Symmetry
 type UnitsRenderObject = MeshRenderObject | LinesRenderObject | PointsRenderObject | DirectVolumeRenderObject
 
 interface UnitsVisualBuilder<P extends UnitsParams, G extends Geometry> {
-    defaultProps: PD.DefaultValues<P>
-    createGeometry(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.DefaultValues<P>, geometry?: G): Promise<G>
+    defaultProps: PD.Values<P>
+    createGeometry(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<P>, geometry?: G): Promise<G>
     createLocationIterator(group: Unit.SymmetryGroup): LocationIterator
     getLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number): Loci
     mark(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean): boolean
-    setUpdateState(state: VisualUpdateState, newProps: PD.DefaultValues<P>, currentProps: PD.DefaultValues<P>, newTheme: Theme, currentTheme: Theme): void
+    setUpdateState(state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme): void
 }
 
 interface UnitsVisualGeometryBuilder<P extends UnitsParams, G extends Geometry> extends UnitsVisualBuilder<P, G> {
     createEmptyGeometry(geometry?: G): G
-    createRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, geometry: Geometry, locationIt: LocationIterator, theme: Theme, currentProps: PD.DefaultValues<P>): Promise<UnitsRenderObject>
-    updateValues(values: RenderableValues, newProps: PD.DefaultValues<P>): void
+    createRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, geometry: Geometry, locationIt: LocationIterator, theme: Theme, currentProps: PD.Values<P>): Promise<UnitsRenderObject>
+    updateValues(values: RenderableValues, newProps: PD.Values<P>): void
 }
 
 export function UnitsVisual<P extends UnitsParams>(builder: UnitsVisualGeometryBuilder<P, Geometry>): UnitsVisual<P> {
@@ -64,7 +64,7 @@ export function UnitsVisual<P extends UnitsParams>(builder: UnitsVisualGeometryB
     const updateState = VisualUpdateState.create()
 
     let renderObject: UnitsRenderObject | undefined
-    let currentProps: PD.DefaultValues<P>
+    let currentProps: PD.Values<P>
     let currentTheme: Theme
     let geometry: Geometry
     let currentGroup: Unit.SymmetryGroup
@@ -72,7 +72,7 @@ export function UnitsVisual<P extends UnitsParams>(builder: UnitsVisualGeometryB
     let locationIt: LocationIterator
     let currentConformationId: UUID
 
-    async function create(ctx: VisualContext, group: Unit.SymmetryGroup, theme: Theme, props: Partial<PD.DefaultValues<P>> = {}) {
+    async function create(ctx: VisualContext, group: Unit.SymmetryGroup, theme: Theme, props: Partial<PD.Values<P>> = {}) {
         currentProps = Object.assign({}, defaultProps, props, { structure: currentStructure })
         currentTheme = theme
         currentGroup = group
@@ -88,7 +88,7 @@ export function UnitsVisual<P extends UnitsParams>(builder: UnitsVisualGeometryB
         renderObject = await createRenderObject(ctx, group, geometry, locationIt, theme, currentProps)
     }
 
-    async function update(ctx: VisualContext, theme: Theme, props: Partial<PD.DefaultValues<P>> = {}) {
+    async function update(ctx: VisualContext, theme: Theme, props: Partial<PD.Values<P>> = {}) {
         if (!renderObject) return
 
         const newProps = Object.assign({}, currentProps, props, { structure: currentStructure })
@@ -147,7 +147,7 @@ export function UnitsVisual<P extends UnitsParams>(builder: UnitsVisualGeometryB
 
     return {
         get renderObject () { return renderObject },
-        async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<PD.DefaultValues<P>> = {}, structureGroup?: StructureGroup) {
+        async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<PD.Values<P>> = {}, structureGroup?: StructureGroup) {
             if (structureGroup) currentStructure = structureGroup.structure
             const group = structureGroup ? structureGroup.group : undefined
             if (!group && !currentGroup) {
@@ -211,7 +211,7 @@ export interface UnitsMeshVisualBuilder<P extends UnitsMeshParams> extends Units
 export function UnitsMeshVisual<P extends UnitsMeshParams>(builder: UnitsMeshVisualBuilder<P>): UnitsVisual<P> {
     return UnitsVisual({
         ...builder,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<P>, currentProps: PD.DefaultValues<P>, newTheme: Theme, currentTheme: Theme) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme) => {
             builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme)
             if (SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true
         },
@@ -235,7 +235,7 @@ export function UnitsPointsVisual<P extends UnitsPointsParams>(builder: UnitsPoi
         ...builder,
         createEmptyGeometry: Points.createEmpty,
         createRenderObject: createUnitsPointsRenderObject,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<P>, currentProps: PD.DefaultValues<P>, newTheme: Theme, currentTheme: Theme) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme) => {
             builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme)
             if (SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true
         },
@@ -257,7 +257,7 @@ export function UnitsLinesVisual<P extends UnitsLinesParams>(builder: UnitsLines
         ...builder,
         createEmptyGeometry: Lines.createEmpty,
         createRenderObject: createUnitsLinesRenderObject,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<P>, currentProps: PD.DefaultValues<P>, newTheme: Theme, currentTheme: Theme) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme) => {
             builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme)
             if (SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true
         },
@@ -279,7 +279,7 @@ export function UnitsDirectVolumeVisual<P extends UnitsDirectVolumeParams>(build
         ...builder,
         createEmptyGeometry: DirectVolume.createEmpty,
         createRenderObject: createUnitsDirectVolumeRenderObject,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<P>, currentProps: PD.DefaultValues<P>, newTheme: Theme, currentTheme: Theme) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme) => {
             builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme)
             if (SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true
         },
diff --git a/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts b/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts
index 7aca257fd4b7256a5d63a1b1717ce7d46db5dfbe..bc2b296c4fe5e6cac32a03e59a214cf4c22d1fe2 100644
--- a/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts
+++ b/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts
@@ -74,7 +74,7 @@ export function CarbohydrateLinkVisual(): ComplexVisual<CarbohydrateLinkParams>
         createLocationIterator: CarbohydrateLinkIterator,
         getLoci: getLinkLoci,
         mark: markLink,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<CarbohydrateLinkParams>, currentProps: PD.DefaultValues<CarbohydrateLinkParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<CarbohydrateLinkParams>, currentProps: PD.Values<CarbohydrateLinkParams>) => {
             state.createGeometry = newProps.radialSegments !== currentProps.radialSegments
         }
     })
diff --git a/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts b/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts
index 96b3dbafa74b05c3182689d7e0351803ba6bf3ac..ab85e6f2a208a43d894e612d9d80b0c6f62f9d0e 100644
--- a/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts
+++ b/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts
@@ -44,7 +44,7 @@ const diamondPrism = DiamondPrism()
 const pentagonalPrism = PentagonalPrism()
 const hexagonalPrism = HexagonalPrism()
 
-async function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.DefaultValues<CarbohydrateSymbolParams>, mesh?: Mesh) {
+async function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<CarbohydrateSymbolParams>, mesh?: Mesh) {
     const builder = MeshBuilder.create(256, 128, mesh)
 
     const { detail } = props
@@ -158,7 +158,7 @@ export function CarbohydrateSymbolVisual(): ComplexVisual<CarbohydrateSymbolPara
         createLocationIterator: CarbohydrateElementIterator,
         getLoci: getCarbohydrateLoci,
         mark: markCarbohydrate,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<CarbohydrateSymbolParams>, currentProps: PD.DefaultValues<CarbohydrateSymbolParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<CarbohydrateSymbolParams>, currentProps: PD.Values<CarbohydrateSymbolParams>) => {
             state.createGeometry = newProps.detail !== currentProps.detail
         }
     })
diff --git a/src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts b/src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts
index 9f949e27f0565246d2504d7f115e3502e1289ef5..1b1d06ea80011194fc9b8b3993a4cc0e8133f1c2 100644
--- a/src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts
+++ b/src/mol-repr/structure/visual/cross-link-restraint-cylinder.ts
@@ -63,7 +63,7 @@ export function CrossLinkRestraintVisual(): ComplexVisual<CrossLinkRestraintPara
         createLocationIterator: CrossLinkRestraintIterator,
         getLoci: getLinkLoci,
         mark: markLink,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<CrossLinkRestraintParams>, currentProps: PD.DefaultValues<CrossLinkRestraintParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<CrossLinkRestraintParams>, currentProps: PD.Values<CrossLinkRestraintParams>) => {
             state.createGeometry = newProps.radialSegments !== currentProps.radialSegments
         }
     })
diff --git a/src/mol-repr/structure/visual/element-point.ts b/src/mol-repr/structure/visual/element-point.ts
index 649d54138543ca8a1212a95b4b613cb0b4969574..174080b4ef6b798b331728ba9bb78946f7cb623a 100644
--- a/src/mol-repr/structure/visual/element-point.ts
+++ b/src/mol-repr/structure/visual/element-point.ts
@@ -24,7 +24,7 @@ export type ElementPointParams = typeof ElementPointParams
 
 // TODO size
 
-export async function createElementPoint(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.DefaultValues<ElementPointParams>, points: Points) {
+export async function createElementPoint(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<ElementPointParams>, points: Points) {
     const elements = unit.elements
     const n = elements.length
     const builder = PointsBuilder.create(n, n / 10, points)
@@ -50,7 +50,7 @@ export function ElementPointVisual(): UnitsVisual<ElementPointParams> {
         createLocationIterator: StructureElementIterator.fromGroup,
         getLoci: getElementLoci,
         mark: markElement,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<ElementPointParams>, currentProps: PD.DefaultValues<ElementPointParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<ElementPointParams>, currentProps: PD.Values<ElementPointParams>) => {
 
         }
     })
diff --git a/src/mol-repr/structure/visual/element-sphere.ts b/src/mol-repr/structure/visual/element-sphere.ts
index 31e01cd664f81d95f595fd7f4721209214962434..90a871221fcf30a52a34673491bc2a32219104a8 100644
--- a/src/mol-repr/structure/visual/element-sphere.ts
+++ b/src/mol-repr/structure/visual/element-sphere.ts
@@ -27,7 +27,7 @@ export function ElementSphereVisual(): UnitsVisual<ElementSphereParams> {
         createLocationIterator: StructureElementIterator.fromGroup,
         getLoci: getElementLoci,
         mark: markElement,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<ElementSphereParams>, currentProps: PD.DefaultValues<ElementSphereParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<ElementSphereParams>, currentProps: PD.Values<ElementSphereParams>) => {
             state.createGeometry = newProps.detail !== currentProps.detail
         }
     })
diff --git a/src/mol-repr/structure/visual/gaussian-density-point.ts b/src/mol-repr/structure/visual/gaussian-density-point.ts
index 2e8e1eaa1e9e3075e687494dce3760988bbee9f9..875705c3cd2253f3e265c6b26ba1b07b2ec046e7 100644
--- a/src/mol-repr/structure/visual/gaussian-density-point.ts
+++ b/src/mol-repr/structure/visual/gaussian-density-point.ts
@@ -62,7 +62,7 @@ export function GaussianDensityPointVisual(): UnitsVisual<GaussianDensityPointPa
         createLocationIterator: StructureElementIterator.fromGroup,
         getLoci: () => EmptyLoci,
         mark: () => false,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<GaussianDensityPointParams>, currentProps: PD.DefaultValues<GaussianDensityPointParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<GaussianDensityPointParams>, currentProps: PD.Values<GaussianDensityPointParams>) => {
             if (newProps.resolution !== currentProps.resolution) state.createGeometry = true
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true
diff --git a/src/mol-repr/structure/visual/gaussian-density-volume.ts b/src/mol-repr/structure/visual/gaussian-density-volume.ts
index 78e48960de447d3a6a61b24b308e227da73fb3d2..5a9f0a681f94d5e0eba5256173afa50a9637396d 100644
--- a/src/mol-repr/structure/visual/gaussian-density-volume.ts
+++ b/src/mol-repr/structure/visual/gaussian-density-volume.ts
@@ -40,7 +40,7 @@ export function GaussianDensityVolumeVisual(): UnitsVisual<GaussianDensityVolume
         createLocationIterator: StructureElementIterator.fromGroup,
         getLoci: getElementLoci,
         mark: markElement,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<GaussianDensityVolumeParams>, currentProps: PD.DefaultValues<GaussianDensityVolumeParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<GaussianDensityVolumeParams>, currentProps: PD.Values<GaussianDensityVolumeParams>) => {
             if (newProps.resolution !== currentProps.resolution) state.createGeometry = true
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true
             if (newProps.smoothness !== currentProps.smoothness) {
diff --git a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts
index cc52de76708ab8149f2515353d4da44cd00d770d..75e5550bef38ece716431eba23d39c589096180e 100644
--- a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts
+++ b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts
@@ -47,7 +47,7 @@ export function GaussianSurfaceVisual(): UnitsVisual<GaussianSurfaceParams> {
         createLocationIterator: StructureElementIterator.fromGroup,
         getLoci: getElementLoci,
         mark: markElement,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<GaussianSurfaceParams>, currentProps: PD.DefaultValues<GaussianSurfaceParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<GaussianSurfaceParams>, currentProps: PD.Values<GaussianSurfaceParams>) => {
             if (newProps.resolution !== currentProps.resolution) state.createGeometry = true
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true
diff --git a/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts b/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts
index 1ed95db64705df238c8461b2c360004d1b932447..eec416e576c406a45a2ae3580e5e909349a04bf6 100644
--- a/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts
+++ b/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts
@@ -46,7 +46,7 @@ export function GaussianWireframeVisual(): UnitsVisual<GaussianWireframeParams>
         createLocationIterator: StructureElementIterator.fromGroup,
         getLoci: getElementLoci,
         mark: markElement,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<GaussianWireframeParams>, currentProps: PD.DefaultValues<GaussianWireframeParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<GaussianWireframeParams>, currentProps: PD.Values<GaussianWireframeParams>) => {
             if (newProps.resolution !== currentProps.resolution) state.createGeometry = true
             if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true
             if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true
diff --git a/src/mol-repr/structure/visual/inter-unit-link-cylinder.ts b/src/mol-repr/structure/visual/inter-unit-link-cylinder.ts
index f38fb1683ace88a9a3757915621ef0339fcd3f86..31e82c69c78b9f1e5bad8b5022b02b3a2f7e7e8c 100644
--- a/src/mol-repr/structure/visual/inter-unit-link-cylinder.ts
+++ b/src/mol-repr/structure/visual/inter-unit-link-cylinder.ts
@@ -62,7 +62,7 @@ export function InterUnitLinkVisual(): ComplexVisual<InterUnitLinkParams> {
         createLocationIterator: LinkIterator.fromStructure,
         getLoci: getLinkLoci,
         mark: markLink,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<InterUnitLinkParams>, currentProps: PD.DefaultValues<InterUnitLinkParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<InterUnitLinkParams>, currentProps: PD.Values<InterUnitLinkParams>) => {
             if (newProps.linkScale !== currentProps.linkScale) state.createGeometry = true
             if (newProps.linkSpacing !== currentProps.linkSpacing) state.createGeometry = true
             if (newProps.radialSegments !== currentProps.radialSegments) state.createGeometry = true
diff --git a/src/mol-repr/structure/visual/intra-unit-link-cylinder.ts b/src/mol-repr/structure/visual/intra-unit-link-cylinder.ts
index d9f55abcbab9d2ff8a8e30759036252751e68ec6..0355d66ba61b842ee1b24d035f9201c9f40d5941 100644
--- a/src/mol-repr/structure/visual/intra-unit-link-cylinder.ts
+++ b/src/mol-repr/structure/visual/intra-unit-link-cylinder.ts
@@ -20,7 +20,7 @@ import { PickingId } from 'mol-geo/geometry/picking';
 import { VisualContext } from 'mol-repr/representation';
 import { Theme } from 'mol-theme/theme';
 
-async function createIntraUnitLinkCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.DefaultValues<IntraUnitLinkParams>, mesh?: Mesh) {
+async function createIntraUnitLinkCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<IntraUnitLinkParams>, mesh?: Mesh) {
     if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh)
 
     const location = StructureElement.create(unit)
diff --git a/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts b/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts
index 11b9329754206a9bb79281f8b876e489909c3089..b10d5cee002e54b7cac5463d1f2215d9ffdee654 100644
--- a/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts
+++ b/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts
@@ -79,7 +79,7 @@ export function PolymerBackboneVisual(): UnitsVisual<PolymerBackboneParams> {
         createLocationIterator: StructureElementIterator.fromGroup,
         getLoci: getElementLoci,
         mark: markElement,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<PolymerBackboneParams>, currentProps: PD.DefaultValues<PolymerBackboneParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<PolymerBackboneParams>, currentProps: PD.Values<PolymerBackboneParams>) => {
             state.createGeometry = newProps.radialSegments !== currentProps.radialSegments
         }
     })
diff --git a/src/mol-repr/structure/visual/polymer-gap-cylinder.ts b/src/mol-repr/structure/visual/polymer-gap-cylinder.ts
index d26da145855cc7b2b095d42b7ff2c8640fb2610d..0d60c166010a7ea7ce2453613813573e7f792e97 100644
--- a/src/mol-repr/structure/visual/polymer-gap-cylinder.ts
+++ b/src/mol-repr/structure/visual/polymer-gap-cylinder.ts
@@ -95,7 +95,7 @@ export function PolymerGapVisual(): UnitsVisual<PolymerGapParams> {
         createLocationIterator: PolymerGapLocationIterator.fromGroup,
         getLoci: getPolymerGapElementLoci,
         mark: markPolymerGapElement,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<PolymerGapParams>, currentProps: PD.DefaultValues<PolymerGapParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<PolymerGapParams>, currentProps: PD.Values<PolymerGapParams>) => {
             state.createGeometry = newProps.radialSegments !== currentProps.radialSegments
         }
     })
diff --git a/src/mol-repr/structure/visual/polymer-trace-mesh.ts b/src/mol-repr/structure/visual/polymer-trace-mesh.ts
index 21c20324bd032d98cf1d3b448dbc618d6e09b0de..698f1f10e1ff14fea1f19f58aac493e6ab5614c8 100644
--- a/src/mol-repr/structure/visual/polymer-trace-mesh.ts
+++ b/src/mol-repr/structure/visual/polymer-trace-mesh.ts
@@ -99,7 +99,7 @@ export function PolymerTraceVisual(): UnitsVisual<PolymerTraceParams> {
         createLocationIterator: PolymerLocationIterator.fromGroup,
         getLoci: getPolymerElementLoci,
         mark: markPolymerElement,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<PolymerTraceParams>, currentProps: PD.DefaultValues<PolymerTraceParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<PolymerTraceParams>, currentProps: PD.Values<PolymerTraceParams>) => {
             state.createGeometry = (
                 newProps.linearSegments !== currentProps.linearSegments ||
                 newProps.radialSegments !== currentProps.radialSegments ||
diff --git a/src/mol-repr/structure/visual/util/common.ts b/src/mol-repr/structure/visual/util/common.ts
index ba4b10e1abbedf706eff43930065417da81d1997..a9b574a2fb38ac4b161f266c668b38c880ee378c 100644
--- a/src/mol-repr/structure/visual/util/common.ts
+++ b/src/mol-repr/structure/visual/util/common.ts
@@ -49,14 +49,14 @@ export function includesUnitKind(unitKinds: UnitKind[], unit: Unit) {
 
 // mesh
 
-export async function createComplexMeshRenderObject(ctx: VisualContext, structure: Structure, mesh: Mesh, locationIt: LocationIterator, theme: Theme, props: PD.DefaultValues<StructureMeshParams>) {
+export async function createComplexMeshRenderObject(ctx: VisualContext, structure: Structure, mesh: Mesh, locationIt: LocationIterator, theme: Theme, props: PD.Values<StructureMeshParams>) {
     const transform = createIdentityTransform()
     const values = await Mesh.createValues(ctx.runtime, mesh, transform, locationIt, theme, props)
     const state = createRenderableState(props)
     return createMeshRenderObject(values, state)
 }
 
-export async function createUnitsMeshRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, mesh: Mesh, locationIt: LocationIterator, theme: Theme, props: PD.DefaultValues<StructureMeshParams>) {
+export async function createUnitsMeshRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, mesh: Mesh, locationIt: LocationIterator, theme: Theme, props: PD.Values<StructureMeshParams>) {
     const transform = createUnitsTransform(group)
     const values = await Mesh.createValues(ctx.runtime, mesh, transform, locationIt, theme, props)
     const state = createRenderableState(props)
@@ -65,7 +65,7 @@ export async function createUnitsMeshRenderObject(ctx: VisualContext, group: Uni
 
 // points
 
-export async function createUnitsPointsRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, points: Points, locationIt: LocationIterator, theme: Theme, props: PD.DefaultValues<StructurePointsParams>) {
+export async function createUnitsPointsRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, points: Points, locationIt: LocationIterator, theme: Theme, props: PD.Values<StructurePointsParams>) {
     const transform = createUnitsTransform(group)
     const values = await Points.createValues(ctx.runtime, points, transform, locationIt, theme, props)
     const state = createRenderableState(props)
@@ -74,7 +74,7 @@ export async function createUnitsPointsRenderObject(ctx: VisualContext, group: U
 
 // lines
 
-export async function createUnitsLinesRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, lines: Lines, locationIt: LocationIterator, theme: Theme, props: PD.DefaultValues<StructureLinesParams>) {
+export async function createUnitsLinesRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, lines: Lines, locationIt: LocationIterator, theme: Theme, props: PD.Values<StructureLinesParams>) {
     const transform = createUnitsTransform(group)
     const values = await Lines.createValues(ctx.runtime, lines, transform, locationIt, theme, props)
     const state = createRenderableState(props)
@@ -83,7 +83,7 @@ export async function createUnitsLinesRenderObject(ctx: VisualContext, group: Un
 
 // direct-volume
 
-export async function createUnitsDirectVolumeRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, directVolume: DirectVolume, locationIt: LocationIterator, theme: Theme, props: PD.DefaultValues<StructureDirectVolumeParams>) {
+export async function createUnitsDirectVolumeRenderObject(ctx: VisualContext, group: Unit.SymmetryGroup, directVolume: DirectVolume, locationIt: LocationIterator, theme: Theme, props: PD.Values<StructureDirectVolumeParams>) {
     const transform = createUnitsTransform(group)
     const values = await DirectVolume.createValues(ctx.runtime, directVolume, transform, locationIt, theme, props)
     const state = createRenderableState(props)
diff --git a/src/mol-repr/volume/direct-volume.ts b/src/mol-repr/volume/direct-volume.ts
index d3890e7e5e58554526cd1a76d20a1a093ccf5ca2..2bdecb1c2e3625dce69ecae78ce65de60d8c4e43 100644
--- a/src/mol-repr/volume/direct-volume.ts
+++ b/src/mol-repr/volume/direct-volume.ts
@@ -143,7 +143,7 @@ export function createDirectVolume3d(ctx: RuntimeContext, webgl: WebGLContext, v
 
 //
 
-export async function createDirectVolume(ctx: VisualContext, volume: VolumeData, props: PD.DefaultValues<DirectVolumeParams>, directVolume?: DirectVolume) {
+export async function createDirectVolume(ctx: VisualContext, volume: VolumeData, props: PD.Values<DirectVolumeParams>, directVolume?: DirectVolume) {
     const { runtime, webgl } = ctx
     if (webgl === undefined) throw new Error('DirectVolumeVisual requires `webgl` in props')
 
@@ -170,9 +170,9 @@ export function DirectVolumeVisual(): VolumeVisual<DirectVolumeParams> {
         createGeometry: createDirectVolume,
         getLoci: () => EmptyLoci,
         mark: () => false,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<DirectVolumeParams>, currentProps: PD.DefaultValues<DirectVolumeParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<DirectVolumeParams>, currentProps: PD.Values<DirectVolumeParams>) => {
         },
-        createRenderObject: async (ctx: VisualContext, geometry: DirectVolume, locationIt: LocationIterator, theme: Theme, props: PD.DefaultValues<DirectVolumeParams>) => {
+        createRenderObject: async (ctx: VisualContext, geometry: DirectVolume, locationIt: LocationIterator, theme: Theme, props: PD.Values<DirectVolumeParams>) => {
             const transform = createIdentityTransform()
             const values = await DirectVolume.createValues(ctx.runtime, geometry, transform, locationIt, theme, props)
             const state = createRenderableState(props)
diff --git a/src/mol-repr/volume/isosurface-mesh.ts b/src/mol-repr/volume/isosurface-mesh.ts
index fd54afcefbdd4ac1f4370f124dd8361cfe18ef42..f7d77406db34a471304bce59a473e1b5100d10ab 100644
--- a/src/mol-repr/volume/isosurface-mesh.ts
+++ b/src/mol-repr/volume/isosurface-mesh.ts
@@ -55,10 +55,10 @@ export function IsosurfaceVisual(): VolumeVisual<IsosurfaceParams> {
         createGeometry: createVolumeIsosurface,
         getLoci: () => EmptyLoci,
         mark: () => false,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.DefaultValues<IsosurfaceParams>, currentProps: PD.DefaultValues<IsosurfaceParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<IsosurfaceParams>, currentProps: PD.Values<IsosurfaceParams>) => {
             if (newProps.isoValueAbsolute !== currentProps.isoValueAbsolute) state.createGeometry = true
         },
-        createRenderObject: async (ctx: VisualContext, geometry: Mesh, locationIt: LocationIterator, theme: Theme, props: PD.DefaultValues<IsosurfaceParams>) => {
+        createRenderObject: async (ctx: VisualContext, geometry: Mesh, locationIt: LocationIterator, theme: Theme, props: PD.Values<IsosurfaceParams>) => {
             const transform = createIdentityTransform()
             const values = await Mesh.createValues(ctx.runtime, geometry, transform, locationIt, theme, props)
             const state = createRenderableState(props)
diff --git a/src/mol-repr/volume/representation.ts b/src/mol-repr/volume/representation.ts
index 0831340cf2e8576834d0240357cae77ffb8044c6..86eb9bb4912d75dce7a6e55a354e6805b53bfd72 100644
--- a/src/mol-repr/volume/representation.ts
+++ b/src/mol-repr/volume/representation.ts
@@ -27,16 +27,16 @@ export interface VolumeVisual<P extends VolumeParams> extends Visual<VolumeData,
 type VolumeRenderObject = MeshRenderObject | LinesRenderObject | PointsRenderObject | DirectVolumeRenderObject
 
 interface VolumeVisualBuilder<P extends VolumeParams, G extends Geometry> {
-    defaultProps: PD.DefaultValues<P>
-    createGeometry(ctx: VisualContext, volumeData: VolumeData, props: PD.DefaultValues<P>, geometry?: G): Promise<G>
+    defaultProps: PD.Values<P>
+    createGeometry(ctx: VisualContext, volumeData: VolumeData, props: PD.Values<P>, geometry?: G): Promise<G>
     getLoci(pickingId: PickingId, id: number): Loci
     mark(loci: Loci, apply: (interval: Interval) => boolean): boolean
-    setUpdateState(state: VisualUpdateState, newProps: PD.DefaultValues<P>, currentProps: PD.DefaultValues<P>): void
+    setUpdateState(state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>): void
 }
 
 interface VolumeVisualGeometryBuilder<P extends VolumeParams, G extends Geometry> extends VolumeVisualBuilder<P, G> {
-    createRenderObject(ctx: VisualContext, geometry: G, locationIt: LocationIterator, theme: Theme, currentProps: PD.DefaultValues<P>): Promise<VolumeRenderObject>
-    updateValues(values: RenderableValues, newProps: PD.DefaultValues<P>): void
+    createRenderObject(ctx: VisualContext, geometry: G, locationIt: LocationIterator, theme: Theme, currentProps: PD.Values<P>): Promise<VolumeRenderObject>
+    updateValues(values: RenderableValues, newProps: PD.Values<P>): void
 }
 
 export function VolumeVisual<P extends VolumeParams>(builder: VolumeVisualGeometryBuilder<P, Geometry>) {
@@ -44,13 +44,13 @@ export function VolumeVisual<P extends VolumeParams>(builder: VolumeVisualGeomet
     const { createRenderObject, updateValues } = builder
     const updateState = VisualUpdateState.create()
 
-    let currentProps: PD.DefaultValues<P>
+    let currentProps: PD.Values<P>
     let renderObject: VolumeRenderObject | undefined
     let currentVolume: VolumeData
     let geometry: Geometry
     let locationIt: LocationIterator
 
-    async function create(ctx: VisualContext, volume: VolumeData, theme: Theme, props: Partial<PD.DefaultValues<P>> = {}) {
+    async function create(ctx: VisualContext, volume: VolumeData, theme: Theme, props: Partial<PD.Values<P>> = {}) {
         currentProps = Object.assign({}, defaultProps, props)
         if (props.isoValueRelative) {
             currentProps.isoValueAbsolute = VolumeIsoValue.calcAbsolute(currentVolume.dataStats, props.isoValueRelative)
@@ -62,7 +62,7 @@ export function VolumeVisual<P extends VolumeParams>(builder: VolumeVisualGeomet
         renderObject = await createRenderObject(ctx, geometry, locationIt, theme, currentProps)
     }
 
-    async function update(ctx: VisualContext, theme: Theme, props: Partial<PD.DefaultValues<P>> = {}) {
+    async function update(ctx: VisualContext, theme: Theme, props: Partial<PD.Values<P>> = {}) {
         if (!renderObject) return
         const newProps = Object.assign({}, currentProps, props)
 
@@ -87,7 +87,7 @@ export function VolumeVisual<P extends VolumeParams>(builder: VolumeVisualGeomet
 
     return {
         get renderObject () { return renderObject },
-        async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<PD.DefaultValues<P>> = {}, volume?: VolumeData) {
+        async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<PD.Values<P>> = {}, volume?: VolumeData) {
             if (!volume && !currentVolume) {
                 throw new Error('missing volume')
             } else if (volume && (!currentVolume || !renderObject)) {
@@ -152,12 +152,12 @@ export function VolumeRepresentation<P extends VolumeParams>(label: string, getP
     let visual: VolumeVisual<P>
 
     let _volume: VolumeData
-    let _props: PD.DefaultValues<P>
+    let _props: PD.Values<P>
     let _params: P
     let _theme: Theme
     let busy = false
 
-    function createOrUpdate(ctx: RepresentationContext, props: Partial<PD.DefaultValues<P>> = {}, themeProps: ThemeProps = {}, volume?: VolumeData) {
+    function createOrUpdate(ctx: RepresentationContext, props: Partial<PD.Values<P>> = {}, themeProps: ThemeProps = {}, volume?: VolumeData) {
         if (volume && volume !== _volume) {
             _params = getParams(ctx, volume)
             _volume = volume
diff --git a/src/mol-theme/color.ts b/src/mol-theme/color.ts
index b92620b7c7e8109b03a5ff84cb228c2194865c9d..028de8ef251322c99b6a5b9f089d7d8867ff7231 100644
--- a/src/mol-theme/color.ts
+++ b/src/mol-theme/color.ts
@@ -63,7 +63,7 @@ namespace ColorTheme {
     }
 
     export interface Provider<P extends PD.Params> {
-        readonly factory: (ctx: ThemeDataContext, props: PD.DefaultValues<P>) => ColorTheme<PD.DefaultValues<P>>
+        readonly factory: (ctx: ThemeDataContext, props: PD.Values<P>) => ColorTheme<PD.Values<P>>
         readonly params: (ctx: ThemeDataContext) => P
     }
 
diff --git a/src/mol-theme/color/carbohydrate-symbol.ts b/src/mol-theme/color/carbohydrate-symbol.ts
index 24940f7a6e813e9c837e738615758ca21b02304f..ecb4b26c414aa53a691033a61a312488b77c4834 100644
--- a/src/mol-theme/color/carbohydrate-symbol.ts
+++ b/src/mol-theme/color/carbohydrate-symbol.ts
@@ -29,7 +29,7 @@ export const CarbohydrateSymbolColorThemeParams = {
 export function getCarbohydrateSymbolColorThemeParams(ctx: ThemeDataContext) {
     return CarbohydrateSymbolColorThemeParams // TODO return copy
 }
-export type CarbohydrateSymbolColorThemeProps = PD.DefaultValues<typeof CarbohydrateSymbolColorThemeParams>
+export type CarbohydrateSymbolColorThemeProps = PD.Values<typeof CarbohydrateSymbolColorThemeParams>
 
 export function CarbohydrateSymbolColorTheme(ctx: ThemeDataContext, props: CarbohydrateSymbolColorThemeProps): ColorTheme<CarbohydrateSymbolColorThemeProps> {
     let color: LocationColor
diff --git a/src/mol-theme/color/chain-id.ts b/src/mol-theme/color/chain-id.ts
index 90045dc3a4a795a072b1b88726bb6c9227405d83..50018cacdd926fd304e7bd2855244d0f89d4e169 100644
--- a/src/mol-theme/color/chain-id.ts
+++ b/src/mol-theme/color/chain-id.ts
@@ -22,7 +22,7 @@ export const ChainIdColorThemeParams = {
 export function getChainIdColorThemeParams(ctx: ThemeDataContext) {
     return ChainIdColorThemeParams // TODO return copy
 }
-export type ChainIdColorThemeProps = PD.DefaultValues<typeof ChainIdColorThemeParams>
+export type ChainIdColorThemeProps = PD.Values<typeof ChainIdColorThemeParams>
 
 function getAsymId(unit: Unit): StructureElement.Property<string> {
     switch (unit.kind) {
diff --git a/src/mol-theme/color/cross-link.ts b/src/mol-theme/color/cross-link.ts
index 031c57eeff17860c584b2fb3e6c8f8f26accd22e..220455d57e71cd64d73ee3cf565706ae7a97a1e6 100644
--- a/src/mol-theme/color/cross-link.ts
+++ b/src/mol-theme/color/cross-link.ts
@@ -24,7 +24,7 @@ export const CrossLinkColorThemeParams = {
 export function getCrossLinkColorThemeParams(ctx: ThemeDataContext) {
     return CrossLinkColorThemeParams // TODO return copy
 }
-export type CrossLinkColorThemeProps = PD.DefaultValues<typeof CrossLinkColorThemeParams>
+export type CrossLinkColorThemeProps = PD.Values<typeof CrossLinkColorThemeParams>
 
 const distVecA = Vec3.zero(), distVecB = Vec3.zero()
 function linkDistance(link: Link.Location) {
diff --git a/src/mol-theme/color/element-index.ts b/src/mol-theme/color/element-index.ts
index 68264878048d981b7e93296a629113c13222022b..c2193810381e81f5815ce43b9ba65e54c9a70ec6 100644
--- a/src/mol-theme/color/element-index.ts
+++ b/src/mol-theme/color/element-index.ts
@@ -22,7 +22,7 @@ export const ElementIndexColorThemeParams = {
 export function getElementIndexColorThemeParams(ctx: ThemeDataContext) {
     return ElementIndexColorThemeParams // TODO return copy
 }
-export type ElementIndexColorThemeProps = PD.DefaultValues<typeof ElementIndexColorThemeParams>
+export type ElementIndexColorThemeProps = PD.Values<typeof ElementIndexColorThemeParams>
 
 export function ElementIndexColorTheme(ctx: ThemeDataContext, props: ElementIndexColorThemeProps): ColorTheme<ElementIndexColorThemeProps> {
     let color: LocationColor
diff --git a/src/mol-theme/color/element-symbol.ts b/src/mol-theme/color/element-symbol.ts
index 8c5d2bb095de8e752289d60c33e263a35fcc326e..33bc576fba0aed57fb30bb9bef0bb2cbf9ee5833 100644
--- a/src/mol-theme/color/element-symbol.ts
+++ b/src/mol-theme/color/element-symbol.ts
@@ -24,7 +24,7 @@ export const ElementSymbolColorThemeParams = {}
 export function getElementSymbolColorThemeParams(ctx: ThemeDataContext) {
     return ElementSymbolColorThemeParams // TODO return copy
 }
-export type ElementSymbolColorThemeProps = PD.DefaultValues<typeof ElementSymbolColorThemeParams>
+export type ElementSymbolColorThemeProps = PD.Values<typeof ElementSymbolColorThemeParams>
 
 export function elementSymbolColor(element: ElementSymbol): Color {
     const c = (ElementSymbolColors as { [k: string]: Color })[element];
diff --git a/src/mol-theme/color/molecule-type.ts b/src/mol-theme/color/molecule-type.ts
index 18dd0440caf9890fd1ffeb02b71d844cd98e8034..d0581ac4bef9d594b6cfeee2e8ae8ef003402f7f 100644
--- a/src/mol-theme/color/molecule-type.ts
+++ b/src/mol-theme/color/molecule-type.ts
@@ -30,7 +30,7 @@ export const MoleculeTypeColorThemeParams = {}
 export function getMoleculeTypeColorThemeParams(ctx: ThemeDataContext) {
     return MoleculeTypeColorThemeParams // TODO return copy
 }
-export type MoleculeTypeColorThemeProps = PD.DefaultValues<typeof MoleculeTypeColorThemeParams>
+export type MoleculeTypeColorThemeProps = PD.Values<typeof MoleculeTypeColorThemeParams>
 
 export function moleculeTypeColor(unit: Unit, element: ElementIndex): Color {
     const moleculeType = getElementMoleculeType(unit, element)
diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts
index 4b54924ef469aca559fc65b70b55886f21cd5755..de03c87007bbf5e7beb22d70ac8257f1f16b993c 100644
--- a/src/mol-theme/color/polymer-index.ts
+++ b/src/mol-theme/color/polymer-index.ts
@@ -21,7 +21,7 @@ export const PolymerIndexColorThemeParams = {
 export function getPolymerIndexColorThemeParams(ctx: ThemeDataContext) {
     return PolymerIndexColorThemeParams // TODO return copy
 }
-export type PolymerIndexColorThemeProps = PD.DefaultValues<typeof PolymerIndexColorThemeParams>
+export type PolymerIndexColorThemeProps = PD.Values<typeof PolymerIndexColorThemeParams>
 
 export function PolymerIndexColorTheme(ctx: ThemeDataContext, props: PolymerIndexColorThemeProps): ColorTheme<PolymerIndexColorThemeProps> {
     let color: LocationColor
diff --git a/src/mol-theme/color/residue-name.ts b/src/mol-theme/color/residue-name.ts
index ec2a645feacd0e73b395fd0fbc438f229354ab3b..d529c1452f16eef6472faea55962b2fd4691f5c7 100644
--- a/src/mol-theme/color/residue-name.ts
+++ b/src/mol-theme/color/residue-name.ts
@@ -65,7 +65,7 @@ export const ResidueNameColorThemeParams = {}
 export function getResidueNameColorThemeParams(ctx: ThemeDataContext) {
     return ResidueNameColorThemeParams // TODO return copy
 }
-export type ResidueNameColorThemeProps = PD.DefaultValues<typeof ResidueNameColorThemeParams>
+export type ResidueNameColorThemeProps = PD.Values<typeof ResidueNameColorThemeParams>
 
 export function residueNameColor(residueName: string): Color {
     const c = (ResidueNameColors as { [k: string]: Color })[residueName];
diff --git a/src/mol-theme/color/secondary-structure.ts b/src/mol-theme/color/secondary-structure.ts
index b53171be85c73d1c7209d571a127bc19c8371670..a11eff2a70a7dc6e8790a17176bf6b4fd754d314 100644
--- a/src/mol-theme/color/secondary-structure.ts
+++ b/src/mol-theme/color/secondary-structure.ts
@@ -35,7 +35,7 @@ export const SecondaryStructureColorThemeParams = {}
 export function getSecondaryStructureColorThemeParams(ctx: ThemeDataContext) {
     return SecondaryStructureColorThemeParams // TODO return copy
 }
-export type SecondaryStructureColorThemeProps = PD.DefaultValues<typeof SecondaryStructureColorThemeParams>
+export type SecondaryStructureColorThemeProps = PD.Values<typeof SecondaryStructureColorThemeParams>
 
 export function secondaryStructureColor(unit: Unit, element: ElementIndex): Color {
     let secStrucType = SecondaryStructureType.create(SecondaryStructureType.Flag.None)
diff --git a/src/mol-theme/color/sequence-id.ts b/src/mol-theme/color/sequence-id.ts
index a0b1b22d4a5b3d35661d67bbe3bb6dcf5db3f232..881c2057dc25260d707ba66a76cf7fd91b064291 100644
--- a/src/mol-theme/color/sequence-id.ts
+++ b/src/mol-theme/color/sequence-id.ts
@@ -22,7 +22,7 @@ export const SequenceIdColorThemeParams = {
 export function getSequenceIdColorThemeParams(ctx: ThemeDataContext) {
     return SequenceIdColorThemeParams // TODO return copy
 }
-export type SequenceIdColorThemeProps = PD.DefaultValues<typeof SequenceIdColorThemeParams>
+export type SequenceIdColorThemeProps = PD.Values<typeof SequenceIdColorThemeParams>
 
 function getSeqId(unit: Unit, element: ElementIndex): number {
     const { model } = unit
diff --git a/src/mol-theme/color/shape-group.ts b/src/mol-theme/color/shape-group.ts
index 172052bd7e0037c4141e207ee614b7c1304f1da1..acbb30625dcfe2b19037a9b54c8f41e08ff9a4f3 100644
--- a/src/mol-theme/color/shape-group.ts
+++ b/src/mol-theme/color/shape-group.ts
@@ -18,7 +18,7 @@ export const ShapeGroupColorThemeParams = {}
 export function getShapeGroupColorThemeParams(ctx: ThemeDataContext) {
     return ShapeGroupColorThemeParams // TODO return copy
 }
-export type ShapeGroupColorThemeProps = PD.DefaultValues<typeof ShapeGroupColorThemeParams>
+export type ShapeGroupColorThemeProps = PD.Values<typeof ShapeGroupColorThemeParams>
 
 export function ShapeGroupColorTheme(ctx: ThemeDataContext, props: ShapeGroupColorThemeProps): ColorTheme<ShapeGroupColorThemeProps> {
     return {
diff --git a/src/mol-theme/color/uniform.ts b/src/mol-theme/color/uniform.ts
index c02644b3f2e9f209fa772a2c799fce408143b33b..6f445450b1dccb7c1fd63181edda2347e9ff0217 100644
--- a/src/mol-theme/color/uniform.ts
+++ b/src/mol-theme/color/uniform.ts
@@ -18,7 +18,7 @@ export const UniformColorThemeParams = {
 export function getUniformColorThemeParams(ctx: ThemeDataContext) {
     return UniformColorThemeParams // TODO return copy
 }
-export type UniformColorThemeProps = PD.DefaultValues<typeof UniformColorThemeParams>
+export type UniformColorThemeProps = PD.Values<typeof UniformColorThemeParams>
 
 export function UniformColorTheme(ctx: ThemeDataContext, props: UniformColorThemeProps): ColorTheme<UniformColorThemeProps> {
     const color = props.value || DefaultColor
diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts
index 06760c3120e24769b6f7acf0712d267b0d19bcd8..d821a61d6c772c2748f04d9de90435c514bfdea0 100644
--- a/src/mol-theme/color/unit-index.ts
+++ b/src/mol-theme/color/unit-index.ts
@@ -21,7 +21,7 @@ export const UnitIndexColorThemeParams = {
 export function getUnitIndexColorThemeParams(ctx: ThemeDataContext) {
     return UnitIndexColorThemeParams // TODO return copy
 }
-export type UnitIndexColorThemeProps = PD.DefaultValues<typeof UnitIndexColorThemeParams>
+export type UnitIndexColorThemeProps = PD.Values<typeof UnitIndexColorThemeParams>
 
 export function UnitIndexColorTheme(ctx: ThemeDataContext, props: UnitIndexColorThemeProps): ColorTheme<UnitIndexColorThemeProps> {
     let color: LocationColor
diff --git a/src/mol-theme/size.ts b/src/mol-theme/size.ts
index 55487c2663c3c311021a533ee82581ee32b6da92..4676d896e9a161325c0afcf640d14987f56da0ae 100644
--- a/src/mol-theme/size.ts
+++ b/src/mol-theme/size.ts
@@ -27,7 +27,7 @@ namespace SizeTheme {
     }
 
     export interface Provider<P extends PD.Params> {
-        readonly factory: (ctx: ThemeDataContext, props: PD.DefaultValues<P>) => SizeTheme<PD.DefaultValues<P>>
+        readonly factory: (ctx: ThemeDataContext, props: PD.Values<P>) => SizeTheme<PD.Values<P>>
         readonly params: (ctx: ThemeDataContext) => P
     }
 
diff --git a/src/mol-theme/size/physical.ts b/src/mol-theme/size/physical.ts
index 45d43ceac6f8549e4f49c2c0db63854a047c0500..65017be880bd71c1a62f63522fb592ed6a8292be 100644
--- a/src/mol-theme/size/physical.ts
+++ b/src/mol-theme/size/physical.ts
@@ -18,7 +18,7 @@ export const PhysicalSizeThemeParams = {}
 export function getPhysicalSizeThemeParams(ctx: ThemeDataContext) {
     return PhysicalSizeThemeParams // TODO return copy
 }
-export type PhysicalSizeThemeProps = PD.DefaultValues<typeof PhysicalSizeThemeParams>
+export type PhysicalSizeThemeProps = PD.Values<typeof PhysicalSizeThemeParams>
 
 export function getPhysicalRadius(unit: Unit, element: ElementIndex): number {
     if (Unit.isAtomic(unit)) {
diff --git a/src/mol-theme/size/uniform.ts b/src/mol-theme/size/uniform.ts
index 139a4bcbc3505fde6ef80ce5270234d868deafd1..dee1b97bfffa8ffdbf63c70008c2291f5248c15c 100644
--- a/src/mol-theme/size/uniform.ts
+++ b/src/mol-theme/size/uniform.ts
@@ -16,7 +16,7 @@ export const UniformSizeThemeParams = {
 export function getUniformSizeThemeParams(ctx: ThemeDataContext) {
     return UniformSizeThemeParams // TODO return copy
 }
-export type UniformSizeThemeProps = PD.DefaultValues<typeof UniformSizeThemeParams>
+export type UniformSizeThemeProps = PD.Values<typeof UniformSizeThemeParams>
 
 export function UniformSizeTheme(ctx: ThemeDataContext, props: UniformSizeThemeProps): SizeTheme<UniformSizeThemeProps> {
     const size = props.value
diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts
index 463dbcf151ad2405541189f4d65c63011a024a96..ffc2d93f582aafbf6c5cf2a433e950650ea5e7a7 100644
--- a/src/mol-util/param-definition.ts
+++ b/src/mol-util/param-definition.ts
@@ -90,24 +90,39 @@ export namespace ParamDefinition {
         return { type: 'interval', label, description, defaultValue }
     }
 
-    export interface Obj<P extends Params> extends Base<{ [K in keyof P]: P[K]['defaultValue']}> {
-        type: 'obj',
-        pivot?: keyof P,
-        params: P
+    export interface Group<T extends { [key: string]: any }> extends Base<T> {
+        type: 'group',
+        params: T
     }
-    export function Obj<P extends Params>(label: string, description: string, params: P, pivot?: keyof P): Obj<P> {
-        return { type: 'obj', label, description, defaultValue: getDefaultValues(params), params, pivot };
+    export function Group<T extends { [key: string]: any }>(label: string, description: string, params: T): Group<T> {
+        return { type: 'group', label, description, defaultValue: getDefaultValues(params), params };
     }
 
-    export type Any = Select<any> | MultiSelect<any> | Boolean | Range | Text | Color | Numeric | Interval | Obj<any>
+    export interface Mapped<T> extends Base<{ name: string, params: T }> {
+        type: 'mapped',
+        select: Select<string>,
+        map(name: string): Params
+    }
+    export function Mapped<T>(label: string, description: string, defaultKey: string, names: [string, string][], map: Mapped<T>['map']): Mapped<T> {
+        return {
+            type: 'mapped',
+            label,
+            description,
+            defaultValue: { name: defaultKey, params: getDefaultValues(map(defaultKey)) as any },
+            select: Select<string>(label, description, defaultKey, names),
+            map
+        };
+    }
+
+    export type Any = Select<any> | MultiSelect<any> | Boolean | Range | Text | Color | Numeric | Interval | Group<any> | Mapped<any>
 
     export type Params = { [k: string]: Any }
-    export type DefaultValues<T extends Params> = { [k in keyof T]: T[k]['defaultValue'] }
+    export type Values<T extends Params> = { [k in keyof T]: T[k]['defaultValue'] }
 
     export function getDefaultValues<T extends Params>(params: T) {
         const d: { [k: string]: any } = {}
         Object.keys(params).forEach(k => d[k] = params[k].defaultValue)
-        return d as DefaultValues<T>
+        return d as Values<T>
     }
 
     export function clone<P extends Params>(params: P): P {