@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 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
@@ -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 };
@@ -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 };