Skip to content

Commit

Permalink
Merge pull request #106 from bruceharrison1984/fix-hide-behavior
Browse files Browse the repository at this point in the history
Fix hide behavior
  • Loading branch information
bruceharrison1984 authored Jul 30, 2023
2 parents 263324f + 3b0f2d5 commit 68a5cd6
Show file tree
Hide file tree
Showing 16 changed files with 96 additions and 50 deletions.
10 changes: 8 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
module.exports = {
parser: '@typescript-eslint/parser',
extends: ['plugin:react-hooks/recommended','plugin:jsx-a11y/recommended', 'turbo', 'prettier'],
plugins: ['sort-imports-es6-autofix', '@typescript-eslint'],
extends: [
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'turbo',
'prettier',
],
plugins: ['sort-imports-es6-autofix', '@typescript-eslint', 'unused-imports'],
rules: {
'react/jsx-key': 'off',
'sort-imports-es6-autofix/sort-imports-es6': [
Expand All @@ -12,5 +17,6 @@ module.exports = {
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
},
],
'unused-imports/no-unused-imports': 'error',
},
};
2 changes: 1 addition & 1 deletion .husky/pre-push
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# npm run test
npm run test
2 changes: 1 addition & 1 deletion apps/schedulely-docs/components/HomePageSchedulely.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Resizable } from 're-resizable';
import { Schedulely, WeekDay, createDefaultAdapter } from 'schedulely';
import { storyEvents } from './helpers.stories';
import { useEffect, useState } from 'react';
import { useState } from 'react';
import { useTheme } from 'nextra-theme-docs';

