From 4660dc7ca88d6839ee556e1a8c1b16f801852f9e Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Thu, 8 Sep 2022 11:57:32 +0200
Subject: [PATCH 01/22] WIP: Calendar view basis

- Added calendar view to Collection view exports
- Base calendar, CSS inline from Notion
- Pages render in the correct days
- Sun-Sat week view
---
 .../third-party/collection-view-calendar.tsx  | 442 ++++++++++++++++++
 .../src/third-party/collection-view.tsx       |   3 +
 packages/react-notion-x/src/utils.ts          |  62 +++
 3 files changed, 507 insertions(+)
 create mode 100644 packages/react-notion-x/src/third-party/collection-view-calendar.tsx

diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
new file mode 100644
index 000000000..f9bbace00
--- /dev/null
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -0,0 +1,442 @@
+import { PageBlock } from 'notion-types'
+import { getPageProperty } from 'notion-utils'
+import * as React from 'react'
+import { useNotionContext } from '../context'
+import { CollectionViewProps } from '../types'
+import { getWeeksInMonth } from '../utils'
+import { CollectionCard } from './collection-card'
+import { CollectionGroup } from './collection-group'
+import { getCollectionGroups } from './collection-utils'
+
+const defaultBlockIds = []
+const currentYear = new Date(Date.now())
+
+export const CollectionViewCalendar: React.FC<CollectionViewProps> = ({
+  collection,
+  collectionView,
+  collectionData
+}) => {
+  const isGroupedCollection = collectionView?.format?.collection_group_by
+
+  if (isGroupedCollection) {
+    const collectionGroups = getCollectionGroups(
+      collection,
+      collectionView,
+      collectionData
+    )
+
+    return collectionGroups.map((group, index) => (
+      <CollectionGroup
+        key={index}
+        {...group}
+        collectionViewComponent={Calendar}
+      />
+    ))
+  }
+
+  const blockIds =
+    (collectionData['collection_group_results']?.blockIds ??
+      collectionData['results:relation:uncategorized']?.blockIds ??
+      collectionData.blockIds) ||
+    defaultBlockIds
+
+  return (
+    <Calendar
+      collectionView={collectionView}
+      collection={collection}
+      blockIds={blockIds}
+    />
+  )
+}
+
+function Calendar({ blockIds, collectionView, collection }) {
+  const { recordMap } = useNotionContext()
+
+  const {
+    gallery_cover = { type: 'none' },
+    gallery_cover_size = 'medium',
+    gallery_cover_aspect = 'cover'
+  } = collectionView.format || {}
+
+  const weeksArr = getWeeksInMonth(
+    currentYear.getFullYear(),
+    currentYear.getMonth()
+  )
+
+  const nextMonth = () => {
+    if (currentYear.getMonth() == 11) {
+      currentYear.setFullYear(currentYear.getFullYear() + 1)
+      currentYear.setMonth(0)
+    } else currentYear.setMonth(currentYear.getMonth() + 1)
+  }
+  const prevMonth = () => {
+    if (currentYear.getMonth() == 0) {
+      currentYear.setFullYear(currentYear.getFullYear() - 1)
+      currentYear.setMonth(11)
+    } else currentYear.setMonth(currentYear.getMonth() - 1)
+  }
+  const nowMonth = () => {
+    currentYear.setMonth(new Date().getMonth())
+  }
+
+  console.log({
+    blockIds,
+    collectionView,
+    collection,
+    weeksArr,
+    dateNow: new Date(Date.now()).getDate()
+  })
+
+  return (
+    <div style={{ position: 'relative', paddingLeft: '1px' }}>
+      <div
+        style={{
+          position: 'absolute',
+          left: '0px',
+          right: '0px',
+          background: 'white',
+          zIndex: 83
+        }}
+      >
+        <div style={{ display: 'flex', height: '42px', alignItems: 'center' }}>
+          <div
+            style={{
+              fontWeight: 600,
+              marginLeft: '8px',
+              marginRight: '8px',
+              lineHeight: '1',
+              fontSize: '14px'
+            }}
+          >
+            {currentYear.getMonth() + ' ' + currentYear.getFullYear()}
+          </div>
+          <div
+            style={{
+              flexGrow: 1
+            }}
+          ></div>
+          <div
+            className='notion-focusable'
+            role='button'
+            tabIndex={0}
+            style={{
+              userSelect: 'none',
+              transition: 'background 20ms ease-in 0s',
+              cursor: 'pointer',
+              display: 'inline-flex',
+              alignItems: 'center',
+              justifyContent: 'center',
+              flexShrink: 0,
+              borderRadius: '3px',
+              height: '24px',
+              width: '24px',
+              padding: '0px'
+            }}
+            onMouseEnter={(e) =>
+              (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
+            }
+            onMouseLeave={(e) => (e.currentTarget.style.background = '')}
+            onClick={prevMonth}
+          >
+            <svg
+              viewBox='0 0 30 30'
+              className='chevronLeft'
+              style={{
+                width: '14px',
+                height: '14px',
+                display: 'block',
+                fill: 'rgba(55, 53, 47, 0.45)',
+                flexShrink: 0,
+                backfaceVisibility: 'hidden'
+              }}
+            >
+              <polygon points='12.6 15 23 25.2 20.2 28 7 15 20.2 2 23 4.8'></polygon>
+            </svg>
+          </div>
+          <div
+            className='notion-focusable'
+            role='button'
+            tabIndex={0}
+            style={{
+              userSelect: 'none',
+              transition: 'background 20ms ease-in 0s',
+              cursor: 'pointer',
+              display: 'inline-flex',
+              alignItems: 'center',
+              flexShrink: 0,
+              whiteSpace: 'nowrap',
+              height: '24px',
+              borderRadius: '3px',
+              fontSize: '14px',
+              lineHeight: '1.2',
+              minWidth: '0px',
+              paddingLeft: '6px',
+              paddingRight: '6px',
+              color: 'rgb(55, 53, 47)'
+            }}
+            onMouseEnter={(e) =>
+              (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
+            }
+            onMouseLeave={(e) => (e.currentTarget.style.background = '')}
+            onClick={nowMonth}
+          >
+            Today
+          </div>
+          <div
+            className='notion-focusable'
+            role='button'
+            tabIndex={0}
+            style={{
+              userSelect: 'none',
+              transition: 'background 20ms ease-in 0s',
+              cursor: 'pointer',
+              display: 'inline-flex',
+              alignItems: 'center',
+              justifyContent: 'center',
+              flexShrink: 0,
+              borderRadius: '3px',
+              height: '24px',
+              width: '24px',
+              padding: '0px'
+            }}
+            onMouseEnter={(e) =>
+              (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
+            }
+            onMouseLeave={(e) => (e.currentTarget.style.background = '')}
+            onClick={nextMonth}
+          >
+            <svg
+              viewBox='0 0 30 30'
+              className='chevronRight'
+              style={{
+                width: '14px',
+                height: '14px',
+                display: 'block',
+                fill: 'rgba(55, 53, 47, 0.45)',
+                flexShrink: 0,
+                backfaceVisibility: 'hidden'
+              }}
+            >
+              <polygon points='17.4,15 7,25.2 9.8,28 23,15 9.8,2 7,4.8'></polygon>
+            </svg>
+          </div>
+        </div>
+        <div
+          className='notion-calendar-header-days'
+          style={{
+            display: 'flex',
+            marginTop: '0px',
+            boxShadow: 'rgb(47, 47, 47) 0px 1px 0px'
+          }}
+        >
+          <div
+            style={{
+              flexGrow: 1,
+              flexBasis: '0px',
+              textAlign: 'center',
+              fontSize: '12px',
+              height: '24px',
+              color: 'rgb(55, 53, 47)'
+            }}
+          >
+            Sun
+          </div>
+          <div
+            style={{
+              flexGrow: 1,
+              flexBasis: '0px',
+              textAlign: 'center',
+              fontSize: '12px',
+              height: '24px',
+              color: 'rgb(55, 53, 47)'
+            }}
+          >
+            Mon
+          </div>
+          <div
+            style={{
+              flexGrow: 1,
+              flexBasis: '0px',
+              textAlign: 'center',
+              fontSize: '12px',
+              height: '24px',
+              color: 'rgb(55, 53, 47)'
+            }}
+          >
+            Tue
+          </div>
+          <div
+            style={{
+              flexGrow: 1,
+              flexBasis: '0px',
+              textAlign: 'center',
+              fontSize: '12px',
+              height: '24px',
+              color: 'rgb(55, 53, 47)'
+            }}
+          >
+            Wed
+          </div>
+          <div
+            style={{
+              flexGrow: 1,
+              flexBasis: '0px',
+              textAlign: 'center',
+              fontSize: '12px',
+              height: '24px',
+              color: 'rgb(55, 53, 47)'
+            }}
+          >
+            Thu
+          </div>
+          <div
+            style={{
+              flexGrow: 1,
+              flexBasis: '0px',
+              textAlign: 'center',
+              fontSize: '12px',
+              height: '24px',
+              color: 'rgb(55, 53, 47)'
+            }}
+          >
+            Fri
+          </div>
+          <div
+            style={{
+              flexGrow: 1,
+              flexBasis: '0px',
+              textAlign: 'center',
+              fontSize: '12px',
+              height: '24px',
+              color: 'rgb(55, 53, 47)'
+            }}
+          >
+            Sat
+          </div>
+        </div>
+      </div>
+
+      <div
+        style={{
+          height: '66px'
+        }}
+      ></div>
+
+      <div
+        style={{
+          boxShadow: 'rgb(233 233 231) -1px 0px 0px',
+          marginTop: '1px',
+          overflow: 'hidden'
+        }}
+      >
+        {[0, 1, 2, 3, 4].map((i) => (
+          <div
+            style={{
+              position: 'relative',
+              display: 'flex',
+              height: '124px'
+            }}
+            key={i}
+          >
+            {[0, 1, 2, 3, 4, 5, 6].map((o) => (
+              <>
+                <div
+                  className='notion-selectable notion-collection_view-block'
+                  style={{
+                    position: 'relative',
+                    flex: '1 0 0px',
+                    borderRight: '1px solid rgb(233, 233, 231)',
+                    borderBottom: '1px solid rgb(233, 233, 231)',
+                    cursor: 'default',
+                    background:
+                      o == 0 || o == 6 ? 'rgb(251, 251, 250)' : 'transparent'
+                  }}
+                  key={o}
+                >
+                  <div
+                    className='notion-calendar-view-day'
+                    style={
+                      weeksArr[i].dates[o] == new Date(Date.now()).getDate() &&
+                      currentYear.getMonth() == new Date(Date.now()).getMonth()
+                        ? {
+                            position: 'absolute',
+                            fontSize: '14px',
+                            top: '4px',
+                            right: '4px',
+                            height: '24px',
+                            width: '24px',
+                            lineHeight: '24px',
+                            borderRadius: '100%',
+                            textAlign: 'center',
+                            color: 'white',
+                            background: 'rgb(235, 87, 87)'
+                          }
+                        : {
+                            position: 'absolute',
+                            fontSize: '14px',
+                            top: '4px',
+                            right: '10px',
+                            height: '24px',
+                            lineHeight: '24px',
+                            textAlign: 'right',
+                            transition: 'color 100ms ease-out 0s',
+                            color: 'rgba(55, 53, 47, 0.5)'
+                          }
+                    }
+                  >
+                    {weeksArr[i].dates[o]}
+                  </div>
+                </div>
+
+                {blockIds?.map((blockId) => {
+                  // check riga
+                  const block = recordMap.block[blockId]?.value as PageBlock
+                  if (!block) return null
+
+                  const blockDate = getPageProperty('Date', block, recordMap)
+
+                  if (
+                    new Date(blockDate as number).getDate() ==
+                      weeksArr[i].dates[o] &&
+                    new Date(blockDate as number).getMonth() ==
+                      currentYear.getMonth()
+                  ) {
+                    const rest = {
+                      style: {
+                        width: 'calc(14.2857%)',
+                        left: `calc(${
+                          new Date(blockDate as number).getDay() == 0
+                            ? 0
+                            : new Date(blockDate as number).getDay() * 14.2857
+                        }%)`,
+                        position: 'absolute',
+                        padding: '3px 6px',
+                        height: '70px',
+                        top: '30px'
+                      }
+                    }
+
+                    return (
+                      <CollectionCard
+                        collection={collection}
+                        block={block}
+                        cover={gallery_cover}
+                        coverSize={gallery_cover_size}
+                        coverAspect={gallery_cover_aspect}
+                        properties={collectionView.format?.calendar_properties}
+                        key={blockId}
+                        {...rest}
+                      />
+                    )
+                  }
+
+                  return null
+                })}
+              </>
+            ))}
+          </div>
+        ))}
+      </div>
+    </div>
+  )
+}
diff --git a/packages/react-notion-x/src/third-party/collection-view.tsx b/packages/react-notion-x/src/third-party/collection-view.tsx
index 8baea2539..107fd30fb 100644
--- a/packages/react-notion-x/src/third-party/collection-view.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view.tsx
@@ -5,6 +5,7 @@ import { CollectionViewTable } from './collection-view-table'
 import { CollectionViewGallery } from './collection-view-gallery'
 import { CollectionViewList } from './collection-view-list'
 import { CollectionViewBoard } from './collection-view-board'
+import { CollectionViewCalendar } from './collection-view-calendar'
 
 export const CollectionViewImpl: React.FC<CollectionViewProps> = (props) => {
   const { collectionView } = props
@@ -21,6 +22,8 @@ export const CollectionViewImpl: React.FC<CollectionViewProps> = (props) => {
 
     case 'board':
       return <CollectionViewBoard {...props} />
+    case 'calendar':
+      return <CollectionViewCalendar {...props} />
 
     default:
       console.warn('unsupported collection view', collectionView)
diff --git a/packages/react-notion-x/src/utils.ts b/packages/react-notion-x/src/utils.ts
index 5c07bb592..e6636eaf7 100644
--- a/packages/react-notion-x/src/utils.ts
+++ b/packages/react-notion-x/src/utils.ts
@@ -82,3 +82,65 @@ export const getYoutubeId = (url: string): string | null => {
 
   return null
 }
+
+export const getWeeksInMonth = (year: number, month: number) => {
+  const weeks = []
+
+  const firstDate = new Date(year, month, 1)
+  const lastDate = new Date(year, month + 1, 0)
+  const numDays = lastDate.getDate()
+  let dayOfWeekCounter = firstDate.getDay()
+
+  for (let date = 1; date <= numDays; date++) {
+    if (dayOfWeekCounter === 0 || weeks.length === 0) {
+      weeks.push([])
+    }
+    weeks[weeks.length - 1].push(date)
+    dayOfWeekCounter = (dayOfWeekCounter + 1) % 7
+  }
+
+  // This is to add the last week of the previous month to the first week of the current month.
+  if (weeks[0].length < 7) {
+    const beforeIndex1 = addMonth(year, month - 1, 1)
+    const indexRefactor = [...beforeIndex1, ...weeks[0]]
+    weeks[0] = indexRefactor
+  }
+
+  // This is to add the first week of the next month to the last week of the current month
+  if (weeks[weeks.length - 1].length < 7) {
+    const afterIndex1 = addMonth(year, month + 1, 0)
+    const indexRefactor = [...weeks[weeks.length - 1], ...afterIndex1]
+    weeks[weeks.length - 1] = indexRefactor
+  }
+
+  return weeks
+    .filter((w) => !!w.length)
+    .map((w) => ({
+      start: w[0],
+      end: w[w.length - 1],
+      dates: w
+    }))
+}
+
+const addMonth = (year: number, month: number, flag: 0 | 1) => {
+  const weeks = []
+  const firstDate = new Date(year, month, 1)
+  const lastDate = new Date(year, month + 1, 0)
+  const numDays = lastDate.getDate()
+  let dayOfWeekCounter = firstDate.getDay()
+
+  for (let date = 1; date <= numDays; date++) {
+    if (dayOfWeekCounter === 0 || weeks.length === 0) {
+      weeks.push([])
+    }
+    weeks[weeks.length - 1].push(date)
+    dayOfWeekCounter = (dayOfWeekCounter + 1) % 7
+  }
+  if (flag == 0) {
+    return weeks[0]
+  } else if (flag == 1) {
+    return weeks[weeks.length - 1]
+  }
+
+  return []
+}

From 049bf1a6bded50a0b7e87c511060e0ba174a6eac Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Thu, 8 Sep 2022 17:43:21 +0200
Subject: [PATCH 02/22] Update collection-view-calendar.tsx

- New custom Collection card for the calendar view
- Show correctly the month
---
 .../third-party/collection-view-calendar.tsx  | 207 ++++++++++++++----
 1 file changed, 166 insertions(+), 41 deletions(-)

diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index f9bbace00..c5cd46e07 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -4,9 +4,9 @@ import * as React from 'react'
 import { useNotionContext } from '../context'
 import { CollectionViewProps } from '../types'
 import { getWeeksInMonth } from '../utils'
-import { CollectionCard } from './collection-card'
 import { CollectionGroup } from './collection-group'
 import { getCollectionGroups } from './collection-utils'
+import { Property } from './property'
 
 const defaultBlockIds = []
 const currentYear = new Date(Date.now())
@@ -50,13 +50,7 @@ export const CollectionViewCalendar: React.FC<CollectionViewProps> = ({
 }
 
 function Calendar({ blockIds, collectionView, collection }) {
-  const { recordMap } = useNotionContext()
-
-  const {
-    gallery_cover = { type: 'none' },
-    gallery_cover_size = 'medium',
-    gallery_cover_aspect = 'cover'
-  } = collectionView.format || {}
+  const { components, recordMap, mapPageUrl } = useNotionContext()
 
   const weeksArr = getWeeksInMonth(
     currentYear.getFullYear(),
@@ -79,13 +73,20 @@ function Calendar({ blockIds, collectionView, collection }) {
     currentYear.setMonth(new Date().getMonth())
   }
 
-  console.log({
-    blockIds,
-    collectionView,
-    collection,
-    weeksArr,
-    dateNow: new Date(Date.now()).getDate()
-  })
+  const months = [
+    'January',
+    'February',
+    'March',
+    'April',
+    'May',
+    'June',
+    'July',
+    'August',
+    'September',
+    'October',
+    'November',
+    'December'
+  ]
 
   return (
     <div style={{ position: 'relative', paddingLeft: '1px' }}>
@@ -108,7 +109,7 @@ function Calendar({ blockIds, collectionView, collection }) {
               fontSize: '14px'
             }}
           >
-            {currentYear.getMonth() + ' ' + currentYear.getFullYear()}
+            {months[currentYear.getMonth()] + ' ' + currentYear.getFullYear()}
           </div>
           <div
             style={{
@@ -334,7 +335,11 @@ function Calendar({ blockIds, collectionView, collection }) {
             style={{
               position: 'relative',
               display: 'flex',
-              height: '124px'
+              height: `${
+                Object.keys(collectionView.format?.calendar_properties).length *
+                  20 +
+                64
+              }px`
             }}
             key={i}
           >
@@ -394,6 +399,8 @@ function Calendar({ blockIds, collectionView, collection }) {
                   if (!block) return null
 
                   const blockDate = getPageProperty('Date', block, recordMap)
+                  const titleSchema = collection.schema.title
+                  const titleData = block?.properties?.title
 
                   if (
                     new Date(blockDate as number).getDate() ==
@@ -401,32 +408,150 @@ function Calendar({ blockIds, collectionView, collection }) {
                     new Date(blockDate as number).getMonth() ==
                       currentYear.getMonth()
                   ) {
-                    const rest = {
-                      style: {
-                        width: 'calc(14.2857%)',
-                        left: `calc(${
-                          new Date(blockDate as number).getDay() == 0
-                            ? 0
-                            : new Date(blockDate as number).getDay() * 14.2857
-                        }%)`,
-                        position: 'absolute',
-                        padding: '3px 6px',
-                        height: '70px',
-                        top: '30px'
-                      }
-                    }
-
                     return (
-                      <CollectionCard
-                        collection={collection}
-                        block={block}
-                        cover={gallery_cover}
-                        coverSize={gallery_cover_size}
-                        coverAspect={gallery_cover_aspect}
-                        properties={collectionView.format?.calendar_properties}
+                      <div
+                        style={{
+                          width: 'calc(14.2857%)',
+                          left: `calc(${
+                            new Date(blockDate as number).getDay() == 0
+                              ? 0
+                              : new Date(blockDate as number).getDay() * 14.2857
+                          }%)`,
+                          position: 'absolute',
+                          padding: '3px 6px',
+                          height: `${
+                            Object.keys(
+                              collectionView.format?.calendar_properties
+                            ).length *
+                              20 +
+                            30
+                          }px`,
+                          top: '30px'
+                        }}
                         key={blockId}
-                        {...rest}
-                      />
+                      >
+                        <components.PageLink
+                          href={mapPageUrl(block.id)}
+                          style={{
+                            display: 'block',
+                            color: 'inherit',
+                            textDecoration: 'none',
+                            height: '100%',
+                            background: 'white',
+                            borderRadius: '3px',
+                            boxShadow:
+                              'rgba(15, 15, 15, 0.1) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 2px 4px'
+                          }}
+                        >
+                          <div
+                            style={{
+                              userSelect: 'none',
+                              transition: 'background 20ms ease-in 0s',
+                              cursor: 'pointer',
+                              width: '100%',
+                              display: 'flex',
+                              position: 'relative',
+                              paddingTop: '2px',
+                              paddingBottom: '2px',
+                              height: '100%',
+                              alignItems: 'flex-start',
+                              flexDirection: 'column'
+                            }}
+                            onMouseEnter={(e) =>
+                              (e.currentTarget.style.background =
+                                'rgba(55,53,47,0.08)')
+                            }
+                            onMouseLeave={(e) =>
+                              (e.currentTarget.style.background = '')
+                            }
+                          >
+                            <div
+                              style={{
+                                paddingLeft: '6px',
+                                paddingRight: '6px',
+                                overflow: 'hidden',
+                                width: '100%',
+                                fontSize: '12px'
+                              }}
+                            >
+                              <div
+                                style={{
+                                  display: 'flex',
+                                  alignItems: 'center',
+                                  height: '20px'
+                                }}
+                              >
+                                <Property
+                                  schema={titleSchema}
+                                  data={titleData}
+                                  block={block}
+                                  collection={collection}
+                                />
+                              </div>
+                            </div>
+                            <div
+                              style={{
+                                paddingLeft: '6px',
+                                paddingRight: '6px',
+                                overflow: 'hidden',
+                                width: '100%'
+                              }}
+                            >
+                              {collectionView.format?.calendar_properties
+                                ?.filter((p) => p.visible)
+                                .map((p, z) => {
+                                  const schema = collection.schema[p.property]
+                                  const data =
+                                    block && block.properties?.[p.property]
+
+                                  if (!schema) {
+                                    return null
+                                  }
+
+                                  return (
+                                    <div
+                                      style={{
+                                        display: 'flex',
+                                        alignItems: 'center',
+                                        fontSize: '12px',
+                                        height: '20px',
+                                        whiteSpace: 'nowrap'
+                                      }}
+                                      key={z}
+                                    >
+                                      <Property
+                                        schema={schema}
+                                        data={data}
+                                        block={block}
+                                        collection={collection}
+                                      />
+                                    </div>
+                                  )
+                                })}
+                            </div>
+                            <div
+                              style={{
+                                position: 'absolute',
+                                top: '0px',
+                                left: '-4px',
+                                height: '100%',
+                                width: '12px',
+                                cursor: 'col-resize'
+                              }}
+                            ></div>
+                            <div
+                              style={{
+                                position: 'absolute',
+                                top: '0px',
+                                right: '-4px',
+                                height: '100%',
+                                width: '12px',
+                                cursor: 'col-resize'
+                              }}
+                            ></div>
+                          </div>
+                        </components.PageLink>
+                      </div>
                     )
                   }
 

From 5347db8c8900bc29344d1697dbbf8998f0240b71 Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Fri, 9 Sep 2022 09:37:08 +0200
Subject: [PATCH 03/22] Update collection-view-calendar.tsx

Improved card title, now more like the Notion one
---
 .../third-party/collection-view-calendar.tsx  | 51 ++++++++++++++++---
 1 file changed, 45 insertions(+), 6 deletions(-)

diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index c5cd46e07..109868172 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -2,6 +2,7 @@ import { PageBlock } from 'notion-types'
 import { getPageProperty } from 'notion-utils'
 import * as React from 'react'
 import { useNotionContext } from '../context'
+import { DefaultPageIcon } from '../icons/default-page-icon'
 import { CollectionViewProps } from '../types'
 import { getWeeksInMonth } from '../utils'
 import { CollectionGroup } from './collection-group'
@@ -481,12 +482,50 @@ function Calendar({ blockIds, collectionView, collection }) {
                                   height: '20px'
                                 }}
                               >
-                                <Property
-                                  schema={titleSchema}
-                                  data={titleData}
-                                  block={block}
-                                  collection={collection}
-                                />
+                                <div
+                                  style={{
+                                    userSelect: 'none',
+                                    transition: 'background 20ms ease-in 0s',
+                                    display: 'flex',
+                                    alignItems: 'center',
+                                    justifyContent: 'center',
+                                    height: '12px',
+                                    width: '12px',
+                                    borderRadius: '0.25em',
+                                    flexShrink: 0,
+                                    marginRight: '4px',
+                                    marginTop: '2px'
+                                  }}
+                                >
+                                  <DefaultPageIcon
+                                    style={{
+                                      width: '10.8px',
+                                      height: '10.8px',
+                                      display: 'block',
+                                      fill: 'rgba(55, 53, 47, 0.85)',
+                                      flexShrink: 0,
+                                      backfaceVisibility: 'hidden'
+                                    }}
+                                  />
+                                </div>
+                                <div
+                                  style={{
+                                    whiteSpace: 'nowrap',
+                                    overflow: 'hidden',
+                                    textOverflow: 'ellipsis',
+                                    flexGrow: 1,
+                                    fontSize: '12px',
+                                    fontWeight: 600
+                                  }}
+                                >
+                                  <Property
+                                    schema={titleSchema}
+                                    data={titleData}
+                                    block={block}
+                                    collection={collection}
+                                    linkToTitlePage={false}
+                                  />
+                                </div>
                               </div>
                             </div>
                             <div

From d761e42ae83bf900c869eb641d2095639373a27a Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Fri, 9 Sep 2022 10:52:16 +0200
Subject: [PATCH 04/22] Calendar controls

- Now calendar controls (next month, prev month and today) works
- Correctly mark current month day numbers
- Display the current month correctly (top left)
- Display the month in the calendar view in the first day of each month
- Show full month in every view
- Edit text component to show long months names
- New method "getPagePropertyFromId" to retrive a page property by a given property ID, used to get the query date used by Notion calendar's view
---
 .../src/get-page-property-from-id.ts          |  88 +++++++++++
 packages/notion-utils/src/index.ts            |   1 +
 .../react-notion-x/src/components/text.tsx    |   7 +-
 .../third-party/collection-view-calendar.tsx  | 144 ++++++++++++------
 .../src/third-party/property.tsx              |   6 +-
 5 files changed, 198 insertions(+), 48 deletions(-)
 create mode 100644 packages/notion-utils/src/get-page-property-from-id.ts

diff --git a/packages/notion-utils/src/get-page-property-from-id.ts b/packages/notion-utils/src/get-page-property-from-id.ts
new file mode 100644
index 000000000..e12b67e48
--- /dev/null
+++ b/packages/notion-utils/src/get-page-property-from-id.ts
@@ -0,0 +1,88 @@
+import { Block, DateFormat, ExtendedRecordMap } from 'notion-types'
+import { getTextContent } from './get-text-content'
+
+/**
+ * Gets the value of a collection property for a given page (collection item).
+ *
+ * @param propertyId property id
+ * @param block Page block, often be first block in blockMap
+ * @param recordMap
+ * @returns - The return value types will follow the following principles:
+ *  1. if property is date type, it will return `number` or `number[]`(depends on `End Date` switch)
+ *  2. property is text-like will return `string`
+ *  3. multi select property will return `string[]`
+ *  4. checkbox property return `boolean`
+ * @todo complete all no-text property type
+ */
+export function getPagePropertyFromId<
+  T = string | number | boolean | string[] | number[]
+>(propertyId: string, block: Block, recordMap: ExtendedRecordMap): T
+export function getPagePropertyFromId(
+  propertyId: string,
+  block: Block,
+  recordMap: ExtendedRecordMap
+) {
+  try {
+    if (!block.properties || !Object.keys(recordMap.collection)) {
+      // console.warn(
+      //   `block ${block.id} has no properties or this recordMap has no collection record`
+      // )
+      return null
+    }
+
+    const collection = recordMap.collection[block.parent_id]?.value
+
+    if (collection) {
+      if (!propertyId) {
+        return null
+      }
+
+      const { type } = collection.schema[propertyId]
+      const content = getTextContent(block.properties[propertyId])
+
+      switch (type) {
+        case 'created_time':
+          return block.created_time
+
+        case 'multi_select':
+          return content.split(',')
+
+        case 'date': {
+          const property = block.properties[propertyId] as [['‣', [DateFormat]]]
+          const formatDate = property[0][1][0][1]
+
+          if (formatDate.type == 'datetime') {
+            return new Date(
+              `${formatDate.start_date} ${formatDate.start_time}`
+            ).getTime()
+          } else if (formatDate.type == 'date') {
+            return new Date(formatDate.start_date).getTime()
+          } else if (formatDate.type == 'datetimerange') {
+            const { start_date, start_time, end_date, end_time } = formatDate
+            const startTime = new Date(`${start_date} ${start_time}`).getTime()
+            const endTime = new Date(`${end_date} ${end_time}`).getTime()
+            return [startTime, endTime]
+          } else {
+            const startTime = new Date(formatDate.start_date).getTime()
+            const endTime = new Date(formatDate.end_date).getTime()
+            return [startTime, endTime]
+          }
+        }
+
+        case 'checkbox':
+          return content == 'Yes'
+
+        case 'last_edited_time':
+          return block.last_edited_time
+
+        default:
+          return content
+      }
+    }
+  } catch {
+    // ensure that no matter what, we don't throw errors because of an unexpected
+    // collection data format
+  }
+
+  return null
+}
diff --git a/packages/notion-utils/src/index.ts b/packages/notion-utils/src/index.ts
index e86921b0e..433dca881 100644
--- a/packages/notion-utils/src/index.ts
+++ b/packages/notion-utils/src/index.ts
@@ -4,6 +4,7 @@ export * from './get-block-icon'
 export * from './get-block-collection-id'
 export * from './get-page-title'
 export * from './get-page-property'
+export * from './get-page-property-from-id'
 export * from './get-date-value'
 export * from './get-block-parent-page'
 export * from './get-page-table-of-contents'
diff --git a/packages/react-notion-x/src/components/text.tsx b/packages/react-notion-x/src/components/text.tsx
index 95b37421e..aab623f57 100644
--- a/packages/react-notion-x/src/components/text.tsx
+++ b/packages/react-notion-x/src/components/text.tsx
@@ -22,7 +22,8 @@ export const Text: React.FC<{
   linkProps?: any
   linkProtocol?: string
   inline?: boolean // TODO: currently unused
-}> = ({ value, block, linkProps, linkProtocol }) => {
+  longMonth?: boolean
+}> = ({ value, block, linkProps, linkProtocol, longMonth }) => {
   const { components, recordMap, mapPageUrl, mapImageUrl, rootDomain } =
     useNotionContext()
 
@@ -189,7 +190,9 @@ export const Text: React.FC<{
                   // Example: Jul 31, 2010
                   const startDate = v.start_date
 
-                  return formatDate(startDate)
+                  return formatDate(startDate, {
+                    month: longMonth ? 'long' : 'short'
+                  })
                 } else if (type === 'daterange') {
                   // Example: Jul 31, 2010 → Jul 31, 2020
                   const startDate = v.start_date
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 109868172..53ecdcdb3 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -1,5 +1,5 @@
 import { PageBlock } from 'notion-types'
-import { getPageProperty } from 'notion-utils'
+import { getPagePropertyFromId } from 'notion-utils'
 import * as React from 'react'
 import { useNotionContext } from '../context'
 import { DefaultPageIcon } from '../icons/default-page-icon'
@@ -11,6 +11,36 @@ import { Property } from './property'
 
 const defaultBlockIds = []
 const currentYear = new Date(Date.now())
+const months = [
+  'January',
+  'February',
+  'March',
+  'April',
+  'May',
+  'June',
+  'July',
+  'August',
+  'September',
+  'October',
+  'November',
+  'December'
+]
+
+const monthsShort = [
+  'Jan',
+  'Feb',
+  'Mar',
+  'Apr',
+  'May',
+  'Jun',
+  'Jul',
+  'Aug',
+  'Sep',
+  'Oct',
+  'Nov',
+  'Dec'
+]
+let currentMonth = 0
 
 export const CollectionViewCalendar: React.FC<CollectionViewProps> = ({
   collection,
@@ -52,42 +82,48 @@ export const CollectionViewCalendar: React.FC<CollectionViewProps> = ({
 
 function Calendar({ blockIds, collectionView, collection }) {
   const { components, recordMap, mapPageUrl } = useNotionContext()
-
-  const weeksArr = getWeeksInMonth(
-    currentYear.getFullYear(),
-    currentYear.getMonth()
+  const [weeksArr, setWeeksArr] = React.useState(
+    getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
   )
 
   const nextMonth = () => {
     if (currentYear.getMonth() == 11) {
       currentYear.setFullYear(currentYear.getFullYear() + 1)
       currentYear.setMonth(0)
-    } else currentYear.setMonth(currentYear.getMonth() + 1)
+    } else {
+      currentYear.setMonth(currentYear.getMonth() + 1)
+    }
+
+    currentMonth = 0
+
+    setWeeksArr(
+      getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
+    )
   }
   const prevMonth = () => {
     if (currentYear.getMonth() == 0) {
       currentYear.setFullYear(currentYear.getFullYear() - 1)
       currentYear.setMonth(11)
-    } else currentYear.setMonth(currentYear.getMonth() - 1)
+    } else {
+      currentYear.setMonth(currentYear.getMonth() - 1)
+    }
+
+    currentMonth = 0
+
+    setWeeksArr(
+      getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
+    )
   }
   const nowMonth = () => {
     currentYear.setMonth(new Date().getMonth())
-  }
+    currentYear.setFullYear(new Date().getFullYear())
+
+    currentMonth = 0
 
-  const months = [
-    'January',
-    'February',
-    'March',
-    'April',
-    'May',
-    'June',
-    'July',
-    'August',
-    'September',
-    'October',
-    'November',
-    'December'
-  ]
+    setWeeksArr(
+      getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
+    )
+  }
 
   return (
     <div style={{ position: 'relative', paddingLeft: '1px' }}>
@@ -228,7 +264,7 @@ function Calendar({ blockIds, collectionView, collection }) {
           style={{
             display: 'flex',
             marginTop: '0px',
-            boxShadow: 'rgb(47, 47, 47) 0px 1px 0px'
+            boxShadow: 'rgb(233 233 231) 0px 1px 0px'
           }}
         >
           <div
@@ -238,7 +274,7 @@ function Calendar({ blockIds, collectionView, collection }) {
               textAlign: 'center',
               fontSize: '12px',
               height: '24px',
-              color: 'rgb(55, 53, 47)'
+              color: 'rgba(55, 53, 47, 0.5)'
             }}
           >
             Sun
@@ -250,7 +286,7 @@ function Calendar({ blockIds, collectionView, collection }) {
               textAlign: 'center',
               fontSize: '12px',
               height: '24px',
-              color: 'rgb(55, 53, 47)'
+              color: 'rgba(55, 53, 47, 0.5)'
             }}
           >
             Mon
@@ -262,7 +298,7 @@ function Calendar({ blockIds, collectionView, collection }) {
               textAlign: 'center',
               fontSize: '12px',
               height: '24px',
-              color: 'rgb(55, 53, 47)'
+              color: 'rgba(55, 53, 47, 0.5)'
             }}
           >
             Tue
@@ -274,7 +310,7 @@ function Calendar({ blockIds, collectionView, collection }) {
               textAlign: 'center',
               fontSize: '12px',
               height: '24px',
-              color: 'rgb(55, 53, 47)'
+              color: 'rgba(55, 53, 47, 0.5)'
             }}
           >
             Wed
@@ -286,7 +322,7 @@ function Calendar({ blockIds, collectionView, collection }) {
               textAlign: 'center',
               fontSize: '12px',
               height: '24px',
-              color: 'rgb(55, 53, 47)'
+              color: 'rgba(55, 53, 47, 0.5)'
             }}
           >
             Thu
@@ -298,7 +334,7 @@ function Calendar({ blockIds, collectionView, collection }) {
               textAlign: 'center',
               fontSize: '12px',
               height: '24px',
-              color: 'rgb(55, 53, 47)'
+              color: 'rgba(55, 53, 47, 0.5)'
             }}
           >
             Fri
@@ -310,7 +346,7 @@ function Calendar({ blockIds, collectionView, collection }) {
               textAlign: 'center',
               fontSize: '12px',
               height: '24px',
-              color: 'rgb(55, 53, 47)'
+              color: 'rgba(55, 53, 47, 0.5)'
             }}
           >
             Sat
@@ -331,7 +367,7 @@ function Calendar({ blockIds, collectionView, collection }) {
           overflow: 'hidden'
         }}
       >
-        {[0, 1, 2, 3, 4].map((i) => (
+        {weeksArr.map((i, indexI) => (
           <div
             style={{
               position: 'relative',
@@ -342,9 +378,9 @@ function Calendar({ blockIds, collectionView, collection }) {
                 64
               }px`
             }}
-            key={i}
+            key={i.dates[indexI]}
           >
-            {[0, 1, 2, 3, 4, 5, 6].map((o) => (
+            {i.dates.map((day, indexY) => (
               <>
                 <div
                   className='notion-selectable notion-collection_view-block'
@@ -355,15 +391,20 @@ function Calendar({ blockIds, collectionView, collection }) {
                     borderBottom: '1px solid rgb(233, 233, 231)',
                     cursor: 'default',
                     background:
-                      o == 0 || o == 6 ? 'rgb(251, 251, 250)' : 'transparent'
+                      indexY == 0 || indexY == 6
+                        ? 'rgb(251, 251, 250)'
+                        : 'transparent'
                   }}
-                  key={o}
+                  key={day}
                 >
                   <div
                     className='notion-calendar-view-day'
                     style={
-                      weeksArr[i].dates[o] == new Date(Date.now()).getDate() &&
-                      currentYear.getMonth() == new Date(Date.now()).getMonth()
+                      day == new Date(Date.now()).getDate() &&
+                      currentYear.getMonth() ==
+                        new Date(Date.now()).getMonth() &&
+                      currentYear.getFullYear() ==
+                        new Date(Date.now()).getFullYear()
                         ? {
                             position: 'absolute',
                             fontSize: '14px',
@@ -386,28 +427,42 @@ function Calendar({ blockIds, collectionView, collection }) {
                             lineHeight: '24px',
                             textAlign: 'right',
                             transition: 'color 100ms ease-out 0s',
-                            color: 'rgba(55, 53, 47, 0.5)'
+                            color:
+                              (day == 1 && currentMonth++ == 0) ||
+                              ((day <= 31 || day >= 28) && currentMonth == 1)
+                                ? 'black'
+                                : 'rgba(55, 53, 47, 0.5)'
                           }
                     }
                   >
-                    {weeksArr[i].dates[o]}
+                    {day == 1
+                      ? `${
+                          monthsShort[currentYear.getMonth() + currentMonth - 1]
+                        } ${day}`
+                      : day}
                   </div>
                 </div>
 
                 {blockIds?.map((blockId) => {
-                  // check riga
                   const block = recordMap.block[blockId]?.value as PageBlock
                   if (!block) return null
 
-                  const blockDate = getPageProperty('Date', block, recordMap)
+                  // Get date from calendar view query
+                  const blockDate = getPagePropertyFromId(
+                    collectionView.query2.calendar_by,
+                    block,
+                    recordMap
+                  )
+
                   const titleSchema = collection.schema.title
                   const titleData = block?.properties?.title
 
                   if (
-                    new Date(blockDate as number).getDate() ==
-                      weeksArr[i].dates[o] &&
+                    new Date(blockDate as number).getDate() == day &&
                     new Date(blockDate as number).getMonth() ==
-                      currentYear.getMonth()
+                      currentYear.getMonth() &&
+                    new Date(blockDate as number).getFullYear() ==
+                      currentYear.getFullYear()
                   ) {
                     return (
                       <div
@@ -563,6 +618,7 @@ function Calendar({ blockIds, collectionView, collection }) {
                                         data={data}
                                         block={block}
                                         collection={collection}
+                                        longMonth={true}
                                       />
                                     </div>
                                   )
diff --git a/packages/react-notion-x/src/third-party/property.tsx b/packages/react-notion-x/src/third-party/property.tsx
index 19cc10d98..b7d8451cf 100644
--- a/packages/react-notion-x/src/third-party/property.tsx
+++ b/packages/react-notion-x/src/third-party/property.tsx
@@ -20,6 +20,7 @@ export interface IPropertyProps {
   inline?: boolean
   linkToTitlePage?: boolean
   pageHeader?: boolean
+  longMonth?: boolean
 }
 
 /**
@@ -46,7 +47,8 @@ export const PropertyImpl: React.FC<IPropertyProps> = (props) => {
     block,
     collection,
     inline = false,
-    linkToTitlePage = true
+    linkToTitlePage = true,
+    longMonth = false
   } = props
 
   const renderTextValue = React.useMemo(
@@ -60,7 +62,7 @@ export const PropertyImpl: React.FC<IPropertyProps> = (props) => {
   const renderDateValue = React.useMemo(
     () =>
       function DateProperty() {
-        return <Text value={data} block={block} />
+        return <Text value={data} block={block} longMonth={longMonth} />
       },
     [block, data]
   )

From 4d1bb6f8d3f9249221a02fe9ce598c9ffb756232 Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Fri, 9 Sep 2022 11:09:35 +0200
Subject: [PATCH 05/22] Hide calendar controls
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

New property for the renderer "showCalendarControls" to show or not the calendar controls (next month, prev month, today)˙
---
 packages/react-notion-x/src/context.tsx       |   3 +
 packages/react-notion-x/src/renderer.tsx      |   3 +
 .../third-party/collection-view-calendar.tsx  | 225 +++++++++---------
 3 files changed, 123 insertions(+), 108 deletions(-)

diff --git a/packages/react-notion-x/src/context.tsx b/packages/react-notion-x/src/context.tsx
index 4f5a25c75..35837bb34 100644
--- a/packages/react-notion-x/src/context.tsx
+++ b/packages/react-notion-x/src/context.tsx
@@ -29,6 +29,7 @@ export interface NotionContext {
   previewImages: boolean
   forceCustomImages: boolean
   showCollectionViewDropdown: boolean
+  showCalendarControls: boolean
   showTableOfContents: boolean
   minTableOfContentsItems: number
   linkTableTitleProperties: boolean
@@ -59,6 +60,7 @@ export interface PartialNotionContext {
   linkTableTitleProperties?: boolean
 
   showTableOfContents?: boolean
+  showCalendarControls?: boolean
   minTableOfContentsItems?: number
 
   defaultPageIcon?: string
@@ -157,6 +159,7 @@ const defaultNotionContext: NotionContext = {
   linkTableTitleProperties: true,
 
   showTableOfContents: false,
+  showCalendarControls: true,
   minTableOfContentsItems: 3,
 
   defaultPageIcon: null,
diff --git a/packages/react-notion-x/src/renderer.tsx b/packages/react-notion-x/src/renderer.tsx
index 1790c5281..3adbe40ab 100644
--- a/packages/react-notion-x/src/renderer.tsx
+++ b/packages/react-notion-x/src/renderer.tsx
@@ -34,6 +34,7 @@ export const NotionRenderer: React.FC<{
   isImageZoomable?: boolean
 
   showTableOfContents?: boolean
+  showCalendarControls?: boolean
   minTableOfContentsItems?: number
 
   defaultPageIcon?: string
@@ -70,6 +71,7 @@ export const NotionRenderer: React.FC<{
   linkTableTitleProperties,
   isImageZoomable = true,
   showTableOfContents,
+  showCalendarControls,
   minTableOfContentsItems,
   defaultPageIcon,
   defaultPageCover,
@@ -103,6 +105,7 @@ export const NotionRenderer: React.FC<{
       showCollectionViewDropdown={showCollectionViewDropdown}
       linkTableTitleProperties={linkTableTitleProperties}
       showTableOfContents={showTableOfContents}
+      showCalendarControls={showCalendarControls}
       minTableOfContentsItems={minTableOfContentsItems}
       defaultPageIcon={defaultPageIcon}
       defaultPageCover={defaultPageCover}
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 53ecdcdb3..729e2d088 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -81,7 +81,8 @@ export const CollectionViewCalendar: React.FC<CollectionViewProps> = ({
 }
 
 function Calendar({ blockIds, collectionView, collection }) {
-  const { components, recordMap, mapPageUrl } = useNotionContext()
+  const { showCalendarControls, components, recordMap, mapPageUrl } =
+    useNotionContext()
   const [weeksArr, setWeeksArr] = React.useState(
     getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
   )
@@ -148,117 +149,125 @@ function Calendar({ blockIds, collectionView, collection }) {
           >
             {months[currentYear.getMonth()] + ' ' + currentYear.getFullYear()}
           </div>
+
           <div
             style={{
               flexGrow: 1
             }}
           ></div>
-          <div
-            className='notion-focusable'
-            role='button'
-            tabIndex={0}
-            style={{
-              userSelect: 'none',
-              transition: 'background 20ms ease-in 0s',
-              cursor: 'pointer',
-              display: 'inline-flex',
-              alignItems: 'center',
-              justifyContent: 'center',
-              flexShrink: 0,
-              borderRadius: '3px',
-              height: '24px',
-              width: '24px',
-              padding: '0px'
-            }}
-            onMouseEnter={(e) =>
-              (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
-            }
-            onMouseLeave={(e) => (e.currentTarget.style.background = '')}
-            onClick={prevMonth}
-          >
-            <svg
-              viewBox='0 0 30 30'
-              className='chevronLeft'
-              style={{
-                width: '14px',
-                height: '14px',
-                display: 'block',
-                fill: 'rgba(55, 53, 47, 0.45)',
-                flexShrink: 0,
-                backfaceVisibility: 'hidden'
-              }}
-            >
-              <polygon points='12.6 15 23 25.2 20.2 28 7 15 20.2 2 23 4.8'></polygon>
-            </svg>
-          </div>
-          <div
-            className='notion-focusable'
-            role='button'
-            tabIndex={0}
-            style={{
-              userSelect: 'none',
-              transition: 'background 20ms ease-in 0s',
-              cursor: 'pointer',
-              display: 'inline-flex',
-              alignItems: 'center',
-              flexShrink: 0,
-              whiteSpace: 'nowrap',
-              height: '24px',
-              borderRadius: '3px',
-              fontSize: '14px',
-              lineHeight: '1.2',
-              minWidth: '0px',
-              paddingLeft: '6px',
-              paddingRight: '6px',
-              color: 'rgb(55, 53, 47)'
-            }}
-            onMouseEnter={(e) =>
-              (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
-            }
-            onMouseLeave={(e) => (e.currentTarget.style.background = '')}
-            onClick={nowMonth}
-          >
-            Today
-          </div>
-          <div
-            className='notion-focusable'
-            role='button'
-            tabIndex={0}
-            style={{
-              userSelect: 'none',
-              transition: 'background 20ms ease-in 0s',
-              cursor: 'pointer',
-              display: 'inline-flex',
-              alignItems: 'center',
-              justifyContent: 'center',
-              flexShrink: 0,
-              borderRadius: '3px',
-              height: '24px',
-              width: '24px',
-              padding: '0px'
-            }}
-            onMouseEnter={(e) =>
-              (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
-            }
-            onMouseLeave={(e) => (e.currentTarget.style.background = '')}
-            onClick={nextMonth}
-          >
-            <svg
-              viewBox='0 0 30 30'
-              className='chevronRight'
-              style={{
-                width: '14px',
-                height: '14px',
-                display: 'block',
-                fill: 'rgba(55, 53, 47, 0.45)',
-                flexShrink: 0,
-                backfaceVisibility: 'hidden'
-              }}
-            >
-              <polygon points='17.4,15 7,25.2 9.8,28 23,15 9.8,2 7,4.8'></polygon>
-            </svg>
-          </div>
+
+          {showCalendarControls && (
+            <>
+              <div
+                className='notion-focusable'
+                role='button'
+                tabIndex={0}
+                style={{
+                  userSelect: 'none',
+                  transition: 'background 20ms ease-in 0s',
+                  cursor: 'pointer',
+                  display: 'inline-flex',
+                  alignItems: 'center',
+                  justifyContent: 'center',
+                  flexShrink: 0,
+                  borderRadius: '3px',
+                  height: '24px',
+                  width: '24px',
+                  padding: '0px'
+                }}
+                onMouseEnter={(e) =>
+                  (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
+                }
+                onMouseLeave={(e) => (e.currentTarget.style.background = '')}
+                onClick={prevMonth}
+              >
+                <svg
+                  viewBox='0 0 30 30'
+                  className='chevronLeft'
+                  style={{
+                    width: '14px',
+                    height: '14px',
+                    display: 'block',
+                    fill: 'rgba(55, 53, 47, 0.45)',
+                    flexShrink: 0,
+                    backfaceVisibility: 'hidden'
+                  }}
+                >
+                  <polygon points='12.6 15 23 25.2 20.2 28 7 15 20.2 2 23 4.8'></polygon>
+                </svg>
+              </div>
+
+              <div
+                className='notion-focusable'
+                role='button'
+                tabIndex={0}
+                style={{
+                  userSelect: 'none',
+                  transition: 'background 20ms ease-in 0s',
+                  cursor: 'pointer',
+                  display: 'inline-flex',
+                  alignItems: 'center',
+                  flexShrink: 0,
+                  whiteSpace: 'nowrap',
+                  height: '24px',
+                  borderRadius: '3px',
+                  fontSize: '14px',
+                  lineHeight: '1.2',
+                  minWidth: '0px',
+                  paddingLeft: '6px',
+                  paddingRight: '6px',
+                  color: 'rgb(55, 53, 47)'
+                }}
+                onMouseEnter={(e) =>
+                  (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
+                }
+                onMouseLeave={(e) => (e.currentTarget.style.background = '')}
+                onClick={nowMonth}
+              >
+                Today
+              </div>
+              <div
+                className='notion-focusable'
+                role='button'
+                tabIndex={0}
+                style={{
+                  userSelect: 'none',
+                  transition: 'background 20ms ease-in 0s',
+                  cursor: 'pointer',
+                  display: 'inline-flex',
+                  alignItems: 'center',
+                  justifyContent: 'center',
+                  flexShrink: 0,
+                  borderRadius: '3px',
+                  height: '24px',
+                  width: '24px',
+                  padding: '0px'
+                }}
+                onMouseEnter={(e) =>
+                  (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
+                }
+                onMouseLeave={(e) => (e.currentTarget.style.background = '')}
+                onClick={nextMonth}
+              >
+                <svg
+                  viewBox='0 0 30 30'
+                  className='chevronRight'
+                  style={{
+                    width: '14px',
+                    height: '14px',
+                    display: 'block',
+                    fill: 'rgba(55, 53, 47, 0.45)',
+                    flexShrink: 0,
+                    backfaceVisibility: 'hidden'
+                  }}
+                >
+                  <polygon points='17.4,15 7,25.2 9.8,28 23,15 9.8,2 7,4.8'></polygon>
+                </svg>
+              </div>
+            </>
+          )}
         </div>
+
         <div
           className='notion-calendar-header-days'
           style={{
@@ -378,7 +387,7 @@ function Calendar({ blockIds, collectionView, collection }) {
                 64
               }px`
             }}
-            key={i.dates[indexI]}
+            key={indexI}
           >
             {i.dates.map((day, indexY) => (
               <>
@@ -395,7 +404,7 @@ function Calendar({ blockIds, collectionView, collection }) {
                         ? 'rgb(251, 251, 250)'
                         : 'transparent'
                   }}
-                  key={day}
+                  key={indexY}
                 >
                   <div
                     className='notion-calendar-view-day'

From a858ae5b400721625cb506175335ebb0acd24418 Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Fri, 9 Sep 2022 11:47:06 +0200
Subject: [PATCH 06/22] Moved style to CSS

TODO: add calendar dark mode theme
---
 packages/react-notion-x/src/styles.css        | 204 +++++++++++-
 .../third-party/collection-view-calendar.tsx  | 313 +++---------------
 2 files changed, 243 insertions(+), 274 deletions(-)

diff --git a/packages/react-notion-x/src/styles.css b/packages/react-notion-x/src/styles.css
index dc44be4f1..8a879c629 100644
--- a/packages/react-notion-x/src/styles.css
+++ b/packages/react-notion-x/src/styles.css
@@ -1600,6 +1600,207 @@ svg.notion-page-icon {
   text-overflow: ellipsis;
 }
 
+.notion-calendar-view {
+  position: relative;
+  padding-left: 1px;
+}
+
+.notion-calendar-header {
+  position: absolute;
+  left: 0px;
+  right: 0px;
+  background: white;
+  z-index: 83;
+}
+
+.notion-calendar-header-inner {
+  display: flex;
+  height: 42px;
+  align-items: center;
+}
+
+.notion-calendar-header-inner-date {
+  font-weight: 600;
+  margin-left: 8px;
+  margin-right: 8px;
+  line-height: 1;
+  font-size: 14px;
+}
+
+.notion-calendar-header-inner-controls-prev {
+  user-select: none;
+  transition: background 20ms ease-in 0s;
+  cursor: pointer;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  flex-shrink: 0;
+  border-radius: 3px;
+  height: 24px;
+  width: 24px;
+  padding: 0px;
+}
+
+.notion-calendar-header-inner-controls-today {
+  user-select: none;
+  transition: background 20ms ease-in 0s;
+  cursor: pointer;
+  display: inline-flex;
+  align-items: center;
+  flex-shrink: 0;
+  white-space: nowrap;
+  height: 24px;
+  border-radius: 3px;
+  font-size: 14px;
+  line-height: 1.2;
+  min-width: 0px;
+  padding-left: 6px;
+  padding-right: 6px;
+  color: rgb(55, 53, 47);
+}
+.notion-calendar-header-inner-controls-next {
+  user-select: none;
+  transition: background 20ms ease-in 0s;
+  cursor: pointer;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  flex-shrink: 0;
+  border-radius: 3px;
+  height: 24px;
+  width: 24px;
+  padding: 0px;
+}
+
+.notion-calendar-header-days {
+  display: flex;
+  margin-top: 0px;
+  box-shadow: rgb(233 233 231) 0px 1px 0px;
+}
+
+.notion-calendar-header-days-day {
+  flex-grow: 1;
+  flex-basis: 0px;
+  text-align: center;
+  font-size: 12px;
+  height: 24px;
+  color: rgba(55, 53, 47, 0.5);
+}
+
+.notion-calendar-body {
+  box-shadow: rgb(233 233 231) -1px 0px 0px;
+  margin-top: 1px;
+  overflow: hidden;
+}
+
+.notion-calendar-body-inner {
+  position: relative;
+  display: flex;
+}
+
+.notion-calendar-body-inner-week {
+  position: relative;
+  flex: 1 0 0px;
+  border-right: 1px solid rgb(233, 233, 231);
+  border-bottom: 1px solid rgb(233, 233, 231);
+  cursor: default;
+}
+
+.notion-calendar-body-inner-day {
+  position: absolute;
+  font-size: 14px;
+  top: 4px;
+  right: 10px;
+  height: 24px;
+  line-height: 24px;
+}
+
+.notion-calendar-body-inner-card {
+  width: calc(14.2857%);
+  position: absolute;
+  padding: 3px 6px;
+  top: 30px;
+}
+
+.notion-calendar-body-inner-card-inner {
+  display: block;
+  color: inherit;
+  text-decoration: none;
+  height: 100%;
+  background: white;
+  border-radius: 3px;
+  box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px,
+    rgba(15, 15, 15, 0.1) 0px 2px 4px;
+}
+
+.notion-calendar-body-inner-card-inner-box {
+  user-select: none;
+  transition: background 20ms ease-in 0s;
+  cursor: pointer;
+  width: 100%;
+  display: flex;
+  position: relative;
+  padding-top: 2px;
+  padding-bottom: 2px;
+  height: 100%;
+  align-items: flex-start;
+  flex-direction: column;
+}
+
+.notion-calendar-body-inner-card-inner-box-title {
+  padding-left: 6px;
+  padding-right: 6px;
+  overflow: hidden;
+  width: 100%;
+  font-size: 12px;
+}
+
+.notion-calendar-body-inner-card-inner-box-title-inner {
+  display: flex;
+  align-items: center;
+  height: 20px;
+}
+
+.notion-calendar-body-inner-card-inner-box-title-inner-icon {
+  user-select: none;
+  transition: background 20ms ease-in 0s;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 12px;
+  width: 12px;
+  border-radius: 0.25em;
+  flex-shrink: 0;
+  margin-right: 4px;
+  margin-top: 2px;
+}
+
+.notion-calendar-body-inner-card-inner-box-title-inner-text {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  flex-grow: 1;
+  font-size: 12px;
+  font-weight: 600;
+}
+
+.notion-calendar-body-inner-card-inner-box-properties {
+  padding-left: 6px;
+  padding-right: 6px;
+  overflow: hidden;
+  width: 100%;
+}
+
+.notion-calendar-body-inner-card-inner-box-properties-property {
+  display: flex;
+  align-items: center;
+  font-size: 12px;
+  height: 20px;
+  white-space: nowrap;
+}
+
+/* TODO: add calendar dark mode theme (append .dark-mode) */
+
 .notion-board {
   width: 100vw;
   max-width: 100vw;
@@ -2554,9 +2755,6 @@ svg.notion-page-icon {
   margin-bottom: 1em;
 }
 
-.notion-collection-group > summary {
-}
-
 .notion-collection-group > summary > div {
   transform: scale(0.85);
   transform-origin: 0% 50%;
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 729e2d088..230530f7f 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -4,7 +4,7 @@ import * as React from 'react'
 import { useNotionContext } from '../context'
 import { DefaultPageIcon } from '../icons/default-page-icon'
 import { CollectionViewProps } from '../types'
-import { getWeeksInMonth } from '../utils'
+import { cs, getWeeksInMonth } from '../utils'
 import { CollectionGroup } from './collection-group'
 import { getCollectionGroups } from './collection-utils'
 import { Property } from './property'
@@ -127,26 +127,10 @@ function Calendar({ blockIds, collectionView, collection }) {
   }
 
   return (
-    <div style={{ position: 'relative', paddingLeft: '1px' }}>
-      <div
-        style={{
-          position: 'absolute',
-          left: '0px',
-          right: '0px',
-          background: 'white',
-          zIndex: 83
-        }}
-      >
-        <div style={{ display: 'flex', height: '42px', alignItems: 'center' }}>
-          <div
-            style={{
-              fontWeight: 600,
-              marginLeft: '8px',
-              marginRight: '8px',
-              lineHeight: '1',
-              fontSize: '14px'
-            }}
-          >
+    <div className='notion-calendar-view'>
+      <div className='notion-calendar-header'>
+        <div className='notion-calendar-header-inner'>
+          <div className='notion-calendar-header-inner-date'>
             {months[currentYear.getMonth()] + ' ' + currentYear.getFullYear()}
           </div>
 
@@ -159,22 +143,12 @@ function Calendar({ blockIds, collectionView, collection }) {
           {showCalendarControls && (
             <>
               <div
-                className='notion-focusable'
+                className={cs(
+                  'notion-focusable',
+                  'notion-calendar-header-inner-controls-prev'
+                )}
                 role='button'
                 tabIndex={0}
-                style={{
-                  userSelect: 'none',
-                  transition: 'background 20ms ease-in 0s',
-                  cursor: 'pointer',
-                  display: 'inline-flex',
-                  alignItems: 'center',
-                  justifyContent: 'center',
-                  flexShrink: 0,
-                  borderRadius: '3px',
-                  height: '24px',
-                  width: '24px',
-                  padding: '0px'
-                }}
                 onMouseEnter={(e) =>
                   (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
                 }
@@ -198,26 +172,12 @@ function Calendar({ blockIds, collectionView, collection }) {
               </div>
 
               <div
-                className='notion-focusable'
+                className={cs(
+                  'notion-focusable',
+                  'notion-calendar-header-inner-controls-today'
+                )}
                 role='button'
                 tabIndex={0}
-                style={{
-                  userSelect: 'none',
-                  transition: 'background 20ms ease-in 0s',
-                  cursor: 'pointer',
-                  display: 'inline-flex',
-                  alignItems: 'center',
-                  flexShrink: 0,
-                  whiteSpace: 'nowrap',
-                  height: '24px',
-                  borderRadius: '3px',
-                  fontSize: '14px',
-                  lineHeight: '1.2',
-                  minWidth: '0px',
-                  paddingLeft: '6px',
-                  paddingRight: '6px',
-                  color: 'rgb(55, 53, 47)'
-                }}
                 onMouseEnter={(e) =>
                   (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
                 }
@@ -227,22 +187,12 @@ function Calendar({ blockIds, collectionView, collection }) {
                 Today
               </div>
               <div
-                className='notion-focusable'
+                className={cs(
+                  'notion-focusable',
+                  'notion-calendar-header-inner-controls-next'
+                )}
                 role='button'
                 tabIndex={0}
-                style={{
-                  userSelect: 'none',
-                  transition: 'background 20ms ease-in 0s',
-                  cursor: 'pointer',
-                  display: 'inline-flex',
-                  alignItems: 'center',
-                  justifyContent: 'center',
-                  flexShrink: 0,
-                  borderRadius: '3px',
-                  height: '24px',
-                  width: '24px',
-                  padding: '0px'
-                }}
                 onMouseEnter={(e) =>
                   (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
                 }
@@ -268,98 +218,14 @@ function Calendar({ blockIds, collectionView, collection }) {
           )}
         </div>
 
-        <div
-          className='notion-calendar-header-days'
-          style={{
-            display: 'flex',
-            marginTop: '0px',
-            boxShadow: 'rgb(233 233 231) 0px 1px 0px'
-          }}
-        >
-          <div
-            style={{
-              flexGrow: 1,
-              flexBasis: '0px',
-              textAlign: 'center',
-              fontSize: '12px',
-              height: '24px',
-              color: 'rgba(55, 53, 47, 0.5)'
-            }}
-          >
-            Sun
-          </div>
-          <div
-            style={{
-              flexGrow: 1,
-              flexBasis: '0px',
-              textAlign: 'center',
-              fontSize: '12px',
-              height: '24px',
-              color: 'rgba(55, 53, 47, 0.5)'
-            }}
-          >
-            Mon
-          </div>
-          <div
-            style={{
-              flexGrow: 1,
-              flexBasis: '0px',
-              textAlign: 'center',
-              fontSize: '12px',
-              height: '24px',
-              color: 'rgba(55, 53, 47, 0.5)'
-            }}
-          >
-            Tue
-          </div>
-          <div
-            style={{
-              flexGrow: 1,
-              flexBasis: '0px',
-              textAlign: 'center',
-              fontSize: '12px',
-              height: '24px',
-              color: 'rgba(55, 53, 47, 0.5)'
-            }}
-          >
-            Wed
-          </div>
-          <div
-            style={{
-              flexGrow: 1,
-              flexBasis: '0px',
-              textAlign: 'center',
-              fontSize: '12px',
-              height: '24px',
-              color: 'rgba(55, 53, 47, 0.5)'
-            }}
-          >
-            Thu
-          </div>
-          <div
-            style={{
-              flexGrow: 1,
-              flexBasis: '0px',
-              textAlign: 'center',
-              fontSize: '12px',
-              height: '24px',
-              color: 'rgba(55, 53, 47, 0.5)'
-            }}
-          >
-            Fri
-          </div>
-          <div
-            style={{
-              flexGrow: 1,
-              flexBasis: '0px',
-              textAlign: 'center',
-              fontSize: '12px',
-              height: '24px',
-              color: 'rgba(55, 53, 47, 0.5)'
-            }}
-          >
-            Sat
-          </div>
+        <div className='notion-calendar-header-days'>
+          <div className='notion-calendar-header-days-day'>Sun</div>
+          <div className='notion-calendar-header-days-day'>Mon</div>
+          <div className='notion-calendar-header-days-day'>Tue</div>
+          <div className='notion-calendar-header-days-day'>Wed</div>
+          <div className='notion-calendar-header-days-day'>Thu</div>
+          <div className='notion-calendar-header-days-day'>Fri</div>
+          <div className='notion-calendar-header-days-day'>Sat</div>
         </div>
       </div>
 
@@ -369,18 +235,11 @@ function Calendar({ blockIds, collectionView, collection }) {
         }}
       ></div>
 
-      <div
-        style={{
-          boxShadow: 'rgb(233 233 231) -1px 0px 0px',
-          marginTop: '1px',
-          overflow: 'hidden'
-        }}
-      >
+      <div className='notion-calendar-body'>
         {weeksArr.map((i, indexI) => (
           <div
+            className='notion-calendar-body-inner'
             style={{
-              position: 'relative',
-              display: 'flex',
               height: `${
                 Object.keys(collectionView.format?.calendar_properties).length *
                   20 +
@@ -392,13 +251,11 @@ function Calendar({ blockIds, collectionView, collection }) {
             {i.dates.map((day, indexY) => (
               <>
                 <div
-                  className='notion-selectable notion-collection_view-block'
+                  className={cs(
+                    'notion-selectable',
+                    'notion-calendar-body-inner-week'
+                  )}
                   style={{
-                    position: 'relative',
-                    flex: '1 0 0px',
-                    borderRight: '1px solid rgb(233, 233, 231)',
-                    borderBottom: '1px solid rgb(233, 233, 231)',
-                    cursor: 'default',
                     background:
                       indexY == 0 || indexY == 6
                         ? 'rgb(251, 251, 250)'
@@ -407,7 +264,7 @@ function Calendar({ blockIds, collectionView, collection }) {
                   key={indexY}
                 >
                   <div
-                    className='notion-calendar-view-day'
+                    className='notion-calendar-body-inner-day'
                     style={
                       day == new Date(Date.now()).getDate() &&
                       currentYear.getMonth() ==
@@ -415,25 +272,13 @@ function Calendar({ blockIds, collectionView, collection }) {
                       currentYear.getFullYear() ==
                         new Date(Date.now()).getFullYear()
                         ? {
-                            position: 'absolute',
-                            fontSize: '14px',
-                            top: '4px',
-                            right: '4px',
-                            height: '24px',
                             width: '24px',
-                            lineHeight: '24px',
                             borderRadius: '100%',
                             textAlign: 'center',
                             color: 'white',
                             background: 'rgb(235, 87, 87)'
                           }
                         : {
-                            position: 'absolute',
-                            fontSize: '14px',
-                            top: '4px',
-                            right: '10px',
-                            height: '24px',
-                            lineHeight: '24px',
                             textAlign: 'right',
                             transition: 'color 100ms ease-out 0s',
                             color:
@@ -475,53 +320,29 @@ function Calendar({ blockIds, collectionView, collection }) {
                   ) {
                     return (
                       <div
+                        className='notion-calendar-body-inner-card'
                         style={{
-                          width: 'calc(14.2857%)',
                           left: `calc(${
                             new Date(blockDate as number).getDay() == 0
                               ? 0
                               : new Date(blockDate as number).getDay() * 14.2857
                           }%)`,
-                          position: 'absolute',
-                          padding: '3px 6px',
                           height: `${
                             Object.keys(
                               collectionView.format?.calendar_properties
                             ).length *
                               20 +
                             30
-                          }px`,
-                          top: '30px'
+                          }px`
                         }}
                         key={blockId}
                       >
                         <components.PageLink
                           href={mapPageUrl(block.id)}
-                          style={{
-                            display: 'block',
-                            color: 'inherit',
-                            textDecoration: 'none',
-                            height: '100%',
-                            background: 'white',
-                            borderRadius: '3px',
-                            boxShadow:
-                              'rgba(15, 15, 15, 0.1) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 2px 4px'
-                          }}
+                          className='notion-calendar-body-inner-card-inner'
                         >
                           <div
-                            style={{
-                              userSelect: 'none',
-                              transition: 'background 20ms ease-in 0s',
-                              cursor: 'pointer',
-                              width: '100%',
-                              display: 'flex',
-                              position: 'relative',
-                              paddingTop: '2px',
-                              paddingBottom: '2px',
-                              height: '100%',
-                              alignItems: 'flex-start',
-                              flexDirection: 'column'
-                            }}
+                            className='notion-calendar-body-inner-card-inner-box'
                             onMouseEnter={(e) =>
                               (e.currentTarget.style.background =
                                 'rgba(55,53,47,0.08)')
@@ -530,37 +351,9 @@ function Calendar({ blockIds, collectionView, collection }) {
                               (e.currentTarget.style.background = '')
                             }
                           >
-                            <div
-                              style={{
-                                paddingLeft: '6px',
-                                paddingRight: '6px',
-                                overflow: 'hidden',
-                                width: '100%',
-                                fontSize: '12px'
-                              }}
-                            >
-                              <div
-                                style={{
-                                  display: 'flex',
-                                  alignItems: 'center',
-                                  height: '20px'
-                                }}
-                              >
-                                <div
-                                  style={{
-                                    userSelect: 'none',
-                                    transition: 'background 20ms ease-in 0s',
-                                    display: 'flex',
-                                    alignItems: 'center',
-                                    justifyContent: 'center',
-                                    height: '12px',
-                                    width: '12px',
-                                    borderRadius: '0.25em',
-                                    flexShrink: 0,
-                                    marginRight: '4px',
-                                    marginTop: '2px'
-                                  }}
-                                >
+                            <div className='notion-calendar-body-inner-card-inner-box-title'>
+                              <div className='notion-calendar-body-inner-card-inner-box-title-inner'>
+                                <div className='notion-calendar-body-inner-card-inner-box-title-inner-icon'>
                                   <DefaultPageIcon
                                     style={{
                                       width: '10.8px',
@@ -572,16 +365,7 @@ function Calendar({ blockIds, collectionView, collection }) {
                                     }}
                                   />
                                 </div>
-                                <div
-                                  style={{
-                                    whiteSpace: 'nowrap',
-                                    overflow: 'hidden',
-                                    textOverflow: 'ellipsis',
-                                    flexGrow: 1,
-                                    fontSize: '12px',
-                                    fontWeight: 600
-                                  }}
-                                >
+                                <div className='notion-calendar-body-inner-card-inner-box-title-inner-text'>
                                   <Property
                                     schema={titleSchema}
                                     data={titleData}
@@ -592,14 +376,7 @@ function Calendar({ blockIds, collectionView, collection }) {
                                 </div>
                               </div>
                             </div>
-                            <div
-                              style={{
-                                paddingLeft: '6px',
-                                paddingRight: '6px',
-                                overflow: 'hidden',
-                                width: '100%'
-                              }}
-                            >
+                            <div className='notion-calendar-body-inner-card-inner-box-properties'>
                               {collectionView.format?.calendar_properties
                                 ?.filter((p) => p.visible)
                                 .map((p, z) => {
@@ -613,13 +390,7 @@ function Calendar({ blockIds, collectionView, collection }) {
 
                                   return (
                                     <div
-                                      style={{
-                                        display: 'flex',
-                                        alignItems: 'center',
-                                        fontSize: '12px',
-                                        height: '20px',
-                                        whiteSpace: 'nowrap'
-                                      }}
+                                      className='notion-calendar-body-inner-card-inner-box-properties-property'
                                       key={z}
                                     >
                                       <Property

From 55a905103a47473ae86b98edb0d36f9731fc68e5 Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Sun, 11 Sep 2022 11:21:22 +0200
Subject: [PATCH 07/22] Added dark-mode css

- Added dark-mode css for the new calendar view
- Updated background of dark-mode to the new Notion one
- Moved hover states from React to CSS
- Removed all dynamic styles and used with classes
---
 packages/react-notion-x/src/styles.css        | 124 +++++++++++++++++-
 .../third-party/collection-view-calendar.tsx  | 101 +++-----------
 2 files changed, 144 insertions(+), 81 deletions(-)

diff --git a/packages/react-notion-x/src/styles.css b/packages/react-notion-x/src/styles.css
index 8a879c629..6f991dcad 100644
--- a/packages/react-notion-x/src/styles.css
+++ b/packages/react-notion-x/src/styles.css
@@ -77,7 +77,7 @@
   --fg-color-6: #fff;
   --fg-color-icon: #fff;
 
-  --bg-color: #2f3437;
+  --bg-color: rgb(25, 25, 25);
   --bg-color-0: rgb(71, 76, 80);
   --bg-color-1: rgb(63, 68, 71);
   --bg-color-2: rgba(135, 131, 120, 0.15);
@@ -1641,6 +1641,12 @@ svg.notion-page-icon {
   padding: 0px;
 }
 
+.notion-calendar-header-inner-controls-prev:hover,
+.notion-calendar-header-inner-controls-today:hover,
+.notion-calendar-header-inner-controls-next:hover {
+  background: rgba(55, 53, 47, 0.08);
+}
+
 .notion-calendar-header-inner-controls-today {
   user-select: none;
   transition: background 20ms ease-in 0s;
@@ -1658,6 +1664,7 @@ svg.notion-page-icon {
   padding-right: 6px;
   color: rgb(55, 53, 47);
 }
+
 .notion-calendar-header-inner-controls-next {
   user-select: none;
   transition: background 20ms ease-in 0s;
@@ -1672,6 +1679,16 @@ svg.notion-page-icon {
   padding: 0px;
 }
 
+.notion-calendar-header-inner-controls-next-svg,
+.notion-calendar-header-inner-controls-prev-svg {
+  width: 14px;
+  height: 14px;
+  display: block;
+  fill: rgba(55, 53, 47, 0.45);
+  flex-shrink: 0;
+  backface-visibility: hidden;
+}
+
 .notion-calendar-header-days {
   display: flex;
   margin-top: 0px;
@@ -1706,6 +1723,10 @@ svg.notion-page-icon {
   cursor: default;
 }
 
+.notion-calendar-body-inner-week-dif {
+  background: rgb(251, 251, 250);
+}
+
 .notion-calendar-body-inner-day {
   position: absolute;
   font-size: 14px;
@@ -1715,6 +1736,27 @@ svg.notion-page-icon {
   line-height: 24px;
 }
 
+.notion-calendar-body-inner-day-today {
+  width: 24px;
+  border-radius: 100%;
+  text-align: center;
+  color: white;
+  background: rgb(235, 87, 87);
+}
+
+.notion-calendar-body-inner-day-normal {
+  text-align: right;
+  transition: color 100ms ease-out 0s;
+}
+
+.notion-calendar-body-inner-day-this-month {
+  color: black;
+}
+
+.notion-calendar-body-inner-day-other-month {
+  color: rgba(55, 53, 47, 0.5);
+}
+
 .notion-calendar-body-inner-card {
   width: calc(14.2857%);
   position: absolute;
@@ -1747,6 +1789,10 @@ svg.notion-page-icon {
   flex-direction: column;
 }
 
+.notion-calendar-body-inner-card-inner-box:hover {
+  background: rgba(55, 53, 47, 0.08);
+}
+
 .notion-calendar-body-inner-card-inner-box-title {
   padding-left: 6px;
   padding-right: 6px;
@@ -1775,6 +1821,15 @@ svg.notion-page-icon {
   margin-top: 2px;
 }
 
+.notion-calendar-body-inner-card-inner-box-title-inner-icon-svg {
+  width: 10.8px;
+  height: 10.8px;
+  display: block;
+  fill: rgba(55, 53, 47, 0.85);
+  flex-shrink: 0;
+  backface-visibility: hidden;
+}
+
 .notion-calendar-body-inner-card-inner-box-title-inner-text {
   white-space: nowrap;
   overflow: hidden;
@@ -1801,6 +1856,73 @@ svg.notion-page-icon {
 
 /* TODO: add calendar dark mode theme (append .dark-mode) */
 
+.dark-mode .notion-calendar-header {
+  background: rgb(25, 25, 25);
+}
+
+.dark-mode .notion-calendar-header-inner-controls-today {
+  color: rgba(255, 255, 255, 0.81);
+}
+
+.dark-mode .notion-calendar-header-days-day {
+  color: rgba(255, 255, 255, 0.282);
+}
+
+.dark-mode .notion-calendar-body {
+  box-shadow: rgb(47 47 47) -1px 0px 0px;
+}
+
+.dark-mode .notion-calendar-body-inner-week {
+  border-right: 1px solid rgb(47, 47, 47);
+  border-bottom: 1px solid rgb(47, 47, 47);
+}
+
+.dark-mode .notion-calendar-body-inner-day {
+  color: white;
+}
+
+.dark-mode .notion-calendar-body-inner-week-dif {
+  background: rgb(32, 32, 32);
+}
+
+.dark-mode .notion-calendar-body-inner-day-normal,
+.dark-mode .notion-calendar-body-inner-day-this-month {
+  color: white;
+}
+
+.dark-mode .notion-calendar-body-inner-day-other-month {
+  color: rgba(255, 255, 255, 0.282);
+}
+
+.dark-mode .notion-calendar-body-inner-card-inner {
+  background: rgb(47, 47, 47);
+}
+
+.dark-mode .notion-calendar-header-days {
+  box-shadow: rgb(47 47 47) 0px 1px 0px;
+}
+
+.dark-mode .notion-calendar-body-inner-card-inner-box-title-inner-icon-svg {
+  fill: rgba(255, 255, 255, 0.81);
+}
+
+.dark-mode .notion-calendar-header-inner-controls-next-svg,
+.dark-mode .notion-calendar-header-inner-controls-prev-svg {
+  fill: rgba(255, 255, 255, 0.443);
+}
+
+.dark-mode .notion-calendar-header-inner-controls-prev:hover,
+.dark-mode .notion-calendar-header-inner-controls-today:hover,
+.dark-mode .notion-calendar-header-inner-controls-next:hover {
+  background: rgba(255, 255, 255, 0.055);
+}
+
+.dark-mode .notion-calendar-body-inner-card-inner-box:hover {
+  background: rgba(255, 255, 255, 0.055);
+}
+
+/**/
+
 .notion-board {
   width: 100vw;
   max-width: 100vw;
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 230530f7f..0226d80ac 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -149,23 +149,11 @@ function Calendar({ blockIds, collectionView, collection }) {
                 )}
                 role='button'
                 tabIndex={0}
-                onMouseEnter={(e) =>
-                  (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
-                }
-                onMouseLeave={(e) => (e.currentTarget.style.background = '')}
                 onClick={prevMonth}
               >
                 <svg
                   viewBox='0 0 30 30'
-                  className='chevronLeft'
-                  style={{
-                    width: '14px',
-                    height: '14px',
-                    display: 'block',
-                    fill: 'rgba(55, 53, 47, 0.45)',
-                    flexShrink: 0,
-                    backfaceVisibility: 'hidden'
-                  }}
+                  className='notion-calendar-header-inner-controls-prev-svg'
                 >
                   <polygon points='12.6 15 23 25.2 20.2 28 7 15 20.2 2 23 4.8'></polygon>
                 </svg>
@@ -178,10 +166,6 @@ function Calendar({ blockIds, collectionView, collection }) {
                 )}
                 role='button'
                 tabIndex={0}
-                onMouseEnter={(e) =>
-                  (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
-                }
-                onMouseLeave={(e) => (e.currentTarget.style.background = '')}
                 onClick={nowMonth}
               >
                 Today
@@ -193,23 +177,11 @@ function Calendar({ blockIds, collectionView, collection }) {
                 )}
                 role='button'
                 tabIndex={0}
-                onMouseEnter={(e) =>
-                  (e.currentTarget.style.background = 'rgba(55,53,47,0.08)')
-                }
-                onMouseLeave={(e) => (e.currentTarget.style.background = '')}
                 onClick={nextMonth}
               >
                 <svg
                   viewBox='0 0 30 30'
-                  className='chevronRight'
-                  style={{
-                    width: '14px',
-                    height: '14px',
-                    display: 'block',
-                    fill: 'rgba(55, 53, 47, 0.45)',
-                    flexShrink: 0,
-                    backfaceVisibility: 'hidden'
-                  }}
+                  className='notion-calendar-header-inner-controls-next-svg'
                 >
                   <polygon points='17.4,15 7,25.2 9.8,28 23,15 9.8,2 7,4.8'></polygon>
                 </svg>
@@ -253,41 +225,28 @@ function Calendar({ blockIds, collectionView, collection }) {
                 <div
                   className={cs(
                     'notion-selectable',
-                    'notion-calendar-body-inner-week'
+                    'notion-calendar-body-inner-week',
+                    indexY == 0 || indexY == 6
+                      ? 'notion-calendar-body-inner-week-dif'
+                      : ''
                   )}
-                  style={{
-                    background:
-                      indexY == 0 || indexY == 6
-                        ? 'rgb(251, 251, 250)'
-                        : 'transparent'
-                  }}
                   key={indexY}
                 >
                   <div
-                    className='notion-calendar-body-inner-day'
-                    style={
+                    className={cs(
+                      'notion-calendar-body-inner-day',
                       day == new Date(Date.now()).getDate() &&
-                      currentYear.getMonth() ==
-                        new Date(Date.now()).getMonth() &&
-                      currentYear.getFullYear() ==
-                        new Date(Date.now()).getFullYear()
-                        ? {
-                            width: '24px',
-                            borderRadius: '100%',
-                            textAlign: 'center',
-                            color: 'white',
-                            background: 'rgb(235, 87, 87)'
-                          }
-                        : {
-                            textAlign: 'right',
-                            transition: 'color 100ms ease-out 0s',
-                            color:
-                              (day == 1 && currentMonth++ == 0) ||
-                              ((day <= 31 || day >= 28) && currentMonth == 1)
-                                ? 'black'
-                                : 'rgba(55, 53, 47, 0.5)'
-                          }
-                    }
+                        currentYear.getMonth() ==
+                          new Date(Date.now()).getMonth() &&
+                        currentYear.getFullYear() ==
+                          new Date(Date.now()).getFullYear()
+                        ? 'notion-calendar-body-inner-day-today'
+                        : 'notion-calendar-body-inner-day-normal',
+                      (day == 1 && currentMonth++ == 0) ||
+                        ((day <= 31 || day >= 28) && currentMonth == 1)
+                        ? 'notion-calendar-body-inner-day-this-month'
+                        : 'notion-calendar-body-inner-day-other-month'
+                    )}
                   >
                     {day == 1
                       ? `${
@@ -341,29 +300,11 @@ function Calendar({ blockIds, collectionView, collection }) {
                           href={mapPageUrl(block.id)}
                           className='notion-calendar-body-inner-card-inner'
                         >
-                          <div
-                            className='notion-calendar-body-inner-card-inner-box'
-                            onMouseEnter={(e) =>
-                              (e.currentTarget.style.background =
-                                'rgba(55,53,47,0.08)')
-                            }
-                            onMouseLeave={(e) =>
-                              (e.currentTarget.style.background = '')
-                            }
-                          >
+                          <div className='notion-calendar-body-inner-card-inner-box'>
                             <div className='notion-calendar-body-inner-card-inner-box-title'>
                               <div className='notion-calendar-body-inner-card-inner-box-title-inner'>
                                 <div className='notion-calendar-body-inner-card-inner-box-title-inner-icon'>
-                                  <DefaultPageIcon
-                                    style={{
-                                      width: '10.8px',
-                                      height: '10.8px',
-                                      display: 'block',
-                                      fill: 'rgba(55, 53, 47, 0.85)',
-                                      flexShrink: 0,
-                                      backfaceVisibility: 'hidden'
-                                    }}
-                                  />
+                                  <DefaultPageIcon className='notion-calendar-body-inner-card-inner-box-title-inner-icon-svg' />
                                 </div>
                                 <div className='notion-calendar-body-inner-card-inner-box-title-inner-text'>
                                   <Property

From 2d89f18b111f61f9e968c27f42c61f63f982c7ac Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Sun, 11 Sep 2022 11:23:43 +0200
Subject: [PATCH 08/22] Fix today box CSS

---
 packages/react-notion-x/src/styles.css                   | 9 ++++-----
 .../src/third-party/collection-view-calendar.tsx         | 5 ++---
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/packages/react-notion-x/src/styles.css b/packages/react-notion-x/src/styles.css
index 6f991dcad..080dafbfc 100644
--- a/packages/react-notion-x/src/styles.css
+++ b/packages/react-notion-x/src/styles.css
@@ -1744,17 +1744,16 @@ svg.notion-page-icon {
   background: rgb(235, 87, 87);
 }
 
-.notion-calendar-body-inner-day-normal {
-  text-align: right;
-  transition: color 100ms ease-out 0s;
-}
-
 .notion-calendar-body-inner-day-this-month {
   color: black;
+  text-align: right;
+  transition: color 100ms ease-out 0s;
 }
 
 .notion-calendar-body-inner-day-other-month {
   color: rgba(55, 53, 47, 0.5);
+  text-align: right;
+  transition: color 100ms ease-out 0s;
 }
 
 .notion-calendar-body-inner-card {
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 0226d80ac..71b064fdd 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -241,9 +241,8 @@ function Calendar({ blockIds, collectionView, collection }) {
                         currentYear.getFullYear() ==
                           new Date(Date.now()).getFullYear()
                         ? 'notion-calendar-body-inner-day-today'
-                        : 'notion-calendar-body-inner-day-normal',
-                      (day == 1 && currentMonth++ == 0) ||
-                        ((day <= 31 || day >= 28) && currentMonth == 1)
+                        : (day == 1 && currentMonth++ == 0) ||
+                          ((day <= 31 || day >= 28) && currentMonth == 1)
                         ? 'notion-calendar-body-inner-day-this-month'
                         : 'notion-calendar-body-inner-day-other-month'
                     )}

From f0ffd8758e1aaa0475a891a624d960ed12cae9e1 Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Sun, 11 Sep 2022 11:38:29 +0200
Subject: [PATCH 09/22] Update styles.css

---
 packages/react-notion-x/src/styles.css | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/packages/react-notion-x/src/styles.css b/packages/react-notion-x/src/styles.css
index 080dafbfc..d5840f70f 100644
--- a/packages/react-notion-x/src/styles.css
+++ b/packages/react-notion-x/src/styles.css
@@ -1853,8 +1853,6 @@ svg.notion-page-icon {
   white-space: nowrap;
 }
 
-/* TODO: add calendar dark mode theme (append .dark-mode) */
-
 .dark-mode .notion-calendar-header {
   background: rgb(25, 25, 25);
 }
@@ -1920,8 +1918,6 @@ svg.notion-page-icon {
   background: rgba(255, 255, 255, 0.055);
 }
 
-/**/
-
 .notion-board {
   width: 100vw;
   max-width: 100vw;

From d129da0a77df9fc346bd9817c281abbdf5ca7943 Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Sun, 11 Sep 2022 18:11:34 +0200
Subject: [PATCH 10/22] Update collection-view-calendar.tsx

Fix linked calendars db errors
---
 .../src/third-party/collection-view-calendar.tsx            | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 71b064fdd..153f4d6e0 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -213,9 +213,10 @@ function Calendar({ blockIds, collectionView, collection }) {
             className='notion-calendar-body-inner'
             style={{
               height: `${
+                collectionView.format?.calendar_properties &&
                 Object.keys(collectionView.format?.calendar_properties).length *
                   20 +
-                64
+                  64
               }px`
             }}
             key={indexI}
@@ -286,11 +287,12 @@ function Calendar({ blockIds, collectionView, collection }) {
                               : new Date(blockDate as number).getDay() * 14.2857
                           }%)`,
                           height: `${
+                            collectionView.format?.calendar_properties &&
                             Object.keys(
                               collectionView.format?.calendar_properties
                             ).length *
                               20 +
-                            30
+                              30
                           }px`
                         }}
                         key={blockId}

From 9cdb9c52347f3804140b024ff5512517d036e721 Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Tue, 13 Sep 2022 18:29:30 +0200
Subject: [PATCH 11/22] Update styles.css

Removed unused class
---
 packages/react-notion-x/src/styles.css | 1 -
 1 file changed, 1 deletion(-)

diff --git a/packages/react-notion-x/src/styles.css b/packages/react-notion-x/src/styles.css
index d5840f70f..ddd441922 100644
--- a/packages/react-notion-x/src/styles.css
+++ b/packages/react-notion-x/src/styles.css
@@ -1882,7 +1882,6 @@ svg.notion-page-icon {
   background: rgb(32, 32, 32);
 }
 
-.dark-mode .notion-calendar-body-inner-day-normal,
 .dark-mode .notion-calendar-body-inner-day-this-month {
   color: white;
 }

From 5045948b990dce242e92361cadc2c2d8f4da8767 Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Tue, 20 Sep 2022 12:33:07 +0200
Subject: [PATCH 12/22] Update collection-view-calendar.tsx

Full width for full page collection view
---
 .../third-party/collection-view-calendar.tsx    | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 153f4d6e0..3418af41c 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -83,6 +83,11 @@ export const CollectionViewCalendar: React.FC<CollectionViewProps> = ({
 function Calendar({ blockIds, collectionView, collection }) {
   const { showCalendarControls, components, recordMap, mapPageUrl } =
     useNotionContext()
+
+  const isCollectionViewPage =
+    recordMap.block[Object.keys(recordMap.block)[0]].value.type ==
+    'collection_view_page'
+
   const [weeksArr, setWeeksArr] = React.useState(
     getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
   )
@@ -126,6 +131,12 @@ function Calendar({ blockIds, collectionView, collection }) {
     )
   }
 
+  React.useEffect(() => {
+    if (isCollectionViewPage) {
+      document.querySelector('.notion-page').classList.add('notion-full-width')
+    }
+  }, [])
+
   return (
     <div className='notion-calendar-view'>
       <div className='notion-calendar-header'>
@@ -210,7 +221,11 @@ function Calendar({ blockIds, collectionView, collection }) {
       <div className='notion-calendar-body'>
         {weeksArr.map((i, indexI) => (
           <div
-            className='notion-calendar-body-inner'
+            className={cs(
+              'notion-calendar-body-inner',
+              weeksArr.length - 1 == indexI &&
+                'notion-calendar-body-inner-last-week'
+            )}
             style={{
               height: `${
                 collectionView.format?.calendar_properties &&

From 4bd0b1131880e30d8f60527bf6b3924d61a2755b Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Fri, 23 Sep 2022 15:56:41 +0200
Subject: [PATCH 13/22] Now can start weeks on monday

- Added the ability to start weeks on Monday via `startWeekOnMonday`
- Made proper icons components for calendar controls
---
 packages/react-notion-x/src/context.tsx       |   3 +
 .../react-notion-x/src/icons/left-chevron.tsx |  11 ++
 .../src/icons/right-chevron.tsx               |  11 ++
 packages/react-notion-x/src/renderer.tsx      |   3 +
 .../third-party/collection-view-calendar.tsx  | 101 ++++++++++++------
 packages/react-notion-x/src/utils.ts          |  29 +++--
 6 files changed, 120 insertions(+), 38 deletions(-)
 create mode 100644 packages/react-notion-x/src/icons/left-chevron.tsx
 create mode 100644 packages/react-notion-x/src/icons/right-chevron.tsx

diff --git a/packages/react-notion-x/src/context.tsx b/packages/react-notion-x/src/context.tsx
index 35837bb34..400f4633e 100644
--- a/packages/react-notion-x/src/context.tsx
+++ b/packages/react-notion-x/src/context.tsx
@@ -30,6 +30,7 @@ export interface NotionContext {
   forceCustomImages: boolean
   showCollectionViewDropdown: boolean
   showCalendarControls: boolean
+  startWeekOnMonday: boolean
   showTableOfContents: boolean
   minTableOfContentsItems: number
   linkTableTitleProperties: boolean
@@ -61,6 +62,7 @@ export interface PartialNotionContext {
 
   showTableOfContents?: boolean
   showCalendarControls?: boolean
+  startWeekOnMonday?: boolean
   minTableOfContentsItems?: number
 
   defaultPageIcon?: string
@@ -160,6 +162,7 @@ const defaultNotionContext: NotionContext = {
 
   showTableOfContents: false,
   showCalendarControls: true,
+  startWeekOnMonday: false,
   minTableOfContentsItems: 3,
 
   defaultPageIcon: null,
diff --git a/packages/react-notion-x/src/icons/left-chevron.tsx b/packages/react-notion-x/src/icons/left-chevron.tsx
new file mode 100644
index 000000000..b2e5e0ccd
--- /dev/null
+++ b/packages/react-notion-x/src/icons/left-chevron.tsx
@@ -0,0 +1,11 @@
+import * as React from 'react'
+
+function SvgLeftChevron(props: React.SVGProps<SVGSVGElement>) {
+  return (
+    <svg viewBox='0 0 30 30' {...props}>
+      <polygon points='12.6 15 23 25.2 20.2 28 7 15 20.2 2 23 4.8'></polygon>
+    </svg>
+  )
+}
+
+export default SvgLeftChevron
diff --git a/packages/react-notion-x/src/icons/right-chevron.tsx b/packages/react-notion-x/src/icons/right-chevron.tsx
new file mode 100644
index 000000000..10862f272
--- /dev/null
+++ b/packages/react-notion-x/src/icons/right-chevron.tsx
@@ -0,0 +1,11 @@
+import * as React from 'react'
+
+function SvgRightChevron(props: React.SVGProps<SVGSVGElement>) {
+  return (
+    <svg viewBox='0 0 30 30' {...props}>
+      <polygon points='17.4,15 7,25.2 9.8,28 23,15 9.8,2 7,4.8'></polygon>
+    </svg>
+  )
+}
+
+export default SvgRightChevron
diff --git a/packages/react-notion-x/src/renderer.tsx b/packages/react-notion-x/src/renderer.tsx
index 3adbe40ab..fa56ce378 100644
--- a/packages/react-notion-x/src/renderer.tsx
+++ b/packages/react-notion-x/src/renderer.tsx
@@ -35,6 +35,7 @@ export const NotionRenderer: React.FC<{
 
   showTableOfContents?: boolean
   showCalendarControls?: boolean
+  startWeekOnMonday?: boolean
   minTableOfContentsItems?: number
 
   defaultPageIcon?: string
@@ -72,6 +73,7 @@ export const NotionRenderer: React.FC<{
   isImageZoomable = true,
   showTableOfContents,
   showCalendarControls,
+  startWeekOnMonday,
   minTableOfContentsItems,
   defaultPageIcon,
   defaultPageCover,
@@ -106,6 +108,7 @@ export const NotionRenderer: React.FC<{
       linkTableTitleProperties={linkTableTitleProperties}
       showTableOfContents={showTableOfContents}
       showCalendarControls={showCalendarControls}
+      startWeekOnMonday={startWeekOnMonday}
       minTableOfContentsItems={minTableOfContentsItems}
       defaultPageIcon={defaultPageIcon}
       defaultPageCover={defaultPageCover}
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 3418af41c..8483abf37 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -3,6 +3,8 @@ import { getPagePropertyFromId } from 'notion-utils'
 import * as React from 'react'
 import { useNotionContext } from '../context'
 import { DefaultPageIcon } from '../icons/default-page-icon'
+import SvgLeftChevron from '../icons/left-chevron'
+import SvgRightChevron from '../icons/right-chevron'
 import { CollectionViewProps } from '../types'
 import { cs, getWeeksInMonth } from '../utils'
 import { CollectionGroup } from './collection-group'
@@ -81,17 +83,27 @@ export const CollectionViewCalendar: React.FC<CollectionViewProps> = ({
 }
 
 function Calendar({ blockIds, collectionView, collection }) {
-  const { showCalendarControls, components, recordMap, mapPageUrl } =
-    useNotionContext()
+  const {
+    showCalendarControls,
+    startWeekOnMonday,
+    components,
+    recordMap,
+    mapPageUrl
+  } = useNotionContext()
 
+  const [weeksArr, setWeeksArr] = React.useState(
+    getWeeksInMonth(
+      currentYear.getFullYear(),
+      currentYear.getMonth(),
+      startWeekOnMonday
+    )
+  )
+
+  // Check if collection view is a standalone page or not
   const isCollectionViewPage =
     recordMap.block[Object.keys(recordMap.block)[0]].value.type ==
     'collection_view_page'
 
-  const [weeksArr, setWeeksArr] = React.useState(
-    getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
-  )
-
   const nextMonth = () => {
     if (currentYear.getMonth() == 11) {
       currentYear.setFullYear(currentYear.getFullYear() + 1)
@@ -103,7 +115,11 @@ function Calendar({ blockIds, collectionView, collection }) {
     currentMonth = 0
 
     setWeeksArr(
-      getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
+      getWeeksInMonth(
+        currentYear.getFullYear(),
+        currentYear.getMonth(),
+        startWeekOnMonday
+      )
     )
   }
   const prevMonth = () => {
@@ -117,7 +133,11 @@ function Calendar({ blockIds, collectionView, collection }) {
     currentMonth = 0
 
     setWeeksArr(
-      getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
+      getWeeksInMonth(
+        currentYear.getFullYear(),
+        currentYear.getMonth(),
+        startWeekOnMonday
+      )
     )
   }
   const nowMonth = () => {
@@ -127,10 +147,15 @@ function Calendar({ blockIds, collectionView, collection }) {
     currentMonth = 0
 
     setWeeksArr(
-      getWeeksInMonth(currentYear.getFullYear(), currentYear.getMonth())
+      getWeeksInMonth(
+        currentYear.getFullYear(),
+        currentYear.getMonth(),
+        startWeekOnMonday
+      )
     )
   }
 
+  // Check on page load if the collection is a page or not
   React.useEffect(() => {
     if (isCollectionViewPage) {
       document.querySelector('.notion-page').classList.add('notion-full-width')
@@ -162,12 +187,7 @@ function Calendar({ blockIds, collectionView, collection }) {
                 tabIndex={0}
                 onClick={prevMonth}
               >
-                <svg
-                  viewBox='0 0 30 30'
-                  className='notion-calendar-header-inner-controls-prev-svg'
-                >
-                  <polygon points='12.6 15 23 25.2 20.2 28 7 15 20.2 2 23 4.8'></polygon>
-                </svg>
+                <SvgLeftChevron className='notion-calendar-header-inner-controls-prev-svg' />
               </div>
 
               <div
@@ -190,25 +210,34 @@ function Calendar({ blockIds, collectionView, collection }) {
                 tabIndex={0}
                 onClick={nextMonth}
               >
-                <svg
-                  viewBox='0 0 30 30'
-                  className='notion-calendar-header-inner-controls-next-svg'
-                >
-                  <polygon points='17.4,15 7,25.2 9.8,28 23,15 9.8,2 7,4.8'></polygon>
-                </svg>
+                <SvgRightChevron className='notion-calendar-header-inner-controls-next-svg' />
               </div>
             </>
           )}
         </div>
 
         <div className='notion-calendar-header-days'>
-          <div className='notion-calendar-header-days-day'>Sun</div>
-          <div className='notion-calendar-header-days-day'>Mon</div>
-          <div className='notion-calendar-header-days-day'>Tue</div>
-          <div className='notion-calendar-header-days-day'>Wed</div>
-          <div className='notion-calendar-header-days-day'>Thu</div>
-          <div className='notion-calendar-header-days-day'>Fri</div>
-          <div className='notion-calendar-header-days-day'>Sat</div>
+          {startWeekOnMonday ? (
+            <>
+              <div className='notion-calendar-header-days-day'>Mon</div>
+              <div className='notion-calendar-header-days-day'>Tue</div>
+              <div className='notion-calendar-header-days-day'>Wed</div>
+              <div className='notion-calendar-header-days-day'>Thu</div>
+              <div className='notion-calendar-header-days-day'>Fri</div>
+              <div className='notion-calendar-header-days-day'>Sat</div>
+              <div className='notion-calendar-header-days-day'>Sun</div>
+            </>
+          ) : (
+            <>
+              <div className='notion-calendar-header-days-day'>Sun</div>
+              <div className='notion-calendar-header-days-day'>Mon</div>
+              <div className='notion-calendar-header-days-day'>Tue</div>
+              <div className='notion-calendar-header-days-day'>Wed</div>
+              <div className='notion-calendar-header-days-day'>Thu</div>
+              <div className='notion-calendar-header-days-day'>Fri</div>
+              <div className='notion-calendar-header-days-day'>Sat</div>
+            </>
+          )}
         </div>
       </div>
 
@@ -242,7 +271,11 @@ function Calendar({ blockIds, collectionView, collection }) {
                   className={cs(
                     'notion-selectable',
                     'notion-calendar-body-inner-week',
-                    indexY == 0 || indexY == 6
+                    startWeekOnMonday
+                      ? indexY == 5 || indexY == 6
+                        ? 'notion-calendar-body-inner-week-dif'
+                        : ''
+                      : indexY == 0 || indexY == 6
                       ? 'notion-calendar-body-inner-week-dif'
                       : ''
                   )}
@@ -281,6 +314,12 @@ function Calendar({ blockIds, collectionView, collection }) {
                     block,
                     recordMap
                   )
+                  const blockDateDATE = new Date(blockDate as number)
+                  const dayBlock = startWeekOnMonday
+                    ? blockDateDATE.getDay() === 0
+                      ? 6
+                      : blockDateDATE.getDay() - 1
+                    : blockDateDATE.getDay()
 
                   const titleSchema = collection.schema.title
                   const titleData = block?.properties?.title
@@ -297,9 +336,7 @@ function Calendar({ blockIds, collectionView, collection }) {
                         className='notion-calendar-body-inner-card'
                         style={{
                           left: `calc(${
-                            new Date(blockDate as number).getDay() == 0
-                              ? 0
-                              : new Date(blockDate as number).getDay() * 14.2857
+                            dayBlock == 0 ? 0 : dayBlock * 14.2857
                           }%)`,
                           height: `${
                             collectionView.format?.calendar_properties &&
diff --git a/packages/react-notion-x/src/utils.ts b/packages/react-notion-x/src/utils.ts
index e6636eaf7..8ec2370b2 100644
--- a/packages/react-notion-x/src/utils.ts
+++ b/packages/react-notion-x/src/utils.ts
@@ -83,13 +83,21 @@ export const getYoutubeId = (url: string): string | null => {
   return null
 }
 
-export const getWeeksInMonth = (year: number, month: number) => {
+export const getWeeksInMonth = (
+  year: number,
+  month: number,
+  startOnMonday?: boolean
+) => {
   const weeks = []
 
   const firstDate = new Date(year, month, 1)
   const lastDate = new Date(year, month + 1, 0)
   const numDays = lastDate.getDate()
-  let dayOfWeekCounter = firstDate.getDay()
+  let dayOfWeekCounter = startOnMonday
+    ? firstDate.getDay() === 0
+      ? 6
+      : firstDate.getDay() - 1
+    : firstDate.getDay()
 
   for (let date = 1; date <= numDays; date++) {
     if (dayOfWeekCounter === 0 || weeks.length === 0) {
@@ -101,14 +109,14 @@ export const getWeeksInMonth = (year: number, month: number) => {
 
   // This is to add the last week of the previous month to the first week of the current month.
   if (weeks[0].length < 7) {
-    const beforeIndex1 = addMonth(year, month - 1, 1)
+    const beforeIndex1 = addMonth(year, month - 1, 1, startOnMonday)
     const indexRefactor = [...beforeIndex1, ...weeks[0]]
     weeks[0] = indexRefactor
   }
 
   // This is to add the first week of the next month to the last week of the current month
   if (weeks[weeks.length - 1].length < 7) {
-    const afterIndex1 = addMonth(year, month + 1, 0)
+    const afterIndex1 = addMonth(year, month + 1, 0, startOnMonday)
     const indexRefactor = [...weeks[weeks.length - 1], ...afterIndex1]
     weeks[weeks.length - 1] = indexRefactor
   }
@@ -122,12 +130,21 @@ export const getWeeksInMonth = (year: number, month: number) => {
     }))
 }
 
-const addMonth = (year: number, month: number, flag: 0 | 1) => {
+const addMonth = (
+  year: number,
+  month: number,
+  flag: 0 | 1,
+  startOnMonday: boolean
+) => {
   const weeks = []
   const firstDate = new Date(year, month, 1)
   const lastDate = new Date(year, month + 1, 0)
   const numDays = lastDate.getDate()
-  let dayOfWeekCounter = firstDate.getDay()
+  let dayOfWeekCounter = startOnMonday
+    ? firstDate.getDay() === 0
+      ? 6
+      : firstDate.getDay() - 1
+    : firstDate.getDay()
 
   for (let date = 1; date <= numDays; date++) {
     if (dayOfWeekCounter === 0 || weeks.length === 0) {

From 78e122f52aaee3bb724b929e746691f95647a5ab Mon Sep 17 00:00:00 2001
From: MichaelCasaDev <michael.casa04@gmail.com>
Date: Fri, 23 Sep 2022 16:16:34 +0200
Subject: [PATCH 14/22] Update readme.md

---
 readme.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/readme.md b/readme.md
index 476c7748d..35d5037b2 100644
--- a/readme.md
+++ b/readme.md
@@ -243,7 +243,7 @@ The majority of Notion blocks and collection views are fully supported.
 | Collection View Gallery  | ✅ Yes     | `collection_view`      | `type = "gallery"` (grid view)                                                                                   |
 | Collection View Board    | ✅ Yes     | `collection_view`      | `type = "board"` (kanban view)                                                                                   |
 | Collection View List     | ✅ Yes     | `collection_view`      | `type = "list"` (vertical list view)                                                                             |
-| Collection View Calendar | ❌ Missing | `collection_view`      | `type = "calendar"` (embedded calendar view)                                                                     |
+| Collection View Calendar | ✅ Yes     | `collection_view`      | `type = "calendar"` (embedded calendar view)                                                                     |
 | Collection View Page     | ✅ Yes     | `collection_view_page` | Collection view as a standalone page                                                                             |
 
 Please let us know if you find any issues or missing blocks.

From 91e6118a5a8977a5f6d493faeef05ab42d5b413c Mon Sep 17 00:00:00 2001
From: Michael Casagrande <michael.casa04@gmail.com>
Date: Fri, 3 Feb 2023 18:10:34 +0100
Subject: [PATCH 15/22] Lot of fixes

- Now page blocks are correctly rendered into the calendar view
- New function method to generate weeks in month
- Fixed some CSS
---
 packages/react-notion-x/src/styles.css        |  12 +-
 .../third-party/collection-view-calendar.tsx  | 131 ++++++++++--------
 packages/react-notion-x/src/utils.ts          | 125 ++++++++---------
 3 files changed, 141 insertions(+), 127 deletions(-)

diff --git a/packages/react-notion-x/src/styles.css b/packages/react-notion-x/src/styles.css
index c6e773420..5b0d4fefa 100644
--- a/packages/react-notion-x/src/styles.css
+++ b/packages/react-notion-x/src/styles.css
@@ -77,7 +77,7 @@
   --fg-color-6: #fff;
   --fg-color-icon: #fff;
 
-  --bg-color: rgb(25, 25, 25);
+  --bg-color: #2f3437;
   --bg-color-0: rgb(71, 76, 80);
   --bg-color-1: rgb(63, 68, 71);
   --bg-color-2: rgba(135, 131, 120, 0.15);
@@ -1607,8 +1607,8 @@ svg.notion-page-icon {
 
 .notion-calendar-header {
   position: absolute;
-  left: 0px;
-  right: 0px;
+  left: 0;
+  right: 0;
   background: white;
   z-index: 83;
 }
@@ -3058,7 +3058,7 @@ svg.notion-page-icon {
   display: flex;
   flex-direction: row;
   flex-wrap: wrap;
-  width: 120%
+  width: 120%;
 }
 
 .notion-collection-view-tabs-content-item {
@@ -3108,9 +3108,9 @@ svg.notion-page-icon {
 }
 
 .nested-form-link {
-  background: none!important;
+  background: none !important;
   border: none;
-  padding: 0!important;
+  padding: 0 !important;
   text-decoration: underline;
   cursor: pointer;
 }
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 8483abf37..2e8de77d6 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -1,6 +1,8 @@
+import * as React from 'react'
+
 import { PageBlock } from 'notion-types'
 import { getPagePropertyFromId } from 'notion-utils'
-import * as React from 'react'
+
 import { useNotionContext } from '../context'
 import { DefaultPageIcon } from '../icons/default-page-icon'
 import SvgLeftChevron from '../icons/left-chevron'
@@ -12,7 +14,7 @@ import { getCollectionGroups } from './collection-utils'
 import { Property } from './property'
 
 const defaultBlockIds = []
-const currentYear = new Date(Date.now())
+const currentYear = new Date()
 const months = [
   'January',
   'February',
@@ -42,7 +44,6 @@ const monthsShort = [
   'Nov',
   'Dec'
 ]
-let currentMonth = 0
 
 export const CollectionViewCalendar: React.FC<CollectionViewProps> = ({
   collection,
@@ -91,6 +92,7 @@ function Calendar({ blockIds, collectionView, collection }) {
     mapPageUrl
   } = useNotionContext()
 
+  const [currentMonth, setCurrentMonth] = React.useState(0)
   const [weeksArr, setWeeksArr] = React.useState(
     getWeeksInMonth(
       currentYear.getFullYear(),
@@ -99,11 +101,6 @@ function Calendar({ blockIds, collectionView, collection }) {
     )
   )
 
-  // Check if collection view is a standalone page or not
-  const isCollectionViewPage =
-    recordMap.block[Object.keys(recordMap.block)[0]].value.type ==
-    'collection_view_page'
-
   const nextMonth = () => {
     if (currentYear.getMonth() == 11) {
       currentYear.setFullYear(currentYear.getFullYear() + 1)
@@ -112,7 +109,7 @@ function Calendar({ blockIds, collectionView, collection }) {
       currentYear.setMonth(currentYear.getMonth() + 1)
     }
 
-    currentMonth = 0
+    setCurrentMonth(0)
 
     setWeeksArr(
       getWeeksInMonth(
@@ -130,7 +127,7 @@ function Calendar({ blockIds, collectionView, collection }) {
       currentYear.setMonth(currentYear.getMonth() - 1)
     }
 
-    currentMonth = 0
+    setCurrentMonth(0)
 
     setWeeksArr(
       getWeeksInMonth(
@@ -144,7 +141,7 @@ function Calendar({ blockIds, collectionView, collection }) {
     currentYear.setMonth(new Date().getMonth())
     currentYear.setFullYear(new Date().getFullYear())
 
-    currentMonth = 0
+    setCurrentMonth(0)
 
     setWeeksArr(
       getWeeksInMonth(
@@ -155,7 +152,49 @@ function Calendar({ blockIds, collectionView, collection }) {
     )
   }
 
-  // Check on page load if the collection is a page or not
+  const checkWeek = (weekNumber: number) => {
+    let max = 0
+
+    for (let i = 0; i < 7; i++) {
+      const newMax = getPagesThisDay(weeksArr[weekNumber][i]).length
+      if (max < newMax) max = newMax
+    }
+
+    return max
+  }
+
+  const getPagesThisDay = (day: { date: number; month: number }) => {
+    const daysTo = []
+
+    blockIds?.map((blockId) => {
+      const block = recordMap.block[blockId]?.value as PageBlock
+      if (!block) return null
+
+      // Get date from calendar view query
+      const blockDate = getPagePropertyFromId(
+        collectionView.query2.calendar_by,
+        block,
+        recordMap
+      )
+      const blockDateDATE = new Date(blockDate as number)
+      if (
+        blockDateDATE.getDate() == day.date &&
+        blockDateDATE.getMonth() == day.month &&
+        blockDateDATE.getFullYear() == currentYear.getFullYear()
+      ) {
+        daysTo.push(block)
+      }
+    })
+
+    return daysTo
+  }
+
+  // Check if collection view is a standalone page or not
+  const isCollectionViewPage =
+    recordMap.block[Object.keys(recordMap.block)[0]].value.type ===
+    'collection_view_page'
+
+  // This is needed because calendar view pages need to be full width (like Notion)
   React.useEffect(() => {
     if (isCollectionViewPage) {
       document.querySelector('.notion-page').classList.add('notion-full-width')
@@ -256,16 +295,19 @@ function Calendar({ blockIds, collectionView, collection }) {
                 'notion-calendar-body-inner-last-week'
             )}
             style={{
-              height: `${
+              /*height: `${
                 collectionView.format?.calendar_properties &&
                 Object.keys(collectionView.format?.calendar_properties).length *
                   20 +
                   64
+              }px`*/
+              height: `${
+                checkWeek(indexI) == 0 ? 143.99 : checkWeek(indexI) * 110 + 34
               }px`
             }}
             key={indexI}
           >
-            {i.dates.map((day, indexY) => (
+            {i.map((day, indexY: number) => (
               <>
                 <div
                   className={cs(
@@ -284,30 +326,26 @@ function Calendar({ blockIds, collectionView, collection }) {
                   <div
                     className={cs(
                       'notion-calendar-body-inner-day',
-                      day == new Date(Date.now()).getDate() &&
-                        currentYear.getMonth() ==
-                          new Date(Date.now()).getMonth() &&
-                        currentYear.getFullYear() ==
-                          new Date(Date.now()).getFullYear()
+
+                      day.date == new Date().getDate() &&
+                        day.month == new Date().getMonth() &&
+                        currentYear.getFullYear() == new Date().getFullYear()
                         ? 'notion-calendar-body-inner-day-today'
-                        : (day == 1 && currentMonth++ == 0) ||
-                          ((day <= 31 || day >= 28) && currentMonth == 1)
+                        : (day.date == 1 &&
+                            currentYear.getMonth() == day.month) ||
+                          ((day.date <= 31 || day.date >= 28) &&
+                            currentYear.getMonth() == day.month)
                         ? 'notion-calendar-body-inner-day-this-month'
                         : 'notion-calendar-body-inner-day-other-month'
                     )}
                   >
-                    {day == 1
-                      ? `${
-                          monthsShort[currentYear.getMonth() + currentMonth - 1]
-                        } ${day}`
-                      : day}
+                    {day.date == 1
+                      ? `${monthsShort[day.month + currentMonth]} ${day.date}`
+                      : day.date}
                   </div>
                 </div>
 
-                {blockIds?.map((blockId) => {
-                  const block = recordMap.block[blockId]?.value as PageBlock
-                  if (!block) return null
-
+                {getPagesThisDay(day).map((block, sum) => {
                   // Get date from calendar view query
                   const blockDate = getPagePropertyFromId(
                     collectionView.query2.calendar_by,
@@ -325,11 +363,9 @@ function Calendar({ blockIds, collectionView, collection }) {
                   const titleData = block?.properties?.title
 
                   if (
-                    new Date(blockDate as number).getDate() == day &&
-                    new Date(blockDate as number).getMonth() ==
-                      currentYear.getMonth() &&
-                    new Date(blockDate as number).getFullYear() ==
-                      currentYear.getFullYear()
+                    blockDateDATE.getDate() == day.date &&
+                    blockDateDATE.getMonth() == day.month &&
+                    blockDateDATE.getFullYear() == currentYear.getFullYear()
                   ) {
                     return (
                       <div
@@ -345,9 +381,12 @@ function Calendar({ blockIds, collectionView, collection }) {
                             ).length *
                               20 +
                               30
+                          }px`,
+                          top: `${
+                            (checkWeek(indexI) != 0 ? sum * 110 : 0) + 30
                           }px`
                         }}
-                        key={blockId}
+                        key={block.id}
                       >
                         <components.PageLink
                           href={mapPageUrl(block.id)}
@@ -398,26 +437,6 @@ function Calendar({ blockIds, collectionView, collection }) {
                                   )
                                 })}
                             </div>
-                            <div
-                              style={{
-                                position: 'absolute',
-                                top: '0px',
-                                left: '-4px',
-                                height: '100%',
-                                width: '12px',
-                                cursor: 'col-resize'
-                              }}
-                            ></div>
-                            <div
-                              style={{
-                                position: 'absolute',
-                                top: '0px',
-                                right: '-4px',
-                                height: '100%',
-                                width: '12px',
-                                cursor: 'col-resize'
-                              }}
-                            ></div>
                           </div>
                         </components.PageLink>
                       </div>
diff --git a/packages/react-notion-x/src/utils.ts b/packages/react-notion-x/src/utils.ts
index 8ec2370b2..f1ca64cb2 100644
--- a/packages/react-notion-x/src/utils.ts
+++ b/packages/react-notion-x/src/utils.ts
@@ -86,78 +86,73 @@ export const getYoutubeId = (url: string): string | null => {
 export const getWeeksInMonth = (
   year: number,
   month: number,
-  startOnMonday?: boolean
+  startWeekOnMonday?: boolean
 ) => {
-  const weeks = []
-
-  const firstDate = new Date(year, month, 1)
-  const lastDate = new Date(year, month + 1, 0)
-  const numDays = lastDate.getDate()
-  let dayOfWeekCounter = startOnMonday
-    ? firstDate.getDay() === 0
-      ? 6
-      : firstDate.getDay() - 1
-    : firstDate.getDay()
-
-  for (let date = 1; date <= numDays; date++) {
-    if (dayOfWeekCounter === 0 || weeks.length === 0) {
-      weeks.push([])
-    }
-    weeks[weeks.length - 1].push(date)
-    dayOfWeekCounter = (dayOfWeekCounter + 1) % 7
+  const weeks = [],
+    firstDate = new Date(year, month, 1),
+    lastDate = new Date(year, month + 1, 0),
+    numDays = lastDate.getDate()
+
+  let start = 1
+  let end = -1
+
+  if (firstDate.getDay() === 1) {
+    end = 7
+  } else if (firstDate.getDay() === 0) {
+    const preMonthEndDay = new Date(year, month, 0)
+
+    start = preMonthEndDay.getDate() - 6 + 1
+    end = 1
+  } else {
+    const preMonthEndDay = new Date(year, month, 0)
+
+    start =
+      preMonthEndDay.getDate() +
+      1 -
+      firstDate.getDay() +
+      (startWeekOnMonday ? 1 : 0)
+    end = 7 - firstDate.getDay() + (startWeekOnMonday ? 1 : 0)
+
+    weeks.push({
+      start: start,
+      end: end
+    })
+
+    start = end + 1
+    end = end + 7
   }
 
-  // This is to add the last week of the previous month to the first week of the current month.
-  if (weeks[0].length < 7) {
-    const beforeIndex1 = addMonth(year, month - 1, 1, startOnMonday)
-    const indexRefactor = [...beforeIndex1, ...weeks[0]]
-    weeks[0] = indexRefactor
-  }
+  while (start <= numDays) {
+    weeks.push({
+      start: start,
+      end: end
+    })
 
-  // This is to add the first week of the next month to the last week of the current month
-  if (weeks[weeks.length - 1].length < 7) {
-    const afterIndex1 = addMonth(year, month + 1, 0, startOnMonday)
-    const indexRefactor = [...weeks[weeks.length - 1], ...afterIndex1]
-    weeks[weeks.length - 1] = indexRefactor
-  }
+    start = end + 1
+    end += 7
+    end = start === 1 && end === 8 ? 1 : end
 
-  return weeks
-    .filter((w) => !!w.length)
-    .map((w) => ({
-      start: w[0],
-      end: w[w.length - 1],
-      dates: w
-    }))
-}
+    if (end > numDays && start <= numDays) {
+      end = end - numDays
 
-const addMonth = (
-  year: number,
-  month: number,
-  flag: 0 | 1,
-  startOnMonday: boolean
-) => {
-  const weeks = []
-  const firstDate = new Date(year, month, 1)
-  const lastDate = new Date(year, month + 1, 0)
-  const numDays = lastDate.getDate()
-  let dayOfWeekCounter = startOnMonday
-    ? firstDate.getDay() === 0
-      ? 6
-      : firstDate.getDay() - 1
-    : firstDate.getDay()
-
-  for (let date = 1; date <= numDays; date++) {
-    if (dayOfWeekCounter === 0 || weeks.length === 0) {
-      weeks.push([])
+      weeks.push({
+        start: start,
+        end: end
+      })
+
+      break
     }
-    weeks[weeks.length - 1].push(date)
-    dayOfWeekCounter = (dayOfWeekCounter + 1) % 7
-  }
-  if (flag == 0) {
-    return weeks[0]
-  } else if (flag == 1) {
-    return weeks[weeks.length - 1]
   }
 
-  return []
+  return weeks.map(({ start, end }, index) => {
+    const sub = +(start > end && index === 0)
+    return Array.from({ length: 7 }, (_, index) => {
+      const date = new Date(year, month - sub, start + index)
+
+      return {
+        date: date.getDate(),
+        month: date.getMonth()
+      }
+    })
+  })
 }

From b8d6cea86ca4cb6c1fc2382151a7126b860866c1 Mon Sep 17 00:00:00 2001
From: Michael Casagrande <michael.casa04@gmail.com>
Date: Fri, 3 Feb 2023 22:06:27 +0100
Subject: [PATCH 16/22] More styling

- Fixed CSSs (using CSS vars)
- Now page icon is correctly updated
---
 packages/react-notion-x/src/styles.css        | 112 +++++-------------
 .../third-party/collection-view-calendar.tsx  |  15 ++-
 2 files changed, 37 insertions(+), 90 deletions(-)

diff --git a/packages/react-notion-x/src/styles.css b/packages/react-notion-x/src/styles.css
index 5b0d4fefa..1f55e86a2 100644
--- a/packages/react-notion-x/src/styles.css
+++ b/packages/react-notion-x/src/styles.css
@@ -16,6 +16,9 @@
   --bg-color-0: rgba(135, 131, 120, 0.15);
   --bg-color-1: rgb(247, 246, 243);
   --bg-color-2: rgba(135, 131, 120, 0.15);
+  --bg-color-3: #fff;
+
+  --box-shadow: rgba(15, 15, 15, 0.1);
 
   --select-color-0: rgb(46, 170, 220);
   --select-color-1: rgba(45, 170, 219, 0.3);
@@ -81,6 +84,9 @@
   --bg-color-0: rgb(71, 76, 80);
   --bg-color-1: rgb(63, 68, 71);
   --bg-color-2: rgba(135, 131, 120, 0.15);
+  --bg-color-3: rgb(47, 47, 47);
+
+  --box-shadow: rgba(20, 20, 20, 0.1);
 
   --notion-red: rgb(255, 115, 105);
   --notion-pink: rgb(226, 85, 161);
@@ -1459,7 +1465,7 @@ svg.notion-page-icon {
   overflow: hidden;
 
   text-decoration: none;
-  box-shadow: rgba(15, 15, 15, 0.1) 0 0 0 1px, rgba(15, 15, 15, 0.1) 0 2px 4px;
+  box-shadow: var(--box-shadow) 0 0 0 1px, var(--box-shadow) 0 2px 4px;
   border-radius: 3px;
   background: var(--bg-color);
   color: var(--fg-color);
@@ -1609,7 +1615,7 @@ svg.notion-page-icon {
   position: absolute;
   left: 0;
   right: 0;
-  background: white;
+  background: var(--bg-color);
   z-index: 83;
 }
 
@@ -1644,7 +1650,7 @@ svg.notion-page-icon {
 .notion-calendar-header-inner-controls-prev:hover,
 .notion-calendar-header-inner-controls-today:hover,
 .notion-calendar-header-inner-controls-next:hover {
-  background: rgba(55, 53, 47, 0.08);
+  background: var(--notion-gray_background);
 }
 
 .notion-calendar-header-inner-controls-today {
@@ -1662,7 +1668,7 @@ svg.notion-page-icon {
   min-width: 0px;
   padding-left: 6px;
   padding-right: 6px;
-  color: rgb(55, 53, 47);
+  color: var(--fg-color);
 }
 
 .notion-calendar-header-inner-controls-next {
@@ -1684,7 +1690,7 @@ svg.notion-page-icon {
   width: 14px;
   height: 14px;
   display: block;
-  fill: rgba(55, 53, 47, 0.45);
+  fill: var(--fg-color-2);
   flex-shrink: 0;
   backface-visibility: hidden;
 }
@@ -1692,7 +1698,7 @@ svg.notion-page-icon {
 .notion-calendar-header-days {
   display: flex;
   margin-top: 0px;
-  box-shadow: rgb(233 233 231) 0px 1px 0px;
+  box-shadow: var(--notion-gray_background) 0px 1px 0px;
 }
 
 .notion-calendar-header-days-day {
@@ -1701,11 +1707,11 @@ svg.notion-page-icon {
   text-align: center;
   font-size: 12px;
   height: 24px;
-  color: rgba(55, 53, 47, 0.5);
+  color: var(--fg-color-3);
 }
 
 .notion-calendar-body {
-  box-shadow: rgb(233 233 231) -1px 0px 0px;
+  box-shadow: var(--notion-gray_background) -1px 0px 0px;
   margin-top: 1px;
   overflow: hidden;
 }
@@ -1718,13 +1724,13 @@ svg.notion-page-icon {
 .notion-calendar-body-inner-week {
   position: relative;
   flex: 1 0 0px;
-  border-right: 1px solid rgb(233, 233, 231);
-  border-bottom: 1px solid rgb(233, 233, 231);
+  border-right: 1px solid var(--notion-gray_background);
+  border-bottom: 1px solid var(--notion-gray_background);
   cursor: default;
 }
 
 .notion-calendar-body-inner-week-dif {
-  background: rgb(251, 251, 250);
+  background: var(--bg-color-1);
 }
 
 .notion-calendar-body-inner-day {
@@ -1741,17 +1747,17 @@ svg.notion-page-icon {
   border-radius: 100%;
   text-align: center;
   color: white;
-  background: rgb(235, 87, 87);
+  background: var(--notion-red);
 }
 
 .notion-calendar-body-inner-day-this-month {
-  color: black;
+  color: var(--fg-color-4);
   text-align: right;
   transition: color 100ms ease-out 0s;
 }
 
 .notion-calendar-body-inner-day-other-month {
-  color: rgba(55, 53, 47, 0.5);
+  color: var(--fg-color-2);
   text-align: right;
   transition: color 100ms ease-out 0s;
 }
@@ -1761,6 +1767,7 @@ svg.notion-page-icon {
   position: absolute;
   padding: 3px 6px;
   top: 30px;
+  z-index: 2;
 }
 
 .notion-calendar-body-inner-card-inner {
@@ -1768,10 +1775,9 @@ svg.notion-page-icon {
   color: inherit;
   text-decoration: none;
   height: 100%;
-  background: white;
+  background: var(--bg-color-3);
   border-radius: 3px;
-  box-shadow: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px,
-    rgba(15, 15, 15, 0.1) 0px 2px 4px;
+  box-shadow: var(--box-shadow) 0px 0px 0px 1px, var(--box-shadow) 0px 2px 4px;
 }
 
 .notion-calendar-body-inner-card-inner-box {
@@ -1788,8 +1794,8 @@ svg.notion-page-icon {
   flex-direction: column;
 }
 
-.notion-calendar-body-inner-card-inner-box:hover {
-  background: rgba(55, 53, 47, 0.08);
+.notion-calendar-body-inner-card-inner:hover {
+  background: var(--notion-gray_background);
 }
 
 .notion-calendar-body-inner-card-inner-box-title {
@@ -1824,7 +1830,7 @@ svg.notion-page-icon {
   width: 10.8px;
   height: 10.8px;
   display: block;
-  fill: rgba(55, 53, 47, 0.85);
+  fill: var(--fg-color-3);
   flex-shrink: 0;
   backface-visibility: hidden;
 }
@@ -1853,70 +1859,6 @@ svg.notion-page-icon {
   white-space: nowrap;
 }
 
-.dark-mode .notion-calendar-header {
-  background: rgb(25, 25, 25);
-}
-
-.dark-mode .notion-calendar-header-inner-controls-today {
-  color: rgba(255, 255, 255, 0.81);
-}
-
-.dark-mode .notion-calendar-header-days-day {
-  color: rgba(255, 255, 255, 0.282);
-}
-
-.dark-mode .notion-calendar-body {
-  box-shadow: rgb(47 47 47) -1px 0px 0px;
-}
-
-.dark-mode .notion-calendar-body-inner-week {
-  border-right: 1px solid rgb(47, 47, 47);
-  border-bottom: 1px solid rgb(47, 47, 47);
-}
-
-.dark-mode .notion-calendar-body-inner-day {
-  color: white;
-}
-
-.dark-mode .notion-calendar-body-inner-week-dif {
-  background: rgb(32, 32, 32);
-}
-
-.dark-mode .notion-calendar-body-inner-day-this-month {
-  color: white;
-}
-
-.dark-mode .notion-calendar-body-inner-day-other-month {
-  color: rgba(255, 255, 255, 0.282);
-}
-
-.dark-mode .notion-calendar-body-inner-card-inner {
-  background: rgb(47, 47, 47);
-}
-
-.dark-mode .notion-calendar-header-days {
-  box-shadow: rgb(47 47 47) 0px 1px 0px;
-}
-
-.dark-mode .notion-calendar-body-inner-card-inner-box-title-inner-icon-svg {
-  fill: rgba(255, 255, 255, 0.81);
-}
-
-.dark-mode .notion-calendar-header-inner-controls-next-svg,
-.dark-mode .notion-calendar-header-inner-controls-prev-svg {
-  fill: rgba(255, 255, 255, 0.443);
-}
-
-.dark-mode .notion-calendar-header-inner-controls-prev:hover,
-.dark-mode .notion-calendar-header-inner-controls-today:hover,
-.dark-mode .notion-calendar-header-inner-controls-next:hover {
-  background: rgba(255, 255, 255, 0.055);
-}
-
-.dark-mode .notion-calendar-body-inner-card-inner-box:hover {
-  background: rgba(255, 255, 255, 0.055);
-}
-
 .notion-board {
   width: 100vw;
   max-width: 100vw;
@@ -2690,7 +2632,7 @@ svg.notion-page-icon {
 
 .notion-search {
   box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px,
-    rgba(15, 15, 15, 0.1) 0px 5px 10px, rgba(15, 15, 15, 0.2) 0px 15px 40px;
+    var(--box-shadow) 0px 5px 10px, rgba(15, 15, 15, 0.2) 0px 15px 40px;
   border-radius: 3px;
   background: var(--bg-color);
 
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 2e8de77d6..7132958ed 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -1,10 +1,10 @@
 import * as React from 'react'
 
 import { PageBlock } from 'notion-types'
-import { getPagePropertyFromId } from 'notion-utils'
+import { getBlockIcon, getPagePropertyFromId } from 'notion-utils'
 
+import { PageIcon } from '../components/page-icon'
 import { useNotionContext } from '../context'
-import { DefaultPageIcon } from '../icons/default-page-icon'
 import SvgLeftChevron from '../icons/left-chevron'
 import SvgRightChevron from '../icons/right-chevron'
 import { CollectionViewProps } from '../types'
@@ -395,9 +395,14 @@ function Calendar({ blockIds, collectionView, collection }) {
                           <div className='notion-calendar-body-inner-card-inner-box'>
                             <div className='notion-calendar-body-inner-card-inner-box-title'>
                               <div className='notion-calendar-body-inner-card-inner-box-title-inner'>
-                                <div className='notion-calendar-body-inner-card-inner-box-title-inner-icon'>
-                                  <DefaultPageIcon className='notion-calendar-body-inner-card-inner-box-title-inner-icon-svg' />
-                                </div>
+                                {getBlockIcon(block, recordMap) && (
+                                  <div className='notion-calendar-body-inner-card-inner-box-title-inner-icon'>
+                                    <PageIcon
+                                      block={block}
+                                      className='notion-calendar-body-inner-card-inner-box-title-inner-icon-svg'
+                                    />
+                                  </div>
+                                )}
                                 <div className='notion-calendar-body-inner-card-inner-box-title-inner-text'>
                                   <Property
                                     schema={titleSchema}

From d156befff87140cfa97334d006291a7a9f729573 Mon Sep 17 00:00:00 2001
From: Michael Casagrande <michael.casa04@gmail.com>
Date: Fri, 3 Feb 2023 22:13:13 +0100
Subject: [PATCH 17/22] Send it!

- Some typos
---
 packages/notion-types/src/collection-view.ts  |  4 ++--
 .../third-party/collection-view-calendar.tsx  | 22 ++++++++-----------
 packages/react-notion-x/src/utils.ts          |  7 ++++++
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/packages/notion-types/src/collection-view.ts b/packages/notion-types/src/collection-view.ts
index 712a8189d..97da19807 100644
--- a/packages/notion-types/src/collection-view.ts
+++ b/packages/notion-types/src/collection-view.ts
@@ -119,8 +119,8 @@ export interface BoardCollectionView extends BaseCollectionView {
 
 export interface CalendarCollectionView extends BaseCollectionView {
   type: 'calendar'
-
-  // TODO
+  visible: boolean
+  property?: PropertyID
 }
 
 export type CollectionView =
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 7132958ed..b890c4dcb 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -1,6 +1,6 @@
 import * as React from 'react'
 
-import { PageBlock } from 'notion-types'
+import { Block, CalendarCollectionView, PageBlock } from 'notion-types'
 import { getBlockIcon, getPagePropertyFromId } from 'notion-utils'
 
 import { PageIcon } from '../components/page-icon'
@@ -13,7 +13,7 @@ import { CollectionGroup } from './collection-group'
 import { getCollectionGroups } from './collection-utils'
 import { Property } from './property'
 
-const defaultBlockIds = []
+const defaultBlockIds: string[] = []
 const currentYear = new Date()
 const months = [
   'January',
@@ -164,9 +164,9 @@ function Calendar({ blockIds, collectionView, collection }) {
   }
 
   const getPagesThisDay = (day: { date: number; month: number }) => {
-    const daysTo = []
+    const daysTo: Block[] = []
 
-    blockIds?.map((blockId) => {
+    blockIds?.map((blockId: string) => {
       const block = recordMap.block[blockId]?.value as PageBlock
       if (!block) return null
 
@@ -295,19 +295,13 @@ function Calendar({ blockIds, collectionView, collection }) {
                 'notion-calendar-body-inner-last-week'
             )}
             style={{
-              /*height: `${
-                collectionView.format?.calendar_properties &&
-                Object.keys(collectionView.format?.calendar_properties).length *
-                  20 +
-                  64
-              }px`*/
               height: `${
                 checkWeek(indexI) == 0 ? 143.99 : checkWeek(indexI) * 110 + 34
               }px`
             }}
             key={indexI}
           >
-            {i.map((day, indexY: number) => (
+            {i.map((day, indexY) => (
               <>
                 <div
                   className={cs(
@@ -416,8 +410,10 @@ function Calendar({ blockIds, collectionView, collection }) {
                             </div>
                             <div className='notion-calendar-body-inner-card-inner-box-properties'>
                               {collectionView.format?.calendar_properties
-                                ?.filter((p) => p.visible)
-                                .map((p, z) => {
+                                ?.filter(
+                                  (p: CalendarCollectionView) => p.visible
+                                )
+                                .map((p: CalendarCollectionView, z) => {
                                   const schema = collection.schema[p.property]
                                   const data =
                                     block && block.properties?.[p.property]
diff --git a/packages/react-notion-x/src/utils.ts b/packages/react-notion-x/src/utils.ts
index f1ca64cb2..c63604570 100644
--- a/packages/react-notion-x/src/utils.ts
+++ b/packages/react-notion-x/src/utils.ts
@@ -83,6 +83,13 @@ export const getYoutubeId = (url: string): string | null => {
   return null
 }
 
+/**
+ * Get dates and month in an array of weeks based on the year and on the month
+ * @param year
+ * @param month
+ * @param startWeekOnMonday
+ * @returns An array of objects with month and date number
+ */
 export const getWeeksInMonth = (
   year: number,
   month: number,

From bbec67191114cb68d483bbaf935dd976b10b910c Mon Sep 17 00:00:00 2001
From: Michael Casagrande <michael.casa04@gmail.com>
Date: Fri, 3 Feb 2023 22:23:34 +0100
Subject: [PATCH 18/22] Run Eslint and Prettier

---
 packages/notion-utils/src/get-page-property-from-id.ts         | 1 +
 .../src/third-party/collection-view-calendar.tsx               | 2 +-
 packages/react-notion-x/src/third-party/collection-view.tsx    | 3 ++-
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/packages/notion-utils/src/get-page-property-from-id.ts b/packages/notion-utils/src/get-page-property-from-id.ts
index e12b67e48..581c8d7c0 100644
--- a/packages/notion-utils/src/get-page-property-from-id.ts
+++ b/packages/notion-utils/src/get-page-property-from-id.ts
@@ -1,4 +1,5 @@
 import { Block, DateFormat, ExtendedRecordMap } from 'notion-types'
+
 import { getTextContent } from './get-text-content'
 
 /**
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index b890c4dcb..4d22152a0 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -199,7 +199,7 @@ function Calendar({ blockIds, collectionView, collection }) {
     if (isCollectionViewPage) {
       document.querySelector('.notion-page').classList.add('notion-full-width')
     }
-  }, [])
+  }, [isCollectionViewPage])
 
   return (
     <div className='notion-calendar-view'>
diff --git a/packages/react-notion-x/src/third-party/collection-view.tsx b/packages/react-notion-x/src/third-party/collection-view.tsx
index 6713313e8..c38adbcb8 100644
--- a/packages/react-notion-x/src/third-party/collection-view.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view.tsx
@@ -2,9 +2,9 @@ import * as React from 'react'
 
 import { CollectionViewProps } from '../types'
 import { CollectionViewBoard } from './collection-view-board'
+import { CollectionViewCalendar } from './collection-view-calendar'
 import { CollectionViewGallery } from './collection-view-gallery'
 import { CollectionViewList } from './collection-view-list'
-import { CollectionViewCalendar } from './collection-view-calendar'
 import { CollectionViewTable } from './collection-view-table'
 
 export const CollectionViewImpl: React.FC<CollectionViewProps> = (props) => {
@@ -22,6 +22,7 @@ export const CollectionViewImpl: React.FC<CollectionViewProps> = (props) => {
 
     case 'board':
       return <CollectionViewBoard {...props} />
+
     case 'calendar':
       return <CollectionViewCalendar {...props} />
 

From 440c985c59f2dfbc127e9d820d7a869786292887 Mon Sep 17 00:00:00 2001
From: Michael Casagrande <michael.casa04@gmail.com>
Date: Mon, 6 Feb 2023 09:06:23 +0100
Subject: [PATCH 19/22] Fix today date indicator

The today date indicator now check also the correct now year
---
 .../src/third-party/collection-view-calendar.tsx               | 2 +-
 packages/react-notion-x/src/utils.ts                           | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 4d22152a0..559298cfe 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -323,7 +323,7 @@ function Calendar({ blockIds, collectionView, collection }) {
 
                       day.date == new Date().getDate() &&
                         day.month == new Date().getMonth() &&
-                        currentYear.getFullYear() == new Date().getFullYear()
+                        day.year == new Date().getFullYear()
                         ? 'notion-calendar-body-inner-day-today'
                         : (day.date == 1 &&
                             currentYear.getMonth() == day.month) ||
diff --git a/packages/react-notion-x/src/utils.ts b/packages/react-notion-x/src/utils.ts
index c63604570..bd034b89e 100644
--- a/packages/react-notion-x/src/utils.ts
+++ b/packages/react-notion-x/src/utils.ts
@@ -158,7 +158,8 @@ export const getWeeksInMonth = (
 
       return {
         date: date.getDate(),
-        month: date.getMonth()
+        month: date.getMonth(),
+        year: date.getFullYear()
       }
     })
   })

From 4ad45dc92a9707a06658378a04fefd26babc2675 Mon Sep 17 00:00:00 2001
From: Michael Casagrande <michael.casa04@gmail.com>
Date: Sun, 1 Oct 2023 16:38:26 +0200
Subject: [PATCH 20/22] Comments and minor fixes

- More comments
- Fixed first day of month red background circle to not show the month name (it's shown up in the calendar controls)

WIP: The October 2023 has a strange bug (probably in the algo) that shows the 1st October as Saturday and not Sunday (only on the view that has Sunday as first week day (by using `startWeekOnMonday` it doesn't appear))
---
 .../third-party/collection-view-calendar.tsx  | 53 ++++++++++++-------
 1 file changed, 34 insertions(+), 19 deletions(-)

diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 559298cfe..9fa668cf6 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -1,6 +1,6 @@
 import * as React from 'react'
 
-import { Block, CalendarCollectionView, PageBlock } from 'notion-types'
+import { CalendarCollectionView, PageBlock } from 'notion-types'
 import { getBlockIcon, getPagePropertyFromId } from 'notion-utils'
 
 import { PageIcon } from '../components/page-icon'
@@ -101,6 +101,9 @@ function Calendar({ blockIds, collectionView, collection }) {
     )
   )
 
+  /**
+   * Set next month to be shown
+   */
   const nextMonth = () => {
     if (currentYear.getMonth() == 11) {
       currentYear.setFullYear(currentYear.getFullYear() + 1)
@@ -119,6 +122,9 @@ function Calendar({ blockIds, collectionView, collection }) {
       )
     )
   }
+  /**
+   * Set previous month to be shown
+   */
   const prevMonth = () => {
     if (currentYear.getMonth() == 0) {
       currentYear.setFullYear(currentYear.getFullYear() - 1)
@@ -137,6 +143,9 @@ function Calendar({ blockIds, collectionView, collection }) {
       )
     )
   }
+  /**
+   * Set current (in the user time) month to be shwon
+   */
   const nowMonth = () => {
     currentYear.setMonth(new Date().getMonth())
     currentYear.setFullYear(new Date().getFullYear())
@@ -152,6 +161,11 @@ function Calendar({ blockIds, collectionView, collection }) {
     )
   }
 
+  /**
+   * Get the highest numer of pages for a specific weeknumer in the current month
+   * @param weekNumber
+   * @returns
+   */
   const checkWeek = (weekNumber: number) => {
     let max = 0
 
@@ -163,8 +177,13 @@ function Calendar({ blockIds, collectionView, collection }) {
     return max
   }
 
+  /**
+   * Get all the pages that has a block in the day parameter
+   * @param day
+   * @returns The blocks in a day
+   */
   const getPagesThisDay = (day: { date: number; month: number }) => {
-    const daysTo: Block[] = []
+    const daysTo: PageBlock[] = []
 
     blockIds?.map((blockId: string) => {
       const block = recordMap.block[blockId]?.value as PageBlock
@@ -189,18 +208,6 @@ function Calendar({ blockIds, collectionView, collection }) {
     return daysTo
   }
 
-  // Check if collection view is a standalone page or not
-  const isCollectionViewPage =
-    recordMap.block[Object.keys(recordMap.block)[0]].value.type ===
-    'collection_view_page'
-
-  // This is needed because calendar view pages need to be full width (like Notion)
-  React.useEffect(() => {
-    if (isCollectionViewPage) {
-      document.querySelector('.notion-page').classList.add('notion-full-width')
-    }
-  }, [isCollectionViewPage])
-
   return (
     <div className='notion-calendar-view'>
       <div className='notion-calendar-header'>
@@ -215,6 +222,7 @@ function Calendar({ blockIds, collectionView, collection }) {
             }}
           ></div>
 
+          {/* Calendar controls | prev - today - next */}
           {showCalendarControls && (
             <>
               <div
@@ -287,6 +295,7 @@ function Calendar({ blockIds, collectionView, collection }) {
       ></div>
 
       <div className='notion-calendar-body'>
+        {/* Rows */}
         {weeksArr.map((i, indexI) => (
           <div
             className={cs(
@@ -301,8 +310,10 @@ function Calendar({ blockIds, collectionView, collection }) {
             }}
             key={indexI}
           >
+            {/* Columns */}
             {i.map((day, indexY) => (
               <>
+                {/* Print the days blocks with the number and month if is day 1 */}
                 <div
                   className={cs(
                     'notion-selectable',
@@ -320,7 +331,6 @@ function Calendar({ blockIds, collectionView, collection }) {
                   <div
                     className={cs(
                       'notion-calendar-body-inner-day',
-
                       day.date == new Date().getDate() &&
                         day.month == new Date().getMonth() &&
                         day.year == new Date().getFullYear()
@@ -333,12 +343,18 @@ function Calendar({ blockIds, collectionView, collection }) {
                         : 'notion-calendar-body-inner-day-other-month'
                     )}
                   >
-                    {day.date == 1
+                    {day.date == 1 &&
+                    !(
+                      day.date == new Date().getDate() &&
+                      day.month == new Date().getMonth() &&
+                      day.year == new Date().getFullYear()
+                    )
                       ? `${monthsShort[day.month + currentMonth]} ${day.date}`
                       : day.date}
                   </div>
                 </div>
 
+                {/* Print the blocks the day */}
                 {getPagesThisDay(day).map((block, sum) => {
                   // Get date from calendar view query
                   const blockDate = getPagePropertyFromId(
@@ -365,9 +381,8 @@ function Calendar({ blockIds, collectionView, collection }) {
                       <div
                         className='notion-calendar-body-inner-card'
                         style={{
-                          left: `calc(${
-                            dayBlock == 0 ? 0 : dayBlock * 14.2857
-                          }%)`,
+                          left: `calc(${dayBlock * 14.2857}%)`,
+                          // Calculate the height of the block based on its properties (also the one that are not supported yet)
                           height: `${
                             collectionView.format?.calendar_properties &&
                             Object.keys(

From 0f9858d9d5aa23fc46a31001e91c7fad328cde0c Mon Sep 17 00:00:00 2001
From: Michael Casagrande <michael.casa04@gmail.com>
Date: Sun, 1 Oct 2023 16:50:16 +0200
Subject: [PATCH 21/22] Update readme.md

More infos about the calendar view and what it can handle and what it can't
---
 readme.md | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/readme.md b/readme.md
index 35d5037b2..e589c4528 100644
--- a/readme.md
+++ b/readme.md
@@ -202,8 +202,8 @@ For a production example, check out the [Next.js Notion Starter Kit](https://git
 
 The majority of Notion blocks and collection views are fully supported.
 
-| Block Type               | Supported  | Block Type Enum        | Notes                                                                                                            |
-| ------------------------ | ---------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
+| Block Type               | Supported | Block Type Enum        | Notes                                                                                                            |
+| ------------------------ | --------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
 | Page                     | ✅ Yes     | `page`                 |
 | Text                     | ✅ Yes     | `text`                 | Supports all known text formatting options                                                                       |
 | Bookmark                 | ✅ Yes     | `bookmark`             | Embedded preview of external URL                                                                                 |
@@ -243,7 +243,7 @@ The majority of Notion blocks and collection views are fully supported.
 | Collection View Gallery  | ✅ Yes     | `collection_view`      | `type = "gallery"` (grid view)                                                                                   |
 | Collection View Board    | ✅ Yes     | `collection_view`      | `type = "board"` (kanban view)                                                                                   |
 | Collection View List     | ✅ Yes     | `collection_view`      | `type = "list"` (vertical list view)                                                                             |
-| Collection View Calendar | ✅ Yes     | `collection_view`      | `type = "calendar"` (embedded calendar view)                                                                     |
+| Collection View Calendar | ✅ Yes     | `collection_view`      | `type = "calendar"` (embedded calendar view [see more details here](#calendar-view))                                     |
 | Collection View Page     | ✅ Yes     | `collection_view_page` | Collection view as a standalone page                                                                             |
 
 Please let us know if you find any issues or missing blocks.
@@ -290,6 +290,20 @@ export default ({ recordMap }) => (
 
 This wraps these next.js components in a compatability layer so `NotionRenderer` can use them the same as their non-next.js equivalents `<img>` and `<a>`.
 
+
+## Calendar view
+Notion's databases calendar view is one of the most complex views that exists on Notion.
+This component is still a Work-In-Progress, **recommended use is for development only**, but will soon be more stable and out of bugs and ready for production deploys.
+
+At the moment it features:
+- Controls (previuous, current, next month views)
+- Display block that has ONLY one day duration (without time)
+- Show calendar in both SUN-SAT and MON-SUN format (use `startWeekOnMonday` parameter)
+
+What is unsupported at the moment:
+- Display blocks that has a day range
+- Display blocks with date and time (it will render but the data and time property will be shown in a bad way)
+
 ## Related
 
 - [Next.js Template](https://github.com/transitive-bullshit/nextjs-notion-starter-kit) - The easiest way to deploy a self-hosted Notion site with Next.js and Vercel.

From e6e62b6d554c56be5a142d88896da2c2e0de849b Mon Sep 17 00:00:00 2001
From: Michael Casagrande <michael.casa04@gmail.com>
Date: Sun, 1 Oct 2023 18:37:08 +0200
Subject: [PATCH 22/22] Fix for PR checks

---
 packages/react-notion-x/src/components/text.tsx            | 7 +++----
 .../src/third-party/collection-view-calendar.tsx           | 1 -
 packages/react-notion-x/src/third-party/property.tsx       | 6 ++----
 3 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/packages/react-notion-x/src/components/text.tsx b/packages/react-notion-x/src/components/text.tsx
index a09214fdb..19dc2c9e4 100644
--- a/packages/react-notion-x/src/components/text.tsx
+++ b/packages/react-notion-x/src/components/text.tsx
@@ -23,8 +23,7 @@ export const Text: React.FC<{
   linkProps?: any
   linkProtocol?: string
   inline?: boolean // TODO: currently unused
-  longMonth?: boolean
-}> = ({ value, block, linkProps, linkProtocol, longMonth }) => {
+}> = ({ value, block, linkProps, linkProtocol }) => {
   const { components, recordMap, mapPageUrl, mapImageUrl, rootDomain } =
     useNotionContext()
 
@@ -190,7 +189,7 @@ export const Text: React.FC<{
                 if (type === 'date') {
                   // Example: Jul 31, 2010
                   const startDate = v.start_date
-                  
+
                   return formatDate(startDate)
                 } else if (type === 'datetime') {
                   // Example: Jul 31, 2010 20:00
@@ -198,7 +197,7 @@ export const Text: React.FC<{
                   const startTime = v.start_time
 
                   return `${formatDate(startDate)} ${startTime}`
-                 } else if (type === 'daterange') {
+                } else if (type === 'daterange') {
                   // Example: Jul 31, 2010 → Jul 31, 2020
                   const startDate = v.start_date
                   const endDate = v.end_date
diff --git a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
index 9fa668cf6..26617e3a7 100644
--- a/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
+++ b/packages/react-notion-x/src/third-party/collection-view-calendar.tsx
@@ -447,7 +447,6 @@ function Calendar({ blockIds, collectionView, collection }) {
                                         data={data}
                                         block={block}
                                         collection={collection}
-                                        longMonth={true}
                                       />
                                     </div>
                                   )
diff --git a/packages/react-notion-x/src/third-party/property.tsx b/packages/react-notion-x/src/third-party/property.tsx
index 40dd6ea15..5ef8f6fa2 100644
--- a/packages/react-notion-x/src/third-party/property.tsx
+++ b/packages/react-notion-x/src/third-party/property.tsx
@@ -22,7 +22,6 @@ export interface IPropertyProps {
   inline?: boolean
   linkToTitlePage?: boolean
   pageHeader?: boolean
-  longMonth?: boolean
 }
 
 /**
@@ -49,8 +48,7 @@ export const PropertyImpl: React.FC<IPropertyProps> = (props) => {
     block,
     collection,
     inline = false,
-    linkToTitlePage = true,
-    longMonth = false
+    linkToTitlePage = true
   } = props
 
   const renderTextValue = React.useMemo(
@@ -64,7 +62,7 @@ export const PropertyImpl: React.FC<IPropertyProps> = (props) => {
   const renderDateValue = React.useMemo(
     () =>
       function DateProperty() {
-        return <Text value={data} block={block} longMonth={longMonth} />
+        return <Text value={data} block={block} />
       },
     [block, data]
   )