@fluid-app/portal-sdk 0.1.239 → 0.1.241

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/{CalendarWidget-BXxNxHDV.mjs → CalendarWidget-C03VcDLQ.mjs} +2 -2
  2. package/dist/{CalendarWidget-BXxNxHDV.mjs.map → CalendarWidget-C03VcDLQ.mjs.map} +1 -1
  3. package/dist/{CalendarWidget-VjQXZW8B.cjs → CalendarWidget-C4Dv_TUk.cjs} +2 -2
  4. package/dist/{CalendarWidget-VjQXZW8B.cjs.map → CalendarWidget-C4Dv_TUk.cjs.map} +1 -1
  5. package/dist/{CardWidget-BNkMlxQ3.mjs → CardWidget-2wcjCf2M.mjs} +2 -2
  6. package/dist/{CardWidget-BNkMlxQ3.mjs.map → CardWidget-2wcjCf2M.mjs.map} +1 -1
  7. package/dist/{CardWidget-CraWMttj.cjs → CardWidget-BQl-8Xrt.cjs} +3 -3
  8. package/dist/{CardWidget-C3I9OwgS.cjs → CardWidget-D-KEikO_.cjs} +2 -2
  9. package/dist/{CardWidget-C3I9OwgS.cjs.map → CardWidget-D-KEikO_.cjs.map} +1 -1
  10. package/dist/{CarouselWidget-p8Z6L-G5.mjs → CarouselWidget-Cn5P4FVN.mjs} +92 -83
  11. package/dist/CarouselWidget-Cn5P4FVN.mjs.map +1 -0
  12. package/dist/{CarouselWidget-CiKlooUF.cjs → CarouselWidget-Cu1b3ERq.cjs} +92 -83
  13. package/dist/CarouselWidget-Cu1b3ERq.cjs.map +1 -0
  14. package/dist/{CatchUpWidget-B9DQlzd_.mjs → CatchUpWidget-B9CI7lq0.mjs} +2 -2
  15. package/dist/{CatchUpWidget-B9DQlzd_.mjs.map → CatchUpWidget-B9CI7lq0.mjs.map} +1 -1
  16. package/dist/{CatchUpWidget-SY7hOHk6.cjs → CatchUpWidget-BzgybvuC.cjs} +2 -2
  17. package/dist/{CatchUpWidget-SY7hOHk6.cjs.map → CatchUpWidget-BzgybvuC.cjs.map} +1 -1
  18. package/dist/ContainerWidget-CDbB8c0E.cjs +8 -0
  19. package/dist/{ContainerWidget-CpwvcxFm.mjs → ContainerWidget-DNenbORS.mjs} +2 -2
  20. package/dist/{ContainerWidget-CpwvcxFm.mjs.map → ContainerWidget-DNenbORS.mjs.map} +1 -1
  21. package/dist/{ContainerWidget-BXpdj06u.cjs → ContainerWidget-DbAhQKbY.cjs} +2 -2
  22. package/dist/{ContainerWidget-BXpdj06u.cjs.map → ContainerWidget-DbAhQKbY.cjs.map} +1 -1
  23. package/dist/{FluidProvider-DL5rChtj.mjs → FluidProvider-BwMwMCxW.mjs} +23 -23
  24. package/dist/{FluidProvider-DL5rChtj.mjs.map → FluidProvider-BwMwMCxW.mjs.map} +1 -1
  25. package/dist/{FluidProvider-D_PHVlUU.cjs → FluidProvider-eT4gA6Io.cjs} +23 -23
  26. package/dist/{FluidProvider-D_PHVlUU.cjs.map → FluidProvider-eT4gA6Io.cjs.map} +1 -1
  27. package/dist/{LayoutWidget-BIfNHlVE.cjs → LayoutWidget-Bt2I2XMy.cjs} +2 -2
  28. package/dist/{LayoutWidget-BIfNHlVE.cjs.map → LayoutWidget-Bt2I2XMy.cjs.map} +1 -1
  29. package/dist/{LayoutWidget-LdF_cKrB.cjs → LayoutWidget-DKqZgCMu.cjs} +3 -3
  30. package/dist/{LayoutWidget-CC3oK78H.mjs → LayoutWidget-UI5fbsx4.mjs} +2 -2
  31. package/dist/{LayoutWidget-CC3oK78H.mjs.map → LayoutWidget-UI5fbsx4.mjs.map} +1 -1
  32. package/dist/{MessagingScreen-Dxy2VQbO.cjs → MessagingScreen-BHYX1Kc6.cjs} +14 -14
  33. package/dist/{MessagingScreen-mt1u3Bs1.mjs → MessagingScreen-CZddjqma.mjs} +2 -2
  34. package/dist/{MessagingScreen-mt1u3Bs1.mjs.map → MessagingScreen-CZddjqma.mjs.map} +1 -1
  35. package/dist/{MessagingScreen-Dkh3Dsp7.cjs → MessagingScreen-D3S230Ba.cjs} +2 -2
  36. package/dist/{MessagingScreen-Dkh3Dsp7.cjs.map → MessagingScreen-D3S230Ba.cjs.map} +1 -1
  37. package/dist/{MySiteWidget-BnjPrQxE.mjs → MySiteWidget-CQNASVaF.mjs} +2 -2
  38. package/dist/{MySiteWidget-BnjPrQxE.mjs.map → MySiteWidget-CQNASVaF.mjs.map} +1 -1
  39. package/dist/{MySiteWidget-C8eFWHOT.cjs → MySiteWidget-CYiH2lmX.cjs} +2 -2
  40. package/dist/{MySiteWidget-C8eFWHOT.cjs.map → MySiteWidget-CYiH2lmX.cjs.map} +1 -1
  41. package/dist/{PointsWidget-C2KB4k48.mjs → PointsWidget-BwA6aGVZ.mjs} +5 -8
  42. package/dist/PointsWidget-BwA6aGVZ.mjs.map +1 -0
  43. package/dist/{PointsWidget-DLp-PYus.cjs → PointsWidget-D1FV8l1h.cjs} +5 -8
  44. package/dist/PointsWidget-D1FV8l1h.cjs.map +1 -0
  45. package/dist/{ProfileScreen-ChCZZ91o.cjs → ProfileScreen-BYJj4D1W.cjs} +14 -14
  46. package/dist/{ProfileScreen-BMe-dQi7.cjs → ProfileScreen-DAujb81k.cjs} +2 -2
  47. package/dist/{ProfileScreen-BMe-dQi7.cjs.map → ProfileScreen-DAujb81k.cjs.map} +1 -1
  48. package/dist/{ProfileScreen-_1GlBr7z.mjs → ProfileScreen-DlMEqXXg.mjs} +2 -2
  49. package/dist/{ProfileScreen-_1GlBr7z.mjs.map → ProfileScreen-DlMEqXXg.mjs.map} +1 -1
  50. package/dist/{RecentActivityWidget-DelPdiwR.mjs → RecentActivityWidget-D1AlZgfV.mjs} +2 -2
  51. package/dist/{RecentActivityWidget-DelPdiwR.mjs.map → RecentActivityWidget-D1AlZgfV.mjs.map} +1 -1
  52. package/dist/{RecentActivityWidget-BNW9aFT4.cjs → RecentActivityWidget-DNyhUZNs.cjs} +2 -2
  53. package/dist/{RecentActivityWidget-BNW9aFT4.cjs.map → RecentActivityWidget-DNyhUZNs.cjs.map} +1 -1
  54. package/dist/{ScreenRenderer-ClYgfQf_.mjs → ScreenRenderer-Cl2aAJ7D.mjs} +2 -2
  55. package/dist/{ScreenRenderer-ClYgfQf_.mjs.map → ScreenRenderer-Cl2aAJ7D.mjs.map} +1 -1
  56. package/dist/{ScreenRenderer-Ct1w4PNu.cjs → ScreenRenderer-xH01YkEQ.cjs} +2 -2
  57. package/dist/{ScreenRenderer-Ct1w4PNu.cjs.map → ScreenRenderer-xH01YkEQ.cjs.map} +1 -1
  58. package/dist/{ShopScreen-DWLGH2gt.cjs → ShopScreen-1yvcCk7l.cjs} +6 -2
  59. package/dist/ShopScreen-1yvcCk7l.cjs.map +1 -0
  60. package/dist/{ShopScreen-CZ_290EP.cjs → ShopScreen-6nEKrNjK.cjs} +14 -14
  61. package/dist/{ShopScreen-BBfOte5o.mjs → ShopScreen-U7G6Jf67.mjs} +6 -2
  62. package/dist/ShopScreen-U7G6Jf67.mjs.map +1 -0
  63. package/dist/{ToDoWidget-CYDsZA0Z.mjs → ToDoWidget-BciI_D70.mjs} +2 -2
  64. package/dist/{ToDoWidget-CYDsZA0Z.mjs.map → ToDoWidget-BciI_D70.mjs.map} +1 -1
  65. package/dist/{ToDoWidget-Bjoan2Rm.cjs → ToDoWidget-OxT9z59F.cjs} +2 -2
  66. package/dist/{ToDoWidget-Bjoan2Rm.cjs.map → ToDoWidget-OxT9z59F.cjs.map} +1 -1
  67. package/dist/{ToDoWidget-C_CvWdLi.cjs → ToDoWidget-mSGQgnu3.cjs} +2 -2
  68. package/dist/index.cjs +22 -22
  69. package/dist/index.d.cts.map +1 -1
  70. package/dist/index.d.mts.map +1 -1
  71. package/dist/index.mjs +22 -22
  72. package/dist/{registry-context-BahYMRqn.mjs → registry-context-CTHUCfEc.mjs} +6 -5
  73. package/dist/{registry-context-bf52ZIJX.cjs.map → registry-context-CTHUCfEc.mjs.map} +1 -1
  74. package/dist/{registry-context-bf52ZIJX.cjs → registry-context-CcZYS15Q.cjs} +6 -5
  75. package/dist/{registry-context-BahYMRqn.mjs.map → registry-context-CcZYS15Q.cjs.map} +1 -1
  76. package/package.json +10 -10
  77. package/dist/CarouselWidget-CiKlooUF.cjs.map +0 -1
  78. package/dist/CarouselWidget-p8Z6L-G5.mjs.map +0 -1
  79. package/dist/ContainerWidget-CyfPYEAv.cjs +0 -8
  80. package/dist/PointsWidget-C2KB4k48.mjs.map +0 -1
  81. package/dist/PointsWidget-DLp-PYus.cjs.map +0 -1
  82. package/dist/ShopScreen-BBfOte5o.mjs.map +0 -1
  83. package/dist/ShopScreen-DWLGH2gt.cjs.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { r as __exportAll } from "./es-BXxGlAp6.mjs";
2
- import { n as useDataSourceRegistryConfig } from "./registry-context-BahYMRqn.mjs";
2
+ import { n as useDataSourceRegistryConfig } from "./registry-context-CTHUCfEc.mjs";
3
3
  import { i as useWidgetsApi, n as useWidgetPreviewContext, t as ErrorState } from "./error-state-DYzHx8tt.mjs";
4
4
  import { l as getColorField, m as getPaddingField, o as getBorderRadiusField, u as getFontSizeField } from "./registries-Ct8o2YRe.mjs";
