@fluid-app/portal-sdk 0.1.207 → 0.1.208
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-Nx31UmWK.cjs → AlertWidget-Bli5ni5t.cjs} +2 -2
- package/dist/{AlertWidget-Nx31UmWK.cjs.map → AlertWidget-Bli5ni5t.cjs.map} +1 -1
- package/dist/{AlertWidget-D1kyQEgu.mjs → AlertWidget-C0wnu4-c.mjs} +2 -2
- package/dist/{AlertWidget-D1kyQEgu.mjs.map → AlertWidget-C0wnu4-c.mjs.map} +1 -1
- package/dist/{BulletListWidget-CouwHMJt.cjs → BulletListWidget-BHkly6-D.cjs} +2 -2
- package/dist/{BulletListWidget-CouwHMJt.cjs.map → BulletListWidget-BHkly6-D.cjs.map} +1 -1
- package/dist/{BulletListWidget-CHWI28yY.mjs → BulletListWidget-DRxFyFKI.mjs} +2 -2
- package/dist/{BulletListWidget-CHWI28yY.mjs.map → BulletListWidget-DRxFyFKI.mjs.map} +1 -1
- package/dist/{CalendarWidget-BtKzQFeO.cjs → CalendarWidget-BcZNsVQo.cjs} +2 -2
- package/dist/{CalendarWidget-BtKzQFeO.cjs.map → CalendarWidget-BcZNsVQo.cjs.map} +1 -1
- package/dist/{CalendarWidget-CZUo7mPL.mjs → CalendarWidget-kZBErtwM.mjs} +2 -2
- package/dist/{CalendarWidget-CZUo7mPL.mjs.map → CalendarWidget-kZBErtwM.mjs.map} +1 -1
- package/dist/{CardWidget-DVi0NVhb.cjs → CardWidget-BAl-3dJF.cjs} +2 -2
- package/dist/{CardWidget-DVi0NVhb.cjs.map → CardWidget-BAl-3dJF.cjs.map} +1 -1
- package/dist/{CardWidget-BVYjwdua.cjs → CardWidget-CFtUC9RB.cjs} +2 -2
- package/dist/{CardWidget-Cx5_Z-lR.mjs → CardWidget-gcPNwuZk.mjs} +2 -2
- package/dist/{CardWidget-Cx5_Z-lR.mjs.map → CardWidget-gcPNwuZk.mjs.map} +1 -1
- package/dist/{CarouselWidget-DLqTBIrf.cjs → CarouselWidget-BWpRWnUV.cjs} +2 -2
- package/dist/{CarouselWidget-DLqTBIrf.cjs.map → CarouselWidget-BWpRWnUV.cjs.map} +1 -1
- package/dist/{CarouselWidget-BENYmIwu.cjs → CarouselWidget-CrQFcQdL.cjs} +2 -2
- package/dist/{CarouselWidget-D1yzBwlG.mjs → CarouselWidget-DPFJhHro.mjs} +2 -2
- package/dist/{CarouselWidget-D1yzBwlG.mjs.map → CarouselWidget-DPFJhHro.mjs.map} +1 -1
- package/dist/{CatchUpWidget-J2SPvIqy.mjs → CatchUpWidget-DGucqTrd.mjs} +2 -2
- package/dist/{CatchUpWidget-J2SPvIqy.mjs.map → CatchUpWidget-DGucqTrd.mjs.map} +1 -1
- package/dist/{CatchUpWidget-BmibiEkX.cjs → CatchUpWidget-sUlMDu2k.cjs} +2 -2
- package/dist/{CatchUpWidget-BmibiEkX.cjs.map → CatchUpWidget-sUlMDu2k.cjs.map} +1 -1
- package/dist/{ChartWidget-B0vgP7df.cjs → ChartWidget-C2fmc4-R.cjs} +2 -2
- package/dist/{ChartWidget-B0vgP7df.cjs.map → ChartWidget-C2fmc4-R.cjs.map} +1 -1
- package/dist/{ChartWidget-C5DS5HRm.mjs → ChartWidget-C9jaZaxZ.mjs} +2 -2
- package/dist/{ChartWidget-C5DS5HRm.mjs.map → ChartWidget-C9jaZaxZ.mjs.map} +1 -1
- package/dist/{ChartWidget-DzgRlcNX.cjs → ChartWidget-DOmPdTxL.cjs} +2 -2
- package/dist/{ContactsScreen-BXWnpPXj.cjs → ContactsScreen-BozwvGrb.cjs} +65 -7
- package/dist/{ContactsScreen-BXWnpPXj.cjs.map → ContactsScreen-BozwvGrb.cjs.map} +1 -1
- package/dist/{ContactsScreen-DSnGEWTK.cjs → ContactsScreen-By3ap4Bv.cjs} +1 -1
- package/dist/{ContactsScreen-C25kLBcG.mjs → ContactsScreen-CCsst8bb.mjs} +67 -9
- package/dist/ContactsScreen-CCsst8bb.mjs.map +1 -0
- package/dist/{ContainerWidget-jI3cpmAu.mjs → ContainerWidget-6XsVE_8u.mjs} +3 -3
- package/dist/{ContainerWidget-jI3cpmAu.mjs.map → ContainerWidget-6XsVE_8u.mjs.map} +1 -1
- package/dist/{ContainerWidget-gtjlMITv.cjs → ContainerWidget-CWVH8szT.cjs} +3 -3
- package/dist/{ContainerWidget-DNo8CkQ7.cjs → ContainerWidget-DWp7gOZM.cjs} +3 -3
- package/dist/{ContainerWidget-DNo8CkQ7.cjs.map → ContainerWidget-DWp7gOZM.cjs.map} +1 -1
- package/dist/{EmbedWidget-BSfycJxm.mjs → EmbedWidget-Buij0edW.mjs} +2 -2
- package/dist/{EmbedWidget-BSfycJxm.mjs.map → EmbedWidget-Buij0edW.mjs.map} +1 -1
- package/dist/{EmbedWidget-CLArhSmx.cjs → EmbedWidget-PIWoA9sU.cjs} +2 -2
- package/dist/{EmbedWidget-CLArhSmx.cjs.map → EmbedWidget-PIWoA9sU.cjs.map} +1 -1
- package/dist/{FluidProvider-5TV1VHtq.mjs → FluidProvider-0Mba_MWW.mjs} +47 -47
- package/dist/{FluidProvider-5TV1VHtq.mjs.map → FluidProvider-0Mba_MWW.mjs.map} +1 -1
- package/dist/{FluidProvider-DP-sbNiR.cjs → FluidProvider-Df88VSWk.cjs} +47 -47
- package/dist/{FluidProvider-DP-sbNiR.cjs.map → FluidProvider-Df88VSWk.cjs.map} +1 -1
- package/dist/{ImageWidget-B7ui4-KU.cjs → ImageWidget-DbV--wn4.cjs} +2 -2
- package/dist/{ImageWidget-B7ui4-KU.cjs.map → ImageWidget-DbV--wn4.cjs.map} +1 -1
- package/dist/{ImageWidget-DAoPOp3e.mjs → ImageWidget-DuqgiO55.mjs} +2 -2
- package/dist/{ImageWidget-DAoPOp3e.mjs.map → ImageWidget-DuqgiO55.mjs.map} +1 -1
- package/dist/{LayoutWidget-DHlXzqUk.cjs → LayoutWidget-BbABNLAR.cjs} +2 -2
- package/dist/{LayoutWidget-DHlXzqUk.cjs.map → LayoutWidget-BbABNLAR.cjs.map} +1 -1
- package/dist/{LayoutWidget-CQYR0aDO.mjs → LayoutWidget-CQeqonHh.mjs} +2 -2
- package/dist/{LayoutWidget-CQYR0aDO.mjs.map → LayoutWidget-CQeqonHh.mjs.map} +1 -1
- package/dist/{LayoutWidget-D5gh0ejr.cjs → LayoutWidget-DFMSbGrN.cjs} +2 -2
- package/dist/{LinkWidget-DfVu-3zf.cjs → LinkWidget-Cn_4oI1U.cjs} +2 -2
- package/dist/{LinkWidget-BfvepYU9.cjs → LinkWidget-DMdMfamp.cjs} +5 -2
- package/dist/{LinkWidget-BfvepYU9.cjs.map → LinkWidget-DMdMfamp.cjs.map} +1 -1
- package/dist/{LinkWidget-BNHPtYLx.mjs → LinkWidget-muhFoV50.mjs} +5 -2
- package/dist/{LinkWidget-BNHPtYLx.mjs.map → LinkWidget-muhFoV50.mjs.map} +1 -1
- package/dist/{ListWidget-Da-YzDAs.cjs → ListWidget-B5jPU4m1.cjs} +2 -2
- package/dist/{ListWidget-Da-YzDAs.cjs.map → ListWidget-B5jPU4m1.cjs.map} +1 -1
- package/dist/{ListWidget-BAf2Vfsx.cjs → ListWidget-C_FkCsCJ.cjs} +2 -2
- package/dist/{ListWidget-cJKGHqJD.mjs → ListWidget-DvZQjspc.mjs} +2 -2
- package/dist/{ListWidget-cJKGHqJD.mjs.map → ListWidget-DvZQjspc.mjs.map} +1 -1
- package/dist/{MessagingScreen-D2G4zfez.cjs → MessagingScreen-BE9FZr7f.cjs} +2 -2
- package/dist/{MessagingScreen-D2G4zfez.cjs.map → MessagingScreen-BE9FZr7f.cjs.map} +1 -1
- package/dist/{MessagingScreen-BSksI6Nw.mjs → MessagingScreen-BKgNsHdQ.mjs} +2 -2
- package/dist/{MessagingScreen-BSksI6Nw.mjs.map → MessagingScreen-BKgNsHdQ.mjs.map} +1 -1
- package/dist/MessagingScreen-BrHK0nrA.cjs +45 -0
- package/dist/{MySiteScreen-DERelKhT.cjs → MySiteScreen-BPwzK-ks.cjs} +1 -1
- package/dist/{MySiteScreen-DUta9jeJ.mjs → MySiteScreen-Dz5htti5.mjs} +23 -3
- package/dist/MySiteScreen-Dz5htti5.mjs.map +1 -0
- package/dist/{MySiteScreen-WFFhf8WZ.cjs → MySiteScreen-aaL_vggP.cjs} +23 -3
- package/dist/MySiteScreen-aaL_vggP.cjs.map +1 -0
- package/dist/{MySiteWidget-ISV__1ng.cjs → MySiteWidget-C1OYAsZw.cjs} +2 -2
- package/dist/{MySiteWidget-ISV__1ng.cjs.map → MySiteWidget-C1OYAsZw.cjs.map} +1 -1
- package/dist/{MySiteWidget-D_XsC3n0.mjs → MySiteWidget-C6IZytLt.mjs} +2 -2
- package/dist/{MySiteWidget-D_XsC3n0.mjs.map → MySiteWidget-C6IZytLt.mjs.map} +1 -1
- package/dist/{NestedWidget-Bgrfl1S7.cjs → NestedWidget-B8ORvmp2.cjs} +2 -2
- package/dist/{NestedWidget-BBOHOg12.cjs → NestedWidget-BSNtbipH.cjs} +2 -2
- package/dist/{NestedWidget-BBOHOg12.cjs.map → NestedWidget-BSNtbipH.cjs.map} +1 -1
- package/dist/{NestedWidget-CGdxVlhr.mjs → NestedWidget-J9sJbt9s.mjs} +2 -2
- package/dist/{NestedWidget-CGdxVlhr.mjs.map → NestedWidget-J9sJbt9s.mjs.map} +1 -1
- package/dist/{PointsWidget-h0jqVXWf.cjs → PointsWidget-Bw08kgNE.cjs} +2 -2
- package/dist/{PointsWidget-h0jqVXWf.cjs.map → PointsWidget-Bw08kgNE.cjs.map} +1 -1
- package/dist/{PointsWidget-D8g-asFn.mjs → PointsWidget-CoDqvWC5.mjs} +2 -2
- package/dist/{PointsWidget-D8g-asFn.mjs.map → PointsWidget-CoDqvWC5.mjs.map} +1 -1
- package/dist/{PortalContentApiProvider-CAa1jYwz.mjs → PortalContentApiProvider-B-miOfQl.mjs} +7 -10
- package/dist/{PortalContentApiProvider-CAa1jYwz.mjs.map → PortalContentApiProvider-B-miOfQl.mjs.map} +1 -1
- package/dist/{PortalContentApiProvider-C5WzWC3k.cjs → PortalContentApiProvider-Cec9tth6.cjs} +7 -10
- package/dist/{PortalContentApiProvider-C5WzWC3k.cjs.map → PortalContentApiProvider-Cec9tth6.cjs.map} +1 -1
- package/dist/{ProductsScreen-BZG_hkqN.cjs → ProductsScreen-62Tzsdap.cjs} +2 -2
- package/dist/{ProductsScreen-BZG_hkqN.cjs.map → ProductsScreen-62Tzsdap.cjs.map} +1 -1
- package/dist/{ProductsScreen-DNXJ6Pml.mjs → ProductsScreen-CRSHQoVn.mjs} +2 -2
- package/dist/{ProductsScreen-DNXJ6Pml.mjs.map → ProductsScreen-CRSHQoVn.mjs.map} +1 -1
- package/dist/{ProductsScreen-dbTX6T_M.mjs → ProductsScreen-CRV1_NVf.mjs} +2 -2
- package/dist/{ProductsScreen-DfKQAJ8t.cjs → ProductsScreen-D1pyistU.cjs} +2 -2
- package/dist/ProfileScreen-DYHRKKVI.cjs +44 -0
- package/dist/{ProfileScreen-Xym_39QW.cjs → ProfileScreen-DtNJ1sdF.cjs} +2 -2
- package/dist/{ProfileScreen-Xym_39QW.cjs.map → ProfileScreen-DtNJ1sdF.cjs.map} +1 -1
- package/dist/{ProfileScreen-Mb6dPLPo.mjs → ProfileScreen-WC3LIwDh.mjs} +2 -2
- package/dist/{ProfileScreen-Mb6dPLPo.mjs.map → ProfileScreen-WC3LIwDh.mjs.map} +1 -1
- package/dist/{QuickShareWidget-C_p3tPs5.cjs → QuickShareWidget-DRbErOlt.cjs} +2 -2
- package/dist/{QuickShareWidget-C_p3tPs5.cjs.map → QuickShareWidget-DRbErOlt.cjs.map} +1 -1
- package/dist/{QuickShareWidget-rft-kn8a.mjs → QuickShareWidget-Dbjueevf.mjs} +2 -2
- package/dist/{QuickShareWidget-rft-kn8a.mjs.map → QuickShareWidget-Dbjueevf.mjs.map} +1 -1
- package/dist/{RecentActivityWidget-Ql-mGLEf.cjs → RecentActivityWidget-CWr6bFgP.cjs} +2 -2
- package/dist/{RecentActivityWidget-Ql-mGLEf.cjs.map → RecentActivityWidget-CWr6bFgP.cjs.map} +1 -1
- package/dist/{RecentActivityWidget-DxlhERm0.mjs → RecentActivityWidget-D-uJcFkE.mjs} +2 -2
- package/dist/{RecentActivityWidget-DxlhERm0.mjs.map → RecentActivityWidget-D-uJcFkE.mjs.map} +1 -1
- package/dist/{SeparatorWidget-_37ala5k.cjs → SeparatorWidget-CjVHbHzQ.cjs} +4 -2
- package/dist/{SeparatorWidget-_37ala5k.cjs.map → SeparatorWidget-CjVHbHzQ.cjs.map} +1 -1
- package/dist/{SeparatorWidget-C5kp4gzo.mjs → SeparatorWidget-Clm35u4g.mjs} +4 -2
- package/dist/{SeparatorWidget-C5kp4gzo.mjs.map → SeparatorWidget-Clm35u4g.mjs.map} +1 -1
- package/dist/{ShareablesScreen-Be0YXQ2y.mjs → ShareablesScreen-BZK_lSdi.mjs} +2 -2
- package/dist/{ShareablesScreen-Be0YXQ2y.mjs.map → ShareablesScreen-BZK_lSdi.mjs.map} +1 -1
- package/dist/{ShareablesScreen-vk_JZ-_9.cjs → ShareablesScreen-BlX1v88I.cjs} +2 -2
- package/dist/{ShareablesScreen-vk_JZ-_9.cjs.map → ShareablesScreen-BlX1v88I.cjs.map} +1 -1
- package/dist/{ShareablesScreen-CpFuhYs5.mjs → ShareablesScreen-Ce7kJAPw.mjs} +2 -2
- package/dist/{ShareablesScreen-B-q3ovAv.cjs → ShareablesScreen-DELGijpZ.cjs} +2 -2
- package/dist/{ShopScreen-BOd8LD3L.mjs → ShopScreen-BfexFHUc.mjs} +2 -2
- package/dist/{ShopScreen-BOd8LD3L.mjs.map → ShopScreen-BfexFHUc.mjs.map} +1 -1
- package/dist/{ShopScreen-B92DRQkQ.cjs → ShopScreen-Bo9YZ_EO.cjs} +2 -2
- package/dist/{ShopScreen-B92DRQkQ.cjs.map → ShopScreen-Bo9YZ_EO.cjs.map} +1 -1
- package/dist/ShopScreen-MZm20clN.cjs +46 -0
- package/dist/{TableWidget-C7qiWZc3.cjs → TableWidget-BA99kJpe.cjs} +2 -2
- package/dist/{TableWidget-DUnz9hrD.cjs → TableWidget-DCWm-ENc.cjs} +2 -2
- package/dist/{TableWidget-DUnz9hrD.cjs.map → TableWidget-DCWm-ENc.cjs.map} +1 -1
- package/dist/{TableWidget-BVufe18A.mjs → TableWidget-DVfzScu1.mjs} +2 -2
- package/dist/{TableWidget-BVufe18A.mjs.map → TableWidget-DVfzScu1.mjs.map} +1 -1
- package/dist/{TextWidget-WKDCwape.mjs → TextWidget-BsDMvSQy.mjs} +8 -2
- package/dist/TextWidget-BsDMvSQy.mjs.map +1 -0
- package/dist/{TextWidget--UgOcUQx.cjs → TextWidget-D9H9WUPH.cjs} +8 -2
- package/dist/TextWidget-D9H9WUPH.cjs.map +1 -0
- package/dist/{ToDoWidget-CG0s98ed.mjs → ToDoWidget-DvNBsmgz.mjs} +2 -2
- package/dist/{ToDoWidget-CG0s98ed.mjs.map → ToDoWidget-DvNBsmgz.mjs.map} +1 -1
- package/dist/{ToDoWidget-B2qEGt7v.cjs → ToDoWidget-x86UGKLQ.cjs} +2 -2
- package/dist/{ToDoWidget-B2qEGt7v.cjs.map → ToDoWidget-x86UGKLQ.cjs.map} +1 -1
- package/dist/{VideoWidget-CHuSla09.mjs → VideoWidget-BpKJv_pg.mjs} +2 -2
- package/dist/{VideoWidget-CHuSla09.mjs.map → VideoWidget-BpKJv_pg.mjs.map} +1 -1
- package/dist/{VideoWidget-sEVQcp9o.cjs → VideoWidget-CvDmuMnA.cjs} +2 -2
- package/dist/{VideoWidget-sEVQcp9o.cjs.map → VideoWidget-CvDmuMnA.cjs.map} +1 -1
- package/dist/index.cjs +47 -47
- package/dist/index.d.cts +10 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +10 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +47 -47
- package/dist/{registries-GJMHub-Q.cjs → registries-CpUM406S.cjs} +9 -1
- package/dist/registries-CpUM406S.cjs.map +1 -0
- package/dist/{registries-CyjQkRM-.mjs → registries-DT36l-bR.mjs} +9 -1
- package/dist/registries-DT36l-bR.mjs.map +1 -0
- package/package.json +6 -6
- package/dist/ContactsScreen-C25kLBcG.mjs.map +0 -1
- package/dist/MessagingScreen-CXAzx8Ra.cjs +0 -45
- package/dist/MySiteScreen-DUta9jeJ.mjs.map +0 -1
- package/dist/MySiteScreen-WFFhf8WZ.cjs.map +0 -1
- package/dist/ProfileScreen-CBwwNrKI.cjs +0 -44
- package/dist/ShopScreen-BRN3JY4l.cjs +0 -46
- package/dist/TextWidget--UgOcUQx.cjs.map +0 -1
- package/dist/TextWidget-WKDCwape.mjs.map +0 -1
- package/dist/registries-CyjQkRM-.mjs.map +0 -1
- package/dist/registries-GJMHub-Q.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MySiteScreen-WFFhf8WZ.cjs","names":["Card","CardHeader","CardTitle","CardContent","Eye","Separator","Users","Card","CardHeader","CardTitle","CardAction","Button","CardContent","Copy","Card","CardHeader","Button","CardContent","LoaderCircle","Button","ArrowLeft","Card","CardContent","cn","Palette","Check","z","z","buttonSchema","z","z","CSS","GripVertical","Button","Pencil","Trash2","usePortalLinks","usePortalCreateLink","usePortalUpdateLink","usePortalDeleteLink","usePortalReorderLinks","useZodForm","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","ArrowLeft","Plus","Skeleton","Card","DndContext","closestCenter","SortableContext","verticalListSortingStrategy","Dialog","DialogContent","DialogHeader","DialogTitle","Label","Input","DialogFooter","CSS","GripVertical","Button","Trash2","usePortalFavorites","usePortalDeleteFavorite","usePortalReorderFavorites","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","ArrowLeft","Skeleton","Card","DndContext","closestCenter","SortableContext","verticalListSortingStrategy","Dialog","DialogContent","DialogHeader","DialogTitle","DialogFooter","usePortalMySiteProfile","usePortalUpdateProfile","ArrowLeft","Card","Button","Camera","CardContent","Label","Input","Textarea","User","Palette","LayoutGrid","Link2","usePortalMySiteProfile","usePortalMySiteThemes","usePortalUpdateSettings","ChevronRight","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","BreadcrumbPage","BreadcrumbSeparator"],"sources":["../../../mysite/ui/src/portal/components/animation-utils.ts","../../../mysite/ui/src/portal/components/VisitorDetailsCard.tsx","../../../mysite/ui/src/portal/components/MySiteLinkCard.tsx","../../../mysite/ui/src/portal/components/PhonePreview.tsx","../../../mysite/ui/src/portal/components/ThemeEditor.tsx","../../../mysite/ui/src/shared/schemas/mysite.schema.ts","../../../mysite/ui/src/shared/schemas/mysite-theme.schema.ts","../../../mysite/ui/src/shared/utils.ts","../../../mysite/ui/src/portal/components/ButtonsEditor.tsx","../../../mysite/ui/src/portal/components/PortalButtonsEditor.tsx","../../../mysite/ui/src/portal/components/PortalFavoritesEditor.tsx","../../../mysite/ui/src/portal/components/MySiteProfileForm.tsx","../src/screens/MySiteScreen/MySiteMainView.tsx","../src/screens/MySiteScreen/use-mysite-editing-section.ts","../src/screens/MySiteScreen/index.tsx"],"sourcesContent":["import type { AnimPhase } from \"./types\";\n\n// Tailwind className helpers for the MySite main → editor slide/fade.\n//\n// The slide transform (`translate-x-[50%]` / `-translate-x-[200%]`) is only\n// meaningful in the 2/3 + 1/3 wide layout where the content + preview columns\n// sit side-by-side. Below the `2xl` breakpoint the preview column stacks below\n// the content column, so we gate the transform classes with `2xl:` — otherwise\n// the content slides off-screen on narrower viewports. Opacity and transition\n// timings still run at all breakpoints so sections still fade in and out.\n\nexport function getContentClassName(phase: AnimPhase): string {\n switch (phase) {\n case \"idle\":\n return \"opacity-100 transition-none\";\n case \"fade-out\":\n return \"opacity-0 transition-opacity duration-300 ease-in-out\";\n case \"slide\":\n return \"opacity-0 2xl:translate-x-[50%] transition-transform duration-500 ease-in-out\";\n case \"fade-in\":\n return \"opacity-100 2xl:translate-x-[50%] transition-opacity duration-300 ease-in-out\";\n case \"editing\":\n return \"opacity-100 2xl:translate-x-[50%] transition-none\";\n case \"exit-fade-out\":\n return \"opacity-0 2xl:translate-x-[50%] transition-opacity duration-300 ease-in-out\";\n case \"exit-slide\":\n return \"opacity-0 transition-transform duration-500 ease-in-out\";\n case \"exit-fade-in\":\n return \"opacity-100 transition-opacity duration-300 ease-in-out\";\n }\n}\n\nexport function getPreviewClassName(phase: AnimPhase): string {\n switch (phase) {\n case \"idle\":\n case \"fade-out\":\n case \"exit-fade-in\":\n return \"transition-none\";\n case \"slide\":\n return \"2xl:-translate-x-[200%] transition-transform duration-500 ease-in-out\";\n case \"fade-in\":\n case \"editing\":\n case \"exit-fade-out\":\n return \"2xl:-translate-x-[200%] transition-none\";\n case \"exit-slide\":\n return \"transition-transform duration-500 ease-in-out\";\n }\n}\n","import { Eye, Users } from \"lucide-react\";\nimport {\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n Separator,\n} from \"@fluid-app/ui-primitives\";\n\nexport function MySiteVisitorDetailsCard({\n views,\n leads,\n}: {\n views: number;\n leads: number;\n}): React.JSX.Element {\n return (\n <Card className=\"h-auto gap-0 py-0 shadow-none\">\n <CardHeader className=\"p-4 pb-3\">\n <CardTitle className=\"text-sm\">Visitor Details</CardTitle>\n </CardHeader>\n <CardContent className=\"flex px-4 pb-4\">\n <div className=\"flex-1\">\n <div className=\"mb-2 flex items-center gap-1.5\">\n <Eye className=\"text-muted-foreground h-3.5 w-3.5\" />\n <span className=\"text-muted-foreground text-sm\">Views</span>\n </div>\n <p className=\"text-foreground text-2xl font-bold\">\n {views.toLocaleString()}\n </p>\n </div>\n <Separator orientation=\"vertical\" className=\"bg-border mx-4 h-auto\" />\n <div className=\"flex-1\">\n <div className=\"mb-2 flex items-center gap-1.5\">\n <Users className=\"text-muted-foreground h-3.5 w-3.5\" />\n <span className=\"text-muted-foreground text-sm\">Leads</span>\n </div>\n <p className=\"text-foreground text-2xl font-bold\">\n {leads.toLocaleString()}\n </p>\n </div>\n </CardContent>\n </Card>\n );\n}\n","import { useCallback, useState } from \"react\";\nimport { Copy } from \"lucide-react\";\nimport {\n Button,\n Card,\n CardAction,\n CardContent,\n CardHeader,\n CardTitle,\n} from \"@fluid-app/ui-primitives\";\n\nexport function MySiteLinkCard({\n mysiteUrl,\n displayUrl,\n onUpdateSlug,\n onToast,\n}: {\n mysiteUrl: string;\n displayUrl: string;\n onUpdateSlug?: (slug: string) => Promise<void>;\n onToast?: (message: string, type: \"success\" | \"error\") => void;\n}): React.JSX.Element {\n const lastSlashIndex = displayUrl.lastIndexOf(\"/\");\n const urlPrefix =\n lastSlashIndex >= 0 ? displayUrl.slice(0, lastSlashIndex + 1) : \"\";\n const currentSlug =\n lastSlashIndex >= 0 ? displayUrl.slice(lastSlashIndex + 1) : displayUrl;\n\n const [isEditingLink, setIsEditingLink] = useState(false);\n const [linkSlugInput, setLinkSlugInput] = useState(currentSlug);\n const [isSaving, setIsSaving] = useState(false);\n\n const handleEditLink = useCallback(() => {\n setLinkSlugInput(currentSlug);\n setIsEditingLink(true);\n }, [currentSlug]);\n\n const handleCancelEditLink = useCallback(() => {\n setIsEditingLink(false);\n setLinkSlugInput(currentSlug);\n }, [currentSlug]);\n\n const handleSaveLink = useCallback(async () => {\n const trimmed = linkSlugInput.trim();\n if (!trimmed) {\n onToast?.(\"Slug cannot be empty\", \"error\");\n return;\n }\n if (trimmed === currentSlug) {\n setIsEditingLink(false);\n return;\n }\n if (!onUpdateSlug) return;\n setIsSaving(true);\n try {\n await onUpdateSlug(trimmed);\n onToast?.(\"MySite link updated\", \"success\");\n setIsEditingLink(false);\n } catch {\n onToast?.(\"Failed to update link\", \"error\");\n } finally {\n setIsSaving(false);\n }\n }, [linkSlugInput, currentSlug, onUpdateSlug, onToast]);\n\n const handleCopyLink = useCallback(async () => {\n if (!mysiteUrl) return;\n try {\n await navigator.clipboard.writeText(mysiteUrl);\n onToast?.(\"Link copied to clipboard\", \"success\");\n } catch {\n onToast?.(\"Failed to copy link\", \"error\");\n }\n }, [mysiteUrl, onToast]);\n\n return (\n <Card className=\"h-auto gap-0 py-0 shadow-none\">\n <CardHeader className=\"items-center p-4\">\n <CardTitle className=\"text-sm\">Your MySite Link</CardTitle>\n {!isEditingLink && onUpdateSlug && (\n <CardAction>\n <Button variant=\"link\" size=\"sm\" onClick={handleEditLink}>\n Edit Link\n </Button>\n </CardAction>\n )}\n </CardHeader>\n <CardContent className=\"px-4 pb-4\">\n <div className=\"text-foreground flex items-center gap-2 rounded-lg border bg-gradient-to-r from-[rgba(72,187,120,0.2)] via-[rgba(236,72,153,0.15)] to-[rgba(251,146,60,0.15)] px-3 py-2.5\">\n {isEditingLink ? (\n <>\n <span className=\"shrink-0 text-sm\">{urlPrefix}</span>\n <input\n type=\"text\"\n value={linkSlugInput}\n onChange={(e) => setLinkSlugInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !isSaving) handleSaveLink();\n if (e.key === \"Escape\") handleCancelEditLink();\n }}\n className=\"border-input text-foreground focus:ring-primary bg-background/60 min-w-0 flex-1 rounded-md border px-2 py-1 text-sm font-medium outline-none focus:ring-1\"\n autoFocus\n />\n </>\n ) : (\n <span className=\"min-w-0 flex-1 truncate text-sm\">\n {displayUrl || \"Not configured\"}\n </span>\n )}\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={handleCopyLink}\n disabled={!mysiteUrl}\n >\n <Copy className=\"h-4 w-4\" />\n </Button>\n </div>\n\n <div\n className=\"grid transition-all duration-300 ease-in-out\"\n style={{\n gridTemplateRows: isEditingLink ? \"1fr\" : \"0fr\",\n opacity: isEditingLink ? 1 : 0,\n marginTop: isEditingLink ? 12 : 0,\n }}\n >\n <div className=\"overflow-hidden\">\n <div className=\"flex justify-end gap-2\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleCancelEditLink}\n >\n Cancel\n </Button>\n <Button size=\"sm\" onClick={handleSaveLink} disabled={isSaving}>\n {isSaving ? \"Saving...\" : \"Save\"}\n </Button>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n );\n}\n","import { LoaderCircle } from \"lucide-react\";\nimport {\n Button,\n Card,\n CardContent,\n CardHeader,\n} from \"@fluid-app/ui-primitives\";\n\nexport function MySitePhonePreview({\n mysiteUrl,\n themeName,\n previewKey,\n isUpdating,\n onPreview,\n}: {\n mysiteUrl: string;\n themeName: string;\n previewKey: number;\n isUpdating: boolean;\n onPreview: () => void;\n}): React.JSX.Element {\n return (\n <Card className=\"items-center gap-4 py-5\">\n <CardHeader className=\"w-full items-center px-5\">\n <div>\n <p className=\"text-muted-foreground text-xs\">Current Theme</p>\n <p className=\"text-foreground text-sm font-semibold\">{themeName}</p>\n </div>\n <Button\n className=\"col-start-2 row-span-2 row-start-1 cursor-pointer self-center justify-self-end\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={onPreview}\n disabled={!mysiteUrl}\n >\n Preview\n </Button>\n </CardHeader>\n\n <CardContent className=\"relative mx-auto my-auto w-[260px] px-0 sm:w-[320px]\">\n <div className=\"overflow-hidden rounded-[32px] border-[6px] border-[#1e2939] bg-[#1e2939] shadow-xl sm:rounded-[40px] sm:border-[8px]\">\n <div className=\"flex items-center justify-between bg-[#101828] px-5 py-1 sm:px-6 sm:py-1.5\">\n <span className=\"text-[10px] font-medium text-[#ffffff] sm:text-[11px]\">\n 9:41\n </span>\n <div className=\"flex items-center gap-1\">\n <div className=\"h-2 w-2 rounded-full bg-[#ffffff60] sm:h-2.5 sm:w-2.5\" />\n <div className=\"h-2 w-3.5 rounded-sm bg-[#ffffff60] sm:h-2.5 sm:w-4\" />\n </div>\n </div>\n\n <div\n className=\"relative h-[490px] overflow-y-auto bg-[#ffffff] sm:h-[600px]\"\n style={{ scrollbarWidth: \"none\" }}\n aria-busy={isUpdating}\n >\n {mysiteUrl ? (\n <>\n <iframe\n key={previewKey}\n className=\"h-full w-full origin-top-left bg-[#ffffff]\"\n src={`${mysiteUrl}?preview=true`}\n title=\"MySite Preview\"\n />\n {isUpdating && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/60\">\n <LoaderCircle className=\"text-muted-foreground h-6 w-6 animate-spin\" />\n </div>\n )}\n </>\n ) : (\n <div className=\"flex h-full items-center justify-center\">\n <p className=\"text-muted-foreground text-sm\">\n No site configured\n </p>\n </div>\n )}\n </div>\n </div>\n\n <div className=\"absolute bottom-1.5 left-1/2 h-1 w-24 -translate-x-1/2 rounded-full bg-white sm:bottom-2 sm:w-28\" />\n </CardContent>\n </Card>\n );\n}\n","import { ArrowLeft, Check, Palette } from \"lucide-react\";\nimport { Button, Card, CardContent, cn } from \"@fluid-app/ui-primitives\";\n\n/** Minimal theme shape accepted by ThemeEditor.\n * Compatible with both core MySiteTheme (preview_url) and legacy MysiteTheme (image_url). */\nexport interface ThemeDisplayItem {\n id: number;\n name: string;\n preview_url?: string | null;\n image_url?: string | null;\n}\n\nexport function MySiteThemeEditor<T extends ThemeDisplayItem>({\n themes,\n selectedThemeId,\n onSelectTheme,\n isPending,\n onBack,\n}: {\n themes: T[];\n selectedThemeId: number | null;\n onSelectTheme: (theme: T) => void;\n isPending: boolean;\n onBack: () => void;\n}): React.JSX.Element {\n return (\n <>\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={onBack}>\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <h1 className=\"text-foreground text-xl font-bold\">Choose a Theme</h1>\n </div>\n\n {themes.length === 0 ? (\n <Card>\n <CardContent className=\"py-8 text-center\">\n <p className=\"text-muted-foreground\">No themes available</p>\n </CardContent>\n </Card>\n ) : (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3\">\n {themes.map((theme) => {\n const isSelected = theme.id === selectedThemeId;\n const imageUrl = theme.preview_url ?? theme.image_url;\n return (\n <button\n key={theme.id}\n type=\"button\"\n onClick={() => onSelectTheme(theme)}\n className={cn(\n \"group focus:ring-primary relative overflow-hidden rounded-lg border-2 transition-all focus:ring-2 focus:ring-offset-2 focus:outline-none\",\n isSelected\n ? \"border-primary ring-primary ring-2\"\n : \"border-border hover:border-muted-foreground/50\",\n )}\n aria-pressed={isSelected}\n disabled={isPending}\n >\n <div className=\"bg-muted relative aspect-[4/3] w-full\">\n {imageUrl ? (\n <img\n src={imageUrl}\n alt={theme.name}\n loading=\"lazy\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n ) : (\n <div className=\"text-muted-foreground/50 flex h-full w-full items-center justify-center\">\n <Palette className=\"h-8 w-8\" />\n </div>\n )}\n {isSelected && (\n <div className=\"bg-primary/20 absolute inset-0 flex items-center justify-center\">\n <div className=\"bg-primary text-primary-foreground flex h-8 w-8 items-center justify-center rounded-full\">\n <Check className=\"h-5 w-5\" />\n </div>\n </div>\n )}\n {!isSelected && (\n <div className=\"absolute inset-0 bg-black/0 transition-colors group-hover:bg-black/10 dark:group-hover:bg-white/10\" />\n )}\n </div>\n <div className=\"bg-card p-2\">\n <p\n className={cn(\n \"truncate text-sm font-medium\",\n isSelected ? \"text-primary\" : \"text-foreground\",\n )}\n >\n {theme.name}\n </p>\n </div>\n </button>\n );\n })}\n </div>\n )}\n </>\n );\n}\n","import { z } from \"zod\";\n\n// User Links (Buttons)\nexport const linkSchema = z.object({\n id: z.number(),\n url: z.string(),\n text: z.string(),\n order: z.number(),\n clicks: z.number().optional().default(0),\n});\n\nexport const linksResponseSchema = z.array(linkSchema);\n\nexport type MySiteLink = z.infer<typeof linkSchema>;\n\n// Favorites\nexport const favoriteableSchema = z\n .object({\n id: z.number(),\n title: z.string().nullable().optional(),\n name: z.string().nullable().optional(),\n image_url: z.string().nullable().optional(),\n type: z.string().optional(),\n })\n .passthrough();\n\nexport const favoriteSchema = z\n .object({\n id: z.number(),\n favoriteable_id: z.number().optional(),\n favoriteable_type: z.string(),\n order: z.number(),\n user_company_id: z.number().optional(),\n created_at: z.string().optional(),\n favoriteable: favoriteableSchema.nullable(),\n })\n .passthrough();\n\nexport const favoritesResponseSchema = z.array(favoriteSchema);\n\nexport type MySiteFavorite = z.infer<typeof favoriteSchema>;\n\n// MySite Update\nexport const mysiteUpdateResponseSchema = z\n .object({\n id: z.number(),\n })\n .passthrough();\n\n// User Profile Update\nexport const profileUpdateResponseSchema = z.object({\n id: z.number(),\n bio: z.string().nullable(),\n facebook: z.string().nullable(),\n twitter: z.string().nullable(),\n instagram: z.string().nullable(),\n youtube: z.string().nullable(),\n pinterest: z.string().nullable(),\n tiktok: z.string().nullable(),\n linkedin: z.string().nullable(),\n whatsapp: z.string().nullable(),\n wechat: z.string().nullable(),\n image_url: z.string().nullable(),\n});\n\nexport type ProfileUpdateResponse = z.infer<typeof profileUpdateResponseSchema>;\n","import { z } from \"zod\";\n\nexport interface MysiteTheme {\n id: number;\n name: string;\n description: string | null;\n public: boolean;\n company_id: number | null;\n created_at: string;\n updated_at: string;\n image_url: string | null;\n application_theme_template_id: number | null;\n}\n\nexport const themeSchema: z.ZodType<MysiteTheme> = z.object({\n id: z.number(),\n name: z.string(),\n description: z.string().nullable(),\n public: z.boolean(),\n company_id: z.number().nullable(),\n created_at: z.string().datetime(),\n updated_at: z.string().datetime(),\n image_url: z.string().nullable(),\n application_theme_template_id: z.number().nullable(),\n});\n\nexport const mysiteThemesSchema: z.ZodType<MysiteTheme[]> =\n z.array(themeSchema);\n\n// --- Legacy Theme (for creating themes via /legacy_themes endpoint) ---\n\ninterface LegacyThemeTemplate {\n id: number;\n name: string;\n content: string | null;\n stylesheet: string | null;\n head: string | null;\n status: string;\n}\n\nconst legacyThemeTemplateSchema: z.ZodType<LegacyThemeTemplate> = z.object({\n id: z.number(),\n name: z.string(),\n content: z.string().nullable(),\n stylesheet: z.string().nullable(),\n head: z.string().nullable(),\n status: z.string(),\n});\n\nexport interface LegacyThemeResponse {\n data: {\n legacy_theme: {\n id: number;\n name: string;\n description: string | null;\n image_url: string | null;\n public: boolean;\n company_id: number | null;\n template: LegacyThemeTemplate;\n };\n };\n}\n\nconst legacyThemeResponseSchema: z.ZodType<LegacyThemeResponse> = z.object({\n data: z.object({\n legacy_theme: z.object({\n id: z.number(),\n name: z.string(),\n description: z.string().nullable(),\n image_url: z.string().nullable(),\n public: z.boolean(),\n company_id: z.number().nullable(),\n template: legacyThemeTemplateSchema,\n }),\n }),\n});\n\nexport { legacyThemeResponseSchema };\n\nexport interface CreateLegacyThemeInput {\n name: string;\n description?: string;\n image_url?: string;\n public?: boolean;\n template?: {\n content?: string;\n stylesheet?: string;\n head?: string;\n };\n}\n","export const sortByOrder = <T extends { order: number }>(items: T[]): T[] => {\n return [...items].sort((a, b) => a.order - b.order);\n};\n\nexport const updateOrders = <T extends { id: number | string; order: number }>(\n items: T[],\n): T[] => {\n return items.map((item, index) => ({\n ...item,\n order: index + 1,\n }));\n};\n\nexport const generateTempId = (): string => {\n return `temp_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;\n};\n\nexport function normalizeUrl(value: string): string {\n const trimmed = value.trim();\n if (!trimmed) return \"\";\n if (/^https?:\\/\\//i.test(trimmed)) return trimmed;\n return `https://${trimmed}`;\n}\n","\"use client\";\nimport { useCallback, useState } from \"react\";\nimport { ArrowLeft, Plus, GripVertical, Pencil, Trash2 } from \"lucide-react\";\nimport {\n Button,\n Badge,\n Card,\n Dialog,\n Skeleton,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n Input,\n Label,\n useZodForm,\n} from \"@fluid-app/ui-primitives\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { z } from \"zod\";\nimport {\n useUserLinks,\n useCreateLink,\n useUpdateLink,\n useDeleteLink,\n useReorderLinks,\n} from \"../../admin/hooks/use-mysite\";\nimport type { FetchClient } from \"@fluid-app/api-client-core\";\nimport type { MySiteLink } from \"../../shared/schemas/mysite.schema\";\nimport { normalizeUrl } from \"../../shared/utils\";\n\nconst buttonSchema = z.object({\n text: z.string().min(1, \"Button text is required\"),\n url: z\n .string()\n .transform(normalizeUrl)\n .pipe(z.string().url(\"Must be a valid URL\")),\n});\n\ntype ButtonFormData = z.infer<typeof buttonSchema>;\n\nfunction SortableButtonCard({\n link,\n onEdit,\n onDelete,\n}: {\n link: MySiteLink;\n onEdit: (link: MySiteLink) => void;\n onDelete: (link: MySiteLink) => void;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: link.id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n };\n\n const truncatedUrl =\n link.url.length > 40 ? `${link.url.substring(0, 40)}...` : link.url;\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n className={`border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4 ${\n isDragging ? \"opacity-50 shadow-lg\" : \"\"\n }`}\n >\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground cursor-grab touch-none\"\n aria-label=\"Drag to reorder\"\n {...attributes}\n {...listeners}\n >\n <GripVertical className=\"h-5 w-5\" />\n </button>\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-foreground truncate font-medium\">{link.text}</p>\n <p className=\"text-muted-foreground truncate text-sm\">{truncatedUrl}</p>\n </div>\n\n <Badge variant=\"secondary\" className=\"hidden shrink-0 sm:inline-flex\">\n {link.clicks ?? 0} clicks\n </Badge>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground hover:text-foreground\"\n onClick={() => onEdit(link)}\n aria-label=\"Edit button\"\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground hover:text-destructive\"\n onClick={() => onDelete(link)}\n aria-label=\"Delete button\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n\nexport function MySiteButtonsEditor({\n onBack,\n onRefreshPreview,\n client,\n userId,\n onToast,\n}: {\n onBack: () => void;\n onRefreshPreview?: () => void;\n client: FetchClient;\n userId: number | null | undefined;\n onToast?: (message: string, type: \"success\" | \"error\") => void;\n}): React.JSX.Element {\n \"use no memo\";\n const { data: links = [], isLoading } = useUserLinks(client, userId);\n const createLinkMutation = useCreateLink(client, userId);\n const updateLinkMutation = useUpdateLink(client, userId);\n const deleteLinkMutation = useDeleteLink(client, userId);\n const reorderLinksMutation = useReorderLinks(client, userId);\n\n const [isAddEditDialogOpen, setIsAddEditDialogOpen] = useState(false);\n const [editingLink, setEditingLink] = useState<MySiteLink | null>(null);\n const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);\n const [deletingLink, setDeletingLink] = useState<MySiteLink | null>(null);\n\n const {\n register,\n handleSubmit: handleButtonSubmit,\n reset: resetButtonForm,\n formState: { errors: buttonErrors, isSubmitting: isButtonSubmitting },\n } = useZodForm<ButtonFormData>(buttonSchema, {\n defaultValues: { text: \"\", url: \"\" },\n });\n\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n }),\n );\n\n const handleOpenAddDialog = useCallback(() => {\n setEditingLink(null);\n resetButtonForm({ text: \"\", url: \"\" });\n setIsAddEditDialogOpen(true);\n }, [resetButtonForm]);\n\n const handleOpenEditDialog = useCallback(\n (link: MySiteLink) => {\n setEditingLink(link);\n resetButtonForm({ text: link.text, url: link.url });\n setIsAddEditDialogOpen(true);\n },\n [resetButtonForm],\n );\n\n const handleCloseAddEditDialog = useCallback(() => {\n setIsAddEditDialogOpen(false);\n setEditingLink(null);\n resetButtonForm({ text: \"\", url: \"\" });\n }, [resetButtonForm]);\n\n const onButtonSubmit = useCallback(\n (data: ButtonFormData) => {\n if (editingLink) {\n updateLinkMutation.mutate(\n { linkId: editingLink.id, data },\n {\n onSuccess: () => {\n onToast?.(\"Button updated\", \"success\");\n handleCloseAddEditDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to update button\", \"error\");\n },\n },\n );\n } else {\n createLinkMutation.mutate(data, {\n onSuccess: () => {\n onToast?.(\"Button created\", \"success\");\n handleCloseAddEditDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to create button\", \"error\");\n },\n });\n }\n },\n [\n editingLink,\n createLinkMutation,\n updateLinkMutation,\n handleCloseAddEditDialog,\n onRefreshPreview,\n onToast,\n ],\n );\n\n const handleOpenDeleteDialog = useCallback((link: MySiteLink) => {\n setDeletingLink(link);\n setIsDeleteDialogOpen(true);\n }, []);\n\n const handleCloseDeleteDialog = useCallback(() => {\n setIsDeleteDialogOpen(false);\n setDeletingLink(null);\n }, []);\n\n const handleConfirmDelete = useCallback(() => {\n if (deletingLink) {\n deleteLinkMutation.mutate(deletingLink.id, {\n onSuccess: () => {\n onToast?.(\"Button deleted\", \"success\");\n handleCloseDeleteDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to delete button\", \"error\");\n },\n });\n }\n }, [\n deletingLink,\n deleteLinkMutation,\n handleCloseDeleteDialog,\n onRefreshPreview,\n onToast,\n ]);\n\n const handleDragEnd = useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n if (over && active.id !== over.id) {\n const oldIndex = links.findIndex((l) => l.id === active.id);\n const newIndex = links.findIndex((l) => l.id === over.id);\n const reordered = arrayMove(links, oldIndex, newIndex);\n const payload = reordered.map((link, index) => ({\n id: link.id,\n order: index + 1,\n }));\n reorderLinksMutation.mutate(\n { payload, optimisticItems: reordered },\n {\n onSuccess: () => {\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to reorder buttons\", \"error\");\n },\n },\n );\n }\n },\n [links, reorderLinksMutation, onRefreshPreview, onToast],\n );\n\n return (\n <>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={onBack}>\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <h1 className=\"text-foreground text-xl font-bold\">Buttons</h1>\n </div>\n <Button size=\"sm\" onClick={handleOpenAddDialog}>\n <Plus className=\"mr-1 h-4 w-4\" />\n Add Button\n </Button>\n </div>\n\n {isLoading ? (\n <div className=\"space-y-2\">\n {Array.from({ length: 3 }).map((_, i) => (\n <div\n key={i}\n className=\"border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4\"\n >\n <Skeleton className=\"h-5 w-5\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-48\" />\n </div>\n <Skeleton className=\"hidden h-5 w-16 sm:block\" />\n <div className=\"flex gap-1\">\n <Skeleton className=\"h-8 w-8\" />\n <Skeleton className=\"h-8 w-8\" />\n </div>\n </div>\n ))}\n </div>\n ) : links.length === 0 ? (\n <Card className=\"p-6 text-center sm:p-8\">\n <p className=\"text-muted-foreground mb-4\">\n No buttons yet. Add custom link buttons to display on your MySite.\n </p>\n <Button size=\"sm\" onClick={handleOpenAddDialog}>\n <Plus className=\"mr-1 h-4 w-4\" />\n Add Button\n </Button>\n </Card>\n ) : (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext\n items={links.map((l) => l.id)}\n strategy={verticalListSortingStrategy}\n >\n <div className=\"space-y-2\">\n {links.map((link) => (\n <SortableButtonCard\n key={link.id}\n link={link}\n onEdit={handleOpenEditDialog}\n onDelete={handleOpenDeleteDialog}\n />\n ))}\n </div>\n </SortableContext>\n </DndContext>\n )}\n\n {/* Add/Edit Dialog */}\n <Dialog open={isAddEditDialogOpen} onOpenChange={setIsAddEditDialogOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {editingLink ? \"Edit Button\" : \"Add Button\"}\n </DialogTitle>\n </DialogHeader>\n <form\n onSubmit={handleButtonSubmit(onButtonSubmit)}\n className=\"space-y-4\"\n >\n <div className=\"space-y-2\">\n <Label htmlFor=\"text\">Button Text</Label>\n <Input\n id=\"text\"\n placeholder=\"Enter button text...\"\n {...register(\"text\")}\n className={buttonErrors.text ? \"border-destructive\" : \"\"}\n />\n {buttonErrors.text && (\n <p className=\"text-destructive text-sm\">\n {buttonErrors.text.message}\n </p>\n )}\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"url\">URL</Label>\n <Input\n id=\"url\"\n placeholder=\"https://example.com\"\n {...register(\"url\")}\n className={buttonErrors.url ? \"border-destructive\" : \"\"}\n />\n {buttonErrors.url && (\n <p className=\"text-destructive text-sm\">\n {buttonErrors.url.message}\n </p>\n )}\n </div>\n <DialogFooter className=\"flex justify-between\">\n {editingLink ? (\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={() => {\n handleCloseAddEditDialog();\n handleOpenDeleteDialog(editingLink);\n }}\n >\n <Trash2 className=\"mr-1 h-4 w-4\" />\n Delete\n </Button>\n ) : (\n <div />\n )}\n <div className=\"flex gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleCloseAddEditDialog}\n >\n Cancel\n </Button>\n <Button\n type=\"submit\"\n disabled={\n isButtonSubmitting ||\n createLinkMutation.isPending ||\n updateLinkMutation.isPending\n }\n >\n {isButtonSubmitting ||\n createLinkMutation.isPending ||\n updateLinkMutation.isPending\n ? \"Saving...\"\n : \"Save\"}\n </Button>\n </div>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n\n {/* Delete Confirmation Dialog */}\n <Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Delete Button</DialogTitle>\n </DialogHeader>\n <p className=\"text-muted-foreground\">\n Are you sure you want to delete the button "\n {deletingLink?.text}"? This action cannot be undone.\n </p>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleCloseDeleteDialog}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={handleConfirmDelete}\n disabled={deleteLinkMutation.isPending}\n >\n {deleteLinkMutation.isPending ? \"Deleting...\" : \"Delete\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","\"use client\";\nimport { useCallback, useState } from \"react\";\nimport { ArrowLeft, Plus, GripVertical, Pencil, Trash2 } from \"lucide-react\";\nimport {\n Button,\n Card,\n Dialog,\n Skeleton,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n Input,\n Label,\n useZodForm,\n} from \"@fluid-app/ui-primitives\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { z } from \"zod\";\nimport {\n usePortalLinks,\n usePortalCreateLink,\n usePortalUpdateLink,\n usePortalDeleteLink,\n usePortalReorderLinks,\n} from \"../hooks/use-mysite-portal\";\nimport type { MySiteLink } from \"@fluid-app/mysite-core/mysite-api-types\";\nimport { normalizeUrl } from \"../../shared/utils\";\n\nconst buttonSchema = z.object({\n title: z.string().min(1, \"Button text is required\"),\n url: z\n .string()\n .transform(normalizeUrl)\n .pipe(z.string().url(\"Must be a valid URL\")),\n});\n\ntype ButtonFormData = z.infer<typeof buttonSchema>;\n\nfunction SortableButtonCard({\n link,\n onEdit,\n onDelete,\n}: {\n link: MySiteLink;\n onEdit: (link: MySiteLink) => void;\n onDelete: (link: MySiteLink) => void;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: link.id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n };\n\n const truncatedUrl =\n link.url.length > 40 ? `${link.url.substring(0, 40)}...` : link.url;\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n className={`border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4 ${\n isDragging ? \"opacity-50 shadow-lg\" : \"\"\n }`}\n >\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground cursor-grab touch-none\"\n aria-label=\"Drag to reorder\"\n {...attributes}\n {...listeners}\n >\n <GripVertical className=\"h-5 w-5\" />\n </button>\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-foreground truncate font-medium\">{link.title}</p>\n <p className=\"text-muted-foreground truncate text-sm\">{truncatedUrl}</p>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground hover:text-foreground\"\n onClick={() => onEdit(link)}\n aria-label=\"Edit button\"\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground hover:text-destructive\"\n onClick={() => onDelete(link)}\n aria-label=\"Delete button\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Portal-specific buttons editor that uses MySiteApi context.\n * No client/userId props needed — data comes from context.\n */\nexport function PortalButtonsEditor({\n onBack,\n onRefreshPreview,\n onToast,\n}: {\n onBack: () => void;\n onRefreshPreview?: () => void;\n onToast?: (message: string, type: \"success\" | \"error\") => void;\n}): React.JSX.Element {\n \"use no memo\";\n const { data: links = [], isLoading } = usePortalLinks();\n const createLinkMutation = usePortalCreateLink();\n const updateLinkMutation = usePortalUpdateLink();\n const deleteLinkMutation = usePortalDeleteLink();\n const reorderLinksMutation = usePortalReorderLinks();\n\n const [isAddEditDialogOpen, setIsAddEditDialogOpen] = useState(false);\n const [editingLink, setEditingLink] = useState<MySiteLink | null>(null);\n const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);\n const [deletingLink, setDeletingLink] = useState<MySiteLink | null>(null);\n\n const {\n register,\n handleSubmit: handleButtonSubmit,\n reset: resetButtonForm,\n formState: { errors: buttonErrors, isSubmitting: isButtonSubmitting },\n } = useZodForm<ButtonFormData>(buttonSchema, {\n defaultValues: { title: \"\", url: \"\" },\n });\n\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n }),\n );\n\n const handleOpenAddDialog = useCallback(() => {\n setEditingLink(null);\n resetButtonForm({ title: \"\", url: \"\" });\n setIsAddEditDialogOpen(true);\n }, [resetButtonForm]);\n\n const handleOpenEditDialog = useCallback(\n (link: MySiteLink) => {\n setEditingLink(link);\n resetButtonForm({ title: link.title, url: link.url });\n setIsAddEditDialogOpen(true);\n },\n [resetButtonForm],\n );\n\n const handleCloseAddEditDialog = useCallback(() => {\n setIsAddEditDialogOpen(false);\n setEditingLink(null);\n resetButtonForm({ title: \"\", url: \"\" });\n }, [resetButtonForm]);\n\n const onButtonSubmit = useCallback(\n (data: ButtonFormData) => {\n if (editingLink) {\n updateLinkMutation.mutate(\n {\n linkId: editingLink.id,\n body: { title: data.title, url: data.url },\n },\n {\n onSuccess: () => {\n onToast?.(\"Button updated\", \"success\");\n handleCloseAddEditDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to update button\", \"error\");\n },\n },\n );\n } else {\n createLinkMutation.mutate(\n { title: data.title, url: data.url },\n {\n onSuccess: () => {\n onToast?.(\"Button created\", \"success\");\n handleCloseAddEditDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to create button\", \"error\");\n },\n },\n );\n }\n },\n [\n editingLink,\n createLinkMutation,\n updateLinkMutation,\n handleCloseAddEditDialog,\n onRefreshPreview,\n onToast,\n ],\n );\n\n const handleOpenDeleteDialog = useCallback((link: MySiteLink) => {\n setDeletingLink(link);\n setIsDeleteDialogOpen(true);\n }, []);\n\n const handleCloseDeleteDialog = useCallback(() => {\n setIsDeleteDialogOpen(false);\n setDeletingLink(null);\n }, []);\n\n const handleConfirmDelete = useCallback(() => {\n if (deletingLink) {\n deleteLinkMutation.mutate(deletingLink.id, {\n onSuccess: () => {\n onToast?.(\"Button deleted\", \"success\");\n handleCloseDeleteDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to delete button\", \"error\");\n },\n });\n }\n }, [\n deletingLink,\n deleteLinkMutation,\n handleCloseDeleteDialog,\n onRefreshPreview,\n onToast,\n ]);\n\n const handleDragEnd = useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n if (over && active.id !== over.id) {\n const oldIndex = links.findIndex((l) => l.id === active.id);\n const newIndex = links.findIndex((l) => l.id === over.id);\n const reordered = arrayMove(links, oldIndex, newIndex);\n const orderedIds = reordered.map((link) => link.id);\n reorderLinksMutation.mutate(\n { orderedIds, optimisticItems: reordered },\n {\n onSuccess: () => {\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to reorder buttons\", \"error\");\n },\n },\n );\n }\n },\n [links, reorderLinksMutation, onRefreshPreview, onToast],\n );\n\n return (\n <>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={onBack}>\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <h1 className=\"text-foreground text-xl font-bold\">Buttons</h1>\n </div>\n <Button size=\"sm\" onClick={handleOpenAddDialog}>\n <Plus className=\"mr-1 h-4 w-4\" />\n Add Button\n </Button>\n </div>\n\n {isLoading ? (\n <div className=\"space-y-2\">\n {Array.from({ length: 3 }).map((_, i) => (\n <div\n key={i}\n className=\"border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4\"\n >\n <Skeleton className=\"h-5 w-5\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-48\" />\n </div>\n <div className=\"flex gap-1\">\n <Skeleton className=\"h-8 w-8\" />\n <Skeleton className=\"h-8 w-8\" />\n </div>\n </div>\n ))}\n </div>\n ) : links.length === 0 ? (\n <Card className=\"p-6 text-center sm:p-8\">\n <p className=\"text-muted-foreground mb-4\">\n No buttons yet. Add custom link buttons to display on your MySite.\n </p>\n <Button size=\"sm\" onClick={handleOpenAddDialog}>\n <Plus className=\"mr-1 h-4 w-4\" />\n Add Button\n </Button>\n </Card>\n ) : (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext\n items={links.map((l) => l.id)}\n strategy={verticalListSortingStrategy}\n >\n <div className=\"space-y-2\">\n {links.map((link) => (\n <SortableButtonCard\n key={link.id}\n link={link}\n onEdit={handleOpenEditDialog}\n onDelete={handleOpenDeleteDialog}\n />\n ))}\n </div>\n </SortableContext>\n </DndContext>\n )}\n\n {/* Add/Edit Dialog */}\n <Dialog open={isAddEditDialogOpen} onOpenChange={setIsAddEditDialogOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>\n {editingLink ? \"Edit Button\" : \"Add Button\"}\n </DialogTitle>\n </DialogHeader>\n <form\n onSubmit={handleButtonSubmit(onButtonSubmit)}\n className=\"space-y-4\"\n >\n <div className=\"space-y-2\">\n <Label htmlFor=\"title\">Button Text</Label>\n <Input\n id=\"title\"\n placeholder=\"Enter button text...\"\n {...register(\"title\")}\n className={buttonErrors.title ? \"border-destructive\" : \"\"}\n />\n {buttonErrors.title && (\n <p className=\"text-destructive text-sm\">\n {buttonErrors.title.message}\n </p>\n )}\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"url\">URL</Label>\n <Input\n id=\"url\"\n placeholder=\"https://example.com\"\n {...register(\"url\")}\n className={buttonErrors.url ? \"border-destructive\" : \"\"}\n />\n {buttonErrors.url && (\n <p className=\"text-destructive text-sm\">\n {buttonErrors.url.message}\n </p>\n )}\n </div>\n <DialogFooter className=\"flex justify-between\">\n {editingLink ? (\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={() => {\n handleCloseAddEditDialog();\n handleOpenDeleteDialog(editingLink);\n }}\n >\n <Trash2 className=\"mr-1 h-4 w-4\" />\n Delete\n </Button>\n ) : (\n <div />\n )}\n <div className=\"flex gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleCloseAddEditDialog}\n >\n Cancel\n </Button>\n <Button\n type=\"submit\"\n disabled={\n isButtonSubmitting ||\n createLinkMutation.isPending ||\n updateLinkMutation.isPending\n }\n >\n {isButtonSubmitting ||\n createLinkMutation.isPending ||\n updateLinkMutation.isPending\n ? \"Saving...\"\n : \"Save\"}\n </Button>\n </div>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n\n {/* Delete Confirmation Dialog */}\n <Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Delete Button</DialogTitle>\n </DialogHeader>\n <p className=\"text-muted-foreground\">\n Are you sure you want to delete the button "\n {deletingLink?.title}"? This action cannot be undone.\n </p>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleCloseDeleteDialog}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={handleConfirmDelete}\n disabled={deleteLinkMutation.isPending}\n >\n {deleteLinkMutation.isPending ? \"Deleting...\" : \"Delete\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","\"use client\";\nimport { useCallback, useState } from \"react\";\nimport { ArrowLeft, GripVertical, Trash2 } from \"lucide-react\";\nimport {\n Button,\n Card,\n Dialog,\n Skeleton,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n} from \"@fluid-app/ui-primitives\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport {\n usePortalFavorites,\n usePortalDeleteFavorite,\n usePortalReorderFavorites,\n} from \"../hooks/use-mysite-portal\";\nimport type { MySiteFavorite } from \"@fluid-app/mysite-core/mysite-api-types\";\n\nconst TYPE_LABELS: Record<string, string> = {\n Medium: \"Media\",\n Library: \"Playlist\",\n EnrollmentPack: \"Enrollment Pack\",\n Page: \"Page\",\n};\n\nfunction SortableFavoriteCard({\n favorite,\n onDelete,\n}: {\n favorite: MySiteFavorite;\n onDelete: (favorite: MySiteFavorite) => void;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: favorite.id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n };\n\n const title = favorite.name ?? \"Untitled\";\n const imageUrl = favorite.image_url;\n const typeLabel =\n favorite.favoriteable_type !== \"Product\"\n ? (TYPE_LABELS[favorite.favoriteable_type] ?? favorite.favoriteable_type)\n : null;\n\n return (\n <div\n ref={setNodeRef}\n style={style}\n className={`border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4 ${\n isDragging ? \"opacity-50 shadow-lg\" : \"\"\n }`}\n >\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground cursor-grab touch-none\"\n aria-label=\"Drag to reorder\"\n {...attributes}\n {...listeners}\n >\n <GripVertical className=\"h-5 w-5\" />\n </button>\n\n <div className=\"bg-muted h-10 w-10 shrink-0 overflow-hidden rounded-md\">\n {imageUrl ? (\n <img\n src={imageUrl}\n alt={title}\n loading=\"lazy\"\n width={40}\n height={40}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"text-muted-foreground flex h-full w-full items-center justify-center text-xs\">\n N/A\n </div>\n )}\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-foreground truncate font-medium\">{title}</p>\n {typeLabel ? (\n <span className=\"text-muted-foreground text-xs\">{typeLabel}</span>\n ) : null}\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-muted-foreground hover:text-destructive\"\n onClick={() => onDelete(favorite)}\n aria-label=\"Remove favorite\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Portal-specific favorites editor that uses MySiteApi context.\n * No client/affiliateId props needed — data comes from context.\n */\nexport function PortalFavoritesEditor({\n onBack,\n onRefreshPreview,\n onToast,\n}: {\n onBack: () => void;\n onRefreshPreview?: () => void;\n onToast?: (message: string, type: \"success\" | \"error\") => void;\n}): React.JSX.Element {\n const { data: favorites = [], isLoading } = usePortalFavorites();\n const deleteFavoriteMutation = usePortalDeleteFavorite();\n const reorderFavoritesMutation = usePortalReorderFavorites();\n\n const [isDeleteFavoriteDialogOpen, setIsDeleteFavoriteDialogOpen] =\n useState(false);\n const [deletingFavorite, setDeletingFavorite] =\n useState<MySiteFavorite | null>(null);\n\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n }),\n );\n\n const handleOpenDeleteFavoriteDialog = useCallback(\n (favorite: MySiteFavorite) => {\n setDeletingFavorite(favorite);\n setIsDeleteFavoriteDialogOpen(true);\n },\n [],\n );\n\n const handleCloseDeleteFavoriteDialog = useCallback(() => {\n setIsDeleteFavoriteDialogOpen(false);\n setDeletingFavorite(null);\n }, []);\n\n const handleConfirmDeleteFavorite = useCallback(() => {\n if (deletingFavorite) {\n deleteFavoriteMutation.mutate(deletingFavorite.id, {\n onSuccess: () => {\n onToast?.(\"Content removed\", \"success\");\n handleCloseDeleteFavoriteDialog();\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to remove content\", \"error\");\n },\n });\n }\n }, [\n deletingFavorite,\n deleteFavoriteMutation,\n handleCloseDeleteFavoriteDialog,\n onRefreshPreview,\n onToast,\n ]);\n\n const handleFavoriteDragEnd = useCallback(\n (event: DragEndEvent) => {\n const { active, over } = event;\n if (over && active.id !== over.id) {\n const oldIndex = favorites.findIndex((f) => f.id === active.id);\n const newIndex = favorites.findIndex((f) => f.id === over.id);\n const reordered = arrayMove(favorites, oldIndex, newIndex);\n const orderedIds = reordered.map((fav) => fav.id);\n reorderFavoritesMutation.mutate(\n { orderedIds, optimisticItems: reordered },\n {\n onSuccess: () => {\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to reorder content\", \"error\");\n },\n },\n );\n }\n },\n [favorites, reorderFavoritesMutation, onRefreshPreview, onToast],\n );\n\n return (\n <>\n <div className=\"flex items-center gap-3\">\n <Button variant=\"ghost\" size=\"icon\" onClick={onBack}>\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n <h1 className=\"text-foreground text-xl font-bold\">MySite Content</h1>\n </div>\n\n {isLoading ? (\n <div className=\"space-y-2\">\n {Array.from({ length: 3 }).map((_, i) => (\n <div\n key={i}\n className=\"border-border bg-card flex items-center gap-3 rounded-lg border p-3 sm:p-4\"\n >\n <Skeleton className=\"h-5 w-5\" />\n <Skeleton className=\"h-10 w-10 rounded-md\" />\n <div className=\"min-w-0 flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-20\" />\n </div>\n <Skeleton className=\"h-8 w-8\" />\n </div>\n ))}\n </div>\n ) : favorites.length === 0 ? (\n <Card className=\"p-6 text-center sm:p-8\">\n <p className=\"text-muted-foreground\">\n No featured content yet. Favorite products, media, or pages to\n display on your MySite.\n </p>\n </Card>\n ) : (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleFavoriteDragEnd}\n >\n <SortableContext\n items={favorites.map((f) => f.id)}\n strategy={verticalListSortingStrategy}\n >\n <div className=\"space-y-2\">\n {favorites.map((fav) => (\n <SortableFavoriteCard\n key={fav.id}\n favorite={fav}\n onDelete={handleOpenDeleteFavoriteDialog}\n />\n ))}\n </div>\n </SortableContext>\n </DndContext>\n )}\n\n {/* Delete Favorite Confirmation Dialog */}\n <Dialog\n open={isDeleteFavoriteDialogOpen}\n onOpenChange={setIsDeleteFavoriteDialogOpen}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Remove Content</DialogTitle>\n </DialogHeader>\n <p className=\"text-muted-foreground\">\n Are you sure you want to remove "\n {deletingFavorite?.name ?? \"this item\"}\n " from your MySite? This action cannot be undone.\n </p>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={handleCloseDeleteFavoriteDialog}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={handleConfirmDeleteFavorite}\n disabled={deleteFavoriteMutation.isPending}\n >\n {deleteFavoriteMutation.isPending ? \"Removing...\" : \"Remove\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","\"use client\";\nimport { useState, useCallback, useEffect, useRef } from \"react\";\nimport { ArrowLeft, Camera } from \"lucide-react\";\nimport {\n Button,\n Card,\n CardContent,\n Input,\n Label,\n Textarea,\n} from \"@fluid-app/ui-primitives\";\nimport {\n usePortalMySiteProfile,\n usePortalUpdateProfile,\n} from \"../hooks/use-mysite-portal\";\n\ninterface ProfileFormState {\n display_name: string;\n bio: string;\n}\n\nexport function MySiteProfileForm({\n onBack,\n onToast,\n onRefreshPreview,\n onUploadPhoto,\n avatarUrl,\n userName,\n userInitial,\n}: {\n onBack: () => void;\n onToast?: (message: string, type: \"success\" | \"error\") => void;\n onRefreshPreview?: () => void;\n onUploadPhoto?: (file: File) => Promise<string>;\n avatarUrl?: string | null;\n userName?: string | null;\n userInitial?: string | null;\n}): React.JSX.Element {\n const { data: profile, isLoading: isProfileLoading } =\n usePortalMySiteProfile();\n\n const updateProfileMutation = usePortalUpdateProfile();\n\n const [formState, setFormState] = useState<ProfileFormState>(() => ({\n display_name: \"\",\n bio: \"\",\n }));\n\n const profileSyncedRef = useRef(false);\n useEffect(() => {\n if (profile && !profileSyncedRef.current) {\n profileSyncedRef.current = true;\n setFormState({\n display_name: profile.display_name ?? \"\",\n bio: profile.bio ?? \"\",\n });\n }\n }, [profile]);\n\n const isDirty =\n formState.display_name !== (profile?.display_name ?? \"\") ||\n formState.bio !== (profile?.bio ?? \"\");\n\n const handleFieldChange = useCallback(\n (field: keyof ProfileFormState, value: string) => {\n setFormState((s) => ({ ...s, [field]: value }));\n },\n [],\n );\n\n const handleSave = useCallback(() => {\n updateProfileMutation.mutate(\n {\n display_name: formState.display_name,\n bio: formState.bio,\n },\n {\n onSuccess: () => {\n profileSyncedRef.current = false;\n onToast?.(\"Profile updated successfully\", \"success\");\n onRefreshPreview?.();\n },\n onError: () => {\n onToast?.(\"Failed to update profile\", \"error\");\n },\n },\n );\n }, [formState, updateProfileMutation, onToast, onRefreshPreview]);\n\n // Avatar upload handling\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isUploadingPhoto, setIsUploadingPhoto] = useState(false);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n\n useEffect(() => {\n return () => {\n if (previewUrl) URL.revokeObjectURL(previewUrl);\n };\n }, [previewUrl]);\n\n const handleFileSelected = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file || !onUploadPhoto) return;\n\n if (!file.type.startsWith(\"image/\")) {\n onToast?.(\"Please select an image file\", \"error\");\n return;\n }\n\n setPreviewUrl(URL.createObjectURL(file));\n setIsUploadingPhoto(true);\n\n try {\n const imageUrl = await onUploadPhoto(file);\n updateProfileMutation.mutate(\n { avatar_url: imageUrl },\n {\n onSuccess: () => {\n onToast?.(\"Profile photo updated\", \"success\");\n onRefreshPreview?.();\n },\n onError: () => {\n setPreviewUrl(null);\n onToast?.(\"Failed to save profile photo\", \"error\");\n },\n },\n );\n } catch {\n setPreviewUrl(null);\n onToast?.(\"Failed to upload photo\", \"error\");\n } finally {\n setIsUploadingPhoto(false);\n if (fileInputRef.current) fileInputRef.current.value = \"\";\n }\n },\n [onUploadPhoto, updateProfileMutation, onToast, onRefreshPreview],\n );\n\n if (isProfileLoading) {\n return (\n <div className=\"flex h-full items-center justify-center\">\n <div className=\"text-muted-foreground animate-pulse\">Loading...</div>\n </div>\n );\n }\n\n const displayAvatarUrl = previewUrl || avatarUrl || profile?.avatar_url;\n\n return (\n <div className=\"space-y-4 p-4 sm:space-y-6 sm:p-6\">\n {/* Header */}\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={onBack}\n className=\"text-muted-foreground hover:bg-muted hover:text-foreground flex h-10 w-10 items-center justify-center rounded-full transition-colors\"\n aria-label=\"Go back\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n <h1 className=\"text-foreground text-xl font-bold sm:text-2xl\">\n Profile\n </h1>\n </div>\n\n {/* Avatar Section (optional) */}\n {onUploadPhoto && (\n <Card className=\"p-4 sm:p-6\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handleFileSelected}\n />\n <div className=\"flex flex-col items-center gap-3 sm:flex-row sm:gap-4\">\n <div className=\"relative h-[120px] w-[120px] shrink-0 overflow-hidden rounded-full bg-gray-200\">\n {displayAvatarUrl ? (\n <img\n src={displayAvatarUrl}\n alt={userName || \"Profile\"}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"bg-background text-foreground flex h-full w-full items-center justify-center text-xl font-semibold\">\n {userInitial || \"U\"}\n </div>\n )}\n {isUploadingPhoto && (\n <div className=\"absolute inset-0 flex items-center justify-center rounded-full bg-black/40\">\n <div className=\"border-t-primary h-6 w-6 animate-spin rounded-full border-2 border-white\" />\n </div>\n )}\n </div>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => fileInputRef.current?.click()}\n disabled={isUploadingPhoto}\n >\n <Camera className=\"mr-1 h-4 w-4\" />\n {isUploadingPhoto ? \"Uploading...\" : \"Change Photo\"}\n </Button>\n </div>\n </Card>\n )}\n\n {/* Display Name + Bio */}\n <Card className=\"h-auto gap-0 py-0 shadow-none\">\n <CardContent className=\"space-y-4 p-4 sm:p-6\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"profile-display-name\">Display Name</Label>\n <Input\n id=\"profile-display-name\"\n type=\"text\"\n value={formState.display_name}\n onChange={(e) =>\n handleFieldChange(\"display_name\", e.target.value)\n }\n placeholder=\"Your display name\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"profile-bio\">Bio</Label>\n <Textarea\n id=\"profile-bio\"\n rows={4}\n value={formState.bio}\n onChange={(e) => handleFieldChange(\"bio\", e.target.value)}\n placeholder=\"Tell people a little about yourself...\"\n />\n </div>\n </CardContent>\n </Card>\n\n {/* Save Button */}\n <div className=\"flex justify-end\">\n <Button\n onClick={handleSave}\n disabled={!isDirty || updateProfileMutation.isPending}\n className=\"w-full sm:w-auto\"\n >\n {updateProfileMutation.isPending ? \"Saving...\" : \"Save Changes\"}\n </Button>\n </div>\n </div>\n );\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport {\n usePortalMySiteProfile,\n usePortalMySiteThemes,\n usePortalUpdateSettings,\n} from \"@fluid-app/mysite-ui/portal/hooks/use-mysite-portal\";\nimport type { MySiteTheme } from \"@fluid-app/mysite-core/mysite-api-types\";\nimport {\n type AnimPhase,\n type EditingSection,\n getContentClassName,\n getPreviewClassName,\n MySiteVisitorDetailsCard,\n MySitePhonePreview,\n MySiteLinkCard,\n MySiteThemeEditor,\n MySiteProfileForm,\n PortalButtonsEditor,\n PortalFavoritesEditor,\n} from \"@fluid-app/mysite-ui/portal/components\";\nimport { ChevronRight, User, Link2, Palette, LayoutGrid } from \"lucide-react\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\n\ntype NavItem = {\n label: string;\n key: Exclude<EditingSection, null>;\n icon: typeof User;\n};\n\nconst navigationItems: NavItem[] = [\n { label: \"Profile\", key: \"profile\", icon: User },\n { label: \"Theme\", key: \"theme\", icon: Palette },\n { label: \"MySite Content\", key: \"content\", icon: LayoutGrid },\n { label: \"Buttons\", key: \"buttons\", icon: Link2 },\n];\n\nfunction defaultToast(message: string, type: \"success\" | \"error\") {\n fluidToast({ title: message, type });\n}\n\nexport interface MySiteMainViewProps {\n editingSection: EditingSection;\n animPhase: AnimPhase;\n showEditContent: boolean;\n onEditSection: (section: EditingSection) => void;\n onBackClick: () => void;\n}\n\nexport function MySiteMainView({\n editingSection,\n animPhase,\n showEditContent,\n onEditSection,\n onBackClick,\n}: MySiteMainViewProps): React.JSX.Element {\n const { data: profile, isLoading: isProfileLoading } =\n usePortalMySiteProfile();\n const { data: themes = [] } = usePortalMySiteThemes();\n const updateSettingsMutation = usePortalUpdateSettings();\n\n const [previewKey, setPreviewKey] = useState(0);\n const refreshPreview = useCallback(() => setPreviewKey((k) => k + 1), []);\n\n const [selectedThemeId, setSelectedThemeId] = useState<number | null>(null);\n\n const resolvedThemeId =\n selectedThemeId ??\n profile?.theme_id ??\n themes.find((t) => t.name === \"Default\")?.id ??\n themes[0]?.id ??\n null;\n\n const currentTheme = themes.find((t) => t.id === resolvedThemeId);\n const themeName = currentTheme?.name ?? \"Default\";\n\n const mysiteUrl = profile?.mysite_url ?? \"\";\n const displayUrl = mysiteUrl ? mysiteUrl.replace(/^https?:\\/\\//, \"\") : \"\";\n const views = profile?.mysite_views ?? 0;\n const leads = profile?.mysite_leads ?? 0;\n\n const handleSelectTheme = useCallback(\n (theme: MySiteTheme) => {\n if (theme.id === resolvedThemeId) return;\n const previousThemeId = selectedThemeId;\n setSelectedThemeId(theme.id);\n updateSettingsMutation.mutate(\n { theme_id: theme.id },\n {\n onSuccess: () => {\n defaultToast(`Theme changed to \"${theme.name}\"`, \"success\");\n refreshPreview();\n },\n onError: () => {\n setSelectedThemeId(previousThemeId);\n defaultToast(\"Failed to update theme\", \"error\");\n },\n },\n );\n },\n [resolvedThemeId, selectedThemeId, updateSettingsMutation, refreshPreview],\n );\n\n const handleUpdateSlug = useCallback(\n async (slug: string) => {\n await new Promise<void>((resolve, reject) => {\n updateSettingsMutation.mutate(\n { slug },\n {\n onSuccess: () => resolve(),\n onError: () => reject(new Error(\"Failed\")),\n },\n );\n });\n },\n [updateSettingsMutation],\n );\n\n const handlePreview = useCallback(() => {\n if (mysiteUrl) window.open(`${mysiteUrl}?preview=true`, \"_blank\");\n }, [mysiteUrl]);\n\n const sectionLabel = useMemo(() => {\n if (editingSection === \"theme\") return \"Theme\";\n if (editingSection === \"buttons\") return \"Buttons\";\n if (editingSection === \"content\") return \"MySite Content\";\n if (editingSection === \"profile\") return \"Profile\";\n return \"\";\n }, [editingSection]);\n\n if (isProfileLoading) {\n return (\n <div className=\"flex h-full flex-col overflow-y-auto px-2 py-6 2xl:flex-row 2xl:overflow-hidden\">\n <div className=\"w-full px-4 2xl:w-2/3 2xl:shrink-0\">\n <div className=\"flex flex-col gap-5\">\n <div className=\"bg-muted h-7 w-32 animate-pulse rounded-md\" />\n <div className=\"bg-muted h-20 w-full animate-pulse rounded-lg\" />\n <div className=\"bg-muted h-16 w-full animate-pulse rounded-lg\" />\n <div className=\"bg-muted h-40 w-full animate-pulse rounded-lg\" />\n </div>\n </div>\n <div className=\"w-full shrink-0 overflow-y-hidden px-4 pt-5 2xl:w-1/3 2xl:pt-0\">\n <div className=\"bg-muted flex h-full flex-col items-center gap-4 rounded-xl p-5\">\n <div className=\"flex w-full items-center justify-between\">\n <div className=\"space-y-1\">\n <div className=\"bg-background/50 h-3 w-24 animate-pulse rounded\" />\n <div className=\"bg-background/50 h-4 w-28 animate-pulse rounded\" />\n </div>\n <div className=\"bg-background/50 h-8 w-20 animate-pulse rounded-md\" />\n </div>\n <div className=\"bg-background/50 h-[490px] w-[260px] animate-pulse rounded-[36px] sm:h-[600px] sm:w-[320px]\" />\n </div>\n </div>\n </div>\n );\n }\n\n const contentAnimClassName = getContentClassName(animPhase);\n const previewAnimClassName = getPreviewClassName(animPhase);\n\n return (\n <div className=\"flex h-full flex-col overflow-y-auto px-2 py-6 2xl:flex-row 2xl:overflow-hidden\">\n {/* Content column */}\n <div\n className={`w-full px-4 2xl:w-2/3 2xl:shrink-0 ${contentAnimClassName}`}\n >\n <div className=\"flex min-w-0 flex-col gap-5 2xl:h-full 2xl:overflow-y-auto\">\n {showEditContent && editingSection === \"theme\" ? (\n <MySiteThemeEditor\n themes={themes}\n selectedThemeId={resolvedThemeId}\n onSelectTheme={handleSelectTheme}\n isPending={updateSettingsMutation.isPending}\n onBack={onBackClick}\n />\n ) : showEditContent && editingSection === \"buttons\" ? (\n <PortalButtonsEditor\n onBack={onBackClick}\n onRefreshPreview={refreshPreview}\n onToast={defaultToast}\n />\n ) : showEditContent && editingSection === \"content\" ? (\n <PortalFavoritesEditor\n onBack={onBackClick}\n onRefreshPreview={refreshPreview}\n onToast={defaultToast}\n />\n ) : showEditContent && editingSection === \"profile\" ? (\n <MySiteProfileForm\n onBack={onBackClick}\n onRefreshPreview={refreshPreview}\n onToast={defaultToast}\n />\n ) : (\n <>\n {/* Header with optional back-to-section label */}\n <div className=\"flex items-center gap-2\">\n <h1 className=\"text-foreground text-xl font-bold\">MySite</h1>\n {animPhase !== \"idle\" && sectionLabel && (\n <>\n <ChevronRight className=\"text-muted-foreground h-4 w-4\" />\n <span className=\"text-foreground text-xl font-bold\">\n {sectionLabel}\n </span>\n </>\n )}\n </div>\n\n <MySiteVisitorDetailsCard views={views} leads={leads} />\n\n <MySiteLinkCard\n mysiteUrl={mysiteUrl}\n displayUrl={displayUrl}\n onUpdateSlug={handleUpdateSlug}\n onToast={defaultToast}\n />\n\n <div className=\"border-border bg-card divide-border divide-y overflow-hidden rounded-lg border\">\n {navigationItems.map((item) => {\n const Icon = item.icon;\n const rowClassName =\n \"group hover:bg-muted flex w-full items-center gap-2.5 px-3 py-2.5 transition-colors text-left cursor-pointer\";\n\n return (\n <button\n key={item.label}\n type=\"button\"\n onClick={() => onEditSection(item.key)}\n className={rowClassName}\n >\n <div className=\"bg-muted text-foreground flex h-7 w-7 shrink-0 items-center justify-center rounded-full\">\n <Icon className=\"h-3.5 w-3.5\" />\n </div>\n <span className=\"text-foreground flex-1 text-sm font-medium\">\n {item.label}\n </span>\n <ChevronRight className=\"text-muted-foreground h-3 w-3 shrink-0 transition-transform group-hover:translate-x-0.5\" />\n </button>\n );\n })}\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* Preview column */}\n <div\n className={`w-full shrink-0 overflow-y-hidden px-4 pt-5 2xl:w-1/3 2xl:pt-0 ${previewAnimClassName}`}\n >\n <MySitePhonePreview\n mysiteUrl={mysiteUrl}\n themeName={themeName}\n previewKey={previewKey}\n isUpdating={updateSettingsMutation.isPending}\n onPreview={handlePreview}\n />\n </div>\n </div>\n );\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n type AnimPhase,\n type EditingSection,\n FADE_MS,\n SLIDE_MS,\n} from \"@fluid-app/mysite-ui/portal/components\";\n\nexport interface MySiteEditingSectionState {\n editingSection: EditingSection;\n animPhase: AnimPhase;\n showEditContent: boolean;\n handleEditSection: (section: EditingSection) => void;\n handleBackClick: () => void;\n}\n\nexport function useMySiteEditingSection(): MySiteEditingSectionState {\n const [animPhase, setAnimPhase] = useState<AnimPhase>(\"idle\");\n const [editingSection, setEditingSection] = useState<EditingSection>(null);\n const timeoutsRef = useRef<ReturnType<typeof setTimeout>[]>([]);\n\n useEffect(() => {\n const ref = timeoutsRef;\n return () => ref.current.forEach(clearTimeout);\n }, []);\n\n const cancelScheduled = useCallback(() => {\n timeoutsRef.current.forEach(clearTimeout);\n timeoutsRef.current = [];\n }, []);\n\n const schedule = useCallback((phase: AnimPhase, delay: number) => {\n const id = setTimeout(() => setAnimPhase(phase), delay);\n timeoutsRef.current.push(id);\n }, []);\n\n const showEditContent = [\n \"slide\",\n \"fade-in\",\n \"editing\",\n \"exit-fade-out\",\n \"exit-slide\",\n ].includes(animPhase);\n\n const handleEditSection = useCallback(\n (section: EditingSection) => {\n cancelScheduled();\n setEditingSection(section);\n setAnimPhase(\"fade-out\");\n schedule(\"slide\", FADE_MS);\n schedule(\"fade-in\", FADE_MS + SLIDE_MS);\n schedule(\"editing\", FADE_MS + SLIDE_MS + FADE_MS);\n },\n [cancelScheduled, schedule],\n );\n\n const handleBackClick = useCallback(() => {\n cancelScheduled();\n setAnimPhase(\"exit-fade-out\");\n schedule(\"exit-slide\", FADE_MS);\n schedule(\"exit-fade-in\", FADE_MS + SLIDE_MS);\n const id = setTimeout(\n () => {\n setAnimPhase(\"idle\");\n setEditingSection(null);\n },\n FADE_MS + SLIDE_MS + FADE_MS,\n );\n timeoutsRef.current.push(id);\n }, [cancelScheduled, schedule]);\n\n return {\n editingSection,\n animPhase,\n showEditContent,\n handleEditSection,\n handleBackClick,\n };\n}\n","import React, { useCallback, useMemo } from \"react\";\nimport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@fluid-app/ui-primitives\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport type { WidgetPropertySchema } from \"../../registries/property-schema-types\";\nimport { MySiteMainView } from \"./MySiteMainView\";\nimport { useMySiteEditingSection } from \"./use-mysite-editing-section\";\nimport type { MySiteScreenProps } from \"./types\";\n\nexport type { MySiteScreenProps } from \"./types\";\nexport type { MeProfile } from \"./types\";\n\nexport function MySiteScreen({\n /* eslint-disable @typescript-eslint/no-unused-vars -- destructured to exclude from divProps spread */\n background,\n textColor,\n accentColor,\n padding,\n borderRadius,\n /* eslint-enable @typescript-eslint/no-unused-vars */\n ...divProps\n}: MySiteScreenProps): React.JSX.Element {\n const {\n editingSection,\n animPhase,\n showEditContent,\n handleEditSection,\n handleBackClick,\n } = useMySiteEditingSection();\n\n const sectionLabel = useMemo(() => {\n if (editingSection === \"theme\") return \"Theme\";\n if (editingSection === \"buttons\") return \"Buttons\";\n if (editingSection === \"content\") return \"MySite Content\";\n if (editingSection === \"profile\") return \"Profile\";\n return null;\n }, [editingSection]);\n\n const handleRootCrumbClick = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n if (editingSection !== null) handleBackClick();\n },\n [editingSection, handleBackClick],\n );\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n {sectionLabel ? (\n <BreadcrumbLink href=\"#\" onClick={handleRootCrumbClick}>\n My Site\n </BreadcrumbLink>\n ) : (\n <BreadcrumbPage className=\"font-semibold\">My Site</BreadcrumbPage>\n )}\n </BreadcrumbItem>\n {sectionLabel && (\n <>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n {sectionLabel}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </>\n )}\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [sectionLabel, handleRootCrumbClick],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n return (\n <div {...divProps} className={`h-full ${divProps.className ?? \"\"}`}>\n <MySiteMainView\n editingSection={editingSection}\n animPhase={animPhase}\n showEditContent={showEditContent}\n onEditSection={handleEditSection}\n onBackClick={handleBackClick}\n />\n </div>\n );\n}\n\nexport const mySiteScreenPropertySchema: WidgetPropertySchema = {\n widgetType: \"MySiteScreen\",\n displayName: \"My Site Screen\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
require("./FluidProvider-DP-sbNiR.cjs");
|
|
3
|
-
require("./ScreenRenderer-DfeRRgBO.cjs");
|
|
4
|
-
require("./account-api-context-DZP9IiGg.cjs");
|
|
5
|
-
require("./store-api-context-D1gZn22Z.cjs");
|
|
6
|
-
require("./mysite-api-context-CilZcDS4.cjs");
|
|
7
|
-
require("./src-BNcNh8fM.cjs");
|
|
8
|
-
require("./registry-context-RWj2xJlC.cjs");
|
|
9
|
-
require("./WidgetInteractionContext-Bd1hEEV2.cjs");
|
|
10
|
-
require("./EmbedWidget-CLArhSmx.cjs");
|
|
11
|
-
require("./error-state-C-AalLnz.cjs");
|
|
12
|
-
require("./LayoutWidget-DHlXzqUk.cjs");
|
|
13
|
-
require("./registries-GJMHub-Q.cjs");
|
|
14
|
-
require("./fields-C8gY9GlT.cjs");
|
|
15
|
-
require("./TextWidget--UgOcUQx.cjs");
|
|
16
|
-
require("./AlertWidget-Nx31UmWK.cjs");
|
|
17
|
-
require("./BulletListWidget-CouwHMJt.cjs");
|
|
18
|
-
require("./CalendarWidget-BtKzQFeO.cjs");
|
|
19
|
-
require("./CardWidget-DVi0NVhb.cjs");
|
|
20
|
-
require("./purify.es-BQcWWtgQ.cjs");
|
|
21
|
-
require("./src-D57IFKXU.cjs");
|
|
22
|
-
require("./scroll-arrows-CzWtSS8l.cjs");
|
|
23
|
-
require("./MediaRenderer-CfgWd0cC.cjs");
|
|
24
|
-
require("./CarouselWidget-DLqTBIrf.cjs");
|
|
25
|
-
require("./CatchUpWidget-BmibiEkX.cjs");
|
|
26
|
-
require("./ChartWidget-B0vgP7df.cjs");
|
|
27
|
-
require("./ContainerWidget-DNo8CkQ7.cjs");
|
|
28
|
-
require("./ImageWidget-B7ui4-KU.cjs");
|
|
29
|
-
require("./LinkWidget-BfvepYU9.cjs");
|
|
30
|
-
require("./ListWidget-Da-YzDAs.cjs");
|
|
31
|
-
require("./MySiteWidget-ISV__1ng.cjs");
|
|
32
|
-
require("./NestedWidget-BBOHOg12.cjs");
|
|
33
|
-
require("./PointsWidget-h0jqVXWf.cjs");
|
|
34
|
-
require("./QuickShareWidget-C_p3tPs5.cjs");
|
|
35
|
-
require("./RecentActivityWidget-Ql-mGLEf.cjs");
|
|
36
|
-
require("./SeparatorWidget-_37ala5k.cjs");
|
|
37
|
-
require("./SpacerWidget-D9lOLPr5.cjs");
|
|
38
|
-
require("./TableWidget-DUnz9hrD.cjs");
|
|
39
|
-
require("./ToDoWidget-B2qEGt7v.cjs");
|
|
40
|
-
require("./VideoWidget-sEVQcp9o.cjs");
|
|
41
|
-
require("./ScreenHeaderContext-BXgWydjB.cjs");
|
|
42
|
-
const require_ProfileScreen = require("./ProfileScreen-Xym_39QW.cjs");
|
|
43
|
-
exports.ProfileScreen = require_ProfileScreen.ProfileScreen;
|
|
44
|
-
exports.profileScreenPropertySchema = require_ProfileScreen.profileScreenPropertySchema;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
require("./FluidProvider-DP-sbNiR.cjs");
|
|
3
|
-
require("./ScreenRenderer-DfeRRgBO.cjs");
|
|
4
|
-
require("./account-api-context-DZP9IiGg.cjs");
|
|
5
|
-
require("./store-api-context-D1gZn22Z.cjs");
|
|
6
|
-
require("./mysite-api-context-CilZcDS4.cjs");
|
|
7
|
-
require("./src-BNcNh8fM.cjs");
|
|
8
|
-
require("./registry-context-RWj2xJlC.cjs");
|
|
9
|
-
require("./WidgetInteractionContext-Bd1hEEV2.cjs");
|
|
10
|
-
require("./EmbedWidget-CLArhSmx.cjs");
|
|
11
|
-
require("./error-state-C-AalLnz.cjs");
|
|
12
|
-
require("./LayoutWidget-DHlXzqUk.cjs");
|
|
13
|
-
require("./registries-GJMHub-Q.cjs");
|
|
14
|
-
require("./fields-C8gY9GlT.cjs");
|
|
15
|
-
require("./TextWidget--UgOcUQx.cjs");
|
|
16
|
-
require("./AlertWidget-Nx31UmWK.cjs");
|
|
17
|
-
require("./BulletListWidget-CouwHMJt.cjs");
|
|
18
|
-
require("./CalendarWidget-BtKzQFeO.cjs");
|
|
19
|
-
require("./CardWidget-DVi0NVhb.cjs");
|
|
20
|
-
require("./purify.es-BQcWWtgQ.cjs");
|
|
21
|
-
require("./src-D57IFKXU.cjs");
|
|
22
|
-
require("./scroll-arrows-CzWtSS8l.cjs");
|
|
23
|
-
require("./MediaRenderer-CfgWd0cC.cjs");
|
|
24
|
-
require("./CarouselWidget-DLqTBIrf.cjs");
|
|
25
|
-
require("./CatchUpWidget-BmibiEkX.cjs");
|
|
26
|
-
require("./ChartWidget-B0vgP7df.cjs");
|
|
27
|
-
require("./ContainerWidget-DNo8CkQ7.cjs");
|
|
28
|
-
require("./ImageWidget-B7ui4-KU.cjs");
|
|
29
|
-
require("./LinkWidget-BfvepYU9.cjs");
|
|
30
|
-
require("./ListWidget-Da-YzDAs.cjs");
|
|
31
|
-
require("./MySiteWidget-ISV__1ng.cjs");
|
|
32
|
-
require("./NestedWidget-BBOHOg12.cjs");
|
|
33
|
-
require("./PointsWidget-h0jqVXWf.cjs");
|
|
34
|
-
require("./QuickShareWidget-C_p3tPs5.cjs");
|
|
35
|
-
require("./RecentActivityWidget-Ql-mGLEf.cjs");
|
|
36
|
-
require("./SeparatorWidget-_37ala5k.cjs");
|
|
37
|
-
require("./SpacerWidget-D9lOLPr5.cjs");
|
|
38
|
-
require("./TableWidget-DUnz9hrD.cjs");
|
|
39
|
-
require("./ToDoWidget-B2qEGt7v.cjs");
|
|
40
|
-
require("./VideoWidget-sEVQcp9o.cjs");
|
|
41
|
-
require("./ScreenHeaderContext-BXgWydjB.cjs");
|
|
42
|
-
require("./SearchSort-ztRXlRwu.cjs");
|
|
43
|
-
require("./PortalProductsApiProvider-Ca1oeTtJ.cjs");
|
|
44
|
-
const require_ShopScreen = require("./ShopScreen-B92DRQkQ.cjs");
|
|
45
|
-
exports.ShopScreen = require_ShopScreen.ShopScreen;
|
|
46
|
-
exports.shopScreenPropertySchema = require_ShopScreen.shopScreenPropertySchema;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TextWidget--UgOcUQx.cjs","names":["borderWidthClasses","borderColorClasses","getFontSizeField","getFontWeightField","getColorField","AlignLeft","AlignCenter","AlignRight","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/widgets/TextWidget.tsx"],"sourcesContent":["import type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getFontWeightField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n FontWeightOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport { AlignCenter, AlignLeft, AlignRight } from \"lucide-react\";\n\ntype TextAlignment = \"left\" | \"center\" | \"right\";\n\nconst textAlignmentClasses: Record<TextAlignment, string> = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n} as const;\n\ntype TextWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleFontWeight?: FontWeightOptions;\n titleColor?: ColorOptions;\n titleAlignment?: TextAlignment;\n\n // Description\n description?: string;\n descriptionFontSize?: FontSizeOptions;\n descriptionFontWeight?: FontWeightOptions;\n descriptionColor?: ColorOptions;\n descriptionAlignment?: TextAlignment;\n\n // Styling\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\nexport function TextWidget({\n titleEnabled = true,\n title = \"Text Widget\",\n titleFontSize = \"xl\",\n titleFontWeight = \"bold\",\n titleColor = \"foreground\",\n titleAlignment = \"left\",\n description = \"This is a text widget\",\n descriptionFontSize = \"md\",\n descriptionFontWeight = \"normal\",\n descriptionColor = \"foreground\",\n descriptionAlignment = \"left\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n className,\n ...props\n}: TextWidgetProps): 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 return (\n <div\n className={`bg-${backgroundColor} p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {titleEnabled && (\n <h2\n className={`text-${titleFontSize} text-${titleColor} ${textAlignmentClasses[titleAlignment]} font-header font-${titleFontWeight}`}\n >\n {title}\n </h2>\n )}\n <p\n className={`text-${descriptionFontSize} text-${descriptionColor} ${textAlignmentClasses[descriptionAlignment]} font-${descriptionFontWeight}`}\n >\n {description}\n </p>\n </div>\n );\n}\n\nexport const textWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"TextWidget\",\n displayName: \"Text Widget\",\n tabsConfig: [{ id: \"content\", label: \"Content\" }],\n dataSourceTargetProps: [\"title\", \"description\"],\n fields: [\n // Content Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the text\",\n defaultValue: true,\n tab: \"content\",\n group: \"Title\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"The title\",\n defaultValue: \"Heads up!\",\n tab: \"content\",\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: \"xl\",\n tab: \"content\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getFontWeightField({\n key: \"titleFontWeight\",\n label: \"Title Font Weight\",\n description: \"Font weight for the title\",\n defaultValue: \"bold\",\n tab: \"content\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"The color of the title\",\n defaultValue: \"foreground\",\n tab: \"content\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n {\n key: \"titleAlignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Text alignment for the title\",\n options: [\n { icon: AlignLeft, value: \"left\" },\n { icon: AlignCenter, value: \"center\" },\n { icon: AlignRight, value: \"right\" },\n ],\n defaultValue: \"left\",\n tab: \"content\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n // Content Tab - Description Group\n {\n key: \"description\",\n label: \"Description\",\n type: \"textarea\",\n description: \"The text message\",\n rows: 3,\n defaultValue:\n \"You can add components and dependencies to your app using the cli.\",\n tab: \"content\",\n group: \"Description\",\n },\n getFontSizeField({\n key: \"descriptionFontSize\",\n label: \"Description Font Size\",\n description: \"Font size for the text\",\n defaultValue: \"md\",\n tab: \"content\",\n group: \"Description\",\n }),\n getFontWeightField({\n key: \"descriptionFontWeight\",\n label: \"Description Font Weight\",\n description: \"Font weight for the text\",\n defaultValue: \"normal\",\n tab: \"content\",\n group: \"Description\",\n }),\n getColorField({\n key: \"descriptionColor\",\n label: \"Description Color\",\n description: \"The color of the text\",\n defaultValue: \"foreground\",\n tab: \"content\",\n group: \"Description\",\n }),\n {\n key: \"descriptionAlignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Text alignment for the description\",\n options: [\n { icon: AlignLeft, value: \"left\" },\n { icon: AlignCenter, value: \"center\" },\n { icon: AlignRight, value: \"right\" },\n ],\n defaultValue: \"left\",\n tab: \"content\",\n group: \"Description\",\n },\n // Content Tab - Style Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the text container\",\n defaultValue: \"background\",\n tab: \"content\",\n group: \"Style\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"The padding of the text container\",\n defaultValue: 4,\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n description: \"The border radius of the text container\",\n label: \"Border Radius\",\n tab: \"content\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"The border width of the text container\",\n defaultValue: \"none\",\n tab: \"content\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"The border color of the text container\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Design\",\n }),\n ],\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TextWidget-WKDCwape.mjs","names":[],"sources":["../../widgets/src/widgets/TextWidget.tsx"],"sourcesContent":["import type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getFontWeightField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n FontWeightOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport { AlignCenter, AlignLeft, AlignRight } from \"lucide-react\";\n\ntype TextAlignment = \"left\" | \"center\" | \"right\";\n\nconst textAlignmentClasses: Record<TextAlignment, string> = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n} as const;\n\ntype TextWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleFontWeight?: FontWeightOptions;\n titleColor?: ColorOptions;\n titleAlignment?: TextAlignment;\n\n // Description\n description?: string;\n descriptionFontSize?: FontSizeOptions;\n descriptionFontWeight?: FontWeightOptions;\n descriptionColor?: ColorOptions;\n descriptionAlignment?: TextAlignment;\n\n // Styling\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n};\n\nexport function TextWidget({\n titleEnabled = true,\n title = \"Text Widget\",\n titleFontSize = \"xl\",\n titleFontWeight = \"bold\",\n titleColor = \"foreground\",\n titleAlignment = \"left\",\n description = \"This is a text widget\",\n descriptionFontSize = \"md\",\n descriptionFontWeight = \"normal\",\n descriptionColor = \"foreground\",\n descriptionAlignment = \"left\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n className,\n ...props\n}: TextWidgetProps): 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 return (\n <div\n className={`bg-${backgroundColor} p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {titleEnabled && (\n <h2\n className={`text-${titleFontSize} text-${titleColor} ${textAlignmentClasses[titleAlignment]} font-header font-${titleFontWeight}`}\n >\n {title}\n </h2>\n )}\n <p\n className={`text-${descriptionFontSize} text-${descriptionColor} ${textAlignmentClasses[descriptionAlignment]} font-${descriptionFontWeight}`}\n >\n {description}\n </p>\n </div>\n );\n}\n\nexport const textWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"TextWidget\",\n displayName: \"Text Widget\",\n tabsConfig: [{ id: \"content\", label: \"Content\" }],\n dataSourceTargetProps: [\"title\", \"description\"],\n fields: [\n // Content Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the text\",\n defaultValue: true,\n tab: \"content\",\n group: \"Title\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"The title\",\n defaultValue: \"Heads up!\",\n tab: \"content\",\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: \"xl\",\n tab: \"content\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getFontWeightField({\n key: \"titleFontWeight\",\n label: \"Title Font Weight\",\n description: \"Font weight for the title\",\n defaultValue: \"bold\",\n tab: \"content\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"The color of the title\",\n defaultValue: \"foreground\",\n tab: \"content\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n {\n key: \"titleAlignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Text alignment for the title\",\n options: [\n { icon: AlignLeft, value: \"left\" },\n { icon: AlignCenter, value: \"center\" },\n { icon: AlignRight, value: \"right\" },\n ],\n defaultValue: \"left\",\n tab: \"content\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n // Content Tab - Description Group\n {\n key: \"description\",\n label: \"Description\",\n type: \"textarea\",\n description: \"The text message\",\n rows: 3,\n defaultValue:\n \"You can add components and dependencies to your app using the cli.\",\n tab: \"content\",\n group: \"Description\",\n },\n getFontSizeField({\n key: \"descriptionFontSize\",\n label: \"Description Font Size\",\n description: \"Font size for the text\",\n defaultValue: \"md\",\n tab: \"content\",\n group: \"Description\",\n }),\n getFontWeightField({\n key: \"descriptionFontWeight\",\n label: \"Description Font Weight\",\n description: \"Font weight for the text\",\n defaultValue: \"normal\",\n tab: \"content\",\n group: \"Description\",\n }),\n getColorField({\n key: \"descriptionColor\",\n label: \"Description Color\",\n description: \"The color of the text\",\n defaultValue: \"foreground\",\n tab: \"content\",\n group: \"Description\",\n }),\n {\n key: \"descriptionAlignment\",\n label: \"Alignment\",\n type: \"buttonGroup\",\n description: \"Text alignment for the description\",\n options: [\n { icon: AlignLeft, value: \"left\" },\n { icon: AlignCenter, value: \"center\" },\n { icon: AlignRight, value: \"right\" },\n ],\n defaultValue: \"left\",\n tab: \"content\",\n group: \"Description\",\n },\n // Content Tab - Style Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the text container\",\n defaultValue: \"background\",\n tab: \"content\",\n group: \"Style\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"The padding of the text container\",\n defaultValue: 4,\n tab: \"content\",\n group: \"Style\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n description: \"The border radius of the text container\",\n label: \"Border Radius\",\n tab: \"content\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"The border width of the text container\",\n defaultValue: \"none\",\n tab: \"content\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"The border color of the text container\",\n defaultValue: \"muted\",\n tab: \"content\",\n group: \"Design\",\n }),\n ],\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registries-CyjQkRM-.mjs","names":[],"sources":["../../core/src/registries/property-schema-types.ts","../../core/src/registries/field-helpers.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport type {\n WidgetType,\n WidgetSchema,\n AlignOptions,\n ColorOptions,\n FontSizeOptions,\n SectionLayoutType,\n StrictOmit,\n BorderRadiusOptions,\n} from \"../types\";\n\n/**\n * Tab configuration for organizing properties\n */\nexport interface TabConfig {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n}\n\n// ============================================================================\n// Property Field Types - Derive from constant for single source of truth\n// ============================================================================\n\n/**\n * Property field type constant - single source of truth for field types.\n * Use PROPERTY_FIELD_TYPES.text instead of \"text\" for type-safe comparisons.\n */\nexport const PROPERTY_FIELD_TYPES = {\n text: \"text\",\n textarea: \"textarea\",\n number: \"number\",\n boolean: \"boolean\",\n select: \"select\",\n color: \"color\",\n range: \"range\",\n dataSource: \"dataSource\",\n resource: \"resource\",\n image: \"image\",\n alignment: \"alignment\",\n slider: \"slider\",\n colorPicker: \"colorPicker\",\n sectionHeader: \"sectionHeader\",\n separator: \"separator\",\n buttonGroup: \"buttonGroup\",\n colorSelect: \"colorSelect\",\n sectionLayoutSelect: \"sectionLayoutSelect\",\n background: \"background\",\n contentPosition: \"contentPosition\",\n textSizeSelect: \"textSizeSelect\",\n cssUnit: \"cssUnit\",\n fontPicker: \"fontPicker\",\n stringArray: \"stringArray\",\n borderRadius: \"borderRadius\",\n screenPicker: \"screenPicker\",\n} as const;\n\n/**\n * Union type of all property field types, derived from PROPERTY_FIELD_TYPES constant.\n * @see deriving-typeof-for-object-keys pattern\n */\nexport type PropertyFieldType =\n (typeof PROPERTY_FIELD_TYPES)[keyof typeof PROPERTY_FIELD_TYPES];\n\n/**\n * Runtime validation for property field types.\n * @param value - The value to check\n * @returns true if value is a valid PropertyFieldType\n */\nexport function isPropertyFieldType(value: string): value is PropertyFieldType {\n return Object.values(PROPERTY_FIELD_TYPES).includes(\n value as PropertyFieldType,\n );\n}\n\n/**\n * Base schema for a property field\n */\nexport interface PropertyFieldSchema {\n /** Property key in the widget props */\n key: string;\n /** Display label for the field */\n label: string;\n /** Field type determines the input control */\n type: PropertyFieldType;\n /** Optional description/help text */\n description?: string;\n /** Optional default value */\n defaultValue?: unknown;\n /** Optional tab ID (must match a TabConfig id if widget has tabsConfig) */\n tab?: string;\n /** Optional group for organizing fields within a tab */\n group?: string;\n /**\n * @deprecated Use requiresKeyValue instead\n */\n requiresKeyToBeTrue?: string;\n /** Optional requires a specific key to have a specific value. Supports single condition or array (AND logic). */\n requiresKeyValue?:\n | { key: string; value: unknown }\n | Array<{ key: string; value: unknown }>;\n}\n\n/**\n * Text field schema\n */\nexport interface TextFieldSchema extends PropertyFieldSchema {\n type: \"text\";\n placeholder?: string;\n maxLength?: number;\n}\n\n/**\n * Textarea field schema\n */\nexport interface TextareaFieldSchema extends PropertyFieldSchema {\n type: \"textarea\";\n placeholder?: string;\n rows?: number;\n maxLength?: number;\n}\n\n/**\n * Number field schema\n */\nexport interface NumberFieldSchema extends PropertyFieldSchema {\n type: \"number\";\n min?: number;\n max?: number;\n step?: number;\n}\n\n/**\n * Boolean field schema\n */\nexport interface BooleanFieldSchema extends PropertyFieldSchema {\n type: \"boolean\";\n}\n\n/**\n * Select field schema with type-safe option values.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface SelectFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"select\";\n options: Array<{ label: string; value: T }>;\n defaultValue?: T;\n}\n\n/**\n * Color field schema\n */\nexport interface ColorFieldSchema extends PropertyFieldSchema {\n type: \"color\";\n}\n\n/**\n * Range slider field schema\n */\nexport interface RangeFieldSchema extends PropertyFieldSchema {\n type: \"range\";\n min: number;\n max: number;\n step?: number;\n}\n\n/**\n * Data source field schema for configuring widget data sources\n */\nexport interface DataSourceFieldSchema extends PropertyFieldSchema {\n type: \"dataSource\";\n}\n\n/**\n * Resource field schema for selecting a single resource from the selection modal\n */\nexport interface ResourceFieldSchema extends PropertyFieldSchema {\n type: \"resource\";\n /** Optional filter to specific shareable types */\n allowedTypes?: string[];\n}\n\n/**\n * Image field schema for selecting a single image from the image picker\n */\nexport interface ImageFieldSchema extends PropertyFieldSchema {\n type: \"image\";\n}\n\n/**\n * Alignment field schema\n */\nexport interface AlignmentFieldSchema extends PropertyFieldSchema {\n type: \"alignment\";\n options: {\n verticalEnabled: boolean;\n horizontalEnabled: boolean;\n };\n defaultValue?: AlignOptions;\n}\n\n/**\n * Slider field schema with optional unit suffix (e.g., \"rem\", \"px\")\n */\nexport interface SliderFieldSchema extends PropertyFieldSchema {\n type: \"slider\";\n min: number;\n max: number;\n step?: number;\n unit?: string;\n}\n\n/**\n * Color picker field schema with optional swatches\n */\nexport interface ColorPickerFieldSchema extends PropertyFieldSchema {\n type: \"colorPicker\";\n swatches?: string[];\n}\n\n/**\n * Section header field schema for visual grouping\n */\nexport interface SectionHeaderFieldSchema extends PropertyFieldSchema {\n type: \"sectionHeader\";\n subtitle?: string;\n}\n\n/**\n * Separator field schema for visual separation\n */\nexport interface SeparatorFieldSchema extends PropertyFieldSchema {\n type: \"separator\";\n}\n\n/**\n * Button group field schema.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface ButtonGroupFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"buttonGroup\";\n options: Array<{ label?: string; icon?: LucideIcon; value: T }>;\n defaultValue?: T;\n}\n\n/**\n * Color select field schema\n */\nexport interface ColorSelectFieldSchema extends PropertyFieldSchema {\n type: \"colorSelect\";\n defaultValue?: ColorOptions;\n excludeColors?: ColorOptions[];\n}\n\n/**\n * Section layout select field schema for visual masonry layout selector\n */\nexport interface SectionLayoutSelectFieldSchema extends PropertyFieldSchema {\n type: \"sectionLayoutSelect\";\n defaultValue?: SectionLayoutType;\n}\n\n/**\n * Background field combines resource selection and color properties.\n * Uses StrictOmit to exclude conflicting \"type\" discriminant from parents.\n */\nexport interface BackgroundFieldSchema\n extends\n StrictOmit<ResourceFieldSchema, \"type\">,\n StrictOmit<ColorFieldSchema, \"type\"> {\n type: \"background\";\n}\n\n/**\n * Content position field schema for 3x3 grid position picker\n */\nexport interface ContentPositionFieldSchema extends PropertyFieldSchema {\n type: \"contentPosition\";\n defaultValue?: string;\n}\n\n/**\n * Text size select field schema for visual font size selector\n */\nexport interface TextSizeSelectFieldSchema extends PropertyFieldSchema {\n type: \"textSizeSelect\";\n defaultValue?: FontSizeOptions;\n}\n\n/**\n * CSS unit type for height/width fields\n */\nexport type CssUnit = \"px\" | \"rem\" | \"vh\" | \"%\";\n\n/**\n * CSS unit field schema for numeric values with selectable units (px, rem, vh, %)\n */\nexport interface CssUnitFieldSchema extends PropertyFieldSchema {\n type: \"cssUnit\";\n minByUnit?: Partial<Record<CssUnit, number>>;\n maxByUnit?: Partial<Record<CssUnit, number>>;\n stepByUnit?: Partial<Record<CssUnit, number>>;\n allowedUnits?: CssUnit[];\n defaultUnit?: CssUnit;\n}\n\n/**\n * Font picker field schema for Google Fonts selection\n */\nexport interface FontPickerFieldSchema extends PropertyFieldSchema {\n type: \"fontPicker\";\n placeholder?: string;\n}\n\n/**\n * String array field schema for managing lists of text items\n */\nexport interface StringArrayFieldSchema extends PropertyFieldSchema {\n type: \"stringArray\";\n placeholder?: string;\n defaultValue?: string[];\n}\n\n/**\n * Border radius composite field schema for controlling 4 corners with a single field.\n * Maps to 4 individual widget prop keys (topLeft, topRight, bottomLeft, bottomRight).\n */\nexport interface BorderRadiusFieldSchema extends PropertyFieldSchema {\n type: \"borderRadius\";\n keys: {\n topLeft: string;\n topRight: string;\n bottomLeft: string;\n bottomRight: string;\n };\n defaultValue?: BorderRadiusOptions;\n}\n\n/**\n * Screen picker field schema for selecting a portal screen (navigation, system, or available)\n */\nexport interface ScreenPickerFieldSchema extends PropertyFieldSchema {\n type: \"screenPicker\";\n /** Whether to include system navigation items in the picker */\n includeSystemItems?: boolean;\n}\n\n/**\n * Union of all field schema types\n */\nexport type PropertyField =\n | TextFieldSchema\n | TextareaFieldSchema\n | NumberFieldSchema\n | BooleanFieldSchema\n | SelectFieldSchema<string | number>\n | ColorFieldSchema\n | RangeFieldSchema\n | DataSourceFieldSchema\n | ResourceFieldSchema\n | ImageFieldSchema\n | AlignmentFieldSchema\n | SliderFieldSchema\n | ColorPickerFieldSchema\n | SectionHeaderFieldSchema\n | SeparatorFieldSchema\n | ButtonGroupFieldSchema<string | number>\n | ColorSelectFieldSchema\n | SectionLayoutSelectFieldSchema\n | BackgroundFieldSchema\n | ContentPositionFieldSchema\n | TextSizeSelectFieldSchema\n | CssUnitFieldSchema\n | FontPickerFieldSchema\n | StringArrayFieldSchema\n | BorderRadiusFieldSchema\n | ScreenPickerFieldSchema;\n\n/**\n * Schema for per-item configuration in custom data sources.\n * Widgets can define this to allow users to configure widget-specific\n * settings for each selected item (e.g., title, description, button).\n */\nexport interface ItemConfigSchema {\n /** Fields available for per-item configuration */\n fields: PropertyField[];\n /** Optional description shown at top of item config panel */\n description?: string;\n}\n\n/**\n * Schema for a widget's editable properties\n */\nexport interface WidgetPropertySchema {\n /** Widget type this schema applies to */\n widgetType: WidgetType;\n /** Display name for the widget */\n displayName: string;\n /** Optional tab configuration - if present, tabs are enabled */\n tabsConfig?: TabConfig[];\n /** Editable property fields */\n fields: PropertyField[];\n /** Optional custom validator function */\n validate?: (props: Record<string, unknown>) => string | null;\n /** Props that can be populated from data sources */\n dataSourceTargetProps?: string[];\n /** Optional schema for per-item configurations in custom data sources */\n itemConfigSchema?: ItemConfigSchema;\n}\n\n/**\n * Registry mapping widget types to their property schemas\n */\nexport type PropertySchemaRegistry = Record<WidgetType, WidgetPropertySchema>;\n\n/**\n * Group property fields by their group property\n */\nexport function groupPropertyFields(\n fields: readonly PropertyField[],\n): Record<string, PropertyField[]> {\n const grouped: Record<string, PropertyField[]> = {};\n\n fields.forEach((field) => {\n const group = field.group || \"General\";\n if (!grouped[group]) {\n grouped[group] = [];\n }\n grouped[group].push(field);\n });\n\n return grouped;\n}\n\n/**\n * Extract current values from widget props based on property fields\n */\nexport function extractPropertyValues(\n widget: Readonly<WidgetSchema>,\n fields: readonly PropertyField[],\n): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n\n fields.forEach((field) => {\n // For borderRadius composite fields, skip the top-level key —\n // it is a schema grouping identifier, not a real widget prop.\n if (field.type === \"borderRadius\") {\n for (const subKey of Object.values(field.keys)) {\n const subValue = widget.props[subKey];\n values[subKey] = subValue !== undefined ? subValue : field.defaultValue;\n }\n return;\n }\n\n const value = widget.props[field.key];\n values[field.key] = value !== undefined ? value : field.defaultValue;\n });\n\n return values;\n}\n\n/**\n * Apply property values to widget props\n */\nexport function applyPropertyValues(\n widget: Readonly<WidgetSchema>,\n values: Readonly<Record<string, unknown>>,\n): WidgetSchema {\n return {\n ...widget,\n props: {\n ...widget.props,\n ...values,\n },\n };\n}\n","import type {\n BorderRadiusFieldSchema,\n ButtonGroupFieldSchema,\n ColorSelectFieldSchema,\n CssUnitFieldSchema,\n TextSizeSelectFieldSchema,\n} from \"./property-schema-types\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontWeightOptions,\n PaddingOptions,\n ButtonSizeOptions,\n GapOptions,\n} from \"../types\";\nimport { Ban } from \"lucide-react\";\n\nexport const getColorField = (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n): ColorSelectFieldSchema => {\n return {\n ...props,\n type: \"colorSelect\",\n };\n};\n\nexport const getBorderRadiusField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderRadiusOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderRadiusOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, value: \"none\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n { label: \"FULL\", value: \"full\" },\n ],\n };\n};\n\nexport const getPaddingField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<PaddingOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<PaddingOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, value: 0 },\n { label: \"SM\", value: 2 },\n { label: \"MD\", value: 4 },\n { label: \"LG\", value: 6 },\n { label: \"XL\", value: 8 },\n { label: \"FULL\", value: 10 },\n ],\n };\n};\n\nexport const getButtonSizeField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<ButtonSizeOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<ButtonSizeOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"default\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getFontWeightField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<FontWeightOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<FontWeightOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"Normal\", value: \"normal\" },\n { label: \"Medium\", value: \"medium\" },\n { label: \"Semibold\", value: \"semibold\" },\n { label: \"Bold\", value: \"bold\" },\n ],\n };\n};\n\nexport const getFontSizeField = (\n props: Readonly<Omit<TextSizeSelectFieldSchema, \"type\">>,\n): TextSizeSelectFieldSchema => {\n return {\n ...props,\n type: \"textSizeSelect\",\n };\n};\n\nexport const getGapField = (\n props: Readonly<Omit<ButtonGroupFieldSchema<GapOptions>, \"options\" | \"type\">>,\n): ButtonGroupFieldSchema<GapOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, value: \"none\" },\n { label: \"XS\", value: \"xs\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getHeightField = (\n props: Readonly<\n Omit<\n CssUnitFieldSchema,\n \"type\" | \"minByUnit\" | \"maxByUnit\" | \"stepByUnit\" | \"allowedUnits\"\n >\n >,\n): CssUnitFieldSchema => {\n return {\n ...props,\n type: \"cssUnit\",\n allowedUnits: [\"px\", \"vh\", \"rem\"],\n minByUnit: { px: 10, vh: 1, rem: 1 },\n maxByUnit: { px: 1200, vh: 100, rem: 75 },\n stepByUnit: { px: 10, vh: 1, rem: 1 },\n };\n};\n\nexport const getBorderRadiusCompositeField = (\n props: Readonly<\n Omit<BorderRadiusFieldSchema, \"type\" | \"keys\"> & {\n keys?: BorderRadiusFieldSchema[\"keys\"];\n }\n >,\n): BorderRadiusFieldSchema => {\n return {\n ...props,\n type: \"borderRadius\",\n keys: props.keys ?? {\n topLeft: \"borderRadiusTL\",\n topRight: \"borderRadiusTR\",\n bottomLeft: \"borderRadiusBL\",\n bottomRight: \"borderRadiusBR\",\n },\n };\n};\n\n/**\n * Gap value mapping - use `as const satisfies` for compile-time validation\n * with literal type preservation.\n */\nexport const gapValues: {\n readonly none: 0;\n readonly xs: 1;\n readonly sm: 2;\n readonly md: 4;\n readonly lg: 6;\n readonly xl: 8;\n} = {\n none: 0,\n xs: 1,\n sm: 2,\n md: 4,\n lg: 6,\n xl: 8,\n} as const satisfies Record<GapOptions, number>;\n\nexport const getBorderWidthField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderWidthOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderWidthOptions> => ({\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, value: \"none\" },\n { label: \"THIN\", value: \"thin\" },\n { label: \"MD\", value: \"medium\" },\n { label: \"THICK\", value: \"thick\" },\n ],\n});\n\nexport const getBorderColorField: (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n) => ColorSelectFieldSchema = getColorField;\n\n/**\n * Border width class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderWidthClasses: {\n readonly none: \"border-0\";\n readonly thin: \"border\";\n readonly medium: \"border-2\";\n readonly thick: \"border-4\";\n} = {\n none: \"border-0\",\n thin: \"border\",\n medium: \"border-2\",\n thick: \"border-4\",\n} as const satisfies Record<BorderWidthOptions, string>;\n\n/**\n * Border color class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderColorClasses: {\n readonly background: \"border-background\";\n readonly foreground: \"border-foreground\";\n readonly primary: \"border-primary\";\n readonly secondary: \"border-secondary\";\n readonly accent: \"border-accent\";\n readonly border: \"border-border\";\n readonly muted: \"border-muted\";\n readonly destructive: \"border-destructive\";\n readonly transparent: \"border-transparent\";\n} = {\n background: \"border-background\",\n foreground: \"border-foreground\",\n primary: \"border-primary\",\n secondary: \"border-secondary\",\n accent: \"border-accent\",\n border: \"border-border\",\n muted: \"border-muted\",\n destructive: \"border-destructive\",\n transparent: \"border-transparent\",\n} as const satisfies Record<ColorOptions, string>;\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registries-GJMHub-Q.cjs","names":["Ban"],"sources":["../../core/src/registries/property-schema-types.ts","../../core/src/registries/field-helpers.ts"],"sourcesContent":["import type { LucideIcon } from \"lucide-react\";\nimport type {\n WidgetType,\n WidgetSchema,\n AlignOptions,\n ColorOptions,\n FontSizeOptions,\n SectionLayoutType,\n StrictOmit,\n BorderRadiusOptions,\n} from \"../types\";\n\n/**\n * Tab configuration for organizing properties\n */\nexport interface TabConfig {\n /** Unique identifier for the tab */\n id: string;\n /** Display label for the tab */\n label: string;\n}\n\n// ============================================================================\n// Property Field Types - Derive from constant for single source of truth\n// ============================================================================\n\n/**\n * Property field type constant - single source of truth for field types.\n * Use PROPERTY_FIELD_TYPES.text instead of \"text\" for type-safe comparisons.\n */\nexport const PROPERTY_FIELD_TYPES = {\n text: \"text\",\n textarea: \"textarea\",\n number: \"number\",\n boolean: \"boolean\",\n select: \"select\",\n color: \"color\",\n range: \"range\",\n dataSource: \"dataSource\",\n resource: \"resource\",\n image: \"image\",\n alignment: \"alignment\",\n slider: \"slider\",\n colorPicker: \"colorPicker\",\n sectionHeader: \"sectionHeader\",\n separator: \"separator\",\n buttonGroup: \"buttonGroup\",\n colorSelect: \"colorSelect\",\n sectionLayoutSelect: \"sectionLayoutSelect\",\n background: \"background\",\n contentPosition: \"contentPosition\",\n textSizeSelect: \"textSizeSelect\",\n cssUnit: \"cssUnit\",\n fontPicker: \"fontPicker\",\n stringArray: \"stringArray\",\n borderRadius: \"borderRadius\",\n screenPicker: \"screenPicker\",\n} as const;\n\n/**\n * Union type of all property field types, derived from PROPERTY_FIELD_TYPES constant.\n * @see deriving-typeof-for-object-keys pattern\n */\nexport type PropertyFieldType =\n (typeof PROPERTY_FIELD_TYPES)[keyof typeof PROPERTY_FIELD_TYPES];\n\n/**\n * Runtime validation for property field types.\n * @param value - The value to check\n * @returns true if value is a valid PropertyFieldType\n */\nexport function isPropertyFieldType(value: string): value is PropertyFieldType {\n return Object.values(PROPERTY_FIELD_TYPES).includes(\n value as PropertyFieldType,\n );\n}\n\n/**\n * Base schema for a property field\n */\nexport interface PropertyFieldSchema {\n /** Property key in the widget props */\n key: string;\n /** Display label for the field */\n label: string;\n /** Field type determines the input control */\n type: PropertyFieldType;\n /** Optional description/help text */\n description?: string;\n /** Optional default value */\n defaultValue?: unknown;\n /** Optional tab ID (must match a TabConfig id if widget has tabsConfig) */\n tab?: string;\n /** Optional group for organizing fields within a tab */\n group?: string;\n /**\n * @deprecated Use requiresKeyValue instead\n */\n requiresKeyToBeTrue?: string;\n /** Optional requires a specific key to have a specific value. Supports single condition or array (AND logic). */\n requiresKeyValue?:\n | { key: string; value: unknown }\n | Array<{ key: string; value: unknown }>;\n}\n\n/**\n * Text field schema\n */\nexport interface TextFieldSchema extends PropertyFieldSchema {\n type: \"text\";\n placeholder?: string;\n maxLength?: number;\n}\n\n/**\n * Textarea field schema\n */\nexport interface TextareaFieldSchema extends PropertyFieldSchema {\n type: \"textarea\";\n placeholder?: string;\n rows?: number;\n maxLength?: number;\n}\n\n/**\n * Number field schema\n */\nexport interface NumberFieldSchema extends PropertyFieldSchema {\n type: \"number\";\n min?: number;\n max?: number;\n step?: number;\n}\n\n/**\n * Boolean field schema\n */\nexport interface BooleanFieldSchema extends PropertyFieldSchema {\n type: \"boolean\";\n}\n\n/**\n * Select field schema with type-safe option values.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface SelectFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"select\";\n options: Array<{ label: string; value: T }>;\n defaultValue?: T;\n}\n\n/**\n * Color field schema\n */\nexport interface ColorFieldSchema extends PropertyFieldSchema {\n type: \"color\";\n}\n\n/**\n * Range slider field schema\n */\nexport interface RangeFieldSchema extends PropertyFieldSchema {\n type: \"range\";\n min: number;\n max: number;\n step?: number;\n}\n\n/**\n * Data source field schema for configuring widget data sources\n */\nexport interface DataSourceFieldSchema extends PropertyFieldSchema {\n type: \"dataSource\";\n}\n\n/**\n * Resource field schema for selecting a single resource from the selection modal\n */\nexport interface ResourceFieldSchema extends PropertyFieldSchema {\n type: \"resource\";\n /** Optional filter to specific shareable types */\n allowedTypes?: string[];\n}\n\n/**\n * Image field schema for selecting a single image from the image picker\n */\nexport interface ImageFieldSchema extends PropertyFieldSchema {\n type: \"image\";\n}\n\n/**\n * Alignment field schema\n */\nexport interface AlignmentFieldSchema extends PropertyFieldSchema {\n type: \"alignment\";\n options: {\n verticalEnabled: boolean;\n horizontalEnabled: boolean;\n };\n defaultValue?: AlignOptions;\n}\n\n/**\n * Slider field schema with optional unit suffix (e.g., \"rem\", \"px\")\n */\nexport interface SliderFieldSchema extends PropertyFieldSchema {\n type: \"slider\";\n min: number;\n max: number;\n step?: number;\n unit?: string;\n}\n\n/**\n * Color picker field schema with optional swatches\n */\nexport interface ColorPickerFieldSchema extends PropertyFieldSchema {\n type: \"colorPicker\";\n swatches?: string[];\n}\n\n/**\n * Section header field schema for visual grouping\n */\nexport interface SectionHeaderFieldSchema extends PropertyFieldSchema {\n type: \"sectionHeader\";\n subtitle?: string;\n}\n\n/**\n * Separator field schema for visual separation\n */\nexport interface SeparatorFieldSchema extends PropertyFieldSchema {\n type: \"separator\";\n}\n\n/**\n * Button group field schema.\n * Uses StrictOmit to ensure \"defaultValue\" key exists on PropertyFieldSchema.\n */\nexport interface ButtonGroupFieldSchema<\n T extends string | number = string | number,\n> extends StrictOmit<PropertyFieldSchema, \"defaultValue\"> {\n type: \"buttonGroup\";\n options: Array<{ label?: string; icon?: LucideIcon; value: T }>;\n defaultValue?: T;\n}\n\n/**\n * Color select field schema\n */\nexport interface ColorSelectFieldSchema extends PropertyFieldSchema {\n type: \"colorSelect\";\n defaultValue?: ColorOptions;\n excludeColors?: ColorOptions[];\n}\n\n/**\n * Section layout select field schema for visual masonry layout selector\n */\nexport interface SectionLayoutSelectFieldSchema extends PropertyFieldSchema {\n type: \"sectionLayoutSelect\";\n defaultValue?: SectionLayoutType;\n}\n\n/**\n * Background field combines resource selection and color properties.\n * Uses StrictOmit to exclude conflicting \"type\" discriminant from parents.\n */\nexport interface BackgroundFieldSchema\n extends\n StrictOmit<ResourceFieldSchema, \"type\">,\n StrictOmit<ColorFieldSchema, \"type\"> {\n type: \"background\";\n}\n\n/**\n * Content position field schema for 3x3 grid position picker\n */\nexport interface ContentPositionFieldSchema extends PropertyFieldSchema {\n type: \"contentPosition\";\n defaultValue?: string;\n}\n\n/**\n * Text size select field schema for visual font size selector\n */\nexport interface TextSizeSelectFieldSchema extends PropertyFieldSchema {\n type: \"textSizeSelect\";\n defaultValue?: FontSizeOptions;\n}\n\n/**\n * CSS unit type for height/width fields\n */\nexport type CssUnit = \"px\" | \"rem\" | \"vh\" | \"%\";\n\n/**\n * CSS unit field schema for numeric values with selectable units (px, rem, vh, %)\n */\nexport interface CssUnitFieldSchema extends PropertyFieldSchema {\n type: \"cssUnit\";\n minByUnit?: Partial<Record<CssUnit, number>>;\n maxByUnit?: Partial<Record<CssUnit, number>>;\n stepByUnit?: Partial<Record<CssUnit, number>>;\n allowedUnits?: CssUnit[];\n defaultUnit?: CssUnit;\n}\n\n/**\n * Font picker field schema for Google Fonts selection\n */\nexport interface FontPickerFieldSchema extends PropertyFieldSchema {\n type: \"fontPicker\";\n placeholder?: string;\n}\n\n/**\n * String array field schema for managing lists of text items\n */\nexport interface StringArrayFieldSchema extends PropertyFieldSchema {\n type: \"stringArray\";\n placeholder?: string;\n defaultValue?: string[];\n}\n\n/**\n * Border radius composite field schema for controlling 4 corners with a single field.\n * Maps to 4 individual widget prop keys (topLeft, topRight, bottomLeft, bottomRight).\n */\nexport interface BorderRadiusFieldSchema extends PropertyFieldSchema {\n type: \"borderRadius\";\n keys: {\n topLeft: string;\n topRight: string;\n bottomLeft: string;\n bottomRight: string;\n };\n defaultValue?: BorderRadiusOptions;\n}\n\n/**\n * Screen picker field schema for selecting a portal screen (navigation, system, or available)\n */\nexport interface ScreenPickerFieldSchema extends PropertyFieldSchema {\n type: \"screenPicker\";\n /** Whether to include system navigation items in the picker */\n includeSystemItems?: boolean;\n}\n\n/**\n * Union of all field schema types\n */\nexport type PropertyField =\n | TextFieldSchema\n | TextareaFieldSchema\n | NumberFieldSchema\n | BooleanFieldSchema\n | SelectFieldSchema<string | number>\n | ColorFieldSchema\n | RangeFieldSchema\n | DataSourceFieldSchema\n | ResourceFieldSchema\n | ImageFieldSchema\n | AlignmentFieldSchema\n | SliderFieldSchema\n | ColorPickerFieldSchema\n | SectionHeaderFieldSchema\n | SeparatorFieldSchema\n | ButtonGroupFieldSchema<string | number>\n | ColorSelectFieldSchema\n | SectionLayoutSelectFieldSchema\n | BackgroundFieldSchema\n | ContentPositionFieldSchema\n | TextSizeSelectFieldSchema\n | CssUnitFieldSchema\n | FontPickerFieldSchema\n | StringArrayFieldSchema\n | BorderRadiusFieldSchema\n | ScreenPickerFieldSchema;\n\n/**\n * Schema for per-item configuration in custom data sources.\n * Widgets can define this to allow users to configure widget-specific\n * settings for each selected item (e.g., title, description, button).\n */\nexport interface ItemConfigSchema {\n /** Fields available for per-item configuration */\n fields: PropertyField[];\n /** Optional description shown at top of item config panel */\n description?: string;\n}\n\n/**\n * Schema for a widget's editable properties\n */\nexport interface WidgetPropertySchema {\n /** Widget type this schema applies to */\n widgetType: WidgetType;\n /** Display name for the widget */\n displayName: string;\n /** Optional tab configuration - if present, tabs are enabled */\n tabsConfig?: TabConfig[];\n /** Editable property fields */\n fields: PropertyField[];\n /** Optional custom validator function */\n validate?: (props: Record<string, unknown>) => string | null;\n /** Props that can be populated from data sources */\n dataSourceTargetProps?: string[];\n /** Optional schema for per-item configurations in custom data sources */\n itemConfigSchema?: ItemConfigSchema;\n}\n\n/**\n * Registry mapping widget types to their property schemas\n */\nexport type PropertySchemaRegistry = Record<WidgetType, WidgetPropertySchema>;\n\n/**\n * Group property fields by their group property\n */\nexport function groupPropertyFields(\n fields: readonly PropertyField[],\n): Record<string, PropertyField[]> {\n const grouped: Record<string, PropertyField[]> = {};\n\n fields.forEach((field) => {\n const group = field.group || \"General\";\n if (!grouped[group]) {\n grouped[group] = [];\n }\n grouped[group].push(field);\n });\n\n return grouped;\n}\n\n/**\n * Extract current values from widget props based on property fields\n */\nexport function extractPropertyValues(\n widget: Readonly<WidgetSchema>,\n fields: readonly PropertyField[],\n): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n\n fields.forEach((field) => {\n // For borderRadius composite fields, skip the top-level key —\n // it is a schema grouping identifier, not a real widget prop.\n if (field.type === \"borderRadius\") {\n for (const subKey of Object.values(field.keys)) {\n const subValue = widget.props[subKey];\n values[subKey] = subValue !== undefined ? subValue : field.defaultValue;\n }\n return;\n }\n\n const value = widget.props[field.key];\n values[field.key] = value !== undefined ? value : field.defaultValue;\n });\n\n return values;\n}\n\n/**\n * Apply property values to widget props\n */\nexport function applyPropertyValues(\n widget: Readonly<WidgetSchema>,\n values: Readonly<Record<string, unknown>>,\n): WidgetSchema {\n return {\n ...widget,\n props: {\n ...widget.props,\n ...values,\n },\n };\n}\n","import type {\n BorderRadiusFieldSchema,\n ButtonGroupFieldSchema,\n ColorSelectFieldSchema,\n CssUnitFieldSchema,\n TextSizeSelectFieldSchema,\n} from \"./property-schema-types\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontWeightOptions,\n PaddingOptions,\n ButtonSizeOptions,\n GapOptions,\n} from \"../types\";\nimport { Ban } from \"lucide-react\";\n\nexport const getColorField = (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n): ColorSelectFieldSchema => {\n return {\n ...props,\n type: \"colorSelect\",\n };\n};\n\nexport const getBorderRadiusField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderRadiusOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderRadiusOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, value: \"none\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n { label: \"FULL\", value: \"full\" },\n ],\n };\n};\n\nexport const getPaddingField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<PaddingOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<PaddingOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, value: 0 },\n { label: \"SM\", value: 2 },\n { label: \"MD\", value: 4 },\n { label: \"LG\", value: 6 },\n { label: \"XL\", value: 8 },\n { label: \"FULL\", value: 10 },\n ],\n };\n};\n\nexport const getButtonSizeField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<ButtonSizeOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<ButtonSizeOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"default\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getFontWeightField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<FontWeightOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<FontWeightOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { label: \"Normal\", value: \"normal\" },\n { label: \"Medium\", value: \"medium\" },\n { label: \"Semibold\", value: \"semibold\" },\n { label: \"Bold\", value: \"bold\" },\n ],\n };\n};\n\nexport const getFontSizeField = (\n props: Readonly<Omit<TextSizeSelectFieldSchema, \"type\">>,\n): TextSizeSelectFieldSchema => {\n return {\n ...props,\n type: \"textSizeSelect\",\n };\n};\n\nexport const getGapField = (\n props: Readonly<Omit<ButtonGroupFieldSchema<GapOptions>, \"options\" | \"type\">>,\n): ButtonGroupFieldSchema<GapOptions> => {\n return {\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, value: \"none\" },\n { label: \"XS\", value: \"xs\" },\n { label: \"SM\", value: \"sm\" },\n { label: \"MD\", value: \"md\" },\n { label: \"LG\", value: \"lg\" },\n { label: \"XL\", value: \"xl\" },\n ],\n };\n};\n\nexport const getHeightField = (\n props: Readonly<\n Omit<\n CssUnitFieldSchema,\n \"type\" | \"minByUnit\" | \"maxByUnit\" | \"stepByUnit\" | \"allowedUnits\"\n >\n >,\n): CssUnitFieldSchema => {\n return {\n ...props,\n type: \"cssUnit\",\n allowedUnits: [\"px\", \"vh\", \"rem\"],\n minByUnit: { px: 10, vh: 1, rem: 1 },\n maxByUnit: { px: 1200, vh: 100, rem: 75 },\n stepByUnit: { px: 10, vh: 1, rem: 1 },\n };\n};\n\nexport const getBorderRadiusCompositeField = (\n props: Readonly<\n Omit<BorderRadiusFieldSchema, \"type\" | \"keys\"> & {\n keys?: BorderRadiusFieldSchema[\"keys\"];\n }\n >,\n): BorderRadiusFieldSchema => {\n return {\n ...props,\n type: \"borderRadius\",\n keys: props.keys ?? {\n topLeft: \"borderRadiusTL\",\n topRight: \"borderRadiusTR\",\n bottomLeft: \"borderRadiusBL\",\n bottomRight: \"borderRadiusBR\",\n },\n };\n};\n\n/**\n * Gap value mapping - use `as const satisfies` for compile-time validation\n * with literal type preservation.\n */\nexport const gapValues: {\n readonly none: 0;\n readonly xs: 1;\n readonly sm: 2;\n readonly md: 4;\n readonly lg: 6;\n readonly xl: 8;\n} = {\n none: 0,\n xs: 1,\n sm: 2,\n md: 4,\n lg: 6,\n xl: 8,\n} as const satisfies Record<GapOptions, number>;\n\nexport const getBorderWidthField = (\n props: Readonly<\n Omit<ButtonGroupFieldSchema<BorderWidthOptions>, \"options\" | \"type\">\n >,\n): ButtonGroupFieldSchema<BorderWidthOptions> => ({\n ...props,\n type: \"buttonGroup\",\n options: [\n { icon: Ban, value: \"none\" },\n { label: \"THIN\", value: \"thin\" },\n { label: \"MD\", value: \"medium\" },\n { label: \"THICK\", value: \"thick\" },\n ],\n});\n\nexport const getBorderColorField: (\n props: Readonly<Omit<ColorSelectFieldSchema, \"type\">>,\n) => ColorSelectFieldSchema = getColorField;\n\n/**\n * Border width class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderWidthClasses: {\n readonly none: \"border-0\";\n readonly thin: \"border\";\n readonly medium: \"border-2\";\n readonly thick: \"border-4\";\n} = {\n none: \"border-0\",\n thin: \"border\",\n medium: \"border-2\",\n thick: \"border-4\",\n} as const satisfies Record<BorderWidthOptions, string>;\n\n/**\n * Border color class mapping - full literal Tailwind classes for scanner.\n */\nexport const borderColorClasses: {\n readonly background: \"border-background\";\n readonly foreground: \"border-foreground\";\n readonly primary: \"border-primary\";\n readonly secondary: \"border-secondary\";\n readonly accent: \"border-accent\";\n readonly border: \"border-border\";\n readonly muted: \"border-muted\";\n readonly destructive: \"border-destructive\";\n readonly transparent: \"border-transparent\";\n} = {\n background: \"border-background\",\n foreground: \"border-foreground\",\n primary: \"border-primary\",\n secondary: \"border-secondary\",\n accent: \"border-accent\",\n border: \"border-border\",\n muted: \"border-muted\",\n destructive: \"border-destructive\",\n transparent: \"border-transparent\",\n} as const satisfies Record<ColorOptions, string>;\n"],"mappings":"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"}
|