first commit

This commit is contained in:
2026-07-21 14:54:36 +10:00
commit e79c793b9c
134 changed files with 14427 additions and 0 deletions

56
docs/architecture.md Normal file
View File

@@ -0,0 +1,56 @@
# Architecture
## Ownership boundary
Vue Router owns matching, lazy components, committed routes, redirects, guards, URL serialization, and browser history. Native Vue Router owns a separate visual ledger containing mounted route entries, scroll/focus state, cache status, and the current interactive transaction.
A forward drag calls `router.resolve()` and Vue Router's public `loadRouteLocation()`, then renders the location through `<RouterView :route>` without calling `push()`. The URL and application history remain unchanged until the gesture commits.
Each preview subtree receives a scoped `routeLocationKey`, so `useRoute()` returns preview params even though the global route is not committed. A normal `router.push()` or `replace()` runs only after the gesture chooses to commit. A guard failure cancels the transaction and removes the preview.
## Transaction lifecycle
Transactions move through `interactive`, `committing`, `settling`, and cancellation states. They expose normalized progress and velocity plus `fromKey`, `toKey`, direction, presentation, and optional source geometry.
The runtime deliberately keeps two ledgers. The navigation stack mirrors committed push/replace/pop semantics and is the only source of predictive-back targets. The view cache owns mounted component instances independently, so a replaced tab can be reused without becoming an accidental back destination.
Pointer movement changes only a CSS progress variable. Built-in presentations restrict active-frame work to compositor-friendly properties. Release uses distance/velocity intent and a damped spring. Reduced-motion mode settles immediately.
Component gesture owners stop propagation before a containing navigator can claim the same pointer. Navigator gestures wait for horizontal intent, use pointer capture, respect form controls and `data-native-gesture="ignore"`, and preserve normal vertical scrolling through `touch-action: pan-y`.
## Route metadata
```ts
interface NativeRouteOptions {
navigator?: string
presentation?: 'push' | 'reveal' | 'slide' | 'fade' | 'modal' | 'sheet' | string
parent?: RouteLocationRaw | ((route) => RouteLocationRaw)
siblingGroup?: string
siblingOrder?: number
siblingHistory?: 'push' | 'replace'
cache?: boolean
gesture?: boolean | 'edge' | 'full'
}
```
`parent` supplies a predictive back target when a deep link starts without an in-memory predecessor. Sibling routes replace history by default and use the built-in `slide` presentation, which moves both pages one-to-one as adjacent surfaces. Direction comes from `siblingOrder`. Set `siblingHistory: 'push'` when browser back should visit prior sibling selections.
## Custom presentations
```ts
nativeRouter.registerPresentation(definePresentation({
name: 'scale-fade',
axis: 'x',
layerStyle({ role, progress }) {
return role === 'to'
? { opacity: progress, transform: `scale(${0.92 + progress * 0.08})` }
: { opacity: 1 - progress * 0.4 }
},
}))
```
Applications can call `beginInteractive()`, `updateInteractive()`, and `finishInteractive()` to drive the same transaction engine from a bespoke recognizer.
## Cache semantics
The active route and recent inactive routes remain mounted. The default limit is eight inactive views per runtime. Older entries keep their route descriptor but are unmounted and lazily restored when revisited. Application data that must survive eviction belongs in an application store.

23
docs/platforms.md Normal file
View File

@@ -0,0 +1,23 @@
# Platform integration
## PWA and browser
The demo uses a standalone manifest, safe-area environment variables, and a generated Workbox service worker. Updates are prompted and cannot reload while a gesture is active. `overscroll-behavior` suppresses pull-to-refresh and history overscroll where supported; `touch-action` reserves horizontal manipulation only on navigator-owned surfaces.
Mobile operating systems can reserve gestures that web content cannot suppress in every browser mode. The full interaction system targets installed PWAs. Normal tabs retain links, buttons, history, and non-interactive transitions as their fallback.
## Electron
Call `disableElectronHistoryGestures(app.commandLine)` before `app.whenReady()`. It disables Chromium's `OverscrollHistoryNavigation`, preventing the host from racing the renderer's interactive stack. The included preload bridge maps app commands and Alt+Arrow shortcuts into the renderer adapter without enabling Node integration.
The demo switches to hash history under `file:` so packaged deep navigation never asks the filesystem for route paths.
## Capacitor
`createCapacitorAdapter()` handles Android hardware back, Universal/App Links, launch URLs, pause cancellation, root exit, and native haptic feedback.
The checked-in iOS and Android projects use Capacitor 8 and include App, Haptics, Splash Screen, and Status Bar plugins. Rebuild the web bundle before `npx cap sync`.
## Accessibility
Inactive live routes are `inert` and `aria-hidden`. Only the active or interactive pair participates in focus and pointer hit testing. Back and tab controls retain native link/button semantics; reduced-motion users receive immediate transaction settling. Custom presentations must preserve the same focus and inert invariants.