@fluid-app/portal-sdk 0.1.90 → 0.1.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/dist/{AppDownloadScreen--gGSPUDm.cjs → AppDownloadScreen-BtvcE4pE.cjs} +2 -2
  2. package/dist/{AppDownloadScreen--gGSPUDm.cjs.map → AppDownloadScreen-BtvcE4pE.cjs.map} +1 -1
  3. package/dist/{AppDownloadScreen-CDMvuvsQ.cjs → AppDownloadScreen-Dx2nilnX.cjs} +3 -3
  4. package/dist/{AppDownloadScreen-Bt--8jSo.mjs → AppDownloadScreen-RX8GSAyq.mjs} +2 -2
  5. package/dist/{AppDownloadScreen-Bt--8jSo.mjs.map → AppDownloadScreen-RX8GSAyq.mjs.map} +1 -1
  6. package/dist/{ContactsScreen-BZOjocjS.cjs → ContactsScreen-CKMZIQlF.cjs} +3 -3
  7. package/dist/{ContactsScreen-21VYWIsO.mjs → ContactsScreen-DOz11uQ_.mjs} +2 -2
  8. package/dist/{ContactsScreen-21VYWIsO.mjs.map → ContactsScreen-DOz11uQ_.mjs.map} +1 -1
  9. package/dist/{ContactsScreen-DH3K85c6.cjs → ContactsScreen-DttcI388.cjs} +2 -2
  10. package/dist/{ContactsScreen-DH3K85c6.cjs.map → ContactsScreen-DttcI388.cjs.map} +1 -1
  11. package/dist/{FluidProvider-CRiIzR8g.mjs → FluidProvider-Eohedipr.mjs} +3 -3
  12. package/dist/{FluidProvider-CRiIzR8g.mjs.map → FluidProvider-Eohedipr.mjs.map} +1 -1
  13. package/dist/{FluidProvider-Cwh9D2D_.cjs → FluidProvider-Sc51VlLw.cjs} +3 -3
  14. package/dist/{FluidProvider-Cwh9D2D_.cjs.map → FluidProvider-Sc51VlLw.cjs.map} +1 -1
  15. package/dist/{MessagingScreen-68mp7aIc.mjs → MessagingScreen-CMxjIURw.mjs} +3 -3
  16. package/dist/{MessagingScreen-68mp7aIc.mjs.map → MessagingScreen-CMxjIURw.mjs.map} +1 -1
  17. package/dist/{MessagingScreen-BIFFfpwv.cjs → MessagingScreen-CdHBUykK.cjs} +3 -3
  18. package/dist/{MessagingScreen-DbXef2ee.mjs → MessagingScreen-Cx0bbvfs.mjs} +3 -3
  19. package/dist/{MessagingScreen-Cljq2xIQ.cjs → MessagingScreen-r67FUDf1.cjs} +3 -3
  20. package/dist/{MessagingScreen-Cljq2xIQ.cjs.map → MessagingScreen-r67FUDf1.cjs.map} +1 -1
  21. package/dist/{MySiteScreen-DMDOaROq.cjs → MySiteScreen-Cf-SZsqW.cjs} +3 -3
  22. package/dist/{MySiteScreen-DMDOaROq.cjs.map → MySiteScreen-Cf-SZsqW.cjs.map} +1 -1
  23. package/dist/{MySiteScreen-BEl882-5.mjs → MySiteScreen-D9VeDi4b.mjs} +3 -3
  24. package/dist/{MySiteScreen-BEl882-5.mjs.map → MySiteScreen-D9VeDi4b.mjs.map} +1 -1
  25. package/dist/{MySiteScreen-Dy1r8mnN.cjs → MySiteScreen-W04JlkW0.cjs} +4 -4
  26. package/dist/{NestedWidget-zn_USrld.cjs → NestedWidget-BXbQcApb.cjs} +1 -1
  27. package/dist/{NestedWidget-L8ppxJib.mjs → NestedWidget-CzSHHhEl.mjs} +2 -2
  28. package/dist/NestedWidget-CzSHHhEl.mjs.map +1 -0
  29. package/dist/{NestedWidget-BGY4LSQq.cjs → NestedWidget-iootjKIl.cjs} +2 -2
  30. package/dist/NestedWidget-iootjKIl.cjs.map +1 -0
  31. package/dist/{OrdersScreen-CPJX2XiN.cjs → OrdersScreen-BaqQzT1F.cjs} +3 -3
  32. package/dist/{OrdersScreen-CPJX2XiN.cjs.map → OrdersScreen-BaqQzT1F.cjs.map} +1 -1
  33. package/dist/{OrdersScreen-BkxKQpwS.mjs → OrdersScreen-D0TnBQc5.mjs} +3 -3
  34. package/dist/{OrdersScreen-BkxKQpwS.mjs.map → OrdersScreen-D0TnBQc5.mjs.map} +1 -1
  35. package/dist/{OrdersScreen-BiuWTsM3.cjs → OrdersScreen-DCOzHNIy.cjs} +3 -3
  36. package/dist/{ProductsScreen-BIO6jWLT.cjs → ProductsScreen-BCt1YkKY.cjs} +5 -5
  37. package/dist/{ProductsScreen-C2qXwQfN.mjs → ProductsScreen-Bdrk83gQ.mjs} +7 -6
  38. package/dist/ProductsScreen-Bdrk83gQ.mjs.map +1 -0
  39. package/dist/{ProductsScreen-CCq96wPT.mjs → ProductsScreen-CAAE2eNw.mjs} +5 -5
  40. package/dist/{ProductsScreen-BQVP1OTk.cjs → ProductsScreen-O-SPvBZ6.cjs} +7 -6
  41. package/dist/ProductsScreen-O-SPvBZ6.cjs.map +1 -0
  42. package/dist/{ProfileScreen-DKJrpeMw.mjs → ProfileScreen-Age0TtEY.mjs} +3 -3
  43. package/dist/{ProfileScreen-DKJrpeMw.mjs.map → ProfileScreen-Age0TtEY.mjs.map} +1 -1
  44. package/dist/{ProfileScreen-ueK01fjb.cjs → ProfileScreen-C8fpr9c3.cjs} +3 -3
  45. package/dist/{ProfileScreen-ueK01fjb.cjs.map → ProfileScreen-C8fpr9c3.cjs.map} +1 -1
  46. package/dist/{ProfileScreen-C6qbR0YJ.cjs → ProfileScreen-DEtgeBnE.cjs} +3 -3
  47. package/dist/{ShareablesScreen-C1hVCjyE.mjs → ShareablesScreen-CdEKba0T.mjs} +7 -7
  48. package/dist/{ShareablesScreen-C1hVCjyE.mjs.map → ShareablesScreen-CdEKba0T.mjs.map} +1 -1
  49. package/dist/{ShareablesScreen-rw5D509g.cjs → ShareablesScreen-Dxg40SZU.cjs} +5 -5
  50. package/dist/{ShareablesScreen-CDSudtJM.cjs → ShareablesScreen-XqD1dh8j.cjs} +7 -7
  51. package/dist/{ShareablesScreen-CDSudtJM.cjs.map → ShareablesScreen-XqD1dh8j.cjs.map} +1 -1
  52. package/dist/{ShareablesScreen-DkaKw-gX.mjs → ShareablesScreen-k3isnSnr.mjs} +5 -5
  53. package/dist/{ShopScreen-jb7kYSxf.cjs → ShopScreen-BYvp-I31.cjs} +67 -51
  54. package/dist/ShopScreen-BYvp-I31.cjs.map +1 -0
  55. package/dist/{ShopScreen-Bj63FiDO.mjs → ShopScreen-C5mWkHyB.mjs} +67 -51
  56. package/dist/ShopScreen-C5mWkHyB.mjs.map +1 -0
  57. package/dist/{ShopScreen-8WqLfyiR.cjs → ShopScreen-DxEIU243.cjs} +3 -3
  58. package/dist/{SubscriptionsScreen-BF4NqbpU.cjs → SubscriptionsScreen-BvS7o_XP.cjs} +3 -3
  59. package/dist/{SubscriptionsScreen-BF4NqbpU.cjs.map → SubscriptionsScreen-BvS7o_XP.cjs.map} +1 -1
  60. package/dist/{SubscriptionsScreen-BSDYjJvj.mjs → SubscriptionsScreen-CBqgpat5.mjs} +3 -3
  61. package/dist/{SubscriptionsScreen-BSDYjJvj.mjs.map → SubscriptionsScreen-CBqgpat5.mjs.map} +1 -1
  62. package/dist/{SubscriptionsScreen-BRx_ocC3.cjs → SubscriptionsScreen-IbsNz0Ki.cjs} +3 -3
  63. package/dist/{dist-BF_4vk1z.cjs → dist-BSbac3uh.cjs} +1 -1
  64. package/dist/{dist-BF_4vk1z.cjs.map → dist-BSbac3uh.cjs.map} +1 -1
  65. package/dist/index.cjs +37 -37
  66. package/dist/index.d.cts.map +1 -1
  67. package/dist/index.d.mts.map +1 -1
  68. package/dist/index.mjs +37 -37
  69. package/dist/products-BAtIML76.cjs +114 -0
  70. package/dist/{products-BKZ1siXg.cjs.map → products-BAtIML76.cjs.map} +1 -1
  71. package/dist/products-StJIeia3.mjs +61 -0
  72. package/dist/{products-DOO1TBcm.mjs.map → products-StJIeia3.mjs.map} +1 -1
  73. package/dist/{sortable.esm-Cz-CP2N8.mjs → sortable.esm-DSrWP4x9.mjs} +1 -1
  74. package/dist/{sortable.esm-Cz-CP2N8.mjs.map → sortable.esm-DSrWP4x9.mjs.map} +1 -1
  75. package/dist/{src-Zv3-NSUf.cjs → src-CMByt6YP.cjs} +1 -1
  76. package/dist/{src-CN7diUEw.mjs.map → src-CMByt6YP.cjs.map} +1 -1
  77. package/dist/{src-Ih5vEO6p.mjs → src-CyrJPIY1.mjs} +3 -3
  78. package/dist/{src-Ih5vEO6p.mjs.map → src-CyrJPIY1.mjs.map} +1 -1
  79. package/dist/{src-CN7diUEw.mjs → src-DryOJTBW.mjs} +1 -1
  80. package/dist/{src-Zv3-NSUf.cjs.map → src-DryOJTBW.mjs.map} +1 -1
  81. package/dist/{src-BbJs882O.cjs → src-t3t8YW1J.cjs} +3 -3
  82. package/dist/{src-BbJs882O.cjs.map → src-t3t8YW1J.cjs.map} +1 -1
  83. package/dist/{use-account-clients-Bg1xqjMk.mjs → use-account-clients-CSWgrCKK.mjs} +2 -2
  84. package/dist/{use-account-clients-Bg1xqjMk.mjs.map → use-account-clients-CSWgrCKK.mjs.map} +1 -1
  85. package/dist/{use-account-clients-BVb_nhg7.cjs → use-account-clients-DaliJYMa.cjs} +2 -2
  86. package/dist/{use-account-clients-BVb_nhg7.cjs.map → use-account-clients-DaliJYMa.cjs.map} +1 -1
  87. package/dist/{use-current-user-DFQ8gYkR.cjs → use-current-user-5erIFUd6.cjs} +3 -3
  88. package/dist/{use-current-user-DFQ8gYkR.cjs.map → use-current-user-5erIFUd6.cjs.map} +1 -1
  89. package/dist/{use-current-user-DqLNoj-3.mjs → use-current-user-BBQg1iYf.mjs} +3 -3
  90. package/dist/{use-current-user-DqLNoj-3.mjs.map → use-current-user-BBQg1iYf.mjs.map} +1 -1
  91. package/dist/{use-customer-account-CY9HqWvJ.mjs → use-customer-account-CRYpHpFM.mjs} +3 -3
  92. package/dist/{use-customer-account-CY9HqWvJ.mjs.map → use-customer-account-CRYpHpFM.mjs.map} +1 -1
  93. package/dist/{use-customer-account-D599KeSp.cjs → use-customer-account-Dzdps4By.cjs} +3 -3
  94. package/dist/{use-customer-account-D599KeSp.cjs.map → use-customer-account-Dzdps4By.cjs.map} +1 -1
  95. package/dist/{use-fluid-api-DHF7svon.cjs → use-fluid-api-BUitsoDu.cjs} +2 -2
  96. package/dist/{use-fluid-api-DHF7svon.cjs.map → use-fluid-api-BUitsoDu.cjs.map} +1 -1
  97. package/dist/{use-fluid-api-CyK8Yoj-.mjs → use-fluid-api-C5ZLs2TP.mjs} +2 -2
  98. package/dist/{use-fluid-api-CyK8Yoj-.mjs.map → use-fluid-api-C5ZLs2TP.mjs.map} +1 -1
  99. package/package.json +18 -18
  100. package/dist/NestedWidget-BGY4LSQq.cjs.map +0 -1
  101. package/dist/NestedWidget-L8ppxJib.mjs.map +0 -1
  102. package/dist/ProductsScreen-BQVP1OTk.cjs.map +0 -1
  103. package/dist/ProductsScreen-C2qXwQfN.mjs.map +0 -1
  104. package/dist/ShopScreen-Bj63FiDO.mjs.map +0 -1
  105. package/dist/ShopScreen-jb7kYSxf.cjs.map +0 -1
  106. package/dist/products-BKZ1siXg.cjs +0 -29
  107. package/dist/products-DOO1TBcm.mjs +0 -18
