@fluid-app/portal-sdk 0.1.77 → 0.1.79

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 (108) hide show
  1. package/dist/{AlertWidget-BrUi7EqF.cjs → AlertWidget-B2Qcisk7.cjs} +2 -2
  2. package/dist/{AlertWidget-BrUi7EqF.cjs.map → AlertWidget-B2Qcisk7.cjs.map} +1 -1
  3. package/dist/{AlertWidget-yjstYYw9.mjs → AlertWidget-C-7uX0HS.mjs} +2 -2
  4. package/dist/{AlertWidget-yjstYYw9.mjs.map → AlertWidget-C-7uX0HS.mjs.map} +1 -1
  5. package/dist/{AppDownloadScreen-B2Cfv-uS.cjs → AppDownloadScreen-6y1seGY3.cjs} +7 -7
  6. package/dist/{AppDownloadScreen-BICgVr39.cjs → AppDownloadScreen-CDdpVdL_.cjs} +2 -2
  7. package/dist/{AppDownloadScreen-BICgVr39.cjs.map → AppDownloadScreen-CDdpVdL_.cjs.map} +1 -1
  8. package/dist/{AppDownloadScreen-0bjHFsn8.mjs → AppDownloadScreen-D2BvFHaa.mjs} +2 -2
  9. package/dist/{AppDownloadScreen-0bjHFsn8.mjs.map → AppDownloadScreen-D2BvFHaa.mjs.map} +1 -1
  10. package/dist/{CalendarWidget-Bj0prW4s.cjs → CalendarWidget-BG5_GulK.cjs} +3 -3
  11. package/dist/CalendarWidget-BG5_GulK.cjs.map +1 -0
  12. package/dist/{CalendarWidget-DDFVe7-h.mjs → CalendarWidget-BHSLd43x.mjs} +3 -3
  13. package/dist/CalendarWidget-BHSLd43x.mjs.map +1 -0
  14. package/dist/{ContactsScreen-BY_bV9hD.cjs → ContactsScreen-B8eVq5y2.cjs} +7 -7
  15. package/dist/{ContactsScreen-B45I4fsu.cjs → ContactsScreen-BRO0Ck6Q.cjs} +2 -2
  16. package/dist/{ContactsScreen-B45I4fsu.cjs.map → ContactsScreen-BRO0Ck6Q.cjs.map} +1 -1
  17. package/dist/{ContactsScreen-fv44z4G1.mjs → ContactsScreen-D5UaRgr5.mjs} +2 -2
  18. package/dist/{ContactsScreen-fv44z4G1.mjs.map → ContactsScreen-D5UaRgr5.mjs.map} +1 -1
  19. package/dist/{FluidProvider-B7LKjuMi.cjs → FluidProvider-7o0dnbFe.cjs} +11 -11
  20. package/dist/{FluidProvider-B7LKjuMi.cjs.map → FluidProvider-7o0dnbFe.cjs.map} +1 -1
  21. package/dist/{FluidProvider-BPFbPldT.mjs → FluidProvider-CiO9GrRT.mjs} +11 -11
  22. package/dist/{FluidProvider-BPFbPldT.mjs.map → FluidProvider-CiO9GrRT.mjs.map} +1 -1
  23. package/dist/{LinkWidget-nstWDcsr.cjs → LinkWidget-JKkMn6Pt.cjs} +5 -4
  24. package/dist/LinkWidget-JKkMn6Pt.cjs.map +1 -0
  25. package/dist/{LinkWidget-DUxod35m.cjs → LinkWidget-RYHmBVzc.cjs} +1 -1
  26. package/dist/{LinkWidget-BdQSowRZ.mjs → LinkWidget-e0aFNkZJ.mjs} +5 -4
  27. package/dist/LinkWidget-e0aFNkZJ.mjs.map +1 -0
  28. package/dist/{ListWidget-CunZTx5S.cjs → ListWidget-BKdwD5kR.cjs} +1 -1
  29. package/dist/{ListWidget-g2qBtmNZ.cjs → ListWidget-Ch386fkp.cjs} +7 -7
  30. package/dist/ListWidget-Ch386fkp.cjs.map +1 -0
  31. package/dist/{ListWidget-xPZwneuu.mjs → ListWidget-DhRPDaP7.mjs} +7 -7
  32. package/dist/ListWidget-DhRPDaP7.mjs.map +1 -0
  33. package/dist/{MessagingScreen-BHulaY7A.mjs → MessagingScreen-BWXeBpfB.mjs} +3 -3
  34. package/dist/{MessagingScreen-BHulaY7A.mjs.map → MessagingScreen-BWXeBpfB.mjs.map} +1 -1
  35. package/dist/{MessagingScreen-L76XP3Oz.mjs → MessagingScreen-D8pvtQxf.mjs} +7 -8
  36. package/dist/{MessagingScreen-DGttFuoB.cjs → MessagingScreen-Jwu6kKrB.cjs} +3 -3
  37. package/dist/{MessagingScreen-DGttFuoB.cjs.map → MessagingScreen-Jwu6kKrB.cjs.map} +1 -1
  38. package/dist/{MessagingScreen-ms1wGWHQ.cjs → MessagingScreen-UrRkoFxL.cjs} +7 -7
  39. package/dist/{MySiteScreen-CEb9L0vp.cjs → MySiteScreen-C8117-zp.cjs} +7 -7
  40. package/dist/{MySiteScreen-BfYDwE3C.mjs → MySiteScreen-CcCkaQa_.mjs} +2 -2
  41. package/dist/{MySiteScreen-BfYDwE3C.mjs.map → MySiteScreen-CcCkaQa_.mjs.map} +1 -1
  42. package/dist/{MySiteScreen-DY7PSqP6.cjs → MySiteScreen-OvCPcgSF.cjs} +2 -2
  43. package/dist/{MySiteScreen-DY7PSqP6.cjs.map → MySiteScreen-OvCPcgSF.cjs.map} +1 -1
  44. package/dist/{OrdersScreen-CuQTI5f9.mjs → OrdersScreen-CNPW9uXl.mjs} +3 -3
  45. package/dist/{OrdersScreen-CuQTI5f9.mjs.map → OrdersScreen-CNPW9uXl.mjs.map} +1 -1
  46. package/dist/{OrdersScreen-D5_PtRCp.cjs → OrdersScreen-D0zERNH6.cjs} +7 -7
  47. package/dist/{OrdersScreen-CB_VOlRI.cjs → OrdersScreen-DHJaHME4.cjs} +3 -3
  48. package/dist/{OrdersScreen-CB_VOlRI.cjs.map → OrdersScreen-DHJaHME4.cjs.map} +1 -1
  49. package/dist/{ProductsScreen-CGe2U2jo.mjs → ProductsScreen-2N-HcLeP.mjs} +3 -3
  50. package/dist/{ProductsScreen-CGe2U2jo.mjs.map → ProductsScreen-2N-HcLeP.mjs.map} +1 -1
  51. package/dist/{ProductsScreen-BQlgLkmn.mjs → ProductsScreen-CvIvqSV_.mjs} +7 -11
  52. package/dist/{ProductsScreen-DzJlDMus.cjs → ProductsScreen-Cy70ceAN.cjs} +3 -3
  53. package/dist/{ProductsScreen-DzJlDMus.cjs.map → ProductsScreen-Cy70ceAN.cjs.map} +1 -1
  54. package/dist/{ProductsScreen-a7n9oVPF.cjs → ProductsScreen-MLonUBzA.cjs} +7 -7
  55. package/dist/{ProfileScreen-Y5zQgZL0.mjs → ProfileScreen-CLFs_gxl.mjs} +3 -3
  56. package/dist/{ProfileScreen-Y5zQgZL0.mjs.map → ProfileScreen-CLFs_gxl.mjs.map} +1 -1
  57. package/dist/{ProfileScreen-VBlfOlav.cjs → ProfileScreen-CZ44ROKG.cjs} +7 -7
  58. package/dist/{ProfileScreen-D6ie-eDm.cjs → ProfileScreen-wOmUspta.cjs} +3 -3
  59. package/dist/{ProfileScreen-D6ie-eDm.cjs.map → ProfileScreen-wOmUspta.cjs.map} +1 -1
  60. package/dist/{ShareablesScreen-BnAtijbM.cjs → ShareablesScreen-C1G_Kq5_.cjs} +7 -7
  61. package/dist/{ShareablesScreen-CRtMGs-h.mjs → ShareablesScreen-C4mm1R2g.mjs} +3 -3
  62. package/dist/{ShareablesScreen-CRtMGs-h.mjs.map → ShareablesScreen-C4mm1R2g.mjs.map} +1 -1
  63. package/dist/{ShareablesScreen-B67BMAUa.mjs → ShareablesScreen-CKw0mto6.mjs} +7 -11
  64. package/dist/{ShareablesScreen-BSy0IA8v.cjs → ShareablesScreen-augy6BSd.cjs} +3 -3
  65. package/dist/{ShareablesScreen-BSy0IA8v.cjs.map → ShareablesScreen-augy6BSd.cjs.map} +1 -1
  66. package/dist/{ShopScreen-OfnN0oCo.cjs → ShopScreen-BjzN4JAK.cjs} +4 -4
  67. package/dist/{ShopScreen-OfnN0oCo.cjs.map → ShopScreen-BjzN4JAK.cjs.map} +1 -1
  68. package/dist/{ShopScreen-5t5Jqdw5.cjs → ShopScreen-Dutx59m8.cjs} +7 -7
  69. package/dist/{ShopScreen-BpQQ00y7.mjs → ShopScreen-JJnPosZq.mjs} +4 -4
  70. package/dist/{ShopScreen-BpQQ00y7.mjs.map → ShopScreen-JJnPosZq.mjs.map} +1 -1
  71. package/dist/{SubscriptionsScreen-D5oQ8bt1.cjs → SubscriptionsScreen-BbLH9p8X.cjs} +3 -3
  72. package/dist/{SubscriptionsScreen-D5oQ8bt1.cjs.map → SubscriptionsScreen-BbLH9p8X.cjs.map} +1 -1
  73. package/dist/{SubscriptionsScreen-CBoAwhKQ.mjs → SubscriptionsScreen-BlFL-eMN.mjs} +3 -3
  74. package/dist/{SubscriptionsScreen-CBoAwhKQ.mjs.map → SubscriptionsScreen-BlFL-eMN.mjs.map} +1 -1
  75. package/dist/{SubscriptionsScreen-DxYZJ0k6.cjs → SubscriptionsScreen-BtuCHsSR.cjs} +7 -7
  76. package/dist/{TextWidget-GofZkamu.cjs → TextWidget-BCzx6OXG.cjs} +8 -7
  77. package/dist/TextWidget-BCzx6OXG.cjs.map +1 -0
  78. package/dist/{TextWidget-CJocBD6P.mjs → TextWidget-CADHRPPp.mjs} +8 -7
  79. package/dist/TextWidget-CADHRPPp.mjs.map +1 -0
  80. package/dist/index.cjs +39 -39
  81. package/dist/index.d.cts.map +1 -1
  82. package/dist/index.d.mts.map +1 -1
  83. package/dist/index.mjs +39 -39
  84. package/dist/{use-account-clients-8yvdvTIC.cjs → use-account-clients-BsxrtNFa.cjs} +2 -2
  85. package/dist/{use-account-clients-8yvdvTIC.cjs.map → use-account-clients-BsxrtNFa.cjs.map} +1 -1
  86. package/dist/{use-account-clients-G3DvbvPH.mjs → use-account-clients-C-0D2liR.mjs} +2 -2
  87. package/dist/{use-account-clients-G3DvbvPH.mjs.map → use-account-clients-C-0D2liR.mjs.map} +1 -1
  88. package/dist/{use-current-user-CWnlXU8G.cjs → use-current-user-BHDPYzyF.cjs} +3 -3
  89. package/dist/{use-current-user-CWnlXU8G.cjs.map → use-current-user-BHDPYzyF.cjs.map} +1 -1
  90. package/dist/{use-current-user-DJW-ZwIi.mjs → use-current-user-DWurIboQ.mjs} +3 -3
  91. package/dist/{use-current-user-DJW-ZwIi.mjs.map → use-current-user-DWurIboQ.mjs.map} +1 -1
  92. package/dist/{use-customer-account-BhjZjCcF.mjs → use-customer-account-4ciS4r5U.mjs} +3 -3
  93. package/dist/{use-customer-account-BhjZjCcF.mjs.map → use-customer-account-4ciS4r5U.mjs.map} +1 -1
  94. package/dist/{use-customer-account-CJDZKn97.cjs → use-customer-account-mnEYhCCO.cjs} +3 -3
  95. package/dist/{use-customer-account-CJDZKn97.cjs.map → use-customer-account-mnEYhCCO.cjs.map} +1 -1
  96. package/dist/{use-fluid-api-BcfyUuOe.cjs → use-fluid-api-CEJVK01Q.cjs} +2 -2
  97. package/dist/{use-fluid-api-BcfyUuOe.cjs.map → use-fluid-api-CEJVK01Q.cjs.map} +1 -1
  98. package/dist/{use-fluid-api-YzLdiq5t.mjs → use-fluid-api-DSUwYl8B.mjs} +2 -2
  99. package/dist/{use-fluid-api-YzLdiq5t.mjs.map → use-fluid-api-DSUwYl8B.mjs.map} +1 -1
  100. package/package.json +16 -16
  101. package/dist/CalendarWidget-Bj0prW4s.cjs.map +0 -1
  102. package/dist/CalendarWidget-DDFVe7-h.mjs.map +0 -1
  103. package/dist/LinkWidget-BdQSowRZ.mjs.map +0 -1
  104. package/dist/LinkWidget-nstWDcsr.cjs.map +0 -1
  105. package/dist/ListWidget-g2qBtmNZ.cjs.map +0 -1
  106. package/dist/ListWidget-xPZwneuu.mjs.map +0 -1
  107. package/dist/TextWidget-CJocBD6P.mjs.map +0 -1
  108. package/dist/TextWidget-GofZkamu.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"use-current-user-CWnlXU8G.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-BHDPYzyF.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-BPFbPldT.mjs";
