Adds support for plugin architecture
This commit is contained in:
parent
c31e896b86
commit
c0ffcab79f
2
dist/formulate.esm.js
vendored
2
dist/formulate.esm.js
vendored
File diff suppressed because one or more lines are too long
2
dist/formulate.min.js
vendored
2
dist/formulate.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/formulate.umd.js
vendored
2
dist/formulate.umd.js
vendored
File diff suppressed because one or more lines are too long
3
dist/snow.min.css
vendored
3
dist/snow.min.css
vendored
File diff suppressed because one or more lines are too long
@ -16,7 +16,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build:umd & npm run build:es & npm run build:unpkg & npm run build:css",
|
||||
"build:css": "node-sass themes/snow/snow.scss dist/snow.css && postcss --use autoprefixer -b '> 2%' < dist/snow.css | postcss --use cssnano > dist/snow.min.css",
|
||||
"build:css": "node-sass themes/snow/snow.scss dist/snow.css && postcss --use autoprefixer -b '> 2%' < dist/snow.css | postcss --no-map --use cssnano > dist/snow.min.css",
|
||||
"build:umd": "rollup --config build/rollup.config.js --format umd --file dist/formulate.umd.js",
|
||||
"build:es": "rollup --config build/rollup.config.js --format es --file dist/formulate.esm.js",
|
||||
"build:unpkg": "rollup --config build/rollup.config.js --format iife --file dist/formulate.min.js",
|
||||
|
@ -24,6 +24,7 @@ class Formulate {
|
||||
* Instantiate our base options.
|
||||
*/
|
||||
constructor () {
|
||||
this.options = {}
|
||||
this.defaults = {
|
||||
components: {
|
||||
FormulateForm,
|
||||
@ -43,6 +44,7 @@ class Formulate {
|
||||
locale: 'en',
|
||||
uploader: fauxUploader,
|
||||
uploadJustCompleteDuration: 1000,
|
||||
plugins: [],
|
||||
locales: {
|
||||
en
|
||||
}
|
||||
@ -54,32 +56,54 @@ class Formulate {
|
||||
*/
|
||||
install (Vue, options) {
|
||||
Vue.prototype.$formulate = this
|
||||
this.options = this.extend(this.defaults, options || {})
|
||||
this.options = this.merge(this.defaults, options || {})
|
||||
if (Array.isArray(this.options.plugins) && this.options.plugins.length) {
|
||||
this.options.plugins
|
||||
.forEach(plugin => (typeof plugin === 'function') ? plugin(this) : null)
|
||||
}
|
||||
for (var componentName in this.options.components) {
|
||||
Vue.component(componentName, this.options.components[componentName])
|
||||
}
|
||||
Object.freeze(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new object by copying properties of base and extendWith.
|
||||
* @param {Object} base
|
||||
* Given a set of options, apply them to the pre-existing options.
|
||||
* @param {Object} extendWith
|
||||
*/
|
||||
extend (base, extendWith) {
|
||||
extend (extendWith) {
|
||||
if (typeof extendWith === 'object') {
|
||||
this.options = this.merge(this.options, extendWith)
|
||||
return this
|
||||
}
|
||||
throw new Error(`VueFormulate extend() should be passed an object (was ${typeof extendWith})`)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new object by copying properties of base and mergeWith.
|
||||
* Note: arrays don't overwrite - they push
|
||||
*
|
||||
* @param {Object} base
|
||||
* @param {Object} mergeWith
|
||||
* @param {boolean} concatArrays
|
||||
*/
|
||||
merge (base, mergeWith, concatArrays = true) {
|
||||
var merged = {}
|
||||
for (var key in base) {
|
||||
if (extendWith.hasOwnProperty(key)) {
|
||||
merged[key] = isPlainObject(extendWith[key]) && isPlainObject(base[key])
|
||||
? this.extend(base[key], extendWith[key])
|
||||
: extendWith[key]
|
||||
if (mergeWith.hasOwnProperty(key)) {
|
||||
if (isPlainObject(mergeWith[key]) && isPlainObject(base[key])) {
|
||||
merged[key] = this.merge(base[key], mergeWith[key], concatArrays)
|
||||
} else if (concatArrays && Array.isArray(base[key]) && Array.isArray(mergeWith[key])) {
|
||||
merged[key] = base[key].concat(mergeWith[key])
|
||||
} else {
|
||||
merged[key] = mergeWith[key]
|
||||
}
|
||||
} else {
|
||||
merged[key] = base[key]
|
||||
}
|
||||
}
|
||||
for (var prop in extendWith) {
|
||||
for (var prop in mergeWith) {
|
||||
if (!merged.hasOwnProperty(prop)) {
|
||||
merged[prop] = extendWith[prop]
|
||||
merged[prop] = mergeWith[prop]
|
||||
}
|
||||
}
|
||||
return merged
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Formulate from '../src/Formulate.js'
|
||||
|
||||
test('can extend simple object', () => {
|
||||
test('can merge simple object', () => {
|
||||
let a = {
|
||||
optionA: true,
|
||||
optionB: '1234'
|
||||
@ -8,14 +8,27 @@ test('can extend simple object', () => {
|
||||
let b = {
|
||||
optionA: false
|
||||
}
|
||||
expect(Formulate.extend(a, b)).toEqual({
|
||||
expect(Formulate.merge(a, b)).toEqual({
|
||||
optionA: false,
|
||||
optionB: '1234'
|
||||
})
|
||||
})
|
||||
|
||||
test('can add to simple array', () => {
|
||||
let a = {
|
||||
optionA: true,
|
||||
optionB: ['first', 'second']
|
||||
}
|
||||
let b = {
|
||||
optionB: ['third']
|
||||
}
|
||||
expect(Formulate.merge(a, b, true)).toEqual({
|
||||
optionA: true,
|
||||
optionB: ['first', 'second', 'third']
|
||||
})
|
||||
})
|
||||
|
||||
test('can extend recursively', () => {
|
||||
test('can merge recursively', () => {
|
||||
let a = {
|
||||
optionA: true,
|
||||
optionC: {
|
||||
@ -33,7 +46,7 @@ test('can extend recursively', () => {
|
||||
second: '789',
|
||||
}
|
||||
}
|
||||
expect(Formulate.extend(a, b)).toEqual({
|
||||
expect(Formulate.merge(a, b)).toEqual({
|
||||
optionA: true,
|
||||
optionC: {
|
||||
first: '1234',
|
||||
@ -69,3 +82,20 @@ test('installs on vue instance', () => {
|
||||
expect(Vue.prototype.$formulate).toBe(Formulate)
|
||||
expect(registry).toEqual(components)
|
||||
})
|
||||
|
||||
test('can extend instance in a plugin', () => {
|
||||
function Vue () {}
|
||||
Vue.component = function (name, instance) {}
|
||||
const plugin = function (i) {
|
||||
i.extend({
|
||||
rules: {
|
||||
testRule: () => false
|
||||
}
|
||||
})
|
||||
}
|
||||
Formulate.install(Vue, {
|
||||
plugins: [ plugin ]
|
||||
})
|
||||
|
||||
expect(typeof Vue.prototype.$formulate.options.rules.testRule).toBe('function')
|
||||
})
|
||||
|
109
themes/boilerplate/boilerplate.scss
Normal file
109
themes/boilerplate/boilerplate.scss
Normal file
@ -0,0 +1,109 @@
|
||||
// Formulate inputs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
.formulate-input {
|
||||
// global wrapper styles
|
||||
|
||||
.formulate-input-label {
|
||||
// global label styles
|
||||
}
|
||||
|
||||
.formulate-input-element {
|
||||
// Global field-level wrapper styles
|
||||
}
|
||||
|
||||
.formulate-input-help {
|
||||
// Global help text styles
|
||||
}
|
||||
|
||||
.formulate-input-errors {
|
||||
// Global error message list wrapper
|
||||
}
|
||||
|
||||
.formulate-input-error,
|
||||
.formulate-file-upload-error {
|
||||
// Error message styles
|
||||
}
|
||||
|
||||
.formulate-input-group-item {
|
||||
// Group of items (like list of checkboxes) wrapper
|
||||
}
|
||||
|
||||
// Text inputs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
&[data-classification='text'] {
|
||||
input {
|
||||
// Style all text-like input elements
|
||||
}
|
||||
}
|
||||
|
||||
// Slider inputs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
&[data-classification='slider'] {
|
||||
input {
|
||||
// Style range inputs
|
||||
}
|
||||
}
|
||||
|
||||
// Textarea inputs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
&[data-classification='textarea'] {
|
||||
textarea {
|
||||
// Style textareas
|
||||
}
|
||||
}
|
||||
|
||||
// Button inputs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
&[data-classification='button'] {
|
||||
button {
|
||||
// Style button inputs
|
||||
}
|
||||
}
|
||||
|
||||
// Select lists
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
&[data-classification='select'] {
|
||||
select {
|
||||
// Style select lists
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Box inputs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
&[data-classification='box'] {
|
||||
.formulate-input-element {
|
||||
// Box input (checkbox and radio) wrapper (might want flex here)
|
||||
input {
|
||||
// Style box element itself
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// File inputs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
&[data-classification="file"] {
|
||||
.formulate-input-upload-area {
|
||||
input {
|
||||
// The actual upload element
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Image uploads
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
[data-type="image"] {
|
||||
// image uploads
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user