{"id":19848115,"url":"https://github.com/shunnnet/vue-use-modal-context","last_synced_at":"2025-05-01T22:30:27.914Z","repository":{"id":197569122,"uuid":"698492680","full_name":"shunnNet/vue-use-modal-context","owner":"shunnNet","description":"Vue modal helpers for simplify modal usage","archived":false,"fork":false,"pushed_at":"2024-08-24T04:31:25.000Z","size":159,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-13T21:05:59.210Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shunnNet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-09-30T04:48:11.000Z","updated_at":"2024-06-27T03:43:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"dbd6926a-7d03-4b74-89a4-dbaeadcb3a05","html_url":"https://github.com/shunnNet/vue-use-modal-context","commit_stats":null,"previous_names":["shunnnet/vue-use-modal-context"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunnNet%2Fvue-use-modal-context","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunnNet%2Fvue-use-modal-context/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunnNet%2Fvue-use-modal-context/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shunnNet%2Fvue-use-modal-context/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shunnNet","download_url":"https://codeload.github.com/shunnNet/vue-use-modal-context/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251954654,"owners_count":21670845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T13:16:11.902Z","updated_at":"2025-05-01T22:30:27.506Z","avatar_url":"https://github.com/shunnNet.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vue-use-modal-context\n[繁體中文](./README.zh-tw.md)\n\nThis is a tool that makes using modals more convenient by using [Vue 3 `provide` / `inject`](https://vuejs.org/guide/components/provide-inject.html). Please familiarize yourself with it before use.\n\nIt provides a simpler way to toggle modals and pass data. It should reduce some of the work when configuring modals.\n\nSupports Vue 3+.\n\nExcludes the modal itself. If you're choosing a modal package, you might consider [vue-final-modal](https://github.com/vue-final/vue-final-modal)。\n\n- [vue-use-modal-context](#vue-use-modal-context)\n  - [Install](#install)\n  - [Tutorial](#tutorial)\n  - [Tutorial - global context](#tutorial---global-context)\n    - [setup global modal](#setup-global-modal)\n  - [documentation](#documentation)\n    - [`useModalContext` and `\u003cModalContext\u003e`](#usemodalcontext-and-modalcontext)\n      - [`\u003cModalContext\u003e`](#modalcontext)\n    - [`useModalProvider` and `\u003cModalProvider\u003e`](#usemodalprovider-and-modalprovider)\n    - [`useModalProvider`](#usemodalprovider)\n    - [`useGlobalModalContext`](#useglobalmodalcontext)\n    - [Types](#types)\n      - [Global components type](#global-components-type)\n\n\n\n## Install\n```sh\nnpm install vue-use-modal-context\n```\n\nYou can globally register the component  `\u003cModalContext\u003e`, `\u003cModalProvider\u003e` using a plugin. (`component: true`)\n\n```ts\nimport { ModalContextPlugin } from \"vue-use-modal-context\"\n\nconst app = createApp(App)\n\napp.use(ModalContextPlugin, { component: true })\n\napp.mount('#app')\n```\n\nAlternatively, you can also import it directly.\n\n```ts\nimport { ModalContext, ModalProvider } from \"vue-use-modal-context\"\n```\n\n[setup global component type](#global-components-type)\n\n## Tutorial \nFirst, let's take a look at a typical example of using a modal.\n\nThis is a situation I often encounter: to set up a modal, I need to configure show, `openModal`, `modalData`, and so on. If there are 10 modals, I have to set it up 10 times.\n\n```vue\n\u003cscript setup\u003e\nimport { ref } from 'vue'\n\nconst show = ref(false)\nconst modalData = ref({\n  userId: 0\n})\n\nconst openModal = (userId) =\u003e {\n  show.value = true\n  modalData.userId = userId\n}\n\nconst onModalClose = () =\u003e {\n  modalData.userId = 0\n}\n\u003c/script\u003e\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cbutton @click=\"openModal(81383)\"\u003eShow user\u003c/button\u003e\n    \u003cUserModal v-model=\"show\" :user-id=\"modalData.userId\" @close=\"onModalClose()\"\u003e\n      \u003c!-- Modal content --\u003e\n    \u003c/UserModal\u003e\n  \u003c/div\u003e\n\n\u003c/template\u003e\n```\n\nNow, let's try using the tools provided by `vue-use-modal-context`, namely `useModalContext` and `ModalProvider`, to simplify this example. First, call `useModalContext()`, and you can obtain `openModal`.\n\n```vue\n\u003c!-- Step 1: call useModalContext --\u003e\n\u003cscript setup\u003e\nimport { useModalContext, ModalProvider } from \"vue-use-modal-context\"\n\nconst { openModal } = useModalContext()\n\u003c/script\u003e\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \n  \u003c/div\u003e\n\u003c/template\u003e\n\n```\n\nNext, you need to add `ModalProvider` to register a modal with the `modalContext`. We registered a modal with the name **UserModal**.\n\n```vue\n\u003c!-- Step 2: use ModalProvider to register modal --\u003e\n\u003cscript setup\u003e\nimport { useModalContext, ModalProvider } from \"vue-use-modal-context\"\n\nconst { openModal } = useModalContext()\n\u003c/script\u003e\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cModalProvider name=\"UserModal\"\u003e\n\n    \u003c/ModalProvider\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n```\n\nNext, you can retrieve the modal's state from the `scoped slot` of `ModalProvider`, which includes `show` and `data`. Connect these two pieces of data to the modal and set the initial data to `init-data`.\n\n```vue\n\u003c!-- Step 3: connect ModalProvider to UserModal --\u003e\n\u003cscript setup\u003e\nimport { useModalContext, ModalProvider } from \"vue-use-modal-context\"\n\nconst { openModal } = useModalContext()\n\u003c/script\u003e\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cModalProvider v-slot=\"{ modal }\" name=\"UserModal\" :init-data=\"{ userId: 0 }\"\u003e\n      \u003cUserModal v-model=\"modal.show\" :user-id=\"modal.data.userId\"  /\u003e\n    \u003c/ModalProvider\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n```\n\nFinally, just add the button to open the modal and bind it to `openModal`.\n\n```vue\n\u003c!-- Step 4: openModal anywhere --\u003e\n\u003cscript setup\u003e\nimport { useModalContext, ModalProvider } from \"vue-use-modal-context\"\n\nconst { openModal } = useModalContext()\n\u003c/script\u003e\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cbutton @click=\"openModal('UserModal', { userId: 81383 })\"\u003eShow user\u003c/button\u003e\n    \u003cModalProvider v-slot=\"{ modal }\" name=\"UserModal\" :init-data=\"{ userId: 0 }\"\u003e\n      \u003cUserModal v-model=\"modal.show\" :user-id=\"modal.data.userId\"  /\u003e\n    \u003c/ModalProvider\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n```\n\nIf you want to add a new modal, you just need to register a new `ModalProvider`.\n\n```vue\n\u003c!-- Step ex: use more modal --\u003e\n\u003cscript setup\u003e\nimport { useModalContext, ModalProvider } from \"vue-use-modal-context\"\n\nconst { openModal } = useModalContext()\n\u003c/script\u003e\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cbutton @click=\"openModal('UserModal', { userId: 81383 })\"\u003eShow user\u003c/button\u003e\n    \u003cbutton @click=\"openModal('OrderModal', { orderId: 233456 })\"\u003eShow order\u003c/button\u003e\n    \u003cbutton @click=\"openModal('PaymentModal', { paymentId: 33445 })\"\u003eShow payment\u003c/button\u003e\n\n    \u003cModalProvider v-slot=\"{ modal }\" name=\"UserModal\" :init-data=\"{ userId: 0 }\"\u003e\n      \u003cUserModal v-model=\"modal.show\" :user-id=\"modal.data.userId\"  /\u003e\n    \u003c/ModalProvider\u003e\n    \n    \u003cModalProvider v-slot=\"{ modal }\" name=\"OrderModal\" :init-data=\"{ orderId: 0 }\"\u003e\n      \u003cUserModal v-model=\"modal.show\" :user-id=\"modal.data.orderId\"  /\u003e\n    \u003c/ModalProvider\u003e\n    \n    \u003cModalProvider v-slot=\"{ modal }\" name=\"PaymentModal\" :init-data=\"{ paymentId: 0 }\"\u003e\n      \u003cUserModal v-model=\"modal.show\" :user-id=\"modal.data.paymentId\"  /\u003e\n    \u003c/ModalProvider\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n```\n\n`useModalContext` also has a component version. If you prefer using components, you can give it a try as well.\n\n```vue\n\u003c!-- Step ex: ModalContext component --\u003e\n\u003cscript setup\u003e\nimport { ModalContext, ModalProvider } from \"vue-use-modal-context\"\n\n\u003c/script\u003e\n\u003ctemplate\u003e\n  \u003cModalContext v-slot=\"{ openModal, closeModal }\"\u003e\n    \u003cdiv\u003e\n      \u003cbutton @click=\"openModal('UserModal', { userId: 81383 })\"\u003eShow user\u003c/button\u003e\n      \u003cbutton @click=\"openModal('OrderModal', { orderId: 233456 })\"\u003eShow order\u003c/button\u003e\n      \u003cbutton @click=\"openModal('PaymentModal', { paymentId: 33445 })\"\u003eShow payment\u003c/button\u003e\n\n      \u003cModalProvider v-slot=\"{ modal }\" name=\"UserModal\" :init-data=\"{ userId: 0 }\"\u003e\n        \u003cUserModal v-model=\"modal.show\" :user-id=\"modal.data.userId\"  /\u003e\n      \u003c/ModalProvider\u003e\n      \n      \u003cModalProvider v-slot=\"{ modal }\" name=\"OrderModal\" :init-data=\"{ orderId: 0 }\"\u003e\n        \u003cUserModal v-model=\"modal.show\" :user-id=\"modal.data.orderId\"  /\u003e\n      \u003c/ModalProvider\u003e\n      \n      \u003cModalProvider v-slot=\"{ modal }\" name=\"PaymentModal\" :init-data=\"{ paymentId: 0 }\"\u003e\n        \u003cUserModal v-model=\"modal.show\" :user-id=\"modal.data.paymentId\"  /\u003e\n      \u003c/ModalProvider\u003e\n    \u003c/div\u003e\n  \u003c/ModalContext\u003e\n\u003c/template\u003e\n```\n\n\n## Tutorial - global context\nYou might need a global modal context that spans across components and contexts. In such cases, you can use `useGlobalModalContext`.\n\nTo use global modal, you need register plugin. Please refer to [document](#install).\n\n### setup global modal\nYou can set `\u003cModalProvider`\u003e anywhere. Remember to set it as `global`.\n\nIt is recommended to use it in the top-level component (e.g., `App.vue`):\n\n```vue\n\u003c!-- App.vue --\u003e\n\u003ctemplate\u003e\n  \u003cModalProvider name=\"LoginModal\" global\u003e\n    \u003c!-- Do anything just like non-global modal --\u003e\n  \u003c/ModalProvider\u003e\n\u003c/template\u003e\n```\n\nThen, you can use `useGlobalModalContext` anywhere.\n\n```vue\n\u003c!-- Child.vue --\u003e\n\u003cscript setup\u003e\nimport { useGlobalModalContext } from \"vue-use-modal-context\"\n\nconst { openGlobalModal, patchGlobalModal, closeGlobalModal, } = useGlobalModalContext()\n\nonMounted(() =\u003e {\n  openGlobalModal(\"LoginModal\")\n})\n\u003c/script\u003e\n```\n\n## documentation\n\n### `useModalContext` and `\u003cModalContext\u003e`\n`useModalContext` is a composition function. It uses the `provide`  to pass modal context data to child components. Additionally, it returns three functions:\n\n- `openModal(name: string, data?: Record\u003cstring, any\u003e) =\u003e void`: Opens the modal with the specified name and passes data. When passing data, it completely overwrites the existing data. Data is optional, but if provided, it must be an object. If not provided, the modal data will be the initial data.\n- `closeModal(name: string) =\u003e void`: Closes the modal with the specified name.\n\n- `patchModal(name: string, data: Record\u003cstring, any\u003e | (data) =\u003e Record\u003cstring, any\u003e) =\u003e void`:  \n  - Updates the data of the specified modal. \n  - It's not an overwrite but rather an update in a way similar to `Object.assign`. \n  - It's recommended to perform patchModal after openModal.\n  - From `0.3.0`, data can be a update function, it receive a current modal data, and it return value will be merged to modal data.\n\n```ts\n// From 0.3.0\n// patch modal by function data\npatchModal(\"UserModal\" ,(currentData) =\u003e {\n  return currentData.userId === 123 ? { \n    order: [\n      ...currentData.order,\n      newOrder\n    ]\n  } : {}\n})\n```\n\n#### `\u003cModalContext\u003e`\n`\u003cModalContext\u003e` is the component version of `useModalContext`, and it is a renderless component. These three functions can also be obtained in the `scoped slot` of the `\u003cModalContext\u003e` component.\n\n```html\n\u003cModalContext v-slot=\"{ openModal, closeModal, patchModal}\"\u003e\n  \u003c!--your content ....--\u003e\n\u003c/ModalContext\u003e\n```\n\nYou can use `ref` to access it methods from `setup`.\n\n```vue\n\u003cscript setup\u003e\nimport { ref, onMounted } from 'vue'\n\nconst ModalContextRef = ref()\nonMounted(() =\u003e {\n  if (ModalContextRef.value){\n    ModalContextRef.value.openModal('UserModal', { userId: 3310 })\n    // or closeModal, patchModal ....\n  }\n})\n\u003c/script\u003e\n\u003ctemplate\u003e\n  \u003cModalContext v-slot=\"{ openModal, closeModal, patchModal}\" ref=\"ModalContextRef\"\u003e\n    \u003c!--your content ....--\u003e\n  \u003c/ModalContext\u003e\n\u003c/template\u003e\n```\n\n### `useModalProvider` and `\u003cModalProvider\u003e`\n`\u003cModalProvider\u003e` is the component version of `useModalProvider` and is a renderless component. It registers the modal within its own `ModalContext`.\n\nIt must be placed inside the `ModalContext`. In other words, its parent component or a higher-level component must have either `useModalContext` or `\u003cModalContext\u003e`.\n\n`\u003cModalProvider\u003e` provides the following parameters:\n\n- `name`: Required. Sets the name of the modal, corresponding to the first argument of openModal.\n- `init-data`: Optional. Determines the initial state of `modal.data`. If not provided, it defaults to `{}`.\n- `global`: `boolean`. Specifies whether it belongs to the globalModalContext. The default is `false` (see [globalModalContext](#useglobalmodalcontext-useglobalmodal)).\n`reset-after-close`: `boolean`. Determines whether to reset data back to `init-data` after closing. The default is `false`.\n\n`\u003cModalProvider\u003e` provides the following `scoped slot`:\n\n- `modal`: Contains the state of the modal and some functions. It is a `reactive` object, so **do not destructure this object**.\n\n  - `modal.show`: boolean, indicating whether the modal is open or closed.\n  - `modal.data`: Defaults to `{}`, and if `init-data` is provided, it defaults to `init-data`. When calling `openModal`, if data is passed, `modal.data` becomes that data. You can also modify `modal.data` when calling `patchModal`.\n  - `closeAnd(fn: () =\u003e any)`: Closes the modal and executes `fn`. Useful when setting event handlers.\n\nHere's an example of using `closeAnd`:\n\n```html\n\u003cModalProvider v-slot=\"{ modal, closeAnd }\" name=\"UserEditModal\" :init-data=\"{ userId: 0 }\"\u003e\n  \u003cModal v-model=\"modal.show\"\u003e\n    \u003cUserForm :user-id=\"modal.data.userId\" @update-sucess=\"closeAnd(fetchUserList)\" /\u003e\n  \u003c/Modal\u003e\n\u003c/ModalProvider\u003e\n```\n\n### `useModalProvider`\n`useModalProvider` is a composition function。`\u003cModalProvder\u003e` use `useModalProvider` internally.\n\nparams:`(name: string, initData: Record\u003cstring, any\u003e = {}, resetAfterClose: boolean = false, global: boolean = false)`\n\n- `name`: Required. Sets the name of the modal, corresponding to the first argument of `openModal`.\n- `initData`: Optional. Determines the initial state of `modal.data`. If not provided, it defaults to `{}`.\n- `resetAfterClose`: `Optional`. Specifies whether to reset data back to `initData` after closing. The default is `false`.\n- `global`: `boolean`. Specifies whether it belongs to the globalModalContext. The default is false (see [globalModalContext](#useglobalmodalcontext-useglobalmodal)).\n\nReturns:\n`modal`: Same as the modal in the \u003cModalProvider\u003e scoped slot.\n\n\n### `useGlobalModalContext`\n`useGlobalModalContext` works the same as `useModalContext`, but manipulate global context. it will returns:\n\n- `openGlobalModal`: Similar to openModal, but can only open global modals.\n- `closeGlobalModal`: Similar to closeModal, but can only close global modals.\n- `patchGlobalModal`: Similar to patchModal, but can only patch global modals.\n\n\n\n### Types\nMost types in this package are exposed. The following explains the most commonly used type settings.\n\n#### Global components type\nWhen you are using globally registered components (e.g: plugin), if you are using `vscode + volar`, you can set the global components type through the following way:\n\n```ts\n// src/components.d.ts\nimport { ModalContext, ModalProvider } from 'vue-use-modal-context'\n\ndeclare module 'vue' {\n  export interface GlobalComponents {\n    ModalContext: typeof ModalContext\n    ModalProvider: typeof ModalProvider\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshunnnet%2Fvue-use-modal-context","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshunnnet%2Fvue-use-modal-context","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshunnnet%2Fvue-use-modal-context/lists"}