@fluid-app/portal-sdk 0.1.211 → 0.1.213
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-CmVC7I4i.cjs +627 -0
- package/dist/CalendarWidget-CmVC7I4i.cjs.map +1 -0
- package/dist/CalendarWidget-RdPgsQLG.mjs +610 -0
- package/dist/CalendarWidget-RdPgsQLG.mjs.map +1 -0
- package/dist/{FluidProvider-DJfKbTQm.mjs → FluidProvider-D2eBYdP9.mjs} +5 -5
- package/dist/{FluidProvider-DJfKbTQm.mjs.map → FluidProvider-D2eBYdP9.mjs.map} +1 -1
- package/dist/{FluidProvider-CfBG1eFt.cjs → FluidProvider-D7-UjZFz.cjs} +5 -5
- package/dist/{FluidProvider-CfBG1eFt.cjs.map → FluidProvider-D7-UjZFz.cjs.map} +1 -1
- package/dist/{MessagingScreen-4QQbsIUy.cjs → MessagingScreen-B0WWqXj9.cjs} +4 -4
- package/dist/{MessagingScreen-C6rXYwlm.cjs → MessagingScreen-CrPiH9br.cjs} +2 -2
- package/dist/{MessagingScreen-C6rXYwlm.cjs.map → MessagingScreen-CrPiH9br.cjs.map} +1 -1
- package/dist/{MessagingScreen-BUSGkkQM.mjs → MessagingScreen-D54c5afj.mjs} +2 -2
- package/dist/{MessagingScreen-BUSGkkQM.mjs.map → MessagingScreen-D54c5afj.mjs.map} +1 -1
- package/dist/{ProfileScreen-aUcLKi7B.mjs → ProfileScreen-C60U8ubV.mjs} +2 -2
- package/dist/{ProfileScreen-aUcLKi7B.mjs.map → ProfileScreen-C60U8ubV.mjs.map} +1 -1
- package/dist/{ProfileScreen-DaDRVK5B.cjs → ProfileScreen-KKkt3e9c.cjs} +2 -2
- package/dist/{ProfileScreen-DaDRVK5B.cjs.map → ProfileScreen-KKkt3e9c.cjs.map} +1 -1
- package/dist/{ProfileScreen-gHoo8LGb.cjs → ProfileScreen-u9MNVGne.cjs} +4 -4
- package/dist/{ShopScreen-jdit46tQ.mjs → ShopScreen-BJfA62O-.mjs} +2 -2
- package/dist/{ShopScreen-jdit46tQ.mjs.map → ShopScreen-BJfA62O-.mjs.map} +1 -1
- package/dist/{ShopScreen-Bdkbl6gq.cjs → ShopScreen-Bc7jZje5.cjs} +4 -4
- package/dist/{ShopScreen-vC7Yk8vC.cjs → ShopScreen-Ct3RyfWT.cjs} +2 -2
- package/dist/{ShopScreen-vC7Yk8vC.cjs.map → ShopScreen-Ct3RyfWT.cjs.map} +1 -1
- package/dist/VideoWidget-CMk4QEx_.mjs +969 -0
- package/dist/VideoWidget-CMk4QEx_.mjs.map +1 -0
- package/dist/VideoWidget-DIUMQy1C.cjs +986 -0
- package/dist/VideoWidget-DIUMQy1C.cjs.map +1 -0
- package/dist/index.cjs +12 -12
- package/dist/index.d.cts +42 -8
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +42 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +12 -12
- package/package.json +16 -16
- package/dist/CalendarWidget-BcZNsVQo.cjs +0 -445
- package/dist/CalendarWidget-BcZNsVQo.cjs.map +0 -1
- package/dist/CalendarWidget-DTqgk0qe.mjs +0 -428
- package/dist/CalendarWidget-DTqgk0qe.mjs.map +0 -1
- package/dist/VideoWidget-B9yfmLXd.cjs +0 -222
- package/dist/VideoWidget-B9yfmLXd.cjs.map +0 -1
- package/dist/VideoWidget-FoAueFwA.mjs +0 -205
- package/dist/VideoWidget-FoAueFwA.mjs.map +0 -1
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
const require_chunk = require("./chunk-9hOWP6kD.cjs");
|
|
2
|
+
const require_registry_context = require("./registry-context-RWj2xJlC.cjs");
|
|
3
|
+
const require_error_state = require("./error-state-C-AalLnz.cjs");
|
|
4
|
+
const require_registries = require("./registries-CpUM406S.cjs");
|
|
5
|
+
let react = require("react");
|
|
6
|
+
let _tanstack_react_query = require("@tanstack/react-query");
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let lucide_react = require("lucide-react");
|
|
9
|
+
//#region ../widgets/src/hooks/use-calendar-events.preview.ts
|
|
10
|
+
const today = /* @__PURE__ */ new Date();
|
|
11
|
+
const inTwoDays = new Date(today);
|
|
12
|
+
inTwoDays.setDate(inTwoDays.getDate() + 2);
|
|
13
|
+
function toISO(date, hours, minutes = 0) {
|
|
14
|
+
const d = new Date(date);
|
|
15
|
+
d.setHours(hours, minutes, 0, 0);
|
|
16
|
+
return d.toISOString();
|
|
17
|
+
}
|
|
18
|
+
function toDateString(date) {
|
|
19
|
+
return date.toISOString().split("T")[0];
|
|
20
|
+
}
|
|
21
|
+
const PREVIEW_DATA = [
|
|
22
|
+
{
|
|
23
|
+
id: 1,
|
|
24
|
+
title: "Team Strategy Call",
|
|
25
|
+
start: toISO(today, 9, 0),
|
|
26
|
+
end: toISO(today, 10, 0),
|
|
27
|
+
status: "active",
|
|
28
|
+
color: "#4f46e5"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 2,
|
|
32
|
+
title: "Product Launch Webinar",
|
|
33
|
+
start: toISO(today, 14, 0),
|
|
34
|
+
end: toISO(today, 15, 30),
|
|
35
|
+
status: "active",
|
|
36
|
+
color: "#0891b2",
|
|
37
|
+
venue: "Zoom"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 3,
|
|
41
|
+
title: "Annual Leadership Summit",
|
|
42
|
+
start: `${toDateString(inTwoDays)}T00:00:00.000Z`,
|
|
43
|
+
end: `${toDateString(inTwoDays)}T23:59:59.000Z`,
|
|
44
|
+
status: "active",
|
|
45
|
+
color: "#059669",
|
|
46
|
+
isAllDay: true,
|
|
47
|
+
venue: "Convention Center"
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region ../widgets/src/hooks/use-calendar-events.ts
|
|
52
|
+
function useCalendarEvents() {
|
|
53
|
+
const widgetsApi = require_error_state.useWidgetsApi();
|
|
54
|
+
const { isPreview } = require_error_state.useWidgetPreviewContext();
|
|
55
|
+
const { baseUrl } = require_registry_context.useDataSourceRegistryConfig();
|
|
56
|
+
return (0, _tanstack_react_query.useQuery)({
|
|
57
|
+
queryKey: [
|
|
58
|
+
"portal-widget-use",
|
|
59
|
+
"calendar-events",
|
|
60
|
+
isPreview ? "preview" : baseUrl
|
|
61
|
+
],
|
|
62
|
+
queryFn: ({ signal }) => widgetsApi.fetchCalendarEvents(signal),
|
|
63
|
+
enabled: !isPreview,
|
|
64
|
+
...isPreview && { placeholderData: PREVIEW_DATA }
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region ../widgets/src/widgets/CalendarWidget.tsx
|
|
69
|
+
var CalendarWidget_exports = /* @__PURE__ */ require_chunk.__exportAll({
|
|
70
|
+
CalendarWidget: () => CalendarWidget,
|
|
71
|
+
calendarWidgetPropertySchema: () => calendarWidgetPropertySchema
|
|
72
|
+
});
|
|
73
|
+
const DAY_NAMES = [
|
|
74
|
+
"Sun",
|
|
75
|
+
"Mon",
|
|
76
|
+
"Tue",
|
|
77
|
+
"Wed",
|
|
78
|
+
"Thu",
|
|
79
|
+
"Fri",
|
|
80
|
+
"Sat"
|
|
81
|
+
];
|
|
82
|
+
const getDaysInMonth = (year, month) => new Date(year, month + 1, 0).getDate();
|
|
83
|
+
const getFirstDayOfMonth = (year, month) => new Date(year, month, 1).getDay();
|
|
84
|
+
const isSameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
85
|
+
const startOfDay = (d) => {
|
|
86
|
+
const x = new Date(d);
|
|
87
|
+
x.setHours(0, 0, 0, 0);
|
|
88
|
+
return x;
|
|
89
|
+
};
|
|
90
|
+
const addDays = (d, n) => {
|
|
91
|
+
const x = new Date(d);
|
|
92
|
+
x.setDate(x.getDate() + n);
|
|
93
|
+
return x;
|
|
94
|
+
};
|
|
95
|
+
const diffDays = (a, b) => {
|
|
96
|
+
const ms = startOfDay(a).getTime() - startOfDay(b).getTime();
|
|
97
|
+
return Math.round(ms / 864e5);
|
|
98
|
+
};
|
|
99
|
+
const generateMonthGrid = (year, month) => {
|
|
100
|
+
const daysInMonth = getDaysInMonth(year, month);
|
|
101
|
+
const firstDay = getFirstDayOfMonth(year, month);
|
|
102
|
+
const today = /* @__PURE__ */ new Date();
|
|
103
|
+
const cells = [];
|
|
104
|
+
for (let i = 0; i < firstDay; i++) cells.push({
|
|
105
|
+
date: null,
|
|
106
|
+
isToday: false,
|
|
107
|
+
isCurrentMonth: false
|
|
108
|
+
});
|
|
109
|
+
for (let day = 1; day <= daysInMonth; day++) {
|
|
110
|
+
const date = new Date(year, month, day);
|
|
111
|
+
cells.push({
|
|
112
|
+
date,
|
|
113
|
+
isToday: isSameDay(date, today),
|
|
114
|
+
isCurrentMonth: true
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return cells;
|
|
118
|
+
};
|
|
119
|
+
const generateWeekGrid = () => {
|
|
120
|
+
const today = /* @__PURE__ */ new Date();
|
|
121
|
+
const weekday = today.getDay();
|
|
122
|
+
return Array.from({ length: 7 }, (_, i) => {
|
|
123
|
+
const date = addDays(today, -weekday + i);
|
|
124
|
+
return {
|
|
125
|
+
date,
|
|
126
|
+
isToday: isSameDay(date, today)
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
const formatTime = (iso) => new Date(iso).toLocaleTimeString("en-US", {
|
|
131
|
+
hour: "numeric",
|
|
132
|
+
minute: "2-digit"
|
|
133
|
+
});
|
|
134
|
+
const formatContextualDate = (date) => {
|
|
135
|
+
const d = diffDays(date, /* @__PURE__ */ new Date());
|
|
136
|
+
const weekday = date.toLocaleDateString("en-US", { weekday: "short" });
|
|
137
|
+
const monthDay = date.toLocaleDateString("en-US", {
|
|
138
|
+
month: "short",
|
|
139
|
+
day: "numeric"
|
|
140
|
+
});
|
|
141
|
+
if (d === 0) return {
|
|
142
|
+
lead: "Today",
|
|
143
|
+
detail: `${weekday}, ${monthDay}`
|
|
144
|
+
};
|
|
145
|
+
if (d === 1) return {
|
|
146
|
+
lead: "Tomorrow",
|
|
147
|
+
detail: `${weekday}, ${monthDay}`
|
|
148
|
+
};
|
|
149
|
+
if (d === -1) return {
|
|
150
|
+
lead: "Yesterday",
|
|
151
|
+
detail: `${weekday}, ${monthDay}`
|
|
152
|
+
};
|
|
153
|
+
return {
|
|
154
|
+
lead: null,
|
|
155
|
+
detail: `${weekday}, ${monthDay}`
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
function DayCellButton({ date, isToday, isSelected, eventCount, accentColor, textColor, showEventDensity, onClick }) {
|
|
159
|
+
const dotCount = showEventDensity ? Math.min(eventCount, 3) : eventCount > 0 ? 1 : 0;
|
|
160
|
+
const baseClasses = "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";
|
|
161
|
+
const stateClasses = isSelected ? `bg-${accentColor} text-${accentColor}-foreground focus-visible:ring-${accentColor}/40` : isToday ? `bg-${accentColor}/10 text-${accentColor} font-semibold hover:bg-${accentColor}/20 focus-visible:ring-${accentColor}/40` : `text-${textColor} hover:bg-${accentColor}/10 focus-visible:ring-${accentColor}/40`;
|
|
162
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
163
|
+
type: "button",
|
|
164
|
+
onClick,
|
|
165
|
+
"aria-label": date.toLocaleDateString("en-US", {
|
|
166
|
+
weekday: "long",
|
|
167
|
+
month: "long",
|
|
168
|
+
day: "numeric"
|
|
169
|
+
}),
|
|
170
|
+
"aria-current": isToday ? "date" : void 0,
|
|
171
|
+
"aria-pressed": isSelected,
|
|
172
|
+
className: `${baseClasses} ${stateClasses}`,
|
|
173
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
174
|
+
className: "leading-none",
|
|
175
|
+
children: date.getDate()
|
|
176
|
+
}), dotCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
177
|
+
"aria-hidden": "true",
|
|
178
|
+
className: "absolute bottom-1.5 flex items-center gap-[2px]",
|
|
179
|
+
children: Array.from({ length: dotCount }).map((_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: `size-1 rounded-full ${isSelected ? `bg-${accentColor}-foreground/70` : `bg-${accentColor}`}` }, i))
|
|
180
|
+
})]
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function EventCard({ event, accentColor, textColor }) {
|
|
184
|
+
const accentVar = `var(--color-${accentColor})`;
|
|
185
|
+
const barColor = event.color || accentVar;
|
|
186
|
+
const timeText = event.isAllDay ? "All day" : `${formatTime(event.start)} – ${formatTime(event.end)}`;
|
|
187
|
+
const content = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
188
|
+
"aria-hidden": "true",
|
|
189
|
+
className: "w-[2px] shrink-0 self-stretch rounded-full",
|
|
190
|
+
style: { backgroundColor: barColor }
|
|
191
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
192
|
+
className: "min-w-0 flex-1",
|
|
193
|
+
children: [
|
|
194
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
195
|
+
className: `truncate text-sm font-semibold text-${textColor} leading-tight`,
|
|
196
|
+
children: event.title
|
|
197
|
+
}),
|
|
198
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
199
|
+
className: `mt-1 text-[11px] tabular-nums text-${textColor}/60 font-medium`,
|
|
200
|
+
children: timeText
|
|
201
|
+
}),
|
|
202
|
+
event.venue && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
203
|
+
className: `mt-1.5 flex items-center gap-1 text-[11px] text-${textColor}/55`,
|
|
204
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.MapPin, { className: "size-2.5 shrink-0" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
205
|
+
className: "truncate",
|
|
206
|
+
children: event.venue
|
|
207
|
+
})]
|
|
208
|
+
})
|
|
209
|
+
]
|
|
210
|
+
})] });
|
|
211
|
+
const wrapperClasses = `group flex gap-x-2 rounded-md px-2 py-2 transition-colors -mx-2`;
|
|
212
|
+
const interactiveClasses = `hover:bg-${accentColor}/5`;
|
|
213
|
+
if (event.url) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
214
|
+
href: event.url,
|
|
215
|
+
target: "_blank",
|
|
216
|
+
rel: "noopener noreferrer",
|
|
217
|
+
className: `${wrapperClasses} ${interactiveClasses}`,
|
|
218
|
+
children: content
|
|
219
|
+
});
|
|
220
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
221
|
+
className: wrapperClasses,
|
|
222
|
+
children: content
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function NavButton({ icon: Icon, label, variant, accentColor, textColor, onClick }) {
|
|
226
|
+
const classes = variant === "accent" ? `bg-${accentColor} text-${accentColor}-foreground hover:bg-${accentColor}/90 focus-visible:ring-${accentColor}/40` : `bg-${textColor}/5 text-${textColor} hover:bg-${textColor}/10 focus-visible:ring-${textColor}/20`;
|
|
227
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
228
|
+
type: "button",
|
|
229
|
+
onClick,
|
|
230
|
+
"aria-label": label,
|
|
231
|
+
className: `flex size-8 items-center justify-center rounded-full text-[12px] transition-colors focus:outline-none focus-visible:ring-2 ${classes}`,
|
|
232
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "size-4" })
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
function CalendarWidget({ titleEnabled = true, titleText = "Calendar", titleFontSize = "xl", titleColor = "foreground", background = {
|
|
236
|
+
type: "solid",
|
|
237
|
+
color: "background"
|
|
238
|
+
}, textColor = "foreground", accentColor = "primary", padding = 4, borderRadius = "md", showEventDensity = true, showTodayButton = true, weekendDim = true, showYearEyebrow = true, className, ...props }) {
|
|
239
|
+
const backgroundColor = background.color || "background";
|
|
240
|
+
const backgroundImage = (background.resource?.image_url || background.resource?.imageUrl) && background.type === "image" ? `url(${background.resource.image_url || background.resource.imageUrl})` : "none";
|
|
241
|
+
const [view, setView] = (0, react.useState)(() => {
|
|
242
|
+
const now = /* @__PURE__ */ new Date();
|
|
243
|
+
return {
|
|
244
|
+
month: now.getMonth(),
|
|
245
|
+
year: now.getFullYear()
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
const currentMonth = view.month;
|
|
249
|
+
const currentYear = view.year;
|
|
250
|
+
const [isCollapsed, setIsCollapsed] = (0, react.useState)(false);
|
|
251
|
+
const [selectedDate, setSelectedDate] = (0, react.useState)(() => /* @__PURE__ */ new Date());
|
|
252
|
+
const [gridTransitioning, setGridTransitioning] = (0, react.useState)(false);
|
|
253
|
+
const { data: events = [], isLoading, isError } = useCalendarEvents();
|
|
254
|
+
const monthGrid = (0, react.useMemo)(() => generateMonthGrid(currentYear, currentMonth), [currentYear, currentMonth]);
|
|
255
|
+
const weekGrid = generateWeekGrid();
|
|
256
|
+
const eventsByDate = (0, react.useMemo)(() => {
|
|
257
|
+
const map = /* @__PURE__ */ new Map();
|
|
258
|
+
for (const event of events) {
|
|
259
|
+
const start = startOfDay(new Date(event.start));
|
|
260
|
+
const end = startOfDay(new Date(event.end));
|
|
261
|
+
for (let cur = start; cur <= end; cur = addDays(cur, 1)) {
|
|
262
|
+
const key = `${cur.getFullYear()}-${cur.getMonth()}-${cur.getDate()}`;
|
|
263
|
+
const list = map.get(key);
|
|
264
|
+
if (list) list.push(event);
|
|
265
|
+
else map.set(key, [event]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return map;
|
|
269
|
+
}, [events]);
|
|
270
|
+
const lookupEventsForDate = (0, react.useCallback)((date) => {
|
|
271
|
+
const key = `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
|
|
272
|
+
return eventsByDate.get(key) ?? [];
|
|
273
|
+
}, [eventsByDate]);
|
|
274
|
+
const selectedDateEvents = (0, react.useMemo)(() => {
|
|
275
|
+
if (!selectedDate) return [];
|
|
276
|
+
return lookupEventsForDate(selectedDate);
|
|
277
|
+
}, [selectedDate, lookupEventsForDate]);
|
|
278
|
+
const transitionTimeoutRef = (0, react.useRef)(null);
|
|
279
|
+
(0, react.useEffect)(() => () => {
|
|
280
|
+
if (transitionTimeoutRef.current !== null) window.clearTimeout(transitionTimeoutRef.current);
|
|
281
|
+
}, []);
|
|
282
|
+
const navigate = (0, react.useCallback)((direction) => {
|
|
283
|
+
if (transitionTimeoutRef.current !== null) window.clearTimeout(transitionTimeoutRef.current);
|
|
284
|
+
setGridTransitioning(true);
|
|
285
|
+
transitionTimeoutRef.current = window.setTimeout(() => {
|
|
286
|
+
setView((prev) => {
|
|
287
|
+
const next = prev.month + direction;
|
|
288
|
+
if (next < 0) return {
|
|
289
|
+
month: 11,
|
|
290
|
+
year: prev.year - 1
|
|
291
|
+
};
|
|
292
|
+
if (next > 11) return {
|
|
293
|
+
month: 0,
|
|
294
|
+
year: prev.year + 1
|
|
295
|
+
};
|
|
296
|
+
return {
|
|
297
|
+
month: next,
|
|
298
|
+
year: prev.year
|
|
299
|
+
};
|
|
300
|
+
});
|
|
301
|
+
setGridTransitioning(false);
|
|
302
|
+
transitionTimeoutRef.current = null;
|
|
303
|
+
}, 120);
|
|
304
|
+
}, []);
|
|
305
|
+
const goToToday = (0, react.useCallback)(() => {
|
|
306
|
+
if (transitionTimeoutRef.current !== null) window.clearTimeout(transitionTimeoutRef.current);
|
|
307
|
+
const now = /* @__PURE__ */ new Date();
|
|
308
|
+
setGridTransitioning(true);
|
|
309
|
+
transitionTimeoutRef.current = window.setTimeout(() => {
|
|
310
|
+
setView({
|
|
311
|
+
month: now.getMonth(),
|
|
312
|
+
year: now.getFullYear()
|
|
313
|
+
});
|
|
314
|
+
setSelectedDate(now);
|
|
315
|
+
setGridTransitioning(false);
|
|
316
|
+
transitionTimeoutRef.current = null;
|
|
317
|
+
}, 80);
|
|
318
|
+
}, []);
|
|
319
|
+
const now = /* @__PURE__ */ new Date();
|
|
320
|
+
const viewingCurrentMonth = currentMonth === now.getMonth() && currentYear === now.getFullYear();
|
|
321
|
+
const monthLabel = new Date(currentYear, currentMonth).toLocaleString("en-US", { month: "long" });
|
|
322
|
+
const yearLabel = String(currentYear);
|
|
323
|
+
const contextualDate = selectedDate ? formatContextualDate(selectedDate) : null;
|
|
324
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
325
|
+
className: `@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} ${className ?? ""}`,
|
|
326
|
+
style: { backgroundImage },
|
|
327
|
+
...props,
|
|
328
|
+
children: [titleEnabled && titleText && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
329
|
+
className: `p-${padding} pb-0`,
|
|
330
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
331
|
+
className: `text-${titleFontSize} text-${titleColor} font-bold tracking-[-0.012em]`,
|
|
332
|
+
children: titleText
|
|
333
|
+
})
|
|
334
|
+
}), isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
335
|
+
className: `flex min-h-[300px] items-center justify-center p-${padding}`,
|
|
336
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
337
|
+
className: `text-${accentColor}`,
|
|
338
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "size-8 animate-spin rounded-full border-2 border-current border-t-transparent" })
|
|
339
|
+
})
|
|
340
|
+
}) : isError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_error_state.ErrorState, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
341
|
+
className: `p-${padding}`,
|
|
342
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
343
|
+
className: "@md:flex @md:gap-6",
|
|
344
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
345
|
+
className: "@md:flex-none",
|
|
346
|
+
children: [
|
|
347
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
348
|
+
className: "mb-4 flex items-start justify-between gap-3",
|
|
349
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
350
|
+
className: "flex min-w-0 flex-col",
|
|
351
|
+
children: [showYearEyebrow && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
352
|
+
className: `text-[10px] font-bold tracking-[0.16em] uppercase text-${textColor}/55`,
|
|
353
|
+
children: yearLabel
|
|
354
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
355
|
+
className: `text-xl leading-tight font-bold tracking-[-0.015em] text-${textColor}`,
|
|
356
|
+
children: monthLabel
|
|
357
|
+
})]
|
|
358
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
359
|
+
className: "flex shrink-0 items-center gap-1.5",
|
|
360
|
+
children: [
|
|
361
|
+
showTodayButton && !viewingCurrentMonth && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
362
|
+
type: "button",
|
|
363
|
+
onClick: goToToday,
|
|
364
|
+
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`,
|
|
365
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.CalendarCheck, { className: "size-3" }), "Today"]
|
|
366
|
+
}),
|
|
367
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavButton, {
|
|
368
|
+
icon: lucide_react.ChevronLeft,
|
|
369
|
+
label: "Previous month",
|
|
370
|
+
variant: "ghost",
|
|
371
|
+
accentColor,
|
|
372
|
+
textColor,
|
|
373
|
+
onClick: () => navigate(-1)
|
|
374
|
+
}),
|
|
375
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavButton, {
|
|
376
|
+
icon: lucide_react.ChevronRight,
|
|
377
|
+
label: "Next month",
|
|
378
|
+
variant: "accent",
|
|
379
|
+
accentColor,
|
|
380
|
+
textColor,
|
|
381
|
+
onClick: () => navigate(1)
|
|
382
|
+
})
|
|
383
|
+
]
|
|
384
|
+
})]
|
|
385
|
+
}),
|
|
386
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
387
|
+
className: "mb-2 grid grid-cols-7 gap-1 text-center",
|
|
388
|
+
children: DAY_NAMES.map((day, idx) => {
|
|
389
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
390
|
+
className: `text-[10px] font-semibold tracking-[0.12em] uppercase text-${textColor}/${weekendDim && (idx === 0 || idx === 6) ? "40" : "55"}`,
|
|
391
|
+
children: day
|
|
392
|
+
}, day);
|
|
393
|
+
})
|
|
394
|
+
}),
|
|
395
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
396
|
+
className: "transition-opacity duration-150 ease-out",
|
|
397
|
+
style: { opacity: gridTransitioning ? .3 : 1 },
|
|
398
|
+
children: [isCollapsed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
399
|
+
className: "grid grid-cols-7 gap-1 @md:hidden",
|
|
400
|
+
children: weekGrid.map(({ date, isToday }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DayCellButton, {
|
|
401
|
+
date,
|
|
402
|
+
isToday,
|
|
403
|
+
isSelected: !!selectedDate && isSameDay(selectedDate, date),
|
|
404
|
+
eventCount: lookupEventsForDate(date).length,
|
|
405
|
+
accentColor,
|
|
406
|
+
textColor,
|
|
407
|
+
showEventDensity,
|
|
408
|
+
onClick: () => setSelectedDate(date)
|
|
409
|
+
}, date.toISOString()))
|
|
410
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
411
|
+
className: `grid grid-cols-7 gap-1 ${isCollapsed ? "hidden @md:grid" : "grid"}`,
|
|
412
|
+
children: monthGrid.map((cell, idx) => {
|
|
413
|
+
if (!cell.date) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "aspect-square" }, `empty-${idx}`);
|
|
414
|
+
const eventCount = lookupEventsForDate(cell.date).length;
|
|
415
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DayCellButton, {
|
|
416
|
+
date: cell.date,
|
|
417
|
+
isToday: cell.isToday,
|
|
418
|
+
isSelected: !!selectedDate && isSameDay(selectedDate, cell.date),
|
|
419
|
+
eventCount,
|
|
420
|
+
accentColor,
|
|
421
|
+
textColor,
|
|
422
|
+
showEventDensity,
|
|
423
|
+
onClick: () => setSelectedDate(cell.date)
|
|
424
|
+
}, cell.date.toISOString());
|
|
425
|
+
})
|
|
426
|
+
})]
|
|
427
|
+
}),
|
|
428
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
429
|
+
type: "button",
|
|
430
|
+
onClick: () => setIsCollapsed(!isCollapsed),
|
|
431
|
+
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`,
|
|
432
|
+
"aria-label": isCollapsed ? "Expand calendar" : "Collapse calendar",
|
|
433
|
+
children: [
|
|
434
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: `h-px w-1/2 bg-${textColor}/20` }),
|
|
435
|
+
isCollapsed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronsDown, { className: "size-3" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronsUp, { className: "size-3" }),
|
|
436
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: `h-px w-1/2 bg-${textColor}/20` })
|
|
437
|
+
]
|
|
438
|
+
})
|
|
439
|
+
]
|
|
440
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
441
|
+
className: `mt-4 border-${textColor}/10 @md:mt-0 @md:w-56 @md:border-l @md:pl-6`,
|
|
442
|
+
children: [contextualDate && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
443
|
+
className: "mb-3",
|
|
444
|
+
children: [contextualDate.lead && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
445
|
+
className: `text-[10px] font-bold tracking-[0.16em] uppercase text-${accentColor}`,
|
|
446
|
+
children: contextualDate.lead
|
|
447
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
448
|
+
className: `text-sm font-semibold text-${textColor} tabular-nums`,
|
|
449
|
+
children: contextualDate.detail
|
|
450
|
+
})]
|
|
451
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
452
|
+
className: "animate-in fade-in slide-in-from-bottom-2 flex flex-col duration-200 ease-out",
|
|
453
|
+
children: selectedDateEvents.length > 0 ? selectedDateEvents.map((event, idx) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EventCard, {
|
|
454
|
+
event,
|
|
455
|
+
accentColor,
|
|
456
|
+
textColor
|
|
457
|
+
}, `${event.id}-${idx}`)) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
458
|
+
className: `flex flex-col items-start gap-1 rounded-md border border-dashed border-${textColor}/15 px-3 py-3`,
|
|
459
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
460
|
+
className: "flex items-center gap-1.5",
|
|
461
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.CalendarCheck, { className: `size-3 text-${textColor}/40` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
462
|
+
className: `text-[11px] font-semibold text-${textColor}/60`,
|
|
463
|
+
children: "Nothing scheduled"
|
|
464
|
+
})]
|
|
465
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
466
|
+
className: `text-[11px] text-${textColor}/45`,
|
|
467
|
+
children: "Enjoy the breather."
|
|
468
|
+
})]
|
|
469
|
+
})
|
|
470
|
+
}, selectedDate?.toISOString() ?? "none")]
|
|
471
|
+
})]
|
|
472
|
+
})
|
|
473
|
+
})]
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
const calendarWidgetPropertySchema = {
|
|
477
|
+
widgetType: "CalendarWidget",
|
|
478
|
+
displayName: "Calendar Widget",
|
|
479
|
+
tabsConfig: [{
|
|
480
|
+
id: "styling",
|
|
481
|
+
label: "Styling"
|
|
482
|
+
}],
|
|
483
|
+
fields: [
|
|
484
|
+
{
|
|
485
|
+
key: "titleEnabled",
|
|
486
|
+
label: "Widget Title",
|
|
487
|
+
type: "boolean",
|
|
488
|
+
description: "Enable the title displayed above the calendar",
|
|
489
|
+
defaultValue: true,
|
|
490
|
+
tab: "styling",
|
|
491
|
+
group: "Title"
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
key: "titleText",
|
|
495
|
+
label: "Title",
|
|
496
|
+
type: "text",
|
|
497
|
+
description: "Title text displayed above the calendar",
|
|
498
|
+
defaultValue: "Calendar",
|
|
499
|
+
tab: "styling",
|
|
500
|
+
group: "Title",
|
|
501
|
+
requiresKeyToBeTrue: "titleEnabled"
|
|
502
|
+
},
|
|
503
|
+
require_registries.getFontSizeField({
|
|
504
|
+
key: "titleFontSize",
|
|
505
|
+
label: "Title Font Size",
|
|
506
|
+
description: "Font size for the widget title",
|
|
507
|
+
defaultValue: "xl",
|
|
508
|
+
tab: "styling",
|
|
509
|
+
group: "Title",
|
|
510
|
+
requiresKeyToBeTrue: "titleEnabled"
|
|
511
|
+
}),
|
|
512
|
+
require_registries.getColorField({
|
|
513
|
+
key: "titleColor",
|
|
514
|
+
label: "Title Color",
|
|
515
|
+
description: "Color for the widget title",
|
|
516
|
+
defaultValue: "foreground",
|
|
517
|
+
tab: "styling",
|
|
518
|
+
group: "Title",
|
|
519
|
+
requiresKeyToBeTrue: "titleEnabled"
|
|
520
|
+
}),
|
|
521
|
+
{
|
|
522
|
+
type: "background",
|
|
523
|
+
key: "background",
|
|
524
|
+
label: "Background",
|
|
525
|
+
description: "Background for the calendar container",
|
|
526
|
+
defaultValue: "background",
|
|
527
|
+
tab: "styling",
|
|
528
|
+
group: "Design"
|
|
529
|
+
},
|
|
530
|
+
require_registries.getColorField({
|
|
531
|
+
key: "textColor",
|
|
532
|
+
label: "Text Color",
|
|
533
|
+
description: "Default text color for calendar content",
|
|
534
|
+
defaultValue: "foreground",
|
|
535
|
+
tab: "styling",
|
|
536
|
+
group: "Design"
|
|
537
|
+
}),
|
|
538
|
+
require_registries.getColorField({
|
|
539
|
+
key: "accentColor",
|
|
540
|
+
label: "Accent Color",
|
|
541
|
+
description: "Drives today highlight, event dots, Today pill, and selected day",
|
|
542
|
+
defaultValue: "primary",
|
|
543
|
+
tab: "styling",
|
|
544
|
+
group: "Design"
|
|
545
|
+
}),
|
|
546
|
+
{
|
|
547
|
+
key: "separator",
|
|
548
|
+
type: "separator",
|
|
549
|
+
label: "Separator",
|
|
550
|
+
tab: "styling",
|
|
551
|
+
group: "Design"
|
|
552
|
+
},
|
|
553
|
+
require_registries.getPaddingField({
|
|
554
|
+
key: "padding",
|
|
555
|
+
label: "Padding",
|
|
556
|
+
description: "Padding around the calendar container",
|
|
557
|
+
defaultValue: 4,
|
|
558
|
+
tab: "styling",
|
|
559
|
+
group: "Design"
|
|
560
|
+
}),
|
|
561
|
+
require_registries.getBorderRadiusField({
|
|
562
|
+
key: "borderRadius",
|
|
563
|
+
label: "Border Radius",
|
|
564
|
+
description: "Border radius for the calendar container",
|
|
565
|
+
defaultValue: "md",
|
|
566
|
+
tab: "styling",
|
|
567
|
+
group: "Design"
|
|
568
|
+
}),
|
|
569
|
+
{
|
|
570
|
+
key: "showYearEyebrow",
|
|
571
|
+
label: "Year Eyebrow",
|
|
572
|
+
type: "boolean",
|
|
573
|
+
description: "Small uppercase year label above the month (e.g. '2026 / November').",
|
|
574
|
+
defaultValue: true,
|
|
575
|
+
tab: "styling",
|
|
576
|
+
group: "Polish"
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
key: "showTodayButton",
|
|
580
|
+
label: "Today Button",
|
|
581
|
+
type: "boolean",
|
|
582
|
+
description: "Show a 'Today' pill when viewing a different month.",
|
|
583
|
+
defaultValue: true,
|
|
584
|
+
tab: "styling",
|
|
585
|
+
group: "Polish"
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
key: "showEventDensity",
|
|
589
|
+
label: "Event Density Dots",
|
|
590
|
+
type: "boolean",
|
|
591
|
+
description: "Show 1–3 dots per day based on event count (off = single dot).",
|
|
592
|
+
defaultValue: true,
|
|
593
|
+
tab: "styling",
|
|
594
|
+
group: "Polish"
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
key: "weekendDim",
|
|
598
|
+
label: "Dim Weekends",
|
|
599
|
+
type: "boolean",
|
|
600
|
+
description: "Subtly dim the Sun/Sat day-of-week headers for visual rhythm.",
|
|
601
|
+
defaultValue: true,
|
|
602
|
+
tab: "styling",
|
|
603
|
+
group: "Polish"
|
|
604
|
+
}
|
|
605
|
+
]
|
|
606
|
+
};
|
|
607
|
+
//#endregion
|
|
608
|
+
Object.defineProperty(exports, "CalendarWidget", {
|
|
609
|
+
enumerable: true,
|
|
610
|
+
get: function() {
|
|
611
|
+
return CalendarWidget;
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
Object.defineProperty(exports, "CalendarWidget_exports", {
|
|
615
|
+
enumerable: true,
|
|
616
|
+
get: function() {
|
|
617
|
+
return CalendarWidget_exports;
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
Object.defineProperty(exports, "calendarWidgetPropertySchema", {
|
|
621
|
+
enumerable: true,
|
|
622
|
+
get: function() {
|
|
623
|
+
return calendarWidgetPropertySchema;
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
//# sourceMappingURL=CalendarWidget-CmVC7I4i.cjs.map
|