@melt-js/demo-vue3 0.0.3 → 2026.11.6
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 +44 -3
- package/dist/assets/CircularMenuView-Bm2jCflo.css +1 -0
- package/dist/assets/CircularMenuView-DVx3F33D.js +2 -0
- package/dist/assets/CircularMenuView-DVx3F33D.js.map +1 -0
- package/dist/assets/HostView-DMHAyQge.js +2 -0
- package/dist/assets/HostView-DMHAyQge.js.map +1 -0
- package/dist/assets/HostView-I-DgsKrJ.css +1 -0
- package/dist/assets/OverviewView-BRUCgEGh.js +2 -0
- package/dist/assets/OverviewView-BRUCgEGh.js.map +1 -0
- package/dist/assets/RemoteView-CD5hkZNz.js +2 -0
- package/dist/assets/RemoteView-CD5hkZNz.js.map +1 -0
- package/dist/assets/RemoteView-CurHWajw.css +1 -0
- package/dist/assets/_plugin-vue_export-helper-CzJpAC-G.js +2 -0
- package/dist/assets/_plugin-vue_export-helper-CzJpAC-G.js.map +1 -0
- package/dist/assets/index-tixem2vV.js +67 -0
- package/dist/assets/index-tixem2vV.js.map +1 -0
- package/dist/assets/loadApp-DK5s6_Re.js +11 -0
- package/dist/assets/loadApp-DK5s6_Re.js.map +1 -0
- package/dist/assets/loadApp-ExrGcnoV.css +1 -0
- package/dist/index.html +1 -1
- package/package.json +42 -40
- package/dist/assets/HostView-CO-PQ4Eg.css +0 -1
- package/dist/assets/HostView-p_QlXO2b.js +0 -2
- package/dist/assets/HostView-p_QlXO2b.js.map +0 -1
- package/dist/assets/OverviewView-Y30WcRVR.js +0 -2
- package/dist/assets/OverviewView-Y30WcRVR.js.map +0 -1
- package/dist/assets/RemoteView-DMITrjYR.js +0 -2
- package/dist/assets/RemoteView-DMITrjYR.js.map +0 -1
- package/dist/assets/index-CuPzn6_v.js +0 -67
- package/dist/assets/index-CuPzn6_v.js.map +0 -1
- package/dist/assets/loadApp-B7EqU81T.js +0 -11
- package/dist/assets/loadApp-B7EqU81T.js.map +0 -1
- package/dist/assets/loadApp-CXgewGYF.css +0 -1
package/README.md
CHANGED
|
@@ -2,18 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
Vue 3 + Vite 5 的 hel 宿主(消费方)示例,消费 [`comps-vue3`](../comps-vue3)。
|
|
4
4
|
|
|
5
|
+
页面使用 **vue-router(hash 模式)** 把示例拆成三个可切换的页面,顶部导航栏同时显示当前示例的简介,示例区右上角有**全屏按钮**(只放大当前示例的组件预览区,基于 `vue-fullscreen` 的 `pageOnly + teleport` 模式)。
|
|
6
|
+
|
|
5
7
|
| 项 | 值 |
|
|
6
8
|
| --- | --- |
|
|
7
9
|
| npm 包名 | `@melt-js/demo-vue3` |
|
|
8
10
|
| unpkg 入口 | `https://unpkg.com/@melt-js/demo-vue3/dist/index.html` |
|
|
9
11
|
| 端口 | `30020` |
|
|
10
12
|
| 消费的远程组件 | `comps-vue3`(开发 `http://localhost:20020` / 生产 unpkg) |
|
|
13
|
+
| 路由 | `vue-router@4.6.4`,hash 模式 |
|
|
14
|
+
| 全屏 | `vue-fullscreen@5.1.2`,`pageOnly` + `teleport`(不调用浏览器原生全屏) |
|
|
15
|
+
|
|
16
|
+
## 示例路由
|
|
17
|
+
|
|
18
|
+
| 路由 | 导航文案 | 内容 |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| `#/` | 简介 | demo 概览:依赖、端口、远端地址与示例入口 |
|
|
21
|
+
| `#/host` | 主应用 | 宿主自己的计数按钮,用来对照远程组件的行为 |
|
|
22
|
+
| `#/remote` | 远程组件 | `preFetchLib` 加载的 `comps-vue3` `HelloWorld` |
|
|
23
|
+
|
|
24
|
+
约定:
|
|
25
|
+
|
|
26
|
+
- **hash 模式**:demo 的构建产物会通过 unpkg 上的 `dist/index.html` 打开,history 模式在那种静态文件路径下会 404。
|
|
27
|
+
- 路由清单在 `src/router/index.ts`,每条路由的 `meta.title` / `meta.description` 同时驱动导航栏 tab 与下方那行简介;新增示例只要加一条路由。
|
|
28
|
+
- 全屏按钮只把当前示例标记为 `data-demo-preview` 的组件预览区送进全屏,页面标题、简介、说明与页脚都留在屏幕外;全屏借用 `vue-fullscreen` 5.x 的 `pageOnly + teleport` 模式:预览区临时挂到 body、用 fixed 铺满视口,退出时还原到页面原位置,不调用浏览器原生 Fullscreen API(iframe 内也可用)。预览区右下角提供「退出全屏」浮层按钮,Esc 也可退出;切换路由时会自动退出并还原。
|
|
29
|
+
- 需要全屏的示例在组件预览区外包一层 `<DemoPreview>`;简介页没有预览区,在路由 `meta` 里标记 `fullscreen: false`,工具栏不显示全屏按钮。
|
|
30
|
+
|
|
31
|
+
## 文件结构
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
demo-vue3/src
|
|
35
|
+
├── App.vue # demo 外壳:导航栏 + 示例舞台(含全屏按钮)+ router-view
|
|
36
|
+
├── components/
|
|
37
|
+
│ ├── DemoNavbar.vue # 顶部导航栏:示例 tab + 当前示例简介
|
|
38
|
+
│ ├── DemoPreview.vue # 组件预览区:全屏目标 + 「退出全屏」浮层按钮
|
|
39
|
+
│ └── ScreenfullButton.vue # 示例区全屏按钮
|
|
40
|
+
├── composables/
|
|
41
|
+
│ └── useDemoFullscreen.ts # vue-fullscreen 的 pageOnly + teleport 封装(provide/inject)
|
|
42
|
+
├── configs/
|
|
43
|
+
│ ├── app.ts # demo 展示信息(名称 / 端口 / unpkg 入口)
|
|
44
|
+
│ └── remote.ts # 远程组件地址与 preFetchLib(Promise 复用)
|
|
45
|
+
├── router/index.ts # 示例路由(hash 模式)
|
|
46
|
+
├── styles/demo-shell.css # 外壳样式(导航栏 / 舞台 / 全屏 / 通用排版)
|
|
47
|
+
├── style.css # 变量与全局重置
|
|
48
|
+
└── views/ # OverviewView / HostView / RemoteView
|
|
49
|
+
```
|
|
11
50
|
|
|
12
51
|
## 关键流程
|
|
13
52
|
|
|
14
53
|
1. `src/main.ts`:`bindVueRuntime({ Vue })` 把宿主 vue 挂到 `window.Vue`,远程组件 external 的 `vue` 会复用这一份(少了这一份会出现双 vue,表现为远程组件点击后视图不更新);随后在入口处调用 `loadRemoteLib()` 预加载远程组件,就绪后再挂载宿主。
|
|
15
54
|
2. `src/configs/remote.ts`:按 `import.meta.env.PROD` 选择远端地址——生产构建指向 unpkg 上的 `hel-meta.json`,本地开发指向 `http://localhost:20020`,可用 `VITE_REMOTE_HOST` 覆盖。`loadRemoteLib()` 内部调用 `preFetchLib('comps-vue3', { custom: { host } })`:host 为 `hel-meta.json` 时直接取元数据,本地 dev server 没有该文件时解析 `index.html`。
|
|
16
|
-
3. `src/
|
|
55
|
+
3. `src/router/index.ts` + `src/loadApp.ts`:创建 hash 路由并在 `createApp(App).use(router)` 时挂载;`#/host`、`#/remote` 等示例按路由懒加载。
|
|
56
|
+
4. `src/views/RemoteView.vue`:`defineAsyncComponent` 复用入口处已预加载的同一个 Promise,渲染远程组件的 `HelloWorld`。
|
|
57
|
+
5. `src/composables/useDemoFullscreen.ts` + `src/components/DemoPreview.vue`:`App.vue` 用 `provideDemoFullscreen()` 创建唯一一份 `useFullscreen` 控制器(`pageOnly`、`teleport`、`fullscreenClass: 'is-demo-fullscreen'`),`ScreenfullButton` 与 `DemoPreview` 通过 `useDemoFullscreen()` 共用它,全屏状态与「退出全屏」按钮始终同步;全屏目标由 App 解析为当前页面的 `[data-demo-preview]`。
|
|
17
58
|
|
|
18
59
|
> `vite build` 的产物会自动从 unpkg 加载已发布的 `comps-vue3`;`vite dev` 仍走本地 20020,无需手动改 `host`。
|
|
19
60
|
|
|
@@ -27,7 +68,7 @@ pnpm comps-vue3:dev
|
|
|
27
68
|
pnpm demo-vue3:dev
|
|
28
69
|
```
|
|
29
70
|
|
|
30
|
-
打开 http://localhost:30020
|
|
71
|
+
打开 <http://localhost:30020> ,`远程组件` 示例会渲染 `comps-vue3` 的 `HelloWorld` 组件。
|
|
31
72
|
|
|
32
73
|
也可以让宿主指向已构建的远程产物:
|
|
33
74
|
|
|
@@ -43,6 +84,6 @@ pnpm demo-vue3:build # 产出 dist/
|
|
|
43
84
|
pnpm --filter @melt-js/demo-vue3 run publish:stage # build → npm stage 暂存,等待 2FA 审批
|
|
44
85
|
```
|
|
45
86
|
|
|
46
|
-
- `vite.config.ts` 的 `base` 为 `./`,发布后 unpkg 上的 `dist/index.html`
|
|
87
|
+
- `vite.config.ts` 的 `base` 为 `./`,发布后 unpkg 上的 `dist/index.html` 可直接加载同目录资源;hash 路由同样可用。
|
|
47
88
|
- `files` 白名单只发布 `dist/` 与 README。
|
|
48
89
|
- 生产构建自动使用 `https://unpkg.com/@melt-js/comps-vue3/hel_dist/hel-meta.json`,本地开发自动使用 `http://localhost:20020`;也可用 `VITE_REMOTE_HOST` 覆盖。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.fan-demo[data-v-054d24e4]{display:flex;flex-direction:column}.fan-stage[data-v-054d24e4]{position:relative;height:15em;margin:16px 0 130px;border-radius:14px;background:#52be7f}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{_ as m,a as u}from"./_plugin-vue_export-helper-CzJpAC-G.js";import{d as p,f as v,D as _,A as o,l as f,g as a,m as t,t as b,u as r,H as g,b as w,o as C,I as x}from"./index-tixem2vV.js";import"./loadApp-DK5s6_Re.js";const y={class:"demo-page"},V={class:"fan-demo"},M={class:"fan-stage"},I={class:"demo-note"},N=p({__name:"CircularMenuView",setup(k){const d=g({loader:async()=>(await x()).CircularMenu,timeout:1e4}),i=[{label:"图"},{label:"乐"},{label:"家"},{label:"视"},{label:"信"}],c=[{label:"关于"},{label:"教程"},{label:"文章"},{label:"片段"},{label:"插件"},{label:"联系"},{label:"关注"}],s=w("—");function l(n){s.value=n.label}return(n,e)=>(C(),v("div",y,[e[6]||(e[6]=_('<header data-v-054d24e4><p class="demo-page__eyebrow" data-v-054d24e4>远程组件</p><h1 class="demo-page__title" data-v-054d24e4>comps-vue3 · CircularMenu</h1><p class="demo-page__lead" data-v-054d24e4> 由 <code data-v-054d24e4>_corner/底部菜单</code> 的两个 jQuery demo 提取成同一个组件,用 <code data-v-054d24e4>variant</code> 区分:<code data-v-054d24e4>wheel</code> 是贴在视口底部、展开半个圆环的环形菜单(原 demo1), <code data-v-054d24e4>fan</code> 是相对定位父元素展开整个圆环的扇叶菜单(原 demo2)。 入口由 <code data-v-054d24e4>items</code> 提供,点击后抛 <code data-v-054d24e4>select</code> 事件。 </p></header>',1)),o(m,null,{default:f(()=>[a("section",V,[e[0]||(e[0]=a("h2",{class:"demo-page__section-title"},'variant="fan" · 扇叶菜单',-1)),e[1]||(e[1]=a("p",{class:"demo-card__text"},[t(" 收起时所有扇区叠回中间,展开后按 "),a("code",null,"192° / (n-1)"),t(" 均匀散开;7 个入口正好是原 demo2 的 32° 一档。 ")],-1)),a("div",M,[o(r(d),{variant:"fan",items:c,onSelect:l})])])]),_:1}),a("p",I,[a("span",null,[e[2]||(e[2]=t(" 最近点击:",-1)),a("strong",null,b(s.value),1),e[3]||(e[3]=t("。下方 ",-1)),e[4]||(e[4]=a("code",null,'variant="wheel"',-1)),e[5]||(e[5]=t(" 的按钮固定在视口底部中间, 点开后可点遮罩或按 Esc 收起(原 demo1 用 document 点击关闭,这里换成遮罩 + Esc,不给宿主挂全局监听)。 ",-1))])]),o(r(d),{variant:"wheel",overlay:"",items:i,onSelect:l})]))}}),A=u(N,[["__scopeId","data-v-054d24e4"]]);export{A as default};
|
|
2
|
+
//# sourceMappingURL=CircularMenuView-DVx3F33D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CircularMenuView-DVx3F33D.js","sources":["../../src/views/CircularMenuView.vue"],"sourcesContent":["<template>\n <div class=\"demo-page\">\n <header>\n <p class=\"demo-page__eyebrow\">远程组件</p>\n <h1 class=\"demo-page__title\">comps-vue3 · CircularMenu</h1>\n <p class=\"demo-page__lead\">\n 由 <code>_corner/底部菜单</code> 的两个 jQuery demo 提取成同一个组件,用 <code>variant</code>\n 区分:<code>wheel</code> 是贴在视口底部、展开半个圆环的环形菜单(原 demo1),\n <code>fan</code> 是相对定位父元素展开整个圆环的扇叶菜单(原 demo2)。\n 入口由 <code>items</code> 提供,点击后抛 <code>select</code> 事件。\n </p>\n </header>\n\n <DemoPreview>\n <section class=\"fan-demo\">\n <h2 class=\"demo-page__section-title\">variant=\"fan\" · 扇叶菜单</h2>\n <p class=\"demo-card__text\">\n 收起时所有扇区叠回中间,展开后按 <code>192° / (n-1)</code> 均匀散开;7 个入口正好是原\n demo2 的 32° 一档。\n </p>\n <div class=\"fan-stage\">\n <CircularMenu variant=\"fan\" :items=\"fanItems\" @select=\"onSelect\" />\n </div>\n </section>\n </DemoPreview>\n\n <p class=\"demo-note\">\n <span>\n 最近点击:<strong>{{ picked }}</strong>。下方 <code>variant=\"wheel\"</code> 的按钮固定在视口底部中间,\n 点开后可点遮罩或按 Esc 收起(原 demo1 用 document 点击关闭,这里换成遮罩 + Esc,不给宿主挂全局监听)。\n </span>\n </p>\n\n <CircularMenu variant=\"wheel\" overlay :items=\"wheelItems\" @select=\"onSelect\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { defineAsyncComponent, ref } from 'vue'\nimport DemoPreview from '../components/DemoPreview.vue'\nimport { loadRemoteLib } from '../configs/remote'\n\n/**\n * 与 RemoteView 相同的远程加载方式:入口处已 preFetchLib,这里只取组件。\n * wheel 是视口级 fixed 定位,放在 DemoPreview 之外,全屏预览时不会跟着被搬走。\n */\nconst CircularMenu = defineAsyncComponent({\n loader: async () => (await loadRemoteLib()).CircularMenu,\n timeout: 10000,\n})\n\n// 原 demo1 的 5 个图标位(图片/耳机/首页/视频/邮件),无图标字体,用单字代替\nconst wheelItems = [{ label: '图' }, { label: '乐' }, { label: '家' }, { label: '视' }, { label: '信' }]\n\n// 原 demo2 的 7 个入口\nconst fanItems = [\n { label: '关于' },\n { label: '教程' },\n { label: '文章' },\n { label: '片段' },\n { label: '插件' },\n { label: '联系' },\n { label: '关注' },\n]\n\nconst picked = ref('—')\n\nfunction onSelect(item: { label: string }) {\n picked.value = item.label\n}\n</script>\n\n<style scoped>\n.fan-demo {\n display: flex;\n flex-direction: column;\n}\n\n/* 相当于原 demo2 的 .component:给 fan 提供定位祖先,按钮压在盒子下边缘 */\n.fan-stage {\n position: relative;\n height: 15em;\n /* 扇区会溢出到盒子下方,留出空档避免压住下面的说明 */\n margin: 16px 0 130px;\n border-radius: 14px;\n background: #52be7f;\n}\n</style>\n"],"names":["CircularMenu","defineAsyncComponent","loadRemoteLib","wheelItems","fanItems","picked","ref","onSelect","item","_openBlock","_createElementBlock","_hoisted_1","_createVNode","DemoPreview","_createElementVNode","_hoisted_2","_cache","_hoisted_3","_unref","_hoisted_4"],"mappings":"kWA8CA,MAAMA,EAAeC,EAAqB,CACxC,OAAQ,UAAa,MAAMC,EAAA,GAAiB,aAC5C,QAAS,GAAA,CACV,EAGKC,EAAa,CAAC,CAAE,MAAO,KAAO,CAAE,MAAO,GAAA,EAAO,CAAE,MAAO,GAAA,EAAO,CAAE,MAAO,KAAO,CAAE,MAAO,IAAK,EAG5FC,EAAW,CACf,CAAE,MAAO,IAAA,EACT,CAAE,MAAO,IAAA,EACT,CAAE,MAAO,IAAA,EACT,CAAE,MAAO,IAAA,EACT,CAAE,MAAO,IAAA,EACT,CAAE,MAAO,IAAA,EACT,CAAE,MAAO,IAAA,CAAK,EAGVC,EAASC,EAAI,GAAG,EAEtB,SAASC,EAASC,EAAyB,CACzCH,EAAO,MAAQG,EAAK,KACtB,eApEEC,EAAA,EAAAC,EAiCM,MAjCNC,EAiCM,8iBArBJC,EAWcC,EAAA,KAAA,WAVZ,IASU,CATVC,EASU,UATVC,EASU,CARRC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAF,EAA8D,KAAA,CAA1D,MAAM,0BAAA,EAA2B,uBAAoB,EAAA,eACzDA,EAGI,IAAA,CAHD,MAAM,mBAAiB,GAAC,oBACR,EAAAA,EAAyB,YAAnB,cAAY,IAAO,kCAE5C,CAAA,OACAA,EAEM,MAFNG,EAEM,CADJL,EAAmEM,EAAAlB,CAAA,EAAA,CAArD,QAAQ,MAAO,MAAOI,EAAW,SAAAG,CAAA,eAKrDO,EAKI,IALJK,EAKI,CAJFL,EAGO,OAAA,KAAA,eAHD,SACC,EAAA,GAAAA,EAA6B,gBAAlBT,EAAA,KAAM,EAAA,CAAA,gBAAY,OAAI,EAAA,GAAAW,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAF,EAA4B,YAAtB,kBAAe,EAAA,iBAAO,oFAEpE,EAAA,EAAA,KAGFF,EAA+EM,EAAAlB,CAAA,EAAA,CAAjE,QAAQ,QAAQ,QAAA,GAAS,MAAOG,EAAa,SAAAI,CAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{_ as n,a as d}from"./_plugin-vue_export-helper-CzJpAC-G.js";import{d as l,f as i,g as e,m as o,A as r,l as m,o as p,t as _,b as c}from"./index-tixem2vV.js";import"./loadApp-DK5s6_Re.js";const u={class:"demo-page"},b={class:"demo-card"},f={class:"host-actions"},v=l({__name:"HostView",setup(g){const s=c(0);return(V,t)=>(p(),i("div",u,[t[4]||(t[4]=e("header",null,[e("p",{class:"demo-page__eyebrow"},"主应用"),e("h1",{class:"demo-page__title"},"宿主自己的内容"),e("p",{class:"demo-page__lead"},[o(" 这块内容完全由宿主渲染,用来对照远程组件:两者用的是同一份 Vue 运行时 ("),e("code",null,"bindVueRuntime"),o(" 注入),所以点击计数都应该即时更新。 ")])],-1)),r(n,{class:"host-preview"},{default:m(()=>[e("section",b,[t[2]||(t[2]=e("h2",{class:"demo-card__title"},"主应用内容",-1)),t[3]||(t[3]=e("p",{class:"demo-card__text"},"宿主按钮的计数只存在宿主里,与远程组件无关。",-1)),e("div",f,[e("button",{type:"button",class:"demo-btn",onClick:t[0]||(t[0]=a=>s.value++)}," host 工程中的按钮 "+_(s.value),1),e("button",{type:"button",class:"demo-btn demo-btn--ghost",onClick:t[1]||(t[1]=a=>s.value=0)}," 重置 ")])])]),_:1})]))}}),y=d(v,[["__scopeId","data-v-d6fb7a4a"]]);export{y as default};
|
|
2
|
+
//# sourceMappingURL=HostView-DMHAyQge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HostView-DMHAyQge.js","sources":["../../src/views/HostView.vue"],"sourcesContent":["<template>\n <div class=\"demo-page\">\n <header>\n <p class=\"demo-page__eyebrow\">主应用</p>\n <h1 class=\"demo-page__title\">宿主自己的内容</h1>\n <p class=\"demo-page__lead\">\n 这块内容完全由宿主渲染,用来对照远程组件:两者用的是同一份 Vue 运行时\n (<code>bindVueRuntime</code> 注入),所以点击计数都应该即时更新。\n </p>\n </header>\n\n <DemoPreview class=\"host-preview\">\n <section class=\"demo-card\">\n <h2 class=\"demo-card__title\">主应用内容</h2>\n <p class=\"demo-card__text\">宿主按钮的计数只存在宿主里,与远程组件无关。</p>\n <div class=\"host-actions\">\n <button type=\"button\" class=\"demo-btn\" @click=\"num++\">\n host 工程中的按钮 {{ num }}\n </button>\n <button type=\"button\" class=\"demo-btn demo-btn--ghost\" @click=\"num = 0\">\n 重置\n </button>\n </div>\n </section>\n </DemoPreview>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport DemoPreview from '../components/DemoPreview.vue'\n\nconst num = ref(0)\n</script>\n\n<style scoped>\n.host-actions {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n margin-top: 14px;\n}\n\n/* 全屏时把宿主卡片居中展示,页面标题与说明留在屏幕外 */\n.host-preview.is-demo-fullscreen {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: var(--demo-bg);\n}\n\n.host-preview.is-demo-fullscreen .demo-card {\n width: 100%;\n max-width: 560px;\n}\n</style>\n"],"names":["num","ref","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_createVNode","DemoPreview","_hoisted_2","_cache","_hoisted_3"],"mappings":"4SAgCA,MAAMA,EAAMC,EAAI,CAAC,gBA/BfC,EAAA,EAAAC,EAwBM,MAxBNC,EAwBM,aAvBJC,EAOS,SAAA,KAAA,CANPA,EAAqC,IAAA,CAAlC,MAAM,oBAAA,EAAqB,KAAG,EACjCA,EAAyC,KAAA,CAArC,MAAM,kBAAA,EAAmB,SAAO,EACpCA,EAGI,IAAA,CAHD,MAAM,mBAAiB,GAAC,0CAExB,EAAAA,EAA2B,YAArB,gBAAc,IAAO,sBAC9B,CAAA,SAGFC,EAacC,EAAA,CAbD,MAAM,gBAAc,WAC/B,IAWU,CAXVF,EAWU,UAXVG,EAWU,CAVRC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAJ,EAAuC,KAAA,CAAnC,MAAM,kBAAA,EAAmB,QAAK,EAAA,GAClCI,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAJ,EAAqD,IAAA,CAAlD,MAAM,iBAAA,EAAkB,yBAAsB,EAAA,GACjDA,EAOM,MAPNK,EAOM,CANJL,EAES,SAAA,CAFD,KAAK,SAAS,MAAM,WAAY,uBAAOL,EAAA,QAAA,EAAO,kBACrCA,EAAA,KAAG,EAAA,CAAA,EAEpBK,EAES,SAAA,CAFD,KAAK,SAAS,MAAM,2BAA4B,uBAAOL,EAAA,MAAG,EAAA,EAAM,MAExE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.host-actions[data-v-d6fb7a4a]{display:flex;flex-wrap:wrap;gap:10px;margin-top:14px}.host-preview.is-demo-fullscreen[data-v-d6fb7a4a]{display:flex;align-items:center;justify-content:center;padding:24px;background:var(--demo-bg)}.host-preview.is-demo-fullscreen .demo-card[data-v-d6fb7a4a]{width:100%;max-width:560px}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{d as v,A as d}from"./loadApp-DK5s6_Re.js";import{d as g,f as m,g as l,t as n,u as o,m as t,R as k,L as f,U as V,F as E,j as b,e as c,o as r,k as x,l as T}from"./index-tixem2vV.js";const O={class:"demo-page"},y={class:"demo-page__title"},L={class:"demo-table"},R=["href"],h={class:"demo-grid"},w={class:"demo-card__title"},A={class:"demo-card__text"},N=g({__name:"OverviewView",setup(B){const p=v.filter(u=>u.name&&u.name!=="overview");return(u,e)=>{const _=c("router-link");return r(),m("div",O,[l("header",null,[e[0]||(e[0]=l("p",{class:"demo-page__eyebrow"},"Vue 3 · hel 宿主",-1)),l("h1",y,n(o(d).name)+" 简介",1),e[1]||(e[1]=l("p",{class:"demo-page__lead"},[t(" Vue 3 + Vite 5 的 hel 宿主(消费方)示例:入口处用 "),l("code",null,"bindVueRuntime"),t(" 注入宿主 Vue 运行时,再用 "),l("code",null,"preFetchLib"),t(" 预加载远程组件 "),l("code",null,"comps-vue3"),t("。 顶部导航栏用于切换示例,示例页右上角的「全屏」按钮只把组件预览区放大到全屏, 简介与说明文字不会进入全屏。 ")],-1))]),l("table",L,[l("tbody",null,[e[7]||(e[7]=l("tr",null,[l("th",null,"npm 包名"),l("td",null,[l("code",null,"@melt-js/demo-vue3")])],-1)),l("tr",null,[e[2]||(e[2]=l("th",null,"unpkg 入口",-1)),l("td",null,[l("a",{href:o(d).unpkgEntry,target:"_blank",rel:"noopener"},n(o(d).unpkgEntry),9,R)])]),l("tr",null,[e[3]||(e[3]=l("th",null,"本地端口",-1)),l("td",null,n(o(d).port),1)]),l("tr",null,[e[6]||(e[6]=l("th",null,"远程组件",-1)),l("td",null,[l("div",null,[l("code",null,n(o(k)),1)]),l("div",null,[e[4]||(e[4]=t("开发:",-1)),l("code",null,n(o(f)),1)]),l("div",null,[e[5]||(e[5]=t("生产:",-1)),l("code",null,n(o(V)),1)])])]),e[8]||(e[8]=l("tr",null,[l("th",null,"运行时共享"),l("td",null,[l("code",null,"bindVueRuntime({ Vue })"),t(",远程组件 external 的 vue 复用宿主这一份")])],-1)),e[9]||(e[9]=l("tr",null,[l("th",null,"路由模式"),l("td",null,[t(" hash("),l("code",null,"#/remote"),t("),保证从 unpkg 的 "),l("code",null,"dist/index.html"),t(" 直接打开也能切换示例 ")])],-1))])]),l("section",null,[e[11]||(e[11]=l("h2",{class:"demo-page__section-title"},"示例导航",-1)),l("div",h,[(r(!0),m(E,null,b(o(p),s=>(r(),x(_,{key:s.path,to:s.path,class:"demo-card demo-card--link"},{default:T(()=>{var a,i;return[l("h3",w,n((a=s.meta)==null?void 0:a.title),1),l("p",A,n((i=s.meta)==null?void 0:i.description),1),e[10]||(e[10]=l("span",{class:"demo-card__action"},"进入示例 →",-1))]}),_:2},1032,["to"]))),128))])]),e[12]||(e[12]=l("p",{class:"demo-note"},[t(" 本地开发先执行 "),l("code",null,"pnpm comps-vue3:dev"),t("(20020),再执行 "),l("code",null,"pnpm demo-vue3:dev"),t(" 打开 http://localhost:30020;远端地址可用 "),l("code",null,"VITE_REMOTE_HOST"),t(" 覆盖。 ")],-1))])}}});export{N as default};
|
|
2
|
+
//# sourceMappingURL=OverviewView-BRUCgEGh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OverviewView-BRUCgEGh.js","sources":["../../src/views/OverviewView.vue"],"sourcesContent":["<template>\n <div class=\"demo-page\">\n <header>\n <p class=\"demo-page__eyebrow\">Vue 3 · hel 宿主</p>\n <h1 class=\"demo-page__title\">{{ APP_META.name }} 简介</h1>\n <p class=\"demo-page__lead\">\n Vue 3 + Vite 5 的 hel 宿主(消费方)示例:入口处用\n <code>bindVueRuntime</code> 注入宿主 Vue 运行时,再用\n <code>preFetchLib</code> 预加载远程组件 <code>comps-vue3</code>。\n 顶部导航栏用于切换示例,示例页右上角的「全屏」按钮只把组件预览区放大到全屏,\n 简介与说明文字不会进入全屏。\n </p>\n </header>\n\n <table class=\"demo-table\">\n <tbody>\n <tr>\n <th>npm 包名</th>\n <td><code>@melt-js/demo-vue3</code></td>\n </tr>\n <tr>\n <th>unpkg 入口</th>\n <td>\n <a :href=\"APP_META.unpkgEntry\" target=\"_blank\" rel=\"noopener\">{{ APP_META.unpkgEntry }}</a>\n </td>\n </tr>\n <tr>\n <th>本地端口</th>\n <td>{{ APP_META.port }}</td>\n </tr>\n <tr>\n <th>远程组件</th>\n <td>\n <div><code>{{ REMOTE_LIB_NAME }}</code></div>\n <div>开发:<code>{{ LOCAL_HOST }}</code></div>\n <div>生产:<code>{{ UNPKG_HOST }}</code></div>\n </td>\n </tr>\n <tr>\n <th>运行时共享</th>\n <td><code>bindVueRuntime({ Vue })</code>,远程组件 external 的 vue 复用宿主这一份</td>\n </tr>\n <tr>\n <th>路由模式</th>\n <td>\n hash(<code>#/remote</code>),保证从 unpkg 的 <code>dist/index.html</code>\n 直接打开也能切换示例\n </td>\n </tr>\n </tbody>\n </table>\n\n <section>\n <h2 class=\"demo-page__section-title\">示例导航</h2>\n <div class=\"demo-grid\">\n <router-link\n v-for=\"item in examples\"\n :key=\"item.path\"\n :to=\"item.path\"\n class=\"demo-card demo-card--link\"\n >\n <h3 class=\"demo-card__title\">{{ item.meta?.title }}</h3>\n <p class=\"demo-card__text\">{{ item.meta?.description }}</p>\n <span class=\"demo-card__action\">进入示例 →</span>\n </router-link>\n </div>\n </section>\n\n <p class=\"demo-note\">\n 本地开发先执行 <code>pnpm comps-vue3:dev</code>(20020),再执行\n <code>pnpm demo-vue3:dev</code> 打开 http://localhost:30020;远端地址可用\n <code>VITE_REMOTE_HOST</code> 覆盖。\n </p>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { APP_META } from '../configs/app'\nimport { LOCAL_HOST, REMOTE_LIB_NAME, UNPKG_HOST } from '../configs/remote'\nimport { demoRoutes } from '../router'\n\n// 简介页也列出其余示例,方便直接跳转\nconst examples = demoRoutes.filter((item) => item.name && item.name !== 'overview')\n</script>\n"],"names":["examples","demoRoutes","item","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_cache","_hoisted_2","_toDisplayString","_unref","_hoisted_3","APP_META","_hoisted_4","REMOTE_LIB_NAME","LOCAL_HOST","UNPKG_HOST","_hoisted_5","_Fragment","_renderList","_createBlock","_component_router_link","_hoisted_6","_a","_hoisted_7","_b"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{d as n,f as m,g as e,m as s,A as r,l as p,D as i,o as d,E as u,G as v,k as _,B as b,u as f,b as g,H as V,I as h}from"./index-tixem2vV.js";import{_ as w,a as x}from"./_plugin-vue_export-helper-CzJpAC-G.js";import"./loadApp-DK5s6_Re.js";const y={class:"demo-page"},k={class:"demo-remote"},B={class:"remote-field"},C=n({__name:"RemoteView",setup(E){const t=g("hel-micro"),l=V({loader:async()=>{console.log("[demo-vue3] 开始加载远程组件...");try{const a=await h();return console.log("[demo-vue3] 远程组件加载完成:",a),a.HelloWorld}catch(a){throw console.error("[demo-vue3] 获取远程组件失败:",a),a}},timeout:1e4});return(a,o)=>(d(),m("div",y,[o[2]||(o[2]=e("header",null,[e("p",{class:"demo-page__eyebrow"},"远程组件"),e("h1",{class:"demo-page__title"},"comps-vue3 · HelloWorld"),e("p",{class:"demo-page__lead"},[s(" 下面的组件由 "),e("code",null,"preFetchLib('comps-vue3')"),s(" 从远端加载,宿主产物里没有它。 组件内的计数按钮验证远程组件复用的是宿主注入的那一份 Vue 运行时。 ")])],-1)),r(w,{class:"remote-preview"},{default:p(()=>[e("div",k,[e("label",B,[o[1]||(o[1]=e("span",null,"name",-1)),u(e("input",{"onUpdate:modelValue":o[0]||(o[0]=c=>t.value=c),type:"text",placeholder:"输入要传递给远程组件的 name"},null,512),[[v,t.value]])]),(d(),_(b(f(l)),{name:t.value,msg:"来自 demo-vue3 的问候"},null,8,["name"]))])]),_:1}),o[3]||(o[3]=i('<p class="demo-note" data-v-06558ab1> 远程组件的 <code data-v-06558ab1>HelloWorld</code> 声明了 <code data-v-06558ab1>props: { msg, name }</code>,宿主用 <code data-v-06558ab1>:name="name"</code> 传值,和给本地组件传 props 完全一样;输入框改的是宿主的 <code data-v-06558ab1>ref</code>,远程组件会跟着重新渲染。 </p><p class="demo-note" data-v-06558ab1> 远端地址:开发 <code data-v-06558ab1>http://localhost:20020</code>(先执行 <code data-v-06558ab1>pnpm comps-vue3:dev</code>),生产 <code data-v-06558ab1>unpkg</code> 上的 <code data-v-06558ab1>hel-meta.json</code>;也可用 <code data-v-06558ab1>VITE_REMOTE_HOST</code> 覆盖。 </p>',2))]))}}),N=x(C,[["__scopeId","data-v-06558ab1"]]);export{N as default};
|
|
2
|
+
//# sourceMappingURL=RemoteView-CD5hkZNz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RemoteView-CD5hkZNz.js","sources":["../../src/views/RemoteView.vue"],"sourcesContent":["<template>\n <div class=\"demo-page\">\n <header>\n <p class=\"demo-page__eyebrow\">远程组件</p>\n <h1 class=\"demo-page__title\">comps-vue3 · HelloWorld</h1>\n <p class=\"demo-page__lead\">\n 下面的组件由 <code>preFetchLib('comps-vue3')</code> 从远端加载,宿主产物里没有它。\n 组件内的计数按钮验证远程组件复用的是宿主注入的那一份 Vue 运行时。\n </p>\n </header>\n\n <DemoPreview class=\"remote-preview\">\n <div class=\"demo-remote\">\n <label class=\"remote-field\">\n <span>name</span>\n <input v-model=\"name\" type=\"text\" placeholder=\"输入要传递给远程组件的 name\" />\n </label>\n <component :is=\"RemoteComp\" :name=\"name\" msg=\"来自 demo-vue3 的问候\" />\n </div>\n </DemoPreview>\n\n <p class=\"demo-note\">\n 远程组件的 <code>HelloWorld</code> 声明了 <code>props: { msg, name }</code>,宿主用\n <code>:name=\"name\"</code> 传值,和给本地组件传 props 完全一样;输入框改的是宿主的\n <code>ref</code>,远程组件会跟着重新渲染。\n </p>\n\n <p class=\"demo-note\">\n 远端地址:开发 <code>http://localhost:20020</code>(先执行\n <code>pnpm comps-vue3:dev</code>),生产 <code>unpkg</code> 上的\n <code>hel-meta.json</code>;也可用 <code>VITE_REMOTE_HOST</code> 覆盖。\n </p>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { defineAsyncComponent, ref } from 'vue'\nimport DemoPreview from '../components/DemoPreview.vue'\nimport { loadRemoteLib } from '../configs/remote'\n\nconst name = ref('hel-micro')\n\nconst RemoteComp = defineAsyncComponent({\n loader: async () => {\n console.log('[demo-vue3] 开始加载远程组件...')\n\n try {\n // 入口处已经预加载,这里复用同一个 Promise(通常已 resolve)\n const lib = await loadRemoteLib()\n\n console.log('[demo-vue3] 远程组件加载完成:', lib)\n return lib.HelloWorld\n } catch (err) {\n console.error('[demo-vue3] 获取远程组件失败:', err)\n throw err\n }\n },\n timeout: 10000,\n})\n</script>\n\n<style scoped>\n.remote-field {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-size: 13px;\n color: var(--demo-muted);\n}\n\n.remote-field input {\n width: 220px;\n padding: 6px 10px;\n border: 1px solid var(--demo-border);\n border-radius: 6px;\n font: inherit;\n color: var(--demo-text);\n background: var(--demo-surface);\n}\n\n/* 全屏时只保留远程组件,页头与说明文字留在屏幕外 */\n.remote-preview.is-demo-fullscreen {\n display: flex;\n padding: 24px;\n background: var(--demo-bg);\n}\n\n.remote-preview.is-demo-fullscreen .demo-remote {\n width: 100%;\n max-width: 1100px;\n /* 内容比视口高时从顶部开始滚,不用 auto 垂直居中,避免顶部被裁掉 */\n margin: 0 auto;\n}\n</style>\n"],"names":["name","ref","RemoteComp","defineAsyncComponent","lib","loadRemoteLib","err","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_createVNode","DemoPreview","_hoisted_2","_hoisted_3","_cache","$event","_createBlock","_resolveDynamicComponent","_unref"],"mappings":"iWAwCA,MAAMA,EAAOC,EAAI,WAAW,EAEtBC,EAAaC,EAAqB,CACtC,OAAQ,SAAY,CAClB,QAAQ,IAAI,yBAAyB,EAErC,GAAI,CAEF,MAAMC,EAAM,MAAMC,EAAA,EAElB,eAAQ,IAAI,wBAAyBD,CAAG,EACjCA,EAAI,UACb,OAASE,EAAK,CACZ,cAAQ,MAAM,wBAAyBA,CAAG,EACpCA,CACR,CACF,EACA,QAAS,GAAA,CACV,gBAzDCC,EAAA,EAAAC,EA+BM,MA/BNC,EA+BM,aA9BJC,EAOS,SAAA,KAAA,CANPA,EAAsC,IAAA,CAAnC,MAAM,oBAAA,EAAqB,MAAI,EAClCA,EAAyD,KAAA,CAArD,MAAM,kBAAA,EAAmB,yBAAuB,EACpDA,EAGI,IAAA,CAHD,MAAM,mBAAiB,GAAC,UAClB,EAAAA,EAAsC,YAAhC,2BAAyB,IAAO,uDAE/C,CAAA,SAGFC,EAQcC,EAAA,CARD,MAAM,kBAAgB,WACjC,IAMM,CANNF,EAMM,MANNG,EAMM,CALJH,EAGQ,QAHRI,EAGQ,CAFNC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAL,EAAiB,YAAX,OAAI,EAAA,KACVA,EAAmE,QAAA,sCAAnDV,EAAI,MAAAgB,GAAE,KAAK,OAAO,YAAY,kBAAA,gBAA9BhB,EAAA,KAAI,CAAA,MAEtBO,IAAAU,EAAkEC,EAAlDC,EAAAjB,CAAA,CAAU,EAAA,CAAG,KAAMF,EAAA,MAAM,IAAI,kBAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.remote-field[data-v-06558ab1]{display:flex;align-items:center;gap:8px;margin-bottom:12px;font-size:13px;color:var(--demo-muted)}.remote-field input[data-v-06558ab1]{width:220px;padding:6px 10px;border:1px solid var(--demo-border);border-radius:6px;font:inherit;color:var(--demo-text);background:var(--demo-surface)}.remote-preview.is-demo-fullscreen[data-v-06558ab1]{display:flex;padding:24px;background:var(--demo-bg)}.remote-preview.is-demo-fullscreen .demo-remote[data-v-06558ab1]{width:100%;max-width:1100px;margin:0 auto}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{d as l,w as c,f as u,g as r,J as d,K as p,o as f,b as _,n as m}from"./index-tixem2vV.js";import{u as v}from"./loadApp-DK5s6_Re.js";const w={class:"demo-preview","data-demo-preview":""},h=l({__name:"DemoPreview",setup(n){const{isFullscreen:a,exit:o}=v(),s=_(null);c(a,async e=>{var t;e&&(await m(),(t=s.value)==null||t.focus({preventScroll:!0}))});function i(){o().catch(e=>{console.warn("[Fullscreen] Failed to exit fullscreen:",e)})}return(e,t)=>(f(),u("div",w,[r("button",{ref_key:"exitButton",ref:s,type:"button",class:"demo-preview__exit",title:"退出全屏(Esc)","aria-label":"退出全屏",onClick:d(i,["stop"])},[...t[0]||(t[0]=[r("svg",{class:"demo-preview__exit-icon",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round","aria-hidden":"true",focusable:"false"},[r("path",{d:"M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"})],-1),r("span",{class:"demo-preview__exit-text"},"退出全屏",-1)])],512),p(e.$slots,"default")]))}}),B=(n,a)=>{const o=n.__vccOpts||n;for(const[s,i]of a)o[s]=i;return o};export{h as _,B as a};
|
|
2
|
+
//# sourceMappingURL=_plugin-vue_export-helper-CzJpAC-G.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_plugin-vue_export-helper-CzJpAC-G.js","sources":["../../src/components/DemoPreview.vue"],"sourcesContent":["<template>\n <div class=\"demo-preview\" data-demo-preview>\n <button\n ref=\"exitButton\"\n type=\"button\"\n class=\"demo-preview__exit\"\n title=\"退出全屏(Esc)\"\n aria-label=\"退出全屏\"\n @click.stop=\"exitFullscreen\"\n >\n <svg\n class=\"demo-preview__exit-icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3\"\n />\n </svg>\n <span class=\"demo-preview__exit-text\">退出全屏</span>\n </button>\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { nextTick, ref, watch } from 'vue'\nimport { useDemoFullscreen } from '../composables/useDemoFullscreen'\n\n/**\n * 组件预览区:全屏按钮的唯一目标。\n *\n * 普通模式下它只是页面里的一个普通容器;进入全屏后由 vue-fullscreen 给根节点\n * 加上 is-demo-fullscreen 类,只保留插槽里的组件内容,页面标题、简介、说明与\n * 页脚都不会进入全屏。右下角的「退出全屏」按钮也只在全屏时出现。\n */\nconst { isFullscreen, exit } = useDemoFullscreen()\nconst exitButton = ref<HTMLButtonElement | null>(null)\n\n// 进入全屏后把焦点移到「退出全屏」,键盘用户可以直接 Esc / Enter 退出\nwatch(isFullscreen, async (value) => {\n if (!value) return\n await nextTick()\n exitButton.value?.focus({ preventScroll: true })\n})\n\nfunction exitFullscreen() {\n exit().catch((error) => {\n console.warn('[Fullscreen] Failed to exit fullscreen:', error)\n })\n}\n</script>\n"],"names":["isFullscreen","exit","useDemoFullscreen","exitButton","ref","watch","value","nextTick","_a","exitFullscreen","error","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_renderSlot","_ctx"],"mappings":"mOA0CA,KAAM,CAAE,aAAAA,EAAc,KAAAC,CAAA,EAASC,EAAA,EACzBC,EAAaC,EAA8B,IAAI,EAGrDC,EAAML,EAAc,MAAOM,GAAU,OAC9BA,IACL,MAAMC,EAAA,GACNC,EAAAL,EAAW,QAAX,MAAAK,EAAkB,MAAM,CAAE,cAAe,KAC3C,CAAC,EAED,SAASC,GAAiB,CACxBR,EAAA,EAAO,MAAOS,GAAU,CACtB,QAAQ,KAAK,0CAA2CA,CAAK,CAC/D,CAAC,CACH,eAvDEC,EAAA,EAAAC,EA2BM,MA3BNC,EA2BM,CA1BJC,EAwBS,SAAA,SAvBH,aAAJ,IAAIX,EACJ,KAAK,SACL,MAAM,qBACN,MAAM,YACN,aAAW,OACV,UAAYM,EAAc,CAAA,MAAA,CAAA,CAAA,mBAE3BK,EAcM,MAAA,CAbJ,MAAM,0BACN,QAAQ,YACR,KAAK,OACL,OAAO,eACP,eAAa,IACb,iBAAe,QACf,kBAAgB,QAChB,cAAY,OACZ,UAAU,OAAA,GAEVA,EAEE,OAAA,CADA,EAAE,gGAA+F,CAAA,MAGrGA,EAAiD,OAAA,CAA3C,MAAM,yBAAA,EAA0B,OAAI,EAAA,CAAA,SAE5CC,EAAQC,EAAA,OAAA,SAAA,CAAA"}
|