@webority/support-react 0.13.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/LICENSE +5 -0
- package/README.md +120 -0
- package/dist/support-react.js +1225 -0
- package/dist/types/ReportIssue.d.ts +23 -0
- package/dist/types/SupportCenter.d.ts +15 -0
- package/dist/types/SupportContact.d.ts +10 -0
- package/dist/types/SupportProvider.d.ts +11 -0
- package/dist/types/client.d.ts +102 -0
- package/dist/types/components/AttachmentField.d.ts +22 -0
- package/dist/types/components/AttachmentThumb.d.ts +16 -0
- package/dist/types/components/MessageThread.d.ts +17 -0
- package/dist/types/components/NewTicketModal.d.ts +19 -0
- package/dist/types/components/RatingPanel.d.ts +20 -0
- package/dist/types/components/ReplyBox.d.ts +16 -0
- package/dist/types/components/TicketDetail.d.ts +13 -0
- package/dist/types/components/TicketForm.d.ts +28 -0
- package/dist/types/components/TicketList.d.ts +17 -0
- package/dist/types/context.d.ts +54 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/lib/files.d.ts +31 -0
- package/dist/types/lib/format.d.ts +13 -0
- package/dist/types/lib/status.d.ts +5 -0
- package/dist/types/lib/url.d.ts +20 -0
- package/package.json +64 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A "Report an issue" button. It takes a screenshot of the page first, then opens a dialog
|
|
3
|
+
* where the person describes the problem, reviews or removes the screenshot, and adds more
|
|
4
|
+
* images. The ticket carries the page address, the browser and the product version.
|
|
5
|
+
*
|
|
6
|
+
* @param {object} props
|
|
7
|
+
* @param {string} [props.label="Report an issue"] The button text.
|
|
8
|
+
* @param {boolean} [props.floating=false] Pin the button to the bottom corner of the screen.
|
|
9
|
+
* @param {string} [props.defaultCategory="Bug report"] Preselected when the config lists it.
|
|
10
|
+
* @param {string} [props.appVersion] The product build, recorded on the ticket.
|
|
11
|
+
* @param {(id: string) => string} [props.getTicketHref] Where the new ticket can be opened; shows a View ticket link.
|
|
12
|
+
* @param {(ticket: any) => void} [props.onOpenTicket] Called by the View ticket button when there is no href.
|
|
13
|
+
* @param {(ticket: any) => void} [props.onCreated] Called once the ticket is raised.
|
|
14
|
+
*/
|
|
15
|
+
export default function ReportIssue({ label, floating, defaultCategory, appVersion, getTicketHref, onOpenTicket, onCreated, }: {
|
|
16
|
+
label?: string;
|
|
17
|
+
floating?: boolean;
|
|
18
|
+
defaultCategory?: string;
|
|
19
|
+
appVersion?: string;
|
|
20
|
+
getTicketHref?: (id: string) => string;
|
|
21
|
+
onOpenTicket?: (ticket: any) => void;
|
|
22
|
+
onCreated?: (ticket: any) => void;
|
|
23
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The customer's support page: their tickets, one ticket's conversation, and a New ticket
|
|
3
|
+
* dialog. Opens the ticket named by `?ticket=<id>` in the address (support emails link there),
|
|
4
|
+
* or `initialTicketId` when given, and keeps that parameter in step as tickets open and close.
|
|
5
|
+
*
|
|
6
|
+
* @param {object} props
|
|
7
|
+
* @param {string} [props.initialTicketId] Open this ticket first. Wins over the address.
|
|
8
|
+
* @param {string} [props.defaultCategory] Preselected in the New ticket form when the config lists it.
|
|
9
|
+
* @param {string} [props.appVersion] The product build, recorded on new tickets.
|
|
10
|
+
*/
|
|
11
|
+
export default function SupportCenter({ initialTicketId, defaultCategory, appVersion }: {
|
|
12
|
+
initialTicketId?: string;
|
|
13
|
+
defaultCategory?: string;
|
|
14
|
+
appVersion?: string;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How to reach support: the email address with a copy button, the phone number as a call link,
|
|
3
|
+
* and the hours. A field the product has not set is left out; nothing renders when none is set.
|
|
4
|
+
*
|
|
5
|
+
* @param {object} props
|
|
6
|
+
* @param {string} [props.className]
|
|
7
|
+
*/
|
|
8
|
+
export default function SupportContact({ className }: {
|
|
9
|
+
className?: string;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Makes a support client available to every support component and hook below it.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} props
|
|
5
|
+
* @param {import('./client.js').SupportClient} props.client From `createSupportClient(http)`.
|
|
6
|
+
* @param {import('react').ReactNode} props.children
|
|
7
|
+
*/
|
|
8
|
+
export default function SupportProvider({ client, children }: {
|
|
9
|
+
client: import('./client.js').SupportClient;
|
|
10
|
+
children: import('react').ReactNode;
|
|
11
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A failed support request. `message` is written for the person and is safe to show as-is.
|
|
3
|
+
*/
|
|
4
|
+
export declare class SupportApiError extends Error {
|
|
5
|
+
code: string;
|
|
6
|
+
status: number;
|
|
7
|
+
/**
|
|
8
|
+
* @param {string} code Machine-readable reason from the API, or "network" when no response arrived.
|
|
9
|
+
* @param {string} message The sentence to show the person.
|
|
10
|
+
* @param {number} [status] HTTP status, when a response arrived.
|
|
11
|
+
*/
|
|
12
|
+
constructor(code: string, message: string, status?: number);
|
|
13
|
+
}
|
|
14
|
+
export type SupportHttp = {
|
|
15
|
+
get: (url: string, config?: object) => Promise<{
|
|
16
|
+
data: any;
|
|
17
|
+
}>;
|
|
18
|
+
post: (url: string, data?: any, config?: object) => Promise<{
|
|
19
|
+
data: any;
|
|
20
|
+
}>;
|
|
21
|
+
};
|
|
22
|
+
export type NewTicketInput = {
|
|
23
|
+
category: string;
|
|
24
|
+
subject: string;
|
|
25
|
+
body: string;
|
|
26
|
+
pageUrl?: string;
|
|
27
|
+
userAgent?: string;
|
|
28
|
+
appVersion?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Files the person picked, pasted or dropped.
|
|
31
|
+
*/
|
|
32
|
+
files?: Blob[];
|
|
33
|
+
/**
|
|
34
|
+
* Page captures taken by the report-an-issue widget.
|
|
35
|
+
*/
|
|
36
|
+
screenshots?: Blob[];
|
|
37
|
+
};
|
|
38
|
+
export type ReplyInput = {
|
|
39
|
+
body: string;
|
|
40
|
+
files?: Blob[];
|
|
41
|
+
screenshots?: Blob[];
|
|
42
|
+
};
|
|
43
|
+
export type RatingInput = {
|
|
44
|
+
satisfaction: "Satisfied" | "Unsatisfied";
|
|
45
|
+
comment?: string;
|
|
46
|
+
};
|
|
47
|
+
export type SupportClient = {
|
|
48
|
+
getConfig: () => Promise<any>;
|
|
49
|
+
listTickets: () => Promise<any[]>;
|
|
50
|
+
getTicket: (id: string) => Promise<any>;
|
|
51
|
+
createTicket: (input: NewTicketInput) => Promise<any>;
|
|
52
|
+
reply: (id: string, input: ReplyInput) => Promise<any>;
|
|
53
|
+
reopen: (id: string) => Promise<any>;
|
|
54
|
+
rate: (id: string, input: RatingInput) => Promise<any>;
|
|
55
|
+
fetchAttachment: (id: string) => Promise<Blob>;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* @typedef {object} SupportHttp An axios-like HTTP client that already carries the bearer token.
|
|
59
|
+
* @property {(url: string, config?: object) => Promise<{ data: any }>} get
|
|
60
|
+
* @property {(url: string, data?: any, config?: object) => Promise<{ data: any }>} post
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* @typedef {object} NewTicketInput
|
|
64
|
+
* @property {string} category
|
|
65
|
+
* @property {string} subject
|
|
66
|
+
* @property {string} body
|
|
67
|
+
* @property {string} [pageUrl]
|
|
68
|
+
* @property {string} [userAgent]
|
|
69
|
+
* @property {string} [appVersion]
|
|
70
|
+
* @property {Blob[]} [files] Files the person picked, pasted or dropped.
|
|
71
|
+
* @property {Blob[]} [screenshots] Page captures taken by the report-an-issue widget.
|
|
72
|
+
*/
|
|
73
|
+
/**
|
|
74
|
+
* @typedef {object} ReplyInput
|
|
75
|
+
* @property {string} body
|
|
76
|
+
* @property {Blob[]} [files]
|
|
77
|
+
* @property {Blob[]} [screenshots]
|
|
78
|
+
*/
|
|
79
|
+
/**
|
|
80
|
+
* @typedef {object} RatingInput
|
|
81
|
+
* @property {"Satisfied"|"Unsatisfied"} satisfaction
|
|
82
|
+
* @property {string} [comment]
|
|
83
|
+
*/
|
|
84
|
+
/**
|
|
85
|
+
* @typedef {object} SupportClient
|
|
86
|
+
* @property {() => Promise<any>} getConfig
|
|
87
|
+
* @property {() => Promise<any[]>} listTickets
|
|
88
|
+
* @property {(id: string) => Promise<any>} getTicket
|
|
89
|
+
* @property {(input: NewTicketInput) => Promise<any>} createTicket
|
|
90
|
+
* @property {(id: string, input: ReplyInput) => Promise<any>} reply
|
|
91
|
+
* @property {(id: string) => Promise<any>} reopen
|
|
92
|
+
* @property {(id: string, input: RatingInput) => Promise<any>} rate
|
|
93
|
+
* @property {(id: string) => Promise<Blob>} fetchAttachment
|
|
94
|
+
*/
|
|
95
|
+
/**
|
|
96
|
+
* Binds the support HTTP contract to the product's own authenticated client.
|
|
97
|
+
*
|
|
98
|
+
* @param {SupportHttp} http The product's axios-like instance (bearer token and refresh already wired).
|
|
99
|
+
* @param {string} [basePath="/api/support"] The prefix the API maps the support endpoints under.
|
|
100
|
+
* @returns {SupportClient}
|
|
101
|
+
*/
|
|
102
|
+
export declare function createSupportClient(http: SupportHttp, basePath?: string): SupportClient;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Picked, dropped or pasted files for a message, limited to what the support config allows.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} props
|
|
5
|
+
* @param {string} [props.id]
|
|
6
|
+
* @param {string} [props.label="Attachments"]
|
|
7
|
+
* @param {File[]} props.files
|
|
8
|
+
* @param {(files: File[]) => void} props.onChange
|
|
9
|
+
* @param {{ maxAttachmentBytes?: number, allowedContentTypes?: string[] }|null} [props.config]
|
|
10
|
+
* @param {string} [props.error]
|
|
11
|
+
*/
|
|
12
|
+
export default function AttachmentField({ id, label, files, onChange, config, error }: {
|
|
13
|
+
id?: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
files: File[];
|
|
16
|
+
onChange: (files: File[]) => void;
|
|
17
|
+
config?: {
|
|
18
|
+
maxAttachmentBytes?: number;
|
|
19
|
+
allowedContentTypes?: string[];
|
|
20
|
+
} | null;
|
|
21
|
+
error?: string;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One attachment on a message. The bytes need the bearer token, so they are fetched through the
|
|
3
|
+
* support client into an object URL that is revoked when the thumbnail goes away.
|
|
4
|
+
*
|
|
5
|
+
* @param {object} props
|
|
6
|
+
* @param {{ id: string, fileName: string, contentType: string, sizeBytes: number, kind: string }} props.attachment
|
|
7
|
+
*/
|
|
8
|
+
export default function AttachmentThumb({ attachment }: {
|
|
9
|
+
attachment: {
|
|
10
|
+
id: string;
|
|
11
|
+
fileName: string;
|
|
12
|
+
contentType: string;
|
|
13
|
+
sizeBytes: number;
|
|
14
|
+
kind: string;
|
|
15
|
+
};
|
|
16
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A ticket's conversation. The customer's own messages sit on the right, the support team's on
|
|
3
|
+
* the left, and status or assignment events show as small centred lines.
|
|
4
|
+
*
|
|
5
|
+
* @param {object} props
|
|
6
|
+
* @param {{ id: string, authorKind: string, authorName: string|null, body: string, createdDateTimeUtc: string, attachments: any[] }[]} props.messages
|
|
7
|
+
*/
|
|
8
|
+
export default function MessageThread({ messages }: {
|
|
9
|
+
messages: {
|
|
10
|
+
id: string;
|
|
11
|
+
authorKind: string;
|
|
12
|
+
authorName: string | null;
|
|
13
|
+
body: string;
|
|
14
|
+
createdDateTimeUtc: string;
|
|
15
|
+
attachments: any[];
|
|
16
|
+
}[];
|
|
17
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The New ticket dialog.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} props
|
|
5
|
+
* @param {boolean} props.open
|
|
6
|
+
* @param {() => void} props.onClose
|
|
7
|
+
* @param {(ticket: any) => void} props.onCreated Receives the new ticket.
|
|
8
|
+
* @param {any} props.config
|
|
9
|
+
* @param {string} [props.defaultCategory]
|
|
10
|
+
* @param {string} [props.appVersion] Recorded on the ticket so support knows which build you were on.
|
|
11
|
+
*/
|
|
12
|
+
export default function NewTicketModal({ open, onClose, onCreated, config, defaultCategory, appVersion }: {
|
|
13
|
+
open: boolean;
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
onCreated: (ticket: any) => void;
|
|
16
|
+
config: any;
|
|
17
|
+
defaultCategory?: string;
|
|
18
|
+
appVersion?: string;
|
|
19
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asks whether a settled ticket solved the problem, or shows the answer already given.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} props
|
|
5
|
+
* @param {"Satisfied"|"Unsatisfied"|null} [props.satisfaction] The rating already given, if any.
|
|
6
|
+
* @param {string|null} [props.comment] The comment given with it.
|
|
7
|
+
* @param {boolean} [props.canRate=false]
|
|
8
|
+
* @param {number} [props.commentMaxLength] From the support config.
|
|
9
|
+
* @param {(input: { satisfaction: "Satisfied"|"Unsatisfied", comment: string }) => Promise<unknown>} props.onRate
|
|
10
|
+
*/
|
|
11
|
+
export default function RatingPanel({ satisfaction, comment, canRate, commentMaxLength, onRate }: {
|
|
12
|
+
satisfaction?: "Satisfied" | "Unsatisfied" | null;
|
|
13
|
+
comment?: string | null;
|
|
14
|
+
canRate?: boolean;
|
|
15
|
+
commentMaxLength?: number;
|
|
16
|
+
onRate: (input: {
|
|
17
|
+
satisfaction: "Satisfied" | "Unsatisfied";
|
|
18
|
+
comment: string;
|
|
19
|
+
}) => Promise<unknown>;
|
|
20
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The customer's reply to a ticket, with attachments. Images pasted into the message are attached.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} props
|
|
5
|
+
* @param {(input: { body: string, files: File[] }) => Promise<unknown>} props.onSend Rejects with a SupportApiError on failure.
|
|
6
|
+
* @param {any} [props.config] The support config, for the text and attachment limits.
|
|
7
|
+
* @param {boolean} [props.reopens=false] The ticket is settled, so a reply reopens it.
|
|
8
|
+
*/
|
|
9
|
+
export default function ReplyBox({ onSend, config, reopens }: {
|
|
10
|
+
onSend: (input: {
|
|
11
|
+
body: string;
|
|
12
|
+
files: File[];
|
|
13
|
+
}) => Promise<unknown>;
|
|
14
|
+
config?: any;
|
|
15
|
+
reopens?: boolean;
|
|
16
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One ticket: its facts, the conversation, and what the customer can do next.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} props
|
|
5
|
+
* @param {string} props.ticketId
|
|
6
|
+
* @param {() => void} props.onBack Return to the ticket list.
|
|
7
|
+
* @param {() => void} [props.onChanged] The ticket changed (reply, reopen, rating), so a list can refresh.
|
|
8
|
+
*/
|
|
9
|
+
export default function TicketDetail({ ticketId, onBack, onChanged }: {
|
|
10
|
+
ticketId: string;
|
|
11
|
+
onBack: () => void;
|
|
12
|
+
onChanged?: () => void;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fields of a new ticket: category, subject, message and attachments. Validates against the
|
|
3
|
+
* support config before anything uploads. The submit button lives outside (a modal footer), tied
|
|
4
|
+
* to this form by `id`.
|
|
5
|
+
*
|
|
6
|
+
* @param {object} props
|
|
7
|
+
* @param {string} props.id The form's id, for a submit button outside it.
|
|
8
|
+
* @param {any} props.config The support config: categories, text limits and attachment limits.
|
|
9
|
+
* @param {string} [props.defaultCategory] Preselected when the config lists it.
|
|
10
|
+
* @param {Blob[]} [props.extraFiles] Files that ride along from elsewhere (a page capture), counted against the limits.
|
|
11
|
+
* @param {(values: { category: string, subject: string, body: string, files: File[] }) => Promise<unknown>} props.onSubmit Rejects with a SupportApiError on failure.
|
|
12
|
+
* @param {(busy: boolean) => void} [props.onBusyChange]
|
|
13
|
+
* @param {import('react').ReactNode} [props.children] Shown above the attachments, such as a capture preview.
|
|
14
|
+
*/
|
|
15
|
+
export default function TicketForm({ id, config, defaultCategory, extraFiles, onSubmit, onBusyChange, children }: {
|
|
16
|
+
id: string;
|
|
17
|
+
config: any;
|
|
18
|
+
defaultCategory?: string;
|
|
19
|
+
extraFiles?: Blob[];
|
|
20
|
+
onSubmit: (values: {
|
|
21
|
+
category: string;
|
|
22
|
+
subject: string;
|
|
23
|
+
body: string;
|
|
24
|
+
files: File[];
|
|
25
|
+
}) => Promise<unknown>;
|
|
26
|
+
onBusyChange?: (busy: boolean) => void;
|
|
27
|
+
children?: import('react').ReactNode;
|
|
28
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The customer's tickets with status tabs and a search box.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} props
|
|
5
|
+
* @param {any[]} props.tickets
|
|
6
|
+
* @param {boolean} props.loading
|
|
7
|
+
* @param {any} [props.error]
|
|
8
|
+
* @param {() => void} props.onRetry
|
|
9
|
+
* @param {(id: string) => void} props.onOpen
|
|
10
|
+
*/
|
|
11
|
+
export default function TicketList({ tickets, loading, error, onRetry, onOpen }: {
|
|
12
|
+
tickets: any[];
|
|
13
|
+
loading: boolean;
|
|
14
|
+
error?: any;
|
|
15
|
+
onRetry: () => void;
|
|
16
|
+
onOpen: (id: string) => void;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** @type {import('react').Context<{ client: import('./client.js').SupportClient, loadConfig: (fresh?: boolean) => Promise<any> } | null>} */
|
|
2
|
+
export declare const SupportContext: import('react').Context<{
|
|
3
|
+
client: import('./client.js').SupportClient;
|
|
4
|
+
loadConfig: (fresh?: boolean) => Promise<any>;
|
|
5
|
+
} | null>;
|
|
6
|
+
/**
|
|
7
|
+
* The support client the nearest SupportProvider holds.
|
|
8
|
+
*
|
|
9
|
+
* @returns {import('./client.js').SupportClient}
|
|
10
|
+
*/
|
|
11
|
+
export declare function useSupportClient(): import('./client.js').SupportClient;
|
|
12
|
+
/**
|
|
13
|
+
* What the customer may send and how to reach support. Loaded once per provider and shared.
|
|
14
|
+
*
|
|
15
|
+
* @returns {{ config: any, loading: boolean, error: any, reload: () => void }}
|
|
16
|
+
*/
|
|
17
|
+
export declare function useSupportConfig(): {
|
|
18
|
+
config: any;
|
|
19
|
+
loading: boolean;
|
|
20
|
+
error: any;
|
|
21
|
+
reload: () => void;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* The signed-in customer's tickets.
|
|
25
|
+
*
|
|
26
|
+
* @returns {{ tickets: any[], loading: boolean, error: any, reload: () => void }}
|
|
27
|
+
*/
|
|
28
|
+
export declare function useSupportTickets(): {
|
|
29
|
+
tickets: any[];
|
|
30
|
+
loading: boolean;
|
|
31
|
+
error: any;
|
|
32
|
+
reload: () => void;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* One ticket with its thread, plus the actions a customer can take on it. Each action returns
|
|
36
|
+
* the updated ticket and replaces the one held here.
|
|
37
|
+
*
|
|
38
|
+
* @param {string|null|undefined} id The ticket's id; nothing loads while it is empty.
|
|
39
|
+
* @returns {{
|
|
40
|
+
* ticket: any, loading: boolean, error: any, reload: () => void,
|
|
41
|
+
* reply: (input: import('./client.js').ReplyInput) => Promise<any>,
|
|
42
|
+
* reopen: () => Promise<any>,
|
|
43
|
+
* rate: (input: import('./client.js').RatingInput) => Promise<any>
|
|
44
|
+
* }}
|
|
45
|
+
*/
|
|
46
|
+
export declare function useSupportTicket(id: string | null | undefined): {
|
|
47
|
+
ticket: any;
|
|
48
|
+
loading: boolean;
|
|
49
|
+
error: any;
|
|
50
|
+
reload: () => void;
|
|
51
|
+
reply: (input: import('./client.js').ReplyInput) => Promise<any>;
|
|
52
|
+
reopen: () => Promise<any>;
|
|
53
|
+
rate: (input: import('./client.js').RatingInput) => Promise<any>;
|
|
54
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createSupportClient, SupportApiError } from "./client.js";
|
|
2
|
+
export { useSupportClient, useSupportConfig, useSupportTicket, useSupportTickets } from "./context.js";
|
|
3
|
+
export { default as ReportIssue } from "./ReportIssue.jsx";
|
|
4
|
+
export { default as SupportCenter } from "./SupportCenter.jsx";
|
|
5
|
+
export { default as SupportContact } from "./SupportContact.jsx";
|
|
6
|
+
export { default as SupportProvider } from "./SupportProvider.jsx";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `accept` attribute for a file input, from the config's allowed content types.
|
|
3
|
+
*
|
|
4
|
+
* @param {{ allowedContentTypes?: string[] }|null|undefined} config
|
|
5
|
+
* @returns {string|undefined}
|
|
6
|
+
*/
|
|
7
|
+
export declare function acceptOf(config: {
|
|
8
|
+
allowedContentTypes?: string[];
|
|
9
|
+
} | null | undefined): string | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Checks files against the config before anything uploads. Returns the first problem as a
|
|
12
|
+
* sentence for the person, or null when every file can go.
|
|
13
|
+
*
|
|
14
|
+
* @param {Blob[]} files Every file on the message, screenshots included.
|
|
15
|
+
* @param {{ maxAttachmentBytes?: number, maxAttachmentsPerMessage?: number, allowedContentTypes?: string[] }|null|undefined} config
|
|
16
|
+
* @returns {string|null}
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateAttachments(files: Blob[], config: {
|
|
19
|
+
maxAttachmentBytes?: number;
|
|
20
|
+
maxAttachmentsPerMessage?: number;
|
|
21
|
+
allowedContentTypes?: string[];
|
|
22
|
+
} | null | undefined): string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Image files from a paste event, named so they read well on the ticket.
|
|
25
|
+
*
|
|
26
|
+
* @param {ClipboardEvent|{ clipboardData?: DataTransfer|null }} event
|
|
27
|
+
* @returns {File[]}
|
|
28
|
+
*/
|
|
29
|
+
export declare function imagesFromPaste(event: ClipboardEvent | {
|
|
30
|
+
clipboardData?: DataTransfer | null;
|
|
31
|
+
}): File[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A timestamp in the viewer's own time zone, with the zone named so the reader knows which clock
|
|
3
|
+
* it is. Returns a plain hyphen for a missing or unreadable value.
|
|
4
|
+
*
|
|
5
|
+
* @param {string|null|undefined} iso
|
|
6
|
+
* @returns {string}
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatDateTime(iso: string | null | undefined): string;
|
|
9
|
+
/**
|
|
10
|
+
* @param {number} bytes
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatBytes(bytes: number): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** The query parameter a support email links with to open one ticket. */
|
|
2
|
+
export declare const TICKET_PARAM = "ticket";
|
|
3
|
+
/**
|
|
4
|
+
* @returns {string|null} The ticket id in the current address, if any.
|
|
5
|
+
*/
|
|
6
|
+
export declare function ticketFromLocation(): string | null;
|
|
7
|
+
/**
|
|
8
|
+
* The current page's address with the ticket parameter set, or removed when `id` is empty.
|
|
9
|
+
*
|
|
10
|
+
* @param {string|null|undefined} id
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
export declare function ticketHref(id: string | null | undefined): string;
|
|
14
|
+
/**
|
|
15
|
+
* Records the open ticket in the address without a navigation, keeping the router's own history
|
|
16
|
+
* state, so a refresh or a shared link lands on the same ticket.
|
|
17
|
+
*
|
|
18
|
+
* @param {string|null|undefined} id
|
|
19
|
+
*/
|
|
20
|
+
export declare function replaceTicketInLocation(id: string | null | undefined): void;
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webority/support-react",
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"description": "Webority customer support for React portals: ticket centre, report-an-issue with a page screenshot, and support contact details, built on @webority/ui-react.",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public",
|
|
9
|
+
"registry": "https://registry.npmjs.org/"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/Webority/webority-ui.git",
|
|
14
|
+
"directory": "packages/support-react"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"main": "./dist/support-react.js",
|
|
20
|
+
"module": "./dist/support-react.js",
|
|
21
|
+
"types": "./dist/types/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/types/index.d.ts",
|
|
25
|
+
"default": "./dist/support-react.js"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
|
+
},
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"bootstrap": "5.3.3",
|
|
32
|
+
"react": "^19.0.0",
|
|
33
|
+
"react-bootstrap": "^2.10.0",
|
|
34
|
+
"react-dom": "^19.0.0",
|
|
35
|
+
"@webority/ui-react": "0.13.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@testing-library/dom": "10.4.2",
|
|
39
|
+
"@testing-library/jest-dom": "7.0.1",
|
|
40
|
+
"@testing-library/react": "^16.3.0",
|
|
41
|
+
"@testing-library/user-event": "^14.6.1",
|
|
42
|
+
"@types/react": "^19.2.17",
|
|
43
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
44
|
+
"@vitest/coverage-v8": "5.0.1",
|
|
45
|
+
"bootstrap": "5.3.3",
|
|
46
|
+
"jsdom": "30.1.1",
|
|
47
|
+
"react": "^19.2.6",
|
|
48
|
+
"react-bootstrap": "^2.10.6",
|
|
49
|
+
"react-dom": "^19.2.6",
|
|
50
|
+
"typescript": "^7.0.2",
|
|
51
|
+
"vite": "^8.0.12",
|
|
52
|
+
"vitest": "5.0.1",
|
|
53
|
+
"@webority/ui-react": "0.13.0"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"html-to-image": "^1.11.13"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "vite build && tsc -p tsconfig.json",
|
|
60
|
+
"test": "vitest run",
|
|
61
|
+
"test:watch": "vitest",
|
|
62
|
+
"test:coverage": "vitest run --coverage"
|
|
63
|
+
}
|
|
64
|
+
}
|