@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 +21 -0
- package/README.md +357 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +357 -0
- package/dist/esm2022/lib/inject-help-panel.mjs +59 -0
- package/dist/esm2022/lib/inject-pillar-tool.mjs +111 -0
- package/dist/esm2022/lib/inject-pillar.mjs +79 -0
- package/dist/esm2022/lib/pillar-panel.component.mjs +80 -0
- package/dist/esm2022/lib/pillar.service.mjs +308 -0
- package/dist/esm2022/lib/types.mjs +5 -0
- package/dist/esm2022/pillar-ai-angular.mjs +5 -0
- package/dist/esm2022/public-api.mjs +67 -0
- package/dist/fesm2022/pillar-ai-angular.mjs +695 -0
- package/dist/fesm2022/pillar-ai-angular.mjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/lib/inject-help-panel.d.ts +34 -0
- package/dist/lib/inject-pillar-tool.d.ts +89 -0
- package/dist/lib/inject-pillar.d.ts +96 -0
- package/dist/lib/pillar-panel.component.d.ts +58 -0
- package/dist/lib/pillar.service.d.ts +126 -0
- package/dist/lib/types.d.ts +119 -0
- package/dist/public-api.d.ts +77 -0
- package/package.json +73 -0
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
|
+
[](https://www.npmjs.com/package/@pillar-ai/angular)
|
|
6
|
+
[](https://www.npmjs.com/package/@pillar-ai/angular)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](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.
|