@open-webapp/calendar 0.9.0 → 0.9.1

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.
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useMemo, useRef, useState } from 'react';
2
+ import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
3
3
  import { filterByRsvp, groupByDay, getOrganizerLabel, formatDayHeader, formatRibbonLabel, isEventCurrent, findNextUpcomingEvent, getCalendarEventKey, DEFAULT_RSVP_STATUSES, } from '../core/events.js';
4
4
  import { GroupedCalendarSelector } from './CalendarSelector.js';
5
5
  function toggleRsvpStatus(selection, status) {
@@ -144,6 +144,8 @@ export function CalendarPane(props) {
144
144
  const chipsRef = useRef(null);
145
145
  const scrollRef = useRef(null);
146
146
  const popupRef = useRef(null);
147
+ const anchorSnapshotRef = useRef(null);
148
+ const didMountRsvpRef = useRef(false);
147
149
  const [now, setNow] = useState(() => new Date());
148
150
  const unacceptedCount = useMemo(() => events.filter((event) => event.selfResponseStatus === 'needsAction').length, [events]);
149
151
  const filteredEvents = useMemo(() => filterByRsvp(events, selectedRsvpStatuses), [events, selectedRsvpStatuses]);
@@ -167,6 +169,53 @@ export function CalendarPane(props) {
167
169
  const nextUpcomingEvent = findNextUpcomingEvent(filteredEvents, now);
168
170
  const selectedEventKey = currentEventKeys.values().next().value ??
169
171
  (nextUpcomingEvent ? getCalendarEventKey(nextUpcomingEvent) : undefined);
172
+ function captureAnchorSnapshot() {
173
+ const scrollEl = scrollRef.current;
174
+ if (!scrollEl)
175
+ return;
176
+ const scrollRect = scrollEl.getBoundingClientRect();
177
+ const offsets = new Map();
178
+ let anchor;
179
+ for (const [dateKey, header] of dayHeaderRefs.current) {
180
+ const rect = header.getBoundingClientRect();
181
+ offsets.set(dateKey, rect.top - scrollRect.top);
182
+ if (rect.bottom > scrollRect.top && (anchor === undefined || dateKey < anchor))
183
+ anchor = dateKey;
184
+ }
185
+ anchorSnapshotRef.current = anchor === undefined ? null : { anchor, offsets };
186
+ }
187
+ // Keep the visible date stable when RSVP filtering adds/removes day groups above the viewport.
188
+ useEffect(() => {
189
+ const scrollEl = scrollRef.current;
190
+ if (!scrollEl)
191
+ return;
192
+ const onScroll = () => captureAnchorSnapshot();
193
+ scrollEl.addEventListener('scroll', onScroll, { passive: true });
194
+ return () => scrollEl.removeEventListener('scroll', onScroll);
195
+ // eslint-disable-next-line react-hooks/exhaustive-deps
196
+ }, []);
197
+ useLayoutEffect(() => {
198
+ if (!didMountRsvpRef.current) {
199
+ didMountRsvpRef.current = true;
200
+ return;
201
+ }
202
+ const scrollEl = scrollRef.current;
203
+ const snap = anchorSnapshotRef.current;
204
+ if (!scrollEl || !snap)
205
+ return;
206
+ const keys = Array.from(dayHeaderRefs.current.keys()).sort();
207
+ const target = (dayHeaderRefs.current.has(snap.anchor) ? snap.anchor : undefined) ??
208
+ keys.find((k) => k > snap.anchor && snap.offsets.has(k)) ??
209
+ keys.reverse().find((k) => k < snap.anchor && snap.offsets.has(k));
210
+ const header = target ? dayHeaderRefs.current.get(target) : undefined;
211
+ if (target && header) {
212
+ const delta = header.getBoundingClientRect().top - scrollEl.getBoundingClientRect().top - snap.offsets.get(target);
213
+ if (delta !== 0)
214
+ scrollEl.scrollTop += delta;
215
+ }
216
+ captureAnchorSnapshot();
217
+ // eslint-disable-next-line react-hooks/exhaustive-deps
218
+ }, [selectedRsvpStatuses]);
170
219
  function handleToggle(status) {
171
220
  props.onRsvpStatusesChange(toggleRsvpStatus(selectedRsvpStatuses, status));
172
221
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-webapp/calendar",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",