33 lines
9.0 KiB
JavaScript
33 lines
9.0 KiB
JavaScript
import{a as g,b as i,c as a,n as m,k as x,Q as v,L as d,X as w,M as h,u,e,h as k,i as I,V as S,j as y,U as C,r as b,F as A,g as q,S as M,N as U,Y as $,t as j}from"./index-BzKy-nNf.js";import{_ as O}from"./ChatWindow.vue_vue_type_script_setup_true_lang-CiskBM0U.js";import"./chat-CR1al33K.js";import"./useNostr-zyhtrXba.js";const T=["aria-label"],_={key:0,"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"},W={key:1,"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 4v16m8-8H4"},B=g({__name:"WidgetFab",props:{isOpen:{type:Boolean},position:{default:"bottom-right"}},emits:["toggle"],setup(s){const n=s,t=x(()=>n.position==="bottom-left"?"bottom-6 left-6":"bottom-6 right-6");return(o,l)=>(i(),a("button",{class:m(["fixed z-50 w-14 h-14 rounded-full path-glass-button flex items-center justify-center transition-all duration-300 hover:scale-105 active:scale-95",t.value]),style:{boxShadow:"0 8px 24px rgba(0, 0, 0, 0.45), 0 0 20px rgba(247, 147, 26, 0.15)"},"aria-label":s.isOpen?"Close AIUI":"Open AIUI",onClick:l[0]||(l[0]=p=>o.$emit("toggle"))},[(i(),a("svg",{class:m(["w-6 h-6 text-accent transition-transform duration-300",s.isOpen?"rotate-45":""]),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[s.isOpen?(i(),a("path",W)):(i(),a("path",_))],2))],10,T))}}),V=g({__name:"WidgetModal",props:{isOpen:{type:Boolean},side:{default:"right"}},emits:["close","switchSide"],setup(s){const n=s,{isDark:t,currentTheme:o}=y(),l=x(()=>n.side==="left"?"bottom-24 left-6":"bottom-24 right-6");return(p,c)=>(i(),v(S,{to:"body"},[d(w,{name:"widget"},{default:h(()=>[s.isOpen?(i(),a("div",{key:0,class:m(["fixed z-40 animate-scale-in",[l.value,u(o)]])},[e("div",{class:"w-[380px] h-[600px] md:w-[420px] md:h-[640px] path-glass-card overflow-hidden",style:k(u(t)?"box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), 0 0 40px rgba(247, 147, 26, 0.06)":"box-shadow: 0 20px 60px rgba(0, 0, 0, 0.12), 0 0 40px rgba(247, 147, 26, 0.04)")},[d(O,{variant:"modal",side:s.side,"show-close":"",onSwitchSide:c[0]||(c[0]=r=>p.$emit("switchSide")),onClose:c[1]||(c[1]=r=>p.$emit("close"))},null,8,["side"])],4)],2)):I("",!0)]),_:1})]))}}),z=C(V,[["__scopeId","data-v-1c052c90"]]),D=g({__name:"AIUIWidget",setup(s){const{currentTheme:n}=y(),t=b(!1),o=b("right"),l=x(()=>o.value==="left"?"bottom-left":"bottom-right");function p(){o.value=o.value==="right"?"left":"right"}return(c,r)=>(i(),a("div",{class:m(u(n))},[d(B,{"is-open":t.value,position:l.value,onToggle:r[0]||(r[0]=f=>t.value=!t.value)},null,8,["is-open","position"]),d(z,{"is-open":t.value,side:o.value,onClose:r[1]||(r[1]=f=>t.value=!1),onSwitchSide:p},null,8,["is-open","side"])],2))}}),H={class:"min-h-full bg-white text-gray-900 font-sans"},P={class:"border-b border-gray-200 bg-white sticky top-0 z-30"},L={class:"max-w-6xl mx-auto px-6 py-4 flex items-center justify-between"},N={class:"flex items-center gap-6 text-sm text-gray-600"},F={class:"max-w-6xl mx-auto px-6 py-12"},K={class:"grid md:grid-cols-2 lg:grid-cols-3 gap-6 mb-16"},R={class:"font-semibold mb-1"},X=g({__name:"WidgetDemoPage",setup(s){return(n,t)=>(i(),a("div",H,[e("nav",P,[e("div",L,[t[4]||(t[4]=e("div",{class:"flex items-center gap-3"},[e("div",{class:"w-8 h-8 rounded-lg bg-blue-600 flex items-center justify-center"},[e("span",{class:"text-white text-sm font-bold"},"A")]),e("span",{class:"text-lg font-semibold"},"Acme App")],-1)),e("div",N,[t[1]||(t[1]=e("a",{href:"#",class:"hover:text-gray-900"},"Dashboard",-1)),t[2]||(t[2]=e("a",{href:"#",class:"hover:text-gray-900"},"Projects",-1)),t[3]||(t[3]=e("a",{href:"#",class:"hover:text-gray-900"},"Settings",-1)),d(u($),{to:"/",class:"text-accent font-medium hover:underline"},{default:h(()=>[...t[0]||(t[0]=[U(" ← Back to AIUI ",-1)])]),_:1})])])]),e("div",F,[t[8]||(t[8]=e("div",{class:"mb-12"},[e("h1",{class:"text-3xl font-bold mb-2"},"Widget Integration Demo"),e("p",{class:"text-gray-500 max-w-2xl"}," This page simulates a third-party web application with the AIUI chat widget embedded. Click the floating button in the bottom corner to open the AI assistant. You can also switch which side it appears on. ")],-1)),e("div",K,[(i(),a(A,null,q(6,o=>e("div",{key:o,class:"bg-gray-50 rounded-2xl p-6 border border-gray-100"},[t[5]||(t[5]=e("div",{class:"w-10 h-10 rounded-xl bg-blue-100 text-blue-600 flex items-center justify-center mb-4"},[e("svg",{class:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})])],-1)),e("h3",R,"Project "+j(o),1),t[6]||(t[6]=e("p",{class:"text-sm text-gray-500 mb-3"}," Sample content card demonstrating how the widget overlays existing UI without disruption. ",-1)),t[7]||(t[7]=e("div",{class:"flex items-center gap-2"},[e("span",{class:"px-2.5 py-0.5 text-xs font-medium rounded-full bg-green-100 text-green-700"},"Active"),e("span",{class:"text-xs text-gray-400"},"Updated 2h ago")],-1))])),64))]),t[9]||(t[9]=M(`<div class="bg-gray-50 rounded-2xl border border-gray-200 p-8 mb-16"><h2 class="text-xl font-bold mb-4">How to embed AIUI in your app</h2><div class="space-y-6 text-sm text-gray-700"><div><h3 class="font-semibold text-gray-900 mb-2">Option 1: Script Tag (simplest)</h3><pre class="bg-gray-900 text-gray-100 rounded-lg p-4 overflow-x-auto text-xs"><code><script src="https://cdn.example.com/aiui-widget.js"></script>
|
|
<script>
|
|
AIUI.init({
|
|
apiKey: 'your-openrouter-key',
|
|
position: 'bottom-right', // or 'bottom-left'
|
|
theme: 'dark',
|
|
})
|
|
</script></code></pre></div><div><h3 class="font-semibold text-gray-900 mb-2">Option 2: Web Component</h3><pre class="bg-gray-900 text-gray-100 rounded-lg p-4 overflow-x-auto text-xs"><code><!-- Load the custom element -->
|
|
<script type="module" src="https://cdn.example.com/aiui-element.js"></script>
|
|
|
|
<!-- Use anywhere in your HTML -->
|
|
<aiui-chat
|
|
api-key="your-key"
|
|
position="bottom-right"
|
|
theme="dark"
|
|
></aiui-chat></code></pre></div><div><h3 class="font-semibold text-gray-900 mb-2">Option 3: npm package (Vue/React/Svelte)</h3><pre class="bg-gray-900 text-gray-100 rounded-lg p-4 overflow-x-auto text-xs"><code>npm install @aiui/widget
|
|
|
|
// Vue 3
|
|
import { AIUIWidget } from '@aiui/widget'
|
|
app.use(AIUIWidget, {
|
|
apiKey: 'your-key',
|
|
position: 'bottom-right',
|
|
})
|
|
|
|
// React
|
|
import { AIUIProvider } from '@aiui/widget/react'
|
|
<AIUIProvider apiKey="your-key" position="bottom-right" /></code></pre></div><div><h3 class="font-semibold text-gray-900 mb-2">Option 4: iframe (maximum isolation)</h3><pre class="bg-gray-900 text-gray-100 rounded-lg p-4 overflow-x-auto text-xs"><code><iframe
|
|
src="https://app.aiui.dev/embed?key=your-key&theme=dark"
|
|
style="position:fixed;bottom:80px;right:24px;width:420px;height:640px;
|
|
border:none;border-radius:16px;z-index:9999;"
|
|
allow="microphone"
|
|
></iframe></code></pre></div></div></div><div class="bg-gray-50 rounded-2xl border border-gray-200 p-8"><h2 class="text-xl font-bold mb-4">Technical Architecture</h2><div class="grid md:grid-cols-2 gap-8 text-sm text-gray-700"><div><h3 class="font-semibold text-gray-900 mb-2">Script Tag / npm</h3><ul class="space-y-1 list-disc list-inside"><li>Injects a Vue micro-app into a shadow DOM container</li><li>Styles are encapsulated — no CSS conflicts with host</li><li>Communicates via CustomEvents or a global AIUI API object</li><li>Host app can pass context (current page, user info)</li><li>Smallest footprint: ~80KB gzipped</li></ul></div><div><h3 class="font-semibold text-gray-900 mb-2">Web Component</h3><ul class="space-y-1 list-disc list-inside"><li>Framework-agnostic Custom Element (works in any HTML)</li><li>Shadow DOM encapsulation by default</li><li>Attributes for configuration, events for callbacks</li><li>Can be lazy-loaded with dynamic import()</li><li>Works in React, Angular, Svelte, plain HTML</li></ul></div><div><h3 class="font-semibold text-gray-900 mb-2">iframe</h3><ul class="space-y-1 list-disc list-inside"><li>Maximum isolation — separate browsing context</li><li>Zero risk of CSS/JS conflicts</li><li>Communication via postMessage API</li><li>API key stays on embedded origin (more secure)</li><li>Slightly larger overhead, but simplest integration</li></ul></div><div><h3 class="font-semibold text-gray-900 mb-2">Host Communication</h3><ul class="space-y-1 list-disc list-inside"><li>Host can send page context to AI for better answers</li><li>Widget can trigger actions in host app via callbacks</li><li>Conversation history syncs via encrypted IndexedDB</li><li>Deep-link support: <code class="bg-gray-200 px-1 rounded">?aiui=open&q=help</code></li></ul></div></div></div>`,2))]),d(D)]))}});export{X as default};
|