@taskp3/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.
Files changed (142) hide show
  1. package/README.md +258 -0
  2. package/dist/changelog-hooks.d.ts +46 -0
  3. package/dist/changelog-hooks.d.ts.map +1 -0
  4. package/dist/changelog-hooks.js +163 -0
  5. package/dist/changelog-hooks.js.map +1 -0
  6. package/dist/changelog.d.ts +17 -0
  7. package/dist/changelog.d.ts.map +1 -0
  8. package/dist/changelog.js +86 -0
  9. package/dist/changelog.js.map +1 -0
  10. package/dist/context.d.ts +33 -0
  11. package/dist/context.d.ts.map +1 -0
  12. package/dist/context.js +62 -0
  13. package/dist/context.js.map +1 -0
  14. package/dist/fetch.d.ts +3 -0
  15. package/dist/fetch.d.ts.map +1 -0
  16. package/dist/fetch.js +19 -0
  17. package/dist/fetch.js.map +1 -0
  18. package/dist/hooks.d.ts +50 -0
  19. package/dist/hooks.d.ts.map +1 -0
  20. package/dist/hooks.js +140 -0
  21. package/dist/hooks.js.map +1 -0
  22. package/dist/icons.d.ts +52 -0
  23. package/dist/icons.d.ts.map +1 -0
  24. package/dist/icons.js +40 -0
  25. package/dist/icons.js.map +1 -0
  26. package/dist/index.d.ts +33 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +43 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/loom-recorder.d.ts +9 -0
  31. package/dist/loom-recorder.d.ts.map +1 -0
  32. package/dist/loom-recorder.js +92 -0
  33. package/dist/loom-recorder.js.map +1 -0
  34. package/dist/past-submissions.d.ts +10 -0
  35. package/dist/past-submissions.d.ts.map +1 -0
  36. package/dist/past-submissions.js +198 -0
  37. package/dist/past-submissions.js.map +1 -0
  38. package/dist/recorder/audio.d.ts +6 -0
  39. package/dist/recorder/audio.d.ts.map +1 -0
  40. package/dist/recorder/audio.js +30 -0
  41. package/dist/recorder/audio.js.map +1 -0
  42. package/dist/recorder/capture.d.ts +6 -0
  43. package/dist/recorder/capture.d.ts.map +1 -0
  44. package/dist/recorder/capture.js +32 -0
  45. package/dist/recorder/capture.js.map +1 -0
  46. package/dist/recorder/finalize-recording-worker-source.d.ts +2 -0
  47. package/dist/recorder/finalize-recording-worker-source.d.ts.map +1 -0
  48. package/dist/recorder/finalize-recording-worker-source.js +6 -0
  49. package/dist/recorder/finalize-recording-worker-source.js.map +1 -0
  50. package/dist/recorder/finalize-recording-worker.d.ts +2 -0
  51. package/dist/recorder/finalize-recording-worker.d.ts.map +1 -0
  52. package/dist/recorder/finalize-recording-worker.js +16 -0
  53. package/dist/recorder/finalize-recording-worker.js.map +1 -0
  54. package/dist/recorder/finalizeRecording.d.ts +12 -0
  55. package/dist/recorder/finalizeRecording.d.ts.map +1 -0
  56. package/dist/recorder/finalizeRecording.js +92 -0
  57. package/dist/recorder/finalizeRecording.js.map +1 -0
  58. package/dist/recorder/finalizeRecordingInWorker.d.ts +3 -0
  59. package/dist/recorder/finalizeRecordingInWorker.d.ts.map +1 -0
  60. package/dist/recorder/finalizeRecordingInWorker.js +49 -0
  61. package/dist/recorder/finalizeRecordingInWorker.js.map +1 -0
  62. package/dist/recorder/index.d.ts +7 -0
  63. package/dist/recorder/index.d.ts.map +1 -0
  64. package/dist/recorder/index.js +14 -0
  65. package/dist/recorder/index.js.map +1 -0
  66. package/dist/recorder/session.d.ts +19 -0
  67. package/dist/recorder/session.d.ts.map +1 -0
  68. package/dist/recorder/session.js +237 -0
  69. package/dist/recorder/session.js.map +1 -0
  70. package/dist/recorder/support.d.ts +8 -0
  71. package/dist/recorder/support.d.ts.map +1 -0
  72. package/dist/recorder/support.js +41 -0
  73. package/dist/recorder/support.js.map +1 -0
  74. package/dist/recorder/timer-worker.d.ts +5 -0
  75. package/dist/recorder/timer-worker.d.ts.map +1 -0
  76. package/dist/recorder/timer-worker.js +28 -0
  77. package/dist/recorder/timer-worker.js.map +1 -0
  78. package/dist/recorder/types.d.ts +26 -0
  79. package/dist/recorder/types.d.ts.map +1 -0
  80. package/dist/recorder/types.js +3 -0
  81. package/dist/recorder/types.js.map +1 -0
  82. package/dist/recorder-preview-player.d.ts +9 -0
  83. package/dist/recorder-preview-player.d.ts.map +1 -0
  84. package/dist/recorder-preview-player.js +136 -0
  85. package/dist/recorder-preview-player.js.map +1 -0
  86. package/dist/screen-recorder-context.d.ts +16 -0
  87. package/dist/screen-recorder-context.d.ts.map +1 -0
  88. package/dist/screen-recorder-context.js +124 -0
  89. package/dist/screen-recorder-context.js.map +1 -0
  90. package/dist/screen-recorder.d.ts +16 -0
  91. package/dist/screen-recorder.d.ts.map +1 -0
  92. package/dist/screen-recorder.js +126 -0
  93. package/dist/screen-recorder.js.map +1 -0
  94. package/dist/styles.d.ts +3 -0
  95. package/dist/styles.d.ts.map +1 -0
  96. package/dist/styles.js +841 -0
  97. package/dist/styles.js.map +1 -0
  98. package/dist/triage-attachments.d.ts +5 -0
  99. package/dist/triage-attachments.d.ts.map +1 -0
  100. package/dist/triage-attachments.js +44 -0
  101. package/dist/triage-attachments.js.map +1 -0
  102. package/dist/triage-button.d.ts +26 -0
  103. package/dist/triage-button.d.ts.map +1 -0
  104. package/dist/triage-button.js +228 -0
  105. package/dist/triage-button.js.map +1 -0
  106. package/dist/triage-rich-content.d.ts +6 -0
  107. package/dist/triage-rich-content.d.ts.map +1 -0
  108. package/dist/triage-rich-content.js +121 -0
  109. package/dist/triage-rich-content.js.map +1 -0
  110. package/dist/triage-slate-editor.d.ts +8 -0
  111. package/dist/triage-slate-editor.d.ts.map +1 -0
  112. package/dist/triage-slate-editor.js +112 -0
  113. package/dist/triage-slate-editor.js.map +1 -0
  114. package/dist/triage-slate.d.ts +20 -0
  115. package/dist/triage-slate.d.ts.map +1 -0
  116. package/dist/triage-slate.js +64 -0
  117. package/dist/triage-slate.js.map +1 -0
  118. package/dist/triage-ui-controller.d.ts +52 -0
  119. package/dist/triage-ui-controller.d.ts.map +1 -0
  120. package/dist/triage-ui-controller.js +146 -0
  121. package/dist/triage-ui-controller.js.map +1 -0
  122. package/dist/triage-ui-notifications.d.ts +5 -0
  123. package/dist/triage-ui-notifications.d.ts.map +1 -0
  124. package/dist/triage-ui-notifications.js +10 -0
  125. package/dist/triage-ui-notifications.js.map +1 -0
  126. package/dist/use-past-submissions.d.ts +43 -0
  127. package/dist/use-past-submissions.d.ts.map +1 -0
  128. package/dist/use-past-submissions.js +240 -0
  129. package/dist/use-past-submissions.js.map +1 -0
  130. package/dist/use-recorder-controller.d.ts +33 -0
  131. package/dist/use-recorder-controller.d.ts.map +1 -0
  132. package/dist/use-recorder-controller.js +309 -0
  133. package/dist/use-recorder-controller.js.map +1 -0
  134. package/dist/use-screen-recorder.d.ts +25 -0
  135. package/dist/use-screen-recorder.d.ts.map +1 -0
  136. package/dist/use-screen-recorder.js +34 -0
  137. package/dist/use-screen-recorder.js.map +1 -0
  138. package/dist/whats-new.d.ts +16 -0
  139. package/dist/whats-new.d.ts.map +1 -0
  140. package/dist/whats-new.js +72 -0
  141. package/dist/whats-new.js.map +1 -0
  142. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,258 @@
