spaps-issue-reporting-react 0.1.3 → 0.1.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.3] - 2026-04-20
4
+
5
+ - Changed: publish the page-first report flow package metadata and align README metadata with the current package version.
6
+
3
7
  ## [0.1.1] - 2026-04-05
4
8
 
5
9
  - Docs: align package README metadata with published version.
package/README.md CHANGED
@@ -10,7 +10,7 @@ Examples in this README use placeholder IDs and app labels. Replace them with va
10
10
  npm install spaps-issue-reporting-react react react-dom @tanstack/react-query
11
11
  ```
12
12
 
13
- This package targets `Node.js >=18` and React 18+.
13
+ This package targets `Node.js >=18` and React 18+. Voice input uses the package's `@elevenlabs/react` dependency and a SPAPS-minted single-use token.
14
14
 
15
15
  ## When It Fits
16
16
 
@@ -43,8 +43,9 @@ export function AppShell() {
43
43
  isEligible={true}
44
44
  principalId="user_123"
45
45
  reporterRoleHint="staff"
46
- allowTenantScope
47
46
  defaultScope="mine"
47
+ inputModes={["text", "voice"]}
48
+ defaultInputMode="text"
48
49
  >
49
50
  <IssueReportingPageConfig createMode="surface_preferred" />
50
51
 
@@ -69,17 +70,63 @@ export function AppShell() {
69
70
  ## What Your App Still Owns
70
71
 
71
72
  - A client with `issueReporting.getStatus`, `list`, `get`, `create`, `update`, and `reply`.
73
+ - A client with `issueReporting.createVoiceToken` when `inputModes` includes `voice`.
72
74
  - Any auth and token refresh behavior needed by that client.
73
75
  - Eligibility rules such as feature flags, account state, or role checks.
74
76
  - The current principal ID and optional role hint passed into the provider.
75
- - Whether users can switch between `mine` and `tenant` queue scope.
77
+ - Whether users can switch between `mine` and a custom tenant queue scope. The stock SPAPS API
78
+ supports `mine` only; use `allowTenantScope` only with a client that implements tenant reads.
76
79
  - Whether a page defaults to `general_page`, `surface_required`, or `surface_preferred` reporting.
80
+ - Whether the app allows `["text"]`, `["voice"]`, or `["text", "voice"]` report input.
77
81
  - Styling integration if your build strips package utility classes.
78
82
  - Any app-specific copy overrides.
79
83
  - Origin registration on the owning SPAPS application if the browser calls SPAPS directly with a publishable key.
80
84
 
81
85
  For direct browser integrations, `allowed_origins` is stored on the SPAPS `applications` row that owns the publishable key. It is not configured on this package. If multiple hostnames share one SPAPS application, put all of them on that row. Updating `allowed_origins` does not require restarting SPAPS.
82
86
 
87
+ ## Voice Input
88
+
89
+ Voice mode is opt-in per app. Configure the owning SPAPS application with either:
90
+
91
+ ```json
92
+ {
93
+ "issue_reporting_input_modes": ["text", "voice"]
94
+ }
95
+ ```
96
+
97
+ or:
98
+
99
+ ```json
100
+ {
101
+ "issue_reporting": {
102
+ "input_modes": ["voice"]
103
+ }
104
+ }
105
+ ```
106
+
107
+ The SPAPS server also needs `ELEVENLABS_API_KEY`. The browser calls your normal SPAPS client, which mints a short-lived Scribe token through `issueReporting.createVoiceToken()`. The committed transcript is submitted as the issue `note`; raw audio is not stored by this package.
108
+
109
+ ```tsx
110
+ <IssueReportingProvider
111
+ client={spaps}
112
+ isEligible={true}
113
+ inputModes={["voice"]}
114
+ defaultInputMode="voice"
115
+ voice={{
116
+ modelId: "scribe_v2_realtime",
117
+ microphone: {
118
+ echoCancellation: true,
119
+ noiseSuppression: true,
120
+ autoGainControl: true,
121
+ },
122
+ }}
123
+ >
124
+ <FloatingIssueReportButton />
125
+ </IssueReportingProvider>
126
+ ```
127
+
128
+ When text and voice are both enabled, the modal keeps the textarea available and lets the user append a committed transcript into the editable note.
129
+
83
130
  ## Exported Surface
84
131
 
85
132
  | Export | Purpose |
@@ -130,12 +177,21 @@ Render `IssueReportingPageConfig` with `createMode="surface_required"` inside th
130
177
 
131
178
  ### Tenant scope never appears
132
179
 
133
- Set `allowTenantScope={true}`. The provider defaults to `mine`.
180
+ The stock SPAPS API supports `mine` only. Set `allowTenantScope={true}` only when your client
181
+ implements tenant-scoped `getStatus` and `list` calls.
134
182
 
135
183
  ### Styles look unformatted
136
184
 
137
185
  Include the package in your Tailwind or CSS-content scan, or override the rendered classes in your host app.
138
186
 
187
+ ### Voice controls do not appear
188
+
189
+ Pass `inputModes={["voice"]}` or `inputModes={["text", "voice"]}` to the provider, and enable `voice` in the owning SPAPS application's issue-reporting settings.
190
+
191
+ ### Voice starts with a token error
192
+
193
+ Confirm that the SPAPS server has `ELEVENLABS_API_KEY` set and that the current user is authenticated and eligible for issue reporting.
194
+
139
195
  ## Limitations
140
196
 
141
197
  - This package assumes React Query is already part of the host app.
@@ -175,7 +231,7 @@ No. This package is UI only. If your browser app calls SPAPS directly with a pub
175
231
  ## Metadata
176
232
 
177
233
  - `package_name`: `spaps-issue-reporting-react`
178
- - `latest_version`: `0.1.1`
234
+ - `latest_version`: `0.1.3`
179
235
  - `minimum_runtime`: `Node.js >=18.0.0`
180
236
  - `api_base_url`: `https://api.sweetpotato.dev`