@@ -1,4 +1,4 @@
1
- import { bt as createFetchClient, l as useFluidAuthContext, n as useFluidContext } from "./FluidProvider-CRiIzR8g.mjs";
1
+ import { bt as createFetchClient, l as useFluidAuthContext, n as useFluidContext } from "./FluidProvider-Eohedipr.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-Bg1xqjMk.mjs.map
118
+ //# sourceMappingURL=use-account-clients-CSWgrCKK.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-account-clients-Bg1xqjMk.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
+ {"version":3,"file":"use-account-clients-CSWgrCKK.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
1
  require("./chunk-9hOWP6kD.cjs");
2
- const require_FluidProvider = require("./FluidProvider-Cwh9D2D_.cjs");
2
+ const require_FluidProvider = require("./FluidProvider-Sc51VlLw.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-BVb_nhg7.cjs.map
154
+ //# sourceMappingURL=use-account-clients-DaliJYMa.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-account-clients-BVb_nhg7.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
+ {"version":3,"file":"use-account-clients-DaliJYMa.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,6 +1,6 @@
1
1
  require("./chunk-9hOWP6kD.cjs");
2
- const require_FluidProvider = require("./FluidProvider-Cwh9D2D_.cjs");
3
- const require_use_fluid_api = require("./use-fluid-api-DHF7svon.cjs");
2
+ const require_FluidProvider = require("./FluidProvider-Sc51VlLw.cjs");
3
+ const require_use_fluid_api = require("./use-fluid-api-BUitsoDu.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-DFQ8gYkR.cjs.map
125
+ //# sourceMappingURL=use-current-user-5erIFUd6.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-current-user-DFQ8gYkR.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
+ {"version":3,"file":"use-current-user-5erIFUd6.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 { l as useFluidAuthContext } from "./FluidProvider-CRiIzR8g.mjs";
2
- import { t as useFluidApi } from "./use-fluid-api-CyK8Yoj-.mjs";
1
+ import { l as useFluidAuthContext } from "./FluidProvider-Eohedipr.mjs";
2
+ import { t as useFluidApi } from "./use-fluid-api-C5ZLs2TP.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-DqLNoj-3.mjs.map
101
+ //# sourceMappingURL=use-current-user-BBQg1iYf.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-current-user-DqLNoj-3.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
+ {"version":3,"file":"use-current-user-BBQg1iYf.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,5 +1,5 @@
1
- import { _t as fetchCustomerAccount } from "./FluidProvider-CRiIzR8g.mjs";
2
- import { n as useFluidPayClient, o as useFluidAuth } from "./use-account-clients-Bg1xqjMk.mjs";
1
+ import { _t as fetchCustomerAccount } from "./FluidProvider-Eohedipr.mjs";
2
+ import { n as useFluidPayClient, o as useFluidAuth } from "./use-account-clients-CSWgrCKK.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-CY9HqWvJ.mjs.map
23
+ //# sourceMappingURL=use-customer-account-CRYpHpFM.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-customer-account-CY9HqWvJ.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
+ {"version":3,"file":"use-customer-account-CRYpHpFM.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-Cwh9D2D_.cjs");
3
- const require_use_account_clients = require("./use-account-clients-BVb_nhg7.cjs");
2
+ const require_FluidProvider = require("./FluidProvider-Sc51VlLw.cjs");
3
+ const require_use_account_clients = require("./use-account-clients-DaliJYMa.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-D599KeSp.cjs.map
29
+ //# sourceMappingURL=use-customer-account-Dzdps4By.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-customer-account-D599KeSp.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
+ {"version":3,"file":"use-customer-account-Dzdps4By.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
- const require_FluidProvider = require("./FluidProvider-Cwh9D2D_.cjs");
1
+ const require_FluidProvider = require("./FluidProvider-Sc51VlLw.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-DHF7svon.cjs.map
32
+ //# sourceMappingURL=use-fluid-api-BUitsoDu.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-fluid-api-DHF7svon.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"}
1
+ {"version":3,"file":"use-fluid-api-BUitsoDu.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"}
@@ -1,4 +1,4 @@
1
- import { n as useFluidContext } from "./FluidProvider-CRiIzR8g.mjs";
1
+ import { n as useFluidContext } from "./FluidProvider-Eohedipr.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-CyK8Yoj-.mjs.map
27
+ //# sourceMappingURL=use-fluid-api-C5ZLs2TP.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-fluid-api-CyK8Yoj-.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
+ {"version":3,"file":"use-fluid-api-C5ZLs2TP.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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-app/portal-sdk",
3
- "version": "0.1.90",
3
+ "version": "0.1.92",
4
4
  "description": "SDK for building custom Fluid portals",
5
5
  "files": [
6
6
  "dist",
@@ -65,46 +65,46 @@
65
65
  "tsdown": "^0.21.0",
66
66
  "typescript": "^5",
67
67
  "zod": "4.3.5",
68
- "@fluid-app/auth": "0.1.0",
69
68
  "@fluid-app/api-client-core": "0.1.0",
70
69
  "@fluid-app/cart-ui": "0.1.12",
70
+ "@fluid-app/auth": "0.1.0",
71
71
  "@fluid-app/company-switcher-core": "0.1.0",
72
- "@fluid-app/company-switcher-ui": "0.1.0",
73
72
  "@fluid-app/contacts-ui": "0.1.0",
73
+ "@fluid-app/company-switcher-ui": "0.1.0",
74
+ "@fluid-app/messaging-api-client": "0.1.0",
74
75
  "@fluid-app/fluid-pay-api-client": "0.1.0",
75
- "@fluid-app/file-picker-api-client": "0.1.0",
76
76
  "@fluid-app/fluidos-api-client": "0.1.0",
77
- "@fluid-app/messaging-api-client": "0.1.0",
78
- "@fluid-app/mysite-ui": "0.1.0",
79
- "@fluid-app/orders-api-client": "0.1.0",
80
- "@fluid-app/orders-core": "0.1.0",
81
77
  "@fluid-app/messaging-core": "0.1.0",
82
78
  "@fluid-app/messaging-ui": "0.1.0",
83
- "@fluid-app/permissions": "0.1.0",
79
+ "@fluid-app/file-picker-api-client": "0.1.0",
80
+ "@fluid-app/mysite-ui": "0.1.0",
84
81
  "@fluid-app/orders-ui": "0.1.0",
85
- "@fluid-app/portal-app-download-ui": "0.1.0",
82
+ "@fluid-app/orders-core": "0.1.0",
83
+ "@fluid-app/permissions": "0.1.0",
86
84
  "@fluid-app/portal-core": "0.1.23",
85
+ "@fluid-app/orders-api-client": "0.1.0",
87
86
  "@fluid-app/portal-preview": "0.1.0",
88
- "@fluid-app/portal-pro-upgrade-ui": "0.1.0",
87
+ "@fluid-app/portal-app-download-ui": "0.1.0",
89
88
  "@fluid-app/portal-widgets": "0.1.22",
90
- "@fluid-app/products-api-client": "0.1.0",
91
- "@fluid-app/portal-react": "0.1.0",
92
89
  "@fluid-app/products-core": "0.1.0",
90
+ "@fluid-app/portal-react": "0.1.0",
91
+ "@fluid-app/portal-pro-upgrade-ui": "0.1.0",
93
92
  "@fluid-app/profile-ui": "0.1.0",
94
93
  "@fluid-app/profile-core": "0.1.0",
95
94
  "@fluid-app/query-persister": "0.1.0",
96
95
  "@fluid-app/shareables-api-client": "0.1.0",
97
96
  "@fluid-app/shareables-core": "0.1.0",
97
+ "@fluid-app/shop-ui": "0.1.0",
98
+ "@fluid-app/subscriptions-core": "0.1.0",
98
99
  "@fluid-app/shareables-ui": "0.1.0",
99
100
  "@fluid-app/subscriptions-api-client": "0.1.0",
100
- "@fluid-app/shop-ui": "0.1.0",
101
101
  "@fluid-app/subscriptions-ui": "0.1.0",
102
- "@fluid-app/subscriptions-core": "0.1.0",
102
+ "@fluid-app/products-api-client": "0.1.0",
103
103
  "@fluid-app/typescript-config": "0.0.0",
104
- "@fluid-app/ui-primitives": "0.1.13",
105
- "@fluid-app/user-notes-api-client": "0.1.0",
106
104
  "@fluid-app/user-contacts-api-client": "0.1.0",
107
- "@fluid-app/user-tasks-api-client": "0.1.0"
105
+ "@fluid-app/user-notes-api-client": "0.1.0",
106
+ "@fluid-app/user-tasks-api-client": "0.1.0",
107
+ "@fluid-app/ui-primitives": "0.1.13"
108
108
  },
109
109
  "peerDependencies": {
110
110
  "@hookform/resolvers": "^5.2.2",
@@ -1 +0,0 @@
1
- {"version":3,"file":"NestedWidget-BGY4LSQq.cjs","names":["useWidgetInteraction","borderWidthClasses","borderColorClasses","MediaRenderer","getMediaPropsFromShareable","gapValues","ScrollArrows","getFontSizeField","getColorField","getHeightField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getGapField"],"sources":["../../widgets/src/widgets/NestedWidget.tsx"],"sourcesContent":["import { useRef, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n AlignOptions,\n GapOptions,\n BackgroundValue,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n} from \"../core/fields\";\nimport { ScrollArrows } from \"../ui/scroll-arrows\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\nconst DEFAULT_SHAREABLES: ShareableItem[] = [];\n\ntype NestedWidgetProps = ComponentProps<\"div\"> & {\n // Content\n resource?: ShareableItem;\n titleEnabled?: boolean;\n titleText?: string;\n shareables?: ShareableItem[];\n\n // Layout\n gap?: GapOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n primaryMediaHeight?: string;\n\n // Title styling\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n titleAlignment?: AlignOptions;\n\n // Nested media styling\n nestedTextColor?: ColorOptions;\n background?: BackgroundValue;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n};\n\nexport function NestedWidget({\n resource,\n titleEnabled = true,\n titleText = \"Featured Collection\",\n shareables = DEFAULT_SHAREABLES,\n gap = \"md\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n primaryMediaHeight = \"400px\",\n titleFontSize = \"xl\",\n titleColor = \"background\",\n titleAlignment = { horizontal: \"left\", vertical: \"bottom\" },\n nestedTextColor = \"foreground\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 50,\n className,\n ...props\n}: NestedWidgetProps): React.JSX.Element {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const scrollByAmount = (direction: \"prev\" | \"next\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const computedGap = parseFloat(getComputedStyle(container).gap) || 0;\n const firstItem = container.firstElementChild as HTMLElement | null;\n const itemWidth = firstItem?.offsetWidth ?? 0;\n const scrollAmount = itemWidth + computedGap;\n\n container.scrollTo({\n left:\n container.scrollLeft +\n (direction === \"next\" ? scrollAmount : -scrollAmount),\n behavior: \"smooth\",\n });\n };\n\n // Cap border radius for the primary media container: \"full\" creates a circle that clips\n // the absolutely-positioned title overlay to the narrow bottom of the circle.\n const primaryMediaRadius = borderRadius === \"full\" ? \"2xl\" : borderRadius;\n\n const { onItemClick } = useWidgetInteraction();\n\n const hasNestedMedia = shareables.length > 0;\n\n const titleAlignmentClasses = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n };\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 return (\n <div\n className={`@container flex w-full overflow-hidden p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} ${className}`}\n {...props}\n style={{\n maxHeight: primaryMediaHeight,\n backgroundImage: backgroundImage,\n }}\n >\n {/* Primary Media Container - Full width on mobile, fixed on desktop */}\n <div\n className={`relative @md:flex-none`}\n style={{\n width: primaryMediaHeight,\n }}\n >\n {/* Media + overlay clipped to rounded shape — title is a sibling so it isn't clipped */}\n <div\n className={`overflow-hidden rounded-${primaryMediaRadius} absolute inset-0`}\n >\n <MediaRenderer\n {...(resource ? getMediaPropsFromShareable(resource) : {})}\n autoplay\n loop\n muted\n />\n\n {/* Overlay */}\n {overlayEnabled && (\n <div\n className={`pointer-events-none absolute inset-0 z-10 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n\n {/* Title and Mobile Nested Media — outside the overflow-hidden clip */}\n {((titleEnabled && titleText) || hasNestedMedia) && (\n <div\n className={`absolute z-20 w-full ${titleAlignmentClasses[titleAlignment?.horizontal ?? \"left\"]} p-${padding} ${\n titleAlignment.vertical === \"top\"\n ? `top-0 pt-${padding}`\n : titleAlignment.vertical === \"center\"\n ? \"top-1/2 -translate-y-1/2\"\n : `bottom-0 pb-${padding}`\n }`}\n >\n {titleEnabled && titleText && (\n <h2\n className={`font-header leading-tight font-bold text-${titleColor} text-${titleFontSize === \"md\" ? \"base\" : titleFontSize}`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Mobile: Products overlay inside primary media */}\n {hasNestedMedia && (\n <div className={`pt-${padding} @md:hidden`}>\n <div\n className={`flex overflow-x-auto gap-${gapValues[gap]} bg-transparent`}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col items-center ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-40 overflow-hidden rounded-${borderRadius}`}\n >\n <MediaRenderer\n {...getMediaPropsFromShareable(shareable)}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Desktop: Products Container - Single row beside primary media */}\n {hasNestedMedia && (\n <div\n className={`relative hidden min-w-0 self-stretch @md:flex @md:flex-1 px-${padding}`}\n >\n <div\n ref={scrollContainerRef}\n className={`flex h-full flex-row overflow-x-auto gap-${gapValues[gap]}`}\n style={{ scrollSnapType: \"x mandatory\" }}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex flex-col gap-1 ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n style={{\n width: `calc(${primaryMediaHeight} * 0.75)`,\n scrollSnapAlign: \"start\",\n }}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-full rounded-${borderRadius} overflow-hidden`}\n >\n <MediaRenderer {...getMediaPropsFromShareable(shareable)} />\n </div>\n <span className={`flex-none text-sm text-${nestedTextColor}`}>\n <p className=\"truncate\">{shareable.title || \"\"}</p>\n <p className=\"truncate\">\n {((shareable.display_price as string) ?? shareable.price) ||\n \"\"}\n </p>\n </span>\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n <div\n className={`absolute inset-x-0 top-1/2 flex w-full -translate-y-1/2 items-center justify-between px-8`}\n >\n <ScrollArrows\n onPrevious={() => scrollByAmount(\"prev\")}\n onNext={() => scrollByAmount(\"next\")}\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const nestedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"NestedWidget\",\n displayName: \"Nested Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"shareables\"],\n fields: [\n // Content tab - Resource group\n {\n key: \"resource\",\n label: \"Primary Media\",\n type: \"resource\",\n description: \"Select the primary media displayed in the large panel\",\n allowedTypes: [\"Medium\"],\n tab: \"styling\",\n group: \"Content\",\n },\n // Content tab - Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed over the primary media\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Main title displayed over the primary media\",\n defaultValue: \"Featured Collection\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n label: \"Title Font Size\",\n defaultValue: \"xl\",\n key: \"titleFontSize\",\n description: \"Font size for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n // Styling tab - Design group\n getHeightField({\n key: \"primaryMediaHeight\",\n label: \"Primary Media Height\",\n description: \"Height of the primary media container\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"titleAlignment\",\n label: \"Content Alignment\",\n type: \"alignment\",\n description: \"Alignment of the content inside the primary media\",\n defaultValue: { horizontal: \"left\", vertical: \"bottom\" },\n options: {\n horizontalEnabled: true,\n verticalEnabled: true,\n },\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 getPaddingField({\n defaultValue: 4,\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding used throughout the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n defaultValue: \"md\",\n label: \"Border Radius\",\n key: \"borderRadius\",\n description: \"Rounded corners for the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\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 widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description:\n \"Add a dark overlay to the primary media for better text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay effect\",\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: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n // Styling tab - Nested Media Styling group\n getGapField({\n label: \"Gap\",\n defaultValue: \"md\",\n key: \"gap\",\n description: \"Gap between nested media items\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n getColorField({\n defaultValue: \"foreground\",\n key: \"nestedTextColor\",\n label: \"Nested Text Color\",\n description: \"Color for nested media labels\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n {\n type: \"background\",\n defaultValue: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background color for nested media container\",\n tab: \"styling\",\n group: \"Nested Design\",\n },\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure dynamic data fetching from an API\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n // Per-item configuration schema for custom data sources\n itemConfigSchema: {\n description: \"Configure settings for this item\",\n fields: [\n {\n key: \"title\",\n label: \"Custom Title\",\n type: \"text\",\n description: \"Override the item's title for this widget\",\n },\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":";;;;;;;;AAoCA,MAAM,qBAAsC,EAAE;AAgC9C,SAAgB,aAAa,EAC3B,UACA,eAAe,MACf,YAAY,uBACZ,aAAa,oBACb,MAAM,MACN,UAAU,GACV,eAAe,MACf,cAAc,QACd,cAAc,SACd,qBAAqB,SACrB,gBAAgB,MAChB,aAAa,cACb,iBAAiB;CAAE,YAAY;CAAQ,UAAU;CAAU,EAC3D,kBAAkB,cAClB,aAAa;CACX,MAAM;CACN,OAAO;CACR,EACD,iBAAiB,MACjB,cAAc,YACd,mBAAmB,IACnB,WACA,GAAG,SACoC;CACvC,MAAM,sBAAA,GAAA,MAAA,QAA4C,KAAK;CAEvD,MAAM,kBAAkB,cAA+B;EACrD,MAAM,YAAY,mBAAmB;AACrC,MAAI,CAAC,UAAW;EAEhB,MAAM,cAAc,WAAW,iBAAiB,UAAU,CAAC,IAAI,IAAI;EAGnE,MAAM,gBAFY,UAAU,mBACC,eAAe,KACX;AAEjC,YAAU,SAAS;GACjB,MACE,UAAU,cACT,cAAc,SAAS,eAAe,CAAC;GAC1C,UAAU;GACX,CAAC;;CAKJ,MAAM,qBAAqB,iBAAiB,SAAS,QAAQ;CAE7D,MAAM,EAAE,gBAAgBA,iCAAAA,sBAAsB;CAE9C,MAAM,iBAAiB,WAAW,SAAS;CAE3C,MAAM,wBAAwB;EAC5B,MAAM;EACN,QAAQ;EACR,OAAO;EACR;CAED,MAAM,kBAAkB,WAAW,SAAS;CAC5C,MAAM,mBACH,WAAW,UAAU,aAAa,WAAW,UAAU,aACxD,WAAW,SAAS,UAChB,OAAO,WAAW,SAAS,aAAa,WAAW,SAAS,SAAS,KACrE;AAEN,QACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;EACE,WAAW,4CAA4C,QAAQ,WAAW,aAAa,GAAGC,mBAAAA,mBAAmB,aAAa,GAAG,gBAAgB,SAASC,mBAAAA,mBAAmB,eAAe,GAAG,MAAM,gBAAgB,GAAG;EACpN,GAAI;EACJ,OAAO;GACL,WAAW;GACM;GAClB;YANH,CASE,iBAAA,GAAA,kBAAA,MAAC,OAAD;GACE,WAAW;GACX,OAAO,EACL,OAAO,oBACR;aAJH,CAOE,iBAAA,GAAA,kBAAA,MAAC,OAAD;IACE,WAAW,2BAA2B,mBAAmB;cAD3D,CAGE,iBAAA,GAAA,kBAAA,KAACC,sBAAAA,eAAD;KACE,GAAK,WAAWC,sBAAAA,2BAA2B,SAAS,GAAG,EAAE;KACzD,UAAA;KACA,MAAA;KACA,OAAA;KACA,CAAA,EAGD,kBACC,iBAAA,GAAA,kBAAA,KAAC,OAAD;KACE,WAAW,6CACT,gBAAgB,aACZ,+CACA;KAEN,OAAO,EACL,UACG,OAAO,OAAO,iBAAiB,CAAC,QAAQ,KAAK,GAAG,CAAC,IAAI,MACtD,KACH;KACD,CAAA,CAEA;QAGH,gBAAgB,aAAc,mBAC/B,iBAAA,GAAA,kBAAA,MAAC,OAAD;IACE,WAAW,wBAAwB,sBAAsB,gBAAgB,cAAc,QAAQ,KAAK,QAAQ,GAC1G,eAAe,aAAa,QACxB,YAAY,YACZ,eAAe,aAAa,WAC1B,6BACA,eAAe;cANzB,CASG,gBAAgB,aACf,iBAAA,GAAA,kBAAA,KAAC,MAAD;KACE,WAAW,4CAA4C,WAAW,QAAQ,kBAAkB,OAAO,SAAS;eAE3G;KACE,CAAA,EAIN,kBACC,iBAAA,GAAA,kBAAA,KAAC,OAAD;KAAK,WAAW,MAAM,QAAQ;eAC5B,iBAAA,GAAA,kBAAA,KAAC,OAAD;MACE,WAAW,4BAA4BC,mBAAAA,UAAU,KAAK;gBAErD,WAAW,KAAK,cACf,iBAAA,GAAA,kBAAA,KAAC,OAAD;OAEE,WAAW,uCAAuC,cAAc,mBAAmB;OACnF,GAAK,cACD;QACE,MAAM;QACN,UAAU;QACV,eAAe,YAAY,UAAU;QACrC,YAAY,MAA2B;AACrC,aAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,YAAE,gBAAgB;AAClB,sBAAY,UAAU;;;QAG3B,GACD,EAAE;iBAEN,iBAAA,GAAA,kBAAA,KAAC,OAAD;QACE,WAAW,2CAA2C;kBAEtD,iBAAA,GAAA,kBAAA,KAACF,sBAAAA,eAAD,EACE,GAAIC,sBAAAA,2BAA2B,UAAU,EACzC,CAAA;QACE,CAAA;OACF,EAvBC,UAAU,GAuBX,CACN;MACE,CAAA;KACF,CAAA,CAEJ;MAEJ;MAGL,kBACC,iBAAA,GAAA,kBAAA,MAAC,OAAD;GACE,WAAW,+DAA+D;aAD5E,CAGE,iBAAA,GAAA,kBAAA,KAAC,OAAD;IACE,KAAK;IACL,WAAW,4CAA4CC,mBAAAA,UAAU;IACjE,OAAO,EAAE,gBAAgB,eAAe;cAEvC,WAAW,KAAK,cACf,iBAAA,GAAA,kBAAA,MAAC,OAAD;KAEE,WAAW,uBAAuB,cAAc,mBAAmB;KACnE,OAAO;MACL,OAAO,QAAQ,mBAAmB;MAClC,iBAAiB;MAClB;KACD,GAAK,cACD;MACE,MAAM;MACN,UAAU;MACV,eAAe,YAAY,UAAU;MACrC,YAAY,MAA2B;AACrC,WAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,UAAE,gBAAgB;AAClB,oBAAY,UAAU;;;MAG3B,GACD,EAAE;eAnBR,CAqBE,iBAAA,GAAA,kBAAA,KAAC,OAAD;MACE,WAAW,6BAA6B,aAAa;gBAErD,iBAAA,GAAA,kBAAA,KAACF,sBAAAA,eAAD,EAAe,GAAIC,sBAAAA,2BAA2B,UAAU,EAAI,CAAA;MACxD,CAAA,EACN,iBAAA,GAAA,kBAAA,MAAC,QAAD;MAAM,WAAW,0BAA0B;gBAA3C,CACE,iBAAA,GAAA,kBAAA,KAAC,KAAD;OAAG,WAAU;iBAAY,UAAU,SAAS;OAAO,CAAA,EACnD,iBAAA,GAAA,kBAAA,KAAC,KAAD;OAAG,WAAU;kBACR,UAAU,iBAA4B,UAAU,UACjD;OACA,CAAA,CACC;QACH;OAhCC,UAAU,GAgCX,CACN;IACE,CAAA,EAGN,iBAAA,GAAA,kBAAA,KAAC,OAAD;IACE,WAAW;cAEX,iBAAA,GAAA,kBAAA,KAACE,sBAAAA,cAAD;KACE,kBAAkB,eAAe,OAAO;KACxC,cAAc,eAAe,OAAO;KACpC,CAAA;IACE,CAAA,CACF;KAEJ;;;AAIV,MAAa,6BAAmD;CAC9D,YAAY;CACZ,aAAa;CACb,YAAY,CACV;EAAE,IAAI;EAAW,OAAO;EAAW,EACnC;EAAE,IAAI;EAAQ,OAAO;EAAQ,CAC9B;CACD,uBAAuB,CAAC,aAAa;CACrC,QAAQ;EAEN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc,CAAC,SAAS;GACxB,KAAK;GACL,OAAO;GACR;EAED;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,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACDC,mBAAAA,iBAAiB;GACf,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACFC,mBAAAA,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAEFC,mBAAAA,eAAe;GACb,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;IAAE,YAAY;IAAQ,UAAU;IAAU;GACxD,SAAS;IACP,mBAAmB;IACnB,iBAAiB;IAClB;GACD,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACDC,mBAAAA,gBAAgB;GACd,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,qBAAqB;GACnB,cAAc;GACd,OAAO;GACP,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;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,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;EAEDC,mBAAAA,YAAY;GACV,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACFN,mBAAAA,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,QAAQ,CACN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACd,CACF;EACF;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"NestedWidget-L8ppxJib.mjs","names":[],"sources":["../../widgets/src/widgets/NestedWidget.tsx"],"sourcesContent":["import { useRef, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n AlignOptions,\n GapOptions,\n BackgroundValue,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n} from \"../core/fields\";\nimport { ScrollArrows } from \"../ui/scroll-arrows\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\nconst DEFAULT_SHAREABLES: ShareableItem[] = [];\n\ntype NestedWidgetProps = ComponentProps<\"div\"> & {\n // Content\n resource?: ShareableItem;\n titleEnabled?: boolean;\n titleText?: string;\n shareables?: ShareableItem[];\n\n // Layout\n gap?: GapOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n primaryMediaHeight?: string;\n\n // Title styling\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n titleAlignment?: AlignOptions;\n\n // Nested media styling\n nestedTextColor?: ColorOptions;\n background?: BackgroundValue;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n};\n\nexport function NestedWidget({\n resource,\n titleEnabled = true,\n titleText = \"Featured Collection\",\n shareables = DEFAULT_SHAREABLES,\n gap = \"md\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n primaryMediaHeight = \"400px\",\n titleFontSize = \"xl\",\n titleColor = \"background\",\n titleAlignment = { horizontal: \"left\", vertical: \"bottom\" },\n nestedTextColor = \"foreground\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 50,\n className,\n ...props\n}: NestedWidgetProps): React.JSX.Element {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const scrollByAmount = (direction: \"prev\" | \"next\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const computedGap = parseFloat(getComputedStyle(container).gap) || 0;\n const firstItem = container.firstElementChild as HTMLElement | null;\n const itemWidth = firstItem?.offsetWidth ?? 0;\n const scrollAmount = itemWidth + computedGap;\n\n container.scrollTo({\n left:\n container.scrollLeft +\n (direction === \"next\" ? scrollAmount : -scrollAmount),\n behavior: \"smooth\",\n });\n };\n\n // Cap border radius for the primary media container: \"full\" creates a circle that clips\n // the absolutely-positioned title overlay to the narrow bottom of the circle.\n const primaryMediaRadius = borderRadius === \"full\" ? \"2xl\" : borderRadius;\n\n const { onItemClick } = useWidgetInteraction();\n\n const hasNestedMedia = shareables.length > 0;\n\n const titleAlignmentClasses = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n };\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 return (\n <div\n className={`@container flex w-full overflow-hidden p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} ${className}`}\n {...props}\n style={{\n maxHeight: primaryMediaHeight,\n backgroundImage: backgroundImage,\n }}\n >\n {/* Primary Media Container - Full width on mobile, fixed on desktop */}\n <div\n className={`relative @md:flex-none`}\n style={{\n width: primaryMediaHeight,\n }}\n >\n {/* Media + overlay clipped to rounded shape — title is a sibling so it isn't clipped */}\n <div\n className={`overflow-hidden rounded-${primaryMediaRadius} absolute inset-0`}\n >\n <MediaRenderer\n {...(resource ? getMediaPropsFromShareable(resource) : {})}\n autoplay\n loop\n muted\n />\n\n {/* Overlay */}\n {overlayEnabled && (\n <div\n className={`pointer-events-none absolute inset-0 z-10 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n\n {/* Title and Mobile Nested Media — outside the overflow-hidden clip */}\n {((titleEnabled && titleText) || hasNestedMedia) && (\n <div\n className={`absolute z-20 w-full ${titleAlignmentClasses[titleAlignment?.horizontal ?? \"left\"]} p-${padding} ${\n titleAlignment.vertical === \"top\"\n ? `top-0 pt-${padding}`\n : titleAlignment.vertical === \"center\"\n ? \"top-1/2 -translate-y-1/2\"\n : `bottom-0 pb-${padding}`\n }`}\n >\n {titleEnabled && titleText && (\n <h2\n className={`font-header leading-tight font-bold text-${titleColor} text-${titleFontSize === \"md\" ? \"base\" : titleFontSize}`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Mobile: Products overlay inside primary media */}\n {hasNestedMedia && (\n <div className={`pt-${padding} @md:hidden`}>\n <div\n className={`flex overflow-x-auto gap-${gapValues[gap]} bg-transparent`}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col items-center ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-40 overflow-hidden rounded-${borderRadius}`}\n >\n <MediaRenderer\n {...getMediaPropsFromShareable(shareable)}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Desktop: Products Container - Single row beside primary media */}\n {hasNestedMedia && (\n <div\n className={`relative hidden min-w-0 self-stretch @md:flex @md:flex-1 px-${padding}`}\n >\n <div\n ref={scrollContainerRef}\n className={`flex h-full flex-row overflow-x-auto gap-${gapValues[gap]}`}\n style={{ scrollSnapType: \"x mandatory\" }}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex flex-col gap-1 ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n style={{\n width: `calc(${primaryMediaHeight} * 0.75)`,\n scrollSnapAlign: \"start\",\n }}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-full rounded-${borderRadius} overflow-hidden`}\n >\n <MediaRenderer {...getMediaPropsFromShareable(shareable)} />\n </div>\n <span className={`flex-none text-sm text-${nestedTextColor}`}>\n <p className=\"truncate\">{shareable.title || \"\"}</p>\n <p className=\"truncate\">\n {((shareable.display_price as string) ?? shareable.price) ||\n \"\"}\n </p>\n </span>\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n <div\n className={`absolute inset-x-0 top-1/2 flex w-full -translate-y-1/2 items-center justify-between px-8`}\n >\n <ScrollArrows\n onPrevious={() => scrollByAmount(\"prev\")}\n onNext={() => scrollByAmount(\"next\")}\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const nestedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"NestedWidget\",\n displayName: \"Nested Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"shareables\"],\n fields: [\n // Content tab - Resource group\n {\n key: \"resource\",\n label: \"Primary Media\",\n type: \"resource\",\n description: \"Select the primary media displayed in the large panel\",\n allowedTypes: [\"Medium\"],\n tab: \"styling\",\n group: \"Content\",\n },\n // Content tab - Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed over the primary media\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Main title displayed over the primary media\",\n defaultValue: \"Featured Collection\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n label: \"Title Font Size\",\n defaultValue: \"xl\",\n key: \"titleFontSize\",\n description: \"Font size for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n // Styling tab - Design group\n getHeightField({\n key: \"primaryMediaHeight\",\n label: \"Primary Media Height\",\n description: \"Height of the primary media container\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"titleAlignment\",\n label: \"Content Alignment\",\n type: \"alignment\",\n description: \"Alignment of the content inside the primary media\",\n defaultValue: { horizontal: \"left\", vertical: \"bottom\" },\n options: {\n horizontalEnabled: true,\n verticalEnabled: true,\n },\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 getPaddingField({\n defaultValue: 4,\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding used throughout the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n defaultValue: \"md\",\n label: \"Border Radius\",\n key: \"borderRadius\",\n description: \"Rounded corners for the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\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 widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description:\n \"Add a dark overlay to the primary media for better text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay effect\",\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: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n // Styling tab - Nested Media Styling group\n getGapField({\n label: \"Gap\",\n defaultValue: \"md\",\n key: \"gap\",\n description: \"Gap between nested media items\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n getColorField({\n defaultValue: \"foreground\",\n key: \"nestedTextColor\",\n label: \"Nested Text Color\",\n description: \"Color for nested media labels\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n {\n type: \"background\",\n defaultValue: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background color for nested media container\",\n tab: \"styling\",\n group: \"Nested Design\",\n },\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure dynamic data fetching from an API\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n // Per-item configuration schema for custom data sources\n itemConfigSchema: {\n description: \"Configure settings for this item\",\n fields: [\n {\n key: \"title\",\n label: \"Custom Title\",\n type: \"text\",\n description: \"Override the item's title for this widget\",\n },\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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ACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;IAAE,YAAY;IAAQ,UAAU;IAAU;GACxD,SAAS;IACP,mBAAmB;IACnB,iBAAiB;IAClB;GACD,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,gBAAgB;GACd,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,cAAc;GACd,OAAO;GACP,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;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,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;EAED,YAAY;GACV,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,QAAQ,CACN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACd,CACF;EACF;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ProductsScreen-BQVP1OTk.cjs","names":["useSdkClient","useCurrentUser","useAppNavigation","createShareablesApiAdapter","ShareablesCoreProvider","ShareablesApiProvider","ShareablesUIProvider","ProductsApp"],"sources":["../src/screens/ProductsScreen.tsx"],"sourcesContent":["import { useCallback, useMemo, type ComponentProps } from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n PaddingOptions,\n} from \"../types\";\nimport type { WidgetPropertySchema } from \"../registries/property-schema-types\";\nimport {\n ShareablesCoreProvider,\n ShareablesApiProvider,\n type ShareablesApi,\n} from \"@fluid-app/shareables-core\";\nimport { ShareablesUIProvider, ProductsApp } from \"@fluid-app/shareables-ui\";\nimport { createShareablesApiAdapter } from \"@fluid-app/shareables-api-client\";\nimport { useCurrentUser } from \"../hooks/use-current-user\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\nimport { useSdkClient } from \"../account/use-account-clients\";\n\ntype ProductsScreenProps = ComponentProps<\"div\"> & {\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n};\n\nexport function ProductsScreen({\n /* eslint-disable @typescript-eslint/no-unused-vars -- destructured to exclude from divProps spread */\n background,\n textColor,\n accentColor,\n padding,\n borderRadius,\n /* eslint-enable @typescript-eslint/no-unused-vars */\n ...divProps\n}: ProductsScreenProps): React.JSX.Element {\n const domainClient = useSdkClient();\n const { data: userData } = useCurrentUser();\n const { currentSlug, navigate } = useAppNavigation();\n\n // Extract product ID from slug: \"products/123\" → \"123\"\n const productId = useMemo(() => {\n const match = currentSlug.match(/^products\\/(.+)/);\n return match?.[1] ?? null;\n }, [currentSlug]);\n\n const handleSelectProduct = useCallback(\n (id: string) => {\n navigate(`products/${id}`);\n },\n [navigate],\n );\n\n const handleBack = useCallback(() => {\n navigate(\"products\");\n }, [navigate]);\n\n const coreConfig = useMemo(\n () => ({\n client: domainClient,\n user: userData ? { id: userData.id } : null,\n }),\n [domainClient, userData],\n );\n\n const shareablesApi = useMemo<ShareablesApi>(\n () => createShareablesApiAdapter(domainClient, { repContext: true }),\n [domainClient],\n );\n\n const uiConfig = useMemo(\n () => ({\n user: userData\n ? {\n id: userData.id,\n company: userData.company\n ? { logo_url: userData.company.logo_url }\n : null,\n }\n : undefined,\n basePath: \"\",\n navigate: (path: string) => {\n navigate(path);\n },\n showToast: (opts: {\n title: string;\n type: \"success\" | \"error\" | \"warning\";\n }) => {\n console.log(`[Products] ${opts.type}: ${opts.title}`);\n },\n }),\n [userData, navigate],\n );\n\n return (\n <div {...divProps} className={`h-full ${divProps.className ?? \"\"}`}>\n <ShareablesCoreProvider config={coreConfig}>\n <ShareablesApiProvider api={shareablesApi}>\n <ShareablesUIProvider config={uiConfig}>\n <ProductsApp\n countryCode={userData?.country?.iso}\n companyLogoUrl={userData?.company?.logo_url}\n productId={productId}\n onSelectProduct={handleSelectProduct}\n onBack={handleBack}\n />\n </ShareablesUIProvider>\n </ShareablesApiProvider>\n </ShareablesCoreProvider>\n </div>\n );\n}\n\nexport const productsScreenPropertySchema: WidgetPropertySchema = {\n widgetType: \"ProductsScreen\",\n displayName: \"Products Screen\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":";;;;;;;;;AA2BA,SAAgB,eAAe,EAE7B,YACA,WACA,aACA,SACA,cAEA,GAAG,YACsC;CACzC,MAAM,eAAeA,4BAAAA,cAAc;CACnC,MAAM,EAAE,MAAM,aAAaC,yBAAAA,gBAAgB;CAC3C,MAAM,EAAE,aAAa,aAAaC,6BAAAA,kBAAkB;CAGpD,MAAM,aAAA,GAAA,MAAA,eAA0B;AAE9B,SADc,YAAY,MAAM,kBAAkB,GACnC,MAAM;IACpB,CAAC,YAAY,CAAC;CAEjB,MAAM,uBAAA,GAAA,MAAA,cACH,OAAe;AACd,WAAS,YAAY,KAAK;IAE5B,CAAC,SAAS,CACX;CAED,MAAM,cAAA,GAAA,MAAA,mBAA+B;AACnC,WAAS,WAAW;IACnB,CAAC,SAAS,CAAC;CAEd,MAAM,cAAA,GAAA,MAAA,gBACG;EACL,QAAQ;EACR,MAAM,WAAW,EAAE,IAAI,SAAS,IAAI,GAAG;EACxC,GACD,CAAC,cAAc,SAAS,CACzB;CAED,MAAM,iBAAA,GAAA,MAAA,eACEC,cAAAA,2BAA2B,cAAc,EAAE,YAAY,MAAM,CAAC,EACpE,CAAC,aAAa,CACf;CAED,MAAM,YAAA,GAAA,MAAA,gBACG;EACL,MAAM,WACF;GACE,IAAI,SAAS;GACb,SAAS,SAAS,UACd,EAAE,UAAU,SAAS,QAAQ,UAAU,GACvC;GACL,GACD,KAAA;EACJ,UAAU;EACV,WAAW,SAAiB;AAC1B,YAAS,KAAK;;EAEhB,YAAY,SAGN;AACJ,WAAQ,IAAI,cAAc,KAAK,KAAK,IAAI,KAAK,QAAQ;;EAExD,GACD,CAAC,UAAU,SAAS,CACrB;AAED,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EAAK,GAAI;EAAU,WAAW,UAAU,SAAS,aAAa;YAC5D,iBAAA,GAAA,kBAAA,KAACC,YAAAA,wBAAD;GAAwB,QAAQ;aAC9B,iBAAA,GAAA,kBAAA,KAACC,YAAAA,uBAAD;IAAuB,KAAK;cAC1B,iBAAA,GAAA,kBAAA,KAACC,YAAAA,sBAAD;KAAsB,QAAQ;eAC5B,iBAAA,GAAA,kBAAA,KAACC,YAAAA,aAAD;MACE,aAAa,UAAU,SAAS;MAChC,gBAAgB,UAAU,SAAS;MACxB;MACX,iBAAiB;MACjB,QAAQ;MACR,CAAA;KACmB,CAAA;IACD,CAAA;GACD,CAAA;EACrB,CAAA;;AAIV,MAAa,+BAAqD;CAChE,YAAY;CACZ,aAAa;CACb,YAAY,CAAC;EAAE,IAAI;EAAW,OAAO;EAAW,CAAC;CACjD,QAAQ,EAAE;CACX"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ProductsScreen-C2qXwQfN.mjs","names":[],"sources":["../src/screens/ProductsScreen.tsx"],"sourcesContent":["import { useCallback, useMemo, type ComponentProps } from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n PaddingOptions,\n} from \"../types\";\nimport type { WidgetPropertySchema } from \"../registries/property-schema-types\";\nimport {\n ShareablesCoreProvider,\n ShareablesApiProvider,\n type ShareablesApi,\n} from \"@fluid-app/shareables-core\";\nimport { ShareablesUIProvider, ProductsApp } from \"@fluid-app/shareables-ui\";\nimport { createShareablesApiAdapter } from \"@fluid-app/shareables-api-client\";\nimport { useCurrentUser } from \"../hooks/use-current-user\";\nimport { useAppNavigation } from \"../shell/AppNavigationContext\";\nimport { useSdkClient } from \"../account/use-account-clients\";\n\ntype ProductsScreenProps = ComponentProps<\"div\"> & {\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n};\n\nexport function ProductsScreen({\n /* eslint-disable @typescript-eslint/no-unused-vars -- destructured to exclude from divProps spread */\n background,\n textColor,\n accentColor,\n padding,\n borderRadius,\n /* eslint-enable @typescript-eslint/no-unused-vars */\n ...divProps\n}: ProductsScreenProps): React.JSX.Element {\n const domainClient = useSdkClient();\n const { data: userData } = useCurrentUser();\n const { currentSlug, navigate } = useAppNavigation();\n\n // Extract product ID from slug: \"products/123\" → \"123\"\n const productId = useMemo(() => {\n const match = currentSlug.match(/^products\\/(.+)/);\n return match?.[1] ?? null;\n }, [currentSlug]);\n\n const handleSelectProduct = useCallback(\n (id: string) => {\n navigate(`products/${id}`);\n },\n [navigate],\n );\n\n const handleBack = useCallback(() => {\n navigate(\"products\");\n }, [navigate]);\n\n const coreConfig = useMemo(\n () => ({\n client: domainClient,\n user: userData ? { id: userData.id } : null,\n }),\n [domainClient, userData],\n );\n\n const shareablesApi = useMemo<ShareablesApi>(\n () => createShareablesApiAdapter(domainClient, { repContext: true }),\n [domainClient],\n );\n\n const uiConfig = useMemo(\n () => ({\n user: userData\n ? {\n id: userData.id,\n company: userData.company\n ? { logo_url: userData.company.logo_url }\n : null,\n }\n : undefined,\n basePath: \"\",\n navigate: (path: string) => {\n navigate(path);\n },\n showToast: (opts: {\n title: string;\n type: \"success\" | \"error\" | \"warning\";\n }) => {\n console.log(`[Products] ${opts.type}: ${opts.title}`);\n },\n }),\n [userData, navigate],\n );\n\n return (\n <div {...divProps} className={`h-full ${divProps.className ?? \"\"}`}>\n <ShareablesCoreProvider config={coreConfig}>\n <ShareablesApiProvider api={shareablesApi}>\n <ShareablesUIProvider config={uiConfig}>\n <ProductsApp\n countryCode={userData?.country?.iso}\n companyLogoUrl={userData?.company?.logo_url}\n productId={productId}\n onSelectProduct={handleSelectProduct}\n onBack={handleBack}\n />\n </ShareablesUIProvider>\n </ShareablesApiProvider>\n </ShareablesCoreProvider>\n </div>\n );\n}\n\nexport const productsScreenPropertySchema: WidgetPropertySchema = {\n widgetType: \"ProductsScreen\",\n displayName: \"Products Screen\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":";;;;;;;;AA2BA,SAAgB,eAAe,EAE7B,YACA,WACA,aACA,SACA,cAEA,GAAG,YACsC;CACzC,MAAM,eAAe,cAAc;CACnC,MAAM,EAAE,MAAM,aAAa,gBAAgB;CAC3C,MAAM,EAAE,aAAa,aAAa,kBAAkB;CAGpD,MAAM,YAAY,cAAc;AAE9B,SADc,YAAY,MAAM,kBAAkB,GACnC,MAAM;IACpB,CAAC,YAAY,CAAC;CAEjB,MAAM,sBAAsB,aACzB,OAAe;AACd,WAAS,YAAY,KAAK;IAE5B,CAAC,SAAS,CACX;CAED,MAAM,aAAa,kBAAkB;AACnC,WAAS,WAAW;IACnB,CAAC,SAAS,CAAC;CAEd,MAAM,aAAa,eACV;EACL,QAAQ;EACR,MAAM,WAAW,EAAE,IAAI,SAAS,IAAI,GAAG;EACxC,GACD,CAAC,cAAc,SAAS,CACzB;CAED,MAAM,gBAAgB,cACd,2BAA2B,cAAc,EAAE,YAAY,MAAM,CAAC,EACpE,CAAC,aAAa,CACf;CAED,MAAM,WAAW,eACR;EACL,MAAM,WACF;GACE,IAAI,SAAS;GACb,SAAS,SAAS,UACd,EAAE,UAAU,SAAS,QAAQ,UAAU,GACvC;GACL,GACD,KAAA;EACJ,UAAU;EACV,WAAW,SAAiB;AAC1B,YAAS,KAAK;;EAEhB,YAAY,SAGN;AACJ,WAAQ,IAAI,cAAc,KAAK,KAAK,IAAI,KAAK,QAAQ;;EAExD,GACD,CAAC,UAAU,SAAS,CACrB;AAED,QACE,oBAAC,OAAD;EAAK,GAAI;EAAU,WAAW,UAAU,SAAS,aAAa;YAC5D,oBAAC,wBAAD;GAAwB,QAAQ;aAC9B,oBAAC,uBAAD;IAAuB,KAAK;cAC1B,oBAAC,sBAAD;KAAsB,QAAQ;eAC5B,oBAAC,aAAD;MACE,aAAa,UAAU,SAAS;MAChC,gBAAgB,UAAU,SAAS;MACxB;MACX,iBAAiB;MACjB,QAAQ;MACR,CAAA;KACmB,CAAA;IACD,CAAA;GACD,CAAA;EACrB,CAAA;;AAIV,MAAa,+BAAqD;CAChE,YAAY;CACZ,aAAa;CACb,YAAY,CAAC;EAAE,IAAI;EAAW,OAAO;EAAW,CAAC;CACjD,QAAQ,EAAE;CACX"}