@fluid-app/portal-sdk 0.1.238 → 0.1.240
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/{CalendarWidget-BaGML5Xh.mjs → CalendarWidget-C03VcDLQ.mjs} +2 -2
- package/dist/{CalendarWidget-BaGML5Xh.mjs.map → CalendarWidget-C03VcDLQ.mjs.map} +1 -1
- package/dist/{CalendarWidget-oGK122s9.cjs → CalendarWidget-C4Dv_TUk.cjs} +2 -2
- package/dist/{CalendarWidget-oGK122s9.cjs.map → CalendarWidget-C4Dv_TUk.cjs.map} +1 -1
- package/dist/{CardWidget-CqYjGkq-.mjs → CardWidget-2wcjCf2M.mjs} +2 -2
- package/dist/{CardWidget-CqYjGkq-.mjs.map → CardWidget-2wcjCf2M.mjs.map} +1 -1
- package/dist/{CardWidget-DjhK0yr-.cjs → CardWidget-BQl-8Xrt.cjs} +3 -3
- package/dist/{CardWidget-CSLSlKM6.cjs → CardWidget-D-KEikO_.cjs} +2 -2
- package/dist/{CardWidget-CSLSlKM6.cjs.map → CardWidget-D-KEikO_.cjs.map} +1 -1
- package/dist/{CarouselWidget-CdQhlRrW.mjs → CarouselWidget-Cn5P4FVN.mjs} +93 -84
- package/dist/CarouselWidget-Cn5P4FVN.mjs.map +1 -0
- package/dist/{CarouselWidget-DlxYQB5j.cjs → CarouselWidget-Cu1b3ERq.cjs} +93 -84
- package/dist/CarouselWidget-Cu1b3ERq.cjs.map +1 -0
- package/dist/{CatchUpWidget-BQjtjcGR.mjs → CatchUpWidget-B9CI7lq0.mjs} +2 -2
- package/dist/{CatchUpWidget-BQjtjcGR.mjs.map → CatchUpWidget-B9CI7lq0.mjs.map} +1 -1
- package/dist/{CatchUpWidget-B1Muaurg.cjs → CatchUpWidget-BzgybvuC.cjs} +2 -2
- package/dist/{CatchUpWidget-B1Muaurg.cjs.map → CatchUpWidget-BzgybvuC.cjs.map} +1 -1
- package/dist/ContainerWidget-CDbB8c0E.cjs +8 -0
- package/dist/{ContainerWidget-DYThUtiZ.mjs → ContainerWidget-DNenbORS.mjs} +2 -2
- package/dist/{ContainerWidget-DYThUtiZ.mjs.map → ContainerWidget-DNenbORS.mjs.map} +1 -1
- package/dist/{ContainerWidget-Cjwrq2MS.cjs → ContainerWidget-DbAhQKbY.cjs} +2 -2
- package/dist/{ContainerWidget-Cjwrq2MS.cjs.map → ContainerWidget-DbAhQKbY.cjs.map} +1 -1
- package/dist/{FluidProvider-B3DjYoUW.mjs → FluidProvider-BbXSELEP.mjs} +67 -84
- package/dist/FluidProvider-BbXSELEP.mjs.map +1 -0
- package/dist/{FluidProvider-DcpUKHrn.cjs → FluidProvider-DRXysbXj.cjs} +67 -84
- package/dist/FluidProvider-DRXysbXj.cjs.map +1 -0
- package/dist/{ImageWidget-xcE0sFf-.cjs → ImageWidget-CbQVxMe3.cjs} +2 -2
- package/dist/{ImageWidget-xcE0sFf-.cjs.map → ImageWidget-CbQVxMe3.cjs.map} +1 -1
- package/dist/{ImageWidget-CFTpbu8X.mjs → ImageWidget-vNWT_O1E.mjs} +2 -2
- package/dist/{ImageWidget-CFTpbu8X.mjs.map → ImageWidget-vNWT_O1E.mjs.map} +1 -1
- package/dist/{LayoutWidget-CK-SvFQL.cjs → LayoutWidget-Bt2I2XMy.cjs} +2 -2
- package/dist/{LayoutWidget-CK-SvFQL.cjs.map → LayoutWidget-Bt2I2XMy.cjs.map} +1 -1
- package/dist/{LayoutWidget-DuueFNAS.cjs → LayoutWidget-DKqZgCMu.cjs} +3 -3
- package/dist/{LayoutWidget-Cx5ZyXSU.mjs → LayoutWidget-UI5fbsx4.mjs} +2 -2
- package/dist/{LayoutWidget-Cx5ZyXSU.mjs.map → LayoutWidget-UI5fbsx4.mjs.map} +1 -1
- package/dist/{LinkWidget-B14FTQP7.cjs → LinkWidget-BoR7nVbH.cjs} +2 -2
- package/dist/{LinkWidget-B14FTQP7.cjs.map → LinkWidget-BoR7nVbH.cjs.map} +1 -1
- package/dist/{LinkWidget-CQHmKO-O.mjs → LinkWidget-CO-Cxf7Z.mjs} +2 -2
- package/dist/{LinkWidget-CQHmKO-O.mjs.map → LinkWidget-CO-Cxf7Z.mjs.map} +1 -1
- package/dist/{LinkWidget-CPmE8gpd.cjs → LinkWidget-M9YzMJT8.cjs} +2 -2
- package/dist/{ListWidget-YvCp7XDq.cjs → ListWidget-CuSjvwEw.cjs} +3 -3
- package/dist/{ListWidget-wBDnXWxa.cjs → ListWidget-CzljZ1LA.cjs} +3 -3
- package/dist/{ListWidget-wBDnXWxa.cjs.map → ListWidget-CzljZ1LA.cjs.map} +1 -1
- package/dist/{ListWidget-BnyD2Hpc.mjs → ListWidget-f88QhcGI.mjs} +3 -3
- package/dist/{ListWidget-BnyD2Hpc.mjs.map → ListWidget-f88QhcGI.mjs.map} +1 -1
- package/dist/{MediaRenderer-CfgWd0cC.cjs → MediaRenderer-CvN8Ku0i.cjs} +4 -4
- package/dist/MediaRenderer-CvN8Ku0i.cjs.map +1 -0
- package/dist/{MediaRenderer-CqUpv3St.mjs → MediaRenderer-DMdb_5xw.mjs} +4 -4
- package/dist/MediaRenderer-DMdb_5xw.mjs.map +1 -0
- package/dist/{MessagingScreen-CPBUg-32.cjs → MessagingScreen-DZvq5j13.cjs} +22 -22
- package/dist/{MessagingScreen-BBqwXPZB.mjs → MessagingScreen-DlRwCPg8.mjs} +2 -2
- package/dist/{MessagingScreen-BBqwXPZB.mjs.map → MessagingScreen-DlRwCPg8.mjs.map} +1 -1
- package/dist/{MessagingScreen-BzWV22JZ.cjs → MessagingScreen-_-sdlwh0.cjs} +2 -2
- package/dist/{MessagingScreen-BzWV22JZ.cjs.map → MessagingScreen-_-sdlwh0.cjs.map} +1 -1
- package/dist/{MySiteWidget-COj7yYQF.mjs → MySiteWidget-CQNASVaF.mjs} +2 -2
- package/dist/{MySiteWidget-COj7yYQF.mjs.map → MySiteWidget-CQNASVaF.mjs.map} +1 -1
- package/dist/{MySiteWidget-DRH4q_YV.cjs → MySiteWidget-CYiH2lmX.cjs} +2 -2
- package/dist/{MySiteWidget-DRH4q_YV.cjs.map → MySiteWidget-CYiH2lmX.cjs.map} +1 -1
- package/dist/{NestedWidget-C_2XwnW0.cjs → NestedWidget-CEoAO2sp.cjs} +3 -3
- package/dist/{NestedWidget-C_2XwnW0.cjs.map → NestedWidget-CEoAO2sp.cjs.map} +1 -1
- package/dist/{NestedWidget-CXIvsJdD.cjs → NestedWidget-CMCZjV6t.cjs} +3 -3
- package/dist/{NestedWidget-WJoWOFda.mjs → NestedWidget-RuyrOrFn.mjs} +3 -3
- package/dist/{NestedWidget-WJoWOFda.mjs.map → NestedWidget-RuyrOrFn.mjs.map} +1 -1
- package/dist/{PointsWidget-CLUWrFjZ.cjs → PointsWidget-C5cXxKlM.cjs} +2 -2
- package/dist/{PointsWidget-CLUWrFjZ.cjs.map → PointsWidget-C5cXxKlM.cjs.map} +1 -1
- package/dist/{PointsWidget-DoUljaNY.mjs → PointsWidget-icodgubL.mjs} +2 -2
- package/dist/{PointsWidget-DoUljaNY.mjs.map → PointsWidget-icodgubL.mjs.map} +1 -1
- package/dist/{ProfileScreen-CwQr_Km7.mjs → ProfileScreen-91WrZUpz.mjs} +2 -2
- package/dist/{ProfileScreen-CwQr_Km7.mjs.map → ProfileScreen-91WrZUpz.mjs.map} +1 -1
- package/dist/{ProfileScreen-MCfnv8eT.cjs → ProfileScreen-BalGphXn.cjs} +22 -22
- package/dist/{ProfileScreen-C0nmvuW1.cjs → ProfileScreen-SWcwqDK4.cjs} +2 -2
- package/dist/{ProfileScreen-C0nmvuW1.cjs.map → ProfileScreen-SWcwqDK4.cjs.map} +1 -1
- package/dist/{RecentActivityWidget-zQxtUECm.mjs → RecentActivityWidget-D1AlZgfV.mjs} +2 -2
- package/dist/{RecentActivityWidget-zQxtUECm.mjs.map → RecentActivityWidget-D1AlZgfV.mjs.map} +1 -1
- package/dist/{RecentActivityWidget-C6RwlUUw.cjs → RecentActivityWidget-DNyhUZNs.cjs} +2 -2
- package/dist/{RecentActivityWidget-C6RwlUUw.cjs.map → RecentActivityWidget-DNyhUZNs.cjs.map} +1 -1
- package/dist/{ScreenRenderer-Bk23YOtN.mjs → ScreenRenderer-Cl2aAJ7D.mjs} +2 -2
- package/dist/{ScreenRenderer-Bk23YOtN.mjs.map → ScreenRenderer-Cl2aAJ7D.mjs.map} +1 -1
- package/dist/{ScreenRenderer-aYfgv6mR.cjs → ScreenRenderer-xH01YkEQ.cjs} +2 -2
- package/dist/{ScreenRenderer-aYfgv6mR.cjs.map → ScreenRenderer-xH01YkEQ.cjs.map} +1 -1
- package/dist/{ShopScreen-CiGozvW4.cjs → ShopScreen-B6Bo1VOu.cjs} +6 -2
- package/dist/ShopScreen-B6Bo1VOu.cjs.map +1 -0
- package/dist/{ShopScreen-Brw7gNMu.cjs → ShopScreen-Ce29yINo.cjs} +22 -22
- package/dist/{ShopScreen-D39WpS6j.mjs → ShopScreen-DbMmVqSK.mjs} +6 -2
- package/dist/ShopScreen-DbMmVqSK.mjs.map +1 -0
- package/dist/{TableWidget-D4jQN-to.cjs → TableWidget-BIn1oRiJ.cjs} +4 -4
- package/dist/TableWidget-BIn1oRiJ.cjs.map +1 -0
- package/dist/{TableWidget-DWAYgQcl.cjs → TableWidget-C--8TSX7.cjs} +3 -3
- package/dist/{TableWidget-B0CRdzNf.mjs → TableWidget-dfUvhH0S.mjs} +4 -4
- package/dist/TableWidget-dfUvhH0S.mjs.map +1 -0
- package/dist/{ToDoWidget-VSaNmtWH.mjs → ToDoWidget-BciI_D70.mjs} +2 -2
- package/dist/{ToDoWidget-VSaNmtWH.mjs.map → ToDoWidget-BciI_D70.mjs.map} +1 -1
- package/dist/{ToDoWidget-BbeXt99H.cjs → ToDoWidget-OxT9z59F.cjs} +2 -2
- package/dist/{ToDoWidget-BbeXt99H.cjs.map → ToDoWidget-OxT9z59F.cjs.map} +1 -1
- package/dist/{ToDoWidget-YHmoDbVU.cjs → ToDoWidget-mSGQgnu3.cjs} +2 -2
- package/dist/{VideoWidget-Bc6ZAAaA.cjs → VideoWidget-CDcV0J5W.cjs} +2 -2
- package/dist/{VideoWidget-Bc6ZAAaA.cjs.map → VideoWidget-CDcV0J5W.cjs.map} +1 -1
- package/dist/{VideoWidget-DcWm239R.mjs → VideoWidget-Dj9wue7j.mjs} +2 -2
- package/dist/{VideoWidget-DcWm239R.mjs.map → VideoWidget-Dj9wue7j.mjs.map} +1 -1
- package/dist/WidgetInteractionContext-B1mELhQ_.mjs +28 -0
- package/dist/{WidgetInteractionContext-D0TJv70C.mjs.map → WidgetInteractionContext-B1mELhQ_.mjs.map} +1 -1
- package/dist/WidgetInteractionContext-DvPmzGqB.cjs +41 -0
- package/dist/{WidgetInteractionContext-Bs3LkFFH.cjs.map → WidgetInteractionContext-DvPmzGqB.cjs.map} +1 -1
- package/dist/index.cjs +81 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +81 -52
- package/dist/index.mjs.map +1 -1
- package/dist/{registry-context-BDH0vNHR.mjs → registry-context-CTHUCfEc.mjs} +17 -24
- package/dist/registry-context-CTHUCfEc.mjs.map +1 -0
- package/dist/{registry-context-C7-RLxVt.cjs → registry-context-CcZYS15Q.cjs} +17 -24
- package/dist/registry-context-CcZYS15Q.cjs.map +1 -0
- package/package.json +17 -17
- package/dist/CarouselWidget-CdQhlRrW.mjs.map +0 -1
- package/dist/CarouselWidget-DlxYQB5j.cjs.map +0 -1
- package/dist/ContainerWidget-NFBqSeRV.cjs +0 -8
- package/dist/FluidProvider-B3DjYoUW.mjs.map +0 -1
- package/dist/FluidProvider-DcpUKHrn.cjs.map +0 -1
- package/dist/MediaRenderer-CfgWd0cC.cjs.map +0 -1
- package/dist/MediaRenderer-CqUpv3St.mjs.map +0 -1
- package/dist/ShopScreen-CiGozvW4.cjs.map +0 -1
- package/dist/ShopScreen-D39WpS6j.mjs.map +0 -1
- package/dist/TableWidget-B0CRdzNf.mjs.map +0 -1
- package/dist/TableWidget-D4jQN-to.cjs.map +0 -1
- package/dist/WidgetInteractionContext-Bs3LkFFH.cjs +0 -18
- package/dist/WidgetInteractionContext-D0TJv70C.mjs +0 -11
- package/dist/registry-context-BDH0vNHR.mjs.map +0 -1
- package/dist/registry-context-C7-RLxVt.cjs.map +0 -1
|
@@ -26,24 +26,16 @@ async function fetchViaAdapter(source, context) {
|
|
|
26
26
|
languageIso: vars?.language_iso,
|
|
27
27
|
signal: context.signal
|
|
28
28
|
});
|
|
29
|
-
case "customer-orders": {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const customerId = vars?.customer_id;
|
|
40
|
-
if (!customerId) return void 0;
|
|
41
|
-
return api.fetchSubscriptions(customerId, {
|
|
42
|
-
limit: vars?.limit ? Number(vars.limit) : void 0,
|
|
43
|
-
status: vars?.status,
|
|
44
|
-
signal: context.signal
|
|
45
|
-
});
|
|
46
|
-
}
|
|
29
|
+
case "customer-orders": return api.fetchOrders(vars?.customer_id ?? "", {
|
|
30
|
+
limit: vars?.limit ? Number(vars.limit) : void 0,
|
|
31
|
+
status: vars?.status,
|
|
32
|
+
signal: context.signal
|
|
33
|
+
});
|
|
34
|
+
case "customer-subscriptions": return api.fetchSubscriptions(vars?.customer_id ?? "", {
|
|
35
|
+
limit: vars?.limit ? Number(vars.limit) : void 0,
|
|
36
|
+
status: vars?.status,
|
|
37
|
+
signal: context.signal
|
|
38
|
+
});
|
|
47
39
|
default: return;
|
|
48
40
|
}
|
|
49
41
|
}
|
|
@@ -115,7 +107,7 @@ async function apiFetcher(source, context) {
|
|
|
115
107
|
...source.variables
|
|
116
108
|
};
|
|
117
109
|
const url = resolveEndpointUrl(endpoint, context.baseUrl, mergedVariables);
|
|
118
|
-
if (/\{\w+\}/.test(url)) return;
|
|
110
|
+
if (/\{\w+\}/.test(url)) return null;
|
|
119
111
|
const fetchOptions = {
|
|
120
112
|
method,
|
|
121
113
|
headers: {
|
|
@@ -314,16 +306,17 @@ const toCarouselSlidesFromShareables = (data, source) => {
|
|
|
314
306
|
const d = item;
|
|
315
307
|
const widgetConfig = extractCustomWidgetConfig(d, source);
|
|
316
308
|
const imageUrl = extractImageUrl(d);
|
|
317
|
-
const isVideo = d.kind === "video" || d.videoUrl || d.video_url;
|
|
309
|
+
const isVideo = d.kind === "video" || d.content_format === "video" || d.videoUrl || d.video_url;
|
|
310
|
+
const videoSrc = (d.videoUrl ?? d.video_url) || (isVideo ? d.url || "" : "");
|
|
318
311
|
const title = d.title ?? d.name ?? "";
|
|
319
312
|
const content = isVideo ? {
|
|
320
313
|
type: "VideoWidget",
|
|
321
314
|
props: {
|
|
322
|
-
src:
|
|
315
|
+
src: videoSrc,
|
|
323
316
|
poster: imageUrl,
|
|
324
317
|
caption: title,
|
|
325
|
-
autoplay:
|
|
326
|
-
loop:
|
|
318
|
+
autoplay: false,
|
|
319
|
+
loop: false,
|
|
327
320
|
muted: true,
|
|
328
321
|
controls: true
|
|
329
322
|
}
|
|
@@ -524,4 +517,4 @@ function useDataSourceRegistryConfig() {
|
|
|
524
517
|
//#endregion
|
|
525
518
|
export { useDataSourceRegistryConfig as n, DataSourceRegistryProvider as t };
|
|
526
519
|
|
|
527
|
-
//# sourceMappingURL=registry-context-
|
|
520
|
+
//# sourceMappingURL=registry-context-CTHUCfEc.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-context-CTHUCfEc.mjs","names":[],"sources":["../../core/src/data-sources/fetchers/api.ts","../../core/src/data-sources/fetchers/custom.ts","../../core/src/data-sources/fetchers/static.ts","../../core/src/data-sources/transformers.ts","../../core/src/data-sources/registry.ts","../../react/src/data-sources/context.tsx","../../react/src/data-sources/registry-context.tsx"],"sourcesContent":["import type { DataSourceShareableType } from \"../../data-source-api-types\";\nimport type { ApiDataSource, DataSourceContext } from \"../types\";\n\n/**\n * Delegates a preset API source to the injected DataSourceApi adapter.\n * Returns undefined for unknown presets (caller falls through to raw fetch).\n */\nasync function fetchViaAdapter(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n const api = context.api!;\n const vars = { ...context.variables, ...source.variables };\n\n switch (source.presetId) {\n case \"rep-most-shared\": {\n return api.fetchMostShared(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"rep-most-viewed\": {\n return api.fetchMostViewed(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"customer-orders\": {\n // BFF scopes by session — customer_id is informational/optional.\n return api.fetchOrders(vars?.customer_id ?? \"\", {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n case \"customer-subscriptions\": {\n // BFF scopes by session — customer_id is informational/optional.\n return api.fetchSubscriptions(vars?.customer_id ?? \"\", {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Extracts a value from an object using dot notation path\n * e.g., getByPath({ data: { items: [1,2,3] } }, 'data.items') => [1,2,3]\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n return path.split(\".\").reduce((current, key) => {\n if (current && typeof current === \"object\" && key in current) {\n return (current as Record<string, unknown>)[key];\n }\n return undefined;\n }, obj);\n}\n\n/**\n * Replaces {variable} placeholders in an endpoint path with values from the\n * variables map. E.g., \"/reps/{rep_id}/most_shared\" with { rep_id: \"42\" }\n * becomes \"/reps/42/most_shared\".\n */\nfunction interpolateVariables(\n endpoint: string,\n variables?: Record<string, string>,\n): string {\n if (!variables) return endpoint;\n const resolved = endpoint.replace(\n /\\{(\\w+)\\}/g,\n (match, key: string) => variables[key] ?? match,\n );\n const unresolved = resolved.match(/\\{(\\w+)\\}/g);\n if (unresolved) {\n console.warn(\n `[DataSource] Unresolved variable placeholders in endpoint: ${unresolved.join(\", \")}. ` +\n `Endpoint: \"${endpoint}\". Available variables: ${Object.keys(variables).join(\", \") || \"(none)\"}`,\n );\n }\n return stripAllQueryParams(resolved);\n}\n\n/**\n * Removes query parameters whose value is \"all\" from a URL.\n *\n * Convention: \"all\" is a reserved no-op value for data source preset\n * config fields. Preset authors should use \"all\" as the default option\n * for \"show everything\" filters. This function strips those params so\n * APIs that don't recognise \"all\" fall back to their default (return\n * everything) behaviour. Do not use \"all\" as a meaningful filter value\n * in preset endpoints.\n */\nfunction stripAllQueryParams(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return url;\n\n const base = url.slice(0, qIndex);\n const query = url.slice(qIndex + 1);\n const kept = query\n .split(\"&\")\n .filter((pair) => {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) return true;\n return pair.slice(eqIndex + 1) !== \"all\";\n })\n .join(\"&\");\n\n return kept ? `${base}?${kept}` : base;\n}\n\n/**\n * Resolves the full URL for an endpoint.\n * - Substitutes {variable} placeholders from context variables\n * - Absolute URLs (starting with http:// or https://) are used as-is\n * - Relative paths are prefixed with the context's baseUrl\n */\nfunction resolveEndpointUrl(\n endpoint: string,\n baseUrl?: string,\n variables?: Record<string, string>,\n): string {\n const resolved = interpolateVariables(endpoint, variables);\n\n // If endpoint is already absolute, use it directly\n if (resolved.startsWith(\"http://\") || resolved.startsWith(\"https://\")) {\n return resolved;\n }\n\n // If we have a baseUrl, prepend it to the relative endpoint\n if (baseUrl) {\n // Ensure proper joining (no double slashes)\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const path = resolved.startsWith(\"/\") ? resolved : `/${resolved}`;\n return `${base}${path}`;\n }\n\n // No baseUrl provided, return endpoint as-is (will likely fail for relative paths)\n return resolved;\n}\n\n/**\n * Default API fetcher implementation\n */\nexport async function apiFetcher(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n // Delegate to adapter if available for preset-backed sources\n if (context.api && source.presetId) {\n const result = await fetchViaAdapter(source, context);\n if (result !== undefined) return result;\n // Fall through to legacy fetch for unknown presets\n }\n\n const { endpoint, method = \"GET\", headers = {}, body, resultPath } = source;\n\n // Merge context variables with per-source variables (source overrides context)\n const mergedVariables = { ...context.variables, ...source.variables };\n\n // Resolve the full URL, substituting variables and using baseUrl for relative endpoints\n const url = resolveEndpointUrl(endpoint, context.baseUrl, mergedVariables);\n\n // Skip the fetch if the URL still contains unresolved {variable} placeholders\n // (e.g. rep_id not yet loaded). Return null — TanStack Query treats undefined\n // as a missing return and throws, so use null for the no-op case.\n if (/\\{\\w+\\}/.test(url)) {\n return null;\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n \"content-type\": \"application/json\",\n ...context.getApiHeaders?.(),\n ...headers,\n },\n signal: context.signal,\n };\n\n if (body && (method === \"POST\" || method === \"PUT\")) {\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n throw new Error(\n `API request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n // Extract data at resultPath if specified\n if (resultPath) {\n return getByPath(data, resultPath);\n }\n\n return data;\n}\n","import type { ResourceType } from \"../../data-source-api-types\";\nimport type {\n CustomDataSource,\n DataSourceContext,\n SelectedItem,\n} from \"../types\";\n\nconst SHAREABLE_TO_RESOURCE_TYPE: Record<string, ResourceType> = {\n Medium: \"Medium\",\n Page: \"Page\",\n Library: \"Library\",\n Product: \"Product\",\n EnrollmentPack: \"EnrollmentPack\",\n};\n\nasync function fetchItemsViaAdapter(\n items: SelectedItem[],\n context: DataSourceContext,\n): Promise<unknown[]> {\n const api = context.api!;\n\n // Use Promise.allSettled so individual failures don't blow up the whole\n // batch, but *do* surface the aggregate failure for visibility — a rep who\n // hand-picked 5 items shouldn't silently see 3 without knowing why.\n const settled = await Promise.allSettled(\n items.map(async (item) => {\n const resourceType = SHAREABLE_TO_RESOURCE_TYPE[item.shareableType];\n if (!resourceType) {\n throw new Error(\n `Unknown shareable type: ${item.shareableType} for item #${item.id}`,\n );\n }\n return api.fetchResource(resourceType, item.id, context.signal);\n }),\n );\n\n const successful: unknown[] = [];\n const failures: { item: SelectedItem; reason: unknown }[] = [];\n\n settled.forEach((result, index) => {\n const item = items[index];\n if (!item) return;\n if (result.status === \"fulfilled\") {\n successful.push(result.value);\n } else {\n failures.push({ item, reason: result.reason });\n }\n });\n\n if (failures.length > 0) {\n // Log once with aggregate context so Sentry/logs show the full picture\n // rather than N scattered warnings that are hard to correlate.\n console.error(\n `[CustomFetcher] ${failures.length}/${items.length} items failed to fetch:`,\n failures.map((f) => ({\n shareableType: f.item.shareableType,\n id: f.item.id,\n error: f.reason instanceof Error ? f.reason.message : f.reason,\n })),\n );\n }\n\n if (successful.length === 0 && items.length > 0) {\n const firstErr = failures[0]?.reason;\n throw new Error(\n `Failed to fetch all ${items.length} item(s)${firstErr instanceof Error ? `: ${firstErr.message}` : \"\"}`,\n );\n }\n\n return successful;\n}\n\n/**\n * Custom fetcher that fetches selected items via the injected DataSourceApi adapter.\n *\n * Fetches all items in parallel for performance.\n * Returns an array of successfully fetched items, preserving order.\n * Logs warnings for failed fetches but doesn't throw unless all items fail.\n */\nexport async function customFetcher(\n source: CustomDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { selectedItems } = source;\n if (!selectedItems || selectedItems.length === 0) {\n return [];\n }\n\n if (!context.api) {\n throw new Error(\n \"customFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n return fetchItemsViaAdapter(selectedItems, context);\n}\n","import type {\n StaticDataSource,\n DataSourceContext,\n StaticSourceType,\n} from \"../types\";\n\n/**\n * Static data source fetcher.\n *\n * Delegates to the injected DataSourceApi adapter to fetch products filtered\n * by collection, category, or tag.\n */\nexport async function staticFetcher(\n source: StaticDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { staticType, selectedId } = source;\n\n if (!context.api) {\n throw new Error(\n \"staticFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n // Validate filterId once at the shared delegation point so BFF and legacy\n // adapters behave identically. Tags are a known-unsupported type the\n // adapters throw for separately.\n if (staticType !== \"tags\" && Number.isNaN(Number(selectedId))) {\n throw new Error(\n `staticFetcher: selectedId must be numeric, got \"${selectedId}\"`,\n );\n }\n\n return context.api.fetchProductsByFilter(\n staticType,\n selectedId,\n context.signal,\n );\n}\n\n/**\n * Endpoints for listing static source items (collections, categories, tags).\n * Used by the portal builder UI for populating selection dropdowns.\n */\nexport const LIST_ENDPOINTS: Record<\n StaticSourceType,\n { endpoint: string; resultKey: string }\n> = {\n collections: {\n endpoint: \"/company/v1/collections\",\n resultKey: \"collections\",\n },\n categories: { endpoint: \"/company/v1/categories\", resultKey: \"categories\" },\n tags: { endpoint: \"/company/v1/tags\", resultKey: \"tags\" },\n};\n","/**\n * Widget Transformers\n *\n * Transform functions that map API response data to widget-specific prop shapes.\n * Each widget has one transformer that handles all data structure variants:\n * - Standard: Direct field name match\n * - Legacy: Different field names that need mapping\n * - Minimal: Bare minimum fields that need defaults\n *\n * Usage:\n * 1. Transformers are registered in the DataSourceRegistry\n * 2. Reference by name in ApiDataSource.transform\n * 3. Applied after resultPath extraction, before targetProps assignment\n */\n\nimport type { DataTransformer, DataSource } from \"./types\";\n\n/**\n * Helper to extract image URL from various API response structures.\n * Handles:\n * - Flat fields (Medium, Page, Product): image_url, imageUrl, thumbnail_url, src\n * - Nested images array (EnrollmentPack): images[0].image_url\n * - Nested library_items (Library): library_items[0].relateable.image_url\n */\nfunction extractImageUrl(d: Record<string, unknown>): string {\n // Try flat fields first (Medium, Page, Product)\n if (d.image_url) return d.image_url as string;\n if (d.imageUrl) return d.imageUrl as string;\n if (d.thumbnail_url) return d.thumbnail_url as string;\n if (d.src) return d.src as string;\n\n // Try nested images array (EnrollmentPack)\n const images = d.images as Array<Record<string, unknown>> | undefined;\n if (images && images.length > 0) {\n const firstImage = images[0];\n if (firstImage?.image_url) return firstImage.image_url as string;\n if (firstImage?.url) return firstImage.url as string;\n }\n\n // Try nested library_items (Library/Playlist)\n const libraryItems = d.library_items as\n | Array<Record<string, unknown>>\n | undefined;\n if (libraryItems && libraryItems.length > 0) {\n const firstItem = libraryItems[0];\n const relateable = firstItem?.relateable as\n | Record<string, unknown>\n | undefined;\n if (relateable?.image_url) return relateable.image_url as string;\n if (relateable?.imageUrl) return relateable.imageUrl as string;\n if (relateable?.thumbnail_url) return relateable.thumbnail_url as string;\n }\n\n return \"\";\n}\n\n/**\n * Helper to extract description from various API response structures.\n * Handles different field names across endpoints.\n */\nfunction extractDescription(d: Record<string, unknown>): string {\n // Try various description field names\n const desc =\n d.description ?? d.stripped ?? d.stripped_description ?? d.body ?? \"\";\n\n // Handle nested description object (some APIs return { body: \"...\" })\n if (typeof desc === \"object\" && desc !== null && \"body\" in desc) {\n return ((desc as Record<string, unknown>).body as string) ?? \"\";\n }\n\n return desc as string;\n}\n\n/**\n * Helper to extract custom widget config from a selected item.\n */\nfunction extractCustomWidgetConfig(\n d: Record<string, unknown>,\n source: DataSource | undefined,\n): Record<string, unknown> {\n if (source === undefined || source.type !== \"custom\") return {};\n\n const selectedItem = source.selectedItems.find(\n (s) => String(s.id) === String(d.id),\n );\n return selectedItem?.widgetConfig ?? {};\n}\n\n/**\n * ImageWidget transformer from shareable data\n */\nconst toImagePropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", alt: \"Image\", objectFit: \"cover\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: extractImageUrl(d),\n alt: (d.title ?? d.name ?? d.alt ?? \"Image\") as string,\n objectFit: \"cover\" as const,\n };\n};\n\n/**\n * VideoWidget transformer from shareable data\n */\nconst toVideoPropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", poster: \"\", caption: \"\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: ((d.video_url ?? d.videoUrl ?? d.src) as string) || \"\",\n poster: extractImageUrl(d),\n caption: (d.title ?? d.name ?? d.caption ?? \"\") as string,\n };\n};\n\n/**\n * Shareable content transformer\n * Normalizes shareable API responses to a consistent format\n */\nconst toShareableProps: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n // Derive a fallback shareable type from the data source configuration.\n // API presets pass shareable_type in their variables (e.g., \"products\").\n // Custom sources store it per-item (handled below).\n const sourceTypeHint =\n source?.type === \"api\" ? source.variables?.shareable_type : undefined;\n\n return data.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n // Resolve shareable type from the item itself, then fall back to source hint\n const shareableType = (d.type ??\n d.relateable_type ??\n d.shareable_type ??\n d.shareableType ??\n sourceTypeHint ??\n \"\") as string;\n\n return {\n ...d,\n id: d.id,\n title: (d.title ?? d.name ?? \"\") as string,\n description: extractDescription(d),\n imageUrl: extractImageUrl(d),\n videoUrl: ((d.video_url ?? d.videoUrl) as string) || null,\n shareableType,\n kind: (d.kind ?? \"image\") as string,\n status: (d.status ?? \"active\") as string,\n wholesalePrice: d.display_wholesale_price ?? d.wholesale_price ?? null,\n subscriptionPrice: d.subscription_price ?? null,\n outOfStock: d.out_of_stock ?? false,\n lowInStock: d.low_in_stock ?? false,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Carousel slides from shareables transformer\n */\nconst toCarouselSlidesFromShareables: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n return data.map((item: unknown, index: number) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n const imageUrl = extractImageUrl(d);\n const isVideo =\n d.kind === \"video\" ||\n d.content_format === \"video\" ||\n d.videoUrl ||\n d.video_url;\n const videoSrc =\n ((d.videoUrl ?? d.video_url) as string) ||\n (isVideo ? (d.url as string) || \"\" : \"\");\n const title = (d.title ?? d.name ?? \"\") as string;\n\n const content = isVideo\n ? {\n type: \"VideoWidget\",\n props: {\n src: videoSrc,\n poster: imageUrl,\n caption: title,\n autoplay: false,\n loop: false,\n muted: true,\n controls: true,\n },\n }\n : {\n type: \"ImageWidget\",\n props: {\n src: imageUrl,\n alt: title || \"Slide image\",\n objectFit: \"cover\",\n },\n };\n\n const baseSlide = {\n id: String(d.id ?? `slide-${index}`),\n content,\n title,\n description: extractDescription(d),\n };\n\n return {\n ...baseSlide,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Orders table transformer\n * Normalizes order list data into ShareableItem rows + column definitions.\n * Returns { data, columns } so multi-targetProp mapping sends each to the widget.\n */\nconst toOrderTableProps: DataTransformer = (data) => {\n const orders = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"order_number\", label: \"Order #\", sortable: true },\n { key: \"price\", label: \"Total\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = orders.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const firstItem = d.first_item as Record<string, unknown> | undefined;\n const amount = parseFloat(String(d.amount ?? \"0\")) || 0;\n\n return {\n ...d,\n id: d.id ?? d.token,\n shareableType: \"Order\",\n imageUrl: (firstItem?.image_url as string) || \"\",\n title: (firstItem?.title as string) || \"\",\n order_number: d.order_number ?? \"\",\n price: amount,\n display_price: (d.total_display_amount as string) ?? d.amount ?? \"\",\n status: (d.status as string) ?? \"unknown\",\n created_at: d.created_at,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * Subscriptions table transformer\n * Normalizes subscription list data into ShareableItem rows + column definitions.\n */\nconst toSubscriptionTableProps: DataTransformer = (data) => {\n const subscriptions = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"title\", label: \"Product\", sortable: true },\n { key: \"price\", label: \"Price\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = subscriptions.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const variant = d.variant as Record<string, unknown> | undefined;\n const product = variant?.product as Record<string, unknown> | undefined;\n\n return {\n ...d,\n id: d.id ?? d.subscription_token,\n shareableType: \"Subscription\",\n imageUrl: (product?.image_url as string) || \"\",\n title: (product?.title as string) || \"\",\n price: parseFloat(String(d.price ?? \"0\")) || 0,\n display_price:\n (product?.price_in_currency as string) ?? String(d.price ?? \"\"),\n status: (d.status as string) ?? \"unknown\",\n next_bill_date: d.next_bill_date,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * All widget transformers bundled for registration\n */\nexport const WIDGET_TRANSFORMERS: Record<string, DataTransformer> = {\n toShareableProps,\n toCarouselSlidesFromShareables,\n toImagePropsFromShareable,\n toVideoPropsFromShareable,\n toOrderTableProps,\n toSubscriptionTableProps,\n};\n","import type {\n DataSourceRegistry,\n DataFetcher,\n DataTransformer,\n DataSourceType,\n} from \"./types\";\nimport { apiFetcher } from \"./fetchers/api\";\nimport { customFetcher } from \"./fetchers/custom\";\nimport { staticFetcher } from \"./fetchers/static\";\nimport { WIDGET_TRANSFORMERS } from \"./transformers\";\n\nexport interface CreateDataSourceRegistryOptions {\n /** Custom fetchers to add or override */\n fetchers?: Partial<Record<DataSourceType, DataFetcher>>;\n /** Custom transform functions */\n transformers?: Record<string, DataTransformer>;\n}\n\n/**\n * Creates a data source registry with default fetchers.\n * Users can extend this with custom fetchers and transformers.\n */\nexport function createDataSourceRegistry(\n options?: CreateDataSourceRegistryOptions,\n): DataSourceRegistry {\n return {\n fetchers: {\n api: apiFetcher,\n custom: customFetcher,\n static: staticFetcher,\n ...options?.fetchers,\n } as Record<DataSourceType, DataFetcher>,\n transformers: {\n ...WIDGET_TRANSFORMERS,\n ...options?.transformers,\n },\n };\n}\n\n/** Default registry instance */\nexport const DEFAULT_DATA_SOURCE_REGISTRY: DataSourceRegistry =\n createDataSourceRegistry();\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\n\nexport interface DataSourceContextValue {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n}\n\nconst DataSourceContext = createContext<DataSourceContextValue>({});\n\nexport interface DataSourceProviderProps {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n children: ReactNode;\n}\n\nexport function DataSourceProvider({\n baseUrl,\n getApiHeaders,\n children,\n}: DataSourceProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({ baseUrl, getApiHeaders }),\n [baseUrl, getApiHeaders],\n );\n\n return (\n <DataSourceContext.Provider value={value}>\n {children}\n </DataSourceContext.Provider>\n );\n}\n\nexport function useDataSourceConfig(): DataSourceContextValue {\n return useContext(DataSourceContext);\n}\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { DataSourceRegistry } from \"@fluid-app/portal-core/data-sources/types\";\nimport { DEFAULT_DATA_SOURCE_REGISTRY } from \"@fluid-app/portal-core/data-sources/registry\";\nimport { DataSourceProvider } from \"./context\";\n\ninterface DataSourceRegistryContextValue {\n registry: DataSourceRegistry;\n baseUrl?: string | undefined;\n /** Get API headers function */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n}\n\nconst DataSourceRegistryContext = createContext<DataSourceRegistryContextValue>(\n {\n registry: DEFAULT_DATA_SOURCE_REGISTRY,\n },\n);\n\nexport interface DataSourceRegistryProviderProps {\n registry?: DataSourceRegistry | undefined;\n /** Base URL for API calls (e.g., \"https://api.fluid.app/api\") */\n baseUrl?: string | undefined;\n /**\n * Get API headers function\n */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n children: ReactNode;\n}\n\n/**\n * Provides data source registry and configuration to all descendants.\n * If no registry is provided, uses the default.\n * Also provides the shared DataSourceProvider from portal-core so that\n * portal-widgets hooks can access baseUrl and getApiHeaders.\n *\n * The DataSourceApi adapter is provided separately via DataSourceApiProvider.\n */\nexport function DataSourceRegistryProvider({\n registry,\n baseUrl,\n getApiHeaders,\n variables,\n children,\n}: DataSourceRegistryProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({\n registry: registry ?? DEFAULT_DATA_SOURCE_REGISTRY,\n baseUrl,\n getApiHeaders,\n variables,\n }),\n [registry, baseUrl, getApiHeaders, variables],\n );\n\n return (\n <DataSourceRegistryContext.Provider value={value}>\n <DataSourceProvider baseUrl={baseUrl} getApiHeaders={getApiHeaders}>\n {children}\n </DataSourceProvider>\n </DataSourceRegistryContext.Provider>\n );\n}\n\n/**\n * Hook to access the data source registry.\n */\nexport function useDataSourceRegistry(): DataSourceRegistry {\n return useContext(DataSourceRegistryContext).registry;\n}\n\n/**\n * Hook to access the full data source registry context (registry + config).\n */\nexport function useDataSourceRegistryConfig(): DataSourceRegistryContextValue {\n return useContext(DataSourceRegistryContext);\n}\n"],"mappings":"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"}
|
|
@@ -27,24 +27,16 @@ async function fetchViaAdapter(source, context) {
|
|
|
27
27
|
languageIso: vars?.language_iso,
|
|
28
28
|
signal: context.signal
|
|
29
29
|
});
|
|
30
|
-
case "customer-orders": {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const customerId = vars?.customer_id;
|
|
41
|
-
if (!customerId) return void 0;
|
|
42
|
-
return api.fetchSubscriptions(customerId, {
|
|
43
|
-
limit: vars?.limit ? Number(vars.limit) : void 0,
|
|
44
|
-
status: vars?.status,
|
|
45
|
-
signal: context.signal
|
|
46
|
-
});
|
|
47
|
-
}
|
|
30
|
+
case "customer-orders": return api.fetchOrders(vars?.customer_id ?? "", {
|
|
31
|
+
limit: vars?.limit ? Number(vars.limit) : void 0,
|
|
32
|
+
status: vars?.status,
|
|
33
|
+
signal: context.signal
|
|
34
|
+
});
|
|
35
|
+
case "customer-subscriptions": return api.fetchSubscriptions(vars?.customer_id ?? "", {
|
|
36
|
+
limit: vars?.limit ? Number(vars.limit) : void 0,
|
|
37
|
+
status: vars?.status,
|
|
38
|
+
signal: context.signal
|
|
39
|
+
});
|
|
48
40
|
default: return;
|
|
49
41
|
}
|
|
50
42
|
}
|
|
@@ -116,7 +108,7 @@ async function apiFetcher(source, context) {
|
|
|
116
108
|
...source.variables
|
|
117
109
|
};
|
|
118
110
|
const url = resolveEndpointUrl(endpoint, context.baseUrl, mergedVariables);
|
|
119
|
-
if (/\{\w+\}/.test(url)) return;
|
|
111
|
+
if (/\{\w+\}/.test(url)) return null;
|
|
120
112
|
const fetchOptions = {
|
|
121
113
|
method,
|
|
122
114
|
headers: {
|
|
@@ -315,16 +307,17 @@ const toCarouselSlidesFromShareables = (data, source) => {
|
|
|
315
307
|
const d = item;
|
|
316
308
|
const widgetConfig = extractCustomWidgetConfig(d, source);
|
|
317
309
|
const imageUrl = extractImageUrl(d);
|
|
318
|
-
const isVideo = d.kind === "video" || d.videoUrl || d.video_url;
|
|
310
|
+
const isVideo = d.kind === "video" || d.content_format === "video" || d.videoUrl || d.video_url;
|
|
311
|
+
const videoSrc = (d.videoUrl ?? d.video_url) || (isVideo ? d.url || "" : "");
|
|
319
312
|
const title = d.title ?? d.name ?? "";
|
|
320
313
|
const content = isVideo ? {
|
|
321
314
|
type: "VideoWidget",
|
|
322
315
|
props: {
|
|
323
|
-
src:
|
|
316
|
+
src: videoSrc,
|
|
324
317
|
poster: imageUrl,
|
|
325
318
|
caption: title,
|
|
326
|
-
autoplay:
|
|
327
|
-
loop:
|
|
319
|
+
autoplay: false,
|
|
320
|
+
loop: false,
|
|
328
321
|
muted: true,
|
|
329
322
|
controls: true
|
|
330
323
|
}
|
|
@@ -536,4 +529,4 @@ Object.defineProperty(exports, "useDataSourceRegistryConfig", {
|
|
|
536
529
|
}
|
|
537
530
|
});
|
|
538
531
|
|
|
539
|
-
//# sourceMappingURL=registry-context-
|
|
532
|
+
//# sourceMappingURL=registry-context-CcZYS15Q.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-context-CcZYS15Q.cjs","names":[],"sources":["../../core/src/data-sources/fetchers/api.ts","../../core/src/data-sources/fetchers/custom.ts","../../core/src/data-sources/fetchers/static.ts","../../core/src/data-sources/transformers.ts","../../core/src/data-sources/registry.ts","../../react/src/data-sources/context.tsx","../../react/src/data-sources/registry-context.tsx"],"sourcesContent":["import type { DataSourceShareableType } from \"../../data-source-api-types\";\nimport type { ApiDataSource, DataSourceContext } from \"../types\";\n\n/**\n * Delegates a preset API source to the injected DataSourceApi adapter.\n * Returns undefined for unknown presets (caller falls through to raw fetch).\n */\nasync function fetchViaAdapter(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n const api = context.api!;\n const vars = { ...context.variables, ...source.variables };\n\n switch (source.presetId) {\n case \"rep-most-shared\": {\n return api.fetchMostShared(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"rep-most-viewed\": {\n return api.fetchMostViewed(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"customer-orders\": {\n // BFF scopes by session — customer_id is informational/optional.\n return api.fetchOrders(vars?.customer_id ?? \"\", {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n case \"customer-subscriptions\": {\n // BFF scopes by session — customer_id is informational/optional.\n return api.fetchSubscriptions(vars?.customer_id ?? \"\", {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Extracts a value from an object using dot notation path\n * e.g., getByPath({ data: { items: [1,2,3] } }, 'data.items') => [1,2,3]\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n return path.split(\".\").reduce((current, key) => {\n if (current && typeof current === \"object\" && key in current) {\n return (current as Record<string, unknown>)[key];\n }\n return undefined;\n }, obj);\n}\n\n/**\n * Replaces {variable} placeholders in an endpoint path with values from the\n * variables map. E.g., \"/reps/{rep_id}/most_shared\" with { rep_id: \"42\" }\n * becomes \"/reps/42/most_shared\".\n */\nfunction interpolateVariables(\n endpoint: string,\n variables?: Record<string, string>,\n): string {\n if (!variables) return endpoint;\n const resolved = endpoint.replace(\n /\\{(\\w+)\\}/g,\n (match, key: string) => variables[key] ?? match,\n );\n const unresolved = resolved.match(/\\{(\\w+)\\}/g);\n if (unresolved) {\n console.warn(\n `[DataSource] Unresolved variable placeholders in endpoint: ${unresolved.join(\", \")}. ` +\n `Endpoint: \"${endpoint}\". Available variables: ${Object.keys(variables).join(\", \") || \"(none)\"}`,\n );\n }\n return stripAllQueryParams(resolved);\n}\n\n/**\n * Removes query parameters whose value is \"all\" from a URL.\n *\n * Convention: \"all\" is a reserved no-op value for data source preset\n * config fields. Preset authors should use \"all\" as the default option\n * for \"show everything\" filters. This function strips those params so\n * APIs that don't recognise \"all\" fall back to their default (return\n * everything) behaviour. Do not use \"all\" as a meaningful filter value\n * in preset endpoints.\n */\nfunction stripAllQueryParams(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return url;\n\n const base = url.slice(0, qIndex);\n const query = url.slice(qIndex + 1);\n const kept = query\n .split(\"&\")\n .filter((pair) => {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) return true;\n return pair.slice(eqIndex + 1) !== \"all\";\n })\n .join(\"&\");\n\n return kept ? `${base}?${kept}` : base;\n}\n\n/**\n * Resolves the full URL for an endpoint.\n * - Substitutes {variable} placeholders from context variables\n * - Absolute URLs (starting with http:// or https://) are used as-is\n * - Relative paths are prefixed with the context's baseUrl\n */\nfunction resolveEndpointUrl(\n endpoint: string,\n baseUrl?: string,\n variables?: Record<string, string>,\n): string {\n const resolved = interpolateVariables(endpoint, variables);\n\n // If endpoint is already absolute, use it directly\n if (resolved.startsWith(\"http://\") || resolved.startsWith(\"https://\")) {\n return resolved;\n }\n\n // If we have a baseUrl, prepend it to the relative endpoint\n if (baseUrl) {\n // Ensure proper joining (no double slashes)\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const path = resolved.startsWith(\"/\") ? resolved : `/${resolved}`;\n return `${base}${path}`;\n }\n\n // No baseUrl provided, return endpoint as-is (will likely fail for relative paths)\n return resolved;\n}\n\n/**\n * Default API fetcher implementation\n */\nexport async function apiFetcher(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n // Delegate to adapter if available for preset-backed sources\n if (context.api && source.presetId) {\n const result = await fetchViaAdapter(source, context);\n if (result !== undefined) return result;\n // Fall through to legacy fetch for unknown presets\n }\n\n const { endpoint, method = \"GET\", headers = {}, body, resultPath } = source;\n\n // Merge context variables with per-source variables (source overrides context)\n const mergedVariables = { ...context.variables, ...source.variables };\n\n // Resolve the full URL, substituting variables and using baseUrl for relative endpoints\n const url = resolveEndpointUrl(endpoint, context.baseUrl, mergedVariables);\n\n // Skip the fetch if the URL still contains unresolved {variable} placeholders\n // (e.g. rep_id not yet loaded). Return null — TanStack Query treats undefined\n // as a missing return and throws, so use null for the no-op case.\n if (/\\{\\w+\\}/.test(url)) {\n return null;\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n \"content-type\": \"application/json\",\n ...context.getApiHeaders?.(),\n ...headers,\n },\n signal: context.signal,\n };\n\n if (body && (method === \"POST\" || method === \"PUT\")) {\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n throw new Error(\n `API request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n // Extract data at resultPath if specified\n if (resultPath) {\n return getByPath(data, resultPath);\n }\n\n return data;\n}\n","import type { ResourceType } from \"../../data-source-api-types\";\nimport type {\n CustomDataSource,\n DataSourceContext,\n SelectedItem,\n} from \"../types\";\n\nconst SHAREABLE_TO_RESOURCE_TYPE: Record<string, ResourceType> = {\n Medium: \"Medium\",\n Page: \"Page\",\n Library: \"Library\",\n Product: \"Product\",\n EnrollmentPack: \"EnrollmentPack\",\n};\n\nasync function fetchItemsViaAdapter(\n items: SelectedItem[],\n context: DataSourceContext,\n): Promise<unknown[]> {\n const api = context.api!;\n\n // Use Promise.allSettled so individual failures don't blow up the whole\n // batch, but *do* surface the aggregate failure for visibility — a rep who\n // hand-picked 5 items shouldn't silently see 3 without knowing why.\n const settled = await Promise.allSettled(\n items.map(async (item) => {\n const resourceType = SHAREABLE_TO_RESOURCE_TYPE[item.shareableType];\n if (!resourceType) {\n throw new Error(\n `Unknown shareable type: ${item.shareableType} for item #${item.id}`,\n );\n }\n return api.fetchResource(resourceType, item.id, context.signal);\n }),\n );\n\n const successful: unknown[] = [];\n const failures: { item: SelectedItem; reason: unknown }[] = [];\n\n settled.forEach((result, index) => {\n const item = items[index];\n if (!item) return;\n if (result.status === \"fulfilled\") {\n successful.push(result.value);\n } else {\n failures.push({ item, reason: result.reason });\n }\n });\n\n if (failures.length > 0) {\n // Log once with aggregate context so Sentry/logs show the full picture\n // rather than N scattered warnings that are hard to correlate.\n console.error(\n `[CustomFetcher] ${failures.length}/${items.length} items failed to fetch:`,\n failures.map((f) => ({\n shareableType: f.item.shareableType,\n id: f.item.id,\n error: f.reason instanceof Error ? f.reason.message : f.reason,\n })),\n );\n }\n\n if (successful.length === 0 && items.length > 0) {\n const firstErr = failures[0]?.reason;\n throw new Error(\n `Failed to fetch all ${items.length} item(s)${firstErr instanceof Error ? `: ${firstErr.message}` : \"\"}`,\n );\n }\n\n return successful;\n}\n\n/**\n * Custom fetcher that fetches selected items via the injected DataSourceApi adapter.\n *\n * Fetches all items in parallel for performance.\n * Returns an array of successfully fetched items, preserving order.\n * Logs warnings for failed fetches but doesn't throw unless all items fail.\n */\nexport async function customFetcher(\n source: CustomDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { selectedItems } = source;\n if (!selectedItems || selectedItems.length === 0) {\n return [];\n }\n\n if (!context.api) {\n throw new Error(\n \"customFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n return fetchItemsViaAdapter(selectedItems, context);\n}\n","import type {\n StaticDataSource,\n DataSourceContext,\n StaticSourceType,\n} from \"../types\";\n\n/**\n * Static data source fetcher.\n *\n * Delegates to the injected DataSourceApi adapter to fetch products filtered\n * by collection, category, or tag.\n */\nexport async function staticFetcher(\n source: StaticDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { staticType, selectedId } = source;\n\n if (!context.api) {\n throw new Error(\n \"staticFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n // Validate filterId once at the shared delegation point so BFF and legacy\n // adapters behave identically. Tags are a known-unsupported type the\n // adapters throw for separately.\n if (staticType !== \"tags\" && Number.isNaN(Number(selectedId))) {\n throw new Error(\n `staticFetcher: selectedId must be numeric, got \"${selectedId}\"`,\n );\n }\n\n return context.api.fetchProductsByFilter(\n staticType,\n selectedId,\n context.signal,\n );\n}\n\n/**\n * Endpoints for listing static source items (collections, categories, tags).\n * Used by the portal builder UI for populating selection dropdowns.\n */\nexport const LIST_ENDPOINTS: Record<\n StaticSourceType,\n { endpoint: string; resultKey: string }\n> = {\n collections: {\n endpoint: \"/company/v1/collections\",\n resultKey: \"collections\",\n },\n categories: { endpoint: \"/company/v1/categories\", resultKey: \"categories\" },\n tags: { endpoint: \"/company/v1/tags\", resultKey: \"tags\" },\n};\n","/**\n * Widget Transformers\n *\n * Transform functions that map API response data to widget-specific prop shapes.\n * Each widget has one transformer that handles all data structure variants:\n * - Standard: Direct field name match\n * - Legacy: Different field names that need mapping\n * - Minimal: Bare minimum fields that need defaults\n *\n * Usage:\n * 1. Transformers are registered in the DataSourceRegistry\n * 2. Reference by name in ApiDataSource.transform\n * 3. Applied after resultPath extraction, before targetProps assignment\n */\n\nimport type { DataTransformer, DataSource } from \"./types\";\n\n/**\n * Helper to extract image URL from various API response structures.\n * Handles:\n * - Flat fields (Medium, Page, Product): image_url, imageUrl, thumbnail_url, src\n * - Nested images array (EnrollmentPack): images[0].image_url\n * - Nested library_items (Library): library_items[0].relateable.image_url\n */\nfunction extractImageUrl(d: Record<string, unknown>): string {\n // Try flat fields first (Medium, Page, Product)\n if (d.image_url) return d.image_url as string;\n if (d.imageUrl) return d.imageUrl as string;\n if (d.thumbnail_url) return d.thumbnail_url as string;\n if (d.src) return d.src as string;\n\n // Try nested images array (EnrollmentPack)\n const images = d.images as Array<Record<string, unknown>> | undefined;\n if (images && images.length > 0) {\n const firstImage = images[0];\n if (firstImage?.image_url) return firstImage.image_url as string;\n if (firstImage?.url) return firstImage.url as string;\n }\n\n // Try nested library_items (Library/Playlist)\n const libraryItems = d.library_items as\n | Array<Record<string, unknown>>\n | undefined;\n if (libraryItems && libraryItems.length > 0) {\n const firstItem = libraryItems[0];\n const relateable = firstItem?.relateable as\n | Record<string, unknown>\n | undefined;\n if (relateable?.image_url) return relateable.image_url as string;\n if (relateable?.imageUrl) return relateable.imageUrl as string;\n if (relateable?.thumbnail_url) return relateable.thumbnail_url as string;\n }\n\n return \"\";\n}\n\n/**\n * Helper to extract description from various API response structures.\n * Handles different field names across endpoints.\n */\nfunction extractDescription(d: Record<string, unknown>): string {\n // Try various description field names\n const desc =\n d.description ?? d.stripped ?? d.stripped_description ?? d.body ?? \"\";\n\n // Handle nested description object (some APIs return { body: \"...\" })\n if (typeof desc === \"object\" && desc !== null && \"body\" in desc) {\n return ((desc as Record<string, unknown>).body as string) ?? \"\";\n }\n\n return desc as string;\n}\n\n/**\n * Helper to extract custom widget config from a selected item.\n */\nfunction extractCustomWidgetConfig(\n d: Record<string, unknown>,\n source: DataSource | undefined,\n): Record<string, unknown> {\n if (source === undefined || source.type !== \"custom\") return {};\n\n const selectedItem = source.selectedItems.find(\n (s) => String(s.id) === String(d.id),\n );\n return selectedItem?.widgetConfig ?? {};\n}\n\n/**\n * ImageWidget transformer from shareable data\n */\nconst toImagePropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", alt: \"Image\", objectFit: \"cover\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: extractImageUrl(d),\n alt: (d.title ?? d.name ?? d.alt ?? \"Image\") as string,\n objectFit: \"cover\" as const,\n };\n};\n\n/**\n * VideoWidget transformer from shareable data\n */\nconst toVideoPropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", poster: \"\", caption: \"\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: ((d.video_url ?? d.videoUrl ?? d.src) as string) || \"\",\n poster: extractImageUrl(d),\n caption: (d.title ?? d.name ?? d.caption ?? \"\") as string,\n };\n};\n\n/**\n * Shareable content transformer\n * Normalizes shareable API responses to a consistent format\n */\nconst toShareableProps: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n // Derive a fallback shareable type from the data source configuration.\n // API presets pass shareable_type in their variables (e.g., \"products\").\n // Custom sources store it per-item (handled below).\n const sourceTypeHint =\n source?.type === \"api\" ? source.variables?.shareable_type : undefined;\n\n return data.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n // Resolve shareable type from the item itself, then fall back to source hint\n const shareableType = (d.type ??\n d.relateable_type ??\n d.shareable_type ??\n d.shareableType ??\n sourceTypeHint ??\n \"\") as string;\n\n return {\n ...d,\n id: d.id,\n title: (d.title ?? d.name ?? \"\") as string,\n description: extractDescription(d),\n imageUrl: extractImageUrl(d),\n videoUrl: ((d.video_url ?? d.videoUrl) as string) || null,\n shareableType,\n kind: (d.kind ?? \"image\") as string,\n status: (d.status ?? \"active\") as string,\n wholesalePrice: d.display_wholesale_price ?? d.wholesale_price ?? null,\n subscriptionPrice: d.subscription_price ?? null,\n outOfStock: d.out_of_stock ?? false,\n lowInStock: d.low_in_stock ?? false,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Carousel slides from shareables transformer\n */\nconst toCarouselSlidesFromShareables: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n return data.map((item: unknown, index: number) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n const imageUrl = extractImageUrl(d);\n const isVideo =\n d.kind === \"video\" ||\n d.content_format === \"video\" ||\n d.videoUrl ||\n d.video_url;\n const videoSrc =\n ((d.videoUrl ?? d.video_url) as string) ||\n (isVideo ? (d.url as string) || \"\" : \"\");\n const title = (d.title ?? d.name ?? \"\") as string;\n\n const content = isVideo\n ? {\n type: \"VideoWidget\",\n props: {\n src: videoSrc,\n poster: imageUrl,\n caption: title,\n autoplay: false,\n loop: false,\n muted: true,\n controls: true,\n },\n }\n : {\n type: \"ImageWidget\",\n props: {\n src: imageUrl,\n alt: title || \"Slide image\",\n objectFit: \"cover\",\n },\n };\n\n const baseSlide = {\n id: String(d.id ?? `slide-${index}`),\n content,\n title,\n description: extractDescription(d),\n };\n\n return {\n ...baseSlide,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Orders table transformer\n * Normalizes order list data into ShareableItem rows + column definitions.\n * Returns { data, columns } so multi-targetProp mapping sends each to the widget.\n */\nconst toOrderTableProps: DataTransformer = (data) => {\n const orders = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"order_number\", label: \"Order #\", sortable: true },\n { key: \"price\", label: \"Total\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = orders.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const firstItem = d.first_item as Record<string, unknown> | undefined;\n const amount = parseFloat(String(d.amount ?? \"0\")) || 0;\n\n return {\n ...d,\n id: d.id ?? d.token,\n shareableType: \"Order\",\n imageUrl: (firstItem?.image_url as string) || \"\",\n title: (firstItem?.title as string) || \"\",\n order_number: d.order_number ?? \"\",\n price: amount,\n display_price: (d.total_display_amount as string) ?? d.amount ?? \"\",\n status: (d.status as string) ?? \"unknown\",\n created_at: d.created_at,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * Subscriptions table transformer\n * Normalizes subscription list data into ShareableItem rows + column definitions.\n */\nconst toSubscriptionTableProps: DataTransformer = (data) => {\n const subscriptions = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"title\", label: \"Product\", sortable: true },\n { key: \"price\", label: \"Price\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = subscriptions.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const variant = d.variant as Record<string, unknown> | undefined;\n const product = variant?.product as Record<string, unknown> | undefined;\n\n return {\n ...d,\n id: d.id ?? d.subscription_token,\n shareableType: \"Subscription\",\n imageUrl: (product?.image_url as string) || \"\",\n title: (product?.title as string) || \"\",\n price: parseFloat(String(d.price ?? \"0\")) || 0,\n display_price:\n (product?.price_in_currency as string) ?? String(d.price ?? \"\"),\n status: (d.status as string) ?? \"unknown\",\n next_bill_date: d.next_bill_date,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * All widget transformers bundled for registration\n */\nexport const WIDGET_TRANSFORMERS: Record<string, DataTransformer> = {\n toShareableProps,\n toCarouselSlidesFromShareables,\n toImagePropsFromShareable,\n toVideoPropsFromShareable,\n toOrderTableProps,\n toSubscriptionTableProps,\n};\n","import type {\n DataSourceRegistry,\n DataFetcher,\n DataTransformer,\n DataSourceType,\n} from \"./types\";\nimport { apiFetcher } from \"./fetchers/api\";\nimport { customFetcher } from \"./fetchers/custom\";\nimport { staticFetcher } from \"./fetchers/static\";\nimport { WIDGET_TRANSFORMERS } from \"./transformers\";\n\nexport interface CreateDataSourceRegistryOptions {\n /** Custom fetchers to add or override */\n fetchers?: Partial<Record<DataSourceType, DataFetcher>>;\n /** Custom transform functions */\n transformers?: Record<string, DataTransformer>;\n}\n\n/**\n * Creates a data source registry with default fetchers.\n * Users can extend this with custom fetchers and transformers.\n */\nexport function createDataSourceRegistry(\n options?: CreateDataSourceRegistryOptions,\n): DataSourceRegistry {\n return {\n fetchers: {\n api: apiFetcher,\n custom: customFetcher,\n static: staticFetcher,\n ...options?.fetchers,\n } as Record<DataSourceType, DataFetcher>,\n transformers: {\n ...WIDGET_TRANSFORMERS,\n ...options?.transformers,\n },\n };\n}\n\n/** Default registry instance */\nexport const DEFAULT_DATA_SOURCE_REGISTRY: DataSourceRegistry =\n createDataSourceRegistry();\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\n\nexport interface DataSourceContextValue {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n}\n\nconst DataSourceContext = createContext<DataSourceContextValue>({});\n\nexport interface DataSourceProviderProps {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n children: ReactNode;\n}\n\nexport function DataSourceProvider({\n baseUrl,\n getApiHeaders,\n children,\n}: DataSourceProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({ baseUrl, getApiHeaders }),\n [baseUrl, getApiHeaders],\n );\n\n return (\n <DataSourceContext.Provider value={value}>\n {children}\n </DataSourceContext.Provider>\n );\n}\n\nexport function useDataSourceConfig(): DataSourceContextValue {\n return useContext(DataSourceContext);\n}\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { DataSourceRegistry } from \"@fluid-app/portal-core/data-sources/types\";\nimport { DEFAULT_DATA_SOURCE_REGISTRY } from \"@fluid-app/portal-core/data-sources/registry\";\nimport { DataSourceProvider } from \"./context\";\n\ninterface DataSourceRegistryContextValue {\n registry: DataSourceRegistry;\n baseUrl?: string | undefined;\n /** Get API headers function */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n}\n\nconst DataSourceRegistryContext = createContext<DataSourceRegistryContextValue>(\n {\n registry: DEFAULT_DATA_SOURCE_REGISTRY,\n },\n);\n\nexport interface DataSourceRegistryProviderProps {\n registry?: DataSourceRegistry | undefined;\n /** Base URL for API calls (e.g., \"https://api.fluid.app/api\") */\n baseUrl?: string | undefined;\n /**\n * Get API headers function\n */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n children: ReactNode;\n}\n\n/**\n * Provides data source registry and configuration to all descendants.\n * If no registry is provided, uses the default.\n * Also provides the shared DataSourceProvider from portal-core so that\n * portal-widgets hooks can access baseUrl and getApiHeaders.\n *\n * The DataSourceApi adapter is provided separately via DataSourceApiProvider.\n */\nexport function DataSourceRegistryProvider({\n registry,\n baseUrl,\n getApiHeaders,\n variables,\n children,\n}: DataSourceRegistryProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({\n registry: registry ?? DEFAULT_DATA_SOURCE_REGISTRY,\n baseUrl,\n getApiHeaders,\n variables,\n }),\n [registry, baseUrl, getApiHeaders, variables],\n );\n\n return (\n <DataSourceRegistryContext.Provider value={value}>\n <DataSourceProvider baseUrl={baseUrl} getApiHeaders={getApiHeaders}>\n {children}\n </DataSourceProvider>\n </DataSourceRegistryContext.Provider>\n );\n}\n\n/**\n * Hook to access the data source registry.\n */\nexport function useDataSourceRegistry(): DataSourceRegistry {\n return useContext(DataSourceRegistryContext).registry;\n}\n\n/**\n * Hook to access the full data source registry context (registry + config).\n */\nexport function useDataSourceRegistryConfig(): DataSourceRegistryContextValue {\n return useContext(DataSourceRegistryContext);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-app/portal-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.240",
|
|
4
4
|
"description": "SDK for building custom Fluid portals",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -72,50 +72,50 @@
|
|
|
72
72
|
"typescript": "^5",
|
|
73
73
|
"zod": "4.3.5",
|
|
74
74
|
"@fluid-app/api-client-core": "0.1.0",
|
|
75
|
-
"@fluid-app/company-switcher-core": "0.1.0",
|
|
76
|
-
"@fluid-app/auth": "0.1.0",
|
|
77
75
|
"@fluid-app/cart-ui": "0.1.17",
|
|
76
|
+
"@fluid-app/auth": "0.1.0",
|
|
77
|
+
"@fluid-app/company-switcher-core": "0.1.0",
|
|
78
|
+
"@fluid-app/company-switcher-ui": "0.1.0",
|
|
78
79
|
"@fluid-app/contacts-core": "0.1.0",
|
|
79
80
|
"@fluid-app/contacts-ui": "0.1.0",
|
|
80
|
-
"@fluid-app/
|
|
81
|
+
"@fluid-app/file-picker-core": "0.1.0",
|
|
81
82
|
"@fluid-app/file-picker-api-client": "0.1.0",
|
|
82
83
|
"@fluid-app/fluid-pay-core": "0.1.0",
|
|
83
|
-
"@fluid-app/file-picker-core": "0.1.0",
|
|
84
84
|
"@fluid-app/fluidos-api-client": "0.1.0",
|
|
85
|
-
"@fluid-app/messaging-api-client": "0.1.0",
|
|
86
85
|
"@fluid-app/messaging-core": "0.1.0",
|
|
87
|
-
"@fluid-app/messaging-ui": "0.1.0",
|
|
88
86
|
"@fluid-app/mysite-core": "0.1.0",
|
|
87
|
+
"@fluid-app/messaging-api-client": "0.1.0",
|
|
88
|
+
"@fluid-app/messaging-ui": "0.1.0",
|
|
89
89
|
"@fluid-app/mysite-ui": "0.1.0",
|
|
90
|
-
"@fluid-app/orders-ui": "0.1.0",
|
|
91
90
|
"@fluid-app/orders-core": "0.1.0",
|
|
91
|
+
"@fluid-app/orders-ui": "0.1.0",
|
|
92
92
|
"@fluid-app/permissions": "0.1.0",
|
|
93
93
|
"@fluid-app/portal-app-download-ui": "0.1.0",
|
|
94
94
|
"@fluid-app/portal-core": "0.1.23",
|
|
95
95
|
"@fluid-app/portal-preview": "0.1.0",
|
|
96
96
|
"@fluid-app/portal-pro-upgrade-ui": "0.1.0",
|
|
97
|
-
"@fluid-app/portal-react": "0.1.0",
|
|
98
97
|
"@fluid-app/portal-tenant-api-client": "0.1.0",
|
|
98
|
+
"@fluid-app/portal-react": "0.1.0",
|
|
99
99
|
"@fluid-app/portal-tenant-contacts-api-client": "0.1.0",
|
|
100
|
-
"@fluid-app/portal-tenant-content-api-client": "0.1.0",
|
|
101
100
|
"@fluid-app/portal-tenant-mysite-api-client": "0.1.0",
|
|
102
|
-
"@fluid-app/portal-tenant-store-api-client": "0.1.0",
|
|
103
101
|
"@fluid-app/portal-tenant-pay-api-client": "0.1.0",
|
|
102
|
+
"@fluid-app/portal-tenant-content-api-client": "0.1.0",
|
|
103
|
+
"@fluid-app/portal-tenant-store-api-client": "0.1.0",
|
|
104
|
+
"@fluid-app/products-core": "0.1.0",
|
|
104
105
|
"@fluid-app/portal-widgets": "0.1.22",
|
|
105
106
|
"@fluid-app/products-api-client": "0.1.0",
|
|
106
|
-
"@fluid-app/products-core": "0.1.0",
|
|
107
107
|
"@fluid-app/profile-core": "0.1.0",
|
|
108
108
|
"@fluid-app/profile-ui": "0.1.0",
|
|
109
109
|
"@fluid-app/query-persister": "0.1.0",
|
|
110
110
|
"@fluid-app/shareables-core": "0.1.0",
|
|
111
|
-
"@fluid-app/shareables-ui": "0.1.0",
|
|
112
111
|
"@fluid-app/shop-ui": "0.1.0",
|
|
113
|
-
"@fluid-app/
|
|
114
|
-
"@fluid-app/store-core": "0.1.0",
|
|
112
|
+
"@fluid-app/shareables-ui": "0.1.0",
|
|
115
113
|
"@fluid-app/subscriptions-core": "0.1.0",
|
|
116
|
-
"@fluid-app/
|
|
114
|
+
"@fluid-app/store-core": "0.1.0",
|
|
115
|
+
"@fluid-app/store-api-client": "0.1.0",
|
|
116
|
+
"@fluid-app/subscriptions-ui": "0.1.0",
|
|
117
117
|
"@fluid-app/ui-primitives": "0.1.13",
|
|
118
|
-
"@fluid-app/
|
|
118
|
+
"@fluid-app/typescript-config": "0.0.0"
|
|
119
119
|
},
|
|
120
120
|
"peerDependencies": {
|
|
121
121
|
"@hookform/resolvers": "^5.2.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselWidget-CdQhlRrW.mjs","names":["DOMPurify"],"sources":["../../widgets/src/widgets/CarouselWidget.tsx"],"sourcesContent":["import type { ComponentProps, CSSProperties } from \"react\";\nimport type React from \"react\";\nimport { useEffect, useState, useCallback } from \"react\";\nimport DOMPurify from \"dompurify\";\nimport {\n MediaRenderer,\n getMediaPropsFromWidgetSchema,\n} from \"../components/MediaRenderer\";\nimport type {\n WidgetSchema,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n AlignOptions,\n FontSizeOptions,\n PaddingOptions,\n ButtonSizeOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n borderColorClasses,\n borderWidthClasses,\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getButtonSizeField,\n getColorField,\n getFontSizeField,\n getHeightField,\n getPaddingField,\n} from \"../core/fields\";\n\ntype CarouselSlide = {\n id: string;\n content: WidgetSchema;\n title?: string;\n description?: string;\n // Editorial additions (all optional — existing configs keep working)\n eyebrow?: string;\n meta?: string;\n tag?: string;\n tagColor?: ColorOptions;\n buttonEnabled?: boolean;\n buttonText?: string;\n buttonVariant?:\n | \"default\"\n | \"secondary\"\n | \"outline\"\n | \"destructive\"\n | \"ghost\"\n | \"link\";\n buttonLink?: string;\n secondaryButtonText?: string;\n secondaryButtonLink?: string;\n};\n\ntype CarouselWidgetProps = ComponentProps<\"div\"> & {\n slides?: CarouselSlide[];\n autoScrollInterval?: number;\n enableAutoScroll?: boolean;\n\n // Layout\n align?: AlignOptions;\n // CSS-unit string (\"400px\", \"30rem\", \"50%\") — kept as string so saved\n // configs from the previous schema continue to render. The schema field\n // is `cssUnit` (via getHeightField), which produces a string with the\n // unit baked in.\n carouselHeight?: string;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n padding?: PaddingOptions;\n\n // Text Styling\n headerSize?: FontSizeOptions;\n headerColor?: ColorOptions;\n textSize?: FontSizeOptions;\n textColor?: ColorOptions;\n textWidth?: string;\n\n // Button\n showButton?: boolean;\n buttonColor?: ColorOptions;\n buttonSize?: ButtonSizeOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Editorial frame (new — opt-out via `editorialFrame={false}`)\n editorialFrame?: boolean;\n frameColor?: ColorOptions;\n};\n\nconst HEADER_SIZE_MAP: Record<FontSizeOptions, string> = {\n xs: \"text-base sm:text-lg\",\n sm: \"text-lg sm:text-xl\",\n md: \"text-xl sm:text-2xl\",\n lg: \"text-2xl sm:text-3xl\",\n xl: \"text-3xl sm:text-[32px]\",\n \"2xl\": \"text-[32px] sm:text-[40px]\",\n};\n\nconst BODY_SIZE_MAP: Record<FontSizeOptions, string> = {\n xs: \"text-[12px]\",\n sm: \"text-[13px]\",\n md: \"text-[14px]\",\n lg: \"text-[15px]\",\n xl: \"text-[16px]\",\n \"2xl\": \"text-[18px]\",\n};\n\nfunction useCarouselController({\n slideCount,\n enableAutoScroll,\n autoScrollInterval,\n}: {\n slideCount: number;\n enableAutoScroll: boolean;\n autoScrollInterval: number;\n}) {\n const [currentIndex, setCurrentIndex] = useState(0);\n // Track hover and keyboard focus separately — combining them in one boolean\n // would let `onMouseLeave` clear the paused state even while a child button\n // still has focus.\n const [isHovered, setIsHovered] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const hasSlides = slideCount > 0;\n const isPaused = isHovered || isFocused;\n\n const goToNext = useCallback(() => {\n if (!hasSlides) return;\n setCurrentIndex((prev) => (prev === slideCount - 1 ? 0 : prev + 1));\n }, [hasSlides, slideCount]);\n\n const goToPrevious = useCallback(() => {\n if (!hasSlides) return;\n setCurrentIndex((prev) => (prev === 0 ? slideCount - 1 : prev - 1));\n }, [hasSlides, slideCount]);\n\n const goToSlide = useCallback(\n (index: number) => {\n if (!hasSlides) return;\n if (index >= 0 && index < slideCount) {\n setCurrentIndex(index);\n }\n },\n [hasSlides, slideCount],\n );\n\n useEffect(() => {\n if (!enableAutoScroll || !hasSlides || isPaused) return;\n const intervalId = setInterval(goToNext, autoScrollInterval);\n return () => clearInterval(intervalId);\n }, [enableAutoScroll, autoScrollInterval, hasSlides, isPaused, goToNext]);\n\n useEffect(() => {\n if (currentIndex >= slideCount && slideCount > 0) {\n setCurrentIndex(0);\n }\n }, [slideCount, currentIndex]);\n\n const handleMouseEnter = useCallback(() => setIsHovered(true), []);\n const handleMouseLeave = useCallback(() => setIsHovered(false), []);\n const handleFocus = useCallback(() => setIsFocused(true), []);\n const handleBlur = useCallback((e: React.FocusEvent<HTMLElement>) => {\n // Only flip to unfocused when focus actually leaves the carousel.\n // When focus moves between two children (e.g. tabbing from prev to next\n // button), `relatedTarget` is the new focus target and is still contained.\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) {\n setIsFocused(false);\n }\n }, []);\n\n return {\n currentIndex,\n hasSlides,\n isPaused,\n goToNext,\n goToPrevious,\n goToSlide,\n handleMouseEnter,\n handleMouseLeave,\n handleFocus,\n handleBlur,\n };\n}\n\nexport function CarouselWidget({\n slides = [],\n autoScrollInterval = 6500,\n enableAutoScroll = false,\n carouselHeight = \"400px\",\n align = { vertical: \"bottom\", horizontal: \"left\" },\n overlayIntensity = 70,\n borderRadius = \"xl\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n padding = 8,\n textWidth = \"620px\",\n headerSize = \"xl\",\n headerColor = \"background\",\n textSize = \"md\",\n textColor = \"background\",\n showButton = true,\n buttonColor = \"background\",\n buttonSize = \"default\",\n overlayEnabled = true,\n overlayType = \"gradient\",\n editorialFrame = true,\n frameColor = \"foreground\",\n className,\n ...props\n}: CarouselWidgetProps): React.JSX.Element {\n const totalSlides = slides.length;\n const {\n currentIndex,\n hasSlides,\n isPaused,\n goToNext,\n goToPrevious,\n goToSlide,\n handleMouseEnter,\n handleMouseLeave,\n handleFocus,\n handleBlur,\n } = useCarouselController({\n slideCount: totalSlides,\n enableAutoScroll,\n autoScrollInterval,\n });\n\n const verticalClass =\n align.vertical === \"top\"\n ? \"items-start\"\n : align.vertical === \"center\"\n ? \"items-center\"\n : \"items-end\";\n\n const horizontalClass =\n align.horizontal === \"center\"\n ? \"justify-center text-center mx-auto\"\n : align.horizontal === \"right\"\n ? \"justify-end ml-auto text-right\"\n : \"justify-start text-left\";\n\n // Themed dual-shadow (crisp + soft ambient) on the editorial frame —\n // derived from the foreground token so the lift reads in both light\n // and dark themes.\n const frameShadowStyle: CSSProperties | undefined = editorialFrame\n ? {\n boxShadow: `0 1px 2px color-mix(in oklch, var(--color-foreground) 4%, transparent), 0 30px 60px -30px color-mix(in oklch, var(--color-foreground) 40%, transparent)`,\n }\n : undefined;\n\n const frameBg = editorialFrame ? `bg-${frameColor}` : \"\";\n\n if (!hasSlides) {\n return (\n <div\n className={`relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${frameBg} ${className ?? \"\"}`}\n style={{ minHeight: carouselHeight, ...frameShadowStyle }}\n {...props}\n >\n <div\n className=\"bg-muted/20 flex h-full w-full items-center justify-center\"\n style={{ minHeight: carouselHeight }}\n >\n <div className=\"text-muted-foreground flex flex-col items-center gap-2\">\n <div className=\"text-4xl\">🎠</div>\n <p className=\"text-sm\">No slides added</p>\n <p className=\"text-muted-foreground/70 text-xs\">\n Add slides to create a carousel\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={`relative isolate w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${frameBg} ${className ?? \"\"}`}\n style={{ minHeight: carouselHeight, ...frameShadowStyle }}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onFocus={handleFocus}\n onBlur={handleBlur}\n {...props}\n >\n <div\n className=\"relative w-full\"\n style={{\n minHeight: carouselHeight,\n height: carouselHeight,\n }}\n >\n {slides.map((slide, index) => {\n const isActive = index === currentIndex;\n // Strip the optional \"%\" suffix, then parse. Use Number.isFinite +\n // clamp so an explicit 0 isn't silently replaced by the 70 fallback\n // (the previous `|| 70` treated 0 as falsy).\n const parsedOverlayIntensity = Number(\n String(overlayIntensity).replace(\"%\", \"\"),\n );\n const overlayOpacity =\n (Number.isFinite(parsedOverlayIntensity)\n ? Math.min(100, Math.max(0, parsedOverlayIntensity))\n : 70) / 100;\n\n return (\n <div\n key={slide.id}\n className=\"absolute inset-0 transition-opacity duration-700 ease-out\"\n style={{\n opacity: isActive ? 1 : 0,\n pointerEvents: isActive ? \"auto\" : \"none\",\n }}\n aria-hidden={!isActive}\n >\n <div\n className=\"absolute inset-0 h-full w-full\"\n style={{\n transform: isActive ? \"scale(1)\" : \"scale(1.04)\",\n animation: isActive\n ? \"fluidCarouselKenBurns 900ms ease-out both\"\n : undefined,\n }}\n >\n <MediaRenderer\n {...getMediaPropsFromWidgetSchema(slide.content)}\n />\n </div>\n\n {overlayEnabled && editorialFrame && (\n <>\n <div\n className={`pointer-events-none absolute inset-0 bg-gradient-to-t from-${frameColor} via-${frameColor}/65 to-${frameColor}/10`}\n style={{ opacity: overlayOpacity }}\n />\n <div\n className={`pointer-events-none absolute inset-0 bg-gradient-to-r from-${frameColor}/80 via-transparent to-transparent`}\n style={{ opacity: Math.min(1, overlayOpacity + 0.1) }}\n />\n </>\n )}\n\n {overlayEnabled && !editorialFrame && (\n <div\n className={`pointer-events-none absolute inset-0 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{ opacity: overlayOpacity }}\n />\n )}\n\n <div\n className={`absolute inset-0 flex px-6 sm:px-10 ${verticalClass} ${\n align.horizontal === \"center\"\n ? \"justify-center\"\n : align.horizontal === \"right\"\n ? \"justify-end\"\n : \"justify-start\"\n }`}\n style={{\n paddingTop: padding * 4,\n paddingBottom: padding * 4 + (totalSlides > 1 ? 24 : 0),\n }}\n >\n <div\n key={`content-${currentIndex}`}\n className={`flex w-full flex-col gap-3 ${horizontalClass}`}\n style={{\n maxWidth: textWidth,\n animation: isActive\n ? \"fluidCarouselTextRise 450ms ease-out both\"\n : undefined,\n animationDelay: isActive ? \"120ms\" : undefined,\n }}\n >\n {(slide.eyebrow || slide.tag || slide.meta) && (\n <div\n className={`flex flex-wrap items-center gap-2 ${\n align.horizontal === \"center\"\n ? \"justify-center\"\n : align.horizontal === \"right\"\n ? \"justify-end\"\n : \"justify-start\"\n }`}\n >\n {slide.tag && (\n <span\n className={`rounded-full bg-${slide.tagColor ?? \"background\"} text-${slide.tagColor ?? \"background\"}-foreground px-2.5 py-1 text-[10px] font-bold tracking-[0.14em] uppercase`}\n style={\n slide.tagColor === \"background\" ||\n slide.tagColor === \"foreground\" ||\n !slide.tagColor\n ? tagFallbackStyle(slide.tagColor, frameColor)\n : undefined\n }\n >\n {slide.tag}\n </span>\n )}\n {slide.eyebrow && (\n <span\n className={`text-${headerColor}/70 text-[10px] font-bold tracking-[0.16em] uppercase`}\n >\n {slide.eyebrow}\n </span>\n )}\n {slide.meta && (\n <span\n className={`text-${headerColor}/60 text-[10px] font-bold tracking-[0.16em] uppercase`}\n >\n {slide.meta}\n </span>\n )}\n </div>\n )}\n\n {slide.title && (\n <h2\n className={`text-${headerColor} font-bold ${HEADER_SIZE_MAP[headerSize]} leading-[1.12] tracking-[-0.018em]`}\n >\n {slide.title}\n </h2>\n )}\n\n {slide.description && (\n // Description supports inline HTML for emphasis / line\n // breaks / lists. Sanitized via DOMPurify with the same\n // allowlist as the previous implementation so saved\n // slides containing <strong>, <em>, <br>, <ul>, etc.\n // continue rendering as authored. Element is a <div>\n // (not <p>) to permit block-level allowed tags.\n <div\n className={`text-${textColor}/70 ${BODY_SIZE_MAP[textSize]} leading-[1.55]`}\n dangerouslySetInnerHTML={{\n __html: DOMPurify.sanitize(slide.description, {\n ALLOWED_TAGS: [\n \"br\",\n \"strong\",\n \"em\",\n \"b\",\n \"i\",\n \"ul\",\n \"ol\",\n \"li\",\n \"p\",\n ],\n ALLOWED_ATTR: [],\n }),\n }}\n />\n )}\n\n {(() => {\n const showPrimary =\n slide.buttonEnabled &&\n showButton &&\n Boolean(slide.buttonText) &&\n Boolean(slide.buttonLink);\n const showSecondary =\n Boolean(slide.secondaryButtonText) &&\n Boolean(slide.secondaryButtonLink);\n if (!showPrimary && !showSecondary) return null;\n\n return (\n <div\n className={`mt-3 flex flex-wrap items-center gap-3 ${\n align.horizontal === \"center\"\n ? \"justify-center\"\n : align.horizontal === \"right\"\n ? \"justify-end\"\n : \"justify-start\"\n }`}\n >\n {showPrimary && (\n <a\n href={slide.buttonLink}\n className={`inline-flex items-center gap-1.5 rounded-full bg-${buttonColor} text-${buttonColor}-foreground px-5 py-2.5 text-[13px] font-bold transition-transform hover:scale-[1.02] ${buttonSizeClass(buttonSize)}`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n {slide.buttonText}\n <span aria-hidden=\"true\" className=\"text-[14px]\">\n →\n </span>\n </a>\n )}\n {showSecondary && (\n <a\n href={slide.secondaryButtonLink}\n className={`inline-flex items-center gap-1 text-${headerColor}/80 hover:text-${headerColor} text-[12px] font-bold transition-colors`}\n >\n {slide.secondaryButtonText}\n <span aria-hidden=\"true\">→</span>\n </a>\n )}\n </div>\n );\n })()}\n </div>\n </div>\n </div>\n );\n })}\n\n {totalSlides > 1 && (\n <div className=\"pointer-events-none absolute inset-0 z-20\">\n <div className=\"pointer-events-auto absolute top-6 right-6 flex items-center gap-1.5\">\n <button\n type=\"button\"\n onClick={goToPrevious}\n aria-label=\"Previous slide\"\n className={`flex size-10 items-center justify-center rounded-full bg-${headerColor}/10 text-${headerColor} ring-1 ring-${headerColor}/15 backdrop-blur-sm transition-colors hover:bg-${headerColor}/20`}\n >\n <ChevronLeftIcon />\n </button>\n <button\n type=\"button\"\n onClick={goToNext}\n aria-label=\"Next slide\"\n className={`flex size-10 items-center justify-center rounded-full bg-${headerColor} text-${headerColor}-foreground transition-transform hover:scale-[1.04]`}\n style={{\n // Themed lift shadow (was hardcoded white) so the active\n // nav button reads on both light and dark frames.\n boxShadow: `0 4px 14px -4px color-mix(in oklch, var(--color-${headerColor}) 45%, transparent)`,\n ...nextButtonFallbackStyle(headerColor, frameColor),\n }}\n >\n <ChevronRightIcon />\n </button>\n </div>\n\n <div className=\"pointer-events-auto absolute inset-x-0 bottom-0 flex items-center gap-1 px-6 pb-2 sm:px-10\">\n {slides.map((_, i) => {\n const state =\n i < currentIndex\n ? \"done\"\n : i === currentIndex\n ? \"active\"\n : \"upcoming\";\n return (\n <button\n key={`progress-${i}`}\n type=\"button\"\n onClick={() => goToSlide(i)}\n aria-label={`Go to slide ${i + 1}`}\n aria-current={state === \"active\" ? \"true\" : \"false\"}\n className=\"group flex-1 py-2\"\n >\n <span\n className={`block h-[2px] w-full overflow-hidden rounded-full bg-${headerColor}/20`}\n >\n <span\n key={`fill-${i}-${currentIndex}`}\n className={`block h-full rounded-full bg-${headerColor}`}\n style={progressFillStyle(\n state,\n enableAutoScroll,\n autoScrollInterval,\n isPaused,\n )}\n />\n </span>\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction progressFillStyle(\n state: \"done\" | \"active\" | \"upcoming\",\n autoScroll: boolean,\n duration: number,\n paused: boolean,\n): CSSProperties {\n if (state === \"done\") return { width: \"100%\" };\n if (state === \"upcoming\") return { width: \"0%\" };\n if (autoScroll) {\n return {\n width: \"0%\",\n animation: `fluidCarouselProgressFill ${duration}ms linear forwards`,\n animationPlayState: paused ? \"paused\" : \"running\",\n };\n }\n return { width: \"100%\" };\n}\n\nfunction tagFallbackStyle(\n tagColor: ColorOptions | undefined,\n frameColor: ColorOptions,\n): CSSProperties | undefined {\n // bg-background/foreground don't emit -foreground utilities by default;\n // fall back to contrast-safe inline colors so tag chips always read.\n if (!tagColor || tagColor === \"background\") {\n return { color: `var(--color-${frameColor})` };\n }\n if (tagColor === \"foreground\") {\n return { color: `var(--color-background)` };\n }\n return undefined;\n}\n\nfunction nextButtonFallbackStyle(\n headerColor: ColorOptions,\n frameColor: ColorOptions,\n): CSSProperties | undefined {\n // Same contrast fix as tags — ensure icon color reads on the active button.\n if (headerColor === \"background\") {\n return { color: `var(--color-${frameColor})` };\n }\n if (headerColor === \"foreground\") {\n return { color: `var(--color-background)` };\n }\n return undefined;\n}\n\nfunction buttonSizeClass(size: ButtonSizeOptions): string {\n if (size === \"sm\") return \"px-4 py-1.5 text-[12px]\";\n if (size === \"lg\") return \"px-6 py-3 text-[14px]\";\n if (size === \"xl\") return \"px-7 py-3.5 text-[15px]\";\n return \"\";\n}\n\nfunction ChevronLeftIcon() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n );\n}\n\nfunction ChevronRightIcon() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n );\n}\n\nexport const carouselWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CarouselWidget\",\n displayName: \"Carousel\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"behavior\", label: \"Behavior\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"slides\"],\n fields: [\n // Styling tab — Frame group (new)\n {\n key: \"editorialFrame\",\n label: \"Editorial Frame\",\n type: \"boolean\",\n description:\n \"Premium dark canvas with layered shadow and gradient stack. Turn off for a classic transparent carousel.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Frame\",\n },\n getColorField({\n defaultValue: \"foreground\",\n key: \"frameColor\",\n label: \"Frame Color\",\n description:\n \"Surface color of the carousel canvas. Drives the frame and gradient overlay.\",\n tab: \"styling\",\n group: \"Frame\",\n requiresKeyToBeTrue: \"editorialFrame\",\n }),\n\n // Text Styling group\n getFontSizeField({\n defaultValue: \"xl\",\n key: \"headerSize\",\n label: \"Header Font Size\",\n description: \"Font size for the slide header\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"headerColor\",\n label: \"Header Color\",\n description:\n \"Headline color. Also drives eyebrow, controls and progress bar.\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Text Styling\",\n },\n getFontSizeField({\n defaultValue: \"md\",\n key: \"textSize\",\n label: \"Text Font Size\",\n description: \"Font size for the slide text\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Color variant for the slide text\",\n tab: \"styling\",\n group: \"Text Styling\",\n }),\n\n // Layout group\n {\n key: \"align\",\n label: \"Alignment\",\n type: \"alignment\",\n description: \"Alignment of the carousel content\",\n defaultValue: { vertical: \"bottom\", horizontal: \"left\" },\n options: {\n verticalEnabled: true,\n horizontalEnabled: true,\n },\n tab: \"styling\",\n group: \"Layout\",\n },\n {\n key: \"textWidth\",\n label: \"Content Width\",\n type: \"cssUnit\",\n description: \"Maximum width for slide content\",\n defaultValue: \"620px\",\n allowedUnits: [\"px\", \"rem\", \"%\"],\n defaultUnit: \"px\",\n minByUnit: { px: 50, rem: 3, \"%\": 10 },\n maxByUnit: { px: 1200, rem: 75, \"%\": 100 },\n stepByUnit: { px: 10, rem: 1, \"%\": 1 },\n tab: \"styling\",\n group: \"Layout\",\n },\n\n // Design group\n getHeightField({\n key: \"carouselHeight\",\n label: \"Carousel Height\",\n description: \"Height of the carousel\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator2\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getBorderRadiusField({\n defaultValue: \"xl\",\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Rounded corners for the carousel\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the carousel container\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the carousel container\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getPaddingField({\n defaultValue: 8,\n key: \"padding\",\n label: \"Padding\",\n description: \"Inner padding around slide content\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add background overlay to slide content\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Overlay style (only applies when editorial frame is off)\",\n defaultValue: \"gradient\",\n options: [\n { label: \"Solid\", value: \"solid\" },\n { label: \"Gradient\", value: \"gradient\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 70,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"showButton\",\n label: \"Show Primary Button\",\n type: \"boolean\",\n description: \"Display the primary CTA in slide content\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n defaultValue: \"background\",\n key: \"buttonColor\",\n label: \"Button Color\",\n description: \"Color variant for the slide button\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"showButton\",\n }),\n getButtonSizeField({\n defaultValue: \"default\",\n key: \"buttonSize\",\n label: \"Button Size\",\n description: \"Size of the slide button\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"showButton\",\n }),\n\n // Behavior tab\n {\n key: \"enableAutoScroll\",\n label: \"Enable Auto-Scroll\",\n type: \"boolean\",\n description:\n \"Automatically advance to the next slide. Progress bar fills at this rate and pauses on hover.\",\n defaultValue: false,\n tab: \"behavior\",\n group: \"Auto-Scroll\",\n },\n {\n key: \"autoScrollInterval\",\n label: \"Auto-Scroll Interval (ms)\",\n type: \"number\",\n description: \"Time between automatic slide transitions\",\n min: 1000,\n max: 15000,\n step: 500,\n defaultValue: 6500,\n tab: \"behavior\",\n group: \"Auto-Scroll\",\n requiresKeyToBeTrue: \"enableAutoScroll\",\n },\n\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n itemConfigSchema: {\n description: \"Configure settings for this slide\",\n fields: [\n {\n key: \"eyebrow\",\n label: \"Eyebrow\",\n type: \"text\",\n description:\n \"Short label above the title (e.g. 'From Fluid · Newsroom')\",\n },\n {\n key: \"tag\",\n label: \"Tag / Category\",\n type: \"text\",\n description: \"Short pill label (e.g. 'Policy', 'New release')\",\n },\n {\n key: \"tagColor\",\n label: \"Tag Color\",\n type: \"colorSelect\",\n description: \"Background color of the tag pill\",\n defaultValue: \"background\",\n },\n {\n key: \"meta\",\n label: \"Meta\",\n type: \"text\",\n description: \"Meta line (e.g. 'Apr 12 · 4 min read')\",\n },\n {\n key: \"separator_slide_1\",\n type: \"separator\",\n label: \"Separator\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Override the item's title for this slide\",\n },\n {\n key: \"description\",\n label: \"Description\",\n type: \"textarea\",\n description: \"Override the item's description for this slide\",\n rows: 3,\n },\n {\n key: \"separator_slide_2\",\n type: \"separator\",\n label: \"Separator\",\n },\n {\n key: \"buttonEnabled\",\n label: \"Show Primary Button\",\n type: \"boolean\",\n description: \"Show the primary CTA on this slide\",\n defaultValue: false,\n },\n {\n key: \"buttonText\",\n label: \"Button Text\",\n type: \"text\",\n description: \"Text for the primary button\",\n requiresKeyToBeTrue: \"buttonEnabled\",\n },\n {\n key: \"buttonLink\",\n label: \"Button Link\",\n type: \"text\",\n description: \"URL for the primary button\",\n requiresKeyToBeTrue: \"buttonEnabled\",\n },\n {\n key: \"secondaryButtonText\",\n label: \"Secondary Link Text\",\n type: \"text\",\n description:\n \"Optional text-only secondary link (renders with an arrow)\",\n },\n {\n key: \"secondaryButtonLink\",\n label: \"Secondary Link URL\",\n type: \"text\",\n description: \"URL for the secondary link\",\n },\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAY,OAAO;IAAY,CACzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACF,mBAAmB;GACjB,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CACD,kBAAkB;EAChB,aAAa;EACb,QAAQ;GACN;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aACE;IACH;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,cAAc;IACf;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,MAAM;IACN,OAAO;IACR;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,MAAM;IACP;GACD;IACE,KAAK;IACL,MAAM;IACN,OAAO;IACR;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,cAAc;IACf;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,qBAAqB;IACtB;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,qBAAqB;IACtB;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aACE;IACH;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACF;EACF;CACF"}
|