diff --git a/src/components/elements/load-more-list.tsx b/src/components/elements/load-more-list.tsx index b1a37910..bdc0e0d8 100644 --- a/src/components/elements/load-more-list.tsx +++ b/src/components/elements/load-more-list.tsx @@ -1,59 +1,59 @@ "use client"; -import { - JSX, - ComponentProps, - RefObject, - useLayoutEffect, - useRef, - useState, - HtmlHTMLAttributes -} from "react"; +import {useLayoutEffect, useRef, HtmlHTMLAttributes, JSX, useId} from "react"; import Button from "@components/elements/button"; import {useAutoAnimate} from "@formkit/auto-animate/react"; -import {Maybe} from "@lib/gql/__generated__/drupal"; +import {useBoolean, useCounter} from "usehooks-ts"; type Props = HtmlHTMLAttributes & { - buttonText?: Maybe | JSX.Element - children: JSX.Element[], - listProps?: ComponentProps - itemProps?: ComponentProps, + buttonText?: string | JSX.Element + ulProps?: HtmlHTMLAttributes + liProps?: HtmlHTMLAttributes, itemsPerPage?: number } -const LoadMoreList = ({buttonText, children, listProps, itemProps, itemsPerPage = 20, ...props}: Props) => { - const [shownItems, setShownItems] = useState(itemsPerPage) - const [allowFocus, setAllowFocus] = useState(false); - const ref: RefObject = useRef(null); +const LoadMoreList = ({buttonText, children, ulProps, liProps, itemsPerPage = 20, ...props}: Props) => { + const id = useId(); + const {count: shownItems, setCount: setShownItems} = useCounter(itemsPerPage) + const {value: focusOnElement, setTrue: enableFocusElement, setFalse: disableFocusElement} = useBoolean(false) + + const ref = useRef(null); const [animationParent] = useAutoAnimate(); const showMoreItems = () => { - setAllowFocus(true); + enableFocusElement(); setShownItems(shownItems + itemsPerPage); } useLayoutEffect(() => ref.current?.focus(), [shownItems]); const focusingItem = shownItems - itemsPerPage; - - const items = typeof children === 'string'? [children]: children; + const items = Array.isArray(children) ? children : [children] + const itemsToShow = items.slice(0, shownItems); return (
-
    +
      - {items.slice(0, shownItems).map((item, i) => + {itemsToShow.map((item, i) =>
    • setAllowFocus(false)} - {...itemProps} + tabIndex={focusingItem === i && focusOnElement ? 0 : undefined} + onBlur={disableFocusElement} + {...liProps} > {item}
    • )}
    - {children.length > shownItems && + + {items.length > itemsPerPage && + + Showing {itemsToShow.length} of {items.length} total items. + + } + + {items.length > shownItems && diff --git a/src/components/nodes/cards/stanford-event/stanford-event-card.tsx b/src/components/nodes/cards/stanford-event/stanford-event-card.tsx index 94ee5107..2b0f561d 100644 --- a/src/components/nodes/cards/stanford-event/stanford-event-card.tsx +++ b/src/components/nodes/cards/stanford-event/stanford-event-card.tsx @@ -49,10 +49,10 @@ const StanfordEventCard = ({node, headingLevel, ...props}: Props) => { -
    +
    + {node.suEventAltLoc &&
    @@ -113,7 +113,13 @@ export const getEventTimeString = (start: Date, end: Date, timezone: string): st endHour === 23 && endMinute === 59 ) { - return 'All Day'; + return start.toLocaleDateString('en-us', { + weekday: "long", + month: "long", + day: "numeric", + year: "numeric", + timeZone: timezone + }); } diff --git a/src/components/nodes/list-item/stanford-event/stanford-event-list-item.tsx b/src/components/nodes/list-item/stanford-event/stanford-event-list-item.tsx index 1ff4f66d..6668fb0b 100644 --- a/src/components/nodes/list-item/stanford-event/stanford-event-list-item.tsx +++ b/src/components/nodes/list-item/stanford-event/stanford-event-list-item.tsx @@ -4,6 +4,7 @@ import Address from "@components/elements/address"; import {H2, H3} from "@components/elements/headers"; import {HtmlHTMLAttributes} from "react"; import {NodeStanfordEvent} from "@lib/gql/__generated__/drupal"; +import {getEventTimeString} from "@components/nodes/cards/stanford-event/stanford-event-card"; type Props = HtmlHTMLAttributes & { node: NodeStanfordEvent @@ -56,10 +57,10 @@ const StanfordEventListItem = ({node, headingLevel, ...props}: Props) => {
    } -
    +
    + {node.suEventLocation &&
    @@ -81,95 +82,4 @@ const StanfordEventListItem = ({node, headingLevel, ...props}: Props) => { ) } - -export const getEventTimeString = (start: Date, end: Date, timezone: string): string => { - const startHour = parseInt(start.toLocaleTimeString("en-US", { - hour: "numeric", - hour12: false, - timeZone: timezone - })) - const startMinute = parseInt(start.toLocaleTimeString("en-US", { - minute: "numeric", - hour12: false, - timeZone: timezone - })) - - const endHour = parseInt(end.toLocaleTimeString("en-US", { - hour: "numeric", - hour12: false, - timeZone: timezone - })) - const endMinute = parseInt(end.toLocaleTimeString("en-US", { - minute: "numeric", - hour12: false, - timeZone: timezone - })) - - let dateTimeString: string; - - // Multiple days. - if (start.toLocaleDateString("en-US", {timeZone: 'America/Los_Angeles'}) != end.toLocaleDateString("en-US", {timeZone: 'America/Los_Angeles'})) { - dateTimeString = start.toLocaleDateString("en-US", { - month: "long", - day: "numeric", - year: "numeric", - timeZone: timezone - }) + ' - ' + end.toLocaleDateString("en-US", { - month: "long", - day: "numeric", - year: "numeric", - timeZone: timezone - }) - return dateTimeString; - } - - // All Day display. - if ( - (startHour === 24 || startHour === 0) && - startMinute === 0 && - endHour === 23 && - endMinute === 59 - ) { - return start.toLocaleDateString('en-us', { - weekday: "long", - month: "long", - day: "numeric", - year: "numeric", - timeZone: timezone - }); - } - - - // Different start and end times. - if (startHour !== endHour || startMinute !== endMinute) { - dateTimeString = start.toLocaleDateString('en-US', { - weekday: "long", - month: "long", - day: "numeric", - year: "numeric", - timeZone: timezone - }); - dateTimeString += " | " + start.toLocaleTimeString("en-US", { - hour: "numeric", - minute: "numeric", - timeZone: timezone - }); - dateTimeString += ' - '; - dateTimeString += end.toLocaleTimeString("en-US", { - hour: "numeric", - minute: "numeric", - timeZoneName: "short", - timeZone: timezone - }) - return dateTimeString; - } - - // Start and end times are the same, just display the start time. - return start.toLocaleTimeString("en-US", { - hour: "numeric", - minute: "numeric", - timeZoneName: "short", - timeZone: timezone - }) -} export default StanfordEventListItem; \ No newline at end of file diff --git a/src/components/nodes/pages/stanford-event/stanford-event-page.tsx b/src/components/nodes/pages/stanford-event/stanford-event-page.tsx index 54de7985..e80572a2 100644 --- a/src/components/nodes/pages/stanford-event/stanford-event-page.tsx +++ b/src/components/nodes/pages/stanford-event/stanford-event-page.tsx @@ -58,10 +58,10 @@ const StanfordEventPage = ({node, ...props}: Props) => {

    Event Details:

    -
    +
    + {(node.suEventEmail || node.suEventTelephone) && diff --git a/src/components/nodes/pages/stanford-news/stanford-news-page.tsx b/src/components/nodes/pages/stanford-news/stanford-news-page.tsx index a65255ef..6c30c145 100644 --- a/src/components/nodes/pages/stanford-news/stanford-news-page.tsx +++ b/src/components/nodes/pages/stanford-news/stanford-news-page.tsx @@ -18,7 +18,7 @@ const StanfordNewsPage = ({node, ...props}: Props) => { month: "long", day: "numeric", year: "numeric" - }) : null; + }) : undefined; let bannerImageUrl: string | undefined, bannerImageAlt: string = "" if (node.suNewsBanner?.__typename === 'MediaImage') { @@ -26,7 +26,7 @@ const StanfordNewsPage = ({node, ...props}: Props) => { bannerImageAlt = node.suNewsBanner.mediaImage.alt || ""; } - const topics = (node.suNewsTopics && node.suNewsTopics.length > 0) ? node.suNewsTopics.slice(0, 3) : undefined; + const topics = node.suNewsTopics?.slice(0, 3); return (
    @@ -51,7 +51,11 @@ const StanfordNewsPage = ({node, ...props}: Props) => { {node.suNewsDek &&
    {node.suNewsDek}
    }
    - {publishDate &&
    {publishDate}
    } + {node.suNewsPublishingDate && + + } {node.suNewsByline &&
    {node.suNewsByline}
    } {!node.suNewsHideSocial && diff --git a/src/components/views/card-view-grid.tsx b/src/components/views/card-view-grid.tsx index 2862f7d8..70c02ed7 100644 --- a/src/components/views/card-view-grid.tsx +++ b/src/components/views/card-view-grid.tsx @@ -5,8 +5,8 @@ import {NodeUnion} from "@lib/gql/__generated__/drupal"; const CardViewGrid = ({items, headingLevel}: { items: NodeUnion[], headingLevel: string }) => { return ( {items.map(item => diff --git a/src/components/views/stanford-courses/course-list-view.tsx b/src/components/views/stanford-courses/course-list-view.tsx index 98a83c82..989deecc 100644 --- a/src/components/views/stanford-courses/course-list-view.tsx +++ b/src/components/views/stanford-courses/course-list-view.tsx @@ -17,8 +17,8 @@ const CourseListView = async ({items = [], emptyMessage, headingLevel}: Props) = return ( Load More courses} - listProps={{className: "list-unstyled mb-20"}} - itemProps={{className: "border-b border-black-20 last-of-type:border-0 pb-10 last:pb-0 pt-10 first:pt-0"}} + ulProps={{className: "list-unstyled mb-20"}} + liProps={{className: "border-b border-black-20 last-of-type:border-0 pb-10 last:pb-0 pt-10 first:pt-0"}} > {items.map(item => diff --git a/src/components/views/stanford-events/events-filtered-list-view.tsx b/src/components/views/stanford-events/events-filtered-list-view.tsx index ae99fe17..2d77321f 100644 --- a/src/components/views/stanford-events/events-filtered-list-view.tsx +++ b/src/components/views/stanford-events/events-filtered-list-view.tsx @@ -76,8 +76,8 @@ const EventsFilteredListView = ({items, topics}: { items: NodeStanfordEvent[], t event.id).join(',')} buttonText={<>Load More Events} - listProps={{className: "list-unstyled mb-20"}} - itemProps={{className: "border-b border-black-20 last-of-type:border-0 pb-10 last:pb-0 pt-10 first:pt-0"}} + ulProps={{className: "list-unstyled mb-20"}} + liProps={{className: "border-b border-black-20 last-of-type:border-0 pb-10 last:pb-0 pt-10 first:pt-0"}} itemsPerPage={3} > {displayedEvents.map(event => )} diff --git a/src/components/views/stanford-events/events-list-view.tsx b/src/components/views/stanford-events/events-list-view.tsx index 45af97fc..e17123b9 100644 --- a/src/components/views/stanford-events/events-list-view.tsx +++ b/src/components/views/stanford-events/events-list-view.tsx @@ -28,8 +28,8 @@ const EventsListView = async ({items = [], emptyMessage, headingLevel}: Props) = return ( Load More Events} - listProps={{className: "list-unstyled mb-20"}} - itemProps={{className: "border-b border-black-20 last-of-type:border-0 pb-10 last:pb-0 pt-10 first:pt-0"}} + ulProps={{className: "list-unstyled mb-20"}} + liProps={{className: "border-b border-black-20 last-of-type:border-0 pb-10 last:pb-0 pt-10 first:pt-0"}} > {items.map(item => diff --git a/src/components/views/stanford-news/news-list-view.tsx b/src/components/views/stanford-news/news-list-view.tsx index 4df7401d..062fb991 100644 --- a/src/components/views/stanford-news/news-list-view.tsx +++ b/src/components/views/stanford-news/news-list-view.tsx @@ -17,8 +17,8 @@ const NewsListView = async ({items = [], emptyMessage, headingLevel}: Props) => return ( Load More news} - listProps={{className: "list-unstyled mb-20"}} - itemProps={{className: "border-b border-black-20 last-of-type:border-0 pb-10 last:pb-0 pt-10 first:pt-0"}} + ulProps={{className: "list-unstyled mb-20"}} + liProps={{className: "border-b border-black-20 last-of-type:border-0 pb-10 last:pb-0 pt-10 first:pt-0"}} > {items.map(item => diff --git a/src/components/views/stanford-page/page-list-view.tsx b/src/components/views/stanford-page/page-list-view.tsx index 5cf0b210..c8ae9ec0 100644 --- a/src/components/views/stanford-page/page-list-view.tsx +++ b/src/components/views/stanford-page/page-list-view.tsx @@ -14,8 +14,8 @@ const PageListView = async ({emptyMessage, items = [], headingLevel}: Props) => } return ( {items.map(item => diff --git a/src/components/views/stanford-publications/publications-chicago-view.tsx b/src/components/views/stanford-publications/publications-chicago-view.tsx index b0a5a13b..11c16607 100644 --- a/src/components/views/stanford-publications/publications-chicago-view.tsx +++ b/src/components/views/stanford-publications/publications-chicago-view.tsx @@ -14,8 +14,8 @@ const PublicationsChicagoView = async ({items = [], emptyMessage, headingLevel}: } return ( {items.map(item =>