@akropolys/kiku 1.8.0 → 2.1.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 +64 -64
- package/dist/chunk-RWGHGIF7.mjs +3 -0
- package/dist/chunk-RWGHGIF7.mjs.map +1 -0
- package/dist/index.d.mts +5 -196
- package/dist/index.d.ts +5 -196
- package/dist/index.js +7 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -46
- package/dist/index.mjs.map +1 -1
- package/dist/lazy-UZ2LZJOA.mjs +39 -0
- package/dist/lazy-UZ2LZJOA.mjs.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +7 -9
- package/dist/kiku.iife.global.js +0 -111
- package/dist/kiku.iife.global.js.map +0 -1
- package/dist/kiku.iife.js +0 -111
- package/dist/kiku.iife.js.map +0 -1
- package/dist/shopify.global.js +0 -111
- package/dist/shopify.global.js.map +0 -1
- package/dist/shopify.js +0 -111
- package/dist/shopify.js.map +0 -1
- package/shopify/README.md +0 -71
- package/shopify/blocks/kiku-button.liquid +0 -121
- package/shopify/snippets/kiku-embed.liquid +0 -45
package/README.md
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
# @akropolys/kiku
|
|
2
|
-
|
|
3
|
-
Pre-built, blindly agnostic multi-modal conversational AI widget with duplex Live Voice, Computer Vision, and real-time comparative tables for any website or transactional platform.
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@akropolys/kiku) [](https://opensource.org/licenses/MIT) [](https://www.typescriptlang.org/)
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Install
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
npm install @akropolys/kiku @akropolys/sdk
|
|
13
|
-
# or
|
|
14
|
-
pnpm add @akropolys/kiku @akropolys/sdk
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Usage (React / Next.js)
|
|
20
|
-
|
|
21
|
-
```tsx
|
|
22
|
-
import { AkropolysProvider } from '@akropolys/sdk';
|
|
23
|
-
import { KikuButton } from '@akropolys/kiku';
|
|
24
|
-
import '@akropolys/kiku/styles.css';
|
|
25
|
-
|
|
26
|
-
export default function App() {
|
|
27
|
-
return (
|
|
28
|
-
<AkropolysProvider
|
|
29
|
-
siteId={process.env.NEXT_PUBLIC_AKROPOLYS_SITE_ID!}
|
|
30
|
-
apiUrl={process.env.NEXT_PUBLIC_AKROPOLYS_API_URL!}
|
|
31
|
-
apiToken={process.env.NEXT_PUBLIC_AKROPOLYS_API_KEY!}
|
|
32
|
-
>
|
|
33
|
-
<KikuButton
|
|
34
|
-
label="Ask me anything"
|
|
35
|
-
enableVoice={true}
|
|
36
|
-
enableVision={true}
|
|
37
|
-
theme={{
|
|
38
|
-
borderRadius: "24px",
|
|
39
|
-
}}
|
|
40
|
-
/>
|
|
41
|
-
</AkropolysProvider>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
> **Next.js Note**: If running an experimental Next.js 15/16 canary with Tailwind CSS v4 on Windows, run `next dev --webpack` if Turbopack experiences resolver latency on Windows ([tracked upstream](https://github.com/vercel/next.js/issues)).
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## Components
|
|
51
|
-
|
|
52
|
-
| Component | Description |
|
|
53
|
-
|---|---|
|
|
54
|
-
| `<KikuButton />` |
|
|
55
|
-
| `<
|
|
56
|
-
| `<
|
|
57
|
-
| `<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## License
|
|
63
|
-
|
|
64
|
-
MIT © [Akropolys](https://akropolys.cloud)
|
|
1
|
+
# @akropolys/kiku
|
|
2
|
+
|
|
3
|
+
Pre-built, blindly agnostic multi-modal conversational AI widget with duplex Live Voice, Computer Vision, and real-time comparative tables for any website or transactional platform.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@akropolys/kiku) [](https://opensource.org/licenses/MIT) [](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @akropolys/kiku @akropolys/sdk
|
|
13
|
+
# or
|
|
14
|
+
pnpm add @akropolys/kiku @akropolys/sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Usage (React / Next.js)
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { AkropolysProvider } from '@akropolys/sdk';
|
|
23
|
+
import { KikuButton } from '@akropolys/kiku';
|
|
24
|
+
import '@akropolys/kiku/styles.css'; // required: the chat window copies its rules from this sheet (serve it same-origin, or with crossorigin="anonymous")
|
|
25
|
+
|
|
26
|
+
export default function App() {
|
|
27
|
+
return (
|
|
28
|
+
<AkropolysProvider
|
|
29
|
+
siteId={process.env.NEXT_PUBLIC_AKROPOLYS_SITE_ID!}
|
|
30
|
+
apiUrl={process.env.NEXT_PUBLIC_AKROPOLYS_API_URL!}
|
|
31
|
+
apiToken={process.env.NEXT_PUBLIC_AKROPOLYS_API_KEY!}
|
|
32
|
+
>
|
|
33
|
+
<KikuButton
|
|
34
|
+
label="Ask me anything"
|
|
35
|
+
enableVoice={true}
|
|
36
|
+
enableVision={true}
|
|
37
|
+
theme={{
|
|
38
|
+
borderRadius: "24px",
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
</AkropolysProvider>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
> **Next.js Note**: If running an experimental Next.js 15/16 canary with Tailwind CSS v4 on Windows, run `next dev --webpack` if Turbopack experiences resolver latency on Windows ([tracked upstream](https://github.com/vercel/next.js/issues)).
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Components
|
|
51
|
+
|
|
52
|
+
| Component | Description |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `<KikuButton />` | Launcher pill that opens the full-screen chat, with live voice and vision. |
|
|
55
|
+
| `<SearchBar />` | Inline catalogue search with streamed results. |
|
|
56
|
+
| `<ScoutRail />` | Dock for the shopper's scouts: send one out, check on it, buy time. |
|
|
57
|
+
| `<ScoutCharacter />` | A single animated scout avatar. |
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
MIT © [Akropolys](https://akropolys.cloud)
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import{resolveDisplayFields as M}from"@akropolys/sdk";function N(t,e){return t.details??(t.fields?M(t.fields,e).details:[])}function O(t){return t.length?` (${t.map(e=>`${e.label}: ${e.value}`).join(", ")})`:""}function w(t){var e,n,r="";if(typeof t=="string"||typeof t=="number")r+=t;else if(typeof t=="object")if(Array.isArray(t)){var a=t.length;for(e=0;e<a;e++)t[e]&&(n=w(t[e]))&&(r&&(r+=" "),r+=n)}else for(n in t)t[n]&&(r&&(r+=" "),r+=n);return r}function $(){for(var t,e,n=0,r="",a=arguments.length;n<a;n++)(t=arguments[n])&&(e=w(t))&&(r&&(r+=" "),r+=e);return r}function L(...t){return $(t)}var k="hsk-sounds",o=null,m=null;function A(){try{return localStorage.getItem(k)!=="off"}catch{return!0}}function K(t){try{localStorage.setItem(k,t?"on":"off")}catch{}t&&S()}function S(){if(typeof window>"u")return;try{let e=navigator.audioSession;e&&e.type!=="playback"&&(e.type="playback")}catch{}if(o){o.state==="suspended"&&o.resume().catch(()=>{});return}let t=window.AudioContext||window.webkitAudioContext;if(t)try{o=new t({latencyHint:"interactive"}),m=o.createGain(),m.gain.value=.28,m.connect(o.destination);let e=o.createBuffer(1,1,o.sampleRate),n=o.createBufferSource();n.buffer=e,n.connect(o.destination),n.start(0),o.resume().catch(()=>{})}catch{o=null}}function p(t,e,n,r,a){if(!o||!m)return;let i=o.createOscillator();i.type="sine",i.frequency.setValueAtTime(e,t),i.frequency.exponentialRampToValueAtTime(Math.max(40,e*n),t+r);let s=o.createBiquadFilter();s.type="lowpass",s.Q.value=.9,s.frequency.setValueAtTime(Math.min(18e3,e*7),t),s.frequency.exponentialRampToValueAtTime(Math.max(80,e*1.5),t+r);let c=o.createGain();c.gain.setValueAtTime(1e-4,t),c.gain.exponentialRampToValueAtTime(a,t+.006),c.gain.exponentialRampToValueAtTime(1e-4,t+r),i.connect(s),s.connect(c),c.connect(m),i.start(t),i.stop(t+r+.02)}function F(t,e){if(!o||!m)return;let n=Math.floor(o.sampleRate*.03),r=o.createBuffer(1,n,o.sampleRate),a=r.getChannelData(0);for(let l=0;l<n;l++)a[l]=(Math.random()*2-1)*Math.pow(1-l/n,3);let i=o.createBufferSource();i.buffer=r;let s=o.createBiquadFilter();s.type="bandpass",s.frequency.value=2600,s.Q.value=5;let c=o.createGain();c.gain.value=e,i.connect(s),s.connect(c),c.connect(m),i.start(t)}function Y(){return A()?o?o.state:"unsupported":"off"}function V(t){!o||!m||(p(t,587.33,.985,.16,.38),p(t+.048,739.99,.985,.18,.42),p(t+.096,880,.985,.28,.46),p(t+.105,1174.66,.985,.22,.22),F(t+.096,.16))}function D(t){!o||!m||p(t,659.25,.97,.09,.26)}function J(t,e=!1){if(!e&&!A()||(S(),!o||!m||o.state==="closed"))return;o.state==="suspended"&&o.resume().catch(()=>{});let n=o.currentTime+.01;switch(t){case"connect":V(n);break;case"heard":D(n);break;case"reply":p(n,440,.94,.13,.5),p(n+.09,660,.94,.16,.42);break;case"interrupt":p(n,520,.62,.17,.4);break;case"send":p(n,300,1.16,.1,.22);break;case"pin":F(n,.35),p(n+.02,880,.97,.07,.22);break}}function Z(t){if(typeof t=="string")return{themeAttr:t,vars:void 0};if(!t)return{themeAttr:void 0,vars:void 0};let e={};return t.primaryColor&&(e["--hsk-primary"]=t.primaryColor),t.backgroundColor&&(e["--hsk-bg"]=t.backgroundColor,e["--hsk-chat-bg"]=t.backgroundColor),t.textColor&&(e["--hsk-text"]=t.textColor,e["--hsk-chat-text"]=t.textColor),t.fontFamily&&(e["--hsk-font"]=t.fontFamily),t.fontSize&&(e["--hsk-font-size"]=t.fontSize),t.mobileFontSize&&(e["--hsk-mobile-font-size"]=t.mobileFontSize),t.borderRadius&&(e["--hsk-border-radius"]=t.borderRadius),{themeAttr:void 0,vars:e}}import{useEffect as E}from"react";var u=new Map;function b(t,e="hsk-font"){let n=5381;for(let r=0;r<t.length;r++)n=(n<<5)+n+t.charCodeAt(r)>>>0;return`${e}-${n.toString(36)}`}function U(t){let e=t.split("?")[0].split("#")[0].split(".").pop()?.toLowerCase();return e==="woff2"?"woff2":e==="woff"?"woff":e==="otf"?"opentype":e==="ttf"?"truetype":""}function x(t){let e=t.trim();return!e||/["'()\\\s]/.test(e)||/^(javascript|vbscript):/i.test(e)?null:e}var R=t=>/["\\{}<>;\n\r]/.test(t)?"":t.trim(),q=/^[Uu]\+[0-9A-Fa-f?]{1,6}(-[0-9A-Fa-f]{1,6})?$/,T=t=>{let e=t.split(",").map(n=>n.trim()).filter(Boolean);return e.length===0||!e.every(n=>q.test(n))?"":e.join(", ")},P=t=>/^\d{3}( \d{3})?$/.test(t)?t:"400";function G(t,e){E(()=>{if(!t||!e||typeof document>"u")return;let n=b(t);if(u.set(t,(u.get(t)??0)+1),!document.getElementById(n)){let r=document.createElement("style");r.id=n,r.textContent=e,document.head.appendChild(r)}return()=>{let r=(u.get(t)??1)-1;if(r>0){u.set(t,r);return}u.delete(t),document.getElementById(n)?.remove()}},[t,e])}function j(t){let e=R(t.family);return e?t.faces.map(n=>{let r=x(n.url);return r?`@font-face{font-family:"${e}";font-style:normal;font-weight:${P(n.weight)};font-display:swap;src:url(${r}) format("woff2");`+(T(n.unicodeRange)?`unicode-range:${T(n.unicodeRange)};`:"")+"}":""}).join(""):""}function nt(t){let e=t?.faces??[],n=t&&e.length?j(t):"";G(n?`script|${t.family}|${e.map(r=>r.url).join("|")}`:"",n)}async function rt(t,e=0){if(typeof document>"u"||!("fonts"in document))return;let n=j(t);if(!n)return;let r=`script|${t.family}|${t.faces.map(i=>i.url).join("|")}`;u.set(r,(u.get(r)??0)+1);let a=b(r);if(!document.getElementById(a)){let i=document.createElement("style");i.id=a,i.textContent=n,document.head.appendChild(i)}if(e>0){let i=document.fonts,s=t.family.replace(/^['"]|['"]$/g,""),c=Array.from(i||[]).filter(f=>f.family.replace(/^['"]|['"]$/g,"")===s),l=c.length>0?c.map(f=>f.load().catch(()=>{})):t.faces.map(f=>{let y=x(f.url);if(!y)return Promise.resolve();try{return new window.FontFace(s,`url(${y})`,{weight:P(f.weight),style:"normal"}).load().then(d=>{document.fonts?.add(d)}).catch(()=>{})}catch{return Promise.resolve()}});await Promise.race([Promise.all(l),new Promise(f=>setTimeout(f,e))])}}var B=["400","500","600","700"];function I(t,e){let n=Array.from(new Set(Array.from(Object.values(e).join("")))).join(""),r=t.map(a=>`"${a.replace(/^['"]|['"]$/g,"")}"`).join(", ");return{text:n,stack:r}}function ot(t,e){let n=typeof document<"u"?document.fonts:null,{text:r,stack:a}=I(t,e);if(!n?.check||!r||!a)return!0;try{return B.every(i=>n.check(`${i} 16px ${a}`,r))}catch{return!0}}async function it(t,e,n){let r=typeof document<"u"?document.fonts:null;if(!r?.load)return;let{text:a,stack:i}=I(t,e);!a||!i||await Promise.race([Promise.all(B.map(s=>r.load(`${s} 16px ${i}`,a).catch(()=>{}))),new Promise(s=>setTimeout(s,n))])}function st(t){let e=typeof t=="object"&&t?t:void 0,n=R(e?.fontFamily?.split(",")[0].trim().replace(/^['"]|['"]$/g,"")??""),r=typeof e?.fontUrl=="string"?{normal:e.fontUrl}:e?.fontUrl??{},a=r.normal??"",i=r.bold??"",s=r.variable??"";E(()=>{if(!n||!a&&!i&&!s)return;let c=s?[["100 900",s]]:[["400",a],["700",i]],l=[];for(let[d,v]of c){if(!v)continue;let h=x(v);if(!h)continue;let C=U(h);l.push(`@font-face{font-family:"${n}";font-style:normal;font-weight:${d};font-display:swap;src:url(${h})${C?` format("${C}")`:""};}`)}if(l.length===0)return;let f=l.join(""),y=`${n}|${a}|${i}|${s}`,g=b(y,"hsk-host-font");if(u.set(y,(u.get(y)??0)+1),!document.getElementById(g)){let d=document.createElement("style");d.id=g,d.textContent=f,document.head.appendChild(d)}return()=>{let d=(u.get(y)??1)-1;if(d>0){u.set(y,d);return}u.delete(y),document.getElementById(g)?.remove()}},[n,a,i,s])}export{N as a,O as b,L as c,A as d,K as e,S as f,Y as g,J as h,Z as i,nt as j,rt as k,ot as l,it as m,st as n};
|
|
3
|
+
//# sourceMappingURL=chunk-RWGHGIF7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/cardDetails.ts","../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs","../src/utils/cn.ts","../src/utils/chime.ts","../src/utils/theme.ts","../src/utils/hostFont.ts"],"sourcesContent":["import { resolveDisplayFields, type CardDetail } from '@akropolys/sdk';\n\n// A card's details are the site's chosen cardFields; voice sources arrive with raw fields and are resolved here.\nexport function detailsOf(src: { details?: CardDetail[]; fields?: Record<string, any> }, cardFields: string[]): CardDetail[] {\n return src.details ?? (src.fields ? resolveDisplayFields(src.fields, cardFields).details : []);\n}\n\nexport function detailsText(details: CardDetail[]): string {\n return details.length ? ` (${details.map(d => `${d.label}: ${d.value}`).join(', ')})` : '';\n}\n","function r(e){var t,f,n=\"\";if(\"string\"==typeof e||\"number\"==typeof e)n+=e;else if(\"object\"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=\" \"),n+=f)}else for(f in e)e[f]&&(n&&(n+=\" \"),n+=f);return n}export function clsx(){for(var e,t,f=0,n=\"\",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=\" \"),n+=t);return n}export default clsx;","import { clsx, type ClassValue } from \"clsx\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return clsx(inputs);\r\n}\r\n","const SOUND_KEY = 'hsk-sounds';\n\nlet ctx: AudioContext | null = null;\nlet master: GainNode | null = null;\n\nexport function soundsEnabled(): boolean {\n try {\n return localStorage.getItem(SOUND_KEY) !== 'off';\n } catch {\n return true;\n }\n}\n\nexport function setSoundsEnabled(on: boolean): void {\n try {\n localStorage.setItem(SOUND_KEY, on ? 'on' : 'off');\n } catch { }\n if (on) primeChimes();\n}\n\nexport function primeChimes(): void {\n if (typeof window === 'undefined') return;\n try {\n const session = (navigator as any).audioSession;\n if (session && session.type !== 'playback') session.type = 'playback';\n } catch { }\n if (ctx) {\n if (ctx.state === 'suspended') ctx.resume().catch(() => {});\n return;\n }\n const AC: typeof AudioContext = (window as any).AudioContext || (window as any).webkitAudioContext;\n if (!AC) return;\n try {\n ctx = new AC({ latencyHint: 'interactive' });\n master = ctx.createGain();\n master.gain.value = 0.28;\n master.connect(ctx.destination);\n const b = ctx.createBuffer(1, 1, ctx.sampleRate);\n const s = ctx.createBufferSource();\n s.buffer = b;\n s.connect(ctx.destination);\n s.start(0);\n ctx.resume().catch(() => {});\n } catch {\n ctx = null;\n }\n}\n\nfunction droplet(at: number, f0: number, glide: number, dur: number, gain: number): void {\n if (!ctx || !master) return;\n const osc = ctx.createOscillator();\n osc.type = 'sine';\n osc.frequency.setValueAtTime(f0, at);\n osc.frequency.exponentialRampToValueAtTime(Math.max(40, f0 * glide), at + dur);\n\n const lp = ctx.createBiquadFilter();\n lp.type = 'lowpass';\n lp.Q.value = 0.9;\n lp.frequency.setValueAtTime(Math.min(18000, f0 * 7), at);\n lp.frequency.exponentialRampToValueAtTime(Math.max(80, f0 * 1.5), at + dur);\n\n const g = ctx.createGain();\n g.gain.setValueAtTime(0.0001, at);\n g.gain.exponentialRampToValueAtTime(gain, at + 0.006);\n g.gain.exponentialRampToValueAtTime(0.0001, at + dur);\n\n osc.connect(lp);\n lp.connect(g);\n g.connect(master);\n osc.start(at);\n osc.stop(at + dur + 0.02);\n}\n\n// Not a tone: a filtered noise burst, so it reads as contact rather than pitch.\nfunction tick(at: number, gain: number): void {\n if (!ctx || !master) return;\n const n = Math.floor(ctx.sampleRate * 0.03);\n const buf = ctx.createBuffer(1, n, ctx.sampleRate);\n const d = buf.getChannelData(0);\n for (let i = 0; i < n; i++) d[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / n, 3);\n\n const src = ctx.createBufferSource();\n src.buffer = buf;\n const bp = ctx.createBiquadFilter();\n bp.type = 'bandpass';\n bp.frequency.value = 2600;\n bp.Q.value = 5;\n const g = ctx.createGain();\n g.gain.value = gain;\n\n src.connect(bp);\n bp.connect(g);\n g.connect(master);\n src.start(at);\n}\n\n/** 'off' | 'unsupported' | AudioContext state - so a silent phone can say why. */\nexport function chimeState(): string {\n if (!soundsEnabled()) return 'off';\n if (!ctx) return 'unsupported';\n return ctx.state;\n}\n\nexport type ChimeEvent = 'reply' | 'interrupt' | 'pin' | 'send' | 'connect' | 'heard';\n\nfunction connectChime(at: number): void {\n if (!ctx || !master) return;\n\n // D5 (587.33 Hz) warm initial chime\n droplet(at, 587.33, 0.985, 0.16, 0.38);\n\n // F#5 (739.99 Hz) ascending major third\n droplet(at + 0.048, 739.99, 0.985, 0.18, 0.42);\n\n // A5 (880.00 Hz) fifth + D6 (1174.66 Hz) high glass shimmer with silky decay\n droplet(at + 0.096, 880.00, 0.985, 0.28, 0.46);\n droplet(at + 0.105, 1174.66, 0.985, 0.22, 0.22);\n\n // Subtle organic acoustic strike transient on the peak note\n tick(at + 0.096, 0.16);\n}\n\nfunction heardChime(at: number): void {\n if (!ctx || !master) return;\n droplet(at, 659.25, 0.97, 0.09, 0.26);\n}\n\n/** force plays even while muted - the toggle has to be able to demonstrate itself. */\nexport function chime(event: ChimeEvent, force = false): void {\n if (!force && !soundsEnabled()) return;\n primeChimes();\n if (!ctx || !master || ctx.state === 'closed') return;\n if (ctx.state === 'suspended') ctx.resume().catch(() => {});\n\n const t = ctx.currentTime + 0.01;\n switch (event) {\n case 'connect':\n connectChime(t);\n break;\n case 'heard':\n heardChime(t);\n break;\n case 'reply':\n droplet(t, 440, 0.94, 0.13, 0.5);\n droplet(t + 0.09, 660, 0.94, 0.16, 0.42);\n break;\n case 'interrupt':\n droplet(t, 520, 0.62, 0.17, 0.4);\n break;\n case 'send':\n droplet(t, 300, 1.16, 0.1, 0.22);\n break;\n case 'pin':\n tick(t, 0.35);\n droplet(t + 0.02, 880, 0.97, 0.07, 0.22);\n break;\n }\n}\n","import type { CSSProperties } from 'react';\r\nimport type { AkropolysTheme } from '@akropolys/sdk';\r\n\r\nexport type ThemeProp = string | AkropolysTheme | undefined;\r\n\r\nexport function resolveTheme(theme: ThemeProp): {\r\n themeAttr: string | undefined;\r\n vars: CSSProperties | undefined;\r\n} {\r\n if (typeof theme === 'string') {\r\n return { themeAttr: theme as any, vars: undefined };\r\n }\r\n if (!theme) {\r\n return { themeAttr: undefined, vars: undefined };\r\n }\r\n const vars: Record<string, string> = {};\r\n if (theme.primaryColor) vars['--hsk-primary'] = theme.primaryColor;\r\n if (theme.backgroundColor) {\r\n vars['--hsk-bg'] = theme.backgroundColor;\r\n vars['--hsk-chat-bg'] = theme.backgroundColor;\r\n }\r\n if (theme.textColor) {\r\n vars['--hsk-text'] = theme.textColor;\r\n vars['--hsk-chat-text'] = theme.textColor;\r\n }\r\n if (theme.fontFamily) vars['--hsk-font'] = theme.fontFamily;\r\n if (theme.fontSize) vars['--hsk-font-size'] = theme.fontSize;\r\n if (theme.mobileFontSize) vars['--hsk-mobile-font-size'] = theme.mobileFontSize;\r\n if (theme.borderRadius) vars['--hsk-border-radius'] = theme.borderRadius;\r\n return { themeAttr: undefined, vars: vars as CSSProperties };\r\n}\r\n","import { useEffect } from 'react';\r\nimport type { AkropolysTheme, ScriptFont } from '@akropolys/sdk';\r\n\r\nconst MOUNTED = new Map<string, number>();\r\n\r\nfunction styleId(key: string, prefix = 'hsk-font'): string {\r\n let h = 5381;\r\n for (let i = 0; i < key.length; i++) h = ((h << 5) + h + key.charCodeAt(i)) >>> 0;\r\n return `${prefix}-${h.toString(36)}`;\r\n}\r\n\r\nfunction formatFor(url: string): string {\r\n const ext = url.split('?')[0].split('#')[0].split('.').pop()?.toLowerCase();\r\n if (ext === 'woff2') return 'woff2';\r\n if (ext === 'woff') return 'woff';\r\n if (ext === 'otf') return 'opentype';\r\n if (ext === 'ttf') return 'truetype';\r\n return '';\r\n}\r\n\r\nfunction safeUrl(url: string): string | null {\r\n const u = url.trim();\r\n if (!u) return null;\r\n if (/[\"'()\\\\\\s]/.test(u)) return null;\r\n if (/^(javascript|vbscript):/i.test(u)) return null;\r\n return u;\r\n}\r\n\r\nconst safeFamily = (f: string): string => (/[\"\\\\{}<>;\\n\\r]/.test(f) ? '' : f.trim());\r\n\r\nconst RANGE_SEGMENT =/^[Uu]\\+[0-9A-Fa-f?]{1,6}(-[0-9A-Fa-f]{1,6})?$/;\r\n\r\nconst safeRange = (r: string): string => {\r\n const parts = r.split(',').map(s => s.trim()).filter(Boolean);\r\n if (parts.length === 0 || !parts.every(p => RANGE_SEGMENT.test(p))) return '';\r\n return parts.join(', ');\r\n};\r\n\r\nconst safeWeight = (w: string): string => (/^\\d{3}( \\d{3})?$/.test(w) ? w : '400');\r\n\r\nfunction useMountedFaces(key: string, css: string): void {\r\n useEffect(() => {\r\n if (!key || !css || typeof document === 'undefined') return;\r\n const id = styleId(key);\r\n\r\n MOUNTED.set(key, (MOUNTED.get(key) ?? 0) + 1);\r\n if (!document.getElementById(id)) {\r\n const el = document.createElement('style');\r\n el.id = id;\r\n el.textContent = css;\r\n document.head.appendChild(el);\r\n }\r\n\r\n return () => {\r\n const left = (MOUNTED.get(key) ?? 1) - 1;\r\n if (left > 0) { MOUNTED.set(key, left); return; }\r\n MOUNTED.delete(key);\r\n document.getElementById(id)?.remove();\r\n };\r\n }, [key, css]);\r\n}\r\n\r\nfunction scriptFontCSS(font: ScriptFont): string {\r\n const family = safeFamily(font.family);\r\n if (!family) return '';\r\n return font.faces\r\n .map(f => {\r\n const url = safeUrl(f.url);\r\n if (!url) return '';\r\n return `@font-face{font-family:\"${family}\";font-style:normal;` +\r\n `font-weight:${safeWeight(f.weight)};font-display:swap;src:url(${url}) format(\"woff2\");` +\r\n (safeRange(f.unicodeRange) ? `unicode-range:${safeRange(f.unicodeRange)};` : '') + '}';\r\n })\r\n .join('');\r\n}\r\n\r\nexport function useScriptFontFace(font: ScriptFont | null | undefined): void {\r\n const faces = font?.faces ?? [];\r\n const css = font && faces.length ? scriptFontCSS(font) : '';\r\n useMountedFaces(css ? `script|${font!.family}|${faces.map(f => f.url).join('|')}` : '', css);\r\n}\r\n\r\nexport async function preloadScriptFont(font: ScriptFont, timeoutMs = 0): Promise<void> {\r\n if (typeof document === 'undefined' || !('fonts' in document)) return;\r\n const css = scriptFontCSS(font);\r\n if (!css) return;\r\n\r\n const key = `script|${font.family}|${font.faces.map(f => f.url).join('|')}`;\r\n MOUNTED.set(key, (MOUNTED.get(key) ?? 0) + 1);\r\n const id = styleId(key);\r\n if (!document.getElementById(id)) {\r\n const el = document.createElement('style');\r\n el.id = id;\r\n el.textContent = css;\r\n document.head.appendChild(el);\r\n }\r\n\r\n if (timeoutMs > 0) {\r\n const fonts = (document as any).fonts;\r\n const cleanFamily = font.family.replace(/^['\"]|['\"]$/g, '');\r\n const matched = Array.from(fonts || []).filter(\r\n (f: any) => f.family.replace(/^['\"]|['\"]$/g, '') === cleanFamily\r\n ) as any[];\r\n\r\n const loads = matched.length > 0\r\n ? matched.map((f: any) => f.load().catch(() => {}))\r\n : font.faces.map(f => {\r\n const url = safeUrl(f.url);\r\n if (!url) return Promise.resolve();\r\n try {\r\n const face = new (window as any).FontFace(cleanFamily, `url(${url})`, {\r\n weight: safeWeight(f.weight),\r\n style: 'normal',\r\n });\r\n return face.load().then((loaded: any) => {\r\n (document as any).fonts?.add(loaded);\r\n }).catch(() => {});\r\n } catch {\r\n return Promise.resolve();\r\n }\r\n });\r\n\r\n await Promise.race([\r\n Promise.all(loads),\r\n new Promise(resolve => setTimeout(resolve, timeoutMs)),\r\n ]);\r\n }\r\n}\r\n\r\nconst UI_WEIGHTS = ['400', '500', '600', '700'];\r\n\r\nfunction fontQuery(families: string[], strings: Record<string, string>) {\r\n const text = Array.from(new Set(Array.from(Object.values(strings).join('')))).join('');\r\n const stack = families.map(f => `\"${f.replace(/^['\"]|['\"]$/g, '')}\"`).join(', ');\r\n return { text, stack };\r\n}\r\n\r\n// True when every face these strings need is already loaded at every weight the widget draws.\r\nexport function fontsLoadedFor(families: string[], strings: Record<string, string>): boolean {\r\n const fonts = typeof document !== 'undefined' ? (document as any).fonts : null;\r\n const { text, stack } = fontQuery(families, strings);\r\n if (!fonts?.check || !text || !stack) return true;\r\n try {\r\n return UI_WEIGHTS.every(w => fonts.check(`${w} 16px ${stack}`, text));\r\n } catch {\r\n return true;\r\n }\r\n}\r\n\r\n// Loads, at every weight the widget draws, each face these strings need; unicode-range faces load only their slices.\r\nexport async function loadFontsFor(families: string[], strings: Record<string, string>, timeoutMs: number): Promise<void> {\r\n const fonts = typeof document !== 'undefined' ? (document as any).fonts : null;\r\n if (!fonts?.load) return;\r\n const { text, stack } = fontQuery(families, strings);\r\n if (!text || !stack) return;\r\n await Promise.race([\r\n Promise.all(UI_WEIGHTS.map(w => fonts.load(`${w} 16px ${stack}`, text).catch(() => {}))),\r\n new Promise(resolve => setTimeout(resolve, timeoutMs)),\r\n ]);\r\n}\r\n\r\nexport function useHostFontFace(theme: 'light' | 'dark' | AkropolysTheme | undefined): void {\r\n const t = typeof theme === 'object' && theme ? theme : undefined;\r\n const family = safeFamily(t?.fontFamily?.split(',')[0].trim().replace(/^['\"]|['\"]$/g, '') ?? '');\r\n const urls = typeof t?.fontUrl === 'string' ? { normal: t.fontUrl } : (t?.fontUrl ?? {});\r\n const normal = urls.normal ?? '';\r\n const bold = urls.bold ?? '';\r\n const variable = urls.variable ?? '';\r\n\r\n useEffect(() => {\r\n if (!family || (!normal && !bold && !variable)) return;\r\n\r\n const weights: ReadonlyArray<readonly [string, string]> = variable\r\n ? [['100 900', variable]]\r\n : [['400', normal], ['700', bold]];\r\n\r\n const faces: string[] = [];\r\n for (const [weight, raw] of weights) {\r\n if (!raw) continue;\r\n const url = safeUrl(raw);\r\n if (!url) continue;\r\n const fmt = formatFor(url);\r\n faces.push(\r\n `@font-face{font-family:\"${family}\";font-style:normal;font-weight:${weight};` +\r\n `font-display:swap;src:url(${url})${fmt ? ` format(\"${fmt}\")` : ''};}`\r\n );\r\n }\r\n if (faces.length === 0) return;\r\n\r\n const css = faces.join('');\r\n const key = `${family}|${normal}|${bold}|${variable}`;\r\n const id = styleId(key, 'hsk-host-font');\r\n\r\n MOUNTED.set(key, (MOUNTED.get(key) ?? 0) + 1);\r\n if (!document.getElementById(id)) {\r\n const el = document.createElement('style');\r\n el.id = id;\r\n el.textContent = css;\r\n document.head.appendChild(el);\r\n }\r\n\r\n return () => {\r\n const left = (MOUNTED.get(key) ?? 1) - 1;\r\n if (left > 0) { MOUNTED.set(key, left); return; }\r\n MOUNTED.delete(key);\r\n document.getElementById(id)?.remove();\r\n };\r\n }, [family, normal, bold, variable]);\r\n}\r\n"],"mappings":"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","names":["resolveDisplayFields","detailsOf","src","cardFields","detailsText","details","d","r","e","t","f","n","o","clsx","cn","inputs","clsx","SOUND_KEY","ctx","master","soundsEnabled","setSoundsEnabled","on","primeChimes","session","AC","b","s","droplet","at","f0","glide","dur","gain","osc","lp","g","tick","buf","d","i","src","bp","chimeState","connectChime","heardChime","chime","event","force","t","resolveTheme","theme","vars","useEffect","MOUNTED","styleId","key","prefix","h","i","formatFor","url","ext","safeUrl","u","safeFamily","f","RANGE_SEGMENT","safeRange","r","parts","s","p","safeWeight","w","useMountedFaces","css","id","el","left","scriptFontCSS","font","family","useScriptFontFace","faces","preloadScriptFont","timeoutMs","fonts","cleanFamily","matched","loads","loaded","resolve","UI_WEIGHTS","fontQuery","families","strings","text","stack","fontsLoadedFor","loadFontsFor","useHostFontFace","theme","t","urls","normal","bold","variable","weights","weight","raw","fmt"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { SearchResult, AkropolysTheme, ChatSource
|
|
2
|
+
import { SearchResult, AkropolysTheme, ChatSource } from '@akropolys/sdk';
|
|
3
3
|
|
|
4
4
|
interface SearchBarProps {
|
|
5
5
|
placeholder?: string;
|
|
@@ -20,44 +20,18 @@ interface SearchBarProps {
|
|
|
20
20
|
}
|
|
21
21
|
declare function SearchBar({ placeholder, limit, debounceMs, onSelect, className, inputClassName, dropdownClassName, renderResult, theme, classNames, }: SearchBarProps): React.JSX.Element;
|
|
22
22
|
|
|
23
|
-
interface ChatWidgetProps {
|
|
24
|
-
title?: string;
|
|
25
|
-
placeholder?: string;
|
|
26
|
-
emptyStateText?: string;
|
|
27
|
-
emptyStateSuggestions?: string;
|
|
28
|
-
defaultCurrency?: string;
|
|
29
|
-
className?: string;
|
|
30
|
-
theme?: AkropolysTheme;
|
|
31
|
-
classNames?: {
|
|
32
|
-
root?: string;
|
|
33
|
-
header?: string;
|
|
34
|
-
messageBubble?: string;
|
|
35
|
-
input?: string;
|
|
36
|
-
};
|
|
37
|
-
onSelectSource?: (source: ChatSource) => void;
|
|
38
|
-
enableVoice?: boolean;
|
|
39
|
-
/** Enable 📷 visual style-match search */
|
|
40
|
-
enableVision?: boolean;
|
|
41
|
-
visionCategoryHint?: string;
|
|
42
|
-
/** Enable 🔊 TTS voice audio responses from AI */
|
|
43
|
-
enableAudioResponse?: boolean;
|
|
44
|
-
/** Optional AI voice preset */
|
|
45
|
-
ttsVoice?: string;
|
|
46
|
-
autoSpeakResponses?: boolean;
|
|
47
|
-
}
|
|
48
|
-
declare function ChatWidget({ title, placeholder, emptyStateText, emptyStateSuggestions, defaultCurrency, className, theme, classNames, onSelectSource, enableVoice, enableVision, visionCategoryHint, enableAudioResponse, ttsVoice, autoSpeakResponses }: ChatWidgetProps): React.JSX.Element;
|
|
49
|
-
|
|
50
23
|
interface KikuButtonProps {
|
|
51
24
|
label?: React.ReactNode;
|
|
52
25
|
children?: React.ReactNode;
|
|
53
26
|
icon?: React.ReactNode;
|
|
54
27
|
title?: string;
|
|
28
|
+
/** Wordmark shown in place of the name in the topbar. */
|
|
29
|
+
logo?: string;
|
|
55
30
|
placeholder?: string;
|
|
56
31
|
backdropColor?: string;
|
|
57
32
|
backdropBlur?: string | number;
|
|
58
33
|
className?: string;
|
|
59
34
|
onSelectSource?: (source: ChatSource) => void;
|
|
60
|
-
defaultCurrency?: string;
|
|
61
35
|
chips?: string[];
|
|
62
36
|
theme?: 'light' | 'dark' | AkropolysTheme;
|
|
63
37
|
classNames?: {
|
|
@@ -70,173 +44,8 @@ interface KikuButtonProps {
|
|
|
70
44
|
enableVoice?: boolean;
|
|
71
45
|
voiceLang?: string;
|
|
72
46
|
enableVision?: boolean;
|
|
73
|
-
visionCategoryHint?: string;
|
|
74
|
-
/** Enable 🔊 TTS voice audio responses from AI */
|
|
75
|
-
enableAudioResponse?: boolean;
|
|
76
|
-
ttsVoice?: string;
|
|
77
|
-
autoSpeakResponses?: boolean;
|
|
78
|
-
}
|
|
79
|
-
declare function KikuButton({ label, children, icon, title, placeholder, backdropColor, backdropBlur, className, onSelectSource, defaultCurrency, chips, theme, classNames, enableVoice, voiceLang, enableVision, visionCategoryHint, enableAudioResponse, ttsVoice, autoSpeakResponses, }: KikuButtonProps): React.JSX.Element;
|
|
80
|
-
|
|
81
|
-
interface SparkleProps {
|
|
82
|
-
productName: string;
|
|
83
|
-
limit?: number;
|
|
84
|
-
onResult?: (results: SearchResult[]) => void;
|
|
85
|
-
backdropColor?: string;
|
|
86
|
-
backdropBlur?: string | number;
|
|
87
|
-
className?: string;
|
|
88
|
-
onNavigate?: (result: SearchResult) => boolean | void;
|
|
89
|
-
theme?: AkropolysTheme;
|
|
90
|
-
classNames?: {
|
|
91
|
-
button?: string;
|
|
92
|
-
backdrop?: string;
|
|
93
|
-
card?: string;
|
|
94
|
-
item?: string;
|
|
95
|
-
};
|
|
96
|
-
product?: Product;
|
|
97
|
-
children?: React.ReactNode;
|
|
98
|
-
}
|
|
99
|
-
declare function Sparkle({ productName, limit, onResult, backdropColor, backdropBlur, className, onNavigate, theme, classNames, product, children, }: SparkleProps): React.JSX.Element;
|
|
100
|
-
|
|
101
|
-
interface VoiceButtonProps {
|
|
102
|
-
onTranscript: (text: string) => void;
|
|
103
|
-
onInterim?: (text: string) => void;
|
|
104
|
-
/** BCP-47 tag. Defaults to the page's <html lang>, then the browser language. */
|
|
105
|
-
lang?: string;
|
|
106
|
-
className?: string;
|
|
107
|
-
disabled?: boolean;
|
|
108
|
-
/** Raw SpeechRecognition error code — 'not-allowed', 'audio-capture', etc. */
|
|
109
|
-
onError?: (code: string) => void;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* VoiceButton — speech to text input with pause-based utterance detection.
|
|
113
|
-
*/
|
|
114
|
-
declare function VoiceButton({ onTranscript, onInterim, lang, className, disabled, onError, }: VoiceButtonProps): React.JSX.Element | null;
|
|
115
|
-
|
|
116
|
-
interface VisualSearchProps {
|
|
117
|
-
/** Called with search results + the base64 preview when Gemini responds. */
|
|
118
|
-
onResults: (res: VisualSearchResponse, previewBase64: string) => void;
|
|
119
|
-
onError?: (err: Error) => void;
|
|
120
|
-
/**
|
|
121
|
-
* Category hint sent to Gemini to sharpen the match_query.
|
|
122
|
-
* e.g. "dress", "curtains", "sofa", "shoes"
|
|
123
|
-
*/
|
|
124
|
-
categoryHint?: string;
|
|
125
|
-
className?: string;
|
|
126
|
-
disabled?: boolean;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* VisualSearch — camera/image-upload button for style-match search.
|
|
130
|
-
*/
|
|
131
|
-
declare function VisualSearch({ onResults, onError, categoryHint, className, disabled, }: VisualSearchProps): React.JSX.Element;
|
|
132
|
-
|
|
133
|
-
interface ScoutRailProps {
|
|
134
|
-
className?: string;
|
|
135
|
-
themeAttr?: string;
|
|
136
|
-
onAsk?: (scout: Scout) => void;
|
|
137
|
-
onNew?: (avatar: string) => void;
|
|
138
|
-
open?: boolean;
|
|
139
|
-
onOpenChange?: (open: boolean) => void;
|
|
140
|
-
}
|
|
141
|
-
declare function ScoutRail({ className, themeAttr, onAsk, onNew, open: openProp, onOpenChange }: ScoutRailProps): React.JSX.Element;
|
|
142
|
-
|
|
143
|
-
type ScoutMood = 'watching' | 'resting' | 'struck' | 'gone';
|
|
144
|
-
interface ScoutCharacterProps {
|
|
145
|
-
scoutId: string;
|
|
146
|
-
avatar?: string;
|
|
147
|
-
mood?: ScoutMood;
|
|
148
|
-
size?: number;
|
|
149
|
-
layer?: 'all' | 'body';
|
|
150
|
-
}
|
|
151
|
-
declare function ScoutCharacter({ scoutId, avatar, mood, size, layer }: ScoutCharacterProps): React.JSX.Element;
|
|
152
|
-
|
|
153
|
-
interface ShopifyProduct {
|
|
154
|
-
id?: number | string;
|
|
155
|
-
title?: string;
|
|
156
|
-
name?: string;
|
|
157
|
-
handle?: string;
|
|
158
|
-
url?: string;
|
|
159
|
-
price?: number | string;
|
|
160
|
-
compare_at_price?: number | string;
|
|
161
|
-
price_min?: number | string;
|
|
162
|
-
featured_image?: string;
|
|
163
|
-
images?: string[] | {
|
|
164
|
-
src: string;
|
|
165
|
-
}[];
|
|
166
|
-
image?: string;
|
|
167
|
-
type?: string;
|
|
168
|
-
product_type?: string;
|
|
169
|
-
category?: string;
|
|
170
|
-
vendor?: string;
|
|
171
|
-
brand?: string;
|
|
172
|
-
tags?: string[] | string;
|
|
173
|
-
description?: string;
|
|
174
|
-
body_html?: string;
|
|
175
|
-
variants?: Array<{
|
|
176
|
-
id: number | string;
|
|
177
|
-
title?: string;
|
|
178
|
-
price?: number | string;
|
|
179
|
-
sku?: string;
|
|
180
|
-
available?: boolean;
|
|
181
|
-
}>;
|
|
182
|
-
available?: boolean;
|
|
183
|
-
[key: string]: any;
|
|
184
|
-
}
|
|
185
|
-
interface StandaloneConfig {
|
|
186
|
-
siteId?: string;
|
|
187
|
-
apiToken?: string;
|
|
188
|
-
apiUrl?: string;
|
|
189
|
-
vertical?: string;
|
|
190
|
-
shopperId?: string;
|
|
191
|
-
theme?: 'dark' | 'light' | any;
|
|
192
|
-
buttonLabel?: string;
|
|
193
|
-
title?: string;
|
|
194
|
-
placeholder?: string;
|
|
195
|
-
defaultCurrency?: string;
|
|
196
|
-
chips?: string[];
|
|
197
|
-
enableVoice?: boolean;
|
|
198
|
-
voiceLang?: string;
|
|
199
|
-
enableVision?: boolean;
|
|
200
|
-
visionCategoryHint?: string;
|
|
201
|
-
enableAudioResponse?: boolean;
|
|
202
47
|
ttsVoice?: string;
|
|
203
|
-
autoSpeakResponses?: boolean;
|
|
204
|
-
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'inline' | 'hidden' | 'custom';
|
|
205
|
-
containerId?: string;
|
|
206
|
-
containerSelector?: string;
|
|
207
|
-
dockable?: boolean;
|
|
208
|
-
product?: ShopifyProduct;
|
|
209
|
-
onAddToCart?: (items: ChatSource[]) => void;
|
|
210
|
-
onAction?: (action: any) => void;
|
|
211
|
-
[key: string]: any;
|
|
212
|
-
}
|
|
213
|
-
declare global {
|
|
214
|
-
interface Window {
|
|
215
|
-
AkropolysConfig?: StandaloneConfig;
|
|
216
|
-
Kiku?: {
|
|
217
|
-
version: string;
|
|
218
|
-
open: () => void;
|
|
219
|
-
close: () => void;
|
|
220
|
-
toggle: () => void;
|
|
221
|
-
ingest: (product: ShopifyProduct) => Promise<void>;
|
|
222
|
-
resetPosition: () => void;
|
|
223
|
-
getClient: () => any;
|
|
224
|
-
config: StandaloneConfig;
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
48
|
}
|
|
228
|
-
|
|
229
|
-
* Normalizes a Shopify product object into Akropolys entity format.
|
|
230
|
-
*/
|
|
231
|
-
declare function normalizeShopifyProduct(p: ShopifyProduct): Record<string, any>;
|
|
232
|
-
/**
|
|
233
|
-
* Native Shopify Cart Integration.
|
|
234
|
-
*/
|
|
235
|
-
declare function shopifyAddToCart(items: ChatSource[]): Promise<any>;
|
|
236
|
-
/**
|
|
237
|
-
* Native Shopify Get Cart.
|
|
238
|
-
*/
|
|
239
|
-
declare function shopifyGetCart(): Promise<any>;
|
|
240
|
-
declare function initKiku(customConfig?: StandaloneConfig): void;
|
|
49
|
+
declare function KikuButton({ label, children, icon, title, logo, placeholder, backdropColor, backdropBlur, className, onSelectSource, chips, theme, classNames, enableVoice, voiceLang, ttsVoice, enableVision, }: KikuButtonProps): React.JSX.Element;
|
|
241
50
|
|
|
242
|
-
export {
|
|
51
|
+
export { KikuButton, type KikuButtonProps, SearchBar, type SearchBarProps };
|