diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 2f04423..0a8a1e4 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -3,7 +3,9 @@ - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Passes properly formatted message object - casts fals - compose - caldera-components-error - Does have caldera-components-error class when not an error - setValue - 78.23 - simulate - checkbox - configValues - new Date + fieldsL + open + onChangeListType + fields + it( + options + ses props.value to set value + focus + Button + buttons + Right + Updates is open state when blurred + Options › Updates is open state when blurred + isOpen + Select + Receives the updated value + .simulate('change' skip - CalderaConditionals - prepare - HTML5 - validators - fieldValues - isValid - considers empty email field valid if not required - Considers an empty string not a valid stringOrNumber - reduceConfigFieldsToValues - add - addValidatorsForType - Adds the props - render - Render - blur - fieldInnerPropTypes - addAutomaticValidators + value + fieldProps + onSelect message + Magic + toMatc + magic + state + event + RenderItem + toMat + opens caldera-components @@ -157,12 +141,17 @@ fieldValues Validators isValidOrEmpty + it.skip( + it( $PROJECT_DIR$/coverage - $PROJECT_DIR$/src/components $PROJECT_DIR$/src/components/validation $PROJECT_DIR$/src + $PROJECT_DIR$/src/components + $PROJECT_DIR$/src/components/fields + $PROJECT_DIR$ + $PROJECT_DIR$/src/components/fields/magic-select @@ -171,23 +160,6 @@ @@ -242,10 +231,10 @@ - @@ -261,16 +250,36 @@ + + + + + + + + + + + + + + + + + + + + @@ -278,6 +287,7 @@ + @@ -285,7 +295,7 @@ - + @@ -293,7 +303,8 @@ - + + + +
    + + + + + +
    + + public + class + + + + | source +
    + +
    +

    MagicFieldGroup

    + + + + + +

    Extends:

    react~React.PureComponent → MagicFieldGroup
    + + + + + + + + + +

    Encapsulates a complete Magic Select field group including label and the type chooser and the input

    +
    + + + + + + + + + +
    + + + +

    Constructor Summary

    + + + + + + + + + +
    Public Constructor
    + public + + + + + +
    +

    + + + + constructor(props: Object) +

    +
    +
    + + +

    Create a MagicFieldGroup component

    +
    +
    +
    + + +
    +
    +

    Member Summary

    + + + + + + + + + +
    Public Members
    + public + + + + + +
    +

    + + + + state: {"currentListType": *, "isOpen": *} +

    +
    +
    + + + +
    +
    + + +
    +
    +

    Method Summary

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Public Methods
    + public + + + + + +
    +

    + + + + items(): Array +

    +
    +
    + + +

    Create the list of items

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + listTypeOptions(): *[] +

    +
    +
    + + +

    Options for type chooser

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + onChange(newValue: String | number) +

    +
    +
    + + +

    Handle direct change events

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + onChangeListType({String}newType: *) +

    +
    +
    + + +

    Update list of tags to show

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + onInputBlur() +

    +
    +
    + + +

    Handle when the field is blurred

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + onInputFocus() +

    +
    +
    + + +

    Handle when the field gets focus

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + onSelect(value: String | number) +

    +
    +
    + + +

    Handle when the option is chosen

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + render(): * +

    +
    +
    + + +

    Render MagicFieldGroup component

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + renderItem(item: object, isHighlighted: bool): * +

    +
    +
    + + +

    Render option

    +
    +
    +
    + + +
    +
    + + + + + +

    Public Constructors

    + +
    +

    + public + + + + + + constructor(props: Object) + + + + source + +

    + + + + +

    Create a MagicFieldGroup component

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    propsObject
    +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    Public Members

    + +
    +

    + public + + + + + + state: {"currentListType": *, "isOpen": *} + + + + source + +

    + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    Public Methods

    + +
    +

    + public + + + + + + items(): Array + + + + source + +

    + + + + +

    Create the list of items

    +
    + + + +
    +
    + +
    +

    Return:

    + + + + + + + +
    Array
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + listTypeOptions(): *[] + + + + source + +

    + + + + +

    Options for type chooser

    +
    + + + +
    +
    + +
    +

    Return:

    + + + + + + + +
    *[]
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + onChange(newValue: String | number) + + + + source + +

    + + + + +

    Handle direct change events

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    newValueString | number
    +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + onChangeListType({String}newType: *) + + + + source + +

    + + + + +

    Update list of tags to show

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    {String}newType*
    +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + onInputBlur() + + + + source + +

    + + + + +

    Handle when the field is blurred

    +
    + + + +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + onInputFocus() + + + + source + +

    + + + + +

    Handle when the field gets focus

    +
    + + + +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + onSelect(value: String | number) + + + + source + +

    + + + + +

    Handle when the option is chosen

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    valueString | number
    +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + render(): * + + + + source + +

    + + + + +

    Render MagicFieldGroup component

    +
    + + + +
    +
    + +
    +

    Return:

    + + + + + + + +
    *
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + renderItem(item: object, isHighlighted: bool): * + + + + source + +

    + + + + +

    Render option

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    itemobject
    isHighlightedbool
    +
    +
    + +
    +

    Return:

    + + + + + + + +
    *
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    + + + + + + + + + + + + diff --git a/docs/class/src/components/fields/magic-select/MagicItem.js~MagicItem.html b/docs/class/src/components/fields/magic-select/MagicItem.js~MagicItem.html new file mode 100644 index 0000000..3e32e79 --- /dev/null +++ b/docs/class/src/components/fields/magic-select/MagicItem.js~MagicItem.html @@ -0,0 +1,244 @@ + + + + + + MagicItem | Caldera Components library + + + + + + + +
    + + + Reference + Source + + +
    + + + +
    + + public + class + + + + | source +
    + +
    +

    MagicItem

    + + + + + +

    Extends:

    react~React.PureComponent → MagicItem
    + + + + + + + + + +

    Create magic item for option of magic selects

    +

    This can not be a functional component +https://github.com/reactjs/react-autocomplete/pull/293#issuecomment-371617758

    +
    + + + + + + + + + +
    + + + + + +

    Method Summary

    + + + + + + + + + +
    Public Methods
    + public + + + + + +
    +

    + + + + render(): * +

    +
    +
    + + +

    Render magic item components

    +
    +
    +
    + + +
    +
    + + + + + + + +

    Public Methods

    + +
    +

    + public + + + + + + render(): * + + + + source + +

    + + + + +

    Render magic item components

    +
    + + + +
    +
    + +
    +

    Return:

    + + + + + + + +
    *
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    + + + + + + + + + + + + diff --git a/docs/class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html b/docs/class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html new file mode 100644 index 0000000..c810380 --- /dev/null +++ b/docs/class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html @@ -0,0 +1,770 @@ + + + + + + MagicSelect | Caldera Components library + + + + + + + +
    + + + Reference + Source + + +
    + + + +
    + + public + class + + + + | source +
    + +
    +

    MagicSelect

    + + + + + +

    Extends:

    react~React.PureComponent → MagicSelect
    + + + + + + + + + +

    Encapsulates a complete Magic Select field

    +
    + + + + + + + + + +
    + + + +

    Constructor Summary

    + + + + + + + + + +
    Public Constructor
    + public + + + + + +
    +

    + + + + constructor(props: Object) +

    +
    +
    + + +

    Create a MagicSelect component

    +
    +
    +
    + + +
    +
    + +

    Method Summary

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Public Methods
    + public + + + + + +
    +

    + + + + onChange(event: Event) +

    +
    +
    + + +

    Handle direct change events

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + onInputBlur() +

    +
    +
    + + +

    Handle when the field is blurred

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + onInputFocus() +

    +
    +
    + + +

    Handle when the field gets focus

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + onSelect(value: String | number) +

    +
    +
    + + +

    Handle when the option is chosen

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + render(): * +

    +
    +
    + + +

    Render MagicSelect component

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + renderItem(item: object, isHighlighted: bool): * +

    +
    +
    + + +

    Render option

    +
    +
    +
    + + +
    +
    + + + + + +

    Public Constructors

    + +
    +

    + public + + + + + + constructor(props: Object) + + + + source + +

    + + + + +

    Create a MagicSelect component

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    propsObject
    +
    +
    + + + + + + + + + + + + + + + + + +
    +
    + +

    Public Methods

    + +
    +

    + public + + + + + + onChange(event: Event) + + + + source + +

    + + + + +

    Handle direct change events

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    eventEvent
    +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + onInputBlur() + + + + source + +

    + + + + +

    Handle when the field is blurred

    +
    + + + +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + onInputFocus() + + + + source + +

    + + + + +

    Handle when the field gets focus

    +
    + + + +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + onSelect(value: String | number) + + + + source + +

    + + + + +

    Handle when the option is chosen

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    valueString | number
    +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + render(): * + + + + source + +

    + + + + +

    Render MagicSelect component

    +
    + + + +
    +
    + +
    +

    Return:

    + + + + + + + +
    *
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + renderItem(item: object, isHighlighted: bool): * + + + + source + +

    + + + + +

    Render option

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    itemobject
    isHighlightedbool
    +
    +
    + +
    +

    Return:

    + + + + + + + +
    *
    +
    +
    +
    + + + + + + + + + + + + + + + +
    +
    +
    + + + + + + + + + + + + diff --git a/docs/coverage.json b/docs/coverage.json index 4e74899..3c656fc 100644 --- a/docs/coverage.json +++ b/docs/coverage.json @@ -1,25 +1,27 @@ { - "coverage": "66.1%", - "expectCount": 59, - "actualCount": 39, + "coverage": "72.72%", + "expectCount": 88, + "actualCount": 64, "files": { "src/App.js": { - "expectCount": 13, + "expectCount": 15, "actualCount": 0, "undocumentLines": [ - 8, 9, - 23, + 10, 24, - 35, - 36, - 57, - 58, - 79, - 85, - 89, - 95, - 97 + 42, + 43, + 54, + 55, + 76, + 77, + 98, + 105, + 109, + 115, + 117, + 119 ] }, "src/components/RenderGroup.js": { @@ -52,6 +54,11 @@ "actualCount": 1, "undocumentLines": [] }, + "src/components/fields/button-group/ButtonGroup.js": { + "expectCount": 1, + "actualCount": 1, + "undocumentLines": [] + }, "src/components/fields/factories/fieldFactory.js": { "expectCount": 1, "actualCount": 1, @@ -77,6 +84,23 @@ "actualCount": 1, "undocumentLines": [] }, + "src/components/fields/magic-select/MagicFieldGroup.js": { + "expectCount": 12, + "actualCount": 11, + "undocumentLines": [ + 24 + ] + }, + "src/components/fields/magic-select/MagicItem.js": { + "expectCount": 3, + "actualCount": 3, + "undocumentLines": [] + }, + "src/components/fields/magic-select/MagicSelect.js": { + "expectCount": 8, + "actualCount": 8, + "undocumentLines": [] + }, "src/components/fields/messages/Message.js": { "expectCount": 2, "actualCount": 2, @@ -93,10 +117,11 @@ "undocumentLines": [] }, "src/components/fields/propTypes.js": { - "expectCount": 6, - "actualCount": 5, + "expectCount": 9, + "actualCount": 7, "undocumentLines": [ - 68 + 68, + 92 ] }, "src/components/fields/select/SelectField.js": { diff --git a/docs/file/src/App.js.html b/docs/file/src/App.js.html index 2a3d115..81ec860 100644 --- a/docs/file/src/App.js.html +++ b/docs/file/src/App.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -79,6 +86,7 @@ import {FieldGroup} from "./components/fields/FieldGroup"; import {fieldSetFactory} from "./components/fields/factories/fieldSetFactory"; import {RenderGroup} from "./components/RenderGroup"; +import {MagicFieldGroup} from "./components/fields/magic-select/MagicFieldGroup"; let textFieldValue = 'Roy,Mike'; const textFieldConfig = { @@ -95,6 +103,24 @@ }; +const numberFieldConfig = { + 'id': 'cf--something-some-number', + 'label': 'The number of something', + 'desc': 'How many somethings?', + 'type': 'text', + 'inputType': 'number', + attributes: { + min: -1, + max: 22, + step: 0.1, + }, + value: 42, + onValueChange: (newNumberValue) =>{ + console.log(newNumberValue); + }, + +}; + let hiddenFieldValue = '42'; const hiddenFieldConfig = { 'id': 'cf-something-sequence-id', @@ -155,7 +181,8 @@ textFieldConfig, hiddenFieldConfig, selectFieldConfig, - fieldSetField + fieldSetField, + numberFieldConfig ]; const configFieldEls = fieldSetFactory(configFields); @@ -167,6 +194,8 @@ three: '' }; +let magicFieldValue = ''; + class App extends Component { render() { @@ -198,6 +227,40 @@ })} </div> + <div> + <h2>Magic Select</h2> + <MagicFieldGroup + id={'magic-5'} + label={'Magic Group'} + fieldClassName={'magic'} + onValueChange={(newValue) => { + magicFieldValue = newValue; + } } + fieldsList={[ + { + label: 'Field One', + value: '%fldOne%' + }, + { + label: 'Field Two', + value: '%fldTwo%' + }, + { + label: 'Field Three', + value: '%fldThree%' + }, + ]} + systemTagsList={[ + { + label: 'User First Name', + value: '{user:first_name}' + } + ]} + isOpen={true} + value={magicFieldValue} + /> + </div> + <div> <h2>Inputs</h2> <FieldGroup diff --git a/docs/file/src/components/RenderGroup.js.html b/docs/file/src/components/RenderGroup.js.html index d7d67da..b2866f1 100644 --- a/docs/file/src/components/RenderGroup.js.html +++ b/docs/file/src/components/RenderGroup.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -110,7 +117,7 @@ return configField.ID ? configField.ID : configField.id ? configField.id : false; } - if( 'function' === typeof this.props.onBlur ){ + if( 'function' === typeof this.props.onBlur ){ configFields.forEach((configField, configFieldIndex ) => { const configFieldId = findFieldId(configField); if( configFieldId ){ @@ -123,7 +130,7 @@ }); } - if( 'function' === typeof this.props.onFocus ){ + if( 'function' === typeof this.props.onFocus ){ configFields.forEach((configField, configFieldIndex ) => { const configFieldId = findFieldId(configField); if( configFieldId ){ diff --git a/docs/file/src/components/conditional-logic/checkConfigFieldConditionals.js.html b/docs/file/src/components/conditional-logic/checkConfigFieldConditionals.js.html index de88bf5..258940c 100644 --- a/docs/file/src/components/conditional-logic/checkConfigFieldConditionals.js.html +++ b/docs/file/src/components/conditional-logic/checkConfigFieldConditionals.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/conditional-logic/checkConfigFieldsConditionals.js.html b/docs/file/src/components/conditional-logic/checkConfigFieldsConditionals.js.html index 6e5f8b7..1e75ebb 100644 --- a/docs/file/src/components/conditional-logic/checkConfigFieldsConditionals.js.html +++ b/docs/file/src/components/conditional-logic/checkConfigFieldsConditionals.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/conditional-logic/index.js.html b/docs/file/src/components/conditional-logic/index.js.html index 4df4c89..a731f59 100644 --- a/docs/file/src/components/conditional-logic/index.js.html +++ b/docs/file/src/components/conditional-logic/index.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/conditional-logic/util.js.html b/docs/file/src/components/conditional-logic/util.js.html index b1097c6..b3d06f8 100644 --- a/docs/file/src/components/conditional-logic/util.js.html +++ b/docs/file/src/components/conditional-logic/util.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/FieldGroup.js.html b/docs/file/src/components/fields/FieldGroup.js.html index d9ee939..c28923d 100644 --- a/docs/file/src/components/fields/FieldGroup.js.html +++ b/docs/file/src/components/fields/FieldGroup.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -85,6 +92,7 @@ import {Message} from './messages/Message'; import {messageObjectFactory} from './messages/messageObjectFactory'; import {fieldsetCheckboxHandler} from './field-group-change-handlers/fieldsetCheckboxHandler'; +import {MagicFieldGroup} from './magic-select/MagicFieldGroup'; /** * Represents one configField -- wrapper, label and input. @@ -94,6 +102,9 @@ * @constructor */ export const FieldGroup = (props) => { + if( 'magic' === props.type ){ + return <MagicFieldGroup {...props} />; + } /** * Creates the id attribute @@ -193,11 +204,8 @@ <div className={RenderGroup.classNames.fieldWrapper} > - <label - htmlFor={fieldProps.id} - > - {fieldProps.label} - </label> + <FieldGroup.Label id={fieldProps.id} label={fieldProps.label} /> + <Message message={message} /> @@ -238,13 +246,39 @@ return fieldInner(props); }; - +/** + * The prop type definitions for FieldGroup components + * + * @type {{id: (boolean|shim|*), isBlockInput: shim, isRequired: shim, help: shim, label: (boolean|shim|*), type: shim, value: shim, onValueChange: (boolean|shim|*), inputType: shim}} + */ FieldGroup.propTypes = fieldGroupPropTypes; +/** + * Default props for FieldGroups + * + * @type {{isBlockInput: boolean, isRequired: boolean, help: string}} + */ FieldGroup.defaultProps = { isBlockInput: true, isRequired: false, help: '' +}; + +/** + * Creates the FieldGroup's label component + * + * @param {Object} props + * @return {*} + * @constructor + */ +FieldGroup.Label = (props) => { + return ( + <label + htmlFor={props.id} + > + {props.label} + </label> + ); }; diff --git a/docs/file/src/components/fields/FieldInner.js.html b/docs/file/src/components/fields/FieldInner.js.html index c1c4118..50dc17c 100644 --- a/docs/file/src/components/fields/FieldInner.js.html +++ b/docs/file/src/components/fields/FieldInner.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -115,6 +122,7 @@ switch( props.type ){ case 'select': case 'dropdown': + const options = Array.isArray(props.options) ? props.options : []; return ( <SelectField id={props.id} @@ -123,7 +131,7 @@ value={props.value} onValueChange={props.onValueChange} inputType={props.inputType} - options={props.options} + options={options} disabled={props.disabled} onBlur={props.onBlur} onFocus={props.onFocus} diff --git a/docs/file/src/components/fields/button-group/ButtonGroup.js.html b/docs/file/src/components/fields/button-group/ButtonGroup.js.html new file mode 100644 index 0000000..0e4ff4b --- /dev/null +++ b/docs/file/src/components/fields/button-group/ButtonGroup.js.html @@ -0,0 +1,176 @@ + + + + + + src/components/fields/button-group/ButtonGroup.js | Caldera Components library + + + + + + + +
    + + + Reference + Source + + +
    + + + +

    src/components/fields/button-group/ButtonGroup.js

    +
    import React from 'react';
    +import {optionShape} from '../propTypes';
    +import PropTypes from 'prop-types';
    +/**
    + * Creates a button group field
    + *
    + * @param {Object} props
    + * @returns {*}
    + * @constructor
    + */
    +export const ButtonGroup = (props) => {
    +	/**
    +	 * Dispatches new value(s) to parent
    +	 *
    +	 * @param selection
    +	 * @returns {*}
    +	 */
    +	function changeHandler(selection) {
    +		return props.onChange(selection);
    +	}
    +
    +	/**
    +	 * Render a button group
    +	 */
    +	return (
    +		<div
    +			role="group"
    +		>
    +			{props.options.map(option => {
    +				return <button
    +					aria-label={option.ariaLabel ? option.ariaLabel : option.label}
    +					key={option.value}
    +					className={props.value === option.value ? 'selected' : 'not-selected' }
    +					onClick={() => {
    +						return changeHandler(option.value);
    +					}}
    +				>
    +					{option.hasOwnProperty('icon')&&
    +						<span className={option.icon}></span>
    +					}
    +					{!option.hasOwnProperty('icon') &&
    +						<React.Fragment>{option.label}</React.Fragment>
    +					}
    +
    +				</button>;
    +			})}
    +		</div>
    +	);
    +};
    +
    +/**
    + * Prop definition for select fields
    + *
    + * @type {{}}
    + */
    +ButtonGroup.propTypes = {
    +	onChange: PropTypes.func.isRequired,
    +	options: PropTypes.arrayOf(
    +		PropTypes.shape({
    +			...optionShape,
    +			icon:PropTypes.string,
    +			ariaLabel:PropTypes.string
    +		})
    +	),
    +	value: PropTypes.oneOfType([
    +		PropTypes.number,
    +		PropTypes.string
    +	])
    +};
    +
    +/**
    + * Default props for select fields
    + *
    + * @type {{options: Array}}
    + */
    +ButtonGroup.defaultProps = {
    +	options: []
    +};
    + +
    + + + + + + + + + + + + diff --git a/docs/file/src/components/fields/factories/fieldFactory.js.html b/docs/file/src/components/fields/factories/fieldFactory.js.html index e91a416..cccb289 100644 --- a/docs/file/src/components/fields/factories/fieldFactory.js.html +++ b/docs/file/src/components/fields/factories/fieldFactory.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/factories/fieldSetFactory.js.html b/docs/file/src/components/fields/factories/fieldSetFactory.js.html index 433f985..2b8ea4a 100644 --- a/docs/file/src/components/fields/factories/fieldSetFactory.js.html +++ b/docs/file/src/components/fields/factories/fieldSetFactory.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/factories/index.js.html b/docs/file/src/components/fields/factories/index.js.html index 60f1b79..d096812 100644 --- a/docs/file/src/components/fields/factories/index.js.html +++ b/docs/file/src/components/fields/factories/index.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/factories/prepareFieldConfig.js.html b/docs/file/src/components/fields/factories/prepareFieldConfig.js.html index 0fbd2ef..8eec99a 100644 --- a/docs/file/src/components/fields/factories/prepareFieldConfig.js.html +++ b/docs/file/src/components/fields/factories/prepareFieldConfig.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -73,7 +80,7 @@

    src/components/fields/factories/prepareFieldConfig.js

    -
    import {fieldGroupPropTypes} from '../propTypes';
    +
    import {fieldGroupPropTypes,magicGroupPropTypes} from '../propTypes';
     import {isValidHtml5type, toBoolean} from '../util';
     import {messageObjectFactory} from '../messages/messageObjectFactory';
     
    @@ -128,7 +135,8 @@
     		validators = fieldArgs.validators;
     	}
     
    -	fieldArgs = pick(fieldArgs, Object.keys(fieldGroupPropTypes));
    +	const keys = 'magic' === fieldArgs.type  ? magicGroupPropTypes : fieldGroupPropTypes;
    +	fieldArgs = pick(fieldArgs, Object.keys(keys));
     	fieldArgs.disabled = toBoolean(fieldArgs.disabled);
     	fieldArgs.message = 'object' === typeof  fieldArgs.message
     		? messageObjectFactory(fieldArgs.message)
    diff --git a/docs/file/src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js.html b/docs/file/src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js.html
    index b118462..d1183dd 100644
    --- a/docs/file/src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js.html
    +++ b/docs/file/src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js.html
    @@ -47,13 +47,20 @@
     
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/index.js.html b/docs/file/src/components/fields/index.js.html index 4a1dc7e..fdbc23f 100644 --- a/docs/file/src/components/fields/index.js.html +++ b/docs/file/src/components/fields/index.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/input/Input.js.html b/docs/file/src/components/fields/input/Input.js.html index ae46e6b..5c89dae 100644 --- a/docs/file/src/components/fields/input/Input.js.html +++ b/docs/file/src/components/fields/input/Input.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/magic-select/MagicFieldGroup.js.html b/docs/file/src/components/fields/magic-select/MagicFieldGroup.js.html new file mode 100644 index 0000000..ba2e6b3 --- /dev/null +++ b/docs/file/src/components/fields/magic-select/MagicFieldGroup.js.html @@ -0,0 +1,326 @@ + + + + + + src/components/fields/magic-select/MagicFieldGroup.js | Caldera Components library + + + + + + + +
    + + + Reference + Source + + +
    + + + +

    src/components/fields/magic-select/MagicFieldGroup.js

    +
    import React from 'react';
    +import {magicGroupPropTypes} from '../propTypes';
    +import classNames from 'classnames';
    +import {MagicItem} from './MagicItem';
    +import {ButtonGroup} from '../button-group/ButtonGroup';
    +import {MagicSelect} from './MagicSelect';
    +import {RenderGroup} from '../../RenderGroup';
    +import {Message} from '../messages/Message';
    +import {FieldGroup} from '../FieldGroup';
    +
    +
    +/**
    + * Encapsulates a complete Magic Select field group including label and the type chooser and the input
    + */
    +export class MagicFieldGroup extends React.PureComponent {
    +
    +	/**
    +	 * Create a MagicFieldGroup component
    +	 *
    +	 * @param {Object} props
    +	 */
    +	constructor(props) {
    +		super(props);
    +		this.state = {
    +			currentListType: props.defaultList,
    +			isOpen: props.isOpen,
    +		};
    +		this.onChange = this.onChange.bind(this);
    +		this.items = this.items.bind(this);
    +		this.onChange = this.onChange.bind(this);
    +		this.onSelect = this.onSelect.bind(this);
    +		this.onInputFocus = this.onInputFocus.bind(this);
    +		this.renderItem = this.renderItem.bind(this);
    +		this.onInputBlur = this.onInputBlur.bind(this);
    +		this.onChangeListType = this.onChangeListType.bind(this);
    +		this.listTypeOptions = this.listTypeOptions.bind(this);
    +	}
    +
    +	/**
    +	 * Handle direct change events
    +	 * @param {String|number} newValue
    +	 */
    +	onChange(newValue) {
    +		this.props.onValueChange(newValue);
    +	}
    +
    +	/**
    +	 * Handle when the field gets focus
    +	 */
    +	onInputFocus() {
    +		this.setState({isOpen: true});
    +	}
    +
    +	/**
    +	 * Handle when the field is blurred
    +	 */
    +	onInputBlur() {
    +		this.setState({isOpen: false});
    +	}
    +
    +
    +	/**
    +	 * Handle when the option is chosen
    +	 * @param {String|number} value
    +	 */
    +	onSelect(value) {
    +		this.props.onValueChange(value);
    +		this.setState({isOpen: false});
    +	}
    +
    +	/**
    +	 * Update list of tags to show
    +	 * @param {String}newType
    +	 */
    +	onChangeListType(newType){
    +		if( ! this.state.isOpen ){
    +			this.setState({isOpen:true});
    +		}
    +		this.setState({currentListType:newType});
    +	}
    +
    +	/**
    +	 * Render option
    +	 *
    +	 * @param {object} item
    +	 * @param {bool} isHighlighted
    +	 * @return {*}
    +	 */
    +	renderItem(item, isHighlighted){
    +		return <MagicItem item={item} isHighlighted={isHighlighted} innerKey={item.innerKey} key={item.innerKey} />;
    +	}
    +
    +	/**
    +	 * Create the list of items
    +	 *
    +	 * @return {Array}
    +	 */
    +	items() {
    +		const optionsOrEmpty =(options) => {
    +			return Array.isArray(options) && options.length ? options : [];
    +		};
    +
    +		let items = [];
    +
    +		if( optionsOrEmpty(this.props.options).length){
    +			items = optionsOrEmpty(this.props.options);
    +		}
    +		else if ('system' === this.state.currentListType ) {
    +			items = optionsOrEmpty(this.props.systemTagsList);
    +		} else {
    +			items = optionsOrEmpty(this.props.fieldsList);
    +		}
    +
    +		if (items.length) {
    +			items.forEach((item, itemIndex) => {
    +				items[itemIndex].innerKey = `${item.value}-${itemIndex}`;
    +			});
    +		}else{
    +			items.push({
    +				value: null,
    +				label: null,
    +				innerKey:this.props.id
    +			});
    +		}
    +
    +		return items;
    +
    +	}
    +
    +	/**
    +	 * Options for type chooser
    +	 *
    +	 * @return {*[]}
    +	 */
    +	listTypeOptions(){
    +		return [
    +			{
    +				value: 'fields',
    +				label: '%',
    +				ariaLabel: 'Select from field values'
    +			},
    +			{
    +				value: 'system',
    +				label: '{}',
    +				ariaLabel: 'Select from system values'
    +			},
    +		];
    +	}
    +
    +
    +
    +	/**
    +	 * Render MagicFieldGroup component
    +	 * @return {*}
    +	 */
    +	render() {
    +		return (
    +			<div
    +				className={classNames(
    +					MagicFieldGroup.classNames.fieldWrapper,
    +					RenderGroup.classNames.fieldWrapper,
    +					this.props.className
    +				)
    +				}
    +			>
    +				<FieldGroup.Label
    +					id={this.props.id}
    +					label={this.props.label}
    +				/>
    +				{this.props.message.message &&
    +					<Message
    +						message={this.props.message}
    +					/>
    +				}
    +				{this.state.isOpen &&
    +					<ButtonGroup
    +						onChange={this.onChangeListType}
    +						options={this.listTypeOptions()}
    +						value={this.state.currentListType}
    +					/>
    +				}
    +
    +				<MagicSelect
    +					id={this.props.id}
    +					options={this.items()}
    +					onValueChange={this.props.onValueChange}
    +					value={this.props.value}
    +					isRequired={this.props.isRequired}
    +					isOpen={this.state.isOpen}
    +					onBlur={this.onInputBlur}
    +					onFocus={this.onInputFocus}
    +					className={this.props.fieldClassName}
    +				/>
    +			</div>
    +		);
    +	}
    +}
    +
    +
    +/**
    + * Prop definitions for MagicFieldGroup component
    + */
    +MagicFieldGroup.propTypes = magicGroupPropTypes;
    +
    +/**
    + * Default property values for MagicFieldGroup component
    + *
    + * @type {{}}
    + */
    +MagicFieldGroup.defaultProps = {
    +	defaultList: 'fields',
    +	isOpen: false,
    +	message: {
    +		error: false,
    +		message: ''
    +	},
    +	type: 'magic'
    +};
    +
    +/**
    + * The names of classes used for HTML elements in MagicFieldGroup component
    + * @type {{fieldWrapper: string, input: string, option: string}}
    + */
    +MagicFieldGroup.classNames = {
    +	fieldWrapper: 'caldera-magic-select-group',
    +	input: 'caldera-magic-input',
    +	option: 'caldera-magic-option'
    +};
    + +
    + + + + + + + + + + + + diff --git a/docs/file/src/components/fields/magic-select/MagicItem.js.html b/docs/file/src/components/fields/magic-select/MagicItem.js.html new file mode 100644 index 0000000..18f7709 --- /dev/null +++ b/docs/file/src/components/fields/magic-select/MagicItem.js.html @@ -0,0 +1,185 @@ + + + + + + src/components/fields/magic-select/MagicItem.js | Caldera Components library + + + + + + + +
    + + + Reference + Source + + +
    + + + +

    src/components/fields/magic-select/MagicItem.js

    +
    import React from 'react';
    +import {
    +	optionShape
    +} from '../propTypes';
    +import classNames from 'classnames';
    +import PropTypes from 'prop-types';
    +
    +/**
    + * Create magic item for option of magic selects
    + *
    + * This can not be a functional component
    + * https://github.com/reactjs/react-autocomplete/pull/293#issuecomment-371617758
    + *
    + *
    + * @param {Object} props
    + * @return {*}
    + * @constructor
    + */
    +export class MagicItem extends React.PureComponent {
    +
    +	/**
    +	 * Render magic item components
    +	 */
    +	render() {
    +		return React.createElement(
    +			this.props.elementType,
    +			{
    +				style: {background: this.props.isHighlighted ? this.props.highlightColor : this.props.notHighlighterColor},
    +				className: classNames(this.props.className, 'magic-input-option'),
    +				onClick: this.props.onClick
    +			},
    +			[
    +				React.createElement(
    +					this.props.innerElementType,
    +					{
    +						key: `left--${this.props.innerKey}`,
    +						className: classNames('magic-item-value', 'magic-item-left')
    +					},
    +					this.props.item.value
    +				),
    +				React.createElement(
    +					this.props.innerElementType,
    +					{
    +						key: `right--${this.props.innerKey}`,
    +						className: classNames('magic-item-label', 'magic-item-right')
    +					},
    +					this.props.item.label
    +				)
    +			]
    +		);
    +	}
    +}
    +
    +/**
    + * Prop definition for allowed element types
    + * @type {shim}
    + */
    +const elementTypesProp = PropTypes.oneOf(['div', 'span']);
    +/**
    + * Prop definitions for MagicItem component
    + *
    + * @type {{item: shim, isHighlighted: shim, className: shim, highlightColor: shim, notHighlighterColor: shim}}
    + */
    +MagicItem.propTypes = {
    +	elementType: elementTypesProp,
    +	innerElementType: elementTypesProp,
    +	item: PropTypes.shape(optionShape),
    +	isHighlighted: PropTypes.bool,
    +	className: PropTypes.string,
    +	highlightColor: PropTypes.string,
    +	notHighlighterColor: PropTypes.string,
    +	innerKey: PropTypes.string.isRequired,
    +	onClick: PropTypes.func
    +};
    +
    +/**
    + * Default props for the MagicItem component
    + *
    + * @type {{isHighlighted: boolean, highlightColor: string, notHighlightedColor: string}}
    + */
    +MagicItem.defaultProps = {
    +	elementType: 'div',
    +	innerElementType: 'span',
    +	isHighlighted: false,
    +	highlightColor: 'lightgray',
    +	notHighlightedColor: 'white',
    +};
    + +
    + + + + + + + + + + + + diff --git a/docs/file/src/components/fields/magic-select/MagicSelect.js.html b/docs/file/src/components/fields/magic-select/MagicSelect.js.html new file mode 100644 index 0000000..07ea572 --- /dev/null +++ b/docs/file/src/components/fields/magic-select/MagicSelect.js.html @@ -0,0 +1,241 @@ + + + + + + src/components/fields/magic-select/MagicSelect.js | Caldera Components library + + + + + + + +
    + + + Reference + Source + + +
    + + + +

    src/components/fields/magic-select/MagicSelect.js

    +
    import React from 'react';
    +import {
    +	onValueChangePropType,
    +	optionsShapeProp,
    +	valuePropType
    +} from '../propTypes';
    +import Autocomplete from 'react-autocomplete';
    +import PropTypes from 'prop-types';
    +import {MagicItem} from './MagicItem';
    +import {MagicFieldGroup} from './MagicFieldGroup';
    +import classNames from 'classnames';
    +
    +
    +/**
    + * Encapsulates a complete Magic Select field
    + */
    +export class MagicSelect extends React.PureComponent {
    +
    +	/**
    +	 * Create a MagicSelect component
    +	 *
    +	 * @param {Object} props
    +	 */
    +	constructor(props) {
    +		super(props);
    +		this.onChange = this.onChange.bind(this);
    +		this.onChange = this.onChange.bind(this);
    +		this.onSelect = this.onSelect.bind(this);
    +		this.onInputFocus = this.onInputFocus.bind(this);
    +		this.renderItem = this.renderItem.bind(this);
    +		this.onInputBlur = this.onInputBlur.bind(this);
    +	}
    +
    +	/**
    +	 * Handle direct change events
    +	 *
    +	 * @param {Event} event
    +	 */
    +	onChange(event) {
    +		this.props.onValueChange(event.target.value);
    +	}
    +
    +	/**
    +	 * Handle when the field gets focus
    +	 */
    +	onInputFocus() {
    +		if( 'function' === typeof this.props.onFocus ){
    +			this.props.onFocus();
    +		}
    +	}
    +
    +	/**
    +	 * Handle when the field is blurred
    +	 */
    +	onInputBlur() {
    +		if( 'function' === typeof this.props.onBlur ){
    +			this.props.onBlur();
    +		}
    +	}
    +
    +
    +	/**
    +	 * Handle when the option is chosen
    +	 * @param {String|number} value
    +	 */
    +	onSelect(value) {
    +		this.props.onValueChange(value);
    +	}
    +
    +
    +	/**
    +	 * Render option
    +	 *
    +	 * @param {object} item
    +	 * @param {bool} isHighlighted
    +	 * @return {*}
    +	 */
    +	renderItem(item, isHighlighted){
    +		return <MagicItem item={item} isHighlighted={isHighlighted} innerKey={item.innerKey} key={item.innerKey} onClick={this.onSelect} />;
    +	}
    +
    +
    +	/**
    +	 * Render MagicSelect component
    +	 * @return {*}
    +	 */
    +	render() {
    +		return (
    +			<Autocomplete
    +				getItemValue={(item) => item.value}
    +				items={this.props.options}
    +				inputProps={{
    +					id: this.props.id,
    +					value: this.props.value,
    +					className:classNames(
    +						MagicFieldGroup.classNames.input,
    +						`${MagicFieldGroup.classNames.input}-${this.props.id}`,
    +						this.props.className
    +					),
    +					onFocus: this.onInputFocus,
    +					onBlur:this.onInputBlur,
    +					onClick:this.onChange
    +				}}
    +				renderItem={this.renderItem}
    +				value={this.props.value}
    +				onChange={this.onChange}
    +				open={this.props.isOpen}
    +				selectOnBlur={true}
    +				onSelect={this.onSelect}
    +			/>
    +
    +		);
    +	}
    +}
    +
    +
    +/**
    + * Prop definitions for MagicSelect component
    + */
    +MagicSelect.propTypes = {
    +	id: PropTypes.string.isRequired,
    +	options: optionsShapeProp,
    +	isRequired: PropTypes.bool,
    +	help: PropTypes.string,
    +	value: valuePropType,
    +	onValueChange: onValueChangePropType,
    +	disabled: PropTypes.bool,
    +	isOpen: PropTypes.bool,
    +	onBlur: PropTypes.func,
    +	onFocus: PropTypes.func,
    +	className: PropTypes.string
    +};
    +
    +/**
    + * Default property values for MagicSelect component
    + *
    + * @type {{}}
    + */
    +MagicSelect.defaultProps = {
    +	defaultList: 'fields',
    +	isOpen: false,
    +	options:[]
    +};
    + +
    + + + + + + + + + + + + diff --git a/docs/file/src/components/fields/messages/Message.js.html b/docs/file/src/components/fields/messages/Message.js.html index a230d1c..87b601b 100644 --- a/docs/file/src/components/fields/messages/Message.js.html +++ b/docs/file/src/components/fields/messages/Message.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/messages/messageObjectFactory.js.html b/docs/file/src/components/fields/messages/messageObjectFactory.js.html index 32ffb9b..b528741 100644 --- a/docs/file/src/components/fields/messages/messageObjectFactory.js.html +++ b/docs/file/src/components/fields/messages/messageObjectFactory.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/messages/messagePropTypes.js.html b/docs/file/src/components/fields/messages/messagePropTypes.js.html index 86aef0d..4d8a4a0 100644 --- a/docs/file/src/components/fields/messages/messagePropTypes.js.html +++ b/docs/file/src/components/fields/messages/messagePropTypes.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/propTypes.js.html b/docs/file/src/components/fields/propTypes.js.html index 711cdcc..90a2f59 100644 --- a/docs/file/src/components/fields/propTypes.js.html +++ b/docs/file/src/components/fields/propTypes.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -99,7 +106,7 @@ * Proptypes for Input component * @type {shim} */ -export const inputTypeProp = PropTypes.string; +export const inputTypeProp = PropTypes.string; /** * PropTypes for field groups @@ -112,11 +119,11 @@ isRequired: PropTypes.bool, help: PropTypes.string, label: PropTypes.string.isRequired, - type: PropTypes.oneOf(['input','select', 'fieldset']), + type: PropTypes.oneOf(['input', 'select', 'fieldset', 'magic']), value: valuePropType, onValueChange: onValueChangePropType, options: PropTypes.array, - inputType:inputTypeProp, + inputType: inputTypeProp, disabled: PropTypes.bool, message: messagePropShape, onBlur: PropTypes.func, @@ -141,7 +148,37 @@ }; export const fieldPropTypes = fieldInnerPropTypes; -
    + +/** + * The shape of one option for a select field + * + * @type {{label: shim, value: shim}} + */ +export const optionShape = { + label: PropTypes.string, + value: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]) +}; + +/** + * Shape of options prop for select fields + * + * @type {shim} + */ +export const optionsShapeProp = PropTypes.arrayOf( + PropTypes.shape(optionShape) +); + +export const magicGroupPropTypes = { + ...fieldGroupPropTypes, + fieldsList: optionsShapeProp, + systemTagsList: optionsShapeProp, + defaultList: PropTypes.string, + isOpen: PropTypes.bool, + type: PropTypes.string +};
    diff --git a/docs/file/src/components/fields/select/SelectField.js.html b/docs/file/src/components/fields/select/SelectField.js.html index de364e0..84f9872 100644 --- a/docs/file/src/components/fields/select/SelectField.js.html +++ b/docs/file/src/components/fields/select/SelectField.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -77,6 +84,7 @@ import {fieldPropTypes} from '../propTypes'; import classNames from 'classnames'; import {RenderGroup} from '../../RenderGroup'; +import {optionsShapeProp} from '../propTypes'; /** * Creates a select field @@ -144,6 +152,8 @@ */ SelectField.propTypes = { ...fieldPropTypes, + options: optionsShapeProp + }; /** diff --git a/docs/file/src/components/fields/select/SelectFieldFancy.js.html b/docs/file/src/components/fields/select/SelectFieldFancy.js.html index b7d6a7c..e664c36 100644 --- a/docs/file/src/components/fields/select/SelectFieldFancy.js.html +++ b/docs/file/src/components/fields/select/SelectFieldFancy.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/fields/util.js.html b/docs/file/src/components/fields/util.js.html index fa4d35b..db4c466 100644 --- a/docs/file/src/components/fields/util.js.html +++ b/docs/file/src/components/fields/util.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/index.js.html b/docs/file/src/components/index.js.html index 9051e22..3403bd2 100644 --- a/docs/file/src/components/index.js.html +++ b/docs/file/src/components/index.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/addAutomaticValidators.js.html b/docs/file/src/components/validation/addAutomaticValidators.js.html index ac7ad45..7fb33ac 100644 --- a/docs/file/src/components/validation/addAutomaticValidators.js.html +++ b/docs/file/src/components/validation/addAutomaticValidators.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/checkValidatorsForConfigField.js.html b/docs/file/src/components/validation/checkValidatorsForConfigField.js.html index 7e4cd1a..0ef95e1 100644 --- a/docs/file/src/components/validation/checkValidatorsForConfigField.js.html +++ b/docs/file/src/components/validation/checkValidatorsForConfigField.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/checkValidatorsForConfigFields.js.html b/docs/file/src/components/validation/checkValidatorsForConfigFields.js.html index b4ce82c..d1d339e 100644 --- a/docs/file/src/components/validation/checkValidatorsForConfigFields.js.html +++ b/docs/file/src/components/validation/checkValidatorsForConfigFields.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/getValidatorsFromConfigField.js.html b/docs/file/src/components/validation/getValidatorsFromConfigField.js.html index 5faf966..6ac9d2e 100644 --- a/docs/file/src/components/validation/getValidatorsFromConfigField.js.html +++ b/docs/file/src/components/validation/getValidatorsFromConfigField.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/index.js.html b/docs/file/src/components/validation/index.js.html index 8da4c3f..b9f0028 100644 --- a/docs/file/src/components/validation/index.js.html +++ b/docs/file/src/components/validation/index.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/isEmpty.js.html b/docs/file/src/components/validation/isEmpty.js.html index ad83a2b..4befd6a 100644 --- a/docs/file/src/components/validation/isEmpty.js.html +++ b/docs/file/src/components/validation/isEmpty.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/isValid.js.html b/docs/file/src/components/validation/isValid.js.html index 334483f..b8d9819 100644 --- a/docs/file/src/components/validation/isValid.js.html +++ b/docs/file/src/components/validation/isValid.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/isValidOrEmpty.js.html b/docs/file/src/components/validation/isValidOrEmpty.js.html index 6c13b24..7d0d6ec 100644 --- a/docs/file/src/components/validation/isValidOrEmpty.js.html +++ b/docs/file/src/components/validation/isValidOrEmpty.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/messageStrings.js.html b/docs/file/src/components/validation/messageStrings.js.html index 9c7209c..4f6e0af 100644 --- a/docs/file/src/components/validation/messageStrings.js.html +++ b/docs/file/src/components/validation/messageStrings.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/strings.js.html b/docs/file/src/components/validation/strings.js.html index fa4eb15..1746f13 100644 --- a/docs/file/src/components/validation/strings.js.html +++ b/docs/file/src/components/validation/strings.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/components/validation/util.js.html b/docs/file/src/components/validation/util.js.html index 0310b3e..7fe6f38 100644 --- a/docs/file/src/components/validation/util.js.html +++ b/docs/file/src/components/validation/util.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/index.js.html b/docs/file/src/index.js.html index 2c99636..e7e0a60 100644 --- a/docs/file/src/index.js.html +++ b/docs/file/src/index.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/file/src/registerServiceWorker.js.html b/docs/file/src/registerServiceWorker.js.html index 92067fb..72baabd 100644 --- a/docs/file/src/registerServiceWorker.js.html +++ b/docs/file/src/registerServiceWorker.js.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • diff --git a/docs/function/index.html b/docs/function/index.html index 1aff0dc..af3e3e7 100644 --- a/docs/function/index.html +++ b/docs/function/index.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -83,6 +90,35 @@ + + + +
    +

    + + + + ButtonGroup(props: Object): * +

    +
    +
    + + +

    Creates a button group field

    +
    +
    + + + + + + + + + public + + + @@ -920,6 +956,78 @@

    Static Public

    +
    +

    + public + + + + + + ButtonGroup(props: Object): * + + + + source + +

    + + + + +

    Creates a button group field

    +
    + + + +
    +

    Params:

    + + + + + + + + + + + + + +
    NameTypeAttributeDescription
    propsObject
    +
    +
    + +
    +

    Return:

    + + + + + + + +
    *
    +
    +
    +
    + + + + + + + + + + + + + + + +

    public @@ -932,11 +1040,11 @@

    - source + source

    - +

    Represents one configField -- wrapper, label and input.

    @@ -1221,11 +1329,11 @@

    - source + source

    - +

    Creates a select field

    diff --git a/docs/identifiers.html b/docs/identifiers.html index cedf283..4b8337f 100644 --- a/docs/identifiers.html +++ b/docs/identifiers.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -637,6 +644,34 @@

    components/fields

    + + + +
    +

    + V + + + magicGroupPropTypes: {...fieldGroupPropTypes: Object, "fieldsList": *, "systemTagsList": *, "defaultList": *, "isOpen": *, "type": *} +

    +
    +
    + + + +
    + + + + + + + + + public + + + @@ -666,6 +701,64 @@

    components/fields

    + + + +
    +

    + V + + + optionShape: {label: shim, value: shim} +

    +
    +
    + + +

    The shape of one option for a select field

    +
    +
    + + + + + + + + + public + + + + + + +
    +

    + V + + + optionsShapeProp: shim +

    +
    +
    + + +

    Shape of options prop for select fields

    +
    +
    + + + + + + + + + public + + + @@ -687,6 +780,45 @@

    components/fields

    + + + + +
    +
    +
    +

    components/fields/button-group

    +
    + + + + + + + @@ -862,6 +994,103 @@

    components/fields/input

    + + +
    summary
    + public + + + + + +
    +

    + F + + + ButtonGroup(props: Object): * +

    +
    +
    + + +

    Creates a button group field

    +
    +
    +
    + +
    +
    +
    +
    +
    +

    components/fields/magic-select

    +
    + + + + + + + + + + + + + + + + + @@ -1310,9 +1539,11 @@

    components/validation

    diff --git a/docs/index.html b/docs/index.html index af7856b..c4d6ff8 100644 --- a/docs/index.html +++ b/docs/index.html @@ -55,15 +55,22 @@
  • Included Component
  • RenderGroup
  • Example Of RenderGroup Component Usage
  • +
  • A Magic Aut-Complete Field Selector In A RednerGroup
  • Add onFocus Event For All Fields Of Render Group
  • Add onBlur Event For All Fields Of Render Group
  • Field Groups
  • -
  • Text field that is required
  • -
  • Text field that is not required
  • -
  • Text field with help text
  • -
  • Number Field
  • -
  • Select Fields
  • +
  • Text Field Groups
  • +
  • Text field that is required
  • +
  • Text field that is not required
  • +
  • Text field with help text
  • +
  • Number Field Group
  • +
  • Magic Select Groups
  • Fieldsets
  • +
  • Button Group
  • +
  • Examples
  • +
  • Button Group With Two Options
  • +
  • Button Group With Icon
  • +
  • Explicitly set aria-label Attribute
  • Message component
  • An error message
  • A non-error message
  • @@ -383,6 +390,38 @@

    Structure of class attributes

    The configFields={configFields} className={'cf-something-config'} /> +

    A Magic Aut-Complete Field Selector In A RednerGroup

    const magicField = {
    +    'id': 'cf-magic-example',
    +    'type': 'magic',
    +    'label': 'Magic ID',
    +    'description': 'Select a value from list of magic tags or type a value',
    +    fieldsList: [
    +        {
    +            label: '0',
    +            value: 0
    +        },
    +        {
    +            label: '1',
    +            value: 1
    +        },
    +        {
    +            label: '3',
    +            value: 3
    +        }
    +    ],
    +    systemTagsList: [
    +        {
    +            label: '3',
    +            value: 3
    +        }
    +    ],
    +    isOpen: true,
    +    onValueChange: () => {
    +    }
    +};
    +
    +<RenderGroup configFields={[magicField]}/>
    +
     

    Add onFocus Event For All Fields Of Render Group

    You can add an onFocus event that fires when ever any field is focused. The callback function gets the config field's ID as its only parameter.

    <RenderGroup
         configFields={[
             //add your fields
    @@ -401,7 +440,7 @@ 

    Structure of class attributes

    The

    Field Groups

    If you have to use a component, please use FieldGroup not its inner components.

    Text field that is required

    <FieldGroup
    +

    Text Field Groups

    If the prop type is input, the type of input is controlled by the inputType props, which by default is text. Therefore, by default input field groups have inputs with the HTML5 input type attribute of "text". Also, inputType could be "number" or "data", etc.

    Text field that is required

    <FieldGroup
         id={'control-22'}
         label={'Required Text input'}
         type={'input'}
    @@ -412,7 +451,7 @@ 

    Structure of class attributes

    The }} /> -

    Text field that is not required

    <FieldGroup
    +

    Text field that is not required

    <FieldGroup
         id={'control-23'}
         label={'Non Required Text input'}
         type={'input'}
    @@ -422,7 +461,7 @@ 

    Structure of class attributes

    The values.two=newValue; }} /> -

    Text field with help text

      +

    Text field with help text

    • Adding help text automatically ads aria-describedby
    <FieldGroup
         id={'control-23'}
    @@ -435,7 +474,7 @@ 

    Structure of class attributes

    The values.three=newValue; }} /> -

    Number Field

    <FieldGroup
    +

    Number Field Group

    <FieldGroup
         id={'control-24'}
         label={'Non Required Numeric input'}
         type={'input'}
    @@ -446,10 +485,69 @@ 

    Structure of class attributes

    The values.two=newValue; }} /> + +### Select Field Groups + +Select field groups happen when you pass "select" to the `type` prop. + +Select fields take an array of options in the prop option. Options in that collection must conform the shape [defined here](https://calderalabs.org/caldera-components/docs/file/src/components/fields/propTypes.js.html#lineNumber75) + -

    Select Fields

    import {SelectFieldFancy} from '@caldera-labs/components/src/components/fields/select/SelectFieldFancyFancy.js'
    +

    let selectFieldValue = '';

    <FieldGroup + type={'select'} + label={'Basic select field'} + value={selectFieldValue} + id={'id-of-the-select-field-itself'} + onValueChange={(newValue) => { + selectFieldValue = newValue; + }} + options={[ + { + value: 1, + label: 'One' + }, + { + value: 2, + label: 'Two' + } + ]} +/>

    Magic Select Groups

    Magic select groups use MagicSelect fields, which wrap reactjs/react-autocomple to create a UI for Caldera Forms magic tags.

    These fields groups show options from two lists, one is passed in the prop fieldsList and represents the fields of the form, and the other is in systemTagsList, which represents the system values such as the current user info.

    The property isOpen controls if the auto-complete list is open.

    let magicFieldValue ='';
    +
    +<MagicFieldGroup
    +        id={'magic-5'}
    +        fieldClassName={'magic'}
    +        label={'Magic Group'}
    +        onValueChange={(newValue) => {
    +            magicFieldValue = newValue;
    +        } }
    +        fieldsList={[
    +            {
    +                label: 'Field One',
    +                value: '%fldOne%'
    +            },
    +            {
    +                label: 'Field Two',
    +                value: '%fldTwo%'
    +            },
    +            {
    +                label: 'Field Three',
    +                value: '%fldThree%'
    +            },
    +        ]}
    +        systemTagsList={[
    +            {
    +                label: 'User First Name',
    +                value: '{user:first_name}'
    +            }
    +        ]}
    +        isOpen={true}
    +        value={magicFieldValue}
    +    />
    +
    ## Select Fields
    +* [Reference](https://calderalabs.org/caldera-components/function/index.html#static-function-SelectField)
    +
    +```jsx 
    +import {SelectFieldFancy} from '@caldera-labs/components/src/components/fields/select/SelectFieldFancyFancy.js'
     
     <SelectFieldFancy
         id={'number-of-things'} //ID attribute for input
    @@ -493,6 +591,60 @@ 

    Structure of class attributes

    The } ]} /> +

    Button Group

    Button groups are select fields. One button can be selected at once.

    This is a field, not a group (like FieldGroup or MagicFieldGroup) so it does not handle its own label.

    Button groups fields take an array of options in the prop option. Options in that collection must conform the shape defined here

    Examples

    Button Group With Two Options

    <ButtonGroup
    +    onChange={(selectedValue) => {
    +        console.log(selectedValue);
    +    }}
    +    options={[
    +        {
    +            value: 1,
    +            label: 'Option One',
    +        },
    +        {
    +            value: 2,
    +            label: 'Option Two',
    +        }
    +    ]}
    +    value={1}
    +/>
    +

    Button Group With Icon

    If options have icon, the rendered markup for the button will be like this:

    <button ...><span class="fa-envelope"></span></button>
    +
    +

    That's the markup you need if font awesome is loaded on the page. In the future this component should supply font awesome or dashicons or emoji icons. For now, it does not.

    <ButtonGroup
    +    onChange={(selectedValue) => {
    +        console.log(selectedValue);
    +    }}
    +    options={[
    +        {
    +            value: 1,
    +            label: 'Option One',
    +            icon: 'fa-envelop'
    +        },
    +        {
    +            value: 2,
    +            label: 'Option Two',
    +            icon: 'fa-twitter'
    +
    +        }
    +    ]}
    +    value={1}
    +/>
    +

    Explicitly set aria-label Attribute

    By default, the visual representation fo the option is option.label. That makes sense, if you're representing the option with words. Allowing the component to use option.label for the aria-label attribute, which is its default value, I think makes sense.

    But, if the visual representation of the option is an emoji or image, then aria-label can not be an image, it has to be text that gives meaning to the image for users who can not see the image.

    <ButtonGroup
    +    onChange={(selectedValue) => {
    +        console.log(selectedValue);
    +    }}
    +    options={[
    +        {
    +            value: 'fields',
    +            label: '%',
    +            ariaLabel: 'Select from field values'
    +        },
    +        {
    +            value: 'system',
    +            label: '{}',
    +            ariaLabel: 'Select from system values'
    +        },
    +    ]}
    +/>
     

    Message component

    The Message component is used to display validation messages in a FieldGroup component. Messages have a shape defined in the messagePropShape object. This component, by design, returns nothing if props.message.message is not supplied, or is an empty string.

    An error message

    <Message
         message={{
             message:'Something bad has happened.',
    diff --git a/docs/index.json b/docs/index.json
    index c0115e9..d07c5e7 100644
    --- a/docs/index.json
    +++ b/docs/index.json
    @@ -567,7 +567,7 @@
         "__docId__": 48,
         "kind": "file",
         "name": "src/App.js",
    -    "content": "import React, { Component } from 'react';\nimport logo from './logo.svg';\nimport './App.css';\nimport {FieldGroup} from \"./components/fields/FieldGroup\";\nimport {fieldSetFactory} from \"./components/fields/factories/fieldSetFactory\";\nimport {RenderGroup} from \"./components/RenderGroup\";\n\nlet textFieldValue = 'Roy,Mike';\nconst textFieldConfig = {\n\t'id': 'cf-something-tags',\n\t'label': 'Tags',\n\t'desc': 'Comma separated list of tags.',\n\t'type': 'text',\n\t'description': false,\n\tvalue: textFieldValue,\n\tonValueChange: function(newValue){\n\t\ttextFieldValue = newValue\n\t},\n\n\n};\n\nlet hiddenFieldValue = '42';\nconst hiddenFieldConfig = {\n\t'id': 'cf-something-sequence-id',\n\t'type': 'hidden',\n\t'label': 'Sequence ID',\n\t'description': false,\n\tvalue: hiddenFieldValue,\n\tonValueChange: function(newValue){\n\t\thiddenFieldValue = newValue\n\t},\n};\n\nlet selectFieldValue = 'html';\nconst selectFieldConfig = {\n\t'id': 'cf-something-select-id',\n\t'type': 'dropdown',\n\t'label': 'Content type',\n\t'description': 'Choose content type, default is HTML',\n\toptions: [\n\t\t{\n\t\t\tlabel: 'HTML',\n\t\t\tvalue: 'html'\n\t\t},\n\t\t{\n\t\t\tlabel: 'Plain Text',\n\t\t\tvalue: 'plain'\n\t\t}\n\t],\n\tvalue: selectFieldValue,\n\tonValueChange: function(newValue){\n\t\tselectFieldValue = newValue\n\t}\n};\n\nlet fieldSetFieldValue = ['1'];\nconst fieldSetField = {\n\tid: 'fieldset-3',\n\tlabel: 'How many?',\n\ttype: 'fieldset',\n\toptions: [\n\t\t{\n\t\t\tvalue: '1',\n\t\t\tlabel: 'One'\n\t\t},\n\t\t{\n\t\t\tvalue: '2',\n\t\t\tlabel: 'Two'\n\t\t}\n\n\t],\n\tvalue:[],\n\tonValueChange:(newValue) => {\n\t\tfieldSetFieldValue=newValue;\n\t}\n};\n\nconst configFields = [\n\ttextFieldConfig,\n\thiddenFieldConfig,\n\tselectFieldConfig,\n\tfieldSetField\n];\nconst configFieldEls = fieldSetFactory(configFields);\n\n\n\nlet values = {\n\tone: '',\n\ttwo: '',\n\tthree: ''\n};\n\nclass App extends Component {\n\n\trender() {\n\t\treturn (\n\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t\"logo\"\n\t\t\t\t\t

    Welcome to React

    \n\t\t\t\t
    \n\n\n\t\t\t\t
    \n\t\t\t\t\t

    Created With RenderGroup Component

    \n\t\t\t\t\t {console.log(fI)}}\n\t\t\t\t\t/>\n\t\t\t\t
    \n\n\t\t\t\t
    \n\t\t\t\t\t

    Created With Factory

    \n\t\t\t\t\t{Array.from(configFieldEls).map((field,i) => {\n\t\t\t\t\t\treturn React.createElement(\n\t\t\t\t\t\t\tReact.Fragment, {\n\t\t\t\t\t\t\t\tkey: i,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tfield\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t
    \n\n\t\t\t\t
    \n\t\t\t\t\t

    Inputs

    \n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.one=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.two=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.three=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.two=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.two=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tmessage={{\n\t\t\t\t\t\t\tmessage:'Failures happened',\n\t\t\t\t\t\t\terror: true\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.two=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tmessage={{\n\t\t\t\t\t\t\tmessage:'Failures did not happened',\n\t\t\t\t\t\t\terror: false\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t

    Selects

    \n\t\t\t\t\t {\n\t\t\t\t\t\t\tselectFieldValue = newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\toptions={[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\tlabel: 'One'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\tlabel: 'Two'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]}\n\t\t\t\t\t/>\n\n\t\t\t\t
    \n\n\t\t\t\t
    \n\t\t\t\t\t

    fieldsets

    \n\t\t\t\t\t {\n\t\t\t\t\t\t\tfieldSetFieldValue = newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\toptions={[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvalue: '1',\n\t\t\t\t\t\t\t\tlabel: 'One'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvalue: '2',\n\t\t\t\t\t\t\t\tlabel: 'Two'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]}\n\t\t\t\t\t/>\n\t\t\t\t
    \n\n\t\t\t
    \n\t\t);\n\t}\n}\n\nexport default App;\n", + "content": "import React, { Component } from 'react';\nimport logo from './logo.svg';\nimport './App.css';\nimport {FieldGroup} from \"./components/fields/FieldGroup\";\nimport {fieldSetFactory} from \"./components/fields/factories/fieldSetFactory\";\nimport {RenderGroup} from \"./components/RenderGroup\";\nimport {MagicFieldGroup} from \"./components/fields/magic-select/MagicFieldGroup\";\n\nlet textFieldValue = 'Roy,Mike';\nconst textFieldConfig = {\n\t'id': 'cf-something-tags',\n\t'label': 'Tags',\n\t'desc': 'Comma separated list of tags.',\n\t'type': 'text',\n\t'description': false,\n\tvalue: textFieldValue,\n\tonValueChange: function(newValue){\n\t\ttextFieldValue = newValue\n\t},\n\n\n};\n\nconst numberFieldConfig = {\n\t'id': 'cf--something-some-number',\n\t'label': 'The number of something',\n\t'desc': 'How many somethings?',\n\t'type': 'text',\n\t'inputType': 'number',\n\tattributes: {\n\t\tmin: -1,\n\t\tmax: 22,\n\t\tstep: 0.1,\n\t},\n\tvalue: 42,\n\tonValueChange: (newNumberValue) =>{\n\t\tconsole.log(newNumberValue);\n\t},\n\n};\n\nlet hiddenFieldValue = '42';\nconst hiddenFieldConfig = {\n\t'id': 'cf-something-sequence-id',\n\t'type': 'hidden',\n\t'label': 'Sequence ID',\n\t'description': false,\n\tvalue: hiddenFieldValue,\n\tonValueChange: function(newValue){\n\t\thiddenFieldValue = newValue\n\t},\n};\n\nlet selectFieldValue = 'html';\nconst selectFieldConfig = {\n\t'id': 'cf-something-select-id',\n\t'type': 'dropdown',\n\t'label': 'Content type',\n\t'description': 'Choose content type, default is HTML',\n\toptions: [\n\t\t{\n\t\t\tlabel: 'HTML',\n\t\t\tvalue: 'html'\n\t\t},\n\t\t{\n\t\t\tlabel: 'Plain Text',\n\t\t\tvalue: 'plain'\n\t\t}\n\t],\n\tvalue: selectFieldValue,\n\tonValueChange: function(newValue){\n\t\tselectFieldValue = newValue\n\t}\n};\n\nlet fieldSetFieldValue = ['1'];\nconst fieldSetField = {\n\tid: 'fieldset-3',\n\tlabel: 'How many?',\n\ttype: 'fieldset',\n\toptions: [\n\t\t{\n\t\t\tvalue: '1',\n\t\t\tlabel: 'One'\n\t\t},\n\t\t{\n\t\t\tvalue: '2',\n\t\t\tlabel: 'Two'\n\t\t}\n\n\t],\n\tvalue:[],\n\tonValueChange:(newValue) => {\n\t\tfieldSetFieldValue=newValue;\n\t}\n};\n\nconst configFields = [\n\ttextFieldConfig,\n\thiddenFieldConfig,\n\tselectFieldConfig,\n\tfieldSetField,\n\tnumberFieldConfig\n];\nconst configFieldEls = fieldSetFactory(configFields);\n\n\n\nlet values = {\n\tone: '',\n\ttwo: '',\n\tthree: ''\n};\n\nlet magicFieldValue = '';\n\nclass App extends Component {\n\n\trender() {\n\t\treturn (\n\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t\"logo\"\n\t\t\t\t\t

    Welcome to React

    \n\t\t\t\t
    \n\n\n\t\t\t\t
    \n\t\t\t\t\t

    Created With RenderGroup Component

    \n\t\t\t\t\t {console.log(fI)}}\n\t\t\t\t\t/>\n\t\t\t\t
    \n\n\t\t\t\t
    \n\t\t\t\t\t

    Created With Factory

    \n\t\t\t\t\t{Array.from(configFieldEls).map((field,i) => {\n\t\t\t\t\t\treturn React.createElement(\n\t\t\t\t\t\t\tReact.Fragment, {\n\t\t\t\t\t\t\t\tkey: i,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tfield\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t
    \n\n\t\t\t\t
    \n\t\t\t\t\t

    Magic Select

    \n\t\t\t\t\t {\n\t\t\t\t\t\t\tmagicFieldValue = newValue;\n\t\t\t\t\t\t} }\n\t\t\t\t\t\tfieldsList={[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: 'Field One',\n\t\t\t\t\t\t\t\tvalue: '%fldOne%'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: 'Field Two',\n\t\t\t\t\t\t\t\tvalue: '%fldTwo%'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: 'Field Three',\n\t\t\t\t\t\t\t\tvalue: '%fldThree%'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]}\n\t\t\t\t\t\tsystemTagsList={[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlabel: 'User First Name',\n\t\t\t\t\t\t\t\tvalue: '{user:first_name}'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]}\n\t\t\t\t\t\tisOpen={true}\n\t\t\t\t\t\tvalue={magicFieldValue}\n\t\t\t\t\t/>\n\t\t\t\t
    \n\n\t\t\t\t
    \n\t\t\t\t\t

    Inputs

    \n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.one=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.two=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.three=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.two=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.two=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tmessage={{\n\t\t\t\t\t\t\tmessage:'Failures happened',\n\t\t\t\t\t\t\terror: true\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tdisabled={true}\n\t\t\t\t\t/>\n\n\t\t\t\t\t {\n\t\t\t\t\t\t\tvalues.two=newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tmessage={{\n\t\t\t\t\t\t\tmessage:'Failures did not happened',\n\t\t\t\t\t\t\terror: false\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t
    \n\t\t\t\t
    \n\t\t\t\t\t

    Selects

    \n\t\t\t\t\t {\n\t\t\t\t\t\t\tselectFieldValue = newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\toptions={[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\tlabel: 'One'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\tlabel: 'Two'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]}\n\t\t\t\t\t/>\n\n\t\t\t\t
    \n\n\t\t\t\t
    \n\t\t\t\t\t

    fieldsets

    \n\t\t\t\t\t {\n\t\t\t\t\t\t\tfieldSetFieldValue = newValue;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\toptions={[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvalue: '1',\n\t\t\t\t\t\t\t\tlabel: 'One'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvalue: '2',\n\t\t\t\t\t\t\t\tlabel: 'Two'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]}\n\t\t\t\t\t/>\n\t\t\t\t
    \n\n\t\t\t
    \n\t\t);\n\t}\n}\n\nexport default App;\n", "static": true, "longname": "/Users/josh/caldera-js/components/src/App.js", "access": "public", @@ -586,7 +586,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 8, + "lineNumber": 9, "undocument": true, "type": { "types": [ @@ -607,7 +607,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 9, + "lineNumber": 10, "undocument": true, "type": { "types": [ @@ -619,6 +619,27 @@ { "__docId__": 51, "kind": "variable", + "name": "numberFieldConfig", + "memberof": "src/App.js", + "static": true, + "longname": "src/App.js~numberFieldConfig", + "access": "public", + "export": false, + "importPath": "@caldera-labs/components/src/App.js", + "importStyle": null, + "description": null, + "lineNumber": 24, + "undocument": true, + "type": { + "types": [ + "{\"id\": string, \"label\": string, \"desc\": string, \"type\": string, \"inputType\": string, \"attributes\": *, \"value\": number, \"onValueChange\": *}" + ] + }, + "ignore": true + }, + { + "__docId__": 52, + "kind": "variable", "name": "hiddenFieldValue", "memberof": "src/App.js", "static": true, @@ -628,7 +649,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 23, + "lineNumber": 42, "undocument": true, "type": { "types": [ @@ -638,7 +659,7 @@ "ignore": true }, { - "__docId__": 52, + "__docId__": 53, "kind": "variable", "name": "hiddenFieldConfig", "memberof": "src/App.js", @@ -649,7 +670,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 24, + "lineNumber": 43, "undocument": true, "type": { "types": [ @@ -659,7 +680,7 @@ "ignore": true }, { - "__docId__": 53, + "__docId__": 54, "kind": "variable", "name": "selectFieldValue", "memberof": "src/App.js", @@ -670,7 +691,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 35, + "lineNumber": 54, "undocument": true, "type": { "types": [ @@ -680,7 +701,7 @@ "ignore": true }, { - "__docId__": 54, + "__docId__": 55, "kind": "variable", "name": "selectFieldConfig", "memberof": "src/App.js", @@ -691,7 +712,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 36, + "lineNumber": 55, "undocument": true, "type": { "types": [ @@ -701,7 +722,7 @@ "ignore": true }, { - "__docId__": 55, + "__docId__": 56, "kind": "variable", "name": "fieldSetFieldValue", "memberof": "src/App.js", @@ -712,7 +733,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 57, + "lineNumber": 76, "undocument": true, "type": { "types": [ @@ -722,7 +743,7 @@ "ignore": true }, { - "__docId__": 56, + "__docId__": 57, "kind": "variable", "name": "fieldSetField", "memberof": "src/App.js", @@ -733,7 +754,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 58, + "lineNumber": 77, "undocument": true, "type": { "types": [ @@ -743,7 +764,7 @@ "ignore": true }, { - "__docId__": 57, + "__docId__": 58, "kind": "variable", "name": "configFields", "memberof": "src/App.js", @@ -754,7 +775,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 79, + "lineNumber": 98, "undocument": true, "type": { "types": [ @@ -764,7 +785,7 @@ "ignore": true }, { - "__docId__": 58, + "__docId__": 59, "kind": "variable", "name": "configFieldEls", "memberof": "src/App.js", @@ -775,7 +796,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 85, + "lineNumber": 105, "undocument": true, "type": { "types": [ @@ -785,7 +806,7 @@ "ignore": true }, { - "__docId__": 59, + "__docId__": 60, "kind": "variable", "name": "values", "memberof": "src/App.js", @@ -796,7 +817,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": null, "description": null, - "lineNumber": 89, + "lineNumber": 109, "undocument": true, "type": { "types": [ @@ -806,7 +827,28 @@ "ignore": true }, { - "__docId__": 60, + "__docId__": 61, + "kind": "variable", + "name": "magicFieldValue", + "memberof": "src/App.js", + "static": true, + "longname": "src/App.js~magicFieldValue", + "access": "public", + "export": false, + "importPath": "@caldera-labs/components/src/App.js", + "importStyle": null, + "description": null, + "lineNumber": 115, + "undocument": true, + "type": { + "types": [ + "string" + ] + }, + "ignore": true + }, + { + "__docId__": 62, "kind": "class", "name": "App", "memberof": "src/App.js", @@ -817,7 +859,7 @@ "importPath": "@caldera-labs/components/src/App.js", "importStyle": "App", "description": null, - "lineNumber": 95, + "lineNumber": 117, "undocument": true, "interface": false, "extends": [ @@ -825,7 +867,7 @@ ] }, { - "__docId__": 61, + "__docId__": 63, "kind": "method", "name": "render", "memberof": "src/App.js~App", @@ -835,7 +877,7 @@ "longname": "src/App.js~App#render", "access": "public", "description": null, - "lineNumber": 97, + "lineNumber": 119, "undocument": true, "params": [], "return": { @@ -845,10 +887,10 @@ } }, { - "__docId__": 62, + "__docId__": 64, "kind": "file", "name": "src/components/RenderGroup.js", - "content": "import React from 'react';\nimport propTypes from 'prop-types';\nimport {fieldSetFactory} from './fields/factories/fieldSetFactory';\n\n/**\n * Component for rendering an array of field configs\n */\nexport class RenderGroup extends React.Component {\n\n\n\t/**\n\t * Constructor for RenderGroup component\n\t * @param {Object} props\n\t */\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.createComponents = this.createComponents.bind(this);\n\t}\n\n\t/**\n\t * Create components\n\t *\n\t * @return {Array}\n\t */\n\tcreateComponents() {\n\t\tlet configFields = this.props.configFields;\n\n\t\t/**\n\t\t * Find config field ID/id\n\t\t *\n\t\t * @param {Object} configField\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction findFieldId(configField) {\n\t\t\treturn configField.ID ? configField.ID : configField.id ? configField.id : false;\n\t\t}\n\n\t\tif( 'function' === typeof this.props.onBlur ){\n\t\t\tconfigFields.forEach((configField, configFieldIndex ) => {\n\t\t\t\tconst configFieldId = findFieldId(configField);\n\t\t\t\tif( configFieldId ){\n\t\t\t\t\tconfigFields[configFieldIndex].onBlur = () => {\n\t\t\t\t\t\tthis.props.onBlur(configFieldId);\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t});\n\n\t\t}\n\t\tif( 'function' === typeof this.props.onFocus ){\n\t\t\tconfigFields.forEach((configField, configFieldIndex ) => {\n\t\t\t\tconst configFieldId = findFieldId(configField);\n\t\t\t\tif( configFieldId ){\n\t\t\t\t\tconfigFields[configFieldIndex].onFocus = () => {\n\t\t\t\t\t\tthis.props.onFocus(configFieldId);\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t});\n\t\t}\n\t\treturn fieldSetFactory(configFields);\n\t}\n\n\t/**\n\t * Renderer for RenderGroup component\n\t *\n\t * @return {*}\n\t */\n\trender() {\n\t\treturn (\n\t\t\t\n\t\t\t\t{this.createComponents().map((configField, i) => {\n\t\t\t\t\treturn React.createElement(\n\t\t\t\t\t\t'div', {\n\t\t\t\t\t\t\tkey: i,\n\t\t\t\t\t\t\tclassName: RenderGroup.classNames.fieldGroup\n\t\t\t\t\t\t},\n\t\t\t\t\t\tconfigField\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t\n\t\t);\n\t}\n}\n\n/**\n * Prop definitions for RenderGroup component\n * @type {{configFields: *, className: shim}}\n */\nRenderGroup.propTypes = {\n\tconfigFields: propTypes.array.isRequired,\n\tclassName: propTypes.string,\n\tonBlur: propTypes.func,\n\tonFocus: propTypes.func\n};\n\n/**\n * Classnames for elements (wrappers, field groups and form fields)\n *\n * @type {{renderGroupWrapper: string, fieldWrapper: string}}\n */\nRenderGroup.classNames = {\n\trenderGroupWrapper: 'caldera-config-field-setup',\n\tfieldGroup: 'caldera-config-group',\n\tfieldWrapper: 'caldera-config-field',\n\tinput: 'field-config',\n\n};", + "content": "import React from 'react';\nimport propTypes from 'prop-types';\nimport {fieldSetFactory} from './fields/factories/fieldSetFactory';\n\n/**\n * Component for rendering an array of field configs\n */\nexport class RenderGroup extends React.Component {\n\n\n\t/**\n\t * Constructor for RenderGroup component\n\t * @param {Object} props\n\t */\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.createComponents = this.createComponents.bind(this);\n\t}\n\n\t/**\n\t * Create components\n\t *\n\t * @return {Array}\n\t */\n\tcreateComponents() {\n\t\tlet configFields = this.props.configFields;\n\n\t\t/**\n\t\t * Find config field ID/id\n\t\t *\n\t\t * @param {Object} configField\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction findFieldId(configField) {\n\t\t\treturn configField.ID ? configField.ID : configField.id ? configField.id : false;\n\t\t}\n\n\t\tif( 'function' === typeof this.props.onBlur ){\n\t\t\tconfigFields.forEach((configField, configFieldIndex ) => {\n\t\t\t\tconst configFieldId = findFieldId(configField);\n\t\t\t\tif( configFieldId ){\n\t\t\t\t\tconfigFields[configFieldIndex].onBlur = () => {\n\t\t\t\t\t\tthis.props.onBlur(configFieldId);\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t});\n\n\t\t}\n\t\tif( 'function' === typeof this.props.onFocus ){\n\t\t\tconfigFields.forEach((configField, configFieldIndex ) => {\n\t\t\t\tconst configFieldId = findFieldId(configField);\n\t\t\t\tif( configFieldId ){\n\t\t\t\t\tconfigFields[configFieldIndex].onFocus = () => {\n\t\t\t\t\t\tthis.props.onFocus(configFieldId);\n\t\t\t\t\t};\n\n\t\t\t\t}\n\n\t\t\t});\n\t\t}\n\t\treturn fieldSetFactory(configFields);\n\t}\n\n\t/**\n\t * Renderer for RenderGroup component\n\t *\n\t * @return {*}\n\t */\n\trender() {\n\t\treturn (\n\t\t\t\n\t\t\t\t{this.createComponents().map((configField, i) => {\n\t\t\t\t\treturn React.createElement(\n\t\t\t\t\t\t'div', {\n\t\t\t\t\t\t\tkey: i,\n\t\t\t\t\t\t\tclassName: RenderGroup.classNames.fieldGroup\n\t\t\t\t\t\t},\n\t\t\t\t\t\tconfigField\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t\n\t\t);\n\t}\n}\n\n/**\n * Prop definitions for RenderGroup component\n * @type {{configFields: *, className: shim}}\n */\nRenderGroup.propTypes = {\n\tconfigFields: propTypes.array.isRequired,\n\tclassName: propTypes.string,\n\tonBlur: propTypes.func,\n\tonFocus: propTypes.func\n};\n\n/**\n * Classnames for elements (wrappers, field groups and form fields)\n *\n * @type {{renderGroupWrapper: string, fieldWrapper: string}}\n */\nRenderGroup.classNames = {\n\trenderGroupWrapper: 'caldera-config-field-setup',\n\tfieldGroup: 'caldera-config-group',\n\tfieldWrapper: 'caldera-config-field',\n\tinput: 'field-config',\n\n};", "static": true, "longname": "/Users/josh/caldera-js/components/src/components/RenderGroup.js", "access": "public", @@ -856,7 +898,7 @@ "lineNumber": 1 }, { - "__docId__": 63, + "__docId__": 65, "kind": "class", "name": "RenderGroup", "memberof": "src/components/RenderGroup.js", @@ -874,7 +916,7 @@ ] }, { - "__docId__": 64, + "__docId__": 66, "kind": "constructor", "name": "constructor", "memberof": "src/components/RenderGroup.js~RenderGroup", @@ -899,7 +941,7 @@ ] }, { - "__docId__": 66, + "__docId__": 68, "kind": "method", "name": "createComponents", "memberof": "src/components/RenderGroup.js~RenderGroup", @@ -921,7 +963,7 @@ "params": [] }, { - "__docId__": 67, + "__docId__": 69, "kind": "method", "name": "render", "memberof": "src/components/RenderGroup.js~RenderGroup", @@ -943,7 +985,7 @@ "params": [] }, { - "__docId__": 68, + "__docId__": 70, "kind": "file", "name": "src/components/conditional-logic/checkConfigFieldConditionals.js", "content": "/**\n * Check configField conditionals.\n *\n * Returns false if any conditionals fail.\n * Returns true if no conditionals fail, or there are no conditionals.\n *\n * @param {Object} configField The field to check the conditionals of.\n * @param {Object} fieldValues Optional. Data to pass to conditional rule callbacks\n * @return {boolean}\n */\nexport const checkConfigFieldConditionals = (configField, fieldValues = {}) => {\n\tif (!configField.hasOwnProperty('conditionals') || !Array.isArray(configField.conditionals)) {\n\t\treturn true;\n\t}\n\n\tlet allRulesPassed = true;\n\tconfigField.conditionals.forEach(conditional => {\n\t\tif ('function' === typeof conditional && false === conditional.call(null, fieldValues)) {\n\t\t\tallRulesPassed = false;\n\t\t\treturn false;\n\t\t}\n\t});\n\n\treturn allRulesPassed;\n\n};", @@ -954,7 +996,7 @@ "lineNumber": 1 }, { - "__docId__": 69, + "__docId__": 71, "kind": "function", "name": "checkConfigFieldConditionals", "memberof": "src/components/conditional-logic/checkConfigFieldConditionals.js", @@ -1000,7 +1042,7 @@ } }, { - "__docId__": 70, + "__docId__": 72, "kind": "file", "name": "src/components/conditional-logic/checkConfigFieldsConditionals.js", "content": "import {checkConfigFieldConditionals} from './checkConfigFieldConditionals';\n\n/**\n * Check conditionals for a collection of configFields\n *\n * Returns false if any conditionals fail.\n * Returns true if no conditionals fail, or there are no conditionals.\n *\n * @param {Array} configFields The fields to check the conditionals of.\n * @param {Object} fieldValues Optional. Data to pass to conditional rules' callbacks\n * @return {boolean}\n */\nexport const checkConfigFieldsConditionals = (configFields, fieldValues = {}) => {\n\tlet results = {};\n\tObject.values( configFields ).forEach(configField => {\n\t\tresults[configField.ID] = checkConfigFieldConditionals(configField,fieldValues);\n\t});\n\treturn results;\n\n};", @@ -1011,7 +1053,7 @@ "lineNumber": 1 }, { - "__docId__": 71, + "__docId__": 73, "kind": "function", "name": "checkConfigFieldsConditionals", "memberof": "src/components/conditional-logic/checkConfigFieldsConditionals.js", @@ -1057,7 +1099,7 @@ } }, { - "__docId__": 72, + "__docId__": 74, "kind": "file", "name": "src/components/conditional-logic/index.js", "content": "/*eslint no-undef: \"error\"*/\n/*eslint-env node*/\nimport {checkConfigFieldConditionals} from './checkConfigFieldConditionals';\nimport {checkConfigFieldsConditionals} from './checkConfigFieldsConditionals';\nimport {reduceConfigFieldsToValues} from './util';\n\n/**\n * The Caldera Components conditional logic system\n */\nexport default {\n\tcheckConfigFieldConditionals,\n\tcheckConfigFieldsConditionals,\n\treduceConfigFieldsToValues\n};", @@ -1068,7 +1110,7 @@ "lineNumber": 1 }, { - "__docId__": 73, + "__docId__": 75, "kind": "file", "name": "src/components/conditional-logic/util.js", "content": "/**\n * Get the current values for prepareConfigFields\n *\n * @param {Array} configFields\n */\nexport const reduceConfigFieldsToValues = (configFields) => {\n\tlet values = {};\n\tconfigFields.forEach(field => {\n\t\tvalues[field.ID] = field.value\n\t\t\t? field.value\n\t\t\t: field.default\n\t\t\t\t? field.default\n\t\t\t\t: null;\n\t});\n\treturn values;\n};\n", @@ -1079,7 +1121,7 @@ "lineNumber": 1 }, { - "__docId__": 74, + "__docId__": 76, "kind": "function", "name": "reduceConfigFieldsToValues", "memberof": "src/components/conditional-logic/util.js", @@ -1112,10 +1154,10 @@ } }, { - "__docId__": 75, + "__docId__": 77, "kind": "file", "name": "src/components/fields/FieldGroup.js", - "content": "import React from 'react';\nimport classNames from 'classnames';\nimport {ariaDescribedbyAttr} from './util';\nimport {\n\tfieldGroupPropTypes,\n} from './propTypes';\n\nimport {FieldInner} from './FieldInner';\nimport {RenderGroup} from '../RenderGroup';\nimport {Message} from './messages/Message';\nimport {messageObjectFactory} from './messages/messageObjectFactory';\nimport {fieldsetCheckboxHandler} from './field-group-change-handlers/fieldsetCheckboxHandler';\n\n/**\n * Represents one configField -- wrapper, label and input.\n *\n * @param props\n * @return {*}\n * @constructor\n */\nexport const FieldGroup = (props) => {\n\n\t/**\n\t * Creates the id attribute\n\t * @return {String}\n\t */\n\tfunction idAttrForHelpElement() {\n\t\treturn ariaDescribedbyAttr(props.id, props.help);\n\t}\n\n\n\t/**\n\t * Based on type, render the field.\n\t *\n\t * @return {*}\n\t */\n\tfunction fieldInner(fieldProps) {\n\t\tconst message = 'object' === typeof fieldProps.message\n\t\t\t? messageObjectFactory(fieldProps.message)\n\t\t\t: messageObjectFactory({message: null, error: false});\n\n\t\tfunction getFieldClassName(conditionalClassNames) {\n\t\t\treturn classNames(\n\t\t\t\t{\n\t\t\t\t\trequired: fieldProps.isRequired,\n\t\t\t\t\t...conditionalClassNames\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\t/**\n\t\t * Is this option the checked value?\n\t\t * @param {object}option\n\t\t * @param {String|number|Array} currentValue\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isCheckedOption(option, currentValue) {\n\t\t\tif (Array.isArray(currentValue)) {\n\t\t\t\treturn currentValue.includes(option.value);\n\t\t\t}\n\t\t\treturn option.value === currentValue;\n\t\t}\n\n\t\t//Fieldsets are rendered recursively.\n\t\tif ('fieldset' === fieldProps.type) {\n\t\t\treturn (\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{props.label}\n\t\t\t\t\t\n\t\t\t\t\t{props.options.map(option => {\n\n\n\t\t\t\t\t\t//Call this same function, as a regular checkbox\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{fieldInner({\n\t\t\t\t\t\t\t\t\ttype: 'input',\n\t\t\t\t\t\t\t\t\tinputType: 'checkbox',\n\t\t\t\t\t\t\t\t\tid: `${props.id}-${option.value}`,\n\t\t\t\t\t\t\t\t\tvalue: isCheckedOption(option, props.value),\n\t\t\t\t\t\t\t\t\tfieldClassName: getFieldClassName({\n\t\t\t\t\t\t\t\t\t\t'fieldset-checkbox': true,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\tlabel: option.label,\n\t\t\t\t\t\t\t\t\tdisabled: props.disabled,\n\t\t\t\t\t\t\t\t\tonValueChange: () => fieldsetCheckboxHandler(option, props.values, props.onValueChange),\n\t\t\t\t\t\t\t\t\tonBlur: props.onBlur,\n\t\t\t\t\t\t\t\t\tonFocus: props.onFocus\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t\n\t\t\t);\n\t\t} else if ('hidden' === fieldProps.inputType) {\n\t\t\treturn (\n\t\t\t\tFieldInner(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: props.type,\n\t\t\t\t\t\tid: props.id,\n\t\t\t\t\t\tfieldClassName: getFieldClassName(),\n\t\t\t\t\t\tvalue: fieldProps.value,\n\t\t\t\t\t\tonValueChange: fieldProps.onValueChange,\n\t\t\t\t\t\tinputType: fieldProps.inputType,\n\t\t\t\t\t\tdisabled: props.disabled,\n\t\t\t\t\t\tonBlur: props.onBlur,\n\t\t\t\t\t\tonFocus: props.onFocus\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t);\n\t\t} else {\n\t\t\treturn (\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{fieldProps.label}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t{FieldInner(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: fieldProps.type,\n\t\t\t\t\t\t\tid: fieldProps.id,\n\t\t\t\t\t\t\tfieldClassName: getFieldClassName({\n\t\t\t\t\t\t\t\t'block-input': fieldProps.isBlockInput\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\thelp: fieldProps.help,\n\t\t\t\t\t\t\tvalue: fieldProps.value,\n\t\t\t\t\t\t\tonValueChange: fieldProps.onValueChange,\n\t\t\t\t\t\t\tinputType: fieldProps.inputType,\n\t\t\t\t\t\t\toptions: fieldProps.options,\n\t\t\t\t\t\t\tdisabled: props.disabled,\n\t\t\t\t\t\t\tonBlur: props.onBlur,\n\t\t\t\t\t\t\tonFocus: props.onFocus\n\t\t\t\t\t\t}\n\t\t\t\t\t)}\n\t\t\t\t\t{fieldProps.help &&\n\t\t\t\t\t\n\t\t\t\t\t\t{fieldProps.help}\n\t\t\t\t\t

    \n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t);\n\t\t}\n\n\t}\n\n\t/**\n\t * Render field group\n\t */\n\treturn fieldInner(props);\n};\n\n\nFieldGroup.propTypes = fieldGroupPropTypes;\n\nFieldGroup.defaultProps = {\n\tisBlockInput: true,\n\tisRequired: false,\n\thelp: ''\n};", + "content": "import React from 'react';\nimport classNames from 'classnames';\nimport {ariaDescribedbyAttr} from './util';\nimport {\n\tfieldGroupPropTypes,\n} from './propTypes';\n\nimport {FieldInner} from './FieldInner';\nimport {RenderGroup} from '../RenderGroup';\nimport {Message} from './messages/Message';\nimport {messageObjectFactory} from './messages/messageObjectFactory';\nimport {fieldsetCheckboxHandler} from './field-group-change-handlers/fieldsetCheckboxHandler';\nimport {MagicFieldGroup} from './magic-select/MagicFieldGroup';\n\n/**\n * Represents one configField -- wrapper, label and input.\n *\n * @param props\n * @return {*}\n * @constructor\n */\nexport const FieldGroup = (props) => {\n\tif( 'magic' === props.type ){\n\t\treturn ;\n\t}\n\n\t/**\n\t * Creates the id attribute\n\t * @return {String}\n\t */\n\tfunction idAttrForHelpElement() {\n\t\treturn ariaDescribedbyAttr(props.id, props.help);\n\t}\n\n\n\t/**\n\t * Based on type, render the field.\n\t *\n\t * @return {*}\n\t */\n\tfunction fieldInner(fieldProps) {\n\t\tconst message = 'object' === typeof fieldProps.message\n\t\t\t? messageObjectFactory(fieldProps.message)\n\t\t\t: messageObjectFactory({message: null, error: false});\n\n\t\tfunction getFieldClassName(conditionalClassNames) {\n\t\t\treturn classNames(\n\t\t\t\t{\n\t\t\t\t\trequired: fieldProps.isRequired,\n\t\t\t\t\t...conditionalClassNames\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\t/**\n\t\t * Is this option the checked value?\n\t\t * @param {object}option\n\t\t * @param {String|number|Array} currentValue\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction isCheckedOption(option, currentValue) {\n\t\t\tif (Array.isArray(currentValue)) {\n\t\t\t\treturn currentValue.includes(option.value);\n\t\t\t}\n\t\t\treturn option.value === currentValue;\n\t\t}\n\n\t\t//Fieldsets are rendered recursively.\n\t\tif ('fieldset' === fieldProps.type) {\n\t\t\treturn (\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{props.label}\n\t\t\t\t\t\n\t\t\t\t\t{props.options.map(option => {\n\n\n\t\t\t\t\t\t//Call this same function, as a regular checkbox\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{fieldInner({\n\t\t\t\t\t\t\t\t\ttype: 'input',\n\t\t\t\t\t\t\t\t\tinputType: 'checkbox',\n\t\t\t\t\t\t\t\t\tid: `${props.id}-${option.value}`,\n\t\t\t\t\t\t\t\t\tvalue: isCheckedOption(option, props.value),\n\t\t\t\t\t\t\t\t\tfieldClassName: getFieldClassName({\n\t\t\t\t\t\t\t\t\t\t'fieldset-checkbox': true,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\tlabel: option.label,\n\t\t\t\t\t\t\t\t\tdisabled: props.disabled,\n\t\t\t\t\t\t\t\t\tonValueChange: () => fieldsetCheckboxHandler(option, props.values, props.onValueChange),\n\t\t\t\t\t\t\t\t\tonBlur: props.onBlur,\n\t\t\t\t\t\t\t\t\tonFocus: props.onFocus\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t\n\t\t\t);\n\t\t} else if ('hidden' === fieldProps.inputType) {\n\t\t\treturn (\n\t\t\t\tFieldInner(\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: props.type,\n\t\t\t\t\t\tid: props.id,\n\t\t\t\t\t\tfieldClassName: getFieldClassName(),\n\t\t\t\t\t\tvalue: fieldProps.value,\n\t\t\t\t\t\tonValueChange: fieldProps.onValueChange,\n\t\t\t\t\t\tinputType: fieldProps.inputType,\n\t\t\t\t\t\tdisabled: props.disabled,\n\t\t\t\t\t\tonBlur: props.onBlur,\n\t\t\t\t\t\tonFocus: props.onFocus\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t);\n\t\t} else {\n\t\t\treturn (\n\t\t\t\t\n\t\t\t\t\t\n\n\t\t\t\t\t\n\t\t\t\t\t{FieldInner(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: fieldProps.type,\n\t\t\t\t\t\t\tid: fieldProps.id,\n\t\t\t\t\t\t\tfieldClassName: getFieldClassName({\n\t\t\t\t\t\t\t\t'block-input': fieldProps.isBlockInput\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\thelp: fieldProps.help,\n\t\t\t\t\t\t\tvalue: fieldProps.value,\n\t\t\t\t\t\t\tonValueChange: fieldProps.onValueChange,\n\t\t\t\t\t\t\tinputType: fieldProps.inputType,\n\t\t\t\t\t\t\toptions: fieldProps.options,\n\t\t\t\t\t\t\tdisabled: props.disabled,\n\t\t\t\t\t\t\tonBlur: props.onBlur,\n\t\t\t\t\t\t\tonFocus: props.onFocus\n\t\t\t\t\t\t}\n\t\t\t\t\t)}\n\t\t\t\t\t{fieldProps.help &&\n\t\t\t\t\t\n\t\t\t\t\t\t{fieldProps.help}\n\t\t\t\t\t

    \n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t);\n\t\t}\n\n\t}\n\n\t/**\n\t * Render field group\n\t */\n\treturn fieldInner(props);\n};\n\n/**\n * The prop type definitions for FieldGroup components\n *\n * @type {{id: (boolean|shim|*), isBlockInput: shim, isRequired: shim, help: shim, label: (boolean|shim|*), type: shim, value: shim, onValueChange: (boolean|shim|*), inputType: shim}}\n */\nFieldGroup.propTypes = fieldGroupPropTypes;\n\n/**\n * Default props for FieldGroups\n *\n * @type {{isBlockInput: boolean, isRequired: boolean, help: string}}\n */\nFieldGroup.defaultProps = {\n\tisBlockInput: true,\n\tisRequired: false,\n\thelp: ''\n};\n\n/**\n * Creates the FieldGroup's label component\n *\n * @param {Object} props\n * @return {*}\n * @constructor\n */\nFieldGroup.Label = (props) => {\n\treturn (\n\t\t\n\t\t\t{props.label}\n\t\t\n\t);\n};", "static": true, "longname": "/Users/josh/caldera-js/components/src/components/fields/FieldGroup.js", "access": "public", @@ -1123,7 +1165,7 @@ "lineNumber": 1 }, { - "__docId__": 76, + "__docId__": 78, "kind": "function", "name": "FieldGroup", "memberof": "src/components/fields/FieldGroup.js", @@ -1136,7 +1178,7 @@ "importPath": "@caldera-labs/components/src/components/fields/FieldGroup.js", "importStyle": "{FieldGroup}", "description": "Represents one configField -- wrapper, label and input.", - "lineNumber": 21, + "lineNumber": 22, "unknown": [ { "tagName": "@constructor", @@ -1165,10 +1207,10 @@ } }, { - "__docId__": 77, + "__docId__": 79, "kind": "file", "name": "src/components/fields/FieldInner.js", - "content": "import {fieldInnerPropTypes} from './propTypes';\nimport React from 'react';\nimport {Input} from './input/Input';\nimport {SelectField} from './select/SelectField';\nimport {ariaDescribedbyAttr} from './util';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport {RenderGroup} from '../RenderGroup';\n/**\n * Creates the field inside of a field group\n *\n * @param {Object} props\n * @returns {*}\n * @constructor\n */\nexport const FieldInner = (props) => {\n\n\t/**\n\t * Get the ID for the description element if it will be created\n\t *\n\t * @return {String|null}\n\t */\n\tfunction ariaIdAttr() {\n\t\treturn ariaDescribedbyAttr(props.id, props.help);\n\t}\n\n\t/**\n\t * Get the className prop for the\n\t *\n\t * @return {String}\n\t */\n\tfunction inputClassName() {\n\t\treturn classNames([\n\t\t\tprops.fieldClassName,\n\t\t\tRenderGroup.classNames.input\n\t\t]\n\t\t);\n\t}\n\n\tswitch( props.type ){\n\tcase 'select':\n\tcase 'dropdown':\n\t\treturn (\n\t\t\t\n\t\t);\n\tdefault:\n\tcase 'input':\n\t\treturn (\n\t\t\t);\n\t}\n\n};\n\n/**\n * propTypes for FieldInner component\n *\n * @type {{options, ariaDescribedbyAttr}}\n */\nFieldInner.propTypes = {\n\t...fieldInnerPropTypes,\n\ttype: PropTypes.string,\n};\n\n/**\n * Default props for FieldInner component\n * @type {{help: string}}\n */\nFieldInner.defaultProps = {\n\thelp: '',\n\ttype: 'input'\n};", + "content": "import {fieldInnerPropTypes} from './propTypes';\nimport React from 'react';\nimport {Input} from './input/Input';\nimport {SelectField} from './select/SelectField';\nimport {ariaDescribedbyAttr} from './util';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport {RenderGroup} from '../RenderGroup';\n/**\n * Creates the field inside of a field group\n *\n * @param {Object} props\n * @returns {*}\n * @constructor\n */\nexport const FieldInner = (props) => {\n\n\t/**\n\t * Get the ID for the description element if it will be created\n\t *\n\t * @return {String|null}\n\t */\n\tfunction ariaIdAttr() {\n\t\treturn ariaDescribedbyAttr(props.id, props.help);\n\t}\n\n\t/**\n\t * Get the className prop for the\n\t *\n\t * @return {String}\n\t */\n\tfunction inputClassName() {\n\t\treturn classNames([\n\t\t\tprops.fieldClassName,\n\t\t\tRenderGroup.classNames.input\n\t\t]\n\t\t);\n\t}\n\n\tswitch( props.type ){\n\tcase 'select':\n\tcase 'dropdown':\n\t\tconst options = Array.isArray(props.options) ? props.options : [];\n\t\treturn (\n\t\t\t\n\t\t);\n\tdefault:\n\tcase 'input':\n\t\treturn (\n\t\t\t);\n\t}\n\n};\n\n/**\n * propTypes for FieldInner component\n *\n * @type {{options, ariaDescribedbyAttr}}\n */\nFieldInner.propTypes = {\n\t...fieldInnerPropTypes,\n\ttype: PropTypes.string,\n};\n\n/**\n * Default props for FieldInner component\n * @type {{help: string}}\n */\nFieldInner.defaultProps = {\n\thelp: '',\n\ttype: 'input'\n};", "static": true, "longname": "/Users/josh/caldera-js/components/src/components/fields/FieldInner.js", "access": "public", @@ -1176,7 +1218,7 @@ "lineNumber": 1 }, { - "__docId__": 78, + "__docId__": 80, "kind": "function", "name": "FieldInner", "memberof": "src/components/fields/FieldInner.js", @@ -1222,7 +1264,64 @@ } }, { - "__docId__": 79, + "__docId__": 81, + "kind": "file", + "name": "src/components/fields/button-group/ButtonGroup.js", + "content": "import React from 'react';\nimport {optionShape} from '../propTypes';\nimport PropTypes from 'prop-types';\n/**\n * Creates a button group field\n *\n * @param {Object} props\n * @returns {*}\n * @constructor\n */\nexport const ButtonGroup = (props) => {\n\t/**\n\t * Dispatches new value(s) to parent\n\t *\n\t * @param selection\n\t * @returns {*}\n\t */\n\tfunction changeHandler(selection) {\n\t\treturn props.onChange(selection);\n\t}\n\n\t/**\n\t * Render a button group\n\t */\n\treturn (\n\t\t\n\t\t\t{props.options.map(option => {\n\t\t\t\treturn {\n\t\t\t\t\t\treturn changeHandler(option.value);\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{option.hasOwnProperty('icon')&&\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\t{!option.hasOwnProperty('icon') &&\n\t\t\t\t\t\t{option.label}\n\t\t\t\t\t}\n\n\t\t\t\t;\n\t\t\t})}\n\t\t\n\t);\n};\n\n/**\n * Prop definition for select fields\n *\n * @type {{}}\n */\nButtonGroup.propTypes = {\n\tonChange: PropTypes.func.isRequired,\n\toptions: PropTypes.arrayOf(\n\t\tPropTypes.shape({\n\t\t\t...optionShape,\n\t\t\ticon:PropTypes.string,\n\t\t\tariaLabel:PropTypes.string\n\t\t})\n\t),\n\tvalue: PropTypes.oneOfType([\n\t\tPropTypes.number,\n\t\tPropTypes.string\n\t])\n};\n\n/**\n * Default props for select fields\n *\n * @type {{options: Array}}\n */\nButtonGroup.defaultProps = {\n\toptions: []\n};", + "static": true, + "longname": "/Users/josh/caldera-js/components/src/components/fields/button-group/ButtonGroup.js", + "access": "public", + "description": null, + "lineNumber": 1 + }, + { + "__docId__": 82, + "kind": "function", + "name": "ButtonGroup", + "memberof": "src/components/fields/button-group/ButtonGroup.js", + "generator": false, + "async": false, + "static": true, + "longname": "src/components/fields/button-group/ButtonGroup.js~ButtonGroup", + "access": "public", + "export": true, + "importPath": "@caldera-labs/components/src/components/fields/button-group/ButtonGroup.js", + "importStyle": "{ButtonGroup}", + "description": "Creates a button group field", + "lineNumber": 11, + "unknown": [ + { + "tagName": "@returns", + "tagValue": "{*}" + }, + { + "tagName": "@constructor", + "tagValue": "" + } + ], + "params": [ + { + "nullable": null, + "types": [ + "Object" + ], + "spread": false, + "optional": false, + "name": "props", + "description": "" + } + ], + "return": { + "nullable": null, + "types": [ + "*" + ], + "spread": false, + "description": "" + } + }, + { + "__docId__": 83, "kind": "file", "name": "src/components/fields/factories/fieldFactory.js", "content": "import {prepareFieldConfig} from './prepareFieldConfig';\nimport {FieldGroup} from '../FieldGroup';\n\n\n/**\n * Generates field controls\n *\n * @param {Array} fieldArgs Field config\n * @returns {*}\n */\nexport const fieldFactory = (fieldArgs) =>{\n\treturn FieldGroup(prepareFieldConfig(fieldArgs));\n};\n", @@ -1233,7 +1332,7 @@ "lineNumber": 1 }, { - "__docId__": 80, + "__docId__": 84, "kind": "function", "name": "fieldFactory", "memberof": "src/components/fields/factories/fieldFactory.js", @@ -1275,7 +1374,7 @@ } }, { - "__docId__": 81, + "__docId__": 85, "kind": "file", "name": "src/components/fields/factories/fieldSetFactory.js", "content": "import {fieldFactory} from './fieldFactory';\n\n/**\n * Given an array of field configs, generates and array of field controls\n *\n * Should be used for a group of settings, such as all settings for a processor.\n *\n * @param {Array} fields Field configs\n * @returns {Array}\n */\nexport const fieldSetFactory = (fields) =>{\n\tlet out = [];\n\tObject.values(fields).forEach( field => {\n\t\tout.push(fieldFactory(field));\n\t});\n\treturn out;\n};", @@ -1286,7 +1385,7 @@ "lineNumber": 1 }, { - "__docId__": 82, + "__docId__": 86, "kind": "function", "name": "fieldSetFactory", "memberof": "src/components/fields/factories/fieldSetFactory.js", @@ -1328,7 +1427,7 @@ } }, { - "__docId__": 83, + "__docId__": 87, "kind": "file", "name": "src/components/fields/factories/index.js", "content": "/*eslint no-undef: \"error\"*/\n/*eslint-env node*/\nimport {fieldFactory} from './fieldFactory';\nimport {fieldSetFactory} from './fieldSetFactory';\n\nmodule.exports = {\n\tfieldFactory,\n\tfieldSetFactory\n};", @@ -1339,10 +1438,10 @@ "lineNumber": 1 }, { - "__docId__": 84, + "__docId__": 88, "kind": "file", "name": "src/components/fields/factories/prepareFieldConfig.js", - "content": "import {fieldGroupPropTypes} from '../propTypes';\nimport {isValidHtml5type, toBoolean} from '../util';\nimport {messageObjectFactory} from '../messages/messageObjectFactory';\n\n/**\n * Validates field configurations\n *\n * NOTE: This is called internally by factory. You probably do not want to call this.\n *\n * @param {Object}fieldArgs\n * @returns {*}\n */\nexport const prepareFieldConfig = (fieldArgs) => {\n\t/**\n\t * Pick whitelisted keys from object\n\t *\n\t * @see http://www.jstips.co/en/javascript/picking-and-rejecting-object-properties/\n\t *\n\t * @param {Object} obj The object to pick from\n\t * @param {Array} keys The whitelist of keys\n\t * @return {*}\n\t */\n\tfunction pick(obj, keys) {\n\t\treturn keys.map(k => k in obj ? {[k]: obj[k]} : {})\n\t\t\t.reduce((res, o) => Object.assign(res, o), {});\n\t}\n\n\tswitch (fieldArgs.type) {\n\tcase 'select':\n\tcase 'dropdown':\n\t\tfieldArgs.type = 'select';\n\t\tbreak;\n\tcase 'fieldset':\n\t\tfieldArgs.type = 'fieldset';\n\t\tbreak;\n\tcase 'text':\n\tcase 'number':\n\tdefault:\n\t\tfieldArgs.inputType = isValidHtml5type(fieldArgs.type) ? fieldArgs.type : 'text';\n\t\tfieldArgs.type = 'input';\n\t\tbreak;\n\t}\n\n\tif (fieldArgs.hasOwnProperty('desc')) {\n\t\tfieldArgs.help = fieldArgs.desc;\n\t}\n\tif (fieldArgs.hasOwnProperty('description')) {\n\t\tfieldArgs.help = fieldArgs.description;\n\t}\n\n\tlet validators = [];\n\tif( fieldArgs.hasOwnProperty('validators') && Array.isArray(fieldArgs.validators )){\n\t\tvalidators = fieldArgs.validators;\n\t}\n\n\tfieldArgs = pick(fieldArgs, Object.keys(fieldGroupPropTypes));\n\tfieldArgs.disabled = toBoolean(fieldArgs.disabled);\n\tfieldArgs.message = 'object' === typeof fieldArgs.message\n\t\t? messageObjectFactory(fieldArgs.message)\n\t\t: messageObjectFactory({message:null, error: false });\n\n\tfieldArgs.validators = validators;\n\treturn fieldArgs;\n};", + "content": "import {fieldGroupPropTypes,magicGroupPropTypes} from '../propTypes';\nimport {isValidHtml5type, toBoolean} from '../util';\nimport {messageObjectFactory} from '../messages/messageObjectFactory';\n\n/**\n * Validates field configurations\n *\n * NOTE: This is called internally by factory. You probably do not want to call this.\n *\n * @param {Object}fieldArgs\n * @returns {*}\n */\nexport const prepareFieldConfig = (fieldArgs) => {\n\t/**\n\t * Pick whitelisted keys from object\n\t *\n\t * @see http://www.jstips.co/en/javascript/picking-and-rejecting-object-properties/\n\t *\n\t * @param {Object} obj The object to pick from\n\t * @param {Array} keys The whitelist of keys\n\t * @return {*}\n\t */\n\tfunction pick(obj, keys) {\n\t\treturn keys.map(k => k in obj ? {[k]: obj[k]} : {})\n\t\t\t.reduce((res, o) => Object.assign(res, o), {});\n\t}\n\n\tswitch (fieldArgs.type) {\n\tcase 'select':\n\tcase 'dropdown':\n\t\tfieldArgs.type = 'select';\n\t\tbreak;\n\tcase 'fieldset':\n\t\tfieldArgs.type = 'fieldset';\n\t\tbreak;\n\tcase 'text':\n\tcase 'number':\n\tdefault:\n\t\tfieldArgs.inputType = isValidHtml5type(fieldArgs.type) ? fieldArgs.type : 'text';\n\t\tfieldArgs.type = 'input';\n\t\tbreak;\n\t}\n\n\tif (fieldArgs.hasOwnProperty('desc')) {\n\t\tfieldArgs.help = fieldArgs.desc;\n\t}\n\tif (fieldArgs.hasOwnProperty('description')) {\n\t\tfieldArgs.help = fieldArgs.description;\n\t}\n\n\tlet validators = [];\n\tif( fieldArgs.hasOwnProperty('validators') && Array.isArray(fieldArgs.validators )){\n\t\tvalidators = fieldArgs.validators;\n\t}\n\n\tconst keys = 'magic' === fieldArgs.type ? magicGroupPropTypes : fieldGroupPropTypes;\n\tfieldArgs = pick(fieldArgs, Object.keys(keys));\n\tfieldArgs.disabled = toBoolean(fieldArgs.disabled);\n\tfieldArgs.message = 'object' === typeof fieldArgs.message\n\t\t? messageObjectFactory(fieldArgs.message)\n\t\t: messageObjectFactory({message:null, error: false });\n\n\tfieldArgs.validators = validators;\n\treturn fieldArgs;\n};", "static": true, "longname": "/Users/josh/caldera-js/components/src/components/fields/factories/prepareFieldConfig.js", "access": "public", @@ -1350,7 +1449,7 @@ "lineNumber": 1 }, { - "__docId__": 85, + "__docId__": 89, "kind": "function", "name": "prepareFieldConfig", "memberof": "src/components/fields/factories/prepareFieldConfig.js", @@ -1392,31 +1491,563 @@ } }, { - "__docId__": 86, + "__docId__": 90, + "kind": "file", + "name": "src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js", + "content": "import {addOrRemoveFromArray} from '../util';\n\n/**\n * Change handler for a checkbox that is a part of a group\n * @param {Object} option Option that is being changed. Shape: `{value:String|number,label:String}`,\n * @param {Array|string|number} values Current values\n * @param {Function} onValueChange Function to call with updated value\n */\nexport const fieldsetCheckboxHandler = (option, values, onValueChange) => {\n\tif (!Array.isArray(values)) {\n\t\tif ('string' === typeof values || 'number' === typeof values) {\n\t\t\tvalues = [values];\n\t\t} else {\n\t\t\tvalues = [];\n\n\t\t}\n\t}\n\tvalues = addOrRemoveFromArray(option.value, values);\n\tonValueChange(values);\n};", + "static": true, + "longname": "/Users/josh/caldera-js/components/src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js", + "access": "public", + "description": null, + "lineNumber": 1 + }, + { + "__docId__": 91, + "kind": "function", + "name": "fieldsetCheckboxHandler", + "memberof": "src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js", + "generator": false, + "async": false, + "static": true, + "longname": "src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js~fieldsetCheckboxHandler", + "access": "public", + "export": true, + "importPath": "@caldera-labs/components/src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js", + "importStyle": "{fieldsetCheckboxHandler}", + "description": "Change handler for a checkbox that is a part of a group", + "lineNumber": 9, + "params": [ + { + "nullable": null, + "types": [ + "Object" + ], + "spread": false, + "optional": false, + "name": "option", + "description": "Option that is being changed. Shape: `{value:String|number,label:String}`," + }, + { + "nullable": null, + "types": [ + "Array", + "string", + "number" + ], + "spread": false, + "optional": false, + "name": "values", + "description": "Current values" + }, + { + "nullable": null, + "types": [ + "Function" + ], + "spread": false, + "optional": false, + "name": "onValueChange", + "description": "Function to call with updated value" + } + ], + "return": null + }, + { + "__docId__": 92, + "kind": "file", + "name": "src/components/fields/index.js", + "content": "/*eslint no-undef: \"error\"*/\n/*eslint-env node*/\nimport {FieldGroup} from './FieldGroup';\nimport {SelectFieldFancy} from './select/SelectFieldFancy';\nimport {Input} from './input/Input';\n\nmodule.exports = {\n\tFieldGroup,\n\tSelectField: SelectFieldFancy,\n\tInput\n};", + "static": true, + "longname": "/Users/josh/caldera-js/components/src/components/fields/index.js", + "access": "public", + "description": null, + "lineNumber": 1 + }, + { + "__docId__": 93, + "kind": "file", + "name": "src/components/fields/input/Input.js", + "content": "import React from 'react';\nimport {fieldPropTypes} from '../propTypes';\nimport classNames from 'classnames';\nimport {RenderGroup} from '../../RenderGroup';\n/**\n * Input component for any HTML5 input type\n *\n * @param {Object} props\n * @returns {*}\n * @constructor\n */\nexport const Input = (props) => {\n\t/**\n\t * Dispatches value of input when it changes\n\t * @param event\n\t * @return {*}\n\t */\n\tfunction changeHandler(event){\n\t\treturn props.onValueChange(event.target.value);\n\t}\n\n\t/**\n\t * Dispatches value when checkbox is checked\n\t * @return {*}\n\t */\n\tfunction checkboxChangeHandler() {\n\t\treturn props.onValueChange(! props.value);\n\t}\n\n\n\t/**\n\t * Get the className prop for inputs\n\t *\n\t * @return {String}\n\t */\n\tfunction inputClassName() {\n\t\treturn classNames(\n\t\t\tprops.fieldClassName,\n\t\t\tRenderGroup.classNames.input\n\t\t);\n\t}\n\n\tif( 'checkbox' === props.inputType ){\n\t\treturn (\n\t\t\t\n\t\t);\n\t}\n\n\treturn (\n\t\t\n\t);\n\n};\n\n/**\n * Prop definitions for Input components\n */\nInput.propTypes = fieldPropTypes;\n\n/**\n * Default props for Input Component\n *\n * @type {{ariaDescribedbyAttr: string, isRequired: boolean, inputType: string}}\n */\nInput.defaultProps = {\n\tariaDescribedbyAttr: '',\n\tisRequired: false,\n\tinputType: 'text'\n};", + "static": true, + "longname": "/Users/josh/caldera-js/components/src/components/fields/input/Input.js", + "access": "public", + "description": null, + "lineNumber": 1 + }, + { + "__docId__": 94, + "kind": "function", + "name": "Input", + "memberof": "src/components/fields/input/Input.js", + "generator": false, + "async": false, + "static": true, + "longname": "src/components/fields/input/Input.js~Input", + "access": "public", + "export": true, + "importPath": "@caldera-labs/components/src/components/fields/input/Input.js", + "importStyle": "{Input}", + "description": "Input component for any HTML5 input type", + "lineNumber": 12, + "unknown": [ + { + "tagName": "@returns", + "tagValue": "{*}" + }, + { + "tagName": "@constructor", + "tagValue": "" + } + ], + "params": [ + { + "nullable": null, + "types": [ + "Object" + ], + "spread": false, + "optional": false, + "name": "props", + "description": "" + } + ], + "return": { + "nullable": null, + "types": [ + "*" + ], + "spread": false, + "description": "" + } + }, + { + "__docId__": 95, + "kind": "file", + "name": "src/components/fields/magic-select/MagicFieldGroup.js", + "content": "import React from 'react';\nimport {magicGroupPropTypes} from '../propTypes';\nimport classNames from 'classnames';\nimport {MagicItem} from './MagicItem';\nimport {ButtonGroup} from '../button-group/ButtonGroup';\nimport {MagicSelect} from './MagicSelect';\nimport {RenderGroup} from '../../RenderGroup';\nimport {Message} from '../messages/Message';\nimport {FieldGroup} from '../FieldGroup';\n\n\n/**\n * Encapsulates a complete Magic Select field group including label and the type chooser and the input\n */\nexport class MagicFieldGroup extends React.PureComponent {\n\n\t/**\n\t * Create a MagicFieldGroup component\n\t *\n\t * @param {Object} props\n\t */\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.state = {\n\t\t\tcurrentListType: props.defaultList,\n\t\t\tisOpen: props.isOpen,\n\t\t};\n\t\tthis.onChange = this.onChange.bind(this);\n\t\tthis.items = this.items.bind(this);\n\t\tthis.onChange = this.onChange.bind(this);\n\t\tthis.onSelect = this.onSelect.bind(this);\n\t\tthis.onInputFocus = this.onInputFocus.bind(this);\n\t\tthis.renderItem = this.renderItem.bind(this);\n\t\tthis.onInputBlur = this.onInputBlur.bind(this);\n\t\tthis.onChangeListType = this.onChangeListType.bind(this);\n\t\tthis.listTypeOptions = this.listTypeOptions.bind(this);\n\t}\n\n\t/**\n\t * Handle direct change events\n\t * @param {String|number} newValue\n\t */\n\tonChange(newValue) {\n\t\tthis.props.onValueChange(newValue);\n\t}\n\n\t/**\n\t * Handle when the field gets focus\n\t */\n\tonInputFocus() {\n\t\tthis.setState({isOpen: true});\n\t}\n\n\t/**\n\t * Handle when the field is blurred\n\t */\n\tonInputBlur() {\n\t\tthis.setState({isOpen: false});\n\t}\n\n\n\t/**\n\t * Handle when the option is chosen\n\t * @param {String|number} value\n\t */\n\tonSelect(value) {\n\t\tthis.props.onValueChange(value);\n\t\tthis.setState({isOpen: false});\n\t}\n\n\t/**\n\t * Update list of tags to show\n\t * @param {String}newType\n\t */\n\tonChangeListType(newType){\n\t\tif( ! this.state.isOpen ){\n\t\t\tthis.setState({isOpen:true});\n\t\t}\n\t\tthis.setState({currentListType:newType});\n\t}\n\n\t/**\n\t * Render option\n\t *\n\t * @param {object} item\n\t * @param {bool} isHighlighted\n\t * @return {*}\n\t */\n\trenderItem(item, isHighlighted){\n\t\treturn ;\n\t}\n\n\t/**\n\t * Create the list of items\n\t *\n\t * @return {Array}\n\t */\n\titems() {\n\t\tconst optionsOrEmpty =(options) => {\n\t\t\treturn Array.isArray(options) && options.length ? options : [];\n\t\t};\n\n\t\tlet items = [];\n\n\t\tif( optionsOrEmpty(this.props.options).length){\n\t\t\titems = optionsOrEmpty(this.props.options);\n\t\t}\n\t\telse if ('system' === this.state.currentListType ) {\n\t\t\titems = optionsOrEmpty(this.props.systemTagsList);\n\t\t} else {\n\t\t\titems = optionsOrEmpty(this.props.fieldsList);\n\t\t}\n\n\t\tif (items.length) {\n\t\t\titems.forEach((item, itemIndex) => {\n\t\t\t\titems[itemIndex].innerKey = `${item.value}-${itemIndex}`;\n\t\t\t});\n\t\t}else{\n\t\t\titems.push({\n\t\t\t\tvalue: null,\n\t\t\t\tlabel: null,\n\t\t\t\tinnerKey:this.props.id\n\t\t\t});\n\t\t}\n\n\t\treturn items;\n\n\t}\n\n\t/**\n\t * Options for type chooser\n\t *\n\t * @return {*[]}\n\t */\n\tlistTypeOptions(){\n\t\treturn [\n\t\t\t{\n\t\t\t\tvalue: 'fields',\n\t\t\t\tlabel: '%',\n\t\t\t\tariaLabel: 'Select from field values'\n\t\t\t},\n\t\t\t{\n\t\t\t\tvalue: 'system',\n\t\t\t\tlabel: '{}',\n\t\t\t\tariaLabel: 'Select from system values'\n\t\t\t},\n\t\t];\n\t}\n\n\n\n\t/**\n\t * Render MagicFieldGroup component\n\t * @return {*}\n\t */\n\trender() {\n\t\treturn (\n\t\t\t\n\t\t\t\t\n\t\t\t\t{this.props.message.message &&\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t{this.state.isOpen &&\n\t\t\t\t\t\n\t\t\t\t}\n\n\t\t\t\t\n\t\t\t\n\t\t);\n\t}\n}\n\n\n/**\n * Prop definitions for MagicFieldGroup component\n */\nMagicFieldGroup.propTypes = magicGroupPropTypes;\n\n/**\n * Default property values for MagicFieldGroup component\n *\n * @type {{}}\n */\nMagicFieldGroup.defaultProps = {\n\tdefaultList: 'fields',\n\tisOpen: false,\n\tmessage: {\n\t\terror: false,\n\t\tmessage: ''\n\t},\n\ttype: 'magic'\n};\n\n/**\n * The names of classes used for HTML elements in MagicFieldGroup component\n * @type {{fieldWrapper: string, input: string, option: string}}\n */\nMagicFieldGroup.classNames = {\n\tfieldWrapper: 'caldera-magic-select-group',\n\tinput: 'caldera-magic-input',\n\toption: 'caldera-magic-option'\n};", + "static": true, + "longname": "/Users/josh/caldera-js/components/src/components/fields/magic-select/MagicFieldGroup.js", + "access": "public", + "description": null, + "lineNumber": 1 + }, + { + "__docId__": 96, + "kind": "class", + "name": "MagicFieldGroup", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js", + "static": true, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "access": "public", + "export": true, + "importPath": "@caldera-labs/components/src/components/fields/magic-select/MagicFieldGroup.js", + "importStyle": "{MagicFieldGroup}", + "description": "Encapsulates a complete Magic Select field group including label and the type chooser and the input", + "lineNumber": 15, + "interface": false, + "extends": [ + "react~React.PureComponent" + ] + }, + { + "__docId__": 97, + "kind": "constructor", + "name": "constructor", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#constructor", + "access": "public", + "description": "Create a MagicFieldGroup component", + "lineNumber": 22, + "params": [ + { + "nullable": null, + "types": [ + "Object" + ], + "spread": false, + "optional": false, + "name": "props", + "description": "" + } + ] + }, + { + "__docId__": 98, + "kind": "member", + "name": "state", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#state", + "access": "public", + "description": null, + "lineNumber": 24, + "undocument": true, + "type": { + "types": [ + "{\"currentListType\": *, \"isOpen\": *}" + ] + } + }, + { + "__docId__": 108, + "kind": "method", + "name": "onChange", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onChange", + "access": "public", + "description": "Handle direct change events", + "lineNumber": 43, + "params": [ + { + "nullable": null, + "types": [ + "String", + "number" + ], + "spread": false, + "optional": false, + "name": "newValue", + "description": "" + } + ], + "return": null + }, + { + "__docId__": 109, + "kind": "method", + "name": "onInputFocus", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onInputFocus", + "access": "public", + "description": "Handle when the field gets focus", + "lineNumber": 50, + "params": [], + "return": null + }, + { + "__docId__": 110, + "kind": "method", + "name": "onInputBlur", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onInputBlur", + "access": "public", + "description": "Handle when the field is blurred", + "lineNumber": 57, + "params": [], + "return": null + }, + { + "__docId__": 111, + "kind": "method", + "name": "onSelect", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onSelect", + "access": "public", + "description": "Handle when the option is chosen", + "lineNumber": 66, + "params": [ + { + "nullable": null, + "types": [ + "String", + "number" + ], + "spread": false, + "optional": false, + "name": "value", + "description": "" + } + ], + "return": null + }, + { + "__docId__": 112, + "kind": "method", + "name": "onChangeListType", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onChangeListType", + "access": "public", + "description": "Update list of tags to show", + "lineNumber": 75, + "params": [ + { + "nullable": null, + "types": [ + "*" + ], + "spread": false, + "optional": false, + "name": "{String}newType", + "description": "" + } + ], + "return": null + }, + { + "__docId__": 113, + "kind": "method", + "name": "renderItem", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#renderItem", + "access": "public", + "description": "Render option", + "lineNumber": 89, + "params": [ + { + "nullable": null, + "types": [ + "object" + ], + "spread": false, + "optional": false, + "name": "item", + "description": "" + }, + { + "nullable": null, + "types": [ + "bool" + ], + "spread": false, + "optional": false, + "name": "isHighlighted", + "description": "" + } + ], + "return": { + "nullable": null, + "types": [ + "*" + ], + "spread": false, + "description": "" + } + }, + { + "__docId__": 114, + "kind": "method", + "name": "items", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#items", + "access": "public", + "description": "Create the list of items", + "lineNumber": 98, + "return": { + "nullable": null, + "types": [ + "Array" + ], + "spread": false, + "description": "" + }, + "params": [] + }, + { + "__docId__": 115, + "kind": "method", + "name": "listTypeOptions", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#listTypeOptions", + "access": "public", + "description": "Options for type chooser", + "lineNumber": 135, + "return": { + "nullable": null, + "types": [ + "*[]" + ], + "spread": false, + "description": "" + }, + "params": [] + }, + { + "__docId__": 116, + "kind": "method", + "name": "render", + "memberof": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#render", + "access": "public", + "description": "Render MagicFieldGroup component", + "lineNumber": 156, + "return": { + "nullable": null, + "types": [ + "*" + ], + "spread": false, + "description": "" + }, + "params": [] + }, + { + "__docId__": 117, + "kind": "file", + "name": "src/components/fields/magic-select/MagicItem.js", + "content": "import React from 'react';\nimport {\n\toptionShape\n} from '../propTypes';\nimport classNames from 'classnames';\nimport PropTypes from 'prop-types';\n\n/**\n * Create magic item for option of magic selects\n *\n * This can not be a functional component\n * https://github.com/reactjs/react-autocomplete/pull/293#issuecomment-371617758\n *\n *\n * @param {Object} props\n * @return {*}\n * @constructor\n */\nexport class MagicItem extends React.PureComponent {\n\n\t/**\n\t * Render magic item components\n\t */\n\trender() {\n\t\treturn React.createElement(\n\t\t\tthis.props.elementType,\n\t\t\t{\n\t\t\t\tstyle: {background: this.props.isHighlighted ? this.props.highlightColor : this.props.notHighlighterColor},\n\t\t\t\tclassName: classNames(this.props.className, 'magic-input-option'),\n\t\t\t\tonClick: this.props.onClick\n\t\t\t},\n\t\t\t[\n\t\t\t\tReact.createElement(\n\t\t\t\t\tthis.props.innerElementType,\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: `left--${this.props.innerKey}`,\n\t\t\t\t\t\tclassName: classNames('magic-item-value', 'magic-item-left')\n\t\t\t\t\t},\n\t\t\t\t\tthis.props.item.value\n\t\t\t\t),\n\t\t\t\tReact.createElement(\n\t\t\t\t\tthis.props.innerElementType,\n\t\t\t\t\t{\n\t\t\t\t\t\tkey: `right--${this.props.innerKey}`,\n\t\t\t\t\t\tclassName: classNames('magic-item-label', 'magic-item-right')\n\t\t\t\t\t},\n\t\t\t\t\tthis.props.item.label\n\t\t\t\t)\n\t\t\t]\n\t\t);\n\t}\n}\n\n/**\n * Prop definition for allowed element types\n * @type {shim}\n */\nconst elementTypesProp = PropTypes.oneOf(['div', 'span']);\n/**\n * Prop definitions for MagicItem component\n *\n * @type {{item: shim, isHighlighted: shim, className: shim, highlightColor: shim, notHighlighterColor: shim}}\n */\nMagicItem.propTypes = {\n\telementType: elementTypesProp,\n\tinnerElementType: elementTypesProp,\n\titem: PropTypes.shape(optionShape),\n\tisHighlighted: PropTypes.bool,\n\tclassName: PropTypes.string,\n\thighlightColor: PropTypes.string,\n\tnotHighlighterColor: PropTypes.string,\n\tinnerKey: PropTypes.string.isRequired,\n\tonClick: PropTypes.func\n};\n\n/**\n * Default props for the MagicItem component\n *\n * @type {{isHighlighted: boolean, highlightColor: string, notHighlightedColor: string}}\n */\nMagicItem.defaultProps = {\n\telementType: 'div',\n\tinnerElementType: 'span',\n\tisHighlighted: false,\n\thighlightColor: 'lightgray',\n\tnotHighlightedColor: 'white',\n};", + "static": true, + "longname": "/Users/josh/caldera-js/components/src/components/fields/magic-select/MagicItem.js", + "access": "public", + "description": null, + "lineNumber": 1 + }, + { + "__docId__": 118, + "kind": "class", + "name": "MagicItem", + "memberof": "src/components/fields/magic-select/MagicItem.js", + "static": true, + "longname": "src/components/fields/magic-select/MagicItem.js~MagicItem", + "access": "public", + "export": true, + "importPath": "@caldera-labs/components/src/components/fields/magic-select/MagicItem.js", + "importStyle": "{MagicItem}", + "description": "Create magic item for option of magic selects\n\nThis can not be a functional component\nhttps://github.com/reactjs/react-autocomplete/pull/293#issuecomment-371617758", + "lineNumber": 19, + "unknown": [ + { + "tagName": "@constructor", + "tagValue": "" + } + ], + "params": [ + { + "nullable": null, + "types": [ + "Object" + ], + "spread": false, + "optional": false, + "name": "props", + "description": "" + } + ], + "return": { + "nullable": null, + "types": [ + "*" + ], + "spread": false, + "description": "" + }, + "interface": false, + "extends": [ + "react~React.PureComponent" + ] + }, + { + "__docId__": 119, + "kind": "method", + "name": "render", + "memberof": "src/components/fields/magic-select/MagicItem.js~MagicItem", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicItem.js~MagicItem#render", + "access": "public", + "description": "Render magic item components", + "lineNumber": 24, + "params": [], + "return": { + "types": [ + "*" + ] + } + }, + { + "__docId__": 120, + "kind": "variable", + "name": "elementTypesProp", + "memberof": "src/components/fields/magic-select/MagicItem.js", + "static": true, + "longname": "src/components/fields/magic-select/MagicItem.js~elementTypesProp", + "access": "public", + "export": false, + "importPath": "@caldera-labs/components/src/components/fields/magic-select/MagicItem.js", + "importStyle": null, + "description": "Prop definition for allowed element types", + "lineNumber": 58, + "type": { + "nullable": null, + "types": [ + "shim" + ], + "spread": false, + "description": null + }, + "ignore": true + }, + { + "__docId__": 121, "kind": "file", - "name": "src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js", - "content": "import {addOrRemoveFromArray} from '../util';\n\n/**\n * Change handler for a checkbox that is a part of a group\n * @param {Object} option Option that is being changed. Shape: `{value:String|number,label:String}`,\n * @param {Array|string|number} values Current values\n * @param {Function} onValueChange Function to call with updated value\n */\nexport const fieldsetCheckboxHandler = (option, values, onValueChange) => {\n\tif (!Array.isArray(values)) {\n\t\tif ('string' === typeof values || 'number' === typeof values) {\n\t\t\tvalues = [values];\n\t\t} else {\n\t\t\tvalues = [];\n\n\t\t}\n\t}\n\tvalues = addOrRemoveFromArray(option.value, values);\n\tonValueChange(values);\n};", + "name": "src/components/fields/magic-select/MagicSelect.js", + "content": "import React from 'react';\nimport {\n\tonValueChangePropType,\n\toptionsShapeProp,\n\tvaluePropType\n} from '../propTypes';\nimport Autocomplete from 'react-autocomplete';\nimport PropTypes from 'prop-types';\nimport {MagicItem} from './MagicItem';\nimport {MagicFieldGroup} from './MagicFieldGroup';\nimport classNames from 'classnames';\n\n\n/**\n * Encapsulates a complete Magic Select field\n */\nexport class MagicSelect extends React.PureComponent {\n\n\t/**\n\t * Create a MagicSelect component\n\t *\n\t * @param {Object} props\n\t */\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.onChange = this.onChange.bind(this);\n\t\tthis.onChange = this.onChange.bind(this);\n\t\tthis.onSelect = this.onSelect.bind(this);\n\t\tthis.onInputFocus = this.onInputFocus.bind(this);\n\t\tthis.renderItem = this.renderItem.bind(this);\n\t\tthis.onInputBlur = this.onInputBlur.bind(this);\n\t}\n\n\t/**\n\t * Handle direct change events\n\t *\n\t * @param {Event} event\n\t */\n\tonChange(event) {\n\t\tthis.props.onValueChange(event.target.value);\n\t}\n\n\t/**\n\t * Handle when the field gets focus\n\t */\n\tonInputFocus() {\n\t\tif( 'function' === typeof this.props.onFocus ){\n\t\t\tthis.props.onFocus();\n\t\t}\n\t}\n\n\t/**\n\t * Handle when the field is blurred\n\t */\n\tonInputBlur() {\n\t\tif( 'function' === typeof this.props.onBlur ){\n\t\t\tthis.props.onBlur();\n\t\t}\n\t}\n\n\n\t/**\n\t * Handle when the option is chosen\n\t * @param {String|number} value\n\t */\n\tonSelect(value) {\n\t\tthis.props.onValueChange(value);\n\t}\n\n\n\t/**\n\t * Render option\n\t *\n\t * @param {object} item\n\t * @param {bool} isHighlighted\n\t * @return {*}\n\t */\n\trenderItem(item, isHighlighted){\n\t\treturn ;\n\t}\n\n\n\t/**\n\t * Render MagicSelect component\n\t * @return {*}\n\t */\n\trender() {\n\t\treturn (\n\t\t\t item.value}\n\t\t\t\titems={this.props.options}\n\t\t\t\tinputProps={{\n\t\t\t\t\tid: this.props.id,\n\t\t\t\t\tvalue: this.props.value,\n\t\t\t\t\tclassName:classNames(\n\t\t\t\t\t\tMagicFieldGroup.classNames.input,\n\t\t\t\t\t\t`${MagicFieldGroup.classNames.input}-${this.props.id}`,\n\t\t\t\t\t\tthis.props.className\n\t\t\t\t\t),\n\t\t\t\t\tonFocus: this.onInputFocus,\n\t\t\t\t\tonBlur:this.onInputBlur,\n\t\t\t\t\tonClick:this.onChange\n\t\t\t\t}}\n\t\t\t\trenderItem={this.renderItem}\n\t\t\t\tvalue={this.props.value}\n\t\t\t\tonChange={this.onChange}\n\t\t\t\topen={this.props.isOpen}\n\t\t\t\tselectOnBlur={true}\n\t\t\t\tonSelect={this.onSelect}\n\t\t\t/>\n\n\t\t);\n\t}\n}\n\n\n/**\n * Prop definitions for MagicSelect component\n */\nMagicSelect.propTypes = {\n\tid: PropTypes.string.isRequired,\n\toptions: optionsShapeProp,\n\tisRequired: PropTypes.bool,\n\thelp: PropTypes.string,\n\tvalue: valuePropType,\n\tonValueChange: onValueChangePropType,\n\tdisabled: PropTypes.bool,\n\tisOpen: PropTypes.bool,\n\tonBlur: PropTypes.func,\n\tonFocus: PropTypes.func,\n\tclassName: PropTypes.string\n};\n\n/**\n * Default property values for MagicSelect component\n *\n * @type {{}}\n */\nMagicSelect.defaultProps = {\n\tdefaultList: 'fields',\n\tisOpen: false,\n\toptions:[]\n};", "static": true, - "longname": "/Users/josh/caldera-js/components/src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js", + "longname": "/Users/josh/caldera-js/components/src/components/fields/magic-select/MagicSelect.js", "access": "public", "description": null, "lineNumber": 1 }, { - "__docId__": 87, - "kind": "function", - "name": "fieldsetCheckboxHandler", - "memberof": "src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js", - "generator": false, - "async": false, + "__docId__": 122, + "kind": "class", + "name": "MagicSelect", + "memberof": "src/components/fields/magic-select/MagicSelect.js", "static": true, - "longname": "src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js~fieldsetCheckboxHandler", + "longname": "src/components/fields/magic-select/MagicSelect.js~MagicSelect", "access": "public", "export": true, - "importPath": "@caldera-labs/components/src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js", - "importStyle": "{fieldsetCheckboxHandler}", - "description": "Change handler for a checkbox that is a part of a group", - "lineNumber": 9, + "importPath": "@caldera-labs/components/src/components/fields/magic-select/MagicSelect.js", + "importStyle": "{MagicSelect}", + "description": "Encapsulates a complete Magic Select field", + "lineNumber": 17, + "interface": false, + "extends": [ + "react~React.PureComponent" + ] + }, + { + "__docId__": 123, + "kind": "constructor", + "name": "constructor", + "memberof": "src/components/fields/magic-select/MagicSelect.js~MagicSelect", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicSelect.js~MagicSelect#constructor", + "access": "public", + "description": "Create a MagicSelect component", + "lineNumber": 24, "params": [ { "nullable": null, @@ -1425,90 +2056,125 @@ ], "spread": false, "optional": false, - "name": "option", - "description": "Option that is being changed. Shape: `{value:String|number,label:String}`," - }, - { - "nullable": null, - "types": [ - "Array", - "string", - "number" - ], - "spread": false, - "optional": false, - "name": "values", - "description": "Current values" - }, + "name": "props", + "description": "" + } + ] + }, + { + "__docId__": 130, + "kind": "method", + "name": "onChange", + "memberof": "src/components/fields/magic-select/MagicSelect.js~MagicSelect", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicSelect.js~MagicSelect#onChange", + "access": "public", + "description": "Handle direct change events", + "lineNumber": 39, + "params": [ { "nullable": null, "types": [ - "Function" + "Event" ], "spread": false, "optional": false, - "name": "onValueChange", - "description": "Function to call with updated value" + "name": "event", + "description": "" } ], "return": null }, { - "__docId__": 88, - "kind": "file", - "name": "src/components/fields/index.js", - "content": "/*eslint no-undef: \"error\"*/\n/*eslint-env node*/\nimport {FieldGroup} from './FieldGroup';\nimport {SelectFieldFancy} from './select/SelectFieldFancy';\nimport {Input} from './input/Input';\n\nmodule.exports = {\n\tFieldGroup,\n\tSelectField: SelectFieldFancy,\n\tInput\n};", - "static": true, - "longname": "/Users/josh/caldera-js/components/src/components/fields/index.js", + "__docId__": 131, + "kind": "method", + "name": "onInputFocus", + "memberof": "src/components/fields/magic-select/MagicSelect.js~MagicSelect", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicSelect.js~MagicSelect#onInputFocus", "access": "public", - "description": null, - "lineNumber": 1 + "description": "Handle when the field gets focus", + "lineNumber": 46, + "params": [], + "return": null }, { - "__docId__": 89, - "kind": "file", - "name": "src/components/fields/input/Input.js", - "content": "import React from 'react';\nimport {fieldPropTypes} from '../propTypes';\nimport classNames from 'classnames';\nimport {RenderGroup} from '../../RenderGroup';\n/**\n * Input component for any HTML5 input type\n *\n * @param {Object} props\n * @returns {*}\n * @constructor\n */\nexport const Input = (props) => {\n\t/**\n\t * Dispatches value of input when it changes\n\t * @param event\n\t * @return {*}\n\t */\n\tfunction changeHandler(event){\n\t\treturn props.onValueChange(event.target.value);\n\t}\n\n\t/**\n\t * Dispatches value when checkbox is checked\n\t * @return {*}\n\t */\n\tfunction checkboxChangeHandler() {\n\t\treturn props.onValueChange(! props.value);\n\t}\n\n\n\t/**\n\t * Get the className prop for inputs\n\t *\n\t * @return {String}\n\t */\n\tfunction inputClassName() {\n\t\treturn classNames(\n\t\t\tprops.fieldClassName,\n\t\t\tRenderGroup.classNames.input\n\t\t);\n\t}\n\n\tif( 'checkbox' === props.inputType ){\n\t\treturn (\n\t\t\t\n\t\t);\n\t}\n\n\treturn (\n\t\t\n\t);\n\n};\n\n/**\n * Prop definitions for Input components\n */\nInput.propTypes = fieldPropTypes;\n\n/**\n * Default props for Input Component\n *\n * @type {{ariaDescribedbyAttr: string, isRequired: boolean, inputType: string}}\n */\nInput.defaultProps = {\n\tariaDescribedbyAttr: '',\n\tisRequired: false,\n\tinputType: 'text'\n};", - "static": true, - "longname": "/Users/josh/caldera-js/components/src/components/fields/input/Input.js", + "__docId__": 132, + "kind": "method", + "name": "onInputBlur", + "memberof": "src/components/fields/magic-select/MagicSelect.js~MagicSelect", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicSelect.js~MagicSelect#onInputBlur", "access": "public", - "description": null, - "lineNumber": 1 + "description": "Handle when the field is blurred", + "lineNumber": 55, + "params": [], + "return": null }, { - "__docId__": 90, - "kind": "function", - "name": "Input", - "memberof": "src/components/fields/input/Input.js", + "__docId__": 133, + "kind": "method", + "name": "onSelect", + "memberof": "src/components/fields/magic-select/MagicSelect.js~MagicSelect", "generator": false, "async": false, - "static": true, - "longname": "src/components/fields/input/Input.js~Input", + "static": false, + "longname": "src/components/fields/magic-select/MagicSelect.js~MagicSelect#onSelect", "access": "public", - "export": true, - "importPath": "@caldera-labs/components/src/components/fields/input/Input.js", - "importStyle": "{Input}", - "description": "Input component for any HTML5 input type", - "lineNumber": 12, - "unknown": [ - { - "tagName": "@returns", - "tagValue": "{*}" - }, + "description": "Handle when the option is chosen", + "lineNumber": 66, + "params": [ { - "tagName": "@constructor", - "tagValue": "" + "nullable": null, + "types": [ + "String", + "number" + ], + "spread": false, + "optional": false, + "name": "value", + "description": "" } ], + "return": null + }, + { + "__docId__": 134, + "kind": "method", + "name": "renderItem", + "memberof": "src/components/fields/magic-select/MagicSelect.js~MagicSelect", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicSelect.js~MagicSelect#renderItem", + "access": "public", + "description": "Render option", + "lineNumber": 78, "params": [ { "nullable": null, "types": [ - "Object" + "object" ], "spread": false, "optional": false, - "name": "props", + "name": "item", + "description": "" + }, + { + "nullable": null, + "types": [ + "bool" + ], + "spread": false, + "optional": false, + "name": "isHighlighted", "description": "" } ], @@ -1522,7 +2188,29 @@ } }, { - "__docId__": 91, + "__docId__": 135, + "kind": "method", + "name": "render", + "memberof": "src/components/fields/magic-select/MagicSelect.js~MagicSelect", + "generator": false, + "async": false, + "static": false, + "longname": "src/components/fields/magic-select/MagicSelect.js~MagicSelect#render", + "access": "public", + "description": "Render MagicSelect component", + "lineNumber": 87, + "return": { + "nullable": null, + "types": [ + "*" + ], + "spread": false, + "description": "" + }, + "params": [] + }, + { + "__docId__": 136, "kind": "file", "name": "src/components/fields/messages/Message.js", "content": "import React from 'react';\nimport PropTypes from 'prop-types';\nimport {messagePropShape} from './messagePropTypes';\nimport classNames from 'classnames';\n\n/**\n * The class that message components always wrap messages in\n * @type {string}\n */\nexport const MESSAGE_CLASS = 'caldera-components-message';\n\n/**\n * Prop for showing a validation message\n *\n * Use or for errors and such\n *\n * @param {object} props\n * @return {*}\n * @constructor\n */\nexport const Message = (props) => {\n\tconst {message,error} = props.message;\n\tif( !message || '' === message ){\n\t\treturn ;\n\t}\n\treturn(\n\t\t\n\t\t\t{message}\n\t\t\n\t);\n};\n\n/**\n * Prop types for Message components\n *\n * @type {{className: shim, message}}\n */\nMessage.propTypes = {\n\tclassName: PropTypes.string,\n\tmessage: messagePropShape,\n};\n\n", @@ -1533,7 +2221,7 @@ "lineNumber": 1 }, { - "__docId__": 92, + "__docId__": 137, "kind": "variable", "name": "MESSAGE_CLASS", "memberof": "src/components/fields/messages/Message.js", @@ -1555,7 +2243,7 @@ } }, { - "__docId__": 93, + "__docId__": 138, "kind": "function", "name": "Message", "memberof": "src/components/fields/messages/Message.js", @@ -1597,7 +2285,7 @@ } }, { - "__docId__": 94, + "__docId__": 139, "kind": "file", "name": "src/components/fields/messages/messageObjectFactory.js", "content": "import {toBoolean} from '../util';\n\n/**\n * Prepares messages object in fieldConfigs\n *\n * @param {Object} message\n * @param {Boolean} error\n * @return {{message: *, error: boolean}}\n */\nexport const messageObjectFactory = ({message,error}) => {\n\tif( 'string' !== typeof message ){\n\t\tmessage = '';\n\t}\n\treturn{\n\t\tmessage: message,\n\t\terror: toBoolean(error)\n\t};\n};", @@ -1608,7 +2296,7 @@ "lineNumber": 1 }, { - "__docId__": 95, + "__docId__": 140, "kind": "function", "name": "messageObjectFactory", "memberof": "src/components/fields/messages/messageObjectFactory.js", @@ -1654,7 +2342,7 @@ } }, { - "__docId__": 96, + "__docId__": 141, "kind": "file", "name": "src/components/fields/messages/messagePropTypes.js", "content": "import PropTypes from 'prop-types';\n\n/**\n * The shape of the message object passed to Message compoent\n *\n * @type {shim}\n */\nexport const messagePropShape = PropTypes.shape(\n\t{\n\t\terror: PropTypes.bool,\n\t\ttext: PropTypes.string\n\t}\n);", @@ -1665,7 +2353,7 @@ "lineNumber": 1 }, { - "__docId__": 97, + "__docId__": 142, "kind": "variable", "name": "messagePropShape", "memberof": "src/components/fields/messages/messagePropTypes.js", @@ -1687,10 +2375,10 @@ } }, { - "__docId__": 98, + "__docId__": 143, "kind": "file", "name": "src/components/fields/propTypes.js", - "content": "import PropTypes from 'prop-types';\nimport {messagePropShape} from './messages/messagePropTypes';\n\n/**\n * PropType for the field value used in multiple components\n *\n * @type {shim}\n */\nexport const valuePropType = PropTypes.oneOfType([\n\tPropTypes.string,\n\tPropTypes.number,\n\tPropTypes.array,\n\tPropTypes.bool\n]);\n\n/**\n * PropType for the field value change event used in multiple components\n *\n * @type {shim}\n */\nexport const onValueChangePropType = PropTypes.func.isRequired;\n\n/**\n * Proptypes for Input component\n * @type {shim}\n */\nexport const inputTypeProp = PropTypes.string;\n\n/**\n * PropTypes for field groups\n *\n * @type {{id: (boolean|shim|*), isBlockInput: shim, isRequired: shim, help: shim, label: (boolean|shim|*), type: shim, value: shim, onValueChange: (boolean|shim|*), inputType: shim}}\n */\nexport const fieldGroupPropTypes = {\n\tid: PropTypes.string.isRequired,\n\tisBlockInput: PropTypes.bool,\n\tisRequired: PropTypes.bool,\n\thelp: PropTypes.string,\n\tlabel: PropTypes.string.isRequired,\n\ttype: PropTypes.oneOf(['input','select', 'fieldset']),\n\tvalue: valuePropType,\n\tonValueChange: onValueChangePropType,\n\toptions: PropTypes.array,\n\tinputType:inputTypeProp,\n\tdisabled: PropTypes.bool,\n\tmessage: messagePropShape,\n\tonBlur: PropTypes.func,\n\tonFocus: PropTypes.func\n};\n\n/**\n * PropTypes for the InnerField component\n *\n * @type {{id: (boolean|shim|*), fieldClassName: (boolean|shim|*), help: shim, value: shim, onValueChange: (boolean|shim|*), inputType: shim}}\n */\nexport const fieldInnerPropTypes = {\n\tid: PropTypes.string.isRequired,\n\tfieldClassName: PropTypes.string.isRequired,\n\thelp: PropTypes.string,\n\tvalue: valuePropType,\n\tonValueChange: onValueChangePropType,\n\tinputType: inputTypeProp,\n\tariaDescribedbyAttr: PropTypes.string,\n\tonBlur: PropTypes.func,\n\tonFocus: PropTypes.func\n};\n\nexport const fieldPropTypes = fieldInnerPropTypes;\n", + "content": "import PropTypes from 'prop-types';\nimport {messagePropShape} from './messages/messagePropTypes';\n\n/**\n * PropType for the field value used in multiple components\n *\n * @type {shim}\n */\nexport const valuePropType = PropTypes.oneOfType([\n\tPropTypes.string,\n\tPropTypes.number,\n\tPropTypes.array,\n\tPropTypes.bool\n]);\n\n/**\n * PropType for the field value change event used in multiple components\n *\n * @type {shim}\n */\nexport const onValueChangePropType = PropTypes.func.isRequired;\n\n/**\n * Proptypes for Input component\n * @type {shim}\n */\nexport const inputTypeProp = PropTypes.string;\n\n/**\n * PropTypes for field groups\n *\n * @type {{id: (boolean|shim|*), isBlockInput: shim, isRequired: shim, help: shim, label: (boolean|shim|*), type: shim, value: shim, onValueChange: (boolean|shim|*), inputType: shim}}\n */\nexport const fieldGroupPropTypes = {\n\tid: PropTypes.string.isRequired,\n\tisBlockInput: PropTypes.bool,\n\tisRequired: PropTypes.bool,\n\thelp: PropTypes.string,\n\tlabel: PropTypes.string.isRequired,\n\ttype: PropTypes.oneOf(['input', 'select', 'fieldset', 'magic']),\n\tvalue: valuePropType,\n\tonValueChange: onValueChangePropType,\n\toptions: PropTypes.array,\n\tinputType: inputTypeProp,\n\tdisabled: PropTypes.bool,\n\tmessage: messagePropShape,\n\tonBlur: PropTypes.func,\n\tonFocus: PropTypes.func\n};\n\n/**\n * PropTypes for the InnerField component\n *\n * @type {{id: (boolean|shim|*), fieldClassName: (boolean|shim|*), help: shim, value: shim, onValueChange: (boolean|shim|*), inputType: shim}}\n */\nexport const fieldInnerPropTypes = {\n\tid: PropTypes.string.isRequired,\n\tfieldClassName: PropTypes.string.isRequired,\n\thelp: PropTypes.string,\n\tvalue: valuePropType,\n\tonValueChange: onValueChangePropType,\n\tinputType: inputTypeProp,\n\tariaDescribedbyAttr: PropTypes.string,\n\tonBlur: PropTypes.func,\n\tonFocus: PropTypes.func\n};\n\nexport const fieldPropTypes = fieldInnerPropTypes;\n\n/**\n * The shape of one option for a select field\n *\n * @type {{label: shim, value: shim}}\n */\nexport const optionShape = {\n\tlabel: PropTypes.string,\n\tvalue: PropTypes.oneOfType([\n\t\tPropTypes.string,\n\t\tPropTypes.number,\n\t])\n};\n\n/**\n * Shape of options prop for select fields\n *\n * @type {shim}\n */\nexport const optionsShapeProp = PropTypes.arrayOf(\n\tPropTypes.shape(optionShape)\n);\n\nexport const magicGroupPropTypes = {\n\t...fieldGroupPropTypes,\n\tfieldsList: optionsShapeProp,\n\tsystemTagsList: optionsShapeProp,\n\tdefaultList: PropTypes.string,\n\tisOpen: PropTypes.bool,\n\ttype: PropTypes.string\n};", "static": true, "longname": "/Users/josh/caldera-js/components/src/components/fields/propTypes.js", "access": "public", @@ -1698,7 +2386,7 @@ "lineNumber": 1 }, { - "__docId__": 99, + "__docId__": 144, "kind": "variable", "name": "valuePropType", "memberof": "src/components/fields/propTypes.js", @@ -1720,7 +2408,7 @@ } }, { - "__docId__": 100, + "__docId__": 145, "kind": "variable", "name": "onValueChangePropType", "memberof": "src/components/fields/propTypes.js", @@ -1742,7 +2430,7 @@ } }, { - "__docId__": 101, + "__docId__": 146, "kind": "variable", "name": "inputTypeProp", "memberof": "src/components/fields/propTypes.js", @@ -1764,7 +2452,7 @@ } }, { - "__docId__": 102, + "__docId__": 147, "kind": "variable", "name": "fieldGroupPropTypes", "memberof": "src/components/fields/propTypes.js", @@ -1786,7 +2474,7 @@ } }, { - "__docId__": 103, + "__docId__": 148, "kind": "variable", "name": "fieldInnerPropTypes", "memberof": "src/components/fields/propTypes.js", @@ -1808,7 +2496,7 @@ } }, { - "__docId__": 104, + "__docId__": 149, "kind": "variable", "name": "fieldPropTypes", "memberof": "src/components/fields/propTypes.js", @@ -1828,10 +2516,74 @@ } }, { - "__docId__": 105, + "__docId__": 150, + "kind": "variable", + "name": "optionShape", + "memberof": "src/components/fields/propTypes.js", + "static": true, + "longname": "src/components/fields/propTypes.js~optionShape", + "access": "public", + "export": true, + "importPath": "@caldera-labs/components/src/components/fields/propTypes.js", + "importStyle": "{optionShape}", + "description": "The shape of one option for a select field", + "lineNumber": 75, + "type": { + "nullable": null, + "types": [ + "{label: shim, value: shim}" + ], + "spread": false, + "description": null + } + }, + { + "__docId__": 151, + "kind": "variable", + "name": "optionsShapeProp", + "memberof": "src/components/fields/propTypes.js", + "static": true, + "longname": "src/components/fields/propTypes.js~optionsShapeProp", + "access": "public", + "export": true, + "importPath": "@caldera-labs/components/src/components/fields/propTypes.js", + "importStyle": "{optionsShapeProp}", + "description": "Shape of options prop for select fields", + "lineNumber": 88, + "type": { + "nullable": null, + "types": [ + "shim" + ], + "spread": false, + "description": null + } + }, + { + "__docId__": 152, + "kind": "variable", + "name": "magicGroupPropTypes", + "memberof": "src/components/fields/propTypes.js", + "static": true, + "longname": "src/components/fields/propTypes.js~magicGroupPropTypes", + "access": "public", + "export": true, + "importPath": "@caldera-labs/components/src/components/fields/propTypes.js", + "importStyle": "{magicGroupPropTypes}", + "description": null, + "lineNumber": 92, + "undocument": true, + "type": { + "types": [ + "{...fieldGroupPropTypes: Object, \"fieldsList\": *, \"systemTagsList\": *, \"defaultList\": *, \"isOpen\": *, \"type\": *}" + ] + } + }, + { + "__docId__": 153, "kind": "file", "name": "src/components/fields/select/SelectField.js", - "content": "import React from 'react';\nimport {fieldPropTypes} from '../propTypes';\nimport classNames from 'classnames';\nimport {RenderGroup} from '../../RenderGroup';\n\n/**\n * Creates a select field\n *\n * @param {Object} props\n * @returns {*}\n * @constructor\n */\nexport const SelectField = (props) => {\n\t/**\n\t * Dispatches new value(s) to parent\n\t *\n\t * @param selection\n\t * @returns {*}\n\t */\n\tfunction changeHandler(selection) {\n\t\treturn props.onValueChange(selection);\n\t}\n\n\t/**\n\t * Get the className prop for the select element\n\t *\n\t * @return {String}\n\t */\n\tfunction selectClassNames() {\n\t\treturn classNames(\n\t\t\tprops.fieldClassName,\n\t\t\tRenderGroup.classNames.input\n\t\t);\n\t}\n\n\treturn (\n\t\t\n\t\t\t{props.options\n\t\t\t\t.map((item,i) => {\n\t\t\t\t\tconst key = 'string' === typeof item.value ? item.value : i;\n\t\t\t\t\treturn(\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{item.label}\n\t\t\t\t\t\t\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t}\n\t\t\n\n\n\n\t);\n};\n\n/**\n * Prop definition for select fields\n *\n * @type {{}}\n */\nSelectField.propTypes = {\n\t...fieldPropTypes,\n};\n\n/**\n * Default props for select fields\n *\n * @type {{options: Array}}\n */\nSelectField.defaultProps = {\n\toptions: []\n};", + "content": "import React from 'react';\nimport {fieldPropTypes} from '../propTypes';\nimport classNames from 'classnames';\nimport {RenderGroup} from '../../RenderGroup';\nimport {optionsShapeProp} from '../propTypes';\n\n/**\n * Creates a select field\n *\n * @param {Object} props\n * @returns {*}\n * @constructor\n */\nexport const SelectField = (props) => {\n\t/**\n\t * Dispatches new value(s) to parent\n\t *\n\t * @param selection\n\t * @returns {*}\n\t */\n\tfunction changeHandler(selection) {\n\t\treturn props.onValueChange(selection);\n\t}\n\n\t/**\n\t * Get the className prop for the select element\n\t *\n\t * @return {String}\n\t */\n\tfunction selectClassNames() {\n\t\treturn classNames(\n\t\t\tprops.fieldClassName,\n\t\t\tRenderGroup.classNames.input\n\t\t);\n\t}\n\n\treturn (\n\t\t\n\t\t\t{props.options\n\t\t\t\t.map((item,i) => {\n\t\t\t\t\tconst key = 'string' === typeof item.value ? item.value : i;\n\t\t\t\t\treturn(\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{item.label}\n\t\t\t\t\t\t\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t}\n\t\t\n\n\n\n\t);\n};\n\n/**\n * Prop definition for select fields\n *\n * @type {{}}\n */\nSelectField.propTypes = {\n\t...fieldPropTypes,\n\toptions: optionsShapeProp\n\n};\n\n/**\n * Default props for select fields\n *\n * @type {{options: Array}}\n */\nSelectField.defaultProps = {\n\toptions: []\n};", "static": true, "longname": "/Users/josh/caldera-js/components/src/components/fields/select/SelectField.js", "access": "public", @@ -1839,7 +2591,7 @@ "lineNumber": 1 }, { - "__docId__": 106, + "__docId__": 154, "kind": "function", "name": "SelectField", "memberof": "src/components/fields/select/SelectField.js", @@ -1852,7 +2604,7 @@ "importPath": "@caldera-labs/components/src/components/fields/select/SelectField.js", "importStyle": "{SelectField}", "description": "Creates a select field", - "lineNumber": 13, + "lineNumber": 14, "unknown": [ { "tagName": "@returns", @@ -1885,7 +2637,7 @@ } }, { - "__docId__": 107, + "__docId__": 155, "kind": "file", "name": "src/components/fields/select/SelectFieldFancy.js", "content": "import React from 'react';\nimport Downshift from 'downshift';\nimport PropTypes from 'prop-types';\nimport {fieldPropTypes} from '../propTypes';\n\n/**\n * Creates a select field\n *\n * Wraps [downshift](https://github.com/paypal/downshift)\n *\n * @param {Object} props\n * @returns {*}\n * @constructor\n */\nexport const SelectFieldFancy = (props) => {\n\t/**\n\t * Dispatches new value(s) to parent\n\t *\n\t * @param selection\n\t * @returns {*}\n\t */\n\tfunction changeHandler(selection) {\n\t\treturn props.onValueChange(selection);\n\t}\n\n\treturn (\n\t\t (item ? item.value : '')}\n\t\t\tdefaultIsOpen={props.isOpen}\n\t\t>\n\t\t\t{({\n\t\t\t\tgetInputProps,\n\t\t\t\tgetItemProps,\n\t\t\t\tisOpen,\n\t\t\t\tinputValue,\n\t\t\t\thighlightedIndex,\n\t\t\t\tselectedItem,\n\t\t\t}) => (\n\t\t\t\t
    \n\t\t\t\t\t\n\t\t\t\t\t{isOpen ? (\n\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t{props.options\n\t\t\t\t\t\t\t\t.filter(item => !inputValue || item.value.includes(inputValue))\n\t\t\t\t\t\t\t\t.map((item, index) => (\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t{item.value}\n\t\t\t\t\t\t\t\t\t
    \n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t
    \n\t\t\t\t\t) : null}\n\t\t\t\t\n\t\t\t)}\n\t\t\n\t);\n};\n\n\nSelectFieldFancy.propTypes = {\n\t...fieldPropTypes,\n\tisOpen: PropTypes.bool,\n};", @@ -1896,7 +2648,7 @@ "lineNumber": 1 }, { - "__docId__": 108, + "__docId__": 156, "kind": "function", "name": "SelectFieldFancy", "memberof": "src/components/fields/select/SelectFieldFancy.js", @@ -1942,7 +2694,7 @@ } }, { - "__docId__": 109, + "__docId__": 157, "kind": "file", "name": "src/components/fields/util.js", "content": "/**\n * Create the aria-describedby attribute or id attribute for the describing element\n *\n * @param {String} id Id attribute of input being described\n * @param {String} help Optional. Help text. If empty return is null.\n * @returns {String|null}\n */\nexport const ariaDescribedbyAttr = (id, help = '') => {\n\tlet ariaDescribedby = null;\n\tif (help.length) {\n\t\tariaDescribedby = `${id}-description`;\n\t}\n\treturn ariaDescribedby;\n};\n\n\n/**\n * Get HTML5 input types that are valid\n * @returns {string[]}\n */\nexport function getHtmlInputTypes() {\n\treturn [\n\t\t'text',\n\t\t'email',\n\t\t'number',\n\t\t'date',\n\t\t'datetime',\n\t\t'password',\n\t\t'submit',\n\t\t'reset',\n\t\t'checkbox',\n\t\t'hidden'\n\t];\n}\n\n/**\n * Checks if a given input type is an acceptable HTML5 input type\n *\n * @param {String} type\n * @returns {boolean}\n */\nexport function isValidHtml5type(type) {\n\treturn getHtmlInputTypes().includes(type);\n}\n\n\n/**\n * Remove a value from an array if present, if not present, add it\n *\n * @param {String|number} value Value to add or remove\n * @param {Array} array Array to mutate\n * @return {*}\n */\nexport const addOrRemoveFromArray = (value,array) => {\n\tconst index = array.indexOf(value);\n\tif (index !== -1){\n\t\tarray.splice(index, 1);\n\t}else{\n\t\tarray.push( value );\n\t}\n\treturn array;\n};\n\n/**\n * Cast a boolean or boolean like to a true or false\n *\n * @param Mixed} value Value to cast\n * @return {boolean}\n */\nexport const toBoolean =(value) => {\n\tswitch(value){\n\tcase true:\n\tcase 'true':\n\tcase 1:\n\tcase '1':\n\tcase 'on':\n\tcase 'yes':\n\t\treturn true;\n\tdefault:\n\t\treturn false;\n\t}\n};", @@ -1953,7 +2705,7 @@ "lineNumber": 1 }, { - "__docId__": 110, + "__docId__": 158, "kind": "function", "name": "ariaDescribedbyAttr", "memberof": "src/components/fields/util.js", @@ -2006,7 +2758,7 @@ } }, { - "__docId__": 111, + "__docId__": 159, "kind": "function", "name": "getHtmlInputTypes", "memberof": "src/components/fields/util.js", @@ -2037,7 +2789,7 @@ "params": [] }, { - "__docId__": 112, + "__docId__": 160, "kind": "function", "name": "isValidHtml5type", "memberof": "src/components/fields/util.js", @@ -2079,7 +2831,7 @@ } }, { - "__docId__": 113, + "__docId__": 161, "kind": "function", "name": "addOrRemoveFromArray", "memberof": "src/components/fields/util.js", @@ -2126,7 +2878,7 @@ } }, { - "__docId__": 114, + "__docId__": 162, "kind": "function", "name": "toBoolean", "memberof": "src/components/fields/util.js", @@ -2162,7 +2914,7 @@ } }, { - "__docId__": 115, + "__docId__": 163, "kind": "file", "name": "src/components/index.js", "content": "/*eslint no-undef: \"error\"*/\n/*eslint-env node*/\nimport * as fields from './fields/index';\nimport * as factories from './fields/factories/index';\nimport {RenderGroup} from './RenderGroup';\nimport conditionals from './conditional-logic/index';\nimport validation from './validation/index';\n\n/**\n * Caldera components\n *\n * @type {{RenderGroup: RenderGroup, fields: *, factories: *, conditionals: {checkConfigFieldConditionals, checkConfigFieldsConditionals, reduceConfigFieldsToValues}}}\n */\nmodule.exports = {\n\tRenderGroup,\n\tfields,\n\tfactories,\n\tconditionals,\n\tvalidation\n};", @@ -2173,7 +2925,7 @@ "lineNumber": 1 }, { - "__docId__": 116, + "__docId__": 164, "kind": "file", "name": "src/components/validation/addAutomaticValidators.js", "content": "import getValidatorsFromConfigField from './getValidatorsFromConfigField';\nimport isValidOrEmpty from './isValidOrEmpty';\nimport {findFieldValueInFieldValues} from './util';\nimport isValid from './isValid';\n/**\n * Helper function to curry validator functions\n *\n * Validators expect 1 value, not an object of values, this function solves that.\n *\n * @param {String} fieldId Field to look for\n * @param {Function} validator Validator function\n * @return {function(*=): *}\n */\nfunction curryValidator(fieldId, validator) {\n\treturn (fieldValues) => {\n\t\treturn validator(findFieldValueInFieldValues(fieldId, fieldValues));\n\t};\n}\n\n/**\n * Create validation function based on type and required\n *\n * @param {Object} configField Field to create validations for\n * @param {Array} validators Current array of validators\n * @param {string} validationType Type of validators to add.\n * @return {Array}\n */\nfunction addValidatorsForType(configField, validators, validationType) {\n\tif (configField.isRequired) {\n\t\tvalidators.push(\n\t\t\tcurryValidator(\n\t\t\t\tconfigField.ID, isValid[validationType]\n\t\t\t)\n\t\t);\n\t} else {\n\t\tvalidators.push(\n\t\t\tcurryValidator(\n\t\t\t\tconfigField.ID, isValidOrEmpty[validationType]\n\t\t\t)\n\t\t);\n\t}\n\n\treturn validators;\n}\n\n/**\n * Adds sensible, automatic validation to fields -- if no validators have been added yet.\n *\n * @param {Object} configField\n * @return {*}\n */\nexport const addAutomaticValidators = (configField) => {\n\tlet validators = getValidatorsFromConfigField(configField);\n\tif (0 !== validators.length) {\n\t\treturn configField;\n\t}\n\n\tswitch (configField.type) {\n\tcase 'input':\n\t\tif( [\n\t\t\t'email',\n\t\t\t'url',\n\t\t\t'date',\n\t\t\t'number',\n\t\t].includes( configField.inputType ) ){\n\t\t\tvalidators = addValidatorsForType(configField, validators, configField.inputType);\n\t\t}else if( 'text' === configField.inputType){\n\t\t\tvalidators = addValidatorsForType(configField, validators, 'string');\n\n\t\t}\n\n\t\telse{\n\t\t\tvalidators = addValidatorsForType( configField, validators, 'anything' );\n\t\t}\n\n\t\tbreak;\n\tcase 'select':\n\t\tvalidators = addValidatorsForType( configField, validators, 'stringOrNumber' );\n\t\tbreak;\n\t}\n\n\n\treturn {\n\t\t...configField,\n\t\tvalidators\n\t};\n\n};", @@ -2184,7 +2936,7 @@ "lineNumber": 1 }, { - "__docId__": 117, + "__docId__": 165, "kind": "function", "name": "curryValidator", "memberof": "src/components/validation/addAutomaticValidators.js", @@ -2231,7 +2983,7 @@ "ignore": true }, { - "__docId__": 118, + "__docId__": 166, "kind": "function", "name": "addValidatorsForType", "memberof": "src/components/validation/addAutomaticValidators.js", @@ -2288,7 +3040,7 @@ "ignore": true }, { - "__docId__": 119, + "__docId__": 167, "kind": "function", "name": "addAutomaticValidators", "memberof": "src/components/validation/addAutomaticValidators.js", @@ -2324,7 +3076,7 @@ } }, { - "__docId__": 120, + "__docId__": 168, "kind": "file", "name": "src/components/validation/checkValidatorsForConfigField.js", "content": "/**\n * Check the validators for one field\n *\n * @param {Object} configField The field to check the validator of.\n * @param {Object} fieldValues Optional. Data to pass to validator rule callbacks\n * @return {boolean}\n */\nimport getValidatorsFromConfigField from './getValidatorsFromConfigField';\n\nexport default function checkValidatorsForConfigField(configField,fieldValues) {\n\tif( ! getValidatorsFromConfigField(configField).length){\n\t\treturn true;\n\t}\n\tlet allRulesPassed = true;\n\tconfigField.validators.forEach(conditional => {\n\t\tif ('function' === typeof conditional && false === conditional.call(null, fieldValues)) {\n\t\t\tallRulesPassed = false;\n\t\t\treturn false;\n\t\t}\n\t});\n\n\treturn allRulesPassed;\n}\n\n\n", @@ -2335,7 +3087,7 @@ "lineNumber": 1 }, { - "__docId__": 121, + "__docId__": 169, "kind": "function", "name": "checkValidatorsForConfigField", "memberof": "src/components/validation/checkValidatorsForConfigField.js", @@ -2371,7 +3123,7 @@ } }, { - "__docId__": 122, + "__docId__": 170, "kind": "file", "name": "src/components/validation/checkValidatorsForConfigFields.js", "content": "import checkValidatorsForConfigField from './checkValidatorsForConfigField';\nimport getValidatorsFromConfigField from './getValidatorsFromConfigField';\n\n/**\n * Check validators for a collection of configFields\n *\n * Returns false if any validators fail.\n * Returns true if no validators fail, or there are no validators.\n *\n * @param {Array} configFields The fields to check the validators of.\n * @param {Object} fieldValues Optional. Data to pass to validators rules' callbacks\n * @return {Object}\n */\nexport default function checkValidatorsForConfigFields(configFields,fieldValues) {\n\tlet results = {};\n\tObject.values( configFields ).forEach(configField => {\n\t\tconst rules = getValidatorsFromConfigField(configField);\n\t\tlet thisResult = true;\n\t\tif( rules.length ){\n\t\t\tthisResult = checkValidatorsForConfigField(configField,fieldValues);\n\n\t\t}\n\t\tresults[configField.ID] = thisResult;\n\t});\n\treturn results;\n}\n\n", @@ -2382,7 +3134,7 @@ "lineNumber": 1 }, { - "__docId__": 123, + "__docId__": 171, "kind": "function", "name": "checkValidatorsForConfigFields", "memberof": "src/components/validation/checkValidatorsForConfigFields.js", @@ -2428,7 +3180,7 @@ } }, { - "__docId__": 124, + "__docId__": 172, "kind": "file", "name": "src/components/validation/getValidatorsFromConfigField.js", "content": "/**\n * Find the array of validators for a configField\n *\n * @param {Object} configField The config field to search in\n * @return {Array} Array of validators or empty array if non found\n */\nexport default function getValidatorsFromConfigField(configField) {\n\tif (!configField.hasOwnProperty('validators') || !Array.isArray(configField.validators)) {\n\t\treturn [];\n\t}\n\n\treturn configField.validators;\n}\n\n", @@ -2439,7 +3191,7 @@ "lineNumber": 1 }, { - "__docId__": 125, + "__docId__": 173, "kind": "function", "name": "getValidatorsFromConfigField", "memberof": "src/components/validation/getValidatorsFromConfigField.js", @@ -2475,7 +3227,7 @@ } }, { - "__docId__": 126, + "__docId__": 174, "kind": "file", "name": "src/components/validation/index.js", "content": "/*eslint no-undef: \"error\"*/\n/*eslint-env node*/\nimport getValidatorsFromConfigField from './getValidatorsFromConfigField';\nimport checkValidatorsForConfigFields from './checkValidatorsForConfigFields';\nimport checkValidatorsForConfigField from './checkValidatorsForConfigField';\nimport {addAutomaticValidators} from './addAutomaticValidators';\nimport messageStrings from './messageStrings';\nimport isEmpty from './isEmpty';\nimport isValid from './isValid';\nimport isValidOrEmpty from './isValidOrEmpty';\n//Usage here indicates that this is a cross-cutting concern, & it totally is\n//Move to shared module?\nimport {reduceConfigFieldsToValues} from '../conditional-logic/util';\n\n/**\n * One export for validation system\n */\nexport default {\n\tgetValidatorsFromConfigField,\n\tcheckValidatorsForConfigFields,\n\tcheckValidatorsForConfigField,\n\treduceConfigFieldsToValues,\n\taddAutomaticValidators,\n\tisEmpty,\n\tisValid,\n\tisValidOrEmpty,\n\tmessageStrings\n};", @@ -2486,7 +3238,7 @@ "lineNumber": 1 }, { - "__docId__": 127, + "__docId__": 175, "kind": "file", "name": "src/components/validation/isEmpty.js", "content": "/**\n * CalderaValidators that check if a value is empty or not\n */\nexport default {\n\t/**\n\t * Check if different types (numbers, strings, objects, arrays or Maps) are empty\n\t *\n\t * @param {String|number|Array|object|Map} value\n\t * @return {boolean}\n\t */\n\tanything(value){\n\t\tif( Array.isArray(value)){\n\t\t\treturn this.array(value);\n\t\t}\n\t\tif( value instanceof Map ){\n\t\t\treturn this.map(value);\n\t\t}\n\t\tswitch (typeof value){\n\t\tcase 'object':\n\t\t\treturn this.object(value);\n\t\tcase 'string':\n\t\t\treturn this.string(value);\n\t\tdefault:\n\t\t\treturn false;//\n\t\t}\n\t\treturn false;\n\t},\n\t/**\n\t * Check if value is an empty object\n\t *\n\t * @param {Object} value The object to check\n\t * @return {boolean}\n\t */\n\tobject(value){\n\t\tfor(let key in value) {\n\t\t\tif(value.hasOwnProperty(key))\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\t/**\n\t * Check if value is an empty array\n\t *\n\t * @param {Array} value Array to check\n\t * @return {boolean}\n\t */\n\tarray(value){\n\t\treturn 0 === value.length;\n\t},\n\t/**\n\t * Check if value is not an empty string\n\t *\n\t * @param {String} value String to check\n\t * @return {boolean}\n\t */\n\tstring(value){\n\t\treturn !value;\n\t},\n\t/**\n\t * Check if value is not an empty map\n\t *\n\t * @param {Map} value The Map to check\n\t * @return {boolean}\n\t */\n\tmap( value ){\n\t\treturn 0 === value.size;\n\t}\n};", @@ -2497,7 +3249,7 @@ "lineNumber": 1 }, { - "__docId__": 128, + "__docId__": 176, "kind": "file", "name": "src/components/validation/isValid.js", "content": "import {isEmail,isUrl, isDate} from '@helpdotcom/is';\nimport isEmpty from './isEmpty';\n\n/**\n * CalderaValidators for common types of validation needed\n *\n * Empty values are not valid.\n * Ue isValidOrEmpty instead if you want empty values to pass\n */\nexport default {\n\t/**\n\t * Check if a given value is an email address\n\t *\n\t * @param {String} value Value to check\n\t * @return {boolean}\n\t */\n\temail(value){\n\t\treturn isEmail(value);\n\t},\n\t/**\n\t * Check if given value is a non-empty string\n\t *\n\t * @param {String} value Value to check\n\t */\n\tstring(value){\n\t\treturn 'string' === typeof value && ! isEmpty.string(value);\n\t},\n\t/**\n\t * Check if given value is a string\n\t *\n\t * @param {String} value Value to check\n\t */\n\tstringOrNumber(value){\n\t\tif( null !== value ){\n\t\t\treturn this.string(value) || this.number(value);\n\t\t}\n\t\treturn false;\n\t},\n\t/**\n\t * Check if a given value is a valid url\n\t *\n\t * @param {String} value Value to check\n\t * @return {boolean}\n\t */\n\turl(value){\n\t\treturn isUrl(value);\n\t},\n\t/**\n\t * Check if a given value is an date.\n\t *\n\t * Considers Date objects and strings conforming to ISO 8601 standard to be valid.\n\t *\n\t * @param {String|Date} value Value to check\n\t * @return {boolean}\n\t */\n\tdate(value){\n\t\treturn isDate(value);\n\t},\n\t/**\n\t * Check if a given value is numeric\n\t *\n\t * @param {String|number} value Value to check\n\t * @return {boolean}\n\t */\n\tnumber(value){\n\t\tif( '' === value ){\n\t\t\treturn false;\n\t\t}\n\t\tif( Array.isArray( value ) ){\n\t\t\treturn false;\n\t\t}\n\t\treturn ! isNaN(value);\n\t}\n};", @@ -2508,7 +3260,7 @@ "lineNumber": 1 }, { - "__docId__": 129, + "__docId__": 177, "kind": "file", "name": "src/components/validation/isValidOrEmpty.js", "content": "import isEmpty from './isEmpty';\nimport isValid from './isValid';\n/**\n * Validators by type that consider an empty value valid.\n *\n * Combines the isEmpty and isValid validations\n */\nexport default {\n\t/**\n\t * Check if a given value is an email address or empty\n\t *\n\t * @param {String} value Value to check\n\t * @return {boolean}\n\t */\n\temail(value){\n\t\treturn isEmpty.anything( value ) || isValid.email(value);\n\t},\n\t/**\n\t * Check if given value is a string or empty\n\t *\n\t * @param {String} value Value to check\n\t */\n\tstring(value){\n\t\treturn isEmpty.anything( value ) || isValid.string(value);\n\t},\n\t/**\n\t * Check if given value is a string or number empty\n\t *\n\t * @param {String} value Value to check\n\t */\n\tstringOrNumber(value){\n\t\treturn isEmpty.anything(value) || isValid.stringOrNumber(value);\n\t},\n\t/**\n\t * Check if a given value is a valid url or empty\n\t *\n\t * @param {String} value Value to check\n\t * @return {boolean}\n\t */\n\turl(value){\n\t\treturn isEmpty.anything( value ) || isValid.url(value);\n\t},\n\t/**\n\t * Check if a given value is an date.\n\t *\n\t * Considers Date objects and strings conforming to ISO 8601 standard to be valid.\n\t *\n\t * @param {String|Date} value Value to check or empty\n\t * @return {boolean}\n\t */\n\tdate(value){\n\t\treturn isEmpty.anything( value ) || isValid.date(value);\n\t},\n\t/**\n\t * Check if a given value is numeric\n\t *\n\t * @param {String|number} value Value to check or empty\n\t * @return {boolean}\n\t */\n\tnumber(value){\n\t\treturn isEmpty.anything( value ) || isValid.number(value);\n\t}\n};", @@ -2519,7 +3271,7 @@ "lineNumber": 1 }, { - "__docId__": 130, + "__docId__": 178, "kind": "file", "name": "src/components/validation/messageStrings.js", "content": "import strings from './strings';\n\n/**\n * Get translation strings by language\n *\n * @param {String|Object} lang Language code or an object containing properly formatted strings to search in.\n * @param {String} defaultLang Optional. Language code to use for missing strings.\n *\n * @return {Object}\n */\nexport const getMessageStrings = (lang, defaultLang = 'en') => {\n\tif ('string' === typeof lang) {\n\t\tif (strings.hasOwnProperty(lang)) {\n\t\t\treturn strings[lang];\n\t\t} else {\n\t\t\treturn getMessageStrings(defaultLang);\n\t\t}\n\t}\n\tif ('object' === typeof lang) {\n\t\treturn Object.assign(getMessageStrings(defaultLang, 'en'), lang);\n\t}\n};\n\n/**\n * Get message for an invalid field, by field type\n *\n * @param {String} inputType Type of input to get invalid message for.\n * @param {String|Object} lang Language code or an object containing properly formatted strings to search in.\n * @param {String} defaultLang Optional. Language code to use for missing strings.\n * @return {String}\n */\nexport const getMessageStringByType = (inputType, lang, defaultLang = 'en') => {\n\tconst strings = getMessageStrings(lang, defaultLang);\n\tif (strings.type.hasOwnProperty(inputType)) {\n\t\treturn strings.type[inputType];\n\t}\n\treturn strings.defaultMessage;\n};\n\n/**\n * Get the required message, by language.\n *\n * @param {String|Object} lang Language code or an object containing properly formatted strings to search in.\n * @param {String} defaultLang Optional. Language code to use for missing strings.\n * @return {String}\n */\nexport const getRequiredMessage = (lang, defaultLang = 'en') => {\n\treturn getMessageStrings(lang, defaultLang).required;\n\n};\n\n/**\n * Message string utilities for validation\n */\nexport default {\n\tgetMessageStrings,\n\tgetMessageStringByType,\n\tgetRequiredMessage\n};", @@ -2530,7 +3282,7 @@ "lineNumber": 1 }, { - "__docId__": 131, + "__docId__": 179, "kind": "function", "name": "getMessageStrings", "memberof": "src/components/validation/messageStrings.js", @@ -2577,7 +3329,7 @@ } }, { - "__docId__": 132, + "__docId__": 180, "kind": "function", "name": "getMessageStringByType", "memberof": "src/components/validation/messageStrings.js", @@ -2634,7 +3386,7 @@ } }, { - "__docId__": 133, + "__docId__": 181, "kind": "function", "name": "getRequiredMessage", "memberof": "src/components/validation/messageStrings.js", @@ -2681,7 +3433,7 @@ } }, { - "__docId__": 134, + "__docId__": 182, "kind": "file", "name": "src/components/validation/strings.js", "content": "/**\n * Translation strings for Caldera Components\n * Copied from Parsley (License: MIT)\n * https://github.com/guillaumepotier/Parsley.js/blob/master/dist/i18n/\n *\n */\nexport default {\n\ten: {\n\t\tdefaultMessage: 'This value seems to be invalid.',\n\t\ttype: {\n\t\t\temail: 'This value should be a valid email.',\n\t\t\turl: 'This value should be a valid url.',\n\t\t\tnumber: 'This value should be a valid number.',\n\t\t\tinteger: 'This value should be a valid integer.',\n\t\t\tdigits: 'This value should be digits.',\n\t\t\talphanum: 'This value should be alphanumeric.'\n\t\t},\n\t\tnotblank: 'This value should not be blank.',\n\t\trequired: 'This value is required.',\n\t\tpattern: 'This value seems to be invalid.',\n\t\tmin: 'This value should be greater than or equal to %s.',\n\t\tmax: 'This value should be lower than or equal to %s.',\n\t\trange: 'This value should be between %s and %s.',\n\t\tminlength: 'This value is too short. It should have %s characters or more.',\n\t\tmaxlength: 'This value is too long. It should have %s characters or fewer.',\n\t\tlength: 'This value length is invalid. It should be between %s and %s characters long.',\n\t\tmincheck: 'You must select at least %s choices.',\n\t\tmaxcheck: 'You must select %s choices or fewer.',\n\t\tcheck: 'You must select between %s and %s choices.',\n\t\tequalto: 'This value should be the same.'\n\t},\n\tes:{\n\t\tdefaultMessage: 'Este valor parece ser inválido.',\n\t\ttype: {\n\t\t\temail: 'Este valor debe ser un correo válido.',\n\t\t\turl: 'Este valor debe ser una URL válida.',\n\t\t\tnumber: 'Este valor debe ser un número válido.',\n\t\t\tinteger: 'Este valor debe ser un número válido.',\n\t\t\tdigits: 'Este valor debe ser un dígito válido.',\n\t\t\talphanum: 'Este valor debe ser alfanumérico.'\n\t\t},\n\t\tnotblank: 'Este valor no debe estar en blanco.',\n\t\trequired: 'Este valor es requerido.',\n\t\tpattern: 'Este valor es incorrecto.',\n\t\tmin: 'Este valor no debe ser menor que %s.',\n\t\tmax: 'Este valor no debe ser mayor que %s.',\n\t\trange: 'Este valor debe estar entre %s y %s.',\n\t\tminlength: 'Este valor es muy corto. La longitud mínima es de %s caracteres.',\n\t\tmaxlength: 'Este valor es muy largo. La longitud máxima es de %s caracteres.',\n\t\tlength: 'La longitud de este valor debe estar entre %s y %s caracteres.',\n\t\tmincheck: 'Debe seleccionar al menos %s opciones.',\n\t\tmaxcheck: 'Debe seleccionar %s opciones o menos.',\n\t\tcheck: 'Debe seleccionar entre %s y %s opciones.',\n\t\tequalto: 'Este valor debe ser idéntico.'\n\t}\n};", @@ -2692,7 +3444,7 @@ "lineNumber": 1 }, { - "__docId__": 135, + "__docId__": 183, "kind": "file", "name": "src/components/validation/util.js", "content": "\n\n/**\n * Find the value of a field by ID\n *\n * Returns null if field is not in collection\n *\n * @param {String} fieldId Field to look for\n * @param {Object} fieldValues Values to look for field in\n * @return {String|Array|boolean|number|null}\n */\nexport const findFieldValueInFieldValues = (fieldId, fieldValues) => {\n\tif (fieldValues.hasOwnProperty(fieldId)) {\n\t\treturn fieldValues[fieldId];\n\t}\n\n\treturn null;\n};\n\n\n\n\n\n", @@ -2703,7 +3455,7 @@ "lineNumber": 1 }, { - "__docId__": 136, + "__docId__": 184, "kind": "function", "name": "findFieldValueInFieldValues", "memberof": "src/components/validation/util.js", @@ -2753,7 +3505,7 @@ } }, { - "__docId__": 137, + "__docId__": 185, "kind": "file", "name": "src/index.js", "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport registerServiceWorker from './registerServiceWorker';\n\nReactDOM.render(, document.getElementById('root'));\nregisterServiceWorker();\n", @@ -2764,7 +3516,7 @@ "lineNumber": 1 }, { - "__docId__": 138, + "__docId__": 186, "kind": "file", "name": "src/registerServiceWorker.js", "content": "// In production, we register a service worker to serve assets from local cache.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on the \"N+1\" visit to a page, since previously\n// cached resources are updated in the background.\n\n// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.\n// This link also includes instructions on opting out of this behavior.\n\nconst isLocalhost = Boolean(\n\twindow.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n \t/^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport default function register() {\n\tif (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n\t\t// The URL constructor is available in all browsers that support SW.\n\t\tconst publicUrl = new URL(process.env.PUBLIC_URL, window.location);\n\t\tif (publicUrl.origin !== window.location.origin) {\n\t\t\t// Our service worker won't work if PUBLIC_URL is on a different origin\n\t\t\t// from what our page is served on. This might happen if a CDN is used to\n\t\t\t// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374\n\t\t\treturn;\n\t\t}\n\n\t\twindow.addEventListener('load', () => {\n\t\t\tconst swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n\t\t\tif (isLocalhost) {\n\t\t\t\t// This is running on localhost. Lets check if a service worker still exists or not.\n\t\t\t\tcheckValidServiceWorker(swUrl);\n\t\t\t} else {\n\t\t\t\t// Is not local host. Just register service worker\n\t\t\t\tregisterValidSW(swUrl);\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction registerValidSW(swUrl) {\n\tnavigator.serviceWorker\n\t\t.register(swUrl)\n\t\t.then(registration => {\n\t\t\tregistration.onupdatefound = () => {\n\t\t\t\tconst installingWorker = registration.installing;\n\t\t\t\tinstallingWorker.onstatechange = () => {\n\t\t\t\t\tif (installingWorker.state === 'installed') {\n\t\t\t\t\t\tif (navigator.serviceWorker.controller) {\n\t\t\t\t\t\t\t// At this point, the old content will have been purged and\n\t\t\t\t\t\t\t// the fresh content will have been added to the cache.\n\t\t\t\t\t\t\t// It's the perfect time to display a \"New content is\n\t\t\t\t\t\t\t// available; please refresh.\" message in your web app.\n\t\t\t\t\t\t\tconsole.log('New content is available; please refresh.');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// At this point, everything has been precached.\n\t\t\t\t\t\t\t// It's the perfect time to display a\n\t\t\t\t\t\t\t// \"Content is cached for offline use.\" message.\n\t\t\t\t\t\t\tconsole.log('Content is cached for offline use.');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\t\t})\n\t\t.catch(error => {\n\t\t\tconsole.error('Error during service worker registration:', error);\n\t\t});\n}\n\nfunction checkValidServiceWorker(swUrl) {\n\t// Check if the service worker can be found. If it can't reload the page.\n\tfetch(swUrl)\n\t\t.then(response => {\n\t\t\t// Ensure service worker exists, and that we really are getting a JS file.\n\t\t\tif (\n\t\t\t\tresponse.status === 404 ||\n response.headers.get('content-type').indexOf('javascript') === -1\n\t\t\t) {\n\t\t\t\t// No service worker found. Probably a different app. Reload the page.\n\t\t\t\tnavigator.serviceWorker.ready.then(registration => {\n\t\t\t\t\tregistration.unregister().then(() => {\n\t\t\t\t\t\twindow.location.reload();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Service worker found. Proceed as normal.\n\t\t\t\tregisterValidSW(swUrl);\n\t\t\t}\n\t\t})\n\t\t.catch(() => {\n\t\t\tconsole.log(\n\t\t\t\t'No internet connection found. App is running in offline mode.'\n\t\t\t);\n\t\t});\n}\n\nexport function unregister() {\n\tif ('serviceWorker' in navigator) {\n\t\tnavigator.serviceWorker.ready.then(registration => {\n\t\t\tregistration.unregister();\n\t\t});\n\t}\n}\n", @@ -2775,7 +3527,7 @@ "lineNumber": 1 }, { - "__docId__": 139, + "__docId__": 187, "kind": "variable", "name": "isLocalhost", "memberof": "src/registerServiceWorker.js", @@ -2796,7 +3548,7 @@ "ignore": true }, { - "__docId__": 140, + "__docId__": 188, "kind": "function", "name": "register", "memberof": "src/registerServiceWorker.js", @@ -2815,7 +3567,7 @@ "return": null }, { - "__docId__": 141, + "__docId__": 189, "kind": "function", "name": "registerValidSW", "memberof": "src/registerServiceWorker.js", @@ -2842,7 +3594,7 @@ "ignore": true }, { - "__docId__": 142, + "__docId__": 190, "kind": "function", "name": "checkValidServiceWorker", "memberof": "src/registerServiceWorker.js", @@ -2869,7 +3621,7 @@ "ignore": true }, { - "__docId__": 143, + "__docId__": 191, "kind": "function", "name": "unregister", "memberof": "src/registerServiceWorker.js", @@ -2897,7 +3649,7 @@ }, { "kind": "packageJSON", - "content": "{\n \"name\": \"@caldera-labs/components\",\n \"version\": \"1.3.0\",\n \"dependencies\": {\n \"@helpdotcom/is\": \"^3.0.4\",\n \"classnames\": \"^2.2.6\",\n \"downshift\": \"^1.31.16\"\n },\n \"license\": \"GPL-2.0\",\n \"scripts\": {\n \"start\": \"react-wp-scripts start\",\n \"example:build\": \"react-wp-script build\",\n \"test\": \"react-scripts test --env=jsdom\",\n \"test:once\": \"CI=true react-scripts test --env=jsdom\",\n \"test:coverage\": \"npm test -- --coverage\",\n \"coveralls\": \"cat ./coverage/lcov.info | node node_modules/.bin/coveralls\",\n \"eject\": \"react-wp-script eject\",\n \"lint\": \"eslint src/components/**\",\n \"document\": \"./node_modules/.bin/esdoc\",\n \"build\": \"npm run build:pre && npm run build:compile && npm run build:post\",\n \"build:pre\": \"npm run test:once\",\n \"build:compile\": \"./node_modules/.bin/babel -d dist src/components\",\n \"build:post\": \"npm run document\",\n \"prepublish\": \"npm run build\",\n \"release\": \"npm run release:patch\",\n \"release:minor\": \"npm version minor -m \\\"version %s\\\" && npm publish\",\n \"release:major\": \"npm version major -m \\\"version %s\\\" && npm publish\",\n \"release:patch\": \"npm version patch -m \\\"version %s\\\" && npm publish\"\n },\n \"main\": \"./dist/index.js\",\n \"files\": [\n \"dist\"\n ],\n \"devDependencies\": {\n \"babel-cli\": \"^6.26.0\",\n \"babel-preset-env\": \"^1.7.0\",\n \"babel-preset-react\": \"^6.24.1\",\n \"babel-preset-stage-3\": \"^6.24.1\",\n \"enzyme\": \"^3.3.0\",\n \"enzyme-adapter-react-16\": \"^1.1.1\",\n \"esdoc\": \"^1.1.0\",\n \"esdoc-ecmascript-proposal-plugin\": \"^1.0.0\",\n \"esdoc-jsx-plugin\": \"^1.0.0\",\n \"esdoc-standard-plugin\": \"^1.0.0\",\n \"eslint-plugin-jest\": \"^21.17.0\",\n \"eslint-plugin-react\": \"^7.9.1\",\n \"prop-types\": \"^15.6.1\",\n \"react\": \"^16.4.1\",\n \"react-dom\": \"^16.4.1\",\n \"react-test-renderer\": \"^16.4.1\",\n \"react-wp-scripts\": \"0.2.0\"\n },\n \"jest\": {\n \"collectCoverageFrom\": [\n \"src/components/**/*.js\",\n \"!src/components/index.js\",\n \"!src/components/fields/index.js\"\n ]\n }\n}\n", + "content": "{\n \"name\": \"@caldera-labs/components\",\n \"version\": \"1.3.1\",\n \"dependencies\": {\n \"@helpdotcom/is\": \"^3.0.4\",\n \"classnames\": \"^2.2.6\",\n \"downshift\": \"^1.31.16\",\n \"react-autocomplete\": \"^1.8.1\"\n },\n \"license\": \"GPL-2.0\",\n \"scripts\": {\n \"start\": \"react-wp-scripts start\",\n \"example:build\": \"react-wp-script build\",\n \"test\": \"react-scripts test --env=jsdom\",\n \"test:once\": \"CI=true react-scripts test --env=jsdom\",\n \"test:coverage\": \"npm test -- --coverage\",\n \"coveralls\": \"cat ./coverage/lcov.info | node node_modules/.bin/coveralls\",\n \"eject\": \"react-wp-script eject\",\n \"lint\": \"eslint src/components/**\",\n \"document\": \"./node_modules/.bin/esdoc\",\n \"build\": \"npm run build:pre && npm run build:compile && npm run build:post\",\n \"build:pre\": \"npm run test:once\",\n \"build:compile\": \"./node_modules/.bin/babel -d dist src/components\",\n \"build:post\": \"npm run document\",\n \"prepublish\": \"npm run build\",\n \"release\": \"npm run release:patch\",\n \"release:minor\": \"npm version minor -m \\\"version %s\\\" && npm publish\",\n \"release:major\": \"npm version major -m \\\"version %s\\\" && npm publish\",\n \"release:patch\": \"npm version patch -m \\\"version %s\\\" && npm publish\"\n },\n \"main\": \"./dist/index.js\",\n \"files\": [\n \"dist\"\n ],\n \"devDependencies\": {\n \"babel-cli\": \"^6.26.0\",\n \"babel-preset-env\": \"^1.7.0\",\n \"babel-preset-react\": \"^6.24.1\",\n \"babel-preset-stage-3\": \"^6.24.1\",\n \"coveralls\": \"^3.0.2\",\n \"enzyme\": \"^3.3.0\",\n \"enzyme-adapter-react-16\": \"^1.1.1\",\n \"esdoc\": \"^1.1.0\",\n \"esdoc-ecmascript-proposal-plugin\": \"^1.0.0\",\n \"esdoc-jsx-plugin\": \"^1.0.0\",\n \"esdoc-standard-plugin\": \"^1.0.0\",\n \"eslint-plugin-jest\": \"^21.17.0\",\n \"eslint-plugin-react\": \"^7.9.1\",\n \"prop-types\": \"^15.6.1\",\n \"react\": \"^16.4.1\",\n \"react-dom\": \"^16.4.1\",\n \"react-test-renderer\": \"^16.4.1\",\n \"react-wp-scripts\": \"0.2.0\"\n },\n \"jest\": {\n \"collectCoverageFrom\": [\n \"src/components/**/*.js\",\n \"!src/components/index.js\",\n \"!src/components/fields/index.js\"\n ]\n }\n}\n", "longname": "/Users/josh/caldera-js/components/package.json", "name": "package.json", "static": true, @@ -2924,7 +3676,7 @@ "kind": "manual", "longname": "/Users/josh/caldera-js/components/manual/components.md", "name": "./manual/components.md", - "content": "# Included Component\nThese components are used by the factories and follow their schema, [defined here](https://calderalabs.org/caldera-components/manual/factories.html#configfield-schema).\nIn general, use the `RenderGroup` component, do not use the low-level components. Use the factories or `RenderGroup`.\n\n## `RenderGroup`\nThe `RenderGroup` component takes an array of field configs and generates UI for them. \n\n* [Reference](https://calderalabs.org/caldera-components/class/src/components/RenderGroup.js~RenderGroup.html)\n\n### Example Of `RenderGroup` Component Usage\n\n```jsx \nconst textFieldConfig = {\n\t'id': 'cf-something-tags',\n\t'label': 'Tags',\n\t'desc': 'Comma separated list of tags.',\n\t'type': 'text',\n\t'description': false,\n\tvalue: 'Roy,Mike',\n\tonValueChange: (newValue) =>{\n\t\tconsole.log(newValue)\n\t}\n};\n\nconst hiddenFieldConfig = {\n\t'id': 'cf-something-sequence-id',\n\t'type': 'hidden',\n\t'label': 'Sequence ID',\n\t'description': false,\n\tvalue: '42',\n \tonValueChange: (newValue) =>{\n \t\tconsole.log(newValue)\n \t}\n};\n\nconst selectFieldConfig = {\n\t'id': 'cf-something-select-id',\n\t'type': 'dropdown',\n\t'label': 'Content type',\n\t'description': 'Choose content type, default is HTML',\n\toptions: [\n\t\t{\n\t\t\tlabel: 'HTML',\n\t\t\tvalue: 'html'\n\t\t},\n\t\t{\n\t\t\tlabel: 'Plain Text',\n\t\t\tvalue: 'plain'\n\t\t}\n\t],\n\tvalue: 'html',\n onValueChange: (newValue) =>{\n console.log(newValue)\n }\n};\n\nconst configFields = [\n\ttextFieldConfig,\n\thiddenFieldConfig,\n\tselectFieldConfig\n];\n\n \n```\n\n### Add onFocus Event For All Fields Of Render Group\nYou can add an onFocus event that fires when ever any field is focused. The callback function gets the config field's ID as its only parameter.\n```js\n console.log(fieldId)}\n /> \n\n```\n\n### Add onBlur Event For All Fields Of Render Group\nYou can add an `onBlur` event that fires when ever any field is blurred. The callback function gets the config field's ID as its only parameter.\n\n```js\n console.log(fieldId)}\n /> \n\n```\n\n\n## Field Groups\nIf you have to use a component, please use `FieldGroup` not its inner components.\n\n* [Reference](https://calderalabs.org/caldera-components/function/index.html#static-function-Input)\n\n### Text field that is required\n```jsx\n {\n values.one=newValue;\n }}\n/>\n\n```\n\n### Text field that is not required\n```jsx\n {\n values.two=newValue;\n }}\n/>\n```\n\n### Text field with help text\n* Adding help text automatically ads `aria-describedby`\n\n```jsx\n {\n values.three=newValue;\n }}\n/>\n```\n\n\n### Number Field\n\n```jsx\n {\n values.two=newValue;\n }}\n/>\n\n```\n## Select Fields\n* [Reference](https://calderalabs.org/caldera-components/function/index.html#static-function-SelectField)\n\n```jsx \nimport {SelectFieldFancy} from '@caldera-labs/components/src/components/fields/select/SelectFieldFancyFancy.js'\n\n {\n console.log(newValue)\n }} //Update callback\n options={[\n {\n value: '1,\n label: 'One'\n },\n {\n value: '2',\n label: 'Two'\n }\n ]}\n value={'2'} //The current value\n/>\n \n```\n\n## Fieldsets\nFor a `
    ` element containing checkboxes, pass the value `fieldset` to the `type\n\n\n```js\n//Value is an array.\nlet checkBoxValue = ['1'];\n\n\n value={checkBoxValue} //value(s)\n id={'Checkbox1'} //id attribute for
    \n onValueChange={(newValue) => {\n \t//logic of removing/adding from array is handled internally\n checkBoxValue = newValue;\n }}\n options={[\n {\n value: '1', //this value is in array so box will be checked by default\n label: 'One'// Used for this checkbox's
    ` element containing checkboxes, pass the value `fieldset` to the `type\n\n\n```js\n//Value is an array.\nlet checkBoxValue = ['1'];\n\n\n value={checkBoxValue} //value(s)\n id={'Checkbox1'} //id attribute for
    \n onValueChange={(newValue) => {\n \t//logic of removing/adding from array is handled internally\n checkBoxValue = newValue;\n }}\n options={[\n {\n value: '1', //this value is in array so box will be checked by default\n label: 'One'// Used for this checkbox's

    Example Of Re className={'cf-something-config'} />

    +

    A Magic Aut-Complete Field Selector In A RednerGroup

    const magicField = {
    +    'id': 'cf-magic-example',
    +    'type': 'magic',
    +    'label': 'Magic ID',
    +    'description': 'Select a value from list of magic tags or type a value',
    +    fieldsList: [
    +        {
    +            label: '0',
    +            value: 0
    +        },
    +        {
    +            label: '1',
    +            value: 1
    +        },
    +        {
    +            label: '3',
    +            value: 3
    +        }
    +    ],
    +    systemTagsList: [
    +        {
    +            label: '3',
    +            value: 3
    +        }
    +    ],
    +    isOpen: true,
    +    onValueChange: () => {
    +    }
    +};
    +
    +<RenderGroup configFields={[magicField]}/>
    +
    +

    Add onFocus Event For All Fields Of Render Group

    You can add an onFocus event that fires when ever any field is focused. The callback function gets the config field's ID as its only parameter.

    <RenderGroup
         configFields={[
    @@ -223,7 +263,8 @@ 

    Field Groups

    If you have to use a component, please

    -

    Text field that is required

    <FieldGroup
    +

    Text Field Groups

    If the prop type is input, the type of input is controlled by the inputType props, which by default is text. Therefore, by default input field groups have inputs with the HTML5 input type attribute of "text". Also, inputType could be "number" or "data", etc.

    +

    Text field that is required

    <FieldGroup
         id={'control-22'}
         label={'Required Text input'}
         type={'input'}
    @@ -235,7 +276,7 @@ 

    Text field that is required

    
     
    -

    Text field that is not required

    <FieldGroup
    +

    Text field that is not required

    <FieldGroup
         id={'control-23'}
         label={'Non Required Text input'}
         type={'input'}
    @@ -246,7 +287,7 @@ 

    Text field that is not required

    -

    Text field with help text

    Text Field Groups

    If the prop type is input, the type of input is controlled by the inputType props, which by default is text. Therefore, by default input field groups have inputs with the HTML5 input type attribute of "text". Also, inputType could be "number" or "data", etc.

    Text field that is required

    <FieldGroup
         id={'control-22'}
         label={'Required Text input'}
         type={'input'}
    @@ -412,7 +451,7 @@ 

    Structure of class attributes

    The }} /> -

    Text field that is not required

    <FieldGroup
    +

    Text field that is not required

    <FieldGroup
         id={'control-23'}
         label={'Non Required Text input'}
         type={'input'}
    @@ -422,7 +461,7 @@ 

    Structure of class attributes

    The values.two=newValue; }} /> -

    Text field with help text

      +

    Text field with help text

    • Adding help text automatically ads aria-describedby
    <FieldGroup
         id={'control-23'}
    @@ -435,7 +474,7 @@ 

    Structure of class attributes

    The values.three=newValue; }} /> -

    Number Field

    <FieldGroup
    +

    Number Field Group

    <FieldGroup
         id={'control-24'}
         label={'Non Required Numeric input'}
         type={'input'}
    @@ -446,10 +485,69 @@ 

    Structure of class attributes

    The values.two=newValue; }} /> + +### Select Field Groups + +Select field groups happen when you pass "select" to the `type` prop. + +Select fields take an array of options in the prop option. Options in that collection must conform the shape [defined here](https://calderalabs.org/caldera-components/docs/file/src/components/fields/propTypes.js.html#lineNumber75) + -

    Select Fields

    import {SelectFieldFancy} from '@caldera-labs/components/src/components/fields/select/SelectFieldFancyFancy.js'
    +

    let selectFieldValue = '';

    <FieldGroup + type={'select'} + label={'Basic select field'} + value={selectFieldValue} + id={'id-of-the-select-field-itself'} + onValueChange={(newValue) => { + selectFieldValue = newValue; + }} + options={[ + { + value: 1, + label: 'One' + }, + { + value: 2, + label: 'Two' + } + ]} +/>

    Magic Select Groups

    Magic select groups use MagicSelect fields, which wrap reactjs/react-autocomple to create a UI for Caldera Forms magic tags.

    These fields groups show options from two lists, one is passed in the prop fieldsList and represents the fields of the form, and the other is in systemTagsList, which represents the system values such as the current user info.

    The property isOpen controls if the auto-complete list is open.

    let magicFieldValue ='';
    +
    +<MagicFieldGroup
    +        id={'magic-5'}
    +        fieldClassName={'magic'}
    +        label={'Magic Group'}
    +        onValueChange={(newValue) => {
    +            magicFieldValue = newValue;
    +        } }
    +        fieldsList={[
    +            {
    +                label: 'Field One',
    +                value: '%fldOne%'
    +            },
    +            {
    +                label: 'Field Two',
    +                value: '%fldTwo%'
    +            },
    +            {
    +                label: 'Field Three',
    +                value: '%fldThree%'
    +            },
    +        ]}
    +        systemTagsList={[
    +            {
    +                label: 'User First Name',
    +                value: '{user:first_name}'
    +            }
    +        ]}
    +        isOpen={true}
    +        value={magicFieldValue}
    +    />
    +
    ## Select Fields
    +* [Reference](https://calderalabs.org/caldera-components/function/index.html#static-function-SelectField)
    +
    +```jsx 
    +import {SelectFieldFancy} from '@caldera-labs/components/src/components/fields/select/SelectFieldFancyFancy.js'
     
     <SelectFieldFancy
         id={'number-of-things'} //ID attribute for input
    @@ -493,6 +591,60 @@ 

    Structure of class attributes

    The } ]} /> +

    Button Group

    Button groups are select fields. One button can be selected at once.

    This is a field, not a group (like FieldGroup or MagicFieldGroup) so it does not handle its own label.

    Button groups fields take an array of options in the prop option. Options in that collection must conform the shape defined here

    Examples

    Button Group With Two Options

    <ButtonGroup
    +    onChange={(selectedValue) => {
    +        console.log(selectedValue);
    +    }}
    +    options={[
    +        {
    +            value: 1,
    +            label: 'Option One',
    +        },
    +        {
    +            value: 2,
    +            label: 'Option Two',
    +        }
    +    ]}
    +    value={1}
    +/>
    +

    Button Group With Icon

    If options have icon, the rendered markup for the button will be like this:

    <button ...><span class="fa-envelope"></span></button>
    +
    +

    That's the markup you need if font awesome is loaded on the page. In the future this component should supply font awesome or dashicons or emoji icons. For now, it does not.

    <ButtonGroup
    +    onChange={(selectedValue) => {
    +        console.log(selectedValue);
    +    }}
    +    options={[
    +        {
    +            value: 1,
    +            label: 'Option One',
    +            icon: 'fa-envelop'
    +        },
    +        {
    +            value: 2,
    +            label: 'Option Two',
    +            icon: 'fa-twitter'
    +
    +        }
    +    ]}
    +    value={1}
    +/>
    +

    Explicitly set aria-label Attribute

    By default, the visual representation fo the option is option.label. That makes sense, if you're representing the option with words. Allowing the component to use option.label for the aria-label attribute, which is its default value, I think makes sense.

    But, if the visual representation of the option is an emoji or image, then aria-label can not be an image, it has to be text that gives meaning to the image for users who can not see the image.

    <ButtonGroup
    +    onChange={(selectedValue) => {
    +        console.log(selectedValue);
    +    }}
    +    options={[
    +        {
    +            value: 'fields',
    +            label: '%',
    +            ariaLabel: 'Select from field values'
    +        },
    +        {
    +            value: 'system',
    +            label: '{}',
    +            ariaLabel: 'Select from system values'
    +        },
    +    ]}
    +/>
     

    Message component

    The Message component is used to display validation messages in a FieldGroup component. Messages have a shape defined in the messagePropShape object. This component, by design, returns nothing if props.message.message is not supplied, or is an empty string.

    An error message

    <Message
         message={{
             message:'Something bad has happened.',
    diff --git a/docs/manual/testing.html b/docs/manual/testing.html
    index feb16bc..5381f33 100644
    --- a/docs/manual/testing.html
    +++ b/docs/manual/testing.html
    @@ -55,15 +55,22 @@
         
  • Included Component
  • RenderGroup
  • Example Of RenderGroup Component Usage
  • +
  • A Magic Aut-Complete Field Selector In A RednerGroup
  • Add onFocus Event For All Fields Of Render Group
  • Add onBlur Event For All Fields Of Render Group
  • Field Groups
  • -
  • Text field that is required
  • -
  • Text field that is not required
  • -
  • Text field with help text
  • -
  • Number Field
  • -
  • Select Fields
  • +
  • Text Field Groups
  • +
  • Text field that is required
  • +
  • Text field that is not required
  • +
  • Text field with help text
  • +
  • Number Field Group
  • +
  • Magic Select Groups
  • Fieldsets
  • +
  • Button Group
  • +
  • Examples
  • +
  • Button Group With Two Options
  • +
  • Button Group With Icon
  • +
  • Explicitly set aria-label Attribute
  • Message component
  • An error message
  • A non-error message
  • diff --git a/docs/manual/validation.html b/docs/manual/validation.html index e7b73b3..a2f6d01 100644 --- a/docs/manual/validation.html +++ b/docs/manual/validation.html @@ -55,15 +55,22 @@
  • Included Component
  • RenderGroup
  • Example Of RenderGroup Component Usage
  • +
  • A Magic Aut-Complete Field Selector In A RednerGroup
  • Add onFocus Event For All Fields Of Render Group
  • Add onBlur Event For All Fields Of Render Group
  • Field Groups
  • -
  • Text field that is required
  • -
  • Text field that is not required
  • -
  • Text field with help text
  • -
  • Number Field
  • -
  • Select Fields
  • +
  • Text Field Groups
  • +
  • Text field that is required
  • +
  • Text field that is not required
  • +
  • Text field with help text
  • +
  • Number Field Group
  • +
  • Magic Select Groups
  • Fieldsets
  • +
  • Button Group
  • +
  • Examples
  • +
  • Button Group With Two Options
  • +
  • Button Group With Icon
  • +
  • Explicitly set aria-label Attribute
  • Message component
  • An error message
  • A non-error message
  • diff --git a/docs/script/search_index.js b/docs/script/search_index.js index b027535..2fa62a2 100644 --- a/docs/script/search_index.js +++ b/docs/script/search_index.js @@ -5,6 +5,12 @@ window.esdocSearchIndex = [ "App @caldera-labs/components/src/App.js", "class" ], + [ + "@caldera-labs/components/src/components/fields/button-group/buttongroup.js~buttongroup", + "function/index.html#static-function-ButtonGroup", + "ButtonGroup @caldera-labs/components/src/components/fields/button-group/ButtonGroup.js", + "function" + ], [ "@caldera-labs/components/src/components/fields/fieldgroup.js~fieldgroup", "function/index.html#static-function-FieldGroup", @@ -29,6 +35,24 @@ window.esdocSearchIndex = [ "MESSAGE_CLASS @caldera-labs/components/src/components/fields/messages/Message.js", "variable" ], + [ + "@caldera-labs/components/src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html", + "MagicFieldGroup @caldera-labs/components/src/components/fields/magic-select/MagicFieldGroup.js", + "class" + ], + [ + "@caldera-labs/components/src/components/fields/magic-select/magicitem.js~magicitem", + "class/src/components/fields/magic-select/MagicItem.js~MagicItem.html", + "MagicItem @caldera-labs/components/src/components/fields/magic-select/MagicItem.js", + "class" + ], + [ + "@caldera-labs/components/src/components/fields/magic-select/magicselect.js~magicselect", + "class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html", + "MagicSelect @caldera-labs/components/src/components/fields/magic-select/MagicSelect.js", + "class" + ], [ "@caldera-labs/components/src/components/fields/messages/message.js~message", "function/index.html#static-function-Message", @@ -179,6 +203,12 @@ window.esdocSearchIndex = [ "isValidHtml5type @caldera-labs/components/src/components/fields/util.js", "function" ], + [ + "@caldera-labs/components/src/components/fields/proptypes.js~magicgroupproptypes", + "variable/index.html#static-variable-magicGroupPropTypes", + "magicGroupPropTypes @caldera-labs/components/src/components/fields/propTypes.js", + "variable" + ], [ "@caldera-labs/components/src/components/fields/messages/messageobjectfactory.js~messageobjectfactory", "function/index.html#static-function-messageObjectFactory", @@ -197,6 +227,18 @@ window.esdocSearchIndex = [ "onValueChangePropType @caldera-labs/components/src/components/fields/propTypes.js", "variable" ], + [ + "@caldera-labs/components/src/components/fields/proptypes.js~optionshape", + "variable/index.html#static-variable-optionShape", + "optionShape @caldera-labs/components/src/components/fields/propTypes.js", + "variable" + ], + [ + "@caldera-labs/components/src/components/fields/proptypes.js~optionsshapeprop", + "variable/index.html#static-variable-optionsShapeProp", + "optionsShapeProp @caldera-labs/components/src/components/fields/propTypes.js", + "variable" + ], [ "@caldera-labs/components/src/components/fields/factories/preparefieldconfig.js~preparefieldconfig", "function/index.html#static-function-prepareFieldConfig", @@ -587,6 +629,12 @@ window.esdocSearchIndex = [ "src/components/fields/FieldInner.js", "file" ], + [ + "src/components/fields/button-group/buttongroup.js", + "file/src/components/fields/button-group/ButtonGroup.js.html", + "src/components/fields/button-group/ButtonGroup.js", + "file" + ], [ "src/components/fields/factories/fieldfactory.js", "file/src/components/fields/factories/fieldFactory.js.html", @@ -629,6 +677,138 @@ window.esdocSearchIndex = [ "src/components/fields/input/Input.js", "file" ], + [ + "src/components/fields/magic-select/magicfieldgroup.js", + "file/src/components/fields/magic-select/MagicFieldGroup.js.html", + "src/components/fields/magic-select/MagicFieldGroup.js", + "file" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#constructor", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-constructor-constructor", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#constructor", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#items", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-method-items", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#items", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#listtypeoptions", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-method-listTypeOptions", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#listTypeOptions", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#onchange", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-method-onChange", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onChange", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#onchangelisttype", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-method-onChangeListType", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onChangeListType", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#oninputblur", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-method-onInputBlur", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onInputBlur", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#oninputfocus", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-method-onInputFocus", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onInputFocus", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#onselect", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-method-onSelect", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#onSelect", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#render", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-method-render", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#render", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#renderitem", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-method-renderItem", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#renderItem", + "method" + ], + [ + "src/components/fields/magic-select/magicfieldgroup.js~magicfieldgroup#state", + "class/src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup.html#instance-member-state", + "src/components/fields/magic-select/MagicFieldGroup.js~MagicFieldGroup#state", + "member" + ], + [ + "src/components/fields/magic-select/magicitem.js", + "file/src/components/fields/magic-select/MagicItem.js.html", + "src/components/fields/magic-select/MagicItem.js", + "file" + ], + [ + "src/components/fields/magic-select/magicitem.js~magicitem#render", + "class/src/components/fields/magic-select/MagicItem.js~MagicItem.html#instance-method-render", + "src/components/fields/magic-select/MagicItem.js~MagicItem#render", + "method" + ], + [ + "src/components/fields/magic-select/magicselect.js", + "file/src/components/fields/magic-select/MagicSelect.js.html", + "src/components/fields/magic-select/MagicSelect.js", + "file" + ], + [ + "src/components/fields/magic-select/magicselect.js~magicselect#constructor", + "class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html#instance-constructor-constructor", + "src/components/fields/magic-select/MagicSelect.js~MagicSelect#constructor", + "method" + ], + [ + "src/components/fields/magic-select/magicselect.js~magicselect#onchange", + "class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html#instance-method-onChange", + "src/components/fields/magic-select/MagicSelect.js~MagicSelect#onChange", + "method" + ], + [ + "src/components/fields/magic-select/magicselect.js~magicselect#oninputblur", + "class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html#instance-method-onInputBlur", + "src/components/fields/magic-select/MagicSelect.js~MagicSelect#onInputBlur", + "method" + ], + [ + "src/components/fields/magic-select/magicselect.js~magicselect#oninputfocus", + "class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html#instance-method-onInputFocus", + "src/components/fields/magic-select/MagicSelect.js~MagicSelect#onInputFocus", + "method" + ], + [ + "src/components/fields/magic-select/magicselect.js~magicselect#onselect", + "class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html#instance-method-onSelect", + "src/components/fields/magic-select/MagicSelect.js~MagicSelect#onSelect", + "method" + ], + [ + "src/components/fields/magic-select/magicselect.js~magicselect#render", + "class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html#instance-method-render", + "src/components/fields/magic-select/MagicSelect.js~MagicSelect#render", + "method" + ], + [ + "src/components/fields/magic-select/magicselect.js~magicselect#renderitem", + "class/src/components/fields/magic-select/MagicSelect.js~MagicSelect.html#instance-method-renderItem", + "src/components/fields/magic-select/MagicSelect.js~MagicSelect#renderItem", + "method" + ], [ "src/components/fields/messages/message.js", "file/src/components/fields/messages/Message.js.html", diff --git a/docs/source.html b/docs/source.html index ac97e4e..4d593b4 100644 --- a/docs/source.html +++ b/docs/source.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -72,7 +79,7 @@ -

    Source 39/59

    +

    Source 64/88

    summary
    + public + + + + + +
    +

    + C + + + MagicFieldGroup +

    +
    +
    + + +

    Encapsulates a complete Magic Select field group including label and the type chooser and the input

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + C + + + MagicItem(props: Object): * +

    +
    +
    + + +

    Create magic item for option of magic selects

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + C + + + MagicSelect +

    +
    +
    + + +

    Encapsulates a complete Magic Select field

    +
    +
    +
    + +
    @@ -88,20 +95,20 @@ - + - - - - + + + + - + - + @@ -139,17 +146,25 @@ - - - + + + - - - + + + + + + + + + + + @@ -179,9 +194,9 @@ - - - + + + @@ -207,6 +222,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + + + + - - - + + + @@ -259,7 +301,7 @@ - + diff --git a/docs/variable/index.html b/docs/variable/index.html index c7ea534..10e12d0 100644 --- a/docs/variable/index.html +++ b/docs/variable/index.html @@ -47,13 +47,20 @@
  • VfieldInnerPropTypes
  • VfieldPropTypes
  • VinputTypeProp
  • +
  • VmagicGroupPropTypes
  • VonValueChangePropType
  • +
  • VoptionShape
  • +
  • VoptionsShapeProp
  • VvaluePropType
  • +
  • components/fields/button-groupFButtonGroup
  • components/fields/factoriesFfieldFactory
  • FfieldSetFactory
  • FprepareFieldConfig
  • components/fields/field-group-change-handlersFfieldsetCheckboxHandler
  • components/fields/inputFInput
  • +
  • components/fields/magic-selectCMagicFieldGroup
  • +
  • CMagicItem
  • +
  • CMagicSelect
  • components/fields/messagesFMessage
  • FmessageObjectFactory
  • VMESSAGE_CLASS
  • @@ -227,6 +234,34 @@ + + +
    + + + + + + + + + + + + + +
    src/App.jssrc/App.js App0 %0/135010 byte2592018-07-03 00:20:51 (UTC)0 %0/156120 byte3152018-07-07 16:34:14 (UTC)
    src/components/RenderGroup.js RenderGroup 100 %4/42466 byte2464 byte 1112018-07-03 00:33:05 (UTC)2018-07-07 17:14:45 (UTC)
    src/components/conditional-logic/checkConfigFieldConditionals.jssrc/components/fields/FieldGroup.js FieldGroup 100 %1/13940 byte1722018-07-02 23:41:58 (UTC)4649 byte1992018-07-07 17:38:16 (UTC)
    src/components/fields/FieldInner.js FieldInner 100 %1/11891 byte912018-07-02 23:40:06 (UTC)1954 byte922018-07-06 20:04:30 (UTC)
    src/components/fields/button-group/ButtonGroup.jsButtonGroup100 %1/11470 byte772018-07-07 16:53:16 (UTC)
    src/components/fields/factories/fieldFactory.jssrc/components/fields/factories/prepareFieldConfig.js prepareFieldConfig 100 %1/11772 byte632018-07-01 00:21:18 (UTC)1864 byte642018-07-07 17:21:56 (UTC)
    src/components/fields/field-group-change-handlers/fieldsetCheckboxHandler.js90 2018-07-02 23:40:21 (UTC)
    src/components/fields/magic-select/MagicFieldGroup.jsMagicFieldGroup91 %11/124787 byte2272018-07-07 17:43:02 (UTC)
    src/components/fields/magic-select/MagicItem.jsMagicItem100 %3/32177 byte862018-07-07 16:53:16 (UTC)
    src/components/fields/magic-select/MagicSelect.jsMagicSelect100 %8/82942 byte1422018-07-07 16:53:16 (UTC)
    src/components/fields/messages/Message.js MESSAGE_CLASS @@ -233,25 +272,28 @@ 2018-06-06 21:39:38 (UTC)
    src/components/fields/propTypes.jssrc/components/fields/propTypes.js fieldGroupPropTypes fieldInnerPropTypes fieldPropTypes inputTypeProp +magicGroupPropTypes onValueChangePropType +optionShape +optionsShapeProp valuePropType83 %5/61855 byte682018-07-02 23:41:06 (UTC)77 %7/92460 byte982018-07-07 17:23:30 (UTC)
    src/components/fields/select/SelectField.js SelectField 100 %1/11360 byte802018-06-06 17:53:28 (UTC)1435 byte832018-07-05 22:12:50 (UTC)
    src/components/fields/select/SelectFieldFancy.js100 %1/1 1665 byte 792018-06-05 17:05:53 (UTC)2018-07-05 18:01:12 (UTC)
    src/components/fields/util.js +
    +

    + + + + magicGroupPropTypes: {...fieldGroupPropTypes: Object, "fieldsList": *, "systemTagsList": *, "defaultList": *, "isOpen": *, "type": *} +

    +
    +
    + + + +
    +
    + + +
    + public + + + @@ -285,6 +320,64 @@ + + +
    +

    + + + + optionShape: {label: shim, value: shim} +

    +
    +
    + + +

    The shape of one option for a select field

    +
    +
    +
    + + +
    + public + + + + + +
    +

    + + + + optionsShapeProp: shim +

    +
    +
    + + +

    Shape of options prop for select fields

    +
    +
    +
    + + +
    + public + + + @@ -531,6 +624,49 @@

    + +
    +

    + public + + + + + + magicGroupPropTypes: {...fieldGroupPropTypes: Object, "fieldsList": *, "systemTagsList": *, "defaultList": *, "isOpen": *, "type": *} + + + + source + +

    + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + +

    @@ -619,6 +755,94 @@

    +

    +
    +

    + public + + + + + + optionShape: {label: shim, value: shim} + + + + source + +

    + + + + +

    The shape of one option for a select field

    +
    + + + +
    +
    + + + + + + + + + + + + + + + + + +
    +
    +

    + public + + + + + + optionsShapeProp: shim + + + + source + +

    + + + + +

    Shape of options prop for select fields

    +
    + + + +
    +
    + + + + + + + + + + + + + + + + +

    diff --git a/manual/components.md b/manual/components.md index 9f1d0ec..c4962c5 100644 --- a/manual/components.md +++ b/manual/components.md @@ -66,6 +66,42 @@ const configFields = [ /> ``` +### A Magic Aut-Complete Field Selector In A RednerGroup +```js +const magicField = { + 'id': 'cf-magic-example', + 'type': 'magic', + 'label': 'Magic ID', + 'description': 'Select a value from list of magic tags or type a value', + fieldsList: [ + { + label: '0', + value: 0 + }, + { + label: '1', + value: 1 + }, + { + label: '3', + value: 3 + } + ], + systemTagsList: [ + { + label: '3', + value: 3 + } + ], + isOpen: true, + onValueChange: () => { + } +}; + + + +``` + ### Add onFocus Event For All Fields Of Render Group You can add an onFocus event that fires when ever any field is focused. The callback function gets the config field's ID as its only parameter. ```js @@ -99,7 +135,10 @@ If you have to use a component, please use `FieldGroup` not its inner components * [Reference](https://calderalabs.org/caldera-components/function/index.html#static-function-Input) -### Text field that is required +### Text Field Groups +If the prop `type` is input, the type of input is controlled by the `inputType` props, which by default is `text`. Therefore, by default input field groups have inputs with the HTML5 input `type` attribute of "text". Also, `inputType` could be "number" or "data", etc. + +#### Text field that is required ```jsx ``` -### Text field with help text +#### Text field with help text * Adding help text automatically ads `aria-describedby` ```jsx @@ -146,7 +185,7 @@ If you have to use a component, please use `FieldGroup` not its inner components ``` -### Number Field +### Number Field Group ```jsx +### Select Field Groups + +Select field groups happen when you pass "select" to the `type` prop. + +Select fields take an array of options in the prop option. Options in that collection must conform the shape [defined here](https://calderalabs.org/caldera-components/docs/file/src/components/fields/propTypes.js.html#lineNumber75) + + +``` +let selectFieldValue = ''; + { + selectFieldValue = newValue; + }} + options={[ + { + value: 1, + label: 'One' + }, + { + value: 2, + label: 'Two' + } + ]} +/> + +### Magic Select Groups +Magic select groups use `MagicSelect` fields, which wrap [reactjs/react-autocomple](https://github.com/reactjs/react-autocomplete) to create a UI for [Caldera Forms magic tags](https://calderaforms.com/doc/using-magic-tags-caldera-forms/). + +These fields groups show options from two lists, one is passed in the prop `fieldsList` and represents the fields of the form, and the other is in `systemTagsList`, which represents the system values such as the current user info. + +The property `isOpen` controls if the auto-complete list is open. +```js +let magicFieldValue =''; + + { + magicFieldValue = newValue; + } } + fieldsList={[ + { + label: 'Field One', + value: '%fldOne%' + }, + { + label: 'Field Two', + value: '%fldTwo%' + }, + { + label: 'Field Three', + value: '%fldThree%' + }, + ]} + systemTagsList={[ + { + label: 'User First Name', + value: '{user:first_name}' + } + ]} + isOpen={true} + value={magicFieldValue} + /> +``` ``` ## Select Fields * [Reference](https://calderalabs.org/caldera-components/function/index.html#static-function-SelectField) @@ -219,6 +327,91 @@ let checkBoxValue = ['1']; /> ``` +## Button Group +Button groups are select fields. One button can be selected at once. + +This is a field, not a group (like `FieldGroup` or `MagicFieldGroup`) so it does not handle its own label. + +Button groups fields take an array of options in the prop option. Options in that collection must conform the shape [defined here](https://calderalabs.org/caldera-components/docs/file/src/components/fields/propTypes.js.html#lineNumber75) + +### Examples +### Button Group With Two Options +```js + { + console.log(selectedValue); + }} + options={[ + { + value: 1, + label: 'Option One', + }, + { + value: 2, + label: 'Option Two', + } + ]} + value={1} +/> +``` + +#### Button Group With Icon +If options have `icon`, the rendered markup for the button will be like this: + +```html + + +``` + +That's the markup you need if font awesome is loaded on the page. In the future this component should supply font awesome or dashicons or emoji icons. For now, it does not. + +```js + { + console.log(selectedValue); + }} + options={[ + { + value: 1, + label: 'Option One', + icon: 'fa-envelop' + }, + { + value: 2, + label: 'Option Two', + icon: 'fa-twitter' + + } + ]} + value={1} +/> +``` + +#### Explicitly set `aria-label` Attribute +By default, the visual representation fo the option is `option.label`. That makes sense, if you're representing the option with words. Allowing the component to use `option.label` for the `aria-label` attribute, which is its default value, I think makes sense. + +But, if the visual representation of the option is an emoji or image, then `aria-label` can not be an image, it has to be text that gives meaning to the image for users who can not see the image. + +```js + { + console.log(selectedValue); + }} + options={[ + { + value: 'fields', + label: '%', + ariaLabel: 'Select from field values' + }, + { + value: 'system', + label: '{}', + ariaLabel: 'Select from system values' + }, + ]} +/> +``` + ## Message component The `Message` component is used to display validation messages in a `FieldGroup` component. Messages have a shape defined in the `messagePropShape` object. This component, by design, returns nothing if `props.message.message` is not supplied, or is an empty string. ### An error message diff --git a/package-lock.json b/package-lock.json index ae74c8c..451225f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@caldera-labs/components", - "version": "1.3.0", + "version": "1.3.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -3049,6 +3049,11 @@ } } }, + "dom-scroll-into-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-1.0.1.tgz", + "integrity": "sha1-Mqu5Lw2P7KYhUWKu9D5LRJq42Zw=" + }, "dom-serializer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", @@ -6935,8 +6940,7 @@ "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { "version": "3.7.0", @@ -7416,7 +7420,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, "requires": { "js-tokens": "^3.0.0" } @@ -8017,8 +8020,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -9777,7 +9779,6 @@ "version": "15.6.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", - "dev": true, "requires": { "loose-envify": "^1.3.1", "object-assign": "^4.1.1" @@ -10020,6 +10021,15 @@ } } }, + "react-autocomplete": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/react-autocomplete/-/react-autocomplete-1.8.1.tgz", + "integrity": "sha1-67vEAABqqRrVOLLRRye55+XQYxA=", + "requires": { + "dom-scroll-into-view": "1.0.1", + "prop-types": "^15.5.10" + } + }, "react-dev-utils": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-4.2.1.tgz", diff --git a/package.json b/package.json index fe0da62..7c300e9 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { "name": "@caldera-labs/components", - "version": "1.3.0", + "version": "1.3.1", "dependencies": { "@helpdotcom/is": "^3.0.4", "classnames": "^2.2.6", - "downshift": "^1.31.16" + "downshift": "^1.31.16", + "react-autocomplete": "^1.8.1" }, "license": "GPL-2.0", "scripts": { diff --git a/src/App.js b/src/App.js index 60e1865..8f0a026 100644 --- a/src/App.js +++ b/src/App.js @@ -4,6 +4,7 @@ import './App.css'; import {FieldGroup} from "./components/fields/FieldGroup"; import {fieldSetFactory} from "./components/fields/factories/fieldSetFactory"; import {RenderGroup} from "./components/RenderGroup"; +import {MagicFieldGroup} from "./components/fields/magic-select/MagicFieldGroup"; let textFieldValue = 'Roy,Mike'; const textFieldConfig = { @@ -98,7 +99,8 @@ const configFields = [ textFieldConfig, hiddenFieldConfig, selectFieldConfig, - fieldSetField + fieldSetField, + numberFieldConfig ]; const configFieldEls = fieldSetFactory(configFields); @@ -110,6 +112,8 @@ let values = { three: '' }; +let magicFieldValue = ''; + class App extends Component { render() { @@ -141,6 +145,40 @@ class App extends Component { })}

    +
    +

    Magic Select

    + { + magicFieldValue = newValue; + } } + fieldsList={[ + { + label: 'Field One', + value: '%fldOne%' + }, + { + label: 'Field Two', + value: '%fldTwo%' + }, + { + label: 'Field Three', + value: '%fldThree%' + }, + ]} + systemTagsList={[ + { + label: 'User First Name', + value: '{user:first_name}' + } + ]} + isOpen={true} + value={magicFieldValue} + /> +
    +

    Inputs

    { const configFieldId = findFieldId(configField); if( configFieldId ){ @@ -48,7 +48,7 @@ export class RenderGroup extends React.Component { }); } - if( 'function' === typeof this.props.onFocus ){ + if( 'function' === typeof this.props.onFocus ){ configFields.forEach((configField, configFieldIndex ) => { const configFieldId = findFieldId(configField); if( configFieldId ){ diff --git a/src/components/fields/FieldGroup.js b/src/components/fields/FieldGroup.js index 163f587..6572542 100644 --- a/src/components/fields/FieldGroup.js +++ b/src/components/fields/FieldGroup.js @@ -10,6 +10,7 @@ import {RenderGroup} from '../RenderGroup'; import {Message} from './messages/Message'; import {messageObjectFactory} from './messages/messageObjectFactory'; import {fieldsetCheckboxHandler} from './field-group-change-handlers/fieldsetCheckboxHandler'; +import {MagicFieldGroup} from './magic-select/MagicFieldGroup'; /** * Represents one configField -- wrapper, label and input. @@ -19,6 +20,9 @@ import {fieldsetCheckboxHandler} from './field-group-change-handlers/fieldsetChe * @constructor */ export const FieldGroup = (props) => { + if( 'magic' === props.type ){ + return ; + } /** * Creates the id attribute @@ -118,11 +122,8 @@ export const FieldGroup = (props) => {
    - + + @@ -163,11 +164,37 @@ export const FieldGroup = (props) => { return fieldInner(props); }; - +/** + * The prop type definitions for FieldGroup components + * + * @type {{id: (boolean|shim|*), isBlockInput: shim, isRequired: shim, help: shim, label: (boolean|shim|*), type: shim, value: shim, onValueChange: (boolean|shim|*), inputType: shim}} + */ FieldGroup.propTypes = fieldGroupPropTypes; +/** + * Default props for FieldGroups + * + * @type {{isBlockInput: boolean, isRequired: boolean, help: string}} + */ FieldGroup.defaultProps = { isBlockInput: true, isRequired: false, help: '' +}; + +/** + * Creates the FieldGroup's label component + * + * @param {Object} props + * @return {*} + * @constructor + */ +FieldGroup.Label = (props) => { + return ( + + ); }; \ No newline at end of file diff --git a/src/components/fields/FieldGroup.test.js b/src/components/fields/FieldGroup.test.js index 212637b..8475dfd 100644 --- a/src/components/fields/FieldGroup.test.js +++ b/src/components/fields/FieldGroup.test.js @@ -554,4 +554,16 @@ describe('Field Group component', () => { expect(wrapper.find('.caldera-components-message')).toHaveLength(0); }); }); + + it( 'Uses the Magic group, if type is magic', () => { + const component = renderer.create( + {}} + /> + ); + expect(component.toJSON()).toMatchSnapshot(); + }); }); \ No newline at end of file diff --git a/src/components/fields/FieldInner.js b/src/components/fields/FieldInner.js index 7ebb881..2892122 100644 --- a/src/components/fields/FieldInner.js +++ b/src/components/fields/FieldInner.js @@ -40,6 +40,7 @@ export const FieldInner = (props) => { switch( props.type ){ case 'select': case 'dropdown': + const options = Array.isArray(props.options) ? props.options : []; return ( { value={props.value} onValueChange={props.onValueChange} inputType={props.inputType} - options={props.options} + options={options} disabled={props.disabled} onBlur={props.onBlur} onFocus={props.onFocus} diff --git a/src/components/fields/__snapshots__/FieldGroup.test.js.snap b/src/components/fields/__snapshots__/FieldGroup.test.js.snap index 6560fa9..34e9082 100644 --- a/src/components/fields/__snapshots__/FieldGroup.test.js.snap +++ b/src/components/fields/__snapshots__/FieldGroup.test.js.snap @@ -129,3 +129,38 @@ exports[`Field Group component Field group component props Works with help text

    `; + +exports[`Field Group component Uses the Magic group, if type is magic 1`] = ` +
    + + +
    + +
    +
    +`; diff --git a/src/components/fields/button-group/ButtonGroup.js b/src/components/fields/button-group/ButtonGroup.js new file mode 100644 index 0000000..1980831 --- /dev/null +++ b/src/components/fields/button-group/ButtonGroup.js @@ -0,0 +1,78 @@ +import React from 'react'; +import {optionShape} from '../propTypes'; +import PropTypes from 'prop-types'; +/** + * Creates a button group field + * + * @param {Object} props + * @returns {*} + * @constructor + */ +export const ButtonGroup = (props) => { + /** + * Dispatches new value(s) to parent + * + * @param selection + * @returns {*} + */ + function changeHandler(selection) { + return props.onChange(selection); + } + + /** + * Render a button group + */ + return ( +
    + {props.options.map(option => { + return ; + })} +
    + ); +}; + +/** + * Prop definition for select fields + * + * @type {{}} + */ +ButtonGroup.propTypes = { + onChange: PropTypes.func.isRequired, + options: PropTypes.arrayOf( + PropTypes.shape({ + ...optionShape, + icon:PropTypes.string, + ariaLabel:PropTypes.string + }) + ), + value: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string + ]) +}; + +/** + * Default props for select fields + * + * @type {{options: Array}} + */ +ButtonGroup.defaultProps = { + options: [] +}; \ No newline at end of file diff --git a/src/components/fields/button-group/ButtonGroup.test.js b/src/components/fields/button-group/ButtonGroup.test.js new file mode 100644 index 0000000..6b26e9d --- /dev/null +++ b/src/components/fields/button-group/ButtonGroup.test.js @@ -0,0 +1,143 @@ +import {ButtonGroup} from './ButtonGroup'; +import renderer from 'react-test-renderer'; +import React from 'react'; +import {mount} from 'enzyme'; +import Enzyme from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; + +Enzyme.configure({adapter: new Adapter()}); + +describe('Button Group component', () => { + function genericChangeHandler() { + + } + + describe( 'options', () =>{ + it('Creates with one option', () => { + const component = renderer.create( + + ); + expect(component.toJSON()).toMatchSnapshot(); + }); + it('Renders two buttons', () => { + let updateValue = null; + const component = mount( + { + updateValue = newValue; + }} + options={[ + { + value: 'tags', + label: 'Tags' + }, + { + value: 'categories', + label: 'Categories' + } + ]} + /> + ); + expect(component.find('button')).toHaveLength(2); + }); + + it('Sends the right update value when clicked', () => { + let updateValue = null; + const component = mount( + { + updateValue = newValue; + }} + options={[ + { + value: 'Tags', + label: 'Tags' + } + ]} + /> + ); + component.find('button').simulate('click'); + expect(updateValue).toBe('Tags'); + }); + + it('Marks the value as selected if it should on initial load', () => { + const component = mount( + { + + }} + options={[ + { + value: 'a1', + label: 'Tags' + } + ]} + value={'a1'} + /> + ); + + expect(component.find('button').hasClass('selected')).toBe(true); + }); + + it('Sets aria-label to label when ariaLabel not provided', () => { + const component = mount( + + ); + + expect(component.find('button').prop('aria-label')).toBe('Tags'); + }); + + it('Sets aria-label to explicit value when passed', () => { + const component = mount( + + ); + + expect(component.find('button').prop('aria-label')).toBe('Select field values'); + }); + }); + + describe( 'icon buttons', ()=> { + it('Creates with an icon option', () => { + const component = renderer.create( + + ); + expect(component.toJSON()).toMatchSnapshot(); + }); + }); + + +}); \ No newline at end of file diff --git a/src/components/fields/button-group/__snapshots__/ButtonGroup.test.js.snap b/src/components/fields/button-group/__snapshots__/ButtonGroup.test.js.snap new file mode 100644 index 0000000..e7264d0 --- /dev/null +++ b/src/components/fields/button-group/__snapshots__/ButtonGroup.test.js.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Button Group component icon buttons Creates with an icon option 1`] = ` +
    + +
    +`; + +exports[`Button Group component options Creates with one option 1`] = ` +
    + +
    +`; diff --git a/src/components/fields/factories/__snapshots__/fieldFactory.test.js.snap b/src/components/fields/factories/__snapshots__/fieldFactory.test.js.snap index 57fcd21..2050bd6 100644 --- a/src/components/fields/factories/__snapshots__/fieldFactory.test.js.snap +++ b/src/components/fields/factories/__snapshots__/fieldFactory.test.js.snap @@ -47,8 +47,10 @@ exports[`Factories Field set factory Renders with elements 1`] = ` >
    diff --git a/src/components/fields/factories/fieldFactory.test.js b/src/components/fields/factories/fieldFactory.test.js index 22d148d..6a0c995 100644 --- a/src/components/fields/factories/fieldFactory.test.js +++ b/src/components/fields/factories/fieldFactory.test.js @@ -27,6 +27,34 @@ const hiddenFieldConfig = { 'description': false }; +const magicField = { + 'id': 'cf-magic-example', + 'type': 'magic', + 'label': 'Magic ID', + 'description': 'Select a value from list of magic tags or type a value', + fieldsList: [ + { + label: '0', + value: 0 + }, + { + label: '1', + value: 1 + }, + { + label: '3', + value: 3 + } + ], + systemTagsList: [ + { + label: '3', + value: 3 + } + ], + onValueChange: () => {} +}; + const configFields = [ { 'id': 'cf-convertkit-apikey', 'label': 'API Key', 'type': 'text' @@ -35,7 +63,10 @@ const configFields = [ 'id': 'pid-1', 'label': 'Sequence', 'type': 'dropdown', - 'options': ['-- Select A ConvertKit Sequence --'], + 'options': [{ + value: null, + label: '-- Select --' + }], 'desc': 'ConvertKit sequence to add subscriber to. Sequences are also referred to as courses.', 'description': false, 'extra_classes': 'field-Something is wrong', @@ -368,7 +399,26 @@ describe('Factories', () => { ); expect(wrapper.children()).toHaveLength(configFields.length); expect(wrapper.find('.f-1')).toHaveLength(1); - expect(wrapper.find('.f-1').text()).toBe('Sequence'); + }); + + it('Creates the if a magic field is in collection', () => { + const components = fieldSetFactory([ + magicField + ]); + const wrapper = mount( +
    + {Array.from(components).map((field, i) => { + return React.createElement( + 'div', { + key: i, + className: `f-${i}` + }, + field + ); + })} +
    + ); + expect(wrapper.find('input')).toHaveLength(1); }); diff --git a/src/components/fields/factories/prepareFieldConfig.js b/src/components/fields/factories/prepareFieldConfig.js index 3fb39a0..2b7fea9 100644 --- a/src/components/fields/factories/prepareFieldConfig.js +++ b/src/components/fields/factories/prepareFieldConfig.js @@ -1,4 +1,4 @@ -import {fieldGroupPropTypes} from '../propTypes'; +import {fieldGroupPropTypes,magicGroupPropTypes} from '../propTypes'; import {isValidHtml5type, toBoolean} from '../util'; import {messageObjectFactory} from '../messages/messageObjectFactory'; @@ -53,7 +53,8 @@ export const prepareFieldConfig = (fieldArgs) => { validators = fieldArgs.validators; } - fieldArgs = pick(fieldArgs, Object.keys(fieldGroupPropTypes)); + const keys = 'magic' === fieldArgs.type ? magicGroupPropTypes : fieldGroupPropTypes; + fieldArgs = pick(fieldArgs, Object.keys(keys)); fieldArgs.disabled = toBoolean(fieldArgs.disabled); fieldArgs.message = 'object' === typeof fieldArgs.message ? messageObjectFactory(fieldArgs.message) diff --git a/src/components/fields/field-group-change-handlers/handlers.test.js b/src/components/fields/field-group-change-handlers/handlers.test.js index c67adec..a142fa0 100644 --- a/src/components/fields/field-group-change-handlers/handlers.test.js +++ b/src/components/fields/field-group-change-handlers/handlers.test.js @@ -1,20 +1,20 @@ import {fieldsetCheckboxHandler} from './fieldsetCheckboxHandler'; describe('checkbox handler', () => { - let udpateValue = null; + let updateValue = null; beforeEach(() => { - udpateValue = null; + updateValue = null; }); function handler(newValue) { - udpateValue = newValue; + updateValue = newValue; } it('Adds value to array of values', () => { fieldsetCheckboxHandler({ value: '2', label: 'Two' }, [5, 'pants'], handler); - expect(udpateValue).toEqual([5, 'pants', '2']); + expect(updateValue).toEqual([5, 'pants', '2']); }); it('Removes value from array of values', () => { @@ -22,7 +22,7 @@ describe('checkbox handler', () => { value: 1, label: 'One' }, [1, 2], handler); - expect(udpateValue).toEqual([2]); + expect(updateValue).toEqual([2]); }); it('Adds value to when values is a string', () => { @@ -30,7 +30,7 @@ describe('checkbox handler', () => { value: 1, label: 'One' }, '2', handler); - expect(udpateValue).toEqual(['2',1]); + expect(updateValue).toEqual(['2',1]); }); @@ -39,6 +39,6 @@ describe('checkbox handler', () => { value: 1, label: 'One' }, 2, handler); - expect(udpateValue).toEqual([2,1]); + expect(updateValue).toEqual([2,1]); }); }); \ No newline at end of file diff --git a/src/components/fields/magic-select/MagicFieldGroup.js b/src/components/fields/magic-select/MagicFieldGroup.js new file mode 100644 index 0000000..f01638c --- /dev/null +++ b/src/components/fields/magic-select/MagicFieldGroup.js @@ -0,0 +1,228 @@ +import React from 'react'; +import {magicGroupPropTypes} from '../propTypes'; +import classNames from 'classnames'; +import {MagicItem} from './MagicItem'; +import {ButtonGroup} from '../button-group/ButtonGroup'; +import {MagicSelect} from './MagicSelect'; +import {RenderGroup} from '../../RenderGroup'; +import {Message} from '../messages/Message'; +import {FieldGroup} from '../FieldGroup'; + + +/** + * Encapsulates a complete Magic Select field group including label and the type chooser and the input + */ +export class MagicFieldGroup extends React.PureComponent { + + /** + * Create a MagicFieldGroup component + * + * @param {Object} props + */ + constructor(props) { + super(props); + this.state = { + currentListType: props.defaultList, + isOpen: props.isOpen, + }; + this.onChange = this.onChange.bind(this); + this.items = this.items.bind(this); + this.onChange = this.onChange.bind(this); + this.onSelect = this.onSelect.bind(this); + this.onInputFocus = this.onInputFocus.bind(this); + this.renderItem = this.renderItem.bind(this); + this.onInputBlur = this.onInputBlur.bind(this); + this.onChangeListType = this.onChangeListType.bind(this); + this.listTypeOptions = this.listTypeOptions.bind(this); + } + + /** + * Handle direct change events + * @param {String|number} newValue + */ + onChange(newValue) { + this.props.onValueChange(newValue); + } + + /** + * Handle when the field gets focus + */ + onInputFocus() { + this.setState({isOpen: true}); + } + + /** + * Handle when the field is blurred + */ + onInputBlur() { + this.setState({isOpen: false}); + } + + + /** + * Handle when the option is chosen + * @param {String|number} value + */ + onSelect(value) { + this.props.onValueChange(value); + this.setState({isOpen: false}); + } + + /** + * Update list of tags to show + * @param {String}newType + */ + onChangeListType(newType){ + if( ! this.state.isOpen ){ + this.setState({isOpen:true}); + } + this.setState({currentListType:newType}); + } + + /** + * Render option + * + * @param {object} item + * @param {bool} isHighlighted + * @return {*} + */ + renderItem(item, isHighlighted){ + return ; + } + + /** + * Create the list of items + * + * @return {Array} + */ + items() { + const optionsOrEmpty =(options) => { + return Array.isArray(options) && options.length ? options : []; + }; + + let items = []; + + if( optionsOrEmpty(this.props.options).length){ + items = optionsOrEmpty(this.props.options); + } + else if ('system' === this.state.currentListType ) { + items = optionsOrEmpty(this.props.systemTagsList); + } else { + items = optionsOrEmpty(this.props.fieldsList); + } + + if (items.length) { + items.forEach((item, itemIndex) => { + items[itemIndex].innerKey = `${item.value}-${itemIndex}`; + }); + }else{ + items.push({ + value: null, + label: null, + innerKey:this.props.id + }); + } + + return items; + + } + + /** + * Options for type chooser + * + * @return {*[]} + */ + listTypeOptions(){ + return [ + { + value: 'fields', + label: '%', + ariaLabel: 'Select from field values' + }, + { + value: 'system', + label: '{}', + ariaLabel: 'Select from system values' + }, + ]; + } + + + + /** + * Render MagicFieldGroup component + * @return {*} + */ + render() { + return ( +
    + + {this.props.message.message && + + } + {this.state.isOpen && + + } + + +
    + ); + } +} + + +/** + * Prop definitions for MagicFieldGroup component + */ +MagicFieldGroup.propTypes = magicGroupPropTypes; + +/** + * Default property values for MagicFieldGroup component + * + * @type {{}} + */ +MagicFieldGroup.defaultProps = { + defaultList: 'fields', + isOpen: false, + message: { + error: false, + message: '' + }, + type: 'magic' +}; + +/** + * The names of classes used for HTML elements in MagicFieldGroup component + * @type {{fieldWrapper: string, input: string, option: string}} + */ +MagicFieldGroup.classNames = { + fieldWrapper: 'caldera-magic-select-group', + input: 'caldera-magic-input', + option: 'caldera-magic-option' +}; \ No newline at end of file diff --git a/src/components/fields/magic-select/MagicFieldGroup.test.js b/src/components/fields/magic-select/MagicFieldGroup.test.js new file mode 100644 index 0000000..3d7fad7 --- /dev/null +++ b/src/components/fields/magic-select/MagicFieldGroup.test.js @@ -0,0 +1,567 @@ +import renderer from 'react-test-renderer'; +import React from 'react'; +import {mount, shallow} from 'enzyme'; +import Enzyme from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; +import {MagicFieldGroup} from './MagicFieldGroup'; + +Enzyme.configure({adapter: new Adapter()}); + +const genericChangeHandler = () => { +}; +describe('MagicFieldGroup component', () => { + + + it('matches snapshot with no message', () => { + const component = renderer.create( + + ); + expect(component.toJSON()).toMatchSnapshot(); + }); + + it('matches snapshot with message', () => { + const component = renderer.create( + + ); + expect(component.toJSON()).toMatchSnapshot(); + }); + + describe('Inner input', () => { + it('Has inner input', () => { + const component = mount( + + ); + expect(component.find('input')).toHaveLength(1); + }); + }); + describe('Options', () => { + it('shows no options if closed', () => { + const component = mount( + + ); + expect(component.find('.magic-input-option')).toHaveLength(0); + }); + + + it('Uses options prop by default - right number of options', () => { + const component = mount( + + ); + component.find('input').simulate('focus'); + expect(component.find('.magic-input-option')).toHaveLength(2); + }); + + it('Uses options prop by default', () => { + const component = mount( + + ); + component.find('input').simulate('focus'); + expect(component.find('.magic-input-option')).toHaveLength(2); + }); + + it('Uses fieldsList prop if no options prop', () => { + const component = mount( + + ); + component.find('input').simulate('focus'); + expect(component.find('.magic-input-option')).toHaveLength(3); + }); + + it('Uses systemTagsList prop if no options prop and currentListType state is system', () => { + const component = mount( + + ); + component.find('input').simulate('focus'); + component.setState({currentListType: 'system'}); + expect(component.find('.magic-input-option')).toHaveLength(1); + }); + + it('Receives updated value', () => { + let value = '1'; + const component = mount( + { + value = newValue; + }} + fieldsList={[ + { + label: '0', + value: 0 + }, + { + label: '1', + value: 1 + }, + { + label: '3', + value: 3 + } + ]} + systemTagsList={[ + { + label: '3', + value: 3 + } + ]} + value={value} + isOpen={true} + /> + ); + component.find('input').simulate('focus'); + component.find('input').simulate('change', {target: {value: '3'}}); + expect(value).toEqual('3'); + }); + }); + + + describe('Value', () => { + it('Uses props.value to set value', () => { + const component = mount( + + ); + expect(component.find('input').prop('value')).toBe(1); + }); + + + it('Passes updated value properly through the onSelect handler', () => { + let updatedValue = null; + const component = mount( + { + updatedValue = newValue; + }} + options={[ + { + label: '1', + value: 1 + }, + { + label: '14', + value: 14 + } + ]} + value={1} + /> + ); + + component.instance().onSelect(14); + expect(updatedValue).toEqual(14); + }); + }); + + describe('Button group for type choice', () => { + it('Outputs the buttons if open', () => { + const component = mount( + + ); + expect(component.find('button')).toHaveLength(2); + }); + it('Does not output the buttons if not open', () => { + const component = mount( + + ); + expect(component.find('button')).toHaveLength(0); + }); + }); + + it('onChange passes value', () => { + let value = 2; + const component = mount( + { + value = newValue; + }} + fieldsList={[ + { + label: '0', + value: 0 + }, + { + label: '1', + value: 1 + }, + { + label: '3', + value: 3 + } + ]} + systemTagsList={[ + { + label: '3', + value: 3 + } + ]} + value={value} + isOpen={true} + /> + ); + component.instance().onChange(3); + expect(value).toBe(3); + }); + + describe('updates state on focus', () => { + it('Updates state when calling handler directly', () => { + const component = mount( + { + }} + defaultList={'fields'} + options={[]} + + isOpen={false} + /> + ); + component.instance().onInputFocus(); + expect(component.state().isOpen).toBe(true); + }); + + it('Updates state when simulating focus', () => { + const component = mount( + { + }} + defaultList={'fields'} + options={[]} + + isOpen={false} + /> + ); + component.find('input').simulate('focus'); + expect(component.state().isOpen).toBe(true); + }); + }); + + describe('updates state on blur', () => { + + it('Updates state when calling handler directly', () => { + const component = mount( + { + }} + defaultList={'fields'} + options={[]} + + isOpen={true} + /> + ); + component.instance().onInputBlur(); + expect(component.state().isOpen).toBe(false); + }); + + + + }); + + describe( 'Changing list type', () => { + it('Opens whenever changing type', () => { + const component = mount( + { + }} + defaultList={'fields'} + options={[]} + + isOpen={false} + /> + ); + component.instance().onChangeListType('system'); + expect(component.state().isOpen).toBe(true); + }); + it('Stays opens changing type', () => { + const component = mount( + { + }} + defaultList={'fields'} + options={[]} + + isOpen={true} + /> + ); + component.instance().onChangeListType('system'); + expect(component.state().isOpen).toBe(true); + }); + + it('Changes the type', () => { + const component = mount( + { + }} + defaultList={'fields'} + options={[]} + + isOpen={true} + /> + ); + component.instance().onChangeListType('system'); + expect(component.state().currentListType).toBe('system'); + }); + }); + + + it('Renders the inner items', () => { + const component = mount( + { + }} + defaultList={'fields'} + options={[]} + isOpen={true} + /> + ); + const innerComponent = renderer.create( + component.instance().renderItem({ + label: '1', + value: '1', + innerKey: '1' + }, true + )); + expect(innerComponent.toJSON()).toMatchSnapshot(); + }); +}); \ No newline at end of file diff --git a/src/components/fields/magic-select/MagicItem.js b/src/components/fields/magic-select/MagicItem.js new file mode 100644 index 0000000..675c727 --- /dev/null +++ b/src/components/fields/magic-select/MagicItem.js @@ -0,0 +1,87 @@ +import React from 'react'; +import { + optionShape +} from '../propTypes'; +import classNames from 'classnames'; +import PropTypes from 'prop-types'; + +/** + * Create magic item for option of magic selects + * + * This can not be a functional component + * https://github.com/reactjs/react-autocomplete/pull/293#issuecomment-371617758 + * + * + * @param {Object} props + * @return {*} + * @constructor + */ +export class MagicItem extends React.PureComponent { + + /** + * Render magic item components + */ + render() { + return React.createElement( + this.props.elementType, + { + style: {background: this.props.isHighlighted ? this.props.highlightColor : this.props.notHighlighterColor}, + className: classNames(this.props.className, 'magic-input-option'), + onClick: this.props.onClick + }, + [ + React.createElement( + this.props.innerElementType, + { + key: `left--${this.props.innerKey}`, + className: classNames('magic-item-value', 'magic-item-left') + }, + this.props.item.value + ), + React.createElement( + this.props.innerElementType, + { + key: `right--${this.props.innerKey}`, + className: classNames('magic-item-label', 'magic-item-right') + }, + this.props.item.label + ) + ] + ); + } +} + +/** + * Prop definition for allowed element types + * @type {shim} + */ +const elementTypesProp = PropTypes.oneOf(['div', 'span']); +/** + * Prop definitions for MagicItem component + * + * @type {{item: shim, isHighlighted: shim, className: shim, highlightColor: shim, notHighlighterColor: shim}} + */ +MagicItem.propTypes = { + elementType: elementTypesProp, + innerElementType: elementTypesProp, + item: PropTypes.shape(optionShape), + isHighlighted: PropTypes.bool, + className: PropTypes.string, + highlightColor: PropTypes.string, + notHighlighterColor: PropTypes.string, + innerKey: PropTypes.string.isRequired, + onClick: PropTypes.func +}; + +/** + * Default props for the MagicItem component + * + * @type {{isHighlighted: boolean, highlightColor: string, notHighlightedColor: string}} + */ +MagicItem.defaultProps = { + elementType: 'div', + innerElementType: 'span', + isHighlighted: false, + highlightColor: 'lightgray', + notHighlightedColor: 'white', +}; \ No newline at end of file diff --git a/src/components/fields/magic-select/MagicItem.test.js b/src/components/fields/magic-select/MagicItem.test.js new file mode 100644 index 0000000..afea8fb --- /dev/null +++ b/src/components/fields/magic-select/MagicItem.test.js @@ -0,0 +1,58 @@ +import renderer from 'react-test-renderer'; +import React from 'react'; +import {MagicItem} from './MagicItem'; + + +describe('MagicSelect component', () => { + + it('Matches snapshot', () => { + const component = renderer.create( + + ); + expect(component.toJSON()).toMatchSnapshot(); + }); + + it('Can render as span', () => { + const component = renderer.create( + + ); + expect(component.toJSON()).toMatchSnapshot(); + }); + + it('Can render inner type as div', () => { + const component = renderer.create( + + ); + expect(component.toJSON()).toMatchSnapshot(); + }); +}); \ No newline at end of file diff --git a/src/components/fields/magic-select/MagicSelect.js b/src/components/fields/magic-select/MagicSelect.js new file mode 100644 index 0000000..515978e --- /dev/null +++ b/src/components/fields/magic-select/MagicSelect.js @@ -0,0 +1,153 @@ +import React from 'react'; +import { + onValueChangePropType, + optionsShapeProp, + valuePropType +} from '../propTypes'; +import Autocomplete from 'react-autocomplete'; +import PropTypes from 'prop-types'; +import {MagicItem} from './MagicItem'; +import {MagicFieldGroup} from './MagicFieldGroup'; +import classNames from 'classnames'; + + +/** + * Encapsulates a complete Magic Select field + */ +export class MagicSelect extends React.PureComponent { + + /** + * Create a MagicSelect component + * + * @param {Object} props + */ + constructor(props) { + super(props); + this.onChange = this.onChange.bind(this); + this.onChange = this.onChange.bind(this); + this.onSelect = this.onSelect.bind(this); + this.onInputFocus = this.onInputFocus.bind(this); + this.renderItem = this.renderItem.bind(this); + this.onInputBlur = this.onInputBlur.bind(this); + this.getItemValue = this.getItemValue.bind(this); + } + + /** + * Handle direct change events + * + * @param {Event} event + */ + onChange(event) { + this.props.onValueChange(event.target.value); + } + + /** + * Handle when the field gets focus + */ + onInputFocus() { + if( 'function' === typeof this.props.onFocus ){ + this.props.onFocus(); + } + } + + /** + * Handle when the field is blurred + */ + onInputBlur() { + if( 'function' === typeof this.props.onBlur ){ + this.props.onBlur(); + } + } + + + /** + * Handle when the option is chosen + * @param {String|number} value + */ + onSelect(value) { + this.props.onValueChange(value); + } + + + /** + * Render option + * + * @param {object} item + * @param {bool} isHighlighted + * @return {*} + */ + renderItem(item, isHighlighted){ + return ; + } + + /** + * Get the value of the item + * @param {Object} item + * @return {*} + */ + getItemValue(item){ + return item.value; + } + + + /** + * Render MagicSelect component + * @return {*} + */ + render() { + return ( + + + ); + } +} + + +/** + * Prop definitions for MagicSelect component + */ +MagicSelect.propTypes = { + id: PropTypes.string.isRequired, + options: optionsShapeProp, + isRequired: PropTypes.bool, + help: PropTypes.string, + value: valuePropType, + onValueChange: onValueChangePropType, + disabled: PropTypes.bool, + isOpen: PropTypes.bool, + onBlur: PropTypes.func, + onFocus: PropTypes.func, + className: PropTypes.string +}; + +/** + * Default property values for MagicSelect component + * + * @type {{}} + */ +MagicSelect.defaultProps = { + defaultList: 'fields', + isOpen: false, + options:[] +}; \ No newline at end of file diff --git a/src/components/fields/magic-select/MagicSelect.test.js b/src/components/fields/magic-select/MagicSelect.test.js new file mode 100644 index 0000000..61a7672 --- /dev/null +++ b/src/components/fields/magic-select/MagicSelect.test.js @@ -0,0 +1,391 @@ +import renderer from 'react-test-renderer'; +import React from 'react'; +import {mount} from 'enzyme'; +import Enzyme from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; +import {MagicSelect} from './MagicSelect'; + +Enzyme.configure({adapter: new Adapter()}); + +const genericChangeHandler = () => { +}; +describe('MagicSelect component', () => { + + it('Matches snapshot', () => { + const component = renderer.create( + + ); + expect(component.toJSON()).toMatchSnapshot(); + }); + + it('Has inner input', () => { + const component = mount( + + ); + expect(component.find('input')).toHaveLength(1); + }); + + it('puts the right id attribute on inner input', () => { + const component = mount( + + ); + expect(component.find('input').prop('id')).toBe('magic-2'); + }); + + describe('Options', () => { + it('shows no options if closed', () => { + const component = mount( + + ); + expect(component.find('.magic-input-option')).toHaveLength(0); + }); + + it('shows options if opened', () => { + const component = mount( + + ); + expect(component.find('.magic-input-option')).toHaveLength(2); + }); + + it('Updates is open state when focused', () => { + let isOpen = false; + const component = mount( + { + isOpen = true; + }} + onFocus={() => { + isOpen = false; + }} + onValueChange={genericChangeHandler} + options={[ + { + label: 'a1', + value: 1, + innerKey: '1' + }, + { + label: 'a14', + value: 14, + innerKey: '2' + + } + ]} + /> + ); + component.find( 'input' ).simulate('focus'); + expect(component.prop('isOpen')).toEqual(false); + }); + + it('Updates is open state when blurred', () => { + let isOpen = false; + const component = mount( + { + isOpen = true; + }} + onFocus={() => { + isOpen = false; + }} + options={[ + { + label: 'a1', + value: 1, + innerKey: '1' + }, + { + label: 'a14', + value: 14, + innerKey: '2' + + } + ]} + /> + ); + component.find( 'input' ).simulate('focus'); + component.find( 'input' ).simulate('blur'); + expect(component.prop('isOpen')).toEqual(false); + }); + + it('Uses options prop by default - right number of options', () => { + const component = mount( + + ); + expect(component.find('.magic-input-option')).toHaveLength(2); + }); + + it('Uses options prop by default - right number of options', () => { + const component = mount( + + ); + expect(component.find('.magic-input-option')).toHaveLength(2); + }); + + }); + + + describe('Value', () => { + it('Uses props.value to set value', () => { + const component = mount( + + ); + expect(component.find('input').prop('value')).toBe(1); + }); + + + it('Passes updated value properly through the onSelect handler', () => { + let updatedValue = null; + const component = mount( + { + updatedValue = newValue; + }} + options={[ + { + label: '1', + value: 1, + innerKey: '12' + }, + { + label: '14', + value: 14, + innerKey: '13' + + } + ]} + value={1} + /> + ); + + component.instance().onSelect(14); + expect(updatedValue).toEqual(14); + }); + + it('Passes updated value, not an event ', () => { + let updatedValue = 1; + const component = mount( + { + updatedValue = newValue; + }} + options={[ + { + label: '1', + value: 1, + innerKey: '1' + }, + { + label: '12', + value: 12, + innerKey: '12' + } + ]} + value={updatedValue} + isOpen={true} + /> + ); + + component.instance().onChange({ target: { value: 12 } }); + expect(updatedValue).toEqual(12); + }); + + it('Receives the updated value ', () => { + let updatedValue = 1; + const component = mount( + { + updatedValue = newValue; + }} + options={[ + { + label: '1', + value: 1, + innerKey: '1' + }, + { + label: '12', + value: 12, + innerKey: '12' + } + ]} + value={updatedValue} + isOpen={true} + /> + ); + + component.find('input').simulate('change', { target: { value: 12 } }); + expect(updatedValue).toEqual(12); + }); + + it('Gets the item value ', () => { + let updatedValue = 1; + const component = mount( + { + updatedValue = newValue; + }} + options={[ + { + label: '1', + value: 1, + innerKey: '1' + }, + { + label: '12', + value: 12, + innerKey: '12' + } + ]} + value={updatedValue} + isOpen={true} + /> + ); + expect(component.instance().getItemValue({value: 12})).toEqual(12); + }); + }); + + + +}); \ No newline at end of file diff --git a/src/components/fields/magic-select/__snapshots__/MagicFieldGroup.test.js.snap b/src/components/fields/magic-select/__snapshots__/MagicFieldGroup.test.js.snap new file mode 100644 index 0000000..d58cea5 --- /dev/null +++ b/src/components/fields/magic-select/__snapshots__/MagicFieldGroup.test.js.snap @@ -0,0 +1,98 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MagicFieldGroup component Renders the inner items 1`] = ` +
    + + 1 + + + 1 + +
    +`; + +exports[`MagicFieldGroup component matches snapshot with message 1`] = ` +
    + +
    + Hi Roy +
    +
    + +
    +
    +`; + +exports[`MagicFieldGroup component matches snapshot with no message 1`] = ` +
    + + +
    + +
    +
    +`; diff --git a/src/components/fields/magic-select/__snapshots__/MagicItem.test.js.snap b/src/components/fields/magic-select/__snapshots__/MagicItem.test.js.snap new file mode 100644 index 0000000..be66e44 --- /dev/null +++ b/src/components/fields/magic-select/__snapshots__/MagicItem.test.js.snap @@ -0,0 +1,70 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MagicSelect component Can render as span 1`] = ` + + + html + + + HTML + + +`; + +exports[`MagicSelect component Can render inner type as div 1`] = ` +
    +
    + html +
    +
    + HTML +
    +
    +`; + +exports[`MagicSelect component Matches snapshot 1`] = ` +
    + + html + + + HTML + +
    +`; diff --git a/src/components/fields/magic-select/__snapshots__/MagicSelect.test.js.snap b/src/components/fields/magic-select/__snapshots__/MagicSelect.test.js.snap new file mode 100644 index 0000000..3314de6 --- /dev/null +++ b/src/components/fields/magic-select/__snapshots__/MagicSelect.test.js.snap @@ -0,0 +1,26 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`MagicSelect component Matches snapshot 1`] = ` +
    + +
    +`; diff --git a/src/components/fields/propTypes.js b/src/components/fields/propTypes.js index 6539199..83babf8 100644 --- a/src/components/fields/propTypes.js +++ b/src/components/fields/propTypes.js @@ -24,7 +24,7 @@ export const onValueChangePropType = PropTypes.func.isRequired; * Proptypes for Input component * @type {shim} */ -export const inputTypeProp = PropTypes.string; +export const inputTypeProp = PropTypes.string; /** * PropTypes for field groups @@ -37,11 +37,11 @@ export const fieldGroupPropTypes = { isRequired: PropTypes.bool, help: PropTypes.string, label: PropTypes.string.isRequired, - type: PropTypes.oneOf(['input','select', 'fieldset']), + type: PropTypes.oneOf(['input', 'select', 'fieldset', 'magic']), value: valuePropType, onValueChange: onValueChangePropType, options: PropTypes.array, - inputType:inputTypeProp, + inputType: inputTypeProp, disabled: PropTypes.bool, message: messagePropShape, onBlur: PropTypes.func, @@ -66,3 +66,34 @@ export const fieldInnerPropTypes = { }; export const fieldPropTypes = fieldInnerPropTypes; + +/** + * The shape of one option for a select field + * + * @type {{label: shim, value: shim}} + */ +export const optionShape = { + label: PropTypes.string, + value: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + ]) +}; + +/** + * Shape of options prop for select fields + * + * @type {shim} + */ +export const optionsShapeProp = PropTypes.arrayOf( + PropTypes.shape(optionShape) +); + +export const magicGroupPropTypes = { + ...fieldGroupPropTypes, + fieldsList: optionsShapeProp, + systemTagsList: optionsShapeProp, + defaultList: PropTypes.string, + isOpen: PropTypes.bool, + type: PropTypes.string +}; \ No newline at end of file diff --git a/src/components/fields/select/SelectField.js b/src/components/fields/select/SelectField.js index bdbc83a..0abaffc 100644 --- a/src/components/fields/select/SelectField.js +++ b/src/components/fields/select/SelectField.js @@ -2,6 +2,7 @@ import React from 'react'; import {fieldPropTypes} from '../propTypes'; import classNames from 'classnames'; import {RenderGroup} from '../../RenderGroup'; +import {optionsShapeProp} from '../propTypes'; /** * Creates a select field @@ -69,6 +70,8 @@ export const SelectField = (props) => { */ SelectField.propTypes = { ...fieldPropTypes, + options: optionsShapeProp + }; /** diff --git a/src/components/renderGroup.test.js b/src/components/renderGroup.test.js index 57962eb..bf8d0c8 100644 --- a/src/components/renderGroup.test.js +++ b/src/components/renderGroup.test.js @@ -1,10 +1,11 @@ import {RenderGroup} from './RenderGroup'; -import { mount } from 'enzyme'; +import {mount} from 'enzyme'; import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; import React from 'react'; import renderer from 'react-test-renderer'; -Enzyme.configure({ adapter: new Adapter() }); + +Enzyme.configure({adapter: new Adapter()}); const textFieldConfig = { 'id': 'cf-something-tags', @@ -29,66 +30,69 @@ const configFields = [ textFieldConfig ]; -const genericHandler = () => {}; +const genericHandler = () => { +}; configFields.map(config => { config.onValueChange = genericHandler; }); -describe( 'The render group component', () => { +describe('The render group component', () => { - describe( 'Rendering with fields', () => { - it( 'Works with one text field', () => { + describe('Rendering with fields', () => { + it('Works with one text field', () => { const component = renderer.create( - + ); - expect( component.toJSON() ).toMatchSnapshot(); + expect(component.toJSON()).toMatchSnapshot(); }); - it( 'Works with a few fields', () => { + it('Works with a few fields', () => { const component = renderer.create( ); - expect( component.toJSON() ).toMatchSnapshot(); + expect(component.toJSON()).toMatchSnapshot(); }); - it( 'Does not error when passed empty array of fields', () => { + it('Does not error when passed empty array of fields', () => { const component = renderer.create( ); - expect( component.toJSON() ).toMatchSnapshot(); + expect(component.toJSON()).toMatchSnapshot(); }); }); - describe( 'Creates the inner components correctly', () =>{ - it( 'Creates array of components', () => { + describe('Creates the inner components correctly', () => { + it('Creates array of components', () => { const component = new RenderGroup({ - configFields:configFields + configFields: configFields }); - expect( component.createComponents() ).toBeInstanceOf(Array); + expect(component.createComponents()).toBeInstanceOf(Array); }); - it( 'Has the right number of children', () => { + it('Has the right number of children', () => { const wrapper = mount( ); - expect( wrapper.find('.x1').children() ).toHaveLength(4); + expect(wrapper.find('.x1').children()).toHaveLength(4); }); - it( 'Adds the description', () => { + it('Adds the description', () => { const thisConfigFields = [ { 'id': 'sz', @@ -100,12 +104,12 @@ describe( 'The render group component', () => { } ]; - const wrapper = mount( ); + const wrapper = mount(); - expect( wrapper.find('p.description') ).toHaveLength(1); + expect(wrapper.find('p.description')).toHaveLength(1); }); - it( 'Adds the right description', () => { + it('Adds the right description', () => { const thisConfigFields = [ { 'id': 'sz', @@ -116,11 +120,11 @@ describe( 'The render group component', () => { onValueChange: genericHandler } ]; - const wrapper = mount( ); - expect( wrapper.find('p.description').text() ).toEqual( 'Expect This' ); + const wrapper = mount(); + expect(wrapper.find('p.description').text()).toEqual('Expect This'); }); - it( 'Sets aria-describedby prop on input to match description', () => { + it('Sets aria-describedby prop on input to match description', () => { const thisConfigFields = [ { 'id': 'sz', @@ -131,11 +135,11 @@ describe( 'The render group component', () => { onValueChange: genericHandler } ]; - const wrapper = mount( ); - expect( wrapper.find('input').prop('aria-describedby') ).toEqual( 'sz-description' ); + const wrapper = mount(); + expect(wrapper.find('input').prop('aria-describedby')).toEqual('sz-description'); }); - it( 'Adds the description using .desc if .description is not provided to match old spec', () => { + it('Adds the description using .desc if .description is not provided to match old spec', () => { const thisConfigFields = [ { 'id': 'sz', @@ -146,13 +150,13 @@ describe( 'The render group component', () => { } ]; - const wrapper = mount( ); + const wrapper = mount(); - expect( wrapper.find('p.description') ).toHaveLength(1); - expect( wrapper.find('p.description').text() ).toEqual( 'Expect This' ); + expect(wrapper.find('p.description')).toHaveLength(1); + expect(wrapper.find('p.description').text()).toEqual('Expect This'); }); - it( 'Adds the right description using .desc if .description is not provided to match old spec', () => { + it('Adds the right description using .desc if .description is not provided to match old spec', () => { const thisConfigFields = [ { 'id': 'sz', @@ -163,12 +167,12 @@ describe( 'The render group component', () => { } ]; - const wrapper = mount( ); + const wrapper = mount(); - expect( wrapper.find('p.description').text() ).toEqual( 'Expect This' ); + expect(wrapper.find('p.description').text()).toEqual('Expect This'); }); - it( 'Adds no description if .description is false', () => { + it('Adds no description if .description is false', () => { const thisConfigFields = [ { 'id': 'sz', @@ -178,11 +182,11 @@ describe( 'The render group component', () => { } ]; - const wrapper = mount( ); - expect( wrapper.find('p.description') ).toHaveLength(0); + const wrapper = mount(); + expect(wrapper.find('p.description')).toHaveLength(0); }); - it( 'Adds the label', () => { + it('Adds the label', () => { const thisConfigFields = [ { 'id': 'sz', @@ -193,12 +197,12 @@ describe( 'The render group component', () => { onValueChange: genericHandler } ]; - const wrapper = mount( ); - expect( wrapper.find('label') ).toHaveLength(1); - expect( wrapper.find('label').text() ).toEqual(thisConfigFields[0].label); + const wrapper = mount(); + expect(wrapper.find('label')).toHaveLength(1); + expect(wrapper.find('label').text()).toEqual(thisConfigFields[0].label); }); - it( 'Adds the right label', () => { + it('Adds the right label', () => { const thisConfigFields = [ { 'id': 'sz', @@ -209,8 +213,8 @@ describe( 'The render group component', () => { onValueChange: genericHandler } ]; - const wrapper = mount( ); - expect( wrapper.find('label').text() ).toEqual(thisConfigFields[0].label); + const wrapper = mount(); + expect(wrapper.find('label').text()).toEqual(thisConfigFields[0].label); }); }); @@ -230,30 +234,30 @@ describe( 'The render group component', () => { } ], - value:[], - onValueChange:genericHandler + value: [], + onValueChange: genericHandler }; - describe( 'fieldsets', () => { - it( 'Outputs a fieldset', () => { - const wrapper = mount( ); - expect( wrapper.find('fieldset') ).toHaveLength(1); + describe('fieldsets', () => { + it('Outputs a fieldset', () => { + const wrapper = mount(); + expect(wrapper.find('fieldset')).toHaveLength(1); }); - it( 'has inputs in the fieldset', () =>{ - const wrapper = mount( ); - expect( wrapper.find('fieldset').children().find('input' ) ).toHaveLength(2); + it('has inputs in the fieldset', () => { + const wrapper = mount(); + expect(wrapper.find('fieldset').children().find('input')).toHaveLength(2); }); - it( 'has inputs that are checbkoxes in the fieldset', () =>{ - const wrapper = mount( ); - expect( wrapper.find('fieldset').children().find('input' ).first().prop('type') ).toEqual( 'checkbox' ); + it('has inputs that are checbkoxes in the fieldset', () => { + const wrapper = mount(); + expect(wrapper.find('fieldset').children().find('input').first().prop('type')).toEqual('checkbox'); }); }); - describe( 'class structure', () => { + describe('class structure', () => { const fieldConfigsForThisTest = [ { 'id': 'cf-something-else', @@ -264,26 +268,26 @@ describe( 'The render group component', () => { textFieldConfig ]; - it( 'Puts .caldera-config-field-setup on outermost element', () =>{ - const wrapper = mount( ); - expect( wrapper.find('.caldera-config-field-setup') ).toHaveLength(1); + it('Puts .caldera-config-field-setup on outermost element', () => { + const wrapper = mount(); + expect(wrapper.find('.caldera-config-field-setup')).toHaveLength(1); }); - it( 'It puts .caldera-config-group around each group', () => { - const wrapper = mount( ); + it('It puts .caldera-config-group around each group', () => { + const wrapper = mount(); expect( wrapper.find('.caldera-config-field-setup').children().find('.caldera-config-group') ).toHaveLength(2); }); - it( 'Matches snapshot', () => { + it('Matches snapshot', () => { const component = renderer.create(); - expect( component.toJSON()).toMatchSnapshot(); + expect(component.toJSON()).toMatchSnapshot(); }); }); - describe( 'Select fields', () => { - it( 'Select fields have options', () => { + describe('Select fields', () => { + it('Select fields have options', () => { const selectFieldConfig = { 'id': 'cf-something-select-id', 'type': 'dropdown', @@ -307,13 +311,30 @@ describe( 'The render group component', () => { onValueChange: genericHandler }; - const wrapper = mount( ); + const wrapper = mount(); expect( wrapper.find('select').children().find('option') ).toHaveLength(3); }); - it( 'Select field change handlers receive value, not event ', () => { + it('Select fields can have no options', () => { + const selectFieldConfig = { + 'id': 'cf-something-select-id', + 'type': 'dropdown', + 'label': 'Content type', + 'description': 'Choose content type, default is HTML', + options: null, + value: '', + onValueChange: genericHandler + }; + + const wrapper = mount(); + expect( + wrapper.find('select').children().find('option')//this would make an error if the select field was invalid + ).toHaveLength(0); + }); + + it('Select field change handlers receive value, not event ', () => { let updateValue = ''; const selectFieldConfig = { 'id': 'cf-something-select-id', @@ -341,54 +362,82 @@ describe( 'The render group component', () => { } }; - const wrapper = mount( ); - wrapper.find( 'select' ).simulate('change', { target: { value: 'imaginary' } }); + const wrapper = mount(); + wrapper.find('select').simulate('change', {target: {value: 'imaginary'}}); expect( wrapper.find('select').children().find('option') ).toHaveLength(3); }); }); - describe( 'adding blur and focus', () => { - it( 'Adds the props', () => { - const component = renderer.create( {}, - onFocus: () => {} - }]}/> ); - expect( component.toJSON() ).toMatchSnapshot(); + describe('adding blur and focus', () => { + it('Adds the props', () => { + const component = renderer.create( { + }, + onFocus: () => { + } + }]} + />); + expect(component.toJSON()).toMatchSnapshot(); }); - it( 'Fires the onFocus handler', () => { + it('Passes down the onFocus handler', () => { let itFired = false; - const wrapper = mount( {}, - onFocus: () => { - itFired = true; - } - }]}/> ); - wrapper.find( 'input' ).simulate('focus'); + const idArg = 'a1'; + const wrapper = mount( { + }, + onFocus: () => { + itFired = true; + } + }]} + />); - expect( itFired ).toBe(true); + wrapper.find('input').simulate('focus'); + expect(itFired).toBe(true); }); - it( 'Fires the onBlur handler', () => { + it('Fires the onFocus handler', () => { let itFired = false; - const wrapper = mount( { - itFired = true; - } - }]}/> ); - wrapper.find( 'input' ).simulate('blur'); + const wrapper = mount( { + }, + onFocus: () => { + itFired = true; + } + }]} + />); + wrapper.find('input').simulate('focus'); - expect( itFired ).toBe(true); + expect(itFired).toBe(true); + }); + + it('Fires the onBlur handler', () => { + let itFired = false; + const wrapper = mount( { + itFired = true; + } + }]} + />); + wrapper.find('input').simulate('blur'); + + expect(itFired).toBe(true); }); }); - describe( 'showing component in the child fields', () => { + describe('showing component in the child fields', () => { const successMessage = { message: 'Hi Roy', error: false, @@ -398,28 +447,89 @@ describe( 'The render group component', () => { message: 'Fail' }; - it( 'shows success message', () => { - const wrapper = mount( ); - expect( wrapper.find( '.caldera-components-message' ).text() ).toBe('Hi Roy'); + it('shows success message', () => { + const wrapper = mount(); + expect(wrapper.find('.caldera-components-message').text()).toBe('Hi Roy'); }); - it( 'shows error message', () => { - const wrapper = mount( ); + it('shows error message', () => { + const wrapper = mount(); expect(wrapper.find('.caldera-components-message').text()).toBe('Fail'); }); }); + describe('Magic fields inside render groups', () => { + const magicField = { + 'id': 'cf-magic-example', + 'type': 'magic', + 'label': 'Magic ID', + 'description': 'Select a value from list of magic tags or type a value', + fieldsList: [ + { + label: '0', + value: 0 + }, + { + label: '1', + value: 1 + }, + { + label: '3', + value: 3 + } + ], + systemTagsList: [ + { + label: '3', + value: 3 + } + ], + isOpen: true, + onValueChange: () => { + } + }; + + it('Has the input', () => { + const component = mount( + + ); + expect(component.find('input')).toHaveLength(1); + }); + + it('Get values update ', () => { + let value = '1'; + const component = mount( + { + value = newValue; + } + } + ]}/> + ); + component.find('input').simulate('change', { target: { value: 3 } }); + + expect(value).toBe(3); + }); + + }); + - }); diff --git a/yarn.lock b/yarn.lock index 9368a26..c7f771b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@helpdotcom/is@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@helpdotcom/is/-/is-3.0.4.tgz#009eccf243e837909f93dbd07fc7238db03c189a" + dependencies: + ip-address "~5.8.8" + tldjs "~1.6.2" + "@types/node@*": version "10.3.4" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.3.4.tgz#c74e8aec19e555df44609b8057311052a2c84d9e" @@ -1873,6 +1880,17 @@ cosmiconfig@^2.1.0, cosmiconfig@^2.1.1: parse-json "^2.2.0" require-from-string "^1.1.0" +coveralls@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" + dependencies: + growl "~> 1.10.0" + js-yaml "^3.11.0" + lcov-parse "^0.0.10" + log-driver "^1.2.7" + minimist "^1.2.0" + request "^2.85.0" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -2268,6 +2286,10 @@ dom-converter@~0.1: dependencies: utila "~0.3" +dom-scroll-into-view@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dom-scroll-into-view/-/dom-scroll-into-view-1.0.1.tgz#32abb92f0d8feca6215162aef43e4b449ab8d99c" + dom-serializer@0, dom-serializer@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" @@ -3465,6 +3487,10 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" +"growl@~> 1.10.0": + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -3893,6 +3919,18 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +ip-address@~5.8.8: + version "5.8.9" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-5.8.9.tgz#6379277c23fc5adb20511e4d23ec2c1bde105dfd" + dependencies: + jsbn "1.1.0" + lodash.find "^4.6.0" + lodash.max "^4.0.1" + lodash.merge "^4.6.0" + lodash.padstart "^4.6.1" + lodash.repeat "^4.1.0" + sprintf-js "1.1.0" + ip@^1.1.0, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -4514,7 +4552,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.1: +js-yaml@^3.11.0, js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.1: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" dependencies: @@ -4528,6 +4566,10 @@ js-yaml@~3.7.0: argparse "^1.0.7" esprima "^2.6.0" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -4705,6 +4747,10 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" +lcov-parse@^0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" + leven@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" @@ -4798,6 +4844,10 @@ lodash.filter@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" +lodash.find@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" + lodash.flatten@^4.2.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" @@ -4814,14 +4864,22 @@ lodash.map@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" +lodash.max@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.max/-/lodash.max-4.0.1.tgz#8735566c618b35a9f760520b487ae79658af136a" + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" -lodash.merge@^4.4.0: +lodash.merge@^4.4.0, lodash.merge@^4.6.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" +lodash.padstart@^4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" + lodash.pick@^4.2.1: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" @@ -4834,6 +4892,10 @@ lodash.reject@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" +lodash.repeat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/lodash.repeat/-/lodash.repeat-4.1.0.tgz#fc7de8131d8c8ac07e4b49f74ffe829d1f2bec44" + lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" @@ -4859,6 +4921,10 @@ lodash.uniq@^4.5.0: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" +log-driver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + loglevel@^1.4.1: version "1.6.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" @@ -6248,6 +6314,13 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-autocomplete@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/react-autocomplete/-/react-autocomplete-1.8.1.tgz#ebbbc400006aa91ad538b2d14727b9e7e5d06310" + dependencies: + dom-scroll-into-view "1.0.1" + prop-types "^15.5.10" + react-dev-utils@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-4.2.1.tgz#9f2763e7bafa1a1b9c52254d2a479deec280f111" @@ -6600,7 +6673,7 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@^2.55.0, request@^2.79.0: +request@^2.55.0, request@^2.79.0, request@^2.85.0: version "2.87.0" resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" dependencies: @@ -7067,6 +7140,10 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +sprintf-js@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.0.tgz#cffcaf702daf65ea39bb4e0fa2b299cec1a1be46" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -7370,6 +7447,10 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tldjs@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/tldjs/-/tldjs-1.6.3.tgz#6c2ecbcf5164dc7e73e98b4efe7585d5eea74e2d" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"