UNPKG

doric-framework

Version:

A column-based widget UI framework for Vue 3

286 lines (214 loc) 7.51 kB
<a name="doric-framework-readme-top"></a> <header><h1 align="center">Doric Framework</h1></header> <!-- TABLE OF CONTENTS --> # Table of Contents - [About the Project](#about-the-project) - [Description](#description) - [Dependencies](#dependencies) - [Installation](#installation) - [Usage](#usage) - [Basic Usage](#basic-usage) - [Writing Widgets](#writing-widgets) - [Passing Widgets to Doric](#passing-widgets-to-doric) - [API Reference](#api-reference) - [Doric Framework Props](#doric-framework-props) - [Exporting the Current Workspace](#exporting-the-current-workspace) - [License](#license) # About the Project ## Description Doric Framework is a column-based widget UI framework for Vue 3. It displays custom widgets in a `workspace`, allowing users to drag and drop widgets into columns and rearrange them. <p align="right">(<a href="#doric-framework-readme-top">back to top</a>)</p> ## Dependencies - [pinia](https://pinia.esm.dev/) - [splitpanes](https://github.com/antoniandre/splitpanes) - [vuedraggable](https://github.com/SortableJS/vue.draggable.next/) Note that the `pinia` dependeny implies that you have mounted an app that uses `pinia` before using Doric. For example: ```ts // main.ts import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' const pinia = createPinia() createApp(App).use(pinia).mount('#app') ``` <p align="right">(<a href="#doric-framework-readme-top">back to top</a>)</p> # Installation ```sh npm install --save doric-framework ``` <p align="right">(<a href="#doric-framework-readme-top">back to top</a>)</p> <!-- USAGE EXAMPLES --> # Usage ## Basic Usage ```vue <script setup lang="ts"> // Required imports for Doric import DoricFramework from 'doric-framework' import "doric-framework/dist/style.css" // Import a map of your widgets from index.ts at this path import widgets from "@/components/doric-widgets/" const workspace = [ [{ type: "passage-ref", }, { type: "dictionary", }], [{ type: "text-display", }] ] </script> <template> <DoricFramework :widgets="widgets" :workspace="workspace" /> </template> ``` <p align="right">(<a href="#doric-framework-readme-top">back to top</a>)</p> ## Writing Widgets Doric displays instance of widgets, which are Vue components. A minimal widget is defined as follows: <details> <summary>Composition API</summary> ```vue <script setup> import { useDoricOutput, useDoricInput } from 'doric-framework'; const setOsisRef = useDoricOutput("osisRef"); const osisRef = useDoricInput("osisRef"); </script> <template> <div> <input type="text" v-model="osisRef.value" /> <button @click="setOsisRef(osisRef)">Set osisRef</button> </div> </template> ``` </details> <details> <summary>Options API</summary> ```vue <template> <div> <input type="text" v-model="osisRef.value" /> <button @click="setOsisRef(osisRef)">Set osisRef</button> </div> </template> <script> import { useDoricOutput, useDoricInput } from 'doric-framework'; export default { data() { return { // Define input methods osisRef: useDoricInput("osisRef"), } }, setup() { // Define output methods return { setOsisRef: useDoricOutput("osisRef"), } }, } </script> ``` </details> <p align="right">(<a href="#doric-framework-readme-top">back to top</a>)</p> ## Passing Widgets to Doric Doric expects a list of widgets to be passed to it. This list is a map of widget types to default labels and widget components. It is typical to import all the widgets in a single file and pass them to Doric. ```ts // /src/components/doric-widgets/index.ts import MyFirstWidget from "@/components/doric-widgets/MyFirstWidget.vue"; import MySecondWidget from "@/components/doric-widgets/MySecondWidget.vue"; export default { "my-first-widget": { defaultLabel: "My First Widget", widget: MyFirstWidget, }, "my-second-widget": { defaultLabel: "My Second Widget", widget: MySecondWidget, }, }; ``` These widgets can then be passed to Doric as follows: ```vue <!-- App.vue --> <script> import DoricFramework from 'doric-framework' // If your Widget map is not in index.ts, you will need to specify it. import widgets from "@/components/doric-widgets/" ... </script> <template> <DoricFramework :widgets="widgets" /> </template> ``` <p align="right">(<a href="#doric-framework-readme-top">back to top</a>)</p> ## API Reference ### Doric Framework Props The DoricFramework component accepts the following props: | Prop | Type | Description | | --- | --- | --- | | `widgets` | `WidgetComponentMap` | A map of widget types to default labels and widget components (see example above). | | `workspace` | `Workspace` | A list of columns, each of which is a list of widgets. A minimal Widget is an object that includes a type, which is a key in the `WidgetComponentMap`. | | `locked` | `boolean` | Whether the workspace is locked. | | `@setSharedParams` | `Function` | A callback function that is emitted whenever a widget's input value changes and it is marked as `shared`. | | `@onWorkspaceReady` | `Function` | A callback function that is emitted after the `workspace` property has been changed and the new workspace is ready. Useful for setting initial state. | ### Pushing State to the Workspace Doric exports the `pushWorkspaceState` function for pushing state to the current workspace. The main use of `pushWorkspaceState` is to set initial values (e.g., from localstorage or a url), but state may also come from outside Doric in realtime applications. `pushWorkspaceState` expects a `WidgetInputState[]`. `WidgetInputState` is an object with three fields: ```ts type WidgetInputState = { widgetId: string; key: string; value: any; }; ``` To set initial state, your application may look something like this: ```vue <script setup> import DoricFramework, { pushWorkspaceState } from "doric-framework"; import widgets from "@/components/doric-widgets/"; const workspace = [ [{ type: "passage-ref", }, { type: "dictionary", }], [{ type: "text-display", }] ] // Set initial state const onWorkspaceReady = () => { pushWorkspaceState([ { widgetId: "passage-ref", key: "osisRef", value: "Gen.1.1", }, { widgetId: "dictionary", key: "selectedLemma", value: "λογός", }, ]); }; </script> <template> <DoricFramework :widgets="widgets" :workspace="workspace" @onWorkspaceReady="onWorkspaceReady" /> </template> ``` ### Exporting the Current Workspace The `doric-framework` package provides an `exportWorkspace` function. This function serializes the current workspace into a minimal `Workspace`—i.e., a `Widget[][]` that includes the position of widgets in columns as well as their non-falsy input values, subscription, sharing states. Thus, the return type of `exportWorkspace` may be passed into `<DoricFramework />` as the `workspace` prop. This allows workspace state to be restored across sessions. It may be imported alongside the `DoricFramework` component as follows: ```vue // App.vue <script setup> import DoricFramework, { exportWorkspace } from 'doric-framework' </script> ``` <p align="right">(<a href="#doric-framework-readme-top">back to top</a>)</p> # License Distributed under the MIT License. See `LICENSE.txt` for more information. <p align="right">(<a href="#doric-framework-readme-top">back to top</a>)</p>