diff --git a/api-generator/components/dynamicdialog.js b/api-generator/components/dynamicdialog.js new file mode 100644 index 000000000..270742556 --- /dev/null +++ b/api-generator/components/dynamicdialog.js @@ -0,0 +1,15 @@ +const DynamicDialogProps = []; + +const DynamicDialogEvents = []; + +const DynamicDialogSlots = []; + +module.exports = { + dynamicdialog: { + name: "DynamicDialog", + description: "Dialogs can be created dynamically with any component as the content using a DialogService.", + props: DynamicDialogProps, + events: DynamicDialogEvents, + slots: DynamicDialogSlots + } +}; diff --git a/package.json b/package.json index 61bfe6b88..37a3ca21b 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "gulp-uglify": "^3.0.2", "gulp-uglifycss": "^1.0.6", "sass": "^1.45.0", - "primeflex": "3.1.2", + "primeflex": "3.2.1", "primeicons": "5.0.0", "prismjs": "^1.15.0", "quill": "^1.3.7", diff --git a/rollup.config.js b/rollup.config.js index 11e325c34..edfccf15a 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -20,9 +20,11 @@ let coreDependencies = { 'primevue/confirmationeventbus': 'primevue.confirmationeventbus', 'primevue/toasteventbus': 'primevue.toasteventbus', 'primevue/overlayeventbus': 'primevue.overlayeventbus', + 'primevue/dynamicdialogeventbus': 'primevue.dynamicdialogeventbus', 'primevue/terminalservice': 'primevue.terminalservice', 'primevue/useconfirm': 'primevue.useconfirm', 'primevue/usetoast': 'primevue.usetoast', + 'primevue/usedialog': 'primevue.usedialog', 'primevue/button': 'primevue.button', 'primevue/inputtext': 'primevue.inputtext', 'primevue/inputnumber': 'primevue.inputnumber', @@ -182,6 +184,9 @@ function addServices() { addEntry('overlayeventbus', 'OverlayEventBus.js', 'overlayeventbus'); addEntry('usetoast', 'UseToast.js', 'usetoast'); addEntry('terminalservice', 'TerminalService.js', 'terminalservice'); + addEntry('usedialog', 'UseDialog.js', 'usedialog'); + addEntry('dialogservice', 'DialogService.js', 'dialogservice'); + addEntry('dynamicdialogeventbus', 'DynamicDialogEventBus.js', 'dynamicdialogeventbus'); } addUtils(); diff --git a/src/assets/menu/menu.json b/src/assets/menu/menu.json index b049bb4ea..88012454c 100644 --- a/src/assets/menu/menu.json +++ b/src/assets/menu/menu.json @@ -580,6 +580,10 @@ "name": "Dialog", "to": "/dialog" }, + { + "name": "DynamicDialog", + "to": "/dynamicdialog" + }, { "name": "OverlayPanel", "to": "/overlaypanel" diff --git a/src/components/dialogservice/DialogService.d.ts b/src/components/dialogservice/DialogService.d.ts new file mode 100644 index 000000000..c63008ae9 --- /dev/null +++ b/src/components/dialogservice/DialogService.d.ts @@ -0,0 +1,47 @@ +import { Plugin, VNode } from 'vue'; +import { DynamicDialogOptions } from '../dynamicdialogoptions'; + +declare const plugin: Plugin; +export default plugin; + +export interface DialogInstance { + /** + * Dynamic component for content template + */ + content: VNode | undefined; + /** + * Instance options + * @see DynamicDialogOptions + */ + options: DynamicDialogOptions; + /** + * Custom data object + */ + data: any; + /** + * Hides the dialog. + * @param {*} params - Parameters sent by the user to the root instance + */ + hide: (params?: any) => void; +} + +export interface DialogServiceMethods { + /** + * Displays the dialog using the dynamic dialog object options. + * @param {VNode} content - Dynamic component for content template + * @param {DynamicDialogOptions} options - DynamicDialog Object + */ + open(content: VNode, options?: DynamicDialogOptions): DialogInstance; +} + +declare module 'vue/types/vue' { + interface Vue { + $dialog: DialogServiceMethods; + } +} + +declare module '@vue/runtime-core' { + interface ComponentCustomProperties { + $dialog: DialogServiceMethods; + } +} diff --git a/src/components/dialogservice/DialogService.js b/src/components/dialogservice/DialogService.js new file mode 100644 index 000000000..d90477e54 --- /dev/null +++ b/src/components/dialogservice/DialogService.js @@ -0,0 +1,28 @@ +import { markRaw } from 'vue'; +import { PrimeVueDialogSymbol } from 'primevue/usedialog'; +import DynamicDialogEventBus from 'primevue/dynamicdialogeventbus'; + +export default { + install: (app) => { + const DialogService = { + open: (content, options) => { + const instance = { + content: content && markRaw(content), + options: options || {}, + data: options && options.data, + hide: (params) => { + DynamicDialogEventBus.emit('close', { instance, params }); + } + } + + DynamicDialogEventBus.emit('open', { instance }); + + return instance; + } + }; + + app.config.unwrapInjectedRef = true; // Remove it after Vue 3.3. Details: https://vuejs.org/guide/components/provide-inject.html#working-with-reactivity + app.config.globalProperties.$dialog = DialogService; + app.provide(PrimeVueDialogSymbol, DialogService); + } +} diff --git a/src/components/dialogservice/package.json b/src/components/dialogservice/package.json new file mode 100644 index 000000000..830106d56 --- /dev/null +++ b/src/components/dialogservice/package.json @@ -0,0 +1,6 @@ +{ + "main": "./dialogservice.cjs.js", + "module": "./dialogservice.esm.js", + "unpkg": "./dialogservice.min.js", + "types": "./DialogService.d.ts" +} diff --git a/src/components/dynamicdialog/DynamicDialog.d.ts b/src/components/dynamicdialog/DynamicDialog.d.ts new file mode 100644 index 000000000..d15d27ba6 --- /dev/null +++ b/src/components/dynamicdialog/DynamicDialog.d.ts @@ -0,0 +1,26 @@ +import { ClassComponent, GlobalComponentConstructor } from '../ts-helpers'; + +export interface DynamicDialogProps {} + +export declare type DynamicDialogEmits = {} + +export interface DynamicDialogSlots {} + +declare class DynamicDialog extends ClassComponent { } + +declare module '@vue/runtime-core' { + interface GlobalComponents { + DynamicDialog: GlobalComponentConstructor + } +} + +/** + * + * DynamicDialogs can be created dynamically with any component as the content using a DialogService. + * + * Demos: + * + * - [DynamicDialog](https://www.primefaces.org/primevue/showcase/#/dynamicdialog) + * + */ +export default DynamicDialog; diff --git a/src/components/dynamicdialog/DynamicDialog.vue b/src/components/dynamicdialog/DynamicDialog.vue new file mode 100644 index 000000000..28852d395 --- /dev/null +++ b/src/components/dynamicdialog/DynamicDialog.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/components/dynamicdialog/package.json b/src/components/dynamicdialog/package.json new file mode 100644 index 000000000..c0fc64e5d --- /dev/null +++ b/src/components/dynamicdialog/package.json @@ -0,0 +1,9 @@ +{ + "main": "./dynamicdialog.cjs.js", + "module": "./dynamicdialog.esm.js", + "unpkg": "./dynamicdialog.min.js", + "types": "./DynamicDialog.d.ts", + "browser": { + "./sfc": "./DynamicDialog.vue" + } +} diff --git a/src/components/dynamicdialogeventbus/DynamicDialogEventBus.js b/src/components/dynamicdialogeventbus/DynamicDialogEventBus.js new file mode 100644 index 000000000..602940783 --- /dev/null +++ b/src/components/dynamicdialogeventbus/DynamicDialogEventBus.js @@ -0,0 +1,3 @@ +import { EventBus } from 'primevue/utils'; + +export default EventBus(); diff --git a/src/components/dynamicdialogeventbus/package.json b/src/components/dynamicdialogeventbus/package.json new file mode 100644 index 000000000..c23adbd52 --- /dev/null +++ b/src/components/dynamicdialogeventbus/package.json @@ -0,0 +1,5 @@ +{ + "main": "./dynamicdialogeventbus.cjs.js", + "module": "./dynamicdialogeventbus.esm.js", + "unpkg": "./dynamicdialogeventbus.min.js" +} diff --git a/src/components/dynamicdialogoptions/DynamicDialogOptions.d.ts b/src/components/dynamicdialogoptions/DynamicDialogOptions.d.ts new file mode 100644 index 000000000..7093820e8 --- /dev/null +++ b/src/components/dynamicdialogoptions/DynamicDialogOptions.d.ts @@ -0,0 +1,53 @@ +import { VNode } from 'vue'; +import { DialogProps } from '../dialog'; + +export type DynamicDialogHideType = 'config-close' | 'dialog-close' | undefined; + +export interface DynamicDialogTemplates { + /** + * Custom header template. + */ + header: () => VNode[]; + /** + * Custom footer template. + */ + footer: () => VNode[]; +} + +export interface DynamicDialogHideOptions { + /** + * Custom data object + */ + data?: any; + /** + * Hide type + * @see DynamicDialogHideType + */ + type: DynamicDialogHideType; +} + +export interface DynamicDialogOptions { + /** + * Dialog Props + * @see DialogProps + */ + props?: DialogProps; + /** + * Dialog Slots + * @see DynamicDialogTemplates + */ + templates?: DynamicDialogTemplates; + /** + * Custom data object + */ + data?: any; + /** + * Hides the dialog. + * @see DynamicDialogHideOptions + */ + onHide?: (options?: DynamicDialogHideOptions) => void; + /** + * Optional + */ + [key: string]: any; +} diff --git a/src/components/dynamicdialogoptions/package.json b/src/components/dynamicdialogoptions/package.json new file mode 100644 index 000000000..2f003bf5c --- /dev/null +++ b/src/components/dynamicdialogoptions/package.json @@ -0,0 +1,3 @@ +{ + "types": "./DynamicDialogOptions.d.ts" +} diff --git a/src/components/usedialog/UseDialog.d.ts b/src/components/usedialog/UseDialog.d.ts new file mode 100644 index 000000000..cb655ca6c --- /dev/null +++ b/src/components/usedialog/UseDialog.d.ts @@ -0,0 +1,6 @@ +//import { DynamicDialogOptions } from '../dynamicdialogoptions'; + +export declare function useDialog(): { + open: (dialog: any) => void; + close: () => void; +} diff --git a/src/components/usedialog/UseDialog.js b/src/components/usedialog/UseDialog.js new file mode 100644 index 000000000..21fa4a313 --- /dev/null +++ b/src/components/usedialog/UseDialog.js @@ -0,0 +1,12 @@ +import { inject } from 'vue'; + +export const PrimeVueDialogSymbol = Symbol(); + +export function useDialog() { + const PrimeVueDialog = inject(PrimeVueDialogSymbol); + if (!PrimeVueDialog) { + throw new Error('No PrimeVue Dialog provided!'); + } + + return PrimeVueDialog; +} \ No newline at end of file diff --git a/src/components/usedialog/package.json b/src/components/usedialog/package.json new file mode 100644 index 000000000..3ebad32fc --- /dev/null +++ b/src/components/usedialog/package.json @@ -0,0 +1,6 @@ +{ + "main": "./usedialog.cjs.js", + "module": "./usedialog.esm.js", + "unpkg": "./usedialog.min.js", + "types": "./UseDialog.d.ts" +} \ No newline at end of file diff --git a/src/components/utils/ObjectUtils.js b/src/components/utils/ObjectUtils.js index 3f153531d..36e145d0a 100755 --- a/src/components/utils/ObjectUtils.js +++ b/src/components/utils/ObjectUtils.js @@ -86,6 +86,10 @@ export default { return !!(obj && obj.constructor && obj.call && obj.apply); }, + getItemValue(obj, ...params) { + return this.isFunction(obj) ? obj(...params) : obj; + }, + filter(value, fields, filterValue) { var filteredItems = []; diff --git a/src/main.js b/src/main.js index e1d46977d..fbfcb753a 100644 --- a/src/main.js +++ b/src/main.js @@ -33,6 +33,8 @@ import DataView from './components/dataview/DataView'; import DataViewLayoutOptions from './components/dataviewlayoutoptions/DataViewLayoutOptions'; import DeferredContent from './components/deferredcontent/DeferredContent'; import Dialog from './components/dialog/Dialog'; +import DynamicDialog from './components/dynamicdialog/DynamicDialog'; +import DialogService from './components/dialogservice/DialogService'; import Divider from './components/divider/Divider'; import Dock from './components/dock/Dock'; import Dropdown from './components/dropdown/Dropdown'; @@ -128,6 +130,7 @@ app.config.globalProperties.$appState = reactive({theme: 'lara-light-blue', dark app.use(PrimeVue, {ripple: true}); app.use(ToastService); app.use(ConfirmationService); +app.use(DialogService); app.use(router); app.directive('badge', BadgeDirective); @@ -163,6 +166,7 @@ app.component('DataView', DataView); app.component('DataViewLayoutOptions', DataViewLayoutOptions); app.component('DeferredContent', DeferredContent); app.component('Dialog', Dialog); +app.component('DynamicDialog', DynamicDialog); app.component('Divider', Divider); app.component('Dock', Dock); app.component('Dropdown', Dropdown); diff --git a/src/router/index.js b/src/router/index.js index 695dd2811..ed1f590f8 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -349,6 +349,11 @@ const routes = [ name: 'dropdown', component: () => import('../views/dropdown/DropdownDemo.vue') }, + { + path: '/dynamicdialog', + name: 'dynamicdialog', + component: () => import('../views/dynamicdialog/DynamicDialogDemo.vue') + }, { path: '/editor', name: 'editor', diff --git a/src/views/dynamicdialog/DynamicDialogDemo.vue b/src/views/dynamicdialog/DynamicDialogDemo.vue new file mode 100644 index 000000000..1dde3fc43 --- /dev/null +++ b/src/views/dynamicdialog/DynamicDialogDemo.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/views/dynamicdialog/InfoDemo.vue b/src/views/dynamicdialog/InfoDemo.vue new file mode 100644 index 000000000..12337bcac --- /dev/null +++ b/src/views/dynamicdialog/InfoDemo.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/views/dynamicdialog/ProductListDemo.vue b/src/views/dynamicdialog/ProductListDemo.vue new file mode 100644 index 000000000..57c117f8e --- /dev/null +++ b/src/views/dynamicdialog/ProductListDemo.vue @@ -0,0 +1,54 @@ + + + diff --git a/vue.config.js b/vue.config.js index a7e8189d3..5fec322dc 100644 --- a/vue.config.js +++ b/vue.config.js @@ -10,6 +10,7 @@ module.exports = { 'primevue/tooltip': path.resolve(__dirname, 'src/components/tooltip/Tooltip.js'), 'primevue/useconfirm': path.resolve(__dirname, 'src/components/useconfirm/UseConfirm.js'), 'primevue/usetoast': path.resolve(__dirname, 'src/components/usetoast/UseToast.js'), + 'primevue/usedialog': path.resolve(__dirname, 'src/components/usedialog/UseDialog.js'), 'primevue/utils': path.resolve(__dirname, 'src/components/utils/Utils.js'), 'primevue/api': path.resolve(__dirname, 'src/components/api/Api.js'), 'primevue/portal': path.resolve(__dirname, 'src/components/portal/Portal.vue'), @@ -28,6 +29,7 @@ module.exports = { 'primevue/toasteventbus': path.resolve(__dirname, 'src/components/toasteventbus/ToastEventBus.js'), 'primevue/overlayeventbus': path.resolve(__dirname, 'src/components/overlayeventbus/OverlayEventBus.js'), 'primevue/terminalservice': path.resolve(__dirname, 'src/components/terminalservice/TerminalService.js'), + 'primevue/dynamicdialogeventbus': path.resolve(__dirname, 'src/components/dynamicdialogeventbus/DynamicDialogEventBus.js'), 'primevue/virtualscroller': path.resolve(__dirname, 'src/components/virtualscroller/VirtualScroller.vue') }, },