@ewjdev/anyclick-react 0.1.0 → 1.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 +123 -19
- package/dist/index.d.mts +172 -12
- package/dist/index.d.ts +172 -12
- package/dist/index.js +859 -289
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +852 -288
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ npm install @ewjdev/anyclick-react
|
|
|
25
25
|
```tsx
|
|
26
26
|
'use client';
|
|
27
27
|
|
|
28
|
-
import {
|
|
28
|
+
import { AnyclickProvider } from '@ewjdev/anyclick-react';
|
|
29
29
|
import { createHttpAdapter } from '@ewjdev/anyclick-github';
|
|
30
30
|
|
|
31
31
|
const adapter = createHttpAdapter({
|
|
@@ -34,9 +34,9 @@ const adapter = createHttpAdapter({
|
|
|
34
34
|
|
|
35
35
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
36
36
|
return (
|
|
37
|
-
<
|
|
37
|
+
<AnyclickProvider adapter={adapter}>
|
|
38
38
|
{children}
|
|
39
|
-
</
|
|
39
|
+
</AnyclickProvider>
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
42
|
```
|
|
@@ -50,6 +50,8 @@ That's it! Users can now right-click any element to submit feedback.
|
|
|
50
50
|
- 📸 **Screenshot Capture** - Automatic screenshots of target, container, and page
|
|
51
51
|
- 🔒 **Role-Based Menu Items** - Show different options based on user roles
|
|
52
52
|
- 📱 **Submenus** - Organize menu items with nested submenus
|
|
53
|
+
- 🎯 **Scoped Providers** - Limit feedback capture to specific components
|
|
54
|
+
- 🎨 **Nested Theming** - Override themes for specific sections of your app
|
|
53
55
|
|
|
54
56
|
## Props
|
|
55
57
|
|
|
@@ -58,12 +60,93 @@ That's it! Users can now right-click any element to submit feedback.
|
|
|
58
60
|
| `adapter` | `FeedbackAdapter` | Required. The adapter for submitting feedback |
|
|
59
61
|
| `menuItems` | `FeedbackMenuItem[]` | Custom menu items |
|
|
60
62
|
| `metadata` | `Record<string, unknown>` | Additional data included with every submission |
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
+
| `theme` | `AnyclickTheme \| null` | Theme configuration (inherits from parent) |
|
|
64
|
+
| `scoped` | `boolean` | Limit capture to this provider's children only |
|
|
63
65
|
| `disabled` | `boolean` | Disable feedback capture |
|
|
64
66
|
| `onSubmitSuccess` | `(payload) => void` | Success callback |
|
|
65
67
|
| `onSubmitError` | `(error, payload) => void` | Error callback |
|
|
66
68
|
|
|
69
|
+
## Scoped Providers
|
|
70
|
+
|
|
71
|
+
Limit feedback capture to specific sections of your app:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import { AnyclickProvider } from '@ewjdev/anyclick-react';
|
|
75
|
+
|
|
76
|
+
function App() {
|
|
77
|
+
return (
|
|
78
|
+
<AnyclickProvider adapter={globalAdapter}>
|
|
79
|
+
{/* Global feedback works everywhere */}
|
|
80
|
+
<Header />
|
|
81
|
+
|
|
82
|
+
{/* Scoped provider - separate configuration */}
|
|
83
|
+
<AnyclickProvider
|
|
84
|
+
adapter={dashboardAdapter}
|
|
85
|
+
scoped
|
|
86
|
+
menuItems={dashboardMenuItems}
|
|
87
|
+
>
|
|
88
|
+
<Dashboard />
|
|
89
|
+
</AnyclickProvider>
|
|
90
|
+
|
|
91
|
+
<Footer />
|
|
92
|
+
</AnyclickProvider>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Nested Theming
|
|
98
|
+
|
|
99
|
+
Override themes for specific sections:
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { AnyclickProvider } from '@ewjdev/anyclick-react';
|
|
103
|
+
|
|
104
|
+
function App() {
|
|
105
|
+
return (
|
|
106
|
+
<AnyclickProvider
|
|
107
|
+
adapter={adapter}
|
|
108
|
+
theme={{
|
|
109
|
+
highlightConfig: {
|
|
110
|
+
colors: { targetColor: '#3b82f6' }
|
|
111
|
+
}
|
|
112
|
+
}}
|
|
113
|
+
>
|
|
114
|
+
{/* Uses blue highlights */}
|
|
115
|
+
<MainContent />
|
|
116
|
+
|
|
117
|
+
{/* Uses red highlights (overrides parent) */}
|
|
118
|
+
<AnyclickProvider
|
|
119
|
+
scoped
|
|
120
|
+
theme={{
|
|
121
|
+
highlightConfig: {
|
|
122
|
+
colors: { targetColor: '#ef4444' }
|
|
123
|
+
}
|
|
124
|
+
}}
|
|
125
|
+
>
|
|
126
|
+
<WarningSection />
|
|
127
|
+
</AnyclickProvider>
|
|
128
|
+
|
|
129
|
+
{/* Disable anyclick for this section */}
|
|
130
|
+
<AnyclickProvider scoped theme={{ disabled: true }}>
|
|
131
|
+
<SensitiveArea />
|
|
132
|
+
</AnyclickProvider>
|
|
133
|
+
</AnyclickProvider>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Theme Configuration
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
interface AnyclickTheme {
|
|
142
|
+
menuStyle?: CSSProperties;
|
|
143
|
+
menuClassName?: string;
|
|
144
|
+
highlightConfig?: HighlightConfig;
|
|
145
|
+
screenshotConfig?: ScreenshotConfig;
|
|
146
|
+
disabled?: boolean; // Disable anyclick in this subtree
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
67
150
|
## Custom Menu Items
|
|
68
151
|
|
|
69
152
|
```tsx
|
|
@@ -90,9 +173,9 @@ const menuItems = [
|
|
|
90
173
|
},
|
|
91
174
|
];
|
|
92
175
|
|
|
93
|
-
<
|
|
176
|
+
<AnyclickProvider adapter={adapter} menuItems={menuItems}>
|
|
94
177
|
{children}
|
|
95
|
-
</
|
|
178
|
+
</AnyclickProvider>
|
|
96
179
|
```
|
|
97
180
|
|
|
98
181
|
## Role-Based Filtering
|
|
@@ -112,30 +195,39 @@ const menuItems = filterMenuItemsByRole(allMenuItems, userContext);
|
|
|
112
195
|
## Highlight Configuration
|
|
113
196
|
|
|
114
197
|
```tsx
|
|
115
|
-
<
|
|
198
|
+
<AnyclickProvider
|
|
116
199
|
adapter={adapter}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
200
|
+
theme={{
|
|
201
|
+
highlightConfig: {
|
|
202
|
+
enabled: true,
|
|
203
|
+
colors: {
|
|
204
|
+
targetColor: '#3b82f6',
|
|
205
|
+
containerColor: '#8b5cf6',
|
|
206
|
+
},
|
|
207
|
+
containerSelectors: ['[data-component]', '.card'],
|
|
122
208
|
},
|
|
123
|
-
containerSelectors: ['[data-component]', '.card'],
|
|
124
209
|
}}
|
|
125
210
|
>
|
|
126
211
|
{children}
|
|
127
|
-
</
|
|
212
|
+
</AnyclickProvider>
|
|
128
213
|
```
|
|
129
214
|
|
|
130
|
-
##
|
|
215
|
+
## useAnyclick Hook
|
|
131
216
|
|
|
132
|
-
Access
|
|
217
|
+
Access anyclick context from child components:
|
|
133
218
|
|
|
134
219
|
```tsx
|
|
135
|
-
import {
|
|
220
|
+
import { useAnyclick } from '@ewjdev/anyclick-react';
|
|
136
221
|
|
|
137
222
|
function MyComponent() {
|
|
138
|
-
const {
|
|
223
|
+
const {
|
|
224
|
+
isSubmitting,
|
|
225
|
+
openMenu,
|
|
226
|
+
closeMenu,
|
|
227
|
+
theme,
|
|
228
|
+
scoped,
|
|
229
|
+
providerId,
|
|
230
|
+
} = useAnyclick();
|
|
139
231
|
|
|
140
232
|
// Open menu programmatically
|
|
141
233
|
const handleClick = (event) => {
|
|
@@ -146,6 +238,18 @@ function MyComponent() {
|
|
|
146
238
|
}
|
|
147
239
|
```
|
|
148
240
|
|
|
241
|
+
## Migration from FeedbackProvider
|
|
242
|
+
|
|
243
|
+
The `FeedbackProvider` component has been renamed to `AnyclickProvider`. The old name is still exported for backward compatibility but is deprecated:
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
// Old (deprecated)
|
|
247
|
+
import { FeedbackProvider, useFeedback } from '@ewjdev/anyclick-react';
|
|
248
|
+
|
|
249
|
+
// New (recommended)
|
|
250
|
+
import { AnyclickProvider, useAnyclick } from '@ewjdev/anyclick-react';
|
|
251
|
+
```
|
|
252
|
+
|
|
149
253
|
## Documentation
|
|
150
254
|
|
|
151
255
|
For full documentation, visit [anyclick.ewj.dev/docs/react](https://anyclick.ewj.dev/docs/react)
|
package/dist/index.d.mts
CHANGED
|
@@ -3,7 +3,24 @@ import { FeedbackAdapter, FeedbackType, FeedbackPayload, ScreenshotConfig, Scree
|
|
|
3
3
|
export { DEFAULT_SCREENSHOT_CONFIG, DEFAULT_SENSITIVE_SELECTORS, ElementContext, FeedbackAdapter, FeedbackPayload, FeedbackType, PageContext, ScreenshotCapture, ScreenshotCaptureMode, ScreenshotConfig, ScreenshotData, captureAllScreenshots, captureScreenshot, estimateTotalSize, formatBytes, isScreenshotSupported } from '@ewjdev/anyclick-core';
|
|
4
4
|
import * as react from 'react';
|
|
5
5
|
import { ReactNode, CSSProperties } from 'react';
|
|
6
|
+
import * as zustand from 'zustand';
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Theme configuration for AnyclickProvider
|
|
10
|
+
* Supports nested theming with inheritance
|
|
11
|
+
*/
|
|
12
|
+
interface AnyclickTheme {
|
|
13
|
+
/** Custom styles for the context menu */
|
|
14
|
+
menuStyle?: CSSProperties;
|
|
15
|
+
/** Custom class name for the context menu */
|
|
16
|
+
menuClassName?: string;
|
|
17
|
+
/** Configuration for element highlighting */
|
|
18
|
+
highlightConfig?: HighlightConfig;
|
|
19
|
+
/** Configuration for screenshot capture */
|
|
20
|
+
screenshotConfig?: ScreenshotConfig;
|
|
21
|
+
/** Whether anyclick functionality is disabled in this theme */
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
}
|
|
7
24
|
/**
|
|
8
25
|
* Configuration for highlight colors
|
|
9
26
|
*/
|
|
@@ -63,9 +80,9 @@ interface FeedbackUserContext {
|
|
|
63
80
|
*/
|
|
64
81
|
declare function filterMenuItemsByRole(items: FeedbackMenuItem[], userContext?: FeedbackUserContext): FeedbackMenuItem[];
|
|
65
82
|
/**
|
|
66
|
-
* Props for the
|
|
83
|
+
* Props for the AnyclickProvider component
|
|
67
84
|
*/
|
|
68
|
-
interface
|
|
85
|
+
interface AnyclickProviderProps {
|
|
69
86
|
/** The adapter to use for submitting feedback */
|
|
70
87
|
adapter: FeedbackAdapter;
|
|
71
88
|
/** Child components */
|
|
@@ -103,11 +120,27 @@ interface FeedbackProviderProps {
|
|
|
103
120
|
highlightConfig?: HighlightConfig;
|
|
104
121
|
/** Configuration for screenshot capture */
|
|
105
122
|
screenshotConfig?: ScreenshotConfig;
|
|
123
|
+
/**
|
|
124
|
+
* Whether to scope this provider to its children only.
|
|
125
|
+
* When true, events will only be captured for elements within this provider's subtree.
|
|
126
|
+
* When false (default), events are captured for the entire document.
|
|
127
|
+
*/
|
|
128
|
+
scoped?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Theme configuration for this provider.
|
|
131
|
+
* Themes are inherited from parent providers and merged (child overrides parent).
|
|
132
|
+
* Set to null or { disabled: true } to disable anyclick in this subtree.
|
|
133
|
+
*/
|
|
134
|
+
theme?: AnyclickTheme | null;
|
|
106
135
|
}
|
|
107
136
|
/**
|
|
108
|
-
*
|
|
137
|
+
* @deprecated Use AnyclickProviderProps instead
|
|
138
|
+
*/
|
|
139
|
+
type FeedbackProviderProps = AnyclickProviderProps;
|
|
140
|
+
/**
|
|
141
|
+
* Context value exposed by AnyclickProvider
|
|
109
142
|
*/
|
|
110
|
-
interface
|
|
143
|
+
interface AnyclickContextValue {
|
|
111
144
|
/** Whether feedback is currently enabled */
|
|
112
145
|
isEnabled: boolean;
|
|
113
146
|
/** Whether a submission is in progress */
|
|
@@ -121,7 +154,17 @@ interface FeedbackContextValue {
|
|
|
121
154
|
}) => void;
|
|
122
155
|
/** Close the feedback menu */
|
|
123
156
|
closeMenu: () => void;
|
|
157
|
+
/** The current merged theme (inherited from ancestors) */
|
|
158
|
+
theme: AnyclickTheme;
|
|
159
|
+
/** Whether this provider is scoped */
|
|
160
|
+
scoped: boolean;
|
|
161
|
+
/** The provider's unique ID */
|
|
162
|
+
providerId: string;
|
|
124
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* @deprecated Use AnyclickContextValue instead
|
|
166
|
+
*/
|
|
167
|
+
type FeedbackContextValue = AnyclickContextValue;
|
|
125
168
|
/**
|
|
126
169
|
* Props for the context menu component
|
|
127
170
|
*/
|
|
@@ -173,9 +216,14 @@ interface ScreenshotPreviewProps {
|
|
|
173
216
|
}
|
|
174
217
|
|
|
175
218
|
/**
|
|
176
|
-
*
|
|
219
|
+
* AnyclickProvider component - wraps your app to enable feedback capture
|
|
220
|
+
* Supports scoped providers and nested theming
|
|
221
|
+
*/
|
|
222
|
+
declare function AnyclickProvider({ adapter, children, targetFilter, menuItems, maxInnerTextLength, maxOuterHTMLLength, maxAncestors, cooldownMs, stripAttributes, metadata, onSubmitSuccess, onSubmitError, menuStyle, menuClassName, disabled, highlightConfig, screenshotConfig, scoped, theme, }: AnyclickProviderProps): react_jsx_runtime.JSX.Element;
|
|
223
|
+
/**
|
|
224
|
+
* @deprecated Use AnyclickProvider instead
|
|
177
225
|
*/
|
|
178
|
-
declare
|
|
226
|
+
declare const FeedbackProvider: typeof AnyclickProvider;
|
|
179
227
|
|
|
180
228
|
/**
|
|
181
229
|
* Context menu component for selecting feedback type
|
|
@@ -188,15 +236,127 @@ declare function ContextMenu({ visible, position, targetElement, containerElemen
|
|
|
188
236
|
declare function ScreenshotPreview({ screenshots, isLoading, onConfirm, onCancel, onRetake, isSubmitting, }: ScreenshotPreviewProps): react_jsx_runtime.JSX.Element;
|
|
189
237
|
|
|
190
238
|
/**
|
|
191
|
-
* React context for
|
|
239
|
+
* React context for anyclick functionality
|
|
240
|
+
*/
|
|
241
|
+
declare const AnyclickContext: react.Context<AnyclickContextValue | null>;
|
|
242
|
+
/**
|
|
243
|
+
* @deprecated Use AnyclickContext instead
|
|
244
|
+
*/
|
|
245
|
+
declare const FeedbackContext: react.Context<AnyclickContextValue | null>;
|
|
246
|
+
/**
|
|
247
|
+
* Hook to access anyclick context
|
|
248
|
+
* @throws Error if used outside of AnyclickProvider
|
|
249
|
+
*/
|
|
250
|
+
declare function useAnyclick(): AnyclickContextValue;
|
|
251
|
+
/**
|
|
252
|
+
* @deprecated Use useAnyclick instead
|
|
253
|
+
*/
|
|
254
|
+
declare function useFeedback(): AnyclickContextValue;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Registered provider instance
|
|
258
|
+
*/
|
|
259
|
+
interface ProviderInstance {
|
|
260
|
+
/** Unique identifier for this provider instance */
|
|
261
|
+
id: string;
|
|
262
|
+
/** Reference to the provider's container element (null if not scoped) */
|
|
263
|
+
containerRef: React.RefObject<Element | null>;
|
|
264
|
+
/** Whether this provider is scoped to its container */
|
|
265
|
+
scoped: boolean;
|
|
266
|
+
/** The provider's theme configuration */
|
|
267
|
+
theme: AnyclickTheme | null;
|
|
268
|
+
/** Whether this provider is disabled */
|
|
269
|
+
disabled: boolean;
|
|
270
|
+
/** Parent provider ID (if nested) */
|
|
271
|
+
parentId: string | null;
|
|
272
|
+
/** Depth in the provider hierarchy (0 = root) */
|
|
273
|
+
depth: number;
|
|
274
|
+
/** Handler to call when an event occurs in this provider's scope */
|
|
275
|
+
onContextMenu?: (event: MouseEvent, element: Element) => void;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Provider registry store state
|
|
279
|
+
*/
|
|
280
|
+
interface ProviderStore {
|
|
281
|
+
/** Map of provider ID to provider instance */
|
|
282
|
+
providers: Map<string, ProviderInstance>;
|
|
283
|
+
/**
|
|
284
|
+
* Register a new provider
|
|
285
|
+
*/
|
|
286
|
+
registerProvider: (provider: ProviderInstance) => void;
|
|
287
|
+
/**
|
|
288
|
+
* Unregister a provider
|
|
289
|
+
*/
|
|
290
|
+
unregisterProvider: (id: string) => void;
|
|
291
|
+
/**
|
|
292
|
+
* Update a provider's configuration
|
|
293
|
+
*/
|
|
294
|
+
updateProvider: (id: string, updates: Partial<ProviderInstance>) => void;
|
|
295
|
+
/**
|
|
296
|
+
* Find all providers that contain a given element, sorted by depth (nearest first)
|
|
297
|
+
*/
|
|
298
|
+
findProvidersForElement: (element: Element) => ProviderInstance[];
|
|
299
|
+
/**
|
|
300
|
+
* Find the nearest parent provider for a given container
|
|
301
|
+
*/
|
|
302
|
+
findParentProvider: (container: Element | null, excludeId?: string) => ProviderInstance | null;
|
|
303
|
+
/**
|
|
304
|
+
* Get merged theme for a provider (includes inherited parent themes)
|
|
305
|
+
*/
|
|
306
|
+
getMergedTheme: (providerId: string) => AnyclickTheme;
|
|
307
|
+
/**
|
|
308
|
+
* Check if any ancestor provider has disabled anyclick
|
|
309
|
+
*/
|
|
310
|
+
isDisabledByAncestor: (providerId: string) => boolean;
|
|
311
|
+
/**
|
|
312
|
+
* Check if an element is inside a disabled scoped provider's container
|
|
313
|
+
* This is used to prevent the global provider from handling events
|
|
314
|
+
* in areas where a disabled scoped provider should block them
|
|
315
|
+
*/
|
|
316
|
+
isElementInDisabledScope: (element: Element) => boolean;
|
|
317
|
+
}
|
|
318
|
+
declare function generateProviderId(): string;
|
|
319
|
+
/**
|
|
320
|
+
* Zustand store for managing provider instances
|
|
192
321
|
*/
|
|
193
|
-
declare const
|
|
322
|
+
declare const useProviderStore: zustand.UseBoundStore<zustand.StoreApi<ProviderStore>>;
|
|
194
323
|
/**
|
|
195
|
-
*
|
|
196
|
-
* @throws Error if used outside of FeedbackProvider
|
|
324
|
+
* Dispatch a context menu event to all matching providers (bubble up)
|
|
197
325
|
*/
|
|
198
|
-
declare function
|
|
326
|
+
declare function dispatchContextMenuEvent(event: MouseEvent, element: Element): void;
|
|
199
327
|
|
|
328
|
+
/**
|
|
329
|
+
* CSS custom properties for menu theming.
|
|
330
|
+
* These can be overridden via the `style` prop on AnyclickProvider.
|
|
331
|
+
*
|
|
332
|
+
* Example:
|
|
333
|
+
* ```tsx
|
|
334
|
+
* <AnyclickProvider
|
|
335
|
+
* theme={{
|
|
336
|
+
* menuStyle: {
|
|
337
|
+
* '--anyclick-menu-bg': 'rgba(0, 0, 0, 0.9)',
|
|
338
|
+
* '--anyclick-menu-text': '#ffffff',
|
|
339
|
+
* '--anyclick-menu-border': 'rgba(255, 255, 255, 0.1)',
|
|
340
|
+
* '--anyclick-menu-hover': 'rgba(255, 255, 255, 0.1)',
|
|
341
|
+
* '--anyclick-menu-accent': '#f59e0b',
|
|
342
|
+
* }
|
|
343
|
+
* }}
|
|
344
|
+
* />
|
|
345
|
+
* ```
|
|
346
|
+
*/
|
|
347
|
+
declare const menuCSSVariables: {
|
|
348
|
+
readonly "--anyclick-menu-bg": "#ffffff";
|
|
349
|
+
readonly "--anyclick-menu-hover": "#f5f5f5";
|
|
350
|
+
readonly "--anyclick-menu-text": "#333333";
|
|
351
|
+
readonly "--anyclick-menu-text-muted": "#666666";
|
|
352
|
+
readonly "--anyclick-menu-border": "#e5e5e5";
|
|
353
|
+
readonly "--anyclick-menu-accent": "#0066cc";
|
|
354
|
+
readonly "--anyclick-menu-accent-text": "#ffffff";
|
|
355
|
+
readonly "--anyclick-menu-input-bg": "#ffffff";
|
|
356
|
+
readonly "--anyclick-menu-input-border": "#dddddd";
|
|
357
|
+
readonly "--anyclick-menu-cancel-bg": "#f0f0f0";
|
|
358
|
+
readonly "--anyclick-menu-cancel-text": "#666666";
|
|
359
|
+
};
|
|
200
360
|
declare const menuStyles: Record<string, CSSProperties>;
|
|
201
361
|
declare const darkMenuStyles: Record<string, CSSProperties>;
|
|
202
362
|
|
|
@@ -236,4 +396,4 @@ declare function applyHighlights(targetElement: Element, config?: HighlightConfi
|
|
|
236
396
|
container: Element | null;
|
|
237
397
|
};
|
|
238
398
|
|
|
239
|
-
export { ContextMenu, type ContextMenuProps, FeedbackContext, type FeedbackContextValue, type FeedbackMenuItem, FeedbackProvider, type FeedbackProviderProps, type FeedbackUserContext, type HighlightColors, type HighlightConfig, ScreenshotPreview, type ScreenshotPreviewProps, applyHighlights, clearHighlights, darkMenuStyles, defaultContainerSelectors, defaultHighlightColors, filterMenuItemsByRole, findContainerParent, highlightContainer, highlightTarget, menuStyles, useFeedback };
|
|
399
|
+
export { AnyclickContext, type AnyclickContextValue, AnyclickProvider, type AnyclickProviderProps, type AnyclickTheme, ContextMenu, type ContextMenuProps, FeedbackContext, type FeedbackContextValue, type FeedbackMenuItem, FeedbackProvider, type FeedbackProviderProps, type FeedbackUserContext, type HighlightColors, type HighlightConfig, type ProviderInstance, ScreenshotPreview, type ScreenshotPreviewProps, applyHighlights, clearHighlights, darkMenuStyles, defaultContainerSelectors, defaultHighlightColors, dispatchContextMenuEvent, filterMenuItemsByRole, findContainerParent, generateProviderId, highlightContainer, highlightTarget, menuCSSVariables, menuStyles, useAnyclick, useFeedback, useProviderStore };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,24 @@ import { FeedbackAdapter, FeedbackType, FeedbackPayload, ScreenshotConfig, Scree
|
|
|
3
3
|
export { DEFAULT_SCREENSHOT_CONFIG, DEFAULT_SENSITIVE_SELECTORS, ElementContext, FeedbackAdapter, FeedbackPayload, FeedbackType, PageContext, ScreenshotCapture, ScreenshotCaptureMode, ScreenshotConfig, ScreenshotData, captureAllScreenshots, captureScreenshot, estimateTotalSize, formatBytes, isScreenshotSupported } from '@ewjdev/anyclick-core';
|
|
4
4
|
import * as react from 'react';
|
|
5
5
|
import { ReactNode, CSSProperties } from 'react';
|
|
6
|
+
import * as zustand from 'zustand';
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Theme configuration for AnyclickProvider
|
|
10
|
+
* Supports nested theming with inheritance
|
|
11
|
+
*/
|
|
12
|
+
interface AnyclickTheme {
|
|
13
|
+
/** Custom styles for the context menu */
|
|
14
|
+
menuStyle?: CSSProperties;
|
|
15
|
+
/** Custom class name for the context menu */
|
|
16
|
+
menuClassName?: string;
|
|
17
|
+
/** Configuration for element highlighting */
|
|
18
|
+
highlightConfig?: HighlightConfig;
|
|
19
|
+
/** Configuration for screenshot capture */
|
|
20
|
+
screenshotConfig?: ScreenshotConfig;
|
|
21
|
+
/** Whether anyclick functionality is disabled in this theme */
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
}
|
|
7
24
|
/**
|
|
8
25
|
* Configuration for highlight colors
|
|
9
26
|
*/
|
|
@@ -63,9 +80,9 @@ interface FeedbackUserContext {
|
|
|
63
80
|
*/
|
|
64
81
|
declare function filterMenuItemsByRole(items: FeedbackMenuItem[], userContext?: FeedbackUserContext): FeedbackMenuItem[];
|
|
65
82
|
/**
|
|
66
|
-
* Props for the
|
|
83
|
+
* Props for the AnyclickProvider component
|
|
67
84
|
*/
|
|
68
|
-
interface
|
|
85
|
+
interface AnyclickProviderProps {
|
|
69
86
|
/** The adapter to use for submitting feedback */
|
|
70
87
|
adapter: FeedbackAdapter;
|
|
71
88
|
/** Child components */
|
|
@@ -103,11 +120,27 @@ interface FeedbackProviderProps {
|
|
|
103
120
|
highlightConfig?: HighlightConfig;
|
|
104
121
|
/** Configuration for screenshot capture */
|
|
105
122
|
screenshotConfig?: ScreenshotConfig;
|
|
123
|
+
/**
|
|
124
|
+
* Whether to scope this provider to its children only.
|
|
125
|
+
* When true, events will only be captured for elements within this provider's subtree.
|
|
126
|
+
* When false (default), events are captured for the entire document.
|
|
127
|
+
*/
|
|
128
|
+
scoped?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Theme configuration for this provider.
|
|
131
|
+
* Themes are inherited from parent providers and merged (child overrides parent).
|
|
132
|
+
* Set to null or { disabled: true } to disable anyclick in this subtree.
|
|
133
|
+
*/
|
|
134
|
+
theme?: AnyclickTheme | null;
|
|
106
135
|
}
|
|
107
136
|
/**
|
|
108
|
-
*
|
|
137
|
+
* @deprecated Use AnyclickProviderProps instead
|
|
138
|
+
*/
|
|
139
|
+
type FeedbackProviderProps = AnyclickProviderProps;
|
|
140
|
+
/**
|
|
141
|
+
* Context value exposed by AnyclickProvider
|
|
109
142
|
*/
|
|
110
|
-
interface
|
|
143
|
+
interface AnyclickContextValue {
|
|
111
144
|
/** Whether feedback is currently enabled */
|
|
112
145
|
isEnabled: boolean;
|
|
113
146
|
/** Whether a submission is in progress */
|
|
@@ -121,7 +154,17 @@ interface FeedbackContextValue {
|
|
|
121
154
|
}) => void;
|
|
122
155
|
/** Close the feedback menu */
|
|
123
156
|
closeMenu: () => void;
|
|
157
|
+
/** The current merged theme (inherited from ancestors) */
|
|
158
|
+
theme: AnyclickTheme;
|
|
159
|
+
/** Whether this provider is scoped */
|
|
160
|
+
scoped: boolean;
|
|
161
|
+
/** The provider's unique ID */
|
|
162
|
+
providerId: string;
|
|
124
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* @deprecated Use AnyclickContextValue instead
|
|
166
|
+
*/
|
|
167
|
+
type FeedbackContextValue = AnyclickContextValue;
|
|
125
168
|
/**
|
|
126
169
|
* Props for the context menu component
|
|
127
170
|
*/
|
|
@@ -173,9 +216,14 @@ interface ScreenshotPreviewProps {
|
|
|
173
216
|
}
|
|
174
217
|
|
|
175
218
|
/**
|
|
176
|
-
*
|
|
219
|
+
* AnyclickProvider component - wraps your app to enable feedback capture
|
|
220
|
+
* Supports scoped providers and nested theming
|
|
221
|
+
*/
|
|
222
|
+
declare function AnyclickProvider({ adapter, children, targetFilter, menuItems, maxInnerTextLength, maxOuterHTMLLength, maxAncestors, cooldownMs, stripAttributes, metadata, onSubmitSuccess, onSubmitError, menuStyle, menuClassName, disabled, highlightConfig, screenshotConfig, scoped, theme, }: AnyclickProviderProps): react_jsx_runtime.JSX.Element;
|
|
223
|
+
/**
|
|
224
|
+
* @deprecated Use AnyclickProvider instead
|
|
177
225
|
*/
|
|
178
|
-
declare
|
|
226
|
+
declare const FeedbackProvider: typeof AnyclickProvider;
|
|
179
227
|
|
|
180
228
|
/**
|
|
181
229
|
* Context menu component for selecting feedback type
|
|
@@ -188,15 +236,127 @@ declare function ContextMenu({ visible, position, targetElement, containerElemen
|
|
|
188
236
|
declare function ScreenshotPreview({ screenshots, isLoading, onConfirm, onCancel, onRetake, isSubmitting, }: ScreenshotPreviewProps): react_jsx_runtime.JSX.Element;
|
|
189
237
|
|
|
190
238
|
/**
|
|
191
|
-
* React context for
|
|
239
|
+
* React context for anyclick functionality
|
|
240
|
+
*/
|
|
241
|
+
declare const AnyclickContext: react.Context<AnyclickContextValue | null>;
|
|
242
|
+
/**
|
|
243
|
+
* @deprecated Use AnyclickContext instead
|
|
244
|
+
*/
|
|
245
|
+
declare const FeedbackContext: react.Context<AnyclickContextValue | null>;
|
|
246
|
+
/**
|
|
247
|
+
* Hook to access anyclick context
|
|
248
|
+
* @throws Error if used outside of AnyclickProvider
|
|
249
|
+
*/
|
|
250
|
+
declare function useAnyclick(): AnyclickContextValue;
|
|
251
|
+
/**
|
|
252
|
+
* @deprecated Use useAnyclick instead
|
|
253
|
+
*/
|
|
254
|
+
declare function useFeedback(): AnyclickContextValue;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Registered provider instance
|
|
258
|
+
*/
|
|
259
|
+
interface ProviderInstance {
|
|
260
|
+
/** Unique identifier for this provider instance */
|
|
261
|
+
id: string;
|
|
262
|
+
/** Reference to the provider's container element (null if not scoped) */
|
|
263
|
+
containerRef: React.RefObject<Element | null>;
|
|
264
|
+
/** Whether this provider is scoped to its container */
|
|
265
|
+
scoped: boolean;
|
|
266
|
+
/** The provider's theme configuration */
|
|
267
|
+
theme: AnyclickTheme | null;
|
|
268
|
+
/** Whether this provider is disabled */
|
|
269
|
+
disabled: boolean;
|
|
270
|
+
/** Parent provider ID (if nested) */
|
|
271
|
+
parentId: string | null;
|
|
272
|
+
/** Depth in the provider hierarchy (0 = root) */
|
|
273
|
+
depth: number;
|
|
274
|
+
/** Handler to call when an event occurs in this provider's scope */
|
|
275
|
+
onContextMenu?: (event: MouseEvent, element: Element) => void;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Provider registry store state
|
|
279
|
+
*/
|
|
280
|
+
interface ProviderStore {
|
|
281
|
+
/** Map of provider ID to provider instance */
|
|
282
|
+
providers: Map<string, ProviderInstance>;
|
|
283
|
+
/**
|
|
284
|
+
* Register a new provider
|
|
285
|
+
*/
|
|
286
|
+
registerProvider: (provider: ProviderInstance) => void;
|
|
287
|
+
/**
|
|
288
|
+
* Unregister a provider
|
|
289
|
+
*/
|
|
290
|
+
unregisterProvider: (id: string) => void;
|
|
291
|
+
/**
|
|
292
|
+
* Update a provider's configuration
|
|
293
|
+
*/
|
|
294
|
+
updateProvider: (id: string, updates: Partial<ProviderInstance>) => void;
|
|
295
|
+
/**
|
|
296
|
+
* Find all providers that contain a given element, sorted by depth (nearest first)
|
|
297
|
+
*/
|
|
298
|
+
findProvidersForElement: (element: Element) => ProviderInstance[];
|
|
299
|
+
/**
|
|
300
|
+
* Find the nearest parent provider for a given container
|
|
301
|
+
*/
|
|
302
|
+
findParentProvider: (container: Element | null, excludeId?: string) => ProviderInstance | null;
|
|
303
|
+
/**
|
|
304
|
+
* Get merged theme for a provider (includes inherited parent themes)
|
|
305
|
+
*/
|
|
306
|
+
getMergedTheme: (providerId: string) => AnyclickTheme;
|
|
307
|
+
/**
|
|
308
|
+
* Check if any ancestor provider has disabled anyclick
|
|
309
|
+
*/
|
|
310
|
+
isDisabledByAncestor: (providerId: string) => boolean;
|
|
311
|
+
/**
|
|
312
|
+
* Check if an element is inside a disabled scoped provider's container
|
|
313
|
+
* This is used to prevent the global provider from handling events
|
|
314
|
+
* in areas where a disabled scoped provider should block them
|
|
315
|
+
*/
|
|
316
|
+
isElementInDisabledScope: (element: Element) => boolean;
|
|
317
|
+
}
|
|
318
|
+
declare function generateProviderId(): string;
|
|
319
|
+
/**
|
|
320
|
+
* Zustand store for managing provider instances
|
|
192
321
|
*/
|
|
193
|
-
declare const
|
|
322
|
+
declare const useProviderStore: zustand.UseBoundStore<zustand.StoreApi<ProviderStore>>;
|
|
194
323
|
/**
|
|
195
|
-
*
|
|
196
|
-
* @throws Error if used outside of FeedbackProvider
|
|
324
|
+
* Dispatch a context menu event to all matching providers (bubble up)
|
|
197
325
|
*/
|
|
198
|
-
declare function
|
|
326
|
+
declare function dispatchContextMenuEvent(event: MouseEvent, element: Element): void;
|
|
199
327
|
|
|
328
|
+
/**
|
|
329
|
+
* CSS custom properties for menu theming.
|
|
330
|
+
* These can be overridden via the `style` prop on AnyclickProvider.
|
|
331
|
+
*
|
|
332
|
+
* Example:
|
|
333
|
+
* ```tsx
|
|
334
|
+
* <AnyclickProvider
|
|
335
|
+
* theme={{
|
|
336
|
+
* menuStyle: {
|
|
337
|
+
* '--anyclick-menu-bg': 'rgba(0, 0, 0, 0.9)',
|
|
338
|
+
* '--anyclick-menu-text': '#ffffff',
|
|
339
|
+
* '--anyclick-menu-border': 'rgba(255, 255, 255, 0.1)',
|
|
340
|
+
* '--anyclick-menu-hover': 'rgba(255, 255, 255, 0.1)',
|
|
341
|
+
* '--anyclick-menu-accent': '#f59e0b',
|
|
342
|
+
* }
|
|
343
|
+
* }}
|
|
344
|
+
* />
|
|
345
|
+
* ```
|
|
346
|
+
*/
|
|
347
|
+
declare const menuCSSVariables: {
|
|
348
|
+
readonly "--anyclick-menu-bg": "#ffffff";
|
|
349
|
+
readonly "--anyclick-menu-hover": "#f5f5f5";
|
|
350
|
+
readonly "--anyclick-menu-text": "#333333";
|
|
351
|
+
readonly "--anyclick-menu-text-muted": "#666666";
|
|
352
|
+
readonly "--anyclick-menu-border": "#e5e5e5";
|
|
353
|
+
readonly "--anyclick-menu-accent": "#0066cc";
|
|
354
|
+
readonly "--anyclick-menu-accent-text": "#ffffff";
|
|
355
|
+
readonly "--anyclick-menu-input-bg": "#ffffff";
|
|
356
|
+
readonly "--anyclick-menu-input-border": "#dddddd";
|
|
357
|
+
readonly "--anyclick-menu-cancel-bg": "#f0f0f0";
|
|
358
|
+
readonly "--anyclick-menu-cancel-text": "#666666";
|
|
359
|
+
};
|
|
200
360
|
declare const menuStyles: Record<string, CSSProperties>;
|
|
201
361
|
declare const darkMenuStyles: Record<string, CSSProperties>;
|
|
202
362
|
|
|
@@ -236,4 +396,4 @@ declare function applyHighlights(targetElement: Element, config?: HighlightConfi
|
|
|
236
396
|
container: Element | null;
|
|
237
397
|
};
|
|
238
398
|
|
|
239
|
-
export { ContextMenu, type ContextMenuProps, FeedbackContext, type FeedbackContextValue, type FeedbackMenuItem, FeedbackProvider, type FeedbackProviderProps, type FeedbackUserContext, type HighlightColors, type HighlightConfig, ScreenshotPreview, type ScreenshotPreviewProps, applyHighlights, clearHighlights, darkMenuStyles, defaultContainerSelectors, defaultHighlightColors, filterMenuItemsByRole, findContainerParent, highlightContainer, highlightTarget, menuStyles, useFeedback };
|
|
399
|
+
export { AnyclickContext, type AnyclickContextValue, AnyclickProvider, type AnyclickProviderProps, type AnyclickTheme, ContextMenu, type ContextMenuProps, FeedbackContext, type FeedbackContextValue, type FeedbackMenuItem, FeedbackProvider, type FeedbackProviderProps, type FeedbackUserContext, type HighlightColors, type HighlightConfig, type ProviderInstance, ScreenshotPreview, type ScreenshotPreviewProps, applyHighlights, clearHighlights, darkMenuStyles, defaultContainerSelectors, defaultHighlightColors, dispatchContextMenuEvent, filterMenuItemsByRole, findContainerParent, generateProviderId, highlightContainer, highlightTarget, menuCSSVariables, menuStyles, useAnyclick, useFeedback, useProviderStore };
|