@fluid-app/portal-sdk 0.1.259 → 0.1.261
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AlertWidget-CcIBGBik.mjs → AlertWidget-Bua0I46v.mjs} +2 -2
- package/dist/{AlertWidget-CcIBGBik.mjs.map → AlertWidget-Bua0I46v.mjs.map} +1 -1
- package/dist/{AlertWidget-BZ67Uqfh.cjs → AlertWidget-ByokSA3K.cjs} +2 -2
- package/dist/{AlertWidget-BZ67Uqfh.cjs.map → AlertWidget-ByokSA3K.cjs.map} +1 -1
- package/dist/{BulletListWidget-iGJI33Ed.cjs → BulletListWidget-BwrMNPZ-.cjs} +2 -2
- package/dist/{BulletListWidget-iGJI33Ed.cjs.map → BulletListWidget-BwrMNPZ-.cjs.map} +1 -1
- package/dist/{BulletListWidget-mRwUgtzN.mjs → BulletListWidget-DvT2x5wg.mjs} +2 -2
- package/dist/{BulletListWidget-mRwUgtzN.mjs.map → BulletListWidget-DvT2x5wg.mjs.map} +1 -1
- package/dist/{CalendarWidget-ByY49yYX.mjs → CalendarWidget-BB1C5K_j.mjs} +2 -2
- package/dist/{CalendarWidget-ByY49yYX.mjs.map → CalendarWidget-BB1C5K_j.mjs.map} +1 -1
- package/dist/{CalendarWidget-CSipLdwg.cjs → CalendarWidget-MVJmxwFQ.cjs} +2 -2
- package/dist/{CalendarWidget-CSipLdwg.cjs.map → CalendarWidget-MVJmxwFQ.cjs.map} +1 -1
- package/dist/{CardWidget-CXsjl-Is.cjs → CardWidget-5hGl1bt9.cjs} +2 -2
- package/dist/{CardWidget-DK4VQau1.mjs → CardWidget-CEERBKUN.mjs} +2 -2
- package/dist/{CardWidget-DK4VQau1.mjs.map → CardWidget-CEERBKUN.mjs.map} +1 -1
- package/dist/{CardWidget-DovkTkKg.cjs → CardWidget-Cf4-dF-v.cjs} +2 -2
- package/dist/{CardWidget-DovkTkKg.cjs.map → CardWidget-Cf4-dF-v.cjs.map} +1 -1
- package/dist/{CarouselWidget-Cu1b3ERq.cjs → CarouselWidget-BJSO17JY.cjs} +2 -2
- package/dist/{CarouselWidget-Cu1b3ERq.cjs.map → CarouselWidget-BJSO17JY.cjs.map} +1 -1
- package/dist/{CarouselWidget-C0X-nFyW.mjs → CarouselWidget-Dhjf60LS.mjs} +2 -2
- package/dist/{CarouselWidget-C0X-nFyW.mjs.map → CarouselWidget-Dhjf60LS.mjs.map} +1 -1
- package/dist/{CatchUpWidget-C17xpj3Z.cjs → CatchUpWidget-CFF-Fgdo.cjs} +2 -2
- package/dist/{CatchUpWidget-C17xpj3Z.cjs.map → CatchUpWidget-CFF-Fgdo.cjs.map} +1 -1
- package/dist/{CatchUpWidget-Bj30ZbUk.mjs → CatchUpWidget-CM-iCMhK.mjs} +2 -2
- package/dist/{CatchUpWidget-Bj30ZbUk.mjs.map → CatchUpWidget-CM-iCMhK.mjs.map} +1 -1
- package/dist/{ChartWidget-Brxz8j4Q.cjs → ChartWidget-6nZLzlQM.cjs} +2 -2
- package/dist/{ChartWidget-Brxz8j4Q.cjs.map → ChartWidget-6nZLzlQM.cjs.map} +1 -1
- package/dist/{ChartWidget-CIscUHUD.mjs → ChartWidget-CJXZ9qf7.mjs} +2 -2
- package/dist/{ChartWidget-CIscUHUD.mjs.map → ChartWidget-CJXZ9qf7.mjs.map} +1 -1
- package/dist/{ChartWidget-CNhmJePK.cjs → ChartWidget-WXGJeXdl.cjs} +2 -2
- package/dist/{ContainerWidget-YMePQ1FG.mjs → ContainerWidget-2Rep2gGz.mjs} +3 -3
- package/dist/{ContainerWidget-YMePQ1FG.mjs.map → ContainerWidget-2Rep2gGz.mjs.map} +1 -1
- package/dist/{ContainerWidget-D5rr47AN.cjs → ContainerWidget-CpIynF1n.cjs} +3 -3
- package/dist/{ContainerWidget-wtuUrr1c.cjs → ContainerWidget-DX9qO1T-.cjs} +3 -3
- package/dist/{ContainerWidget-wtuUrr1c.cjs.map → ContainerWidget-DX9qO1T-.cjs.map} +1 -1
- package/dist/{EmbedWidget-DE1yhLR1.mjs → EmbedWidget-Czn_RJbm.mjs} +2 -2
- package/dist/{EmbedWidget-DE1yhLR1.mjs.map → EmbedWidget-Czn_RJbm.mjs.map} +1 -1
- package/dist/{EmbedWidget-BO0TonyK.cjs → EmbedWidget-DFlg5AI7.cjs} +2 -2
- package/dist/{EmbedWidget-BO0TonyK.cjs.map → EmbedWidget-DFlg5AI7.cjs.map} +1 -1
- package/dist/{FluidProvider-CDNk3Ssn.mjs → FluidProvider-C0YKxODs.mjs} +49 -49
- package/dist/{FluidProvider-CDNk3Ssn.mjs.map → FluidProvider-C0YKxODs.mjs.map} +1 -1
- package/dist/{FluidProvider-P_MBgI-c.cjs → FluidProvider-CoSgK0jL.cjs} +49 -49
- package/dist/{FluidProvider-P_MBgI-c.cjs.map → FluidProvider-CoSgK0jL.cjs.map} +1 -1
- package/dist/{ImageWidget-DmaAQZBK.mjs → ImageWidget--WJppfij.mjs} +2 -2
- package/dist/{ImageWidget-DmaAQZBK.mjs.map → ImageWidget--WJppfij.mjs.map} +1 -1
- package/dist/{ImageWidget-CbQVxMe3.cjs → ImageWidget-CU2cet5p.cjs} +2 -2
- package/dist/{ImageWidget-CbQVxMe3.cjs.map → ImageWidget-CU2cet5p.cjs.map} +1 -1
- package/dist/{LayoutWidget-BK8AxE60.cjs → LayoutWidget-8DwDBW24.cjs} +2 -2
- package/dist/{LayoutWidget-BK8AxE60.cjs.map → LayoutWidget-8DwDBW24.cjs.map} +1 -1
- package/dist/{LayoutWidget-K2iF13-C.cjs → LayoutWidget-CUjv-pB1.cjs} +2 -2
- package/dist/{LayoutWidget-8KxCmJcd.mjs → LayoutWidget-iKNNIRPq.mjs} +2 -2
- package/dist/{LayoutWidget-8KxCmJcd.mjs.map → LayoutWidget-iKNNIRPq.mjs.map} +1 -1
- package/dist/{LinkWidget-Dvb6WlaR.mjs → LinkWidget-BoVmB_zf.mjs} +2 -2
- package/dist/{LinkWidget-Dvb6WlaR.mjs.map → LinkWidget-BoVmB_zf.mjs.map} +1 -1
- package/dist/{LinkWidget-DnAGzdnF.cjs → LinkWidget-BzgMcUuV.cjs} +2 -2
- package/dist/{LinkWidget-88wWH7-i.cjs → LinkWidget-DpylGthu.cjs} +2 -2
- package/dist/{LinkWidget-88wWH7-i.cjs.map → LinkWidget-DpylGthu.cjs.map} +1 -1
- package/dist/{ListWidget-xetptWnX.cjs → ListWidget-CQgei8SF.cjs} +2 -2
- package/dist/{ListWidget-xetptWnX.cjs.map → ListWidget-CQgei8SF.cjs.map} +1 -1
- package/dist/{ListWidget-Bsi4jdcz.mjs → ListWidget-CuwsaMQ9.mjs} +2 -2
- package/dist/{ListWidget-Bsi4jdcz.mjs.map → ListWidget-CuwsaMQ9.mjs.map} +1 -1
- package/dist/{ListWidget-BzuYuJkf.cjs → ListWidget-TXPwy2v6.cjs} +2 -2
- package/dist/MessagingScreen-CKIs5m0_.cjs +48 -0
- package/dist/{MessagingScreen-SQXX6kkC.mjs → MessagingScreen-Ck6c7BK3.mjs} +2 -2
- package/dist/{MessagingScreen-SQXX6kkC.mjs.map → MessagingScreen-Ck6c7BK3.mjs.map} +1 -1
- package/dist/MessagingScreen-DgS_ZEzO.mjs +46 -0
- package/dist/{MessagingScreen-CsZsCnnX.cjs → MessagingScreen-ga_zEAeB.cjs} +2 -2
- package/dist/{MessagingScreen-CsZsCnnX.cjs.map → MessagingScreen-ga_zEAeB.cjs.map} +1 -1
- package/dist/{MySiteWidget-DXY59o3T.cjs → MySiteWidget-BziY8ylH.cjs} +2 -2
- package/dist/{MySiteWidget-DXY59o3T.cjs.map → MySiteWidget-BziY8ylH.cjs.map} +1 -1
- package/dist/{MySiteWidget-8XrZA0Un.mjs → MySiteWidget-CsJzjc7o.mjs} +2 -2
- package/dist/{MySiteWidget-8XrZA0Un.mjs.map → MySiteWidget-CsJzjc7o.mjs.map} +1 -1
- package/dist/{NestedWidget-CSA2gUPx.cjs → NestedWidget-B1Rwz6nb.cjs} +2 -2
- package/dist/{NestedWidget-B8lW9Fzv.mjs → NestedWidget-DrZ62oaO.mjs} +2 -2
- package/dist/{NestedWidget-B8lW9Fzv.mjs.map → NestedWidget-DrZ62oaO.mjs.map} +1 -1
- package/dist/{NestedWidget-C2D4eWqb.cjs → NestedWidget-vrohV65N.cjs} +2 -2
- package/dist/{NestedWidget-C2D4eWqb.cjs.map → NestedWidget-vrohV65N.cjs.map} +1 -1
- package/dist/{PointsWidget-ComTSNQZ.cjs → PointsWidget-DI3N8-6W.cjs} +2 -2
- package/dist/{PointsWidget-ComTSNQZ.cjs.map → PointsWidget-DI3N8-6W.cjs.map} +1 -1
- package/dist/{PointsWidget-CRvG5LOV.mjs → PointsWidget-ubAn0b-m.mjs} +2 -2
- package/dist/{PointsWidget-CRvG5LOV.mjs.map → PointsWidget-ubAn0b-m.mjs.map} +1 -1
- package/dist/ProfileScreen-90-Jf8IH.mjs +46 -0
- package/dist/ProfileScreen-B7sbMdbH.cjs +48 -0
- package/dist/{ProfileScreen-C6Z8g6-L.cjs → ProfileScreen-DYO-1rw4.cjs} +2 -2
- package/dist/{ProfileScreen-C6Z8g6-L.cjs.map → ProfileScreen-DYO-1rw4.cjs.map} +1 -1
- package/dist/{ProfileScreen-C45yTIj-.mjs → ProfileScreen-FG1DZum3.mjs} +2 -2
- package/dist/{ProfileScreen-C45yTIj-.mjs.map → ProfileScreen-FG1DZum3.mjs.map} +1 -1
- package/dist/{QuickLinksWidget-Bcl4CxfW.cjs → QuickLinksWidget-Cpq1V-uX.cjs} +2 -2
- package/dist/{QuickLinksWidget-Bcl4CxfW.cjs.map → QuickLinksWidget-Cpq1V-uX.cjs.map} +1 -1
- package/dist/{QuickLinksWidget-roBJQ1Ge.mjs → QuickLinksWidget-J5axodVF.mjs} +2 -2
- package/dist/{QuickLinksWidget-roBJQ1Ge.mjs.map → QuickLinksWidget-J5axodVF.mjs.map} +1 -1
- package/dist/{QuickShareWidget-D_Ghjgwz.cjs → QuickShareWidget-CYPOXs8X.cjs} +2 -2
- package/dist/{QuickShareWidget-D_Ghjgwz.cjs.map → QuickShareWidget-CYPOXs8X.cjs.map} +1 -1
- package/dist/{QuickShareWidget-D-NVbmfw.mjs → QuickShareWidget-CyYW9nS6.mjs} +2 -2
- package/dist/{QuickShareWidget-D-NVbmfw.mjs.map → QuickShareWidget-CyYW9nS6.mjs.map} +1 -1
- package/dist/{RecentActivityWidget-Bz54YXQN.mjs → RecentActivityWidget-CndO-Ac0.mjs} +2 -2
- package/dist/{RecentActivityWidget-Bz54YXQN.mjs.map → RecentActivityWidget-CndO-Ac0.mjs.map} +1 -1
- package/dist/{RecentActivityWidget-sv_3ewZa.cjs → RecentActivityWidget-Cp3fYBM2.cjs} +2 -2
- package/dist/{RecentActivityWidget-sv_3ewZa.cjs.map → RecentActivityWidget-Cp3fYBM2.cjs.map} +1 -1
- package/dist/{SeparatorWidget-CY6uMLHP.cjs → SeparatorWidget-DW_9_L9_.cjs} +2 -2
- package/dist/{SeparatorWidget-CY6uMLHP.cjs.map → SeparatorWidget-DW_9_L9_.cjs.map} +1 -1
- package/dist/{SeparatorWidget-DR75Yj_C.mjs → SeparatorWidget-eI7b2n6u.mjs} +2 -2
- package/dist/{SeparatorWidget-DR75Yj_C.mjs.map → SeparatorWidget-eI7b2n6u.mjs.map} +1 -1
- package/dist/{ShopScreen-C3PYT1v_.cjs → ShopScreen-BDhf2CmC.cjs} +2 -2
- package/dist/{ShopScreen-C3PYT1v_.cjs.map → ShopScreen-BDhf2CmC.cjs.map} +1 -1
- package/dist/ShopScreen-BgTi5eCl.cjs +49 -0
- package/dist/ShopScreen-BhYkCXLT.mjs +47 -0
- package/dist/{ShopScreen-BFKwuM2U.mjs → ShopScreen-D0p5rQD8.mjs} +2 -2
- package/dist/{ShopScreen-BFKwuM2U.mjs.map → ShopScreen-D0p5rQD8.mjs.map} +1 -1
- package/dist/{TableWidget-yky-XAA1.cjs → TableWidget-BORWeyOR.cjs} +2 -2
- package/dist/{TableWidget-CiI5pArP.cjs → TableWidget-CT6T3IgY.cjs} +2 -2
- package/dist/{TableWidget-CiI5pArP.cjs.map → TableWidget-CT6T3IgY.cjs.map} +1 -1
- package/dist/{TableWidget-C87Czlh6.mjs → TableWidget-D8HBHejy.mjs} +2 -2
- package/dist/{TableWidget-C87Czlh6.mjs.map → TableWidget-D8HBHejy.mjs.map} +1 -1
- package/dist/{TextWidget-C7oY0X3r.cjs → TextWidget-CMOofhaH.cjs} +2 -2
- package/dist/{TextWidget-C7oY0X3r.cjs.map → TextWidget-CMOofhaH.cjs.map} +1 -1
- package/dist/{TextWidget-CfLUQr6V.mjs → TextWidget-DSGevTKM.mjs} +2 -2
- package/dist/{TextWidget-CfLUQr6V.mjs.map → TextWidget-DSGevTKM.mjs.map} +1 -1
- package/dist/{ToDoWidget-BY-6VIxD.mjs → ToDoWidget-5IiWutYI.mjs} +2 -2
- package/dist/{ToDoWidget-BY-6VIxD.mjs.map → ToDoWidget-5IiWutYI.mjs.map} +1 -1
- package/dist/{ToDoWidget-CpO7jdw0.cjs → ToDoWidget-B97blWRO.cjs} +2 -2
- package/dist/{ToDoWidget-CpO7jdw0.cjs.map → ToDoWidget-B97blWRO.cjs.map} +1 -1
- package/dist/{ToDoWidget-CjY1i0lz.cjs → ToDoWidget-kn1dtlKi.cjs} +2 -2
- package/dist/{VideoWidget-DSPDdiYr.mjs → VideoWidget-BiaPF0-w.mjs} +2 -2
- package/dist/{VideoWidget-DSPDdiYr.mjs.map → VideoWidget-BiaPF0-w.mjs.map} +1 -1
- package/dist/{VideoWidget-BpEF3gRZ.cjs → VideoWidget-zdT_mVo9.cjs} +2 -2
- package/dist/{VideoWidget-BpEF3gRZ.cjs.map → VideoWidget-zdT_mVo9.cjs.map} +1 -1
- package/dist/index.cjs +42 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +42 -42
- package/dist/index.mjs.map +1 -1
- package/dist/{registries-kvRRUHcO.mjs → registries-6F90ZS1m.mjs} +10 -1
- package/dist/registries-6F90ZS1m.mjs.map +1 -0
- package/dist/{registries-DBb6VjAX.cjs → registries-CVsthTnW.cjs} +10 -1
- package/dist/registries-CVsthTnW.cjs.map +1 -0
- package/package.json +18 -18
- package/dist/MessagingScreen-J59IMCoQ.mjs +0 -46
- package/dist/MessagingScreen-Sur4umLF.cjs +0 -48
- package/dist/ProfileScreen-B1J74rK1.cjs +0 -48
- package/dist/ProfileScreen-BdmW4weg.mjs +0 -46
- package/dist/ShopScreen-C_8yLQjA.mjs +0 -47
- package/dist/ShopScreen-Cg_DoIMi.cjs +0 -49
- package/dist/registries-DBb6VjAX.cjs.map +0 -1
- package/dist/registries-kvRRUHcO.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickLinksWidget-roBJQ1Ge.mjs","names":["LinkIcon"],"sources":["../../widgets/src/widgets/QuickLinksWidget.tsx"],"sourcesContent":["import { 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 {\n PropertyField,\n WidgetPropertySchema,\n} 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 Bell,\n BookmarkIcon,\n Calendar,\n ChevronRight,\n ExternalLink,\n Gift,\n Globe,\n Heart,\n Link as LinkIcon,\n Mail,\n MapPin,\n MessageCircle,\n Package,\n Phone,\n Play,\n Share2,\n ShoppingBag,\n Sparkles,\n Star,\n Trophy,\n User,\n Video,\n Zap,\n type LucideIcon,\n} from \"lucide-react\";\n\n// ---------- icon registry ----------\n\nconst ICON_MAP: Record<string, LucideIcon> = {\n User,\n Share2,\n ShoppingBag,\n Video,\n Mail,\n MessageCircle,\n Globe,\n Calendar,\n Bell,\n Heart,\n Star,\n Zap,\n Gift,\n Phone,\n MapPin,\n Play,\n Package,\n ExternalLink,\n Bookmark: BookmarkIcon,\n Trophy,\n Sparkles,\n Link: LinkIcon,\n};\n\nconst ICON_OPTIONS: Array<{ label: string; value: string }> = [\n { label: \"Link (default)\", value: \"Link\" },\n { label: \"User / Profile\", value: \"User\" },\n { label: \"Share\", value: \"Share2\" },\n { label: \"Shopping Bag\", value: \"ShoppingBag\" },\n { label: \"Video\", value: \"Video\" },\n { label: \"Mail\", value: \"Mail\" },\n { label: \"Message\", value: \"MessageCircle\" },\n { label: \"Globe\", value: \"Globe\" },\n { label: \"Calendar\", value: \"Calendar\" },\n { label: \"Bell / Notifications\", value: \"Bell\" },\n { label: \"Heart\", value: \"Heart\" },\n { label: \"Star\", value: \"Star\" },\n { label: \"Zap / Lightning\", value: \"Zap\" },\n { label: \"Gift\", value: \"Gift\" },\n { label: \"Phone\", value: \"Phone\" },\n { label: \"Map Pin\", value: \"MapPin\" },\n { label: \"Play\", value: \"Play\" },\n { label: \"Package\", value: \"Package\" },\n { label: \"External Link\", value: \"ExternalLink\" },\n { label: \"Bookmark\", value: \"Bookmark\" },\n { label: \"Trophy\", value: \"Trophy\" },\n { label: \"Sparkles\", value: \"Sparkles\" },\n];\n\nconst capitalize = (s: string): string =>\n s ? s.charAt(0).toUpperCase() + s.slice(1) : s;\n\nconst getIcon = (name: string | undefined): LucideIcon => {\n if (!name) return LinkIcon;\n return ICON_MAP[name] ?? ICON_MAP[capitalize(name)] ?? LinkIcon;\n};\n\n// ---------- link parsing / collection ----------\n\ntype ParsedLink = {\n id: string;\n label: string;\n url: string;\n iconName: string;\n iconColor: ColorOptions;\n};\n\nconst isColorOption = (value: string): value is ColorOptions =>\n [\n \"background\",\n \"foreground\",\n \"primary\",\n \"secondary\",\n \"accent\",\n \"muted\",\n \"destructive\",\n ].includes(value);\n\nconst FALLBACK_COLOR_CYCLE: ColorOptions[] = [\n \"primary\",\n \"accent\",\n \"secondary\",\n \"destructive\",\n];\n\n// Legacy format per line: \"Label | URL | IconName | ColorOption\"\n// Kept for backwards compatibility with existing saved configs.\nconst parseLegacyLinks = (raw: string[] | string): ParsedLink[] => {\n const lines = Array.isArray(raw) ? raw : raw.split(/\\r?\\n/).filter(Boolean);\n return lines\n .map((line, index) => {\n const parts = line.split(\"|\").map((s) => s.trim());\n const label = parts[0] ?? \"\";\n if (!label) return null;\n const url = parts[1] ?? \"#\";\n const iconName = parts[2] && parts[2].length > 0 ? parts[2] : \"Link\";\n const colorCandidate = parts[3];\n const iconColor: ColorOptions =\n colorCandidate && isColorOption(colorCandidate)\n ? colorCandidate\n : (FALLBACK_COLOR_CYCLE[index % FALLBACK_COLOR_CYCLE.length] ??\n \"primary\");\n return {\n id: `link-${index}`,\n label,\n url,\n iconName,\n iconColor,\n };\n })\n .filter((x): x is ParsedLink => x !== null);\n};\n\n// New structured format — gather links from individual link{n}* props\nconst MAX_LINKS = 8;\n\ntype SlotProps = {\n enabled: boolean;\n label: string | undefined;\n url: string | undefined;\n icon: string | undefined;\n color: ColorOptions | undefined;\n};\n\n// Per-slot merge of structured props with the legacy `links` array. A slot\n// is \"structurally configured\" when at least one of its content props\n// (label / url / icon / color) is explicitly set; in that case structured\n// props win and the slot's `enabled` flag is honored. Slots that haven't\n// been structurally touched fall back to the legacy entry at the same\n// index — so editing one slot in a legacy-format widget doesn't silently\n// drop URLs/icons/colors for the other slots.\nconst resolveLinks = (\n slots: SlotProps[],\n legacy: ParsedLink[],\n): ParsedLink[] => {\n return slots\n .map((slot, index): ParsedLink | null => {\n const legacyEntry = legacy[index];\n\n const hasStructured =\n slot.label !== undefined ||\n slot.url !== undefined ||\n slot.icon !== undefined ||\n slot.color !== undefined;\n\n if (hasStructured) {\n // Slot 1 is always enabled; slots 2+ need enabled=true.\n const isSlotActive = index === 0 || slot.enabled;\n if (!isSlotActive) return null;\n\n const label = (slot.label ?? legacyEntry?.label ?? \"\").trim();\n if (!label) return null;\n\n const url =\n slot.url && slot.url.length > 0\n ? slot.url\n : (legacyEntry?.url ?? \"#\");\n const iconName =\n slot.icon && slot.icon.length > 0\n ? slot.icon\n : (legacyEntry?.iconName ?? \"Link\");\n const iconColor: ColorOptions =\n slot.color ??\n legacyEntry?.iconColor ??\n FALLBACK_COLOR_CYCLE[index % FALLBACK_COLOR_CYCLE.length] ??\n \"primary\";\n\n return {\n id: `link-${index}`,\n label,\n url,\n iconName,\n iconColor,\n };\n }\n\n // No structured props for this slot — use the legacy entry as-is.\n // Legacy widgets predate the per-slot `enabled` toggle, so we don't\n // gate legacy entries on it (otherwise legacy slots 5+ would vanish\n // because their `linkNEnabled` defaults to `false`).\n return legacyEntry ?? null;\n })\n .filter((x): x is ParsedLink => x !== null);\n};\n\n// ---------- link row ----------\n\ntype LinkRowProps = {\n link: ParsedLink;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n openInNewTab: boolean;\n showChevron: boolean;\n iconRadius: BorderRadiusOptions;\n layout: \"cards\" | \"list\";\n isLast: boolean;\n};\n\nfunction LinkRow({\n link,\n textColor,\n borderRadius,\n openInNewTab,\n showChevron,\n iconRadius,\n layout,\n isLast,\n}: LinkRowProps) {\n const Icon = getIcon(link.iconName);\n\n const wrapperBase = `group relative flex items-center gap-3 py-3 transition-all duration-200`;\n const wrapperCardClasses = `rounded-${borderRadius} px-3 bg-${textColor}/5 hover:bg-${textColor}/10 hover:-translate-y-0.5`;\n const wrapperListClasses = `px-0 hover:bg-${textColor}/5 rounded-md`;\n\n const wrapperClasses =\n layout === \"cards\"\n ? `${wrapperBase} ${wrapperCardClasses}`\n : `${wrapperBase} ${wrapperListClasses}`;\n\n const content = (\n <>\n {/* Icon badge — colored gradient square with white icon centered */}\n <span\n aria-hidden=\"true\"\n className={`relative flex size-10 shrink-0 items-center justify-center rounded-${iconRadius} text-${link.iconColor}-foreground`}\n style={{\n background: `linear-gradient(135deg, color-mix(in oklch, var(--color-${link.iconColor}) 75%, white 25%) 0%, var(--color-${link.iconColor}) 100%)`,\n boxShadow: `\n inset 0 1px 0 rgba(255,255,255,0.25),\n inset 0 -1px 0 rgba(0,0,0,0.1),\n 0 1px 2px color-mix(in oklch, var(--color-${link.iconColor}) 30%, transparent)\n `,\n }}\n >\n <Icon className=\"size-5\" strokeWidth={2.25} />\n </span>\n\n {/* Label */}\n <span\n className={`min-w-0 flex-1 truncate text-[15px] font-bold tracking-[-0.01em] text-${textColor}`}\n >\n {link.label}\n </span>\n\n {/* Chevron */}\n {showChevron && (\n <ChevronRight\n aria-hidden=\"true\"\n className={`size-4 shrink-0 text-${textColor}/35 transition-transform duration-200 group-hover:translate-x-0.5 group-hover:text-${textColor}/60`}\n />\n )}\n </>\n );\n\n const separator =\n layout === \"list\" && !isLast ? (\n <div\n aria-hidden=\"true\"\n className=\"ml-[52px]\"\n style={{\n borderBottom: `1px solid color-mix(in oklch, var(--color-${textColor}) 8%, transparent)`,\n }}\n />\n ) : null;\n\n const href = link.url && link.url !== \"#\" ? link.url : undefined;\n\n if (href) {\n return (\n <>\n <a\n href={href}\n target={openInNewTab ? \"_blank\" : undefined}\n rel={openInNewTab ? \"noopener noreferrer\" : undefined}\n className={wrapperClasses}\n >\n {content}\n </a>\n {separator}\n </>\n );\n }\n\n return (\n <>\n <div className={wrapperClasses}>{content}</div>\n {separator}\n </>\n );\n}\n\n// ---------- widget ----------\n\ntype QuickLinksWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Links — new structured per-slot props\n link1Label?: string;\n link1Url?: string;\n link1Icon?: string;\n link1Color?: ColorOptions;\n link2Enabled?: boolean;\n link2Label?: string;\n link2Url?: string;\n link2Icon?: string;\n link2Color?: ColorOptions;\n link3Enabled?: boolean;\n link3Label?: string;\n link3Url?: string;\n link3Icon?: string;\n link3Color?: ColorOptions;\n link4Enabled?: boolean;\n link4Label?: string;\n link4Url?: string;\n link4Icon?: string;\n link4Color?: ColorOptions;\n link5Enabled?: boolean;\n link5Label?: string;\n link5Url?: string;\n link5Icon?: string;\n link5Color?: ColorOptions;\n link6Enabled?: boolean;\n link6Label?: string;\n link6Url?: string;\n link6Icon?: string;\n link6Color?: ColorOptions;\n link7Enabled?: boolean;\n link7Label?: string;\n link7Url?: string;\n link7Icon?: string;\n link7Color?: ColorOptions;\n link8Enabled?: boolean;\n link8Label?: string;\n link8Url?: string;\n link8Icon?: string;\n link8Color?: ColorOptions;\n\n // Legacy — still accepted for backwards compatibility\n links?: string[] | string;\n\n // Layout\n layout?: \"cards\" | \"list\";\n iconRadius?: BorderRadiusOptions;\n showChevron?: boolean;\n openInNewTab?: boolean;\n\n // Design\n background?: BackgroundValue;\n textColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\nexport function QuickLinksWidget({\n titleEnabled = true,\n title = \"Quick Links\",\n titleFontSize = \"md\",\n titleColor = \"foreground\",\n\n link1Label,\n link1Url,\n link1Icon,\n link1Color,\n link2Enabled = true,\n link2Label,\n link2Url,\n link2Icon,\n link2Color,\n link3Enabled = true,\n link3Label,\n link3Url,\n link3Icon,\n link3Color,\n link4Enabled = true,\n link4Label,\n link4Url,\n link4Icon,\n link4Color,\n link5Enabled = false,\n link5Label,\n link5Url,\n link5Icon,\n link5Color,\n link6Enabled = false,\n link6Label,\n link6Url,\n link6Icon,\n link6Color,\n link7Enabled = false,\n link7Label,\n link7Url,\n link7Icon,\n link7Color,\n link8Enabled = false,\n link8Label,\n link8Url,\n link8Icon,\n link8Color,\n\n links,\n\n layout = \"cards\",\n iconRadius = \"lg\",\n showChevron = true,\n openInNewTab = false,\n\n background = { type: \"solid\", color: \"background\" },\n textColor = \"foreground\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n className,\n ...props\n}: QuickLinksWidgetProps): 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\n // Pass props through verbatim — schema `defaultValue`s pre-populate the\n // builder, so the component shouldn't second-guess with hardcoded\n // fallbacks (which would mask a user's explicit blank label).\n const slots: SlotProps[] = [\n {\n enabled: true,\n label: link1Label,\n url: link1Url,\n icon: link1Icon,\n color: link1Color,\n },\n {\n enabled: link2Enabled,\n label: link2Label,\n url: link2Url,\n icon: link2Icon,\n color: link2Color,\n },\n {\n enabled: link3Enabled,\n label: link3Label,\n url: link3Url,\n icon: link3Icon,\n color: link3Color,\n },\n {\n enabled: link4Enabled,\n label: link4Label,\n url: link4Url,\n icon: link4Icon,\n color: link4Color,\n },\n {\n enabled: link5Enabled,\n label: link5Label,\n url: link5Url,\n icon: link5Icon,\n color: link5Color,\n },\n {\n enabled: link6Enabled,\n label: link6Label,\n url: link6Url,\n icon: link6Icon,\n color: link6Color,\n },\n {\n enabled: link7Enabled,\n label: link7Label,\n url: link7Url,\n icon: link7Icon,\n color: link7Color,\n },\n {\n enabled: link8Enabled,\n label: link8Label,\n url: link8Url,\n icon: link8Icon,\n color: link8Color,\n },\n ];\n\n const legacyLinks: ParsedLink[] = links ? parseLegacyLinks(links) : [];\n const parsed: ParsedLink[] = resolveLinks(slots, legacyLinks);\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div className={`p-${padding} flex flex-col gap-3`}>\n {titleEnabled && title && (\n <h2\n className={`text-${titleFontSize} leading-tight font-bold tracking-[-0.01em] text-${titleColor}`}\n >\n {title}\n </h2>\n )}\n\n {parsed.length === 0 ? (\n <p className={`text-[13px] text-${textColor}/55`}>\n No links configured.\n </p>\n ) : layout === \"cards\" ? (\n <div className=\"flex flex-col gap-2\">\n {parsed.map((link, idx) => (\n <LinkRow\n key={link.id}\n link={link}\n textColor={textColor}\n borderRadius={borderRadius}\n openInNewTab={openInNewTab}\n showChevron={showChevron}\n iconRadius={iconRadius}\n layout=\"cards\"\n isLast={idx === parsed.length - 1}\n />\n ))}\n </div>\n ) : (\n <div\n className={`flex flex-col overflow-hidden rounded-${borderRadius} bg-${textColor}/5`}\n >\n {parsed.map((link, idx) => (\n <LinkRow\n key={link.id}\n link={link}\n textColor={textColor}\n borderRadius={borderRadius}\n openInNewTab={openInNewTab}\n showChevron={showChevron}\n iconRadius={iconRadius}\n layout=\"list\"\n isLast={idx === parsed.length - 1}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n\n// ---------- schema helpers ----------\n\ntype SlotDefaults = {\n label: string;\n icon: string;\n color: ColorOptions;\n};\n\nconst SLOT_DEFAULTS: Record<number, SlotDefaults | undefined> = {\n 1: { label: \"Profile\", icon: \"User\", color: \"primary\" },\n 2: { label: \"Social\", icon: \"Share2\", color: \"accent\" },\n 3: { label: \"Product Links\", icon: \"ShoppingBag\", color: \"secondary\" },\n 4: { label: \"Video\", icon: \"Video\", color: \"destructive\" },\n};\n\nfunction buildLinkSlotFields(slot: number): PropertyField[] {\n const group = `Link ${slot}`;\n const isFirst = slot === 1;\n const defaults = SLOT_DEFAULTS[slot];\n // Enable slots 2-4 by default to match the previous widget behavior.\n const enabledDefault = slot >= 2 && slot <= 4;\n const requires = isFirst ? undefined : `link${slot}Enabled`;\n\n const fields: PropertyField[] = [];\n\n if (!isFirst) {\n fields.push({\n key: `link${slot}Enabled`,\n label: `Show Link ${slot}`,\n type: \"boolean\",\n description: `Display link slot ${slot}`,\n defaultValue: enabledDefault,\n group,\n });\n }\n\n fields.push({\n key: `link${slot}Label`,\n label: \"Label\",\n type: \"text\",\n description: \"Text shown on the link\",\n defaultValue: defaults?.label ?? \"\",\n group,\n ...(requires ? { requiresKeyToBeTrue: requires } : {}),\n });\n\n fields.push({\n key: `link${slot}Url`,\n label: \"URL\",\n type: \"text\",\n description: \"Where the link points (use '#' for a placeholder)\",\n defaultValue: \"#\",\n group,\n ...(requires ? { requiresKeyToBeTrue: requires } : {}),\n });\n\n fields.push({\n key: `link${slot}Icon`,\n label: \"Icon\",\n type: \"select\",\n description: \"Icon displayed in the colored badge\",\n options: ICON_OPTIONS,\n defaultValue: defaults?.icon ?? \"Link\",\n group,\n ...(requires ? { requiresKeyToBeTrue: requires } : {}),\n });\n\n fields.push({\n key: `link${slot}Color`,\n label: \"Badge Color\",\n type: \"colorSelect\",\n description: \"Color of the icon badge\",\n defaultValue:\n defaults?.color ??\n FALLBACK_COLOR_CYCLE[(slot - 1) % FALLBACK_COLOR_CYCLE.length] ??\n \"primary\",\n group,\n ...(requires ? { requiresKeyToBeTrue: requires } : {}),\n });\n\n return fields;\n}\n\nconst linkSlotFields: PropertyField[] = Array.from(\n { length: MAX_LINKS },\n (_, i) => buildLinkSlotFields(i + 1),\n).flat();\n\n// ---------- schema ----------\n\nexport const quickLinksWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickLinksWidget\",\n displayName: \"Quick Links\",\n fields: [\n // Title group\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Small heading shown above the link list\",\n defaultValue: true,\n group: \"Title\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Heading shown above the links\",\n defaultValue: \"Quick Links\",\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: \"md\",\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 group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Links — 8 structured slots\n ...linkSlotFields,\n\n // Layout group\n {\n key: \"layout\",\n label: \"Layout\",\n type: \"buttonGroup\",\n description: \"Cards: separated tiles. List: grouped rows with dividers.\",\n defaultValue: \"cards\",\n options: [\n { label: \"Cards\", value: \"cards\" },\n { label: \"List\", value: \"list\" },\n ],\n group: \"Layout\",\n },\n getBorderRadiusField({\n key: \"iconRadius\",\n label: \"Icon Corner Radius\",\n description: \"Corner radius for the colored icon badge\",\n defaultValue: \"lg\",\n group: \"Layout\",\n }),\n {\n key: \"showChevron\",\n label: \"Show Chevron\",\n type: \"boolean\",\n description: \"Right-aligned chevron indicating each row is a link\",\n defaultValue: true,\n group: \"Layout\",\n },\n {\n key: \"openInNewTab\",\n label: \"Open in New Tab\",\n type: \"boolean\",\n description: \"Open links in a new tab instead of the same window\",\n defaultValue: false,\n group: \"Layout\",\n },\n\n // Design group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the widget container\",\n defaultValue: \"background\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description:\n \"Label + chevron color, and the base for row backgrounds (via opacity)\",\n defaultValue: \"foreground\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget\",\n defaultValue: 4,\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description:\n \"Widget border radius (also drives row corners in cards layout)\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Widget border width\",\n defaultValue: \"none\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Widget border color\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"QuickLinksWidget-J5axodVF.mjs","names":["LinkIcon"],"sources":["../../widgets/src/widgets/QuickLinksWidget.tsx"],"sourcesContent":["import { 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 {\n PropertyField,\n WidgetPropertySchema,\n} 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 Bell,\n BookmarkIcon,\n Calendar,\n ChevronRight,\n ExternalLink,\n Gift,\n Globe,\n Heart,\n Link as LinkIcon,\n Mail,\n MapPin,\n MessageCircle,\n Package,\n Phone,\n Play,\n Share2,\n ShoppingBag,\n Sparkles,\n Star,\n Trophy,\n User,\n Video,\n Zap,\n type LucideIcon,\n} from \"lucide-react\";\n\n// ---------- icon registry ----------\n\nconst ICON_MAP: Record<string, LucideIcon> = {\n User,\n Share2,\n ShoppingBag,\n Video,\n Mail,\n MessageCircle,\n Globe,\n Calendar,\n Bell,\n Heart,\n Star,\n Zap,\n Gift,\n Phone,\n MapPin,\n Play,\n Package,\n ExternalLink,\n Bookmark: BookmarkIcon,\n Trophy,\n Sparkles,\n Link: LinkIcon,\n};\n\nconst ICON_OPTIONS: Array<{ label: string; value: string }> = [\n { label: \"Link (default)\", value: \"Link\" },\n { label: \"User / Profile\", value: \"User\" },\n { label: \"Share\", value: \"Share2\" },\n { label: \"Shopping Bag\", value: \"ShoppingBag\" },\n { label: \"Video\", value: \"Video\" },\n { label: \"Mail\", value: \"Mail\" },\n { label: \"Message\", value: \"MessageCircle\" },\n { label: \"Globe\", value: \"Globe\" },\n { label: \"Calendar\", value: \"Calendar\" },\n { label: \"Bell / Notifications\", value: \"Bell\" },\n { label: \"Heart\", value: \"Heart\" },\n { label: \"Star\", value: \"Star\" },\n { label: \"Zap / Lightning\", value: \"Zap\" },\n { label: \"Gift\", value: \"Gift\" },\n { label: \"Phone\", value: \"Phone\" },\n { label: \"Map Pin\", value: \"MapPin\" },\n { label: \"Play\", value: \"Play\" },\n { label: \"Package\", value: \"Package\" },\n { label: \"External Link\", value: \"ExternalLink\" },\n { label: \"Bookmark\", value: \"Bookmark\" },\n { label: \"Trophy\", value: \"Trophy\" },\n { label: \"Sparkles\", value: \"Sparkles\" },\n];\n\nconst capitalize = (s: string): string =>\n s ? s.charAt(0).toUpperCase() + s.slice(1) : s;\n\nconst getIcon = (name: string | undefined): LucideIcon => {\n if (!name) return LinkIcon;\n return ICON_MAP[name] ?? ICON_MAP[capitalize(name)] ?? LinkIcon;\n};\n\n// ---------- link parsing / collection ----------\n\ntype ParsedLink = {\n id: string;\n label: string;\n url: string;\n iconName: string;\n iconColor: ColorOptions;\n};\n\nconst isColorOption = (value: string): value is ColorOptions =>\n [\n \"background\",\n \"foreground\",\n \"primary\",\n \"secondary\",\n \"accent\",\n \"muted\",\n \"destructive\",\n ].includes(value);\n\nconst FALLBACK_COLOR_CYCLE: ColorOptions[] = [\n \"primary\",\n \"accent\",\n \"secondary\",\n \"destructive\",\n];\n\n// Legacy format per line: \"Label | URL | IconName | ColorOption\"\n// Kept for backwards compatibility with existing saved configs.\nconst parseLegacyLinks = (raw: string[] | string): ParsedLink[] => {\n const lines = Array.isArray(raw) ? raw : raw.split(/\\r?\\n/).filter(Boolean);\n return lines\n .map((line, index) => {\n const parts = line.split(\"|\").map((s) => s.trim());\n const label = parts[0] ?? \"\";\n if (!label) return null;\n const url = parts[1] ?? \"#\";\n const iconName = parts[2] && parts[2].length > 0 ? parts[2] : \"Link\";\n const colorCandidate = parts[3];\n const iconColor: ColorOptions =\n colorCandidate && isColorOption(colorCandidate)\n ? colorCandidate\n : (FALLBACK_COLOR_CYCLE[index % FALLBACK_COLOR_CYCLE.length] ??\n \"primary\");\n return {\n id: `link-${index}`,\n label,\n url,\n iconName,\n iconColor,\n };\n })\n .filter((x): x is ParsedLink => x !== null);\n};\n\n// New structured format — gather links from individual link{n}* props\nconst MAX_LINKS = 8;\n\ntype SlotProps = {\n enabled: boolean;\n label: string | undefined;\n url: string | undefined;\n icon: string | undefined;\n color: ColorOptions | undefined;\n};\n\n// Per-slot merge of structured props with the legacy `links` array. A slot\n// is \"structurally configured\" when at least one of its content props\n// (label / url / icon / color) is explicitly set; in that case structured\n// props win and the slot's `enabled` flag is honored. Slots that haven't\n// been structurally touched fall back to the legacy entry at the same\n// index — so editing one slot in a legacy-format widget doesn't silently\n// drop URLs/icons/colors for the other slots.\nconst resolveLinks = (\n slots: SlotProps[],\n legacy: ParsedLink[],\n): ParsedLink[] => {\n return slots\n .map((slot, index): ParsedLink | null => {\n const legacyEntry = legacy[index];\n\n const hasStructured =\n slot.label !== undefined ||\n slot.url !== undefined ||\n slot.icon !== undefined ||\n slot.color !== undefined;\n\n if (hasStructured) {\n // Slot 1 is always enabled; slots 2+ need enabled=true.\n const isSlotActive = index === 0 || slot.enabled;\n if (!isSlotActive) return null;\n\n const label = (slot.label ?? legacyEntry?.label ?? \"\").trim();\n if (!label) return null;\n\n const url =\n slot.url && slot.url.length > 0\n ? slot.url\n : (legacyEntry?.url ?? \"#\");\n const iconName =\n slot.icon && slot.icon.length > 0\n ? slot.icon\n : (legacyEntry?.iconName ?? \"Link\");\n const iconColor: ColorOptions =\n slot.color ??\n legacyEntry?.iconColor ??\n FALLBACK_COLOR_CYCLE[index % FALLBACK_COLOR_CYCLE.length] ??\n \"primary\";\n\n return {\n id: `link-${index}`,\n label,\n url,\n iconName,\n iconColor,\n };\n }\n\n // No structured props for this slot — use the legacy entry as-is.\n // Legacy widgets predate the per-slot `enabled` toggle, so we don't\n // gate legacy entries on it (otherwise legacy slots 5+ would vanish\n // because their `linkNEnabled` defaults to `false`).\n return legacyEntry ?? null;\n })\n .filter((x): x is ParsedLink => x !== null);\n};\n\n// ---------- link row ----------\n\ntype LinkRowProps = {\n link: ParsedLink;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n openInNewTab: boolean;\n showChevron: boolean;\n iconRadius: BorderRadiusOptions;\n layout: \"cards\" | \"list\";\n isLast: boolean;\n};\n\nfunction LinkRow({\n link,\n textColor,\n borderRadius,\n openInNewTab,\n showChevron,\n iconRadius,\n layout,\n isLast,\n}: LinkRowProps) {\n const Icon = getIcon(link.iconName);\n\n const wrapperBase = `group relative flex items-center gap-3 py-3 transition-all duration-200`;\n const wrapperCardClasses = `rounded-${borderRadius} px-3 bg-${textColor}/5 hover:bg-${textColor}/10 hover:-translate-y-0.5`;\n const wrapperListClasses = `px-0 hover:bg-${textColor}/5 rounded-md`;\n\n const wrapperClasses =\n layout === \"cards\"\n ? `${wrapperBase} ${wrapperCardClasses}`\n : `${wrapperBase} ${wrapperListClasses}`;\n\n const content = (\n <>\n {/* Icon badge — colored gradient square with white icon centered */}\n <span\n aria-hidden=\"true\"\n className={`relative flex size-10 shrink-0 items-center justify-center rounded-${iconRadius} text-${link.iconColor}-foreground`}\n style={{\n background: `linear-gradient(135deg, color-mix(in oklch, var(--color-${link.iconColor}) 75%, white 25%) 0%, var(--color-${link.iconColor}) 100%)`,\n boxShadow: `\n inset 0 1px 0 rgba(255,255,255,0.25),\n inset 0 -1px 0 rgba(0,0,0,0.1),\n 0 1px 2px color-mix(in oklch, var(--color-${link.iconColor}) 30%, transparent)\n `,\n }}\n >\n <Icon className=\"size-5\" strokeWidth={2.25} />\n </span>\n\n {/* Label */}\n <span\n className={`min-w-0 flex-1 truncate text-[15px] font-bold tracking-[-0.01em] text-${textColor}`}\n >\n {link.label}\n </span>\n\n {/* Chevron */}\n {showChevron && (\n <ChevronRight\n aria-hidden=\"true\"\n className={`size-4 shrink-0 text-${textColor}/35 transition-transform duration-200 group-hover:translate-x-0.5 group-hover:text-${textColor}/60`}\n />\n )}\n </>\n );\n\n const separator =\n layout === \"list\" && !isLast ? (\n <div\n aria-hidden=\"true\"\n className=\"ml-[52px]\"\n style={{\n borderBottom: `1px solid color-mix(in oklch, var(--color-${textColor}) 8%, transparent)`,\n }}\n />\n ) : null;\n\n const href = link.url && link.url !== \"#\" ? link.url : undefined;\n\n if (href) {\n return (\n <>\n <a\n href={href}\n target={openInNewTab ? \"_blank\" : undefined}\n rel={openInNewTab ? \"noopener noreferrer\" : undefined}\n className={wrapperClasses}\n >\n {content}\n </a>\n {separator}\n </>\n );\n }\n\n return (\n <>\n <div className={wrapperClasses}>{content}</div>\n {separator}\n </>\n );\n}\n\n// ---------- widget ----------\n\ntype QuickLinksWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Links — new structured per-slot props\n link1Label?: string;\n link1Url?: string;\n link1Icon?: string;\n link1Color?: ColorOptions;\n link2Enabled?: boolean;\n link2Label?: string;\n link2Url?: string;\n link2Icon?: string;\n link2Color?: ColorOptions;\n link3Enabled?: boolean;\n link3Label?: string;\n link3Url?: string;\n link3Icon?: string;\n link3Color?: ColorOptions;\n link4Enabled?: boolean;\n link4Label?: string;\n link4Url?: string;\n link4Icon?: string;\n link4Color?: ColorOptions;\n link5Enabled?: boolean;\n link5Label?: string;\n link5Url?: string;\n link5Icon?: string;\n link5Color?: ColorOptions;\n link6Enabled?: boolean;\n link6Label?: string;\n link6Url?: string;\n link6Icon?: string;\n link6Color?: ColorOptions;\n link7Enabled?: boolean;\n link7Label?: string;\n link7Url?: string;\n link7Icon?: string;\n link7Color?: ColorOptions;\n link8Enabled?: boolean;\n link8Label?: string;\n link8Url?: string;\n link8Icon?: string;\n link8Color?: ColorOptions;\n\n // Legacy — still accepted for backwards compatibility\n links?: string[] | string;\n\n // Layout\n layout?: \"cards\" | \"list\";\n iconRadius?: BorderRadiusOptions;\n showChevron?: boolean;\n openInNewTab?: boolean;\n\n // Design\n background?: BackgroundValue;\n textColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\nexport function QuickLinksWidget({\n titleEnabled = true,\n title = \"Quick Links\",\n titleFontSize = \"md\",\n titleColor = \"foreground\",\n\n link1Label,\n link1Url,\n link1Icon,\n link1Color,\n link2Enabled = true,\n link2Label,\n link2Url,\n link2Icon,\n link2Color,\n link3Enabled = true,\n link3Label,\n link3Url,\n link3Icon,\n link3Color,\n link4Enabled = true,\n link4Label,\n link4Url,\n link4Icon,\n link4Color,\n link5Enabled = false,\n link5Label,\n link5Url,\n link5Icon,\n link5Color,\n link6Enabled = false,\n link6Label,\n link6Url,\n link6Icon,\n link6Color,\n link7Enabled = false,\n link7Label,\n link7Url,\n link7Icon,\n link7Color,\n link8Enabled = false,\n link8Label,\n link8Url,\n link8Icon,\n link8Color,\n\n links,\n\n layout = \"cards\",\n iconRadius = \"lg\",\n showChevron = true,\n openInNewTab = false,\n\n background = { type: \"solid\", color: \"background\" },\n textColor = \"foreground\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n className,\n ...props\n}: QuickLinksWidgetProps): 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\n // Pass props through verbatim — schema `defaultValue`s pre-populate the\n // builder, so the component shouldn't second-guess with hardcoded\n // fallbacks (which would mask a user's explicit blank label).\n const slots: SlotProps[] = [\n {\n enabled: true,\n label: link1Label,\n url: link1Url,\n icon: link1Icon,\n color: link1Color,\n },\n {\n enabled: link2Enabled,\n label: link2Label,\n url: link2Url,\n icon: link2Icon,\n color: link2Color,\n },\n {\n enabled: link3Enabled,\n label: link3Label,\n url: link3Url,\n icon: link3Icon,\n color: link3Color,\n },\n {\n enabled: link4Enabled,\n label: link4Label,\n url: link4Url,\n icon: link4Icon,\n color: link4Color,\n },\n {\n enabled: link5Enabled,\n label: link5Label,\n url: link5Url,\n icon: link5Icon,\n color: link5Color,\n },\n {\n enabled: link6Enabled,\n label: link6Label,\n url: link6Url,\n icon: link6Icon,\n color: link6Color,\n },\n {\n enabled: link7Enabled,\n label: link7Label,\n url: link7Url,\n icon: link7Icon,\n color: link7Color,\n },\n {\n enabled: link8Enabled,\n label: link8Label,\n url: link8Url,\n icon: link8Icon,\n color: link8Color,\n },\n ];\n\n const legacyLinks: ParsedLink[] = links ? parseLegacyLinks(links) : [];\n const parsed: ParsedLink[] = resolveLinks(slots, legacyLinks);\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div className={`p-${padding} flex flex-col gap-3`}>\n {titleEnabled && title && (\n <h2\n className={`text-${titleFontSize} leading-tight font-bold tracking-[-0.01em] text-${titleColor}`}\n >\n {title}\n </h2>\n )}\n\n {parsed.length === 0 ? (\n <p className={`text-[13px] text-${textColor}/55`}>\n No links configured.\n </p>\n ) : layout === \"cards\" ? (\n <div className=\"flex flex-col gap-2\">\n {parsed.map((link, idx) => (\n <LinkRow\n key={link.id}\n link={link}\n textColor={textColor}\n borderRadius={borderRadius}\n openInNewTab={openInNewTab}\n showChevron={showChevron}\n iconRadius={iconRadius}\n layout=\"cards\"\n isLast={idx === parsed.length - 1}\n />\n ))}\n </div>\n ) : (\n <div\n className={`flex flex-col overflow-hidden rounded-${borderRadius} bg-${textColor}/5`}\n >\n {parsed.map((link, idx) => (\n <LinkRow\n key={link.id}\n link={link}\n textColor={textColor}\n borderRadius={borderRadius}\n openInNewTab={openInNewTab}\n showChevron={showChevron}\n iconRadius={iconRadius}\n layout=\"list\"\n isLast={idx === parsed.length - 1}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n\n// ---------- schema helpers ----------\n\ntype SlotDefaults = {\n label: string;\n icon: string;\n color: ColorOptions;\n};\n\nconst SLOT_DEFAULTS: Record<number, SlotDefaults | undefined> = {\n 1: { label: \"Profile\", icon: \"User\", color: \"primary\" },\n 2: { label: \"Social\", icon: \"Share2\", color: \"accent\" },\n 3: { label: \"Product Links\", icon: \"ShoppingBag\", color: \"secondary\" },\n 4: { label: \"Video\", icon: \"Video\", color: \"destructive\" },\n};\n\nfunction buildLinkSlotFields(slot: number): PropertyField[] {\n const group = `Link ${slot}`;\n const isFirst = slot === 1;\n const defaults = SLOT_DEFAULTS[slot];\n // Enable slots 2-4 by default to match the previous widget behavior.\n const enabledDefault = slot >= 2 && slot <= 4;\n const requires = isFirst ? undefined : `link${slot}Enabled`;\n\n const fields: PropertyField[] = [];\n\n if (!isFirst) {\n fields.push({\n key: `link${slot}Enabled`,\n label: `Show Link ${slot}`,\n type: \"boolean\",\n description: `Display link slot ${slot}`,\n defaultValue: enabledDefault,\n group,\n });\n }\n\n fields.push({\n key: `link${slot}Label`,\n label: \"Label\",\n type: \"text\",\n description: \"Text shown on the link\",\n defaultValue: defaults?.label ?? \"\",\n group,\n ...(requires ? { requiresKeyToBeTrue: requires } : {}),\n });\n\n fields.push({\n key: `link${slot}Url`,\n label: \"URL\",\n type: \"text\",\n description: \"Where the link points (use '#' for a placeholder)\",\n defaultValue: \"#\",\n group,\n ...(requires ? { requiresKeyToBeTrue: requires } : {}),\n });\n\n fields.push({\n key: `link${slot}Icon`,\n label: \"Icon\",\n type: \"select\",\n description: \"Icon displayed in the colored badge\",\n options: ICON_OPTIONS,\n defaultValue: defaults?.icon ?? \"Link\",\n group,\n ...(requires ? { requiresKeyToBeTrue: requires } : {}),\n });\n\n fields.push({\n key: `link${slot}Color`,\n label: \"Badge Color\",\n type: \"colorSelect\",\n description: \"Color of the icon badge\",\n defaultValue:\n defaults?.color ??\n FALLBACK_COLOR_CYCLE[(slot - 1) % FALLBACK_COLOR_CYCLE.length] ??\n \"primary\",\n group,\n ...(requires ? { requiresKeyToBeTrue: requires } : {}),\n });\n\n return fields;\n}\n\nconst linkSlotFields: PropertyField[] = Array.from(\n { length: MAX_LINKS },\n (_, i) => buildLinkSlotFields(i + 1),\n).flat();\n\n// ---------- schema ----------\n\nexport const quickLinksWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickLinksWidget\",\n displayName: \"Quick Links\",\n fields: [\n // Title group\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Small heading shown above the link list\",\n defaultValue: true,\n group: \"Title\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Heading shown above the links\",\n defaultValue: \"Quick Links\",\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: \"md\",\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 group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Links — 8 structured slots\n ...linkSlotFields,\n\n // Layout group\n {\n key: \"layout\",\n label: \"Layout\",\n type: \"buttonGroup\",\n description: \"Cards: separated tiles. List: grouped rows with dividers.\",\n defaultValue: \"cards\",\n options: [\n { label: \"Cards\", value: \"cards\" },\n { label: \"List\", value: \"list\" },\n ],\n group: \"Layout\",\n },\n getBorderRadiusField({\n key: \"iconRadius\",\n label: \"Icon Corner Radius\",\n description: \"Corner radius for the colored icon badge\",\n defaultValue: \"lg\",\n group: \"Layout\",\n }),\n {\n key: \"showChevron\",\n label: \"Show Chevron\",\n type: \"boolean\",\n description: \"Right-aligned chevron indicating each row is a link\",\n defaultValue: true,\n group: \"Layout\",\n },\n {\n key: \"openInNewTab\",\n label: \"Open in New Tab\",\n type: \"boolean\",\n description: \"Open links in a new tab instead of the same window\",\n defaultValue: false,\n group: \"Layout\",\n },\n\n // Design group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the widget container\",\n defaultValue: \"background\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description:\n \"Label + chevron color, and the base for row backgrounds (via opacity)\",\n defaultValue: \"foreground\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget\",\n defaultValue: 4,\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description:\n \"Widget border radius (also drives row corners in cards layout)\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Widget border width\",\n defaultValue: \"none\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Widget border color\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
const require_registries = require("./registries-
|
|
2
|
+
const require_registries = require("./registries-CVsthTnW.cjs");
|
|
3
3
|
let react = require("react");
|
|
4
4
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
5
|
let lucide_react = require("lucide-react");
|
|
@@ -605,4 +605,4 @@ Object.defineProperty(exports, "quickShareWidgetPropertySchema", {
|
|
|
605
605
|
}
|
|
606
606
|
});
|
|
607
607
|
|
|
608
|
-
//# sourceMappingURL=QuickShareWidget-
|
|
608
|
+
//# sourceMappingURL=QuickShareWidget-CYPOXs8X.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickShareWidget-D_Ghjgwz.cjs","names":["Package","FileText","Ticket","ImageIcon","BookOpen","CircleDot","borderWidthClasses","borderColorClasses","QRCodeSVG","Check","Copy","ShoppingCart","Mail","MessageCircle","Share2","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/widgets/QuickShareWidget.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useState,\n type ComponentProps,\n type CSSProperties,\n} from \"react\";\nimport type React from \"react\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n borderColorClasses,\n borderWidthClasses,\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport {\n BookOpen,\n Check,\n CircleDot,\n Copy,\n FileText,\n Image as ImageIcon,\n Mail,\n MessageCircle,\n Package,\n Share2,\n ShoppingCart,\n Ticket,\n type LucideIcon,\n} from \"lucide-react\";\n\ntype QuickShareWidgetProps = ComponentProps<\"div\"> & {\n // Resource\n shareableResource?: ShareableItem;\n\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Actions\n showBuyButton?: boolean;\n\n // Polish (new, additive)\n showResourceType?: boolean;\n showShareActions?: boolean;\n showDomainPrefix?: boolean;\n};\n\ntype ResourceDescriptor = {\n label: string;\n icon: LucideIcon;\n};\n\ntype QuickShareCSSProperties = CSSProperties &\n Record<`--${string}`, string | number | undefined>;\n\nconst RESOURCE_TYPE_MAP: Record<string, ResourceDescriptor> = {\n Product: { label: \"Product\", icon: Package },\n Page: { label: \"Page\", icon: FileText },\n EnrollmentPack: { label: \"Enrollment\", icon: Ticket },\n Medium: { label: \"Media\", icon: ImageIcon },\n Library: { label: \"Library\", icon: BookOpen },\n};\n\nconst getResourceDescriptor = (\n resource: ShareableItem | undefined,\n): ResourceDescriptor | null => {\n const rawType = (resource?.type || resource?.shareableType || \"\") as string;\n if (!rawType) return null;\n return RESOURCE_TYPE_MAP[rawType] ?? { label: rawType, icon: CircleDot };\n};\n\nconst splitUrl = (url: string): { prefix: string; path: string } => {\n try {\n const parsed = new URL(url);\n return {\n prefix: `${parsed.protocol}//${parsed.host}`,\n path: `${parsed.pathname}${parsed.search}${parsed.hash}`,\n };\n } catch {\n return { prefix: \"\", path: url };\n }\n};\n\nconst CURRENCY_FIELD_KEYS = [\n \"currency\",\n \"currency_code\",\n \"currencyCode\",\n \"currencyIso\",\n \"currency_iso\",\n] as const;\n\nconst getResourceCurrency = (\n resource: ShareableItem | undefined,\n): string | null => {\n if (!resource) return null;\n for (const key of CURRENCY_FIELD_KEYS) {\n const value = resource[key];\n if (typeof value === \"string\" && /^[A-Z]{3}$/i.test(value)) {\n return value.toUpperCase();\n }\n }\n return null;\n};\n\nconst formatNumericPrice = (price: number, resource: ShareableItem): string => {\n const currency = getResourceCurrency(resource);\n if (!currency) return String(price);\n try {\n return price.toLocaleString(undefined, { style: \"currency\", currency });\n } catch {\n return String(price);\n }\n};\n\nconst getDisplayPrice = (\n resource: ShareableItem | undefined,\n): string | null => {\n if (!resource) return null;\n if (typeof resource.display_price === \"string\" && resource.display_price) {\n return resource.display_price;\n }\n if (resource.price != null) {\n return typeof resource.price === \"number\"\n ? formatNumericPrice(resource.price, resource)\n : String(resource.price);\n }\n return null;\n};\n\nconst getColorCssValue = (color: ColorOptions): string =>\n color === \"transparent\" ? \"transparent\" : `var(--color-${color})`;\n\nconst colorMix = (color: ColorOptions, amount: number): string =>\n color === \"transparent\"\n ? \"transparent\"\n : `color-mix(in oklch, ${getColorCssValue(color)} ${amount}%, transparent)`;\n\nconst insetBorder = (color: ColorOptions, amount: number): string =>\n `inset 0 0 0 1px ${colorMix(color, amount)}`;\n\ntype CopyState = \"idle\" | \"copied\";\n\nfunction useTimedCopyState(timeoutMs: number) {\n const [copyState, setCopyState] = useState<CopyState>(\"idle\");\n\n useEffect(() => {\n if (copyState !== \"copied\") return;\n const id = window.setTimeout(() => setCopyState(\"idle\"), timeoutMs);\n return () => window.clearTimeout(id);\n }, [copyState, timeoutMs]);\n\n const markCopied = useCallback(() => {\n setCopyState(\"copied\");\n }, []);\n\n return { copyState, markCopied };\n}\n\nfunction useImageFailureFallback(imageUrl: string) {\n const [imageFailed, setImageFailed] = useState(false);\n\n // Reset the failed-image state when the resource (and thus the image URL)\n // changes — otherwise switching to a new resource keeps showing EmptyHero\n // because the React state outlives the previous load failure.\n useEffect(() => {\n setImageFailed(false);\n }, [imageUrl]);\n\n const handleImageError = useCallback(() => {\n setImageFailed(true);\n }, []);\n\n return { imageFailed, handleImageError };\n}\n\nfunction useShareCapabilities() {\n const [canNativeShare, setCanNativeShare] = useState(false);\n const [canSendSms, setCanSendSms] = useState(false);\n\n useEffect(() => {\n setCanNativeShare(\n typeof navigator !== \"undefined\" && typeof navigator.share === \"function\",\n );\n setCanSendSms(\n typeof navigator !== \"undefined\" &&\n (/Android|iPhone|iPad|iPod/i.test(navigator.userAgent) ||\n (/Macintosh/i.test(navigator.userAgent) &&\n navigator.maxTouchPoints > 1)),\n );\n }, []);\n\n return { canNativeShare, canSendSms };\n}\n\nexport function QuickShareWidget({\n shareableResource,\n\n titleEnabled = true,\n titleText = \"\",\n titleFontSize = \"2xl\",\n titleColor = \"background\",\n\n textColor = \"background\",\n accentColor = \"primary\",\n padding = 6,\n borderRadius = \"xl\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 70,\n\n showBuyButton = false,\n\n showResourceType = true,\n showShareActions = true,\n showDomainPrefix = true,\n\n className,\n style,\n ...props\n}: QuickShareWidgetProps): React.JSX.Element {\n const backgroundImageUrl =\n shareableResource?.image_url || shareableResource?.imageUrl || \"\";\n const { copyState, markCopied } = useTimedCopyState(1600);\n // Hero image fallback: if the resource image 404s or fails to decode, flip\n // to the EmptyHero treatment instead of rendering a broken image.\n const { imageFailed, handleImageError } =\n useImageFailureFallback(backgroundImageUrl);\n\n const showHeroImage = Boolean(backgroundImageUrl) && !imageFailed;\n const shareLink = shareableResource?.share_link || \"\";\n const hasShareLink = !!shareLink;\n\n const displayTitle =\n titleText || shareableResource?.title || \"Select content to share\";\n const resourceDescriptor = getResourceDescriptor(shareableResource);\n const displayPrice = getDisplayPrice(shareableResource);\n\n const isProduct =\n shareableResource?.type === \"Product\" ||\n shareableResource?.shareableType === \"Product\";\n const shouldShowBuyButton = showBuyButton && isProduct;\n\n const parsedOverlayIntensity = Number(\n String(overlayIntensity).replace(\"%\", \"\"),\n );\n const overlayOpacity =\n (Number.isFinite(parsedOverlayIntensity)\n ? Math.min(100, Math.max(0, parsedOverlayIntensity))\n : 70) / 100;\n\n const editorialGradient: CSSProperties | undefined =\n overlayEnabled && showHeroImage\n ? {\n background: `linear-gradient(to top, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 100)}%, transparent), color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 55)}%, transparent) 45%, transparent 85%)`,\n }\n : undefined;\n\n const handleCopy = async () => {\n if (!hasShareLink) return;\n try {\n await navigator.clipboard.writeText(shareLink);\n markCopied();\n } catch (error) {\n console.error(\"Failed to copy to clipboard:\", error);\n }\n };\n\n const handleNativeShare = async () => {\n if (!hasShareLink) return;\n if (typeof navigator.share === \"function\") {\n try {\n await navigator.share({\n title: displayTitle,\n url: shareLink,\n });\n } catch {\n // Ignore abort\n }\n } else {\n await handleCopy();\n }\n };\n\n const { prefix, path } = hasShareLink\n ? splitUrl(shareLink)\n : { prefix: \"\", path: \"\" };\n\n return (\n <div\n className={`relative isolate overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-muted text-${textColor} ${className ?? \"\"}`}\n style={{\n // Themed dual-shadow (crisp + soft ambient), derived from the\n // foreground token so the lift reads in both light and dark.\n boxShadow: `0 1px 2px color-mix(in oklch, var(--color-foreground) 4%, transparent), 0 20px 40px -20px color-mix(in oklch, var(--color-foreground) 25%, transparent)`,\n ...style,\n }}\n {...props}\n >\n {/* Hero image or empty-state surface */}\n {showHeroImage ? (\n <div className=\"absolute inset-0\">\n <img\n src={backgroundImageUrl}\n alt=\"\"\n loading=\"lazy\"\n onError={handleImageError}\n className=\"h-full w-full object-cover\"\n />\n {overlayEnabled && (\n <>\n {/* Layer 1 — main bottom-to-top legibility gradient */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={editorialGradient}\n />\n {/* Layer 2 — diagonal bottom-left anchor (image reads top-right, content reads bottom-left) */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={{\n background: `linear-gradient(to top right, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 65)}%, transparent), color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 25)}%, transparent) 35%, transparent 65%)`,\n }}\n />\n {/* Layer 3 — radial pool anchoring the bottom-left share panel */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={{\n background: `radial-gradient(ellipse 70% 55% at 15% 100%, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 45)}%, transparent), transparent 70%)`,\n }}\n />\n {overlayType === \"solid\" && (\n <div\n className=\"bg-foreground pointer-events-none absolute inset-0\"\n style={{ opacity: overlayOpacity * 0.35 }}\n />\n )}\n </>\n )}\n </div>\n ) : (\n <EmptyHero accentColor={accentColor} textColor={textColor} />\n )}\n\n {/* Content */}\n <div className={`relative flex min-h-[440px] flex-col p-${padding}`}>\n {/* Top row: resource type eyebrow + optional price chip */}\n {(showResourceType && resourceDescriptor) || displayPrice ? (\n <div className=\"flex items-start justify-between gap-3\">\n {showResourceType && resourceDescriptor ? (\n (() => {\n const { icon: ResourceIcon, label } = resourceDescriptor;\n return (\n <span\n className={`inline-flex items-center gap-1.5 rounded-${borderRadius} bg-${textColor}/15 px-2.5 py-1 text-[10px] font-bold tracking-[0.18em] uppercase text-${textColor} backdrop-blur-sm`}\n style={{\n boxShadow: insetBorder(textColor, 15),\n }}\n >\n <ResourceIcon className=\"size-3\" />\n {label}\n </span>\n );\n })()\n ) : (\n <span />\n )}\n {displayPrice && (\n <span\n className={`inline-flex items-center rounded-${borderRadius} bg-${accentColor} px-2.5 py-1 text-[11px] font-bold tabular-nums text-${accentColor}-foreground`}\n style={{\n boxShadow: `0 4px 14px -4px color-mix(in oklch, var(--color-foreground) 30%, transparent)`,\n }}\n >\n {displayPrice}\n </span>\n )}\n </div>\n ) : null}\n\n {/* Middle: spacer that keeps share panel bottom-anchored.\n Optional title renders inside it without changing layout rhythm. */}\n <div className=\"mt-4 flex flex-1 flex-col justify-end\">\n {titleEnabled && displayTitle && (\n <h2\n className={`text-${titleFontSize} font-header leading-[1.12] font-bold tracking-[-0.015em] text-${titleColor}`}\n style={{\n // Themed via foreground so the legibility shadow flips with\n // the title color when the theme switches to dark mode.\n textShadow: showHeroImage\n ? `0 2px 12px color-mix(in oklch, var(--color-foreground) 40%, transparent)`\n : undefined,\n }}\n >\n {displayTitle}\n </h2>\n )}\n </div>\n\n {/* Bottom: share panel */}\n <div className=\"mt-6 flex flex-col gap-3\">\n <div className=\"flex items-stretch gap-3\">\n {/* QR card */}\n <div\n className={`group relative shrink-0 rounded-${borderRadius} bg-white p-2.5 transition-transform duration-300 hover:scale-[1.02]`}\n style={{\n // QR card stays white for scanner contrast; lift shadow is\n // themed via foreground so it reads in dark mode too.\n boxShadow: `0 4px 16px -4px color-mix(in oklch, var(--color-foreground) 25%, transparent), inset 0 0 0 1px rgba(255,255,255,0.4)`,\n }}\n aria-label=\"QR code for share link\"\n >\n <QRCodeSVG\n value={shareLink || \"https://example.com\"}\n size={96}\n level=\"H\"\n bgColor=\"#ffffff\"\n fgColor=\"#0f172a\"\n />\n </div>\n\n {/* URL chip + share actions rail */}\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <span\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${textColor}/70`}\n >\n Share link\n </span>\n <button\n type=\"button\"\n onClick={handleCopy}\n disabled={!hasShareLink}\n aria-label={\n copyState === \"copied\" ? \"Copied to clipboard\" : \"Copy link\"\n }\n className={`group flex items-center justify-between gap-2 rounded-${borderRadius} bg-${textColor}/10 px-3 py-2 text-left text-[12px] backdrop-blur-sm transition-all duration-300 hover:bg-${textColor}/15 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--quick-share-focus-ring)] disabled:opacity-50 ${copyState === \"copied\" ? `bg-${accentColor}/20` : \"\"}`}\n style={\n {\n \"--quick-share-focus-ring\": colorMix(accentColor, 40),\n boxShadow: insetBorder(textColor, 15),\n } as QuickShareCSSProperties\n }\n >\n <span\n className={`min-w-0 flex-1 truncate font-medium tabular-nums text-${textColor}`}\n >\n {hasShareLink ? (\n <>\n {showDomainPrefix && prefix && (\n <span className={`opacity-60`}>{prefix}</span>\n )}\n <span className=\"font-semibold\">{path}</span>\n </>\n ) : (\n <span className={`opacity-60`}>No link yet</span>\n )}\n </span>\n <span\n className={`flex size-7 shrink-0 items-center justify-center rounded-full transition-all duration-300 ${copyState === \"copied\" ? `bg-${accentColor} text-${accentColor}-foreground scale-110` : `bg-${textColor}/15 text-${textColor}`}`}\n >\n {copyState === \"copied\" ? (\n <Check className=\"size-3.5\" />\n ) : (\n <Copy className=\"size-3.5\" />\n )}\n </span>\n </button>\n <span className=\"sr-only\" aria-live=\"polite\" role=\"status\">\n {copyState === \"copied\" ? \"Copied to clipboard\" : \"\"}\n </span>\n\n {showShareActions && (\n <ShareActionRow\n shareLink={shareLink}\n displayTitle={displayTitle}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n onNative={handleNativeShare}\n />\n )}\n </div>\n </div>\n\n {shouldShowBuyButton &&\n (hasShareLink ? (\n <a\n href={shareLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`flex w-full items-center justify-center gap-2 rounded-${borderRadius} bg-${accentColor} px-4 py-3 text-[13px] font-bold text-${accentColor}-foreground transition-transform hover:scale-[1.01]`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n <ShoppingCart className=\"size-4\" />\n <span>Buy now</span>\n </a>\n ) : (\n <button\n type=\"button\"\n disabled\n className={`flex w-full cursor-not-allowed items-center justify-center gap-2 rounded-${borderRadius} bg-${accentColor} px-4 py-3 text-[13px] font-bold text-${accentColor}-foreground opacity-50`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n <ShoppingCart className=\"size-4\" />\n <span>Buy now</span>\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n}\n\ntype ShareActionRowProps = {\n shareLink: string;\n displayTitle: string;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n onNative: () => void;\n};\n\nfunction ShareActionRow({\n shareLink,\n displayTitle,\n accentColor,\n textColor,\n borderRadius,\n onNative,\n}: ShareActionRowProps) {\n const disabled = !shareLink;\n const { canNativeShare, canSendSms } = useShareCapabilities();\n\n const emailHref = shareLink\n ? `mailto:?subject=${encodeURIComponent(displayTitle)}&body=${encodeURIComponent(shareLink)}`\n : undefined;\n const smsHref = shareLink\n ? `sms:?body=${encodeURIComponent(`${displayTitle} — ${shareLink}`)}`\n : undefined;\n\n return (\n <div className=\"flex items-center gap-1.5\">\n <ShareActionButton\n icon={Mail}\n label=\"Email\"\n href={emailHref}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n {canSendSms && (\n <ShareActionButton\n icon={MessageCircle}\n label=\"Text\"\n href={smsHref}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n )}\n {canNativeShare && (\n <ShareActionButton\n icon={Share2}\n label=\"Share\"\n onClick={onNative}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n )}\n </div>\n );\n}\n\ntype ShareActionButtonProps = {\n icon: LucideIcon;\n label: string;\n href?: string | undefined;\n onClick?: () => void;\n disabled: boolean;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n};\n\nfunction ShareActionButton({\n icon: Icon,\n label,\n href,\n onClick,\n disabled,\n accentColor,\n textColor,\n borderRadius,\n}: ShareActionButtonProps) {\n const className = `group inline-flex items-center gap-1.5 rounded-${borderRadius} bg-${textColor}/10 px-2.5 py-1.5 text-[11px] font-semibold text-${textColor} backdrop-blur-sm transition-all duration-200 hover:-translate-y-0.5 hover:bg-${accentColor} hover:text-${accentColor}-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--quick-share-focus-ring)] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:translate-y-0`;\n const style: QuickShareCSSProperties = {\n \"--quick-share-focus-ring\": colorMix(accentColor, 40),\n boxShadow: insetBorder(textColor, 15),\n };\n\n const content = (\n <>\n <Icon className=\"size-3\" />\n <span>{label}</span>\n </>\n );\n\n if (href && !disabled) {\n return (\n <a href={href} className={className} style={style} aria-label={label}>\n {content}\n </a>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className={className}\n style={style}\n aria-label={label}\n >\n {content}\n </button>\n );\n}\n\nfunction EmptyHero({\n accentColor,\n textColor,\n}: {\n accentColor: ColorOptions;\n textColor: ColorOptions;\n}) {\n return (\n <div className={`bg-muted absolute inset-0`}>\n <div\n className=\"absolute inset-0\"\n style={{\n background: `radial-gradient(circle at 30% 20%, ${colorMix(accentColor, 15)}, transparent 60%), radial-gradient(circle at 80% 90%, ${colorMix(accentColor, 10)}, transparent 55%)`,\n }}\n />\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-3\">\n <div\n className={`flex size-14 items-center justify-center rounded-2xl bg-${textColor}/5`}\n style={{ boxShadow: insetBorder(textColor, 10) }}\n >\n <ImageIcon className={`size-6 text-${textColor}/40`} />\n </div>\n <span\n className={`text-[10px] font-bold tracking-[0.2em] uppercase text-${textColor}/45`}\n >\n Nothing selected\n </span>\n </div>\n </div>\n );\n}\n\nexport const quickShareWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickShareWidget\",\n displayName: \"Quick Share Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Content\n {\n key: \"shareableResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select the content to generate a share link for\",\n allowedTypes: [\"Product\", \"Page\", \"EnrollmentPack\", \"Medium\", \"Library\"],\n tab: \"styling\",\n group: \"Content\",\n },\n\n // Title\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Display a title on the hero\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description:\n \"Custom title text (defaults to the resource title if empty)\",\n defaultValue: \"\",\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 title\",\n defaultValue: \"2xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Share panel polish (new)\n {\n key: \"showResourceType\",\n label: \"Show Resource Type Pill\",\n type: \"boolean\",\n description:\n \"Display a small type eyebrow chip (Product · Page · Media…)\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showShareActions\",\n label: \"Show Share Actions\",\n type: \"boolean\",\n description:\n \"Show Email, Text, and native Share buttons under the link chip\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showDomainPrefix\",\n label: \"Show Domain Prefix\",\n type: \"boolean\",\n description:\n \"Include the domain in the link chip (dimmed) with the path emphasized\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showBuyButton\",\n label: \"Show Buy Button\",\n type: \"boolean\",\n description: \"Display the Buy button (only shown for Product resources)\",\n defaultValue: false,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n\n // Design\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for widget content (over the hero)\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description:\n \"Drives the price chip, primary button, and copy-success flash\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add editorial gradient stack for legibility over the hero\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description:\n \"Gradient only (recommended) or gradient + solid wash (heavier)\",\n defaultValue: \"gradient\",\n options: [\n { label: \"Gradient\", value: \"gradient\" },\n { label: \"Solid\", value: \"solid\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 70,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"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 widget content\",\n defaultValue: 6,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget container\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget container\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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N,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EAGDA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAY,OAAO;IAAY,EACxC;IAAE,OAAO;IAAS,OAAO;IAAS,CACnC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACDC,mBAAAA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}
|
|
1
|
+
{"version":3,"file":"QuickShareWidget-CYPOXs8X.cjs","names":["Package","FileText","Ticket","ImageIcon","BookOpen","CircleDot","borderWidthClasses","borderColorClasses","QRCodeSVG","Check","Copy","ShoppingCart","Mail","MessageCircle","Share2","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/widgets/QuickShareWidget.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useState,\n type ComponentProps,\n type CSSProperties,\n} from \"react\";\nimport type React from \"react\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n borderColorClasses,\n borderWidthClasses,\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport {\n BookOpen,\n Check,\n CircleDot,\n Copy,\n FileText,\n Image as ImageIcon,\n Mail,\n MessageCircle,\n Package,\n Share2,\n ShoppingCart,\n Ticket,\n type LucideIcon,\n} from \"lucide-react\";\n\ntype QuickShareWidgetProps = ComponentProps<\"div\"> & {\n // Resource\n shareableResource?: ShareableItem;\n\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Actions\n showBuyButton?: boolean;\n\n // Polish (new, additive)\n showResourceType?: boolean;\n showShareActions?: boolean;\n showDomainPrefix?: boolean;\n};\n\ntype ResourceDescriptor = {\n label: string;\n icon: LucideIcon;\n};\n\ntype QuickShareCSSProperties = CSSProperties &\n Record<`--${string}`, string | number | undefined>;\n\nconst RESOURCE_TYPE_MAP: Record<string, ResourceDescriptor> = {\n Product: { label: \"Product\", icon: Package },\n Page: { label: \"Page\", icon: FileText },\n EnrollmentPack: { label: \"Enrollment\", icon: Ticket },\n Medium: { label: \"Media\", icon: ImageIcon },\n Library: { label: \"Library\", icon: BookOpen },\n};\n\nconst getResourceDescriptor = (\n resource: ShareableItem | undefined,\n): ResourceDescriptor | null => {\n const rawType = (resource?.type || resource?.shareableType || \"\") as string;\n if (!rawType) return null;\n return RESOURCE_TYPE_MAP[rawType] ?? { label: rawType, icon: CircleDot };\n};\n\nconst splitUrl = (url: string): { prefix: string; path: string } => {\n try {\n const parsed = new URL(url);\n return {\n prefix: `${parsed.protocol}//${parsed.host}`,\n path: `${parsed.pathname}${parsed.search}${parsed.hash}`,\n };\n } catch {\n return { prefix: \"\", path: url };\n }\n};\n\nconst CURRENCY_FIELD_KEYS = [\n \"currency\",\n \"currency_code\",\n \"currencyCode\",\n \"currencyIso\",\n \"currency_iso\",\n] as const;\n\nconst getResourceCurrency = (\n resource: ShareableItem | undefined,\n): string | null => {\n if (!resource) return null;\n for (const key of CURRENCY_FIELD_KEYS) {\n const value = resource[key];\n if (typeof value === \"string\" && /^[A-Z]{3}$/i.test(value)) {\n return value.toUpperCase();\n }\n }\n return null;\n};\n\nconst formatNumericPrice = (price: number, resource: ShareableItem): string => {\n const currency = getResourceCurrency(resource);\n if (!currency) return String(price);\n try {\n return price.toLocaleString(undefined, { style: \"currency\", currency });\n } catch {\n return String(price);\n }\n};\n\nconst getDisplayPrice = (\n resource: ShareableItem | undefined,\n): string | null => {\n if (!resource) return null;\n if (typeof resource.display_price === \"string\" && resource.display_price) {\n return resource.display_price;\n }\n if (resource.price != null) {\n return typeof resource.price === \"number\"\n ? formatNumericPrice(resource.price, resource)\n : String(resource.price);\n }\n return null;\n};\n\nconst getColorCssValue = (color: ColorOptions): string =>\n color === \"transparent\" ? \"transparent\" : `var(--color-${color})`;\n\nconst colorMix = (color: ColorOptions, amount: number): string =>\n color === \"transparent\"\n ? \"transparent\"\n : `color-mix(in oklch, ${getColorCssValue(color)} ${amount}%, transparent)`;\n\nconst insetBorder = (color: ColorOptions, amount: number): string =>\n `inset 0 0 0 1px ${colorMix(color, amount)}`;\n\ntype CopyState = \"idle\" | \"copied\";\n\nfunction useTimedCopyState(timeoutMs: number) {\n const [copyState, setCopyState] = useState<CopyState>(\"idle\");\n\n useEffect(() => {\n if (copyState !== \"copied\") return;\n const id = window.setTimeout(() => setCopyState(\"idle\"), timeoutMs);\n return () => window.clearTimeout(id);\n }, [copyState, timeoutMs]);\n\n const markCopied = useCallback(() => {\n setCopyState(\"copied\");\n }, []);\n\n return { copyState, markCopied };\n}\n\nfunction useImageFailureFallback(imageUrl: string) {\n const [imageFailed, setImageFailed] = useState(false);\n\n // Reset the failed-image state when the resource (and thus the image URL)\n // changes — otherwise switching to a new resource keeps showing EmptyHero\n // because the React state outlives the previous load failure.\n useEffect(() => {\n setImageFailed(false);\n }, [imageUrl]);\n\n const handleImageError = useCallback(() => {\n setImageFailed(true);\n }, []);\n\n return { imageFailed, handleImageError };\n}\n\nfunction useShareCapabilities() {\n const [canNativeShare, setCanNativeShare] = useState(false);\n const [canSendSms, setCanSendSms] = useState(false);\n\n useEffect(() => {\n setCanNativeShare(\n typeof navigator !== \"undefined\" && typeof navigator.share === \"function\",\n );\n setCanSendSms(\n typeof navigator !== \"undefined\" &&\n (/Android|iPhone|iPad|iPod/i.test(navigator.userAgent) ||\n (/Macintosh/i.test(navigator.userAgent) &&\n navigator.maxTouchPoints > 1)),\n );\n }, []);\n\n return { canNativeShare, canSendSms };\n}\n\nexport function QuickShareWidget({\n shareableResource,\n\n titleEnabled = true,\n titleText = \"\",\n titleFontSize = \"2xl\",\n titleColor = \"background\",\n\n textColor = \"background\",\n accentColor = \"primary\",\n padding = 6,\n borderRadius = \"xl\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 70,\n\n showBuyButton = false,\n\n showResourceType = true,\n showShareActions = true,\n showDomainPrefix = true,\n\n className,\n style,\n ...props\n}: QuickShareWidgetProps): React.JSX.Element {\n const backgroundImageUrl =\n shareableResource?.image_url || shareableResource?.imageUrl || \"\";\n const { copyState, markCopied } = useTimedCopyState(1600);\n // Hero image fallback: if the resource image 404s or fails to decode, flip\n // to the EmptyHero treatment instead of rendering a broken image.\n const { imageFailed, handleImageError } =\n useImageFailureFallback(backgroundImageUrl);\n\n const showHeroImage = Boolean(backgroundImageUrl) && !imageFailed;\n const shareLink = shareableResource?.share_link || \"\";\n const hasShareLink = !!shareLink;\n\n const displayTitle =\n titleText || shareableResource?.title || \"Select content to share\";\n const resourceDescriptor = getResourceDescriptor(shareableResource);\n const displayPrice = getDisplayPrice(shareableResource);\n\n const isProduct =\n shareableResource?.type === \"Product\" ||\n shareableResource?.shareableType === \"Product\";\n const shouldShowBuyButton = showBuyButton && isProduct;\n\n const parsedOverlayIntensity = Number(\n String(overlayIntensity).replace(\"%\", \"\"),\n );\n const overlayOpacity =\n (Number.isFinite(parsedOverlayIntensity)\n ? Math.min(100, Math.max(0, parsedOverlayIntensity))\n : 70) / 100;\n\n const editorialGradient: CSSProperties | undefined =\n overlayEnabled && showHeroImage\n ? {\n background: `linear-gradient(to top, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 100)}%, transparent), color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 55)}%, transparent) 45%, transparent 85%)`,\n }\n : undefined;\n\n const handleCopy = async () => {\n if (!hasShareLink) return;\n try {\n await navigator.clipboard.writeText(shareLink);\n markCopied();\n } catch (error) {\n console.error(\"Failed to copy to clipboard:\", error);\n }\n };\n\n const handleNativeShare = async () => {\n if (!hasShareLink) return;\n if (typeof navigator.share === \"function\") {\n try {\n await navigator.share({\n title: displayTitle,\n url: shareLink,\n });\n } catch {\n // Ignore abort\n }\n } else {\n await handleCopy();\n }\n };\n\n const { prefix, path } = hasShareLink\n ? splitUrl(shareLink)\n : { prefix: \"\", path: \"\" };\n\n return (\n <div\n className={`relative isolate overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-muted text-${textColor} ${className ?? \"\"}`}\n style={{\n // Themed dual-shadow (crisp + soft ambient), derived from the\n // foreground token so the lift reads in both light and dark.\n boxShadow: `0 1px 2px color-mix(in oklch, var(--color-foreground) 4%, transparent), 0 20px 40px -20px color-mix(in oklch, var(--color-foreground) 25%, transparent)`,\n ...style,\n }}\n {...props}\n >\n {/* Hero image or empty-state surface */}\n {showHeroImage ? (\n <div className=\"absolute inset-0\">\n <img\n src={backgroundImageUrl}\n alt=\"\"\n loading=\"lazy\"\n onError={handleImageError}\n className=\"h-full w-full object-cover\"\n />\n {overlayEnabled && (\n <>\n {/* Layer 1 — main bottom-to-top legibility gradient */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={editorialGradient}\n />\n {/* Layer 2 — diagonal bottom-left anchor (image reads top-right, content reads bottom-left) */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={{\n background: `linear-gradient(to top right, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 65)}%, transparent), color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 25)}%, transparent) 35%, transparent 65%)`,\n }}\n />\n {/* Layer 3 — radial pool anchoring the bottom-left share panel */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={{\n background: `radial-gradient(ellipse 70% 55% at 15% 100%, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 45)}%, transparent), transparent 70%)`,\n }}\n />\n {overlayType === \"solid\" && (\n <div\n className=\"bg-foreground pointer-events-none absolute inset-0\"\n style={{ opacity: overlayOpacity * 0.35 }}\n />\n )}\n </>\n )}\n </div>\n ) : (\n <EmptyHero accentColor={accentColor} textColor={textColor} />\n )}\n\n {/* Content */}\n <div className={`relative flex min-h-[440px] flex-col p-${padding}`}>\n {/* Top row: resource type eyebrow + optional price chip */}\n {(showResourceType && resourceDescriptor) || displayPrice ? (\n <div className=\"flex items-start justify-between gap-3\">\n {showResourceType && resourceDescriptor ? (\n (() => {\n const { icon: ResourceIcon, label } = resourceDescriptor;\n return (\n <span\n className={`inline-flex items-center gap-1.5 rounded-${borderRadius} bg-${textColor}/15 px-2.5 py-1 text-[10px] font-bold tracking-[0.18em] uppercase text-${textColor} backdrop-blur-sm`}\n style={{\n boxShadow: insetBorder(textColor, 15),\n }}\n >\n <ResourceIcon className=\"size-3\" />\n {label}\n </span>\n );\n })()\n ) : (\n <span />\n )}\n {displayPrice && (\n <span\n className={`inline-flex items-center rounded-${borderRadius} bg-${accentColor} px-2.5 py-1 text-[11px] font-bold tabular-nums text-${accentColor}-foreground`}\n style={{\n boxShadow: `0 4px 14px -4px color-mix(in oklch, var(--color-foreground) 30%, transparent)`,\n }}\n >\n {displayPrice}\n </span>\n )}\n </div>\n ) : null}\n\n {/* Middle: spacer that keeps share panel bottom-anchored.\n Optional title renders inside it without changing layout rhythm. */}\n <div className=\"mt-4 flex flex-1 flex-col justify-end\">\n {titleEnabled && displayTitle && (\n <h2\n className={`text-${titleFontSize} font-header leading-[1.12] font-bold tracking-[-0.015em] text-${titleColor}`}\n style={{\n // Themed via foreground so the legibility shadow flips with\n // the title color when the theme switches to dark mode.\n textShadow: showHeroImage\n ? `0 2px 12px color-mix(in oklch, var(--color-foreground) 40%, transparent)`\n : undefined,\n }}\n >\n {displayTitle}\n </h2>\n )}\n </div>\n\n {/* Bottom: share panel */}\n <div className=\"mt-6 flex flex-col gap-3\">\n <div className=\"flex items-stretch gap-3\">\n {/* QR card */}\n <div\n className={`group relative shrink-0 rounded-${borderRadius} bg-white p-2.5 transition-transform duration-300 hover:scale-[1.02]`}\n style={{\n // QR card stays white for scanner contrast; lift shadow is\n // themed via foreground so it reads in dark mode too.\n boxShadow: `0 4px 16px -4px color-mix(in oklch, var(--color-foreground) 25%, transparent), inset 0 0 0 1px rgba(255,255,255,0.4)`,\n }}\n aria-label=\"QR code for share link\"\n >\n <QRCodeSVG\n value={shareLink || \"https://example.com\"}\n size={96}\n level=\"H\"\n bgColor=\"#ffffff\"\n fgColor=\"#0f172a\"\n />\n </div>\n\n {/* URL chip + share actions rail */}\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <span\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${textColor}/70`}\n >\n Share link\n </span>\n <button\n type=\"button\"\n onClick={handleCopy}\n disabled={!hasShareLink}\n aria-label={\n copyState === \"copied\" ? \"Copied to clipboard\" : \"Copy link\"\n }\n className={`group flex items-center justify-between gap-2 rounded-${borderRadius} bg-${textColor}/10 px-3 py-2 text-left text-[12px] backdrop-blur-sm transition-all duration-300 hover:bg-${textColor}/15 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--quick-share-focus-ring)] disabled:opacity-50 ${copyState === \"copied\" ? `bg-${accentColor}/20` : \"\"}`}\n style={\n {\n \"--quick-share-focus-ring\": colorMix(accentColor, 40),\n boxShadow: insetBorder(textColor, 15),\n } as QuickShareCSSProperties\n }\n >\n <span\n className={`min-w-0 flex-1 truncate font-medium tabular-nums text-${textColor}`}\n >\n {hasShareLink ? (\n <>\n {showDomainPrefix && prefix && (\n <span className={`opacity-60`}>{prefix}</span>\n )}\n <span className=\"font-semibold\">{path}</span>\n </>\n ) : (\n <span className={`opacity-60`}>No link yet</span>\n )}\n </span>\n <span\n className={`flex size-7 shrink-0 items-center justify-center rounded-full transition-all duration-300 ${copyState === \"copied\" ? `bg-${accentColor} text-${accentColor}-foreground scale-110` : `bg-${textColor}/15 text-${textColor}`}`}\n >\n {copyState === \"copied\" ? (\n <Check className=\"size-3.5\" />\n ) : (\n <Copy className=\"size-3.5\" />\n )}\n </span>\n </button>\n <span className=\"sr-only\" aria-live=\"polite\" role=\"status\">\n {copyState === \"copied\" ? \"Copied to clipboard\" : \"\"}\n </span>\n\n {showShareActions && (\n <ShareActionRow\n shareLink={shareLink}\n displayTitle={displayTitle}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n onNative={handleNativeShare}\n />\n )}\n </div>\n </div>\n\n {shouldShowBuyButton &&\n (hasShareLink ? (\n <a\n href={shareLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`flex w-full items-center justify-center gap-2 rounded-${borderRadius} bg-${accentColor} px-4 py-3 text-[13px] font-bold text-${accentColor}-foreground transition-transform hover:scale-[1.01]`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n <ShoppingCart className=\"size-4\" />\n <span>Buy now</span>\n </a>\n ) : (\n <button\n type=\"button\"\n disabled\n className={`flex w-full cursor-not-allowed items-center justify-center gap-2 rounded-${borderRadius} bg-${accentColor} px-4 py-3 text-[13px] font-bold text-${accentColor}-foreground opacity-50`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n <ShoppingCart className=\"size-4\" />\n <span>Buy now</span>\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n}\n\ntype ShareActionRowProps = {\n shareLink: string;\n displayTitle: string;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n onNative: () => void;\n};\n\nfunction ShareActionRow({\n shareLink,\n displayTitle,\n accentColor,\n textColor,\n borderRadius,\n onNative,\n}: ShareActionRowProps) {\n const disabled = !shareLink;\n const { canNativeShare, canSendSms } = useShareCapabilities();\n\n const emailHref = shareLink\n ? `mailto:?subject=${encodeURIComponent(displayTitle)}&body=${encodeURIComponent(shareLink)}`\n : undefined;\n const smsHref = shareLink\n ? `sms:?body=${encodeURIComponent(`${displayTitle} — ${shareLink}`)}`\n : undefined;\n\n return (\n <div className=\"flex items-center gap-1.5\">\n <ShareActionButton\n icon={Mail}\n label=\"Email\"\n href={emailHref}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n {canSendSms && (\n <ShareActionButton\n icon={MessageCircle}\n label=\"Text\"\n href={smsHref}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n )}\n {canNativeShare && (\n <ShareActionButton\n icon={Share2}\n label=\"Share\"\n onClick={onNative}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n )}\n </div>\n );\n}\n\ntype ShareActionButtonProps = {\n icon: LucideIcon;\n label: string;\n href?: string | undefined;\n onClick?: () => void;\n disabled: boolean;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n};\n\nfunction ShareActionButton({\n icon: Icon,\n label,\n href,\n onClick,\n disabled,\n accentColor,\n textColor,\n borderRadius,\n}: ShareActionButtonProps) {\n const className = `group inline-flex items-center gap-1.5 rounded-${borderRadius} bg-${textColor}/10 px-2.5 py-1.5 text-[11px] font-semibold text-${textColor} backdrop-blur-sm transition-all duration-200 hover:-translate-y-0.5 hover:bg-${accentColor} hover:text-${accentColor}-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--quick-share-focus-ring)] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:translate-y-0`;\n const style: QuickShareCSSProperties = {\n \"--quick-share-focus-ring\": colorMix(accentColor, 40),\n boxShadow: insetBorder(textColor, 15),\n };\n\n const content = (\n <>\n <Icon className=\"size-3\" />\n <span>{label}</span>\n </>\n );\n\n if (href && !disabled) {\n return (\n <a href={href} className={className} style={style} aria-label={label}>\n {content}\n </a>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className={className}\n style={style}\n aria-label={label}\n >\n {content}\n </button>\n );\n}\n\nfunction EmptyHero({\n accentColor,\n textColor,\n}: {\n accentColor: ColorOptions;\n textColor: ColorOptions;\n}) {\n return (\n <div className={`bg-muted absolute inset-0`}>\n <div\n className=\"absolute inset-0\"\n style={{\n background: `radial-gradient(circle at 30% 20%, ${colorMix(accentColor, 15)}, transparent 60%), radial-gradient(circle at 80% 90%, ${colorMix(accentColor, 10)}, transparent 55%)`,\n }}\n />\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-3\">\n <div\n className={`flex size-14 items-center justify-center rounded-2xl bg-${textColor}/5`}\n style={{ boxShadow: insetBorder(textColor, 10) }}\n >\n <ImageIcon className={`size-6 text-${textColor}/40`} />\n </div>\n <span\n className={`text-[10px] font-bold tracking-[0.2em] uppercase text-${textColor}/45`}\n >\n Nothing selected\n </span>\n </div>\n </div>\n );\n}\n\nexport const quickShareWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickShareWidget\",\n displayName: \"Quick Share Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Content\n {\n key: \"shareableResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select the content to generate a share link for\",\n allowedTypes: [\"Product\", \"Page\", \"EnrollmentPack\", \"Medium\", \"Library\"],\n tab: \"styling\",\n group: \"Content\",\n },\n\n // Title\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Display a title on the hero\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description:\n \"Custom title text (defaults to the resource title if empty)\",\n defaultValue: \"\",\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 title\",\n defaultValue: \"2xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Share panel polish (new)\n {\n key: \"showResourceType\",\n label: \"Show Resource Type Pill\",\n type: \"boolean\",\n description:\n \"Display a small type eyebrow chip (Product · Page · Media…)\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showShareActions\",\n label: \"Show Share Actions\",\n type: \"boolean\",\n description:\n \"Show Email, Text, and native Share buttons under the link chip\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showDomainPrefix\",\n label: \"Show Domain Prefix\",\n type: \"boolean\",\n description:\n \"Include the domain in the link chip (dimmed) with the path emphasized\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showBuyButton\",\n label: \"Show Buy Button\",\n type: \"boolean\",\n description: \"Display the Buy button (only shown for Product resources)\",\n defaultValue: false,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n\n // Design\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for widget content (over the hero)\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description:\n \"Drives the price chip, primary button, and copy-success flash\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add editorial gradient stack for legibility over the hero\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description:\n \"Gradient only (recommended) or gradient + solid wash (heavier)\",\n defaultValue: \"gradient\",\n options: [\n { label: \"Gradient\", value: \"gradient\" },\n { label: \"Solid\", value: \"solid\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 70,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"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 widget content\",\n defaultValue: 6,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget container\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget container\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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N,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EAGDA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAY,OAAO;IAAY,EACxC;IAAE,OAAO;IAAS,OAAO;IAAS,CACnC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACDC,mBAAAA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { I as __exportAll } from "./portal_tenant_content-DPLnrtOG.mjs";
|
|
2
|
-
import { i as getBorderColorField, l as getColorField, m as getPaddingField, n as borderWidthClasses, o as getBorderRadiusField, s as getBorderWidthField, t as borderColorClasses, u as getFontSizeField } from "./registries-
|
|
2
|
+
import { i as getBorderColorField, l as getColorField, m as getPaddingField, n as borderWidthClasses, o as getBorderRadiusField, s as getBorderWidthField, t as borderColorClasses, u as getFontSizeField } from "./registries-6F90ZS1m.mjs";
|
|
3
3
|
import { useCallback, useEffect, useState } from "react";
|
|
4
4
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { BookOpen, Check, CircleDot, Copy, FileText, Image, Mail, MessageCircle, Package, Share2, ShoppingCart, Ticket } from "lucide-react";
|
|
@@ -588,4 +588,4 @@ const quickShareWidgetPropertySchema = {
|
|
|
588
588
|
//#endregion
|
|
589
589
|
export { QuickShareWidget_exports as n, quickShareWidgetPropertySchema as r, QuickShareWidget as t };
|
|
590
590
|
|
|
591
|
-
//# sourceMappingURL=QuickShareWidget-
|
|
591
|
+
//# sourceMappingURL=QuickShareWidget-CyYW9nS6.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickShareWidget-D-NVbmfw.mjs","names":["ImageIcon"],"sources":["../../widgets/src/widgets/QuickShareWidget.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useState,\n type ComponentProps,\n type CSSProperties,\n} from \"react\";\nimport type React from \"react\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n borderColorClasses,\n borderWidthClasses,\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport {\n BookOpen,\n Check,\n CircleDot,\n Copy,\n FileText,\n Image as ImageIcon,\n Mail,\n MessageCircle,\n Package,\n Share2,\n ShoppingCart,\n Ticket,\n type LucideIcon,\n} from \"lucide-react\";\n\ntype QuickShareWidgetProps = ComponentProps<\"div\"> & {\n // Resource\n shareableResource?: ShareableItem;\n\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Actions\n showBuyButton?: boolean;\n\n // Polish (new, additive)\n showResourceType?: boolean;\n showShareActions?: boolean;\n showDomainPrefix?: boolean;\n};\n\ntype ResourceDescriptor = {\n label: string;\n icon: LucideIcon;\n};\n\ntype QuickShareCSSProperties = CSSProperties &\n Record<`--${string}`, string | number | undefined>;\n\nconst RESOURCE_TYPE_MAP: Record<string, ResourceDescriptor> = {\n Product: { label: \"Product\", icon: Package },\n Page: { label: \"Page\", icon: FileText },\n EnrollmentPack: { label: \"Enrollment\", icon: Ticket },\n Medium: { label: \"Media\", icon: ImageIcon },\n Library: { label: \"Library\", icon: BookOpen },\n};\n\nconst getResourceDescriptor = (\n resource: ShareableItem | undefined,\n): ResourceDescriptor | null => {\n const rawType = (resource?.type || resource?.shareableType || \"\") as string;\n if (!rawType) return null;\n return RESOURCE_TYPE_MAP[rawType] ?? { label: rawType, icon: CircleDot };\n};\n\nconst splitUrl = (url: string): { prefix: string; path: string } => {\n try {\n const parsed = new URL(url);\n return {\n prefix: `${parsed.protocol}//${parsed.host}`,\n path: `${parsed.pathname}${parsed.search}${parsed.hash}`,\n };\n } catch {\n return { prefix: \"\", path: url };\n }\n};\n\nconst CURRENCY_FIELD_KEYS = [\n \"currency\",\n \"currency_code\",\n \"currencyCode\",\n \"currencyIso\",\n \"currency_iso\",\n] as const;\n\nconst getResourceCurrency = (\n resource: ShareableItem | undefined,\n): string | null => {\n if (!resource) return null;\n for (const key of CURRENCY_FIELD_KEYS) {\n const value = resource[key];\n if (typeof value === \"string\" && /^[A-Z]{3}$/i.test(value)) {\n return value.toUpperCase();\n }\n }\n return null;\n};\n\nconst formatNumericPrice = (price: number, resource: ShareableItem): string => {\n const currency = getResourceCurrency(resource);\n if (!currency) return String(price);\n try {\n return price.toLocaleString(undefined, { style: \"currency\", currency });\n } catch {\n return String(price);\n }\n};\n\nconst getDisplayPrice = (\n resource: ShareableItem | undefined,\n): string | null => {\n if (!resource) return null;\n if (typeof resource.display_price === \"string\" && resource.display_price) {\n return resource.display_price;\n }\n if (resource.price != null) {\n return typeof resource.price === \"number\"\n ? formatNumericPrice(resource.price, resource)\n : String(resource.price);\n }\n return null;\n};\n\nconst getColorCssValue = (color: ColorOptions): string =>\n color === \"transparent\" ? \"transparent\" : `var(--color-${color})`;\n\nconst colorMix = (color: ColorOptions, amount: number): string =>\n color === \"transparent\"\n ? \"transparent\"\n : `color-mix(in oklch, ${getColorCssValue(color)} ${amount}%, transparent)`;\n\nconst insetBorder = (color: ColorOptions, amount: number): string =>\n `inset 0 0 0 1px ${colorMix(color, amount)}`;\n\ntype CopyState = \"idle\" | \"copied\";\n\nfunction useTimedCopyState(timeoutMs: number) {\n const [copyState, setCopyState] = useState<CopyState>(\"idle\");\n\n useEffect(() => {\n if (copyState !== \"copied\") return;\n const id = window.setTimeout(() => setCopyState(\"idle\"), timeoutMs);\n return () => window.clearTimeout(id);\n }, [copyState, timeoutMs]);\n\n const markCopied = useCallback(() => {\n setCopyState(\"copied\");\n }, []);\n\n return { copyState, markCopied };\n}\n\nfunction useImageFailureFallback(imageUrl: string) {\n const [imageFailed, setImageFailed] = useState(false);\n\n // Reset the failed-image state when the resource (and thus the image URL)\n // changes — otherwise switching to a new resource keeps showing EmptyHero\n // because the React state outlives the previous load failure.\n useEffect(() => {\n setImageFailed(false);\n }, [imageUrl]);\n\n const handleImageError = useCallback(() => {\n setImageFailed(true);\n }, []);\n\n return { imageFailed, handleImageError };\n}\n\nfunction useShareCapabilities() {\n const [canNativeShare, setCanNativeShare] = useState(false);\n const [canSendSms, setCanSendSms] = useState(false);\n\n useEffect(() => {\n setCanNativeShare(\n typeof navigator !== \"undefined\" && typeof navigator.share === \"function\",\n );\n setCanSendSms(\n typeof navigator !== \"undefined\" &&\n (/Android|iPhone|iPad|iPod/i.test(navigator.userAgent) ||\n (/Macintosh/i.test(navigator.userAgent) &&\n navigator.maxTouchPoints > 1)),\n );\n }, []);\n\n return { canNativeShare, canSendSms };\n}\n\nexport function QuickShareWidget({\n shareableResource,\n\n titleEnabled = true,\n titleText = \"\",\n titleFontSize = \"2xl\",\n titleColor = \"background\",\n\n textColor = \"background\",\n accentColor = \"primary\",\n padding = 6,\n borderRadius = \"xl\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 70,\n\n showBuyButton = false,\n\n showResourceType = true,\n showShareActions = true,\n showDomainPrefix = true,\n\n className,\n style,\n ...props\n}: QuickShareWidgetProps): React.JSX.Element {\n const backgroundImageUrl =\n shareableResource?.image_url || shareableResource?.imageUrl || \"\";\n const { copyState, markCopied } = useTimedCopyState(1600);\n // Hero image fallback: if the resource image 404s or fails to decode, flip\n // to the EmptyHero treatment instead of rendering a broken image.\n const { imageFailed, handleImageError } =\n useImageFailureFallback(backgroundImageUrl);\n\n const showHeroImage = Boolean(backgroundImageUrl) && !imageFailed;\n const shareLink = shareableResource?.share_link || \"\";\n const hasShareLink = !!shareLink;\n\n const displayTitle =\n titleText || shareableResource?.title || \"Select content to share\";\n const resourceDescriptor = getResourceDescriptor(shareableResource);\n const displayPrice = getDisplayPrice(shareableResource);\n\n const isProduct =\n shareableResource?.type === \"Product\" ||\n shareableResource?.shareableType === \"Product\";\n const shouldShowBuyButton = showBuyButton && isProduct;\n\n const parsedOverlayIntensity = Number(\n String(overlayIntensity).replace(\"%\", \"\"),\n );\n const overlayOpacity =\n (Number.isFinite(parsedOverlayIntensity)\n ? Math.min(100, Math.max(0, parsedOverlayIntensity))\n : 70) / 100;\n\n const editorialGradient: CSSProperties | undefined =\n overlayEnabled && showHeroImage\n ? {\n background: `linear-gradient(to top, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 100)}%, transparent), color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 55)}%, transparent) 45%, transparent 85%)`,\n }\n : undefined;\n\n const handleCopy = async () => {\n if (!hasShareLink) return;\n try {\n await navigator.clipboard.writeText(shareLink);\n markCopied();\n } catch (error) {\n console.error(\"Failed to copy to clipboard:\", error);\n }\n };\n\n const handleNativeShare = async () => {\n if (!hasShareLink) return;\n if (typeof navigator.share === \"function\") {\n try {\n await navigator.share({\n title: displayTitle,\n url: shareLink,\n });\n } catch {\n // Ignore abort\n }\n } else {\n await handleCopy();\n }\n };\n\n const { prefix, path } = hasShareLink\n ? splitUrl(shareLink)\n : { prefix: \"\", path: \"\" };\n\n return (\n <div\n className={`relative isolate overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-muted text-${textColor} ${className ?? \"\"}`}\n style={{\n // Themed dual-shadow (crisp + soft ambient), derived from the\n // foreground token so the lift reads in both light and dark.\n boxShadow: `0 1px 2px color-mix(in oklch, var(--color-foreground) 4%, transparent), 0 20px 40px -20px color-mix(in oklch, var(--color-foreground) 25%, transparent)`,\n ...style,\n }}\n {...props}\n >\n {/* Hero image or empty-state surface */}\n {showHeroImage ? (\n <div className=\"absolute inset-0\">\n <img\n src={backgroundImageUrl}\n alt=\"\"\n loading=\"lazy\"\n onError={handleImageError}\n className=\"h-full w-full object-cover\"\n />\n {overlayEnabled && (\n <>\n {/* Layer 1 — main bottom-to-top legibility gradient */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={editorialGradient}\n />\n {/* Layer 2 — diagonal bottom-left anchor (image reads top-right, content reads bottom-left) */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={{\n background: `linear-gradient(to top right, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 65)}%, transparent), color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 25)}%, transparent) 35%, transparent 65%)`,\n }}\n />\n {/* Layer 3 — radial pool anchoring the bottom-left share panel */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={{\n background: `radial-gradient(ellipse 70% 55% at 15% 100%, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 45)}%, transparent), transparent 70%)`,\n }}\n />\n {overlayType === \"solid\" && (\n <div\n className=\"bg-foreground pointer-events-none absolute inset-0\"\n style={{ opacity: overlayOpacity * 0.35 }}\n />\n )}\n </>\n )}\n </div>\n ) : (\n <EmptyHero accentColor={accentColor} textColor={textColor} />\n )}\n\n {/* Content */}\n <div className={`relative flex min-h-[440px] flex-col p-${padding}`}>\n {/* Top row: resource type eyebrow + optional price chip */}\n {(showResourceType && resourceDescriptor) || displayPrice ? (\n <div className=\"flex items-start justify-between gap-3\">\n {showResourceType && resourceDescriptor ? (\n (() => {\n const { icon: ResourceIcon, label } = resourceDescriptor;\n return (\n <span\n className={`inline-flex items-center gap-1.5 rounded-${borderRadius} bg-${textColor}/15 px-2.5 py-1 text-[10px] font-bold tracking-[0.18em] uppercase text-${textColor} backdrop-blur-sm`}\n style={{\n boxShadow: insetBorder(textColor, 15),\n }}\n >\n <ResourceIcon className=\"size-3\" />\n {label}\n </span>\n );\n })()\n ) : (\n <span />\n )}\n {displayPrice && (\n <span\n className={`inline-flex items-center rounded-${borderRadius} bg-${accentColor} px-2.5 py-1 text-[11px] font-bold tabular-nums text-${accentColor}-foreground`}\n style={{\n boxShadow: `0 4px 14px -4px color-mix(in oklch, var(--color-foreground) 30%, transparent)`,\n }}\n >\n {displayPrice}\n </span>\n )}\n </div>\n ) : null}\n\n {/* Middle: spacer that keeps share panel bottom-anchored.\n Optional title renders inside it without changing layout rhythm. */}\n <div className=\"mt-4 flex flex-1 flex-col justify-end\">\n {titleEnabled && displayTitle && (\n <h2\n className={`text-${titleFontSize} font-header leading-[1.12] font-bold tracking-[-0.015em] text-${titleColor}`}\n style={{\n // Themed via foreground so the legibility shadow flips with\n // the title color when the theme switches to dark mode.\n textShadow: showHeroImage\n ? `0 2px 12px color-mix(in oklch, var(--color-foreground) 40%, transparent)`\n : undefined,\n }}\n >\n {displayTitle}\n </h2>\n )}\n </div>\n\n {/* Bottom: share panel */}\n <div className=\"mt-6 flex flex-col gap-3\">\n <div className=\"flex items-stretch gap-3\">\n {/* QR card */}\n <div\n className={`group relative shrink-0 rounded-${borderRadius} bg-white p-2.5 transition-transform duration-300 hover:scale-[1.02]`}\n style={{\n // QR card stays white for scanner contrast; lift shadow is\n // themed via foreground so it reads in dark mode too.\n boxShadow: `0 4px 16px -4px color-mix(in oklch, var(--color-foreground) 25%, transparent), inset 0 0 0 1px rgba(255,255,255,0.4)`,\n }}\n aria-label=\"QR code for share link\"\n >\n <QRCodeSVG\n value={shareLink || \"https://example.com\"}\n size={96}\n level=\"H\"\n bgColor=\"#ffffff\"\n fgColor=\"#0f172a\"\n />\n </div>\n\n {/* URL chip + share actions rail */}\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <span\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${textColor}/70`}\n >\n Share link\n </span>\n <button\n type=\"button\"\n onClick={handleCopy}\n disabled={!hasShareLink}\n aria-label={\n copyState === \"copied\" ? \"Copied to clipboard\" : \"Copy link\"\n }\n className={`group flex items-center justify-between gap-2 rounded-${borderRadius} bg-${textColor}/10 px-3 py-2 text-left text-[12px] backdrop-blur-sm transition-all duration-300 hover:bg-${textColor}/15 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--quick-share-focus-ring)] disabled:opacity-50 ${copyState === \"copied\" ? `bg-${accentColor}/20` : \"\"}`}\n style={\n {\n \"--quick-share-focus-ring\": colorMix(accentColor, 40),\n boxShadow: insetBorder(textColor, 15),\n } as QuickShareCSSProperties\n }\n >\n <span\n className={`min-w-0 flex-1 truncate font-medium tabular-nums text-${textColor}`}\n >\n {hasShareLink ? (\n <>\n {showDomainPrefix && prefix && (\n <span className={`opacity-60`}>{prefix}</span>\n )}\n <span className=\"font-semibold\">{path}</span>\n </>\n ) : (\n <span className={`opacity-60`}>No link yet</span>\n )}\n </span>\n <span\n className={`flex size-7 shrink-0 items-center justify-center rounded-full transition-all duration-300 ${copyState === \"copied\" ? `bg-${accentColor} text-${accentColor}-foreground scale-110` : `bg-${textColor}/15 text-${textColor}`}`}\n >\n {copyState === \"copied\" ? (\n <Check className=\"size-3.5\" />\n ) : (\n <Copy className=\"size-3.5\" />\n )}\n </span>\n </button>\n <span className=\"sr-only\" aria-live=\"polite\" role=\"status\">\n {copyState === \"copied\" ? \"Copied to clipboard\" : \"\"}\n </span>\n\n {showShareActions && (\n <ShareActionRow\n shareLink={shareLink}\n displayTitle={displayTitle}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n onNative={handleNativeShare}\n />\n )}\n </div>\n </div>\n\n {shouldShowBuyButton &&\n (hasShareLink ? (\n <a\n href={shareLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`flex w-full items-center justify-center gap-2 rounded-${borderRadius} bg-${accentColor} px-4 py-3 text-[13px] font-bold text-${accentColor}-foreground transition-transform hover:scale-[1.01]`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n <ShoppingCart className=\"size-4\" />\n <span>Buy now</span>\n </a>\n ) : (\n <button\n type=\"button\"\n disabled\n className={`flex w-full cursor-not-allowed items-center justify-center gap-2 rounded-${borderRadius} bg-${accentColor} px-4 py-3 text-[13px] font-bold text-${accentColor}-foreground opacity-50`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n <ShoppingCart className=\"size-4\" />\n <span>Buy now</span>\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n}\n\ntype ShareActionRowProps = {\n shareLink: string;\n displayTitle: string;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n onNative: () => void;\n};\n\nfunction ShareActionRow({\n shareLink,\n displayTitle,\n accentColor,\n textColor,\n borderRadius,\n onNative,\n}: ShareActionRowProps) {\n const disabled = !shareLink;\n const { canNativeShare, canSendSms } = useShareCapabilities();\n\n const emailHref = shareLink\n ? `mailto:?subject=${encodeURIComponent(displayTitle)}&body=${encodeURIComponent(shareLink)}`\n : undefined;\n const smsHref = shareLink\n ? `sms:?body=${encodeURIComponent(`${displayTitle} — ${shareLink}`)}`\n : undefined;\n\n return (\n <div className=\"flex items-center gap-1.5\">\n <ShareActionButton\n icon={Mail}\n label=\"Email\"\n href={emailHref}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n {canSendSms && (\n <ShareActionButton\n icon={MessageCircle}\n label=\"Text\"\n href={smsHref}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n )}\n {canNativeShare && (\n <ShareActionButton\n icon={Share2}\n label=\"Share\"\n onClick={onNative}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n )}\n </div>\n );\n}\n\ntype ShareActionButtonProps = {\n icon: LucideIcon;\n label: string;\n href?: string | undefined;\n onClick?: () => void;\n disabled: boolean;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n};\n\nfunction ShareActionButton({\n icon: Icon,\n label,\n href,\n onClick,\n disabled,\n accentColor,\n textColor,\n borderRadius,\n}: ShareActionButtonProps) {\n const className = `group inline-flex items-center gap-1.5 rounded-${borderRadius} bg-${textColor}/10 px-2.5 py-1.5 text-[11px] font-semibold text-${textColor} backdrop-blur-sm transition-all duration-200 hover:-translate-y-0.5 hover:bg-${accentColor} hover:text-${accentColor}-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--quick-share-focus-ring)] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:translate-y-0`;\n const style: QuickShareCSSProperties = {\n \"--quick-share-focus-ring\": colorMix(accentColor, 40),\n boxShadow: insetBorder(textColor, 15),\n };\n\n const content = (\n <>\n <Icon className=\"size-3\" />\n <span>{label}</span>\n </>\n );\n\n if (href && !disabled) {\n return (\n <a href={href} className={className} style={style} aria-label={label}>\n {content}\n </a>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className={className}\n style={style}\n aria-label={label}\n >\n {content}\n </button>\n );\n}\n\nfunction EmptyHero({\n accentColor,\n textColor,\n}: {\n accentColor: ColorOptions;\n textColor: ColorOptions;\n}) {\n return (\n <div className={`bg-muted absolute inset-0`}>\n <div\n className=\"absolute inset-0\"\n style={{\n background: `radial-gradient(circle at 30% 20%, ${colorMix(accentColor, 15)}, transparent 60%), radial-gradient(circle at 80% 90%, ${colorMix(accentColor, 10)}, transparent 55%)`,\n }}\n />\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-3\">\n <div\n className={`flex size-14 items-center justify-center rounded-2xl bg-${textColor}/5`}\n style={{ boxShadow: insetBorder(textColor, 10) }}\n >\n <ImageIcon className={`size-6 text-${textColor}/40`} />\n </div>\n <span\n className={`text-[10px] font-bold tracking-[0.2em] uppercase text-${textColor}/45`}\n >\n Nothing selected\n </span>\n </div>\n </div>\n );\n}\n\nexport const quickShareWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickShareWidget\",\n displayName: \"Quick Share Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Content\n {\n key: \"shareableResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select the content to generate a share link for\",\n allowedTypes: [\"Product\", \"Page\", \"EnrollmentPack\", \"Medium\", \"Library\"],\n tab: \"styling\",\n group: \"Content\",\n },\n\n // Title\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Display a title on the hero\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description:\n \"Custom title text (defaults to the resource title if empty)\",\n defaultValue: \"\",\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 title\",\n defaultValue: \"2xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Share panel polish (new)\n {\n key: \"showResourceType\",\n label: \"Show Resource Type Pill\",\n type: \"boolean\",\n description:\n \"Display a small type eyebrow chip (Product · Page · Media…)\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showShareActions\",\n label: \"Show Share Actions\",\n type: \"boolean\",\n description:\n \"Show Email, Text, and native Share buttons under the link chip\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showDomainPrefix\",\n label: \"Show Domain Prefix\",\n type: \"boolean\",\n description:\n \"Include the domain in the link chip (dimmed) with the path emphasized\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showBuyButton\",\n label: \"Show Buy Button\",\n type: \"boolean\",\n description: \"Display the Buy button (only shown for Product resources)\",\n defaultValue: false,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n\n // Design\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for widget content (over the hero)\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description:\n \"Drives the price chip, primary button, and copy-success flash\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add editorial gradient stack for legibility over the hero\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description:\n \"Gradient only (recommended) or gradient + solid wash (heavier)\",\n defaultValue: \"gradient\",\n options: [\n { label: \"Gradient\", value: \"gradient\" },\n { label: \"Solid\", value: \"solid\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 70,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"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 widget content\",\n defaultValue: 6,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget container\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget container\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EAGD,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAY,OAAO;IAAY,EACxC;IAAE,OAAO;IAAS,OAAO;IAAS,CACnC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}
|
|
1
|
+
{"version":3,"file":"QuickShareWidget-CyYW9nS6.mjs","names":["ImageIcon"],"sources":["../../widgets/src/widgets/QuickShareWidget.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useState,\n type ComponentProps,\n type CSSProperties,\n} from \"react\";\nimport type React from \"react\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n ShareableItem,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n borderColorClasses,\n borderWidthClasses,\n getBorderColorField,\n getBorderRadiusField,\n getBorderWidthField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport {\n BookOpen,\n Check,\n CircleDot,\n Copy,\n FileText,\n Image as ImageIcon,\n Mail,\n MessageCircle,\n Package,\n Share2,\n ShoppingCart,\n Ticket,\n type LucideIcon,\n} from \"lucide-react\";\n\ntype QuickShareWidgetProps = ComponentProps<\"div\"> & {\n // Resource\n shareableResource?: ShareableItem;\n\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n\n // Actions\n showBuyButton?: boolean;\n\n // Polish (new, additive)\n showResourceType?: boolean;\n showShareActions?: boolean;\n showDomainPrefix?: boolean;\n};\n\ntype ResourceDescriptor = {\n label: string;\n icon: LucideIcon;\n};\n\ntype QuickShareCSSProperties = CSSProperties &\n Record<`--${string}`, string | number | undefined>;\n\nconst RESOURCE_TYPE_MAP: Record<string, ResourceDescriptor> = {\n Product: { label: \"Product\", icon: Package },\n Page: { label: \"Page\", icon: FileText },\n EnrollmentPack: { label: \"Enrollment\", icon: Ticket },\n Medium: { label: \"Media\", icon: ImageIcon },\n Library: { label: \"Library\", icon: BookOpen },\n};\n\nconst getResourceDescriptor = (\n resource: ShareableItem | undefined,\n): ResourceDescriptor | null => {\n const rawType = (resource?.type || resource?.shareableType || \"\") as string;\n if (!rawType) return null;\n return RESOURCE_TYPE_MAP[rawType] ?? { label: rawType, icon: CircleDot };\n};\n\nconst splitUrl = (url: string): { prefix: string; path: string } => {\n try {\n const parsed = new URL(url);\n return {\n prefix: `${parsed.protocol}//${parsed.host}`,\n path: `${parsed.pathname}${parsed.search}${parsed.hash}`,\n };\n } catch {\n return { prefix: \"\", path: url };\n }\n};\n\nconst CURRENCY_FIELD_KEYS = [\n \"currency\",\n \"currency_code\",\n \"currencyCode\",\n \"currencyIso\",\n \"currency_iso\",\n] as const;\n\nconst getResourceCurrency = (\n resource: ShareableItem | undefined,\n): string | null => {\n if (!resource) return null;\n for (const key of CURRENCY_FIELD_KEYS) {\n const value = resource[key];\n if (typeof value === \"string\" && /^[A-Z]{3}$/i.test(value)) {\n return value.toUpperCase();\n }\n }\n return null;\n};\n\nconst formatNumericPrice = (price: number, resource: ShareableItem): string => {\n const currency = getResourceCurrency(resource);\n if (!currency) return String(price);\n try {\n return price.toLocaleString(undefined, { style: \"currency\", currency });\n } catch {\n return String(price);\n }\n};\n\nconst getDisplayPrice = (\n resource: ShareableItem | undefined,\n): string | null => {\n if (!resource) return null;\n if (typeof resource.display_price === \"string\" && resource.display_price) {\n return resource.display_price;\n }\n if (resource.price != null) {\n return typeof resource.price === \"number\"\n ? formatNumericPrice(resource.price, resource)\n : String(resource.price);\n }\n return null;\n};\n\nconst getColorCssValue = (color: ColorOptions): string =>\n color === \"transparent\" ? \"transparent\" : `var(--color-${color})`;\n\nconst colorMix = (color: ColorOptions, amount: number): string =>\n color === \"transparent\"\n ? \"transparent\"\n : `color-mix(in oklch, ${getColorCssValue(color)} ${amount}%, transparent)`;\n\nconst insetBorder = (color: ColorOptions, amount: number): string =>\n `inset 0 0 0 1px ${colorMix(color, amount)}`;\n\ntype CopyState = \"idle\" | \"copied\";\n\nfunction useTimedCopyState(timeoutMs: number) {\n const [copyState, setCopyState] = useState<CopyState>(\"idle\");\n\n useEffect(() => {\n if (copyState !== \"copied\") return;\n const id = window.setTimeout(() => setCopyState(\"idle\"), timeoutMs);\n return () => window.clearTimeout(id);\n }, [copyState, timeoutMs]);\n\n const markCopied = useCallback(() => {\n setCopyState(\"copied\");\n }, []);\n\n return { copyState, markCopied };\n}\n\nfunction useImageFailureFallback(imageUrl: string) {\n const [imageFailed, setImageFailed] = useState(false);\n\n // Reset the failed-image state when the resource (and thus the image URL)\n // changes — otherwise switching to a new resource keeps showing EmptyHero\n // because the React state outlives the previous load failure.\n useEffect(() => {\n setImageFailed(false);\n }, [imageUrl]);\n\n const handleImageError = useCallback(() => {\n setImageFailed(true);\n }, []);\n\n return { imageFailed, handleImageError };\n}\n\nfunction useShareCapabilities() {\n const [canNativeShare, setCanNativeShare] = useState(false);\n const [canSendSms, setCanSendSms] = useState(false);\n\n useEffect(() => {\n setCanNativeShare(\n typeof navigator !== \"undefined\" && typeof navigator.share === \"function\",\n );\n setCanSendSms(\n typeof navigator !== \"undefined\" &&\n (/Android|iPhone|iPad|iPod/i.test(navigator.userAgent) ||\n (/Macintosh/i.test(navigator.userAgent) &&\n navigator.maxTouchPoints > 1)),\n );\n }, []);\n\n return { canNativeShare, canSendSms };\n}\n\nexport function QuickShareWidget({\n shareableResource,\n\n titleEnabled = true,\n titleText = \"\",\n titleFontSize = \"2xl\",\n titleColor = \"background\",\n\n textColor = \"background\",\n accentColor = \"primary\",\n padding = 6,\n borderRadius = \"xl\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 70,\n\n showBuyButton = false,\n\n showResourceType = true,\n showShareActions = true,\n showDomainPrefix = true,\n\n className,\n style,\n ...props\n}: QuickShareWidgetProps): React.JSX.Element {\n const backgroundImageUrl =\n shareableResource?.image_url || shareableResource?.imageUrl || \"\";\n const { copyState, markCopied } = useTimedCopyState(1600);\n // Hero image fallback: if the resource image 404s or fails to decode, flip\n // to the EmptyHero treatment instead of rendering a broken image.\n const { imageFailed, handleImageError } =\n useImageFailureFallback(backgroundImageUrl);\n\n const showHeroImage = Boolean(backgroundImageUrl) && !imageFailed;\n const shareLink = shareableResource?.share_link || \"\";\n const hasShareLink = !!shareLink;\n\n const displayTitle =\n titleText || shareableResource?.title || \"Select content to share\";\n const resourceDescriptor = getResourceDescriptor(shareableResource);\n const displayPrice = getDisplayPrice(shareableResource);\n\n const isProduct =\n shareableResource?.type === \"Product\" ||\n shareableResource?.shareableType === \"Product\";\n const shouldShowBuyButton = showBuyButton && isProduct;\n\n const parsedOverlayIntensity = Number(\n String(overlayIntensity).replace(\"%\", \"\"),\n );\n const overlayOpacity =\n (Number.isFinite(parsedOverlayIntensity)\n ? Math.min(100, Math.max(0, parsedOverlayIntensity))\n : 70) / 100;\n\n const editorialGradient: CSSProperties | undefined =\n overlayEnabled && showHeroImage\n ? {\n background: `linear-gradient(to top, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 100)}%, transparent), color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 55)}%, transparent) 45%, transparent 85%)`,\n }\n : undefined;\n\n const handleCopy = async () => {\n if (!hasShareLink) return;\n try {\n await navigator.clipboard.writeText(shareLink);\n markCopied();\n } catch (error) {\n console.error(\"Failed to copy to clipboard:\", error);\n }\n };\n\n const handleNativeShare = async () => {\n if (!hasShareLink) return;\n if (typeof navigator.share === \"function\") {\n try {\n await navigator.share({\n title: displayTitle,\n url: shareLink,\n });\n } catch {\n // Ignore abort\n }\n } else {\n await handleCopy();\n }\n };\n\n const { prefix, path } = hasShareLink\n ? splitUrl(shareLink)\n : { prefix: \"\", path: \"\" };\n\n return (\n <div\n className={`relative isolate overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-muted text-${textColor} ${className ?? \"\"}`}\n style={{\n // Themed dual-shadow (crisp + soft ambient), derived from the\n // foreground token so the lift reads in both light and dark.\n boxShadow: `0 1px 2px color-mix(in oklch, var(--color-foreground) 4%, transparent), 0 20px 40px -20px color-mix(in oklch, var(--color-foreground) 25%, transparent)`,\n ...style,\n }}\n {...props}\n >\n {/* Hero image or empty-state surface */}\n {showHeroImage ? (\n <div className=\"absolute inset-0\">\n <img\n src={backgroundImageUrl}\n alt=\"\"\n loading=\"lazy\"\n onError={handleImageError}\n className=\"h-full w-full object-cover\"\n />\n {overlayEnabled && (\n <>\n {/* Layer 1 — main bottom-to-top legibility gradient */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={editorialGradient}\n />\n {/* Layer 2 — diagonal bottom-left anchor (image reads top-right, content reads bottom-left) */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={{\n background: `linear-gradient(to top right, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 65)}%, transparent), color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 25)}%, transparent) 35%, transparent 65%)`,\n }}\n />\n {/* Layer 3 — radial pool anchoring the bottom-left share panel */}\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={{\n background: `radial-gradient(ellipse 70% 55% at 15% 100%, color-mix(in oklch, var(--color-foreground) ${Math.round(overlayOpacity * 45)}%, transparent), transparent 70%)`,\n }}\n />\n {overlayType === \"solid\" && (\n <div\n className=\"bg-foreground pointer-events-none absolute inset-0\"\n style={{ opacity: overlayOpacity * 0.35 }}\n />\n )}\n </>\n )}\n </div>\n ) : (\n <EmptyHero accentColor={accentColor} textColor={textColor} />\n )}\n\n {/* Content */}\n <div className={`relative flex min-h-[440px] flex-col p-${padding}`}>\n {/* Top row: resource type eyebrow + optional price chip */}\n {(showResourceType && resourceDescriptor) || displayPrice ? (\n <div className=\"flex items-start justify-between gap-3\">\n {showResourceType && resourceDescriptor ? (\n (() => {\n const { icon: ResourceIcon, label } = resourceDescriptor;\n return (\n <span\n className={`inline-flex items-center gap-1.5 rounded-${borderRadius} bg-${textColor}/15 px-2.5 py-1 text-[10px] font-bold tracking-[0.18em] uppercase text-${textColor} backdrop-blur-sm`}\n style={{\n boxShadow: insetBorder(textColor, 15),\n }}\n >\n <ResourceIcon className=\"size-3\" />\n {label}\n </span>\n );\n })()\n ) : (\n <span />\n )}\n {displayPrice && (\n <span\n className={`inline-flex items-center rounded-${borderRadius} bg-${accentColor} px-2.5 py-1 text-[11px] font-bold tabular-nums text-${accentColor}-foreground`}\n style={{\n boxShadow: `0 4px 14px -4px color-mix(in oklch, var(--color-foreground) 30%, transparent)`,\n }}\n >\n {displayPrice}\n </span>\n )}\n </div>\n ) : null}\n\n {/* Middle: spacer that keeps share panel bottom-anchored.\n Optional title renders inside it without changing layout rhythm. */}\n <div className=\"mt-4 flex flex-1 flex-col justify-end\">\n {titleEnabled && displayTitle && (\n <h2\n className={`text-${titleFontSize} font-header leading-[1.12] font-bold tracking-[-0.015em] text-${titleColor}`}\n style={{\n // Themed via foreground so the legibility shadow flips with\n // the title color when the theme switches to dark mode.\n textShadow: showHeroImage\n ? `0 2px 12px color-mix(in oklch, var(--color-foreground) 40%, transparent)`\n : undefined,\n }}\n >\n {displayTitle}\n </h2>\n )}\n </div>\n\n {/* Bottom: share panel */}\n <div className=\"mt-6 flex flex-col gap-3\">\n <div className=\"flex items-stretch gap-3\">\n {/* QR card */}\n <div\n className={`group relative shrink-0 rounded-${borderRadius} bg-white p-2.5 transition-transform duration-300 hover:scale-[1.02]`}\n style={{\n // QR card stays white for scanner contrast; lift shadow is\n // themed via foreground so it reads in dark mode too.\n boxShadow: `0 4px 16px -4px color-mix(in oklch, var(--color-foreground) 25%, transparent), inset 0 0 0 1px rgba(255,255,255,0.4)`,\n }}\n aria-label=\"QR code for share link\"\n >\n <QRCodeSVG\n value={shareLink || \"https://example.com\"}\n size={96}\n level=\"H\"\n bgColor=\"#ffffff\"\n fgColor=\"#0f172a\"\n />\n </div>\n\n {/* URL chip + share actions rail */}\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <span\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${textColor}/70`}\n >\n Share link\n </span>\n <button\n type=\"button\"\n onClick={handleCopy}\n disabled={!hasShareLink}\n aria-label={\n copyState === \"copied\" ? \"Copied to clipboard\" : \"Copy link\"\n }\n className={`group flex items-center justify-between gap-2 rounded-${borderRadius} bg-${textColor}/10 px-3 py-2 text-left text-[12px] backdrop-blur-sm transition-all duration-300 hover:bg-${textColor}/15 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--quick-share-focus-ring)] disabled:opacity-50 ${copyState === \"copied\" ? `bg-${accentColor}/20` : \"\"}`}\n style={\n {\n \"--quick-share-focus-ring\": colorMix(accentColor, 40),\n boxShadow: insetBorder(textColor, 15),\n } as QuickShareCSSProperties\n }\n >\n <span\n className={`min-w-0 flex-1 truncate font-medium tabular-nums text-${textColor}`}\n >\n {hasShareLink ? (\n <>\n {showDomainPrefix && prefix && (\n <span className={`opacity-60`}>{prefix}</span>\n )}\n <span className=\"font-semibold\">{path}</span>\n </>\n ) : (\n <span className={`opacity-60`}>No link yet</span>\n )}\n </span>\n <span\n className={`flex size-7 shrink-0 items-center justify-center rounded-full transition-all duration-300 ${copyState === \"copied\" ? `bg-${accentColor} text-${accentColor}-foreground scale-110` : `bg-${textColor}/15 text-${textColor}`}`}\n >\n {copyState === \"copied\" ? (\n <Check className=\"size-3.5\" />\n ) : (\n <Copy className=\"size-3.5\" />\n )}\n </span>\n </button>\n <span className=\"sr-only\" aria-live=\"polite\" role=\"status\">\n {copyState === \"copied\" ? \"Copied to clipboard\" : \"\"}\n </span>\n\n {showShareActions && (\n <ShareActionRow\n shareLink={shareLink}\n displayTitle={displayTitle}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n onNative={handleNativeShare}\n />\n )}\n </div>\n </div>\n\n {shouldShowBuyButton &&\n (hasShareLink ? (\n <a\n href={shareLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`flex w-full items-center justify-center gap-2 rounded-${borderRadius} bg-${accentColor} px-4 py-3 text-[13px] font-bold text-${accentColor}-foreground transition-transform hover:scale-[1.01]`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n <ShoppingCart className=\"size-4\" />\n <span>Buy now</span>\n </a>\n ) : (\n <button\n type=\"button\"\n disabled\n className={`flex w-full cursor-not-allowed items-center justify-center gap-2 rounded-${borderRadius} bg-${accentColor} px-4 py-3 text-[13px] font-bold text-${accentColor}-foreground opacity-50`}\n style={{\n boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n }}\n >\n <ShoppingCart className=\"size-4\" />\n <span>Buy now</span>\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n}\n\ntype ShareActionRowProps = {\n shareLink: string;\n displayTitle: string;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n onNative: () => void;\n};\n\nfunction ShareActionRow({\n shareLink,\n displayTitle,\n accentColor,\n textColor,\n borderRadius,\n onNative,\n}: ShareActionRowProps) {\n const disabled = !shareLink;\n const { canNativeShare, canSendSms } = useShareCapabilities();\n\n const emailHref = shareLink\n ? `mailto:?subject=${encodeURIComponent(displayTitle)}&body=${encodeURIComponent(shareLink)}`\n : undefined;\n const smsHref = shareLink\n ? `sms:?body=${encodeURIComponent(`${displayTitle} — ${shareLink}`)}`\n : undefined;\n\n return (\n <div className=\"flex items-center gap-1.5\">\n <ShareActionButton\n icon={Mail}\n label=\"Email\"\n href={emailHref}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n {canSendSms && (\n <ShareActionButton\n icon={MessageCircle}\n label=\"Text\"\n href={smsHref}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n )}\n {canNativeShare && (\n <ShareActionButton\n icon={Share2}\n label=\"Share\"\n onClick={onNative}\n disabled={disabled}\n accentColor={accentColor}\n textColor={textColor}\n borderRadius={borderRadius}\n />\n )}\n </div>\n );\n}\n\ntype ShareActionButtonProps = {\n icon: LucideIcon;\n label: string;\n href?: string | undefined;\n onClick?: () => void;\n disabled: boolean;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n borderRadius: BorderRadiusOptions;\n};\n\nfunction ShareActionButton({\n icon: Icon,\n label,\n href,\n onClick,\n disabled,\n accentColor,\n textColor,\n borderRadius,\n}: ShareActionButtonProps) {\n const className = `group inline-flex items-center gap-1.5 rounded-${borderRadius} bg-${textColor}/10 px-2.5 py-1.5 text-[11px] font-semibold text-${textColor} backdrop-blur-sm transition-all duration-200 hover:-translate-y-0.5 hover:bg-${accentColor} hover:text-${accentColor}-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--quick-share-focus-ring)] disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:translate-y-0`;\n const style: QuickShareCSSProperties = {\n \"--quick-share-focus-ring\": colorMix(accentColor, 40),\n boxShadow: insetBorder(textColor, 15),\n };\n\n const content = (\n <>\n <Icon className=\"size-3\" />\n <span>{label}</span>\n </>\n );\n\n if (href && !disabled) {\n return (\n <a href={href} className={className} style={style} aria-label={label}>\n {content}\n </a>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className={className}\n style={style}\n aria-label={label}\n >\n {content}\n </button>\n );\n}\n\nfunction EmptyHero({\n accentColor,\n textColor,\n}: {\n accentColor: ColorOptions;\n textColor: ColorOptions;\n}) {\n return (\n <div className={`bg-muted absolute inset-0`}>\n <div\n className=\"absolute inset-0\"\n style={{\n background: `radial-gradient(circle at 30% 20%, ${colorMix(accentColor, 15)}, transparent 60%), radial-gradient(circle at 80% 90%, ${colorMix(accentColor, 10)}, transparent 55%)`,\n }}\n />\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-3\">\n <div\n className={`flex size-14 items-center justify-center rounded-2xl bg-${textColor}/5`}\n style={{ boxShadow: insetBorder(textColor, 10) }}\n >\n <ImageIcon className={`size-6 text-${textColor}/40`} />\n </div>\n <span\n className={`text-[10px] font-bold tracking-[0.2em] uppercase text-${textColor}/45`}\n >\n Nothing selected\n </span>\n </div>\n </div>\n );\n}\n\nexport const quickShareWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"QuickShareWidget\",\n displayName: \"Quick Share Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Content\n {\n key: \"shareableResource\",\n label: \"Shareable Content\",\n type: \"resource\",\n description: \"Select the content to generate a share link for\",\n allowedTypes: [\"Product\", \"Page\", \"EnrollmentPack\", \"Medium\", \"Library\"],\n tab: \"styling\",\n group: \"Content\",\n },\n\n // Title\n {\n key: \"titleEnabled\",\n label: \"Show Title\",\n type: \"boolean\",\n description: \"Display a title on the hero\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description:\n \"Custom title text (defaults to the resource title if empty)\",\n defaultValue: \"\",\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 title\",\n defaultValue: \"2xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Share panel polish (new)\n {\n key: \"showResourceType\",\n label: \"Show Resource Type Pill\",\n type: \"boolean\",\n description:\n \"Display a small type eyebrow chip (Product · Page · Media…)\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showShareActions\",\n label: \"Show Share Actions\",\n type: \"boolean\",\n description:\n \"Show Email, Text, and native Share buttons under the link chip\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showDomainPrefix\",\n label: \"Show Domain Prefix\",\n type: \"boolean\",\n description:\n \"Include the domain in the link chip (dimmed) with the path emphasized\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n {\n key: \"showBuyButton\",\n label: \"Show Buy Button\",\n type: \"boolean\",\n description: \"Display the Buy button (only shown for Product resources)\",\n defaultValue: false,\n tab: \"styling\",\n group: \"Share Panel\",\n },\n\n // Design\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for widget content (over the hero)\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description:\n \"Drives the price chip, primary button, and copy-success flash\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description: \"Add editorial gradient stack for legibility over the hero\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description:\n \"Gradient only (recommended) or gradient + solid wash (heavier)\",\n defaultValue: \"gradient\",\n options: [\n { label: \"Gradient\", value: \"gradient\" },\n { label: \"Solid\", value: \"solid\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 70,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"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 widget content\",\n defaultValue: 6,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget container\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget container\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EAGD,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAY,OAAO;IAAY,EACxC;IAAE,OAAO;IAAS,OAAO;IAAS,CACnC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}
|