@fluid-app/portal-sdk 0.1.135 → 0.1.136

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 (31) hide show
  1. package/dist/ProductsScreen-C7cXqLN8.cjs +110 -0
  2. package/dist/ProductsScreen-C7cXqLN8.cjs.map +1 -0
  3. package/dist/{ProductsScreen-CbKT2maZ.mjs → ProductsScreen-CTUejNR0.mjs} +2 -2
  4. package/dist/{ProductsScreen-T1tGuiGy.cjs → ProductsScreen-CcF3f9VD.cjs} +2 -2
  5. package/dist/ProductsScreen-Di6uVQCx.mjs +98 -0
  6. package/dist/ProductsScreen-Di6uVQCx.mjs.map +1 -0
  7. package/dist/ShareablesScreen-B-uZ3B5d.cjs +430 -0
  8. package/dist/ShareablesScreen-B-uZ3B5d.cjs.map +1 -0
  9. package/dist/{ShareablesScreen-DSW36iS7.mjs → ShareablesScreen-BHyxG-oy.mjs} +2 -2
  10. package/dist/{ShareablesScreen-BLbzr0Jb.cjs → ShareablesScreen-DAM01cxf.cjs} +2 -2
  11. package/dist/ShareablesScreen-iBUd6p7M.mjs +412 -0
  12. package/dist/ShareablesScreen-iBUd6p7M.mjs.map +1 -0
  13. package/dist/index.cjs +7 -7
  14. package/dist/index.d.cts.map +1 -1
  15. package/dist/index.d.mts.map +1 -1
  16. package/dist/index.mjs +7 -7
  17. package/dist/{src-BbjxT3sc.mjs → portal-tenant-product-media-adapter-Co9Kw-US.mjs} +980 -4
  18. package/dist/portal-tenant-product-media-adapter-Co9Kw-US.mjs.map +1 -0
  19. package/dist/{src-DmzXXBVt.cjs → portal-tenant-product-media-adapter-DM94zJXA.cjs} +1039 -3
  20. package/dist/portal-tenant-product-media-adapter-DM94zJXA.cjs.map +1 -0
  21. package/package.json +16 -16
  22. package/dist/ProductsScreen-B1OAGNQx.cjs +0 -283
  23. package/dist/ProductsScreen-B1OAGNQx.cjs.map +0 -1
  24. package/dist/ProductsScreen-CL71MQNL.mjs +0 -271
  25. package/dist/ProductsScreen-CL71MQNL.mjs.map +0 -1
  26. package/dist/ShareablesScreen-CecBPoFO.mjs +0 -1360
  27. package/dist/ShareablesScreen-CecBPoFO.mjs.map +0 -1
  28. package/dist/ShareablesScreen-DDutXKpW.cjs +0 -1378
  29. package/dist/ShareablesScreen-DDutXKpW.cjs.map +0 -1
  30. package/dist/src-BbjxT3sc.mjs.map +0 -1
  31. package/dist/src-DmzXXBVt.cjs.map +0 -1
