@akropolys/kiku 1.0.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 +204 -0
- package/dist/index.d.mts +109 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +2538 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2504 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +3717 -0
- package/dist/styles.css.map +1 -0
- package/dist/styles.d.mts +2 -0
- package/dist/styles.d.ts +2 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# @akropolys/kiku
|
|
2
|
+
|
|
3
|
+
> Plug-and-play React AI chat, search, and commerce UI components.
|
|
4
|
+
|
|
5
|
+
Kiku is the ready-made UI layer for Akropolys. Drop in a floating chat button, a search bar with AI-powered results, a product comparison matrix, or a full checkout modal — all styled, animated, and wired to the Akropolys backend out of the box.
|
|
6
|
+
|
|
7
|
+
If you want full control over the UI, use [`@akropolys/sdk`](https://www.npmjs.com/package/@akropolys/sdk) directly.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @akropolys/kiku @akropolys/sdk
|
|
15
|
+
# or
|
|
16
|
+
pnpm add @akropolys/kiku @akropolys/sdk
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Import the stylesheet once in your app entry point:**
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import '@akropolys/kiku/styles.css';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { AkropolysProvider } from '@akropolys/sdk';
|
|
31
|
+
import { KikuButton } from '@akropolys/kiku';
|
|
32
|
+
import '@akropolys/kiku/styles.css';
|
|
33
|
+
|
|
34
|
+
export default function App() {
|
|
35
|
+
return (
|
|
36
|
+
<AkropolysProvider
|
|
37
|
+
siteId="your-site-id"
|
|
38
|
+
apiUrl="https://api.akropolys.io"
|
|
39
|
+
apiToken="your-api-token"
|
|
40
|
+
>
|
|
41
|
+
{/* Floating chat button — renders the full AI shopping assistant */}
|
|
42
|
+
<KikuButton label="Chat with Kiku" />
|
|
43
|
+
</AkropolysProvider>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Components
|
|
51
|
+
|
|
52
|
+
### `<KikuButton />` — Floating AI chat assistant
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { KikuButton } from '@akropolys/kiku';
|
|
56
|
+
|
|
57
|
+
<KikuButton
|
|
58
|
+
label="Ask Kiku"
|
|
59
|
+
title="Shopping Assistant"
|
|
60
|
+
placeholder="What are you looking for?"
|
|
61
|
+
theme="dark" // 'light' | 'dark' | AkropolysTheme
|
|
62
|
+
chips={['Best phones', 'Laptops under KSh 50K']}
|
|
63
|
+
onSelectSource={(src) => console.log(src)}
|
|
64
|
+
/>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### `<KikuChat />` — Inline embedded chat widget
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { KikuChat } from '@akropolys/kiku';
|
|
73
|
+
|
|
74
|
+
<KikuChat
|
|
75
|
+
title="AI Shopping Assistant"
|
|
76
|
+
placeholder="Ask about anything in our store…"
|
|
77
|
+
defaultCurrency="KES"
|
|
78
|
+
/>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### `<SearchBar />` — Debounced AI search with dropdown
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { SearchBar } from '@akropolys/kiku';
|
|
87
|
+
|
|
88
|
+
<SearchBar
|
|
89
|
+
placeholder="Search products…"
|
|
90
|
+
limit={8}
|
|
91
|
+
debounceMs={300}
|
|
92
|
+
onSelect={(result) => {
|
|
93
|
+
window.location.href = result.product.url;
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### `<Sparkle />` — Per-product AI assistant button
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { Sparkle } from '@akropolys/kiku';
|
|
104
|
+
|
|
105
|
+
// Place next to any product on a listing or detail page
|
|
106
|
+
<Sparkle productName="Samsung Galaxy S24" />
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### `<ComparisonMatrix />` — Side-by-side product comparison table
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
import { ComparisonMatrix } from '@akropolys/kiku';
|
|
115
|
+
|
|
116
|
+
// sources come from useKiku() or useSearch()
|
|
117
|
+
<ComparisonMatrix sources={sources} defaultCurrency="KES" />
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
### `<CartBadge />` — Cart item count badge
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
import { CartBadge } from '@akropolys/kiku';
|
|
126
|
+
|
|
127
|
+
<CartBadge className="my-badge" />
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### `<CartDrawer />` — Slide-out cart drawer
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
import { CartDrawer } from '@akropolys/kiku';
|
|
136
|
+
|
|
137
|
+
<CartDrawer trigger={<button>🛒 Cart</button>} theme="dark" />
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### `<CheckoutModal />` — Full checkout modal (M-Pesa + extensible)
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
import { CheckoutModal } from '@akropolys/kiku';
|
|
146
|
+
|
|
147
|
+
<CheckoutModal onClose={() => setOpen(false)} theme="dark" />
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Theming
|
|
153
|
+
|
|
154
|
+
All components accept a `theme` prop. Pass `'light'` | `'dark'` for the built-in modes, or pass an `AkropolysTheme` object for full control:
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
<KikuButton
|
|
158
|
+
theme={{
|
|
159
|
+
primaryColor: '#6d28d9',
|
|
160
|
+
backgroundColor: '#0f0f0f',
|
|
161
|
+
textColor: '#f5f5f5',
|
|
162
|
+
fontFamily: 'Inter, sans-serif',
|
|
163
|
+
borderRadius: '12px',
|
|
164
|
+
}}
|
|
165
|
+
/>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Alternatively, override CSS variables globally in your stylesheet:
|
|
169
|
+
|
|
170
|
+
```css
|
|
171
|
+
:root {
|
|
172
|
+
--hsk-primary: #6d28d9;
|
|
173
|
+
--hsk-bg: #0f0f0f;
|
|
174
|
+
--hsk-text: #f5f5f5;
|
|
175
|
+
--hsk-font: 'Inter', sans-serif;
|
|
176
|
+
--hsk-border-radius: 12px;
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Using the headless SDK instead
|
|
183
|
+
|
|
184
|
+
If you want to build your own UI from scratch, install only the core:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
npm install @akropolys/sdk
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
import { useKiku } from '@akropolys/sdk';
|
|
192
|
+
|
|
193
|
+
const { send, messages, loading, streaming } = useKiku({
|
|
194
|
+
onToken: (token) => appendToMyUI(token),
|
|
195
|
+
onMeta: (meta) => showProducts(meta.sources),
|
|
196
|
+
onDone: (full) => saveToDatabase(full),
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
MIT © Akropolys
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SearchResult, AkropolysTheme, ChatSource, Product } from '@akropolys/sdk';
|
|
3
|
+
|
|
4
|
+
interface SearchBarProps {
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
limit?: number;
|
|
7
|
+
/** Debounce in ms — default 300 for smooth type-ahead */
|
|
8
|
+
debounceMs?: number;
|
|
9
|
+
onSelect?: (result: SearchResult) => void;
|
|
10
|
+
className?: string;
|
|
11
|
+
inputClassName?: string;
|
|
12
|
+
dropdownClassName?: string;
|
|
13
|
+
renderResult?: (result: SearchResult) => React.ReactNode;
|
|
14
|
+
theme?: AkropolysTheme;
|
|
15
|
+
classNames?: {
|
|
16
|
+
root?: string;
|
|
17
|
+
input?: string;
|
|
18
|
+
dropdown?: string;
|
|
19
|
+
row?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
declare function SearchBar({ placeholder, limit, debounceMs, onSelect, className, inputClassName, dropdownClassName, renderResult, theme, classNames, }: SearchBarProps): React.JSX.Element;
|
|
23
|
+
|
|
24
|
+
interface ChatWidgetProps {
|
|
25
|
+
title?: string;
|
|
26
|
+
placeholder?: string;
|
|
27
|
+
emptyStateText?: string;
|
|
28
|
+
emptyStateSuggestions?: string;
|
|
29
|
+
defaultCurrency?: string;
|
|
30
|
+
className?: string;
|
|
31
|
+
theme?: AkropolysTheme;
|
|
32
|
+
classNames?: {
|
|
33
|
+
root?: string;
|
|
34
|
+
header?: string;
|
|
35
|
+
messageBubble?: string;
|
|
36
|
+
input?: string;
|
|
37
|
+
};
|
|
38
|
+
onSelectSource?: (source: ChatSource) => void;
|
|
39
|
+
}
|
|
40
|
+
declare function ChatWidget({ title, placeholder, emptyStateText, emptyStateSuggestions, defaultCurrency, className, theme, classNames, onSelectSource }: ChatWidgetProps): React.JSX.Element;
|
|
41
|
+
|
|
42
|
+
interface KikuButtonProps {
|
|
43
|
+
label?: string;
|
|
44
|
+
title?: string;
|
|
45
|
+
placeholder?: string;
|
|
46
|
+
backdropColor?: string;
|
|
47
|
+
backdropBlur?: string | number;
|
|
48
|
+
className?: string;
|
|
49
|
+
onSelectSource?: (source: ChatSource) => void;
|
|
50
|
+
defaultCurrency?: string;
|
|
51
|
+
chips?: string[];
|
|
52
|
+
theme?: 'light' | 'dark' | AkropolysTheme;
|
|
53
|
+
classNames?: {
|
|
54
|
+
button?: string;
|
|
55
|
+
overlay?: string;
|
|
56
|
+
panel?: string;
|
|
57
|
+
input?: string;
|
|
58
|
+
sendButton?: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
declare function KikuButton({ label, title, placeholder, backdropColor, backdropBlur, className, onSelectSource, defaultCurrency, chips, theme, classNames, }: KikuButtonProps): React.JSX.Element;
|
|
62
|
+
|
|
63
|
+
interface SparkleProps {
|
|
64
|
+
productName: string;
|
|
65
|
+
limit?: number;
|
|
66
|
+
onResult?: (results: SearchResult[]) => void;
|
|
67
|
+
/** Override the backdrop colour (any CSS colour/gradient) */
|
|
68
|
+
backdropColor?: string;
|
|
69
|
+
/** Override backdrop blur — e.g. "8px" or 8 */
|
|
70
|
+
backdropBlur?: string | number;
|
|
71
|
+
/** Extra classes on the trigger button */
|
|
72
|
+
className?: string;
|
|
73
|
+
/** Called when user clicks a result — return false to prevent default navigation */
|
|
74
|
+
onNavigate?: (result: SearchResult) => boolean | void;
|
|
75
|
+
theme?: AkropolysTheme;
|
|
76
|
+
classNames?: {
|
|
77
|
+
button?: string;
|
|
78
|
+
backdrop?: string;
|
|
79
|
+
card?: string;
|
|
80
|
+
item?: string;
|
|
81
|
+
};
|
|
82
|
+
product?: Product;
|
|
83
|
+
}
|
|
84
|
+
declare function Sparkle({ productName, limit, onResult, backdropColor, backdropBlur, className, onNavigate, theme, classNames, product, }: SparkleProps): React.JSX.Element;
|
|
85
|
+
|
|
86
|
+
declare function CartBadge({ className }: {
|
|
87
|
+
className?: string;
|
|
88
|
+
}): React.JSX.Element | null;
|
|
89
|
+
|
|
90
|
+
declare function CartDrawer({ trigger, className, theme }: {
|
|
91
|
+
trigger?: React.ReactNode;
|
|
92
|
+
className?: string;
|
|
93
|
+
theme?: 'light' | 'dark' | AkropolysTheme;
|
|
94
|
+
}): React.JSX.Element;
|
|
95
|
+
|
|
96
|
+
declare function CheckoutModal({ onClose, theme, customStyles, hskThemeAttr }: {
|
|
97
|
+
onClose: () => void;
|
|
98
|
+
theme?: string;
|
|
99
|
+
customStyles?: React.CSSProperties;
|
|
100
|
+
hskThemeAttr?: string;
|
|
101
|
+
}): React.ReactPortal;
|
|
102
|
+
|
|
103
|
+
interface ComparisonMatrixProps {
|
|
104
|
+
sources: ChatSource[];
|
|
105
|
+
defaultCurrency?: string;
|
|
106
|
+
}
|
|
107
|
+
declare function ComparisonMatrix({ sources, defaultCurrency }: ComparisonMatrixProps): React.JSX.Element | null;
|
|
108
|
+
|
|
109
|
+
export { CartBadge, CartDrawer, ChatWidget, type ChatWidgetProps, CheckoutModal, ComparisonMatrix, KikuButton, type KikuButtonProps, ChatWidget as KikuChat, type ChatWidgetProps as KikuChatProps, SearchBar, type SearchBarProps, Sparkle };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SearchResult, AkropolysTheme, ChatSource, Product } from '@akropolys/sdk';
|
|
3
|
+
|
|
4
|
+
interface SearchBarProps {
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
limit?: number;
|
|
7
|
+
/** Debounce in ms — default 300 for smooth type-ahead */
|
|
8
|
+
debounceMs?: number;
|
|
9
|
+
onSelect?: (result: SearchResult) => void;
|
|
10
|
+
className?: string;
|
|
11
|
+
inputClassName?: string;
|
|
12
|
+
dropdownClassName?: string;
|
|
13
|
+
renderResult?: (result: SearchResult) => React.ReactNode;
|
|
14
|
+
theme?: AkropolysTheme;
|
|
15
|
+
classNames?: {
|
|
16
|
+
root?: string;
|
|
17
|
+
input?: string;
|
|
18
|
+
dropdown?: string;
|
|
19
|
+
row?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
declare function SearchBar({ placeholder, limit, debounceMs, onSelect, className, inputClassName, dropdownClassName, renderResult, theme, classNames, }: SearchBarProps): React.JSX.Element;
|
|
23
|
+
|
|
24
|
+
interface ChatWidgetProps {
|
|
25
|
+
title?: string;
|
|
26
|
+
placeholder?: string;
|
|
27
|
+
emptyStateText?: string;
|
|
28
|
+
emptyStateSuggestions?: string;
|
|
29
|
+
defaultCurrency?: string;
|
|
30
|
+
className?: string;
|
|
31
|
+
theme?: AkropolysTheme;
|
|
32
|
+
classNames?: {
|
|
33
|
+
root?: string;
|
|
34
|
+
header?: string;
|
|
35
|
+
messageBubble?: string;
|
|
36
|
+
input?: string;
|
|
37
|
+
};
|
|
38
|
+
onSelectSource?: (source: ChatSource) => void;
|
|
39
|
+
}
|
|
40
|
+
declare function ChatWidget({ title, placeholder, emptyStateText, emptyStateSuggestions, defaultCurrency, className, theme, classNames, onSelectSource }: ChatWidgetProps): React.JSX.Element;
|
|
41
|
+
|
|
42
|
+
interface KikuButtonProps {
|
|
43
|
+
label?: string;
|
|
44
|
+
title?: string;
|
|
45
|
+
placeholder?: string;
|
|
46
|
+
backdropColor?: string;
|
|
47
|
+
backdropBlur?: string | number;
|
|
48
|
+
className?: string;
|
|
49
|
+
onSelectSource?: (source: ChatSource) => void;
|
|
50
|
+
defaultCurrency?: string;
|
|
51
|
+
chips?: string[];
|
|
52
|
+
theme?: 'light' | 'dark' | AkropolysTheme;
|
|
53
|
+
classNames?: {
|
|
54
|
+
button?: string;
|
|
55
|
+
overlay?: string;
|
|
56
|
+
panel?: string;
|
|
57
|
+
input?: string;
|
|
58
|
+
sendButton?: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
declare function KikuButton({ label, title, placeholder, backdropColor, backdropBlur, className, onSelectSource, defaultCurrency, chips, theme, classNames, }: KikuButtonProps): React.JSX.Element;
|
|
62
|
+
|
|
63
|
+
interface SparkleProps {
|
|
64
|
+
productName: string;
|
|
65
|
+
limit?: number;
|
|
66
|
+
onResult?: (results: SearchResult[]) => void;
|
|
67
|
+
/** Override the backdrop colour (any CSS colour/gradient) */
|
|
68
|
+
backdropColor?: string;
|
|
69
|
+
/** Override backdrop blur — e.g. "8px" or 8 */
|
|
70
|
+
backdropBlur?: string | number;
|
|
71
|
+
/** Extra classes on the trigger button */
|
|
72
|
+
className?: string;
|
|
73
|
+
/** Called when user clicks a result — return false to prevent default navigation */
|
|
74
|
+
onNavigate?: (result: SearchResult) => boolean | void;
|
|
75
|
+
theme?: AkropolysTheme;
|
|
76
|
+
classNames?: {
|
|
77
|
+
button?: string;
|
|
78
|
+
backdrop?: string;
|
|
79
|
+
card?: string;
|
|
80
|
+
item?: string;
|
|
81
|
+
};
|
|
82
|
+
product?: Product;
|
|
83
|
+
}
|
|
84
|
+
declare function Sparkle({ productName, limit, onResult, backdropColor, backdropBlur, className, onNavigate, theme, classNames, product, }: SparkleProps): React.JSX.Element;
|
|
85
|
+
|
|
86
|
+
declare function CartBadge({ className }: {
|
|
87
|
+
className?: string;
|
|
88
|
+
}): React.JSX.Element | null;
|
|
89
|
+
|
|
90
|
+
declare function CartDrawer({ trigger, className, theme }: {
|
|
91
|
+
trigger?: React.ReactNode;
|
|
92
|
+
className?: string;
|
|
93
|
+
theme?: 'light' | 'dark' | AkropolysTheme;
|
|
94
|
+
}): React.JSX.Element;
|
|
95
|
+
|
|
96
|
+
declare function CheckoutModal({ onClose, theme, customStyles, hskThemeAttr }: {
|
|
97
|
+
onClose: () => void;
|
|
98
|
+
theme?: string;
|
|
99
|
+
customStyles?: React.CSSProperties;
|
|
100
|
+
hskThemeAttr?: string;
|
|
101
|
+
}): React.ReactPortal;
|
|
102
|
+
|
|
103
|
+
interface ComparisonMatrixProps {
|
|
104
|
+
sources: ChatSource[];
|
|
105
|
+
defaultCurrency?: string;
|
|
106
|
+
}
|
|
107
|
+
declare function ComparisonMatrix({ sources, defaultCurrency }: ComparisonMatrixProps): React.JSX.Element | null;
|
|
108
|
+
|
|
109
|
+
export { CartBadge, CartDrawer, ChatWidget, type ChatWidgetProps, CheckoutModal, ComparisonMatrix, KikuButton, type KikuButtonProps, ChatWidget as KikuChat, type ChatWidgetProps as KikuChatProps, SearchBar, type SearchBarProps, Sparkle };
|