1
+ # @taskp3/react
2
+
3
+ React components for [TaskP3](https://www.taskp3.com) — shared triage, changelog, and "What's New" UI for integrations built on the SDK.
4
+
5
+ For the server-side SDK, see [`@taskp3/sdk`](https://www.npmjs.com/package/@taskp3/sdk).
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @taskp3/react @taskp3/sdk
11
+ ```
12
+
13
+ Peer dependencies: `react >= 17`, `react-dom >= 17`, `@taskp3/sdk >= 0.1.0`.
14
+
15
+ ## Quick Start
16
+
17
+ 1. Mount the Express adapter on your server (see [`@taskp3/sdk`](https://www.npmjs.com/package/@taskp3/sdk) docs).
18
+ 2. Wrap your app with `<TaskP3Provider>` and mount the shared components:
19
+
20
+ ```tsx
21
+ import { TaskP3Provider, TriageButton, WhatsNew } from "@taskp3/react";
22
+
23
+ function App() {
24
+ return (
25
+ <TaskP3Provider apiUrl="https://your-app.com/api/triage">
26
+ <YourApp />
27
+ <TriageButton />
28
+ <WhatsNew />
29
+ </TaskP3Provider>
30
+ );
31
+ }
32
+ ```
33
+
34
+ ## Components
35
+
36
+ ### `<TaskP3Provider>`
37
+
38
+ Required wrapper that configures the API URL, theme, and optional auth headers.
39
+
40
+ ```tsx
41
+ <TaskP3Provider
42
+ apiUrl="https://your-app.com/api/triage"
43
+ theme={{ primaryColor: "#6366f1" }}
44
+ getHeaders={() => ({ Authorization: `Bearer ${token}` })}
45
+ >
46
+ {children}
47
+ </TaskP3Provider>
48
+ ```
49
+
50
+ | Prop | Type | Required | Description |
51
+ |---|---|---|---|
52
+ | `apiUrl` | `string` | Yes | Full URL where `createTriageRouter` is mounted |
53
+ | `theme` | `TaskP3Theme` | No | Visual customisation (see [Theming](#theming)) |
54
+ | `getHeaders` | `() => Record<string, string>` | No | Extra headers sent with every request (e.g. `Authorization`) |
55
+ | `fetcher` | `(url: string, init: RequestInit) => Promise<Response>` | No | Custom fetch implementation — use to plug in your own API service with interceptors, retry logic, etc. Defaults to native `fetch`. |
56
+
57
+ ### `<TriageButton>`
58
+
59
+ Floating help button for the initial triage submission flow: category tabs, file upload, screen recording, and submission.
60
+
61
+ ```tsx
62
+ <TriageButton
63
+ position="bottom-right"
64
+ buttonText="Help"
65
+ onSubmitSuccess={(data) => console.log("Submitted", data)}
66
+ />
67
+ ```
68
+
69
+ | Prop | Type | Default | Description |
70
+ |---|---|---|---|
71
+ | `position` | `"bottom-right" \| "bottom-left"` | `"bottom-right"` | Screen corner |
72
+ | `categories` | `(TriageSubmissionType \| string)[]` | All types | Submission types to show |
73
+ | `buttonText` | `string` | `"Help"` | Button label |
74
+ | `enableFileUpload` | `boolean` | `true` | Allow file attachments |
75
+ | `onSubmitSuccess` | `(data: unknown) => void` | — | Callback after successful submit |
76
+ | `onSubmitError` | `(error: Error) => void` | — | Callback on error |
77
+
78
+ `TriageButton` is the closest CP9 parity surface today. It covers the initial submission happy path well, but full CP9 drop-in behavior still depends on host integration for route state, alerts, and some recorder handoff workflows.
79
+
80
+ ### `<PastSubmissions>`
81
+
82
+ Shared modal for browsing past submissions: list pane, filters/search/sort, response thread, and a lightweight reply composer.
83
+
84
+ ```tsx
85
+ <PastSubmissions open={open} onClose={() => setOpen(false)} />
86
+ ```
87
+
88
+ | Prop | Type | Required | Description |
89
+ |---|---|---|---|
90
+ | `open` | `boolean` | Yes | Controls modal visibility |
91
+ | `onClose` | `() => void` | Yes | Close handler |
92
+ | `title` | `string` | No | Modal title |
93
+ | `pageSize` | `number` | No | Page size for submissions/responses |
94
+ | `sortOrder` | `"ASC" \| "DESC"` | No | Initial sort |
95
+ | `filters` | `PastSubmissionsFilters` | No | Initial filters |
96
+ | `searchTerm` | `string` | No | Initial search value |
97
+
98
+ `PastSubmissions` is intentionally lighter than CP9's full in-app history workflow today. Rich Slate rendering, attachment rendering/uploading, reply recordings, and some deep-link/router orchestration still require host-specific work. See the parity matrix in [`@taskp3/sdk`](../p3-sdk/CP_PARITY_MATRIX.md) for the current drop-in status.
99
+
100
+ ### `<Changelog>`
101
+
102
+ Full changelog feed with type chips, descriptions, and expandable code changes.
103
+
104
+ ```tsx
105
+ <Changelog limit={10} types="New Feature,Bug fix" />
106
+ ```
107
+
108
+ | Prop | Type | Default | Description |
109
+ |---|---|---|---|
110
+ | `limit` | `number` | `10` | Entries per page |
111
+ | `types` | `string` | — | Comma-separated filter (e.g. `"New Feature,Bug fix"`) |
112
+ | `className` | `string` | — | CSS class on root container |
113
+ | `emptyText` | `string` | `"No changelog entries yet."` | Text when no entries exist |
114
+
115
+ ### `<WhatsNew>`
116
+
117
+ Auto-showing modal for the latest changelog entry. Uses `localStorage` to track when the user last dismissed it — only re-appears when a newer release exists.
118
+
119
+ ```tsx
120
+ <WhatsNew onDismiss={(entry) => console.log("dismissed", entry.id)} />
121
+ ```
122
+
123
+ | Prop | Type | Default | Description |
124
+ |---|---|---|---|
125
+ | `storageKey` | `string` | `"p3-changelog-last-seen"` | localStorage key for tracking |
126
+ | `onDismiss` | `(entry: ChangelogEntry) => void` | — | Callback when user dismisses |
127
+ | `open` | `boolean` | — | Force open/closed (overrides auto-show) |
128
+
129
+ ## Hooks
130
+
131
+ All hooks must be called inside `<TaskP3Provider>`.
132
+
133
+ ### `useTriage()`
134
+
135
+ Low-level hook for building fully custom triage UIs.
136
+
137
+ ```tsx
138
+ const { createTask, createResponse, uploadFile, getSubmissions, getResponses } = useTriage();
139
+ ```
140
+
141
+ | Method | Returns | Description |
142
+ |---|---|---|
143
+ | `createTask(data)` | `Promise<any>` | Submit a triage task |
144
+ | `getSubmission(taskId)` | `Promise<TriageSubmission>` | Get a single submission |
145
+ | `uploadFile(file)` | `Promise<TriageFileUpload & { localFile: File }>` | Upload via presigned URL |
146
+ | `getSubmissions(params?)` | `Promise<TriageSubmissionsResponse>` | List submissions (paginated) |
147
+ | `createResponse(taskId, data)` | `Promise<TriageSubmission>` | Send a response |
148
+ | `getResponses(taskId, params?)` | `Promise<TriageResponsesResult>` | List responses for a task |
149
+ | `createSubmissionFile(taskId, file)` | `Promise<TriageLinkedFileUploadResponse>` | Attach file to submission |
150
+ | `createResponseFile(responseId, file)` | `Promise<TriageLinkedFileUploadResponse>` | Attach file to response |
151
+ | `getFile(fileId)` | `Promise<TriageFile>` | Get file metadata + presigned URL |
152
+ | `getSubmissionFiles(taskId, params?)` | `Promise<TriageFilesResponse>` | List submission files |
153
+ | `getResponseFiles(responseId, params?)` | `Promise<TriageFilesResponse>` | List response files |
154
+
155
+ ### `usePastSubmissions(options?)`
156
+
157
+ Stateful hook backing past-submissions workflows.
158
+
159
+ ```tsx
160
+ const {
161
+ submissions,
162
+ selectedTask,
163
+ responses,
164
+ responseDraft,
165
+ setResponseDraft,
166
+ sendResponse,
167
+ } = usePastSubmissions();
168
+ ```
169
+
170
+ Deep-link example:
171
+
172
+ ```tsx
173
+ const taskIdFromQuery = new URLSearchParams(location.search).get("triageTaskId") ?? undefined;
174
+ const past = usePastSubmissions({ triageTaskId: taskIdFromQuery });
175
+ ```
176
+
177
+ `triageTaskId` preselects a task in the modal workflow and fetches it directly when it is not part of the currently loaded page.
178
+
179
+ ## Migration Notes
180
+
181
+ - Transcript polling/UI has been removed from `@taskp3/react`.
182
+ - If you previously used transcript helpers/components, migrate that behavior to your own app-level API/UI implementation.
183
+
184
+ ### `useChangelog(options?)`
185
+
186
+ Fetches paginated changelog entries.
187
+
188
+ ```tsx
189
+ const { entries, isLoading, error, hasMore, loadMore } = useChangelog({ limit: 10 });
190
+ ```
191
+
192
+ | Option | Type | Default | Description |
193
+ |---|---|---|---|
194
+ | `limit` | `number` | `10` | Entries per page |
195
+ | `types` | `string` | — | Comma-separated type filter |
196
+
197
+ | Return | Type | Description |
198
+ |---|---|---|
199
+ | `entries` | `ChangelogEntry[]` | Loaded entries |
200
+ | `isLoading` | `boolean` | True during fetch |
201
+ | `error` | `Error \| null` | Fetch error, if any |
202
+ | `hasMore` | `boolean` | More pages available |
203
+ | `loadMore` | `() => void` | Load next page |
204
+
205
+ ### `useChangelogCodeChanges(options)`
206
+
207
+ Fetches paginated code changes for a single changelog entry.
208
+
209
+ ```tsx
210
+ const { codeChanges, isLoading, hasMore, loadMore } = useChangelogCodeChanges({
211
+ entryId: entry.id,
212
+ initialChanges: entry.codeChanges,
213
+ });
214
+ ```
215
+
216
+ | Option | Type | Required | Description |
217
+ |---|---|---|---|
218
+ | `entryId` | `string` | Yes | Changelog entry ID |
219
+ | `initialChanges` | `ChangelogCodeChange[]` | No | Pre-loaded changes (avoids duplicate fetch) |
220
+ | `limit` | `number` | No | Changes per page (default `25`) |
221
+
222
+ ## Theming
223
+
224
+ Pass a `theme` object to `<TaskP3Provider>`. Zero external CSS — all styles are injected automatically.
225
+
226
+ ```tsx
227
+ <TaskP3Provider
228
+ apiUrl="https://your-app.com/api/triage"
229
+ theme={{
230
+ primaryColor: "#6366f1",
231
+ primaryHoverColor: "#4f46e5",
232
+ textOnPrimary: "#ffffff",
233
+ fontFamily: "Inter, sans-serif",
234
+ borderRadius: 12,
235
+ zIndex: 10000,
236
+ panelWidth: 440,
237
+ }}
238
+ >
239
+ {children}
240
+ </TaskP3Provider>
241
+ ```
242
+
243
+ | Property | Type | Default | Description |
244
+ |---|---|---|---|
245
+ | `primaryColor` | `string` | `"#1F93FF"` | Primary brand color |
246
+ | `primaryHoverColor` | `string` | `"#0E7EE3"` | Hover state |
247
+ | `textOnPrimary` | `string` | `"#ffffff"` | Text color on primary backgrounds |
248
+ | `fontFamily` | `string` | System font stack | CSS font-family |
249
+ | `borderRadius` | `number` | `8` | Border radius in px |
250
+ | `zIndex` | `number` | `9999` | Base z-index for floating elements |
251
+ | `panelWidth` | `number` | `420` | Triage panel width in px |
252
+
253
+ ## Related Packages
254
+
255
+ | Package | Description |
256
+ |---|---|
257
+ | [`@taskp3/sdk`](https://www.npmjs.com/package/@taskp3/sdk) | Server-side client + Express adapter |
258
+ | [`@taskp3/react`](https://www.npmjs.com/package/@taskp3/react) | React components — `<TriageButton>`, `<Changelog>`, `<WhatsNew>` |
@@ -0,0 +1,46 @@
1
+ import type { ChangelogEntry, ChangelogCodeChange } from "@taskp3/sdk";
2
+ export interface UseChangelogOptions {
3
+ limit?: number;
4
+ types?: string;
5
+ codeChangesLimit?: number;
6
+ enabled?: boolean;
7
+ }
8
+ export interface UseChangelogResult {
9
+ entries: ChangelogEntry[];
10
+ isLoading: boolean;
11
+ error: Error | null;
12
+ hasMore: boolean;
13
+ loadMore: () => void;
14
+ }
15
+ /**
16
+ * Fetches changelog entries with pagination.
17
+ *
18
+ * ```tsx
19
+ * const { entries, isLoading, hasMore, loadMore } = useChangelog({ limit: 10 });
20
+ * ```
21
+ */
22
+ export declare function useChangelog(options?: UseChangelogOptions): UseChangelogResult;
23
+ export interface UseChangelogCodeChangesOptions {
24
+ entryId: string;
25
+ initialChanges?: ChangelogCodeChange[];
26
+ limit?: number;
27
+ enabled?: boolean;
28
+ }
29
+ export interface UseChangelogCodeChangesResult {
30
+ codeChanges: ChangelogCodeChange[];
31
+ isLoading: boolean;
32
+ hasMore: boolean;
33
+ loadMore: () => void;
34
+ }
35
+ /**
36
+ * Fetches paginated code changes for a single changelog entry.
37
+ *
38
+ * ```tsx
39
+ * const { codeChanges, hasMore, loadMore } = useChangelogCodeChanges({
40
+ * entryId: entry.id,
41
+ * initialChanges: entry.codeChanges,
42
+ * });
43
+ * ```
44
+ */
45
+ export declare function useChangelogCodeChanges(options: UseChangelogCodeChangesOptions): UseChangelogCodeChangesResult;
46
+ //# sourceMappingURL=changelog-hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changelog-hooks.d.ts","sourceRoot":"","sources":["../src/changelog-hooks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,cAAc,EAEd,mBAAmB,EACpB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,kBAAkB,CA4GpB;AAED,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,6BAA6B;IAC5C,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,8BAA8B,GACtC,6BAA6B,CAwD/B"}
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useChangelog = useChangelog;
4
+ exports.useChangelogCodeChanges = useChangelogCodeChanges;
5
+ const react_1 = require("react");
6
+ const context_1 = require("./context");
7
+ const fetch_1 = require("./fetch");
8
+ /**
9
+ * Fetches changelog entries with pagination.
10
+ *
11
+ * ```tsx
12
+ * const { entries, isLoading, hasMore, loadMore } = useChangelog({ limit: 10 });
13
+ * ```
14
+ */
15
+ function useChangelog(options = {}) {
16
+ const { apiUrl, getHeaders, fetcher } = (0, context_1.useTaskP3Context)();
17
+ const { limit = 10, types, codeChangesLimit, enabled = true } = options;
18
+ const [entries, setEntries] = (0, react_1.useState)([]);
19
+ const [page, setPage] = (0, react_1.useState)(1);
20
+ const [totalPages, setTotalPages] = (0, react_1.useState)(1);
21
+ const [isLoading, setIsLoading] = (0, react_1.useState)(true);
22
+ const [error, setError] = (0, react_1.useState)(null);
23
+ const isFetching = (0, react_1.useRef)(false);
24
+ const depsRef = (0, react_1.useRef)({
25
+ apiUrl,
26
+ getHeaders,
27
+ fetcher,
28
+ limit,
29
+ types,
30
+ codeChangesLimit,
31
+ enabled,
32
+ });
33
+ depsRef.current = {
34
+ apiUrl,
35
+ getHeaders,
36
+ fetcher,
37
+ limit,
38
+ types,
39
+ codeChangesLimit,
40
+ enabled,
41
+ };
42
+ const fetchPage = (0, react_1.useCallback)(async (p) => {
43
+ if (isFetching.current)
44
+ return;
45
+ isFetching.current = true;
46
+ const { apiUrl: au, getHeaders: gh, fetcher: f, limit: lim, types: t, codeChangesLimit: ccl, enabled: en, } = depsRef.current;
47
+ if (!en) {
48
+ setEntries([]);
49
+ setTotalPages(1);
50
+ setPage(1);
51
+ setIsLoading(false);
52
+ isFetching.current = false;
53
+ return;
54
+ }
55
+ try {
56
+ const query = new URLSearchParams({
57
+ page: String(p),
58
+ limit: String(lim),
59
+ });
60
+ if (t)
61
+ query.set("types", t);
62
+ if (ccl !== undefined)
63
+ query.set("codeChangesLimit", String(ccl));
64
+ const res = await (0, fetch_1.p3Fetch)(`${au}/changelog?${query}`, { method: "GET" }, gh, f);
65
+ const data = await res.json();
66
+ setEntries((prev) => p === 1 ? data.entries : [...prev, ...data.entries]);
67
+ setTotalPages(data.totalPages);
68
+ setPage(p);
69
+ setError(null);
70
+ }
71
+ catch (err) {
72
+ setError(err instanceof Error ? err : new Error(String(err)));
73
+ }
74
+ finally {
75
+ setIsLoading(false);
76
+ isFetching.current = false;
77
+ }
78
+ }, []);
79
+ (0, react_1.useEffect)(() => {
80
+ if (!enabled) {
81
+ setEntries([]);
82
+ setPage(1);
83
+ setTotalPages(1);
84
+ setIsLoading(false);
85
+ setError(null);
86
+ return;
87
+ }
88
+ setIsLoading(true);
89
+ setEntries([]);
90
+ fetchPage(1);
91
+ }, [apiUrl, limit, types, codeChangesLimit, enabled, fetchPage]);
92
+ const loadMore = (0, react_1.useCallback)(() => {
93
+ if (!enabled)
94
+ return;
95
+ if (page < totalPages && !isFetching.current) {
96
+ fetchPage(page + 1);
97
+ }
98
+ }, [page, totalPages, fetchPage, enabled]);
99
+ return {
100
+ entries,
101
+ isLoading,
102
+ error,
103
+ hasMore: page < totalPages,
104
+ loadMore,
105
+ };
106
+ }
107
+ /**
108
+ * Fetches paginated code changes for a single changelog entry.
109
+ *
110
+ * ```tsx
111
+ * const { codeChanges, hasMore, loadMore } = useChangelogCodeChanges({
112
+ * entryId: entry.id,
113
+ * initialChanges: entry.codeChanges,
114
+ * });
115
+ * ```
116
+ */
117
+ function useChangelogCodeChanges(options) {
118
+ const { apiUrl, getHeaders, fetcher } = (0, context_1.useTaskP3Context)();
119
+ const { entryId, initialChanges = [], limit = 25, enabled = true } = options;
120
+ const [extra, setExtra] = (0, react_1.useState)([]);
121
+ const [page, setPage] = (0, react_1.useState)(1);
122
+ const [hasMore, setHasMore] = (0, react_1.useState)(false);
123
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
124
+ const isFetching = (0, react_1.useRef)(false);
125
+ const initialIds = (0, react_1.useRef)(new Set(initialChanges.map((c) => c.id)));
126
+ const loadMore = (0, react_1.useCallback)(async () => {
127
+ if (isFetching.current)
128
+ return;
129
+ if (!enabled || !entryId)
130
+ return;
131
+ isFetching.current = true;
132
+ setIsLoading(true);
133
+ try {
134
+ const nextPage = page + 1;
135
+ const query = new URLSearchParams({
136
+ page: String(nextPage),
137
+ limit: String(limit),
138
+ });
139
+ const res = await (0, fetch_1.p3Fetch)(`${apiUrl}/changelog/${entryId}/code-changes?${query}`, { method: "GET" }, getHeaders, fetcher);
140
+ const data = await res.json();
141
+ const unique = data.codeChanges.filter((c) => !initialIds.current.has(c.id));
142
+ setExtra((prev) => [...prev, ...unique]);
143
+ setPage(nextPage);
144
+ setHasMore(nextPage < data.totalPages);
145
+ }
146
+ catch {
147
+ // non-fatal
148
+ }
149
+ finally {
150
+ setIsLoading(false);
151
+ isFetching.current = false;
152
+ }
153
+ }, [apiUrl, getHeaders, fetcher, entryId, limit, page, enabled]);
154
+ (0, react_1.useEffect)(() => {
155
+ setExtra([]);
156
+ setPage(1);
157
+ setHasMore(false);
158
+ setIsLoading(false);
159
+ }, [entryId, enabled]);
160
+ const codeChanges = [...initialChanges, ...extra];
161
+ return { codeChanges, isLoading, hasMore, loadMore };
162
+ }
163
+ //# sourceMappingURL=changelog-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changelog-hooks.js","sourceRoot":"","sources":["../src/changelog-hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type UseChangelogOptions } from "./changelog-hooks";
2
+ export interface ChangelogProps extends UseChangelogOptions {
3
+ className?: string;
4
+ emptyText?: string;
5
+ }
6
+ /**
7
+ * Drop-in changelog feed.
8
+ *
9
+ * ```tsx
10
+ * <Changelog limit={10} />
11
+ * ```
12
+ */
13
+ export declare function Changelog({ className, emptyText, ...opts }: ChangelogProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function TypeChip({ type }: {
15
+ type: string;
16
+ }): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=changelog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../src/changelog.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAC;AA0B3B,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,SAAuC,EACvC,GAAG,IAAI,EACR,EAAE,cAAc,2CAoDhB;AAmED,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,2CAOlD"}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Changelog = Changelog;
4
+ exports.TypeChip = TypeChip;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
7
+ const changelog_hooks_1 = require("./changelog-hooks");
8
+ const TYPE_COLORS = {
9
+ "New Feature": { bg: "#dcfce7", fg: "#15803d" },
10
+ "Bug fix": { bg: "#fef3c7", fg: "#b45309" },
11
+ Improvement: { bg: "#dbeafe", fg: "#1d4ed8" },
12
+ Deprecation: { bg: "#f3f4f6", fg: "#4b5563" },
13
+ };
14
+ function chipColor(type) {
15
+ return TYPE_COLORS[type] ?? { bg: "#f3f4f6", fg: "#374151" };
16
+ }
17
+ function formatDate(iso) {
18
+ try {
19
+ return new Intl.DateTimeFormat("en-US", {
20
+ month: "long",
21
+ day: "numeric",
22
+ year: "numeric",
23
+ }).format(new Date(iso));
24
+ }
25
+ catch {
26
+ return iso;
27
+ }
28
+ }
29
+ /**
30
+ * Drop-in changelog feed.
31
+ *
32
+ * ```tsx
33
+ * <Changelog limit={10} />
34
+ * ```
35
+ */
36
+ function Changelog({ className, emptyText = "No changelog entries yet.", ...opts }) {
37
+ const { entries, isLoading, error, hasMore, loadMore } = (0, changelog_hooks_1.useChangelog)(opts);
38
+ if (isLoading && entries.length === 0) {
39
+ return ((0, jsx_runtime_1.jsx)("div", { className: `p3-cl ${className ?? ""}`, children: (0, jsx_runtime_1.jsx)("div", { className: "p3-cl-loading", children: (0, jsx_runtime_1.jsx)(Spinner, {}) }) }));
40
+ }
41
+ if (error) {
42
+ return ((0, jsx_runtime_1.jsx)("div", { className: `p3-cl ${className ?? ""}`, children: (0, jsx_runtime_1.jsx)("p", { className: "p3-cl-empty", children: "Failed to load changelog." }) }));
43
+ }
44
+ if (entries.length === 0) {
45
+ return ((0, jsx_runtime_1.jsx)("div", { className: `p3-cl ${className ?? ""}`, children: (0, jsx_runtime_1.jsx)("p", { className: "p3-cl-empty", children: emptyText }) }));
46
+ }
47
+ const sentinelRef = (0, react_1.useRef)(null);
48
+ (0, react_1.useEffect)(() => {
49
+ if (!hasMore || isLoading || !sentinelRef.current)
50
+ return;
51
+ const observer = new IntersectionObserver(([e]) => { if (e.isIntersecting)
52
+ loadMore(); }, { threshold: 0.1, rootMargin: "200px" });
53
+ observer.observe(sentinelRef.current);
54
+ return () => observer.disconnect();
55
+ }, [hasMore, isLoading, loadMore]);
56
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `p3-cl ${className ?? ""}`, children: [entries.map((entry) => ((0, jsx_runtime_1.jsx)(EntryCard, { entry: entry }, entry.id))), hasMore && (0, jsx_runtime_1.jsx)("div", { ref: sentinelRef, style: { height: 1 } }), isLoading && entries.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "p3-cl-loading", style: { padding: "12px 0" }, children: (0, jsx_runtime_1.jsx)(Spinner, { size: 18 }) }))] }));
57
+ }
58
+ function EntryCard({ entry }) {
59
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "p3-cl-entry", children: [(0, jsx_runtime_1.jsxs)("div", { className: "p3-cl-entry-header", children: [(0, jsx_runtime_1.jsxs)("h3", { className: "p3-cl-entry-date", children: ["Release ", formatDate(entry.releaseDate)] }), entry.types.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "p3-cl-chips", children: entry.types.map((t) => ((0, jsx_runtime_1.jsx)(TypeChip, { type: t }, t))) })), entry.description && ((0, jsx_runtime_1.jsx)("p", { className: "p3-cl-entry-desc", children: entry.description }))] }), (0, jsx_runtime_1.jsx)(CodeChangesList, { entry: entry })] }));
60
+ }
61
+ function CodeChangesList({ entry }) {
62
+ const { codeChanges, hasMore, loadMore, isLoading } = (0, changelog_hooks_1.useChangelogCodeChanges)({
63
+ entryId: entry.id,
64
+ initialChanges: entry.codeChanges ?? [],
65
+ });
66
+ const sentinelRef = (0, react_1.useRef)(null);
67
+ (0, react_1.useEffect)(() => {
68
+ if (!hasMore || isLoading || !sentinelRef.current)
69
+ return;
70
+ const observer = new IntersectionObserver(([e]) => { if (e.isIntersecting)
71
+ loadMore(); }, { threshold: 0.1, rootMargin: "100px" });
72
+ observer.observe(sentinelRef.current);
73
+ return () => observer.disconnect();
74
+ }, [hasMore, isLoading, loadMore]);
75
+ if (codeChanges.length === 0)
76
+ return null;
77
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "p3-cl-changes", children: [(0, jsx_runtime_1.jsx)("h4", { className: "p3-cl-changes-title", children: "What's Changed" }), (0, jsx_runtime_1.jsx)("ul", { className: "p3-cl-changes-list", children: codeChanges.map((c) => ((0, jsx_runtime_1.jsxs)("li", { className: "p3-cl-change", children: [(0, jsx_runtime_1.jsx)("span", { className: "p3-cl-change-chip", children: (0, jsx_runtime_1.jsx)(TypeChip, { type: c.type }) }), (0, jsx_runtime_1.jsx)("span", { className: "p3-cl-change-desc", children: c.description })] }, c.id))) }), hasMore && (0, jsx_runtime_1.jsx)("div", { ref: sentinelRef, style: { height: 1 } }), isLoading && ((0, jsx_runtime_1.jsx)("div", { className: "p3-cl-loading", style: { padding: "8px 0" }, children: (0, jsx_runtime_1.jsx)(Spinner, { size: 16 }) }))] }));
78
+ }
79
+ function TypeChip({ type }) {
80
+ const c = chipColor(type);
81
+ return ((0, jsx_runtime_1.jsx)("span", { className: "p3-cl-chip", style: { background: c.bg, color: c.fg }, children: type }));
82
+ }
83
+ function Spinner({ size = 20 }) {
84
+ return ((0, jsx_runtime_1.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", style: { animation: "p3-spin 0.8s linear infinite" }, children: [(0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "3", strokeDasharray: "50 20", strokeLinecap: "round", opacity: 0.3 }), (0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "3", strokeDasharray: "15 55", strokeLinecap: "round" })] }));
85
+ }
86
+ //# sourceMappingURL=changelog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../src/changelog.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ export type P3Fetcher = (url: string, init: RequestInit) => Promise<Response>;
3
+ export interface TaskP3Theme {
4
+ primaryColor?: string;
5
+ primaryHoverColor?: string;
6
+ textOnPrimary?: string;
7
+ fontFamily?: string;
8
+ borderRadius?: number;
9
+ zIndex?: number;
10
+ panelWidth?: number;
11
+ }
12
+ export interface TaskP3ContextValue {
13
+ apiUrl: string;
14
+ theme: Required<TaskP3Theme>;
15
+ getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
16
+ fetcher: P3Fetcher;
17
+ }
18
+ export interface TaskP3ProviderProps {
19
+ /** Full URL where createTriageRouter is mounted, e.g. "https://app.example.com/api/triage" */
20
+ apiUrl?: string;
21
+ /** @deprecated Use `apiUrl` instead. */
22
+ basePath?: string;
23
+ /** Visual customisation */
24
+ theme?: TaskP3Theme;
25
+ /** Optional fn that returns extra headers (e.g. Authorization) for every request */
26
+ getHeaders?: () => Record<string, string> | Promise<Record<string, string>>;
27
+ /** Optional custom fetch implementation. Receives the same args as native `fetch`. Defaults to `globalThis.fetch` with `credentials: "same-origin"`. */
28
+ fetcher?: P3Fetcher;
29
+ children: React.ReactNode;
30
+ }
31
+ export declare function TaskP3Provider({ apiUrl, basePath, theme, getHeaders, fetcher, children, }: TaskP3ProviderProps): import("react/jsx-runtime").JSX.Element;
32
+ export declare function useTaskP3Context(): TaskP3ContextValue;
33
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAGf,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE9E,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5E,OAAO,EAAE,SAAS,CAAC;CACpB;AAeD,MAAM,WAAW,mBAAmB;IAClC,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5E,wJAAwJ;IACxJ,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAID,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,QAAQ,EACR,KAAK,EACL,UAAU,EACV,OAAO,EACP,QAAQ,GACT,EAAE,mBAAmB,2CA+DrB;AAED,wBAAgB,gBAAgB,IAAI,kBAAkB,CASrD"}