From 8d1748fcc795cf679e2c128413a8c942efff8eef Mon Sep 17 00:00:00 2001 From: "Markus T." <19794318+marcus-wishes@users.noreply.github.com> Date: Fri, 29 Nov 2024 09:43:36 +0100 Subject: [PATCH 1/4] fixed missing right paddingon select multi value option which is fixed --- library/src/components/inputs/Select.tsx | 1 + showcase/src/components/showcase/wrapper/SelectShowcase.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/library/src/components/inputs/Select.tsx b/library/src/components/inputs/Select.tsx index 27b8c8a7..82c92393 100644 --- a/library/src/components/inputs/Select.tsx +++ b/library/src/components/inputs/Select.tsx @@ -164,6 +164,7 @@ function useClassNamesConfig( provided.isDisabled ? "bg-disabled text-disabled-text" : undefined, + provided.data.isFixed ? "pr-1" : undefined, ), "text-ellipsis whitespace-nowrap", classNamesConfig?.multiValue?.(provided), diff --git a/showcase/src/components/showcase/wrapper/SelectShowcase.tsx b/showcase/src/components/showcase/wrapper/SelectShowcase.tsx index 60dc2693..443c6fc4 100644 --- a/showcase/src/components/showcase/wrapper/SelectShowcase.tsx +++ b/showcase/src/components/showcase/wrapper/SelectShowcase.tsx @@ -298,7 +298,7 @@ function SelectShowcase(props: ShowcaseProps) { }} isMulti options={options} - value={options[4]} + defaultValue={options[4]} /** adding some custom classnames to the styling */ classNames={{ control: () => "bg-warning", From 144cfd5fe9fe70ecd89893f21df7eef9cb6232ab Mon Sep 17 00:00:00 2001 From: "Markus T." <19794318+marcus-wishes@users.noreply.github.com> Date: Fri, 29 Nov 2024 09:56:10 +0100 Subject: [PATCH 2/4] loading button - fixed height of loading spinner --- library/src/components/Button.tsx | 39 ++++++++++++------- .../src/components/timetable/TimeTable.tsx | 2 + .../components/timetable/TimeTableRows.tsx | 13 ++++--- library/src/components/timetable/index.ts | 3 ++ showcase/public/showcase-sources.txt | 14 +++++++ .../showcase/wrapper/ButtonShowcase.tsx | 1 + .../showcase/wrapper/TimeTableShowcase.tsx | 28 +++++++++++-- 7 files changed, 79 insertions(+), 21 deletions(-) diff --git a/library/src/components/Button.tsx b/library/src/components/Button.tsx index 06dc8f2b..3cd0bfa6 100644 --- a/library/src/components/Button.tsx +++ b/library/src/components/Button.tsx @@ -1,5 +1,11 @@ import type React from "react" -import { type CSSProperties, forwardRef, type HTMLProps, useMemo } from "react" +import { + type CSSProperties, + forwardRef, + type HTMLProps, + useMemo, + useRef, +} from "react" import { twJoin, twMerge } from "tailwind-merge" import { LoadingSpinner } from "./LoadingSpinner" @@ -204,6 +210,10 @@ export const LoadingButton = ({ loadingSpinnerClassName, ...props }: ButtonProps & { loading: boolean; loadingSpinnerClassName?: string }) => { + const ref = useRef(null) + + const height = ref.current?.clientHeight ?? 0 + return ( ) } diff --git a/library/src/components/timetable/TimeTable.tsx b/library/src/components/timetable/TimeTable.tsx index c53785b6..37447f3c 100644 --- a/library/src/components/timetable/TimeTable.tsx +++ b/library/src/components/timetable/TimeTable.tsx @@ -205,6 +205,8 @@ const nowbarUpdateIntervall = 1000 * 60 // 1 minute * Each column in the table is actually 2 columns. 1 fixed size one, and 1 dynamic sized on. Like that I can simulate min-width on the columns, which else is not allowed. * * The index exports a memoized version of the LPTimeTable, which is used by the parent component. + * + * @emits allGroupsRendered (exported, string: timetable-allgroupsrendered) - when all groups are rendered */ export default function LPTimeTable< G extends TimeTableGroup, diff --git a/library/src/components/timetable/TimeTableRows.tsx b/library/src/components/timetable/TimeTableRows.tsx index 17e39721..91cc869d 100644 --- a/library/src/components/timetable/TimeTableRows.tsx +++ b/library/src/components/timetable/TimeTableRows.tsx @@ -43,6 +43,8 @@ import type { ItemRowEntry } from "./useGoupRows" import { getLeftAndWidth } from "./timeTableUtils" import { useDebounceHelper, useIdleRateLimitHelper } from "../../utils" +export const allGroupsRenderedEvent = "timetable-allgroupsrendered" as const + interface TimeTableRowsProps< G extends TimeTableGroup, I extends TimeSlotBooking, @@ -464,13 +466,14 @@ export default function TimeTableRows< if (groupRowsRenderedIdx < entries.length) { rateLimiterRendering(renderBatch) } else { - console.info( - "TimeTable - all group rows rendered", - groupRowsRenderedIdx, - entries.length, - ) if (!allPlaceholderRendered.current) { + console.info( + "TimeTable - all group rows rendered", + groupRowsRenderedIdx, + entries.length, + ) allPlaceholderRendered.current = true + window.dispatchEvent(new Event(allGroupsRenderedEvent)) // we need to render all placeholders rateLimiterIntersection(handleIntersections) } diff --git a/library/src/components/timetable/index.ts b/library/src/components/timetable/index.ts index 972b0fbf..9fdcc943 100644 --- a/library/src/components/timetable/index.ts +++ b/library/src/components/timetable/index.ts @@ -60,3 +60,6 @@ export namespace TimeTableTypes { I extends TimeSlotBooking, > = LPTimeTableProps } + +/** Evnts */ +export { allGroupsRenderedEvent } from "./TimeTableRows" diff --git a/showcase/public/showcase-sources.txt b/showcase/public/showcase-sources.txt index ac3d43b6..2b1ad266 100644 --- a/showcase/public/showcase-sources.txt +++ b/showcase/public/showcase-sources.txt @@ -7689,6 +7689,7 @@ import ChevronDownIcon from "@atlaskit/icon/glyph/chevron-down" import { useTranslation } from "@linked-planet/ui-kit-ts/localization/LocaleContext" import type { TranslatedTimeTableMessages } from "@linked-planet/ui-kit-ts/components/timetable/TimeTableMessageContext" import type { TimeTableTypes } from "@linked-planet/ui-kit-ts/components/timetable" +import { allGroupsRenderedEvent } from "@linked-planet/ui-kit-ts/components/timetable/TimeTableRows" //import "@linked-planet/ui-kit-ts/dist/style.css" //-> this is not necessary in this setup, but in the real library usage @@ -8191,6 +8192,10 @@ function CustomHeaderRowHeader< ) } +window.addEventListener(allGroupsRenderedEvent, () => { + console.info("All groups rendered") +}) + function Example() { //#region timetable @@ -8582,6 +8587,15 @@ function Example() { > Create New Item +
} iconAfter={} + className="h-6" > Icon Loading Button diff --git a/showcase/src/components/showcase/wrapper/TimeTableShowcase.tsx b/showcase/src/components/showcase/wrapper/TimeTableShowcase.tsx index aef127ee..fac899fa 100644 --- a/showcase/src/components/showcase/wrapper/TimeTableShowcase.tsx +++ b/showcase/src/components/showcase/wrapper/TimeTableShowcase.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo } from "react" +import { useCallback, useMemo } from "react" import { useState } from "react" import dayjs, { type Dayjs } from "dayjs" import ShowcaseWrapperItem, { @@ -15,6 +15,7 @@ import ChevronDownIcon from "@atlaskit/icon/glyph/chevron-down" import { useTranslation } from "@linked-planet/ui-kit-ts/localization/LocaleContext" import type { TranslatedTimeTableMessages } from "@linked-planet/ui-kit-ts/components/timetable/TimeTableMessageContext" import type { TimeTableTypes } from "@linked-planet/ui-kit-ts/components/timetable" +import { allGroupsRenderedEvent } from "@linked-planet/ui-kit-ts/components/timetable/TimeTableRows" //import "@linked-planet/ui-kit-ts/dist/style.css" //-> this is not necessary in this setup, but in the real library usage @@ -435,6 +436,9 @@ function TestCustomHeaderRowTimeSlot< entries, tableCellRef, }: TimeTableTypes.CustomHeaderRowTimeSlotProps) { + if (!entries || !entries[1]) { + return null + } const groupItems = entries[1].items if (!groupItems.length) { return null @@ -510,6 +514,9 @@ function CustomHeaderRowHeader< viewType, entries, }: TimeTableTypes.CustomHeaderRowHeaderProps) { + if (!entries || !entries[1]) { + return <> + } return (
{entries[1].group.title} has {entries.length} entries @@ -517,6 +524,10 @@ function CustomHeaderRowHeader< ) } +window.addEventListener(allGroupsRenderedEvent, () => { + console.info("All groups rendered") +}) + function Example() { //#region timetable @@ -652,7 +663,7 @@ function Example() { [], ) - useEffect(() => { + /*useEffect(() => { requestMoreEntriesCB() requestMoreEntriesCB() requestMoreEntriesCB() @@ -685,7 +696,9 @@ function Example() { requestMoreEntriesCB() requestMoreEntriesCB() requestMoreEntriesCB() - }, [requestMoreEntriesCB]) + }, [requestMoreEntriesCB])*/ + + console.log("ENTRIES", entries) return ( <> @@ -908,6 +921,15 @@ function Example() { > Create New Item +
Date: Sat, 30 Nov 2024 18:41:51 +0100 Subject: [PATCH 3/4] time table - fixed logical error of handling all month and years as same length --- .../src/components/timetable/TimeTable.tsx | 52 ++-- .../timetable/TimeTableConfigStore.ts | 18 +- .../components/timetable/TimeTableHeader.tsx | 8 +- .../components/timetable/TimeTableRows.tsx | 58 +++-- .../timetable/TimeTableSelectionStore.ts | 16 +- .../components/timetable/timeTableUtils.ts | 146 +++++++---- .../src/components/timetable/useGoupRows.ts | 18 +- package-lock.json | 230 +++++++++--------- package.json | 6 +- showcase/public/showcase-sources.txt | 37 ++- .../showcase/wrapper/TimeTableShowcase.tsx | 20 +- 11 files changed, 347 insertions(+), 262 deletions(-) diff --git a/library/src/components/timetable/TimeTable.tsx b/library/src/components/timetable/TimeTable.tsx index 37447f3c..c89dbdee 100644 --- a/library/src/components/timetable/TimeTable.tsx +++ b/library/src/components/timetable/TimeTable.tsx @@ -36,7 +36,7 @@ import { } from "./TimeTableSelectionStore" import { useGroupRows } from "./useGoupRows" import { twMerge } from "tailwind-merge" -import { getStartAndEndSlot } from "./timeTableUtils" +import { getStartAndEndSlot, getTimeSlotMinutes } from "./timeTableUtils" import { flushSync } from "react-dom" export interface TimeSlotBooking { @@ -272,7 +272,7 @@ const LPTimeTableImpl = ({ // biome-ignore lint/correctness/useExhaustiveDependencies: just remove the message is props change useEffect(() => { setMessage?.(undefined) // clear the message on time frame change - }, [viewType, startDate, endDate, setMessage, timeStepsMinutes]) + }, [startDate, endDate, setMessage, timeStepsMinutes]) const tableRef = useRef(null) const tableHeaderRef = useRef(null) @@ -318,7 +318,7 @@ const LPTimeTableImpl = ({ itemsWithSameStartAndEnd, slotsArray, timeFrameDay, - timeSlotMinutes, + viewType: currViewType, } = useGroupRows(entries) if (!slotsArray || slotsArray.length === 0) { @@ -403,18 +403,10 @@ const LPTimeTableImpl = ({ tableHeaderRef, tableBodyRef, timeFrameDay, - timeSlotMinutes, - viewType, + currViewType, setMessage, ) - }, [ - slotsArray, - nowOverwrite, - timeFrameDay, - timeSlotMinutes, - viewType, - setMessage, - ]) + }, [slotsArray, nowOverwrite, timeFrameDay, currViewType, setMessage]) // initial run, and start interval to move the now bar useEffect(() => { @@ -441,11 +433,10 @@ const LPTimeTableImpl = ({ tableHeaderRef, tableBodyRef, timeFrameDay, - timeSlotMinutes, - viewType, + currViewType, setMessage, ) - }, [setMessage, slotsArray, timeFrameDay, timeSlotMinutes, viewType]) + }, [setMessage, slotsArray, timeFrameDay, currViewType]) useResizeObserver({ ref: tableBodyRef, @@ -509,12 +500,11 @@ const LPTimeTableImpl = ({ > slotsArray={slotsArray} - timeSlotMinutes={timeSlotMinutes} columnWidth={columnWidth} groupHeaderColumnWidth={groupHeaderColumnWidth} startDate={startDate} endDate={endDate} - viewType={viewType} + viewType={currViewType} timeFrameDay={timeFrameDay} showTimeSlotHeader={ showTimeSlotHeader === undefined || @@ -541,9 +531,8 @@ const LPTimeTableImpl = ({ } headerRef={tableHeaderRef} slotsArray={slotsArray} - timeSlotMinutes={timeSlotMinutes} timeFrameDay={timeFrameDay} - viewType={viewType} + viewType={currViewType} /> @@ -570,7 +559,6 @@ function moveNowBar( tableHeaderRef: MutableRefObject, tableBodyRef: MutableRefObject, timeFrameDay: TimeFrameDay, - timeSlotMinutes: number, viewType: TimeTableViewType, setMessage?: (message: TimeTableMessage) => void, ) { @@ -625,7 +613,6 @@ function moveNowBar( nowItem, slotsArray, timeFrameDay, - timeSlotMinutes, viewType, ) if (startAndEndSlot.status !== "in") { @@ -686,19 +673,13 @@ function moveNowBar( nowBarRef.current = nowBar } - let currentTimeSlot = slotsArray[startSlot] - if (viewType !== "hours") { - currentTimeSlot = currentTimeSlot - .add(timeFrameDay.startHour, "hour") - .add(timeFrameDay.startMinute, "minute") - } - - const diffNowDays = now.diff(currentTimeSlot, "days") - let diffNow = now.diff(currentTimeSlot, "minutes") - if (diffNowDays > 0) { - const dDay = 24 * 60 - timeFrameDay.oneDayMinutes - diffNow = diffNow - dDay * diffNowDays - } + const currentTimeSlot = slotsArray[startSlot] + const timeSlotMinutes = getTimeSlotMinutes( + currentTimeSlot, + timeFrameDay, + viewType, + ) + const diffNow = now.diff(currentTimeSlot, "minutes") const diffPerc = diffNow / timeSlotMinutes nowBar.style.left = `${diffPerc * 100}%` @@ -729,6 +710,7 @@ function moveNowBar( console.error("unable to find header date row") return } + const headerDateCells = headerDateRow.children for (const headerDateCell of headerDateCells) { headerDateCell.classList.remove("text-text-subtle") diff --git a/library/src/components/timetable/TimeTableConfigStore.ts b/library/src/components/timetable/TimeTableConfigStore.ts index 8b993534..257d7afd 100644 --- a/library/src/components/timetable/TimeTableConfigStore.ts +++ b/library/src/components/timetable/TimeTableConfigStore.ts @@ -8,9 +8,8 @@ export type TimeTableConfig = { basicProperties: { timeFrameDay: TimeFrameDay slotsArray: readonly Dayjs[] - timeSlotMinutes: number // length of 1 slot in minutes (for example if the day starts at 8, and ends at 16, and the time slot is a week, that this means (16-8)*60*7 minutes) + viewType: TimeTableViewType } - viewType: TimeTableViewType disableWeekendInteractions: boolean hideOutOfRangeMarkers: boolean timeSlotSelectionDisabled: boolean @@ -73,7 +72,6 @@ export function initAndUpdateTimeTableConfigStore( timeTableConfigStore[ident] = proxy>({ basicProperties, - viewType, propTimeSlotMinutes, @@ -107,7 +105,7 @@ export function initAndUpdateTimeTableConfigStore( timeTableConfigStore[ident].endDate !== endDateString || timeTableConfigStore[ident].propTimeSlotMinutes !== propTimeSlotMinutes || - timeTableConfigStore[ident].viewType !== viewType + timeTableConfigStore[ident].basicProperties.viewType !== viewType ) { const basicProperties = calculateTimeSlotPropertiesForView( startDate, @@ -134,7 +132,7 @@ export function initAndUpdateTimeTableConfigStore( timeTableConfigStore[ident].propTimeSlotMinutes !== propTimeSlotMinutes, "view type updated", - timeTableConfigStore[ident].viewType !== viewType, + timeTableConfigStore[ident].basicProperties.viewType !== viewType, ) clearTimeSlotSelection(ident, true) @@ -156,12 +154,10 @@ export function initAndUpdateTimeTableConfigStore( }*/ timeTableConfigStore[ident].basicProperties = basicProperties - timeTableConfigStore[ident].viewType = viewType timeTableConfigStore[ident].propTimeSlotMinutes = propTimeSlotMinutes timeTableConfigStore[ident].startDate = startDateString timeTableConfigStore[ident].endDate = endDateString timeTableConfigStore[ident].propTimeSlotMinutes = propTimeSlotMinutes - timeTableConfigStore[ident].viewType = viewType } if (isCellDisabled !== timeTableConfigStore[ident].isCellDisabled) { @@ -246,14 +242,6 @@ export function useTTCTimeSlotSelectionDisabled(ident: string) { return timeSlotSelectionDisabled } -/** - * returns the view type and a setter for it - */ -export function useTTCViewType(ident: string) { - const viewType = useSnapshot(timeTableConfigStore[ident]).viewType - return viewType -} - //#endregion //#region utilities diff --git a/library/src/components/timetable/TimeTableHeader.tsx b/library/src/components/timetable/TimeTableHeader.tsx index 1c358916..1c305525 100644 --- a/library/src/components/timetable/TimeTableHeader.tsx +++ b/library/src/components/timetable/TimeTableHeader.tsx @@ -23,6 +23,7 @@ import type { } from "./TimeTable" import type { TimeFrameDay } from "./TimeTableConfigStore" import useResizeObserver, { type ObservedSize } from "use-resize-observer" +import { getTimeSlotMinutes } from "./timeTableUtils" const headerTimeSlotFormat: { [viewType in TimeTableViewType]: string } = { hours: "HH:mm", @@ -88,7 +89,6 @@ type TimeTableHeaderProps< I extends TimeSlotBooking, > = { slotsArray: readonly Dayjs[] - timeSlotMinutes: number groupHeaderColumnWidth: number | string columnWidth: number | string startDate: Dayjs @@ -120,7 +120,6 @@ export const LPTimeTableHeader = function TimeTableHeader< I extends TimeSlotBooking, >({ slotsArray, - timeSlotMinutes, groupHeaderColumnWidth, columnWidth, startDate, @@ -311,6 +310,11 @@ export const LPTimeTableHeader = function TimeTableHeader< const isLastOfDay = i === slotsArray.length - 1 || !slotsArray[i + 1].isSame(slot, "day") + const timeSlotMinutes = getTimeSlotMinutes( + slotsArray[i], + timeFrameDay, + viewType, + ) return ( ) { const storeIdent = useTimeTableIdent() @@ -109,7 +107,6 @@ export default function TimeTableRows< const groupRowsRendered = useRef(new Array(entries.length)) const slotsArrayCurrent = useRef(slotsArray) - const timeSlotMinutesCurrent = useRef(timeSlotMinutes) const viewTypeCurrent = useRef(viewType) const timeFrameDayCurrent = useRef(timeFrameDay) @@ -123,14 +120,12 @@ export default function TimeTableRows< if ( slotsArrayCurrent.current !== slotsArray || - timeSlotMinutesCurrent.current !== timeSlotMinutes || viewTypeCurrent.current !== viewType || timeFrameDayCurrent.current !== timeFrameDay ) { // reset the rendered cells renderedCells.current.clear() slotsArrayCurrent.current = slotsArray - timeSlotMinutesCurrent.current = timeSlotMinutes viewTypeCurrent.current = viewType timeFrameDayCurrent.current = timeFrameDay setGroupRowsRenderedIdx(0) @@ -239,6 +234,7 @@ export default function TimeTableRows< console.info("TimeTable - all group rows updated") return } + // determine when new ones start let newOne = -1 const keys = Object.keys(currentGroupRows) @@ -278,8 +274,8 @@ export default function TimeTableRows< return ret }) currentGroupRows.current = groupRows - //rateLimiterRendering(() => window.setTimeout(renderBatch, 0)) - }, [groupRows]) + rateLimiterRendering(renderBatch) + }, [groupRows, rateLimiterRendering]) //useEffect(handleIntersections, []) // handle intersection observer, create new observer if the intersectionContainerRef changes @@ -325,6 +321,26 @@ export default function TimeTableRows< let start = groupRowsRenderedIdx + // removal of too many rendered elements + for ( + let g = entries.length; + g < groupRowsRendered.current.length; + g++ + ) { + if (groupRowsRendered.current[g]) { + console.log("REMOVING ", g, groupRowsRendered.current) + delete groupRowsRendered.current[g] + delete refCollection.current[g] + renderedCells.current.delete(g) + if (renderCells.current[0] >= g) { + renderCells.current[0] = g - 2 > 0 ? g - 2 : 0 + } + if (renderCells.current[1] >= g) { + renderCells.current[1] = g - 1 > 0 ? g - 1 : 0 + } + } + } + // get the group entries which required rendering let startRender = -1 for ( @@ -373,7 +389,7 @@ export default function TimeTableRows< end = groupRowKeys.length } - for (let g = start; g < end && g < groupRowKeys.length; g++) { + for (let g = start; g < end; g++) { const groupEntry = entries[g] if (!groupEntry) { console.warn( @@ -419,7 +435,6 @@ export default function TimeTableRows< mref={mref} slotsArray={slotsArray} timeFrameDay={timeFrameDay} - timeSlotsMinutes={timeSlotMinutes} viewType={viewType} /> ) @@ -455,7 +470,6 @@ export default function TimeTableRows< placeHolderHeight, slotsArray, timeFrameDay, - timeSlotMinutes, viewType, ]) @@ -478,7 +492,6 @@ export default function TimeTableRows< rateLimiterIntersection(handleIntersections) } } - return groupRowsRendered.current } @@ -633,6 +646,7 @@ function TableCell({ currentLeft, slotsArray, bookingItemsBeginningInCell, + width, ) } @@ -857,7 +871,6 @@ type GroupRowsProps = { mref: React.MutableRefObject slotsArray: readonly Dayjs[] timeFrameDay: TimeFrameDay - timeSlotsMinutes: number viewType: TimeTableViewType } @@ -874,7 +887,6 @@ function GroupRows({ placeHolderHeight, slotsArray, timeFrameDay, - timeSlotsMinutes, viewType, mref, }: GroupRowsProps) { @@ -974,17 +986,22 @@ function GroupRows({ timeSlotNumber < slotsArray.length; timeSlotNumber++ ) { + const timeSlotMinutes = getTimeSlotMinutes( + slotsArray[timeSlotNumber], + timeFrameDay, + viewType, + ) tds.push( key={timeSlotNumber} group={group} groupNumber={groupNumber} timeSlotNumber={timeSlotNumber} - timeSlotMinutes={timeSlotsMinutes} viewType={viewType} slotsArray={slotsArray} selectedTimeSlots={selectedTimeSlots ?? undefined} placeHolderHeight={placeHolderHeight} + timeSlotMinutes={timeSlotMinutes} />, ) } @@ -994,11 +1011,11 @@ function GroupRows({ groupNumber, timeSlotSelectionDisabled, slotsArray, - timeSlotsMinutes, viewType, selectedTimeSlots, renderCells, placeHolderHeight, + timeFrameDay, ]) const normalRows = useMemo(() => { @@ -1022,6 +1039,12 @@ function GroupRows({ ) : undefined + const timeSlotMinutes = getTimeSlotMinutes( + slotsArray[timeSlotNumber], + timeFrameDay, + viewType, + ) + tds.push( key={`${groupNumber}-${timeSlotNumber}-${viewType}`} @@ -1036,7 +1059,7 @@ function GroupRows({ slotsArray={slotsArray} timeFrameDay={timeFrameDay} viewType={viewType} - timeSlotMinutes={timeSlotsMinutes} + timeSlotMinutes={timeSlotMinutes} />, ) } @@ -1055,7 +1078,6 @@ function GroupRows({ selectedTimeSlotItem, onTimeSlotItemClick, renderCells, - timeSlotsMinutes, ]) if (!renderCells) { diff --git a/library/src/components/timetable/TimeTableSelectionStore.ts b/library/src/components/timetable/TimeTableSelectionStore.ts index b78349c9..d17d9b9c 100644 --- a/library/src/components/timetable/TimeTableSelectionStore.ts +++ b/library/src/components/timetable/TimeTableSelectionStore.ts @@ -2,6 +2,7 @@ import { proxy, snapshot, useSnapshot } from "valtio" import type { TimeTableGroup } from "./TimeTable" import { getTTCBasicProperties } from "./TimeTableConfigStore" import type { Dayjs } from "dayjs" +import { getTimeSlotMinutes } from "./timeTableUtils" export type onTimeRangeSelectedType = | React.Dispatch< @@ -154,7 +155,6 @@ function setTimeSlotSelectionByDateRange( const basicConfig = getTTCBasicProperties(ident) const slotsArray = basicConfig.slotsArray - const timeSlotMinutes = basicConfig.timeSlotMinutes // find the time range in the slots array const newSlots: number[] = [] @@ -163,6 +163,13 @@ function setTimeSlotSelectionByDateRange( if (!newSlots.length && slot.isSame(startDate)) { newSlots.push(i) } + + const timeSlotMinutes = getTimeSlotMinutes( + slot, + basicConfig.timeFrameDay, + basicConfig.viewType, + ) + const slotEnd = slot.add(timeSlotMinutes, "minutes") if ( newSlots.length && @@ -363,8 +370,13 @@ function notifyOnTimeRangeSelected( const basicProps = getTTCBasicProperties(ident) const startDate = basicProps.slotsArray[firstSlot] + const timeSlotMinutes = getTimeSlotMinutes( + basicProps.slotsArray[lastSlot], + basicProps.timeFrameDay, + basicProps.viewType, + ) const endDate = basicProps.slotsArray[lastSlot].add( - basicProps.timeSlotMinutes, + timeSlotMinutes, "minutes", ) store.onTimeRangeSelected({ group, startDate, endDate }) diff --git a/library/src/components/timetable/timeTableUtils.ts b/library/src/components/timetable/timeTableUtils.ts index 0d4765c0..097b363a 100644 --- a/library/src/components/timetable/timeTableUtils.ts +++ b/library/src/components/timetable/timeTableUtils.ts @@ -4,6 +4,7 @@ dayjs.extend(isoWeek) import type { TimeSlotBooking, TimeTableViewType } from "./TimeTable" import type { TimeTableMessage } from "./TimeTableMessageContext" import type { TimeFrameDay } from "./TimeTableConfigStore" +import { assertUnreachable } from "../../utils/assertUnreachable" export function isOverlapping( item: TimeSlotBooking, @@ -210,7 +211,7 @@ export function calculateTimeSlotPropertiesForView( ): { timeFrameDay: TimeFrameDay slotsArray: Dayjs[] - timeSlotMinutes: number + viewType: TimeTableViewType } { const startHour = startDate.hour() const startMinute = startDate.minute() @@ -236,7 +237,7 @@ export function calculateTimeSlotPropertiesForView( oneDayMinutes: 0, }, slotsArray: [], - timeSlotMinutes: 0, + viewType, } } @@ -247,7 +248,7 @@ export function calculateTimeSlotPropertiesForView( timeStepsMinute, setMessage, ) - return Object.freeze(res) + return Object.freeze({ ...res, viewType }) } // get the actual end time fitting to the time slots @@ -329,12 +330,27 @@ export function calculateTimeSlotPropertiesForView( .startOf("day") .add(1, unit) .diff(dayjs().startOf("day"), "days") - const timeSlotMinutes = unitDays * oneDayMinutes + //const timeSlotMinutes = unitDays * oneDayMinutes + let timeSlotMinutes = timeStepsMinute + switch (viewType) { + case "days": { + timeSlotMinutes = oneDayMinutes + break + } + case "weeks": { + timeSlotMinutes = 6 * 24 * 60 + oneDayMinutes + break + } + case "months": { + timeSlotMinutes = 29 * 24 * 60 + oneDayMinutes + break + } + } return Object.freeze({ timeFrameDay, slotsArray, - timeSlotMinutes, + viewType, }) } @@ -345,6 +361,8 @@ export function calculateTimeSlotPropertiesForView( * @param endSlot * @param slotsArray * @param timeSteps + * @param timeFrameDay + * @param viewType */ export function getLeftAndWidth( item: TimeSlotBooking, @@ -353,7 +371,6 @@ export function getLeftAndWidth( slotsArray: readonly Dayjs[], timeFrameDay: TimeFrameDay, viewType: TimeTableViewType, - timeSlotMinutes: number, ) { let itemModStart = item.startDate const timeFrameStartStart = slotsArray[0] @@ -391,20 +408,22 @@ export function getLeftAndWidth( ) itemModEnd = itemModStart } else { - let timeFrameEndEnd = slotsArray[slotsArray.length - 1].add( + const timeSlotMinutes = getTimeSlotMinutes( + slotsArray[slotsArray.length - 1], + timeFrameDay, + viewType, + ) + const timeFrameEndEnd = slotsArray[slotsArray.length - 1].add( timeSlotMinutes, "minutes", ) - if (viewType !== "hours") { - timeFrameEndEnd = timeFrameEndEnd - .add(1, viewType) - .subtract(1, "day") - } + if (itemModEnd.isAfter(timeFrameEndEnd)) { itemModEnd = timeFrameEndEnd } else if (item.endDate.hour() === 0 && item.endDate.minute() === 0) { - //itemModEnd = itemModEnd.subtract(1, "minute") - itemModEnd = timeFrameEndEnd + //itemModEnd = itemModEnd.subtract(1, "second") // this is a hack to make the end time of the day inclusive + //console.log("HACK APPLIED", itemModEnd) + //itemModEnd = timeFrameEndEnd //.startOf("day") //.add(timeFrameDay.endHour, "hour") //.add(timeFrameDay.endMinute, "minutes") @@ -414,6 +433,7 @@ export function getLeftAndWidth( item.endDate.minute() > timeFrameDay.endMinute) ) { if (timeFrameDay.endHour !== 0 && timeFrameDay.endMinute !== 0) { + console.log("WARG", item, itemModEnd, timeFrameDay) itemModEnd = itemModEnd .startOf("day") .add(timeFrameDay.endHour, "hour") @@ -422,19 +442,14 @@ export function getLeftAndWidth( } } - const dTimeDay = 24 * 60 - timeFrameDay.oneDayMinutes + const slotStart = slotsArray[startSlot] + const timeSlotMinutes = getTimeSlotMinutes( + slotStart, + timeFrameDay, + viewType, + ) - let slotStart = slotsArray[startSlot] - if (viewType !== "hours") { - slotStart = slotStart - .add(timeFrameDay.startHour, "hour") - .add(timeFrameDay.startMinute, "minutes") - } - const dstartDays = itemModStart.diff(slotStart, "day") - let dstartMin = itemModStart.diff(slotStart, "minute") - if (dstartDays > 0) { - dstartMin -= dstartDays * dTimeDay - } + const dstartMin = itemModStart.diff(slotStart, "minute") let left = dstartMin / timeSlotMinutes if (left < 0) { console.error( @@ -450,11 +465,7 @@ export function getLeftAndWidth( left = 0 } - const timeSpanDays = itemModEnd.diff(itemModStart, "day") - let timeSpanMin = itemModEnd.diff(itemModStart, "minute") - if (timeSpanDays > 0) { - timeSpanMin -= timeSpanDays * dTimeDay - } + const timeSpanMin = itemModEnd.diff(itemModStart, "minute") const width = timeSpanMin / timeSlotMinutes /*let dmin = itemModEnd.diff(slotsArray[endSlot], "minute") @@ -486,8 +497,6 @@ export function getLeftAndWidth( slotsArray, timeSlotMinutes, timeSpanMin, - timeSpanDays, - dTimeDay, itemModStart, itemModEnd, ) @@ -506,7 +515,6 @@ export function getStartAndEndSlot( item: TimeSlotBooking, slotsArray: readonly Dayjs[], timeFrameDay: TimeFrameDay, - timeSlotMinutes: number, viewType: TimeTableViewType, ): { startSlot: number @@ -519,16 +527,36 @@ export function getStartAndEndSlot( .add(timeFrameDay.startHour, "hours") .add(timeFrameDay.startMinute, "minutes") } - let timeFrameEnd = slotsArray[slotsArray.length - 1].add( - timeSlotMinutes, - "minutes", - ) - //.startOf("day") - //.add(timeFrameDay.endHour, "hours") - //.add(timeFrameDay.endMinute, "minutes") - if (viewType !== "hours") { - timeFrameEnd = timeFrameEnd.add(1, viewType).subtract(1, "day") + let timeFrameEnd = slotsArray[slotsArray.length - 1] + switch (viewType) { + case "hours": + timeFrameEnd = timeFrameEnd.add(1, "hour") + break + case "days": + timeFrameEnd = timeFrameEnd.add( + timeFrameDay.oneDayMinutes, + "minutes", + ) + break + case "weeks": + timeFrameEnd = timeFrameEnd + .add(6, "days") + .add(timeFrameDay.oneDayMinutes, "minutes") + break + case "months": + timeFrameEnd = timeFrameEnd + .add(1, "month") + .subtract(1, "day") + .add(timeFrameDay.oneDayMinutes, "minutes") + break + case "years": + timeFrameEnd = timeFrameEnd + .add(1, "year") + .subtract(1, "day") + .add(timeFrameDay.oneDayMinutes, "minutes") + break } + if ( item.endDate.isBefore(timeFrameStart) || item.endDate.isSame(timeFrameStart) @@ -605,7 +633,7 @@ export function getStartAndEndSlot( let endSlotEnd = slotsArray[endSlot] if (viewType === "hours") { - endSlotEnd = endSlotEnd.add(timeSlotMinutes, "minutes") + endSlotEnd = endSlotEnd.add(60, "minutes") } else { endSlotEnd = endSlotEnd .add(timeFrameDay.endHour, "hours") @@ -619,3 +647,33 @@ export function getStartAndEndSlot( return { startSlot, endSlot, status: "in" } } + +export function getTimeSlotMinutes( + slotStart: Dayjs, + timeFrameDay: TimeFrameDay, + viewType: TimeTableViewType, +) { + switch (viewType) { + case "hours": + return 60 + case "days": + return timeFrameDay.oneDayMinutes + case "weeks": + return 6 * 24 * 60 + timeFrameDay.oneDayMinutes + case "months": + return slotStart + .add(1, "month") + .subtract(1, "day") + .add(timeFrameDay.oneDayMinutes, "minutes") + .diff(slotStart, "minutes") + case "years": + return slotStart + .add(1, "year") + .subtract(1, "day") + .add(timeFrameDay.oneDayMinutes, "minutes") + .diff(slotStart, "minutes") + + default: + assertUnreachable(viewType) + } +} diff --git a/library/src/components/timetable/useGoupRows.ts b/library/src/components/timetable/useGoupRows.ts index d37a8fe5..f31548c7 100644 --- a/library/src/components/timetable/useGoupRows.ts +++ b/library/src/components/timetable/useGoupRows.ts @@ -8,7 +8,6 @@ import type { import { getTTCBasicProperties, type TimeFrameDay, - useTTCViewType, } from "./TimeTableConfigStore" import { useTimeTableIdent } from "./TimeTableIdentContext" import { getStartAndEndSlot, isOverlapping } from "./timeTableUtils" @@ -31,9 +30,8 @@ export function useGroupRows< I extends TimeSlotBooking, >(entries: TimeTableEntry[]) { const storeIdent = useTimeTableIdent() - const { timeFrameDay, slotsArray, timeSlotMinutes } = + const { timeFrameDay, slotsArray, viewType } = getTTCBasicProperties(storeIdent) - const viewType = useTTCViewType(storeIdent) const currentEntries = useRef[]>() @@ -49,7 +47,7 @@ export function useGroupRows< const currentTimeSlots = useRef(slotsArray) const currentTimeFrameDay = useRef(timeFrameDay) - const currentTimeSlotMinutes = useRef(timeSlotMinutes) + const currentViewType = useRef(viewType) const [calcBatch, setCalcBatch] = useState(-1) @@ -57,7 +55,8 @@ export function useGroupRows< const requireNewGroupRows = currentTimeSlots.current !== slotsArray || currentTimeFrameDay.current !== timeFrameDay || - currentTimeSlotMinutes.current !== timeSlotMinutes + currentViewType.current !== viewType || + currentEntries.current !== entries const clearGroupRows = useCallback(() => { groupRowsState.current = {} @@ -140,7 +139,6 @@ export function useGroupRows< entry.items, slotsArray, timeFrameDay, - timeSlotMinutes, viewType, ) @@ -182,7 +180,7 @@ export function useGroupRows< groupRowsState.current = updatedGroupRows // we need to rerender the component to update the group rows setCalcBatch((prev) => (prev > 10 ? prev - 1 : prev + 1)) - }, [slotsArray, timeFrameDay, timeSlotMinutes, viewType]) + }, [slotsArray, timeFrameDay, viewType]) const rateLimiterCalc = useIdleRateLimitHelper(renderIdleTimeout) @@ -190,7 +188,7 @@ export function useGroupRows< currentEntries.current = entries currentTimeSlots.current = slotsArray currentTimeFrameDay.current = timeFrameDay - currentTimeSlotMinutes.current = timeSlotMinutes + currentViewType.current = viewType clearGroupRows() rateLimiterCalc(calculateGroupRows) } @@ -256,7 +254,7 @@ export function useGroupRows< itemsOutsideOfDayRange: itemsOutsideOfDayRange.current, itemsWithSameStartAndEnd: itemsWithSameStartAndEnd.current, // those three are cached for consistency to render with the correct data even through the data might have been updated in between - timeSlotMinutes: currentTimeSlotMinutes.current, + viewType: currentViewType.current, timeFrameDay: currentTimeFrameDay.current, slotsArray: currentTimeSlots.current, // @@ -272,7 +270,6 @@ function getGroupItemStack( groupItems: I[], slotsArray: readonly Dayjs[], timeFrameDay: TimeFrameDay, - timeSlotMinutes: number, viewType: TimeTableViewType, ) { const itemRows: ItemRowEntry[][] = [] @@ -293,7 +290,6 @@ function getGroupItemStack( item, slotsArray, timeFrameDay, - timeSlotMinutes, viewType, ) diff --git a/package-lock.json b/package-lock.json index 24479572..bc2d2250 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "Apache-2.0", "dependencies": { "@atlaskit/empty-state": "^7.12.3", - "@atlaskit/icon": "^22.26.0", + "@atlaskit/icon": "^22.27.0", "@emotion/css": "^11.13.5", "@hello-pangea/dnd": "^17.0.0", "@radix-ui/react-accordion": "^1.2.1", @@ -66,7 +66,7 @@ "@formatjs/cli": "^6.3.11", "@monaco-editor/react": "^4.6.0", "@total-typescript/ts-reset": "^0.6.1", - "@types/node": "^22.10.0", + "@types/node": "^22.10.1", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@typescript-eslint/eslint-plugin": "^8.16.0", @@ -84,7 +84,7 @@ "react-dom": "^18.3.1", "rollup": "4.21", "rollup-plugin-polyfill-node": "^0.13.0", - "stylelint": "^16.10.0", + "stylelint": "^16.11.0", "stylelint-config-standard": "^36.0.1", "stylelint-config-tailwindcss": "^0.0.7", "stylelint-order": "^6.0.4", @@ -169,12 +169,12 @@ } }, "node_modules/@atlaskit/app-provider": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@atlaskit/app-provider/-/app-provider-1.4.2.tgz", - "integrity": "sha512-CtkObk1aqAGdn1eMC4INzeqkJsq0r9KtmCCtNwk08m84w2Jx+c/zr1+lJ9bJLzG3ozkWb7s0TeCOkT4j1iuwJw==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@atlaskit/app-provider/-/app-provider-1.4.3.tgz", + "integrity": "sha512-D1/qY2ZgCVLBgtjRmUO+wlICibvYGI0rEGp+5g4e2Z4KDEq9TRz0P2ibDDedZv8paM0eo7PstrmWA3J2xmE5RQ==", "license": "Apache-2.0", "dependencies": { - "@atlaskit/tokens": "^2.2.0", + "@atlaskit/tokens": "^2.4.0", "@babel/runtime": "^7.0.0", "bind-event-listener": "^3.0.0" }, @@ -211,21 +211,21 @@ } }, "node_modules/@atlaskit/button": { - "version": "20.3.2", - "resolved": "https://registry.npmjs.org/@atlaskit/button/-/button-20.3.2.tgz", - "integrity": "sha512-LuV9GbG5HQLu6n2ObX+UKsBzuhA4NnAUD1OdxvN1Bvac9jfLL7dDAaI+wsmx7n8wq1W/eTrPO/t/rAwUAQamew==", + "version": "20.3.3", + "resolved": "https://registry.npmjs.org/@atlaskit/button/-/button-20.3.3.tgz", + "integrity": "sha512-iW5OoZkfW2WRzHqplZvHjgrDhJSvfQZ3GttKu+96hzNqFLItvjCiMn3nT/uJlwa/4MtiWlPFnDcdcKwOOJjPBg==", "license": "Apache-2.0", "dependencies": { "@atlaskit/analytics-next": "^10.1.0", "@atlaskit/ds-lib": "^3.2.0", - "@atlaskit/focus-ring": "^1.7.0", - "@atlaskit/icon": "^22.24.0", + "@atlaskit/focus-ring": "^2.0.0", + "@atlaskit/icon": "^22.26.0", "@atlaskit/interaction-context": "^2.1.0", "@atlaskit/platform-feature-flags": "^0.3.0", - "@atlaskit/primitives": "^13.2.0", + "@atlaskit/primitives": "^13.3.0", "@atlaskit/spinner": "^16.3.0", "@atlaskit/theme": "^14.0.0", - "@atlaskit/tokens": "^2.2.0", + "@atlaskit/tokens": "^2.3.0", "@atlaskit/tooltip": "^18.9.0", "@atlaskit/visually-hidden": "^1.5.0", "@babel/runtime": "^7.0.0", @@ -295,9 +295,9 @@ } }, "node_modules/@atlaskit/ds-lib": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@atlaskit/ds-lib/-/ds-lib-3.2.2.tgz", - "integrity": "sha512-nZrUJtrNLbxk+UW/woJWkM4ocQTx51eDXhy/1D2ttHvP3vCHehhbC6/f8JxkKwXY98jinjC4utYqAWnIGA15xg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@atlaskit/ds-lib/-/ds-lib-3.3.0.tgz", + "integrity": "sha512-8bgJRFvL4C9dOc3XQ0nJLze4OSXtfemmE2os2h/T80hSdQO57hPMnXB22Pl6nT/6nEP7kZ4kAH6hDuJ3vBUNPA==", "license": "Apache-2.0", "dependencies": { "@atlaskit/platform-feature-flags": "^0.3.0", @@ -329,12 +329,12 @@ } }, "node_modules/@atlaskit/focus-ring": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@atlaskit/focus-ring/-/focus-ring-1.7.0.tgz", - "integrity": "sha512-k+Ix8mat1MiB3Pn35NcNQetQSPG4oxAW/TZlJ1yaawRqvS14ymfWRP+5Rh+A3vSYHAoWBamytbd+jd4A5j33yA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@atlaskit/focus-ring/-/focus-ring-2.0.0.tgz", + "integrity": "sha512-EjCPbwGotrIhOHKAvWiRTcCEeorzhvS2c0t3BD6I4qdOnJzdUATp6YmAn8yAhT1tYIEHg3SKthf/RzwIQWMTKw==", "license": "Apache-2.0", "dependencies": { - "@atlaskit/tokens": "^2.0.0", + "@atlaskit/tokens": "^2.3.0", "@babel/runtime": "^7.0.0", "@compiled/react": "^0.18.1", "@emotion/react": "^11.7.1" @@ -359,13 +359,13 @@ } }, "node_modules/@atlaskit/icon": { - "version": "22.26.0", - "resolved": "https://registry.npmjs.org/@atlaskit/icon/-/icon-22.26.0.tgz", - "integrity": "sha512-uOh011NZMp5F9ueUTM9TVqWPdnO45ZfMM7e4jpYZCmT77TkyBl1pqVmMgrBertczBcyOp/bh8K3PV93NQLtFjA==", + "version": "22.27.0", + "resolved": "https://registry.npmjs.org/@atlaskit/icon/-/icon-22.27.0.tgz", + "integrity": "sha512-ncI8/VITFgxp6FEFbRoYrx6D03Q3jgyjlgUjBrLqKg92ketA2c8ev1m4lgHRefaYo+9t40AsCfjMvr5YVROMVA==", "license": "Apache-2.0", "dependencies": { "@atlaskit/platform-feature-flags": "^0.3.0", - "@atlaskit/tokens": "^2.3.0", + "@atlaskit/tokens": "^2.4.0", "@babel/runtime": "^7.0.0", "@emotion/react": "^11.7.1" }, @@ -440,18 +440,18 @@ } }, "node_modules/@atlaskit/menu": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/@atlaskit/menu/-/menu-2.13.4.tgz", - "integrity": "sha512-WBBK3leJfvBRFeY9rgPQ8IYb/bX0ee8xSsBaq24z5Gaqpj9VAnYfiacsVkoW0CfITtlBIAEVYHLcJczsAwypbQ==", + "version": "2.13.5", + "resolved": "https://registry.npmjs.org/@atlaskit/menu/-/menu-2.13.5.tgz", + "integrity": "sha512-3TrXbIpbH1gT8BuxGK7e8jjrqr5Bm3ZrgmnnBTcgiwsN0hd9G8y/hXl3kVDq8k3HFYuC0jvOsWtgN1HSr8CZGA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@atlaskit/app-provider": "^1.4.0", "@atlaskit/ds-lib": "^3.2.0", - "@atlaskit/focus-ring": "^1.7.0", + "@atlaskit/focus-ring": "^2.0.0", "@atlaskit/interaction-context": "^2.1.0", "@atlaskit/platform-feature-flags": "^0.3.0", - "@atlaskit/primitives": "^13.2.0", + "@atlaskit/primitives": "^13.3.0", "@atlaskit/theme": "^14.0.0", "@atlaskit/tokens": "^2.3.0", "@babel/runtime": "^7.0.0", @@ -523,22 +523,22 @@ } }, "node_modules/@atlaskit/popup": { - "version": "1.29.4", - "resolved": "https://registry.npmjs.org/@atlaskit/popup/-/popup-1.29.4.tgz", - "integrity": "sha512-KaChYn0tRtVZmhaXARQogBjZadjh4iWg36lVlQZ0rifvtRLA/49cXC8IKriIrC/6XIePy3oECWk+TIphahewOQ==", + "version": "1.29.5", + "resolved": "https://registry.npmjs.org/@atlaskit/popup/-/popup-1.29.5.tgz", + "integrity": "sha512-yYSw365KPr92s0tgmlBtoMDeQtrjQuSDxSTEsrKCP8eKjG2x01+NNO5YCeheNGyqtph/Q734B8jbQVWR8X6buQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@atlaskit/css": "^0.6.0", "@atlaskit/ds-lib": "^3.2.0", - "@atlaskit/focus-ring": "^1.7.0", + "@atlaskit/focus-ring": "^2.0.0", "@atlaskit/layering": "^0.8.0", "@atlaskit/platform-feature-flags": "^0.3.0", "@atlaskit/popper": "^6.3.0", "@atlaskit/portal": "^4.9.0", - "@atlaskit/primitives": "^13.2.0", + "@atlaskit/primitives": "^13.3.0", "@atlaskit/theme": "^14.0.0", - "@atlaskit/tokens": "^2.2.0", + "@atlaskit/tokens": "^2.3.0", "@babel/runtime": "^7.0.0", "@emotion/react": "^11.7.1", "bind-event-listener": "^3.0.0", @@ -567,9 +567,9 @@ } }, "node_modules/@atlaskit/primitives": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/@atlaskit/primitives/-/primitives-13.2.0.tgz", - "integrity": "sha512-BkWXoQuWTGPPCnChgOJa85gMtN6PKURAKq4Lqz/X9QTGXfx3VLLoxeonddb7DtF6p7lML6YjvN5jP5hFApqqBw==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@atlaskit/primitives/-/primitives-13.3.0.tgz", + "integrity": "sha512-5/NeDaRjXw7PPdvUaVHOlICJL7TMbjnZ6fwIwEanK1vY/mJtmFZ8aa4nA88LqAA4ty3mte+WBSmL40in5XJkZA==", "license": "Apache-2.0", "dependencies": { "@atlaskit/analytics-next": "^10.1.0", @@ -578,7 +578,7 @@ "@atlaskit/ds-lib": "^3.2.0", "@atlaskit/interaction-context": "^2.1.0", "@atlaskit/platform-feature-flags": "^0.3.0", - "@atlaskit/tokens": "^2.2.0", + "@atlaskit/tokens": "^2.3.0", "@atlaskit/visually-hidden": "^1.5.0", "@babel/runtime": "^7.0.0", "@compiled/react": "^0.18.1", @@ -739,12 +739,12 @@ } }, "node_modules/@atlaskit/tokens": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@atlaskit/tokens/-/tokens-2.3.0.tgz", - "integrity": "sha512-trtYLU1TQ2HPK0Ej3pJ8vLPz+madd55cRbxqm9tE9TjtHtsA2aiLN79Ab1fXnQ+zFX2FGIDcJf81iz9/OexuZQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@atlaskit/tokens/-/tokens-2.4.0.tgz", + "integrity": "sha512-GfDX+1j4WJLBOMaBib/Gaa73FaDsNReHCy5qxaoYnNyVQJC0LWtiFT15l4VaIyDhtI3Vl+WWsdkUWDu10Mksag==", "license": "Apache-2.0", "dependencies": { - "@atlaskit/ds-lib": "^3.2.0", + "@atlaskit/ds-lib": "^3.3.0", "@atlaskit/platform-feature-flags": "^0.3.0", "@babel/runtime": "^7.0.0", "@babel/traverse": "^7.23.2", @@ -1158,9 +1158,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", - "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.2.tgz", + "integrity": "sha512-EUos465uvVvMJehckATTlNqGj4UJWkTmdWuDMjqvSUkjGpmOyFZBVwb4knxCm/k2GMTXY+c/5RkdndzFYWeX5A==", "dev": true, "funding": [ { @@ -1177,14 +1177,14 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.1", - "@csstools/css-tokenizer": "^3.0.1" + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" } }, "node_modules/@csstools/selector-specificity": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-4.0.0.tgz", - "integrity": "sha512-189nelqtPd8++phaHNwYovKZI0FOzH1vQEE3QhHHkNIGrg5fSs9CbYP3RvfEH5geztnIA9Jwq91wyOIwAW5JIQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", "dev": true, "funding": [ { @@ -1201,7 +1201,7 @@ "node": ">=18" }, "peerDependencies": { - "postcss-selector-parser": "^6.1.0" + "postcss-selector-parser": "^7.0.0" } }, "node_modules/@dual-bundle/import-meta-resolve": { @@ -1898,9 +1898,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", - "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", + "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", "dev": true, "license": "MIT", "peer": true, @@ -4622,9 +4622,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.0.tgz", - "integrity": "sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==", + "version": "22.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", + "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6084,9 +6084,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.65", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.65.tgz", - "integrity": "sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==", + "version": "1.5.67", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.67.tgz", + "integrity": "sha512-nz88NNBsD7kQSAGGJyp8hS6xSPtWwqNogA0mjtc2nUYeEf3nURK9qpV18TuBdDmEDgVWotS8Wkzf+V52dSQ/LQ==", "dev": true, "license": "ISC" }, @@ -6213,9 +6213,9 @@ } }, "node_modules/eslint": { - "version": "9.15.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", - "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", + "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", "dev": true, "license": "MIT", "peer": true, @@ -6225,7 +6225,7 @@ "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.9.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.15.0", + "@eslint/js": "9.16.0", "@eslint/plugin-kit": "^0.2.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -7570,9 +7570,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.34.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.34.0.tgz", - "integrity": "sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==", + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", + "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", "dev": true, "license": "MIT" }, @@ -9104,20 +9104,6 @@ "postcss": "^8.1.0" } }, - "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", - "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-modules-scope": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", @@ -9134,20 +9120,6 @@ "postcss": "^8.1.0" } }, - "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", - "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-nested": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", @@ -9174,6 +9146,20 @@ "postcss": "^8.2.14" } }, + "node_modules/postcss-nested/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", @@ -9209,9 +9195,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10500,9 +10486,9 @@ } }, "node_modules/stylelint": { - "version": "16.10.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.10.0.tgz", - "integrity": "sha512-z/8X2rZ52dt2c0stVwI9QL2AFJhLhbPkyfpDFcizs200V/g7v+UYY6SNcB9hKOLcDDX/yGLDsY/pX08sLkz9xQ==", + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.11.0.tgz", + "integrity": "sha512-zrl4IrKmjJQ+h9FoMp69UMCq5SxeHk0URhxUBj4d3ISzo/DplOFBJZc7t7Dr6otB+1bfbbKNLOmCDpzKSlW+Nw==", "dev": true, "funding": [ { @@ -10516,16 +10502,16 @@ ], "license": "MIT", "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.1", - "@csstools/css-tokenizer": "^3.0.1", - "@csstools/media-query-list-parser": "^3.0.1", - "@csstools/selector-specificity": "^4.0.0", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2", + "@csstools/selector-specificity": "^5.0.0", "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", "css-functions-list": "^3.2.3", - "css-tree": "^3.0.0", + "css-tree": "^3.0.1", "debug": "^4.3.7", "fast-glob": "^3.3.2", "fastest-levenshtein": "^1.0.16", @@ -10537,16 +10523,16 @@ "ignore": "^6.0.2", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.34.0", + "known-css-properties": "^0.35.0", "mathml-tag-names": "^2.1.3", "meow": "^13.2.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", - "picocolors": "^1.0.1", - "postcss": "^8.4.47", + "picocolors": "^1.1.1", + "postcss": "^8.4.49", "postcss-resolve-nested-selector": "^0.1.6", "postcss-safe-parser": "^7.0.1", - "postcss-selector-parser": "^6.1.2", + "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", @@ -10977,6 +10963,20 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -11074,9 +11074,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.2.tgz", - "integrity": "sha512-ZF5gQIQa/UmzfvxbHZI3JXN0/Jt+vnAfAviNRAMc491laiK6YCLpCW9ft8oaCRFOTxCZtUTE6XB0ZQAe3olntw==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 56a94660..f4a401ac 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ }, "dependencies": { "@atlaskit/empty-state": "^7.12.3", - "@atlaskit/icon": "^22.26.0", + "@atlaskit/icon": "^22.27.0", "@emotion/css": "^11.13.5", "@hello-pangea/dnd": "^17.0.0", "@radix-ui/react-accordion": "^1.2.1", @@ -133,7 +133,7 @@ "@formatjs/cli": "^6.3.11", "@monaco-editor/react": "^4.6.0", "@total-typescript/ts-reset": "^0.6.1", - "@types/node": "^22.10.0", + "@types/node": "^22.10.1", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@typescript-eslint/eslint-plugin": "^8.16.0", @@ -151,7 +151,7 @@ "react-dom": "^18.3.1", "rollup": "4.21", "rollup-plugin-polyfill-node": "^0.13.0", - "stylelint": "^16.10.0", + "stylelint": "^16.11.0", "stylelint-config-standard": "^36.0.1", "stylelint-config-tailwindcss": "^0.0.7", "stylelint-order": "^6.0.4", diff --git a/showcase/public/showcase-sources.txt b/showcase/public/showcase-sources.txt index 2b1ad266..8909f4c5 100644 --- a/showcase/public/showcase-sources.txt +++ b/showcase/public/showcase-sources.txt @@ -1573,6 +1573,7 @@ function ButtonShowcase(props: ShowcaseProps) { loading={isLoading} iconBefore={} iconAfter={} + className="h-6" > Icon Loading Button @@ -6366,7 +6367,7 @@ function SelectShowcase(props: ShowcaseProps) { }} isMulti options={options} - value={options[4]} + defaultValue={options[4]} /** adding some custom classnames to the styling */ classNames={{ control: () => "bg-warning", @@ -7672,7 +7673,7 @@ function TextFieldShowcase(props: ShowcaseProps) { export default TextFieldShowcase -import { useCallback, useEffect, useMemo } from "react" +import { useCallback, useMemo } from "react" import { useState } from "react" import dayjs, { type Dayjs } from "dayjs" import ShowcaseWrapperItem, { @@ -7712,7 +7713,7 @@ const exampleEntries: TimeTableTypes.TimeTableEntry< ExampleGroup, ExampleItem >[] = [ - { + /*{ group: { id: "group-empty", title: "Empty Group", @@ -7972,7 +7973,7 @@ const exampleEntries: TimeTableTypes.TimeTableEntry< title: "Item 5-3", }, ], - }, + },*/ { group: { id: "group-6", @@ -7980,7 +7981,7 @@ const exampleEntries: TimeTableTypes.TimeTableEntry< subtitle: "Whole Time Frame", }, items: [ - { + /*{ // this case ends after the end of the day and starts before startDate: dayjs().startOf("day").add(7, "hours"), endDate: dayjs().startOf("day").add(12, "hours"), @@ -7991,7 +7992,7 @@ const exampleEntries: TimeTableTypes.TimeTableEntry< startDate: dayjs().startOf("day").add(12, "hours"), endDate: dayjs().startOf("day").add(16, "hours"), title: "Item 6-1-1", - }, + },*/ { startDate: dayjs().startOf("day").add(1, "day"), endDate: dayjs().startOf("day").add(2, "day"), @@ -8004,7 +8005,7 @@ const exampleEntries: TimeTableTypes.TimeTableEntry< }, ], }, - { + /*{ group: { id: "group-7", title: "Group 7 (Full Day)", @@ -8018,7 +8019,7 @@ const exampleEntries: TimeTableTypes.TimeTableEntry< title: "Item 7-1", }, ], - }, + },*/ ] function createTestItems( @@ -8110,6 +8111,9 @@ function TestCustomHeaderRowTimeSlot< entries, tableCellRef, }: TimeTableTypes.CustomHeaderRowTimeSlotProps) { + if (!entries || !entries[1]) { + return null + } const groupItems = entries[1].items if (!groupItems.length) { return null @@ -8185,6 +8189,9 @@ function CustomHeaderRowHeader< viewType, entries, }: TimeTableTypes.CustomHeaderRowHeaderProps) { + if (!entries || !entries[1]) { + return <> + } return (
{entries[1].group.title} has {entries.length} entries @@ -8331,7 +8338,7 @@ function Example() { [], ) - useEffect(() => { + /*useEffect(() => { requestMoreEntriesCB() requestMoreEntriesCB() requestMoreEntriesCB() @@ -8364,7 +8371,7 @@ function Example() { requestMoreEntriesCB() requestMoreEntriesCB() requestMoreEntriesCB() - }, [requestMoreEntriesCB]) + }, [requestMoreEntriesCB])*/ return ( <> @@ -8591,6 +8598,16 @@ function Example() { onClick={() => { setEntries([]) }} + title="Clear Groups and Items" + className="mb-2 mr-2" + > + Clear Groups and Items + + +