# Core-v2 integration patterns ## Contents 1. [Install and bootstrap](#install-and-bootstrap) 2. [Mental model](#mental-model) 3. [Actions and retained history](#actions-and-retained-history) 4. [Gesture builder](#gesture-builder) 5. [Custom choreography](#custom-choreography) 6. [Connected partial presentations](#connected-partial-presentations) 7. [Nested scenes](#nested-scenes) 8. [Constraints and verification](#constraints-and-verification) ## Install and bootstrap Install the Git package. Pin a commit or tag for reproducible applications: ```bash npm install "git+https://git.harvmaster.com/Harvmaster/Native-Router-Vue.git#" ``` The unpinned default-branch form is useful during active development: ```bash npm install git+https://git.harvmaster.com/Harvmaster/Native-Router-Vue.git ``` The installed package name is `@native-vue-router/core-v2`. It has one peer dependency: Vue `^3.5.0`. It does not depend on Vue Router. Create the scene: ```ts // src/scene.ts import { createOriginScene, originView } from "@native-vue-router/core-v2"; import HomeView from "./views/HomeView.vue"; export const scene = createOriginScene({ initial: originView( HomeView, { accountId: "42" }, { key: "home", name: "Home" }, ), }); ``` Render it: ```vue ``` The scene needs a definite width and height. Its view hosts are stable, absolutely positioned siblings. ## Mental model - `OriginView`: immutable recipe containing a Vue component, props, and optional diagnostic key/name. - Scene node: one mounted instance created from a recipe. - Operation edge: temporary source→target relationship with progress, velocity, choreography, and commit/cancel outcome. - Origin: the mounted component that handled the event. There is no global current view. - Retained history: linked mounted instances, independent of URLs. A newly created target can originate another operation while its incoming operation settles. Visual transforms compose by origin frame: ```text visual(Y) = X→Y.target × Y→Z.source visual(Z) = X→Y.target × Y→Z.target ``` ## Actions and retained history Helpers are overloaded: - Without choreography they return `OriginNavigationIntent` for a gesture builder. - With choreography they return a complete `OriginAction` for `begin()` or `perform()`. ### Forward ```ts const profileView = () => originView( ProfileView, { userId: "7" }, { key: "profile-7", name: "Profile" }, ); await origin.perform(forward(profileView(), slideLeft)); ``` Commit parks but retains the origin. Back later restores that exact instance, including local state and DOM scroll position. ### Back ```ts if (origin.context.value.canGoBack) { await origin.perform(back(slideRight)); } ``` Back has no target recipe. It resolves `previousNodeKey`, animates the retained instance, and unmounts the current entry only on commit. Useful context: ```ts const origin = useOrigin(); origin.nodeKey; origin.context.value.view; origin.context.value.previous; origin.context.value.history; origin.context.value.canGoBack; ``` ### Replace ```ts await origin.perform( replace( originView( OrderConfirmationView, { orderId: "NVO-2048" }, { key: "confirmation", name: "Confirmation" }, ), slideLeft, ), ); ``` Replace creates a target linked to the current origin's predecessor. Commit unmounts the current entry; cancellation removes the proposed replacement and restores the current entry. Back from the replacement skips the removed view. ### Placement `above()` and `under()` select stacking, not direction or history: ```ts above(originView(DialogView), fade); under(originView(BackdropView), reveal); ``` Prefer `forward`, `back`, and `replace` when expressing history semantics. ## Gesture builder Declare an anywhere forward gesture and responsive edge Back: ```vue ``` Builder stages: 1. Optional `.from`: pointer-down eligibility. 2. `.to`: direction recognition and axis lock. 3. Optional `.complete`: release policy. 4. `.navigate`: destination/history intent. 5. `.animate`: visual choreography. Starting at `.to` permits pointer-down anywhere. Edge distances accept CSS pixels, percentages, `calc()`, and `clamp()`. Use `.from.when(context => ...)` for arbitrary shapes, safe areas, or exclusion regions. Set explicit completion policy for product-specific velocity behavior: ```ts const open = gesture.to .left() .complete( ({ progress, velocity }) => progress >= 0.38 || (progress >= 0.06 && velocity >= 0.85), ) .navigate(() => forward(detailsView())) .animate(slideLeft); ``` Use `OriginGesture` when only one definition owns the host: ```vue
...
``` ## Custom choreography Effects are recomputed often. Keep them pure: ```ts import { defineOriginChoreography } from "@native-vue-router/core-v2"; const percent = (value: number) => `${value * 100}%`; export const focusCard = defineOriginChoreography({ name: "focus-card", commitThreshold: 0.36, effects: ({ progress }) => ({ frame: { transform: `translateY(${-Math.sin(progress * Math.PI) * 8}px)`, }, source: { transform: `scale(${1 - progress * 0.08})`, opacity: 1 - progress * 0.45, }, target: { transform: `translateY(${percent((1 - progress) * 0.1)}) scale(${ 0.82 + progress * 0.18 })`, opacity: progress, style: { borderRadius: `${(1 - progress) * 28}px`, }, }, }), }); ``` `frame` affects both sides and descendants. Transforms concatenate, opacities multiply, and other `style` properties use local-last precedence. Choreography context includes progress, velocity, phase, intent, measured origin/target rectangles, and scene viewport. ## Connected partial presentations Normal forward commit removes its operation edge and parks the retained source. Set `persistAtRest: true` when progress-1 effects must remain connected: ```ts export const openDrawer = defineOriginChoreography({ name: "open-two-thirds-drawer", persistAtRest: true, effects: ({ progress }) => ({ source: { transform: `translateX(${progress * 66.6667}%)`, }, target: { transform: `translateX(${(progress - 1) * 66.6667}%)`, }, }), }); export const closeDrawer = defineOriginChoreography({ name: "close-two-thirds-drawer", effects: ({ progress }) => ({ source: { transform: `translateX(${-progress * 66.6667}%)`, }, target: { transform: `translateX(${(1 - progress) * 66.6667}%)`, }, }), }); ``` Open with a retained push: ```ts forward(originView(DrawerView), openDrawer); ``` The source becomes `exposed`: mounted and visible, but inert and `aria-hidden`. The drawer is active. Back temporarily suspends the settled opening edge and uses the close choreography. A cancelled Back restores the opening relationship; committed Back removes the drawer. Requirements: - Use `persistAtRest` only with push history. - Make close progress 0 visually identical to open progress 1. - Put a transparent interactive region in the target if tapping the exposed source area should dismiss; the source itself is intentionally inert. - Do not treat settled connected edges as live animations in diagnostics. ## Nested scenes Create another scene when an embedded component needs independent history: ```ts const carouselScene = createOriginScene({ initial: originView(CarouselSlide, { index: 0 }), }); ``` Render `` inside the parent view. The nearest injected node scope owns `useOrigin()` and gestures. Current parent/child ownership is selected at pointer-down. Give the child a non-overlapping `.from` region when the parent must retain fallback behavior. Do not assume a child can decline after capture and automatically hand the same pointer sequence to its parent. ## Constraints and verification - No URL, deep-link, route-param, or browser-history model is included. Model data as props/state and bridge host Back separately. - No global active view exists. The component receiving the event is the origin. - Pushed entries remain mounted until Back pops them. There is no eviction policy yet. - Parked/exposed entries are inert, but their Vue watchers, timers, and effects continue running. - One origin owns at most one outgoing operation; a target may originate the next operation once its incoming intent commits. - Gesture recognition handles one primary pointer and one axis. - Nested scenes have separate history and measurements. - `KeepAlive` is not the scene cache and should not wrap scene navigation. - Reduced-motion preference settles operations immediately. Verify scene diagnostics and DOM behavior: ```ts scene.nodes.value; scene.operations.value; scene.contextFor(nodeKey); scene.styleForNode(nodeKey); ``` Test committed and cancelled operations, component mount/unmount counts, retained DOM identity, scroll position, rapid chained operations, replace history, connected presentation cancellation, responsive edge regions, focus, inert/ARIA behavior, and production bundling.