### Ovee.js Starter Project Setup Source: https://github.com/owlsdepartment/ovee/blob/master/docs/guide.md Set up a new Ovee.js project using npx and degit, then install dependencies and run the development server. ```shell npx degit owlsdepartment/ovee-starter my-project cd my-project # install dependencies yarn # and run it! yarn dev # or serve ``` -------------------------------- ### Initialize and Run Ovee.js App Source: https://context7.com/owlsdepartment/ovee/llms.txt Demonstrates how to instantiate the App, register components and modules, configure options, and start the application. Includes examples of imperative registration and accessing modules via the event bus. ```javascript import { App } from 'ovee.js'; import OveeBarba from '@ovee.js/barba'; import NavMenu from './components/NavMenu'; import Slider from './components/Slider'; import AnalyticsModule from './modules/AnalyticsModule'; // Register via constructor (recommended) const app = new App({ config: { namespace: 'myapp', // CSS class prefix and event namespace productionTip: false // suppress dev tip in non-production builds }, components: [ NavMenu, // no options [Slider, { loop: true, speed: 400 }] // with per-component options ], modules: [ [OveeBarba, { transitions: [], preventRunning: true }] ] }); // Or register imperatively after creation app.registerComponent(NavMenu); app.registerComponent(Slider, { loop: true }); app.registerComponents([NavMenu, Slider]); app.use(AnalyticsModule, { trackingId: 'UA-XXXXX' }); // Boot the app — starts MutationObserver and harvests existing DOM components const root = document.getElementById('app'); app.run(root); // Access a module by class (preferred, fully typed) or by name string const analytics = app.getModule(AnalyticsModule); const analytics2 = app.getModule('AnalyticsModule'); // App-level event bus app.$on('user:login', (e) => console.log('user logged in', e.detail)); app.$emit('user:login', { userId: 42 }); app.$off('user:login', handler); // Retrieve current config (returns a copy, not the live object) const config = app.getConfig(); // { namespace: 'myapp', productionTip: false, global: window, document: document } // Tear down the entire app (destroys all components and modules) app.destroy(); ``` -------------------------------- ### Install Ovee.js Source: https://github.com/owlsdepartment/ovee/blob/master/docs/guide.md Install Ovee.js using yarn or npm. Lit-html is a required peer dependency. ```shell yarn add ovee.js # or npm install --save ovee.js ``` ```shell yarn add lit-html # or npm install --save lit-html ``` -------------------------------- ### Barba.js Plugin Integration Source: https://github.com/owlsdepartment/ovee/blob/master/docs/addons.md Example of how to install and use the Barba.js plugin with Ovee.js, including basic configuration and hooks. ```APIDOC ## Barba.js Plugin Integration ### Description Integrates Barba.js for page transitions within an Ovee.js application. ### Installation ```shell yarn add @ovee.js/barba # or npm install --save @ovee.js/barba ``` ### Getting Started ```js import { App } from 'ovee.js'; import OveeBarba from '@ovee.js/barba'; import { defaultTransition } from 'transitions'; const root = document.body; const app = new App(); app.use(OveeBarba, { transitions: [ defaultTransition ], timeout: 20000, preventRunning: true, hooks: { after() { if (global.dataLayer !== undefined) { try { global.dataLayer.push({ event: 'content-view', 'content-name': global.location.pathname }); // eslint-disable-next-line no-empty } catch {} } } } }); app.run(root); ``` ### Available Options | Option | Default Value | Description | |:------ |:------------- |:----------- | | `plugins` | `[]` | add Barba plugins from [Plugins](https://barba.js.org/docs/plugins/). More in section [Plugins](#plugins) | | `hooks` | `{}` | you can pass methods to hook into Barba's lifecycle globally. More in section [Hooks](#hooks) | ### Methods | Method | Description | |:------ |:----------- | | `$go(href: string, trigger?: Trigger, e?: LinkEvent | PopStateEvent)` | Tell Barba to go to a specific URL | | `$prefetch(href: string)` | Prefetch the given URL | ### Hooks You can add globall hooks callbacks in module options under `hooks` option. Every hook also emits global event on `$app` instance. Available hooks and theire events are: - `before` | event: `barba:before` - `beforeLeave` | event: `barba:before-leave` - `leave` | event: `barba:leave` - `afterLeave` | event: `barba:after-leave` - `beforeEnter` | event: `barba:before-enter` - `enter` | event: `barba:enter` - `afterEnter` | event: `barba:after-enter` - `after` | event: `barba:after` ### Plugins To add Barba plugins, you need to install it in you project and pass to `plugins` option. Example: ```js import { App } from 'ovee.js'; import OveeBarba from '@ovee.js/barba'; import barbaPrefetch from '@barba/prefetch'; import barbaRouter from '@barba/router'; const root = document.body; const app = new App(); app.use(OveeBarba, { plugins: [ barbaPrefetch, [barbaRouter, { routes: [ /* barba routes here */ ] }] ], }); app.run(root); ``` ### Defining Custom Transitions To define your transitions, just pass transition definitions to `transitions` array of the module config. We don't do anything with them by any meaning, so you shall just follow the [official docs](https://barba.js.org/docs/advanced/transitions/) to get more details. ``` -------------------------------- ### Install Barba.js Plugin Source: https://github.com/owlsdepartment/ovee/blob/master/docs/addons.md Install the Barba.js plugin for Ovee.js using yarn or npm. ```shell yarn add @ovee.js/barba # or npm install --save @ovee.js/barba ``` -------------------------------- ### Initialize Ovee.js with Barba.js Plugin Source: https://github.com/owlsdepartment/ovee/blob/master/docs/addons.md Initialize your Ovee.js app and use the Barba.js plugin with custom transitions and hooks. Ensure Barba.js is installed separately if needed. ```javascript import { App } from 'ovee.js'; import OveeBarba from '@ovee.js/barba'; import { defaultTransition } from 'transitions'; const root = document.body; const app = new App(); app.use(OveeBarba, { transitions: [ defaultTransition ], timeout: 20000, preventRunning: true, hooks: { after() { if (global.dataLayer !== undefined) { try { global.dataLayer.push({ event: 'content-view', 'content-name': global.location.pathname }); // eslint-disable-next-line no-empty } catch {} } } } }); app.run(root); ``` -------------------------------- ### Configuring Ovee App Initialization Source: https://github.com/owlsdepartment/ovee/blob/master/docs/guide.md Configure the App object by passing a `config` object to the constructor options or using the `setConfig` method. Configuration is merged with defaults. This example sets the namespace and disables production tips. ```javascript const app = new App({ options: { namespace: 'ymce', productionTip: false } }); ``` -------------------------------- ### Reactive Array Example Source: https://github.com/owlsdepartment/ovee/blob/master/docs/reactivity/overview.md Demonstrates how assigning a new array to a `ref` triggers reactivity. Useful for updating UI based on array changes. ```javascript const arr = ref([1, 2, 3]) arr.value = [1, 2, 3] // <- this will trigger a change! ``` -------------------------------- ### Integrate Barba.js Plugins with Ovee.js Source: https://github.com/owlsdepartment/ovee/blob/master/docs/addons.md Configure the Barba.js plugin within Ovee.js to include additional Barba.js plugins like prefetch and router. Ensure these plugins are installed in your project. ```javascript import { App } from 'ovee.js'; import OveeBarba from '@ovee.js/barba'; import barbaPrefetch from '@barba/prefetch'; import barbaRouter from '@barba/router'; const root = document.body; const app = new App(); app.use(OveeBarba, { plugins: [ barbaPrefetch, [barbaRouter, { routes: [ /* barba routes here */ ] }] ], }); app.run(root); ``` -------------------------------- ### Use Reactive Store with Dynamic Parameters Source: https://github.com/owlsdepartment/ovee/blob/master/docs/reactivity/overview.md This example demonstrates how to use a computed property that accepts parameters (`getPostsByUserId`) within a `TemplateComponent`. It utilizes decorators like `@reactive()` and `@dataParam()` for component state management. ```javascript import { postsStore } from '@/store' export class PostsList extends TemplateComponent { @reactive() @dataParam() id; template(html) { return html`
] — elements with ref="value" } // Lifecycle: called just before teardown beforeDestroy() { console.log('Counter about to be destroyed'); } // Lifecycle: called after teardown destroy() { console.log('Counter destroyed'); } // Event binding via decorator — auto-unbound on destroy @bind('click', { target: '.counter__btn' }) increment() { this.count += this.$options.step; } // Watcher — called whenever `count` changes @watch('count', { immediate: true }) onCountChange(newVal: number, oldVal: number) { if (this.$refs.value[0]) { this.$refs.value[0].textContent = `Count: ${newVal}`; } } // Manual event API (same as @bind, returns removal function) bindScrollListener() { const remove = this.$on('scroll', this.onScroll, { target: window, passive: true }); this.$on('click', () => remove(), { target: '.stop-scroll', root: true }); } onScroll(e: Event) { /* ... */ } // Emit a custom event up the DOM notifyParent() { this.$emit('counter:changed', { count: this.count }); } static defaultOptions(): CounterOptions { return { step: 1 }; } } ``` -------------------------------- ### App Initialization and Configuration Source: https://context7.com/owlsdepartment/ovee/llms.txt Demonstrates how to instantiate the App class, configure its settings, and register components and modules. It also shows how to imperatively register components and use modules. ```APIDOC ## App Initialization and Configuration ### Description Instantiate the `App` class, configure its settings, and register components and modules. Components can be registered with or without options, and modules can be registered with their own configurations. ### Usage ```js import { App } from 'ovee.js'; import OveeBarba from '@ovee.js/barba'; import NavMenu from './components/NavMenu'; import Slider from './components/Slider'; import AnalyticsModule from './modules/AnalyticsModule'; // Register via constructor (recommended) const app = new App({ config: { namespace: 'myapp', // CSS class prefix and event namespace productionTip: false // suppress dev tip in non-production builds }, components: [ NavMenu, // no options [Slider, { loop: true, speed: 400 }] // with per-component options ], modules: [ [OveeBarba, { transitions: [], preventRunning: true }] ] }); // Or register imperatively after creation app.registerComponent(NavMenu); app.registerComponent(Slider, { loop: true }); app.registerComponents([NavMenu, Slider]); app.use(AnalyticsModule, { trackingId: 'UA-XXXXX' }); ``` ``` -------------------------------- ### App Bootstrapping and Lifecycle Source: https://context7.com/owlsdepartment/ovee/llms.txt Shows how to run the application, access modules, use the app-level event bus, retrieve configuration, and tear down the application. ```APIDOC ## App Bootstrapping and Lifecycle ### Description Bootstraps the Ovee.js application, allowing it to scan the DOM for components. It also covers accessing registered modules, emitting and listening to application-level events, retrieving configuration, and destroying the application instance. ### Usage ```js // Boot the app — starts MutationObserver and harvests existing DOM components const root = document.getElementById('app'); app.run(root); // Access a module by class (preferred, fully typed) or by name string const analytics = app.getModule(AnalyticsModule); const analytics2 = app.getModule('AnalyticsModule'); // App-level event bus app.$on('user:login', (e) => console.log('user logged in', e.detail)); app.$emit('user:login', { userId: 42 }); app.$off('user:login', handler); // Retrieve current config (returns a copy, not the live object) const config = app.getConfig(); // { namespace: 'myapp', productionTip: false, global: window, document: document } // Tear down the entire app (destroys all components and modules) app.destroy(); ``` ``` -------------------------------- ### Registering Components with Global Options Source: https://github.com/owlsdepartment/ovee/blob/master/docs/components.md Demonstrates how to provide default global options to components during App initialization or dynamic registration. These options are accessible via `this.$options` within the component. ```js // passing options via App constructor const app = new App({ components: [ [MyComponent, { option1: 'a', option2: true }] ] }) // or via dynamic registration app.registerComponent(MyComponent, { option1: 'a', option2: true }) ``` -------------------------------- ### Initialize Ovee.js App Source: https://github.com/owlsdepartment/ovee/blob/master/docs/guide.md Initialize a new Ovee.js application by creating an App instance and running it on a root element. ```html
``` ```javascript import { App } from 'ovee.js'; const root = document.getElementById('app'); const app = new App(); app.run(root); ``` -------------------------------- ### Lazy and Cached Computed Properties with @computed Source: https://github.com/owlsdepartment/ovee/blob/master/docs/component-decorators.md Utilize the @computed decorator on a 'get' accessor to create reactive properties that cache their results. They re-evaluate only when their reactive dependencies change, similar to Vue's computed properties. ```js import { ref } from 'ovee.js' // we can use external reactive variable const counter = ref(0) @register('my-component') class MyComponent extends Component { multiplier = 2 @computed() get multipliedCounter() { return counter.value * this.multiplier; } init() { // counter: 0, multiplier: 2 console.log(this.multipliedCounter) // 0 counter.value += 1; // counter: 1, multiplier: 2 console.log(this.multipliedCounter) // 2 this.multiplier = 4; // we changed multiplier value, but computed is not reevaluated, // because multiplier is not reactive // counter: 1, multiplier: 4 console.log(this.multipliedCounter) // 2 counter.value += 1 // counter: 2, multiplier: 4 console.log(this.multipliedCounter) // 8 } } ``` -------------------------------- ### Register Components and Modules with App Constructor Source: https://github.com/owlsdepartment/ovee/blob/master/docs/guide.md Register components and modules when creating a new App instance using an options object. ```javascript import { App } from 'ovee'; import OveeBarba from '@ovee.js/barba'; import TodoList from './components/TodoList'; import TodoListItem from './components/TodoListItem'; const app = new App({ components: [ TodoList, TodoListItem ], modules: [ OveeBarba ] }); ``` -------------------------------- ### Register Components and Modules with App Methods Source: https://github.com/owlsdepartment/ovee/blob/master/docs/guide.md Register components and modules using `registerComponent`, `registerComponents`, and `use` methods on an App instance. ```javascript import { App } from 'ovee.js'; import OveeBarba from '@ovee.js/barba'; import TodoList from './components/TodoList'; import TodoListItem from './components/TodoListItem'; const app = new App(); app.registerComponent(TodoList); app.registerComponent(TodoListItem); // OR app.registerComponents([ TodoList, TodoListItem ]); app.use(OveeBarba); ``` -------------------------------- ### Defining Default Component Options Source: https://github.com/owlsdepartment/ovee/blob/master/docs/components.md Shows how to define default options for a component using the `static defaultOptions()` method. These defaults are merged with options provided during registration. ```js @register('my-component') export class MyComponent extends Component { static defaultOptions() { return { myOption: 'custom option' } } init() { // 'myOption' will be 'custom option' by default, if not changed during registration console.log(this.$options.myOption) } } ``` -------------------------------- ### Register Module with app.use() Source: https://github.com/owlsdepartment/ovee/blob/master/docs/modules.md Register a module instance with the app.use() method, optionally providing configuration options. This is an alternative to registering modules via the App constructor. ```javascript app.use(ThirdModule, { // options }); ``` -------------------------------- ### Initialize Dialogs with Reactive Array Source: https://github.com/owlsdepartment/ovee/blob/master/docs/reactivity/overview.md Initializes the DialogSystem with a reactive array to store dialogs using `ref`. Requires `ovee.js` import. ```javascript import { ref } from 'ovee.js'; let instance; export class DialogSystem { constructor() { const root = document.createElement('div'); root.classList.add('dialog-root') document.body.appendChild(document) // store dialogs this.dialogs = ref([]) } /* ... */ } ``` -------------------------------- ### Register Modules with App Constructor Source: https://github.com/owlsdepartment/ovee/blob/master/docs/modules.md Register modules when creating a new App instance by passing an array to the 'modules' configuration. Modules can be passed directly or as an array with their configuration options. ```javascript const app = new App({ modules: [ FirstModule, [SecondModule, { // options }] ] }); ``` -------------------------------- ### Ovee.js Reactivity API Usage Source: https://context7.com/owlsdepartment/ovee/llms.txt Demonstrates the use of ref, makeReactive, makeComputed, markRaw, and doWatchEffect for managing reactive state and side effects. Use these primitives for shared state, store patterns, or utility classes outside of components. ```javascript import { ref, makeReactive, makeComputed, doWatchEffect, markRaw, toRefs, isRef } from 'ovee.js'; // --- ref: single reactive value --- const count = ref(0); count.value++; console.log(count.value); // 1 // --- makeReactive: reactive plain object --- const store = makeReactive({ users: [], loading: false, }); store.users.push({ id: 1, name: 'Alice' }); // --- makeComputed: lazy cached computation --- const activeUsers = makeComputed(() => store.users.filter(u => u.active)); console.log(activeUsers.value); // evaluated lazily // --- markRaw: prevent deep reactivity wrapping --- const socket = markRaw(new WebSocket('wss://example.com')); store.socket = socket; // won't be made reactive // --- doWatchEffect: auto-tracking effect --- const stop = doWatchEffect(() => { document.title = `Users online: ${activeUsers.value.length}`; // Automatically re-runs when activeUsers changes }); // Call stop() to cancel the effect stop(); // --- Shared state store pattern --- export const postsStore = makeReactive({ posts: [] as Post[], selectedId: null as number | null, selected: makeComputed(() => { return postsStore.posts.find(p => p.id === postsStore.selectedId) ?? null; }), }); export const postsMutations = { async fetchAll() { const res = await fetch('/api/posts'); postsStore.posts = await res.json(); }, select(id: number) { postsStore.selectedId = id; }, }; // Use in any TemplateComponent — template re-renders on store change import { TemplateComponent, register } from 'ovee.js'; @register('posts-list') class PostsList extends TemplateComponent { template() { return this.html`Current value: ${this.counter}
` } } ``` -------------------------------- ### Render Open Dialogs with Computed and Watcher Source: https://github.com/owlsdepartment/ovee/blob/master/docs/reactivity/overview.md Uses `makeComputed` to filter open dialogs and `watchEffect` to re-render the dialogs when their state changes. Requires `ovee.js`. ```javascript export class DialogSystem { /* ... */ constructor() { /* ... */ this.openDialogs = makeComputed(() => { return this.dialogs.filter(d => d.isOpen) }) watchEffect(() => { this.root.innerHTML = this.openDialogs.value.reduce((acc, dialog) => { return acc + dialog.render(); }, '') }) } /* ... */ } ``` -------------------------------- ### @reactive Source: https://github.com/owlsdepartment/ovee/blob/master/docs/component-decorators.md Makes a class property reactive by utilizing the `makeReactive` function. This allows for automatic updates and state management. ```APIDOC ## @reactive Makes property reactive by using [`makeReactive`](/reactivity#makeReactive). ### Example ```js @register('my-component') class MyComponent extends Component { @reactive() counter; } ``` ``` -------------------------------- ### Register Component with @register Source: https://github.com/owlsdepartment/ovee/blob/master/docs/component-decorators.md Use the @register decorator to add a static getName() method to a component, which is required for registration. The name must be a two-word string in PascalCase, camelCase, or kebab-case. ```javascript @register('my-component') class MyComponent extends Component {} ``` -------------------------------- ### Ovee.js TodoList TemplateComponent Implementation Source: https://context7.com/owlsdepartment/ovee/llms.txt Implements a todo list component using TemplateComponent for reactive DOM rendering with lit-html. Reactive properties automatically trigger re-renders. Use `dataParam` to sync attributes. ```typescript import { TemplateComponent, register, reactive, bind, dataParam } from 'ovee.js'; @register('todo-list') export class TodoList extends TemplateComponent { @reactive() items: string[] = []; @reactive() @dataParam('filter') // reads from data-filter attribute, auto-syncs filter = 'all'; @bind('click', { target: '.add-btn' }) addItem() { this.items = [...this.items, `Item ${this.items.length + 1}`]; } // Override to provide reactive HTML — re-runs automatically on reactive changes template() { const visible = this.filter === 'all' ? this.items : this.items.slice(0, 3); return this.html`Showing ${visible.length} of ${this.items.length}
`; } async init() { // Wait for first render before accessing rendered elements await this.$requestUpdate(); console.log('First render complete'); console.log(this.$element.querySelector('.todo-list')); //