5
5
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -627,4 +627,4 @@ const calendarWidgetPropertySchema = {
627
627
  //#endregion
628
628
  export { CalendarWidget_exports as n, calendarWidgetPropertySchema as r, CalendarWidget as t };
629
629
 
630
- //# sourceMappingURL=CalendarWidget-BXxNxHDV.mjs.map
630
+ //# sourceMappingURL=CalendarWidget-C03VcDLQ.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"CalendarWidget-BXxNxHDV.mjs","names":[],"sources":["../../widgets/src/hooks/use-calendar-events.preview.ts","../../widgets/src/hooks/use-calendar-events.ts","../../widgets/src/widgets/CalendarWidget.tsx"],"sourcesContent":["import type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nconst today = new Date();\nconst inTwoDays = new Date(today);\ninTwoDays.setDate(inTwoDays.getDate() + 2);\n\nfunction toISO(date: Date, hours: number, minutes = 0): string {\n const d = new Date(date);\n d.setHours(hours, minutes, 0, 0);\n return d.toISOString();\n}\n\nfunction toDateString(date: Date): string {\n return date.toISOString().split(\"T\")[0]!;\n}\n\nexport const PREVIEW_DATA: CalendarEvent[] = [\n {\n id: 1,\n title: \"Team Strategy Call\",\n start: toISO(today, 9, 0),\n end: toISO(today, 10, 0),\n status: \"active\",\n color: \"#4f46e5\",\n },\n {\n id: 2,\n title: \"Product Launch Webinar\",\n start: toISO(today, 14, 0),\n end: toISO(today, 15, 30),\n status: \"active\",\n color: \"#0891b2\",\n venue: \"Zoom\",\n },\n {\n id: 3,\n title: \"Annual Leadership Summit\",\n start: `${toDateString(inTwoDays)}T00:00:00.000Z`,\n end: `${toDateString(inTwoDays)}T23:59:59.000Z`,\n status: \"active\",\n color: \"#059669\",\n isAllDay: true,\n venue: \"Convention Center\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useWidgetsApi } from \"@fluid-app/portal-core/widgets-api-context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { PREVIEW_DATA } from \"./use-calendar-events.preview\";\nimport type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport function useCalendarEvents(): UseQueryResult<CalendarEvent[], Error> {\n const widgetsApi = useWidgetsApi();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"calendar-events\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: ({ signal }) => widgetsApi.fetchCalendarEvents(signal),\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import {\n useState,\n useMemo,\n useCallback,\n useRef,\n useEffect,\n type ComponentProps,\n} from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport {\n useCalendarEvents,\n type CalendarEvent,\n} from \"../hooks/use-calendar-events\";\nimport { ErrorState } from \"../components/error-state\";\nimport {\n CalendarCheck,\n ChevronLeft,\n ChevronRight,\n ChevronsDown,\n ChevronsUp,\n MapPin,\n type LucideIcon,\n} from \"lucide-react\";\n\nconst DAY_NAMES = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"] as const;\n\nconst getDaysInMonth = (year: number, month: number): number =>\n new Date(year, month + 1, 0).getDate();\n\nconst getFirstDayOfMonth = (year: number, month: number): number =>\n new Date(year, month, 1).getDay();\n\nconst isSameDay = (a: Date, b: Date): boolean =>\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\n\nconst startOfDay = (d: Date): Date => {\n const x = new Date(d);\n x.setHours(0, 0, 0, 0);\n return x;\n};\n\nconst addDays = (d: Date, n: number): Date => {\n const x = new Date(d);\n x.setDate(x.getDate() + n);\n return x;\n};\n\nconst diffDays = (a: Date, b: Date): number => {\n const ms = startOfDay(a).getTime() - startOfDay(b).getTime();\n return Math.round(ms / 86400000);\n};\n\ntype DayCell = {\n date: Date | null;\n isToday: boolean;\n isCurrentMonth: boolean;\n};\n\nconst generateMonthGrid = (year: number, month: number): DayCell[] => {\n const daysInMonth = getDaysInMonth(year, month);\n const firstDay = getFirstDayOfMonth(year, month);\n const today = new Date();\n const cells: DayCell[] = [];\n\n for (let i = 0; i < firstDay; i++) {\n cells.push({ date: null, isToday: false, isCurrentMonth: false });\n }\n\n for (let day = 1; day <= daysInMonth; day++) {\n const date = new Date(year, month, day);\n cells.push({\n date,\n isToday: isSameDay(date, today),\n isCurrentMonth: true,\n });\n }\n\n return cells;\n};\n\nconst generateWeekGrid = (): Array<{ date: Date; isToday: boolean }> => {\n const today = new Date();\n const weekday = today.getDay();\n return Array.from({ length: 7 }, (_, i) => {\n const date = addDays(today, -weekday + i);\n return { date, isToday: isSameDay(date, today) };\n });\n};\n\nconst formatTime = (iso: string): string =>\n new Date(iso).toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n\nconst formatContextualDate = (\n date: Date,\n): { lead: string | null; detail: string } => {\n const today = new Date();\n const d = diffDays(date, today);\n const weekday = date.toLocaleDateString(\"en-US\", { weekday: \"short\" });\n const monthDay = date.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n });\n if (d === 0) return { lead: \"Today\", detail: `${weekday}, ${monthDay}` };\n if (d === 1) return { lead: \"Tomorrow\", detail: `${weekday}, ${monthDay}` };\n if (d === -1) return { lead: \"Yesterday\", detail: `${weekday}, ${monthDay}` };\n return { lead: null, detail: `${weekday}, ${monthDay}` };\n};\n\ntype DayCellButtonProps = {\n date: Date;\n isToday: boolean;\n isSelected: boolean;\n eventCount: number;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n showEventDensity: boolean;\n onClick: () => void;\n};\n\nfunction DayCellButton({\n date,\n isToday,\n isSelected,\n eventCount,\n accentColor,\n textColor,\n showEventDensity,\n onClick,\n}: DayCellButtonProps) {\n const dotCount = showEventDensity\n ? Math.min(eventCount, 3)\n : eventCount > 0\n ? 1\n : 0;\n\n const baseClasses =\n \"group relative flex aspect-square w-full flex-col items-center justify-center rounded-lg text-sm tabular-nums transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-0\";\n\n const stateClasses = isSelected\n ? `bg-${accentColor} text-${accentColor}-foreground focus-visible:ring-${accentColor}/40`\n : isToday\n ? `bg-${accentColor}/10 text-${accentColor} font-semibold hover:bg-${accentColor}/20 focus-visible:ring-${accentColor}/40`\n : `text-${textColor} hover:bg-${accentColor}/10 focus-visible:ring-${accentColor}/40`;\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={date.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n })}\n aria-current={isToday ? \"date\" : undefined}\n aria-pressed={isSelected}\n className={`${baseClasses} ${stateClasses}`}\n >\n <span className=\"leading-none\">{date.getDate()}</span>\n {dotCount > 0 && (\n <span\n aria-hidden=\"true\"\n className=\"absolute bottom-1.5 flex items-center gap-[2px]\"\n >\n {Array.from({ length: dotCount }).map((_, i) => (\n <span\n key={i}\n className={`size-1 rounded-full ${\n isSelected\n ? `bg-${accentColor}-foreground/70`\n : `bg-${accentColor}`\n }`}\n />\n ))}\n </span>\n )}\n </button>\n );\n}\n\ntype EventCardProps = {\n event: CalendarEvent;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n};\n\nfunction EventCard({ event, accentColor, textColor }: EventCardProps) {\n const accentVar = `var(--color-${accentColor})`;\n const barColor = event.color || accentVar;\n const timeText = event.isAllDay\n ? \"All day\"\n : `${formatTime(event.start)} – ${formatTime(event.end)}`;\n\n const content = (\n <>\n <span\n aria-hidden=\"true\"\n className=\"w-[2px] shrink-0 self-stretch rounded-full\"\n style={{ backgroundColor: barColor }}\n />\n <div className=\"min-w-0 flex-1\">\n <div\n className={`truncate text-sm font-semibold text-${textColor} leading-tight`}\n >\n {event.title}\n </div>\n <div\n className={`mt-1 text-[11px] tabular-nums text-${textColor}/60 font-medium`}\n >\n {timeText}\n </div>\n {event.venue && (\n <div\n className={`mt-1.5 flex items-center gap-1 text-[11px] text-${textColor}/55`}\n >\n <MapPin className=\"size-2.5 shrink-0\" />\n <span className=\"truncate\">{event.venue}</span>\n </div>\n )}\n </div>\n </>\n );\n\n const wrapperClasses = `group flex gap-x-2 rounded-md px-2 py-2 transition-colors -mx-2`;\n const interactiveClasses = `hover:bg-${accentColor}/5`;\n\n if (event.url) {\n return (\n <a\n href={event.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`${wrapperClasses} ${interactiveClasses}`}\n >\n {content}\n </a>\n );\n }\n\n return <div className={wrapperClasses}>{content}</div>;\n}\n\ntype NavButtonProps = {\n icon: LucideIcon;\n label: string;\n variant: \"ghost\" | \"accent\";\n accentColor: ColorOptions;\n textColor: ColorOptions;\n onClick: () => void;\n};\n\nfunction NavButton({\n icon: Icon,\n label,\n variant,\n accentColor,\n textColor,\n onClick,\n}: NavButtonProps) {\n const classes =\n variant === \"accent\"\n ? `bg-${accentColor} text-${accentColor}-foreground hover:bg-${accentColor}/90 focus-visible:ring-${accentColor}/40`\n : `bg-${textColor}/5 text-${textColor} hover:bg-${textColor}/10 focus-visible:ring-${textColor}/20`;\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className={`flex size-8 items-center justify-center rounded-full text-[12px] transition-colors focus:outline-none focus-visible:ring-2 ${classes}`}\n >\n <Icon className=\"size-4\" />\n </button>\n );\n}\n\ntype CalendarView = {\n month: number;\n year: number;\n};\n\nconst getInitialCalendarView = (): CalendarView => {\n const now = new Date();\n return { month: now.getMonth(), year: now.getFullYear() };\n};\n\nfunction useCalendarNavigation(\n setSelectedDate: React.Dispatch<React.SetStateAction<Date | null>>,\n) {\n const [view, setView] = useState(getInitialCalendarView);\n const [gridTransitioning, setGridTransitioning] = useState(false);\n const transitionTimeoutRef = useRef<number | null>(null);\n\n useEffect(\n () => () => {\n if (transitionTimeoutRef.current !== null) {\n window.clearTimeout(transitionTimeoutRef.current);\n }\n },\n [],\n );\n\n const clearPendingTransition = useCallback(() => {\n if (transitionTimeoutRef.current !== null) {\n window.clearTimeout(transitionTimeoutRef.current);\n transitionTimeoutRef.current = null;\n }\n }, []);\n\n const navigate = useCallback(\n (direction: -1 | 1) => {\n clearPendingTransition();\n setGridTransitioning(true);\n transitionTimeoutRef.current = window.setTimeout(() => {\n setView((prev) => {\n const next = prev.month + direction;\n if (next < 0) return { month: 11, year: prev.year - 1 };\n if (next > 11) return { month: 0, year: prev.year + 1 };\n return { month: next, year: prev.year };\n });\n setGridTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 120);\n },\n [clearPendingTransition],\n );\n\n const goToToday = useCallback(() => {\n clearPendingTransition();\n const now = new Date();\n setGridTransitioning(true);\n transitionTimeoutRef.current = window.setTimeout(() => {\n setView({ month: now.getMonth(), year: now.getFullYear() });\n setSelectedDate(now);\n setGridTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 80);\n }, [clearPendingTransition, setSelectedDate]);\n\n return { view, gridTransitioning, navigate, goToToday };\n}\n\nfunction useCalendarEventIndex(\n events: CalendarEvent[],\n selectedDate: Date | null,\n) {\n const eventsByDate = useMemo(() => {\n const map = new Map<string, CalendarEvent[]>();\n for (const event of events) {\n const start = startOfDay(new Date(event.start));\n const end = startOfDay(new Date(event.end));\n for (let cur = start; cur <= end; cur = addDays(cur, 1)) {\n const key = `${cur.getFullYear()}-${cur.getMonth()}-${cur.getDate()}`;\n const list = map.get(key);\n if (list) {\n list.push(event);\n } else {\n map.set(key, [event]);\n }\n }\n }\n return map;\n }, [events]);\n\n const lookupEventsForDate = useCallback(\n (date: Date): CalendarEvent[] => {\n const key = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;\n return eventsByDate.get(key) ?? [];\n },\n [eventsByDate],\n );\n\n const selectedDateEvents = useMemo(() => {\n if (!selectedDate) return [];\n return lookupEventsForDate(selectedDate);\n }, [selectedDate, lookupEventsForDate]);\n\n return { lookupEventsForDate, selectedDateEvents };\n}\n\ntype CalendarWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Premium polish (new, additive)\n showEventDensity?: boolean;\n showTodayButton?: boolean;\n weekendDim?: boolean;\n showYearEyebrow?: boolean;\n};\n\nexport function CalendarWidget({\n titleEnabled = true,\n titleText = \"Calendar\",\n titleFontSize = \"xl\",\n titleColor = \"foreground\",\n\n background = { type: \"solid\", color: \"background\" },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n showEventDensity = true,\n showTodayButton = true,\n weekendDim = true,\n showYearEyebrow = true,\n\n className,\n ...props\n}: CalendarWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [selectedDate, setSelectedDate] = useState<Date | null>(\n () => new Date(),\n );\n const { view, gridTransitioning, navigate, goToToday } =\n useCalendarNavigation(setSelectedDate);\n const currentMonth = view.month;\n const currentYear = view.year;\n\n const { data: events = [], isLoading, isError } = useCalendarEvents();\n\n const monthGrid = useMemo(\n () => generateMonthGrid(currentYear, currentMonth),\n [currentYear, currentMonth],\n );\n const weekGrid = generateWeekGrid();\n const { lookupEventsForDate, selectedDateEvents } = useCalendarEventIndex(\n events,\n selectedDate,\n );\n\n const now = new Date();\n const viewingCurrentMonth =\n currentMonth === now.getMonth() && currentYear === now.getFullYear();\n\n const monthLabel = new Date(currentYear, currentMonth).toLocaleString(\n \"en-US\",\n { month: \"long\" },\n );\n const yearLabel = String(currentYear);\n\n const contextualDate = selectedDate\n ? formatContextualDate(selectedDate)\n : null;\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {titleEnabled && titleText && (\n <div className={`p-${padding} pb-0`}>\n <h2\n className={`text-${titleFontSize} text-${titleColor} font-bold tracking-[-0.012em]`}\n >\n {titleText}\n </h2>\n </div>\n )}\n\n {isLoading ? (\n <div\n className={`flex min-h-[300px] items-center justify-center p-${padding}`}\n >\n <div className={`text-${accentColor}`}>\n <div className=\"size-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n </div>\n ) : isError ? (\n <ErrorState />\n ) : (\n <div className={`p-${padding}`}>\n <div className=\"@md:flex @md:gap-6\">\n <div className=\"@md:flex-none\">\n {/* Header row: year eyebrow + month + asymmetric nav + Today pill */}\n <div className=\"mb-4 flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 flex-col\">\n {showYearEyebrow && (\n <span\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${textColor}/55`}\n >\n {yearLabel}\n </span>\n )}\n <span\n className={`text-xl leading-tight font-bold tracking-[-0.015em] text-${textColor}`}\n >\n {monthLabel}\n </span>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1.5\">\n {showTodayButton && !viewingCurrentMonth && (\n <button\n type=\"button\"\n onClick={goToToday}\n className={`flex items-center gap-1 rounded-full bg-${accentColor}/10 px-2.5 py-1 text-[11px] font-semibold text-${accentColor} transition-colors hover:bg-${accentColor}/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-${accentColor}/40`}\n >\n <CalendarCheck className=\"size-3\" />\n Today\n </button>\n )}\n <NavButton\n icon={ChevronLeft}\n label=\"Previous month\"\n variant=\"ghost\"\n accentColor={accentColor}\n textColor={textColor}\n onClick={() => navigate(-1)}\n />\n <NavButton\n icon={ChevronRight}\n label=\"Next month\"\n variant=\"accent\"\n accentColor={accentColor}\n textColor={textColor}\n onClick={() => navigate(1)}\n />\n </div>\n </div>\n\n {/* Day-of-week headers */}\n <div className=\"mb-2 grid grid-cols-7 gap-1 text-center\">\n {DAY_NAMES.map((day, idx) => {\n const isWeekend = idx === 0 || idx === 6;\n const dimmed = weekendDim && isWeekend;\n return (\n <div\n key={day}\n className={`text-[10px] font-semibold tracking-[0.12em] uppercase text-${textColor}/${dimmed ? \"40\" : \"55\"}`}\n >\n {day}\n </div>\n );\n })}\n </div>\n\n {/* Grid wrapper (opacity transitions on month navigate) */}\n <div\n className=\"transition-opacity duration-150 ease-out\"\n style={{ opacity: gridTransitioning ? 0.3 : 1 }}\n >\n {/* Collapsed week view on mobile */}\n {isCollapsed && (\n <div className=\"grid grid-cols-7 gap-1 @md:hidden\">\n {weekGrid.map(({ date, isToday }) => (\n <DayCellButton\n key={date.toISOString()}\n date={date}\n isToday={isToday}\n isSelected={\n !!selectedDate && isSameDay(selectedDate, date)\n }\n eventCount={lookupEventsForDate(date).length}\n accentColor={accentColor}\n textColor={textColor}\n showEventDensity={showEventDensity}\n onClick={() => setSelectedDate(date)}\n />\n ))}\n </div>\n )}\n\n {/* Month grid */}\n <div\n className={`grid grid-cols-7 gap-1 ${isCollapsed ? \"hidden @md:grid\" : \"grid\"}`}\n >\n {monthGrid.map((cell, idx) => {\n if (!cell.date) {\n return (\n <div key={`empty-${idx}`} className=\"aspect-square\" />\n );\n }\n const eventCount = lookupEventsForDate(cell.date).length;\n return (\n <DayCellButton\n key={cell.date.toISOString()}\n date={cell.date}\n isToday={cell.isToday}\n isSelected={\n !!selectedDate && isSameDay(selectedDate, cell.date)\n }\n eventCount={eventCount}\n accentColor={accentColor}\n textColor={textColor}\n showEventDensity={showEventDensity}\n onClick={() => setSelectedDate(cell.date)}\n />\n );\n })}\n </div>\n </div>\n\n {/* Mobile collapse toggle */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className={`mt-2 flex w-full items-center justify-center gap-3 rounded-full p-1 text-${textColor}/40 transition-colors hover:text-${textColor}/60 @md:hidden`}\n aria-label={\n isCollapsed ? \"Expand calendar\" : \"Collapse calendar\"\n }\n >\n <div className={`h-px w-1/2 bg-${textColor}/20`} />\n {isCollapsed ? (\n <ChevronsDown className=\"size-3\" />\n ) : (\n <ChevronsUp className=\"size-3\" />\n )}\n <div className={`h-px w-1/2 bg-${textColor}/20`} />\n </button>\n </div>\n\n {/* Events rail */}\n <div\n className={`mt-4 border-${textColor}/10 @md:mt-0 @md:w-56 @md:border-l @md:pl-6`}\n >\n {/* Context header */}\n {contextualDate && (\n <div className=\"mb-3\">\n {contextualDate.lead && (\n <div\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${accentColor}`}\n >\n {contextualDate.lead}\n </div>\n )}\n <div\n className={`text-sm font-semibold text-${textColor} tabular-nums`}\n >\n {contextualDate.detail}\n </div>\n </div>\n )}\n\n {/* Events list with soft fade-in keyed by selected date */}\n <div\n key={selectedDate?.toISOString() ?? \"none\"}\n className=\"animate-in fade-in slide-in-from-bottom-2 flex flex-col duration-200 ease-out\"\n >\n {selectedDateEvents.length > 0 ? (\n selectedDateEvents.map((event, idx) => (\n <EventCard\n key={`${event.id}-${idx}`}\n event={event}\n accentColor={accentColor}\n textColor={textColor}\n />\n ))\n ) : (\n <div\n className={`flex flex-col items-start gap-1 rounded-md border border-dashed border-${textColor}/15 px-3 py-3`}\n >\n <div className=\"flex items-center gap-1.5\">\n <CalendarCheck\n className={`size-3 text-${textColor}/40`}\n />\n <span\n className={`text-[11px] font-semibold text-${textColor}/60`}\n >\n Nothing scheduled\n </span>\n </div>\n <span className={`text-[11px] text-${textColor}/45`}>\n Enjoy the breather.\n </span>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const calendarWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CalendarWidget\",\n displayName: \"Calendar Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the calendar\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the calendar\",\n defaultValue: \"Calendar\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Design group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the calendar container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for calendar content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description:\n \"Drives today highlight, event dots, Today pill, and selected day\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the calendar container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the calendar container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n\n // Polish group (new)\n {\n key: \"showYearEyebrow\",\n label: \"Year Eyebrow\",\n type: \"boolean\",\n description:\n \"Small uppercase year label above the month (e.g. '2026 / November').\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"showTodayButton\",\n label: \"Today Button\",\n type: \"boolean\",\n description: \"Show a 'Today' pill when viewing a different month.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"showEventDensity\",\n label: \"Event Density Dots\",\n type: \"boolean\",\n description:\n \"Show 1–3 dots per day based on event count (off = single dot).\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"weekendDim\",\n label: \"Dim Weekends\",\n type: \"boolean\",\n description:\n \"Subtly dim the Sun/Sat day-of-week headers for visual rhythm.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
1
+ {"version":3,"file":"CalendarWidget-C03VcDLQ.mjs","names":[],"sources":["../../widgets/src/hooks/use-calendar-events.preview.ts","../../widgets/src/hooks/use-calendar-events.ts","../../widgets/src/widgets/CalendarWidget.tsx"],"sourcesContent":["import type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nconst today = new Date();\nconst inTwoDays = new Date(today);\ninTwoDays.setDate(inTwoDays.getDate() + 2);\n\nfunction toISO(date: Date, hours: number, minutes = 0): string {\n const d = new Date(date);\n d.setHours(hours, minutes, 0, 0);\n return d.toISOString();\n}\n\nfunction toDateString(date: Date): string {\n return date.toISOString().split(\"T\")[0]!;\n}\n\nexport const PREVIEW_DATA: CalendarEvent[] = [\n {\n id: 1,\n title: \"Team Strategy Call\",\n start: toISO(today, 9, 0),\n end: toISO(today, 10, 0),\n status: \"active\",\n color: \"#4f46e5\",\n },\n {\n id: 2,\n title: \"Product Launch Webinar\",\n start: toISO(today, 14, 0),\n end: toISO(today, 15, 30),\n status: \"active\",\n color: \"#0891b2\",\n venue: \"Zoom\",\n },\n {\n id: 3,\n title: \"Annual Leadership Summit\",\n start: `${toDateString(inTwoDays)}T00:00:00.000Z`,\n end: `${toDateString(inTwoDays)}T23:59:59.000Z`,\n status: \"active\",\n color: \"#059669\",\n isAllDay: true,\n venue: \"Convention Center\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useWidgetsApi } from \"@fluid-app/portal-core/widgets-api-context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { PREVIEW_DATA } from \"./use-calendar-events.preview\";\nimport type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport function useCalendarEvents(): UseQueryResult<CalendarEvent[], Error> {\n const widgetsApi = useWidgetsApi();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"calendar-events\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: ({ signal }) => widgetsApi.fetchCalendarEvents(signal),\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import {\n useState,\n useMemo,\n useCallback,\n useRef,\n useEffect,\n type ComponentProps,\n} from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport {\n useCalendarEvents,\n type CalendarEvent,\n} from \"../hooks/use-calendar-events\";\nimport { ErrorState } from \"../components/error-state\";\nimport {\n CalendarCheck,\n ChevronLeft,\n ChevronRight,\n ChevronsDown,\n ChevronsUp,\n MapPin,\n type LucideIcon,\n} from \"lucide-react\";\n\nconst DAY_NAMES = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"] as const;\n\nconst getDaysInMonth = (year: number, month: number): number =>\n new Date(year, month + 1, 0).getDate();\n\nconst getFirstDayOfMonth = (year: number, month: number): number =>\n new Date(year, month, 1).getDay();\n\nconst isSameDay = (a: Date, b: Date): boolean =>\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\n\nconst startOfDay = (d: Date): Date => {\n const x = new Date(d);\n x.setHours(0, 0, 0, 0);\n return x;\n};\n\nconst addDays = (d: Date, n: number): Date => {\n const x = new Date(d);\n x.setDate(x.getDate() + n);\n return x;\n};\n\nconst diffDays = (a: Date, b: Date): number => {\n const ms = startOfDay(a).getTime() - startOfDay(b).getTime();\n return Math.round(ms / 86400000);\n};\n\ntype DayCell = {\n date: Date | null;\n isToday: boolean;\n isCurrentMonth: boolean;\n};\n\nconst generateMonthGrid = (year: number, month: number): DayCell[] => {\n const daysInMonth = getDaysInMonth(year, month);\n const firstDay = getFirstDayOfMonth(year, month);\n const today = new Date();\n const cells: DayCell[] = [];\n\n for (let i = 0; i < firstDay; i++) {\n cells.push({ date: null, isToday: false, isCurrentMonth: false });\n }\n\n for (let day = 1; day <= daysInMonth; day++) {\n const date = new Date(year, month, day);\n cells.push({\n date,\n isToday: isSameDay(date, today),\n isCurrentMonth: true,\n });\n }\n\n return cells;\n};\n\nconst generateWeekGrid = (): Array<{ date: Date; isToday: boolean }> => {\n const today = new Date();\n const weekday = today.getDay();\n return Array.from({ length: 7 }, (_, i) => {\n const date = addDays(today, -weekday + i);\n return { date, isToday: isSameDay(date, today) };\n });\n};\n\nconst formatTime = (iso: string): string =>\n new Date(iso).toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n\nconst formatContextualDate = (\n date: Date,\n): { lead: string | null; detail: string } => {\n const today = new Date();\n const d = diffDays(date, today);\n const weekday = date.toLocaleDateString(\"en-US\", { weekday: \"short\" });\n const monthDay = date.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n });\n if (d === 0) return { lead: \"Today\", detail: `${weekday}, ${monthDay}` };\n if (d === 1) return { lead: \"Tomorrow\", detail: `${weekday}, ${monthDay}` };\n if (d === -1) return { lead: \"Yesterday\", detail: `${weekday}, ${monthDay}` };\n return { lead: null, detail: `${weekday}, ${monthDay}` };\n};\n\ntype DayCellButtonProps = {\n date: Date;\n isToday: boolean;\n isSelected: boolean;\n eventCount: number;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n showEventDensity: boolean;\n onClick: () => void;\n};\n\nfunction DayCellButton({\n date,\n isToday,\n isSelected,\n eventCount,\n accentColor,\n textColor,\n showEventDensity,\n onClick,\n}: DayCellButtonProps) {\n const dotCount = showEventDensity\n ? Math.min(eventCount, 3)\n : eventCount > 0\n ? 1\n : 0;\n\n const baseClasses =\n \"group relative flex aspect-square w-full flex-col items-center justify-center rounded-lg text-sm tabular-nums transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-0\";\n\n const stateClasses = isSelected\n ? `bg-${accentColor} text-${accentColor}-foreground focus-visible:ring-${accentColor}/40`\n : isToday\n ? `bg-${accentColor}/10 text-${accentColor} font-semibold hover:bg-${accentColor}/20 focus-visible:ring-${accentColor}/40`\n : `text-${textColor} hover:bg-${accentColor}/10 focus-visible:ring-${accentColor}/40`;\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={date.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n })}\n aria-current={isToday ? \"date\" : undefined}\n aria-pressed={isSelected}\n className={`${baseClasses} ${stateClasses}`}\n >\n <span className=\"leading-none\">{date.getDate()}</span>\n {dotCount > 0 && (\n <span\n aria-hidden=\"true\"\n className=\"absolute bottom-1.5 flex items-center gap-[2px]\"\n >\n {Array.from({ length: dotCount }).map((_, i) => (\n <span\n key={i}\n className={`size-1 rounded-full ${\n isSelected\n ? `bg-${accentColor}-foreground/70`\n : `bg-${accentColor}`\n }`}\n />\n ))}\n </span>\n )}\n </button>\n );\n}\n\ntype EventCardProps = {\n event: CalendarEvent;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n};\n\nfunction EventCard({ event, accentColor, textColor }: EventCardProps) {\n const accentVar = `var(--color-${accentColor})`;\n const barColor = event.color || accentVar;\n const timeText = event.isAllDay\n ? \"All day\"\n : `${formatTime(event.start)} – ${formatTime(event.end)}`;\n\n const content = (\n <>\n <span\n aria-hidden=\"true\"\n className=\"w-[2px] shrink-0 self-stretch rounded-full\"\n style={{ backgroundColor: barColor }}\n />\n <div className=\"min-w-0 flex-1\">\n <div\n className={`truncate text-sm font-semibold text-${textColor} leading-tight`}\n >\n {event.title}\n </div>\n <div\n className={`mt-1 text-[11px] tabular-nums text-${textColor}/60 font-medium`}\n >\n {timeText}\n </div>\n {event.venue && (\n <div\n className={`mt-1.5 flex items-center gap-1 text-[11px] text-${textColor}/55`}\n >\n <MapPin className=\"size-2.5 shrink-0\" />\n <span className=\"truncate\">{event.venue}</span>\n </div>\n )}\n </div>\n </>\n );\n\n const wrapperClasses = `group flex gap-x-2 rounded-md px-2 py-2 transition-colors -mx-2`;\n const interactiveClasses = `hover:bg-${accentColor}/5`;\n\n if (event.url) {\n return (\n <a\n href={event.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`${wrapperClasses} ${interactiveClasses}`}\n >\n {content}\n </a>\n );\n }\n\n return <div className={wrapperClasses}>{content}</div>;\n}\n\ntype NavButtonProps = {\n icon: LucideIcon;\n label: string;\n variant: \"ghost\" | \"accent\";\n accentColor: ColorOptions;\n textColor: ColorOptions;\n onClick: () => void;\n};\n\nfunction NavButton({\n icon: Icon,\n label,\n variant,\n accentColor,\n textColor,\n onClick,\n}: NavButtonProps) {\n const classes =\n variant === \"accent\"\n ? `bg-${accentColor} text-${accentColor}-foreground hover:bg-${accentColor}/90 focus-visible:ring-${accentColor}/40`\n : `bg-${textColor}/5 text-${textColor} hover:bg-${textColor}/10 focus-visible:ring-${textColor}/20`;\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className={`flex size-8 items-center justify-center rounded-full text-[12px] transition-colors focus:outline-none focus-visible:ring-2 ${classes}`}\n >\n <Icon className=\"size-4\" />\n </button>\n );\n}\n\ntype CalendarView = {\n month: number;\n year: number;\n};\n\nconst getInitialCalendarView = (): CalendarView => {\n const now = new Date();\n return { month: now.getMonth(), year: now.getFullYear() };\n};\n\nfunction useCalendarNavigation(\n setSelectedDate: React.Dispatch<React.SetStateAction<Date | null>>,\n) {\n const [view, setView] = useState(getInitialCalendarView);\n const [gridTransitioning, setGridTransitioning] = useState(false);\n const transitionTimeoutRef = useRef<number | null>(null);\n\n useEffect(\n () => () => {\n if (transitionTimeoutRef.current !== null) {\n window.clearTimeout(transitionTimeoutRef.current);\n }\n },\n [],\n );\n\n const clearPendingTransition = useCallback(() => {\n if (transitionTimeoutRef.current !== null) {\n window.clearTimeout(transitionTimeoutRef.current);\n transitionTimeoutRef.current = null;\n }\n }, []);\n\n const navigate = useCallback(\n (direction: -1 | 1) => {\n clearPendingTransition();\n setGridTransitioning(true);\n transitionTimeoutRef.current = window.setTimeout(() => {\n setView((prev) => {\n const next = prev.month + direction;\n if (next < 0) return { month: 11, year: prev.year - 1 };\n if (next > 11) return { month: 0, year: prev.year + 1 };\n return { month: next, year: prev.year };\n });\n setGridTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 120);\n },\n [clearPendingTransition],\n );\n\n const goToToday = useCallback(() => {\n clearPendingTransition();\n const now = new Date();\n setGridTransitioning(true);\n transitionTimeoutRef.current = window.setTimeout(() => {\n setView({ month: now.getMonth(), year: now.getFullYear() });\n setSelectedDate(now);\n setGridTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 80);\n }, [clearPendingTransition, setSelectedDate]);\n\n return { view, gridTransitioning, navigate, goToToday };\n}\n\nfunction useCalendarEventIndex(\n events: CalendarEvent[],\n selectedDate: Date | null,\n) {\n const eventsByDate = useMemo(() => {\n const map = new Map<string, CalendarEvent[]>();\n for (const event of events) {\n const start = startOfDay(new Date(event.start));\n const end = startOfDay(new Date(event.end));\n for (let cur = start; cur <= end; cur = addDays(cur, 1)) {\n const key = `${cur.getFullYear()}-${cur.getMonth()}-${cur.getDate()}`;\n const list = map.get(key);\n if (list) {\n list.push(event);\n } else {\n map.set(key, [event]);\n }\n }\n }\n return map;\n }, [events]);\n\n const lookupEventsForDate = useCallback(\n (date: Date): CalendarEvent[] => {\n const key = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;\n return eventsByDate.get(key) ?? [];\n },\n [eventsByDate],\n );\n\n const selectedDateEvents = useMemo(() => {\n if (!selectedDate) return [];\n return lookupEventsForDate(selectedDate);\n }, [selectedDate, lookupEventsForDate]);\n\n return { lookupEventsForDate, selectedDateEvents };\n}\n\ntype CalendarWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Premium polish (new, additive)\n showEventDensity?: boolean;\n showTodayButton?: boolean;\n weekendDim?: boolean;\n showYearEyebrow?: boolean;\n};\n\nexport function CalendarWidget({\n titleEnabled = true,\n titleText = \"Calendar\",\n titleFontSize = \"xl\",\n titleColor = \"foreground\",\n\n background = { type: \"solid\", color: \"background\" },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n showEventDensity = true,\n showTodayButton = true,\n weekendDim = true,\n showYearEyebrow = true,\n\n className,\n ...props\n}: CalendarWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [selectedDate, setSelectedDate] = useState<Date | null>(\n () => new Date(),\n );\n const { view, gridTransitioning, navigate, goToToday } =\n useCalendarNavigation(setSelectedDate);\n const currentMonth = view.month;\n const currentYear = view.year;\n\n const { data: events = [], isLoading, isError } = useCalendarEvents();\n\n const monthGrid = useMemo(\n () => generateMonthGrid(currentYear, currentMonth),\n [currentYear, currentMonth],\n );\n const weekGrid = generateWeekGrid();\n const { lookupEventsForDate, selectedDateEvents } = useCalendarEventIndex(\n events,\n selectedDate,\n );\n\n const now = new Date();\n const viewingCurrentMonth =\n currentMonth === now.getMonth() && currentYear === now.getFullYear();\n\n const monthLabel = new Date(currentYear, currentMonth).toLocaleString(\n \"en-US\",\n { month: \"long\" },\n );\n const yearLabel = String(currentYear);\n\n const contextualDate = selectedDate\n ? formatContextualDate(selectedDate)\n : null;\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {titleEnabled && titleText && (\n <div className={`p-${padding} pb-0`}>\n <h2\n className={`text-${titleFontSize} text-${titleColor} font-bold tracking-[-0.012em]`}\n >\n {titleText}\n </h2>\n </div>\n )}\n\n {isLoading ? (\n <div\n className={`flex min-h-[300px] items-center justify-center p-${padding}`}\n >\n <div className={`text-${accentColor}`}>\n <div className=\"size-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n </div>\n ) : isError ? (\n <ErrorState />\n ) : (\n <div className={`p-${padding}`}>\n <div className=\"@md:flex @md:gap-6\">\n <div className=\"@md:flex-none\">\n {/* Header row: year eyebrow + month + asymmetric nav + Today pill */}\n <div className=\"mb-4 flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 flex-col\">\n {showYearEyebrow && (\n <span\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${textColor}/55`}\n >\n {yearLabel}\n </span>\n )}\n <span\n className={`text-xl leading-tight font-bold tracking-[-0.015em] text-${textColor}`}\n >\n {monthLabel}\n </span>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1.5\">\n {showTodayButton && !viewingCurrentMonth && (\n <button\n type=\"button\"\n onClick={goToToday}\n className={`flex items-center gap-1 rounded-full bg-${accentColor}/10 px-2.5 py-1 text-[11px] font-semibold text-${accentColor} transition-colors hover:bg-${accentColor}/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-${accentColor}/40`}\n >\n <CalendarCheck className=\"size-3\" />\n Today\n </button>\n )}\n <NavButton\n icon={ChevronLeft}\n label=\"Previous month\"\n variant=\"ghost\"\n accentColor={accentColor}\n textColor={textColor}\n onClick={() => navigate(-1)}\n />\n <NavButton\n icon={ChevronRight}\n label=\"Next month\"\n variant=\"accent\"\n accentColor={accentColor}\n textColor={textColor}\n onClick={() => navigate(1)}\n />\n </div>\n </div>\n\n {/* Day-of-week headers */}\n <div className=\"mb-2 grid grid-cols-7 gap-1 text-center\">\n {DAY_NAMES.map((day, idx) => {\n const isWeekend = idx === 0 || idx === 6;\n const dimmed = weekendDim && isWeekend;\n return (\n <div\n key={day}\n className={`text-[10px] font-semibold tracking-[0.12em] uppercase text-${textColor}/${dimmed ? \"40\" : \"55\"}`}\n >\n {day}\n </div>\n );\n })}\n </div>\n\n {/* Grid wrapper (opacity transitions on month navigate) */}\n <div\n className=\"transition-opacity duration-150 ease-out\"\n style={{ opacity: gridTransitioning ? 0.3 : 1 }}\n >\n {/* Collapsed week view on mobile */}\n {isCollapsed && (\n <div className=\"grid grid-cols-7 gap-1 @md:hidden\">\n {weekGrid.map(({ date, isToday }) => (\n <DayCellButton\n key={date.toISOString()}\n date={date}\n isToday={isToday}\n isSelected={\n !!selectedDate && isSameDay(selectedDate, date)\n }\n eventCount={lookupEventsForDate(date).length}\n accentColor={accentColor}\n textColor={textColor}\n showEventDensity={showEventDensity}\n onClick={() => setSelectedDate(date)}\n />\n ))}\n </div>\n )}\n\n {/* Month grid */}\n <div\n className={`grid grid-cols-7 gap-1 ${isCollapsed ? \"hidden @md:grid\" : \"grid\"}`}\n >\n {monthGrid.map((cell, idx) => {\n if (!cell.date) {\n return (\n <div key={`empty-${idx}`} className=\"aspect-square\" />\n );\n }\n const eventCount = lookupEventsForDate(cell.date).length;\n return (\n <DayCellButton\n key={cell.date.toISOString()}\n date={cell.date}\n isToday={cell.isToday}\n isSelected={\n !!selectedDate && isSameDay(selectedDate, cell.date)\n }\n eventCount={eventCount}\n accentColor={accentColor}\n textColor={textColor}\n showEventDensity={showEventDensity}\n onClick={() => setSelectedDate(cell.date)}\n />\n );\n })}\n </div>\n </div>\n\n {/* Mobile collapse toggle */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className={`mt-2 flex w-full items-center justify-center gap-3 rounded-full p-1 text-${textColor}/40 transition-colors hover:text-${textColor}/60 @md:hidden`}\n aria-label={\n isCollapsed ? \"Expand calendar\" : \"Collapse calendar\"\n }\n >\n <div className={`h-px w-1/2 bg-${textColor}/20`} />\n {isCollapsed ? (\n <ChevronsDown className=\"size-3\" />\n ) : (\n <ChevronsUp className=\"size-3\" />\n )}\n <div className={`h-px w-1/2 bg-${textColor}/20`} />\n </button>\n </div>\n\n {/* Events rail */}\n <div\n className={`mt-4 border-${textColor}/10 @md:mt-0 @md:w-56 @md:border-l @md:pl-6`}\n >\n {/* Context header */}\n {contextualDate && (\n <div className=\"mb-3\">\n {contextualDate.lead && (\n <div\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${accentColor}`}\n >\n {contextualDate.lead}\n </div>\n )}\n <div\n className={`text-sm font-semibold text-${textColor} tabular-nums`}\n >\n {contextualDate.detail}\n </div>\n </div>\n )}\n\n {/* Events list with soft fade-in keyed by selected date */}\n <div\n key={selectedDate?.toISOString() ?? \"none\"}\n className=\"animate-in fade-in slide-in-from-bottom-2 flex flex-col duration-200 ease-out\"\n >\n {selectedDateEvents.length > 0 ? (\n selectedDateEvents.map((event, idx) => (\n <EventCard\n key={`${event.id}-${idx}`}\n event={event}\n accentColor={accentColor}\n textColor={textColor}\n />\n ))\n ) : (\n <div\n className={`flex flex-col items-start gap-1 rounded-md border border-dashed border-${textColor}/15 px-3 py-3`}\n >\n <div className=\"flex items-center gap-1.5\">\n <CalendarCheck\n className={`size-3 text-${textColor}/40`}\n />\n <span\n className={`text-[11px] font-semibold text-${textColor}/60`}\n >\n Nothing scheduled\n </span>\n </div>\n <span className={`text-[11px] text-${textColor}/45`}>\n Enjoy the breather.\n </span>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const calendarWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CalendarWidget\",\n displayName: \"Calendar Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the calendar\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the calendar\",\n defaultValue: \"Calendar\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Design group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the calendar container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for calendar content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description:\n \"Drives today highlight, event dots, Today pill, and selected day\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the calendar container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the calendar container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n\n // Polish group (new)\n {\n key: \"showYearEyebrow\",\n label: \"Year Eyebrow\",\n type: \"boolean\",\n description:\n \"Small uppercase year label above the month (e.g. '2026 / November').\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"showTodayButton\",\n label: \"Today Button\",\n type: \"boolean\",\n description: \"Show a 'Today' pill when viewing a different month.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"showEventDensity\",\n label: \"Event Density Dots\",\n type: \"boolean\",\n description:\n \"Show 1–3 dots per day based on event count (off = single dot).\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"weekendDim\",\n label: \"Dim Weekends\",\n type: \"boolean\",\n description:\n \"Subtly dim the Sun/Sat day-of-week headers for visual rhythm.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-9hOWP6kD.cjs");
2
- const require_registry_context = require("./registry-context-bf52ZIJX.cjs");
2
+ const require_registry_context = require("./registry-context-CcZYS15Q.cjs");
3
3
  const require_error_state = require("./error-state-BDhSltIa.cjs");
4
4
  const require_registries = require("./registries-DBb6VjAX.cjs");
5
5
  let react = require("react");
@@ -644,4 +644,4 @@ Object.defineProperty(exports, "calendarWidgetPropertySchema", {
644
644
  }
645
645
  });
646
646
 
647
- //# sourceMappingURL=CalendarWidget-VjQXZW8B.cjs.map
647
+ //# sourceMappingURL=CalendarWidget-C4Dv_TUk.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"CalendarWidget-VjQXZW8B.cjs","names":["useWidgetsApi","useWidgetPreviewContext","useDataSourceRegistryConfig","MapPin","ErrorState","CalendarCheck","ChevronLeft","ChevronRight","ChevronsDown","ChevronsUp","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField"],"sources":["../../widgets/src/hooks/use-calendar-events.preview.ts","../../widgets/src/hooks/use-calendar-events.ts","../../widgets/src/widgets/CalendarWidget.tsx"],"sourcesContent":["import type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nconst today = new Date();\nconst inTwoDays = new Date(today);\ninTwoDays.setDate(inTwoDays.getDate() + 2);\n\nfunction toISO(date: Date, hours: number, minutes = 0): string {\n const d = new Date(date);\n d.setHours(hours, minutes, 0, 0);\n return d.toISOString();\n}\n\nfunction toDateString(date: Date): string {\n return date.toISOString().split(\"T\")[0]!;\n}\n\nexport const PREVIEW_DATA: CalendarEvent[] = [\n {\n id: 1,\n title: \"Team Strategy Call\",\n start: toISO(today, 9, 0),\n end: toISO(today, 10, 0),\n status: \"active\",\n color: \"#4f46e5\",\n },\n {\n id: 2,\n title: \"Product Launch Webinar\",\n start: toISO(today, 14, 0),\n end: toISO(today, 15, 30),\n status: \"active\",\n color: \"#0891b2\",\n venue: \"Zoom\",\n },\n {\n id: 3,\n title: \"Annual Leadership Summit\",\n start: `${toDateString(inTwoDays)}T00:00:00.000Z`,\n end: `${toDateString(inTwoDays)}T23:59:59.000Z`,\n status: \"active\",\n color: \"#059669\",\n isAllDay: true,\n venue: \"Convention Center\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useWidgetsApi } from \"@fluid-app/portal-core/widgets-api-context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { PREVIEW_DATA } from \"./use-calendar-events.preview\";\nimport type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport function useCalendarEvents(): UseQueryResult<CalendarEvent[], Error> {\n const widgetsApi = useWidgetsApi();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"calendar-events\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: ({ signal }) => widgetsApi.fetchCalendarEvents(signal),\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import {\n useState,\n useMemo,\n useCallback,\n useRef,\n useEffect,\n type ComponentProps,\n} from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport {\n useCalendarEvents,\n type CalendarEvent,\n} from \"../hooks/use-calendar-events\";\nimport { ErrorState } from \"../components/error-state\";\nimport {\n CalendarCheck,\n ChevronLeft,\n ChevronRight,\n ChevronsDown,\n ChevronsUp,\n MapPin,\n type LucideIcon,\n} from \"lucide-react\";\n\nconst DAY_NAMES = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"] as const;\n\nconst getDaysInMonth = (year: number, month: number): number =>\n new Date(year, month + 1, 0).getDate();\n\nconst getFirstDayOfMonth = (year: number, month: number): number =>\n new Date(year, month, 1).getDay();\n\nconst isSameDay = (a: Date, b: Date): boolean =>\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\n\nconst startOfDay = (d: Date): Date => {\n const x = new Date(d);\n x.setHours(0, 0, 0, 0);\n return x;\n};\n\nconst addDays = (d: Date, n: number): Date => {\n const x = new Date(d);\n x.setDate(x.getDate() + n);\n return x;\n};\n\nconst diffDays = (a: Date, b: Date): number => {\n const ms = startOfDay(a).getTime() - startOfDay(b).getTime();\n return Math.round(ms / 86400000);\n};\n\ntype DayCell = {\n date: Date | null;\n isToday: boolean;\n isCurrentMonth: boolean;\n};\n\nconst generateMonthGrid = (year: number, month: number): DayCell[] => {\n const daysInMonth = getDaysInMonth(year, month);\n const firstDay = getFirstDayOfMonth(year, month);\n const today = new Date();\n const cells: DayCell[] = [];\n\n for (let i = 0; i < firstDay; i++) {\n cells.push({ date: null, isToday: false, isCurrentMonth: false });\n }\n\n for (let day = 1; day <= daysInMonth; day++) {\n const date = new Date(year, month, day);\n cells.push({\n date,\n isToday: isSameDay(date, today),\n isCurrentMonth: true,\n });\n }\n\n return cells;\n};\n\nconst generateWeekGrid = (): Array<{ date: Date; isToday: boolean }> => {\n const today = new Date();\n const weekday = today.getDay();\n return Array.from({ length: 7 }, (_, i) => {\n const date = addDays(today, -weekday + i);\n return { date, isToday: isSameDay(date, today) };\n });\n};\n\nconst formatTime = (iso: string): string =>\n new Date(iso).toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n\nconst formatContextualDate = (\n date: Date,\n): { lead: string | null; detail: string } => {\n const today = new Date();\n const d = diffDays(date, today);\n const weekday = date.toLocaleDateString(\"en-US\", { weekday: \"short\" });\n const monthDay = date.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n });\n if (d === 0) return { lead: \"Today\", detail: `${weekday}, ${monthDay}` };\n if (d === 1) return { lead: \"Tomorrow\", detail: `${weekday}, ${monthDay}` };\n if (d === -1) return { lead: \"Yesterday\", detail: `${weekday}, ${monthDay}` };\n return { lead: null, detail: `${weekday}, ${monthDay}` };\n};\n\ntype DayCellButtonProps = {\n date: Date;\n isToday: boolean;\n isSelected: boolean;\n eventCount: number;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n showEventDensity: boolean;\n onClick: () => void;\n};\n\nfunction DayCellButton({\n date,\n isToday,\n isSelected,\n eventCount,\n accentColor,\n textColor,\n showEventDensity,\n onClick,\n}: DayCellButtonProps) {\n const dotCount = showEventDensity\n ? Math.min(eventCount, 3)\n : eventCount > 0\n ? 1\n : 0;\n\n const baseClasses =\n \"group relative flex aspect-square w-full flex-col items-center justify-center rounded-lg text-sm tabular-nums transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-0\";\n\n const stateClasses = isSelected\n ? `bg-${accentColor} text-${accentColor}-foreground focus-visible:ring-${accentColor}/40`\n : isToday\n ? `bg-${accentColor}/10 text-${accentColor} font-semibold hover:bg-${accentColor}/20 focus-visible:ring-${accentColor}/40`\n : `text-${textColor} hover:bg-${accentColor}/10 focus-visible:ring-${accentColor}/40`;\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={date.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n })}\n aria-current={isToday ? \"date\" : undefined}\n aria-pressed={isSelected}\n className={`${baseClasses} ${stateClasses}`}\n >\n <span className=\"leading-none\">{date.getDate()}</span>\n {dotCount > 0 && (\n <span\n aria-hidden=\"true\"\n className=\"absolute bottom-1.5 flex items-center gap-[2px]\"\n >\n {Array.from({ length: dotCount }).map((_, i) => (\n <span\n key={i}\n className={`size-1 rounded-full ${\n isSelected\n ? `bg-${accentColor}-foreground/70`\n : `bg-${accentColor}`\n }`}\n />\n ))}\n </span>\n )}\n </button>\n );\n}\n\ntype EventCardProps = {\n event: CalendarEvent;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n};\n\nfunction EventCard({ event, accentColor, textColor }: EventCardProps) {\n const accentVar = `var(--color-${accentColor})`;\n const barColor = event.color || accentVar;\n const timeText = event.isAllDay\n ? \"All day\"\n : `${formatTime(event.start)} – ${formatTime(event.end)}`;\n\n const content = (\n <>\n <span\n aria-hidden=\"true\"\n className=\"w-[2px] shrink-0 self-stretch rounded-full\"\n style={{ backgroundColor: barColor }}\n />\n <div className=\"min-w-0 flex-1\">\n <div\n className={`truncate text-sm font-semibold text-${textColor} leading-tight`}\n >\n {event.title}\n </div>\n <div\n className={`mt-1 text-[11px] tabular-nums text-${textColor}/60 font-medium`}\n >\n {timeText}\n </div>\n {event.venue && (\n <div\n className={`mt-1.5 flex items-center gap-1 text-[11px] text-${textColor}/55`}\n >\n <MapPin className=\"size-2.5 shrink-0\" />\n <span className=\"truncate\">{event.venue}</span>\n </div>\n )}\n </div>\n </>\n );\n\n const wrapperClasses = `group flex gap-x-2 rounded-md px-2 py-2 transition-colors -mx-2`;\n const interactiveClasses = `hover:bg-${accentColor}/5`;\n\n if (event.url) {\n return (\n <a\n href={event.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`${wrapperClasses} ${interactiveClasses}`}\n >\n {content}\n </a>\n );\n }\n\n return <div className={wrapperClasses}>{content}</div>;\n}\n\ntype NavButtonProps = {\n icon: LucideIcon;\n label: string;\n variant: \"ghost\" | \"accent\";\n accentColor: ColorOptions;\n textColor: ColorOptions;\n onClick: () => void;\n};\n\nfunction NavButton({\n icon: Icon,\n label,\n variant,\n accentColor,\n textColor,\n onClick,\n}: NavButtonProps) {\n const classes =\n variant === \"accent\"\n ? `bg-${accentColor} text-${accentColor}-foreground hover:bg-${accentColor}/90 focus-visible:ring-${accentColor}/40`\n : `bg-${textColor}/5 text-${textColor} hover:bg-${textColor}/10 focus-visible:ring-${textColor}/20`;\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className={`flex size-8 items-center justify-center rounded-full text-[12px] transition-colors focus:outline-none focus-visible:ring-2 ${classes}`}\n >\n <Icon className=\"size-4\" />\n </button>\n );\n}\n\ntype CalendarView = {\n month: number;\n year: number;\n};\n\nconst getInitialCalendarView = (): CalendarView => {\n const now = new Date();\n return { month: now.getMonth(), year: now.getFullYear() };\n};\n\nfunction useCalendarNavigation(\n setSelectedDate: React.Dispatch<React.SetStateAction<Date | null>>,\n) {\n const [view, setView] = useState(getInitialCalendarView);\n const [gridTransitioning, setGridTransitioning] = useState(false);\n const transitionTimeoutRef = useRef<number | null>(null);\n\n useEffect(\n () => () => {\n if (transitionTimeoutRef.current !== null) {\n window.clearTimeout(transitionTimeoutRef.current);\n }\n },\n [],\n );\n\n const clearPendingTransition = useCallback(() => {\n if (transitionTimeoutRef.current !== null) {\n window.clearTimeout(transitionTimeoutRef.current);\n transitionTimeoutRef.current = null;\n }\n }, []);\n\n const navigate = useCallback(\n (direction: -1 | 1) => {\n clearPendingTransition();\n setGridTransitioning(true);\n transitionTimeoutRef.current = window.setTimeout(() => {\n setView((prev) => {\n const next = prev.month + direction;\n if (next < 0) return { month: 11, year: prev.year - 1 };\n if (next > 11) return { month: 0, year: prev.year + 1 };\n return { month: next, year: prev.year };\n });\n setGridTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 120);\n },\n [clearPendingTransition],\n );\n\n const goToToday = useCallback(() => {\n clearPendingTransition();\n const now = new Date();\n setGridTransitioning(true);\n transitionTimeoutRef.current = window.setTimeout(() => {\n setView({ month: now.getMonth(), year: now.getFullYear() });\n setSelectedDate(now);\n setGridTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 80);\n }, [clearPendingTransition, setSelectedDate]);\n\n return { view, gridTransitioning, navigate, goToToday };\n}\n\nfunction useCalendarEventIndex(\n events: CalendarEvent[],\n selectedDate: Date | null,\n) {\n const eventsByDate = useMemo(() => {\n const map = new Map<string, CalendarEvent[]>();\n for (const event of events) {\n const start = startOfDay(new Date(event.start));\n const end = startOfDay(new Date(event.end));\n for (let cur = start; cur <= end; cur = addDays(cur, 1)) {\n const key = `${cur.getFullYear()}-${cur.getMonth()}-${cur.getDate()}`;\n const list = map.get(key);\n if (list) {\n list.push(event);\n } else {\n map.set(key, [event]);\n }\n }\n }\n return map;\n }, [events]);\n\n const lookupEventsForDate = useCallback(\n (date: Date): CalendarEvent[] => {\n const key = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;\n return eventsByDate.get(key) ?? [];\n },\n [eventsByDate],\n );\n\n const selectedDateEvents = useMemo(() => {\n if (!selectedDate) return [];\n return lookupEventsForDate(selectedDate);\n }, [selectedDate, lookupEventsForDate]);\n\n return { lookupEventsForDate, selectedDateEvents };\n}\n\ntype CalendarWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Premium polish (new, additive)\n showEventDensity?: boolean;\n showTodayButton?: boolean;\n weekendDim?: boolean;\n showYearEyebrow?: boolean;\n};\n\nexport function CalendarWidget({\n titleEnabled = true,\n titleText = \"Calendar\",\n titleFontSize = \"xl\",\n titleColor = \"foreground\",\n\n background = { type: \"solid\", color: \"background\" },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n showEventDensity = true,\n showTodayButton = true,\n weekendDim = true,\n showYearEyebrow = true,\n\n className,\n ...props\n}: CalendarWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [selectedDate, setSelectedDate] = useState<Date | null>(\n () => new Date(),\n );\n const { view, gridTransitioning, navigate, goToToday } =\n useCalendarNavigation(setSelectedDate);\n const currentMonth = view.month;\n const currentYear = view.year;\n\n const { data: events = [], isLoading, isError } = useCalendarEvents();\n\n const monthGrid = useMemo(\n () => generateMonthGrid(currentYear, currentMonth),\n [currentYear, currentMonth],\n );\n const weekGrid = generateWeekGrid();\n const { lookupEventsForDate, selectedDateEvents } = useCalendarEventIndex(\n events,\n selectedDate,\n );\n\n const now = new Date();\n const viewingCurrentMonth =\n currentMonth === now.getMonth() && currentYear === now.getFullYear();\n\n const monthLabel = new Date(currentYear, currentMonth).toLocaleString(\n \"en-US\",\n { month: \"long\" },\n );\n const yearLabel = String(currentYear);\n\n const contextualDate = selectedDate\n ? formatContextualDate(selectedDate)\n : null;\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {titleEnabled && titleText && (\n <div className={`p-${padding} pb-0`}>\n <h2\n className={`text-${titleFontSize} text-${titleColor} font-bold tracking-[-0.012em]`}\n >\n {titleText}\n </h2>\n </div>\n )}\n\n {isLoading ? (\n <div\n className={`flex min-h-[300px] items-center justify-center p-${padding}`}\n >\n <div className={`text-${accentColor}`}>\n <div className=\"size-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n </div>\n ) : isError ? (\n <ErrorState />\n ) : (\n <div className={`p-${padding}`}>\n <div className=\"@md:flex @md:gap-6\">\n <div className=\"@md:flex-none\">\n {/* Header row: year eyebrow + month + asymmetric nav + Today pill */}\n <div className=\"mb-4 flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 flex-col\">\n {showYearEyebrow && (\n <span\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${textColor}/55`}\n >\n {yearLabel}\n </span>\n )}\n <span\n className={`text-xl leading-tight font-bold tracking-[-0.015em] text-${textColor}`}\n >\n {monthLabel}\n </span>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1.5\">\n {showTodayButton && !viewingCurrentMonth && (\n <button\n type=\"button\"\n onClick={goToToday}\n className={`flex items-center gap-1 rounded-full bg-${accentColor}/10 px-2.5 py-1 text-[11px] font-semibold text-${accentColor} transition-colors hover:bg-${accentColor}/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-${accentColor}/40`}\n >\n <CalendarCheck className=\"size-3\" />\n Today\n </button>\n )}\n <NavButton\n icon={ChevronLeft}\n label=\"Previous month\"\n variant=\"ghost\"\n accentColor={accentColor}\n textColor={textColor}\n onClick={() => navigate(-1)}\n />\n <NavButton\n icon={ChevronRight}\n label=\"Next month\"\n variant=\"accent\"\n accentColor={accentColor}\n textColor={textColor}\n onClick={() => navigate(1)}\n />\n </div>\n </div>\n\n {/* Day-of-week headers */}\n <div className=\"mb-2 grid grid-cols-7 gap-1 text-center\">\n {DAY_NAMES.map((day, idx) => {\n const isWeekend = idx === 0 || idx === 6;\n const dimmed = weekendDim && isWeekend;\n return (\n <div\n key={day}\n className={`text-[10px] font-semibold tracking-[0.12em] uppercase text-${textColor}/${dimmed ? \"40\" : \"55\"}`}\n >\n {day}\n </div>\n );\n })}\n </div>\n\n {/* Grid wrapper (opacity transitions on month navigate) */}\n <div\n className=\"transition-opacity duration-150 ease-out\"\n style={{ opacity: gridTransitioning ? 0.3 : 1 }}\n >\n {/* Collapsed week view on mobile */}\n {isCollapsed && (\n <div className=\"grid grid-cols-7 gap-1 @md:hidden\">\n {weekGrid.map(({ date, isToday }) => (\n <DayCellButton\n key={date.toISOString()}\n date={date}\n isToday={isToday}\n isSelected={\n !!selectedDate && isSameDay(selectedDate, date)\n }\n eventCount={lookupEventsForDate(date).length}\n accentColor={accentColor}\n textColor={textColor}\n showEventDensity={showEventDensity}\n onClick={() => setSelectedDate(date)}\n />\n ))}\n </div>\n )}\n\n {/* Month grid */}\n <div\n className={`grid grid-cols-7 gap-1 ${isCollapsed ? \"hidden @md:grid\" : \"grid\"}`}\n >\n {monthGrid.map((cell, idx) => {\n if (!cell.date) {\n return (\n <div key={`empty-${idx}`} className=\"aspect-square\" />\n );\n }\n const eventCount = lookupEventsForDate(cell.date).length;\n return (\n <DayCellButton\n key={cell.date.toISOString()}\n date={cell.date}\n isToday={cell.isToday}\n isSelected={\n !!selectedDate && isSameDay(selectedDate, cell.date)\n }\n eventCount={eventCount}\n accentColor={accentColor}\n textColor={textColor}\n showEventDensity={showEventDensity}\n onClick={() => setSelectedDate(cell.date)}\n />\n );\n })}\n </div>\n </div>\n\n {/* Mobile collapse toggle */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className={`mt-2 flex w-full items-center justify-center gap-3 rounded-full p-1 text-${textColor}/40 transition-colors hover:text-${textColor}/60 @md:hidden`}\n aria-label={\n isCollapsed ? \"Expand calendar\" : \"Collapse calendar\"\n }\n >\n <div className={`h-px w-1/2 bg-${textColor}/20`} />\n {isCollapsed ? (\n <ChevronsDown className=\"size-3\" />\n ) : (\n <ChevronsUp className=\"size-3\" />\n )}\n <div className={`h-px w-1/2 bg-${textColor}/20`} />\n </button>\n </div>\n\n {/* Events rail */}\n <div\n className={`mt-4 border-${textColor}/10 @md:mt-0 @md:w-56 @md:border-l @md:pl-6`}\n >\n {/* Context header */}\n {contextualDate && (\n <div className=\"mb-3\">\n {contextualDate.lead && (\n <div\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${accentColor}`}\n >\n {contextualDate.lead}\n </div>\n )}\n <div\n className={`text-sm font-semibold text-${textColor} tabular-nums`}\n >\n {contextualDate.detail}\n </div>\n </div>\n )}\n\n {/* Events list with soft fade-in keyed by selected date */}\n <div\n key={selectedDate?.toISOString() ?? \"none\"}\n className=\"animate-in fade-in slide-in-from-bottom-2 flex flex-col duration-200 ease-out\"\n >\n {selectedDateEvents.length > 0 ? (\n selectedDateEvents.map((event, idx) => (\n <EventCard\n key={`${event.id}-${idx}`}\n event={event}\n accentColor={accentColor}\n textColor={textColor}\n />\n ))\n ) : (\n <div\n className={`flex flex-col items-start gap-1 rounded-md border border-dashed border-${textColor}/15 px-3 py-3`}\n >\n <div className=\"flex items-center gap-1.5\">\n <CalendarCheck\n className={`size-3 text-${textColor}/40`}\n />\n <span\n className={`text-[11px] font-semibold text-${textColor}/60`}\n >\n Nothing scheduled\n </span>\n </div>\n <span className={`text-[11px] text-${textColor}/45`}>\n Enjoy the breather.\n </span>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const calendarWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CalendarWidget\",\n displayName: \"Calendar Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the calendar\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the calendar\",\n defaultValue: \"Calendar\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Design group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the calendar container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for calendar content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description:\n \"Drives today highlight, event dots, Today pill, and selected day\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the calendar container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the calendar container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n\n // Polish group (new)\n {\n key: \"showYearEyebrow\",\n label: \"Year Eyebrow\",\n type: \"boolean\",\n description:\n \"Small uppercase year label above the month (e.g. '2026 / November').\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"showTodayButton\",\n label: \"Today Button\",\n type: \"boolean\",\n description: \"Show a 'Today' pill when viewing a different month.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"showEventDensity\",\n label: \"Event Density Dots\",\n type: \"boolean\",\n description:\n \"Show 1–3 dots per day based on event count (off = single dot).\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"weekendDim\",\n label: \"Dim Weekends\",\n type: \"boolean\",\n description:\n \"Subtly dim the Sun/Sat day-of-week headers for visual rhythm.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
1
+ {"version":3,"file":"CalendarWidget-C4Dv_TUk.cjs","names":["useWidgetsApi","useWidgetPreviewContext","useDataSourceRegistryConfig","MapPin","ErrorState","CalendarCheck","ChevronLeft","ChevronRight","ChevronsDown","ChevronsUp","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField"],"sources":["../../widgets/src/hooks/use-calendar-events.preview.ts","../../widgets/src/hooks/use-calendar-events.ts","../../widgets/src/widgets/CalendarWidget.tsx"],"sourcesContent":["import type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nconst today = new Date();\nconst inTwoDays = new Date(today);\ninTwoDays.setDate(inTwoDays.getDate() + 2);\n\nfunction toISO(date: Date, hours: number, minutes = 0): string {\n const d = new Date(date);\n d.setHours(hours, minutes, 0, 0);\n return d.toISOString();\n}\n\nfunction toDateString(date: Date): string {\n return date.toISOString().split(\"T\")[0]!;\n}\n\nexport const PREVIEW_DATA: CalendarEvent[] = [\n {\n id: 1,\n title: \"Team Strategy Call\",\n start: toISO(today, 9, 0),\n end: toISO(today, 10, 0),\n status: \"active\",\n color: \"#4f46e5\",\n },\n {\n id: 2,\n title: \"Product Launch Webinar\",\n start: toISO(today, 14, 0),\n end: toISO(today, 15, 30),\n status: \"active\",\n color: \"#0891b2\",\n venue: \"Zoom\",\n },\n {\n id: 3,\n title: \"Annual Leadership Summit\",\n start: `${toDateString(inTwoDays)}T00:00:00.000Z`,\n end: `${toDateString(inTwoDays)}T23:59:59.000Z`,\n status: \"active\",\n color: \"#059669\",\n isAllDay: true,\n venue: \"Convention Center\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useWidgetsApi } from \"@fluid-app/portal-core/widgets-api-context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { PREVIEW_DATA } from \"./use-calendar-events.preview\";\nimport type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type { CalendarEvent } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport function useCalendarEvents(): UseQueryResult<CalendarEvent[], Error> {\n const widgetsApi = useWidgetsApi();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"calendar-events\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: ({ signal }) => widgetsApi.fetchCalendarEvents(signal),\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import {\n useState,\n useMemo,\n useCallback,\n useRef,\n useEffect,\n type ComponentProps,\n} from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport {\n useCalendarEvents,\n type CalendarEvent,\n} from \"../hooks/use-calendar-events\";\nimport { ErrorState } from \"../components/error-state\";\nimport {\n CalendarCheck,\n ChevronLeft,\n ChevronRight,\n ChevronsDown,\n ChevronsUp,\n MapPin,\n type LucideIcon,\n} from \"lucide-react\";\n\nconst DAY_NAMES = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"] as const;\n\nconst getDaysInMonth = (year: number, month: number): number =>\n new Date(year, month + 1, 0).getDate();\n\nconst getFirstDayOfMonth = (year: number, month: number): number =>\n new Date(year, month, 1).getDay();\n\nconst isSameDay = (a: Date, b: Date): boolean =>\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate();\n\nconst startOfDay = (d: Date): Date => {\n const x = new Date(d);\n x.setHours(0, 0, 0, 0);\n return x;\n};\n\nconst addDays = (d: Date, n: number): Date => {\n const x = new Date(d);\n x.setDate(x.getDate() + n);\n return x;\n};\n\nconst diffDays = (a: Date, b: Date): number => {\n const ms = startOfDay(a).getTime() - startOfDay(b).getTime();\n return Math.round(ms / 86400000);\n};\n\ntype DayCell = {\n date: Date | null;\n isToday: boolean;\n isCurrentMonth: boolean;\n};\n\nconst generateMonthGrid = (year: number, month: number): DayCell[] => {\n const daysInMonth = getDaysInMonth(year, month);\n const firstDay = getFirstDayOfMonth(year, month);\n const today = new Date();\n const cells: DayCell[] = [];\n\n for (let i = 0; i < firstDay; i++) {\n cells.push({ date: null, isToday: false, isCurrentMonth: false });\n }\n\n for (let day = 1; day <= daysInMonth; day++) {\n const date = new Date(year, month, day);\n cells.push({\n date,\n isToday: isSameDay(date, today),\n isCurrentMonth: true,\n });\n }\n\n return cells;\n};\n\nconst generateWeekGrid = (): Array<{ date: Date; isToday: boolean }> => {\n const today = new Date();\n const weekday = today.getDay();\n return Array.from({ length: 7 }, (_, i) => {\n const date = addDays(today, -weekday + i);\n return { date, isToday: isSameDay(date, today) };\n });\n};\n\nconst formatTime = (iso: string): string =>\n new Date(iso).toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n\nconst formatContextualDate = (\n date: Date,\n): { lead: string | null; detail: string } => {\n const today = new Date();\n const d = diffDays(date, today);\n const weekday = date.toLocaleDateString(\"en-US\", { weekday: \"short\" });\n const monthDay = date.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n });\n if (d === 0) return { lead: \"Today\", detail: `${weekday}, ${monthDay}` };\n if (d === 1) return { lead: \"Tomorrow\", detail: `${weekday}, ${monthDay}` };\n if (d === -1) return { lead: \"Yesterday\", detail: `${weekday}, ${monthDay}` };\n return { lead: null, detail: `${weekday}, ${monthDay}` };\n};\n\ntype DayCellButtonProps = {\n date: Date;\n isToday: boolean;\n isSelected: boolean;\n eventCount: number;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n showEventDensity: boolean;\n onClick: () => void;\n};\n\nfunction DayCellButton({\n date,\n isToday,\n isSelected,\n eventCount,\n accentColor,\n textColor,\n showEventDensity,\n onClick,\n}: DayCellButtonProps) {\n const dotCount = showEventDensity\n ? Math.min(eventCount, 3)\n : eventCount > 0\n ? 1\n : 0;\n\n const baseClasses =\n \"group relative flex aspect-square w-full flex-col items-center justify-center rounded-lg text-sm tabular-nums transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-0\";\n\n const stateClasses = isSelected\n ? `bg-${accentColor} text-${accentColor}-foreground focus-visible:ring-${accentColor}/40`\n : isToday\n ? `bg-${accentColor}/10 text-${accentColor} font-semibold hover:bg-${accentColor}/20 focus-visible:ring-${accentColor}/40`\n : `text-${textColor} hover:bg-${accentColor}/10 focus-visible:ring-${accentColor}/40`;\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={date.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n })}\n aria-current={isToday ? \"date\" : undefined}\n aria-pressed={isSelected}\n className={`${baseClasses} ${stateClasses}`}\n >\n <span className=\"leading-none\">{date.getDate()}</span>\n {dotCount > 0 && (\n <span\n aria-hidden=\"true\"\n className=\"absolute bottom-1.5 flex items-center gap-[2px]\"\n >\n {Array.from({ length: dotCount }).map((_, i) => (\n <span\n key={i}\n className={`size-1 rounded-full ${\n isSelected\n ? `bg-${accentColor}-foreground/70`\n : `bg-${accentColor}`\n }`}\n />\n ))}\n </span>\n )}\n </button>\n );\n}\n\ntype EventCardProps = {\n event: CalendarEvent;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n};\n\nfunction EventCard({ event, accentColor, textColor }: EventCardProps) {\n const accentVar = `var(--color-${accentColor})`;\n const barColor = event.color || accentVar;\n const timeText = event.isAllDay\n ? \"All day\"\n : `${formatTime(event.start)} – ${formatTime(event.end)}`;\n\n const content = (\n <>\n <span\n aria-hidden=\"true\"\n className=\"w-[2px] shrink-0 self-stretch rounded-full\"\n style={{ backgroundColor: barColor }}\n />\n <div className=\"min-w-0 flex-1\">\n <div\n className={`truncate text-sm font-semibold text-${textColor} leading-tight`}\n >\n {event.title}\n </div>\n <div\n className={`mt-1 text-[11px] tabular-nums text-${textColor}/60 font-medium`}\n >\n {timeText}\n </div>\n {event.venue && (\n <div\n className={`mt-1.5 flex items-center gap-1 text-[11px] text-${textColor}/55`}\n >\n <MapPin className=\"size-2.5 shrink-0\" />\n <span className=\"truncate\">{event.venue}</span>\n </div>\n )}\n </div>\n </>\n );\n\n const wrapperClasses = `group flex gap-x-2 rounded-md px-2 py-2 transition-colors -mx-2`;\n const interactiveClasses = `hover:bg-${accentColor}/5`;\n\n if (event.url) {\n return (\n <a\n href={event.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`${wrapperClasses} ${interactiveClasses}`}\n >\n {content}\n </a>\n );\n }\n\n return <div className={wrapperClasses}>{content}</div>;\n}\n\ntype NavButtonProps = {\n icon: LucideIcon;\n label: string;\n variant: \"ghost\" | \"accent\";\n accentColor: ColorOptions;\n textColor: ColorOptions;\n onClick: () => void;\n};\n\nfunction NavButton({\n icon: Icon,\n label,\n variant,\n accentColor,\n textColor,\n onClick,\n}: NavButtonProps) {\n const classes =\n variant === \"accent\"\n ? `bg-${accentColor} text-${accentColor}-foreground hover:bg-${accentColor}/90 focus-visible:ring-${accentColor}/40`\n : `bg-${textColor}/5 text-${textColor} hover:bg-${textColor}/10 focus-visible:ring-${textColor}/20`;\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className={`flex size-8 items-center justify-center rounded-full text-[12px] transition-colors focus:outline-none focus-visible:ring-2 ${classes}`}\n >\n <Icon className=\"size-4\" />\n </button>\n );\n}\n\ntype CalendarView = {\n month: number;\n year: number;\n};\n\nconst getInitialCalendarView = (): CalendarView => {\n const now = new Date();\n return { month: now.getMonth(), year: now.getFullYear() };\n};\n\nfunction useCalendarNavigation(\n setSelectedDate: React.Dispatch<React.SetStateAction<Date | null>>,\n) {\n const [view, setView] = useState(getInitialCalendarView);\n const [gridTransitioning, setGridTransitioning] = useState(false);\n const transitionTimeoutRef = useRef<number | null>(null);\n\n useEffect(\n () => () => {\n if (transitionTimeoutRef.current !== null) {\n window.clearTimeout(transitionTimeoutRef.current);\n }\n },\n [],\n );\n\n const clearPendingTransition = useCallback(() => {\n if (transitionTimeoutRef.current !== null) {\n window.clearTimeout(transitionTimeoutRef.current);\n transitionTimeoutRef.current = null;\n }\n }, []);\n\n const navigate = useCallback(\n (direction: -1 | 1) => {\n clearPendingTransition();\n setGridTransitioning(true);\n transitionTimeoutRef.current = window.setTimeout(() => {\n setView((prev) => {\n const next = prev.month + direction;\n if (next < 0) return { month: 11, year: prev.year - 1 };\n if (next > 11) return { month: 0, year: prev.year + 1 };\n return { month: next, year: prev.year };\n });\n setGridTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 120);\n },\n [clearPendingTransition],\n );\n\n const goToToday = useCallback(() => {\n clearPendingTransition();\n const now = new Date();\n setGridTransitioning(true);\n transitionTimeoutRef.current = window.setTimeout(() => {\n setView({ month: now.getMonth(), year: now.getFullYear() });\n setSelectedDate(now);\n setGridTransitioning(false);\n transitionTimeoutRef.current = null;\n }, 80);\n }, [clearPendingTransition, setSelectedDate]);\n\n return { view, gridTransitioning, navigate, goToToday };\n}\n\nfunction useCalendarEventIndex(\n events: CalendarEvent[],\n selectedDate: Date | null,\n) {\n const eventsByDate = useMemo(() => {\n const map = new Map<string, CalendarEvent[]>();\n for (const event of events) {\n const start = startOfDay(new Date(event.start));\n const end = startOfDay(new Date(event.end));\n for (let cur = start; cur <= end; cur = addDays(cur, 1)) {\n const key = `${cur.getFullYear()}-${cur.getMonth()}-${cur.getDate()}`;\n const list = map.get(key);\n if (list) {\n list.push(event);\n } else {\n map.set(key, [event]);\n }\n }\n }\n return map;\n }, [events]);\n\n const lookupEventsForDate = useCallback(\n (date: Date): CalendarEvent[] => {\n const key = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;\n return eventsByDate.get(key) ?? [];\n },\n [eventsByDate],\n );\n\n const selectedDateEvents = useMemo(() => {\n if (!selectedDate) return [];\n return lookupEventsForDate(selectedDate);\n }, [selectedDate, lookupEventsForDate]);\n\n return { lookupEventsForDate, selectedDateEvents };\n}\n\ntype CalendarWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n\n // Premium polish (new, additive)\n showEventDensity?: boolean;\n showTodayButton?: boolean;\n weekendDim?: boolean;\n showYearEyebrow?: boolean;\n};\n\nexport function CalendarWidget({\n titleEnabled = true,\n titleText = \"Calendar\",\n titleFontSize = \"xl\",\n titleColor = \"foreground\",\n\n background = { type: \"solid\", color: \"background\" },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n\n showEventDensity = true,\n showTodayButton = true,\n weekendDim = true,\n showYearEyebrow = true,\n\n className,\n ...props\n}: CalendarWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [selectedDate, setSelectedDate] = useState<Date | null>(\n () => new Date(),\n );\n const { view, gridTransitioning, navigate, goToToday } =\n useCalendarNavigation(setSelectedDate);\n const currentMonth = view.month;\n const currentYear = view.year;\n\n const { data: events = [], isLoading, isError } = useCalendarEvents();\n\n const monthGrid = useMemo(\n () => generateMonthGrid(currentYear, currentMonth),\n [currentYear, currentMonth],\n );\n const weekGrid = generateWeekGrid();\n const { lookupEventsForDate, selectedDateEvents } = useCalendarEventIndex(\n events,\n selectedDate,\n );\n\n const now = new Date();\n const viewingCurrentMonth =\n currentMonth === now.getMonth() && currentYear === now.getFullYear();\n\n const monthLabel = new Date(currentYear, currentMonth).toLocaleString(\n \"en-US\",\n { month: \"long\" },\n );\n const yearLabel = String(currentYear);\n\n const contextualDate = selectedDate\n ? formatContextualDate(selectedDate)\n : null;\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {titleEnabled && titleText && (\n <div className={`p-${padding} pb-0`}>\n <h2\n className={`text-${titleFontSize} text-${titleColor} font-bold tracking-[-0.012em]`}\n >\n {titleText}\n </h2>\n </div>\n )}\n\n {isLoading ? (\n <div\n className={`flex min-h-[300px] items-center justify-center p-${padding}`}\n >\n <div className={`text-${accentColor}`}>\n <div className=\"size-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n </div>\n ) : isError ? (\n <ErrorState />\n ) : (\n <div className={`p-${padding}`}>\n <div className=\"@md:flex @md:gap-6\">\n <div className=\"@md:flex-none\">\n {/* Header row: year eyebrow + month + asymmetric nav + Today pill */}\n <div className=\"mb-4 flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 flex-col\">\n {showYearEyebrow && (\n <span\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${textColor}/55`}\n >\n {yearLabel}\n </span>\n )}\n <span\n className={`text-xl leading-tight font-bold tracking-[-0.015em] text-${textColor}`}\n >\n {monthLabel}\n </span>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1.5\">\n {showTodayButton && !viewingCurrentMonth && (\n <button\n type=\"button\"\n onClick={goToToday}\n className={`flex items-center gap-1 rounded-full bg-${accentColor}/10 px-2.5 py-1 text-[11px] font-semibold text-${accentColor} transition-colors hover:bg-${accentColor}/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-${accentColor}/40`}\n >\n <CalendarCheck className=\"size-3\" />\n Today\n </button>\n )}\n <NavButton\n icon={ChevronLeft}\n label=\"Previous month\"\n variant=\"ghost\"\n accentColor={accentColor}\n textColor={textColor}\n onClick={() => navigate(-1)}\n />\n <NavButton\n icon={ChevronRight}\n label=\"Next month\"\n variant=\"accent\"\n accentColor={accentColor}\n textColor={textColor}\n onClick={() => navigate(1)}\n />\n </div>\n </div>\n\n {/* Day-of-week headers */}\n <div className=\"mb-2 grid grid-cols-7 gap-1 text-center\">\n {DAY_NAMES.map((day, idx) => {\n const isWeekend = idx === 0 || idx === 6;\n const dimmed = weekendDim && isWeekend;\n return (\n <div\n key={day}\n className={`text-[10px] font-semibold tracking-[0.12em] uppercase text-${textColor}/${dimmed ? \"40\" : \"55\"}`}\n >\n {day}\n </div>\n );\n })}\n </div>\n\n {/* Grid wrapper (opacity transitions on month navigate) */}\n <div\n className=\"transition-opacity duration-150 ease-out\"\n style={{ opacity: gridTransitioning ? 0.3 : 1 }}\n >\n {/* Collapsed week view on mobile */}\n {isCollapsed && (\n <div className=\"grid grid-cols-7 gap-1 @md:hidden\">\n {weekGrid.map(({ date, isToday }) => (\n <DayCellButton\n key={date.toISOString()}\n date={date}\n isToday={isToday}\n isSelected={\n !!selectedDate && isSameDay(selectedDate, date)\n }\n eventCount={lookupEventsForDate(date).length}\n accentColor={accentColor}\n textColor={textColor}\n showEventDensity={showEventDensity}\n onClick={() => setSelectedDate(date)}\n />\n ))}\n </div>\n )}\n\n {/* Month grid */}\n <div\n className={`grid grid-cols-7 gap-1 ${isCollapsed ? \"hidden @md:grid\" : \"grid\"}`}\n >\n {monthGrid.map((cell, idx) => {\n if (!cell.date) {\n return (\n <div key={`empty-${idx}`} className=\"aspect-square\" />\n );\n }\n const eventCount = lookupEventsForDate(cell.date).length;\n return (\n <DayCellButton\n key={cell.date.toISOString()}\n date={cell.date}\n isToday={cell.isToday}\n isSelected={\n !!selectedDate && isSameDay(selectedDate, cell.date)\n }\n eventCount={eventCount}\n accentColor={accentColor}\n textColor={textColor}\n showEventDensity={showEventDensity}\n onClick={() => setSelectedDate(cell.date)}\n />\n );\n })}\n </div>\n </div>\n\n {/* Mobile collapse toggle */}\n <button\n type=\"button\"\n onClick={() => setIsCollapsed(!isCollapsed)}\n className={`mt-2 flex w-full items-center justify-center gap-3 rounded-full p-1 text-${textColor}/40 transition-colors hover:text-${textColor}/60 @md:hidden`}\n aria-label={\n isCollapsed ? \"Expand calendar\" : \"Collapse calendar\"\n }\n >\n <div className={`h-px w-1/2 bg-${textColor}/20`} />\n {isCollapsed ? (\n <ChevronsDown className=\"size-3\" />\n ) : (\n <ChevronsUp className=\"size-3\" />\n )}\n <div className={`h-px w-1/2 bg-${textColor}/20`} />\n </button>\n </div>\n\n {/* Events rail */}\n <div\n className={`mt-4 border-${textColor}/10 @md:mt-0 @md:w-56 @md:border-l @md:pl-6`}\n >\n {/* Context header */}\n {contextualDate && (\n <div className=\"mb-3\">\n {contextualDate.lead && (\n <div\n className={`text-[10px] font-bold tracking-[0.16em] uppercase text-${accentColor}`}\n >\n {contextualDate.lead}\n </div>\n )}\n <div\n className={`text-sm font-semibold text-${textColor} tabular-nums`}\n >\n {contextualDate.detail}\n </div>\n </div>\n )}\n\n {/* Events list with soft fade-in keyed by selected date */}\n <div\n key={selectedDate?.toISOString() ?? \"none\"}\n className=\"animate-in fade-in slide-in-from-bottom-2 flex flex-col duration-200 ease-out\"\n >\n {selectedDateEvents.length > 0 ? (\n selectedDateEvents.map((event, idx) => (\n <EventCard\n key={`${event.id}-${idx}`}\n event={event}\n accentColor={accentColor}\n textColor={textColor}\n />\n ))\n ) : (\n <div\n className={`flex flex-col items-start gap-1 rounded-md border border-dashed border-${textColor}/15 px-3 py-3`}\n >\n <div className=\"flex items-center gap-1.5\">\n <CalendarCheck\n className={`size-3 text-${textColor}/40`}\n />\n <span\n className={`text-[11px] font-semibold text-${textColor}/60`}\n >\n Nothing scheduled\n </span>\n </div>\n <span className={`text-[11px] text-${textColor}/45`}>\n Enjoy the breather.\n </span>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const calendarWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CalendarWidget\",\n displayName: \"Calendar Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the calendar\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the calendar\",\n defaultValue: \"Calendar\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Design group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the calendar container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for calendar content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description:\n \"Drives today highlight, event dots, Today pill, and selected day\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the calendar container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the calendar container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n\n // Polish group (new)\n {\n key: \"showYearEyebrow\",\n label: \"Year Eyebrow\",\n type: \"boolean\",\n description:\n \"Small uppercase year label above the month (e.g. '2026 / November').\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"showTodayButton\",\n label: \"Today Button\",\n type: \"boolean\",\n description: \"Show a 'Today' pill when viewing a different month.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"showEventDensity\",\n label: \"Event Density Dots\",\n type: \"boolean\",\n description:\n \"Show 1–3 dots per day based on event count (off = single dot).\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n {\n key: \"weekendDim\",\n label: \"Dim Weekends\",\n type: \"boolean\",\n description:\n \"Subtly dim the Sun/Sat day-of-week headers for visual rhythm.\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Polish\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { r as __exportAll } from "./es-BXxGlAp6.mjs";
2
- import { c as useScreenRenderer, t as ScreenRenderer, u as useRegistry } from "./ScreenRenderer-ClYgfQf_.mjs";
2
+ import { c as useScreenRenderer, t as ScreenRenderer, u as useRegistry } from "./ScreenRenderer-Cl2aAJ7D.mjs";
3
3
  import { f as getGapField, i as getBorderColorField, l as getColorField, m as getPaddingField, n as borderWidthClasses, o as getBorderRadiusField, r as gapValues, s as getBorderWidthField, t as borderColorClasses, u as getFontSizeField } from "./registries-Ct8o2YRe.mjs";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region ../widgets/src/widgets/CardWidget.tsx
@@ -187,4 +187,4 @@ const cardWidgetPropertySchema = {
187
187
  //#endregion
188
188
  export { CardWidget_exports as n, cardWidgetPropertySchema as r, CardWidget as t };
189
189
 
190
- //# sourceMappingURL=CardWidget-BNkMlxQ3.mjs.map
190
+ //# sourceMappingURL=CardWidget-2wcjCf2M.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"CardWidget-BNkMlxQ3.mjs","names":["ScreenRenderer","DefaultScreenRenderer"],"sources":["../../widgets/src/widgets/CardWidget.tsx"],"sourcesContent":["import { ScreenRenderer as DefaultScreenRenderer } from \"../core/ScreenRenderer\";\nimport { useRegistry } from \"../contexts/RegistryContext\";\nimport { useScreenRenderer } from \"../contexts/ScreenRendererContext\";\nimport type {\n WidgetSchema,\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n PaddingOptions,\n GapOptions,\n ColorOptions,\n FontSizeOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type React from \"react\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\n\nconst DEFAULT_BACKGROUND: BackgroundValue = {\n type: \"solid\",\n color: \"background\",\n};\nconst DEFAULT_CHILDREN: (WidgetSchema | null)[] = [];\n\ntype CardWidgetProps = {\n // Header\n headerEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n headerBackground?: ColorOptions;\n\n // Footer\n footerEnabled?: boolean;\n footerContent?: string;\n footerColor?: ColorOptions;\n footerBackground?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n /** @deprecated Use borderWidth instead */\n borderEnabled?: boolean;\n gapSize?: GapOptions;\n\n // Container props (children = other widgets)\n children?: (WidgetSchema | null)[];\n\n // Styling\n className?: string;\n};\n\nexport function CardWidget({\n // Header\n headerEnabled = true,\n title = \"Card Title\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n headerBackground = \"transparent\",\n\n // Footer\n footerEnabled = false,\n footerContent = \"\",\n footerColor = \"muted\",\n footerBackground = \"transparent\",\n\n // Styling\n background = DEFAULT_BACKGROUND,\n padding = 6,\n borderRadius = \"xl\",\n borderWidth = \"thin\",\n borderColor = \"muted\",\n borderEnabled,\n gapSize = \"md\",\n\n // Container\n children = DEFAULT_CHILDREN,\n\n className = \"\",\n}: CardWidgetProps): React.JSX.Element {\n // Get registry from context if not provided as prop\n const contextRegistry = useRegistry();\n\n // Use ScreenRenderer from context, fall back to local\n const ContextScreenRenderer = useScreenRenderer();\n const ScreenRenderer = ContextScreenRenderer ?? DefaultScreenRenderer;\n\n // Extract background values\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n const gapSizeValue = gapSize ? gapValues[gapSize] : 4;\n\n // Backwards compatibility: if legacy borderEnabled prop exists, map it\n const effectiveBorderWidth = borderEnabled === false ? \"none\" : borderWidth;\n\n const cardClasses = [\n \"flex flex-col gap-6\",\n `bg-${backgroundColor}`,\n `p-${padding}`,\n `rounded-${borderRadius}`,\n borderWidthClasses[effectiveBorderWidth],\n effectiveBorderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const containerStyle: React.CSSProperties = {\n backgroundImage,\n };\n\n // Filter out null children\n const validChildren = children.filter(\n (child): child is WidgetSchema => child !== null,\n );\n\n return (\n <div data-slot=\"card\" className={cardClasses} style={containerStyle}>\n {headerEnabled && (title || headerBackground !== \"transparent\") && (\n <div\n data-slot=\"card-header\"\n className={\n headerBackground !== \"transparent\"\n ? `bg-${headerBackground} -mx-${padding} -mt-${padding} px-${padding} py-${padding} rounded-t-${borderRadius}`\n : undefined\n }\n >\n {title && (\n <div\n data-slot=\"card-title\"\n className={`text-${titleFontSize} text-${titleColor} font-header leading-none font-semibold`}\n >\n {title}\n </div>\n )}\n </div>\n )}\n\n <div data-slot=\"card-content\" className=\"@container flex-1\">\n {contextRegistry ? (\n <ScreenRenderer\n screen={validChildren}\n registry={contextRegistry}\n className={`flex flex-col gap-${gapSizeValue}`}\n />\n ) : (\n <div className={`flex flex-col gap-${gapSizeValue}`} />\n )}\n </div>\n\n {footerEnabled && footerContent && (\n <div\n data-slot=\"card-footer\"\n className={[\n `text-sm text-${footerColor} flex items-center`,\n footerBackground !== \"transparent\"\n ? `bg-${footerBackground} -mx-${padding} -mb-${padding} px-${padding} py-${padding} rounded-b-${borderRadius}`\n : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {footerContent}\n </div>\n )}\n </div>\n );\n}\n\nexport const cardWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CardWidget\",\n displayName: \"Card\",\n fields: [\n // Header\n {\n key: \"headerEnabled\",\n label: \"Show Header\",\n type: \"boolean\",\n description: \"Toggle header visibility\",\n defaultValue: true,\n group: \"Header\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Card title text\",\n defaultValue: \"Card Title\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"lg\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"foreground\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n getColorField({\n key: \"headerBackground\",\n label: \"Header Background\",\n description: \"Background color for the header\",\n defaultValue: \"transparent\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n\n // Footer\n {\n key: \"footerEnabled\",\n label: \"Show Footer\",\n type: \"boolean\",\n description: \"Toggle footer visibility\",\n defaultValue: false,\n group: \"Footer\",\n },\n {\n key: \"footerContent\",\n label: \"Footer Text\",\n type: \"text\",\n description: \"Footer content text\",\n defaultValue: \"\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n },\n getColorField({\n key: \"footerColor\",\n label: \"Footer Color\",\n description: \"Color for the footer text\",\n defaultValue: \"muted\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n }),\n getColorField({\n key: \"footerBackground\",\n label: \"Footer Background\",\n description: \"Background color for the footer\",\n defaultValue: \"transparent\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n }),\n\n // Design\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the card\",\n defaultValue: \"background\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Card padding\",\n defaultValue: 6,\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Card border radius\",\n defaultValue: \"xl\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Card border width\",\n defaultValue: \"thin\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Card border color\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n getGapField({\n key: \"gapSize\",\n label: \"Gap\",\n description: \"Gap between child widgets\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n ],\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"CardWidget-2wcjCf2M.mjs","names":["ScreenRenderer","DefaultScreenRenderer"],"sources":["../../widgets/src/widgets/CardWidget.tsx"],"sourcesContent":["import { ScreenRenderer as DefaultScreenRenderer } from \"../core/ScreenRenderer\";\nimport { useRegistry } from \"../contexts/RegistryContext\";\nimport { useScreenRenderer } from \"../contexts/ScreenRendererContext\";\nimport type {\n WidgetSchema,\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n PaddingOptions,\n GapOptions,\n ColorOptions,\n FontSizeOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type React from \"react\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\n\nconst DEFAULT_BACKGROUND: BackgroundValue = {\n type: \"solid\",\n color: \"background\",\n};\nconst DEFAULT_CHILDREN: (WidgetSchema | null)[] = [];\n\ntype CardWidgetProps = {\n // Header\n headerEnabled?: boolean;\n title?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n headerBackground?: ColorOptions;\n\n // Footer\n footerEnabled?: boolean;\n footerContent?: string;\n footerColor?: ColorOptions;\n footerBackground?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n /** @deprecated Use borderWidth instead */\n borderEnabled?: boolean;\n gapSize?: GapOptions;\n\n // Container props (children = other widgets)\n children?: (WidgetSchema | null)[];\n\n // Styling\n className?: string;\n};\n\nexport function CardWidget({\n // Header\n headerEnabled = true,\n title = \"Card Title\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n headerBackground = \"transparent\",\n\n // Footer\n footerEnabled = false,\n footerContent = \"\",\n footerColor = \"muted\",\n footerBackground = \"transparent\",\n\n // Styling\n background = DEFAULT_BACKGROUND,\n padding = 6,\n borderRadius = \"xl\",\n borderWidth = \"thin\",\n borderColor = \"muted\",\n borderEnabled,\n gapSize = \"md\",\n\n // Container\n children = DEFAULT_CHILDREN,\n\n className = \"\",\n}: CardWidgetProps): React.JSX.Element {\n // Get registry from context if not provided as prop\n const contextRegistry = useRegistry();\n\n // Use ScreenRenderer from context, fall back to local\n const ContextScreenRenderer = useScreenRenderer();\n const ScreenRenderer = ContextScreenRenderer ?? DefaultScreenRenderer;\n\n // Extract background values\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n const gapSizeValue = gapSize ? gapValues[gapSize] : 4;\n\n // Backwards compatibility: if legacy borderEnabled prop exists, map it\n const effectiveBorderWidth = borderEnabled === false ? \"none\" : borderWidth;\n\n const cardClasses = [\n \"flex flex-col gap-6\",\n `bg-${backgroundColor}`,\n `p-${padding}`,\n `rounded-${borderRadius}`,\n borderWidthClasses[effectiveBorderWidth],\n effectiveBorderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const containerStyle: React.CSSProperties = {\n backgroundImage,\n };\n\n // Filter out null children\n const validChildren = children.filter(\n (child): child is WidgetSchema => child !== null,\n );\n\n return (\n <div data-slot=\"card\" className={cardClasses} style={containerStyle}>\n {headerEnabled && (title || headerBackground !== \"transparent\") && (\n <div\n data-slot=\"card-header\"\n className={\n headerBackground !== \"transparent\"\n ? `bg-${headerBackground} -mx-${padding} -mt-${padding} px-${padding} py-${padding} rounded-t-${borderRadius}`\n : undefined\n }\n >\n {title && (\n <div\n data-slot=\"card-title\"\n className={`text-${titleFontSize} text-${titleColor} font-header leading-none font-semibold`}\n >\n {title}\n </div>\n )}\n </div>\n )}\n\n <div data-slot=\"card-content\" className=\"@container flex-1\">\n {contextRegistry ? (\n <ScreenRenderer\n screen={validChildren}\n registry={contextRegistry}\n className={`flex flex-col gap-${gapSizeValue}`}\n />\n ) : (\n <div className={`flex flex-col gap-${gapSizeValue}`} />\n )}\n </div>\n\n {footerEnabled && footerContent && (\n <div\n data-slot=\"card-footer\"\n className={[\n `text-sm text-${footerColor} flex items-center`,\n footerBackground !== \"transparent\"\n ? `bg-${footerBackground} -mx-${padding} -mb-${padding} px-${padding} py-${padding} rounded-b-${borderRadius}`\n : \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {footerContent}\n </div>\n )}\n </div>\n );\n}\n\nexport const cardWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"CardWidget\",\n displayName: \"Card\",\n fields: [\n // Header\n {\n key: \"headerEnabled\",\n label: \"Show Header\",\n type: \"boolean\",\n description: \"Toggle header visibility\",\n defaultValue: true,\n group: \"Header\",\n },\n {\n key: \"title\",\n label: \"Title\",\n type: \"text\",\n description: \"Card title text\",\n defaultValue: \"Card Title\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the title\",\n defaultValue: \"lg\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the title\",\n defaultValue: \"foreground\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n getColorField({\n key: \"headerBackground\",\n label: \"Header Background\",\n description: \"Background color for the header\",\n defaultValue: \"transparent\",\n group: \"Header\",\n requiresKeyToBeTrue: \"headerEnabled\",\n }),\n\n // Footer\n {\n key: \"footerEnabled\",\n label: \"Show Footer\",\n type: \"boolean\",\n description: \"Toggle footer visibility\",\n defaultValue: false,\n group: \"Footer\",\n },\n {\n key: \"footerContent\",\n label: \"Footer Text\",\n type: \"text\",\n description: \"Footer content text\",\n defaultValue: \"\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n },\n getColorField({\n key: \"footerColor\",\n label: \"Footer Color\",\n description: \"Color for the footer text\",\n defaultValue: \"muted\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n }),\n getColorField({\n key: \"footerBackground\",\n label: \"Footer Background\",\n description: \"Background color for the footer\",\n defaultValue: \"transparent\",\n group: \"Footer\",\n requiresKeyToBeTrue: \"footerEnabled\",\n }),\n\n // Design\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the card\",\n defaultValue: \"background\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Card padding\",\n defaultValue: 6,\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Card border radius\",\n defaultValue: \"xl\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Card border width\",\n defaultValue: \"thin\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Card border color\",\n defaultValue: \"muted\",\n group: \"Design\",\n }),\n getGapField({\n key: \"gapSize\",\n label: \"Gap\",\n description: \"Gap between child widgets\",\n defaultValue: \"md\",\n group: \"Design\",\n }),\n ],\n};\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  require("./chunk-9hOWP6kD.cjs");
2
- require("./ScreenRenderer-Ct1w4PNu.cjs");
3
- require("./registry-context-bf52ZIJX.cjs");
2
+ require("./ScreenRenderer-xH01YkEQ.cjs");
3
+ require("./registry-context-CcZYS15Q.cjs");
4
4
  require("./registries-DBb6VjAX.cjs");
5
5
  require("./fields-COJ84ouS.cjs");
6
- const require_CardWidget = require("./CardWidget-C3I9OwgS.cjs");
6
+ const require_CardWidget = require("./CardWidget-D-KEikO_.cjs");
7
7
  exports.cardWidgetPropertySchema = require_CardWidget.cardWidgetPropertySchema;
@@ -1,5 +1,5 @@
1
1
  require("./chunk-9hOWP6kD.cjs");
2
- const require_ScreenRenderer = require("./ScreenRenderer-Ct1w4PNu.cjs");
2
+ const require_ScreenRenderer = require("./ScreenRenderer-xH01YkEQ.cjs");
3
3
  const require_registries = require("./registries-DBb6VjAX.cjs");
4
4
  let react_jsx_runtime = require("react/jsx-runtime");
5
5
  //#region ../widgets/src/widgets/CardWidget.tsx
@@ -194,4 +194,4 @@ Object.defineProperty(exports, "cardWidgetPropertySchema", {
194
194
  }
195
195
  });
196
196
 
197
- //# sourceMappingURL=CardWidget-C3I9OwgS.cjs.map
197
+ //# sourceMappingURL=CardWidget-D-KEikO_.cjs.map