const HomepageSchedulely = () => {
Expand Down
33 changes: 32 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"eslint-plugin-react": "^7.33.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-sort-imports-es6-autofix": "^0.6.0",
"eslint-plugin-unused-imports": "^3.0.0",
"husky": "^8.0.3",
"prettier": "^3.0.0",
"turbo": "^1.10.9",
Expand Down
4 changes: 2 additions & 2 deletions packages/Schedulely/__stories__/CalendarTester.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@ export const CalendarStoryTester = (props: PropsWithChildren) => {
changeEvents(events);
}}
>
Add Event
Add Event To Initial Month
</button>
</div>
<div>
<button onClick={clearEvents}>Clear Events</button>
<button onClick={clearEvents}>Clear All Events</button>
</div>
</div>
<hr />
Expand Down
4 changes: 3 additions & 1 deletion packages/Schedulely/__tests__/hooks/useCalendar.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CalendarProvider } from '@/providers';
import { Chance } from 'chance';
import { ComponentSize, DateTimeAdapter } from '@/types';
import { ComponentSize } from '@/types';
import { EventPriority } from '@/types/EventPriority';
import { ReactNode } from 'react';
import { act, renderHook } from '@testing-library/react';
import { createDefaultAdapter } from '@/dateAdapters/date';
Expand Down Expand Up @@ -117,6 +118,7 @@ const wrapper = ({ children }: { children: ReactNode }) => (
dateAdapter={testDateAdapter}
initialDate={testDate.toISOString()}
calendarEvents={[]}
eventPriority={EventPriority.long}
>
{children}
</CalendarProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ let mockIsHighlighted = vi.fn((eventId: string) => false);
let mockEventOnClickHandler = vi.fn(() => {});

let mockSetParentContainerRef = vi.fn((eventId: string) => {});
let mockGetEvent = vi.fn((eventId: string) => {});
let mockEventPriority = vi.fn(() => {});

vi.mock('@/hooks', () => ({
Expand All @@ -65,6 +66,7 @@ vi.mock('@/hooks', () => ({
})),
useEventIntersection: vi.fn(() => ({
setParentContainerRef: mockSetParentContainerRef,
getEvent: mockGetEvent,
})),
useCalendar: vi.fn(() => ({
eventPriority: mockEventPriority,
Expand Down
2 changes: 1 addition & 1 deletion packages/Schedulely/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "schedulely",
"version": "0.3.3",
"version": "0.3.4",
"keywords": [
"schedule",
"calendar",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { HeaderComponent } from '@/types';
import { useCallback } from 'react';

/**
* The default header representation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const EventWeekLayout = ({
const { eventComponent: EventComponent } = useComponents();
const { setHighlight, clearHighlight, isHighlighted } = useEventHighlight();
const { onEventClick } = useActions();
const { setParentContainerRef } = useEventIntersection();
const { setParentContainerRef, getEvent } = useEventIntersection();
const { eventPriority } = useCalendar();

const calculateOrder = (event: InternalCalendarEvent) => {
Expand All @@ -81,7 +81,7 @@ export const EventWeekLayout = ({
data-eventid={event.id}
style={{
gridColumn: getEventPosition(event, daysInweek),
visibility: 'hidden', // start hidden to avoid flashes of events that will be hidden
visibility: getEvent(event.id)?.visible ? undefined : 'hidden', // start hidden to avoid flashes of events that will be hidden
order: calculateOrder(event),
}}
onMouseOver={() => setHighlight(event.id)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const MonthLayout = () => {
className="week-container"
data-week={idx}
>
<EventIntersectionProvider eventsInWeek={events}>
<EventIntersectionProvider eventsInWeek={events} weekNumber={idx}>
<EventWeekLayout eventsInWeek={events} daysInweek={daysInWeek} />
<WeekLayout dates={daysInWeek} />
</EventIntersectionProvider>
Expand Down
2 changes: 1 addition & 1 deletion packages/Schedulely/src/providers/ActionProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ActionContextState } from '@/types';
import { PropsWithChildren, createContext, useCallback } from 'react';
import { PropsWithChildren, createContext } from 'react';

export const ActionContext = createContext<ActionContextState | null>(null);
ActionContext.displayName = 'ActionContext';
Expand Down
3 changes: 2 additions & 1 deletion packages/Schedulely/src/providers/CalendarProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,13 @@ export const CalendarProvider = ({

const calendarWithEvents = useMemo<InternalEventWeek[]>(
() =>
calendarView.map<InternalEventWeek>((week) => ({
calendarView.map<InternalEventWeek>((week, weekNumber) => ({
daysInWeek: week,
events: events
.filter((event) =>
dateAdapter.isEventInWeek(event.start, event.end, week)
)
.map((x) => ({ ...x, weekNumber: weekNumber + 1 }))
.sort(
(x, y) =>
x.end.valueOf() -
Expand Down
71 changes: 36 additions & 35 deletions packages/Schedulely/src/providers/EventIntersectionProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
EventIntersectionState,
InternalCalendarEvent,
InternalEventWeek,
} from '@/types';
import { EventIntersectionState, InternalCalendarEvent } from '@/types';
import {
ReactNode,
createContext,
Expand All @@ -11,7 +7,7 @@ import {
useRef,
useState,
} from 'react';
import { useCalendar } from '@/hooks';
import { useCalendar } from '../hooks/useCalendar';

export const EventIntersectionContext =
createContext<EventIntersectionState | null>(null);
Expand All @@ -26,9 +22,11 @@ EventIntersectionContext.displayName = 'EventIntersectionContext';
export const EventIntersectionProvider = ({
children,
eventsInWeek,
weekNumber,
}: {
children: ReactNode;
eventsInWeek: InternalCalendarEvent[];
weekNumber: number;
}) => {
const {
dateAdapter: { isDateBetween },
Expand All @@ -39,9 +37,19 @@ export const EventIntersectionProvider = ({

const observerRef = useRef<IntersectionObserver | undefined>();

const getEventIntersectionId = useCallback(
(eventId: string) => [eventId, weekNumber].join('-'),
[weekNumber]
);

const [eventVisibility, setEventVisibility] = useState<
Record<string, InternalCalendarEvent>
>(Object.assign({}, ...eventsInWeek.map((x) => ({ [x.id]: x }))));
>(
Object.assign(
{},
...eventsInWeek.map((x) => ({ [getEventIntersectionId(x.id)]: x }))
)
);

const getEventsOnDate = useCallback(
(date: Date) =>
Expand All @@ -52,42 +60,34 @@ export const EventIntersectionProvider = ({
);

/**
* This method checks if an event is fully visible, and if not hides it
* We do this via direct Refs because direct updates are faster and cleaner than relying upon
* React to route the property before and after a render.
*
* This could possibly be done in a more React-y way by splitting this context, but this seems pretty straight-forward as it.
* this controls the event data that is sent back to the DayComponent for retrieving event visibility via getEventsOnDate
*/
const checkIntersection: IntersectionObserverCallback = useCallback(
(entries) =>
entries.map((x) => {
const currentStyle =
x.target
.getAttribute('style')
?.split(';')
.filter((x) => x && !x.includes('visibility')) || [];

if (x.isIntersecting)
x.target.setAttribute('style', currentStyle.join(';'));
else {
currentStyle.push('visibility: hidden');
x.target.setAttribute('style', currentStyle.join(';'));
}

// this controls the event data that is sent back to the DayComponent for event visibility
entries.map(({ target, isIntersecting }) =>
setEventVisibility((current) => {
var eventId = x.target.attributes.getNamedItem('data-eventid')?.value;
if (!eventId) return { ...current };
var eventId = target.attributes.getNamedItem('data-eventid')?.value;

if (!eventId)
throw new Error(
'Event does not have a data-eventid attribute! Did you manually create it?'
);

if (!current[eventId]) {
const matchingEvent = eventsInWeek.find((x) => x.id === eventId)!;
current[eventId] = matchingEvent;
const matchingEvent = eventsInWeek.find(({ id }) => id === eventId);

if (!matchingEvent) {
throw new Error(
`Event ${eventId} not found in event intersection dictionary!`
);
}
current[getEventIntersectionId(eventId)] = matchingEvent;
}
current[eventId].visible = x.isIntersecting;
current[getEventIntersectionId(eventId)].visible = isIntersecting;
return { ...current };
});
}),
[eventsInWeek]
})
),
[eventsInWeek, getEventIntersectionId]
);

useEffect(() => {
Expand All @@ -113,6 +113,7 @@ export const EventIntersectionProvider = ({
const value: EventIntersectionState = {
setParentContainerRef,
getEventsOnDate,
getEvent: (id) => eventVisibility[getEventIntersectionId(id)],
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ export type EventIntersectionState = {

/** Gets an array of events that occur on or span the supplied date. */
getEventsOnDate: (date: Date) => InternalCalendarEvent[];

/** Gets an array of events that occur on or span the supplied date. */
getEvent: (eventId: string) => InternalCalendarEvent;
};

0 comments on commit 68a5cd6

Please sign in to comment.