@pillar-ai/angular 0.1.11

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Pillar, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,357 @@
1
+ # @pillar-ai/angular
2
+
3
+ Angular SDK for the [Pillar](https://trypillar.com) open-source AI copilot — embed a product assistant in your Angular app that executes tasks, not just answers questions. [GitHub](https://github.com/pillarhq/pillar) · [Docs](https://trypillar.com/docs)
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@pillar-ai/angular)](https://www.npmjs.com/package/@pillar-ai/angular)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@pillar-ai/angular)](https://www.npmjs.com/package/@pillar-ai/angular)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue)](https://www.typescriptlang.org/)
9
+
10
+ ## What is Pillar?
11
+
12
+ Pillar is a product copilot for SaaS and web applications. Users say what they want, and Pillar uses your UI to make it happen — navigating pages, pre-filling forms, and calling your APIs.
13
+
14
+ For example, a user could ask:
15
+
16
+ > "Close the Walmart deal as won in Salesforce and notify implementation"
17
+
18
+ > "Create a P1 bug in Linear for the checkout crash and add it to this sprint"
19
+
20
+ > "How do I set up a webhook in Stripe?"
21
+
22
+ Pillar understands the intent, builds a multi-step plan, and executes it client-side with the user's session.
23
+
24
+ ## Requirements
25
+
26
+ - Angular 17.0.0 or higher
27
+ - `@pillar-ai/sdk` (installed automatically as a dependency)
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ npm install @pillar-ai/angular
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ ### 1. Initialize Pillar in your app config
38
+
39
+ ```typescript
40
+ // app.config.ts
41
+ import { ApplicationConfig, APP_INITIALIZER, inject } from '@angular/core';
42
+ import { PillarService } from '@pillar-ai/angular';
43
+
44
+ function initPillar() {
45
+ const pillar = inject(PillarService);
46
+ return () => pillar.init({ productKey: 'your-product-key' });
47
+ }
48
+
49
+ export const appConfig: ApplicationConfig = {
50
+ providers: [
51
+ { provide: APP_INITIALIZER, useFactory: initPillar, multi: true },
52
+ ],
53
+ };
54
+ ```
55
+
56
+ ### 2. Use Pillar in your components
57
+
58
+ ```typescript
59
+ // help-button.component.ts
60
+ import { Component } from '@angular/core';
61
+ import { injectPillar } from '@pillar-ai/angular';
62
+
63
+ @Component({
64
+ selector: 'app-help-button',
65
+ standalone: true,
66
+ template: `
67
+ <button (click)="toggle()">
68
+ {{ isPanelOpen() ? 'Close Help' : 'Get Help' }}
69
+ </button>
70
+ `,
71
+ })
72
+ export class HelpButtonComponent {
73
+ private pillar = injectPillar();
74
+ isPanelOpen = this.pillar.isPanelOpen;
75
+ toggle = this.pillar.toggle;
76
+ }
77
+ ```
78
+
79
+ ## API Reference
80
+
81
+ ### PillarService
82
+
83
+ Injectable service that manages the Pillar SDK lifecycle.
84
+
85
+ ```typescript
86
+ import { PillarService } from '@pillar-ai/angular';
87
+
88
+ @Component({...})
89
+ export class MyComponent {
90
+ constructor(private pillarService: PillarService) {}
91
+ }
92
+ ```
93
+
94
+ #### Methods
95
+
96
+ | Method | Description |
97
+ |--------|-------------|
98
+ | `init(config)` | Initialize the SDK with your product key |
99
+ | `open(options?)` | Open the help panel |
100
+ | `close()` | Close the help panel |
101
+ | `toggle()` | Toggle the help panel |
102
+ | `openArticle(slug)` | Open a specific article |
103
+ | `openCategory(slug)` | Navigate to a category |
104
+ | `search(query)` | Open search with a query |
105
+ | `navigate(view, params?)` | Navigate to a specific view |
106
+ | `setTheme(theme)` | Update the panel theme |
107
+ | `setTextSelectionEnabled(enabled)` | Toggle text selection popover |
108
+ | `on(event, callback)` | Subscribe to SDK events |
109
+ | `onTask(taskName, handler)` | Register a task handler |
110
+
111
+ #### Signals
112
+
113
+ | Signal | Type | Description |
114
+ |--------|------|-------------|
115
+ | `state` | `WritableSignal<PillarState>` | Current SDK state |
116
+ | `isReady` | `Signal<boolean>` | Whether SDK is ready |
117
+ | `isPanelOpen` | `WritableSignal<boolean>` | Whether panel is open |
118
+
119
+ ### injectPillar()
120
+
121
+ Angular injection function for accessing the Pillar SDK with full functionality.
122
+
123
+ ```typescript
124
+ import { injectPillar } from '@pillar-ai/angular';
125
+
126
+ @Component({...})
127
+ export class MyComponent {
128
+ private pillar = injectPillar();
129
+
130
+ handleHelp() {
131
+ this.pillar.open({ view: 'chat' });
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### injectHelpPanel()
137
+
138
+ Simplified injection function focused on panel controls.
139
+
140
+ ```typescript
141
+ import { injectHelpPanel } from '@pillar-ai/angular';
142
+
143
+ @Component({...})
144
+ export class HelpMenuComponent {
145
+ private panel = injectHelpPanel();
146
+
147
+ isOpen = this.panel.isOpen;
148
+ toggle = this.panel.toggle;
149
+ openChat = this.panel.openChat;
150
+ }
151
+ ```
152
+
153
+ ### PillarPanelComponent
154
+
155
+ Standalone component for custom panel placement.
156
+
157
+ ```typescript
158
+ import { PillarPanelComponent } from '@pillar-ai/angular';
159
+
160
+ @Component({
161
+ selector: 'app-layout',
162
+ standalone: true,
163
+ imports: [PillarPanelComponent],
164
+ template: `
165
+ <div class="layout">
166
+ <pillar-panel class="help-panel" />
167
+ <main>
168
+ <router-outlet />
169
+ </main>
170
+ </div>
171
+ `,
172
+ })
173
+ export class LayoutComponent {}
174
+ ```
175
+
176
+ **Important**: When using `PillarPanelComponent`, set `panel.container: 'manual'` in your config:
177
+
178
+ ```typescript
179
+ pillar.init({
180
+ productKey: 'your-product-key',
181
+ config: { panel: { container: 'manual' } }
182
+ });
183
+ ```
184
+
185
+ ## Advanced Usage
186
+
187
+ ### Type-Safe Task Handlers
188
+
189
+ Define your actions and get full TypeScript support:
190
+
191
+ ```typescript
192
+ // lib/pillar/actions.ts
193
+ import { defineActions } from '@pillar-ai/sdk';
194
+
195
+ export const actions = defineActions({
196
+ invite_member: {
197
+ description: 'Invite a team member',
198
+ data: {
199
+ email: { type: 'string', description: 'Email address' },
200
+ role: { type: 'string', description: 'Member role' },
201
+ },
202
+ },
203
+ });
204
+ ```
205
+
206
+ ```typescript
207
+ // my.component.ts
208
+ import { Component, OnInit, OnDestroy } from '@angular/core';
209
+ import { injectPillar } from '@pillar-ai/angular';
210
+ import { actions } from './lib/pillar/actions';
211
+
212
+ @Component({...})
213
+ export class MyComponent implements OnInit, OnDestroy {
214
+ private pillar = injectPillar<typeof actions>();
215
+ private unsubscribe?: () => void;
216
+
217
+ ngOnInit() {
218
+ // TypeScript knows the exact shape of data
219
+ this.unsubscribe = this.pillar.onTask('invite_member', (data) => {
220
+ console.log(data.email); // ✓ Typed as string
221
+ console.log(data.role); // ✓ Typed as string
222
+ });
223
+ }
224
+
225
+ ngOnDestroy() {
226
+ this.unsubscribe?.();
227
+ }
228
+ }
229
+ ```
230
+
231
+ ### Custom Card Components
232
+
233
+ Render custom Angular components for inline UI actions:
234
+
235
+ ```typescript
236
+ // invite-card.component.ts
237
+ import { Component, input } from '@angular/core';
238
+ import type { CardComponentProps } from '@pillar-ai/angular';
239
+
240
+ @Component({
241
+ selector: 'app-invite-card',
242
+ standalone: true,
243
+ template: `
244
+ <div class="invite-card">
245
+ <h3>Invite Team Members</h3>
246
+ <input [(ngModel)]="email" placeholder="Email address" />
247
+ <button (click)="confirm()">Send Invite</button>
248
+ <button (click)="cancel()">Cancel</button>
249
+ </div>
250
+ `,
251
+ })
252
+ export class InviteCardComponent implements CardComponentProps {
253
+ data = input.required<Record<string, unknown>>();
254
+ onConfirm = input.required<(data?: Record<string, unknown>) => void>();
255
+ onCancel = input.required<() => void>();
256
+ onStateChange = input<(state: 'loading' | 'success' | 'error', message?: string) => void>();
257
+
258
+ email = '';
259
+
260
+ confirm() {
261
+ this.onConfirm()({ email: this.email });
262
+ }
263
+
264
+ cancel() {
265
+ this.onCancel()();
266
+ }
267
+ }
268
+ ```
269
+
270
+ ```typescript
271
+ // app.config.ts
272
+ pillar.init({
273
+ productKey: 'your-product-key',
274
+ cards: {
275
+ invite_member: InviteCardComponent,
276
+ },
277
+ });
278
+ ```
279
+
280
+ ### Theme Synchronization
281
+
282
+ Sync Pillar's theme with your app's dark mode:
283
+
284
+ ```typescript
285
+ @Component({...})
286
+ export class ThemeToggleComponent {
287
+ private pillar = injectPillar();
288
+
289
+ toggleDarkMode(isDark: boolean) {
290
+ this.pillar.setTheme({ mode: isDark ? 'dark' : 'light' });
291
+ }
292
+ }
293
+ ```
294
+
295
+ ### Subscribe to Events
296
+
297
+ ```typescript
298
+ @Component({...})
299
+ export class AnalyticsComponent implements OnInit, OnDestroy {
300
+ private pillar = injectPillar();
301
+ private unsubscribes: (() => void)[] = [];
302
+
303
+ ngOnInit() {
304
+ this.unsubscribes.push(
305
+ this.pillar.on('panel:open', () => {
306
+ analytics.track('help_panel_opened');
307
+ }),
308
+ this.pillar.on('task:execute', (task) => {
309
+ analytics.track('task_executed', { name: task.name });
310
+ })
311
+ );
312
+ }
313
+
314
+ ngOnDestroy() {
315
+ this.unsubscribes.forEach(unsub => unsub());
316
+ }
317
+ }
318
+ ```
319
+
320
+ ## Configuration Options
321
+
322
+ ```typescript
323
+ interface PillarInitConfig {
324
+ /** Your product key from app.trypillar.com */
325
+ productKey: string;
326
+
327
+ /** Additional SDK configuration */
328
+ config?: {
329
+ panel?: {
330
+ /** Panel placement: 'auto' | 'manual' */
331
+ container?: string;
332
+ /** Use Shadow DOM for style isolation */
333
+ useShadowDOM?: boolean;
334
+ };
335
+ theme?: {
336
+ /** Theme mode: 'light' | 'dark' | 'auto' */
337
+ mode?: string;
338
+ /** Custom colors */
339
+ colors?: {
340
+ primary?: string;
341
+ // ... other color options
342
+ };
343
+ };
344
+ // ... other options
345
+ };
346
+
347
+ /** Global task handler */
348
+ onTask?: (task: TaskExecutePayload) => void;
349
+
350
+ /** Custom card components */
351
+ cards?: Record<string, Type<any>>;
352
+ }
353
+ ```
354
+
355
+ ## License
356
+
357
+ MIT
package/dist/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Pillar, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.