@fluid-app/portal-sdk 0.1.82 → 0.1.83
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/{AppDownloadScreen-3DHcVSP9.cjs → AppDownloadScreen-B-JdFulZ.cjs} +3 -3
- package/dist/{AppDownloadScreen-BZ8IA_i0.mjs → AppDownloadScreen-BE6M8WxN.mjs} +2 -2
- package/dist/{AppDownloadScreen-BZ8IA_i0.mjs.map → AppDownloadScreen-BE6M8WxN.mjs.map} +1 -1
- package/dist/{AppDownloadScreen-BDnZv0Ve.cjs → AppDownloadScreen-CaTNCtzb.cjs} +2 -2
- package/dist/{AppDownloadScreen-BDnZv0Ve.cjs.map → AppDownloadScreen-CaTNCtzb.cjs.map} +1 -1
- package/dist/{ContactsScreen-BF2txIn2.cjs → ContactsScreen-6gXKTN61.cjs} +2 -2
- package/dist/{ContactsScreen-BF2txIn2.cjs.map → ContactsScreen-6gXKTN61.cjs.map} +1 -1
- package/dist/{ContactsScreen-w2w-l_0b.mjs → ContactsScreen-FJUtn2_G.mjs} +2 -2
- package/dist/{ContactsScreen-w2w-l_0b.mjs.map → ContactsScreen-FJUtn2_G.mjs.map} +1 -1
- package/dist/{ContactsScreen-Cphil7Lf.cjs → ContactsScreen-aPH9Xaim.cjs} +3 -3
- package/dist/{FluidProvider-BeQDNd2R.cjs → FluidProvider-BSBLJp15.cjs} +3 -3
- package/dist/{FluidProvider-BeQDNd2R.cjs.map → FluidProvider-BSBLJp15.cjs.map} +1 -1
- package/dist/{FluidProvider-aDOk1vw3.mjs → FluidProvider-CwkMUOoy.mjs} +3 -3
- package/dist/{FluidProvider-aDOk1vw3.mjs.map → FluidProvider-CwkMUOoy.mjs.map} +1 -1
- package/dist/{MessagingScreen-B3_sZuUW.mjs → MessagingScreen-7_YhiLVY.mjs} +3 -3
- package/dist/{MessagingScreen-B3_sZuUW.mjs.map → MessagingScreen-7_YhiLVY.mjs.map} +1 -1
- package/dist/{MessagingScreen-DzwIbgUU.cjs → MessagingScreen-B_5Ci5s-.cjs} +3 -3
- package/dist/{MessagingScreen-DzwIbgUU.cjs.map → MessagingScreen-B_5Ci5s-.cjs.map} +1 -1
- package/dist/{MessagingScreen-yHZm0vFM.cjs → MessagingScreen-CWJA4usG.cjs} +3 -3
- package/dist/{MessagingScreen-CnBpPXBm.mjs → MessagingScreen-DWNe8VFM.mjs} +3 -3
- package/dist/{MySiteScreen-DJ-rkDlD.mjs → MySiteScreen-Cspeq0cy.mjs} +2 -2
- package/dist/{MySiteScreen-DJ-rkDlD.mjs.map → MySiteScreen-Cspeq0cy.mjs.map} +1 -1
- package/dist/{MySiteScreen-DkHGVOlx.cjs → MySiteScreen-CtVL7wfc.cjs} +2 -2
- package/dist/{MySiteScreen-DkHGVOlx.cjs.map → MySiteScreen-CtVL7wfc.cjs.map} +1 -1
- package/dist/{MySiteScreen-BwdayTZT.cjs → MySiteScreen-D5tr7TdT.cjs} +3 -3
- package/dist/{OrdersScreen-C_fTfG0m.cjs → OrdersScreen-Bu82RCok.cjs} +3 -3
- package/dist/{OrdersScreen-C_fTfG0m.cjs.map → OrdersScreen-Bu82RCok.cjs.map} +1 -1
- package/dist/{OrdersScreen-DipdGDcy.cjs → OrdersScreen-DiKPQvwJ.cjs} +3 -3
- package/dist/{OrdersScreen-C0dg1NEJ.mjs → OrdersScreen-DrCPl7uv.mjs} +3 -3
- package/dist/{OrdersScreen-C0dg1NEJ.mjs.map → OrdersScreen-DrCPl7uv.mjs.map} +1 -1
- package/dist/{PointsWidget-Cc88UHqD.mjs → PointsWidget-CYesuDDG.mjs} +3 -3
- package/dist/PointsWidget-CYesuDDG.mjs.map +1 -0
- package/dist/{PointsWidget-DISBtuAm.cjs → PointsWidget-D8U2k-_A.cjs} +3 -3
- package/dist/PointsWidget-D8U2k-_A.cjs.map +1 -0
- package/dist/{ProductsScreen-B2_8nFMd.mjs → ProductsScreen-BHHo6Wen.mjs} +3 -3
- package/dist/{ProductsScreen-B2_8nFMd.mjs.map → ProductsScreen-BHHo6Wen.mjs.map} +1 -1
- package/dist/{ProductsScreen-DHgkH0rd.cjs → ProductsScreen-CCNyLHqR.cjs} +3 -3
- package/dist/{ProductsScreen-BjCjYPiq.mjs → ProductsScreen-CoyGeILD.mjs} +3 -3
- package/dist/{ProductsScreen-D7ag_21-.cjs → ProductsScreen-Doc9tmAQ.cjs} +3 -3
- package/dist/{ProductsScreen-D7ag_21-.cjs.map → ProductsScreen-Doc9tmAQ.cjs.map} +1 -1
- package/dist/{ProfileScreen-DhS4QlAJ.cjs → ProfileScreen-BKKIMZiD.cjs} +3 -3
- package/dist/{ProfileScreen-DHZDYTid.mjs → ProfileScreen-C4g7ZGPo.mjs} +3 -3
- package/dist/{ProfileScreen-DHZDYTid.mjs.map → ProfileScreen-C4g7ZGPo.mjs.map} +1 -1
- package/dist/{ProfileScreen-B8XYP1GA.cjs → ProfileScreen-CANmoFsP.cjs} +3 -3
- package/dist/{ProfileScreen-B8XYP1GA.cjs.map → ProfileScreen-CANmoFsP.cjs.map} +1 -1
- package/dist/{ShareablesScreen-3a7V8ZEB.mjs → ShareablesScreen-BRxLz3zn.mjs} +3 -3
- package/dist/{ShareablesScreen-BtZfpC1v.cjs → ShareablesScreen-C5GJg1EP.cjs} +3 -3
- package/dist/{ShareablesScreen-DBSG5bbX.mjs → ShareablesScreen-CNMWSoKY.mjs} +3 -3
- package/dist/{ShareablesScreen-DBSG5bbX.mjs.map → ShareablesScreen-CNMWSoKY.mjs.map} +1 -1
- package/dist/{ShareablesScreen-DDcnZnRA.cjs → ShareablesScreen-Dp3BcjuA.cjs} +3 -3
- package/dist/{ShareablesScreen-DDcnZnRA.cjs.map → ShareablesScreen-Dp3BcjuA.cjs.map} +1 -1
- package/dist/{ShopScreen-BiFPqcSn.cjs → ShopScreen-CPWZhKgE.cjs} +4 -4
- package/dist/{ShopScreen-BiFPqcSn.cjs.map → ShopScreen-CPWZhKgE.cjs.map} +1 -1
- package/dist/{ShopScreen-5DkzkCmK.mjs → ShopScreen-CVxmqfmN.mjs} +4 -4
- package/dist/{ShopScreen-5DkzkCmK.mjs.map → ShopScreen-CVxmqfmN.mjs.map} +1 -1
- package/dist/{ShopScreen-CK5hcRSz.cjs → ShopScreen-nJhut901.cjs} +3 -3
- package/dist/{SubscriptionsScreen-iSqfV2RZ.cjs → SubscriptionsScreen-C1UWxvQk.cjs} +3 -3
- package/dist/{SubscriptionsScreen-CRJjvX47.mjs → SubscriptionsScreen-CJdcyH-e.mjs} +3 -3
- package/dist/{SubscriptionsScreen-CRJjvX47.mjs.map → SubscriptionsScreen-CJdcyH-e.mjs.map} +1 -1
- package/dist/{SubscriptionsScreen-BM4Tk_vo.cjs → SubscriptionsScreen-CSKVsakI.cjs} +3 -3
- package/dist/{SubscriptionsScreen-BM4Tk_vo.cjs.map → SubscriptionsScreen-CSKVsakI.cjs.map} +1 -1
- package/dist/index.cjs +311 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +311 -37
- package/dist/index.mjs.map +1 -1
- package/dist/{use-account-clients-DJVDMbzf.cjs → use-account-clients-62dZrh9E.cjs} +2 -2
- package/dist/{use-account-clients-DJVDMbzf.cjs.map → use-account-clients-62dZrh9E.cjs.map} +1 -1
- package/dist/{use-account-clients-D3YbXh9Y.mjs → use-account-clients-Cf_6sxeC.mjs} +2 -2
- package/dist/{use-account-clients-D3YbXh9Y.mjs.map → use-account-clients-Cf_6sxeC.mjs.map} +1 -1
- package/dist/{use-current-user-DIkhY-Or.mjs → use-current-user-Bl9nPNFt.mjs} +3 -3
- package/dist/{use-current-user-DIkhY-Or.mjs.map → use-current-user-Bl9nPNFt.mjs.map} +1 -1
- package/dist/{use-current-user-B_BV-XL3.cjs → use-current-user-SFCzJt0q.cjs} +3 -3
- package/dist/{use-current-user-B_BV-XL3.cjs.map → use-current-user-SFCzJt0q.cjs.map} +1 -1
- package/dist/{use-customer-account-Bh4RXGq-.mjs → use-customer-account-B0DeL6m0.mjs} +3 -3
- package/dist/{use-customer-account-Bh4RXGq-.mjs.map → use-customer-account-B0DeL6m0.mjs.map} +1 -1
- package/dist/{use-customer-account-D3WQH1de.cjs → use-customer-account-Dysq4hpT.cjs} +3 -3
- package/dist/{use-customer-account-D3WQH1de.cjs.map → use-customer-account-Dysq4hpT.cjs.map} +1 -1
- package/dist/{use-fluid-api-DDS0EZdY.mjs → use-fluid-api-DPhr-9Jv.mjs} +2 -2
- package/dist/{use-fluid-api-DDS0EZdY.mjs.map → use-fluid-api-DPhr-9Jv.mjs.map} +1 -1
- package/dist/{use-fluid-api-BL1IJowk.cjs → use-fluid-api-DwRQk00z.cjs} +2 -2
- package/dist/{use-fluid-api-BL1IJowk.cjs.map → use-fluid-api-DwRQk00z.cjs.map} +1 -1
- package/package.json +14 -14
- package/dist/PointsWidget-Cc88UHqD.mjs.map +0 -1
- package/dist/PointsWidget-DISBtuAm.cjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
const require_FluidProvider = require("./FluidProvider-
|
|
2
|
+
const require_FluidProvider = require("./FluidProvider-BSBLJp15.cjs");
|
|
3
3
|
let react = require("react");
|
|
4
4
|
//#region src/hooks/use-fluid-auth.ts
|
|
5
5
|
/**
|
|
@@ -151,4 +151,4 @@ Object.defineProperty(exports, "useSubscriptionsClient", {
|
|
|
151
151
|
}
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
-
//# sourceMappingURL=use-account-clients-
|
|
154
|
+
//# sourceMappingURL=use-account-clients-62dZrh9E.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-account-clients-
|
|
1
|
+
{"version":3,"file":"use-account-clients-62dZrh9E.cjs","names":["useFluidAuthContext","useFluidContext","createOrdersFetchClient","createSubscriptionsFetchClient","createFluidPayFetchClient","createCoreFetchClient"],"sources":["../src/hooks/use-fluid-auth.ts","../src/account/use-account-clients.ts"],"sourcesContent":["/**\n * useFluidAuth Hook\n *\n * Provides access to authentication state and utilities.\n * This is the primary hook for interacting with auth in components.\n */\n\nimport { useFluidAuthContext } from \"../providers/FluidAuthProvider\";\nimport type { FluidAuthContextValue } from \"../auth/types\";\n\n/**\n * Hook to access authentication state and utilities.\n *\n * Must be used within a `FluidAuthProvider`.\n *\n * @returns Authentication context with user info, loading state, and utilities\n * @throws Error if used outside FluidAuthProvider\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const { isAuthenticated, isLoading, user, clearAuth } = useFluidAuth();\n *\n * if (isLoading) {\n * return <Spinner />;\n * }\n *\n * if (!isAuthenticated) {\n * return <p>Please log in</p>;\n * }\n *\n * return (\n * <div>\n * <p>Welcome, {user.full_name}!</p>\n * <button onClick={clearAuth}>Log out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useFluidAuth(): FluidAuthContextValue {\n return useFluidAuthContext();\n}\n","import { useMemo } from \"react\";\nimport {\n createFetchClient as createOrdersFetchClient,\n type FetchClient as OrdersFetchClient,\n} from \"@fluid-app/orders-api-client\";\nimport {\n createFetchClient as createSubscriptionsFetchClient,\n type FetchClient as SubscriptionsFetchClient,\n} from \"@fluid-app/subscriptions-api-client\";\nimport {\n createFetchClient as createFluidPayFetchClient,\n type FetchClient as FluidPayFetchClient,\n} from \"@fluid-app/fluid-pay-api-client\";\nimport {\n createFetchClient as createCoreFetchClient,\n type FetchClient as CoreFetchClient,\n} from \"@fluid-app/api-client-core\";\nimport { useFluidContext } from \"../providers/FluidProvider\";\nimport { useFluidAuth } from \"../hooks/use-fluid-auth\";\n\n/** API version prefix for versioned endpoints (e.g. points ledger) */\nexport const API_VERSION = \"/v202506\";\n\n/**\n * Ensures baseUrl ends with /api.\n * Domain-specific API clients (orders, subscriptions, fluid-pay) use endpoint\n * paths without /api (e.g. /fluid_pay/me, /subscriptions), matching fluid-admin's\n * NEXT_PUBLIC_API_URL convention. The portal SDK's config.baseUrl is the domain\n * root (e.g. https://api.fluid.app), so we append /api here.\n */\nfunction withApiPrefix(baseUrl: string): string {\n const base = baseUrl.replace(/\\/+$/, \"\");\n return base.endsWith(\"/api\") ? base : `${base}/api`;\n}\n\nexport function useOrdersClient(): OrdersFetchClient {\n const { config } = useFluidContext();\n const { token } = useFluidAuth();\n\n return useMemo(\n () =>\n createOrdersFetchClient({\n baseUrl: withApiPrefix(config.baseUrl),\n getAuthToken: () => token,\n onAuthError: config.onAuthError,\n }),\n [config.baseUrl, config.onAuthError, token],\n );\n}\n\nexport function useSubscriptionsClient(): SubscriptionsFetchClient {\n const { config } = useFluidContext();\n const { token } = useFluidAuth();\n\n return useMemo(\n () =>\n createSubscriptionsFetchClient({\n baseUrl: withApiPrefix(config.baseUrl),\n getAuthToken: () => token,\n onAuthError: config.onAuthError,\n }),\n [config.baseUrl, config.onAuthError, token],\n );\n}\n\nexport function useFluidPayClient(): FluidPayFetchClient {\n const { config } = useFluidContext();\n const { token } = useFluidAuth();\n\n return useMemo(\n () =>\n createFluidPayFetchClient({\n baseUrl: withApiPrefix(config.baseUrl),\n getAuthToken: () => token,\n onAuthError: config.onAuthError,\n }),\n [config.baseUrl, config.onAuthError, token],\n );\n}\n\n/**\n * Generic SDK fetch client for endpoints not covered by domain-specific clients\n * (e.g. /countries, /v202506/customers/:id/points_ledgers).\n * Uses the same auth/baseUrl/error handling as the domain clients.\n */\nexport function useSdkClient(): CoreFetchClient {\n const { config } = useFluidContext();\n const { token } = useFluidAuth();\n\n return useMemo(\n () =>\n createCoreFetchClient({\n baseUrl: withApiPrefix(config.baseUrl),\n getAuthToken: () => token,\n onAuthError: config.onAuthError,\n }),\n [config.baseUrl, config.onAuthError, token],\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,eAAsC;AACpD,QAAOA,sBAAAA,qBAAqB;;;;;ACpB9B,MAAa,cAAc;;;;;;;;AAS3B,SAAS,cAAc,SAAyB;CAC9C,MAAM,OAAO,QAAQ,QAAQ,QAAQ,GAAG;AACxC,QAAO,KAAK,SAAS,OAAO,GAAG,OAAO,GAAG,KAAK;;AAGhD,SAAgB,kBAAqC;CACnD,MAAM,EAAE,WAAWC,sBAAAA,iBAAiB;CACpC,MAAM,EAAE,UAAU,cAAc;AAEhC,SAAA,GAAA,MAAA,eAEIC,sBAAAA,kBAAwB;EACtB,SAAS,cAAc,OAAO,QAAQ;EACtC,oBAAoB;EACpB,aAAa,OAAO;EACrB,CAAC,EACJ;EAAC,OAAO;EAAS,OAAO;EAAa;EAAM,CAC5C;;AAGH,SAAgB,yBAAmD;CACjE,MAAM,EAAE,WAAWD,sBAAAA,iBAAiB;CACpC,MAAM,EAAE,UAAU,cAAc;AAEhC,SAAA,GAAA,MAAA,eAEIE,sBAAAA,kBAA+B;EAC7B,SAAS,cAAc,OAAO,QAAQ;EACtC,oBAAoB;EACpB,aAAa,OAAO;EACrB,CAAC,EACJ;EAAC,OAAO;EAAS,OAAO;EAAa;EAAM,CAC5C;;AAGH,SAAgB,oBAAyC;CACvD,MAAM,EAAE,WAAWF,sBAAAA,iBAAiB;CACpC,MAAM,EAAE,UAAU,cAAc;AAEhC,SAAA,GAAA,MAAA,eAEIG,sBAAAA,kBAA0B;EACxB,SAAS,cAAc,OAAO,QAAQ;EACtC,oBAAoB;EACpB,aAAa,OAAO;EACrB,CAAC,EACJ;EAAC,OAAO;EAAS,OAAO;EAAa;EAAM,CAC5C;;;;;;;AAQH,SAAgB,eAAgC;CAC9C,MAAM,EAAE,WAAWH,sBAAAA,iBAAiB;CACpC,MAAM,EAAE,UAAU,cAAc;AAEhC,SAAA,GAAA,MAAA,eAEII,sBAAAA,kBAAsB;EACpB,SAAS,cAAc,OAAO,QAAQ;EACtC,oBAAoB;EACpB,aAAa,OAAO;EACrB,CAAC,EACJ;EAAC,OAAO;EAAS,OAAO;EAAa;EAAM,CAC5C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bt as createFetchClient, l as useFluidAuthContext, n as useFluidContext } from "./FluidProvider-
|
|
1
|
+
import { bt as createFetchClient, l as useFluidAuthContext, n as useFluidContext } from "./FluidProvider-CwkMUOoy.mjs";
|
|
2
2
|
import { useMemo } from "react";
|
|
3
3
|
//#region src/hooks/use-fluid-auth.ts
|
|
4
4
|
/**
|
|
@@ -115,4 +115,4 @@ function useSdkClient() {
|
|
|
115
115
|
//#endregion
|
|
116
116
|
export { useSubscriptionsClient as a, useSdkClient as i, useFluidPayClient as n, useFluidAuth as o, useOrdersClient as r, API_VERSION as t };
|
|
117
117
|
|
|
118
|
-
//# sourceMappingURL=use-account-clients-
|
|
118
|
+
//# sourceMappingURL=use-account-clients-Cf_6sxeC.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-account-clients-
|
|
1
|
+
{"version":3,"file":"use-account-clients-Cf_6sxeC.mjs","names":["createOrdersFetchClient","createSubscriptionsFetchClient","createFluidPayFetchClient","createCoreFetchClient"],"sources":["../src/hooks/use-fluid-auth.ts","../src/account/use-account-clients.ts"],"sourcesContent":["/**\n * useFluidAuth Hook\n *\n * Provides access to authentication state and utilities.\n * This is the primary hook for interacting with auth in components.\n */\n\nimport { useFluidAuthContext } from \"../providers/FluidAuthProvider\";\nimport type { FluidAuthContextValue } from \"../auth/types\";\n\n/**\n * Hook to access authentication state and utilities.\n *\n * Must be used within a `FluidAuthProvider`.\n *\n * @returns Authentication context with user info, loading state, and utilities\n * @throws Error if used outside FluidAuthProvider\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const { isAuthenticated, isLoading, user, clearAuth } = useFluidAuth();\n *\n * if (isLoading) {\n * return <Spinner />;\n * }\n *\n * if (!isAuthenticated) {\n * return <p>Please log in</p>;\n * }\n *\n * return (\n * <div>\n * <p>Welcome, {user.full_name}!</p>\n * <button onClick={clearAuth}>Log out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useFluidAuth(): FluidAuthContextValue {\n return useFluidAuthContext();\n}\n","import { useMemo } from \"react\";\nimport {\n createFetchClient as createOrdersFetchClient,\n type FetchClient as OrdersFetchClient,\n} from \"@fluid-app/orders-api-client\";\nimport {\n createFetchClient as createSubscriptionsFetchClient,\n type FetchClient as SubscriptionsFetchClient,\n} from \"@fluid-app/subscriptions-api-client\";\nimport {\n createFetchClient as createFluidPayFetchClient,\n type FetchClient as FluidPayFetchClient,\n} from \"@fluid-app/fluid-pay-api-client\";\nimport {\n createFetchClient as createCoreFetchClient,\n type FetchClient as CoreFetchClient,\n} from \"@fluid-app/api-client-core\";\nimport { useFluidContext } from \"../providers/FluidProvider\";\nimport { useFluidAuth } from \"../hooks/use-fluid-auth\";\n\n/** API version prefix for versioned endpoints (e.g. points ledger) */\nexport const API_VERSION = \"/v202506\";\n\n/**\n * Ensures baseUrl ends with /api.\n * Domain-specific API clients (orders, subscriptions, fluid-pay) use endpoint\n * paths without /api (e.g. /fluid_pay/me, /subscriptions), matching fluid-admin's\n * NEXT_PUBLIC_API_URL convention. The portal SDK's config.baseUrl is the domain\n * root (e.g. https://api.fluid.app), so we append /api here.\n */\nfunction withApiPrefix(baseUrl: string): string {\n const base = baseUrl.replace(/\\/+$/, \"\");\n return base.endsWith(\"/api\") ? base : `${base}/api`;\n}\n\nexport function useOrdersClient(): OrdersFetchClient {\n const { config } = useFluidContext();\n const { token } = useFluidAuth();\n\n return useMemo(\n () =>\n createOrdersFetchClient({\n baseUrl: withApiPrefix(config.baseUrl),\n getAuthToken: () => token,\n onAuthError: config.onAuthError,\n }),\n [config.baseUrl, config.onAuthError, token],\n );\n}\n\nexport function useSubscriptionsClient(): SubscriptionsFetchClient {\n const { config } = useFluidContext();\n const { token } = useFluidAuth();\n\n return useMemo(\n () =>\n createSubscriptionsFetchClient({\n baseUrl: withApiPrefix(config.baseUrl),\n getAuthToken: () => token,\n onAuthError: config.onAuthError,\n }),\n [config.baseUrl, config.onAuthError, token],\n );\n}\n\nexport function useFluidPayClient(): FluidPayFetchClient {\n const { config } = useFluidContext();\n const { token } = useFluidAuth();\n\n return useMemo(\n () =>\n createFluidPayFetchClient({\n baseUrl: withApiPrefix(config.baseUrl),\n getAuthToken: () => token,\n onAuthError: config.onAuthError,\n }),\n [config.baseUrl, config.onAuthError, token],\n );\n}\n\n/**\n * Generic SDK fetch client for endpoints not covered by domain-specific clients\n * (e.g. /countries, /v202506/customers/:id/points_ledgers).\n * Uses the same auth/baseUrl/error handling as the domain clients.\n */\nexport function useSdkClient(): CoreFetchClient {\n const { config } = useFluidContext();\n const { token } = useFluidAuth();\n\n return useMemo(\n () =>\n createCoreFetchClient({\n baseUrl: withApiPrefix(config.baseUrl),\n getAuthToken: () => token,\n onAuthError: config.onAuthError,\n }),\n [config.baseUrl, config.onAuthError, token],\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,eAAsC;AACpD,QAAO,qBAAqB;;;;;ACpB9B,MAAa,cAAc;;;;;;;;AAS3B,SAAS,cAAc,SAAyB;CAC9C,MAAM,OAAO,QAAQ,QAAQ,QAAQ,GAAG;AACxC,QAAO,KAAK,SAAS,OAAO,GAAG,OAAO,GAAG,KAAK;;AAGhD,SAAgB,kBAAqC;CACnD,MAAM,EAAE,WAAW,iBAAiB;CACpC,MAAM,EAAE,UAAU,cAAc;AAEhC,QAAO,cAEHA,kBAAwB;EACtB,SAAS,cAAc,OAAO,QAAQ;EACtC,oBAAoB;EACpB,aAAa,OAAO;EACrB,CAAC,EACJ;EAAC,OAAO;EAAS,OAAO;EAAa;EAAM,CAC5C;;AAGH,SAAgB,yBAAmD;CACjE,MAAM,EAAE,WAAW,iBAAiB;CACpC,MAAM,EAAE,UAAU,cAAc;AAEhC,QAAO,cAEHC,kBAA+B;EAC7B,SAAS,cAAc,OAAO,QAAQ;EACtC,oBAAoB;EACpB,aAAa,OAAO;EACrB,CAAC,EACJ;EAAC,OAAO;EAAS,OAAO;EAAa;EAAM,CAC5C;;AAGH,SAAgB,oBAAyC;CACvD,MAAM,EAAE,WAAW,iBAAiB;CACpC,MAAM,EAAE,UAAU,cAAc;AAEhC,QAAO,cAEHC,kBAA0B;EACxB,SAAS,cAAc,OAAO,QAAQ;EACtC,oBAAoB;EACpB,aAAa,OAAO;EACrB,CAAC,EACJ;EAAC,OAAO;EAAS,OAAO;EAAa;EAAM,CAC5C;;;;;;;AAQH,SAAgB,eAAgC;CAC9C,MAAM,EAAE,WAAW,iBAAiB;CACpC,MAAM,EAAE,UAAU,cAAc;AAEhC,QAAO,cAEHC,kBAAsB;EACpB,SAAS,cAAc,OAAO,QAAQ;EACtC,oBAAoB;EACpB,aAAa,OAAO;EACrB,CAAC,EACJ;EAAC,OAAO;EAAS,OAAO;EAAa;EAAM,CAC5C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as useFluidAuthContext } from "./FluidProvider-
|
|
2
|
-
import { t as useFluidApi } from "./use-fluid-api-
|
|
1
|
+
import { l as useFluidAuthContext } from "./FluidProvider-CwkMUOoy.mjs";
|
|
2
|
+
import { t as useFluidApi } from "./use-fluid-api-DPhr-9Jv.mjs";
|
|
3
3
|
import { useCallback, useRef } from "react";
|
|
4
4
|
import { useQuery } from "@tanstack/react-query";
|
|
5
5
|
//#region src/hooks/query-keys.ts
|
|
@@ -98,4 +98,4 @@ function useCurrentUser() {
|
|
|
98
98
|
//#endregion
|
|
99
99
|
export { useCompanyScopedQueryKey as i, useCurrentUser as n, createCompanyQueryKey as r, CURRENT_USER_QUERY_KEY as t };
|
|
100
100
|
|
|
101
|
-
//# sourceMappingURL=use-current-user-
|
|
101
|
+
//# sourceMappingURL=use-current-user-Bl9nPNFt.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-current-user-
|
|
1
|
+
{"version":3,"file":"use-current-user-Bl9nPNFt.mjs","names":[],"sources":["../src/hooks/query-keys.ts","../src/hooks/use-current-user.ts"],"sourcesContent":["/**\n * Company-scoped query key factory for TanStack Query.\n *\n * All portal SDK query keys are prefixed with [\"company\", companyId, ...]\n * so that switching companies naturally invalidates the entire cache scope.\n *\n * The exported `*_QUERY_KEY` constants (e.g. PROFILE_QUERY_KEY) remain as\n * backwards-compatible base keys. The runtime keys used by hooks include the\n * company prefix via {@link createCompanyQueryKey}.\n */\n\nimport { useCallback, useRef } from \"react\";\nimport { useFluidAuthContext } from \"../providers/FluidAuthProvider\";\n\n/**\n * Create a company-scoped query key by prepending [\"company\", companyId].\n *\n * @param companyId - The company ID from the JWT payload\n * @param baseKey - The base query key segments (e.g. [\"fluid\", \"profile\"])\n * @returns A tuple like [\"company\", 42, \"fluid\", \"profile\"]\n *\n * @example\n * ```ts\n * const key = createCompanyQueryKey(42, \"fluid\", \"profile\");\n * // => [\"company\", 42, \"fluid\", \"profile\"]\n * ```\n */\nexport function createCompanyQueryKey(\n companyId: number,\n ...baseKey: readonly string[]\n): readonly [\"company\", number, ...string[]] {\n return [\"company\", companyId, ...baseKey] as const;\n}\n\n/**\n * Hook that returns a `scopeKey` function bound to the current company ID\n * from the auth context. If the user is not authenticated or has no\n * company_id, the base key is returned unscoped (graceful degradation).\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { scopeKey } = useCompanyScopedQueryKey();\n * const queryKey = scopeKey(PROFILE_QUERY_KEY);\n * // => [\"company\", 42, \"fluid\", \"profile\"] (when authenticated)\n * // => [\"fluid\", \"profile\"] (fallback)\n * }\n * ```\n */\nexport function useCompanyScopedQueryKey(): {\n readonly companyId: number | undefined;\n readonly scopeKey: <T extends readonly string[]>(\n baseKey: T,\n ) => readonly (string | number)[];\n} {\n const auth = useFluidAuthContext();\n const companyId = auth.user?.company_id;\n\n // Warn (once per component instance) when an authenticated user has no\n // company_id. This is a security-relevant condition: unscoped keys allow\n // cross-company cache collisions. The warning fires in all environments\n // so that it's visible in production logs if a misconfigured JWT is issued.\n const hasWarnedRef = useRef(false);\n if (auth.isAuthenticated && companyId == null && !hasWarnedRef.current) {\n hasWarnedRef.current = true;\n console.warn(\n \"[portal-sdk] Authenticated user has no company_id in JWT. \" +\n \"Query keys will fall back to unscoped keys, which may cause \" +\n \"cross-company cache collisions. Ensure the JWT includes company_id.\",\n );\n }\n\n const scopeKey = useCallback(\n <T extends readonly string[]>(baseKey: T): readonly (string | number)[] => {\n if (companyId != null) {\n return createCompanyQueryKey(companyId, ...baseKey);\n }\n return baseKey;\n },\n [companyId],\n );\n\n return { companyId, scopeKey } as const;\n}\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useFluidApi } from \"./use-fluid-api\";\nimport { useCompanyScopedQueryKey } from \"./query-keys\";\nimport type { UserMe } from \"../types/rep\";\n\n/**\n * Base query key for current user data.\n * Kept for backwards compatibility — the runtime key used by the hook\n * includes a company prefix via {@link useCompanyScopedQueryKey}.\n */\nexport const CURRENT_USER_QUERY_KEY = [\"fluid\", \"currentUser\"] as const;\n\n/**\n * Hook to fetch the currently authenticated user's full profile.\n * Returns company, country, and other fields from GET /api/me.\n *\n * @example\n * ```tsx\n * function ShopPage() {\n * const { data: user, isLoading } = useCurrentUser();\n * const subdomain = user?.company?.subdomain;\n * const countryIso = user?.country?.iso ?? \"US\";\n * // ...\n * }\n * ```\n */\nexport function useCurrentUser(): UseQueryResult<UserMe> {\n const api = useFluidApi();\n const { scopeKey } = useCompanyScopedQueryKey();\n\n return useQuery({\n queryKey: scopeKey(CURRENT_USER_QUERY_KEY),\n queryFn: () => api.users.me(),\n staleTime: 5 * 60 * 1000,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,sBACd,WACA,GAAG,SACwC;AAC3C,QAAO;EAAC;EAAW;EAAW,GAAG;EAAQ;;;;;;;;;;;;;;;;;AAkB3C,SAAgB,2BAKd;CACA,MAAM,OAAO,qBAAqB;CAClC,MAAM,YAAY,KAAK,MAAM;CAM7B,MAAM,eAAe,OAAO,MAAM;AAClC,KAAI,KAAK,mBAAmB,aAAa,QAAQ,CAAC,aAAa,SAAS;AACtE,eAAa,UAAU;AACvB,UAAQ,KACN,4LAGD;;AAaH,QAAO;EAAE;EAAW,UAVH,aACe,YAA6C;AACzE,OAAI,aAAa,KACf,QAAO,sBAAsB,WAAW,GAAG,QAAQ;AAErD,UAAO;KAET,CAAC,UAAU,CACZ;EAE6B;;;;;;;;;ACxEhC,MAAa,yBAAyB,CAAC,SAAS,cAAc;;;;;;;;;;;;;;;AAgB9D,SAAgB,iBAAyC;CACvD,MAAM,MAAM,aAAa;CACzB,MAAM,EAAE,aAAa,0BAA0B;AAE/C,QAAO,SAAS;EACd,UAAU,SAAS,uBAAuB;EAC1C,eAAe,IAAI,MAAM,IAAI;EAC7B,WAAW,MAAS;EACrB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
const require_FluidProvider = require("./FluidProvider-
|
|
3
|
-
const require_use_fluid_api = require("./use-fluid-api-
|
|
2
|
+
const require_FluidProvider = require("./FluidProvider-BSBLJp15.cjs");
|
|
3
|
+
const require_use_fluid_api = require("./use-fluid-api-DwRQk00z.cjs");
|
|
4
4
|
let react = require("react");
|
|
5
5
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
6
6
|
//#region src/hooks/query-keys.ts
|
|
@@ -122,4 +122,4 @@ Object.defineProperty(exports, "useCurrentUser", {
|
|
|
122
122
|
}
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
-
//# sourceMappingURL=use-current-user-
|
|
125
|
+
//# sourceMappingURL=use-current-user-SFCzJt0q.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-current-user-
|
|
1
|
+
{"version":3,"file":"use-current-user-SFCzJt0q.cjs","names":["useFluidAuthContext","useFluidApi"],"sources":["../src/hooks/query-keys.ts","../src/hooks/use-current-user.ts"],"sourcesContent":["/**\n * Company-scoped query key factory for TanStack Query.\n *\n * All portal SDK query keys are prefixed with [\"company\", companyId, ...]\n * so that switching companies naturally invalidates the entire cache scope.\n *\n * The exported `*_QUERY_KEY` constants (e.g. PROFILE_QUERY_KEY) remain as\n * backwards-compatible base keys. The runtime keys used by hooks include the\n * company prefix via {@link createCompanyQueryKey}.\n */\n\nimport { useCallback, useRef } from \"react\";\nimport { useFluidAuthContext } from \"../providers/FluidAuthProvider\";\n\n/**\n * Create a company-scoped query key by prepending [\"company\", companyId].\n *\n * @param companyId - The company ID from the JWT payload\n * @param baseKey - The base query key segments (e.g. [\"fluid\", \"profile\"])\n * @returns A tuple like [\"company\", 42, \"fluid\", \"profile\"]\n *\n * @example\n * ```ts\n * const key = createCompanyQueryKey(42, \"fluid\", \"profile\");\n * // => [\"company\", 42, \"fluid\", \"profile\"]\n * ```\n */\nexport function createCompanyQueryKey(\n companyId: number,\n ...baseKey: readonly string[]\n): readonly [\"company\", number, ...string[]] {\n return [\"company\", companyId, ...baseKey] as const;\n}\n\n/**\n * Hook that returns a `scopeKey` function bound to the current company ID\n * from the auth context. If the user is not authenticated or has no\n * company_id, the base key is returned unscoped (graceful degradation).\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { scopeKey } = useCompanyScopedQueryKey();\n * const queryKey = scopeKey(PROFILE_QUERY_KEY);\n * // => [\"company\", 42, \"fluid\", \"profile\"] (when authenticated)\n * // => [\"fluid\", \"profile\"] (fallback)\n * }\n * ```\n */\nexport function useCompanyScopedQueryKey(): {\n readonly companyId: number | undefined;\n readonly scopeKey: <T extends readonly string[]>(\n baseKey: T,\n ) => readonly (string | number)[];\n} {\n const auth = useFluidAuthContext();\n const companyId = auth.user?.company_id;\n\n // Warn (once per component instance) when an authenticated user has no\n // company_id. This is a security-relevant condition: unscoped keys allow\n // cross-company cache collisions. The warning fires in all environments\n // so that it's visible in production logs if a misconfigured JWT is issued.\n const hasWarnedRef = useRef(false);\n if (auth.isAuthenticated && companyId == null && !hasWarnedRef.current) {\n hasWarnedRef.current = true;\n console.warn(\n \"[portal-sdk] Authenticated user has no company_id in JWT. \" +\n \"Query keys will fall back to unscoped keys, which may cause \" +\n \"cross-company cache collisions. Ensure the JWT includes company_id.\",\n );\n }\n\n const scopeKey = useCallback(\n <T extends readonly string[]>(baseKey: T): readonly (string | number)[] => {\n if (companyId != null) {\n return createCompanyQueryKey(companyId, ...baseKey);\n }\n return baseKey;\n },\n [companyId],\n );\n\n return { companyId, scopeKey } as const;\n}\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useFluidApi } from \"./use-fluid-api\";\nimport { useCompanyScopedQueryKey } from \"./query-keys\";\nimport type { UserMe } from \"../types/rep\";\n\n/**\n * Base query key for current user data.\n * Kept for backwards compatibility — the runtime key used by the hook\n * includes a company prefix via {@link useCompanyScopedQueryKey}.\n */\nexport const CURRENT_USER_QUERY_KEY = [\"fluid\", \"currentUser\"] as const;\n\n/**\n * Hook to fetch the currently authenticated user's full profile.\n * Returns company, country, and other fields from GET /api/me.\n *\n * @example\n * ```tsx\n * function ShopPage() {\n * const { data: user, isLoading } = useCurrentUser();\n * const subdomain = user?.company?.subdomain;\n * const countryIso = user?.country?.iso ?? \"US\";\n * // ...\n * }\n * ```\n */\nexport function useCurrentUser(): UseQueryResult<UserMe> {\n const api = useFluidApi();\n const { scopeKey } = useCompanyScopedQueryKey();\n\n return useQuery({\n queryKey: scopeKey(CURRENT_USER_QUERY_KEY),\n queryFn: () => api.users.me(),\n staleTime: 5 * 60 * 1000,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,sBACd,WACA,GAAG,SACwC;AAC3C,QAAO;EAAC;EAAW;EAAW,GAAG;EAAQ;;;;;;;;;;;;;;;;;AAkB3C,SAAgB,2BAKd;CACA,MAAM,OAAOA,sBAAAA,qBAAqB;CAClC,MAAM,YAAY,KAAK,MAAM;CAM7B,MAAM,gBAAA,GAAA,MAAA,QAAsB,MAAM;AAClC,KAAI,KAAK,mBAAmB,aAAa,QAAQ,CAAC,aAAa,SAAS;AACtE,eAAa,UAAU;AACvB,UAAQ,KACN,4LAGD;;AAaH,QAAO;EAAE;EAAW,WAAA,GAAA,MAAA,cATY,YAA6C;AACzE,OAAI,aAAa,KACf,QAAO,sBAAsB,WAAW,GAAG,QAAQ;AAErD,UAAO;KAET,CAAC,UAAU,CACZ;EAE6B;;;;;;;;;ACxEhC,MAAa,yBAAyB,CAAC,SAAS,cAAc;;;;;;;;;;;;;;;AAgB9D,SAAgB,iBAAyC;CACvD,MAAM,MAAMC,sBAAAA,aAAa;CACzB,MAAM,EAAE,aAAa,0BAA0B;AAE/C,SAAA,GAAA,sBAAA,UAAgB;EACd,UAAU,SAAS,uBAAuB;EAC1C,eAAe,IAAI,MAAM,IAAI;EAC7B,WAAW,MAAS;EACrB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _t as fetchCustomerAccount } from "./FluidProvider-
|
|
2
|
-
import { n as useFluidPayClient, o as useFluidAuth } from "./use-account-clients-
|
|
1
|
+
import { _t as fetchCustomerAccount } from "./FluidProvider-CwkMUOoy.mjs";
|
|
2
|
+
import { n as useFluidPayClient, o as useFluidAuth } from "./use-account-clients-Cf_6sxeC.mjs";
|
|
3
3
|
import { useQuery } from "@tanstack/react-query";
|
|
4
4
|
//#region src/account/use-customer-account.ts
|
|
5
5
|
function useCustomerAccount({ enabled = true } = {}) {
|
|
@@ -20,4 +20,4 @@ function useCustomerAccount({ enabled = true } = {}) {
|
|
|
20
20
|
//#endregion
|
|
21
21
|
export { useCustomerAccount as t };
|
|
22
22
|
|
|
23
|
-
//# sourceMappingURL=use-customer-account-
|
|
23
|
+
//# sourceMappingURL=use-customer-account-B0DeL6m0.mjs.map
|
package/dist/{use-customer-account-Bh4RXGq-.mjs.map → use-customer-account-B0DeL6m0.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-customer-account-
|
|
1
|
+
{"version":3,"file":"use-customer-account-B0DeL6m0.mjs","names":["customersApi.fetchCustomerAccount"],"sources":["../src/account/use-customer-account.ts"],"sourcesContent":["import { useQuery } from \"@tanstack/react-query\";\nimport { customersApi } from \"@fluid-app/fluid-pay-api-client\";\nimport { useFluidAuth } from \"../hooks/use-fluid-auth\";\nimport { useFluidPayClient } from \"./use-account-clients\";\n\nexport function useCustomerAccount({\n enabled = true,\n}: { enabled?: boolean } = {}) {\n const { token, user } = useFluidAuth();\n const fluidPayClient = useFluidPayClient();\n const jwt = token ?? \"\";\n\n const query = useQuery({\n queryKey: [\"fluidPayAccount\", user?.id],\n queryFn: () => customersApi.fetchCustomerAccount(fluidPayClient, jwt),\n enabled: !!jwt && enabled,\n });\n\n return {\n customerId: query.data?.customer?.id,\n isLoadingCustomer: query.isLoading,\n isCustomerError: query.isError,\n };\n}\n"],"mappings":";;;;AAKA,SAAgB,mBAAmB,EACjC,UAAU,SACe,EAAE,EAAE;CAC7B,MAAM,EAAE,OAAO,SAAS,cAAc;CACtC,MAAM,iBAAiB,mBAAmB;CAC1C,MAAM,MAAM,SAAS;CAErB,MAAM,QAAQ,SAAS;EACrB,UAAU,CAAC,mBAAmB,MAAM,GAAG;EACvC,eAAeA,qBAAkC,gBAAgB,IAAI;EACrE,SAAS,CAAC,CAAC,OAAO;EACnB,CAAC;AAEF,QAAO;EACL,YAAY,MAAM,MAAM,UAAU;EAClC,mBAAmB,MAAM;EACzB,iBAAiB,MAAM;EACxB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
const require_FluidProvider = require("./FluidProvider-
|
|
3
|
-
const require_use_account_clients = require("./use-account-clients-
|
|
2
|
+
const require_FluidProvider = require("./FluidProvider-BSBLJp15.cjs");
|
|
3
|
+
const require_use_account_clients = require("./use-account-clients-62dZrh9E.cjs");
|
|
4
4
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
5
5
|
//#region src/account/use-customer-account.ts
|
|
6
6
|
function useCustomerAccount({ enabled = true } = {}) {
|
|
@@ -26,4 +26,4 @@ Object.defineProperty(exports, "useCustomerAccount", {
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
//# sourceMappingURL=use-customer-account-
|
|
29
|
+
//# sourceMappingURL=use-customer-account-Dysq4hpT.cjs.map
|
package/dist/{use-customer-account-D3WQH1de.cjs.map → use-customer-account-Dysq4hpT.cjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-customer-account-
|
|
1
|
+
{"version":3,"file":"use-customer-account-Dysq4hpT.cjs","names":["useFluidAuth","useFluidPayClient"],"sources":["../src/account/use-customer-account.ts"],"sourcesContent":["import { useQuery } from \"@tanstack/react-query\";\nimport { customersApi } from \"@fluid-app/fluid-pay-api-client\";\nimport { useFluidAuth } from \"../hooks/use-fluid-auth\";\nimport { useFluidPayClient } from \"./use-account-clients\";\n\nexport function useCustomerAccount({\n enabled = true,\n}: { enabled?: boolean } = {}) {\n const { token, user } = useFluidAuth();\n const fluidPayClient = useFluidPayClient();\n const jwt = token ?? \"\";\n\n const query = useQuery({\n queryKey: [\"fluidPayAccount\", user?.id],\n queryFn: () => customersApi.fetchCustomerAccount(fluidPayClient, jwt),\n enabled: !!jwt && enabled,\n });\n\n return {\n customerId: query.data?.customer?.id,\n isLoadingCustomer: query.isLoading,\n isCustomerError: query.isError,\n };\n}\n"],"mappings":";;;;;AAKA,SAAgB,mBAAmB,EACjC,UAAU,SACe,EAAE,EAAE;CAC7B,MAAM,EAAE,OAAO,SAASA,4BAAAA,cAAc;CACtC,MAAM,iBAAiBC,4BAAAA,mBAAmB;CAC1C,MAAM,MAAM,SAAS;CAErB,MAAM,SAAA,GAAA,sBAAA,UAAiB;EACrB,UAAU,CAAC,mBAAmB,MAAM,GAAG;EACvC,eAAA,sBAAA,qBAAiD,gBAAgB,IAAI;EACrE,SAAS,CAAC,CAAC,OAAO;EACnB,CAAC;AAEF,QAAO;EACL,YAAY,MAAM,MAAM,UAAU;EAClC,mBAAmB,MAAM;EACzB,iBAAiB,MAAM;EACxB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as useFluidContext } from "./FluidProvider-
|
|
1
|
+
import { n as useFluidContext } from "./FluidProvider-CwkMUOoy.mjs";
|
|
2
2
|
//#region src/hooks/use-fluid-api.ts
|
|
3
3
|
/**
|
|
4
4
|
* Hook to access the Fluid API client
|
|
@@ -24,4 +24,4 @@ function useFluidApi() {
|
|
|
24
24
|
//#endregion
|
|
25
25
|
export { useFluidApi as t };
|
|
26
26
|
|
|
27
|
-
//# sourceMappingURL=use-fluid-api-
|
|
27
|
+
//# sourceMappingURL=use-fluid-api-DPhr-9Jv.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-fluid-api-
|
|
1
|
+
{"version":3,"file":"use-fluid-api-DPhr-9Jv.mjs","names":[],"sources":["../src/hooks/use-fluid-api.ts"],"sourcesContent":["import { useFluidContext } from \"../providers/FluidProvider\";\nimport type { FluidClient } from \"../client/fluid-client\";\n\n/**\n * Hook to access the Fluid API client\n *\n * @example\n * ```tsx\n * function ProductList() {\n * const api = useFluidApi();\n *\n * const { data: products } = useQuery({\n * queryKey: [\"products\"],\n * queryFn: () => api.products.list(),\n * });\n *\n * return <ul>{products?.map(p => <li key={p.id}>{p.name}</li>)}</ul>;\n * }\n * ```\n */\nexport function useFluidApi(): FluidClient {\n const { client } = useFluidContext();\n return client;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,cAA2B;CACzC,MAAM,EAAE,WAAW,iBAAiB;AACpC,QAAO"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_FluidProvider = require("./FluidProvider-
|
|
1
|
+
const require_FluidProvider = require("./FluidProvider-BSBLJp15.cjs");
|
|
2
2
|
//#region src/hooks/use-fluid-api.ts
|
|
3
3
|
/**
|
|
4
4
|
* Hook to access the Fluid API client
|
|
@@ -29,4 +29,4 @@ Object.defineProperty(exports, "useFluidApi", {
|
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
//# sourceMappingURL=use-fluid-api-
|
|
32
|
+
//# sourceMappingURL=use-fluid-api-DwRQk00z.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-fluid-api-
|
|
1
|
+
{"version":3,"file":"use-fluid-api-DwRQk00z.cjs","names":["useFluidContext"],"sources":["../src/hooks/use-fluid-api.ts"],"sourcesContent":["import { useFluidContext } from \"../providers/FluidProvider\";\nimport type { FluidClient } from \"../client/fluid-client\";\n\n/**\n * Hook to access the Fluid API client\n *\n * @example\n * ```tsx\n * function ProductList() {\n * const api = useFluidApi();\n *\n * const { data: products } = useQuery({\n * queryKey: [\"products\"],\n * queryFn: () => api.products.list(),\n * });\n *\n * return <ul>{products?.map(p => <li key={p.id}>{p.name}</li>)}</ul>;\n * }\n * ```\n */\nexport function useFluidApi(): FluidClient {\n const { client } = useFluidContext();\n return client;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,cAA2B;CACzC,MAAM,EAAE,WAAWA,sBAAAA,iBAAiB;AACpC,QAAO"}
|
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.83",
|
|
4
4
|
"description": "SDK for building custom Fluid portals",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -66,44 +66,44 @@
|
|
|
66
66
|
"typescript": "^5",
|
|
67
67
|
"zod": "4.3.5",
|
|
68
68
|
"@fluid-app/api-client-core": "0.1.0",
|
|
69
|
+
"@fluid-app/auth": "0.1.0",
|
|
69
70
|
"@fluid-app/cart-ui": "0.1.12",
|
|
70
71
|
"@fluid-app/company-switcher-core": "0.1.0",
|
|
71
|
-
"@fluid-app/auth": "0.1.0",
|
|
72
72
|
"@fluid-app/company-switcher-ui": "0.1.0",
|
|
73
73
|
"@fluid-app/contacts-ui": "0.1.0",
|
|
74
74
|
"@fluid-app/fluid-pay-api-client": "0.1.0",
|
|
75
|
+
"@fluid-app/file-picker-api-client": "0.1.0",
|
|
75
76
|
"@fluid-app/fluidos-api-client": "0.1.0",
|
|
76
77
|
"@fluid-app/messaging-api-client": "0.1.0",
|
|
77
|
-
"@fluid-app/messaging-ui": "0.1.0",
|
|
78
|
-
"@fluid-app/mysite-ui": "0.1.0",
|
|
79
78
|
"@fluid-app/messaging-core": "0.1.0",
|
|
80
|
-
"@fluid-app/
|
|
79
|
+
"@fluid-app/mysite-ui": "0.1.0",
|
|
80
|
+
"@fluid-app/messaging-ui": "0.1.0",
|
|
81
81
|
"@fluid-app/orders-api-client": "0.1.0",
|
|
82
|
-
"@fluid-app/file-picker-api-client": "0.1.0",
|
|
83
|
-
"@fluid-app/permissions": "0.1.0",
|
|
84
82
|
"@fluid-app/orders-ui": "0.1.0",
|
|
83
|
+
"@fluid-app/orders-core": "0.1.0",
|
|
84
|
+
"@fluid-app/permissions": "0.1.0",
|
|
85
85
|
"@fluid-app/portal-app-download-ui": "0.1.0",
|
|
86
|
-
"@fluid-app/portal-pro-upgrade-ui": "0.1.0",
|
|
87
|
-
"@fluid-app/portal-preview": "0.1.0",
|
|
88
86
|
"@fluid-app/portal-core": "0.1.23",
|
|
87
|
+
"@fluid-app/portal-preview": "0.1.0",
|
|
88
|
+
"@fluid-app/portal-pro-upgrade-ui": "0.1.0",
|
|
89
89
|
"@fluid-app/portal-react": "0.1.0",
|
|
90
90
|
"@fluid-app/portal-widgets": "0.1.22",
|
|
91
|
-
"@fluid-app/products-core": "0.1.0",
|
|
92
91
|
"@fluid-app/products-api-client": "0.1.0",
|
|
92
|
+
"@fluid-app/products-core": "0.1.0",
|
|
93
93
|
"@fluid-app/profile-core": "0.1.0",
|
|
94
94
|
"@fluid-app/profile-ui": "0.1.0",
|
|
95
|
+
"@fluid-app/query-persister": "0.1.0",
|
|
96
|
+
"@fluid-app/shareables-api-client": "0.1.0",
|
|
95
97
|
"@fluid-app/shareables-core": "0.1.0",
|
|
96
98
|
"@fluid-app/shareables-ui": "0.1.0",
|
|
97
|
-
"@fluid-app/query-persister": "0.1.0",
|
|
98
99
|
"@fluid-app/shop-ui": "0.1.0",
|
|
99
100
|
"@fluid-app/subscriptions-api-client": "0.1.0",
|
|
100
|
-
"@fluid-app/shareables-api-client": "0.1.0",
|
|
101
101
|
"@fluid-app/subscriptions-ui": "0.1.0",
|
|
102
102
|
"@fluid-app/subscriptions-core": "0.1.0",
|
|
103
|
-
"@fluid-app/ui-primitives": "0.1.13",
|
|
104
|
-
"@fluid-app/user-contacts-api-client": "0.1.0",
|
|
105
103
|
"@fluid-app/typescript-config": "0.0.0",
|
|
104
|
+
"@fluid-app/ui-primitives": "0.1.13",
|
|
106
105
|
"@fluid-app/user-notes-api-client": "0.1.0",
|
|
106
|
+
"@fluid-app/user-contacts-api-client": "0.1.0",
|
|
107
107
|
"@fluid-app/user-tasks-api-client": "0.1.0"
|
|
108
108
|
},
|
|
109
109
|
"peerDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PointsWidget-Cc88UHqD.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/registry-context.tsx","../../widgets/src/hooks/use-points-ledger.preview.ts","../../widgets/src/hooks/use-points-ledger.ts","../../widgets/src/widgets/PointsWidget.tsx"],"sourcesContent":["import type { ApiDataSource, DataSourceContext } from \"../types\";\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 const { endpoint, method = \"GET\", headers = {}, body } = 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. customer_id not yet loaded). Returning undefined avoids a bad API request.\n if (/\\{\\w+\\}/.test(url)) {\n return undefined;\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 (source.resultPath) {\n return getByPath(data, source.resultPath);\n }\n\n return data;\n}\n","import type {\n CustomDataSource,\n DataSourceContext,\n SelectedItem,\n ShareableType,\n} from \"../types\";\n\n/**\n * Individual resource endpoints for each shareable type.\n * These fetch single items by ID from the company API.\n */\nconst SHAREABLE_ENDPOINTS: Record<\n ShareableType,\n (id: string | number) => string\n> = {\n Medium: (id) => `/company/media/${id}`,\n Page: (id) => `/company/pages/${id}`,\n Library: (id) => `/company/libraries/${id}`,\n Product: (id) => `/company/v1/products/${id}`,\n EnrollmentPack: (id) => `/enrollment_packs/${id}`,\n};\n\n/**\n * Extract the actual resource data from various API response structures.\n * Different endpoints wrap their data differently:\n * - Product: { status, resource: { product: {...} } }\n * - EnrollmentPack: { status, resource: { enrollment_pack: {...} } }\n * - Medium/Page/Library: Direct root or { medium: {...} }\n */\nfunction extractResourceData(\n json: Record<string, unknown>,\n shareableType: ShareableType,\n): Record<string, unknown> {\n // Try nested resource structure first (Product, EnrollmentPack)\n const resource = json.resource as Record<string, unknown> | undefined;\n if (resource) {\n // Check for type-specific key within resource\n const typeKey = shareableType.toLowerCase().replace(\"pack\", \"_pack\");\n if (resource[typeKey]) {\n return resource[typeKey] as Record<string, unknown>;\n }\n // Check common keys\n if (resource.product) return resource.product as Record<string, unknown>;\n if (resource.enrollment_pack)\n return resource.enrollment_pack as Record<string, unknown>;\n }\n\n // Try direct type key (e.g., { medium: {...} })\n const directKey = shareableType.toLowerCase().replace(\"pack\", \"_pack\");\n if (json[directKey]) {\n return json[directKey] as Record<string, unknown>;\n }\n\n // Try common response shapes\n if (json.data) return json.data as Record<string, unknown>;\n if (json.medium) return json.medium as Record<string, unknown>;\n if (json.page) return json.page as Record<string, unknown>;\n if (json.library) return json.library as Record<string, unknown>;\n if (json.product) return json.product as Record<string, unknown>;\n if (json.enrollment_pack)\n return json.enrollment_pack as Record<string, unknown>;\n\n // Return as-is if no wrapper found (Library uses direct serialization)\n return json;\n}\n\n/**\n * Result from fetching a single shareable item\n */\ninterface FetchResult {\n item: SelectedItem;\n data: unknown;\n error?: Error;\n}\n\n/**\n * Fetch a single shareable item by ID from the individual resource endpoint.\n */\nasync function fetchSingleItem(\n item: SelectedItem,\n signal: AbortSignal,\n baseUrl: string = \"\",\n getApiHeaders?: () => Record<string, string>,\n): Promise<FetchResult> {\n const getEndpoint = SHAREABLE_ENDPOINTS[item.shareableType];\n if (!getEndpoint) {\n return {\n item,\n data: null,\n error: new Error(`Unknown shareable type: ${item.shareableType}`),\n };\n }\n\n const endpoint = `${baseUrl}${getEndpoint(item.id)}`;\n\n try {\n const response = await fetch(endpoint, {\n method: \"GET\",\n headers: {\n ...getApiHeaders?.(),\n \"Content-Type\": \"application/json\",\n },\n signal,\n });\n\n if (!response.ok) {\n return {\n item,\n data: null,\n error: new Error(\n `Failed to fetch ${item.shareableType} with ID ${item.id}: ${response.status}`,\n ),\n };\n }\n\n const json = await response.json();\n\n // Extract the actual resource data from the response wrapper\n const resourceData = extractResourceData(json, item.shareableType);\n\n // Add shareable_type to the response for transformer compatibility\n if (resourceData && typeof resourceData === \"object\") {\n (resourceData as Record<string, unknown>).shareable_type =\n item.shareableType;\n }\n\n return { item, data: resourceData };\n } catch (error) {\n return {\n item,\n data: null,\n error:\n error instanceof Error\n ? error\n : new Error(\n `Unknown error fetching ${item.shareableType} ${item.id}`,\n ),\n };\n }\n}\n\n/**\n * Custom fetcher that fetches selected items.\n *\n * Fetches items from individual resource endpoints using the configured\n * getApiHeaders for authentication.\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.\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 // Fallback: fetch from individual endpoints (no auth)\n const results = await Promise.all(\n selectedItems.map((item) =>\n fetchSingleItem(\n item,\n context.signal,\n context.baseUrl,\n context.getApiHeaders,\n ),\n ),\n );\n\n // Process results, collecting successful data and tracking errors\n const successfulData: unknown[] = [];\n const errors: Error[] = [];\n\n for (const result of results) {\n if (result.error) {\n console.warn(\n `[CustomFetcher] Failed to fetch ${result.item.shareableType} #${result.item.id}:`,\n result.error.message,\n );\n errors.push(result.error);\n continue;\n }\n\n if (result.data) {\n successfulData.push(result.data);\n }\n }\n\n // Throw error if all fetches failed\n if (successfulData.length === 0 && errors.length > 0) {\n throw new Error(\n `Failed to fetch all ${errors.length} item(s): ${errors[0]?.message || \"Unknown error\"}`,\n );\n }\n\n return successfulData;\n}\n","import type {\n StaticDataSource,\n DataSourceContext,\n StaticSourceType,\n} from \"../types\";\n\n/**\n * Endpoint patterns for fetching products by static source type.\n * Tags require backend API support (not yet available).\n */\nconst STATIC_ENDPOINTS: Record<\"collections\" | \"categories\", string> = {\n collections: \"/company/v1/products\",\n categories: \"/company/v1/products\",\n};\n\n/**\n * Query parameter names for each static source type.\n */\nconst STATIC_QUERY_PARAMS: Record<\"collections\" | \"categories\", string> = {\n collections: \"collection_id\",\n categories: \"category_id\",\n};\n\n/**\n * Extract products array from API response.\n * The /company/v1/products endpoint returns { products: [...], meta: {...} }\n */\nfunction extractProducts(json: Record<string, unknown>): unknown[] {\n if (Array.isArray(json.products)) {\n return json.products;\n }\n if (Array.isArray(json.data)) {\n return json.data;\n }\n if (Array.isArray(json)) {\n return json;\n }\n console.warn(\n \"[extractProducts] Could not find products array. Available keys:\",\n Object.keys(json),\n );\n return [];\n}\n\n/**\n * Static data source fetcher.\n *\n * Fetches products filtered by collection or category ID.\n * Tags are not yet supported (requires backend API changes).\n *\n * @param source - The static data source configuration\n * @param context - The data source context with baseUrl and headers\n * @returns Array of products matching the filter criteria\n */\nexport async function staticFetcher(\n source: StaticDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { staticType, selectedId } = source;\n\n // Tags require backend API support - not yet implemented\n if (staticType === \"tags\") {\n throw new Error(\n \"Tags data source is not yet supported. Please select Collections or Categories instead.\",\n );\n }\n\n const endpoint = STATIC_ENDPOINTS[staticType];\n const queryParam = STATIC_QUERY_PARAMS[staticType];\n\n if (!endpoint || !queryParam) {\n throw new Error(\n `Invalid data source configuration: \"${staticType}\" is not a supported static source type.`,\n );\n }\n\n const url = new URL(\n `${context.baseUrl ?? \"\"}${endpoint}`,\n context.baseUrl ? undefined : window.location.origin,\n );\n url.searchParams.set(queryParam, String(selectedId));\n\n try {\n const response = await fetch(url.toString(), {\n method: \"GET\",\n headers: {\n ...context.getApiHeaders?.(),\n \"Content-Type\": \"application/json\",\n },\n signal: context.signal,\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch products for ${staticType} ${selectedId}: ${response.status} ${response.statusText}`,\n );\n }\n\n const json = await response.json();\n return extractProducts(json);\n } catch (error) {\n if (error instanceof Error && error.name === \"AbortError\") {\n // Request was cancelled, don't log as error\n return [];\n }\n console.error(\n `[staticFetcher] Error fetching ${staticType} ${selectedId}:`,\n error,\n );\n throw error;\n }\n}\n\n/**\n * Endpoints for listing static source items (collections, categories, tags).\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 = d.kind === \"video\" || d.videoUrl || d.video_url;\n const title = (d.title ?? d.name ?? \"\") as string;\n\n const content = isVideo\n ? {\n type: \"VideoWidget\",\n props: {\n src: ((d.videoUrl ?? d.video_url) as string) || \"\",\n poster: imageUrl,\n caption: title,\n autoplay: true,\n loop: true,\n muted: true,\n controls: false,\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\";\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 */\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","import type { PointsData } from \"./use-points-ledger.types\";\n\nconst now = new Date();\n\nfunction daysAgo(days: number): string {\n return new Date(now.getTime() - days * 86_400_000).toISOString();\n}\n\nexport const PREVIEW_DATA: PointsData = {\n balance: 25,\n entries: [\n {\n id: 1,\n description: \"Purchase March 3rd\",\n amount: 20,\n createdAt: daysAgo(3),\n },\n {\n id: 2,\n description: \"Referral Bonus\",\n amount: 50,\n createdAt: daysAgo(14),\n },\n {\n id: 3,\n description: \"Points Redemption\",\n amount: -75,\n createdAt: daysAgo(60),\n },\n {\n id: 4,\n description: \"Welcome Reward\",\n amount: 30,\n createdAt: daysAgo(90),\n },\n ],\n};\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useDataSourceConfig } from \"@fluid-app/portal-react/data-sources/context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { PREVIEW_DATA } from \"./use-points-ledger.preview\";\nimport type { PointsData, PointsEntry } from \"./use-points-ledger.types\";\n\nexport type { PointsData, PointsEntry } from \"./use-points-ledger.types\";\n\nexport const POINTS_LEDGER_QUERY_KEY = \"points-ledger\" as const;\n\ntype ApiPointsLedger = {\n id: number;\n amount: number;\n company_id: number;\n created_at: string;\n customer_id: number;\n metadata: {\n transaction_type?: string;\n source?: { name?: string; reason?: string };\n };\n total_balance: number;\n updated_at: string;\n};\n\ntype ApiResponse = {\n points_ledgers: ApiPointsLedger[];\n meta: {\n request_id: string;\n timestamp: string;\n pagination: {\n current_page: number;\n total_pages: number;\n total_count: number;\n per_page: number;\n };\n };\n};\n\nfunction formatDescription(ledger: ApiPointsLedger): string {\n if (ledger.metadata?.transaction_type) {\n return ledger.metadata.transaction_type\n .split(\"_\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n }\n if (ledger.metadata?.source?.reason) {\n return ledger.metadata.source.reason;\n }\n const date = new Date(ledger.created_at);\n return `Transaction ${date.toLocaleDateString(\"en-US\", { month: \"long\", day: \"numeric\" })}`;\n}\n\nfunction transformResponse(data: ApiResponse): PointsData {\n const ledgers = data.points_ledgers;\n\n // Sort newest-first to get current balance from the most recent entry\n const sorted = [...ledgers].sort(\n (a, b) =>\n new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),\n );\n const balance = sorted[0]?.total_balance ?? 0;\n\n const entries: PointsEntry[] = sorted.map((ledger) => ({\n id: ledger.id,\n description: formatDescription(ledger),\n amount: ledger.amount,\n createdAt: ledger.created_at,\n }));\n\n return { balance, entries };\n}\n\nexport function usePointsLedger(): UseQueryResult<PointsData, Error> {\n const { baseUrl, getApiHeaders } = useDataSourceConfig();\n const { isPreview } = useWidgetPreviewContext();\n const registryConfig = useDataSourceRegistryConfig();\n const customerId = registryConfig.variables?.customer_id;\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n POINTS_LEDGER_QUERY_KEY,\n isPreview ? \"preview\" : baseUrl,\n customerId,\n ] as const,\n queryFn: async ({ signal }): Promise<PointsData> => {\n const base = baseUrl ?? \"\";\n const url = `${base}/v202506/customers/${customerId}/points_ledgers?page=1&per_page=100&sort_by=created_at&sort_dir=desc`;\n const response = await fetch(url, {\n headers: {\n \"content-type\": \"application/json\",\n ...getApiHeaders?.(),\n },\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch points ledger: ${response.status}`);\n }\n\n const data: ApiResponse = await response.json();\n return transformResponse(data);\n },\n enabled: !isPreview && !!customerId,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import { useId, useState, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport { usePointsLedger, type PointsEntry } from \"../hooks/use-points-ledger\";\nimport { ErrorState } from \"../components/error-state\";\nimport { ChevronDown, Coins } from \"lucide-react\";\n\nconst formatRelativeTime = (dateString: string): string => {\n const now = new Date();\n const date = new Date(dateString);\n const diffMs = now.getTime() - date.getTime();\n const diffDays = Math.floor(diffMs / 86_400_000);\n\n if (diffDays < 1) return \"Today\";\n if (diffDays === 1) return \"1 day ago\";\n if (diffDays < 7) return `${diffDays} days ago`;\n if (diffDays < 14) return \"1 week ago\";\n if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`;\n if (diffDays < 60) return \"1 month ago\";\n return `${Math.floor(diffDays / 30)} months ago`;\n};\n\nconst formatBalance = (balance: number): string => {\n return balance.toLocaleString(\"en-US\");\n};\n\ntype PointsWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Balance\n balanceColor?: ColorOptions;\n\n // History\n historyEnabled?: boolean;\n historyTitle?: string;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\nfunction PointsEntryRow({\n entry,\n textColor,\n accentColor,\n}: {\n entry: PointsEntry;\n textColor: ColorOptions;\n accentColor: ColorOptions;\n}) {\n const sign = entry.amount >= 0 ? \"+\" : \"-\";\n return (\n <div className=\"flex w-full items-center gap-3\">\n <div className=\"min-w-0 flex-1\">\n <p className={`text-sm text-${textColor} truncate`}>\n {entry.description}\n </p>\n <p className={`text-[10px] text-${textColor} leading-tight opacity-70`}>\n {formatRelativeTime(entry.createdAt)}\n </p>\n </div>\n <div className={`bg-${accentColor}/20 shrink-0 rounded-md px-1.5`}>\n <span className={`text-xs font-medium text-${accentColor} opacity-70`}>\n {sign}\n {Math.abs(entry.amount).toLocaleString(\"en-US\")}pts\n </span>\n </div>\n </div>\n );\n}\n\nexport function PointsWidget({\n // Title\n titleEnabled = true,\n title = \"Points\",\n titleFontSize = \"md\",\n titleColor = \"foreground\",\n\n // Balance\n balanceColor = \"primary\",\n\n // History\n historyEnabled = true,\n historyTitle = \"History\",\n\n // Styling\n background = { type: \"solid\", color: \"background\" },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n className,\n ...props\n}: PointsWidgetProps): React.JSX.Element {\n const [historyOpen, setHistoryOpen] = useState(false);\n const historyPanelId = useId();\n\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n const { data, isLoading, isError } = usePointsLedger();\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div className={`p-${padding} flex flex-col gap-2.5`}>\n {/* Header: Title + Balance */}\n {titleEnabled && (\n <h2\n className={`text-${titleFontSize} font-header font-bold text-${titleColor}`}\n >\n {title}\n </h2>\n )}\n {!isLoading && data && (\n <span\n className={`text-3xl font-semibold text-${balanceColor} font-header leading-snug`}\n >\n {formatBalance(data.balance)}\n </span>\n )}\n\n {/* Loading */}\n {isLoading ? (\n <div className=\"flex min-h-[60px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n <ErrorState />\n ) : historyEnabled && (!data || data.entries.length === 0) ? (\n /* Empty state — only shown when history is enabled but no entries */\n <div className=\"flex min-h-[60px] flex-col items-center justify-center gap-2\">\n <Coins className={`size-10 text-${textColor} opacity-30`} />\n <p className={`text-sm font-semibold text-${textColor} opacity-50`}>\n No Points Activity\n </p>\n </div>\n ) : historyEnabled && data && data.entries.length > 0 ? (\n /* History dropdown */\n <div className=\"flex flex-col gap-2\">\n {/* Dropdown toggle */}\n <button\n type=\"button\"\n aria-expanded={historyOpen}\n aria-controls={historyPanelId}\n onClick={() => setHistoryOpen((prev) => !prev)}\n className={`flex w-full items-center text-xs font-semibold text-${textColor} cursor-pointer`}\n >\n <span className=\"flex-1 text-left\">{historyTitle}</span>\n <ChevronDown\n className={`size-4 transition-transform duration-200 ${historyOpen ? \"rotate-180\" : \"\"}`}\n />\n </button>\n <div className={`bg-${textColor}/20 h-px w-full`} />\n\n {/* Collapsible entries */}\n <div\n id={historyPanelId}\n className={`flex flex-col gap-3 ${!historyOpen ? \"hidden\" : \"\"}`}\n >\n {data.entries.map((entry) => (\n <PointsEntryRow\n key={entry.id}\n entry={entry}\n textColor={textColor}\n accentColor={accentColor}\n />\n ))}\n </div>\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\nexport const pointsWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"PointsWidget\",\n displayName: \"Points\",\n fields: [\n // Title group\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Toggle title visibility\",\n defaultValue: true,\n\n group: \"Title\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the balance\",\n defaultValue: \"Points\",\n\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"md\",\n\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"foreground\",\n\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Balance group\n getColorField({\n key: \"balanceColor\",\n label: \"Balance Color\",\n description: \"Color for the points balance number\",\n defaultValue: \"primary\",\n\n group: \"Balance\",\n }),\n\n // History group\n {\n key: \"historyEnabled\",\n label: \"Show History\",\n type: \"boolean\",\n description: \"Show a collapsible history dropdown below the balance\",\n defaultValue: true,\n\n group: \"History\",\n },\n {\n key: \"historyTitle\",\n label: \"History Title\",\n type: \"text\",\n description: \"Title for the history dropdown\",\n defaultValue: \"History\",\n\n group: \"History\",\n requiresKeyToBeTrue: \"historyEnabled\",\n },\n\n // Design group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the widget\",\n defaultValue: \"background\",\n\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color\",\n defaultValue: \"foreground\",\n\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color for points badges and highlights\",\n defaultValue: \"primary\",\n\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Widget padding\",\n defaultValue: 4,\n\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Widget border radius\",\n defaultValue: \"md\",\n\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Widget border width\",\n defaultValue: \"none\",\n\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Widget border color\",\n defaultValue: \"muted\",\n\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
|