@@ -1,1378 +0,0 @@
1
- require("./chunk-9hOWP6kD.cjs");
2
- const require_FluidProvider = require("./FluidProvider-Dyq7lCdf.cjs");
3
- const require_use_fluid_auth = require("./use-fluid-auth-DCaxdBCx.cjs");
4
- const require_use_current_user = require("./use-current-user-C4oXzxPk.cjs");
5
- const require_AppNavigationContext = require("./AppNavigationContext-Agp0UkCQ.cjs");
6
- const require_use_account_clients = require("./use-account-clients-C6QS6yk6.cjs");
7
- const require_src = require("./src-DmzXXBVt.cjs");
8
- const require_use_portal_products_client = require("./use-portal-products-client-CTaxgbMq.cjs");
9
- let react = require("react");
10
- let react_jsx_runtime = require("react/jsx-runtime");
11
- let zod = require("zod");
12
- //#region src/hooks/use-user-type.ts
13
- /**
14
- * Convenience hook for user-type checks in the portal SDK.
15
- */
16
- function useUserType() {
17
- const { user } = require_use_fluid_auth.useFluidAuth();
18
- return (0, react.useMemo)(() => {
19
- const userType = user?.user_type ?? null;
20
- return {
21
- userType,
22
- isCustomer: userType === require_FluidProvider.USER_TYPES.customer,
23
- isRep: userType === require_FluidProvider.USER_TYPES.rep,
24
- isAdmin: userType === require_FluidProvider.USER_TYPES.admin || userType === require_FluidProvider.USER_TYPES.root_admin
25
- };
26
- }, [user?.user_type]);
27
- }
28
- //#endregion
29
- //#region ../../file-picker/core/src/schemas/dam.ts
30
- const damVariantSchema = zod.z.object({
31
- id: zod.z.string(),
32
- url: zod.z.string().nullable(),
33
- file_name: zod.z.string(),
34
- mime_type: zod.z.string(),
35
- content: zod.z.any().nullable(),
36
- created_at: zod.z.string(),
37
- updated_at: zod.z.string(),
38
- default: zod.z.boolean(),
39
- is_original: zod.z.boolean(),
40
- is_text: zod.z.boolean(),
41
- media_type: zod.z.string(),
42
- processing_status: zod.z.string(),
43
- tags: zod.z.array(zod.z.string())
44
- });
45
- const damAssetSchema = zod.z.object({
46
- id: zod.z.number(),
47
- canonical_path: zod.z.string(),
48
- category: zod.z.string(),
49
- code: zod.z.string(),
50
- company: zod.z.string(),
51
- created_at: zod.z.string(),
52
- default_variant_id: zod.z.string(),
53
- default_variant_url: zod.z.string().optional(),
54
- description: zod.z.string(),
55
- name: zod.z.string(),
56
- updated_at: zod.z.string(),
57
- variants: zod.z.array(damVariantSchema).optional()
58
- });
59
- const damTreeFolderNodeSchema = zod.z.object({
60
- asset_code: zod.z.union([zod.z.string(), zod.z.record(zod.z.string(), zod.z.unknown())]).optional(),
61
- name: zod.z.union([zod.z.string(), zod.z.record(zod.z.string(), zod.z.unknown())]).optional(),
62
- category: zod.z.union([zod.z.string(), zod.z.record(zod.z.string(), zod.z.unknown())]).optional(),
63
- variants: zod.z.union([zod.z.array(zod.z.unknown()), zod.z.record(zod.z.string(), zod.z.unknown())]).optional()
64
- }).passthrough();
65
- const damTreeSchema = zod.z.record(zod.z.string(), zod.z.union([
66
- zod.z.lazy(() => damTreeSchema),
67
- damAssetSchema,
68
- damTreeFolderNodeSchema
69
- ]));
70
- const damQueryResponseSchema = zod.z.object({
71
- path: zod.z.string(),
72
- tree: damTreeSchema,
73
- meta: zod.z.object({ next_cursor: zod.z.string().optional() }).optional()
74
- });
75
- zod.z.object({ asset: zod.z.object({
76
- file: zod.z.any(),
77
- name: zod.z.string(),
78
- description: zod.z.string().optional(),
79
- tags: zod.z.string().optional()
80
- }) });
81
- zod.z.object({
82
- asset: damAssetSchema,
83
- meta: zod.z.object({
84
- request_id: zod.z.string(),
85
- timestamp: zod.z.string()
86
- })
87
- });
88
- zod.z.object({
89
- placeholder_asset: zod.z.object({
90
- mime_type: zod.z.string(),
91
- name: zod.z.string().optional(),
92
- description: zod.z.string().optional()
93
- }),
94
- skip_autotagging: zod.z.boolean().optional()
95
- });
96
- zod.z.object({
97
- asset: zod.z.object({
98
- file: zod.z.any(),
99
- name: zod.z.string(),
100
- description: zod.z.string().optional(),
101
- tags: zod.z.string().optional()
102
- }).optional(),
103
- text_asset: zod.z.object({
104
- file_name: zod.z.string(),
105
- mime_type: zod.z.string(),
106
- text: zod.z.string(),
107
- name: zod.z.string().optional(),
108
- description: zod.z.string().optional(),
109
- tags: zod.z.string().optional()
110
- }).optional(),
111
- placeholder_asset: zod.z.object({
112
- mime_type: zod.z.string(),
113
- name: zod.z.string().optional(),
114
- description: zod.z.string().optional()
115
- }).optional(),
116
- skip_autotagging: zod.z.boolean().optional()
117
- });
118
- zod.z.object({
119
- asset: zod.z.object({
120
- id: zod.z.number(),
121
- canonical_path: zod.z.string(),
122
- name: zod.z.string()
123
- }),
124
- meta: zod.z.object({
125
- request_id: zod.z.string(),
126
- timestamp: zod.z.string()
127
- })
128
- });
129
- //#endregion
130
- //#region ../../api-clients/portal-tenant-content/src/namespaces/portal_tenant_content.ts
131
- /**
132
- * List media (own uploads and company media)
133
- * Returns a paginated list of the member's own uploads and company-owned media.
134
- *
135
- * @param client - Fetch client instance
136
- * @param [params] - params
137
- */
138
- async function media_list(client, params) {
139
- return client.get(`/api/content/media`, params);
140
- }
141
- /**
142
- * Create a new media item
143
- * Creates a new media item record.
144
- *
145
- * @param client - Fetch client instance
146
- * @param body - body
147
- */
148
- async function media_create(client, body) {
149
- return client.post(`/api/content/media`, body);
150
- }
151
- /**
152
- * Get a specific media item
153
- * Returns a single media item by ID.
154
- *
155
- * @param client - Fetch client instance
156
- * @param id - id
157
- */
158
- async function media_show(client, id) {
159
- return client.get(`/api/content/media/${id}`);
160
- }
161
- /**
162
- * Update a media item (own uploads only)
163
- * Updates a media item's title or description.
164
- *
165
- * @param client - Fetch client instance
166
- * @param id - id
167
- * @param body - body
168
- */
169
- async function media_update(client, id, body) {
170
- return client.patch(`/api/content/media/${id}`, body);
171
- }
172
- /**
173
- * Delete a media item (own uploads only)
174
- * Removes a media item.
175
- *
176
- * @param client - Fetch client instance
177
- * @param id - id
178
- */
179
- async function media_destroy(client, id) {
180
- return client.delete(`/api/content/media/${id}`);
181
- }
182
- /**
183
- * List playlists with cursor pagination
184
- * Returns a paginated list of playlists.
185
- *
186
- * @param client - Fetch client instance
187
- * @param [params] - params
188
- */
189
- async function playlists_list(client, params) {
190
- return client.get(`/api/content/playlists`, params);
191
- }
192
- /**
193
- * Create a new playlist
194
- * Creates a new playlist.
195
- *
196
- * @param client - Fetch client instance
197
- * @param body - body
198
- */
199
- async function playlists_create(client, body) {
200
- return client.post(`/api/content/playlists`, body);
201
- }
202
- /**
203
- * Get a specific playlist
204
- * Returns a single playlist by ID.
205
- *
206
- * @param client - Fetch client instance
207
- * @param id - id
208
- */
209
- async function playlists_show(client, id) {
210
- return client.get(`/api/content/playlists/${id}`);
211
- }
212
- /**
213
- * Update a playlist
214
- * Updates a playlist's title or metadata.
215
- *
216
- * @param client - Fetch client instance
217
- * @param id - id
218
- * @param body - body
219
- */
220
- async function playlists_update(client, id, body) {
221
- return client.patch(`/api/content/playlists/${id}`, body);
222
- }
223
- /**
224
- * Delete a playlist
225
- * Removes a playlist.
226
- *
227
- * @param client - Fetch client instance
228
- * @param id - id
229
- */
230
- async function playlists_destroy(client, id) {
231
- return client.delete(`/api/content/playlists/${id}`);
232
- }
233
- /**
234
- * List items in a playlist
235
- * Returns a paginated list of items in a playlist.
236
- *
237
- * @param client - Fetch client instance
238
- * @param playlist_id - playlist_id
239
- * @param [params] - params
240
- */
241
- async function playlists_items_list(client, playlist_id, params) {
242
- return client.get(`/api/content/playlists/${playlist_id}/items`, params);
243
- }
244
- /**
245
- * Add an item to a playlist
246
- * Adds a media item to a playlist.
247
- *
248
- * @param client - Fetch client instance
249
- * @param playlist_id - playlist_id
250
- * @param body - body
251
- */
252
- async function playlists_items_add(client, playlist_id, body) {
253
- return client.post(`/api/content/playlists/${playlist_id}/items`, body);
254
- }
255
- /**
256
- * Remove an item from a playlist
257
- * Removes a single item from a playlist.
258
- *
259
- * @param client - Fetch client instance
260
- * @param playlist_id - playlist_id
261
- * @param id - id
262
- */
263
- async function playlists_items_remove(client, playlist_id, id) {
264
- return client.delete(`/api/content/playlists/${playlist_id}/items/${id}`);
265
- }
266
- /**
267
- * List share links for the current user
268
- * Returns a paginated list of share links.
269
- *
270
- * @param client - Fetch client instance
271
- * @param [params] - params
272
- */
273
- async function shares_list(client, params) {
274
- return client.get(`/api/shares`, params);
275
- }
276
- /**
277
- * Create a share link
278
- * Creates a new share link for content.
279
- *
280
- * @param client - Fetch client instance
281
- * @param body - body
282
- */
283
- async function shares_create(client, body) {
284
- return client.post(`/api/shares`, body);
285
- }
286
- /**
287
- * List DAM assets
288
- * Returns a paginated list of DAM assets for the company.
289
- *
290
- * @param client - Fetch client instance
291
- * @param [params] - params
292
- */
293
- async function dam_assets_list(client, params) {
294
- return client.get(`/api/content/dam/assets`, params);
295
- }
296
- /**
297
- * Create a DAM asset
298
- * Creates a new DAM asset. Supports two modes:
299
- 1. **JSON placeholder** — send `application/json` with `asset[name]` to
300
- create a placeholder record for later file upload.
301
-
302
- 2. **File upload** — send `multipart/form-data` with `asset[file]`,
303
- `asset[name]`, and optionally `asset[description]` and `asset[tags]`
304
- to upload a file and create the full asset with variants.
305
- *
306
- * @param client - Fetch client instance
307
- * @param body - body
308
- */
309
- async function dam_assets_create(client, body) {
310
- return client.post(`/api/content/dam/assets`, body);
311
- }
312
- /**
313
- * List paths for a DAM asset
314
- * Returns a paginated list of path aliases for a DAM asset.
315
- *
316
- * @param client - Fetch client instance
317
- * @param asset_code - asset_code
318
- * @param [params] - params
319
- */
320
- async function dam_asset_paths_list(client, asset_code, params) {
321
- return client.get(`/api/content/dam/assets/${asset_code}/paths`, params);
322
- }
323
- /**
324
- * Create a path alias for a DAM asset
325
- * Creates a new path alias for an existing DAM asset.
326
- *
327
- * @param client - Fetch client instance
328
- * @param asset_code - asset_code
329
- * @param body - body
330
- */
331
- async function dam_asset_paths_create(client, asset_code, body) {
332
- return client.post(`/api/content/dam/assets/${asset_code}/paths`, body);
333
- }
334
- /**
335
- * Query DAM assets using tree paths and tags
336
- * Searches and retrieves DAM assets using tree path pattern matching, tag-based variant filtering, wildcard name matching, and partial search. Supports cursor pagination for large result sets.
337
- *
338
- * @param client - Fetch client instance
339
- * @param body - body
340
- */
341
- async function dam_query(client, body) {
342
- return client.post(`/api/content/dam/query`, body);
343
- }
344
- /**
345
- * Delete a DAM asset
346
- * Permanently destroys a DAM asset, including its ImageKit storage, variants, and database records.
347
- *
348
- * @param client - Fetch client instance
349
- * @param code - code
350
- */
351
- async function dam_assets_destroy(client, code) {
352
- return client.delete(`/api/content/dam/assets/${code}`);
353
- }
354
- /**
355
- * Discard (soft-delete) a DAM asset
356
- * Soft-deletes a DAM asset. Used to discard an in-progress upload without permanently removing the record.
357
- *
358
- * @param client - Fetch client instance
359
- * @param code - code
360
- */
361
- async function dam_assets_discard(client, code) {
362
- return client.patch(`/api/content/dam/assets/${code}/discard`);
363
- }
364
- //#endregion
365
- //#region ../../shareables/api-client/src/portal-tenant-media-adapter.ts
366
- /**
367
- * Maps a BFF media object to the port's Media shape, providing defaults
368
- * for optional fields returned by the generated client.
369
- */
370
- function mapMedia(raw) {
371
- return {
372
- id: raw.id ?? 0,
373
- title: raw.title ?? "",
374
- description: raw.description ?? null,
375
- media_type: raw.media_type ?? "",
376
- url: raw.url ?? null,
377
- thumbnail_url: raw.thumbnail_url ?? null,
378
- owner_type: raw.owner_type ?? "",
379
- created_at: raw.created_at ?? "",
380
- updated_at: raw.updated_at ?? ""
381
- };
382
- }
383
- /**
384
- * Maps the BFF meta envelope to the port's ApiMeta shape.
385
- */
386
- function mapMeta$3(raw) {
387
- return {
388
- request_id: raw?.request_id ?? null,
389
- timestamp: raw?.timestamp ?? "",
390
- pagination: raw?.pagination ? {
391
- cursor: raw.pagination.cursor ?? null,
392
- limit: raw.pagination.limit,
393
- next_cursor: raw.pagination.next_cursor ?? null,
394
- prev_cursor: raw.pagination.prev_cursor ?? null
395
- } : void 0
396
- };
397
- }
398
- /**
399
- * Creates a ContentMediaApi adapter backed by the portal-tenant content BFF.
400
- *
401
- * Maps the generated portal-tenant-content namespace functions to the abstract
402
- * ContentMediaApi port, closing over the FetchClient so consumers don't need
403
- * to pass it per-call.
404
- */
405
- function createPortalTenantMediaAdapter(client) {
406
- return {
407
- listMedia: async (params) => {
408
- const response = await media_list(client, {
409
- "page[cursor]": params?.cursor,
410
- "page[limit]": params?.limit,
411
- media_type: params?.media_type,
412
- "filter[title]": params?.["filter[title]"],
413
- sort: params?.sort
414
- });
415
- return {
416
- media: (response.media ?? []).map(mapMedia),
417
- meta: mapMeta$3(response.meta)
418
- };
419
- },
420
- createMedia: async (body) => {
421
- const response = await media_create(client, { media: body });
422
- return {
423
- media: mapMedia(response.media ?? {}),
424
- meta: mapMeta$3(response.meta)
425
- };
426
- },
427
- getMedia: async (id) => {
428
- const response = await media_show(client, id);
429
- return {
430
- media: mapMedia(response.media ?? {}),
431
- meta: mapMeta$3(response.meta)
432
- };
433
- },
434
- updateMedia: async (id, body) => {
435
- const response = await media_update(client, id, { media: body });
436
- return {
437
- media: mapMedia(response.media ?? {}),
438
- meta: mapMeta$3(response.meta)
439
- };
440
- },
441
- deleteMedia: async (id) => {
442
- const response = await media_destroy(client, id);
443
- return {
444
- media: { id: response.media?.id ?? 0 },
445
- meta: mapMeta$3(response.meta)
446
- };
447
- }
448
- };
449
- }
450
- function mediaKindFromType$1(mediaType) {
451
- if (mediaType === "video") return "video";
452
- if (mediaType === "image") return "image";
453
- if (mediaType === "document" || mediaType === "pdf") return "pdf";
454
- return null;
455
- }
456
- function toBffMediumResponse(bff) {
457
- const kind = mediaKindFromType$1(bff.media_type);
458
- const isVideo = bff.media_type === "video";
459
- const isPdf = bff.media_type === "pdf" || bff.media_type === "document";
460
- return {
461
- id: bff.id,
462
- user_id: null,
463
- media_type: bff.media_type,
464
- media_format: bff.media_type,
465
- image_url: !isVideo && !isPdf ? bff.url ?? bff.thumbnail_url ?? null : bff.thumbnail_url ?? null,
466
- video_url: isVideo ? bff.url ?? null : null,
467
- pdf_url: isPdf ? bff.url ?? null : null,
468
- title: bff.title,
469
- description: {
470
- id: null,
471
- name: null,
472
- body: bff.description ?? null,
473
- record_type: null,
474
- record_id: null,
475
- created_at: bff.created_at ?? null,
476
- updated_at: bff.updated_at ?? null,
477
- locale: null
478
- },
479
- stripped: bff.description ?? null,
480
- kind,
481
- active: true,
482
- visibility: null,
483
- share_link: null,
484
- views: 0,
485
- leads: 0,
486
- watch: null,
487
- video_status: null,
488
- duration: null,
489
- cta_url: null,
490
- cta_button_text: null,
491
- cta_enabled: false,
492
- cta_action_type: null,
493
- video_shopping_enabled: false,
494
- prompts_enabled: false,
495
- ranks: [],
496
- preview_link: null,
497
- attached_shareables: [],
498
- created_at: bff.created_at
499
- };
500
- }
501
- /**
502
- * Creates a ShareablesApi["media"]-compatible adapter backed by the
503
- * portal-tenant content BFF. Includes cursor-to-page-number caching
504
- * for bridging the legacy UI's page-number pagination.
505
- */
506
- function createPortalTenantMediaShareablesAdapter(client) {
507
- const portAdapter = createPortalTenantMediaAdapter(client);
508
- const cursorByPage = /* @__PURE__ */ new Map();
509
- let lastFilterKey = "";
510
- return {
511
- getMedia: async (options) => {
512
- const pageNumber = options?.page ?? 1;
513
- const filterKey = `${options?.search_query ?? ""}|${options?.sorted_by ?? ""}|${options?.media_type ?? options?.with_type ?? ""}`;
514
- if (filterKey !== lastFilterKey) {
515
- cursorByPage.clear();
516
- lastFilterKey = filterKey;
517
- }
518
- const cursor = pageNumber > 1 ? cursorByPage.get(pageNumber) : void 0;
519
- const rawSort = options?.sorted_by;
520
- let bffSort;
521
- if (rawSort === "title_asc") bffSort = "title_asc";
522
- else if (rawSort === "title_desc") bffSort = "title_desc";
523
- const response = await portAdapter.listMedia({
524
- cursor,
525
- limit: options?.per_page,
526
- media_type: options?.media_type ?? options?.with_type,
527
- "filter[title]": options?.search_query,
528
- sort: bffSort
529
- });
530
- const nextCursor = response.meta.pagination?.next_cursor;
531
- if (nextCursor) cursorByPage.set(pageNumber + 1, nextCursor);
532
- const transformedItems = response.media.map(toBffMediumResponse);
533
- return {
534
- data: transformedItems,
535
- status: "success",
536
- media: transformedItems,
537
- meta: {
538
- total_count: transformedItems.length,
539
- current: pageNumber,
540
- per_page: options?.per_page ?? 24,
541
- pages: nextCursor ? pageNumber + 1 : pageNumber,
542
- next: nextCursor ? pageNumber + 1 : null,
543
- previous: pageNumber > 1 ? pageNumber - 1 : null
544
- }
545
- };
546
- },
547
- getMediaById: async (id) => {
548
- const medium = toBffMediumResponse((await portAdapter.getMedia(id)).media);
549
- return {
550
- data: medium,
551
- status: "success",
552
- media: medium
553
- };
554
- },
555
- createMedia: async (mediaData) => {
556
- return toBffMediumResponse((await portAdapter.createMedia({
557
- title: mediaData.title ?? "",
558
- description: mediaData.description,
559
- media_type: mediaData.media_type ?? "image",
560
- url: mediaData.image_url ?? mediaData.video_url ?? mediaData.pdf_url ?? void 0
561
- })).media);
562
- },
563
- updateMedia: async (id, mediaData) => {
564
- return toBffMediumResponse((await portAdapter.updateMedia(id, {
565
- title: mediaData.title,
566
- description: mediaData.description
567
- })).media);
568
- },
569
- deleteMedia: async (id) => {
570
- await portAdapter.deleteMedia(id);
571
- return { success: true };
572
- }
573
- };
574
- }
575
- //#endregion
576
- //#region ../../shareables/api-client/src/portal-tenant-playlists-adapter.ts
577
- /**
578
- * Maps a BFF playlist object to the port's Playlist shape.
579
- */
580
- function mapPlaylist(raw) {
581
- return {
582
- id: raw.id ?? 0,
583
- title: raw.title ?? "",
584
- description: raw.description ?? null,
585
- items_count: raw.items_count ?? 0,
586
- user_id: raw.user_id,
587
- is_favorited: raw.is_favorited,
588
- image_url: raw.image_url ?? null,
589
- created_at: raw.created_at ?? "",
590
- updated_at: raw.updated_at ?? ""
591
- };
592
- }
593
- /**
594
- * Maps a BFF playlist item to the port's PlaylistItem shape.
595
- */
596
- function mapPlaylistItem(raw) {
597
- return {
598
- id: raw.id ?? 0,
599
- media_id: raw.media_id ?? 0,
600
- position: raw.position ?? null,
601
- title: raw.title,
602
- image_url: raw.image_url ?? null,
603
- media_type: raw.media_type,
604
- video_url: raw.video_url ?? null,
605
- duration: raw.duration ?? null,
606
- created_at: raw.created_at ?? ""
607
- };
608
- }
609
- /**
610
- * Maps the BFF meta envelope to the port's ApiMeta shape.
611
- */
612
- function mapMeta$2(raw) {
613
- return {
614
- request_id: raw?.request_id ?? null,
615
- timestamp: raw?.timestamp ?? "",
616
- pagination: raw?.pagination ? {
617
- cursor: raw.pagination.cursor ?? null,
618
- limit: raw.pagination.limit,
619
- next_cursor: raw.pagination.next_cursor ?? null,
620
- prev_cursor: raw.pagination.prev_cursor ?? null
621
- } : void 0
622
- };
623
- }
624
- /**
625
- * Creates a ContentPlaylistsApi adapter backed by the portal-tenant content BFF.
626
- *
627
- * Maps the generated portal-tenant-content namespace functions to the abstract
628
- * ContentPlaylistsApi port, closing over the FetchClient so consumers don't
629
- * need to pass it per-call.
630
- */
631
- function createPortalTenantPlaylistsAdapter(client) {
632
- return {
633
- listPlaylists: async (params) => {
634
- const response = await playlists_list(client, {
635
- "page[cursor]": params?.cursor,
636
- "page[limit]": params?.limit,
637
- "filter[title]": params?.["filter[title]"],
638
- sort: params?.sort
639
- });
640
- return {
641
- playlists: (response.playlists ?? []).map(mapPlaylist),
642
- meta: mapMeta$2(response.meta)
643
- };
644
- },
645
- createPlaylist: async (body) => {
646
- const response = await playlists_create(client, { playlist: body });
647
- return {
648
- playlist: mapPlaylist(response.playlist ?? {}),
649
- meta: mapMeta$2(response.meta)
650
- };
651
- },
652
- getPlaylist: async (id) => {
653
- const response = await playlists_show(client, id);
654
- return {
655
- playlist: mapPlaylist(response.playlist ?? {}),
656
- meta: mapMeta$2(response.meta)
657
- };
658
- },
659
- updatePlaylist: async (id, body) => {
660
- const response = await playlists_update(client, id, { playlist: body });
661
- return {
662
- playlist: mapPlaylist(response.playlist ?? {}),
663
- meta: mapMeta$2(response.meta)
664
- };
665
- },
666
- deletePlaylist: async (id) => {
667
- const response = await playlists_destroy(client, id);
668
- return {
669
- playlist: { id: response.playlist?.id ?? 0 },
670
- meta: mapMeta$2(response.meta)
671
- };
672
- },
673
- listPlaylistItems: async (playlistId, params) => {
674
- const response = await playlists_items_list(client, playlistId, {
675
- "page[cursor]": params?.cursor,
676
- "page[limit]": params?.limit
677
- });
678
- return {
679
- playlist_items: (response.playlist_items ?? []).map(mapPlaylistItem),
680
- meta: mapMeta$2(response.meta)
681
- };
682
- },
683
- addPlaylistItem: async (playlistId, body) => {
684
- const response = await playlists_items_add(client, playlistId, { item: body });
685
- return {
686
- playlist_item: mapPlaylistItem(response.playlist_item ?? {}),
687
- meta: mapMeta$2(response.meta)
688
- };
689
- },
690
- removePlaylistItem: async (playlistId, itemId) => {
691
- const response = await playlists_items_remove(client, playlistId, itemId);
692
- return {
693
- playlist_item: { id: response.playlist_item?.id ?? 0 },
694
- meta: mapMeta$2(response.meta)
695
- };
696
- }
697
- };
698
- }
699
- function mediaKindFromType(mediaType) {
700
- if (mediaType === "video") return "video";
701
- if (mediaType === "image") return "image";
702
- if (mediaType === "document" || mediaType === "pdf") return "pdf";
703
- return null;
704
- }
705
- function toBffPlaylist(bff, items) {
706
- return {
707
- id: bff.id,
708
- title: bff.title,
709
- description: bff.description ?? null,
710
- image_url: bff.image_url ?? null,
711
- slug: null,
712
- active: true,
713
- user_id: bff.user_id ?? null,
714
- is_favorited: bff.is_favorited ?? false,
715
- items: items ?? [],
716
- items_count: bff.items_count
717
- };
718
- }
719
- /**
720
- * Creates a ShareablesApi["playlists"]-compatible adapter backed by the
721
- * portal-tenant content BFF. Fetches playlist + items in parallel for
722
- * detail views and maps enriched flat fields onto playlist items.
723
- */
724
- function createPortalTenantPlaylistsShareablesAdapter(client) {
725
- const portAdapter = createPortalTenantPlaylistsAdapter(client);
726
- return {
727
- getPlaylists: async (options) => {
728
- const rawSort = options?.sort;
729
- let bffSort;
730
- if (rawSort === "title_asc" || rawSort === "title") bffSort = "title_asc";
731
- else if (rawSort === "title_desc" || rawSort === "-title") bffSort = "title_desc";
732
- else if (rawSort === "created_at_asc" || rawSort === "created_at") bffSort = "created_at_asc";
733
- else if (rawSort === "created_at_desc" || rawSort === "-created_at") bffSort = "created_at_desc";
734
- const response = await portAdapter.listPlaylists({
735
- cursor: options?.["page[cursor]"],
736
- limit: options?.["page[limit]"],
737
- "filter[title]": options?.["filter[title]"],
738
- sort: bffSort
739
- });
740
- return {
741
- playlists: response.playlists.map((p) => toBffPlaylist(p)),
742
- meta: {
743
- request_id: response.meta.request_id ?? "",
744
- timestamp: response.meta.timestamp ?? "",
745
- pagination: {
746
- cursor: response.meta.pagination?.cursor ?? null,
747
- limit: response.meta.pagination?.limit ?? 12,
748
- prev_cursor: response.meta.pagination?.prev_cursor ?? null,
749
- next_cursor: response.meta.pagination?.next_cursor ?? null,
750
- total_count: 0,
751
- total_pages: 0
752
- }
753
- }
754
- };
755
- },
756
- getPlaylistById: async (id) => {
757
- const response = await portAdapter.getPlaylist(id);
758
- const allItems = [];
759
- let cursor;
760
- const MAX_PAGES = 50;
761
- for (let i = 0; i < MAX_PAGES; i++) {
762
- const page = await portAdapter.listPlaylistItems(id, {
763
- cursor,
764
- limit: 100
765
- });
766
- allItems.push(...page.playlist_items);
767
- cursor = page.meta.pagination?.next_cursor ?? void 0;
768
- if (!cursor) break;
769
- }
770
- const items = allItems.map((item) => ({
771
- id: item.id,
772
- order: item.position ?? void 0,
773
- relateable_type: "Medium",
774
- relateable: { id: item.media_id },
775
- title: item.title ?? "Untitled",
776
- image_url: item.image_url ?? null,
777
- kind: mediaKindFromType(item.media_type ?? ""),
778
- video_url: item.video_url ?? null,
779
- duration: item.duration ?? null,
780
- media_format: item.media_type ?? null
781
- }));
782
- return {
783
- playlist: toBffPlaylist(response.playlist, items),
784
- meta: {
785
- request_id: response.meta.request_id ?? "",
786
- timestamp: response.meta.timestamp ?? ""
787
- }
788
- };
789
- },
790
- createPlaylist: async (data) => {
791
- const response = await portAdapter.createPlaylist({
792
- title: data.playlist.title,
793
- description: data.playlist.description
794
- });
795
- return {
796
- playlist: toBffPlaylist(response.playlist),
797
- meta: {
798
- request_id: response.meta.request_id ?? "",
799
- timestamp: response.meta.timestamp ?? ""
800
- }
801
- };
802
- },
803
- updatePlaylist: async (id, data) => {
804
- const response = await portAdapter.updatePlaylist(id, {
805
- title: data.playlist.title,
806
- description: data.playlist.description
807
- });
808
- return {
809
- playlist: toBffPlaylist(response.playlist),
810
- meta: {
811
- request_id: response.meta.request_id ?? "",
812
- timestamp: response.meta.timestamp ?? ""
813
- }
814
- };
815
- },
816
- addItemToPlaylist: async (id, data) => {
817
- await Promise.all(data.items.map((item) => portAdapter.addPlaylistItem(id, {
818
- media_id: item.relateable_id,
819
- position: typeof item.order === "number" ? item.order : Number(item.order)
820
- })));
821
- return toBffPlaylist((await portAdapter.getPlaylist(id)).playlist);
822
- },
823
- removeItemsFromPlaylist: async (playlistId, data) => {
824
- await Promise.all(data.item_ids.map((itemId) => portAdapter.removePlaylistItem(playlistId, itemId)));
825
- return toBffPlaylist((await portAdapter.getPlaylist(playlistId)).playlist);
826
- }
827
- };
828
- }
829
- //#endregion
830
- //#region ../../shareables/api-client/src/portal-tenant-dam-assets-adapter.ts
831
- /**
832
- * Maps a BFF DAM asset to the port's DamAsset shape.
833
- */
834
- function mapDamAsset(raw) {
835
- return {
836
- id: raw.id ?? 0,
837
- code: raw.code ?? "",
838
- name: raw.name ?? "",
839
- description: raw.description ?? null,
840
- category: raw.category ?? null,
841
- company: raw.company ?? null,
842
- default_variant_id: raw.default_variant_id ?? null,
843
- default_variant_url: raw.default_variant_url ?? null,
844
- canonical_path: raw.canonical_path ?? null,
845
- created_at: raw.created_at ?? "",
846
- updated_at: raw.updated_at ?? ""
847
- };
848
- }
849
- /**
850
- * Maps a BFF DAM asset path to the port's DamAssetPath shape.
851
- */
852
- function mapDamAssetPath(raw) {
853
- return {
854
- id: raw.id ?? 0,
855
- asset_code: raw.asset_code ?? "",
856
- path: raw.path ?? "",
857
- created_at: raw.created_at ?? ""
858
- };
859
- }
860
- /**
861
- * Maps the BFF meta envelope to the port's ApiMeta shape.
862
- */
863
- function mapMeta$1(raw) {
864
- return {
865
- request_id: raw?.request_id ?? null,
866
- timestamp: raw?.timestamp ?? "",
867
- pagination: raw?.pagination ? {
868
- cursor: raw.pagination.cursor ?? null,
869
- limit: raw.pagination.limit,
870
- next_cursor: raw.pagination.next_cursor ?? null,
871
- prev_cursor: raw.pagination.prev_cursor ?? null
872
- } : void 0
873
- };
874
- }
875
- /**
876
- * Creates a ContentDamAssetsApi adapter backed by the portal-tenant content BFF.
877
- *
878
- * Maps the generated portal-tenant-content namespace functions to the abstract
879
- * ContentDamAssetsApi port, closing over the FetchClient so consumers don't
880
- * need to pass it per-call.
881
- */
882
- function createPortalTenantDamAssetsAdapter(client) {
883
- return {
884
- listAssets: async (params) => {
885
- const response = await dam_assets_list(client, {
886
- "page[cursor]": params?.cursor,
887
- "page[limit]": params?.limit
888
- });
889
- return {
890
- assets: (response.assets ?? []).map(mapDamAsset),
891
- meta: mapMeta$1(response.meta)
892
- };
893
- },
894
- createAsset: async (body) => {
895
- const response = await dam_assets_create(client, { asset: body });
896
- return {
897
- asset: mapDamAsset(response.asset ?? {}),
898
- meta: mapMeta$1(response.meta)
899
- };
900
- },
901
- listAssetPaths: async (assetCode, params) => {
902
- const response = await dam_asset_paths_list(client, assetCode, {
903
- "page[cursor]": params?.cursor,
904
- "page[limit]": params?.limit
905
- });
906
- return {
907
- asset_paths: (response.asset_paths ?? []).map(mapDamAssetPath),
908
- meta: mapMeta$1(response.meta)
909
- };
910
- },
911
- createAssetPath: async (assetCode, body) => {
912
- const response = await dam_asset_paths_create(client, assetCode, { asset_path: body });
913
- return {
914
- asset_path: mapDamAssetPath(response.asset_path ?? {}),
915
- meta: mapMeta$1(response.meta)
916
- };
917
- }
918
- };
919
- }
920
- /**
921
- * Creates a ShareablesApi["fileResources"]-compatible adapter backed by the
922
- * portal-tenant content BFF. Maps DamAsset to FileResource shape and
923
- * includes cursor-to-page-number caching for legacy UI pagination.
924
- */
925
- function createPortalTenantFilesShareablesAdapter(client) {
926
- const portAdapter = createPortalTenantDamAssetsAdapter(client);
927
- const cursorByPage = /* @__PURE__ */ new Map();
928
- return { getFileResources: async (params) => {
929
- const pageNumber = params?.pageParam ? Number(params.pageParam) : 1;
930
- const pageSize = params?.pageSize ? Number(params.pageSize) : 25;
931
- const cursor = pageNumber > 1 ? cursorByPage.get(pageNumber) : void 0;
932
- const response = await portAdapter.listAssets({
933
- cursor,
934
- limit: pageSize
935
- });
936
- const nextCursor = response.meta.pagination?.next_cursor;
937
- if (nextCursor) cursorByPage.set(pageNumber + 1, nextCursor);
938
- const fileResources = response.assets.map((asset) => ({
939
- id: asset.id,
940
- alt_text: asset.name,
941
- url: asset.default_variant_url ?? "",
942
- filename: asset.name,
943
- content_type: "application/octet-stream",
944
- content_size: 0,
945
- handle: asset.code,
946
- dam_asset_code: asset.code,
947
- preview_image_url: asset.default_variant_url ?? "",
948
- created_at: asset.created_at,
949
- updated_at: asset.updated_at ?? "",
950
- relateable_type: null,
951
- relateable_id: null,
952
- content: null
953
- }));
954
- const hasNextPage = !!nextCursor;
955
- return {
956
- file_resources: fileResources,
957
- meta: {
958
- total_count: fileResources.length,
959
- per_page: pageSize,
960
- current_page: pageNumber,
961
- total_pages: hasNextPage ? pageNumber + 1 : pageNumber
962
- }
963
- };
964
- } };
965
- }
966
- //#endregion
967
- //#region ../../shareables/api-client/src/portal-tenant-shares-adapter.ts
968
- /**
969
- * Narrows an unknown string to a valid ShareableType at runtime.
970
- */
971
- function isShareableType(value) {
972
- return value === "media" || value === "product" || value === "library" || value === "page";
973
- }
974
- /**
975
- * Maps a BFF share to the port's Share shape.
976
- */
977
- function mapShare(raw) {
978
- return {
979
- id: raw.id ?? 0,
980
- url: raw.url ?? "",
981
- shareable_type: isShareableType(raw.shareable_type) ? raw.shareable_type : "media",
982
- shareable_id: raw.shareable_id ?? 0,
983
- created_at: raw.created_at ?? ""
984
- };
985
- }
986
- /**
987
- * Maps the BFF meta envelope to the port's ApiMeta shape.
988
- */
989
- function mapMeta(raw) {
990
- return {
991
- request_id: raw?.request_id ?? null,
992
- timestamp: raw?.timestamp ?? "",
993
- pagination: raw?.pagination ? {
994
- cursor: raw.pagination.cursor ?? null,
995
- limit: raw.pagination.limit,
996
- next_cursor: raw.pagination.next_cursor ?? null,
997
- prev_cursor: raw.pagination.prev_cursor ?? null
998
- } : void 0
999
- };
1000
- }
1001
- /**
1002
- * Creates a ContentSharesApi adapter backed by the portal-tenant content BFF.
1003
- *
1004
- * Maps the generated portal-tenant-content namespace functions to the abstract
1005
- * ContentSharesApi port, closing over the FetchClient so consumers don't need
1006
- * to pass it per-call.
1007
- */
1008
- function createPortalTenantSharesAdapter(client) {
1009
- return {
1010
- listShares: async (params) => {
1011
- const response = await shares_list(client, {
1012
- "page[cursor]": params?.cursor,
1013
- "page[limit]": params?.limit
1014
- });
1015
- return {
1016
- shares: (response.shares ?? []).map(mapShare),
1017
- meta: mapMeta(response.meta)
1018
- };
1019
- },
1020
- createShare: async (body) => {
1021
- const response = await shares_create(client, { share: body });
1022
- return {
1023
- share: mapShare(response.share ?? {}),
1024
- meta: mapMeta(response.meta)
1025
- };
1026
- }
1027
- };
1028
- }
1029
- /**
1030
- * Maps legacy Rails model names (used by the UI) to BFF shareable_type values.
1031
- */
1032
- const SHAREABLE_TYPE_MAP = {
1033
- Medium: "media",
1034
- media: "media",
1035
- Product: "product",
1036
- product: "product",
1037
- Library: "library",
1038
- library: "library",
1039
- Page: "page",
1040
- page: "page"
1041
- };
1042
- /**
1043
- * Creates a ShareablesApi["share"]-compatible adapter backed by the
1044
- * portal-tenant content BFF. Maps legacy model names to BFF shareable types.
1045
- */
1046
- function createPortalTenantSharesShareablesAdapter(client) {
1047
- const portAdapter = createPortalTenantSharesAdapter(client);
1048
- return { createShareLink: async (input) => {
1049
- if (!input.relateableId) throw new Error("Cannot create share link without a relateableId");
1050
- const shareableType = SHAREABLE_TYPE_MAP[input.relateableType];
1051
- if (!shareableType) throw new Error(`Unknown shareable type: "${input.relateableType}"`);
1052
- return (await portAdapter.createShare({
1053
- shareable_type: shareableType,
1054
- shareable_id: input.relateableId
1055
- })).share.url;
1056
- } };
1057
- }
1058
- //#endregion
1059
- //#region ../../file-picker/api-client/src/api/url-proxy.ts
1060
- const urlProxyResponseSchema = zod.z.object({
1061
- data: zod.z.string(),
1062
- contentType: zod.z.string(),
1063
- size: zod.z.number()
1064
- });
1065
- /**
1066
- * Proxy a URL fetch through the backend to bypass CORS restrictions.
1067
- * The backend fetches the file and returns it as base64-encoded data.
1068
- *
1069
- * @param url - The URL to fetch
1070
- * @param proxyEndpoint - The proxy endpoint (defaults to "/api/proxy-url")
1071
- */
1072
- async function proxyUrlFetch(url, proxyEndpoint = "/api/proxy-url") {
1073
- const response = await fetch(proxyEndpoint, {
1074
- method: "POST",
1075
- headers: { "Content-Type": "application/json" },
1076
- body: JSON.stringify({ url })
1077
- });
1078
- if (!response.ok) {
1079
- const errorData = await response.json().catch(() => ({ error: "Failed to proxy URL fetch" }));
1080
- throw new Error(errorData.error || `HTTP ${response.status}`);
1081
- }
1082
- const data = await response.json();
1083
- return urlProxyResponseSchema.parse(data);
1084
- }
1085
- //#endregion
1086
- //#region ../../file-picker/api-client/src/portal-tenant-adapter.ts
1087
- /**
1088
- * Maps a BFF DAM asset to the file-picker port's DamAssetCreateResponse shape.
1089
- *
1090
- * The BFF response includes nullable meta.request_id (from Api::Response),
1091
- * while the port schema requires a string. We coalesce to empty string.
1092
- */
1093
- function mapCreateResponse(response) {
1094
- const raw = response.asset ?? {};
1095
- return {
1096
- asset: damAssetSchema.parse({
1097
- ...raw,
1098
- canonical_path: raw.canonical_path ?? "",
1099
- category: raw.category ?? "",
1100
- company: raw.company ?? "",
1101
- description: raw.description ?? "",
1102
- default_variant_id: raw.default_variant_id ?? ""
1103
- }),
1104
- meta: {
1105
- request_id: response.meta?.request_id ?? "",
1106
- timestamp: response.meta?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
1107
- }
1108
- };
1109
- }
1110
- /**
1111
- * Maps a BFF asset path response to the file-picker port's shape.
1112
- */
1113
- function mapAssetPathCreateResponse(response) {
1114
- const assetPath = response.asset_path ?? {};
1115
- return {
1116
- asset: {
1117
- id: assetPath.id ?? 0,
1118
- canonical_path: assetPath.path ?? "",
1119
- name: assetPath.asset_code ?? ""
1120
- },
1121
- meta: {
1122
- request_id: response.meta?.request_id ?? "",
1123
- timestamp: response.meta?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
1124
- }
1125
- };
1126
- }
1127
- /**
1128
- * Creates a FilePickerApi adapter backed by the portal-tenant BFF's
1129
- * `/api/content/dam/*` endpoints, using cookie-based auth via the
1130
- * provided FetchClient.
1131
- *
1132
- * Unsplash search is not available through the BFF — callers that need
1133
- * Unsplash should use the legacy adapter or provide their own
1134
- * implementation.
1135
- *
1136
- * The `onProgress` callback in `createDamAsset` is not supported — the
1137
- * underlying `fetch` API does not expose upload progress events.
1138
- *
1139
- * URL proxy delegates to the same-origin `/api/proxy-url` endpoint
1140
- * (served by the hosting app, not the BFF) for CORS bypass, identical
1141
- * to the legacy adapter behaviour.
1142
- */
1143
- function createPortalTenantFilePickerApiAdapter(client) {
1144
- return {
1145
- createDamAsset: async (params) => {
1146
- const formData = new FormData();
1147
- formData.append("asset[file]", params.file);
1148
- formData.append("asset[name]", params.name);
1149
- if (params.description) formData.append("asset[description]", params.description);
1150
- if (params.tags && params.tags.length > 0) formData.append("asset[tags]", params.tags.join(","));
1151
- return mapCreateResponse(await client.requestWithFormData("/api/content/dam/assets", formData, { method: "POST" }));
1152
- },
1153
- queryDamAssets: async (params) => {
1154
- const response = await dam_query(client, params);
1155
- return damQueryResponseSchema.parse({
1156
- ...response,
1157
- meta: response.meta ? { next_cursor: response.meta.pagination?.next_cursor ?? void 0 } : void 0
1158
- });
1159
- },
1160
- deleteDamAsset: async (code) => {
1161
- return dam_assets_destroy(client, code);
1162
- },
1163
- discardDamAsset: async (code) => {
1164
- return dam_assets_discard(client, code);
1165
- },
1166
- createDamAssetPathForAssets: async (params) => {
1167
- return mapAssetPathCreateResponse(await dam_asset_paths_create(client, params.code, { asset_path: { path: params.asset_paths.join(",") } }));
1168
- },
1169
- searchUnsplash: async (_query, _page, _perPage) => {
1170
- throw new Error("Unsplash search is not available through the portal-tenant BFF. Configure an Unsplash access key and use the standard FilePickerApi adapter instead.");
1171
- },
1172
- proxyUrlFetch: (url) => proxyUrlFetch(url)
1173
- };
1174
- }
1175
- //#endregion
1176
- //#region src/screens/ShareablesScreen.tsx
1177
- /**
1178
- * Parse the current shareables sub-route from the full slug.
1179
- *
1180
- * System nav slugs are "share/products", "share/media", "share/playlists".
1181
- * Detail pages append an ID: "share/products/123", "share/media/456".
1182
- *
1183
- * "share/products" → screen="products", detailId=null
1184
- * "share/products/123" → screen="products", detailId="123"
1185
- * "share/media/456" → screen="media", detailId="456"
1186
- * "share/playlists" → screen="playlists", detailId=null
1187
- * "share/playlists/789" → screen="playlists", detailId="789"
1188
- * "share/files" → screen="files", detailId=null
1189
- * "share" → screen=null (default to products)
1190
- */
1191
- function parseShareablesRoute(currentSlug) {
1192
- const slugWithoutPrefix = currentSlug.replace(/^share\/?/, "");
1193
- if (!slugWithoutPrefix) return {
1194
- screen: null,
1195
- detailId: null,
1196
- action: null
1197
- };
1198
- const parts = slugWithoutPrefix.split("/");
1199
- return {
1200
- screen: parts[0] || null,
1201
- detailId: parts[1] || null,
1202
- action: parts[2] || null
1203
- };
1204
- }
1205
- function ShareablesScreen({ background, textColor, accentColor, padding, borderRadius, ...divProps }) {
1206
- const domainClient = require_use_account_clients.useSdkClient();
1207
- const portalProductsApi = require_use_portal_products_client.usePortalProductsClient();
1208
- const portalTenantClient = require_FluidProvider.usePortalTenantClient();
1209
- const { config } = require_FluidProvider.useFluidContext();
1210
- const { data: userData } = require_use_current_user.useCurrentUser();
1211
- const { currentSlug, navigate } = require_AppNavigationContext.useAppNavigation();
1212
- const { isCustomer } = useUserType();
1213
- const fetchProducts = (0, react.useCallback)(async (search, cursor, limit) => {
1214
- if (search) return portalProductsApi.searchProducts(search, {
1215
- cursor,
1216
- limit
1217
- });
1218
- return portalProductsApi.listProducts({
1219
- cursor,
1220
- limit
1221
- });
1222
- }, [portalProductsApi]);
1223
- const fetchProduct = (0, react.useCallback)(async (id) => portalProductsApi.getProduct(id), [portalProductsApi]);
1224
- const { screen, detailId, action } = parseShareablesRoute(currentSlug);
1225
- const handleNavigate = (0, react.useCallback)((subScreen, id) => {
1226
- navigate(id ? `share/${subScreen}/${id}` : `share/${subScreen}`);
1227
- }, [navigate]);
1228
- const handleBack = (0, react.useCallback)(() => {
1229
- if (detailId && screen) navigate(`share/${screen}`);
1230
- else navigate("share/products");
1231
- }, [
1232
- navigate,
1233
- detailId,
1234
- screen
1235
- ]);
1236
- const coreConfig = (0, react.useMemo)(() => ({
1237
- client: domainClient,
1238
- user: userData ? { id: userData.id } : null,
1239
- repContext: true
1240
- }), [domainClient, userData]);
1241
- const playlistsAdapter = (0, react.useMemo)(() => createPortalTenantPlaylistsAdapter(portalTenantClient), [portalTenantClient]);
1242
- const shareablesApi = (0, react.useMemo)(() => ({
1243
- media: createPortalTenantMediaShareablesAdapter(portalTenantClient),
1244
- playlists: createPortalTenantPlaylistsShareablesAdapter(portalTenantClient),
1245
- fileResources: createPortalTenantFilesShareablesAdapter(portalTenantClient),
1246
- share: createPortalTenantSharesShareablesAdapter(portalTenantClient),
1247
- productMedia: { getProductMedia: async (productId) => {
1248
- return { media: ((await portalProductsApi.getProductMedia(productId)).media ?? []).map((item) => {
1249
- const isVideo = item.media_type === "video";
1250
- const isPdf = item.media_type === "pdf" || item.media_type === "document";
1251
- return {
1252
- id: item.id ?? 0,
1253
- slug: null,
1254
- title: item.title ?? "",
1255
- kind: isVideo ? "video" : isPdf ? "pdf" : "image",
1256
- media_type: item.media_type ?? "image",
1257
- media_format: item.media_type ?? "image",
1258
- image_url: !isVideo && !isPdf ? item.url ?? null : null,
1259
- video_url: isVideo ? item.url ?? null : null,
1260
- pdf_url: isPdf ? item.url ?? null : null,
1261
- powerpoint_url: null,
1262
- duration: 0,
1263
- description: null,
1264
- subtitles: {},
1265
- comments_count: 0
1266
- };
1267
- }) };
1268
- } }
1269
- }), [portalTenantClient, portalProductsApi]);
1270
- const filePickerApi = (0, react.useMemo)(() => {
1271
- const baseUrl = config.baseUrl.replace(/\/+$/, "").replace(/\/api$/, "");
1272
- const csrfToken = typeof document !== "undefined" ? document.querySelector("meta[name=\"csrf-token\"]")?.getAttribute("content") : null;
1273
- return createPortalTenantFilePickerApiAdapter(require_FluidProvider.createFetchClient({
1274
- baseUrl,
1275
- getAuthToken: config.getAuthToken,
1276
- onAuthError: config.onAuthError,
1277
- credentials: "include",
1278
- defaultHeaders: {
1279
- ...config.defaultHeaders,
1280
- ...csrfToken ? { "X-CSRF-Token": csrfToken } : {}
1281
- }
1282
- }));
1283
- }, [
1284
- config.baseUrl,
1285
- config.getAuthToken,
1286
- config.onAuthError,
1287
- config.defaultHeaders
1288
- ]);
1289
- const uiConfig = (0, react.useMemo)(() => ({
1290
- user: userData ? {
1291
- id: userData.id,
1292
- company: userData.company ? { logo_url: userData.company.logo_url } : null
1293
- } : void 0,
1294
- affiliateId: userData?.affiliate_id ?? null,
1295
- basePath: "",
1296
- navigate: (path) => {
1297
- const cleanPath = path.replace(/^\//, "");
1298
- navigate(cleanPath.startsWith("share/") ? cleanPath : `share/${cleanPath}`);
1299
- },
1300
- showToast: (opts) => {
1301
- console.warn(`[Shareables] ${opts.type}: ${opts.title}`);
1302
- },
1303
- filePickerApi,
1304
- onToggleFavorite: async (params) => {
1305
- const affiliateId = userData?.affiliate_id;
1306
- if (!affiliateId) throw new Error("No affiliate ID");
1307
- return domainClient.post(`/user_companies/${affiliateId}/favorites/toggle.json`, {
1308
- favoriteable_id: params.favoriteableId,
1309
- favoriteable_type: params.favoriteableType
1310
- });
1311
- },
1312
- onDeletePlaylist: isCustomer ? void 0 : async (playlistId) => {
1313
- await playlistsAdapter.deletePlaylist(playlistId);
1314
- },
1315
- readOnly: isCustomer
1316
- }), [
1317
- userData,
1318
- navigate,
1319
- filePickerApi,
1320
- domainClient,
1321
- isCustomer,
1322
- playlistsAdapter
1323
- ]);
1324
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1325
- ...divProps,
1326
- className: `h-full ${divProps.className ?? ""}`,
1327
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ShareablesCoreProvider, {
1328
- config: coreConfig,
1329
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ShareablesApiProvider, {
1330
- api: shareablesApi,
1331
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ShareablesUIProvider, {
1332
- config: uiConfig,
1333
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.ShareablesApp, {
1334
- screen,
1335
- detailId,
1336
- action,
1337
- companyLogoUrl: userData?.company?.logo_url,
1338
- countryCode: userData?.country?.iso,
1339
- fetchProducts,
1340
- fetchProduct,
1341
- onNavigate: handleNavigate,
1342
- onBack: handleBack
1343
- })
1344
- })
1345
- })
1346
- })
1347
- });
1348
- }
1349
- const shareablesScreenPropertySchema = {
1350
- widgetType: "ShareablesScreen",
1351
- displayName: "Shareables Screen",
1352
- tabsConfig: [{
1353
- id: "styling",
1354
- label: "Styling"
1355
- }],
1356
- fields: []
1357
- };
1358
- //#endregion
1359
- Object.defineProperty(exports, "ShareablesScreen", {
1360
- enumerable: true,
1361
- get: function() {
1362
- return ShareablesScreen;
1363
- }
1364
- });
1365
- Object.defineProperty(exports, "shareablesScreenPropertySchema", {
1366
- enumerable: true,
1367
- get: function() {
1368
- return shareablesScreenPropertySchema;
1369
- }
1370
- });
1371
- Object.defineProperty(exports, "useUserType", {
1372
- enumerable: true,
1373
- get: function() {
1374
- return useUserType;
1375
- }
1376
- });
1377
-
1378
- //# sourceMappingURL=ShareablesScreen-DDutXKpW.cjs.map