2
- import { t as useFluidApi } from "./use-fluid-api-YzLdiq5t.mjs";
1
+ import { l as useFluidAuthContext } from "./FluidProvider-CiO9GrRT.mjs";
2
+ import { t as useFluidApi } from "./use-fluid-api-DSUwYl8B.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-DJW-ZwIi.mjs.map
101
+ //# sourceMappingURL=use-current-user-DWurIboQ.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-current-user-DJW-ZwIi.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-DWurIboQ.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-BPFbPldT.mjs";
2
- import { n as useFluidPayClient, o as useFluidAuth } from "./use-account-clients-G3DvbvPH.mjs";
1
+ import { _t as fetchCustomerAccount } from "./FluidProvider-CiO9GrRT.mjs";
2
+ import { n as useFluidPayClient, o as useFluidAuth } from "./use-account-clients-C-0D2liR.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-BhjZjCcF.mjs.map
23
+ //# sourceMappingURL=use-customer-account-4ciS4r5U.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-customer-account-BhjZjCcF.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-4ciS4r5U.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-B7LKjuMi.cjs");
3
- const require_use_account_clients = require("./use-account-clients-8yvdvTIC.cjs");
2
+ const require_FluidProvider = require("./FluidProvider-7o0dnbFe.cjs");
3
+ const require_use_account_clients = require("./use-account-clients-BsxrtNFa.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-CJDZKn97.cjs.map
29
+ //# sourceMappingURL=use-customer-account-mnEYhCCO.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-customer-account-CJDZKn97.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-mnEYhCCO.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-B7LKjuMi.cjs");
1
+ const require_FluidProvider = require("./FluidProvider-7o0dnbFe.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-BcfyUuOe.cjs.map
32
+ //# sourceMappingURL=use-fluid-api-CEJVK01Q.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-fluid-api-BcfyUuOe.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-CEJVK01Q.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-BPFbPldT.mjs";
1
+ import { n as useFluidContext } from "./FluidProvider-CiO9GrRT.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-YzLdiq5t.mjs.map
27
+ //# sourceMappingURL=use-fluid-api-DSUwYl8B.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-fluid-api-YzLdiq5t.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-DSUwYl8B.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.77",
3
+ "version": "0.1.79",
4
4
  "description": "SDK for building custom Fluid portals",
5
5
  "files": [
6
6
  "dist",
@@ -66,42 +66,42 @@
66
66
  "typescript": "^5",
67
67
  "zod": "4.3.5",
68
68
  "@fluid-app/api-client-core": "0.1.0",
69
- "@fluid-app/auth": "0.1.0",
70
69
  "@fluid-app/cart-ui": "0.1.12",
71
- "@fluid-app/company-switcher-core": "0.1.0",
72
70
  "@fluid-app/company-switcher-ui": "0.1.0",
73
- "@fluid-app/contacts-ui": "0.1.0",
71
+ "@fluid-app/auth": "0.1.0",
72
+ "@fluid-app/company-switcher-core": "0.1.0",
74
73
  "@fluid-app/file-picker-api-client": "0.1.0",
74
+ "@fluid-app/contacts-ui": "0.1.0",
75
75
  "@fluid-app/fluid-pay-api-client": "0.1.0",
76
- "@fluid-app/messaging-api-client": "0.1.0",
77
- "@fluid-app/fluidos-api-client": "0.1.0",
78
- "@fluid-app/messaging-ui": "0.1.0",
79
76
  "@fluid-app/messaging-core": "0.1.0",
80
77
  "@fluid-app/mysite-ui": "0.1.0",
78
+ "@fluid-app/messaging-ui": "0.1.0",
79
+ "@fluid-app/fluidos-api-client": "0.1.0",
80
+ "@fluid-app/messaging-api-client": "0.1.0",
81
+ "@fluid-app/orders-core": "0.1.0",
82
+ "@fluid-app/permissions": "0.1.0",
81
83
  "@fluid-app/orders-api-client": "0.1.0",
82
84
  "@fluid-app/orders-ui": "0.1.0",
85
+ "@fluid-app/portal-core": "0.1.23",
83
86
  "@fluid-app/portal-app-download-ui": "0.1.0",
84
- "@fluid-app/permissions": "0.1.0",
85
- "@fluid-app/orders-core": "0.1.0",
86
87
  "@fluid-app/portal-preview": "0.1.0",
87
- "@fluid-app/portal-core": "0.1.23",
88
- "@fluid-app/portal-pro-upgrade-ui": "0.1.0",
89
88
  "@fluid-app/portal-react": "0.1.0",
90
- "@fluid-app/portal-widgets": "0.1.22",
91
89
  "@fluid-app/products-api-client": "0.1.0",
90
+ "@fluid-app/portal-pro-upgrade-ui": "0.1.0",
92
91
  "@fluid-app/profile-core": "0.1.0",
93
- "@fluid-app/products-core": "0.1.0",
92
+ "@fluid-app/portal-widgets": "0.1.22",
94
93
  "@fluid-app/profile-ui": "0.1.0",
95
94
  "@fluid-app/query-persister": "0.1.0",
96
- "@fluid-app/shareables-core": "0.1.0",
97
95
  "@fluid-app/shareables-ui": "0.1.0",
96
+ "@fluid-app/products-core": "0.1.0",
97
+ "@fluid-app/shareables-core": "0.1.0",
98
98
  "@fluid-app/shareables-api-client": "0.1.0",
99
99
  "@fluid-app/shop-ui": "0.1.0",
100
100
  "@fluid-app/subscriptions-core": "0.1.0",
101
- "@fluid-app/subscriptions-ui": "0.1.0",
102
101
  "@fluid-app/subscriptions-api-client": "0.1.0",
103
- "@fluid-app/typescript-config": "0.0.0",
102
+ "@fluid-app/subscriptions-ui": "0.1.0",
104
103
  "@fluid-app/ui-primitives": "0.1.13",
104
+ "@fluid-app/typescript-config": "0.0.0",
105
105
  "@fluid-app/user-contacts-api-client": "0.1.0",
106
106
  "@fluid-app/user-notes-api-client": "0.1.0",
107
107
  "@fluid-app/user-tasks-api-client": "0.1.0"
@@ -1 +0,0 @@
1
- {"version":3,"file":"CalendarWidget-Bj0prW4s.cjs","names":["useDataSourceConfig","useWidgetPreviewContext","borderWidthClasses","borderColorClasses","ErrorState","ChevronLeft","ChevronRight","ChevronsDown","ChevronsUp","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/hooks/use-calendar-events.preview.ts","../../widgets/src/hooks/use-calendar-events.ts","../../widgets/src/widgets/CalendarWidget.tsx"],"sourcesContent":["import type { CalendarEvent } from \"./use-calendar-events.types\";\n\nconst today = new Date();\nconst inTwoDays = new Date(today);\ninTwoDays.setDate(inTwoDays.getDate() + 2);\n\nfunction toISO(date: Date, hours: number, minutes = 0): string {\n const d = new Date(date);\n d.setHours(hours, minutes, 0, 0);\n return d.toISOString();\n}\n\nfunction toDateString(date: Date): string {\n return date.toISOString().split(\"T\")[0]!;\n}\n\nexport const PREVIEW_DATA: CalendarEvent[] = [\n {\n id: 1,\n title: \"Team Strategy Call\",\n start: toISO(today, 9, 0),\n end: toISO(today, 10, 0),\n status: \"active\",\n color: \"#4f46e5\",\n },\n {\n id: 2,\n title: \"Product Launch Webinar\",\n start: toISO(today, 14, 0),\n end: toISO(today, 15, 30),\n status: \"active\",\n color: \"#0891b2\",\n venue: \"Zoom\",\n },\n {\n id: 3,\n title: \"Annual Leadership Summit\",\n start: `${toDateString(inTwoDays)}T00:00:00.000Z`,\n end: `${toDateString(inTwoDays)}T23:59:59.000Z`,\n status: \"active\",\n color: \"#059669\",\n isAllDay: true,\n venue: \"Convention Center\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useDataSourceConfig } from \"@fluid-app/portal-react/data-sources/context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { PREVIEW_DATA } from \"./use-calendar-events.preview\";\n\nimport type { CalendarEvent } from \"./use-calendar-events.types\";\n\nexport type { CalendarEvent } from \"./use-calendar-events.types\";\n\nexport function useCalendarEvents(): UseQueryResult<CalendarEvent[], Error> {\n const { baseUrl, getApiHeaders } = useDataSourceConfig();\n const { isPreview } = useWidgetPreviewContext();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"calendar-events\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: async ({ signal }): Promise<CalendarEvent[]> => {\n const url = baseUrl\n ? `${baseUrl}/events.json?event_timeline=upcoming`\n : \"/events.json?event_timeline=upcoming\";\n const response = await fetch(url, {\n headers: {\n \"content-type\": \"application/json\",\n ...getApiHeaders?.(),\n },\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch calendar events: ${response.status}`);\n }\n\n return response.json();\n },\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import { useState, useMemo, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport {\n useCalendarEvents,\n type CalendarEvent,\n} from \"../hooks/use-calendar-events\";\nimport { ErrorState } from \"../components/error-state\";\nimport {\n ChevronLeft,\n ChevronRight,\n ChevronsDown,\n ChevronsUp,\n} from \"lucide-react\";\n\n// Utility to get days in a month\nconst getDaysInMonth = (year: number, month: number) => {\n return new Date(year, month + 1, 0).getDate();\n};\n\n// Utility to get the first day of month (0 = Sunday, 1 = Monday, etc.)\nconst getFirstDayOfMonth = (year: number, month: number) => {\n return new Date(year, month, 1).getDay();\n};\n\n// Generate calendar grid for a month\nconst generateMonthGrid = (year: number, month: number) => {\n const daysInMonth = getDaysInMonth(year, month);\n const firstDay = getFirstDayOfMonth(year, month);\n const today = new Date();\n\n const days: Array<{\n date: Date | null;\n isToday: boolean;\n isCurrentMonth: boolean;\n }> = [];\n\n // Add empty slots for days before the 1st\n for (let i = 0; i < firstDay; i++) {\n days.push({ date: null, isToday: false, isCurrentMonth: false });\n }\n\n // Add days of the month\n for (let day = 1; day <= daysInMonth; day++) {\n const date = new Date(year, month, day);\n const isToday =\n date.getDate() === today.getDate() &&\n date.getMonth() === today.getMonth() &&\n date.getFullYear() === today.getFullYear();\n days.push({ date, isToday, isCurrentMonth: true });\n }\n\n return days;\n};\n\n// Generate week grid for current week\nconst generateWeekGrid = () => {\n const today = new Date();\n const currentDay = today.getDay();\n const days: Array<{\n date: Date;\n isToday: boolean;\n }> = [];\n\n for (let i = 0; i < 7; i++) {\n const date = new Date(today);\n date.setDate(today.getDate() - currentDay + i);\n days.push({\n date,\n isToday: date.toDateString() === today.toDateString(),\n });\n }\n\n return days;\n};\n\n// Get events for a specific date\nconst getEventsForDate = (date: Date, events: CalendarEvent[]) => {\n const dayStart = new Date(date);\n dayStart.setHours(0, 0, 0, 0);\n const dayEnd = new Date(date);\n dayEnd.setHours(23, 59, 59, 999);\n\n return events.filter((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n return eventStart <= dayEnd && eventEnd >= dayStart;\n });\n};\n\n// Check if a date has events\nconst hasEventsOnDate = (date: Date | null, events: CalendarEvent[]) => {\n if (!date) return false;\n return getEventsForDate(date, events).length > 0;\n};\n\n// Event item component\nconst EventItem = ({\n title,\n start,\n end,\n color,\n isAllDay,\n accentColor,\n}: CalendarEvent & { accentColor?: string }) => {\n const startTime = new Date(start).toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n const endTime = new Date(end).toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n\n return (\n <div className=\"flex gap-x-2\">\n <div\n className=\"w-0.5 shrink-0 rounded-full\"\n style={{ backgroundColor: color || accentColor }}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-medium\">{title}</div>\n <div className=\"text-xs opacity-60\">\n {isAllDay ? \"All day\" : `${startTime} - ${endTime}`}\n </div>\n </div>\n </div>\n );\n};\n\nconst dayNames = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n\ntype DayButtonProps = {\n date: Date;\n isToday: boolean;\n isSelected: boolean;\n hasEvents: boolean;\n accentColor: string;\n onClick: () => void;\n extraClassName?: string;\n};\n\nfunction DayButton({\n date,\n isToday,\n isSelected,\n hasEvents,\n accentColor,\n onClick,\n extraClassName = \"\",\n}: DayButtonProps) {\n return (\n <button\n onClick={onClick}\n className={`relative flex aspect-square items-center justify-center rounded-full text-sm transition-colors ${\n isSelected\n ? `bg-${accentColor} text-${accentColor}-foreground`\n : isToday\n ? `bg-${accentColor}/30 text-${accentColor}-foreground hover:bg-${accentColor}/50`\n : `hover:bg-${accentColor}/50 hover:text-${accentColor}-foreground`\n } ${extraClassName}`}\n >\n {date.getDate()}\n {hasEvents && (\n <div\n className={`absolute bottom-1 h-1 w-1 rounded-full bg-${accentColor}`}\n />\n )}\n </button>\n );\n}\n\ntype CalendarWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\nexport function CalendarWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"Calendar\",\n titleFontSize = \"xl\",\n titleColor = \"foreground\",\n\n // Styling defaults\n background = {\n type: \"solid\",\n color: \"background\",\n },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n className,\n ...props\n}: CalendarWidgetProps): React.JSX.Element {\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 const today = new Date();\n const [currentMonth, setCurrentMonth] = useState(today.getMonth());\n const [currentYear, setCurrentYear] = useState(today.getFullYear());\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [selectedDate, setSelectedDate] = useState<Date | null>(today);\n\n const { data: events = [], isLoading, isError } = useCalendarEvents();\n\n // Generate calendar grids\n const monthGrid = useMemo(\n () => generateMonthGrid(currentYear, currentMonth),\n [currentYear, currentMonth],\n );\n const weekGrid = useMemo(() => generateWeekGrid(), []);\n\n // Get events for selected date\n const selectedDateEvents = useMemo(() => {\n if (!selectedDate) return [];\n return getEventsForDate(selectedDate, events);\n }, [selectedDate, events]);\n\n // Navigation handlers\n const goToPrevMonth = () => {\n if (currentMonth === 0) {\n setCurrentMonth(11);\n setCurrentYear(currentYear - 1);\n } else {\n setCurrentMonth(currentMonth - 1);\n }\n };\n\n const goToNextMonth = () => {\n if (currentMonth === 11) {\n setCurrentMonth(0);\n setCurrentYear(currentYear + 1);\n } else {\n setCurrentMonth(currentMonth + 1);\n }\n };\n\n const monthYearLabel = new Date(currentYear, currentMonth).toLocaleString(\n \"en-US\",\n {\n month: \"long\",\n year: \"numeric\",\n },\n );\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} text-${textColor} ${className}`}\n style={{ backgroundImage }}\n {...props}\n >\n {/* Title */}\n {titleEnabled && titleText && (\n <div className={`p-${padding} pb-0`}>\n <h2\n className={`text-${titleFontSize} font-header font-bold text-${titleColor}`}\n >\n {titleText}\n </h2>\n </div>\n )}\n\n {/* Loading state */}\n {isLoading ? (\n <div\n className={`flex min-h-[300px] items-center justify-center p-${padding}`}\n >\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n /* Error state */\n <ErrorState />\n ) : (\n <div className={`p-${padding}`}>\n {/* Desktop: Side by side layout */}\n <div className=\"@md:flex @md:gap-6\">\n {/* Calendar Section */}\n <div className=\"@md:flex-none\">\n {/* Month/Year Header with Navigation */}\n <div className=\"mb-4 flex items-center justify-between\">\n <button\n onClick={goToPrevMonth}\n className=\"hover:bg-foreground/10 rounded-full p-1\"\n aria-label=\"Previous month\"\n >\n <ChevronLeft className=\"size-4\" />\n </button>\n\n <span className=\"text-base font-semibold\">\n {monthYearLabel}\n </span>\n\n <button\n onClick={goToNextMonth}\n className=\"hover:bg-foreground/10 rounded-full p-1\"\n aria-label=\"Next month\"\n >\n <ChevronRight className=\"size-4\" />\n </button>\n </div>\n\n {/* Day Headers */}\n <div className=\"mb-2 grid grid-cols-7 gap-1 text-center\">\n {dayNames.map((day, idx) => (\n <div\n key={idx}\n className=\"text-xs font-medium uppercase opacity-60\"\n >\n {day}\n </div>\n ))}\n </div>\n\n {/* Calendar Grid - Week view on mobile when collapsed */}\n {isCollapsed && (\n <div className=\"grid grid-cols-7 gap-1 @md:hidden\">\n {weekGrid.map(({ date, isToday }, idx) => (\n <DayButton\n key={idx}\n date={date}\n isToday={isToday}\n isSelected={\n selectedDate?.toDateString() === date.toDateString()\n }\n hasEvents={hasEventsOnDate(date, events)}\n accentColor={accentColor}\n onClick={() => setSelectedDate(date)}\n />\n ))}\n </div>\n )}\n\n {/* Month view (always on desktop, when not collapsed on mobile) */}\n <div\n className={`grid grid-cols-7 gap-1 ${isCollapsed ? \"hidden @md:grid\" : \"grid\"}`}\n >\n {monthGrid.map((day, idx) => {\n if (!day.date) {\n return <div key={idx} className=\"aspect-square\" />;\n }\n\n return (\n <DayButton\n key={idx}\n date={day.date}\n isToday={day.isToday}\n isSelected={\n selectedDate?.toDateString() === day.date.toDateString()\n }\n hasEvents={hasEventsOnDate(day.date, events)}\n accentColor={accentColor}\n onClick={() => setSelectedDate(day.date)}\n extraClassName=\"p-2 @md:m-3\"\n />\n );\n })}\n </div>\n\n {/* Mobile collapse toggle */}\n <button\n onClick={() => setIsCollapsed(!isCollapsed)}\n className={`ml-2 flex w-full items-center justify-center gap-3 rounded-full p-1 text-${textColor}/50 @md:hidden`}\n aria-label={\n isCollapsed ? \"Expand calendar\" : \"Collapse calendar\"\n }\n >\n <div className={`h-1 w-1/2 bg-${textColor}/50`} />\n {isCollapsed ? (\n <ChevronsDown className=\"size-4\" />\n ) : (\n <ChevronsUp className=\"size-4\" />\n )}\n <div className={`h-1 w-1/2 bg-${textColor}/50`} />\n </button>\n </div>\n\n {/* Events Panel */}\n <div className=\"border-muted mt-4 pt-4 @md:mt-0 @md:w-56 @md:border-l @md:pt-0 @md:pl-6\">\n <div className=\"mb-2 text-sm font-medium opacity-60\">\n {selectedDate\n ? selectedDate.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n month: \"short\",\n day: \"numeric\",\n })\n : \"Select a date\"}\n </div>\n\n {selectedDateEvents.length > 0 ? (\n <div className=\"flex flex-col gap-3\">\n {selectedDateEvents.map((event, idx) => (\n <EventItem\n key={`${event.id}-${idx}`}\n {...event}\n accentColor={`var(--${accentColor})`}\n />\n ))}\n </div>\n ) : (\n <div className=\"text-sm opacity-50\">No events</div>\n )}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const calendarWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CalendarWidget\",\n displayName: \"Calendar Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the calendar\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the calendar\",\n defaultValue: \"Calendar\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Design Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the calendar container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for calendar content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color used for today highlight and event indicators\",\n defaultValue: \"primary\",\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 getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the calendar container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the calendar container\",\n defaultValue: \"md\",\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} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"CalendarWidget-DDFVe7-h.mjs","names":[],"sources":["../../widgets/src/hooks/use-calendar-events.preview.ts","../../widgets/src/hooks/use-calendar-events.ts","../../widgets/src/widgets/CalendarWidget.tsx"],"sourcesContent":["import type { CalendarEvent } from \"./use-calendar-events.types\";\n\nconst today = new Date();\nconst inTwoDays = new Date(today);\ninTwoDays.setDate(inTwoDays.getDate() + 2);\n\nfunction toISO(date: Date, hours: number, minutes = 0): string {\n const d = new Date(date);\n d.setHours(hours, minutes, 0, 0);\n return d.toISOString();\n}\n\nfunction toDateString(date: Date): string {\n return date.toISOString().split(\"T\")[0]!;\n}\n\nexport const PREVIEW_DATA: CalendarEvent[] = [\n {\n id: 1,\n title: \"Team Strategy Call\",\n start: toISO(today, 9, 0),\n end: toISO(today, 10, 0),\n status: \"active\",\n color: \"#4f46e5\",\n },\n {\n id: 2,\n title: \"Product Launch Webinar\",\n start: toISO(today, 14, 0),\n end: toISO(today, 15, 30),\n status: \"active\",\n color: \"#0891b2\",\n venue: \"Zoom\",\n },\n {\n id: 3,\n title: \"Annual Leadership Summit\",\n start: `${toDateString(inTwoDays)}T00:00:00.000Z`,\n end: `${toDateString(inTwoDays)}T23:59:59.000Z`,\n status: \"active\",\n color: \"#059669\",\n isAllDay: true,\n venue: \"Convention Center\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useDataSourceConfig } from \"@fluid-app/portal-react/data-sources/context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { PREVIEW_DATA } from \"./use-calendar-events.preview\";\n\nimport type { CalendarEvent } from \"./use-calendar-events.types\";\n\nexport type { CalendarEvent } from \"./use-calendar-events.types\";\n\nexport function useCalendarEvents(): UseQueryResult<CalendarEvent[], Error> {\n const { baseUrl, getApiHeaders } = useDataSourceConfig();\n const { isPreview } = useWidgetPreviewContext();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"calendar-events\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: async ({ signal }): Promise<CalendarEvent[]> => {\n const url = baseUrl\n ? `${baseUrl}/events.json?event_timeline=upcoming`\n : \"/events.json?event_timeline=upcoming\";\n const response = await fetch(url, {\n headers: {\n \"content-type\": \"application/json\",\n ...getApiHeaders?.(),\n },\n signal,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch calendar events: ${response.status}`);\n }\n\n return response.json();\n },\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import { useState, useMemo, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport {\n useCalendarEvents,\n type CalendarEvent,\n} from \"../hooks/use-calendar-events\";\nimport { ErrorState } from \"../components/error-state\";\nimport {\n ChevronLeft,\n ChevronRight,\n ChevronsDown,\n ChevronsUp,\n} from \"lucide-react\";\n\n// Utility to get days in a month\nconst getDaysInMonth = (year: number, month: number) => {\n return new Date(year, month + 1, 0).getDate();\n};\n\n// Utility to get the first day of month (0 = Sunday, 1 = Monday, etc.)\nconst getFirstDayOfMonth = (year: number, month: number) => {\n return new Date(year, month, 1).getDay();\n};\n\n// Generate calendar grid for a month\nconst generateMonthGrid = (year: number, month: number) => {\n const daysInMonth = getDaysInMonth(year, month);\n const firstDay = getFirstDayOfMonth(year, month);\n const today = new Date();\n\n const days: Array<{\n date: Date | null;\n isToday: boolean;\n isCurrentMonth: boolean;\n }> = [];\n\n // Add empty slots for days before the 1st\n for (let i = 0; i < firstDay; i++) {\n days.push({ date: null, isToday: false, isCurrentMonth: false });\n }\n\n // Add days of the month\n for (let day = 1; day <= daysInMonth; day++) {\n const date = new Date(year, month, day);\n const isToday =\n date.getDate() === today.getDate() &&\n date.getMonth() === today.getMonth() &&\n date.getFullYear() === today.getFullYear();\n days.push({ date, isToday, isCurrentMonth: true });\n }\n\n return days;\n};\n\n// Generate week grid for current week\nconst generateWeekGrid = () => {\n const today = new Date();\n const currentDay = today.getDay();\n const days: Array<{\n date: Date;\n isToday: boolean;\n }> = [];\n\n for (let i = 0; i < 7; i++) {\n const date = new Date(today);\n date.setDate(today.getDate() - currentDay + i);\n days.push({\n date,\n isToday: date.toDateString() === today.toDateString(),\n });\n }\n\n return days;\n};\n\n// Get events for a specific date\nconst getEventsForDate = (date: Date, events: CalendarEvent[]) => {\n const dayStart = new Date(date);\n dayStart.setHours(0, 0, 0, 0);\n const dayEnd = new Date(date);\n dayEnd.setHours(23, 59, 59, 999);\n\n return events.filter((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n return eventStart <= dayEnd && eventEnd >= dayStart;\n });\n};\n\n// Check if a date has events\nconst hasEventsOnDate = (date: Date | null, events: CalendarEvent[]) => {\n if (!date) return false;\n return getEventsForDate(date, events).length > 0;\n};\n\n// Event item component\nconst EventItem = ({\n title,\n start,\n end,\n color,\n isAllDay,\n accentColor,\n}: CalendarEvent & { accentColor?: string }) => {\n const startTime = new Date(start).toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n const endTime = new Date(end).toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n\n return (\n <div className=\"flex gap-x-2\">\n <div\n className=\"w-0.5 shrink-0 rounded-full\"\n style={{ backgroundColor: color || accentColor }}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-medium\">{title}</div>\n <div className=\"text-xs opacity-60\">\n {isAllDay ? \"All day\" : `${startTime} - ${endTime}`}\n </div>\n </div>\n </div>\n );\n};\n\nconst dayNames = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n\ntype DayButtonProps = {\n date: Date;\n isToday: boolean;\n isSelected: boolean;\n hasEvents: boolean;\n accentColor: string;\n onClick: () => void;\n extraClassName?: string;\n};\n\nfunction DayButton({\n date,\n isToday,\n isSelected,\n hasEvents,\n accentColor,\n onClick,\n extraClassName = \"\",\n}: DayButtonProps) {\n return (\n <button\n onClick={onClick}\n className={`relative flex aspect-square items-center justify-center rounded-full text-sm transition-colors ${\n isSelected\n ? `bg-${accentColor} text-${accentColor}-foreground`\n : isToday\n ? `bg-${accentColor}/30 text-${accentColor}-foreground hover:bg-${accentColor}/50`\n : `hover:bg-${accentColor}/50 hover:text-${accentColor}-foreground`\n } ${extraClassName}`}\n >\n {date.getDate()}\n {hasEvents && (\n <div\n className={`absolute bottom-1 h-1 w-1 rounded-full bg-${accentColor}`}\n />\n )}\n </button>\n );\n}\n\ntype CalendarWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\nexport function CalendarWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"Calendar\",\n titleFontSize = \"xl\",\n titleColor = \"foreground\",\n\n // Styling defaults\n background = {\n type: \"solid\",\n color: \"background\",\n },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n className,\n ...props\n}: CalendarWidgetProps): React.JSX.Element {\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 const today = new Date();\n const [currentMonth, setCurrentMonth] = useState(today.getMonth());\n const [currentYear, setCurrentYear] = useState(today.getFullYear());\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [selectedDate, setSelectedDate] = useState<Date | null>(today);\n\n const { data: events = [], isLoading, isError } = useCalendarEvents();\n\n // Generate calendar grids\n const monthGrid = useMemo(\n () => generateMonthGrid(currentYear, currentMonth),\n [currentYear, currentMonth],\n );\n const weekGrid = useMemo(() => generateWeekGrid(), []);\n\n // Get events for selected date\n const selectedDateEvents = useMemo(() => {\n if (!selectedDate) return [];\n return getEventsForDate(selectedDate, events);\n }, [selectedDate, events]);\n\n // Navigation handlers\n const goToPrevMonth = () => {\n if (currentMonth === 0) {\n setCurrentMonth(11);\n setCurrentYear(currentYear - 1);\n } else {\n setCurrentMonth(currentMonth - 1);\n }\n };\n\n const goToNextMonth = () => {\n if (currentMonth === 11) {\n setCurrentMonth(0);\n setCurrentYear(currentYear + 1);\n } else {\n setCurrentMonth(currentMonth + 1);\n }\n };\n\n const monthYearLabel = new Date(currentYear, currentMonth).toLocaleString(\n \"en-US\",\n {\n month: \"long\",\n year: \"numeric\",\n },\n );\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} text-${textColor} ${className}`}\n style={{ backgroundImage }}\n {...props}\n >\n {/* Title */}\n {titleEnabled && titleText && (\n <div className={`p-${padding} pb-0`}>\n <h2\n className={`text-${titleFontSize} font-header font-bold text-${titleColor}`}\n >\n {titleText}\n </h2>\n </div>\n )}\n\n {/* Loading state */}\n {isLoading ? (\n <div\n className={`flex min-h-[300px] items-center justify-center p-${padding}`}\n >\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n /* Error state */\n <ErrorState />\n ) : (\n <div className={`p-${padding}`}>\n {/* Desktop: Side by side layout */}\n <div className=\"@md:flex @md:gap-6\">\n {/* Calendar Section */}\n <div className=\"@md:flex-none\">\n {/* Month/Year Header with Navigation */}\n <div className=\"mb-4 flex items-center justify-between\">\n <button\n onClick={goToPrevMonth}\n className=\"hover:bg-foreground/10 rounded-full p-1\"\n aria-label=\"Previous month\"\n >\n <ChevronLeft className=\"size-4\" />\n </button>\n\n <span className=\"text-base font-semibold\">\n {monthYearLabel}\n </span>\n\n <button\n onClick={goToNextMonth}\n className=\"hover:bg-foreground/10 rounded-full p-1\"\n aria-label=\"Next month\"\n >\n <ChevronRight className=\"size-4\" />\n </button>\n </div>\n\n {/* Day Headers */}\n <div className=\"mb-2 grid grid-cols-7 gap-1 text-center\">\n {dayNames.map((day, idx) => (\n <div\n key={idx}\n className=\"text-xs font-medium uppercase opacity-60\"\n >\n {day}\n </div>\n ))}\n </div>\n\n {/* Calendar Grid - Week view on mobile when collapsed */}\n {isCollapsed && (\n <div className=\"grid grid-cols-7 gap-1 @md:hidden\">\n {weekGrid.map(({ date, isToday }, idx) => (\n <DayButton\n key={idx}\n date={date}\n isToday={isToday}\n isSelected={\n selectedDate?.toDateString() === date.toDateString()\n }\n hasEvents={hasEventsOnDate(date, events)}\n accentColor={accentColor}\n onClick={() => setSelectedDate(date)}\n />\n ))}\n </div>\n )}\n\n {/* Month view (always on desktop, when not collapsed on mobile) */}\n <div\n className={`grid grid-cols-7 gap-1 ${isCollapsed ? \"hidden @md:grid\" : \"grid\"}`}\n >\n {monthGrid.map((day, idx) => {\n if (!day.date) {\n return <div key={idx} className=\"aspect-square\" />;\n }\n\n return (\n <DayButton\n key={idx}\n date={day.date}\n isToday={day.isToday}\n isSelected={\n selectedDate?.toDateString() === day.date.toDateString()\n }\n hasEvents={hasEventsOnDate(day.date, events)}\n accentColor={accentColor}\n onClick={() => setSelectedDate(day.date)}\n extraClassName=\"p-2 @md:m-3\"\n />\n );\n })}\n </div>\n\n {/* Mobile collapse toggle */}\n <button\n onClick={() => setIsCollapsed(!isCollapsed)}\n className={`ml-2 flex w-full items-center justify-center gap-3 rounded-full p-1 text-${textColor}/50 @md:hidden`}\n aria-label={\n isCollapsed ? \"Expand calendar\" : \"Collapse calendar\"\n }\n >\n <div className={`h-1 w-1/2 bg-${textColor}/50`} />\n {isCollapsed ? (\n <ChevronsDown className=\"size-4\" />\n ) : (\n <ChevronsUp className=\"size-4\" />\n )}\n <div className={`h-1 w-1/2 bg-${textColor}/50`} />\n </button>\n </div>\n\n {/* Events Panel */}\n <div className=\"border-muted mt-4 pt-4 @md:mt-0 @md:w-56 @md:border-l @md:pt-0 @md:pl-6\">\n <div className=\"mb-2 text-sm font-medium opacity-60\">\n {selectedDate\n ? selectedDate.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n month: \"short\",\n day: \"numeric\",\n })\n : \"Select a date\"}\n </div>\n\n {selectedDateEvents.length > 0 ? (\n <div className=\"flex flex-col gap-3\">\n {selectedDateEvents.map((event, idx) => (\n <EventItem\n key={`${event.id}-${idx}`}\n {...event}\n accentColor={`var(--${accentColor})`}\n />\n ))}\n </div>\n ) : (\n <div className=\"text-sm opacity-50\">No events</div>\n )}\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const calendarWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CalendarWidget\",\n displayName: \"Calendar Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the calendar\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the calendar\",\n defaultValue: \"Calendar\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Design Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the calendar container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for calendar content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color used for today highlight and event indicators\",\n defaultValue: \"primary\",\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 getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the calendar container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the calendar container\",\n defaultValue: \"md\",\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} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"LinkWidget-BdQSowRZ.mjs","names":[],"sources":["../../widgets/src/widgets/LinkWidget.tsx"],"sourcesContent":["import type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport { useCallback, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport { Button } from \"@fluid-app/ui-primitives\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\nimport {\n getBorderRadiusCompositeField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getButtonSizeField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ButtonSizeOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { ShareableItem } from \"@fluid-app/portal-core/types\";\n\ntype LinkVariant =\n | \"default\"\n | \"outline\"\n | \"secondary\"\n | \"ghost\"\n | \"destructive\";\n\nconst borderRadiusTLClasses: Record<BorderRadiusOptions, string> = {\n none: \"rounded-tl-none\",\n sm: \"rounded-tl-sm\",\n md: \"rounded-tl-md\",\n lg: \"rounded-tl-lg\",\n xl: \"rounded-tl-xl\",\n full: \"rounded-tl-full\",\n};\n\nconst borderRadiusTRClasses: Record<BorderRadiusOptions, string> = {\n none: \"rounded-tr-none\",\n sm: \"rounded-tr-sm\",\n md: \"rounded-tr-md\",\n lg: \"rounded-tr-lg\",\n xl: \"rounded-tr-xl\",\n full: \"rounded-tr-full\",\n};\n\nconst borderRadiusBLClasses: Record<BorderRadiusOptions, string> = {\n none: \"rounded-bl-none\",\n sm: \"rounded-bl-sm\",\n md: \"rounded-bl-md\",\n lg: \"rounded-bl-lg\",\n xl: \"rounded-bl-xl\",\n full: \"rounded-bl-full\",\n};\n\nconst borderRadiusBRClasses: Record<BorderRadiusOptions, string> = {\n none: \"rounded-br-none\",\n sm: \"rounded-br-sm\",\n md: \"rounded-br-md\",\n lg: \"rounded-br-lg\",\n xl: \"rounded-br-xl\",\n full: \"rounded-br-full\",\n};\n\nfunction sanitizeHref(url: string): string | undefined {\n if (!url) return undefined;\n if (/^(https?:|mailto:|tel:|\\/)/i.test(url)) return url;\n return undefined;\n}\n\nexport type LinkType = \"url\" | \"screen\" | \"share\";\nexport type ShareSource = \"resource\" | \"url\";\n\ntype LinkWidgetProps = ComponentProps<\"div\"> & {\n text?: string;\n linkType?: LinkType;\n // URL mode\n href?: string;\n openInNewTab?: boolean;\n // Screen mode\n screenSlug?: string;\n // Share mode\n shareSource?: ShareSource;\n shareResource?: ShareableItem;\n shareUrl?: string;\n // Styling\n variant?: LinkVariant;\n size?: ButtonSizeOptions;\n fontSize?: FontSizeOptions;\n alignment?: \"left\" | \"center\" | \"right\";\n fullWidth?: boolean;\n padding?: PaddingOptions;\n /** @deprecated Use per-corner props instead */\n borderRadius?: BorderRadiusOptions;\n borderRadiusTL?: BorderRadiusOptions;\n borderRadiusTR?: BorderRadiusOptions;\n borderRadiusBL?: BorderRadiusOptions;\n borderRadiusBR?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n underline?: boolean;\n previewMode?: boolean;\n editMode?: boolean;\n};\n\nconst alignmentClasses = {\n left: \"justify-start\",\n center: \"justify-center\",\n right: \"justify-end\",\n} as const;\n\nexport function LinkWidget({\n text = \"Click Here\",\n linkType = \"url\",\n href = \"\",\n openInNewTab = true,\n screenSlug,\n shareSource,\n shareResource,\n shareUrl,\n variant = \"default\",\n size = \"default\",\n fontSize = \"sm\",\n alignment = \"center\",\n fullWidth = false,\n padding = 0,\n borderRadius,\n borderRadiusTL,\n borderRadiusTR,\n borderRadiusBL,\n borderRadiusBR,\n borderWidth = \"none\",\n borderColor = \"muted\",\n underline = false,\n previewMode = false,\n editMode = false,\n className,\n ...props\n}: LinkWidgetProps): React.JSX.Element {\n const { onNavigate, buildHref } = useWidgetInteraction();\n\n const handleShareClick = useCallback(async () => {\n const isResourceMode = shareSource === \"resource\" || shareSource == null;\n const url = isResourceMode\n ? (shareResource?.share_link ?? undefined)\n : (shareUrl ?? undefined);\n if (!url) return;\n\n if (navigator.share) {\n try {\n await navigator.share({\n url,\n ...(isResourceMode && shareResource?.title\n ? { title: shareResource.title }\n : {}),\n });\n return;\n } catch (e) {\n // User intentionally dismissed the share sheet — do not copy to clipboard\n if (e instanceof DOMException && e.name === \"AbortError\") return;\n // Other errors (e.g. NotAllowedError) — fall through to clipboard\n }\n }\n\n try {\n await navigator.clipboard.writeText(url);\n } catch {\n // Clipboard API not available\n }\n }, [shareSource, shareUrl, shareResource]);\n\n const handleScreenClick = useCallback(\n (e: React.MouseEvent) => {\n if (onNavigate && screenSlug) {\n e.preventDefault();\n onNavigate(screenSlug);\n }\n },\n [onNavigate, screenSlug],\n );\n\n const screenHref = screenSlug\n ? (buildHref?.(screenSlug) ?? screenSlug)\n : undefined;\n if (previewMode) {\n return (\n <div className={`flex justify-center p-4 ${className ?? \"\"}`} {...props}>\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"36px\",\n padding: \"0 16px\",\n borderRadius: \"6px\",\n backgroundColor: \"#18181b\",\n color: \"#ffffff\",\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n {text}\n </span>\n </div>\n );\n }\n\n const fallback = borderRadius ?? \"md\";\n const tl = borderRadiusTL ?? fallback;\n const tr = borderRadiusTR ?? fallback;\n const bl = borderRadiusBL ?? fallback;\n const br = borderRadiusBR ?? fallback;\n const borderRadiusClasses = `rounded-none ${borderRadiusTLClasses[tl]} ${borderRadiusTRClasses[tr]} ${borderRadiusBLClasses[bl]} ${borderRadiusBRClasses[br]}`;\n const buttonClasses = `text-${fontSize} ${borderRadiusClasses} ${fullWidth ? \"w-full\" : \"\"} ${underline ? \"underline\" : \"\"}`;\n\n return (\n <div\n className={`flex ${alignmentClasses[alignment]} p-${padding} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n {...props}\n >\n <Button asChild variant={variant} size={size} className={buttonClasses}>\n {editMode ? (\n <span className=\"cursor-default\">{text}</span>\n ) : linkType === \"share\" ? (\n <button type=\"button\" onClick={handleShareClick}>\n {text}\n </button>\n ) : linkType === \"screen\" ? (\n screenSlug ? (\n <a href={screenHref} onClick={handleScreenClick}>\n {text}\n </a>\n ) : (\n <span className=\"cursor-default\">{text}</span>\n )\n ) : (\n <a\n href={sanitizeHref(href)}\n {...(openInNewTab\n ? { target: \"_blank\", rel: \"noopener noreferrer\" }\n : {})}\n >\n {text}\n </a>\n )}\n </Button>\n </div>\n );\n}\n\nexport const linkWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"LinkWidget\",\n displayName: \"Link Button\",\n fields: [\n // Link Group\n {\n key: \"linkType\",\n label: \"Link Type\",\n type: \"buttonGroup\",\n options: [\n { label: \"URL\", value: \"url\" },\n { label: \"Screen\", value: \"screen\" },\n { label: \"Share\", value: \"share\" },\n ],\n defaultValue: \"url\",\n group: \"Link\",\n },\n {\n key: \"text\",\n label: \"Text\",\n type: \"text\",\n description: \"The button label text\",\n defaultValue: \"Click Here\",\n group: \"Link\",\n },\n // URL mode fields\n {\n key: \"href\",\n label: \"URL\",\n type: \"text\",\n description: \"The destination URL\",\n defaultValue: \"\",\n group: \"Link\",\n requiresKeyValue: { key: \"linkType\", value: \"url\" },\n },\n {\n key: \"openInNewTab\",\n label: \"Open in New Tab\",\n type: \"boolean\",\n description: \"Whether to open the link in a new tab\",\n defaultValue: true,\n group: \"Link\",\n requiresKeyValue: { key: \"linkType\", value: \"url\" },\n },\n // Screen mode fields\n {\n key: \"screenSlug\",\n label: \"Screen\",\n type: \"screenPicker\",\n description: \"Select a screen to navigate to\",\n includeSystemItems: true,\n group: \"Link\",\n requiresKeyValue: { key: \"linkType\", value: \"screen\" },\n },\n // Share mode fields\n {\n key: \"shareSource\",\n label: \"Share Source\",\n type: \"buttonGroup\",\n options: [\n { label: \"Resource\", value: \"resource\" },\n { label: \"URL\", value: \"url\" },\n ],\n defaultValue: \"resource\",\n group: \"Link\",\n requiresKeyValue: { key: \"linkType\", value: \"share\" },\n },\n {\n key: \"shareResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select content to share\",\n allowedTypes: [\"Product\", \"Medium\", \"Library\", \"Page\", \"EnrollmentPack\"],\n group: \"Link\",\n requiresKeyValue: [\n { key: \"linkType\", value: \"share\" },\n { key: \"shareSource\", value: \"resource\" },\n ],\n },\n {\n key: \"shareUrl\",\n label: \"Share URL\",\n type: \"text\",\n description: \"The URL to share\",\n defaultValue: \"\",\n group: \"Link\",\n requiresKeyValue: [\n { key: \"linkType\", value: \"share\" },\n { key: \"shareSource\", value: \"url\" },\n ],\n },\n // Button Style Group\n {\n key: \"variant\",\n label: \"Variant\",\n type: \"select\",\n description: \"The visual style of the button\",\n options: [\n { label: \"Default\", value: \"default\" },\n { label: \"Outline\", value: \"outline\" },\n { label: \"Secondary\", value: \"secondary\" },\n { label: \"Ghost\", value: \"ghost\" },\n { label: \"Destructive\", value: \"destructive\" },\n ],\n defaultValue: \"default\",\n group: \"Button Style\",\n },\n getButtonSizeField({\n key: \"size\",\n label: \"Size\",\n description: \"The size of the button\",\n defaultValue: \"default\",\n group: \"Button Style\",\n }),\n getFontSizeField({\n key: \"fontSize\",\n label: \"Text Size\",\n description: \"The font size of the button text\",\n defaultValue: \"sm\",\n group: \"Button Style\",\n }),\n {\n key: \"underline\",\n label: \"Underline\",\n type: \"boolean\",\n description: \"Underline the button text\",\n defaultValue: false,\n group: \"Button Style\",\n },\n // Layout Group\n {\n key: \"alignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Horizontal alignment of the button\",\n options: [\n { label: \"Left\", value: \"left\" },\n { label: \"Center\", value: \"center\" },\n { label: \"Right\", value: \"right\" },\n ],\n defaultValue: \"center\",\n group: \"Layout\",\n },\n {\n key: \"fullWidth\",\n label: \"Full Width\",\n type: \"boolean\",\n description: \"Makes the button stretch to full container width\",\n defaultValue: false,\n group: \"Layout\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Outer container padding\",\n defaultValue: 0,\n group: \"Layout\",\n }),\n // Design Group\n getBorderRadiusCompositeField({\n key: \"borderRadiusGroup\",\n label: \"Border Radius\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\n defaultValue: \"none\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n ],\n};\n"],"mappings":";;;;;;;;;;;AAgCA,MAAM,wBAA6D;CACjE,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;CACP;AAED,MAAM,wBAA6D;CACjE,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;CACP;AAED,MAAM,wBAA6D;CACjE,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;CACP;AAED,MAAM,wBAA6D;CACjE,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;CACP;AAED,SAAS,aAAa,KAAiC;AACrD,KAAI,CAAC,IAAK,QAAO,KAAA;AACjB,KAAI,8BAA8B,KAAK,IAAI,CAAE,QAAO;;AAuCtD,MAAM,mBAAmB;CACvB,MAAM;CACN,QAAQ;CACR,OAAO;CACR;AAED,SAAgB,WAAW,EACzB,OAAO,cACP,WAAW,OACX,OAAO,IACP,eAAe,MACf,YACA,aACA,eACA,UACA,UAAU,WACV,OAAO,WACP,WAAW,MACX,YAAY,UACZ,YAAY,OACZ,UAAU,GACV,cACA,gBACA,gBACA,gBACA,gBACA,cAAc,QACd,cAAc,SACd,YAAY,OACZ,cAAc,OACd,WAAW,OACX,WACA,GAAG,SACkC;CACrC,MAAM,EAAE,YAAY,cAAc,sBAAsB;CAExD,MAAM,mBAAmB,YAAY,YAAY;EAC/C,MAAM,iBAAiB,gBAAgB,cAAc,eAAe;EACpE,MAAM,MAAM,iBACP,eAAe,cAAc,KAAA,IAC7B,YAAY,KAAA;AACjB,MAAI,CAAC,IAAK;AAEV,MAAI,UAAU,MACZ,KAAI;AACF,SAAM,UAAU,MAAM;IACpB;IACA,GAAI,kBAAkB,eAAe,QACjC,EAAE,OAAO,cAAc,OAAO,GAC9B,EAAE;IACP,CAAC;AACF;WACO,GAAG;AAEV,OAAI,aAAa,gBAAgB,EAAE,SAAS,aAAc;;AAK9D,MAAI;AACF,SAAM,UAAU,UAAU,UAAU,IAAI;UAClC;IAGP;EAAC;EAAa;EAAU;EAAc,CAAC;CAE1C,MAAM,oBAAoB,aACvB,MAAwB;AACvB,MAAI,cAAc,YAAY;AAC5B,KAAE,gBAAgB;AAClB,cAAW,WAAW;;IAG1B,CAAC,YAAY,WAAW,CACzB;CAED,MAAM,aAAa,aACd,YAAY,WAAW,IAAI,aAC5B,KAAA;AACJ,KAAI,YACF,QACE,oBAAC,OAAD;EAAK,WAAW,2BAA2B,aAAa;EAAM,GAAI;YAChE,oBAAC,QAAD;GACE,OAAO;IACL,SAAS;IACT,YAAY;IACZ,gBAAgB;IAChB,QAAQ;IACR,SAAS;IACT,cAAc;IACd,iBAAiB;IACjB,OAAO;IACP,UAAU;IACV,YAAY;IACb;aAEA;GACI,CAAA;EACH,CAAA;CAIV,MAAM,WAAW,gBAAgB;CACjC,MAAM,KAAK,kBAAkB;CAC7B,MAAM,KAAK,kBAAkB;CAC7B,MAAM,KAAK,kBAAkB;CAC7B,MAAM,KAAK,kBAAkB;CAE7B,MAAM,gBAAgB,QAAQ,SAAS,GADX,gBAAgB,sBAAsB,IAAI,GAAG,sBAAsB,IAAI,GAAG,sBAAsB,IAAI,GAAG,sBAAsB,MAC3F,GAAG,YAAY,WAAW,GAAG,GAAG,YAAY,cAAc;AAExH,QACE,oBAAC,OAAD;EACE,WAAW,QAAQ,iBAAiB,WAAW,KAAK,QAAQ,GAAG,mBAAmB,aAAa,GAAG,gBAAgB,SAAS,mBAAmB,eAAe,GAAG,GAAG,aAAa;EAChL,GAAI;YAEJ,oBAAC,QAAD;GAAQ,SAAA;GAAiB;GAAe;GAAM,WAAW;aACtD,WACC,oBAAC,QAAD;IAAM,WAAU;cAAkB;IAAY,CAAA,GAC5C,aAAa,UACf,oBAAC,UAAD;IAAQ,MAAK;IAAS,SAAS;cAC5B;IACM,CAAA,GACP,aAAa,WACf,aACE,oBAAC,KAAD;IAAG,MAAM;IAAY,SAAS;cAC3B;IACC,CAAA,GAEJ,oBAAC,QAAD;IAAM,WAAU;cAAkB;IAAY,CAAA,GAGhD,oBAAC,KAAD;IACE,MAAM,aAAa,KAAK;IACxB,GAAK,eACD;KAAE,QAAQ;KAAU,KAAK;KAAuB,GAChD,EAAE;cAEL;IACC,CAAA;GAEC,CAAA;EACL,CAAA;;AAIV,MAAa,2BAAiD;CAC5D,YAAY;CACZ,aAAa;CACb,QAAQ;EAEN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS;IACP;KAAE,OAAO;KAAO,OAAO;KAAO;IAC9B;KAAE,OAAO;KAAU,OAAO;KAAU;IACpC;KAAE,OAAO;KAAS,OAAO;KAAS;IACnC;GACD,cAAc;GACd,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAY,OAAO;IAAO;GACpD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAY,OAAO;IAAO;GACpD;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,oBAAoB;GACpB,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAY,OAAO;IAAU;GACvD;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,SAAS,CACP;IAAE,OAAO;IAAY,OAAO;IAAY,EACxC;IAAE,OAAO;IAAO,OAAO;IAAO,CAC/B;GACD,cAAc;GACd,OAAO;GACP,kBAAkB;IAAE,KAAK;IAAY,OAAO;IAAS;GACtD;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;IAAC;IAAW;IAAU;IAAW;IAAQ;IAAiB;GACxE,OAAO;GACP,kBAAkB,CAChB;IAAE,KAAK;IAAY,OAAO;IAAS,EACnC;IAAE,KAAK;IAAe,OAAO;IAAY,CAC1C;GACF;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,OAAO;GACP,kBAAkB,CAChB;IAAE,KAAK;IAAY,OAAO;IAAS,EACnC;IAAE,KAAK;IAAe,OAAO;IAAO,CACrC;GACF;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,SAAS;IACP;KAAE,OAAO;KAAW,OAAO;KAAW;IACtC;KAAE,OAAO;KAAW,OAAO;KAAW;IACtC;KAAE,OAAO;KAAa,OAAO;KAAa;IAC1C;KAAE,OAAO;KAAS,OAAO;KAAS;IAClC;KAAE,OAAO;KAAe,OAAO;KAAe;IAC/C;GACD,cAAc;GACd,OAAO;GACR;EACD,mBAAmB;GACjB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,OAAO;GACR,CAAC;EACF,iBAAiB;GACf,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,SAAS;IACP;KAAE,OAAO;KAAQ,OAAO;KAAQ;IAChC;KAAE,OAAO;KAAU,OAAO;KAAU;IACpC;KAAE,OAAO;KAAS,OAAO;KAAS;IACnC;GACD,cAAc;GACd,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,OAAO;GACR;EACD,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,OAAO;GACR,CAAC;EAEF,8BAA8B;GAC5B,KAAK;GACL,OAAO;GACP,cAAc;GACd,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,OAAO;GACR,CAAC;EACH;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"LinkWidget-nstWDcsr.cjs","names":["useWidgetInteraction","borderWidthClasses","borderColorClasses","Button","getButtonSizeField","getFontSizeField","getPaddingField","getBorderRadiusCompositeField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/widgets/LinkWidget.tsx"],"sourcesContent":["import type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport { useCallback, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport { Button } from \"@fluid-app/ui-primitives\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\nimport {\n getBorderRadiusCompositeField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getButtonSizeField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ButtonSizeOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { ShareableItem } from \"@fluid-app/portal-core/types\";\n\ntype LinkVariant =\n | \"default\"\n | \"outline\"\n | \"secondary\"\n | \"ghost\"\n | \"destructive\";\n\nconst borderRadiusTLClasses: Record<BorderRadiusOptions, string> = {\n none: \"rounded-tl-none\",\n sm: \"rounded-tl-sm\",\n md: \"rounded-tl-md\",\n lg: \"rounded-tl-lg\",\n xl: \"rounded-tl-xl\",\n full: \"rounded-tl-full\",\n};\n\nconst borderRadiusTRClasses: Record<BorderRadiusOptions, string> = {\n none: \"rounded-tr-none\",\n sm: \"rounded-tr-sm\",\n md: \"rounded-tr-md\",\n lg: \"rounded-tr-lg\",\n xl: \"rounded-tr-xl\",\n full: \"rounded-tr-full\",\n};\n\nconst borderRadiusBLClasses: Record<BorderRadiusOptions, string> = {\n none: \"rounded-bl-none\",\n sm: \"rounded-bl-sm\",\n md: \"rounded-bl-md\",\n lg: \"rounded-bl-lg\",\n xl: \"rounded-bl-xl\",\n full: \"rounded-bl-full\",\n};\n\nconst borderRadiusBRClasses: Record<BorderRadiusOptions, string> = {\n none: \"rounded-br-none\",\n sm: \"rounded-br-sm\",\n md: \"rounded-br-md\",\n lg: \"rounded-br-lg\",\n xl: \"rounded-br-xl\",\n full: \"rounded-br-full\",\n};\n\nfunction sanitizeHref(url: string): string | undefined {\n if (!url) return undefined;\n if (/^(https?:|mailto:|tel:|\\/)/i.test(url)) return url;\n return undefined;\n}\n\nexport type LinkType = \"url\" | \"screen\" | \"share\";\nexport type ShareSource = \"resource\" | \"url\";\n\ntype LinkWidgetProps = ComponentProps<\"div\"> & {\n text?: string;\n linkType?: LinkType;\n // URL mode\n href?: string;\n openInNewTab?: boolean;\n // Screen mode\n screenSlug?: string;\n // Share mode\n shareSource?: ShareSource;\n shareResource?: ShareableItem;\n shareUrl?: string;\n // Styling\n variant?: LinkVariant;\n size?: ButtonSizeOptions;\n fontSize?: FontSizeOptions;\n alignment?: \"left\" | \"center\" | \"right\";\n fullWidth?: boolean;\n padding?: PaddingOptions;\n /** @deprecated Use per-corner props instead */\n borderRadius?: BorderRadiusOptions;\n borderRadiusTL?: BorderRadiusOptions;\n borderRadiusTR?: BorderRadiusOptions;\n borderRadiusBL?: BorderRadiusOptions;\n borderRadiusBR?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n underline?: boolean;\n previewMode?: boolean;\n editMode?: boolean;\n};\n\nconst alignmentClasses = {\n left: \"justify-start\",\n center: \"justify-center\",\n right: \"justify-end\",\n} as const;\n\nexport function LinkWidget({\n text = \"Click Here\",\n linkType = \"url\",\n href = \"\",\n openInNewTab = true,\n screenSlug,\n shareSource,\n shareResource,\n shareUrl,\n variant = \"default\",\n size = \"default\",\n fontSize = \"sm\",\n alignment = \"center\",\n fullWidth = false,\n padding = 0,\n borderRadius,\n borderRadiusTL,\n borderRadiusTR,\n borderRadiusBL,\n borderRadiusBR,\n borderWidth = \"none\",\n borderColor = \"muted\",\n underline = false,\n previewMode = false,\n editMode = false,\n className,\n ...props\n}: LinkWidgetProps): React.JSX.Element {\n const { onNavigate, buildHref } = useWidgetInteraction();\n\n const handleShareClick = useCallback(async () => {\n const isResourceMode = shareSource === \"resource\" || shareSource == null;\n const url = isResourceMode\n ? (shareResource?.share_link ?? undefined)\n : (shareUrl ?? undefined);\n if (!url) return;\n\n if (navigator.share) {\n try {\n await navigator.share({\n url,\n ...(isResourceMode && shareResource?.title\n ? { title: shareResource.title }\n : {}),\n });\n return;\n } catch (e) {\n // User intentionally dismissed the share sheet — do not copy to clipboard\n if (e instanceof DOMException && e.name === \"AbortError\") return;\n // Other errors (e.g. NotAllowedError) — fall through to clipboard\n }\n }\n\n try {\n await navigator.clipboard.writeText(url);\n } catch {\n // Clipboard API not available\n }\n }, [shareSource, shareUrl, shareResource]);\n\n const handleScreenClick = useCallback(\n (e: React.MouseEvent) => {\n if (onNavigate && screenSlug) {\n e.preventDefault();\n onNavigate(screenSlug);\n }\n },\n [onNavigate, screenSlug],\n );\n\n const screenHref = screenSlug\n ? (buildHref?.(screenSlug) ?? screenSlug)\n : undefined;\n if (previewMode) {\n return (\n <div className={`flex justify-center p-4 ${className ?? \"\"}`} {...props}>\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"36px\",\n padding: \"0 16px\",\n borderRadius: \"6px\",\n backgroundColor: \"#18181b\",\n color: \"#ffffff\",\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n {text}\n </span>\n </div>\n );\n }\n\n const fallback = borderRadius ?? \"md\";\n const tl = borderRadiusTL ?? fallback;\n const tr = borderRadiusTR ?? fallback;\n const bl = borderRadiusBL ?? fallback;\n const br = borderRadiusBR ?? fallback;\n const borderRadiusClasses = `rounded-none ${borderRadiusTLClasses[tl]} ${borderRadiusTRClasses[tr]} ${borderRadiusBLClasses[bl]} ${borderRadiusBRClasses[br]}`;\n const buttonClasses = `text-${fontSize} ${borderRadiusClasses} ${fullWidth ? \"w-full\" : \"\"} ${underline ? \"underline\" : \"\"}`;\n\n return (\n <div\n className={`flex ${alignmentClasses[alignment]} p-${padding} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n {...props}\n >\n <Button asChild variant={variant} size={size} className={buttonClasses}>\n {editMode ? (\n <span className=\"cursor-default\">{text}</span>\n ) : linkType === \"share\" ? (\n <button type=\"button\" onClick={handleShareClick}>\n {text}\n </button>\n ) : linkType === \"screen\" ? (\n screenSlug ? (\n <a href={screenHref} onClick={handleScreenClick}>\n {text}\n </a>\n ) : (\n <span className=\"cursor-default\">{text}</span>\n )\n ) : (\n <a\n href={sanitizeHref(href)}\n {...(openInNewTab\n ? { target: \"_blank\", rel: \"noopener noreferrer\" }\n : {})}\n >\n {text}\n </a>\n )}\n </Button>\n </div>\n );\n}\n\nexport const linkWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"LinkWidget\",\n displayName: \"Link Button\",\n fields: [\n // Link Group\n {\n key: \"linkType\",\n label: \"Link Type\",\n type: \"buttonGroup\",\n options: [\n { label: \"URL\", value: \"url\" },\n { label: \"Screen\", value: \"screen\" },\n { label: \"Share\", value: \"share\" },\n ],\n defaultValue: \"url\",\n group: \"Link\",\n },\n {\n key: \"text\",\n label: \"Text\",\n type: \"text\",\n description: \"The button label text\",\n defaultValue: \"Click Here\",\n group: \"Link\",\n },\n // URL mode fields\n {\n key: \"href\",\n label: \"URL\",\n type: \"text\",\n description: \"The destination URL\",\n defaultValue: \"\",\n group: \"Link\",\n requiresKeyValue: { key: \"linkType\", value: \"url\" },\n },\n {\n key: \"openInNewTab\",\n label: \"Open in New Tab\",\n type: \"boolean\",\n description: \"Whether to open the link in a new tab\",\n defaultValue: true,\n group: \"Link\",\n requiresKeyValue: { key: \"linkType\", value: \"url\" },\n },\n // Screen mode fields\n {\n key: \"screenSlug\",\n label: \"Screen\",\n type: \"screenPicker\",\n description: \"Select a screen to navigate to\",\n includeSystemItems: true,\n group: \"Link\",\n requiresKeyValue: { key: \"linkType\", value: \"screen\" },\n },\n // Share mode fields\n {\n key: \"shareSource\",\n label: \"Share Source\",\n type: \"buttonGroup\",\n options: [\n { label: \"Resource\", value: \"resource\" },\n { label: \"URL\", value: \"url\" },\n ],\n defaultValue: \"resource\",\n group: \"Link\",\n requiresKeyValue: { key: \"linkType\", value: \"share\" },\n },\n {\n key: \"shareResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select content to share\",\n allowedTypes: [\"Product\", \"Medium\", \"Library\", \"Page\", \"EnrollmentPack\"],\n group: \"Link\",\n requiresKeyValue: [\n { key: \"linkType\", value: \"share\" },\n { key: \"shareSource\", value: \"resource\" },\n ],\n },\n {\n key: \"shareUrl\",\n label: \"Share URL\",\n type: \"text\",\n description: \"The URL to share\",\n defaultValue: \"\",\n group: \"Link\",\n requiresKeyValue: [\n { key: \"linkType\", value: \"share\" },\n { key: \"shareSource\", value: \"url\" },\n ],\n },\n // Button Style Group\n {\n key: \"variant\",\n label: \"Variant\",\n type: \"select\",\n description: \"The visual style of the button\",\n options: [\n { label: \"Default\", value: \"default\" },\n { label: \"Outline\", value: \"outline\" },\n { label: \"Secondary\", value: \"secondary\" },\n { label: \"Ghost\", value: \"ghost\" },\n { label: \"Destructive\", value: \"destructive\" },\n ],\n defaultValue: \"default\",\n group: \"Button Style\",\n },\n getButtonSizeField({\n key: \"size\",\n label: \"Size\",\n description: \"The size of the button\",\n defaultValue: \"default\",\n group: \"Button Style\",\n }),\n getFontSizeField({\n key: \"fontSize\",\n label: \"Text Size\",\n description: \"The font size of the button text\",\n defaultValue: \"sm\",\n group: \"Button Style\",\n }),\n {\n key: \"underline\",\n label: \"Underline\",\n type: \"boolean\",\n description: \"Underline the button text\",\n defaultValue: false,\n group: \"Button Style\",\n },\n // Layout Group\n {\n key: \"alignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Horizontal alignment of the button\",\n options: [\n { label: \"Left\", value: \"left\" },\n { label: \"Center\", value: \"center\" },\n { label: \"Right\", value: \"right\" },\n ],\n defaultValue: \"center\",\n group: \"Layout\",\n },\n {\n key: \"fullWidth\",\n label: \"Full Width\",\n type: \"boolean\",\n description: \"Makes the button stretch to full container width\",\n defaultValue: false,\n group: \"Layout\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Outer container padding\",\n defaultValue: 0,\n group: \"Layout\",\n }),\n // Design Group\n getBorderRadiusCompositeField({\n key: \"borderRadiusGroup\",\n label: \"Border Radius\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\n defaultValue: \"none\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n ],\n};\n"],"mappings":"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"}