@pillar-ai/react 0.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 ADDED
@@ -0,0 +1,162 @@
1
+ # @pillar-ai/react
2
+
3
+ React bindings for the Pillar Embedded Help SDK.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @pillar-ai/react
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ Wrap your app with `PillarProvider`:
14
+
15
+ ```tsx
16
+ import { PillarProvider } from '@pillar-ai/react';
17
+
18
+ function App() {
19
+ return (
20
+ <PillarProvider helpCenter="your-help-center" publicKey="pk_live_xxx">
21
+ <MyApp />
22
+ </PillarProvider>
23
+ );
24
+ }
25
+ ```
26
+
27
+ ## Components
28
+
29
+ ### PillarProvider
30
+
31
+ The root provider that initializes the SDK and provides context to child components.
32
+
33
+ ```tsx
34
+ <PillarProvider
35
+ helpCenter="your-help-center"
36
+ publicKey="pk_live_xxx"
37
+ config={{
38
+ panel: { position: 'right' },
39
+ floatingButton: { enabled: true },
40
+ theme: { mode: 'system' },
41
+ }}
42
+ >
43
+ {children}
44
+ </PillarProvider>
45
+ ```
46
+
47
+ ### Tooltip
48
+
49
+ Attach contextual tooltips to any element:
50
+
51
+ ```tsx
52
+ import { Tooltip } from '@pillar-ai/react';
53
+
54
+ <Tooltip tooltipId="welcome-tooltip">
55
+ <button>Hover me for help</button>
56
+ </Tooltip>;
57
+ ```
58
+
59
+ ### PillarPanel
60
+
61
+ For custom panel placement (when using `container: 'manual'`):
62
+
63
+ ```tsx
64
+ import { PillarProvider, PillarPanel } from '@pillar-ai/react';
65
+
66
+ function App() {
67
+ return (
68
+ <PillarProvider
69
+ helpCenter="your-help-center"
70
+ publicKey="pk_live_xxx"
71
+ config={{ panel: { container: 'manual' } }}
72
+ >
73
+ <div className="layout">
74
+ <main>Your content</main>
75
+ <PillarPanel className="sidebar-panel" />
76
+ </div>
77
+ </PillarProvider>
78
+ );
79
+ }
80
+ ```
81
+
82
+ ## Hooks
83
+
84
+ ### usePillar
85
+
86
+ Access the SDK instance and state:
87
+
88
+ ```tsx
89
+ import { usePillar } from '@pillar-ai/react';
90
+
91
+ function MyComponent() {
92
+ const { isReady, isOpen, pillar } = usePillar();
93
+
94
+ if (!isReady) return <div>Loading...</div>;
95
+
96
+ return <div>Panel is {isOpen ? 'open' : 'closed'}</div>;
97
+ }
98
+ ```
99
+
100
+ ### useHelpPanel
101
+
102
+ Control the help panel:
103
+
104
+ ```tsx
105
+ import { useHelpPanel } from '@pillar-ai/react';
106
+
107
+ function HelpButton() {
108
+ const { open, close, toggle, isOpen } = useHelpPanel();
109
+
110
+ return (
111
+ <button onClick={toggle}>{isOpen ? 'Close Help' : 'Get Help'}</button>
112
+ );
113
+ }
114
+ ```
115
+
116
+ ## Type-Safe Actions
117
+
118
+ Define custom actions with full TypeScript support:
119
+
120
+ ```tsx
121
+ import { PillarProvider, usePillar } from '@pillar-ai/react';
122
+ import type { ActionDefinitions } from '@pillar-ai/react';
123
+
124
+ // Define your actions
125
+ const actions = {
126
+ openSettings: {
127
+ type: 'navigate' as const,
128
+ label: 'Open Settings',
129
+ description: 'Navigate to settings page',
130
+ },
131
+ showNotification: {
132
+ type: 'trigger' as const,
133
+ label: 'Show Notification',
134
+ description: 'Display a notification',
135
+ dataSchema: {
136
+ message: { type: 'string' as const, required: true },
137
+ },
138
+ },
139
+ } satisfies ActionDefinitions;
140
+
141
+ function App() {
142
+ return (
143
+ <PillarProvider
144
+ helpCenter="your-help-center"
145
+ publicKey="pk_live_xxx"
146
+ actions={actions}
147
+ onTask={(type, data) => {
148
+ // TypeScript knows the exact shape of data based on type
149
+ if (type === 'showNotification') {
150
+ console.log(data.message); // Typed!
151
+ }
152
+ }}
153
+ >
154
+ <MyApp />
155
+ </PillarProvider>
156
+ );
157
+ }
158
+ ```
159
+
160
+ ## License
161
+
162
+ MIT
@@ -0,0 +1,62 @@
1
+ /**
2
+ * HelpButton Component
3
+ * Pre-styled button to open the help panel
4
+ *
5
+ * Styling follows the dual-class pattern:
6
+ * - Internal class (_pillar-help-btn): Contains default styles
7
+ * - Public class (pillar-help-btn): Empty by default, for user overrides
8
+ *
9
+ * Supports CSS variable customization:
10
+ * - --pillar-btn-primary-bg
11
+ * - --pillar-btn-primary-color
12
+ * - --pillar-btn-secondary-bg
13
+ * - --pillar-btn-secondary-color
14
+ * - --pillar-btn-ghost-color
15
+ * - --pillar-btn-radius
16
+ * - --pillar-btn-font-family
17
+ */
18
+ import { type ButtonHTMLAttributes, type ReactNode } from 'react';
19
+ export interface HelpButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {
20
+ /** Button content - defaults to "Help" */
21
+ children?: ReactNode;
22
+ /** What to open when clicked */
23
+ action?: 'toggle' | 'open' | 'chat' | 'search';
24
+ /** Initial search query (when action is 'search') */
25
+ searchQuery?: string;
26
+ /** Article slug to open (when action is 'open') */
27
+ articleSlug?: string;
28
+ /** Custom click handler (overrides action) */
29
+ onClick?: () => void;
30
+ /** Visual variant */
31
+ variant?: 'primary' | 'secondary' | 'ghost';
32
+ /** Button size */
33
+ size?: 'sm' | 'md' | 'lg';
34
+ }
35
+ /**
36
+ * Pre-styled help button that integrates with Pillar
37
+ *
38
+ * Uses CSS classes for styling with CSS variable support:
39
+ * - Internal classes (_pillar-help-btn-*): Default styles
40
+ * - Public classes (pillar-help-btn-*): For user overrides
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * // Basic usage
45
+ * <HelpButton>Get Help</HelpButton>
46
+ *
47
+ * // Open chat directly
48
+ * <HelpButton action="chat">Ask AI</HelpButton>
49
+ *
50
+ * // Search with query
51
+ * <HelpButton action="search" searchQuery="getting started">
52
+ * Search Help
53
+ * </HelpButton>
54
+ *
55
+ * // Customize via CSS variables
56
+ * // :root { --pillar-btn-primary-bg: #8b5cf6; }
57
+ *
58
+ * // Or via public class overrides
59
+ * // .pillar-help-btn--primary { background: #8b5cf6; }
60
+ * ```
61
+ */
62
+ export declare function HelpButton({ children, action, searchQuery, articleSlug, onClick: customOnClick, variant, size, style, disabled, className, ...props }: HelpButtonProps): JSX.Element;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * PillarPanel Component
3
+ * Renders the Pillar help panel at a custom location in the DOM
4
+ */
5
+ import React, { type CSSProperties, type HTMLAttributes } from 'react';
6
+ export interface PillarPanelProps extends HTMLAttributes<HTMLDivElement> {
7
+ /** Custom class name for the container */
8
+ className?: string;
9
+ /** Custom inline styles for the container */
10
+ style?: CSSProperties;
11
+ }
12
+ /**
13
+ * Renders the Pillar help panel at a custom location in the DOM.
14
+ * Use this when you want to control where the panel is rendered instead of
15
+ * having it automatically appended to document.body.
16
+ *
17
+ * **Important**: When using this component, set `panel.container: 'manual'` in your
18
+ * PillarProvider config to prevent automatic mounting.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * <PillarProvider
23
+ * helpCenter="my-help"
24
+ * publicKey="pk_xxx"
25
+ * config={{ panel: { container: 'manual' } }}
26
+ * >
27
+ * <div className="my-layout">
28
+ * <Sidebar />
29
+ * <PillarPanel className="help-panel-container" />
30
+ * <MainContent />
31
+ * </div>
32
+ * </PillarProvider>
33
+ * ```
34
+ */
35
+ export declare function PillarPanel({ className, style, ...props }: PillarPanelProps): React.ReactElement;
@@ -0,0 +1,118 @@
1
+ /**
2
+ * PillarProvider
3
+ * Context provider that initializes and manages the Pillar SDK
4
+ */
5
+ import { Pillar, type PillarConfig, type PillarEvents, type PillarState, type TaskExecutePayload, type ThemeConfig } from '@pillar-ai/sdk';
6
+ import React, { type ReactNode, type ComponentType } from 'react';
7
+ /**
8
+ * Props passed to custom card components.
9
+ */
10
+ export interface CardComponentProps<T = Record<string, unknown>> {
11
+ /** Data extracted by the AI for this action */
12
+ data: T;
13
+ /** Called when user confirms the action */
14
+ onConfirm: (modifiedData?: Record<string, unknown>) => void;
15
+ /** Called when user cancels the action */
16
+ onCancel: () => void;
17
+ /** Called to report state changes (loading, success, error) */
18
+ onStateChange?: (state: 'loading' | 'success' | 'error', message?: string) => void;
19
+ }
20
+ /**
21
+ * A React component that can be used as a custom card renderer.
22
+ */
23
+ export type CardComponent<T = Record<string, unknown>> = ComponentType<CardComponentProps<T>>;
24
+ export interface PillarContextValue {
25
+ /** The Pillar SDK instance */
26
+ pillar: Pillar | null;
27
+ /** Current SDK state */
28
+ state: PillarState;
29
+ /** Whether the SDK is ready */
30
+ isReady: boolean;
31
+ /** Whether the panel is currently open */
32
+ isPanelOpen: boolean;
33
+ /** Open the help panel */
34
+ open: (options?: {
35
+ view?: string;
36
+ article?: string;
37
+ search?: string;
38
+ focusInput?: boolean;
39
+ }) => void;
40
+ /** Close the help panel */
41
+ close: () => void;
42
+ /** Toggle the help panel */
43
+ toggle: () => void;
44
+ /** Open a specific article */
45
+ openArticle: (slug: string) => void;
46
+ /** Open a specific category */
47
+ openCategory: (slug: string) => Promise<void>;
48
+ /** Perform a search */
49
+ search: (query: string) => void;
50
+ /** Navigate to a specific view */
51
+ navigate: (view: string, params?: Record<string, string>) => void;
52
+ /** Update the panel theme at runtime */
53
+ setTheme: (theme: Partial<ThemeConfig>) => void;
54
+ /** Enable or disable the text selection "Ask AI" popover */
55
+ setTextSelectionEnabled: (enabled: boolean) => void;
56
+ /** Subscribe to SDK events */
57
+ on: <K extends keyof PillarEvents>(event: K, callback: (data: PillarEvents[K]) => void) => () => void;
58
+ }
59
+ export interface PillarProviderProps {
60
+ /** Help center subdomain or identifier */
61
+ helpCenter: string;
62
+ /** Public API key */
63
+ publicKey: string;
64
+ /**
65
+ * Additional SDK configuration
66
+ *
67
+ * Notable options:
68
+ * - `panel.useShadowDOM`: Whether to isolate styles in Shadow DOM (default: false).
69
+ * Set to false to let custom cards inherit your app's CSS (Tailwind, etc.)
70
+ */
71
+ config?: Omit<PillarConfig, 'helpCenter' | 'publicKey'>;
72
+ /**
73
+ * Handler called when a task action is triggered from the chat.
74
+ * Use this to handle AI-suggested actions like opening modals, navigating, etc.
75
+ *
76
+ * @example
77
+ * ```tsx
78
+ * <PillarProvider
79
+ * helpCenter="my-app"
80
+ * publicKey="pk_..."
81
+ * onTask={(task) => {
82
+ * switch (task.name) {
83
+ * case 'invite_team_member':
84
+ * openInviteModal(task.data);
85
+ * break;
86
+ * case 'open_settings':
87
+ * router.push('/settings');
88
+ * break;
89
+ * }
90
+ * }}
91
+ * >
92
+ * ```
93
+ */
94
+ onTask?: (task: TaskExecutePayload) => void;
95
+ /**
96
+ * Custom card components to render for inline_ui type actions.
97
+ * Map card type names to React components that will render the inline UI.
98
+ *
99
+ * @example
100
+ * ```tsx
101
+ * import { InviteMembersCard } from './cards/InviteMembersCard';
102
+ *
103
+ * <PillarProvider
104
+ * helpCenter="my-app"
105
+ * publicKey="pk_..."
106
+ * cards={{
107
+ * invite_members: InviteMembersCard,
108
+ * confirm_delete: ConfirmDeleteCard,
109
+ * }}
110
+ * >
111
+ * ```
112
+ */
113
+ cards?: Record<string, CardComponent>;
114
+ /** Children components */
115
+ children: ReactNode;
116
+ }
117
+ export declare function PillarProvider({ helpCenter, publicKey, config, onTask, cards, children, }: PillarProviderProps): React.ReactElement;
118
+ export declare function usePillarContext(): PillarContextValue;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Tooltip Component
3
+ * Wrapper component that adds tooltip functionality to children
4
+ */
5
+ import React, { type ReactNode, type CSSProperties } from 'react';
6
+ export interface TooltipProps {
7
+ /** Unique tooltip ID that matches a tooltip in your Pillar dashboard */
8
+ tooltipId: string;
9
+ /** Trigger behavior: hover, click, focus, or icon (shows info icon) */
10
+ trigger?: 'hover' | 'click' | 'focus' | 'icon';
11
+ /** Tooltip position relative to the target */
12
+ position?: 'top' | 'bottom' | 'left' | 'right' | 'auto';
13
+ /** Children elements to attach the tooltip to */
14
+ children: ReactNode;
15
+ /** Additional class name for the wrapper */
16
+ className?: string;
17
+ /** Additional inline styles for the wrapper */
18
+ style?: CSSProperties;
19
+ /** Whether the wrapper should be a span (inline) or div (block) */
20
+ inline?: boolean;
21
+ }
22
+ /**
23
+ * Tooltip wrapper component that adds Pillar tooltip functionality to children
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * <Tooltip tooltipId="feature-explanation" trigger="hover">
28
+ * <button>Learn More</button>
29
+ * </Tooltip>
30
+ * ```
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * <Tooltip tooltipId="input-help" trigger="icon">
35
+ * <label>Email Address</label>
36
+ * </Tooltip>
37
+ * ```
38
+ */
39
+ export declare function Tooltip({ tooltipId, trigger, position, children, className, style, inline, }: TooltipProps): React.ReactElement;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * useHelpPanel Hook
3
+ * Panel-specific controls and state
4
+ */
5
+ export interface UseHelpPanelResult {
6
+ /** Whether the panel is currently open */
7
+ isOpen: boolean;
8
+ /** Open the panel */
9
+ open: (options?: {
10
+ view?: string;
11
+ article?: string;
12
+ search?: string;
13
+ }) => void;
14
+ /** Close the panel */
15
+ close: () => void;
16
+ /** Toggle the panel */
17
+ toggle: () => void;
18
+ /** Open a specific article in the panel */
19
+ openArticle: (slug: string) => void;
20
+ /** Open a specific category in the panel */
21
+ openCategory: (slug: string) => Promise<void>;
22
+ /** Open search with a query */
23
+ openSearch: (query?: string) => void;
24
+ /** Open the AI chat */
25
+ openChat: () => void;
26
+ }
27
+ /**
28
+ * Hook for panel-specific controls
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * function HelpButton() {
33
+ * const { isOpen, toggle, openChat } = useHelpPanel();
34
+ *
35
+ * return (
36
+ * <div>
37
+ * <button onClick={toggle}>
38
+ * {isOpen ? 'Close' : 'Help'}
39
+ * </button>
40
+ * <button onClick={openChat}>
41
+ * Ask AI
42
+ * </button>
43
+ * </div>
44
+ * );
45
+ * }
46
+ * ```
47
+ */
48
+ export declare function useHelpPanel(): UseHelpPanelResult;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * usePillar Hook
3
+ * Access Pillar SDK instance and state with optional type-safe onTask
4
+ */
5
+ import type { SyncActionDefinitions, ActionDefinitions, ActionDataType, ActionNames } from '@pillar-ai/sdk';
6
+ import { type PillarContextValue } from '../PillarProvider';
7
+ export type UsePillarResult = PillarContextValue;
8
+ /**
9
+ * Extended result with type-safe onTask method.
10
+ *
11
+ * @template TActions - The action definitions for type inference
12
+ */
13
+ export interface TypedUsePillarResult<TActions extends SyncActionDefinitions | ActionDefinitions> extends Omit<PillarContextValue, 'pillar'> {
14
+ pillar: PillarContextValue['pillar'];
15
+ /**
16
+ * Type-safe task handler registration.
17
+ *
18
+ * @param taskName - The action name (autocompleted from your actions)
19
+ * @param handler - Handler function with typed data parameter
20
+ * @returns Unsubscribe function
21
+ */
22
+ onTask: <TName extends ActionNames<TActions>>(taskName: TName, handler: (data: ActionDataType<TActions, TName>) => void) => () => void;
23
+ }
24
+ /**
25
+ * Hook to access the Pillar SDK instance and state
26
+ *
27
+ * @example Basic usage (untyped)
28
+ * ```tsx
29
+ * function MyComponent() {
30
+ * const { isReady, open, close, isPanelOpen } = usePillar();
31
+ *
32
+ * if (!isReady) return <div>Loading...</div>;
33
+ *
34
+ * return (
35
+ * <button onClick={() => open()}>
36
+ * {isPanelOpen ? 'Close Help' : 'Get Help'}
37
+ * </button>
38
+ * );
39
+ * }
40
+ * ```
41
+ *
42
+ * @example Type-safe onTask with action definitions
43
+ * ```tsx
44
+ * import { actions } from '@/lib/pillar/actions';
45
+ *
46
+ * function MyComponent() {
47
+ * const { pillar, onTask } = usePillar<typeof actions>();
48
+ *
49
+ * useEffect(() => {
50
+ * // TypeScript knows data has { type, url, name }
51
+ * const unsub = onTask('add_new_source', (data) => {
52
+ * console.log(data.url); // ✓ Typed!
53
+ * });
54
+ * return unsub;
55
+ * }, [onTask]);
56
+ * }
57
+ * ```
58
+ */
59
+ export declare function usePillar<TActions extends SyncActionDefinitions | ActionDefinitions = SyncActionDefinitions>(): TypedUsePillarResult<TActions>;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @pillar-ai/react - React bindings for Pillar Embedded Help SDK
3
+ *
4
+ * @example
5
+ * ```tsx
6
+ * import { PillarProvider, Tooltip, PillarPanel, usePillar, useHelpPanel } from '@pillar-ai/react';
7
+ *
8
+ * function App() {
9
+ * return (
10
+ * <PillarProvider helpCenter="your-help-center" publicKey="pk_live_xxx">
11
+ * <MyApp />
12
+ * </PillarProvider>
13
+ * );
14
+ * }
15
+ *
16
+ * function MyApp() {
17
+ * const { isReady } = usePillar();
18
+ * const { toggle } = useHelpPanel();
19
+ *
20
+ * return (
21
+ * <div>
22
+ * <Tooltip tooltipId="welcome-tooltip">
23
+ * <h1>Welcome!</h1>
24
+ * </Tooltip>
25
+ * <button onClick={toggle}>Get Help</button>
26
+ * </div>
27
+ * );
28
+ * }
29
+ *
30
+ * // Custom panel placement example:
31
+ * function AppWithCustomPanel() {
32
+ * return (
33
+ * <PillarProvider
34
+ * helpCenter="your-help-center"
35
+ * publicKey="pk_live_xxx"
36
+ * config={{ panel: { container: 'manual' } }}
37
+ * >
38
+ * <div className="layout">
39
+ * <PillarPanel className="custom-panel" />
40
+ * <main>Your content</main>
41
+ * </div>
42
+ * </PillarProvider>
43
+ * );
44
+ * }
45
+ * ```
46
+ */
47
+ export { PillarProvider, usePillarContext, type PillarContextValue, type PillarProviderProps, type CardComponentProps, type CardComponent, } from './PillarProvider';
48
+ export { PillarPanel, type PillarPanelProps } from './PillarPanel';
49
+ export { Tooltip, type TooltipProps } from './Tooltip';
50
+ export { useHelpPanel, type UseHelpPanelResult } from './hooks/useHelpPanel';
51
+ export { usePillar, type UsePillarResult, type TypedUsePillarResult } from './hooks/usePillar';
52
+ export type { FloatingButtonConfig, PanelConfig, PillarConfig, PillarEvents, PillarState, ResolvedConfig, ResolvedThemeConfig, TaskExecutePayload, TextSelectionConfig, ThemeColors, ThemeConfig, ThemeMode, TooltipsConfig, CardCallbacks, CardRenderer, SidebarTabConfig, ActionDefinitions, SyncActionDefinitions, ActionDataType, ActionNames, } from '@pillar-ai/sdk';