@fluid-app/portal-sdk 0.1.367 → 0.1.369
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{CalendarWidget-CkuTpX1q.mjs → CalendarWidget--EIsxRov.mjs} +20 -4
- package/dist/CalendarWidget--EIsxRov.mjs.map +1 -0
- package/dist/{CalendarWidget-DEqx8mjm.cjs → CalendarWidget-M1_WyHA_.cjs} +19 -3
- package/dist/CalendarWidget-M1_WyHA_.cjs.map +1 -0
- package/dist/{FluidProvider-CztaeoZL.mjs → FluidProvider-DIhrcma3.mjs} +5 -5
- package/dist/{FluidProvider-CztaeoZL.mjs.map → FluidProvider-DIhrcma3.mjs.map} +1 -1
- package/dist/{FluidProvider-CKmCaFub.cjs → FluidProvider-iStLA04k.cjs} +5 -5
- package/dist/{FluidProvider-CKmCaFub.cjs.map → FluidProvider-iStLA04k.cjs.map} +1 -1
- package/dist/{MessagingScreen-C8XHBT4q.mjs → MessagingScreen-BFpKQppV.mjs} +4 -4
- package/dist/{MessagingScreen-BkruuTwv.mjs → MessagingScreen-BOAnKE3v.mjs} +2 -2
- package/dist/{MessagingScreen-BkruuTwv.mjs.map → MessagingScreen-BOAnKE3v.mjs.map} +1 -1
- package/dist/{MessagingScreen-Cz47JOvi.cjs → MessagingScreen-C5Pejtlt.cjs} +4 -4
- package/dist/{MessagingScreen-0cNGHReM.cjs → MessagingScreen-y_A92ivV.cjs} +2 -2
- package/dist/{MessagingScreen-0cNGHReM.cjs.map → MessagingScreen-y_A92ivV.cjs.map} +1 -1
- package/dist/{NestedWidget-DrRazqvX.cjs → NestedWidget-0YTK04F7.cjs} +26 -17
- package/dist/NestedWidget-0YTK04F7.cjs.map +1 -0
- package/dist/{NestedWidget-Cgsv6RTh.mjs → NestedWidget-BXnLrul1.mjs} +26 -17
- package/dist/NestedWidget-BXnLrul1.mjs.map +1 -0
- package/dist/{NestedWidget-DpCvLNRl.cjs → NestedWidget-C9ypn_4q.cjs} +1 -1
- package/dist/{OrdersScreen-gMh1RSU1.cjs → OrdersScreen-B_jWMXAy.cjs} +2 -2
- package/dist/{OrdersScreen-gMh1RSU1.cjs.map → OrdersScreen-B_jWMXAy.cjs.map} +1 -1
- package/dist/{OrdersScreen-fY13DxDW.cjs → OrdersScreen-BlYerRr0.cjs} +4 -4
- package/dist/{OrdersScreen-DsQqt4qM.mjs → OrdersScreen-BzibsZC0.mjs} +2 -2
- package/dist/{OrdersScreen-DsQqt4qM.mjs.map → OrdersScreen-BzibsZC0.mjs.map} +1 -1
- package/dist/{OrdersScreen-DMzbr6H7.mjs → OrdersScreen-wtdmNSwV.mjs} +4 -4
- package/dist/{ProfileScreen-krWbnTCL.mjs → ProfileScreen-B5bNfcEX.mjs} +3 -3
- package/dist/{ProfileScreen-krWbnTCL.mjs.map → ProfileScreen-B5bNfcEX.mjs.map} +1 -1
- package/dist/{ProfileScreen-B2fDaEd2.cjs → ProfileScreen-BF7Xp0EB.cjs} +3 -3
- package/dist/{ProfileScreen-B2fDaEd2.cjs.map → ProfileScreen-BF7Xp0EB.cjs.map} +1 -1
- package/dist/{ProfileScreen-CYolxWbw.mjs → ProfileScreen-CUEECEVi.mjs} +5 -5
- package/dist/{ProfileScreen-CrQ1t4xC.cjs → ProfileScreen-DXaE0EJ2.cjs} +5 -5
- package/dist/{ShopScreen-CyDAFe-O.cjs → ShopScreen-CIXdmZvI.cjs} +4 -4
- package/dist/{ShopScreen-TjkdGDqA.cjs → ShopScreen-CTdqSSs6.cjs} +2 -2
- package/dist/{ShopScreen-TjkdGDqA.cjs.map → ShopScreen-CTdqSSs6.cjs.map} +1 -1
- package/dist/{ShopScreen-BosF9GYb.mjs → ShopScreen-CUQtjHcp.mjs} +4 -4
- package/dist/{ShopScreen-DlUOUOnJ.mjs → ShopScreen-ChWVG5vG.mjs} +2 -2
- package/dist/{ShopScreen-DlUOUOnJ.mjs.map → ShopScreen-ChWVG5vG.mjs.map} +1 -1
- package/dist/{SubscriptionsScreen-B5-XgmRs.cjs → SubscriptionsScreen-C8Oc4iYz.cjs} +3 -3
- package/dist/{SubscriptionsScreen-B5-XgmRs.cjs.map → SubscriptionsScreen-C8Oc4iYz.cjs.map} +1 -1
- package/dist/{SubscriptionsScreen-33ZWzTC_.mjs → SubscriptionsScreen-CXrorIz1.mjs} +5 -5
- package/dist/{SubscriptionsScreen-C_sIL3Qp.mjs → SubscriptionsScreen-CwH8QyDm.mjs} +3 -3
- package/dist/{SubscriptionsScreen-C_sIL3Qp.mjs.map → SubscriptionsScreen-CwH8QyDm.mjs.map} +1 -1
- package/dist/{SubscriptionsScreen-D4oef3ub.cjs → SubscriptionsScreen-_X2bwjKO.cjs} +5 -5
- package/dist/index.cjs +20 -20
- package/dist/index.d.cts +4 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +4 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +20 -20
- package/dist/preview/preview-entry.cjs +4 -4
- package/dist/preview/preview-entry.mjs +4 -4
- package/dist/{use-portal-card-add-3ds-flow-BXIP3nVI.mjs → use-portal-card-add-3ds-flow-CKkPV6zg.mjs} +2 -2
- package/dist/{use-portal-card-add-3ds-flow-BXIP3nVI.mjs.map → use-portal-card-add-3ds-flow-CKkPV6zg.mjs.map} +1 -1
- package/dist/{use-portal-card-add-3ds-flow-Dd_sgVYj.cjs → use-portal-card-add-3ds-flow-DJoxmO7y.cjs} +2 -2
- package/dist/{use-portal-card-add-3ds-flow-Dd_sgVYj.cjs.map → use-portal-card-add-3ds-flow-DJoxmO7y.cjs.map} +1 -1
- package/dist/{widget-package-utils-Cr6iaMPm.mjs → widget-package-utils-BkrdrNr7.mjs} +2 -2
- package/dist/{widget-package-utils-Cr6iaMPm.mjs.map → widget-package-utils-BkrdrNr7.mjs.map} +1 -1
- package/dist/{widget-package-utils-CTC5WJJq.cjs → widget-package-utils-C00ijCm-.cjs} +2 -2
- package/dist/{widget-package-utils-CTC5WJJq.cjs.map → widget-package-utils-C00ijCm-.cjs.map} +1 -1
- package/package.json +11 -11
- package/dist/CalendarWidget-CkuTpX1q.mjs.map +0 -1
- package/dist/CalendarWidget-DEqx8mjm.cjs.map +0 -1
- package/dist/NestedWidget-Cgsv6RTh.mjs.map +0 -1
- package/dist/NestedWidget-DrRazqvX.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CalendarWidget-CkuTpX1q.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 Calendar,\n CalendarCheck,\n ChevronLeft,\n ChevronRight,\n ChevronsDown,\n ChevronsUp,\n Link2,\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 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-0.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\nconst safeTimeZone = (tz: string | null | undefined): string | undefined => {\n if (!tz) return undefined;\n try {\n new Intl.DateTimeFormat(undefined, { timeZone: tz });\n return tz;\n } catch {\n return undefined;\n }\n};\n\nconst formatLongDateTime = (iso: string, timeZone: string | null): string => {\n const d = new Date(iso);\n const tz = safeTimeZone(timeZone);\n const datePart = d.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: tz,\n });\n const timePart = d.toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n timeZoneName: \"short\",\n timeZone: tz,\n });\n return `${datePart} at ${timePart}`;\n};\n\nconst formatLongDate = (iso: string, timeZone: string | null): string => {\n return new Date(iso).toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: safeTimeZone(timeZone),\n });\n};\n\nconst isSafeHttpUrl = (url: string): boolean => {\n try {\n const parsed = new URL(url);\n return parsed.protocol === \"http:\" || parsed.protocol === \"https:\";\n } catch {\n return false;\n }\n};\n\nconst deriveEventStatus = (\n event: CalendarEvent,\n): { label: string; tone: \"upcoming\" | \"live\" | \"past\" } => {\n const rawStatus = event.status?.trim();\n const normalized = rawStatus?.toLowerCase();\n if (rawStatus && normalized !== \"active\" && normalized !== \"confirmed\") {\n const label =\n rawStatus.charAt(0).toUpperCase() + rawStatus.slice(1).toLowerCase();\n return { label, tone: \"past\" };\n }\n const startMs = new Date(event.start).getTime();\n const endMs = new Date(event.end).getTime();\n const now = Date.now();\n if (now < startMs) return { label: \"Upcoming\", tone: \"upcoming\" };\n if (now <= endMs) return { label: \"Live\", tone: \"live\" };\n return { label: \"Past\", tone: \"past\" };\n};\n\nfunction EventCard({ event, accentColor, textColor }: EventCardProps) {\n const accentVar = `var(--color-${accentColor})`;\n const barColor = event.color || accentVar;\n const startDate = new Date(event.start);\n const eventTz = safeTimeZone(event.timeZone);\n const weekday = startDate.toLocaleDateString(\"en-US\", {\n weekday: \"short\",\n timeZone: eventTz,\n });\n const monthDay = startDate.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n timeZone: eventTz,\n });\n const status = deriveEventStatus(event);\n const description = event.description?.body;\n\n const startDisplay = event.isAllDay\n ? formatLongDate(event.start, event.timeZone ?? null)\n : formatLongDateTime(event.start, event.timeZone ?? null);\n const endDisplay = event.isAllDay\n ? formatLongDate(event.end, event.timeZone ?? null)\n : formatLongDateTime(event.end, event.timeZone ?? null);\n\n const statusToneClasses =\n status.tone === \"live\"\n ? `bg-${accentColor}/15 text-${accentColor}`\n : status.tone === \"upcoming\"\n ? `bg-${accentColor}/10 text-${accentColor}`\n : `bg-${textColor}/10 text-${textColor}/60`;\n\n return (\n <article\n className={`relative overflow-hidden rounded-lg border border-${textColor}/10`}\n >\n <span\n aria-hidden=\"true\"\n className=\"absolute inset-y-0 left-0 w-[3px]\"\n style={{ backgroundColor: barColor }}\n />\n\n {event.imageUrl && (\n <img\n src={event.imageUrl}\n alt=\"\"\n className=\"aspect-[16/7] w-full object-cover\"\n />\n )}\n\n <div className=\"flex flex-col gap-4 p-4 pl-5\">\n <div className=\"flex items-start gap-4\">\n <div\n className={`shrink-0 text-${textColor} leading-tight tabular-nums`}\n >\n <div className={`text-xs font-semibold text-${textColor}/55`}>\n {weekday}\n </div>\n <div className=\"text-2xl font-bold tracking-[-0.015em]\">\n {monthDay}\n </div>\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <h4\n className={`text-base font-bold text-${textColor} leading-tight tracking-[-0.01em]`}\n >\n {event.title}\n </h4>\n {description && (\n <p\n className={`mt-1 text-sm leading-snug whitespace-pre-wrap text-${textColor}/65`}\n >\n {description}\n </p>\n )}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2.5\">\n <div className=\"flex items-start gap-2\">\n <Calendar\n className={`mt-0.5 size-4 shrink-0 text-${textColor}/55`}\n />\n <div\n className={`text-sm leading-snug text-${textColor}/80 tabular-nums`}\n >\n <div>\n <span className=\"font-semibold\">Start</span> {startDisplay}\n </div>\n <div>\n <span className=\"font-semibold\">End</span> {endDisplay}\n </div>\n </div>\n </div>\n\n <div>\n <span\n className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold ${statusToneClasses}`}\n >\n {status.label}\n </span>\n </div>\n\n {event.url && isSafeHttpUrl(event.url) && (\n <a\n href={event.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`flex items-center gap-2 text-sm text-${accentColor} break-all hover:underline`}\n >\n <Link2 className={`size-4 shrink-0 text-${textColor}/55`} />\n <span>{event.url}</span>\n </a>\n )}\n\n {event.venue && (\n <a\n href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(event.venue)}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`flex items-start gap-2 text-sm text-${accentColor} hover:underline`}\n >\n <MapPin\n className={`mt-0.5 size-4 shrink-0 text-${textColor}/55`}\n />\n <span>{event.venue}</span>\n </a>\n )}\n </div>\n </div>\n </article>\n );\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 min-w-0 border-${textColor}/10 @md:relative @md:mt-0 @md:flex-1 @md:border-l`}\n >\n <div className=\"@md:absolute @md:inset-0 @md:overflow-y-auto @md:pr-1 @md:pl-6\">\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 gap-3 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 </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":";;;;;;;;;;AAEA,MAAM,wBAAQ,IAAI,MAAM;AACxB,MAAM,YAAY,IAAI,KAAK,MAAM;AACjC,UAAU,QAAQ,UAAU,SAAS,GAAG,EAAE;AAE1C,SAAS,MAAM,MAAY,OAAe,UAAU,GAAW;CAC7D,MAAM,IAAI,IAAI,KAAK,KAAK;AACxB,GAAE,SAAS,OAAO,SAAS,GAAG,EAAE;AAChC,QAAO,EAAE,aAAa;;AAGxB,SAAS,aAAa,MAAoB;AACxC,QAAO,KAAK,aAAa,CAAC,MAAM,IAAI,CAAC;;AAGvC,MAAa,eAAgC;CAC3C;EACE,IAAI;EACJ,OAAO;EACP,OAAO,MAAM,OAAO,GAAG,EAAE;EACzB,KAAK,MAAM,OAAO,IAAI,EAAE;EACxB,QAAQ;EACR,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,OAAO,MAAM,OAAO,IAAI,EAAE;EAC1B,KAAK,MAAM,OAAO,IAAI,GAAG;EACzB,QAAQ;EACR,OAAO;EACP,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,OAAO,GAAG,aAAa,UAAU,CAAC;EAClC,KAAK,GAAG,aAAa,UAAU,CAAC;EAChC,QAAQ;EACR,OAAO;EACP,UAAU;EACV,OAAO;EACR;CACF;;;ACnCD,SAAgB,oBAA4D;CAC1E,MAAM,aAAa,eAAe;CAClC,MAAM,EAAE,cAAc,yBAAyB;CAC/C,MAAM,EAAE,YAAY,6BAA6B;AAEjD,QAAO,SAAS;EACd,UAAU;GACR;GACA;GACA,YAAY,YAAY;GACzB;EACD,UAAU,EAAE,aAAa,WAAW,oBAAoB,OAAO;EAC/D,SAAS,CAAC;EACV,GAAI,aAAa,EAAE,iBAAiB,cAAc;EACnD,CAAC;;;;;;;;ACiBJ,MAAM,YAAY;CAAC;CAAO;CAAO;CAAO;CAAO;CAAO;CAAO;CAAM;AAEnE,MAAM,kBAAkB,MAAc,UACpC,IAAI,KAAK,MAAM,QAAQ,GAAG,EAAE,CAAC,SAAS;AAExC,MAAM,sBAAsB,MAAc,UACxC,IAAI,KAAK,MAAM,OAAO,EAAE,CAAC,QAAQ;AAEnC,MAAM,aAAa,GAAS,MAC1B,EAAE,aAAa,KAAK,EAAE,aAAa,IACnC,EAAE,UAAU,KAAK,EAAE,UAAU,IAC7B,EAAE,SAAS,KAAK,EAAE,SAAS;AAE7B,MAAM,cAAc,MAAkB;CACpC,MAAM,IAAI,IAAI,KAAK,EAAE;AACrB,GAAE,SAAS,GAAG,GAAG,GAAG,EAAE;AACtB,QAAO;;AAGT,MAAM,WAAW,GAAS,MAAoB;CAC5C,MAAM,IAAI,IAAI,KAAK,EAAE;AACrB,GAAE,QAAQ,EAAE,SAAS,GAAG,EAAE;AAC1B,QAAO;;AAGT,MAAM,YAAY,GAAS,MAAoB;CAC7C,MAAM,KAAK,WAAW,EAAE,CAAC,SAAS,GAAG,WAAW,EAAE,CAAC,SAAS;AAC5D,QAAO,KAAK,MAAM,KAAK,MAAS;;AASlC,MAAM,qBAAqB,MAAc,UAA6B;CACpE,MAAM,cAAc,eAAe,MAAM,MAAM;CAC/C,MAAM,WAAW,mBAAmB,MAAM,MAAM;CAChD,MAAM,wBAAQ,IAAI,MAAM;CACxB,MAAM,QAAmB,EAAE;AAE3B,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,IAC5B,OAAM,KAAK;EAAE,MAAM;EAAM,SAAS;EAAO,gBAAgB;EAAO,CAAC;AAGnE,MAAK,IAAI,MAAM,GAAG,OAAO,aAAa,OAAO;EAC3C,MAAM,OAAO,IAAI,KAAK,MAAM,OAAO,IAAI;AACvC,QAAM,KAAK;GACT;GACA,SAAS,UAAU,MAAM,MAAM;GAC/B,gBAAgB;GACjB,CAAC;;AAGJ,QAAO;;AAGT,MAAM,yBAAkE;CACtE,MAAM,wBAAQ,IAAI,MAAM;CACxB,MAAM,UAAU,MAAM,QAAQ;AAC9B,QAAO,MAAM,KAAK,EAAE,QAAQ,GAAG,GAAG,GAAG,MAAM;EACzC,MAAM,OAAO,QAAQ,OAAO,CAAC,UAAU,EAAE;AACzC,SAAO;GAAE;GAAM,SAAS,UAAU,MAAM,MAAM;GAAE;GAChD;;AAGJ,MAAM,wBACJ,SAC4C;CAE5C,MAAM,IAAI,SAAS,sBADL,IAAI,MAAM,CACO;CAC/B,MAAM,UAAU,KAAK,mBAAmB,SAAS,EAAE,SAAS,SAAS,CAAC;CACtE,MAAM,WAAW,KAAK,mBAAmB,SAAS;EAChD,OAAO;EACP,KAAK;EACN,CAAC;AACF,KAAI,MAAM,EAAG,QAAO;EAAE,MAAM;EAAS,QAAQ,GAAG,QAAQ,IAAI;EAAY;AACxE,KAAI,MAAM,EAAG,QAAO;EAAE,MAAM;EAAY,QAAQ,GAAG,QAAQ,IAAI;EAAY;AAC3E,KAAI,MAAM,GAAI,QAAO;EAAE,MAAM;EAAa,QAAQ,GAAG,QAAQ,IAAI;EAAY;AAC7E,QAAO;EAAE,MAAM;EAAM,QAAQ,GAAG,QAAQ,IAAI;EAAY;;AAc1D,SAAS,cAAc,EACrB,MACA,SACA,YACA,YACA,aACA,WACA,kBACA,WACqB;CACrB,MAAM,WAAW,mBACb,KAAK,IAAI,YAAY,EAAE,GACvB,aAAa,IACX,IACA;CAEN,MAAM,cACJ;CAEF,MAAM,eAAe,aACjB,MAAM,YAAY,QAAQ,YAAY,iCAAiC,YAAY,OACnF,UACE,MAAM,YAAY,WAAW,YAAY,0BAA0B,YAAY,yBAAyB,YAAY,OACpH,QAAQ,UAAU,YAAY,YAAY,yBAAyB,YAAY;AAErF,QACE,qBAAC,UAAD;EACE,MAAK;EACI;EACT,cAAY,KAAK,mBAAmB,SAAS;GAC3C,SAAS;GACT,OAAO;GACP,KAAK;GACN,CAAC;EACF,gBAAc,UAAU,SAAS,KAAA;EACjC,gBAAc;EACd,WAAW,GAAG,YAAY,GAAG;YAV/B,CAYE,oBAAC,QAAD;GAAM,WAAU;aAAgB,KAAK,SAAS;GAAQ,CAAA,EACrD,WAAW,KACV,oBAAC,QAAD;GACE,eAAY;GACZ,WAAU;aAET,MAAM,KAAK,EAAE,QAAQ,UAAU,CAAC,CAAC,KAAK,GAAG,MACxC,oBAAC,QAAD,EAEE,WAAW,uBACT,aACI,MAAM,YAAY,kBAClB,MAAM,iBAEZ,EANK,EAML,CACF;GACG,CAAA,CAEF;;;AAUb,MAAM,gBAAgB,OAAsD;AAC1E,KAAI,CAAC,GAAI,QAAO,KAAA;AAChB,KAAI;AACF,MAAI,KAAK,eAAe,KAAA,GAAW,EAAE,UAAU,IAAI,CAAC;AACpD,SAAO;SACD;AACN;;;AAIJ,MAAM,sBAAsB,KAAa,aAAoC;CAC3E,MAAM,IAAI,IAAI,KAAK,IAAI;CACvB,MAAM,KAAK,aAAa,SAAS;AAajC,QAAO,GAZU,EAAE,mBAAmB,SAAS;EAC7C,OAAO;EACP,KAAK;EACL,MAAM;EACN,UAAU;EACX,CAAC,CAOiB,MANF,EAAE,mBAAmB,SAAS;EAC7C,MAAM;EACN,QAAQ;EACR,cAAc;EACd,UAAU;EACX,CAAC;;AAIJ,MAAM,kBAAkB,KAAa,aAAoC;AACvE,QAAO,IAAI,KAAK,IAAI,CAAC,mBAAmB,SAAS;EAC/C,OAAO;EACP,KAAK;EACL,MAAM;EACN,UAAU,aAAa,SAAS;EACjC,CAAC;;AAGJ,MAAM,iBAAiB,QAAyB;AAC9C,KAAI;EACF,MAAM,SAAS,IAAI,IAAI,IAAI;AAC3B,SAAO,OAAO,aAAa,WAAW,OAAO,aAAa;SACpD;AACN,SAAO;;;AAIX,MAAM,qBACJ,UAC0D;CAC1D,MAAM,YAAY,MAAM,QAAQ,MAAM;CACtC,MAAM,aAAa,WAAW,aAAa;AAC3C,KAAI,aAAa,eAAe,YAAY,eAAe,YAGzD,QAAO;EAAE,OADP,UAAU,OAAO,EAAE,CAAC,aAAa,GAAG,UAAU,MAAM,EAAE,CAAC,aAAa;EACtD,MAAM;EAAQ;CAEhC,MAAM,UAAU,IAAI,KAAK,MAAM,MAAM,CAAC,SAAS;CAC/C,MAAM,QAAQ,IAAI,KAAK,MAAM,IAAI,CAAC,SAAS;CAC3C,MAAM,MAAM,KAAK,KAAK;AACtB,KAAI,MAAM,QAAS,QAAO;EAAE,OAAO;EAAY,MAAM;EAAY;AACjE,KAAI,OAAO,MAAO,QAAO;EAAE,OAAO;EAAQ,MAAM;EAAQ;AACxD,QAAO;EAAE,OAAO;EAAQ,MAAM;EAAQ;;AAGxC,SAAS,UAAU,EAAE,OAAO,aAAa,aAA6B;CACpE,MAAM,YAAY,eAAe,YAAY;CAC7C,MAAM,WAAW,MAAM,SAAS;CAChC,MAAM,YAAY,IAAI,KAAK,MAAM,MAAM;CACvC,MAAM,UAAU,aAAa,MAAM,SAAS;CAC5C,MAAM,UAAU,UAAU,mBAAmB,SAAS;EACpD,SAAS;EACT,UAAU;EACX,CAAC;CACF,MAAM,WAAW,UAAU,mBAAmB,SAAS;EACrD,OAAO;EACP,KAAK;EACL,UAAU;EACX,CAAC;CACF,MAAM,SAAS,kBAAkB,MAAM;CACvC,MAAM,cAAc,MAAM,aAAa;CAEvC,MAAM,eAAe,MAAM,WACvB,eAAe,MAAM,OAAO,MAAM,YAAY,KAAK,GACnD,mBAAmB,MAAM,OAAO,MAAM,YAAY,KAAK;CAC3D,MAAM,aAAa,MAAM,WACrB,eAAe,MAAM,KAAK,MAAM,YAAY,KAAK,GACjD,mBAAmB,MAAM,KAAK,MAAM,YAAY,KAAK;CAEzD,MAAM,oBACJ,OAAO,SAAS,SACZ,MAAM,YAAY,WAAW,gBAC7B,OAAO,SAAS,aACd,MAAM,YAAY,WAAW,gBAC7B,MAAM,UAAU,WAAW,UAAU;AAE7C,QACE,qBAAC,WAAD;EACE,WAAW,qDAAqD,UAAU;YAD5E;GAGE,oBAAC,QAAD;IACE,eAAY;IACZ,WAAU;IACV,OAAO,EAAE,iBAAiB,UAAU;IACpC,CAAA;GAED,MAAM,YACL,oBAAC,OAAD;IACE,KAAK,MAAM;IACX,KAAI;IACJ,WAAU;IACV,CAAA;GAGJ,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,qBAAC,OAAD;MACE,WAAW,iBAAiB,UAAU;gBADxC,CAGE,oBAAC,OAAD;OAAK,WAAW,8BAA8B,UAAU;iBACrD;OACG,CAAA,EACN,oBAAC,OAAD;OAAK,WAAU;iBACZ;OACG,CAAA,CACF;SAEN,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,oBAAC,MAAD;OACE,WAAW,4BAA4B,UAAU;iBAEhD,MAAM;OACJ,CAAA,EACJ,eACC,oBAAC,KAAD;OACE,WAAW,sDAAsD,UAAU;iBAE1E;OACC,CAAA,CAEF;QACF;QAEN,qBAAC,OAAD;KAAK,WAAU;eAAf;MACE,qBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,oBAAC,UAAD,EACE,WAAW,+BAA+B,UAAU,MACpD,CAAA,EACF,qBAAC,OAAD;QACE,WAAW,6BAA6B,UAAU;kBADpD,CAGE,qBAAC,OAAD,EAAA,UAAA;SACE,oBAAC,QAAD;UAAM,WAAU;oBAAgB;UAAY,CAAA;;SAAE;SAC1C,EAAA,CAAA,EACN,qBAAC,OAAD,EAAA,UAAA;SACE,oBAAC,QAAD;UAAM,WAAU;oBAAgB;UAAU,CAAA;;SAAE;SACxC,EAAA,CAAA,CACF;UACF;;MAEN,oBAAC,OAAD,EAAA,UACE,oBAAC,QAAD;OACE,WAAW,6EAA6E;iBAEvF,OAAO;OACH,CAAA,EACH,CAAA;MAEL,MAAM,OAAO,cAAc,MAAM,IAAI,IACpC,qBAAC,KAAD;OACE,MAAM,MAAM;OACZ,QAAO;OACP,KAAI;OACJ,WAAW,wCAAwC,YAAY;iBAJjE,CAME,oBAAC,OAAD,EAAO,WAAW,wBAAwB,UAAU,MAAQ,CAAA,EAC5D,oBAAC,QAAD,EAAA,UAAO,MAAM,KAAW,CAAA,CACtB;;MAGL,MAAM,SACL,qBAAC,KAAD;OACE,MAAM,mDAAmD,mBAAmB,MAAM,MAAM;OACxF,QAAO;OACP,KAAI;OACJ,WAAW,uCAAuC,YAAY;iBAJhE,CAME,oBAAC,QAAD,EACE,WAAW,+BAA+B,UAAU,MACpD,CAAA,EACF,oBAAC,QAAD,EAAA,UAAO,MAAM,OAAa,CAAA,CACxB;;MAEF;OACF;;GACE;;;AAad,SAAS,UAAU,EACjB,MAAM,MACN,OACA,SACA,aACA,WACA,WACiB;CACjB,MAAM,UACJ,YAAY,WACR,MAAM,YAAY,QAAQ,YAAY,uBAAuB,YAAY,yBAAyB,YAAY,OAC9G,MAAM,UAAU,UAAU,UAAU,YAAY,UAAU,yBAAyB,UAAU;AAEnG,QACE,oBAAC,UAAD;EACE,MAAK;EACI;EACT,cAAY;EACZ,WAAW,8HAA8H;YAEzI,oBAAC,MAAD,EAAM,WAAU,UAAW,CAAA;EACpB,CAAA;;AASb,MAAM,+BAA6C;CACjD,MAAM,sBAAM,IAAI,MAAM;AACtB,QAAO;EAAE,OAAO,IAAI,UAAU;EAAE,MAAM,IAAI,aAAa;EAAE;;AAG3D,SAAS,sBACP,iBACA;CACA,MAAM,CAAC,MAAM,WAAW,SAAS,uBAAuB;CACxD,MAAM,CAAC,mBAAmB,wBAAwB,SAAS,MAAM;CACjE,MAAM,uBAAuB,OAAsB,KAAK;AAExD,uBACc;AACV,MAAI,qBAAqB,YAAY,KACnC,QAAO,aAAa,qBAAqB,QAAQ;IAGrD,EAAE,CACH;CAED,MAAM,yBAAyB,kBAAkB;AAC/C,MAAI,qBAAqB,YAAY,MAAM;AACzC,UAAO,aAAa,qBAAqB,QAAQ;AACjD,wBAAqB,UAAU;;IAEhC,EAAE,CAAC;AAgCN,QAAO;EAAE;EAAM;EAAmB,UA9BjB,aACd,cAAsB;AACrB,2BAAwB;AACxB,wBAAqB,KAAK;AAC1B,wBAAqB,UAAU,OAAO,iBAAiB;AACrD,aAAS,SAAS;KAChB,MAAM,OAAO,KAAK,QAAQ;AAC1B,SAAI,OAAO,EAAG,QAAO;MAAE,OAAO;MAAI,MAAM,KAAK,OAAO;MAAG;AACvD,SAAI,OAAO,GAAI,QAAO;MAAE,OAAO;MAAG,MAAM,KAAK,OAAO;MAAG;AACvD,YAAO;MAAE,OAAO;MAAM,MAAM,KAAK;MAAM;MACvC;AACF,yBAAqB,MAAM;AAC3B,yBAAqB,UAAU;MAC9B,IAAI;KAET,CAAC,uBAAuB,CACzB;EAc2C,WAZ1B,kBAAkB;AAClC,2BAAwB;GACxB,MAAM,sBAAM,IAAI,MAAM;AACtB,wBAAqB,KAAK;AAC1B,wBAAqB,UAAU,OAAO,iBAAiB;AACrD,YAAQ;KAAE,OAAO,IAAI,UAAU;KAAE,MAAM,IAAI,aAAa;KAAE,CAAC;AAC3D,oBAAgB,IAAI;AACpB,yBAAqB,MAAM;AAC3B,yBAAqB,UAAU;MAC9B,GAAG;KACL,CAAC,wBAAwB,gBAAgB,CAAC;EAEU;;AAGzD,SAAS,sBACP,QACA,cACA;CACA,MAAM,eAAe,cAAc;EACjC,MAAM,sBAAM,IAAI,KAA8B;AAC9C,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,QAAQ,WAAW,IAAI,KAAK,MAAM,MAAM,CAAC;GAC/C,MAAM,MAAM,WAAW,IAAI,KAAK,MAAM,IAAI,CAAC;AAC3C,QAAK,IAAI,MAAM,OAAO,OAAO,KAAK,MAAM,QAAQ,KAAK,EAAE,EAAE;IACvD,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,IAAI,SAAS;IACnE,MAAM,OAAO,IAAI,IAAI,IAAI;AACzB,QAAI,KACF,MAAK,KAAK,MAAM;QAEhB,KAAI,IAAI,KAAK,CAAC,MAAM,CAAC;;;AAI3B,SAAO;IACN,CAAC,OAAO,CAAC;CAEZ,MAAM,sBAAsB,aACzB,SAAgC;EAC/B,MAAM,MAAM,GAAG,KAAK,aAAa,CAAC,GAAG,KAAK,UAAU,CAAC,GAAG,KAAK,SAAS;AACtE,SAAO,aAAa,IAAI,IAAI,IAAI,EAAE;IAEpC,CAAC,aAAa,CACf;AAOD,QAAO;EAAE;EAAqB,oBALH,cAAc;AACvC,OAAI,CAAC,aAAc,QAAO,EAAE;AAC5B,UAAO,oBAAoB,aAAa;KACvC,CAAC,cAAc,oBAAoB,CAAC;EAEW;;AAwBpD,SAAgB,eAAe,EAC7B,eAAe,MACf,YAAY,YACZ,gBAAgB,MAChB,aAAa,cAEb,aAAa;CAAE,MAAM;CAAS,OAAO;CAAc,EACnD,YAAY,cACZ,cAAc,WACd,UAAU,GACV,eAAe,MAEf,mBAAmB,MACnB,kBAAkB,MAClB,aAAa,MACb,kBAAkB,MAElB,WACA,GAAG,SACsC;CACzC,MAAM,kBAAkB,WAAW,SAAS;CAC5C,MAAM,mBACH,WAAW,UAAU,aAAa,WAAW,UAAU,aACxD,WAAW,SAAS,UAChB,OAAO,WAAW,SAAS,aAAa,WAAW,SAAS,SAAS,KACrE;CAEN,MAAM,CAAC,aAAa,kBAAkB,SAAS,MAAM;CACrD,MAAM,CAAC,cAAc,mBAAmB,+BAChC,IAAI,MAAM,CACjB;CACD,MAAM,EAAE,MAAM,mBAAmB,UAAU,cACzC,sBAAsB,gBAAgB;CACxC,MAAM,eAAe,KAAK;CAC1B,MAAM,cAAc,KAAK;CAEzB,MAAM,EAAE,MAAM,SAAS,EAAE,EAAE,WAAW,YAAY,mBAAmB;CAErE,MAAM,YAAY,cACV,kBAAkB,aAAa,aAAa,EAClD,CAAC,aAAa,aAAa,CAC5B;CACD,MAAM,WAAW,kBAAkB;CACnC,MAAM,EAAE,qBAAqB,uBAAuB,sBAClD,QACA,aACD;CAED,MAAM,sBAAM,IAAI,MAAM;CACtB,MAAM,sBACJ,iBAAiB,IAAI,UAAU,IAAI,gBAAgB,IAAI,aAAa;CAEtE,MAAM,aAAa,IAAI,KAAK,aAAa,aAAa,CAAC,eACrD,SACA,EAAE,OAAO,QAAQ,CAClB;CACD,MAAM,YAAY,OAAO,YAAY;CAErC,MAAM,iBAAiB,eACnB,qBAAqB,aAAa,GAClC;AAEJ,QACE,qBAAC,OAAD;EACE,WAAW,sCAAsC,aAAa,MAAM,gBAAgB,QAAQ,UAAU,GAAG,aAAa;EACtH,OAAO,EAAE,iBAAiB;EAC1B,GAAI;YAHN,CAKG,gBAAgB,aACf,oBAAC,OAAD;GAAK,WAAW,KAAK,QAAQ;aAC3B,oBAAC,MAAD;IACE,WAAW,QAAQ,cAAc,QAAQ,WAAW;cAEnD;IACE,CAAA;GACD,CAAA,EAGP,YACC,oBAAC,OAAD;GACE,WAAW,oDAAoD;aAE/D,oBAAC,OAAD;IAAK,WAAW,QAAQ;cACtB,oBAAC,OAAD,EAAK,WAAU,iFAAkF,CAAA;IAC7F,CAAA;GACF,CAAA,GACJ,UACF,oBAAC,YAAD,EAAc,CAAA,GAEd,oBAAC,OAAD;GAAK,WAAW,KAAK;aACnB,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,qBAAC,OAAD;KAAK,WAAU;eAAf;MAEE,qBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,qBAAC,OAAD;QAAK,WAAU;kBAAf,CACG,mBACC,oBAAC,QAAD;SACE,WAAW,0DAA0D,UAAU;mBAE9E;SACI,CAAA,EAET,oBAAC,QAAD;SACE,WAAW,4DAA4D;mBAEtE;SACI,CAAA,CACH;WAEN,qBAAC,OAAD;QAAK,WAAU;kBAAf;SACG,mBAAmB,CAAC,uBACnB,qBAAC,UAAD;UACE,MAAK;UACL,SAAS;UACT,WAAW,2CAA2C,YAAY,iDAAiD,YAAY,8BAA8B,YAAY,iEAAiE,YAAY;oBAHxP,CAKE,oBAAC,eAAD,EAAe,WAAU,UAAW,CAAA,EAAA,QAE7B;;SAEX,oBAAC,WAAD;UACE,MAAM;UACN,OAAM;UACN,SAAQ;UACK;UACF;UACX,eAAe,SAAS,GAAG;UAC3B,CAAA;SACF,oBAAC,WAAD;UACE,MAAM;UACN,OAAM;UACN,SAAQ;UACK;UACF;UACX,eAAe,SAAS,EAAE;UAC1B,CAAA;SACE;UACF;;MAGN,oBAAC,OAAD;OAAK,WAAU;iBACZ,UAAU,KAAK,KAAK,QAAQ;AAG3B,eACE,oBAAC,OAAD;SAEE,WAAW,8DAA8D,UAAU,GAJxE,eADG,QAAQ,KAAK,QAAQ,KAK4D,OAAO;mBAErG;SACG,EAJC,IAID;SAER;OACE,CAAA;MAGN,qBAAC,OAAD;OACE,WAAU;OACV,OAAO,EAAE,SAAS,oBAAoB,KAAM,GAAG;iBAFjD,CAKG,eACC,oBAAC,OAAD;QAAK,WAAU;kBACZ,SAAS,KAAK,EAAE,MAAM,cACrB,oBAAC,eAAD;SAEQ;SACG;SACT,YACE,CAAC,CAAC,gBAAgB,UAAU,cAAc,KAAK;SAEjD,YAAY,oBAAoB,KAAK,CAAC;SACzB;SACF;SACO;SAClB,eAAe,gBAAgB,KAAK;SACpC,EAXK,KAAK,aAAa,CAWvB,CACF;QACE,CAAA,EAIR,oBAAC,OAAD;QACE,WAAW,0BAA0B,cAAc,oBAAoB;kBAEtE,UAAU,KAAK,MAAM,QAAQ;AAC5B,aAAI,CAAC,KAAK,KACR,QACE,oBAAC,OAAD,EAA0B,WAAU,iBAAkB,EAA5C,SAAS,MAAmC;SAG1D,MAAM,aAAa,oBAAoB,KAAK,KAAK,CAAC;AAClD,gBACE,oBAAC,eAAD;UAEE,MAAM,KAAK;UACX,SAAS,KAAK;UACd,YACE,CAAC,CAAC,gBAAgB,UAAU,cAAc,KAAK,KAAK;UAE1C;UACC;UACF;UACO;UAClB,eAAe,gBAAgB,KAAK,KAAK;UACzC,EAXK,KAAK,KAAK,aAAa,CAW5B;UAEJ;QACE,CAAA,CACF;;MAGN,qBAAC,UAAD;OACE,MAAK;OACL,eAAe,eAAe,CAAC,YAAY;OAC3C,WAAW,4EAA4E,UAAU,mCAAmC,UAAU;OAC9I,cACE,cAAc,oBAAoB;iBALtC;QAQE,oBAAC,OAAD,EAAK,WAAW,iBAAiB,UAAU,MAAQ,CAAA;QAClD,cACC,oBAAC,cAAD,EAAc,WAAU,UAAW,CAAA,GAEnC,oBAAC,YAAD,EAAY,WAAU,UAAW,CAAA;QAEnC,oBAAC,OAAD,EAAK,WAAW,iBAAiB,UAAU,MAAQ,CAAA;QAC5C;;MACL;QAGN,oBAAC,OAAD;KACE,WAAW,uBAAuB,UAAU;eAE5C,qBAAC,OAAD;MAAK,WAAU;gBAAf,CAEG,kBACC,qBAAC,OAAD;OAAK,WAAU;iBAAf,CACG,eAAe,QACd,oBAAC,OAAD;QACE,WAAW,0DAA0D;kBAEpE,eAAe;QACZ,CAAA,EAER,oBAAC,OAAD;QACE,WAAW,8BAA8B,UAAU;kBAElD,eAAe;QACZ,CAAA,CACF;UAIR,oBAAC,OAAD;OAEE,WAAU;iBAET,mBAAmB,SAAS,IAC3B,mBAAmB,KAAK,OAAO,QAC7B,oBAAC,WAAD;QAES;QACM;QACF;QACX,EAJK,GAAG,MAAM,GAAG,GAAG,MAIpB,CACF,GAEF,qBAAC,OAAD;QACE,WAAW,0EAA0E,UAAU;kBADjG,CAGE,qBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,oBAAC,eAAD,EACE,WAAW,eAAe,UAAU,MACpC,CAAA,EACF,oBAAC,QAAD;UACE,WAAW,kCAAkC,UAAU;oBACxD;UAEM,CAAA,CACH;YACN,oBAAC,QAAD;SAAM,WAAW,oBAAoB,UAAU;mBAAM;SAE9C,CAAA,CACH;;OAEJ,EA/BC,cAAc,aAAa,IAAI,OA+BhC,CACF;;KACF,CAAA,CACF;;GACF,CAAA,CAEJ;;;AAIV,MAAa,+BAAqD;CAChE,YAAY;CACZ,aAAa;CACb,YAAY,CAAC;EAAE,IAAI;EAAW,OAAO;EAAW,CAAC;CACjD,QAAQ;EAEN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD,iBAAiB;GACf,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACF,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,MAAM;GACN,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACF;CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CalendarWidget-DEqx8mjm.cjs","names":["useWidgetsApi","useWidgetPreviewContext","useDataSourceRegistryConfig","Calendar","Link2","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 Calendar,\n CalendarCheck,\n ChevronLeft,\n ChevronRight,\n ChevronsDown,\n ChevronsUp,\n Link2,\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 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-0.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\nconst safeTimeZone = (tz: string | null | undefined): string | undefined => {\n if (!tz) return undefined;\n try {\n new Intl.DateTimeFormat(undefined, { timeZone: tz });\n return tz;\n } catch {\n return undefined;\n }\n};\n\nconst formatLongDateTime = (iso: string, timeZone: string | null): string => {\n const d = new Date(iso);\n const tz = safeTimeZone(timeZone);\n const datePart = d.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: tz,\n });\n const timePart = d.toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n timeZoneName: \"short\",\n timeZone: tz,\n });\n return `${datePart} at ${timePart}`;\n};\n\nconst formatLongDate = (iso: string, timeZone: string | null): string => {\n return new Date(iso).toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n timeZone: safeTimeZone(timeZone),\n });\n};\n\nconst isSafeHttpUrl = (url: string): boolean => {\n try {\n const parsed = new URL(url);\n return parsed.protocol === \"http:\" || parsed.protocol === \"https:\";\n } catch {\n return false;\n }\n};\n\nconst deriveEventStatus = (\n event: CalendarEvent,\n): { label: string; tone: \"upcoming\" | \"live\" | \"past\" } => {\n const rawStatus = event.status?.trim();\n const normalized = rawStatus?.toLowerCase();\n if (rawStatus && normalized !== \"active\" && normalized !== \"confirmed\") {\n const label =\n rawStatus.charAt(0).toUpperCase() + rawStatus.slice(1).toLowerCase();\n return { label, tone: \"past\" };\n }\n const startMs = new Date(event.start).getTime();\n const endMs = new Date(event.end).getTime();\n const now = Date.now();\n if (now < startMs) return { label: \"Upcoming\", tone: \"upcoming\" };\n if (now <= endMs) return { label: \"Live\", tone: \"live\" };\n return { label: \"Past\", tone: \"past\" };\n};\n\nfunction EventCard({ event, accentColor, textColor }: EventCardProps) {\n const accentVar = `var(--color-${accentColor})`;\n const barColor = event.color || accentVar;\n const startDate = new Date(event.start);\n const eventTz = safeTimeZone(event.timeZone);\n const weekday = startDate.toLocaleDateString(\"en-US\", {\n weekday: \"short\",\n timeZone: eventTz,\n });\n const monthDay = startDate.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n timeZone: eventTz,\n });\n const status = deriveEventStatus(event);\n const description = event.description?.body;\n\n const startDisplay = event.isAllDay\n ? formatLongDate(event.start, event.timeZone ?? null)\n : formatLongDateTime(event.start, event.timeZone ?? null);\n const endDisplay = event.isAllDay\n ? formatLongDate(event.end, event.timeZone ?? null)\n : formatLongDateTime(event.end, event.timeZone ?? null);\n\n const statusToneClasses =\n status.tone === \"live\"\n ? `bg-${accentColor}/15 text-${accentColor}`\n : status.tone === \"upcoming\"\n ? `bg-${accentColor}/10 text-${accentColor}`\n : `bg-${textColor}/10 text-${textColor}/60`;\n\n return (\n <article\n className={`relative overflow-hidden rounded-lg border border-${textColor}/10`}\n >\n <span\n aria-hidden=\"true\"\n className=\"absolute inset-y-0 left-0 w-[3px]\"\n style={{ backgroundColor: barColor }}\n />\n\n {event.imageUrl && (\n <img\n src={event.imageUrl}\n alt=\"\"\n className=\"aspect-[16/7] w-full object-cover\"\n />\n )}\n\n <div className=\"flex flex-col gap-4 p-4 pl-5\">\n <div className=\"flex items-start gap-4\">\n <div\n className={`shrink-0 text-${textColor} leading-tight tabular-nums`}\n >\n <div className={`text-xs font-semibold text-${textColor}/55`}>\n {weekday}\n </div>\n <div className=\"text-2xl font-bold tracking-[-0.015em]\">\n {monthDay}\n </div>\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <h4\n className={`text-base font-bold text-${textColor} leading-tight tracking-[-0.01em]`}\n >\n {event.title}\n </h4>\n {description && (\n <p\n className={`mt-1 text-sm leading-snug whitespace-pre-wrap text-${textColor}/65`}\n >\n {description}\n </p>\n )}\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2.5\">\n <div className=\"flex items-start gap-2\">\n <Calendar\n className={`mt-0.5 size-4 shrink-0 text-${textColor}/55`}\n />\n <div\n className={`text-sm leading-snug text-${textColor}/80 tabular-nums`}\n >\n <div>\n <span className=\"font-semibold\">Start</span> {startDisplay}\n </div>\n <div>\n <span className=\"font-semibold\">End</span> {endDisplay}\n </div>\n </div>\n </div>\n\n <div>\n <span\n className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold ${statusToneClasses}`}\n >\n {status.label}\n </span>\n </div>\n\n {event.url && isSafeHttpUrl(event.url) && (\n <a\n href={event.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`flex items-center gap-2 text-sm text-${accentColor} break-all hover:underline`}\n >\n <Link2 className={`size-4 shrink-0 text-${textColor}/55`} />\n <span>{event.url}</span>\n </a>\n )}\n\n {event.venue && (\n <a\n href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(event.venue)}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={`flex items-start gap-2 text-sm text-${accentColor} hover:underline`}\n >\n <MapPin\n className={`mt-0.5 size-4 shrink-0 text-${textColor}/55`}\n />\n <span>{event.venue}</span>\n </a>\n )}\n </div>\n </div>\n </article>\n );\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 min-w-0 border-${textColor}/10 @md:relative @md:mt-0 @md:flex-1 @md:border-l`}\n >\n <div className=\"@md:absolute @md:inset-0 @md:overflow-y-auto @md:pr-1 @md:pl-6\">\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 gap-3 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 </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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MAAM;GACN,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACDA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACDC,mBAAAA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACF;CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NestedWidget-Cgsv6RTh.mjs","names":[],"sources":["../../widgets/src/ui/scroll-arrows.tsx","../../widgets/src/widgets/NestedWidget.tsx"],"sourcesContent":["import type React from \"react\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\n\ntype ScrollArrowsProps = {\n onPrevious: () => void;\n onNext: () => void;\n};\n\nexport function ScrollArrows({\n onPrevious,\n onNext,\n}: ScrollArrowsProps): React.JSX.Element {\n return (\n <>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex size-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onPrevious}\n aria-label=\"Previous slide\"\n >\n <ChevronLeft className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex size-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onNext}\n aria-label=\"Next slide\"\n >\n <ChevronRight className=\"size-4\" />\n </button>\n </>\n );\n}\n","import { useRef, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n AlignOptions,\n GapOptions,\n BackgroundValue,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n} from \"../core/fields\";\nimport { ScrollArrows } from \"../ui/scroll-arrows\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\nconst DEFAULT_SHAREABLES: ShareableItem[] = [];\n\ntype NestedWidgetProps = ComponentProps<\"div\"> & {\n // Content\n resource?: ShareableItem;\n titleEnabled?: boolean;\n titleText?: string;\n shareables?: ShareableItem[];\n\n // Layout\n gap?: GapOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n primaryMediaHeight?: string;\n\n // Title styling\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n titleAlignment?: AlignOptions;\n\n // Nested media styling\n nestedTextColor?: ColorOptions;\n background?: BackgroundValue;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n};\n\nexport function NestedWidget({\n resource,\n titleEnabled = true,\n titleText = \"Featured Collection\",\n shareables = DEFAULT_SHAREABLES,\n gap = \"md\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n primaryMediaHeight = \"400px\",\n titleFontSize = \"xl\",\n titleColor = \"background\",\n titleAlignment = { horizontal: \"left\", vertical: \"bottom\" },\n nestedTextColor = \"foreground\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 50,\n className,\n ...props\n}: NestedWidgetProps): React.JSX.Element {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const scrollByAmount = (direction: \"prev\" | \"next\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const computedGap = parseFloat(getComputedStyle(container).gap) || 0;\n const firstItem = container.firstElementChild as HTMLElement | null;\n const itemWidth = firstItem?.offsetWidth ?? 0;\n const scrollAmount = itemWidth + computedGap;\n\n container.scrollTo({\n left:\n container.scrollLeft +\n (direction === \"next\" ? scrollAmount : -scrollAmount),\n behavior: \"smooth\",\n });\n };\n\n // Cap border radius for the primary media container: \"full\" creates a circle that clips\n // the absolutely-positioned title overlay to the narrow bottom of the circle.\n const primaryMediaRadius = borderRadius === \"full\" ? \"2xl\" : borderRadius;\n\n const { onItemClick } = useWidgetInteraction();\n\n const hasNestedMedia = shareables.length > 0;\n\n const titleAlignmentClasses = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n };\n\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n return (\n <div\n className={`@container flex w-full overflow-hidden p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} ${className}`}\n {...props}\n style={{\n height: primaryMediaHeight,\n backgroundImage: backgroundImage,\n }}\n >\n {/* Primary Media Container - Full width on mobile, fixed on desktop */}\n <div\n className={`relative @md:flex-none`}\n style={{\n width: primaryMediaHeight,\n }}\n >\n {/* Media + overlay clipped to rounded shape — title is a sibling so it isn't clipped */}\n <div\n className={`overflow-hidden rounded-${primaryMediaRadius} absolute inset-0`}\n >\n <MediaRenderer\n {...(resource ? getMediaPropsFromShareable(resource) : {})}\n autoplay\n loop\n muted\n />\n\n {/* Overlay */}\n {overlayEnabled && (\n <div\n className={`pointer-events-none absolute inset-0 z-10 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n\n {/* Title and Mobile Nested Media — outside the overflow-hidden clip */}\n {((titleEnabled && titleText) || hasNestedMedia) && (\n <div\n className={`absolute z-20 w-full ${titleAlignmentClasses[titleAlignment?.horizontal ?? \"left\"]} p-${padding} ${\n titleAlignment.vertical === \"top\"\n ? `top-0 pt-${padding}`\n : titleAlignment.vertical === \"center\"\n ? \"top-1/2 -translate-y-1/2\"\n : `bottom-0 pb-${padding}`\n }`}\n >\n {titleEnabled && titleText && (\n <h2\n className={`font-header leading-tight font-bold text-${titleColor} text-${titleFontSize === \"md\" ? \"base\" : titleFontSize}`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Mobile: Products overlay inside primary media */}\n {hasNestedMedia && (\n <div className={`pt-${padding} @md:hidden`}>\n <div\n className={`flex overflow-x-auto gap-${gapValues[gap]} bg-transparent`}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col items-center ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-40 overflow-hidden rounded-${borderRadius}`}\n >\n <MediaRenderer\n {...getMediaPropsFromShareable(shareable)}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Desktop: Products Container - Single row beside primary media */}\n {hasNestedMedia && (\n <div\n className={`relative hidden min-w-0 self-stretch @md:flex @md:flex-1 px-${padding}`}\n >\n <div\n ref={scrollContainerRef}\n className={`flex h-full flex-row overflow-x-auto gap-${gapValues[gap]}`}\n style={{ scrollSnapType: \"x mandatory\" }}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col gap-1 ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n style={{\n width: `calc(${primaryMediaHeight} * 0.75)`,\n scrollSnapAlign: \"start\",\n }}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-full rounded-${borderRadius} overflow-hidden`}\n >\n <MediaRenderer {...getMediaPropsFromShareable(shareable)} />\n </div>\n <span className={`flex-none text-sm text-${nestedTextColor}`}>\n <p className=\"truncate\">{shareable.title || \"\"}</p>\n <p className=\"truncate\">\n {((shareable.display_price as string) ?? shareable.price) ||\n \"\"}\n </p>\n </span>\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n <div\n className={`absolute inset-x-0 top-1/2 flex w-full -translate-y-1/2 items-center justify-between px-8`}\n >\n <ScrollArrows\n onPrevious={() => scrollByAmount(\"prev\")}\n onNext={() => scrollByAmount(\"next\")}\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const nestedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"NestedWidget\",\n displayName: \"Nested Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"shareables\"],\n fields: [\n // Content tab - Resource group\n {\n key: \"resource\",\n label: \"Primary Media\",\n type: \"image\",\n accept: \"any\",\n description: \"Select the primary media displayed in the large panel\",\n tab: \"styling\",\n group: \"Content\",\n },\n // Content tab - Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed over the primary media\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Main title displayed over the primary media\",\n defaultValue: \"Featured Collection\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n label: \"Title Font Size\",\n defaultValue: \"xl\",\n key: \"titleFontSize\",\n description: \"Font size for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n // Styling tab - Design group\n getHeightField({\n key: \"primaryMediaHeight\",\n label: \"Primary Media Height\",\n description: \"Height of the primary media container\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"titleAlignment\",\n label: \"Content Alignment\",\n type: \"alignment\",\n description: \"Alignment of the content inside the primary media\",\n defaultValue: { horizontal: \"left\", vertical: \"bottom\" },\n options: {\n horizontalEnabled: true,\n verticalEnabled: true,\n },\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"separator2\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n defaultValue: 4,\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding used throughout the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n defaultValue: \"md\",\n label: \"Border Radius\",\n key: \"borderRadius\",\n description: \"Rounded corners for the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description:\n \"Add a dark overlay to the primary media for better text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay effect\",\n defaultValue: \"gradient\",\n options: [\n { label: \"Solid\", value: \"solid\" },\n { label: \"Gradient\", value: \"gradient\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n // Styling tab - Nested Media Styling group\n getGapField({\n label: \"Gap\",\n defaultValue: \"md\",\n key: \"gap\",\n description: \"Gap between nested media items\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n getColorField({\n defaultValue: \"foreground\",\n key: \"nestedTextColor\",\n label: \"Nested Text Color\",\n description: \"Color for nested media labels\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n {\n type: \"background\",\n defaultValue: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background color for nested media container\",\n tab: \"styling\",\n group: \"Nested Design\",\n },\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure dynamic data fetching from an API\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n // Per-item configuration schema for custom data sources\n itemConfigSchema: {\n description: \"Configure settings for this item\",\n fields: [\n {\n key: \"title\",\n label: \"Custom Title\",\n type: \"text\",\n description: \"Override the item's title for this widget\",\n },\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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AAiB;GACf,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACF,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAEF,eAAe;GACb,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;IAAE,YAAY;IAAQ,UAAU;IAAU;GACxD,SAAS;IACP,mBAAmB;IACnB,iBAAiB;IAClB;GACD,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD,gBAAgB;GACd,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,qBAAqB;GACnB,cAAc;GACd,OAAO;GACP,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAY,OAAO;IAAY,CACzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAED,YAAY;GACV,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,QAAQ,CACN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACd,CACF;EACF;CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NestedWidget-DrRazqvX.cjs","names":["ChevronLeft","ChevronRight","useWidgetInteraction","borderWidthClasses","borderColorClasses","MediaRenderer","getMediaPropsFromShareable","gapValues","getFontSizeField","getColorField","getHeightField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField","getGapField"],"sources":["../../widgets/src/ui/scroll-arrows.tsx","../../widgets/src/widgets/NestedWidget.tsx"],"sourcesContent":["import type React from \"react\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\n\ntype ScrollArrowsProps = {\n onPrevious: () => void;\n onNext: () => void;\n};\n\nexport function ScrollArrows({\n onPrevious,\n onNext,\n}: ScrollArrowsProps): React.JSX.Element {\n return (\n <>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex size-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onPrevious}\n aria-label=\"Previous slide\"\n >\n <ChevronLeft className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n className=\"bg-foreground text-background flex size-6 items-center justify-center rounded-2xl opacity-70 transition-colors hover:opacity-50 disabled:opacity-30\"\n onClick={onNext}\n aria-label=\"Next slide\"\n >\n <ChevronRight className=\"size-4\" />\n </button>\n </>\n );\n}\n","import { useRef, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport {\n MediaRenderer,\n getMediaPropsFromShareable,\n} from \"../components/MediaRenderer\";\nimport type {\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n AlignOptions,\n GapOptions,\n BackgroundValue,\n} from \"@fluid-app/portal-core/types\";\nimport {\n getHeightField,\n type WidgetPropertySchema,\n} from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getGapField,\n getPaddingField,\n gapValues,\n} from \"../core/fields\";\nimport { ScrollArrows } from \"../ui/scroll-arrows\";\nimport { type ShareableItem } from \"@fluid-app/portal-core/types\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\n\nconst DEFAULT_SHAREABLES: ShareableItem[] = [];\n\ntype NestedWidgetProps = ComponentProps<\"div\"> & {\n // Content\n resource?: ShareableItem;\n titleEnabled?: boolean;\n titleText?: string;\n shareables?: ShareableItem[];\n\n // Layout\n gap?: GapOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n primaryMediaHeight?: string;\n\n // Title styling\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n titleAlignment?: AlignOptions;\n\n // Nested media styling\n nestedTextColor?: ColorOptions;\n background?: BackgroundValue;\n\n // Overlay\n overlayEnabled?: boolean;\n overlayType?: \"solid\" | \"gradient\";\n overlayIntensity?: number;\n};\n\nexport function NestedWidget({\n resource,\n titleEnabled = true,\n titleText = \"Featured Collection\",\n shareables = DEFAULT_SHAREABLES,\n gap = \"md\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"none\",\n borderColor = \"muted\",\n primaryMediaHeight = \"400px\",\n titleFontSize = \"xl\",\n titleColor = \"background\",\n titleAlignment = { horizontal: \"left\", vertical: \"bottom\" },\n nestedTextColor = \"foreground\",\n background = {\n type: \"solid\",\n color: \"background\",\n },\n overlayEnabled = true,\n overlayType = \"gradient\",\n overlayIntensity = 50,\n className,\n ...props\n}: NestedWidgetProps): React.JSX.Element {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n\n const scrollByAmount = (direction: \"prev\" | \"next\") => {\n const container = scrollContainerRef.current;\n if (!container) return;\n\n const computedGap = parseFloat(getComputedStyle(container).gap) || 0;\n const firstItem = container.firstElementChild as HTMLElement | null;\n const itemWidth = firstItem?.offsetWidth ?? 0;\n const scrollAmount = itemWidth + computedGap;\n\n container.scrollTo({\n left:\n container.scrollLeft +\n (direction === \"next\" ? scrollAmount : -scrollAmount),\n behavior: \"smooth\",\n });\n };\n\n // Cap border radius for the primary media container: \"full\" creates a circle that clips\n // the absolutely-positioned title overlay to the narrow bottom of the circle.\n const primaryMediaRadius = borderRadius === \"full\" ? \"2xl\" : borderRadius;\n\n const { onItemClick } = useWidgetInteraction();\n\n const hasNestedMedia = shareables.length > 0;\n\n const titleAlignmentClasses = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n };\n\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n\n return (\n <div\n className={`@container flex w-full overflow-hidden p-${padding} rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} ${className}`}\n {...props}\n style={{\n height: primaryMediaHeight,\n backgroundImage: backgroundImage,\n }}\n >\n {/* Primary Media Container - Full width on mobile, fixed on desktop */}\n <div\n className={`relative @md:flex-none`}\n style={{\n width: primaryMediaHeight,\n }}\n >\n {/* Media + overlay clipped to rounded shape — title is a sibling so it isn't clipped */}\n <div\n className={`overflow-hidden rounded-${primaryMediaRadius} absolute inset-0`}\n >\n <MediaRenderer\n {...(resource ? getMediaPropsFromShareable(resource) : {})}\n autoplay\n loop\n muted\n />\n\n {/* Overlay */}\n {overlayEnabled && (\n <div\n className={`pointer-events-none absolute inset-0 z-10 ${\n overlayType === \"gradient\"\n ? \"bg-gradient-to-t from-black to-transparent\"\n : \"bg-black\"\n }`}\n style={{\n opacity:\n (Number(String(overlayIntensity).replace(\"%\", \"\")) || 50) /\n 100,\n }}\n />\n )}\n </div>\n\n {/* Title and Mobile Nested Media — outside the overflow-hidden clip */}\n {((titleEnabled && titleText) || hasNestedMedia) && (\n <div\n className={`absolute z-20 w-full ${titleAlignmentClasses[titleAlignment?.horizontal ?? \"left\"]} p-${padding} ${\n titleAlignment.vertical === \"top\"\n ? `top-0 pt-${padding}`\n : titleAlignment.vertical === \"center\"\n ? \"top-1/2 -translate-y-1/2\"\n : `bottom-0 pb-${padding}`\n }`}\n >\n {titleEnabled && titleText && (\n <h2\n className={`font-header leading-tight font-bold text-${titleColor} text-${titleFontSize === \"md\" ? \"base\" : titleFontSize}`}\n >\n {titleText}\n </h2>\n )}\n\n {/* Mobile: Products overlay inside primary media */}\n {hasNestedMedia && (\n <div className={`pt-${padding} @md:hidden`}>\n <div\n className={`flex overflow-x-auto gap-${gapValues[gap]} bg-transparent`}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col items-center ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-40 overflow-hidden rounded-${borderRadius}`}\n >\n <MediaRenderer\n {...getMediaPropsFromShareable(shareable)}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Desktop: Products Container - Single row beside primary media */}\n {hasNestedMedia && (\n <div\n className={`relative hidden min-w-0 self-stretch @md:flex @md:flex-1 px-${padding}`}\n >\n <div\n ref={scrollContainerRef}\n className={`flex h-full flex-row overflow-x-auto gap-${gapValues[gap]}`}\n style={{ scrollSnapType: \"x mandatory\" }}\n >\n {shareables.map((shareable) => (\n <div\n key={shareable.id}\n className={`flex shrink-0 flex-col gap-1 ${onItemClick ? \"cursor-pointer\" : \"\"}`}\n style={{\n width: `calc(${primaryMediaHeight} * 0.75)`,\n scrollSnapAlign: \"start\",\n }}\n {...(onItemClick\n ? {\n role: \"button\",\n tabIndex: 0,\n onClick: () => onItemClick(shareable),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onItemClick(shareable);\n }\n },\n }\n : {})}\n >\n <div\n className={`aspect-3/4 h-full rounded-${borderRadius} overflow-hidden`}\n >\n <MediaRenderer {...getMediaPropsFromShareable(shareable)} />\n </div>\n <span className={`flex-none text-sm text-${nestedTextColor}`}>\n <p className=\"truncate\">{shareable.title || \"\"}</p>\n <p className=\"truncate\">\n {((shareable.display_price as string) ?? shareable.price) ||\n \"\"}\n </p>\n </span>\n </div>\n ))}\n </div>\n\n {/* Navigation arrows */}\n <div\n className={`absolute inset-x-0 top-1/2 flex w-full -translate-y-1/2 items-center justify-between px-8`}\n >\n <ScrollArrows\n onPrevious={() => scrollByAmount(\"prev\")}\n onNext={() => scrollByAmount(\"next\")}\n />\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const nestedWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"NestedWidget\",\n displayName: \"Nested Widget\",\n tabsConfig: [\n { id: \"styling\", label: \"Styling\" },\n { id: \"data\", label: \"Data\" },\n ],\n dataSourceTargetProps: [\"shareables\"],\n fields: [\n // Content tab - Resource group\n {\n key: \"resource\",\n label: \"Primary Media\",\n type: \"image\",\n accept: \"any\",\n description: \"Select the primary media displayed in the large panel\",\n tab: \"styling\",\n group: \"Content\",\n },\n // Content tab - Title group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed over the primary media\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Main title displayed over the primary media\",\n defaultValue: \"Featured Collection\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n label: \"Title Font Size\",\n defaultValue: \"xl\",\n key: \"titleFontSize\",\n description: \"Font size for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n defaultValue: \"background\",\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n // Styling tab - Design group\n getHeightField({\n key: \"primaryMediaHeight\",\n label: \"Primary Media Height\",\n description: \"Height of the primary media container\",\n defaultValue: \"400px\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"titleAlignment\",\n label: \"Content Alignment\",\n type: \"alignment\",\n description: \"Alignment of the content inside the primary media\",\n defaultValue: { horizontal: \"left\", vertical: \"bottom\" },\n options: {\n horizontalEnabled: true,\n verticalEnabled: true,\n },\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"separator2\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n defaultValue: 4,\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding used throughout the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n defaultValue: \"md\",\n label: \"Border Radius\",\n key: \"borderRadius\",\n description: \"Rounded corners for the widget\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget\",\n defaultValue: \"none\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"overlayEnabled\",\n label: \"Enable Overlay\",\n type: \"boolean\",\n description:\n \"Add a dark overlay to the primary media for better text readability\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Design\",\n },\n {\n key: \"overlayType\",\n label: \"Overlay Type\",\n type: \"buttonGroup\",\n description: \"Type of overlay effect\",\n defaultValue: \"gradient\",\n options: [\n { label: \"Solid\", value: \"solid\" },\n { label: \"Gradient\", value: \"gradient\" },\n ],\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n {\n key: \"overlayIntensity\",\n label: \"Overlay Intensity\",\n type: \"slider\",\n description: \"Opacity of the overlay (0-100)\",\n min: 0,\n max: 100,\n step: 5,\n defaultValue: 50,\n unit: \"%\",\n tab: \"styling\",\n group: \"Design\",\n requiresKeyToBeTrue: \"overlayEnabled\",\n },\n // Styling tab - Nested Media Styling group\n getGapField({\n label: \"Gap\",\n defaultValue: \"md\",\n key: \"gap\",\n description: \"Gap between nested media items\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n getColorField({\n defaultValue: \"foreground\",\n key: \"nestedTextColor\",\n label: \"Nested Text Color\",\n description: \"Color for nested media labels\",\n tab: \"styling\",\n group: \"Nested Design\",\n }),\n {\n type: \"background\",\n defaultValue: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background color for nested media container\",\n tab: \"styling\",\n group: \"Nested Design\",\n },\n // Data tab\n {\n key: \"dataSource\",\n label: \"Data Source\",\n type: \"dataSource\",\n description: \"Configure dynamic data fetching from an API\",\n tab: \"data\",\n group: \"Data Configuration\",\n },\n ],\n // Per-item configuration schema for custom data sources\n itemConfigSchema: {\n description: \"Configure settings for this item\",\n fields: [\n {\n key: \"title\",\n label: \"Custom Title\",\n type: \"text\",\n description: \"Override the item's title for this widget\",\n },\n ],\n },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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qBAAqB;GACnB,cAAc;GACd,OAAO;GACP,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,SAAS,CACP;IAAE,OAAO;IAAS,OAAO;IAAS,EAClC;IAAE,OAAO;IAAY,OAAO;IAAY,CACzC;GACD,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAEDC,mBAAAA,YAAY;GACV,OAAO;GACP,cAAc;GACd,KAAK;GACL,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACFN,mBAAAA,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACR;EAED;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,OAAO;GACR;EACF;CAED,kBAAkB;EAChB,aAAa;EACb,QAAQ,CACN;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACd,CACF;EACF;CACF"}
|