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": {
|
"scripts": {
|
||||||
"build": "npm run build:umd & npm run build:es & npm run build:unpkg & npm run build:css",
|
"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: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: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",
|
"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.
|
* Instantiate our base options.
|
||||||
*/
|
*/
|
||||||
constructor () {
|
constructor () {
|
||||||
|
this.options = {}
|
||||||
this.defaults = {
|
this.defaults = {
|
||||||
components: {
|
components: {
|
||||||
FormulateForm,
|
FormulateForm,
|
||||||
@ -43,6 +44,7 @@ class Formulate {
|
|||||||
locale: 'en',
|
locale: 'en',
|
||||||
uploader: fauxUploader,
|
uploader: fauxUploader,
|
||||||
uploadJustCompleteDuration: 1000,
|
uploadJustCompleteDuration: 1000,
|
||||||
|
plugins: [],
|
||||||
locales: {
|
locales: {
|
||||||
en
|
en
|
||||||
}
|
}
|
||||||
@ -54,32 +56,54 @@ class Formulate {
|
|||||||
*/
|
*/
|
||||||
install (Vue, options) {
|
install (Vue, options) {
|
||||||
Vue.prototype.$formulate = this
|
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) {
|
for (var componentName in this.options.components) {
|
||||||
Vue.component(componentName, this.options.components[componentName])
|
Vue.component(componentName, this.options.components[componentName])
|
||||||
}
|
}
|
||||||
Object.freeze(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new object by copying properties of base and extendWith.
|
* Given a set of options, apply them to the pre-existing options.
|
||||||
* @param {Object} base
|
|
||||||
* @param {Object} extendWith
|
* @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 = {}
|
var merged = {}
|
||||||
for (var key in base) {
|
for (var key in base) {
|
||||||
if (extendWith.hasOwnProperty(key)) {
|
if (mergeWith.hasOwnProperty(key)) {
|
||||||
merged[key] = isPlainObject(extendWith[key]) && isPlainObject(base[key])
|
if (isPlainObject(mergeWith[key]) && isPlainObject(base[key])) {
|
||||||
? this.extend(base[key], extendWith[key])
|
merged[key] = this.merge(base[key], mergeWith[key], concatArrays)
|
||||||
: extendWith[key]
|
} else if (concatArrays && Array.isArray(base[key]) && Array.isArray(mergeWith[key])) {
|
||||||
|
merged[key] = base[key].concat(mergeWith[key])
|
||||||
|
} else {
|
||||||
|
merged[key] = mergeWith[key]
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
merged[key] = base[key]
|
merged[key] = base[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var prop in extendWith) {
|
for (var prop in mergeWith) {
|
||||||
if (!merged.hasOwnProperty(prop)) {
|
if (!merged.hasOwnProperty(prop)) {
|
||||||
merged[prop] = extendWith[prop]
|
merged[prop] = mergeWith[prop]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return merged
|
return merged
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Formulate from '../src/Formulate.js'
|
import Formulate from '../src/Formulate.js'
|
||||||
|
|
||||||
test('can extend simple object', () => {
|
test('can merge simple object', () => {
|
||||||
let a = {
|
let a = {
|
||||||
optionA: true,
|
optionA: true,
|
||||||
optionB: '1234'
|
optionB: '1234'
|
||||||
@ -8,14 +8,27 @@ test('can extend simple object', () => {
|
|||||||
let b = {
|
let b = {
|
||||||
optionA: false
|
optionA: false
|
||||||
}
|
}
|
||||||
expect(Formulate.extend(a, b)).toEqual({
|
expect(Formulate.merge(a, b)).toEqual({
|
||||||
optionA: false,
|
optionA: false,
|
||||||
optionB: '1234'
|
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 = {
|
let a = {
|
||||||
optionA: true,
|
optionA: true,
|
||||||
optionC: {
|
optionC: {
|
||||||
@ -33,7 +46,7 @@ test('can extend recursively', () => {
|
|||||||
second: '789',
|
second: '789',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect(Formulate.extend(a, b)).toEqual({
|
expect(Formulate.merge(a, b)).toEqual({
|
||||||
optionA: true,
|
optionA: true,
|
||||||
optionC: {
|
optionC: {
|
||||||
first: '1234',
|
first: '1234',
|
||||||
@ -69,3 +82,20 @@ test('installs on vue instance', () => {
|
|||||||
expect(Vue.prototype.$formulate).toBe(Formulate)
|
expect(Vue.prototype.$formulate).toBe(Formulate)
|
||||||
expect(registry).toEqual(components)
|
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…
x
Reference in New Issue
Block a user