From fd4dd6394680c953004b1dc8c8049dad5910227c Mon Sep 17 00:00:00 2001 From: mlmoravek Date: Tue, 21 Jan 2025 16:18:46 +0100 Subject: [PATCH] docs: add Composable documentation --- packages/docs/.vitepress/config.ts | 4 + packages/docs/documentation/composables.md | 236 ++++++++++++++++++ packages/docs/documentation/customisation.md | 92 +------ .../oruga/src/components/loading/index.ts | 6 +- .../tests/useLoadingProgrammatic.test.ts | 10 +- .../loading/useLoadingProgrammatic.ts | 16 +- packages/oruga/src/components/modal/index.ts | 6 +- .../modal/tests/useModalProgrammatic.test.ts | 10 +- .../components/modal/useModalProgrammatic.ts | 20 +- .../src/components/notification/index.ts | 6 +- .../tests/useNotificationProgrammatic.test.ts | 10 +- .../useNotificationProgrammatic.ts | 18 +- .../programmatic/ProgrammaticComponent.ts | 4 +- .../src/components/programmatic/index.ts | 12 +- .../tests/useProgrammatic.test.ts | 28 +-- .../programmatic/useProgrammatic.ts | 10 +- .../oruga/src/components/sidebar/index.ts | 6 +- .../tests/useSidebarProgrammatic.test.ts | 10 +- .../sidebar/useSidebarProgrammatic.ts | 18 +- 19 files changed, 338 insertions(+), 184 deletions(-) create mode 100644 packages/docs/documentation/composables.md diff --git a/packages/docs/.vitepress/config.ts b/packages/docs/.vitepress/config.ts index 2e0c348b8..43356eb95 100644 --- a/packages/docs/.vitepress/config.ts +++ b/packages/docs/.vitepress/config.ts @@ -34,6 +34,10 @@ const getStartedItems = [ text: "Themes", link: "/documentation/themes", }, + { + text: "Composable", + link: "/documentation/composables", + }, ]; export default defineConfig({ diff --git a/packages/docs/documentation/composables.md b/packages/docs/documentation/composables.md new file mode 100644 index 000000000..68250e657 --- /dev/null +++ b/packages/docs/documentation/composables.md @@ -0,0 +1,236 @@ +# Composable + +Besides the main Vue plugin and the components, Oruga provides a programmatic composable `useOruga()`, which can be used to access the config as well as any registered programmatic component interfaces. A programmatic component interface will be registered when using the main plugin or any individual component plugin. + +The composable can be imported by: + +```typescript +import { useOruga } from "@oruga-ui/oruga-next"; +``` + + +## Programmatic config {#config} + +The `config` interface can be used to customise the Oruga [global configuration](/documentation/customisation) by overriding the `Config` object programmatically: + +```typescript +import { useOruga } from '@oruga-ui/oruga-next'; + +const oruga = useOruga(); + +// get the current config +const config = oruga.config.getOptions(); + +// modify the config object +const myThemeConfig = { + ...config, + autocomplete: { + rootClass: 'autocomplete-root', + itemClass: 'autocomplete-item', + ... + } +} + +// update the config +oruga.config.setOptions(myThemeConfig); +``` + +However, you can also customise each component by using the dedicated `ConfigProgrammatic` object, which is the same as the one added to the object provided by the main `useOruga()` composable: + +```typescript +import { ConfigProgrammatic } from '@oruga-ui/oruga-next'; + +// get the current config +const config = ConfigProgrammatic.getOptions(); + +// modify the config object +const myThemeConfig = { + ...config, + autocomplete: { + rootClass: 'autocomplete-root', + itemClass: 'autocomplete-item', + ... + } +} + +// update the config +ConfigProgrammatic.setOptions(myThemeConfig); +``` + +### Individual config plugin {#configplugin} + +If you use individual component plugins instead of the default main Oruga plugin, the programmatic config will **not** be registered to the `useOruga()` composable by default. +Therefore, you can make the config interface available by adding the special `OrugaConfig` plugin. As a second parameter you can pass an optional config object like the main Oruga plugin. + +```typescript +import { createApp } from 'vue'; +import { Autocomplete, Sidebar, OrugaConfig, useOruga } from '@oruga-ui/oruga-next'; + +const myConfig = { ... }; + +createApp(...) + // register individual components by using their dedicated vue plugin + .use(Autocomplete) + .use(Sidebar) + // register the global oruga config plugin + .use(OrugaConfig, myConfig); + +const oruga = useOruga(); + +// now this is available +const config = oruga.config.getOptions(); + +config.setOption("autocomplete", { + rootClass: 'autocomplete-root', + itemClass: 'autocomplete-item', + ... +}); + +config.setOption("sidebar", { ... }); +``` + + +## Programmatic components {#components} + +Some components come with their own programmatic interface. These interfaces will be registered and added to the main `useOruga()` composable when using the default main Oruga plugin or the individual plugin for the component. + +> ***Note:*** The programmatic interfaces will not be added if you only use the component itself and not its dedicated plugin. + + +List of components with an programmatic interface: + +- [`Loading`](/components/Loading.html#programmatically) +- [`Modal`](/components/Modal.html#programmatically) +- [`Notification`](/components/Notification.html#programmatically) +- [`Sidebar`](/components/Sidebar.html#programmatically) + +You can access each component's programmatic interface using the `useOruga()` composable. +To create a new instance of the component, you need to call the `open()` function. The open function takes two arguments. First, an object with the props of the individual component, and second, a target where the component should be mounted. + +```typescript +import { useOruga } from "@oruga-ui/oruga-next"; + +const oruga = useOruga(); + +const target = document.body; + +oruga.sidebar.open({ + component: MyCoolComponent, + fullheight: true, + overlay: true, +}, target); +``` + +You can also access the programmatic interface of a component by using the dedicated object, which is the same as the one added to the object provided by the main `useOruga()` composable. For example: + +```typescript +import { NotificationProgrammatic } from '@oruga-ui/oruga-next'; + +NotificationProgrammatic.open({ + duration: 5000, + message: "You did a greate job!", + variant: "info", + position: "top", + closable: true, +}); +``` + +### Programmatic interface {#interface} + +The object for each programmatic interface of a component looks like this: + +```typescript +type ProgrammaticInterface = { + /** Returns the number of registered active instances. */ + count: () => number; + /** + * Create a new programmatic component instance. + * The options argument depend on the component. + * The target specifies the element the component get rendered into - default is `document.body`. + */ + open: (options: Record, target?: string | HTMLElement) => ProgrammaticExpose; + /** + * Close the last registred instance in the programmatic instance registry. + * Any arguments which get passed to the exposed `close()` function of the component. + */ + close: (...args: unknown[]) => void; + /** + * Close all instances in the programmatic instance registry. + * Any arguments which get passed to the exposed `close()` function of the component. + */ + closeAll: (...args: unknown[]) => void; +}; + +type ProgrammaticExpose = { + /** Call the close event of the component. */ + close: (...args: unknown[]) => void; + /** Promise which get resolved on the close event. */ + promise: Promise; +}; +``` + +## Component Programmatic {#programmatic} +Oruga comes with a component that is only available programmatically. This component can be used to mount **any** custom component programmatically, using the [Vue render function](https://vuejs.org/api/render-function.html#render-function-apis) and [Creating Vnodes](https://vuejs.org/guide/extras/render-function.html#render-function-recipes). + +The component works as follows: The programmatic component renders a wrapper component in a sperate shadow Vue instance. The separate Vue instance will have the same context object as the current one. The provided component is then rendered in a wrapper component that handles the Vue lifecycle events of the provided component. +The rendered component is then extracted from the shadow Vue instance and placed into the target container of the real DOM instance. +By closing the instance of the wrapper component, for example by calling `oruga.programmatic.close()` from outside, or by firing a `close` event from inside the provided component, the wrapper component and the shadow Vue instance will be destroyed and DOM will be cleaned up. + +> ***Note:*** When using the programmatic component, you may experience some DX issues if you run the Vue Devtools and inspect the programmatic component. + +By adding this component using the main Oruga plugin or the dedicated `ComponentProgrammatic` plugin, the component adds an interface `programmatic` to the `useOruga()` composable and provides the `ComponentProgrammatic` object export, but it does not have a Vue component to mount directly. + +```typescript +import { useOruga } from "@oruga-ui/oruga-next"; +import MyComponent from "..."; + +const oruga = useOruga(); + +const slot = "My default slot content"; + +oruga.programmatic.open( + MyComponent, + { + target: document.body, // target the component get rendered into + props: { ... }, // component specific props + onClose: (...args: unknown[]) => { ... }, // on close event handler + }, + // component default slot render content + slot, +); + +``` + +The programmatic interface of this component looks much like the other programmatic component interfaces. However, the `open()` function takes some different attributes. The type definition of the `open()` function looks like this: + +```typescript +type open = ( + /** component to render **/ + component: C, + /** render options */ + options?: ProgrammaticOptions, + /** default slot content */ + slot?: unknown +) => ProgrammaticExpose; + + +type ProgrammaticOptions = { + /** + * The target specifies the element the component get rendered into - default is `document.body`. + */ + target?: string | HTMLElement; + /** + * Props to be binded to the injected component. + * Both attributes and properties can be used in props. + * Vue automatically picks the right way to assign it. + * `class` and `style` have the same object / array value support like in templates. + * Event listeners should be passed as onXxx. + */ + props: ComponentProps, + /** + * On component close event. + * This get called when the component emits `close` or the exposed `close` function get called. + */ + onClose?: (...args: unknown[]) => void, +} +``` diff --git a/packages/docs/documentation/customisation.md b/packages/docs/documentation/customisation.md index 5d111980e..55b50e35b 100644 --- a/packages/docs/documentation/customisation.md +++ b/packages/docs/documentation/customisation.md @@ -11,7 +11,7 @@ You can customise component classes in 3 different ways: - [Global configuration](#global) - [Individual configuration](#individual) -- [Programmatically configuration](#programmatic) +- [Programmatically configuration](/documentation/composables) ::: info Although all components have predefined classes, Oruga allows you to easily override the style of existing components by appending one or more classes, either globally or programmatically, to individual components. @@ -215,93 +215,3 @@ You can also add and override classes to a component directly using `class` prop Have a look at the docs of each component to know all the customisable fields/props by config. - -## Programmatic usage {#programmatic} - -As alternative Oruga provide a programmatic interface `useOruga()` to access the config as well as programmatic component interfaces such as [`Modal`](/components/Modal.html#programmatically) or [`Sidebar`](/components/Sidebar.html#programmatically). -This interface gives you access to all registered programmatic components. A programmatic component interface get registered while using the main or an individual component plugin. - - -### Programmatic component - -If you use the default main plugin export or any plugin of a component with a programmatic interface, this interface will be registered and can be accessed using the `useOruga()` composable: - -```js -import { useOruga } from "@oruga-ui/oruga-next"; - -const oruga = useOruga(); - -oruga.sidebar.open({ - component: MyCoolComponent, - fullheight: true, - overlay: true, - destroyOnHide: true, -}); -``` - -### Programmatic config - -The config can be customised for each component by overriding the `Config` object programmatically: - -```js -import { useOruga } from '@oruga-ui/oruga-next'; - -const oruga = useOruga(); - -const config = oruga.config.getOptions(); - -const myThemeConfig = { - ...config, - autocomplete: { - rootClass: 'autocomplete-root', - itemClass: 'autocomplete-item', - ... - } -} - -oruga.config.setOptions(myThemeConfig); -``` - -However, you can also customise each component by using the dedicated `ConfigProgrammatic` object: - -```js -import { ConfigProgrammatic } from '@oruga-ui/oruga-next'; - -const config = ConfigProgrammatic.getOptions(); - -const myThemeConfig = { - ...config, - autocomplete: { - rootClass: 'autocomplete-root', - itemClass: 'autocomplete-item', - ... - } -} - -ConfigProgrammatic.setOptions(myThemeConfig); -``` - -If you use individual imports instead of the default main plugin export, the programmatic config will not be registered to the `useOruga()` interface by default. -Therefore, you can make the config interface available by adding the dedicated `OrugaConfig` plugin: - -```js -import { createApp } from 'vue'; -import { OAutocomplete, OSidebar, OrugaConfig, useOruga } from '@oruga-ui/oruga-next'; - -createApp(...) - .component(OAutocomplete) - .component(OSidebar) - .use(OrugaConfig); - -const oruga = useOruga(); - -const config = oruga.config.getOptions(); - -config.setOption("autocomplete", { - rootClass: 'autocomplete-root', - itemClass: 'autocomplete-item', - ... -}); - -config.setOption("sidebar", { ... }); -``` \ No newline at end of file diff --git a/packages/oruga/src/components/loading/index.ts b/packages/oruga/src/components/loading/index.ts index ea5952dc2..d61f3d3dc 100644 --- a/packages/oruga/src/components/loading/index.ts +++ b/packages/oruga/src/components/loading/index.ts @@ -1,7 +1,7 @@ import type { App, Plugin } from "vue"; import Loading from "./Loading.vue"; -import useLoadingProgrammatic from "./useLoadingProgrammatic"; +import LoadingProgrammatic from "./useLoadingProgrammatic"; import { registerComponent, @@ -15,9 +15,9 @@ import { export default { install(app: App) { registerComponent(app, Loading); - registerComponentProgrammatic(app, "loading", useLoadingProgrammatic); + registerComponentProgrammatic(app, "loading", LoadingProgrammatic); }, } as Plugin; /** export loading components & composables */ -export { Loading as OLoading, useLoadingProgrammatic }; +export { Loading as OLoading, LoadingProgrammatic }; diff --git a/packages/oruga/src/components/loading/tests/useLoadingProgrammatic.test.ts b/packages/oruga/src/components/loading/tests/useLoadingProgrammatic.test.ts index f3151f633..73d35cee4 100644 --- a/packages/oruga/src/components/loading/tests/useLoadingProgrammatic.test.ts +++ b/packages/oruga/src/components/loading/tests/useLoadingProgrammatic.test.ts @@ -1,7 +1,7 @@ import { describe, test, expect, afterEach, vi, beforeEach } from "vitest"; import { enableAutoUnmount, flushPromises } from "@vue/test-utils"; -import useLoadingProgrammatic from "../useLoadingProgrammatic"; +import LoadingProgrammatic from "../useLoadingProgrammatic"; describe("useLoadingProgrammatic tests", () => { beforeEach(() => { @@ -20,7 +20,7 @@ describe("useLoadingProgrammatic tests", () => { const label = "My Label"; // open element - const { close, promise } = useLoadingProgrammatic.open(label); + const { close, promise } = LoadingProgrammatic.open(label); // check promise get called const handler = vi.fn(); @@ -51,7 +51,7 @@ describe("useLoadingProgrammatic tests", () => { const label = "My loading Content"; // open element - const { close } = useLoadingProgrammatic.open( + const { close } = LoadingProgrammatic.open( label, "#my-cool-container", ); @@ -80,7 +80,7 @@ describe("useLoadingProgrammatic tests", () => { const label = "My loading Content"; // open element - const { close } = useLoadingProgrammatic.open({ + const { close } = LoadingProgrammatic.open({ label, active: false, }); @@ -103,7 +103,7 @@ describe("useLoadingProgrammatic tests", () => { const onClose = vi.fn(); // open element - const { close } = useLoadingProgrammatic.open({ label, onClose }); + const { close } = LoadingProgrammatic.open({ label, onClose }); // check element exist let loading = document.body.querySelector( diff --git a/packages/oruga/src/components/loading/useLoadingProgrammatic.ts b/packages/oruga/src/components/loading/useLoadingProgrammatic.ts index 4ca7cd453..cab4aec94 100644 --- a/packages/oruga/src/components/loading/useLoadingProgrammatic.ts +++ b/packages/oruga/src/components/loading/useLoadingProgrammatic.ts @@ -1,8 +1,8 @@ import { type ComponentInternalInstance } from "vue"; import { InstanceRegistry, - useProgrammatic, - type PublicProgrammaticComponentOptions, + ComponentProgrammatic, + type ProgrammaticComponentOptions, type ProgrammaticExpose, } from "../programmatic"; @@ -12,7 +12,7 @@ import type { LoadingProps } from "./props"; declare module "../../index" { interface OrugaProgrammatic { - loading: typeof useLoadingProgrammatic; + loading: typeof LoadingProgrammatic; } } @@ -22,11 +22,11 @@ const instances = new InstanceRegistry(); /** useLoadingProgrammatic composable options */ type LoadingProgrammaticOptions = Readonly> & { label?: string | Array; -} & PublicProgrammaticComponentOptions; +} & ProgrammaticComponentOptions; -const useLoadingProgrammatic = { +const LoadingProgrammatic = { /** - * create a new programmatic modal component + * Create a new programmatic loading component. * @param options loading label string or loading component props object * @param target specify a target the component get rendered into * @returns ProgrammaticExpose @@ -52,7 +52,7 @@ const useLoadingProgrammatic = { }; // create programmatic component - return useProgrammatic.open( + return ComponentProgrammatic.open( Loading, { instances, // custom programmatic instance registry @@ -74,4 +74,4 @@ const useLoadingProgrammatic = { }, }; -export default useLoadingProgrammatic; +export default LoadingProgrammatic; diff --git a/packages/oruga/src/components/modal/index.ts b/packages/oruga/src/components/modal/index.ts index ec3f28601..d67da4033 100644 --- a/packages/oruga/src/components/modal/index.ts +++ b/packages/oruga/src/components/modal/index.ts @@ -1,7 +1,7 @@ import type { App, Plugin } from "vue"; import Modal from "./Modal.vue"; -import useModalProgrammatic from "./useModalProgrammatic"; +import ModalProgrammatic from "./useModalProgrammatic"; import { registerComponent, @@ -15,9 +15,9 @@ import { export default { install(app: App) { registerComponent(app, Modal); - registerComponentProgrammatic(app, "modal", useModalProgrammatic); + registerComponentProgrammatic(app, "modal", ModalProgrammatic); }, } as Plugin; /** export modal components & composables */ -export { Modal as OModal, useModalProgrammatic }; +export { Modal as OModal, ModalProgrammatic }; diff --git a/packages/oruga/src/components/modal/tests/useModalProgrammatic.test.ts b/packages/oruga/src/components/modal/tests/useModalProgrammatic.test.ts index 90b78592b..5cfc2eccd 100644 --- a/packages/oruga/src/components/modal/tests/useModalProgrammatic.test.ts +++ b/packages/oruga/src/components/modal/tests/useModalProgrammatic.test.ts @@ -2,7 +2,7 @@ import { createVNode } from "vue"; import { describe, test, expect, afterEach, vi, beforeEach } from "vitest"; import { enableAutoUnmount, flushPromises } from "@vue/test-utils"; -import useModalProgrammatic from "../useModalProgrammatic"; +import ModalProgrammatic from "../useModalProgrammatic"; describe("useModalProgrammatic tests", () => { beforeEach(() => { @@ -21,7 +21,7 @@ describe("useModalProgrammatic tests", () => { const content = "My Modal Content"; // open element - const { close, promise } = useModalProgrammatic.open(content); + const { close, promise } = ModalProgrammatic.open(content); // check promise get called const handler = vi.fn(); @@ -54,7 +54,7 @@ describe("useModalProgrammatic tests", () => { const content = "My Modal Content"; // open element - const { close } = useModalProgrammatic.open( + const { close } = ModalProgrammatic.open( content, "#my-cool-container", ); @@ -85,7 +85,7 @@ describe("useModalProgrammatic tests", () => { }); // open element - useModalProgrammatic.open({ + ModalProgrammatic.open({ component, props: { "data-oruga": "programmatic" }, }); @@ -113,7 +113,7 @@ describe("useModalProgrammatic tests", () => { const onClose = vi.fn(); // open element - useModalProgrammatic.open({ content, onClose }); + ModalProgrammatic.open({ content, onClose }); // check element exist let el = document.body.querySelector(".o-icon"); diff --git a/packages/oruga/src/components/modal/useModalProgrammatic.ts b/packages/oruga/src/components/modal/useModalProgrammatic.ts index 2817e4ae4..c5c93c310 100644 --- a/packages/oruga/src/components/modal/useModalProgrammatic.ts +++ b/packages/oruga/src/components/modal/useModalProgrammatic.ts @@ -5,8 +5,8 @@ import { } from "vue"; import { InstanceRegistry, - useProgrammatic, - type PublicProgrammaticComponentOptions, + ComponentProgrammatic, + type ProgrammaticComponentOptions, type ProgrammaticExpose, } from "../programmatic"; @@ -16,7 +16,7 @@ import type { ModalProps } from "./props"; declare module "../../index" { interface OrugaProgrammatic { - modal: typeof useModalProgrammatic; + modal: typeof ModalProgrammatic; } } @@ -28,13 +28,13 @@ type ModalProgrammaticOptions = Readonly< Omit, "content"> > & { content?: string | Array; -} & PublicProgrammaticComponentOptions; +} & ProgrammaticComponentOptions; -const useModalProgrammatic = { +const ModalProgrammatic = { /** - * create a new programmatic modal component + * Create a new programmatic modal component. * @param options modal content string or modal component props object - * @param target specify a target the component get rendered into + * @param target specify a target the component get rendered into - default is `document.body` * @returns ProgrammaticExpose */ open( @@ -57,7 +57,7 @@ const useModalProgrammatic = { }; // create programmatic component - return useProgrammatic.open( + return ComponentProgrammatic.open( Modal as VNodeTypes, { instances, // custom programmatic instance registry @@ -65,7 +65,7 @@ const useModalProgrammatic = { props: componentProps, // component specific props onClose: _options.onClose, // on close event handler }, - // component default slot render + // component default slot to render content slot, ); }, @@ -79,4 +79,4 @@ const useModalProgrammatic = { }, }; -export default useModalProgrammatic; +export default ModalProgrammatic; diff --git a/packages/oruga/src/components/notification/index.ts b/packages/oruga/src/components/notification/index.ts index 4b99ce9b9..91bae2b7e 100644 --- a/packages/oruga/src/components/notification/index.ts +++ b/packages/oruga/src/components/notification/index.ts @@ -1,7 +1,7 @@ import type { App, Plugin } from "vue"; import Notification from "./Notification.vue"; -import useNotificationProgrammatic from "./useNotificationProgrammatic"; +import NotificationProgrammatic from "./useNotificationProgrammatic"; import { registerComponent, @@ -18,10 +18,10 @@ export default { registerComponentProgrammatic( app, "notification", - useNotificationProgrammatic, + NotificationProgrammatic, ); }, } as Plugin; /** export notification components & composables */ -export { Notification as ONotification, useNotificationProgrammatic }; +export { Notification as ONotification, NotificationProgrammatic }; diff --git a/packages/oruga/src/components/notification/tests/useNotificationProgrammatic.test.ts b/packages/oruga/src/components/notification/tests/useNotificationProgrammatic.test.ts index a53b7bc98..1a70f9266 100644 --- a/packages/oruga/src/components/notification/tests/useNotificationProgrammatic.test.ts +++ b/packages/oruga/src/components/notification/tests/useNotificationProgrammatic.test.ts @@ -2,7 +2,7 @@ import { createVNode, nextTick } from "vue"; import { describe, test, expect, afterEach, vi, beforeEach } from "vitest"; import { enableAutoUnmount, flushPromises } from "@vue/test-utils"; -import useNotificationProgrammatic from "../useNotificationProgrammatic"; +import NotificationProgrammatic from "../useNotificationProgrammatic"; describe("useNotificationProgrammatic tests", () => { beforeEach(() => { @@ -21,7 +21,7 @@ describe("useNotificationProgrammatic tests", () => { const message = "My Fany Message"; // open element - const { close, promise } = useNotificationProgrammatic.open(message); + const { close, promise } = NotificationProgrammatic.open(message); // check promise get called const handler = vi.fn(); @@ -60,7 +60,7 @@ describe("useNotificationProgrammatic tests", () => { }); // open element - const { close } = useNotificationProgrammatic.open( + const { close } = NotificationProgrammatic.open( { component }, "#my-cool-container", ); @@ -102,7 +102,7 @@ describe("useNotificationProgrammatic tests", () => { }); // open element - useNotificationProgrammatic.open({ + NotificationProgrammatic.open({ component, props: { "data-oruga": "programmatic" }, }); @@ -136,7 +136,7 @@ describe("useNotificationProgrammatic tests", () => { const onClose = vi.fn(); // open element - useNotificationProgrammatic.open({ component, onClose }); + NotificationProgrammatic.open({ component, onClose }); // check element exist let el = document.body.querySelector("button"); diff --git a/packages/oruga/src/components/notification/useNotificationProgrammatic.ts b/packages/oruga/src/components/notification/useNotificationProgrammatic.ts index 1136604e1..92412dd9a 100644 --- a/packages/oruga/src/components/notification/useNotificationProgrammatic.ts +++ b/packages/oruga/src/components/notification/useNotificationProgrammatic.ts @@ -1,8 +1,8 @@ import type { Component, ComponentInternalInstance } from "vue"; import { InstanceRegistry, - useProgrammatic, - type PublicProgrammaticComponentOptions, + ComponentProgrammatic, + type ProgrammaticComponentOptions, type ProgrammaticExpose, } from "../programmatic"; import { getOption } from "@/utils/config"; @@ -13,7 +13,7 @@ import type { NotificationProps, NotificationNoticeProps } from "./props"; declare module "../../index" { interface OrugaProgrammatic { - notification: typeof useNotificationProgrammatic; + notification: typeof NotificationProgrammatic; } } @@ -28,13 +28,13 @@ type NotificationProgrammaticOptions = Readonly< > > & { message?: string | Array; -} & PublicProgrammaticComponentOptions; +} & ProgrammaticComponentOptions; -const useNotificationProgrammatic = { +const NotificationProgrammatic = { /** - * create a new programmatic modal component + * Create a new programmatic notification component. * @param options notification message string or notification component props object - * @param target specify a target the component get rendered into + * @param target specify a target the component get rendered into - default is `document.body` * @returns ProgrammaticExpose */ open( @@ -58,7 +58,7 @@ const useNotificationProgrammatic = { }; // create programmatic component - return useProgrammatic.open( + return ComponentProgrammatic.open( NotificationNotice, { instances, // custom programmatic instance registry @@ -80,4 +80,4 @@ const useNotificationProgrammatic = { }, }; -export default useNotificationProgrammatic; +export default NotificationProgrammatic; diff --git a/packages/oruga/src/components/programmatic/ProgrammaticComponent.ts b/packages/oruga/src/components/programmatic/ProgrammaticComponent.ts index 8ddb7786f..721dd6b7b 100644 --- a/packages/oruga/src/components/programmatic/ProgrammaticComponent.ts +++ b/packages/oruga/src/components/programmatic/ProgrammaticComponent.ts @@ -51,9 +51,9 @@ export type ProgrammaticComponentEmits = { // >; export type ProgrammaticComponentExpose = { - /** call close event function */ + /** Call the close event of the component. */ close: (...args: unknown[]) => void; - /** promise which get called on close event */ + /** Promise which get resolved on the close event. */ promise: Promise; }; diff --git a/packages/oruga/src/components/programmatic/index.ts b/packages/oruga/src/components/programmatic/index.ts index c8e311036..4abfca056 100644 --- a/packages/oruga/src/components/programmatic/index.ts +++ b/packages/oruga/src/components/programmatic/index.ts @@ -1,6 +1,6 @@ import type { App, Plugin } from "vue"; -import Programmatic from "./useProgrammatic"; +import ComponentProgrammatic from "./useProgrammatic"; import { registerComponentProgrammatic } from "@/utils/plugins"; import InstanceRegistry from "./InstanceRegistry"; @@ -9,16 +9,20 @@ import InstanceRegistry from "./InstanceRegistry"; export type { ProgrammaticOptions, ProgrammaticExpose, - PublicProgrammaticComponentOptions, + ProgrammaticComponentOptions, } from "./useProgrammatic"; export { InstanceRegistry }; /** export programmatic plugin */ export default { install(app: App) { - registerComponentProgrammatic(app, "programmatic", Programmatic); + registerComponentProgrammatic( + app, + "programmatic", + ComponentProgrammatic, + ); }, } as Plugin; /** export composables here */ -export { useProgrammatic } from "./useProgrammatic"; +export { ComponentProgrammatic } from "./useProgrammatic"; diff --git a/packages/oruga/src/components/programmatic/tests/useProgrammatic.test.ts b/packages/oruga/src/components/programmatic/tests/useProgrammatic.test.ts index 0501a2bc6..85d546cd0 100644 --- a/packages/oruga/src/components/programmatic/tests/useProgrammatic.test.ts +++ b/packages/oruga/src/components/programmatic/tests/useProgrammatic.test.ts @@ -3,7 +3,7 @@ import { describe, test, expect, afterEach, vi, beforeEach } from "vitest"; import { enableAutoUnmount, flushPromises } from "@vue/test-utils"; import InstanceRegistry from "../InstanceRegistry"; -import useProgrammatic from "../useProgrammatic"; +import ComponentProgrammatic from "../useProgrammatic"; describe("useProgrammatic tests", () => { beforeEach(() => { @@ -24,7 +24,7 @@ describe("useProgrammatic tests", () => { }); // open element - const { close, promise } = useProgrammatic.open(component); + const { close, promise } = ComponentProgrammatic.open(component); // check promise get called const handler = vi.fn(); @@ -57,7 +57,7 @@ describe("useProgrammatic tests", () => { }); // open element - const { close } = useProgrammatic.open(component, { + const { close } = ComponentProgrammatic.open(component, { target: "#my-cool-container", }); @@ -89,7 +89,7 @@ describe("useProgrammatic tests", () => { const onClose = vi.fn(); // open element - useProgrammatic.open(component, { onClose }); + ComponentProgrammatic.open(component, { onClose }); // check element exist let el = document.body.querySelector("button"); @@ -112,7 +112,7 @@ describe("useProgrammatic tests", () => { }); // open element - const { close } = useProgrammatic.open(component, { + const { close } = ComponentProgrammatic.open(component, { props: { "data-oruga": "programmatic" }, }); @@ -139,7 +139,7 @@ describe("useProgrammatic tests", () => { expect(instanceRegistry.entries).toHaveLength(0); - const { close } = useProgrammatic.open("div", { + const { close } = ComponentProgrammatic.open("div", { instances: instanceRegistry, }); @@ -153,14 +153,14 @@ describe("useProgrammatic tests", () => { test("test closeAll is working correctly", async () => { // open elements - useProgrammatic.open("div"); - useProgrammatic.open("div"); + ComponentProgrammatic.open("div"); + ComponentProgrammatic.open("div"); let bodyElements = document.body.querySelectorAll("*"); expect(bodyElements).toHaveLength(2); // close all elements - useProgrammatic.closeAll(); + ComponentProgrammatic.closeAll(); vi.runAllTimers(); bodyElements = document.body.querySelectorAll("*"); @@ -169,21 +169,21 @@ describe("useProgrammatic tests", () => { test("test close last is working correctly", async () => { // open elements - useProgrammatic.open("div"); - useProgrammatic.open("div"); + ComponentProgrammatic.open("div"); + ComponentProgrammatic.open("div"); let bodyElements = document.body.querySelectorAll("*"); expect(bodyElements).toHaveLength(2); // close last element - useProgrammatic.close(); + ComponentProgrammatic.close(); vi.runAllTimers(); bodyElements = document.body.querySelectorAll("*"); expect(bodyElements).toHaveLength(1); // close last element - useProgrammatic.close(); + ComponentProgrammatic.close(); vi.runAllTimers(); bodyElements = document.body.querySelectorAll("*"); @@ -199,7 +199,7 @@ describe("useProgrammatic tests", () => { const slot = h("p", { "data-oruga": "inner-slot" }, "HELP"); // open elements - const { close } = useProgrammatic.open(component, {}, slot); + const { close } = ComponentProgrammatic.open(component, {}, slot); // check element exist const button = document.body.querySelector("button"); diff --git a/packages/oruga/src/components/programmatic/useProgrammatic.ts b/packages/oruga/src/components/programmatic/useProgrammatic.ts index 2028d87c9..540f67487 100644 --- a/packages/oruga/src/components/programmatic/useProgrammatic.ts +++ b/packages/oruga/src/components/programmatic/useProgrammatic.ts @@ -20,7 +20,7 @@ import { declare module "../../index" { interface OrugaProgrammatic { - programmatic: typeof useProgrammatic; + programmatic: typeof ComponentProgrammatic; } } @@ -38,7 +38,7 @@ export type ProgrammaticOptions = { EmitsToProps>; // component emit props /** public options interface for programmatically called components */ -export type PublicProgrammaticComponentOptions = EmitsToProps< +export type ProgrammaticComponentOptions = EmitsToProps< Pick > & // make the type extendable @@ -47,9 +47,9 @@ export type PublicProgrammaticComponentOptions = EmitsToProps< /** useProgrammatic composable `open` function return value */ export type ProgrammaticExpose = ProgrammaticComponentExpose; -export const useProgrammatic = { +export const ComponentProgrammatic = { /** - * create a new programmatic component + * Create a new programmatic component. * @param component component to render * @param options render options * @param slot default slot content - see {@link https://vuejs.org/api/render-function.html#render-function-apis |Vue render function} @@ -114,4 +114,4 @@ export const useProgrammatic = { }, }; -export default useProgrammatic; +export default ComponentProgrammatic; diff --git a/packages/oruga/src/components/sidebar/index.ts b/packages/oruga/src/components/sidebar/index.ts index 7586cd19d..8ea88226e 100644 --- a/packages/oruga/src/components/sidebar/index.ts +++ b/packages/oruga/src/components/sidebar/index.ts @@ -1,7 +1,7 @@ import type { App, Plugin } from "vue"; import Sidebar from "./Sidebar.vue"; -import useSidebarProgrammatic from "./useSidebarProgrammatic"; +import SidebarProgrammatic from "./useSidebarProgrammatic"; import { registerComponent, @@ -15,9 +15,9 @@ import { export default { install(app: App) { registerComponent(app, Sidebar); - registerComponentProgrammatic(app, "sidebar", useSidebarProgrammatic); + registerComponentProgrammatic(app, "sidebar", SidebarProgrammatic); }, } as Plugin; /** export sidebar components & composables */ -export { Sidebar as OSidebar, useSidebarProgrammatic }; +export { Sidebar as OSidebar, SidebarProgrammatic }; diff --git a/packages/oruga/src/components/sidebar/tests/useSidebarProgrammatic.test.ts b/packages/oruga/src/components/sidebar/tests/useSidebarProgrammatic.test.ts index a6b8dc5f6..3a3afc59e 100644 --- a/packages/oruga/src/components/sidebar/tests/useSidebarProgrammatic.test.ts +++ b/packages/oruga/src/components/sidebar/tests/useSidebarProgrammatic.test.ts @@ -2,7 +2,7 @@ import { createVNode } from "vue"; import { describe, test, expect, afterEach, vi, beforeEach } from "vitest"; import { enableAutoUnmount, flushPromises } from "@vue/test-utils"; -import useSidebarProgrammatic from "../useSidebarProgrammatic"; +import SidebarProgrammatic from "../useSidebarProgrammatic"; describe("useSidebarProgrammatic tests", () => { beforeEach(() => { @@ -23,7 +23,7 @@ describe("useSidebarProgrammatic tests", () => { }); // open element - const { close, promise } = useSidebarProgrammatic.open({ component }); + const { close, promise } = SidebarProgrammatic.open({ component }); // check promise get called const handler = vi.fn(); @@ -58,7 +58,7 @@ describe("useSidebarProgrammatic tests", () => { }); // open element - const { close } = useSidebarProgrammatic.open( + const { close } = SidebarProgrammatic.open( { component }, "#my-cool-container", ); @@ -91,7 +91,7 @@ describe("useSidebarProgrammatic tests", () => { }); // open element - useSidebarProgrammatic.open({ + SidebarProgrammatic.open({ component, props: { "data-oruga": "programmatic" }, }); @@ -121,7 +121,7 @@ describe("useSidebarProgrammatic tests", () => { const onClose = vi.fn(); // open element - useSidebarProgrammatic.open({ component, onClose }); + SidebarProgrammatic.open({ component, onClose }); // check element exist let el = document.body.querySelector("button"); diff --git a/packages/oruga/src/components/sidebar/useSidebarProgrammatic.ts b/packages/oruga/src/components/sidebar/useSidebarProgrammatic.ts index e56091d0d..b01c59f1d 100644 --- a/packages/oruga/src/components/sidebar/useSidebarProgrammatic.ts +++ b/packages/oruga/src/components/sidebar/useSidebarProgrammatic.ts @@ -5,8 +5,8 @@ import { } from "vue"; import { InstanceRegistry, - useProgrammatic, - type PublicProgrammaticComponentOptions, + ComponentProgrammatic, + type ProgrammaticComponentOptions, type ProgrammaticExpose, } from "../programmatic"; @@ -16,7 +16,7 @@ import type { SidebarProps } from "./props"; declare module "../../index" { interface OrugaProgrammatic { - sidebar: typeof useSidebarProgrammatic; + sidebar: typeof SidebarProgrammatic; } } @@ -27,13 +27,13 @@ const instances = new InstanceRegistry(); type SidebarProgrammaticOptions = Readonly< SidebarProps > & - PublicProgrammaticComponentOptions; + ProgrammaticComponentOptions; -const useSidebarProgrammatic = { +const SidebarProgrammatic = { /** - * create a new programmatic modal component + * Create a new programmatic sidebar component. * @param options sidebar component props object - * @param target specify a target the component get rendered into + * @param target specify a target the component get rendered into - default is `document.body` * @returns ProgrammaticExpose */ open( @@ -46,7 +46,7 @@ const useSidebarProgrammatic = { }; // create programmatic component - return useProgrammatic.open(Sidebar as VNodeTypes, { + return ComponentProgrammatic.open(Sidebar as VNodeTypes, { instances, // custom programmatic instance registry target, // target the component get rendered into props: componentProps, // component specific props @@ -63,4 +63,4 @@ const useSidebarProgrammatic = { }, }; -export default useSidebarProgrammatic; +export default SidebarProgrammatic;