vue-modal-dialogs
Advanced tools
Comparing version 1.1.4 to 2.0.0-alpha.1
'use strict' | ||
import { find, findIndex, defaultsDeep } from './util' | ||
/** All dialog wrappers */ | ||
export var wrappers = {} | ||
/* Filter bad wrapper options and add default options */ | ||
function parseWrapperOptions (options) { | ||
if (typeof options !== 'object') { options = {} } | ||
/** | ||
* Map props definition to args. | ||
* | ||
* If the name of the first prop is one of the keys of the first argument, | ||
* that argument will be ignored. | ||
* | ||
* e.g. `makeDialog(component, 'title')({ title: 'some title' })`. | ||
* The `title` will be `'some title'`, not the object `{ title: 'some title' }`. | ||
* This will be less ambiguous. | ||
* | ||
* @param {string[]} props | ||
* @param {any[]} args | ||
*/ | ||
function collectProps (props, args) { | ||
return props.reduce(function (propsData, prop, i) { | ||
if ( | ||
(i !== 0 && args[i] !== undefined) || | ||
typeof args[0] !== 'object' || | ||
args[0][props[0]] === undefined | ||
) { | ||
propsData[prop] = args[i] | ||
} | ||
if (options.wrapper && typeof options.wrapper !== 'object') { | ||
options.wrapper = undefined | ||
} | ||
return propsData | ||
}, {}) | ||
} | ||
if (options.zIndex === false) { | ||
options.zIndex = { | ||
value: null, | ||
autoIncrement: false | ||
/** DialogsWrapper component */ | ||
export default { | ||
name: 'DialogsWrapper', | ||
props: { | ||
name: { | ||
type: String, | ||
default: 'default', | ||
validator: function (value) { return value; } | ||
}, | ||
transitionName: String, | ||
appear: Boolean, | ||
appearActiveClass: String, | ||
appearClass: String, | ||
appearToClass: String, | ||
css: Boolean, | ||
duration: String, | ||
enterActiveClass: String, | ||
enterClass: String, | ||
enterToClass: String, | ||
leaveActiveClass: String, | ||
leaveClass: String, | ||
leaveToClass: String, | ||
moveClass: String, | ||
tag: String, | ||
type: String | ||
}, | ||
data: function () { return ({ | ||
/** An auto-increment id */ | ||
id: 0, | ||
/** All dialogs to render. Dialog render options is stored here */ | ||
dialogs: {} | ||
}); }, | ||
computed: { | ||
dialogIds: function dialogIds () { | ||
return Object.keys(this.dialogs) | ||
} | ||
} else if (options.zIndex && typeof options.zIndex !== 'object') { | ||
options.zIndex = undefined | ||
} | ||
var result = defaultsDeep(options, { | ||
wrapper: { | ||
class: 'modal-dialogs-wrapper', | ||
props: { | ||
tag: 'div', | ||
name: 'modal-dialog' | ||
}, | ||
created: function created () { | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (wrappers[this.name]) { | ||
console.error(("[vue-modal-dialogs] The wrapper '" + (this.name) + "' is already exist. Please make sure that every wrapper has a unique name.")) | ||
} | ||
}, | ||
zIndex: { | ||
value: 1000, | ||
autoIncrement: true | ||
} | ||
}) | ||
return result | ||
} | ||
// Expose wrapper component | ||
if (!wrappers[this.name]) { | ||
wrappers[this.name] = this | ||
} | ||
}, | ||
render: function render (createElement) { | ||
var this$1 = this; | ||
export default function modalWrapperFactory (Vue, wrapperOptions) { | ||
wrapperOptions = parseWrapperOptions(wrapperOptions) | ||
// Render the wrapper as transition-group | ||
return createElement( | ||
'transition-group', | ||
{ | ||
props: Object.assign({}, | ||
this.$attrs, this.$props, | ||
{ name: this.transitionName } | ||
), | ||
on: this.$listeners | ||
}, | ||
this.dialogIds.map(function (dialogId) { | ||
var dialog = this$1.dialogs[dialogId] | ||
return createElement(dialog.component, { | ||
key: dialog.id, | ||
props: dialog.propsData, | ||
on: { 'vue-modal-dialogs:close': dialog.close } | ||
}) | ||
}) | ||
) | ||
}, | ||
methods: { | ||
/** | ||
* Add a new dialog into this wrapper | ||
* | ||
* @private | ||
* @param {Object} options Dialog options created in the `makeDialog` function | ||
* @param {any[]} args Arguments from the dialog function | ||
*/ | ||
add: function add (options, args) { | ||
var id = this.id++ | ||
var resolve | ||
// an auto-increment id to identify dialogs | ||
var _id = 0 | ||
// This promise will be resolved when 'close' function is called | ||
var promise = new Promise(function (res) { resolve = res }) | ||
return Vue.extend({ | ||
name: 'ModalDialogsWrapper', | ||
data: function () { return ({ | ||
dialogs: [] | ||
}); }, | ||
methods: { | ||
// add a new modal dialog into this wrapper | ||
add: function add (dialogOptions, args) { | ||
var this$1 = this; | ||
// Prepare the props of the dialog component | ||
var defaultPropsData = { | ||
dialogId: id, | ||
arguments: args | ||
} | ||
// the unique id of this dialog | ||
var id = _id++ | ||
// If the first argument of the dialog function is an object, | ||
// use it as a part of the propsData | ||
var firstArgObject = typeof args[0] === 'object' ? args[0] : {} | ||
var propsData = Object.assign( | ||
{}, | ||
defaultPropsData, | ||
firstArgObject, | ||
collectProps(options.props, args) | ||
) | ||
// the function for closing this dialog | ||
var close = this.close.bind(this, id) | ||
return this.pushDialog(Object.assign.apply(Object, [ { id: id, propsData: propsData, promise: promise, resolve: resolve } ].concat( options ))) | ||
}, | ||
// this promise will be resolved when 'close' function is called | ||
var promise = new Promise(function (resolve, reject) { | ||
this$1.dialogs.push(Object.freeze({ | ||
id: id, | ||
args: args, | ||
close: close, | ||
promise: promise, | ||
resolve: resolve, | ||
options: defaultsDeep(dialogOptions, { render: {} }), | ||
zIndex: wrapperOptions.zIndex.value | ||
})) | ||
/** | ||
* Add a dialog to `this.dialogs` | ||
* | ||
* @private | ||
* @param {Object} renderOptions Dialog render options generated in the `add` method | ||
* @returns {Promise} The promise | ||
*/ | ||
pushDialog: function pushDialog (renderOptions) { | ||
var this$1 = this; | ||
if (wrapperOptions.zIndex.autoIncrement) { | ||
++wrapperOptions.zIndex.value | ||
} | ||
}).then(function (data) { | ||
var index = findIndex(this$1.dialogs, function (dialog) { return dialog.id === id; }) | ||
if (index > -1) { this$1.dialogs.splice(index, 1) } | ||
return data | ||
}) | ||
// Resolve previously created promise in 'add' method | ||
renderOptions.close = function (data) { | ||
renderOptions.resolve(data) | ||
return renderOptions.promise | ||
} | ||
// inject 'close' function into this promise | ||
promise.close = close | ||
return promise | ||
}, | ||
// close a modal dialog by id | ||
close: function close (id, data) { | ||
var dialog = find(this.dialogs, function (item) { return item.id === id; }) | ||
if (dialog) { | ||
// resolve previously created promise in 'add' method | ||
dialog.resolve(data) | ||
} | ||
// Remove the dialog after it is closed | ||
renderOptions.promise = renderOptions.promise.then(function (data) { | ||
this$1.$delete(this$1.dialogs, renderOptions.id) | ||
return data | ||
}) | ||
return Promise.resolve(dialog ? dialog.promise : null) | ||
} | ||
}, | ||
render: function render (createElement) { | ||
return createElement('transition-group', wrapperOptions.wrapper, this.dialogs.map(function (dialog) { | ||
// map args to props | ||
var props = dialog.options.props.reduce(function (props, prop, i) { | ||
props[prop] = dialog.args[i] | ||
return props | ||
}, { | ||
dialogId: dialog.id, | ||
arguments: dialog.args | ||
}) | ||
// Inject 'close' function into `promise` | ||
renderOptions.promise.close = renderOptions.close | ||
// merge the default render options with user's render options | ||
var renderOptions = defaultsDeep(dialog.options.render, { | ||
key: dialog.id, | ||
style: { zIndex: dialog.zIndex }, | ||
props: props, | ||
on: { 'vue-modal-dialogs:close': dialog.close } | ||
}) | ||
// Use Object.freeze to prevent vue from observing renderOptions | ||
this.$set(this.dialogs, renderOptions.id, Object.freeze(renderOptions)) | ||
// render component | ||
return createElement(dialog.options.component, renderOptions) | ||
})) | ||
return renderOptions.promise | ||
} | ||
}) | ||
} | ||
} |
'use strict' | ||
import diff from 'arr-diff' | ||
import { isVueComponent } from './util' | ||
import dialogsWrapperFactory from './dialogs-wrapper' | ||
export var makeDialog = require('./make-dialog').default | ||
export var DialogsWrapper = require('./dialogs-wrapper').default | ||
var Vue = null | ||
var dialogsWrapper = null | ||
var debug = process.env.NODE_ENV === 'development' | ||
var VueModalDialogs = { | ||
// VueModalDialogs plugin installer | ||
install: function install (vue, options) { | ||
Vue = vue | ||
options = Object.assign({ el: null }, options) | ||
// A mount element for the DialogsWrapper component | ||
var el = options.el | ||
if (typeof el === 'string') { | ||
el = document.querySelector(el) | ||
} | ||
if (el == null) { | ||
el = document.createElement('div') | ||
document.body.insertBefore(el, document.body.childNodes[0]) | ||
} | ||
// Mount the DialogsWrapper component on `el`. | ||
// Dialog components will be added into this wrapper. | ||
var DialogsWrapper = dialogsWrapperFactory(Vue, options) | ||
dialogsWrapper = new DialogsWrapper(options.wrapperComponentOptions) | ||
dialogsWrapper.$mount(el) | ||
/** VueModalDialogs plugin installer */ | ||
install: function install (Vue, options) { | ||
Vue.component('DialogsWrapper', DialogsWrapper) | ||
}, | ||
makeDialog: makeDialog | ||
makeDialog: makeDialog, | ||
DialogsWrapper: DialogsWrapper | ||
} | ||
@@ -39,47 +17,1 @@ | ||
export default VueModalDialogs | ||
// Dialog function maker | ||
export function makeDialog (options) { | ||
var props = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) props[ len ] = arguments[ len + 1 ]; | ||
var component | ||
if (isVueComponent(options)) { | ||
component = options | ||
} else if (isVueComponent(options.component)) { | ||
props = options.props | ||
component = options.component | ||
} else { | ||
if (debug) { console.error('[vue-modal-dialogs] No Vue component specified') } | ||
return | ||
} | ||
// Dialog component and props | ||
var dialogConfig = { | ||
props: props, | ||
// Inject a `$close` function and pre-defined props into dialog component | ||
component: Vue.extend({ | ||
extends: component, | ||
props: diff(['dialogId', 'arguments' ].concat( props), Object.keys(component.props || [])), | ||
methods: { | ||
$close: function $close (data) { | ||
this.$emit('vue-modal-dialogs:close', data) | ||
} | ||
} | ||
}) | ||
} | ||
// Return dialog function | ||
return function dialogFunction () { | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
if (dialogsWrapper) { | ||
// Add dialog component into dialogsWrapper component | ||
return dialogsWrapper.add(dialogConfig, args) | ||
} else if (debug) { | ||
console.error('[vue-modal-dialogs] Plugin not initialized. Please call Vue.use before calling dialog functions.') | ||
} | ||
} | ||
} |
{ | ||
"name": "vue-modal-dialogs", | ||
"version": "1.1.4", | ||
"version": "2.0.0-alpha.1", | ||
"description": "A Promise-based modal dialog helper for Vue.js", | ||
@@ -16,3 +16,4 @@ "main": "dist/index.js", | ||
"dev": "webpack-dev-server", | ||
"lint": "eslint src example" | ||
"lint": "eslint src example", | ||
"test": "NODE_ENV=production BABEL_ENV=test karma start test/karma.conf.js --single-run" | ||
}, | ||
@@ -37,12 +38,13 @@ "repository": { | ||
"devDependencies": { | ||
"@types/express": "^4.0.34", | ||
"@types/webpack": "^2.1.0", | ||
"@types/webpack-merge": "0.0.4", | ||
"autoprefixer": "^6.6.0", | ||
"babel-core": "^6.21.0", | ||
"babel-eslint": "^7.1.1", | ||
"babel-helper-vue-jsx-merge-props": "^2.0.2", | ||
"babel-loader": "^7.1.2", | ||
"babel-plugin-syntax-jsx": "^6.18.0", | ||
"babel-plugin-transform-runtime": "^6.15.0", | ||
"babel-plugin-transform-vue-jsx": "^3.5.0", | ||
"babel-preset-env": "^1.6.0", | ||
"babel-preset-stage-2": "^6.18.0", | ||
"chai": "^4.1.2", | ||
"css-loader": "^0.26.1", | ||
@@ -57,4 +59,13 @@ "eslint": "^3.12.2", | ||
"html-webpack-plugin": "^2.30.1", | ||
"karma": "^1.7.1", | ||
"karma-chrome-launcher": "^2.2.0", | ||
"karma-mocha": "^1.3.0", | ||
"karma-sinon-chai": "^1.3.3", | ||
"karma-sourcemap-loader": "^0.3.7", | ||
"karma-spec-reporter": "^0.0.31", | ||
"karma-webpack": "^2.0.5", | ||
"less": "^2.7.1", | ||
"less-loader": "^2.2.3", | ||
"mocha": "^4.0.1", | ||
"puppeteer": "^0.12.0", | ||
"rollup": "^0.50.0", | ||
@@ -66,7 +77,11 @@ "rollup-plugin-babel": "^2.7.1", | ||
"rollup-plugin-replace": "^2.0.0", | ||
"sinon": "^4.0.2", | ||
"sinon-chai": "^2.14.0", | ||
"style-loader": "^0.13.1", | ||
"uglify-js": "^3.1.0", | ||
"vue-loader": "^13.0.4", | ||
"vue": "^2.5.2", | ||
"vue-loader": "^13.3.0", | ||
"vue-style-loader": "^3.0.3", | ||
"vue-template-compiler": "^2.4.4", | ||
"vue-template-compiler": "^2.5.2", | ||
"vue-test-utils": "^1.0.0-beta.3", | ||
"webpack": "^3.6.0", | ||
@@ -76,9 +91,4 @@ "webpack-dev-server": "^2.8.2" | ||
"dependencies": { | ||
"arr-diff": "^4.0.0", | ||
"for-own": "^0.1.4", | ||
"is-extendable": "^0.1.1" | ||
}, | ||
"peerDependencies": { | ||
"vue": "^2.0.0" | ||
"arr-diff": "^4.0.0" | ||
} | ||
} |
@@ -1,52 +0,10 @@ | ||
import Vue from 'vue' | ||
import Vue, { ComponentOptions } from 'vue' | ||
import { VueConstructor, Vue as _Vue, ExtendedVue } from 'vue/types/vue' | ||
export as namespace VueModalDialogs | ||
export interface PluginOptions { | ||
/** | ||
* Mount point of the wrapper element. All dialogs will be inside this wrapper. | ||
* vue-modal-dialogs automatically creates a new element if that element is not present. | ||
* | ||
* Defaults to `undefined`. | ||
*/ | ||
el?: HTMLElement | string, | ||
/** | ||
* Render options of the wrapper element. | ||
* | ||
* This options is the same to VNode's render option. | ||
* You can pass any props/events supported by the <transition-group> component. | ||
* See https://vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth | ||
*/ | ||
wrapper?: Vue.VNodeData | ||
/** | ||
* Component options of the dialog wrapper component. | ||
*/ | ||
wrapperComponentOptions?: Vue.ComponentOptions<Vue> | ||
/** | ||
* Options to control the `z-index` css property of each dialog. | ||
* This feature guarantees that the newer dialog is always on the top of the older dialogs. | ||
* You can disable this feature by setting this option to `false`. | ||
*/ | ||
zIndex?: { | ||
/** | ||
* The initial value of `z-index`. | ||
* | ||
* Defaults to `1000`. | ||
*/ | ||
value?: number, | ||
/** | ||
* Indicates if the `z-index` auto increases | ||
* when a new modal dialog is shown. | ||
* | ||
* Defaults to `true`. | ||
*/ | ||
autoIncrement?: boolean | ||
} | false | ||
export interface DialogPromise<ReturnType> extends Promise<ReturnType> { | ||
close (data: ReturnType): DialogPromise<ReturnType> | ||
} | ||
/** A Vue component that registered as a dialog */ | ||
export class DialogComponent<T> extends Vue { | ||
export interface DialogComponent<ReturnType> extends Vue { | ||
/** The unique id of this dialog */ | ||
@@ -59,13 +17,11 @@ readonly dialogId: number | ||
/** Close dialog */ | ||
$close (data: T): void | ||
$close (data: ReturnType): DialogPromise<ReturnType> | ||
} | ||
export interface DialogPromise<T> extends Promise<T> { | ||
close (data: T): DialogPromise<T> | ||
} | ||
export type Component<ReturnType, PropsDef> = ComponentOptions<Vue, DialogComponent<ReturnType> & PropsDef> | VueConstructor | ||
/** Options to build a dialog function */ | ||
export interface DialogOptions<T> { | ||
export interface DialogOptions<ReturnType, PropsDef> { | ||
/** A Vue component that will be the 'dialog component' */ | ||
component: DialogComponent<T>, | ||
component: Component<ReturnType, PropsDef>, | ||
@@ -75,24 +31,72 @@ /** An array that maps the argument list to props */ | ||
/** | ||
* Options to render the dialog component. | ||
* | ||
* This is the same to the VNode's render options. | ||
* See https://vuejs.org/v2/guide/render-function.html#The-Data-Object-In-Depth | ||
*/ | ||
render?: Vue.VNodeData | ||
/** The wrapper that the dialog will be added into */ | ||
wrapper: string[] | ||
} | ||
export interface DialogFunction<T> { | ||
(...args: any[]): DialogPromise<T> | ||
interface DialogFunction<ReturnType = any, PropsDef extends object = {}> { | ||
(...args: any[]): DialogPromise<ReturnType> | ||
(data?: PropsDef): DialogPromise<ReturnType> | ||
} | ||
export declare function makeDialog< | ||
ReturnType = any, | ||
PropsDef extends object = {} | ||
> ( | ||
options: DialogOptions<ReturnType, PropsDef> | ||
): DialogFunction<ReturnType, PropsDef> | ||
export declare function makeDialog< | ||
ReturnType = any, | ||
PropsDef extends object = {} | ||
> ( | ||
component: Component<ReturnType, PropsDef> | ||
): (data?: PropsDef) => DialogPromise<ReturnType> | ||
export declare function makeDialog< | ||
ReturnType = any, | ||
Arg1 = any, | ||
PropsDef extends object = {} | ||
> ( | ||
component: Component<ReturnType, PropsDef>, | ||
prop1: string | ||
): (arg1: Arg1) => DialogPromise<ReturnType> | ||
export declare function makeDialog< | ||
ReturnType = any, | ||
Arg1 = any, | ||
Arg2 = any, | ||
PropsDef extends object = {} | ||
> ( | ||
component: Component<ReturnType, PropsDef>, | ||
prop1: string, | ||
prop2: string | ||
): (arg1: Arg1, arg2: Arg2) => DialogPromise<ReturnType> | ||
export declare function makeDialog< | ||
ReturnType = any, | ||
Arg1 = any, | ||
Arg2 = any, | ||
Arg3 = any, | ||
PropsDef extends object = {} | ||
> ( | ||
component: Component<ReturnType, PropsDef>, | ||
prop1: string, | ||
prop2: string, | ||
prop3: string | ||
): (arg1: Arg1, arg2: Arg2, arg3: Arg3) => DialogPromise<ReturnType> | ||
export declare function makeDialog< | ||
ReturnType = any, | ||
PropsDef extends object = {} | ||
> ( | ||
component: Component<ReturnType, PropsDef>, | ||
...props: string[] | ||
): DialogFunction<ReturnType, PropsDef> | ||
/** Dialogs wrapper component */ | ||
export declare const DialogsWrapper: ExtendedVue<Vue, {}, {}, {}, {}> | ||
export interface ModalDialogsInstance { | ||
/** Install `vue-modal-dialogs` into Vue */ | ||
install (vue: typeof Vue, options?: PluginOptions): void, | ||
/** Create a dialog function */ | ||
makeDialog<T> (component: Vue.Component, ...props: string[]): DialogFunction<T>, | ||
/** Create a dialog function */ | ||
makeDialog<T> (options: DialogOptions<T>): DialogFunction<T> | ||
install (vue: typeof _Vue): void | ||
} | ||
@@ -102,7 +106,1 @@ | ||
export default modalDialogs | ||
/** Create a dialog function */ | ||
export function makeDialog<T> (component: Vue.Component, ...props: string[]): DialogFunction<T> | ||
/** Create a dialog function */ | ||
export function makeDialog<T> (options: DialogOptions<T>): DialogFunction<T> |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1
21630
48
317
1
3
1
- Removedfor-own@^0.1.4
- Removedis-extendable@^0.1.1
- Removed@babel/helper-string-parser@7.25.9(transitive)
- Removed@babel/helper-validator-identifier@7.25.9(transitive)
- Removed@babel/parser@7.26.9(transitive)
- Removed@babel/types@7.26.9(transitive)
- Removed@vue/compiler-sfc@2.7.16(transitive)
- Removedcsstype@3.1.3(transitive)
- Removedfor-in@1.0.2(transitive)
- Removedfor-own@0.1.5(transitive)
- Removedis-extendable@0.1.1(transitive)
- Removednanoid@3.3.8(transitive)
- Removedpicocolors@1.1.1(transitive)
- Removedpostcss@8.5.3(transitive)
- Removedprettier@2.8.8(transitive)
- Removedsource-map@0.6.1(transitive)
- Removedsource-map-js@1.2.1(transitive)
- Removedvue@2.7.16(transitive)