181
237
 
package/dist/index.d.mts CHANGED
@@ -2,11 +2,24 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default, { ReactNode } from 'react';
4
4
  import * as spaps_types from 'spaps-types';
5
- import { IssueReportScope, IssueReportStatusResult, IssueReportStatus, IssueReportListResult, IssueReport, CreateIssueReportRequest, UpdateIssueReportRequest, ReplyIssueReportRequest } from 'spaps-types';
5
+ import { IssueReportScope, IssueReportStatusResult, IssueReportStatus, IssueReportListResult, IssueReport, CreateIssueReportRequest, UpdateIssueReportRequest, ReplyIssueReportRequest, IssueReportingVoiceTokenResult, IssueReportingInputMode, IssueReportingVoiceProvider } from 'spaps-types';
6
6
  export { CreateIssueReportRequest, IssueReport, IssueReportListResult, IssueReportScope, IssueReportStatus, IssueReportStatusResult, ReplyIssueReportRequest, UpdateIssueReportRequest } from 'spaps-types';
7
7
  import * as _tanstack_query_core from '@tanstack/query-core';
8
8
  import * as _tanstack_react_query from '@tanstack/react-query';
9
9
 
10
+ interface IssueReportingVoiceMicrophoneConfig {
11
+ deviceId?: string;
12
+ echoCancellation?: boolean;
13
+ noiseSuppression?: boolean;
14
+ autoGainControl?: boolean;
15
+ channelCount?: number;
16
+ }
17
+ interface IssueReportingVoiceConfig {
18
+ provider?: IssueReportingVoiceProvider;
19
+ modelId?: string;
20
+ requireMicrophonePermission?: boolean;
21
+ microphone?: IssueReportingVoiceMicrophoneConfig;
22
+ }
10
23
  interface IssueReportingClient {
11
24
  issueReporting: {
12
25
  getStatus: (params?: {
@@ -22,6 +35,7 @@ interface IssueReportingClient {
22
35
  create: (payload: CreateIssueReportRequest) => Promise<IssueReport>;
23
36
  update: (issueReportId: string, payload: UpdateIssueReportRequest) => Promise<IssueReport>;
24
37
  reply: (issueReportId: string, payload: ReplyIssueReportRequest) => Promise<IssueReport>;
38
+ createVoiceToken?: () => Promise<IssueReportingVoiceTokenResult>;
25
39
  };
26
40
  }
27
41
  interface ReportableTargetDescriptor {
@@ -89,6 +103,9 @@ interface IssueReportingProviderProps {
89
103
  defaultScope?: IssueReportScope;
90
104
  allowTenantScope?: boolean;
91
105
  defaultCreateMode?: IssueReportingCreateMode;
106
+ inputModes?: IssueReportingInputMode[];
107
+ defaultInputMode?: IssueReportingInputMode;
108
+ voice?: IssueReportingVoiceConfig;
92
109
  copy?: Partial<IssueReportingCopy>;
93
110
  children: ReactNode;
94
111
  }
@@ -149,6 +166,11 @@ type IssueReportingContextValue = {
149
166
  setScope: (scope: IssueReportScope) => void;
150
167
  allowTenantScope: boolean;
151
168
  createMode: IssueReportingCreateMode;
169
+ inputModes: IssueReportingInputMode[];
170
+ defaultInputMode: IssueReportingInputMode;
171
+ voice: Required<Pick<IssueReportingVoiceConfig, "provider" | "modelId" | "requireMicrophonePermission">> & {
172
+ microphone?: IssueReportingVoiceConfig["microphone"];
173
+ };
152
174
  };
153
175
  declare const defaultIssueReportingCopy: IssueReportingCopy;
154
176
  declare const issueReportingKeys: {
@@ -362,7 +384,7 @@ declare function useIssueReportingMutations(): {
362
384
  reporterRoleHint?: string;
363
385
  }, unknown>;
364
386
  };
365
- declare function IssueReportingProvider({ client, isEligible, reporterRoleHint, principalId, getPageUrl, defaultScope, allowTenantScope, defaultCreateMode, copy, children, }: IssueReportingProviderProps): react_jsx_runtime.JSX.Element;
387
+ declare function IssueReportingProvider({ client, isEligible, reporterRoleHint, principalId, getPageUrl, defaultScope, allowTenantScope, defaultCreateMode, inputModes, defaultInputMode, voice, copy, children, }: IssueReportingProviderProps): react_jsx_runtime.JSX.Element;
366
388
 
367
389
  interface ReportModeContextValue {
368
390
  isReportMode: boolean;
package/dist/index.d.ts CHANGED
@@ -2,11 +2,24 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default, { ReactNode } from 'react';
4
4
  import * as spaps_types from 'spaps-types';
5
- import { IssueReportScope, IssueReportStatusResult, IssueReportStatus, IssueReportListResult, IssueReport, CreateIssueReportRequest, UpdateIssueReportRequest, ReplyIssueReportRequest } from 'spaps-types';
5
+ import { IssueReportScope, IssueReportStatusResult, IssueReportStatus, IssueReportListResult, IssueReport, CreateIssueReportRequest, UpdateIssueReportRequest, ReplyIssueReportRequest, IssueReportingVoiceTokenResult, IssueReportingInputMode, IssueReportingVoiceProvider } from 'spaps-types';
6
6
  export { CreateIssueReportRequest, IssueReport, IssueReportListResult, IssueReportScope, IssueReportStatus, IssueReportStatusResult, ReplyIssueReportRequest, UpdateIssueReportRequest } from 'spaps-types';
7
7
  import * as _tanstack_query_core from '@tanstack/query-core';
8
8
  import * as _tanstack_react_query from '@tanstack/react-query';
9
9
 
10
+ interface IssueReportingVoiceMicrophoneConfig {
11
+ deviceId?: string;
12
+ echoCancellation?: boolean;
13
+ noiseSuppression?: boolean;
14
+ autoGainControl?: boolean;
15
+ channelCount?: number;
16
+ }
17
+ interface IssueReportingVoiceConfig {
18
+ provider?: IssueReportingVoiceProvider;
19
+ modelId?: string;
20
+ requireMicrophonePermission?: boolean;
21
+ microphone?: IssueReportingVoiceMicrophoneConfig;
22
+ }
10
23
  interface IssueReportingClient {
11
24
  issueReporting: {
12
25
  getStatus: (params?: {
@@ -22,6 +35,7 @@ interface IssueReportingClient {
22
35
  create: (payload: CreateIssueReportRequest) => Promise<IssueReport>;
23
36
  update: (issueReportId: string, payload: UpdateIssueReportRequest) => Promise<IssueReport>;
24
37
  reply: (issueReportId: string, payload: ReplyIssueReportRequest) => Promise<IssueReport>;
38
+ createVoiceToken?: () => Promise<IssueReportingVoiceTokenResult>;
25
39
  };
26
40
  }
27
41
  interface ReportableTargetDescriptor {
@@ -89,6 +103,9 @@ interface IssueReportingProviderProps {
89
103
  defaultScope?: IssueReportScope;
90
104
  allowTenantScope?: boolean;
91
105
  defaultCreateMode?: IssueReportingCreateMode;
106
+ inputModes?: IssueReportingInputMode[];
107
+ defaultInputMode?: IssueReportingInputMode;
108
+ voice?: IssueReportingVoiceConfig;
92
109
  copy?: Partial<IssueReportingCopy>;
93
110
  children: ReactNode;
94
111
  }
@@ -149,6 +166,11 @@ type IssueReportingContextValue = {
149
166
  setScope: (scope: IssueReportScope) => void;
150
167
  allowTenantScope: boolean;
151
168
  createMode: IssueReportingCreateMode;
169
+ inputModes: IssueReportingInputMode[];
170
+ defaultInputMode: IssueReportingInputMode;
171
+ voice: Required<Pick<IssueReportingVoiceConfig, "provider" | "modelId" | "requireMicrophonePermission">> & {
172
+ microphone?: IssueReportingVoiceConfig["microphone"];
173
+ };
152
174
  };
153
175
  declare const defaultIssueReportingCopy: IssueReportingCopy;
154
176
  declare const issueReportingKeys: {
@@ -362,7 +384,7 @@ declare function useIssueReportingMutations(): {
362
384
  reporterRoleHint?: string;
363
385
  }, unknown>;
364
386
  };
365
- declare function IssueReportingProvider({ client, isEligible, reporterRoleHint, principalId, getPageUrl, defaultScope, allowTenantScope, defaultCreateMode, copy, children, }: IssueReportingProviderProps): react_jsx_runtime.JSX.Element;
387
+ declare function IssueReportingProvider({ client, isEligible, reporterRoleHint, principalId, getPageUrl, defaultScope, allowTenantScope, defaultCreateMode, inputModes, defaultInputMode, voice, copy, children, }: IssueReportingProviderProps): react_jsx_runtime.JSX.Element;
366
388
 
367
389
  interface ReportModeContextValue {
368
390
  isReportMode: boolean;