@ssgoi/vue 7.4.0 → 7.5.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ssgoi/vue
2
2
 
3
- Vue and Nuxt bindings for SSGOI.
3
+ Native app-like page transitions for Vue and Nuxt. Make a web app, PWA or WebView app (Capacitor, Tauri, Ionic) feel like a native app without replacing your router.
4
4
 
5
5
  [![SSGOI live showcase](https://ssgoi.dev/readme.png)](https://ssgoi.dev)
6
6
 
@@ -12,15 +12,59 @@ npm install @ssgoi/vue
12
12
 
13
13
  Agent setup guide: https://ssgoi.dev/llms/vue.txt
14
14
 
15
- ## Router helpers
15
+ ## Layout boundary
16
16
 
17
- Install this framework package once; router helpers are optional subpaths.
18
- These router helpers are experimental APIs and may change.
17
+ Pass a reactive route getter to `<Ssgoi>` once, then wrap routed content in
18
+ `SsgoiLayoutBoundary`.
19
19
 
20
- | Router | Import | API |
21
- | ---------- | ----------------------- | -------------------- |
22
- | Vue Router | `@ssgoi/vue/vue-router` | `SsgoiRouteBoundary` |
23
- | Nuxt | `@ssgoi/vue/nuxt` | `SsgoiRouteBoundary` |
20
+ ```vue
21
+ <script setup lang="ts">
22
+ import { useRouter } from "vue-router"; // Nuxt: auto-imported
23
+ import { Ssgoi, SsgoiLayoutBoundary } from "@ssgoi/vue";
24
+
25
+ const router = useRouter();
26
+ const framework = {
27
+ getRoute: () => ({ pathname: router.currentRoute.value.path }),
28
+ };
29
+ </script>
30
+
31
+ <template>
32
+ <Ssgoi :config="config" :framework="framework">
33
+ <SsgoiLayoutBoundary>
34
+ <RouterView />
35
+ </SsgoiLayoutBoundary>
36
+ </Ssgoi>
37
+ </template>
38
+ ```
39
+
40
+ Each boundary marks the current path with `data-ssgoi-transition`. Nest them
41
+ freely: depth is automatic. Declare which paths share a layout in
42
+ `config.layouts`; the scope matched at a boundary's depth keeps its DOM, and
43
+ past the declared scopes a boundary remounts on every path change (the default
44
+ without `layouts`).
45
+
46
+ ```ts
47
+ const TOP_LEVEL = ["/home", "/search", "/profile"];
48
+ const config = {
49
+ layouts: [
50
+ { paths: TOP_LEVEL }, // tabs share one depth-0 layout
51
+ {
52
+ paths: "/**",
53
+ except: TOP_LEVEL,
54
+ layouts: [{ paths: "/products/**" }], // depth-1 scope inside details
55
+ },
56
+ ],
57
+ transitions: [/* ... */],
58
+ };
59
+ ```
60
+
61
+ The first matching scope at each level wins. Single-segment captures (`*`,
62
+ `:id`, `[id]`) split instances, so `/projects/:id/**` keeps one layout per
63
+ project; `**` tails do not. `SsgoiLayoutBoundary` takes no SSGOI props (`as`
64
+ sets the element) and throws without `framework` on `<Ssgoi>`.
65
+
66
+ `SsgoiRouteBoundary` from `@ssgoi/vue/vue-router` and `@ssgoi/vue/nuxt` is
67
+ deprecated; use `SsgoiLayoutBoundary` with `framework` instead.
24
68
 
25
69
  See the [framework guide](https://ssgoi.dev/docs/frameworks/vue) for wiring and limits.
26
70
 
@@ -31,6 +75,10 @@ See the [framework guide](https://ssgoi.dev/docs/frameworks/vue) for wiring and
31
75
  import { Ssgoi } from "@ssgoi/vue";
32
76
  import { drill } from "@ssgoi/vue/view-transitions";
33
77
 
78
+ const router = useRouter();
79
+ const framework = {
80
+ getRoute: () => ({ pathname: router.currentRoute.value.path }),
81
+ };
34
82
  const config = {
35
83
  transitions: [{ on: "/posts/**", except: "/posts", transition: drill() }],
36
84
  };
@@ -38,7 +86,7 @@ const config = {
38
86
 
39
87
  <template>
40
88
  <main class="ssgoi-shell">
41
- <Ssgoi :config="config">
89
+ <Ssgoi :config="config" :framework="framework">
42
90
  <NuxtPage />
43
91
  </Ssgoi>
44
92
  </main>
package/dist/context.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),t=Symbol("ssgoi-context"),s=o=>{e.provide(t,o)},i=()=>{const o=e.inject(t);if(!o)throw new Error("useSsgoi must be used within Ssgoi component");return o};exports.provideSsgoi=s;exports.useSsgoi=i;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("vue"),i=Symbol("ssgoi-context"),r=Symbol("ssgoi-layout"),u=Symbol("ssgoi-layout-depth"),a=(o,e)=>{t.provide(i,o),t.provide(r,e)},S=()=>t.inject(r,void 0),g=()=>{const o=t.inject(u,0);return t.provide(u,o+1),o},l=()=>{const o=t.inject(i);if(!o)throw new Error("useSsgoi must be used within Ssgoi component");return o},y=()=>{const o=t.inject(i);if(!o)throw new Error("useSsgoiTransition must be used within Ssgoi component");const e=t.shallowRef(o.value.getTransitionState());let s;return t.watch(o,n=>{s?.(),e.value=n.getTransitionState(),s=n.subscribe(c=>{e.value=c})},{immediate:!0}),t.onScopeDispose(()=>s?.()),t.shallowReadonly(e)};exports.provideSsgoi=a;exports.useLayoutDepth=g;exports.useSsgoi=l;exports.useSsgoiLayout=S;exports.useSsgoiTransition=y;
package/dist/context.d.ts CHANGED
@@ -1,6 +1,26 @@
1
- import { ComputedRef } from 'vue';
2
- import { SsgoiContext } from './types';
1
+ import { ComputedRef, ShallowRef } from 'vue';
2
+ import { SsgoiContext, SsgoiTransitionState } from './types';
3
+ /** Route state `<Ssgoi>` resolves once for every layout boundary below it. */
4
+ export interface SsgoiLayoutState {
5
+ routePath: string;
6
+ chain: string[];
7
+ }
3
8
  type SsgoiContextRef = ComputedRef<SsgoiContext>;
4
- export declare const provideSsgoi: (context: SsgoiContextRef) => void;
9
+ type SsgoiLayoutRef = ComputedRef<SsgoiLayoutState | undefined>;
10
+ export declare const provideSsgoi: (context: SsgoiContextRef, layout: SsgoiLayoutRef) => void;
11
+ /** Layout state of the nearest `<Ssgoi>`; undefined without a framework. */
12
+ export declare const useSsgoiLayout: () => SsgoiLayoutRef | undefined;
13
+ /** Depth of the calling layout boundary; its descendants see one deeper. */
14
+ export declare const useLayoutDepth: () => number;
5
15
  export declare const useSsgoi: () => SsgoiContextRef;
16
+ /**
17
+ * Ref of the provider's transition lifecycle: whether a page transition is
18
+ * preparing or playing, and which routes it joins.
19
+ *
20
+ * Use it to defer work that would fight the animation, such as a programmatic
21
+ * scroll on the arriving page, until the status returns to `"idle"`.
22
+ *
23
+ * Must be called in `setup()`, under `<Ssgoi>`.
24
+ */
25
+ export declare const useSsgoiTransition: () => Readonly<ShallowRef<SsgoiTransitionState>>;
6
26
  export {};
package/dist/context.js CHANGED
@@ -1,13 +1,36 @@
1
- import { provide as e, inject as s } from "vue";
2
- const t = Symbol("ssgoi-context"), n = (o) => {
3
- e(t, o);
4
- }, r = () => {
5
- const o = s(t);
1
+ import { inject as e, provide as n, shallowRef as S, watch as g, onScopeDispose as l, shallowReadonly as y } from "vue";
2
+ const i = Symbol("ssgoi-context"), c = Symbol("ssgoi-layout"), u = Symbol("ssgoi-layout-depth"), h = (o, t) => {
3
+ n(i, o), n(c, t);
4
+ }, m = () => e(c, void 0), b = () => {
5
+ const o = e(u, 0);
6
+ return n(u, o + 1), o;
7
+ }, d = () => {
8
+ const o = e(i);
6
9
  if (!o)
7
10
  throw new Error("useSsgoi must be used within Ssgoi component");
8
11
  return o;
12
+ }, w = () => {
13
+ const o = e(i);
14
+ if (!o)
15
+ throw new Error("useSsgoiTransition must be used within Ssgoi component");
16
+ const t = S(
17
+ o.value.getTransitionState()
18
+ );
19
+ let s;
20
+ return g(
21
+ o,
22
+ (r) => {
23
+ s?.(), t.value = r.getTransitionState(), s = r.subscribe((a) => {
24
+ t.value = a;
25
+ });
26
+ },
27
+ { immediate: !0 }
28
+ ), l(() => s?.()), y(t);
9
29
  };
10
30
  export {
11
- n as provideSsgoi,
12
- r as useSsgoi
31
+ h as provideSsgoi,
32
+ b as useLayoutDepth,
33
+ d as useSsgoi,
34
+ m as useSsgoiLayout,
35
+ w as useSsgoiTransition
13
36
  };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@ssgoi/core/types"),o=require("./ssgoi.vue.cjs"),s=require("./ssgoi-transition.vue.cjs"),r=require("@ssgoi/core");exports.Ssgoi=o.default;exports.SsgoiTransition=s.default;Object.keys(t).forEach(e=>{e!=="default"&&!Object.prototype.hasOwnProperty.call(exports,e)&&Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})});Object.keys(r).forEach(e=>{e!=="default"&&!Object.prototype.hasOwnProperty.call(exports,e)&&Object.defineProperty(exports,e,{enumerable:!0,get:()=>r[e]})});
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@ssgoi/core/types"),o=require("./ssgoi.vue.cjs"),s=require("./context.cjs"),u=require("./layout-boundary.cjs"),i=require("./legacy/ssgoi-transition.vue.cjs"),r=require("@ssgoi/core");exports.Ssgoi=o.default;exports.useSsgoiTransition=s.useSsgoiTransition;exports.SsgoiLayoutBoundary=u.SsgoiLayoutBoundary;exports.SsgoiTransition=i.default;Object.keys(t).forEach(e=>{e!=="default"&&!Object.prototype.hasOwnProperty.call(exports,e)&&Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})});Object.keys(r).forEach(e=>{e!=="default"&&!Object.prototype.hasOwnProperty.call(exports,e)&&Object.defineProperty(exports,e,{enumerable:!0,get:()=>r[e]})});
package/dist/index.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  export * from './types';
2
2
  export { default as Ssgoi } from './ssgoi.vue';
3
- /** @deprecated Set `data-ssgoi-transition` directly on an element inside `<Ssgoi>` instead. */
4
- export { default as SsgoiTransition } from './ssgoi-transition.vue';
3
+ export { useSsgoiTransition } from './context';
4
+ export { SsgoiLayoutBoundary } from './layout-boundary';
5
+ export type { SsgoiLayoutBoundaryProps } from './layout-boundary';
6
+ /** @deprecated Will be removed in 8.0.0. */
7
+ export { default as SsgoiTransition } from './routers/ssgoi-transition.vue';
5
8
  export * from '@ssgoi/core';
package/dist/index.js CHANGED
@@ -1,8 +1,12 @@
1
1
  export * from "@ssgoi/core/types";
2
2
  import { default as e } from "./ssgoi.vue.js";
3
- import { default as a } from "./ssgoi-transition.vue.js";
3
+ import { useSsgoiTransition as a } from "./context.js";
4
+ import { SsgoiLayoutBoundary as i } from "./layout-boundary.js";
5
+ import { default as p } from "./legacy/ssgoi-transition.vue.js";
4
6
  export * from "@ssgoi/core";
5
7
  export {
6
8
  e as Ssgoi,
7
- a as SsgoiTransition
9
+ i as SsgoiLayoutBoundary,
10
+ p as SsgoiTransition,
11
+ a as useSsgoiTransition
8
12
  };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("vue"),n=require("./context.cjs");function i(o,u,{attrs:e,slots:r}){const t=a.computed(o);return()=>a.h(u(),{...e,key:t.value.key,"data-ssgoi-transition":t.value.id},r.default?.())}function s(){throw new Error('SSGOI: SsgoiLayoutBoundary requires a framework. Pass it to <Ssgoi :framework="{ getRoute }">.')}const d=a.defineComponent({name:"SsgoiLayoutBoundary",inheritAttrs:!1,props:{as:{type:String,default:"div"}},setup(o,u){const e=n.useSsgoiLayout();e?.value||s();const r=n.useLayoutDepth();return i(()=>{const{routePath:t,chain:y}=e.value??s();return{id:t,key:y[r]??t}},()=>o.as,u)}});exports.SsgoiLayoutBoundary=d;exports.setupRouteBoundary=i;
@@ -0,0 +1,26 @@
1
+ import { PropType, SetupContext } from 'vue';
2
+ export interface SsgoiLayoutBoundaryProps {
3
+ as?: keyof HTMLElementTagNameMap;
4
+ }
5
+ /** Shared setup; renders an element keyed by `state().key`. */
6
+ export declare function setupRouteBoundary(state: () => {
7
+ id: string;
8
+ key: string | number;
9
+ }, as: () => keyof HTMLElementTagNameMap, { attrs, slots }: Pick<SetupContext, "attrs" | "slots">): () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
10
+ [key: string]: any;
11
+ }>;
12
+ export declare const SsgoiLayoutBoundary: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
13
+ as: {
14
+ type: PropType<keyof HTMLElementTagNameMap>;
15
+ default: string;
16
+ };
17
+ }>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
18
+ [key: string]: any;
19
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
20
+ as: {
21
+ type: PropType<keyof HTMLElementTagNameMap>;
22
+ default: string;
23
+ };
24
+ }>> & Readonly<{}>, {
25
+ as: keyof HTMLElementTagNameMap;
26
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -0,0 +1,46 @@
1
+ import { defineComponent as s, computed as i, h as y } from "vue";
2
+ import { useSsgoiLayout as d, useLayoutDepth as p } from "./context.js";
3
+ function f(e, r, { attrs: t, slots: a }) {
4
+ const o = i(e);
5
+ return () => y(
6
+ r(),
7
+ {
8
+ ...t,
9
+ key: o.value.key,
10
+ "data-ssgoi-transition": o.value.id
11
+ },
12
+ a.default?.()
13
+ );
14
+ }
15
+ function u() {
16
+ throw new Error(
17
+ 'SSGOI: SsgoiLayoutBoundary requires a framework. Pass it to <Ssgoi :framework="{ getRoute }">.'
18
+ );
19
+ }
20
+ const g = s({
21
+ name: "SsgoiLayoutBoundary",
22
+ inheritAttrs: !1,
23
+ props: {
24
+ as: {
25
+ type: String,
26
+ default: "div"
27
+ }
28
+ },
29
+ setup(e, r) {
30
+ const t = d();
31
+ t?.value || u();
32
+ const a = p();
33
+ return f(
34
+ () => {
35
+ const { routePath: o, chain: n } = t.value ?? u();
36
+ return { id: o, key: n[a] ?? o };
37
+ },
38
+ () => e.as,
39
+ r
40
+ );
41
+ }
42
+ });
43
+ export {
44
+ g as SsgoiLayoutBoundary,
45
+ f as setupRouteBoundary
46
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("vue"),i=require("../layout-boundary.cjs"),d=u=>a.defineComponent({name:"SsgoiRouteBoundary",inheritAttrs:!1,props:{as:{type:String,default:"div"},routeKey:{type:[String,Number],default:void 0},resolve:{type:Function,default:void 0}},setup(e,r){const n=u();return i.setupRouteBoundary(()=>{const o=n.getRoute(),t=e.resolve?.(o)??{id:o.pathname};return{id:t.id,key:e.routeKey??t.key??t.id}},()=>e.as,r)}});exports.createSubpathRouteBoundary=d;
@@ -0,0 +1,34 @@
1
+ import { defineComponent as a } from "vue";
2
+ import { setupRouteBoundary as i } from "../layout-boundary.js";
3
+ const y = (r) => a({
4
+ name: "SsgoiRouteBoundary",
5
+ inheritAttrs: !1,
6
+ props: {
7
+ as: {
8
+ type: String,
9
+ default: "div"
10
+ },
11
+ routeKey: { type: [String, Number], default: void 0 },
12
+ resolve: {
13
+ type: Function,
14
+ default: void 0
15
+ }
16
+ },
17
+ setup(e, u) {
18
+ const n = r();
19
+ return i(
20
+ () => {
21
+ const o = n.getRoute(), t = e.resolve?.(o) ?? { id: o.pathname };
22
+ return {
23
+ id: t.id,
24
+ key: e.routeKey ?? t.key ?? t.id
25
+ };
26
+ },
27
+ () => e.as,
28
+ u
29
+ );
30
+ }
31
+ });
32
+ export {
33
+ y as createSubpathRouteBoundary
34
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),r=require("../context.cjs"),l=e.defineComponent({__name:"ssgoi-transition",props:{id:{},as:{default:"div"},class:{default:void 0}},setup(t){const n=t,i=r.useSsgoi(),c=s=>{const o=s,a=s instanceof HTMLElement?s:o?.$el;a instanceof HTMLElement&&i.value.refFor(n.id)(a)};return(s,o)=>(e.openBlock(),e.createBlock(e.resolveDynamicComponent(t.as),{ref:c,"data-ssgoi-transition":t.id,class:e.normalizeClass(n.class)},{default:e.withCtx(()=>[e.renderSlot(s.$slots,"default")]),_:3},8,["data-ssgoi-transition","class"]))}});exports.default=l;
@@ -1,5 +1,5 @@
1
1
  import { defineComponent as r, openBlock as c, createBlock as l, resolveDynamicComponent as d, normalizeClass as f, withCtx as m, renderSlot as u } from "vue";
2
- import { useSsgoi as p } from "./context.js";
2
+ import { useSsgoi as p } from "../context.js";
3
3
  const C = /* @__PURE__ */ r({
4
4
  __name: "ssgoi-transition",
5
5
  props: {
package/dist/nuxt.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("nuxt/app"),r=require("./routers/route-boundary.cjs"),t=r.createRouteBoundary(()=>{const e=o.useRouter();return()=>e.currentRoute.value.path});exports.SsgoiRouteBoundary=t;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("nuxt/app"),o=require("./legacy/route-boundary.cjs"),u=o.createSubpathRouteBoundary(()=>{const e=t.useRouter();return{getRoute:()=>({pathname:e.currentRoute.value.path})}});exports.SsgoiRouteBoundary=u;
package/dist/nuxt.d.ts CHANGED
@@ -1,2 +1 @@
1
- export * from './routers/nuxt'
2
1
  export {}
package/dist/nuxt.js CHANGED
@@ -1,9 +1,9 @@
1
- import { useRouter as r } from "nuxt/app";
2
- import { createRouteBoundary as t } from "./routers/route-boundary.js";
3
- const n = t(() => {
4
- const o = r();
5
- return () => o.currentRoute.value.path;
1
+ import { useRouter as o } from "nuxt/app";
2
+ import { createSubpathRouteBoundary as e } from "./legacy/route-boundary.js";
3
+ const a = e(() => {
4
+ const t = o();
5
+ return { getRoute: () => ({ pathname: t.currentRoute.value.path }) };
6
6
  });
7
7
  export {
8
- n as SsgoiRouteBoundary
8
+ a as SsgoiRouteBoundary
9
9
  };
@@ -1,5 +1,8 @@
1
1
  export type { RouteBoundaryState, SsgoiRouteBoundaryProps, } from './route-boundary';
2
- /** @experimental nuxt integration. The API may change. */
2
+ /**
3
+ * @experimental nuxt integration. The API may change.
4
+ * @deprecated Will be removed in 8.0.0. Use `SsgoiLayoutBoundary` from "@ssgoi/vue" with `<Ssgoi :framework="{ getRoute: () => ({ pathname: router.currentRoute.value.path }) }">` (`useRouter` from "nuxt/app") instead.
5
+ */
3
6
  export declare const SsgoiRouteBoundary: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
4
7
  as: {
5
8
  type: import('vue').PropType<keyof HTMLElementTagNameMap>;
@@ -1,8 +1,11 @@
1
1
  import { PropType } from 'vue';
2
+ import { SsgoiFramework } from '../types';
3
+ /** @deprecated Will be removed in 8.0.0. Declare layout scopes in `config.layouts` and use `SsgoiLayoutBoundary` from "@ssgoi/vue" instead. */
2
4
  export interface RouteBoundaryState {
3
5
  id: string;
4
6
  key?: string | number;
5
7
  }
8
+ /** @deprecated Will be removed in 8.0.0. Declare layout scopes in `config.layouts` and use `SsgoiLayoutBoundary` from "@ssgoi/vue" instead. */
6
9
  export interface SsgoiRouteBoundaryProps {
7
10
  as?: keyof HTMLElementTagNameMap;
8
11
  routeKey?: string | number;
@@ -10,8 +13,12 @@ export interface SsgoiRouteBoundaryProps {
10
13
  pathname: string;
11
14
  }) => RouteBoundaryState;
12
15
  }
13
- /** Shared rendering only; each subpath supplies its own router hook. */
14
- export declare function createRouteBoundary(usePathname: () => () => string): import('vue').DefineComponent<import('vue').ExtractPropTypes<{
16
+ /**
17
+ * Legacy subpath boundary; each subpath builds its framework from its own
18
+ * router hook instead of reading `<Ssgoi :framework>`.
19
+ * @deprecated Will be removed in 8.0.0. Use `SsgoiLayoutBoundary` from "@ssgoi/vue" instead.
20
+ */
21
+ export declare const createSubpathRouteBoundary: (useFramework: () => SsgoiFramework) => import('vue').DefineComponent<import('vue').ExtractPropTypes<{
15
22
  as: {
16
23
  type: PropType<keyof HTMLElementTagNameMap>;
17
24
  default: string;
@@ -1,7 +1,4 @@
1
- /**
2
- * @deprecated Set `data-ssgoi-transition` directly on the page boundary
3
- * element inside `<Ssgoi>` instead.
4
- */
1
+ /** @deprecated Will be removed in 8.0.0. */
5
2
  interface Props {
6
3
  id: string;
7
4
  as?: keyof HTMLElementTagNameMap;
@@ -1,5 +1,8 @@
1
1
  export type { RouteBoundaryState, SsgoiRouteBoundaryProps, } from './route-boundary';
2
- /** @experimental vue-router integration. The API may change. */
2
+ /**
3
+ * @experimental vue-router integration. The API may change.
4
+ * @deprecated Will be removed in 8.0.0. Use `SsgoiLayoutBoundary` from "@ssgoi/vue" with `<Ssgoi :framework="{ getRoute: () => ({ pathname: router.currentRoute.value.path }) }">` instead.
5
+ */
3
6
  export declare const SsgoiRouteBoundary: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
4
7
  as: {
5
8
  type: import('vue').PropType<keyof HTMLElementTagNameMap>;
@@ -1 +1 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),a=require("./context.cjs"),i=require("@ssgoi/core/internal"),l=e.defineComponent({__name:"ssgoi",props:{config:{},host:{}},setup(c){const s=c,t=e.computed(()=>i.createSggoiTransitionContext(s.config,{host:s.host}));a.provideSsgoi(t);const n=e.ref(null);let o;const r=()=>{o?.(),o=void 0,n.value&&(o=i.observeSsgoiTransitions(n.value,t.value))};return e.onMounted(r),e.watch(t,r),e.onBeforeUnmount(()=>o?.()),(u,d)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"root",ref:n,"data-ssgoi-root":"",style:{display:"contents"}},[e.renderSlot(u.$slots,"default")],512))}});exports.default=l;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),d=require("./context.cjs"),i=require("@ssgoi/core/internal"),f=e.defineComponent({__name:"ssgoi",props:{config:{},host:{},framework:{}},setup(c){const t=c,r=e.computed(()=>i.createSggoiTransitionContext(t.config,{host:t.host})),l=e.computed(()=>{const o=t.framework?.getRoute();if(!o)return;const a=o.renderedPath??o.pathname;return{routePath:a,chain:i.resolveLayoutChain(t.config.layouts,a)}});d.provideSsgoi(r,l);const s=e.ref(null);let n;const u=()=>{n?.(),n=void 0,s.value&&(n=i.observeSsgoiTransitions(s.value,r.value))};return e.onMounted(u),e.watch(r,u),e.onBeforeUnmount(()=>n?.()),(o,a)=>(e.openBlock(),e.createElementBlock("div",{ref_key:"root",ref:s,"data-ssgoi-root":"",style:{display:"contents"}},[e.renderSlot(o.$slots,"default")],512))}});exports.default=f;
@@ -1,8 +1,9 @@
1
- import { SsgoiConfig } from './types';
1
+ import { SsgoiConfig, SsgoiFramework } from './types';
2
2
  import { HostAnimation } from '@ssgoi/core/internal';
3
3
  interface Props {
4
4
  config: SsgoiConfig;
5
5
  host?: HostAnimation;
6
+ framework?: SsgoiFramework;
6
7
  }
7
8
  declare function __VLS_template(): {
8
9
  attrs: Partial<{}>;
package/dist/ssgoi.vue.js CHANGED
@@ -1,32 +1,41 @@
1
- import { defineComponent as a, computed as c, ref as l, onMounted as p, watch as f, onBeforeUnmount as u, openBlock as m, createElementBlock as d, renderSlot as g } from "vue";
2
- import { provideSsgoi as v } from "./context.js";
3
- import { createSggoiTransitionContext as _, observeSsgoiTransitions as h } from "@ssgoi/core/internal";
4
- const y = /* @__PURE__ */ a({
1
+ import { defineComponent as l, computed as i, ref as f, onMounted as p, watch as m, onBeforeUnmount as d, openBlock as g, createElementBlock as v, renderSlot as h } from "vue";
2
+ import { provideSsgoi as y } from "./context.js";
3
+ import { createSggoiTransitionContext as _, resolveLayoutChain as k, observeSsgoiTransitions as S } from "@ssgoi/core/internal";
4
+ const B = /* @__PURE__ */ l({
5
5
  __name: "ssgoi",
6
6
  props: {
7
7
  config: {},
8
- host: {}
8
+ host: {},
9
+ framework: {}
9
10
  },
10
- setup(r) {
11
- const n = r, t = c(
12
- () => _(n.config, { host: n.host })
13
- );
14
- v(t);
15
- const e = l(null);
16
- let o;
17
- const s = () => {
18
- o?.(), o = void 0, e.value && (o = h(e.value, t.value));
11
+ setup(c) {
12
+ const t = c, r = i(
13
+ () => _(t.config, { host: t.host })
14
+ ), u = i(() => {
15
+ const o = t.framework?.getRoute();
16
+ if (!o) return;
17
+ const s = o.renderedPath ?? o.pathname;
18
+ return {
19
+ routePath: s,
20
+ chain: k(t.config.layouts, s)
21
+ };
22
+ });
23
+ y(r, u);
24
+ const n = f(null);
25
+ let e;
26
+ const a = () => {
27
+ e?.(), e = void 0, n.value && (e = S(n.value, r.value));
19
28
  };
20
- return p(s), f(t, s), u(() => o?.()), (i, S) => (m(), d("div", {
29
+ return p(a), m(r, a), d(() => e?.()), (o, s) => (g(), v("div", {
21
30
  ref_key: "root",
22
- ref: e,
31
+ ref: n,
23
32
  "data-ssgoi-root": "",
24
33
  style: { display: "contents" }
25
34
  }, [
26
- g(i.$slots, "default")
35
+ h(o.$slots, "default")
27
36
  ], 512));
28
37
  }
29
38
  });
30
39
  export {
31
- y as default
40
+ B as default
32
41
  };
package/dist/types.d.ts CHANGED
@@ -1 +1,12 @@
1
1
  export * from '@ssgoi/core/types';
2
+ /**
3
+ * Router bridge for `<Ssgoi :framework>`. `getRoute` must be a reactive
4
+ * getter, e.g. `() => ({ pathname: router.currentRoute.value.path })`.
5
+ * `renderedPath`, when given, is the path the page content shows.
6
+ */
7
+ export interface SsgoiFramework {
8
+ getRoute: () => {
9
+ pathname: string;
10
+ renderedPath?: string;
11
+ };
12
+ }
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("vue-router"),r=require("./routers/route-boundary.cjs"),t=r.createRouteBoundary(()=>{const e=o.useRouter();return()=>e.currentRoute.value.path});exports.SsgoiRouteBoundary=t;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("vue-router"),u=require("./legacy/route-boundary.cjs"),o=u.createSubpathRouteBoundary(()=>{const e=t.useRouter();return{getRoute:()=>({pathname:e.currentRoute.value.path})}});exports.SsgoiRouteBoundary=o;
@@ -1,2 +1 @@
1
- export * from './routers/vue-router'
2
1
  export {}
@@ -1,9 +1,9 @@
1
- import { useRouter as r } from "vue-router";
2
- import { createRouteBoundary as t } from "./routers/route-boundary.js";
3
- const n = t(() => {
4
- const o = r();
5
- return () => o.currentRoute.value.path;
1
+ import { useRouter as o } from "vue-router";
2
+ import { createSubpathRouteBoundary as e } from "./legacy/route-boundary.js";
3
+ const a = e(() => {
4
+ const t = o();
5
+ return { getRoute: () => ({ pathname: t.currentRoute.value.path }) };
6
6
  });
7
7
  export {
8
- n as SsgoiRouteBoundary
8
+ a as SsgoiRouteBoundary
9
9
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ssgoi/vue",
3
- "version": "7.4.0",
4
- "description": "Vue bindings for SSGOI - Native app-like page transitions for Vue applications",
3
+ "version": "7.5.0-beta.0",
4
+ "description": "Native app-like page transitions for Vue and Nuxt. Make a web app, PWA or WebView app feel native.",
5
5
  "private": false,
6
6
  "type": "module",
7
7
  "files": [
@@ -45,12 +45,12 @@
45
45
  }
46
46
  },
47
47
  "dependencies": {
48
- "@ssgoi/core": "^7.4.0"
48
+ "@ssgoi/core": "^7.5.0-beta.0"
49
49
  },
50
50
  "peerDependencies": {
51
+ "nuxt": "*",
51
52
  "vue": "^3.5.0",
52
- "vue-router": "*",
53
- "nuxt": "*"
53
+ "vue-router": "*"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@eslint/js": "^9.30.1",
@@ -59,22 +59,42 @@
59
59
  "eslint": "^9.30.1",
60
60
  "eslint-plugin-vue": "^9.33.0",
61
61
  "globals": "^16.3.0",
62
+ "jsdom": "^26.1.0",
63
+ "nuxt": "^3.20.2",
62
64
  "prettier": "^3.6.2",
63
65
  "rollup-plugin-preserve-directives": "^0.4.0",
64
66
  "typescript": "~5.8.3",
65
67
  "typescript-eslint": "^8.35.1",
66
68
  "vite": "^7.0.4",
67
69
  "vite-plugin-dts": "^4.5.4",
68
- "vue-tsc": "^2.2.12",
70
+ "vitest": "^3.2.4",
69
71
  "vue-router": "^4.6.3",
70
- "nuxt": "^3.20.2"
72
+ "vue-tsc": "^2.2.12"
71
73
  },
72
74
  "keywords": [
73
75
  "vue",
76
+ "vue-router",
77
+ "nuxt",
74
78
  "page-transition",
79
+ "page-transitions",
80
+ "route-transition",
81
+ "navigation-animation",
82
+ "native-app",
83
+ "app-like",
84
+ "mobile-web",
85
+ "webview",
86
+ "pwa",
87
+ "capacitor",
88
+ "react-native-webview",
89
+ "hybrid-app",
90
+ "view-transitions",
91
+ "view-transition-api-alternative",
92
+ "shared-element-transition",
93
+ "hero-transition",
94
+ "spring-physics",
95
+ "web-animations",
75
96
  "animation",
76
- "ssgoi",
77
- "spring-physics"
97
+ "ssgoi"
78
98
  ],
79
99
  "author": "MeurSyphus <tmdeoans@snu.ac.kr>",
80
100
  "license": "MIT",
@@ -107,6 +127,7 @@
107
127
  "watch": "vite build --watch",
108
128
  "lint": "eslint .",
109
129
  "preview": "vite preview",
110
- "package": "vite build"
130
+ "package": "vite build",
131
+ "test:run": "vitest run"
111
132
  }
112
133
  }
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("vue");function d(o){return u.defineComponent({name:"SsgoiRouteBoundary",inheritAttrs:!1,props:{as:{type:String,default:"div"},routeKey:{type:[String,Number],default:void 0},resolve:{type:Function,default:void 0}},setup(e,{attrs:a,slots:r}){const i=o(),t=u.computed(()=>{const n=i();return e.resolve?.({pathname:n})??{id:n}});return()=>u.h(e.as,{...a,key:e.routeKey??t.value.key??t.value.id,"data-ssgoi-transition":t.value.id},r.default?.())}})}exports.createRouteBoundary=d;
@@ -1,36 +0,0 @@
1
- import { defineComponent as i, computed as d, h as s } from "vue";
2
- function y(o) {
3
- return i({
4
- name: "SsgoiRouteBoundary",
5
- inheritAttrs: !1,
6
- props: {
7
- as: {
8
- type: String,
9
- default: "div"
10
- },
11
- routeKey: { type: [String, Number], default: void 0 },
12
- resolve: {
13
- type: Function,
14
- default: void 0
15
- }
16
- },
17
- setup(e, { attrs: a, slots: r }) {
18
- const u = o(), t = d(() => {
19
- const n = u();
20
- return e.resolve?.({ pathname: n }) ?? { id: n };
21
- });
22
- return () => s(
23
- e.as,
24
- {
25
- ...a,
26
- key: e.routeKey ?? t.value.key ?? t.value.id,
27
- "data-ssgoi-transition": t.value.id
28
- },
29
- r.default?.()
30
- );
31
- }
32
- });
33
- }
34
- export {
35
- y as createRouteBoundary
36
- };
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),r=require("./context.cjs"),l=e.defineComponent({__name:"ssgoi-transition",props:{id:{},as:{default:"div"},class:{default:void 0}},setup(t){const n=t,i=r.useSsgoi(),c=s=>{const o=s,a=s instanceof HTMLElement?s:o?.$el;a instanceof HTMLElement&&i.value.refFor(n.id)(a)};return(s,o)=>(e.openBlock(),e.createBlock(e.resolveDynamicComponent(t.as),{ref:c,"data-ssgoi-transition":t.id,class:e.normalizeClass(n.class)},{default:e.withCtx(()=>[e.renderSlot(s.$slots,"default")]),_:3},8,["data-ssgoi-transition","class"]))}});exports.default=l;