Skip to content

Commit

Permalink
feat: props table featured controls with actions
Browse files Browse the repository at this point in the history
  • Loading branch information
atanasster committed May 3, 2020
1 parent 42944f2 commit fc9a8f7
Show file tree
Hide file tree
Showing 30 changed files with 381 additions and 241 deletions.
18 changes: 10 additions & 8 deletions core/core/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { ControlTypes } from '@component-controls/specification';
import {
ControlTypes,
ComponentControls,
} from '@component-controls/specification';

import {
mergeControlValues,
resetControlValues,
getControlValues,
LoadedComponentControls,
} from './index';

describe('Controls utils', () => {
const controls: LoadedComponentControls = {
name: { type: ControlTypes.TEXT, value: 'hello', defaultValue: 'hello' },
age: { type: ControlTypes.NUMBER, value: 19, defaultValue: 19 },
const controls: ComponentControls = {
name: { type: ControlTypes.TEXT, value: 'hello', resetValue: 'hello' },
age: { type: ControlTypes.NUMBER, value: 19, resetValue: 19 },
};
const modifiedControls: LoadedComponentControls = {
name: { type: ControlTypes.TEXT, value: 'today', defaultValue: 'hello' },
age: { type: ControlTypes.NUMBER, value: 19, defaultValue: 19 },
const modifiedControls: ComponentControls = {
name: { type: ControlTypes.TEXT, value: 'today', resetValue: 'hello' },
age: { type: ControlTypes.NUMBER, value: 19, resetValue: 19 },
};

it('Should merge property value', () => {
Expand Down
19 changes: 11 additions & 8 deletions core/core/src/randomize.test.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
const faker = require('faker/locale/en_US');
import { LoadedComponentControls, LoadedComponentControl } from './utils';
import { ControlTypes } from '@component-controls/specification';
import {
ControlTypes,
ComponentControls,
ComponentControl,
} from '@component-controls/specification';
import { randomizeData } from '@component-controls/core/src/randomizeData';

describe('Options utility functions', () => {
const name: LoadedComponentControl = {
const name: ComponentControl = {
type: ControlTypes.TEXT,
value: 'Tom',
defaultValue: 'Tom',
};
const lastName: LoadedComponentControl = {
const lastName: ComponentControl = {
type: ControlTypes.TEXT,
value: 'Mark',
defaultValue: 'Mark',
};
const age: LoadedComponentControl = {
const age: ComponentControl = {
type: ControlTypes.NUMBER,
value: 19,
defaultValue: 19,
};
const male: LoadedComponentControl = {
const male: ComponentControl = {
type: ControlTypes.BOOLEAN,
value: true,
defaultValue: true,
};
const object: LoadedComponentControl = {
const object: ComponentControl = {
type: ControlTypes.OBJECT,
value: {
name,
Expand All @@ -39,7 +42,7 @@ describe('Options utility functions', () => {
male,
},
};
const controls: LoadedComponentControls = {
const controls: ComponentControl = {
name,
lastName,
age,
Expand Down
9 changes: 3 additions & 6 deletions core/core/src/randomizeData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import {
ControlTypes,
ComponentControlNumber,
ComponentControlOptions,
ComponentControls,
} from '@component-controls/specification';
const faker = require('faker/locale/en_US');

import { LoadedComponentControls } from './utils';

const arrayElements = (arr: any[], c?: number) => {
const array = arr || ['a', 'b', 'c'];
let count = 0;
Expand All @@ -32,9 +31,7 @@ interface RandomizedData {
[key: string]: any;
}

export const randomizeData = (
controls: LoadedComponentControls,
): RandomizedData => {
export const randomizeData = (controls: ComponentControls): RandomizedData => {
return Object.keys(controls)
.map(name => {
const control = controls[name];
Expand Down Expand Up @@ -109,7 +106,7 @@ export const randomizeData = (
return {
name,
value: {
...randomizeData(control.value as LoadedComponentControls),
...randomizeData(control.value as ComponentControls),
},
};
}
Expand Down
45 changes: 11 additions & 34 deletions core/core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,12 @@ import {
ControlTypes,
} from '@component-controls/specification';

/**
* once controls are loaded, the value is saved into
* defaultValue, an additional field in Loaded...
*/

export type LoadedComponentControl = ComponentControl & { defaultValue?: any };
export interface LoadedComponentControls {
[name: string]: LoadedComponentControl;
}

// save default value for 'reset'
export const loadControls = (
controls: ComponentControls,
): LoadedComponentControls =>
Object.keys(controls).reduce((v, key) => {
const prop = controls[key];
return { ...v, [key]: { ...prop, defaultValue: prop.value } };
}, {});

const mergeValue = (control: ComponentControl, value: any): any => {
if (control && control.type === ControlTypes.OBJECT) {
return {
...control,
value: mergeControlValues(
control.value as LoadedComponentControls,
control.value as ComponentControls,
undefined,
value,
),
Expand All @@ -39,18 +20,16 @@ const mergeValue = (control: ComponentControl, value: any): any => {
return {
...control,
value,
defaultValue:
(control as LoadedComponentControl).defaultValue === undefined
? control.value
: (control as LoadedComponentControl).defaultValue,
resetValue:
control.resetValue === undefined ? control.value : control.resetValue,
};
};

export const mergeControlValues = (
controls: LoadedComponentControls,
controls: ComponentControls,
controlName: string | undefined,
value: any,
): LoadedComponentControls => {
): ComponentControls => {
return controlName
? {
...controls,
Expand All @@ -69,15 +48,15 @@ export const mergeControlValues = (
};

export const resetControlValues = (
controls: LoadedComponentControls,
controls: ComponentControls,
controlName?: string,
) => {
return controlName
? controls[controlName].defaultValue
? controls[controlName].resetValue
: Object.keys(controls).reduce(
(acc, key) => ({
...acc,
[key]: controls[key].defaultValue,
[key]: controls[key].resetValue,
}),
{},
);
Expand All @@ -88,7 +67,7 @@ export interface ControlValues {
}

export const getControlValue = (
controls: LoadedComponentControls,
controls: ComponentControls,
propName: string,
): any => {
const control: ComponentControl = controls[propName];
Expand All @@ -104,16 +83,14 @@ export const getControlValue = (
control.type === ControlTypes.OBJECT &&
typeof value === 'object'
) {
return getControlValues(value as LoadedComponentControls);
return getControlValues(value as ComponentControls);
}
return value;
}
return undefined;
};

export const getControlValues = (
controls: LoadedComponentControls,
): ControlValues =>
export const getControlValues = (controls: ComponentControls): ControlValues =>
controls
? Object.keys(controls).reduce((acc, key) => {
const value = getControlValue(controls, key);
Expand Down
28 changes: 18 additions & 10 deletions core/instrument/test/__snapshots__/csf-props-info.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,48 @@ Can adapt to multiple groups of controls, displaying them in their own tabs.",
"description": "if false, will nothave a collapsible frame.",
"parentName": "BlockContainerProps",
"type": Object {
"name": "boolean",
"raw": "boolean",
"name": "any",
"raw": "any",
},
},
"description": Object {
"description": "optional markdown description.",
"parentName": "BlockContainerProps",
"type": Object {
"name": "any",
"raw": "any",
},
},
"id": Object {
"description": "id of the story",
"parentName": "StoryInputProps",
"type": Object {
"name": "string",
"raw": "string",
"name": "any",
"raw": "any",
},
},
"name": Object {
"description": "alternatively you can use the name of a story to load from an external file",
"parentName": "StoryInputProps",
"type": Object {
"name": "string",
"raw": "string",
"name": "any",
"raw": "any",
},
},
"sxStyle": Object {
"description": "theme-ui styling object for Block Box",
"parentName": "BlockContainerProps",
"type": Object {
"name": "SystemStyleObject",
"raw": "SystemStyleObject",
"name": "any",
"raw": "any",
},
},
"title": Object {
"description": "optional section title for the block.",
"parentName": "BlockContainerProps",
"type": Object {
"name": "string",
"raw": "string",
"name": "any",
"raw": "any",
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,14 @@ Array values are converted into responsive values.
],
},
},
"description": Object {
"description": "optional markdown description.",
"parentName": "BlockContainerProps",
"type": Object {
"name": "string",
"raw": "string",
},
},
"dir": Object {
"parentName": "HTMLAttributes",
"type": Object {
Expand Down Expand Up @@ -2246,7 +2254,7 @@ If an array of components is specified, each component will be displayed in a se
if the function returns false, it can stop chabging to the new tab",
"type": Object {
"name": "function",
"raw": "((name: string, component: StoryComponent) => boolean | void) & ((event: SyntheticEvent<HTMLDivElement, Event>) => void)",
"raw": "((event: SyntheticEvent<HTMLDivElement, Event>) => void) | ((name: string, component: StoryComponent) => boolean | void)",
},
},
"onSelectCapture": Object {
Expand Down Expand Up @@ -2902,6 +2910,13 @@ import { jsx } from 'theme-ui'
"raw": "string",
},
},
"visibleOnControlsOnly": Object {
"description": "set to true if you need the blockto be visible even if only controls are available",
"type": Object {
"name": "boolean",
"raw": "boolean",
},
},
"vocab": Object {
"parentName": "HTMLAttributes",
"type": Object {
Expand Down
18 changes: 18 additions & 0 deletions core/specification/src/controls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,28 @@ export interface ComponentControlBase<T> {
*/
value?: T;

/**
* default value is usually set at run-time, from the value
*/
defaultValue?: T;

/**
* reset value - this is automatically saved as the initial 'value'
* used when user wants to click rest and go back to the initial values
*/
resetValue?: T;

/**
* hide the label from the property editor
*/
hideLabel?: boolean;

/**
* full text property description.
* can use markdown.
*/
description?: string;

/**
* hide the property editor for this property
* will only use the value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,26 @@ overview.story = {
'Story with two dynamic control values: `name` and `age`. You can use the controls to edit the story properties at run-time.',

controls: {
name: { type: ControlTypes.TEXT, label: 'Name', value: 'Mark' },
name: {
type: ControlTypes.TEXT,
label: 'Name',
value: 'Mark',
description: `
## name of the person
any text is allowed
`,
},
age: {
type: ControlTypes.NUMBER,
description: `
## age of the person
numeric, values between 10 and 75 allowed
`,
label: 'Age',
value: 19,
defaultValue: null,
min: 10,
max: 75,
},
Expand Down
1 change: 1 addition & 0 deletions integrations/storybook/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export default config({
'./src/register-props-panel.tsx',
'./src/register-storysource-panel.tsx',
'./src//docs-page/full-page.tsx',
'./src//docs-page/testing-page.tsx',
],
});
16 changes: 16 additions & 0 deletions integrations/storybook/src/docs-page/testing-page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* eslint-disable react/display-name */
import React from 'react';
import { TestingPage } from '@component-controls/pages';
import { DocsContainer } from './DocsContainer';

export default {
key: 'test',
title: 'Testing',
render: ({ active }: { active: boolean }) => {
return (
<DocsContainer active={active}>
<TestingPage />
</DocsContainer>
);
},
};
Loading

0 comments on commit fc9a8f7

Please sign in to comment.