@fluid-app/portal-sdk 0.1.13 → 0.1.15
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/dist/AccountScreen-B08uxzt6.mjs +2 -0
- package/dist/AccountScreen-CQCwpKEC.mjs +741 -0
- package/dist/AccountScreen-CQCwpKEC.mjs.map +1 -0
- package/dist/AccountScreen-CbhrIAa4.cjs +780 -0
- package/dist/AccountScreen-CbhrIAa4.cjs.map +1 -0
- package/dist/{ContactsScreen-CB6l0Lf1.mjs → ContactsScreen-CHLFZX_N.mjs} +2 -2
- package/dist/{ContactsScreen-CB6l0Lf1.mjs.map → ContactsScreen-CHLFZX_N.mjs.map} +1 -1
- package/dist/{ContactsScreen-Dwn5onLu.cjs → ContactsScreen-CjnCemeI.cjs} +4 -4
- package/dist/{ContactsScreen-Dwn5onLu.cjs.map → ContactsScreen-CjnCemeI.cjs.map} +1 -1
- package/dist/{CoreScreenPlaceholder-Bw8YOPwv.cjs → CoreScreenPlaceholder-C9lBkcyc.cjs} +2 -2
- package/dist/{CoreScreenPlaceholder-Bw8YOPwv.cjs.map → CoreScreenPlaceholder-C9lBkcyc.cjs.map} +1 -1
- package/dist/{CoreScreenPlaceholder-D93ZYKt2.mjs → CoreScreenPlaceholder-DCJ1hFvJ.mjs} +1 -1
- package/dist/{CoreScreenPlaceholder-D93ZYKt2.mjs.map → CoreScreenPlaceholder-DCJ1hFvJ.mjs.map} +1 -1
- package/dist/{CustomersScreen-gQb6cWL5.cjs → CustomersScreen-CqwRJogV.cjs} +4 -4
- package/dist/{CustomersScreen-gQb6cWL5.cjs.map → CustomersScreen-CqwRJogV.cjs.map} +1 -1
- package/dist/{CustomersScreen-BEar6Leg.mjs → CustomersScreen-DBicCB3o.mjs} +2 -2
- package/dist/{CustomersScreen-BEar6Leg.mjs.map → CustomersScreen-DBicCB3o.mjs.map} +1 -1
- package/dist/{MessagingScreen-YyzXdr95.mjs → FluidProvider-BafZw8PJ.mjs} +6 -503
- package/dist/FluidProvider-BafZw8PJ.mjs.map +1 -0
- package/dist/{MessagingScreen-Ca22FObh.cjs → FluidProvider-C6SCZDjX.cjs} +3 -542
- package/dist/FluidProvider-C6SCZDjX.cjs.map +1 -0
- package/dist/MessagingScreen-Bd-1_J9q.cjs +369 -0
- package/dist/MessagingScreen-Bd-1_J9q.cjs.map +1 -0
- package/dist/MessagingScreen-D8W8V2TW.mjs +2 -0
- package/dist/MessagingScreen-DCS0mtbd.mjs +324 -0
- package/dist/MessagingScreen-DCS0mtbd.mjs.map +1 -0
- package/dist/{OrdersScreen-DB1v051q.mjs → OrdersScreen-B6JCMBY5.mjs} +2 -2
- package/dist/{OrdersScreen-DB1v051q.mjs.map → OrdersScreen-B6JCMBY5.mjs.map} +1 -1
- package/dist/{OrdersScreen-DbON-kBA.cjs → OrdersScreen-DBxpXgZ9.cjs} +4 -4
- package/dist/{OrdersScreen-DbON-kBA.cjs.map → OrdersScreen-DBxpXgZ9.cjs.map} +1 -1
- package/dist/{ProductsScreen-CMDGGvE2.cjs → ProductsScreen-BK8cz_MN.cjs} +4 -4
- package/dist/{ProductsScreen-CMDGGvE2.cjs.map → ProductsScreen-BK8cz_MN.cjs.map} +1 -1
- package/dist/{ProductsScreen-nVDsY6kf.mjs → ProductsScreen-DafsauTY.mjs} +2 -2
- package/dist/{ProductsScreen-nVDsY6kf.mjs.map → ProductsScreen-DafsauTY.mjs.map} +1 -1
- package/dist/index.cjs +73 -138
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -22
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +29 -22
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +49 -116
- package/dist/index.mjs.map +1 -1
- package/package.json +19 -13
- package/dist/MessagingScreen-Ca22FObh.cjs.map +0 -1
- package/dist/MessagingScreen-YyzXdr95.mjs.map +0 -1
|
@@ -1,194 +1,14 @@
|
|
|
1
1
|
import { n as __reExport, t as __exportAll } from "./chunk-D1SwGrFN.mjs";
|
|
2
2
|
import { createContext, useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
3
|
-
import { QueryClient, QueryClientProvider
|
|
3
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
4
|
+
import { createFetchClient as createFetchClient$1 } from "@fluid-app/api-client-core";
|
|
4
5
|
import { AUTH_REDIRECT_TOKEN_KEY, DEFAULT_AUTH_URL, cleanTokenFromUrl, clearTokens, createDefaultAuthRedirect, createDevUser, extractTokenFromUrl, getStoredToken, isDevBypassActive, isTokenExpired, resolveAuthFailureHandler, storeToken, validateToken, verifyToken } from "@fluid-app/auth";
|
|
5
6
|
import { buildThemeDefinition, getActiveThemeId, getActiveThemeId as getActiveThemeId$1, transformThemes, transformThemes as transformThemes$1 } from "@fluid-app/portal-core/theme";
|
|
6
|
-
import { jsx
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
8
|
import { DataSourceRegistryProvider } from "@fluid-app/portal-core/data-sources/registry-context";
|
|
8
9
|
import { RegistryProvider } from "@fluid-app/portal-widgets/contexts";
|
|
9
10
|
import { createWidgetRegistry } from "@fluid-app/portal-core/widget-utils";
|
|
10
11
|
import { AlertWidget, CalendarWidget, CarouselWidget, CatchUpWidget, ChartWidget, ContainerWidget, EmbedWidget, ImageWidget, LayoutWidget, ListWidget, MySiteWidget, NestedWidget, QuickShareWidget, RecentActivityWidget, SpacerWidget, TableWidget, TextWidget, ToDoWidget, VideoWidget } from "@fluid-app/portal-widgets/widgets";
|
|
11
|
-
import { getFileTypeFromMimetype } from "@fluid-app/messaging-core";
|
|
12
|
-
import { MessagingApp } from "@fluid-app/messaging-ui/app";
|
|
13
|
-
import { extractEmoji, formatMessageChannelName } from "@fluid-app/messaging-ui";
|
|
14
|
-
import { listConnectedRecipients, searchConversations } from "@fluid-app/messaging-api-client";
|
|
15
|
-
//#region ../../platform/api-client-core/src/fetch-client.ts
|
|
16
|
-
/**
|
|
17
|
-
* API Error class compatible with fluid-admin's ApiError
|
|
18
|
-
*/
|
|
19
|
-
var ApiError$1 = class ApiError$1 extends Error {
|
|
20
|
-
status;
|
|
21
|
-
data;
|
|
22
|
-
constructor(message, status, data) {
|
|
23
|
-
super(message);
|
|
24
|
-
this.name = "ApiError";
|
|
25
|
-
this.status = status;
|
|
26
|
-
this.data = data;
|
|
27
|
-
if ("captureStackTrace" in Error) Error.captureStackTrace(this, ApiError$1);
|
|
28
|
-
}
|
|
29
|
-
toJSON() {
|
|
30
|
-
return {
|
|
31
|
-
name: this.name,
|
|
32
|
-
message: this.message,
|
|
33
|
-
status: this.status,
|
|
34
|
-
data: this.data
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* Creates a configured fetch client instance
|
|
40
|
-
*/
|
|
41
|
-
function createFetchClient(config) {
|
|
42
|
-
const { baseUrl, getAuthToken, onAuthError, defaultHeaders = {} } = config;
|
|
43
|
-
/**
|
|
44
|
-
* Build headers for a request
|
|
45
|
-
*/
|
|
46
|
-
async function buildHeaders(customHeaders) {
|
|
47
|
-
const headers = {
|
|
48
|
-
Accept: "application/json",
|
|
49
|
-
"Content-Type": "application/json",
|
|
50
|
-
...defaultHeaders,
|
|
51
|
-
...customHeaders
|
|
52
|
-
};
|
|
53
|
-
if (getAuthToken) {
|
|
54
|
-
const token = await getAuthToken();
|
|
55
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
56
|
-
}
|
|
57
|
-
return headers;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Join baseUrl + endpoint via string concatenation (matches fetchApi).
|
|
61
|
-
* Using `new URL(endpoint, baseUrl)` would strip any path prefix from
|
|
62
|
-
* baseUrl (e.g. "/api") when the endpoint starts with "/".
|
|
63
|
-
*/
|
|
64
|
-
function joinUrl(endpoint) {
|
|
65
|
-
return `${baseUrl}${endpoint}`;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Build URL with query parameters for GET requests
|
|
69
|
-
* Compatible with fluid-admin's query param handling
|
|
70
|
-
*/
|
|
71
|
-
function buildUrl(endpoint, params) {
|
|
72
|
-
const fullUrl = joinUrl(endpoint);
|
|
73
|
-
if (!params || Object.keys(params).length === 0) return fullUrl;
|
|
74
|
-
const queryString = new URLSearchParams();
|
|
75
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
76
|
-
if (value === void 0 || value === null) return;
|
|
77
|
-
if (Array.isArray(value)) value.forEach((item) => queryString.append(`${key}[]`, String(item)));
|
|
78
|
-
else if (typeof value === "object") Object.entries(value).forEach(([subKey, subValue]) => {
|
|
79
|
-
if (subValue === void 0 || subValue === null) return;
|
|
80
|
-
if (Array.isArray(subValue)) subValue.forEach((item) => queryString.append(`${key}[${subKey}][]`, String(item)));
|
|
81
|
-
else queryString.append(`${key}[${subKey}]`, String(subValue));
|
|
82
|
-
});
|
|
83
|
-
else queryString.append(key, String(value));
|
|
84
|
-
});
|
|
85
|
-
const qs = queryString.toString();
|
|
86
|
-
return qs ? `${fullUrl}?${qs}` : fullUrl;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Shared response handler for both JSON and FormData requests.
|
|
90
|
-
* Handles auth errors, non-OK responses, 204 No Content, and JSON parsing.
|
|
91
|
-
*/
|
|
92
|
-
async function handleResponse(response, method, _url) {
|
|
93
|
-
if (response.status === 401 && onAuthError) onAuthError();
|
|
94
|
-
if (!response.ok) {
|
|
95
|
-
const errorText = await response.text().catch(() => "");
|
|
96
|
-
if (response.headers.get("content-type")?.includes("application/json")) {
|
|
97
|
-
let data;
|
|
98
|
-
try {
|
|
99
|
-
data = JSON.parse(errorText);
|
|
100
|
-
} catch {
|
|
101
|
-
throw new ApiError$1(errorText.slice(0, 200) || `${method} request failed with status ${response.status}`, response.status, null);
|
|
102
|
-
}
|
|
103
|
-
throw new ApiError$1(data.message || data.error_message || `${method} request failed`, response.status, data.errors || data);
|
|
104
|
-
} else throw new ApiError$1(`${method} request failed with status ${response.status}`, response.status, null);
|
|
105
|
-
}
|
|
106
|
-
if (response.status === 204 || response.headers.get("content-length") === "0") return null;
|
|
107
|
-
if (response.headers.get("content-type")?.includes("application/json")) try {
|
|
108
|
-
return await response.json();
|
|
109
|
-
} catch {
|
|
110
|
-
try {
|
|
111
|
-
return await response.text();
|
|
112
|
-
} catch {
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Main request function
|
|
120
|
-
*/
|
|
121
|
-
async function request(endpoint, options = {}) {
|
|
122
|
-
const { method = "GET", headers: customHeaders, params, body, signal } = options;
|
|
123
|
-
const url = params ? buildUrl(endpoint, params) : joinUrl(endpoint);
|
|
124
|
-
const headers = await buildHeaders(customHeaders);
|
|
125
|
-
let response;
|
|
126
|
-
try {
|
|
127
|
-
const fetchOptions = {
|
|
128
|
-
method,
|
|
129
|
-
headers
|
|
130
|
-
};
|
|
131
|
-
const serializedBody = body && method !== "GET" ? JSON.stringify(body) : null;
|
|
132
|
-
if (serializedBody) fetchOptions.body = serializedBody;
|
|
133
|
-
if (signal) fetchOptions.signal = signal;
|
|
134
|
-
response = await fetch(url, fetchOptions);
|
|
135
|
-
} catch (networkError) {
|
|
136
|
-
throw new ApiError$1(`Network error: ${networkError instanceof Error ? networkError.message : "Unknown network error"}`, 0, null);
|
|
137
|
-
}
|
|
138
|
-
return handleResponse(response, method, url);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Request with FormData (for file uploads)
|
|
142
|
-
*/
|
|
143
|
-
async function requestWithFormData(endpoint, formData, options = {}) {
|
|
144
|
-
const { method = "POST", headers: customHeaders, signal } = options;
|
|
145
|
-
const url = joinUrl(endpoint);
|
|
146
|
-
const headers = await buildHeaders(customHeaders);
|
|
147
|
-
delete headers["Content-Type"];
|
|
148
|
-
let response;
|
|
149
|
-
try {
|
|
150
|
-
const fetchOptions = {
|
|
151
|
-
method,
|
|
152
|
-
headers,
|
|
153
|
-
body: formData
|
|
154
|
-
};
|
|
155
|
-
if (signal) fetchOptions.signal = signal;
|
|
156
|
-
response = await fetch(url, fetchOptions);
|
|
157
|
-
} catch (networkError) {
|
|
158
|
-
throw new ApiError$1(`Network error: ${networkError instanceof Error ? networkError.message : "Unknown network error"}`, 0, null);
|
|
159
|
-
}
|
|
160
|
-
return handleResponse(response, method, url);
|
|
161
|
-
}
|
|
162
|
-
return {
|
|
163
|
-
request,
|
|
164
|
-
requestWithFormData,
|
|
165
|
-
get: (endpoint, params, options) => request(endpoint, {
|
|
166
|
-
...options,
|
|
167
|
-
method: "GET",
|
|
168
|
-
...params && { params }
|
|
169
|
-
}),
|
|
170
|
-
post: (endpoint, body, options) => request(endpoint, {
|
|
171
|
-
...options,
|
|
172
|
-
method: "POST",
|
|
173
|
-
body
|
|
174
|
-
}),
|
|
175
|
-
put: (endpoint, body, options) => request(endpoint, {
|
|
176
|
-
...options,
|
|
177
|
-
method: "PUT",
|
|
178
|
-
body
|
|
179
|
-
}),
|
|
180
|
-
patch: (endpoint, body, options) => request(endpoint, {
|
|
181
|
-
...options,
|
|
182
|
-
method: "PATCH",
|
|
183
|
-
body
|
|
184
|
-
}),
|
|
185
|
-
delete: (endpoint, options) => request(endpoint, {
|
|
186
|
-
...options,
|
|
187
|
-
method: "DELETE"
|
|
188
|
-
})
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
//#endregion
|
|
192
12
|
//#region ../../api-clients/fluidos/src/namespaces/fluid_os.ts
|
|
193
13
|
/**
|
|
194
14
|
* Get active Fluid OS definition
|
|
@@ -357,7 +177,7 @@ function extractErrorMessage(data, fallback) {
|
|
|
357
177
|
function createFluidClient(config) {
|
|
358
178
|
const { baseUrl, getAuthToken, onAuthError, defaultHeaders = {} } = config;
|
|
359
179
|
const effectiveOnAuthError = onAuthError ?? createDefaultAuthRedirect();
|
|
360
|
-
const fetchClient = createFetchClient({
|
|
180
|
+
const fetchClient = createFetchClient$1({
|
|
361
181
|
baseUrl,
|
|
362
182
|
...getAuthToken ? { getAuthToken } : {},
|
|
363
183
|
onAuthError: effectiveOnAuthError,
|
|
@@ -962,323 +782,6 @@ function useFluidContext() {
|
|
|
962
782
|
return context;
|
|
963
783
|
}
|
|
964
784
|
//#endregion
|
|
965
|
-
|
|
966
|
-
/**
|
|
967
|
-
* Hook to access the Fluid API client
|
|
968
|
-
*
|
|
969
|
-
* @example
|
|
970
|
-
* ```tsx
|
|
971
|
-
* function ProductList() {
|
|
972
|
-
* const api = useFluidApi();
|
|
973
|
-
*
|
|
974
|
-
* const { data: products } = useQuery({
|
|
975
|
-
* queryKey: ["products"],
|
|
976
|
-
* queryFn: () => api.products.list(),
|
|
977
|
-
* });
|
|
978
|
-
*
|
|
979
|
-
* return <ul>{products?.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
|
|
980
|
-
* }
|
|
981
|
-
* ```
|
|
982
|
-
*/
|
|
983
|
-
function useFluidApi() {
|
|
984
|
-
const { client } = useFluidContext();
|
|
985
|
-
return client;
|
|
986
|
-
}
|
|
987
|
-
//#endregion
|
|
988
|
-
//#region src/messaging/use-messaging-auth.ts
|
|
989
|
-
/**
|
|
990
|
-
* Bridge hook: maps portal SDK auth context to MessagingAuthContext.
|
|
991
|
-
*
|
|
992
|
-
* The messaging system identifies users by `recipient_id`, which is NOT in the
|
|
993
|
-
* JWT payload or the /reps/me endpoint. It IS returned by GET /api/me.
|
|
994
|
-
* This hook fetches that data and maps it into the shape MessagingApp expects.
|
|
995
|
-
*/
|
|
996
|
-
const USERS_ME_QUERY_KEY = [
|
|
997
|
-
"fluid",
|
|
998
|
-
"users",
|
|
999
|
-
"me"
|
|
1000
|
-
];
|
|
1001
|
-
function useMessagingAuth() {
|
|
1002
|
-
const auth = useFluidAuthContext();
|
|
1003
|
-
const api = useFluidApi();
|
|
1004
|
-
const { data: userMe, isLoading: isUserMeLoading, isError } = useQuery({
|
|
1005
|
-
queryKey: USERS_ME_QUERY_KEY,
|
|
1006
|
-
queryFn: () => api.users.me(),
|
|
1007
|
-
enabled: auth.isAuthenticated,
|
|
1008
|
-
staleTime: Infinity,
|
|
1009
|
-
retry: 1
|
|
1010
|
-
});
|
|
1011
|
-
if (auth.isLoading || auth.isAuthenticated && isUserMeLoading) return {
|
|
1012
|
-
recipientId: null,
|
|
1013
|
-
companyId: null,
|
|
1014
|
-
currentUser: null,
|
|
1015
|
-
isLoading: true
|
|
1016
|
-
};
|
|
1017
|
-
if (!auth.isAuthenticated || isError || !userMe) return {
|
|
1018
|
-
recipientId: null,
|
|
1019
|
-
companyId: null,
|
|
1020
|
-
currentUser: null,
|
|
1021
|
-
isLoading: false
|
|
1022
|
-
};
|
|
1023
|
-
const currentUser = userMe.recipient_id ? {
|
|
1024
|
-
id: userMe.id,
|
|
1025
|
-
recipientId: userMe.recipient_id,
|
|
1026
|
-
firstName: userMe.first_name ?? "",
|
|
1027
|
-
lastName: userMe.last_name ?? "",
|
|
1028
|
-
email: userMe.email,
|
|
1029
|
-
...userMe.image_url != null && { imageUrl: userMe.image_url },
|
|
1030
|
-
...userMe.affiliate_id != null && { affiliateId: userMe.affiliate_id }
|
|
1031
|
-
} : null;
|
|
1032
|
-
return {
|
|
1033
|
-
recipientId: userMe.recipient_id,
|
|
1034
|
-
companyId: userMe.company_id ?? null,
|
|
1035
|
-
currentUser,
|
|
1036
|
-
isLoading: false
|
|
1037
|
-
};
|
|
1038
|
-
}
|
|
1039
|
-
//#endregion
|
|
1040
|
-
//#region src/messaging/use-messaging-config.ts
|
|
1041
|
-
/**
|
|
1042
|
-
* Hook that derives MessagingApiConfig from the portal SDK's FluidProvider context.
|
|
1043
|
-
*
|
|
1044
|
-
* Maps FluidSDKConfig fields to the shape expected by MessagingApp:
|
|
1045
|
-
* - baseUrl -> from config.baseUrl
|
|
1046
|
-
* - getHeaders -> builds Authorization header from config.getAuthToken()
|
|
1047
|
-
* - onAuthError -> from config.onAuthError
|
|
1048
|
-
* - websocketUrl -> config.websocketUrl or derived from baseUrl
|
|
1049
|
-
* - token -> from auth context
|
|
1050
|
-
*/
|
|
1051
|
-
function deriveWebsocketUrl(baseUrl) {
|
|
1052
|
-
return `${baseUrl.replace(/\/+$/, "").replace(/\/api$/, "")}/cable`;
|
|
1053
|
-
}
|
|
1054
|
-
function useMessagingConfig() {
|
|
1055
|
-
const { config } = useFluidContext();
|
|
1056
|
-
const auth = useFluidAuthContext();
|
|
1057
|
-
const getHeaders = useCallback(async () => {
|
|
1058
|
-
const headers = {
|
|
1059
|
-
"Content-Type": "application/json",
|
|
1060
|
-
...config.defaultHeaders
|
|
1061
|
-
};
|
|
1062
|
-
if (config.getAuthToken) {
|
|
1063
|
-
const token = await config.getAuthToken();
|
|
1064
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
1065
|
-
}
|
|
1066
|
-
return headers;
|
|
1067
|
-
}, [config]);
|
|
1068
|
-
const apiBaseUrl = useMemo(() => {
|
|
1069
|
-
const base = config.baseUrl.replace(/\/+$/, "");
|
|
1070
|
-
return base.endsWith("/api") ? base : `${base}/api`;
|
|
1071
|
-
}, [config.baseUrl]);
|
|
1072
|
-
return {
|
|
1073
|
-
apiConfig: useMemo(() => ({
|
|
1074
|
-
baseUrl: apiBaseUrl,
|
|
1075
|
-
getHeaders,
|
|
1076
|
-
...config.onAuthError != null && { onAuthError: config.onAuthError }
|
|
1077
|
-
}), [
|
|
1078
|
-
apiBaseUrl,
|
|
1079
|
-
config.onAuthError,
|
|
1080
|
-
getHeaders
|
|
1081
|
-
]),
|
|
1082
|
-
websocketUrl: useMemo(() => config.websocketUrl ?? deriveWebsocketUrl(config.baseUrl), [config.websocketUrl, config.baseUrl]),
|
|
1083
|
-
token: auth.token
|
|
1084
|
-
};
|
|
1085
|
-
}
|
|
1086
|
-
//#endregion
|
|
1087
|
-
//#region src/messaging/fluid-file-uploader.ts
|
|
1088
|
-
const FILESTACK_UPLOAD_URL = "https://www.filestackapi.com/api/store/S3";
|
|
1089
|
-
function getImageDimensions(file) {
|
|
1090
|
-
if (!file.type.startsWith("image/")) return Promise.resolve(null);
|
|
1091
|
-
return new Promise((resolve) => {
|
|
1092
|
-
const img = new Image();
|
|
1093
|
-
const url = URL.createObjectURL(file);
|
|
1094
|
-
img.onload = () => {
|
|
1095
|
-
URL.revokeObjectURL(url);
|
|
1096
|
-
resolve({
|
|
1097
|
-
width: img.naturalWidth,
|
|
1098
|
-
height: img.naturalHeight
|
|
1099
|
-
});
|
|
1100
|
-
};
|
|
1101
|
-
img.onerror = () => {
|
|
1102
|
-
URL.revokeObjectURL(url);
|
|
1103
|
-
resolve(null);
|
|
1104
|
-
};
|
|
1105
|
-
img.src = url;
|
|
1106
|
-
});
|
|
1107
|
-
}
|
|
1108
|
-
function uploadToFilestack(file, apiKey, callbacks) {
|
|
1109
|
-
const xhr = new XMLHttpRequest();
|
|
1110
|
-
let aborted = false;
|
|
1111
|
-
getImageDimensions(file).then((metadata) => {
|
|
1112
|
-
if (aborted) return;
|
|
1113
|
-
const url = `${FILESTACK_UPLOAD_URL}?key=${encodeURIComponent(apiKey)}`;
|
|
1114
|
-
xhr.open("POST", url);
|
|
1115
|
-
xhr.setRequestHeader("Content-Type", file.type);
|
|
1116
|
-
xhr.upload.onprogress = (event) => {
|
|
1117
|
-
if (event.lengthComputable) {
|
|
1118
|
-
const progress = Math.round(event.loaded / event.total * 100);
|
|
1119
|
-
callbacks.onProgress(progress);
|
|
1120
|
-
}
|
|
1121
|
-
};
|
|
1122
|
-
xhr.onload = () => {
|
|
1123
|
-
if (xhr.status >= 200 && xhr.status < 300) try {
|
|
1124
|
-
const result = {
|
|
1125
|
-
url: JSON.parse(xhr.responseText).url,
|
|
1126
|
-
size: file.size,
|
|
1127
|
-
mimetype: file.type,
|
|
1128
|
-
kind: getFileTypeFromMimetype(file.type),
|
|
1129
|
-
metadata
|
|
1130
|
-
};
|
|
1131
|
-
callbacks.onSuccess(result);
|
|
1132
|
-
} catch {
|
|
1133
|
-
callbacks.onError(/* @__PURE__ */ new Error("Failed to parse upload response"));
|
|
1134
|
-
}
|
|
1135
|
-
else callbacks.onError(/* @__PURE__ */ new Error(`Upload failed with status ${xhr.status}`));
|
|
1136
|
-
};
|
|
1137
|
-
xhr.onerror = () => {
|
|
1138
|
-
if (!aborted) callbacks.onError(/* @__PURE__ */ new Error("Upload failed due to a network error"));
|
|
1139
|
-
};
|
|
1140
|
-
xhr.onabort = () => {};
|
|
1141
|
-
xhr.send(file);
|
|
1142
|
-
}).catch((error) => {
|
|
1143
|
-
if (!aborted) callbacks.onError(error instanceof Error ? error : /* @__PURE__ */ new Error("Upload preparation failed"));
|
|
1144
|
-
});
|
|
1145
|
-
return { abort: () => {
|
|
1146
|
-
aborted = true;
|
|
1147
|
-
xhr.abort();
|
|
1148
|
-
} };
|
|
1149
|
-
}
|
|
1150
|
-
/**
|
|
1151
|
-
* Creates a FileUploader that uploads to Filestack using the REST API.
|
|
1152
|
-
*
|
|
1153
|
-
* @param apiKey - Filestack API key. If falsy, returns a noop uploader
|
|
1154
|
-
* that rejects uploads with a helpful error message.
|
|
1155
|
-
*/
|
|
1156
|
-
function createFluidFileUploader(apiKey) {
|
|
1157
|
-
if (!apiKey) return { uploadFile: (_file, callbacks) => {
|
|
1158
|
-
callbacks.onError(/* @__PURE__ */ new Error("File uploads are not configured. Set filestackApiKey in your SDK config to enable attachments."));
|
|
1159
|
-
return { abort: () => {} };
|
|
1160
|
-
} };
|
|
1161
|
-
return { uploadFile: (file, callbacks) => uploadToFilestack(file, apiKey, callbacks) };
|
|
1162
|
-
}
|
|
1163
|
-
//#endregion
|
|
1164
|
-
//#region src/screens/MessagingScreen.tsx
|
|
1165
|
-
var MessagingScreen_exports = /* @__PURE__ */ __exportAll({
|
|
1166
|
-
MessagingScreen: () => MessagingScreen,
|
|
1167
|
-
messagingScreenPropertySchema: () => messagingScreenPropertySchema
|
|
1168
|
-
});
|
|
1169
|
-
function renderImage(props) {
|
|
1170
|
-
return /* @__PURE__ */ jsx("img", {
|
|
1171
|
-
src: props.src,
|
|
1172
|
-
alt: props.alt,
|
|
1173
|
-
width: props.width,
|
|
1174
|
-
height: props.height,
|
|
1175
|
-
className: props.className
|
|
1176
|
-
});
|
|
1177
|
-
}
|
|
1178
|
-
function defaultToast(message, type) {
|
|
1179
|
-
if (type === "error") console.warn("[Messaging]", message);
|
|
1180
|
-
}
|
|
1181
|
-
function MessagingScreen({ onToast, filestackApiKey, websocketUrl: websocketUrlOverride, background, textColor, accentColor, padding, borderRadius, ...divProps }) {
|
|
1182
|
-
const { config } = useFluidContext();
|
|
1183
|
-
const { apiConfig, websocketUrl, token } = useMessagingConfig();
|
|
1184
|
-
const messagingAuth = useMessagingAuth();
|
|
1185
|
-
const effectiveApiKey = filestackApiKey ?? config.filestackApiKey;
|
|
1186
|
-
const uploader = useMemo(() => createFluidFileUploader(effectiveApiKey), [effectiveApiKey]);
|
|
1187
|
-
const effectiveWsUrl = websocketUrlOverride ?? websocketUrl;
|
|
1188
|
-
const effectiveToast = onToast ?? defaultToast;
|
|
1189
|
-
const searchUsers = useCallback(async (query) => {
|
|
1190
|
-
return ((await listConnectedRecipients(apiConfig, {
|
|
1191
|
-
filterrific: { search_query: query },
|
|
1192
|
-
per_page: 10,
|
|
1193
|
-
page: 1
|
|
1194
|
-
}))?.[1]?.items ?? []).map((user) => {
|
|
1195
|
-
const name = [user.first_name, user.last_name].filter(Boolean).length > 0 ? [user.first_name, user.last_name].filter(Boolean).join(" ") : `User ${user.id}`;
|
|
1196
|
-
return {
|
|
1197
|
-
id: String(user.id),
|
|
1198
|
-
label: name,
|
|
1199
|
-
imageType: "user",
|
|
1200
|
-
userData: {
|
|
1201
|
-
first_name: user.first_name,
|
|
1202
|
-
last_name: user.last_name,
|
|
1203
|
-
image_url: user.avatar_url,
|
|
1204
|
-
phone: user.phone || void 0,
|
|
1205
|
-
email: user.email || void 0
|
|
1206
|
-
},
|
|
1207
|
-
conversationName: name
|
|
1208
|
-
};
|
|
1209
|
-
});
|
|
1210
|
-
}, [apiConfig]);
|
|
1211
|
-
const searchChannels = useCallback(async (query) => {
|
|
1212
|
-
return (await searchConversations(apiConfig, { filterrific: { search_query: query } }) ?? []).map((channel) => {
|
|
1213
|
-
const { text: nameWithoutEmoji } = extractEmoji(channel.name);
|
|
1214
|
-
return {
|
|
1215
|
-
id: `channel-${channel.id}`,
|
|
1216
|
-
label: formatMessageChannelName(nameWithoutEmoji),
|
|
1217
|
-
imageType: "channel",
|
|
1218
|
-
userData: {
|
|
1219
|
-
first_name: channel.name,
|
|
1220
|
-
last_name: null,
|
|
1221
|
-
image_url: channel.avatar_url
|
|
1222
|
-
},
|
|
1223
|
-
conversationName: channel.name
|
|
1224
|
-
};
|
|
1225
|
-
});
|
|
1226
|
-
}, [apiConfig]);
|
|
1227
|
-
if (messagingAuth.isLoading) return /* @__PURE__ */ jsx("div", {
|
|
1228
|
-
...divProps,
|
|
1229
|
-
className: `flex h-full items-center justify-center ${divProps.className ?? ""}`,
|
|
1230
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
1231
|
-
className: "text-muted-foreground",
|
|
1232
|
-
children: "Loading messaging..."
|
|
1233
|
-
})
|
|
1234
|
-
});
|
|
1235
|
-
if (!messagingAuth.recipientId) return /* @__PURE__ */ jsx("div", {
|
|
1236
|
-
...divProps,
|
|
1237
|
-
className: `flex h-full items-center justify-center ${divProps.className ?? ""}`,
|
|
1238
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
1239
|
-
className: "border-border max-w-sm rounded-lg border border-dashed p-8 text-center",
|
|
1240
|
-
children: [/* @__PURE__ */ jsx("h2", {
|
|
1241
|
-
className: "text-foreground text-xl font-semibold",
|
|
1242
|
-
children: "Messaging"
|
|
1243
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
1244
|
-
className: "text-muted-foreground mt-2",
|
|
1245
|
-
children: "Messaging is not available for your account"
|
|
1246
|
-
})]
|
|
1247
|
-
})
|
|
1248
|
-
});
|
|
1249
|
-
return /* @__PURE__ */ jsx("div", {
|
|
1250
|
-
...divProps,
|
|
1251
|
-
className: `h-full ${divProps.className ?? ""}`,
|
|
1252
|
-
children: /* @__PURE__ */ jsx(MessagingApp, {
|
|
1253
|
-
config: apiConfig,
|
|
1254
|
-
auth: messagingAuth,
|
|
1255
|
-
websocketUrl: effectiveWsUrl,
|
|
1256
|
-
token,
|
|
1257
|
-
renderImage,
|
|
1258
|
-
showAdminFeatures: false,
|
|
1259
|
-
onToast: effectiveToast,
|
|
1260
|
-
messagesViewProps: {
|
|
1261
|
-
uploader,
|
|
1262
|
-
saveDrafts: true,
|
|
1263
|
-
onToast: effectiveToast
|
|
1264
|
-
},
|
|
1265
|
-
newMessageViewProps: {
|
|
1266
|
-
searchUsers,
|
|
1267
|
-
searchChannels
|
|
1268
|
-
}
|
|
1269
|
-
})
|
|
1270
|
-
});
|
|
1271
|
-
}
|
|
1272
|
-
const messagingScreenPropertySchema = {
|
|
1273
|
-
widgetType: "MessagingScreen",
|
|
1274
|
-
displayName: "Messaging Screen",
|
|
1275
|
-
tabsConfig: [{
|
|
1276
|
-
id: "styling",
|
|
1277
|
-
label: "Styling"
|
|
1278
|
-
}],
|
|
1279
|
-
fields: []
|
|
1280
|
-
};
|
|
1281
|
-
//#endregion
|
|
1282
|
-
export { toNavigationItem as C, createDefaultAuthRedirect as D, DEFAULT_AUTH_URL as E, transformThemes$1 as S, toScreenDefinition as T, createFluidClient as _, useMessagingConfig as a, getActiveThemeId$1 as b, FluidProvider as c, FluidAuthProvider as d, useFluidAuthContext as f, ApiError as g, themes_exports as h, createFluidFileUploader as i, useFluidContext as l, useThemeContext as m, MessagingScreen_exports as n, useMessagingAuth as o, FluidThemeProvider as p, messagingScreenPropertySchema as r, useFluidApi as s, MessagingScreen as t, DEFAULT_SDK_WIDGET_REGISTRY as u, isApiError as v, normalizeComponentTree as w, transformManifestToRepAppData as x, buildThemeDefinition as y };
|
|
785
|
+
export { normalizeComponentTree as _, useFluidAuthContext as a, createDefaultAuthRedirect as b, themes_exports as c, isApiError as d, buildThemeDefinition as f, toNavigationItem as g, transformThemes$1 as h, FluidAuthProvider as i, ApiError as l, transformManifestToRepAppData as m, useFluidContext as n, FluidThemeProvider as o, getActiveThemeId$1 as p, DEFAULT_SDK_WIDGET_REGISTRY as r, useThemeContext as s, FluidProvider as t, createFluidClient as u, toScreenDefinition as v, DEFAULT_AUTH_URL as y };
|
|
1283
786
|
|
|
1284
|
-
//# sourceMappingURL=
|
|
787
|
+
//# sourceMappingURL=FluidProvider-BafZw8PJ.mjs.map
|