From 66cbbf6767137daeaec290ee33a807f3cd394183 Mon Sep 17 00:00:00 2001 From: Mike Decker Date: Wed, 12 Jun 2024 11:23:27 -0700 Subject: [PATCH] Apply prettier on all files --- .storybook/stories/menu/MainMenu.stories.tsx | 26 +- .storybook/stories/menu/SideMenu.stories.tsx | 28 +- .../stories/paragraphs/Banner.stories.tsx | 41 +- .../stories/paragraphs/Card.stories.tsx | 43 +- .../stories/paragraphs/Gallery.stories.tsx | 50 +- .../paragraphs/MediaWithCaption.stories.tsx | 44 +- app/@modal/(.)gallery/[...uuid]/page.tsx | 73 +- app/@modal/default.tsx | 2 +- app/[...slug]/metadata.tsx | 87 +- app/[...slug]/page.tsx | 35 +- app/api/draft/disable/route.tsx | 10 +- app/api/draft/route.tsx | 11 +- app/api/revalidate/route.tsx | 31 +- app/error.tsx | 24 +- app/gallery/[...uuid]/page.tsx | 34 +- app/layout.tsx | 86 +- app/not-found.tsx | 8 +- app/page.tsx | 49 +- app/preview/[...slug]/page.tsx | 28 +- app/preview/layout.tsx | 22 +- app/preview/page.tsx | 12 +- app/search/page.tsx | 32 +- app/sitemap.tsx | 31 +- package.json | 38 +- src/components/algolia/algolia-search.tsx | 98 +- src/components/algolia/hits/default.tsx | 41 +- .../config-pages/global-message.tsx | 56 +- src/components/config-pages/local-footer.tsx | 200 ++-- src/components/config-pages/super-footer.tsx | 42 +- src/components/elements/accordion.tsx | 46 +- src/components/elements/action-link.tsx | 20 +- src/components/elements/address.tsx | 58 +- src/components/elements/back-to-top.tsx | 33 +- src/components/elements/button.tsx | 40 +- .../elements/drupal-window-sync.tsx | 33 +- src/components/elements/email.tsx | 15 +- src/components/elements/headers.tsx | 38 +- .../elements/icons/FacebookIcon.tsx | 4 +- .../elements/icons/InstagramIcon.tsx | 12 +- .../elements/icons/LinkedInIcon.tsx | 4 +- src/components/elements/icons/TwitterIcon.tsx | 4 +- src/components/elements/icons/YoutubeIcon.tsx | 13 +- .../elements/interception-modal.tsx | 57 +- src/components/elements/link.tsx | 51 +- src/components/elements/load-more-list.tsx | 53 +- src/components/elements/lockup/lockup-a.tsx | 32 +- src/components/elements/lockup/lockup-b.tsx | 22 +- src/components/elements/lockup/lockup-d.tsx | 22 +- src/components/elements/lockup/lockup-e.tsx | 22 +- src/components/elements/lockup/lockup-h.tsx | 26 +- src/components/elements/lockup/lockup-i.tsx | 26 +- .../elements/lockup/lockup-logo.tsx | 18 +- src/components/elements/lockup/lockup-m.tsx | 24 +- src/components/elements/lockup/lockup-o.tsx | 20 +- src/components/elements/lockup/lockup-p.tsx | 28 +- src/components/elements/lockup/lockup-r.tsx | 22 +- src/components/elements/lockup/lockup-s.tsx | 22 +- src/components/elements/lockup/lockup-t.tsx | 22 +- src/components/elements/lockup/lockup.tsx | 101 +- src/components/elements/ombed.tsx | 35 +- src/components/elements/paged-list.tsx | 100 +- src/components/elements/select-list.tsx | 223 ++-- src/components/elements/slideshow.tsx | 58 +- src/components/elements/string-with-lines.tsx | 10 +- src/components/elements/tabs.tsx | 63 +- src/components/elements/telephone.tsx | 16 +- .../elements/unpublished-banner.tsx | 17 +- src/components/elements/user-analytics.tsx | 23 +- src/components/elements/wysiwyg.tsx | 153 +-- src/components/global/page-footer.tsx | 89 +- src/components/global/page-header.tsx | 40 +- src/components/images/stanford-wordmark.tsx | 68 +- src/components/layouts/interior-page.tsx | 53 +- src/components/menu/main-menu.tsx | 177 ++-- src/components/menu/side-nav.tsx | 54 +- src/components/nodes/cards/node-card.tsx | 94 +- .../stanford-course/stanford-course-card.tsx | 34 +- .../stanford-event-series-card.tsx | 27 +- .../stanford-event/stanford-event-card.tsx | 205 ++-- .../stanford-news/stanford-news-card.tsx | 52 +- .../stanford-page/stanford-page-card.tsx | 37 +- .../stanford-person/stanford-person-card.tsx | 37 +- .../stanford-policy/stanford-policy-card.tsx | 36 +- .../stanford-publication-card.tsx | 38 +- .../nodes/list-item/node-list-item.tsx | 96 +- .../stanford-course-list-item.tsx | 55 +- .../stanford-event-series-list-item.tsx | 26 +- .../stanford-event-list-item.tsx | 95 +- .../stanford-news/stanford-news-list-item.tsx | 66 +- .../stanford-page/stanford-page-list-item.tsx | 53 +- .../stanford-person-list-item.tsx | 37 +- .../stanford-policy-list-item.tsx | 26 +- .../stanford-publication-list-item.tsx | 39 +- src/components/nodes/pages/node-page.tsx | 88 +- .../stanford-course/stanford-course-page.tsx | 59 +- .../stanford-event-series-page.tsx | 46 +- .../stanford-event/stanford-event-page.tsx | 193 ++-- .../pages/stanford-news/social-icons.tsx | 46 +- .../stanford-news/stanford-news-page.tsx | 86 +- .../stanford-page/stanford-page-page.tsx | 61 +- .../stanford-person/stanford-person-page.tsx | 186 ++-- .../stanford-policy/stanford-policy-page.tsx | 102 +- .../pages/stanford-publication/citation.tsx | 27 +- .../stanford-publication-page.tsx | 56 +- .../paragraphs/get-paragraph-behaviors.tsx | 10 +- src/components/paragraphs/paragraph.tsx | 88 +- src/components/paragraphs/rows/one-column.tsx | 28 +- src/components/paragraphs/rows/rows.tsx | 73 +- .../paragraphs/rows/three-column.tsx | 33 +- src/components/paragraphs/rows/two-column.tsx | 35 +- .../stanford-banner/banner-paragraph.tsx | 71 +- .../stanford-card/card-paragraph.tsx | 81 +- .../stanford-entity/entity-paragraph.tsx | 83 +- .../stanford-gallery/gallery-paragraph.tsx | 84 +- .../stanford-lists/list-paragraph.tsx | 183 ++-- .../media-caption-paragraph.tsx | 37 +- .../page-title-banner-paragraph.tsx | 15 +- .../person-cta-paragraph.tsx | 33 +- .../stanford-schedule/schedule-paragraph.tsx | 51 +- .../stanford-spacer/spacer-paragraph.tsx | 13 +- .../stanford-wysiwyg/wysiwyg-paragraph.tsx | 16 +- src/components/patterns/hero-banner.tsx | 28 +- src/components/patterns/image-card.tsx | 33 +- src/components/search/site-search-form.tsx | 31 +- src/components/tools/editorially.tsx | 14 +- src/components/tools/mathjax.tsx | 9 +- src/components/views/card-view-grid.tsx | 18 +- .../shared-tags/shared-tags-card-view.tsx | 11 +- .../stanford-courses/course-card-view.tsx | 11 +- .../stanford-courses/course-list-view.tsx | 24 +- .../stanford-events/events-card-view.tsx | 11 +- .../events-filtered-list-view.tsx | 84 +- .../stanford-events/events-list-view.tsx | 37 +- .../views/stanford-news/news-card-view.tsx | 11 +- .../views/stanford-news/news-list-view.tsx | 20 +- .../views/stanford-page/page-card-view.tsx | 11 +- .../views/stanford-page/page-list-view.tsx | 18 +- .../stanford-person/person-card-view.tsx | 11 +- .../publications-apa-view.tsx | 11 +- .../publications-chicago-view.tsx | 19 +- src/components/views/view.tsx | 168 +-- src/lib/drupal/deserialize.tsx | 6 +- src/lib/drupal/drupal-jsonapi.d.tsx | 38 +- src/lib/drupal/get-access-token.tsx | 25 +- src/lib/drupal/get-search-index.tsx | 14 +- src/lib/drupal/get-taxonomy-tree.tsx | 30 +- src/lib/drupal/utils.tsx | 31 +- src/lib/gql/__generated__/drupal.d.ts | 520 +++++----- src/lib/gql/__generated__/queries.ts | 73 +- src/lib/gql/fragments-fields.drupal.gql | 125 +++ ....drupal.gql => fragments-nodes.drupal.gql} | 316 +----- src/lib/gql/fragments-paragraphs.drupal.gql | 182 ++++ src/lib/gql/gql-client.tsx | 27 +- src/lib/gql/gql-queries.tsx | 120 +-- src/lib/hooks/useActiveTrail.tsx | 28 +- src/lib/hooks/useFocusOnRender.tsx | 19 +- src/lib/hooks/useOutsideClick.tsx | 6 +- src/lib/hooks/usePagination.tsx | 57 +- src/styles/centered-container.tsx | 44 +- src/styles/fonts.tsx | 4 +- src/styles/typography/global-message.tsx | 12 +- src/styles/typography/local-footer.tsx | 16 +- src/styles/typography/wysiwyg.tsx | 13 +- vercel.json | 1 + yarn.lock | 958 ++++++++---------- 165 files changed, 4896 insertions(+), 4635 deletions(-) create mode 100644 src/lib/gql/fragments-fields.drupal.gql rename src/lib/gql/{fragments.drupal.gql => fragments-nodes.drupal.gql} (54%) create mode 100644 src/lib/gql/fragments-paragraphs.drupal.gql diff --git a/.storybook/stories/menu/MainMenu.stories.tsx b/.storybook/stories/menu/MainMenu.stories.tsx index 6166a10b..a1e36c82 100644 --- a/.storybook/stories/menu/MainMenu.stories.tsx +++ b/.storybook/stories/menu/MainMenu.stories.tsx @@ -1,19 +1,19 @@ -import type {Meta, StoryObj} from '@storybook/react'; +import type {Meta, StoryObj} from "@storybook/react" -import MainMenu from "@components/menu/main-menu"; +import MainMenu from "@components/menu/main-menu" // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { - title: 'Design/Menu/Main Menu', + title: "Design/Menu/Main Menu", component: MainMenu, - tags: ['autodocs'], - argTypes: {} -}; + tags: ["autodocs"], + argTypes: {}, +} -export default meta; -type Story = StoryObj; +export default meta +type Story = StoryObj -const defaultMenuProps = {children: [], attributes: {}, expanded: true, internal: true} +const defaultMenuProps = {children: [], attributes: {}, expanded: true, internal: true, langcode: {}} // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args export const MainMenuComponent: Story = { args: { @@ -35,13 +35,13 @@ export const MainMenuComponent: Story = { {id: "8", title: "First Item", url: "#", ...defaultMenuProps}, {id: "9", title: "Second Item", url: "#", ...defaultMenuProps}, {id: "10", title: "Third Item", url: "#", ...defaultMenuProps}, - ] + ], }, {id: "7", title: "Third Item", url: "#", ...defaultMenuProps}, - ] + ], }, {id: "2", title: "Second Item", url: "#", ...defaultMenuProps}, {id: "3", title: "Third Item", url: "#", ...defaultMenuProps}, - ] + ], }, -}; +} diff --git a/.storybook/stories/menu/SideMenu.stories.tsx b/.storybook/stories/menu/SideMenu.stories.tsx index 8e61c4b3..cb7e2bd8 100644 --- a/.storybook/stories/menu/SideMenu.stories.tsx +++ b/.storybook/stories/menu/SideMenu.stories.tsx @@ -1,25 +1,25 @@ -import type {Meta, StoryObj} from '@storybook/react'; +import type {Meta, StoryObj} from "@storybook/react" -import SideNav from "@components/menu/side-nav"; +import SideNav from "@components/menu/side-nav" // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { - title: 'Design/Menu/Side Nav', + title: "Design/Menu/Side Nav", component: SideNav, - tags: ['autodocs'], + tags: ["autodocs"], argTypes: { menuItems: { table: { disable: true, - } - } - } -}; + }, + }, + }, +} -export default meta; -type Story = StoryObj; +export default meta +type Story = StoryObj -const defaultMenuProps = {children: [], attributes: {}, expanded: true, internal: true} +const defaultMenuProps = {children: [], attributes: {}, expanded: true, internal: true, langcode: {}} // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args export const SideNavComponent: Story = { args: { @@ -41,14 +41,14 @@ export const SideNavComponent: Story = { {id: "8", title: "First Item", url: "/foo/baz/foo", ...defaultMenuProps}, {id: "9", title: "Second Item", url: "/foo/baz/bar", ...defaultMenuProps}, {id: "10", title: "Third Item", url: "/foo/baz/bin", ...defaultMenuProps}, - ] + ], }, {id: "7", title: "Third Item", url: "/foo/bin", ...defaultMenuProps}, - ] + ], }, {id: "2", title: "Second Item", url: "/bar", ...defaultMenuProps}, {id: "3", title: "Third Item", url: "/baz", ...defaultMenuProps}, ], activeTrail: ["4", "6", "8"], }, -}; +} diff --git a/.storybook/stories/paragraphs/Banner.stories.tsx b/.storybook/stories/paragraphs/Banner.stories.tsx index 6e5ade45..42471aa5 100644 --- a/.storybook/stories/paragraphs/Banner.stories.tsx +++ b/.storybook/stories/paragraphs/Banner.stories.tsx @@ -1,8 +1,8 @@ -import type {Meta, StoryObj} from '@storybook/react'; -import {ComponentProps} from "react"; -import {ParagraphStanfordBanner, Text} from "@lib/gql/__generated__/drupal"; -import BannerParagraph from '@components/paragraphs/stanford-banner/banner-paragraph'; -import { getStoryBookImage } from '../storybook-entities'; +import type {Meta, StoryObj} from "@storybook/react" +import {ComponentProps} from "react" +import {ParagraphStanfordBanner, Text} from "@lib/gql/__generated__/drupal" +import BannerParagraph from "@components/paragraphs/stanford-banner/banner-paragraph" +import {getStoryBookImage} from "../storybook-entities" type ComponentStoryProps = ComponentProps & { text: Text["processed"] @@ -10,38 +10,39 @@ type ComponentStoryProps = ComponentProps & { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { - title: 'Design/Paragraphs/Banner', + title: "Design/Paragraphs/Banner", component: BannerParagraph, - tags: ['autodocs'], - argTypes: {} -}; + tags: ["autodocs"], + argTypes: {}, +} -export default meta; -type Story = StoryObj; +export default meta +type Story = StoryObj // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args export const Banner: Story = { render: ({...args}) => { - return + return }, args: { - paragraph:{ - __typename: 'ParagraphStanfordBanner', + paragraph: { + __typename: "ParagraphStanfordBanner", + status: true, composition: {}, langcode: {}, created: { offset: "", timestamp: Math.round(new Date().getTime() / 1000), time: new Date().toISOString(), - timezone: "America/Los_Angeles" + timezone: "America/Los_Angeles", }, id: "9954cc81-919b-4498-9151-bf930831fca7", suBannerHeader: "Nam scelerisque, urna vitae auctor efficitur, tortor nunc cursus tortor, ut blandit purus arcu quis sapien", suBannerBody: { - processed: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vitae dignissim felis. Nullam nulla leo, venenatis at feugiat sit amet, ultricies non lorem.

" + processed: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vitae dignissim felis. Nullam nulla leo, venenatis at feugiat sit amet, ultricies non lorem.

", }, suBannerImage: getStoryBookImage(), - suBannerSupHeader: "Vestibulum" - } - } -}; + suBannerSupHeader: "Vestibulum", + }, + }, +} diff --git a/.storybook/stories/paragraphs/Card.stories.tsx b/.storybook/stories/paragraphs/Card.stories.tsx index 9480ad0e..00cb2980 100644 --- a/.storybook/stories/paragraphs/Card.stories.tsx +++ b/.storybook/stories/paragraphs/Card.stories.tsx @@ -1,8 +1,8 @@ -import type {Meta, StoryObj} from '@storybook/react'; -import {ComponentProps} from "react"; -import {ParagraphStanfordCard, Text} from "@lib/gql/__generated__/drupal"; -import CardParagraph from '@components/paragraphs/stanford-card/card-paragraph'; -import { getStoryBookImage } from '../storybook-entities'; +import type {Meta, StoryObj} from "@storybook/react" +import {ComponentProps} from "react" +import {ParagraphStanfordCard, Text} from "@lib/gql/__generated__/drupal" +import CardParagraph from "@components/paragraphs/stanford-card/card-paragraph" +import {getStoryBookImage} from "../storybook-entities" type ComponentStoryProps = ComponentProps & { text: Text["processed"] @@ -10,43 +10,44 @@ type ComponentStoryProps = ComponentProps & { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { - title: 'Design/Paragraphs/Card', + title: "Design/Paragraphs/Card", component: CardParagraph, - tags: ['autodocs'], - argTypes: {} -}; + tags: ["autodocs"], + argTypes: {}, +} -export default meta; -type Story = StoryObj; +export default meta +type Story = StoryObj // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args export const Card: Story = { render: ({...args}) => { - return + return }, args: { - paragraph:{ - __typename: 'ParagraphStanfordCard', + paragraph: { + __typename: "ParagraphStanfordCard", + status: true, composition: {}, langcode: {}, created: { offset: "", timestamp: Math.round(new Date().getTime() / 1000), time: new Date().toISOString(), - timezone: "America/Los_Angeles" + timezone: "America/Los_Angeles", }, id: "9954cc81-919b-4498-9151-bf930831fca7", suCardHeader: "Nam scelerisque, urna vitae auctor efficitur, tortor nunc cursus tortor, ut blandit purus arcu quis sapien", suCardBody: { - processed: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vitae dignissim felis. Nullam nulla leo, venenatis at feugiat sit amet, ultricies non lorem.

" + processed: "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vitae dignissim felis. Nullam nulla leo, venenatis at feugiat sit amet, ultricies non lorem.

", }, suCardLink: { title: "Button", url: "/", - internal: true + internal: true, }, suCardMedia: getStoryBookImage(), - suCardSuperHeader: "Vestibulum" - } - } -}; + suCardSuperHeader: "Vestibulum", + }, + }, +} diff --git a/.storybook/stories/paragraphs/Gallery.stories.tsx b/.storybook/stories/paragraphs/Gallery.stories.tsx index 872c26e3..191513d1 100644 --- a/.storybook/stories/paragraphs/Gallery.stories.tsx +++ b/.storybook/stories/paragraphs/Gallery.stories.tsx @@ -1,7 +1,7 @@ -import type {Meta, StoryObj} from '@storybook/react'; -import {ComponentProps} from "react"; -import GalleryParagraph from '@components/paragraphs/stanford-gallery/gallery-paragraph'; -import { getStoryBookGalleryImage } from '../storybook-entities'; +import type {Meta, StoryObj} from "@storybook/react" +import {ComponentProps} from "react" +import GalleryParagraph from "@components/paragraphs/stanford-gallery/gallery-paragraph" +import {getStoryBookGalleryImage} from "../storybook-entities" type ComponentStoryProps = ComponentProps & { numberofimages: number @@ -9,55 +9,61 @@ type ComponentStoryProps = ComponentProps & { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { - title: 'Design/Paragraphs/Gallery', + title: "Design/Paragraphs/Gallery", component: GalleryParagraph, - tags: ['autodocs'], + tags: ["autodocs"], argTypes: { numberofimages: { control: { - type: 'number', + type: "number", min: 1, max: 20, - } + }, }, }, -}; +} -export default meta; -type Story = StoryObj; +export default meta +type Story = StoryObj // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args export const Gallery: Story = { render: ({numberofimages, paragraph, ...args}) => { paragraph.suGalleryImages = [] for (let i = 0; i < numberofimages; i++) { - paragraph.suGalleryImages.push(getStoryBookGalleryImage(undefined, 'Lorem Ipsum')) + paragraph.suGalleryImages.push(getStoryBookGalleryImage(undefined, "Lorem Ipsum")) } - return + return ( + + ) }, args: { numberofimages: 3, - paragraph:{ - __typename: 'ParagraphStanfordGallery', + paragraph: { + __typename: "ParagraphStanfordGallery", + status: true, composition: {}, langcode: {}, created: { offset: "", timestamp: Math.round(new Date().getTime() / 1000), time: new Date().toISOString(), - timezone: "America/Los_Angeles" + timezone: "America/Los_Angeles", }, id: "1e0c21ee-7cb8-4eff-8877-862d16c9885c", suGalleryButton: { url: "http://stanford.edu", title: "Button text", - internal:false, + internal: false, }, suGalleryDescription: { - processed: "

Pepper jack fromage frais pecorino cheesecake cheesy grin camembert de normandie macaroni cheese the big cheese.

" + processed: "

Pepper jack fromage frais pecorino cheesecake cheesy grin camembert de normandie macaroni cheese the big cheese.

", }, suGalleryHeadline: "This is a Gallery Headline", - suGalleryImages: [] - } - } -}; + suGalleryImages: [], + }, + }, +} diff --git a/.storybook/stories/paragraphs/MediaWithCaption.stories.tsx b/.storybook/stories/paragraphs/MediaWithCaption.stories.tsx index bde24f70..e51eb936 100644 --- a/.storybook/stories/paragraphs/MediaWithCaption.stories.tsx +++ b/.storybook/stories/paragraphs/MediaWithCaption.stories.tsx @@ -1,7 +1,7 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { ComponentProps } from "react"; -import StanfordMediaCaption from '@components/paragraphs/stanford-media-caption/media-caption-paragraph'; -import { getStoryBookImage } from '../storybook-entities'; +import type {Meta, StoryObj} from "@storybook/react" +import {ComponentProps} from "react" +import StanfordMediaCaption from "@components/paragraphs/stanford-media-caption/media-caption-paragraph" +import {getStoryBookImage} from "../storybook-entities" type ComponentStoryProps = ComponentProps & { // text: Text["processed"] @@ -9,42 +9,42 @@ type ComponentStoryProps = ComponentProps & { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { - title: 'Design/Paragraphs/MediaCaption', + title: "Design/Paragraphs/MediaCaption", component: StanfordMediaCaption, - tags: ['autodocs'], - argTypes: {} -}; + tags: ["autodocs"], + argTypes: {}, +} -export default meta; -type Story = StoryObj; +export default meta +type Story = StoryObj // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args export const Caption: Story = { - render: ({ ...args }) => { + render: ({...args}) => { return }, args: { paragraph: { - id:"6fa23537-dda7-4861-930a-648445d9904c", - __typename: 'ParagraphStanfordMediaCaption', + __typename: "ParagraphStanfordMediaCaption", + id: "6fa23537-dda7-4861-930a-648445d9904c", + status: true, composition: {}, langcode: {}, created: { offset: "", timestamp: Math.round(new Date().getTime() / 1000), time: new Date().toISOString(), - timezone: "America/Los_Angeles" + timezone: "America/Los_Angeles", }, suMediaCaptionCaption: { - processed:"

Here is my caption.

" + processed: "

Here is my caption.

", }, suMediaCaptionLink: { - title:"Link text.", - url:"/publications", - internal:true + title: "Link text.", + url: "/publications", + internal: true, }, suMediaCaptionMedia: getStoryBookImage(), - } - } -}; - + }, + }, +} diff --git a/app/@modal/(.)gallery/[...uuid]/page.tsx b/app/@modal/(.)gallery/[...uuid]/page.tsx index 72e9a461..df6b1d1d 100644 --- a/app/@modal/(.)gallery/[...uuid]/page.tsx +++ b/app/@modal/(.)gallery/[...uuid]/page.tsx @@ -1,36 +1,36 @@ -import Image from "next/image"; -import InterceptionModal from "@components/elements/interception-modal"; -import Link from "@components/elements/link"; -import {ParagraphStanfordGallery} from "@lib/gql/__generated__/drupal.d"; -import {graphqlClient} from "@lib/gql/gql-client"; -import {notFound} from "next/navigation"; -import {useId} from "react"; +import Image from "next/image" +import InterceptionModal from "@components/elements/interception-modal" +import Link from "@components/elements/link" +import {ParagraphStanfordGallery} from "@lib/gql/__generated__/drupal.d" +import {graphqlClient} from "@lib/gql/gql-client" +import {notFound} from "next/navigation" +import {useId} from "react" type Props = { - params: { uuid: string[] } + params: {uuid: string[]} } const Page = async ({params: {uuid}}: Props) => { - const captionId = useId(); + const captionId = useId() const [paragraphId, mediaUuid] = uuid - const paragraphQuery = await graphqlClient().Paragraph({uuid: paragraphId}); - if (paragraphQuery.paragraph?.__typename !== "ParagraphStanfordGallery") notFound(); + const paragraphQuery = await graphqlClient().Paragraph({uuid: paragraphId}) + if (paragraphQuery.paragraph?.__typename !== "ParagraphStanfordGallery") notFound() - const paragraph = paragraphQuery.paragraph as ParagraphStanfordGallery; + const paragraph = paragraphQuery.paragraph as ParagraphStanfordGallery - const currentImageIndex = paragraph.suGalleryImages?.findIndex((image => image.id === mediaUuid)) || 0; - const prevImageIndex = paragraph.suGalleryImages?.[currentImageIndex - 1] ? currentImageIndex - 1 : -1; - const nextImageIndex = paragraph.suGalleryImages?.[currentImageIndex + 1] ? currentImageIndex + 1 : -1; + const currentImageIndex = paragraph.suGalleryImages?.findIndex(image => image.id === mediaUuid) || 0 + const prevImageIndex = paragraph.suGalleryImages?.[currentImageIndex - 1] ? currentImageIndex - 1 : -1 + const nextImageIndex = paragraph.suGalleryImages?.[currentImageIndex + 1] ? currentImageIndex + 1 : -1 - let galleryImages = mediaUuid ? paragraph.suGalleryImages?.filter(image => image.id === mediaUuid) : paragraph.suGalleryImages; + let galleryImages = mediaUuid ? paragraph.suGalleryImages?.filter(image => image.id === mediaUuid) : paragraph.suGalleryImages galleryImages = galleryImages?.filter(image => !!image.suGalleryImage?.url) return ( {galleryImages?.map(galleryImage => { - if (!galleryImage.suGalleryImage?.url) return; + if (!galleryImage.suGalleryImage?.url) return return (
@@ -41,39 +41,52 @@ const Page = async ({params: {uuid}}: Props) => { width={galleryImage.suGalleryImage.width} height={galleryImage.suGalleryImage.height} alt={galleryImage.suGalleryImage.alt || ""} - className="max-w-full h-auto m-0 p-0" + className="m-0 h-auto max-w-full p-0" /> - {galleryImage.suGalleryCaption && -
+ {galleryImage.suGalleryCaption && ( +
{galleryImage.suGalleryCaption}
- } + )} - {(prevImageIndex || nextImageIndex) && + {(prevImageIndex || nextImageIndex) && ( - } + )}
) })}
) } -export default Page; \ No newline at end of file +export default Page diff --git a/app/@modal/default.tsx b/app/@modal/default.tsx index 6ddf1b76..86b9e9a3 100644 --- a/app/@modal/default.tsx +++ b/app/@modal/default.tsx @@ -1,3 +1,3 @@ export default function Default() { - return null; + return null } diff --git a/app/[...slug]/metadata.tsx b/app/[...slug]/metadata.tsx index 43b7522e..15643672 100644 --- a/app/[...slug]/metadata.tsx +++ b/app/[...slug]/metadata.tsx @@ -1,53 +1,53 @@ -import {Maybe, NodeStanfordEvent, NodeStanfordNews, NodeStanfordPage, NodeStanfordPerson, NodeStanfordPolicy, NodeUnion, ParagraphStanfordWysiwyg, ParagraphUnion} from "@lib/gql/__generated__/drupal.d"; -import {Metadata} from "next"; -import {decode} from "html-entities"; +import {Maybe, NodeStanfordEvent, NodeStanfordNews, NodeStanfordPage, NodeStanfordPerson, NodeStanfordPolicy, NodeUnion, ParagraphStanfordWysiwyg, ParagraphUnion} from "@lib/gql/__generated__/drupal.d" +import {Metadata} from "next" +import {decode} from "html-entities" export const getNodeMetadata = (node: NodeUnion): Metadata => { const defaultData = { title: node.title, - other: {} + other: {}, } switch (node.__typename) { case "NodeStanfordPage": return { ...getBasicPageMetaData(node), - ...defaultData + ...defaultData, } case "NodeStanfordNews": return { ...getNewsMetaData(node), - ...defaultData + ...defaultData, } case "NodeStanfordEvent": return { ...getEventMetaData(node), - ...defaultData + ...defaultData, } case "NodeStanfordPerson": return { ...getPersonMetaData(node), - ...defaultData + ...defaultData, } case "NodeStanfordPolicy": return { ...getPolicyMetaData(node), - ...defaultData + ...defaultData, } } - return defaultData; + return defaultData } const getBasicPageMetaData = (node: NodeStanfordPage) => { - const pageTitleBannerImage = node.suPageBanner?.__typename === "ParagraphStanfordPageTitleBanner" && node.suPageBanner.suTitleBannerImage.mediaImage; - const bannerImage = node.suPageBanner?.__typename === "ParagraphStanfordBanner" && node.suPageBanner.suBannerImage?.mediaImage; - const image = node.suPageImage?.mediaImage || pageTitleBannerImage || bannerImage; + const pageTitleBannerImage = node.suPageBanner?.__typename === "ParagraphStanfordPageTitleBanner" && node.suPageBanner.suTitleBannerImage.mediaImage + const bannerImage = node.suPageBanner?.__typename === "ParagraphStanfordBanner" && node.suPageBanner.suBannerImage?.mediaImage + const image = node.suPageImage?.mediaImage || pageTitleBannerImage || bannerImage - const description = node.suPageDescription || getFirstText(node.suPageComponents); + const description = node.suPageDescription || getFirstText(node.suPageComponents) return { description: description, @@ -55,21 +55,21 @@ const getBasicPageMetaData = (node: NodeStanfordPage) => { type: "website", title: node.title, description: description, - images: image ? getOpenGraphImage(image.url, image.alt || "") : [] - } + images: image ? getOpenGraphImage(image.url, image.alt || "") : [], + }, } } const getNewsMetaData = (node: NodeStanfordNews) => { - const pageImage = node.suNewsFeaturedMedia?.mediaImage; - const bannerImage = node.suNewsBanner?.__typename === "MediaImage" ? node.suNewsBanner.mediaImage : undefined; + const pageImage = node.suNewsFeaturedMedia?.mediaImage + const bannerImage = node.suNewsBanner?.__typename === "MediaImage" ? node.suNewsBanner.mediaImage : undefined const imageUrl = pageImage?.url || bannerImage?.url - const imageAlt = pageImage?.alt || bannerImage?.alt || ""; + const imageAlt = pageImage?.alt || bannerImage?.alt || "" - const description = node.suNewsDek || getFirstText(node.suNewsComponents); + const description = node.suNewsDek || getFirstText(node.suNewsComponents) - let publishTime; + let publishTime if (node.suNewsPublishingDate) { publishTime = new Date(node.suNewsPublishingDate.time).toISOString() } @@ -82,16 +82,16 @@ const getNewsMetaData = (node: NodeStanfordNews) => { description: description, publishedTime: publishTime || null, tag: node.suNewsTopics?.map(term => term.name) || [], - images: getOpenGraphImage(imageUrl, imageAlt) - } + images: getOpenGraphImage(imageUrl, imageAlt), + }, } } const getPersonMetaData = (node: NodeStanfordPerson) => { - const pageImage = node.suPersonPhoto?.mediaImage; - const imageUrl = pageImage?.url; - const imageAlt = pageImage?.alt || ""; - const description = node.suPersonFullTitle || getCleanDescription(node.body?.processed); + const pageImage = node.suPersonPhoto?.mediaImage + const imageUrl = pageImage?.url + const imageAlt = pageImage?.alt || "" + const description = node.suPersonFullTitle || getCleanDescription(node.body?.processed) return { description: description, @@ -101,13 +101,13 @@ const getPersonMetaData = (node: NodeStanfordPerson) => { description: description, firstName: node.suPersonFirstName, lastName: node.suPersonLastName, - images: getOpenGraphImage(imageUrl, imageAlt) - } + images: getOpenGraphImage(imageUrl, imageAlt), + }, } } const getEventMetaData = (node: NodeStanfordEvent) => { - const description = node.suEventSubheadline || getCleanDescription(node.body?.processed); + const description = node.suEventSubheadline || getCleanDescription(node.body?.processed) return { description: description, @@ -115,12 +115,12 @@ const getEventMetaData = (node: NodeStanfordEvent) => { type: "website", title: node.title, description: description, - } + }, } } const getPolicyMetaData = (node: NodeStanfordPolicy) => { - const description = getCleanDescription(node.body?.processed); + const description = getCleanDescription(node.body?.processed) return { description: description, @@ -128,25 +128,30 @@ const getPolicyMetaData = (node: NodeStanfordPolicy) => { type: "website", title: node.title, description: description, - } + }, } } const getFirstText = (components?: Maybe) => { - const firstWysiwyg = components?.find(component => component.__typename === "ParagraphStanfordWysiwyg") as ParagraphStanfordWysiwyg; + const firstWysiwyg = components?.find(component => component.__typename === "ParagraphStanfordWysiwyg") as ParagraphStanfordWysiwyg if (firstWysiwyg) { - return getCleanDescription(firstWysiwyg.suWysiwygText?.processed); + return getCleanDescription(firstWysiwyg.suWysiwygText?.processed) } } const getCleanDescription = (description: string | undefined): string | undefined => { if (description) { - const text: string = description.replace(/(<([^>]+)>)/gi, " ").replace("/ +/", " ").split(".").slice(0, 1).join(".") + "."; - return text?.length > 1 ? decode(text) : undefined; + const text: string = + description + .replace(/(<([^>]+)>)/gi, " ") + .replace("/ +/", " ") + .split(".") + .slice(0, 1) + .join(".") + "." + return text?.length > 1 ? decode(text) : undefined } } - const getOpenGraphImage = (imageUrl?: string, imageAlt?: string) => { if (imageUrl) { return [ @@ -155,8 +160,8 @@ const getOpenGraphImage = (imageUrl?: string, imageAlt?: string) => { width: 956, height: 478, alt: imageAlt, - } + }, ] } - return []; -} \ No newline at end of file + return [] +} diff --git a/app/[...slug]/page.tsx b/app/[...slug]/page.tsx index 51b34133..6532c8b1 100644 --- a/app/[...slug]/page.tsx +++ b/app/[...slug]/page.tsx @@ -1,35 +1,36 @@ -import NodePage from "@components/nodes/pages/node-page"; -import {Metadata} from "next"; -import {NodeUnion} from "@lib/gql/__generated__/drupal.d"; -import {getAllNodes, getEntityFromPath} from "@lib/gql/gql-queries"; -import {getNodeMetadata} from "./metadata"; -import {notFound, redirect} from "next/navigation"; -import {getPathFromContext, PageProps} from "@lib/drupal/utils"; +import NodePage from "@components/nodes/pages/node-page" +import {Metadata} from "next" +import {NodeUnion} from "@lib/gql/__generated__/drupal.d" +import {getAllNodes, getEntityFromPath} from "@lib/gql/gql-queries" +import {getNodeMetadata} from "./metadata" +import {notFound, redirect} from "next/navigation" +import {getPathFromContext, PageProps} from "@lib/drupal/utils" // https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config -export const revalidate = false; -export const dynamic = "force-static"; +export const revalidate = false +export const dynamic = "force-static" const Page = async ({params}: PageProps) => { - const {redirect: redirectPath, entity, error} = await getEntityFromPath(getPathFromContext({params})) + const path = getPathFromContext({params}) + const {redirect: redirectPath, entity, error} = await getEntityFromPath(path) - if (error) throw new Error(error); + if (error) throw error if (redirectPath?.url) redirect(redirectPath.url) - if (!entity) notFound(); + if (!entity) notFound() - return + return } export const generateMetadata = async ({params}: PageProps): Promise => { const path = getPathFromContext({params}) const {entity} = await getEntityFromPath(path) - return entity ? getNodeMetadata(entity) : {}; + return entity ? getNodeMetadata(entity) : {} } export const generateStaticParams = async (): Promise => { if (process.env.BUILD_COMPLETE !== "true") return [] - const nodes = await getAllNodes(); - return nodes.map(node => ({slug: node.path.split("/").filter(part => !!part)})); + const nodes = await getAllNodes() + return nodes.map(node => ({slug: node.path.split("/").filter(part => !!part)})) } -export default Page; \ No newline at end of file +export default Page diff --git a/app/api/draft/disable/route.tsx b/app/api/draft/disable/route.tsx index b43c903b..80816f0e 100644 --- a/app/api/draft/disable/route.tsx +++ b/app/api/draft/disable/route.tsx @@ -1,9 +1,9 @@ -import {NextResponse} from "next/server"; -import {cookies} from "next/headers"; +import {NextResponse} from "next/server" +import {cookies} from "next/headers" -export const revalidate = 0; +export const revalidate = 0 export async function GET() { - cookies().delete("preview"); + cookies().delete("preview") return NextResponse.json({disabled: true}, {status: 200}) -} \ No newline at end of file +} diff --git a/app/api/draft/route.tsx b/app/api/draft/route.tsx index b52e06b4..510443bf 100644 --- a/app/api/draft/route.tsx +++ b/app/api/draft/route.tsx @@ -1,11 +1,10 @@ -import {NextRequest, NextResponse} from "next/server"; +import {NextRequest, NextResponse} from "next/server" import {redirect} from "next/navigation" -import {cookies} from "next/headers"; +import {cookies} from "next/headers" -export const revalidate = 0; +export const revalidate = 0 export async function GET(request: NextRequest) { - const secret = request.nextUrl.searchParams.get("secret") const slug = request.nextUrl.searchParams.get("slug") @@ -24,9 +23,9 @@ export async function GET(request: NextRequest) { sameSite: "none", secure: true, partitioned: true, - }); + }) // Redirect to the path from the fetched post // We don"t redirect to searchParams.slug as that might lead to open redirect vulnerabilities redirect(`/preview${slug === "/home" ? "" : slug}`) -} \ No newline at end of file +} diff --git a/app/api/revalidate/route.tsx b/app/api/revalidate/route.tsx index 10280791..97b4280b 100644 --- a/app/api/revalidate/route.tsx +++ b/app/api/revalidate/route.tsx @@ -1,21 +1,24 @@ -import {NextRequest, NextResponse} from "next/server"; -import {cache as nodeCache} from "@lib/drupal/get-cache"; -import {revalidateTag} from "next/cache"; +import {NextRequest, NextResponse} from "next/server" +import {cache as nodeCache} from "@lib/drupal/get-cache" +import {revalidateTag} from "next/cache" -export const revalidate = 0; +export const revalidate = 0 export const GET = async (request: NextRequest) => { + const secret = request.nextUrl.searchParams.get("secret") + if (secret !== process.env.DRUPAL_REVALIDATE_SECRET) return NextResponse.json({message: "Invalid token"}, {status: 403}) - const secret = request.nextUrl.searchParams.get("secret"); - if (secret !== process.env.DRUPAL_REVALIDATE_SECRET) return NextResponse.json({message: "Invalid token"}, {status: 403}); + let path = request.nextUrl.searchParams.get("slug") + if (!path || path.startsWith("/node/")) return NextResponse.json({message: "Invalid slug"}, {status: 400}) - let path = request.nextUrl.searchParams.get("slug"); - if (!path || path.startsWith("/node/")) return NextResponse.json({message: "Invalid slug"}, {status: 400}); + const tagsInvalidated = ["paths", `paths:${path}`] + if (path.startsWith("/tags/")) + path + .substring(6) + .split("/") + .map(tag => tagsInvalidated.push(tag)) - const tagsInvalidated = ["paths", `paths:${path}`]; - if (path.startsWith("/tags/")) path.substring(6).split("/").map(tag => tagsInvalidated.push(tag)) - - tagsInvalidated.map(tag => revalidateTag(tag)); + tagsInvalidated.map(tag => revalidateTag(tag)) nodeCache.del(tagsInvalidated) - return NextResponse.json({revalidated: true, tags: tagsInvalidated}); -} \ No newline at end of file + return NextResponse.json({revalidated: true, tags: tagsInvalidated}) +} diff --git a/app/error.tsx b/app/error.tsx index 3b07979b..7726a4ea 100644 --- a/app/error.tsx +++ b/app/error.tsx @@ -1,19 +1,21 @@ -"use client"; +"use client" -import Button from "@components/elements/button"; +import Button from "@components/elements/button" -const ErrorPage = ({error, reset}: { error: Error; reset: () => void }) => { - console.warn(error.message); +const ErrorPage = ({error, reset}: {error: Error; reset: () => void}) => { + console.warn(error.message) return ( -
+

Something went wrong!

-

- Apologies, an error occurred when attempting to preset the page you are attempting to view. Please try a - different path. -

- +

Apologies, an error occurred when attempting to preset the page you are attempting to view. Please try a different path.

+
) } -export default ErrorPage \ No newline at end of file +export default ErrorPage diff --git a/app/gallery/[...uuid]/page.tsx b/app/gallery/[...uuid]/page.tsx index 68bf7de9..0ce90fc8 100644 --- a/app/gallery/[...uuid]/page.tsx +++ b/app/gallery/[...uuid]/page.tsx @@ -1,28 +1,28 @@ -import {H1} from "@components/elements/headers"; -import {graphqlClient} from "@lib/gql/gql-client"; -import {notFound} from "next/navigation"; -import {ParagraphStanfordGallery} from "@lib/gql/__generated__/drupal"; -import Image from "next/image"; +import {H1} from "@components/elements/headers" +import {graphqlClient} from "@lib/gql/gql-client" +import {notFound} from "next/navigation" +import {ParagraphStanfordGallery} from "@lib/gql/__generated__/drupal" +import Image from "next/image" export const metadata = { title: "Gallery Image", robots: { - index: false - } + index: false, + }, } type Props = { - params: { uuid: string[] } + params: {uuid: string[]} } const Page = async ({params: {uuid}}: Props) => { const [paragraphId, mediaUuid] = uuid - const paragraphQuery = await graphqlClient().Paragraph({uuid: paragraphId}); - if (paragraphQuery.paragraph?.__typename !== "ParagraphStanfordGallery") notFound(); + const paragraphQuery = await graphqlClient().Paragraph({uuid: paragraphId}) + if (paragraphQuery.paragraph?.__typename !== "ParagraphStanfordGallery") notFound() - const paragraph = paragraphQuery.paragraph as ParagraphStanfordGallery; - let galleryImages = mediaUuid ? paragraph.suGalleryImages?.filter(image => image.id === mediaUuid) : paragraph.suGalleryImages; + const paragraph = paragraphQuery.paragraph as ParagraphStanfordGallery + let galleryImages = mediaUuid ? paragraph.suGalleryImages?.filter(image => image.id === mediaUuid) : paragraph.suGalleryImages galleryImages = galleryImages?.filter(image => !!image.suGalleryImage?.url) @@ -30,7 +30,7 @@ const Page = async ({params: {uuid}}: Props) => {

{paragraph.suGalleryHeadline || "Media"}

{galleryImages?.map(galleryImage => { - if (!galleryImage.suGalleryImage?.url) return; + if (!galleryImage.suGalleryImage?.url) return return (
@@ -41,11 +41,7 @@ const Page = async ({params: {uuid}}: Props) => { alt={""} /> - {galleryImage.suGalleryCaption && -
- {galleryImage.suGalleryCaption} -
- } + {galleryImage.suGalleryCaption &&
{galleryImage.suGalleryCaption}
}
) })} @@ -53,4 +49,4 @@ const Page = async ({params: {uuid}}: Props) => { ) } -export default Page \ No newline at end of file +export default Page diff --git a/app/layout.tsx b/app/layout.tsx index e5383aff..a953dd26 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,22 +1,22 @@ -import "../src/styles/index.css"; -import BackToTop from "@components/elements/back-to-top"; -import PageFooter from "@components/global/page-footer"; -import PageHeader from "@components/global/page-header"; -import {Icon} from "next/dist/lib/metadata/types/metadata-types"; -import {sourceSans3} from "../src/styles/fonts"; -import DrupalWindowSync from "@components/elements/drupal-window-sync"; -import {isPreviewMode} from "@lib/drupal/utils"; -import UserAnalytics from "@components/elements/user-analytics"; +import "../src/styles/index.css" +import BackToTop from "@components/elements/back-to-top" +import PageFooter from "@components/global/page-footer" +import PageHeader from "@components/global/page-header" +import {Icon} from "next/dist/lib/metadata/types/metadata-types" +import {sourceSans3} from "../src/styles/fonts" +import DrupalWindowSync from "@components/elements/drupal-window-sync" +import {isPreviewMode} from "@lib/drupal/utils" +import UserAnalytics from "@components/elements/user-analytics" const appleIcons: Icon[] = [60, 72, 76, 114, 120, 144, 152, 180].map(size => ({ url: `https://www-media.stanford.edu/assets/favicon/apple-touch-icon-${size}x${size}.png`, sizes: `${size}x${size}`, -})); +})) const icons: Icon[] = [16, 32, 96, 128, 192, 196].map(size => ({ url: size === 128 ? `https://www-media.stanford.edu/assets/favicon/favicon-${size}.png` : `https://www-media.stanford.edu/assets/favicon/favicon-${size}x${size}.png`, - sizes: `${size}x${size}` -})); + sizes: `${size}x${size}`, +})) /** * Metadata that does not change often. @@ -35,39 +35,47 @@ export const metadata = { }, icons: { icon: [{url: "/favicon.ico"}, ...icons], - apple: appleIcons - } + apple: appleIcons, + }, } // https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config -export const revalidate = false; +export const revalidate = false -const RootLayout = ({children, modal}: { children: React.ReactNode, modal: React.ReactNode }) => { - const isPreview = isPreviewMode(); +const RootLayout = ({children, modal}: {children: React.ReactNode; modal: React.ReactNode}) => { + const isPreview = isPreviewMode() return ( - - {/* Add Google Analytics and SiteImprove when not in preview mode. */} - {!isPreview && - - } - - - - -
- -
- {children} + + {/* Add Google Analytics and SiteImprove when not in preview mode. */} + {!isPreview && } + + + -
- - -
- {modal} - +
+ +
+ {children} +
+ + +
+ {modal} + ) } -export default RootLayout; \ No newline at end of file +export default RootLayout diff --git a/app/not-found.tsx b/app/not-found.tsx index 5a46f80c..01f85e83 100644 --- a/app/not-found.tsx +++ b/app/not-found.tsx @@ -1,13 +1,11 @@ -import {H1} from "@components/elements/headers"; +import {H1} from "@components/elements/headers" const NotFound = () => { return (

Page not found

-

- Unable to find the page you were looking for. -

+

Unable to find the page you were looking for.

) } -export default NotFound; \ No newline at end of file +export default NotFound diff --git a/app/page.tsx b/app/page.tsx index 005d2aba..a0d127f9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,32 +1,33 @@ -import Rows from "@components/paragraphs/rows/rows"; -import {notFound} from "next/navigation"; -import {getConfigPage, getEntityFromPath} from "@lib/gql/gql-queries"; -import {NodeStanfordPage, NodeUnion, StanfordBasicSiteSetting} from "@lib/gql/__generated__/drupal.d"; -import {isPreviewMode} from "@lib/drupal/utils"; -import {Metadata} from "next"; -import {getNodeMetadata} from "./[...slug]/metadata"; -import BannerParagraph from "@components/paragraphs/stanford-banner/banner-paragraph"; +import Rows from "@components/paragraphs/rows/rows" +import {notFound} from "next/navigation" +import {getConfigPage, getEntityFromPath} from "@lib/gql/gql-queries" +import {NodeStanfordPage, NodeUnion, StanfordBasicSiteSetting} from "@lib/gql/__generated__/drupal.d" +import {isPreviewMode} from "@lib/drupal/utils" +import {Metadata} from "next" +import {getNodeMetadata} from "./[...slug]/metadata" +import BannerParagraph from "@components/paragraphs/stanford-banner/banner-paragraph" // https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config -export const revalidate = false; -export const dynamic = "force-static"; +export const revalidate = false +export const dynamic = "force-static" const Home = async () => { - const {entity, error} = await getEntityFromPath("/", isPreviewMode()); + const {entity, error} = await getEntityFromPath("/", isPreviewMode()) - if (error) throw new Error(error); - if (!entity) notFound(); + if (error) throw error + if (!entity) notFound() return (
- {entity.suPageBanner?.__typename === "ParagraphStanfordBanner" && + {entity.suPageBanner?.__typename === "ParagraphStanfordBanner" && (
- +
- } - {entity.suPageComponents && - - } + )} + {entity.suPageComponents && }
) } @@ -34,10 +35,10 @@ const Home = async () => { export const generateMetadata = async (): Promise => { const siteSettingsConfig = await getConfigPage("StanfordBasicSiteSetting") const {entity} = await getEntityFromPath("/") - const metadata = entity ? getNodeMetadata(entity) : {}; - metadata.title = siteSettingsConfig?.suSiteName || metadata.title; - if (metadata.openGraph?.title) metadata.openGraph.title = siteSettingsConfig?.suSiteName || metadata.openGraph.title; - return metadata; + const metadata = entity ? getNodeMetadata(entity) : {} + metadata.title = siteSettingsConfig?.suSiteName || metadata.title + if (metadata.openGraph?.title) metadata.openGraph.title = siteSettingsConfig?.suSiteName || metadata.openGraph.title + return metadata } -export default Home; \ No newline at end of file +export default Home diff --git a/app/preview/[...slug]/page.tsx b/app/preview/[...slug]/page.tsx index 64fe5dd9..9a45abff 100644 --- a/app/preview/[...slug]/page.tsx +++ b/app/preview/[...slug]/page.tsx @@ -1,25 +1,23 @@ -import NodePage from "@components/nodes/pages/node-page"; -import UnpublishedBanner from "@components/elements/unpublished-banner"; -import {NodeUnion} from "@lib/gql/__generated__/drupal.d"; -import {getEntityFromPath} from "@lib/gql/gql-queries"; -import {notFound} from "next/navigation"; -import {getPathFromContext, isPreviewMode, PageProps} from "@lib/drupal/utils"; +import NodePage from "@components/nodes/pages/node-page" +import UnpublishedBanner from "@components/elements/unpublished-banner" +import {NodeUnion} from "@lib/gql/__generated__/drupal.d" +import {getEntityFromPath} from "@lib/gql/gql-queries" +import {notFound} from "next/navigation" +import {getPathFromContext, isPreviewMode, PageProps} from "@lib/drupal/utils" const PreviewPage = async ({params}: PageProps) => { - if (!isPreviewMode()) notFound(); - const { entity, error} = await getEntityFromPath(getPathFromContext({params}), true) + if (!isPreviewMode()) notFound() + const {entity, error} = await getEntityFromPath(getPathFromContext({params}), true) - if (error) throw new Error(error); - if (!entity) notFound(); + if (error) throw error + if (!entity) notFound() return ( <> - - Unpublished Page - - + Unpublished Page + ) } -export default PreviewPage; \ No newline at end of file +export default PreviewPage diff --git a/app/preview/layout.tsx b/app/preview/layout.tsx index e18c6c8e..5d0fe3d2 100644 --- a/app/preview/layout.tsx +++ b/app/preview/layout.tsx @@ -1,21 +1,19 @@ -import {isPreviewMode} from "@lib/drupal/utils"; -import Editori11y from "@components/tools/editorially"; -import UnpublishedBanner from "@components/elements/unpublished-banner"; +import {isPreviewMode} from "@lib/drupal/utils" +import Editori11y from "@components/tools/editorially" +import UnpublishedBanner from "@components/elements/unpublished-banner" -const Layout = ({children}: { children: React.ReactNode }) => { - const inPreview = isPreviewMode(); +const Layout = ({children}: {children: React.ReactNode}) => { + const inPreview = isPreviewMode() return ( <> - {inPreview && + {inPreview && ( <> - - - Preview Mode - + + Preview Mode - } + )} {children} ) } -export default Layout; \ No newline at end of file +export default Layout diff --git a/app/preview/page.tsx b/app/preview/page.tsx index 292c2c7f..60ce1ca0 100644 --- a/app/preview/page.tsx +++ b/app/preview/page.tsx @@ -1,10 +1,10 @@ -import {notFound} from "next/navigation"; -import {isPreviewMode} from "@lib/drupal/utils"; -import Page from "../page"; +import {notFound} from "next/navigation" +import {isPreviewMode} from "@lib/drupal/utils" +import Page from "../page" const PreviewPage = async () => { - if (!isPreviewMode()) notFound(); - return + if (!isPreviewMode()) notFound() + return } -export default PreviewPage; \ No newline at end of file +export default PreviewPage diff --git a/app/search/page.tsx b/app/search/page.tsx index 58c3580b..313fb193 100644 --- a/app/search/page.tsx +++ b/app/search/page.tsx @@ -1,11 +1,11 @@ -import {H1} from "@components/elements/headers"; -import {getConfigPage} from "@lib/gql/gql-queries"; -import {StanfordBasicSiteSetting} from "@lib/gql/__generated__/drupal.d"; -import {IndexUiState} from "instantsearch.js/es/types/ui-state"; -import AlgoliaSearch from "@components/algolia/algolia-search"; +import {H1} from "@components/elements/headers" +import {getConfigPage} from "@lib/gql/gql-queries" +import {StanfordBasicSiteSetting} from "@lib/gql/__generated__/drupal.d" +import {IndexUiState} from "instantsearch.js/es/types/ui-state" +import AlgoliaSearch from "@components/algolia/algolia-search" // https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config -export const revalidate = false; +export const revalidate = false export const metadata = { title: "Search", @@ -14,10 +14,9 @@ export const metadata = { index: false, follow: false, noarchive: true, - } + }, } -const Page = async ({searchParams}: { searchParams?: { [_key: string]: string } }) => { - +const Page = async ({searchParams}: {searchParams?: {[_key: string]: string}}) => { const siteSettingsConfig = await getConfigPage("StanfordBasicSiteSetting") const initialState: IndexUiState = {refinementList: {}} @@ -25,10 +24,15 @@ const Page = async ({searchParams}: { searchParams?: { [_key: string]: string } return (
-
-

Search

+
+

+ Search +

- {(siteSettingsConfig?.suSiteAlgoliaId && siteSettingsConfig?.suSiteAlgoliaIndex && siteSettingsConfig?.suSiteAlgoliaSearch) && + {siteSettingsConfig?.suSiteAlgoliaId && siteSettingsConfig?.suSiteAlgoliaIndex && siteSettingsConfig?.suSiteAlgoliaSearch && ( <> - } + )}
) } -export default Page; \ No newline at end of file +export default Page diff --git a/app/sitemap.tsx b/app/sitemap.tsx index 4c8a5fbc..dc480078 100644 --- a/app/sitemap.tsx +++ b/app/sitemap.tsx @@ -1,23 +1,24 @@ -import {MetadataRoute} from "next"; -import {getAllNodes} from "@lib/gql/gql-queries"; +import {MetadataRoute} from "next" +import {getAllNodes} from "@lib/gql/gql-queries" // https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config -export const revalidate = false; -export const dynamic = "force-static"; +export const revalidate = false +export const dynamic = "force-static" const Sitemap = async (): Promise => { - const nodes = await getAllNodes(); - const sitemap: MetadataRoute.Sitemap = []; + const nodes = await getAllNodes() + const sitemap: MetadataRoute.Sitemap = [] - nodes.map(node => sitemap.push({ - url: `${process.env.NEXT_PUBLIC_DOMAIN || ""}${node.path}`, - lastModified: new Date(node.changed.time), - priority: node.__typename === "NodeStanfordPage" ? 1 : .8, - changeFrequency: node.__typename === "NodeStanfordPage" ? "weekly": "monthly" - })); + nodes.map(node => + sitemap.push({ + url: `${process.env.NEXT_PUBLIC_DOMAIN || ""}${node.path}`, + lastModified: new Date(node.changed.time), + priority: node.__typename === "NodeStanfordPage" ? 1 : 0.8, + changeFrequency: node.__typename === "NodeStanfordPage" ? "weekly" : "monthly", + }) + ) - return sitemap; + return sitemap } - -export default Sitemap; \ No newline at end of file +export default Sitemap diff --git a/package.json b/package.json index 5e217a0e..e0c30268 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dev": "NODE_OPTIONS='--inspect' DEV=true next dev", "build": "next build", "analyze": "ANALYZE=true next build", - "preview": "next build && next start", + "preview": "next build --no-lint && next start", "start": "next start", "lint": "next lint && tsc", "storybook": "storybook dev -p 6006", @@ -18,9 +18,9 @@ "@heroicons/react": "^2.1.3", "@js-temporal/polyfill": "^0.4.4", "@mui/base": "^5.0.0-dev.20240529-082515-213b5e33ab", - "@next/third-parties": "^14.2.3", + "@next/third-parties": "^14.2.4", "@tailwindcss/container-queries": "^0.1.1", - "@types/node": "^20.14.0", + "@types/node": "^20.14.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "algoliasearch": "^4.23.3", @@ -30,26 +30,26 @@ "decanter": "^7.3.0", "drupal-jsonapi-params": "^2.3.1", "eslint": "^8.57.0", - "eslint-config-next": "^14.2.3", - "graphql": "^16.8.1", + "eslint-config-next": "^14.2.4", + "graphql": "^16.8.2", "graphql-request": "^7.0.1", "graphql-tag": "^2.12.6", "html-entities": "^2.5.2", "html-react-parser": "^5.1.10", - "next": "^14.2.3", + "next": "^14.2.4", "next-drupal": "^1.6.0", "postcss": "^8.4.38", "qs": "^6.12.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-focus-lock": "^2.12.1", - "react-instantsearch": "^7.10.0", - "react-instantsearch-nextjs": "^0.3.0", + "react-instantsearch": "^7.11.1", + "react-instantsearch-nextjs": "^0.3.2", "react-slick": "^0.30.2", "react-tiny-oembed": "^1.1.0", "sharp": "^0.33.4", "tailwind-merge": "^2.3.0", - "tailwindcss": "^3.4.3", + "tailwindcss": "^3.4.4", "typescript": "^5.4.5", "usehooks-ts": "^3.1.0" }, @@ -59,14 +59,14 @@ "@graphql-codegen/import-types-preset": "^3.0.0", "@graphql-codegen/typescript-graphql-request": "^6.2.0", "@graphql-codegen/typescript-operations": "^4.2.1", - "@next/bundle-analyzer": "^14.2.3", - "@storybook/addon-essentials": "^8.1.5", - "@storybook/addon-interactions": "^8.1.4", - "@storybook/addon-links": "^8.1.5", + "@next/bundle-analyzer": "^14.2.4", + "@storybook/addon-essentials": "^8.1.7", + "@storybook/addon-interactions": "^8.1.7", + "@storybook/addon-links": "^8.1.7", "@storybook/addon-styling": "^1.3.7", - "@storybook/blocks": "^8.1.5", - "@storybook/nextjs": "^8.1.5", - "@storybook/react": "^8.1.5", + "@storybook/blocks": "^8.1.7", + "@storybook/nextjs": "^8.1.7", + "@storybook/react": "^8.1.7", "@storybook/testing-library": "^0.2.2", "@types/react-slick": "^0.23.13", "concurrently": "^8.2.2", @@ -74,10 +74,10 @@ "eslint-plugin-deprecation": "^3.0.0", "eslint-plugin-storybook": "^0.8.0", "eslint-plugin-unused-imports": "^4.0.0", - "prettier": "^3.3.0", - "prettier-plugin-tailwindcss": "^0.6.1", + "prettier": "^3.3.2", + "prettier-plugin-tailwindcss": "^0.6.3", "react-docgen": "^7.0.3", - "storybook": "^8.1.5", + "storybook": "^8.1.7", "tsconfig-paths-webpack-plugin": "^4.1.0" }, "packageManager": "yarn@4.1.1" diff --git a/src/components/algolia/algolia-search.tsx b/src/components/algolia/algolia-search.tsx index aa020b7f..42873fa9 100644 --- a/src/components/algolia/algolia-search.tsx +++ b/src/components/algolia/algolia-search.tsx @@ -1,15 +1,15 @@ -"use client"; +"use client" -import algoliasearch from "algoliasearch/lite"; -import {useHits, useSearchBox} from "react-instantsearch"; -import {InstantSearchNext} from "react-instantsearch-nextjs"; -import {useRef} from "react"; -import Button from "@components/elements/button"; -import {UseSearchBoxProps} from "react-instantsearch"; -import {useRouter} from "next/navigation"; -import {IndexUiState} from "instantsearch.js/es/types/ui-state"; -import DefaultHit, {DefaultAlgoliaHit} from "@components/algolia/hits/default"; -import {Hit as HitType} from "instantsearch.js"; +import algoliasearch from "algoliasearch/lite" +import {useHits, useSearchBox} from "react-instantsearch" +import {InstantSearchNext} from "react-instantsearch-nextjs" +import {useRef} from "react" +import Button from "@components/elements/button" +import {UseSearchBoxProps} from "react-instantsearch" +import {useRouter} from "next/navigation" +import {IndexUiState} from "instantsearch.js/es/types/ui-state" +import DefaultHit, {DefaultAlgoliaHit} from "@components/algolia/hits/default" +import {Hit as HitType} from "instantsearch.js" type Props = { appId: string @@ -19,7 +19,7 @@ type Props = { } const AlgoliaSearch = ({appId, searchIndex, searchApiKey, initialUiState = {}}: Props) => { - const searchClient = algoliasearch(appId, searchApiKey); + const searchClient = algoliasearch(appId, searchApiKey) return (
@@ -30,8 +30,8 @@ const AlgoliaSearch = ({appId, searchIndex, searchApiKey, initialUiState = {}}: future={{preserveSharedStateOnUnmount: true}} >
- - + +
@@ -39,30 +39,29 @@ const AlgoliaSearch = ({appId, searchIndex, searchApiKey, initialUiState = {}}: } const HitList = () => { - const {hits} = useHits>(); + const {items: hits} = useHits>() if (hits.length === 0) { - return ( -

No results for your search. Please try another search.

- ) + return

No results for your search. Please try another search.

} return (
    - {hits.map(hit => -
  • - + {hits.map(hit => ( +
  • +
  • - )} + ))}
) } - - const SearchBox = (props?: UseSearchBoxProps) => { - const router = useRouter(); - const {query, refine} = useSearchBox(props); - const inputRef = useRef(null); + const router = useRouter() + const {query, refine} = useSearchBox(props) + const inputRef = useRef(null) if (query) { router.replace(`?q=${query}`, {scroll: false}) @@ -74,30 +73,33 @@ const SearchBox = (props?: UseSearchBoxProps) => { action="" role="search" noValidate - onSubmit={(e) => { - e.preventDefault(); - e.stopPropagation(); - inputRef.current?.blur(); - refine(inputRef.current?.value || ""); + onSubmit={e => { + e.preventDefault() + e.stopPropagation() + inputRef.current?.blur() + refine(inputRef.current?.value || "") }} - onReset={(event) => { - event.preventDefault(); - event.stopPropagation(); - refine(""); + onReset={event => { + event.preventDefault() + event.stopPropagation() + refine("") if (inputRef.current) { - inputRef.current.value = ""; - inputRef.current.focus(); + inputRef.current.value = "" + inputRef.current.focus() } }} >
-
- +
-
Showing results for {query}
+
+ Showing results for {query} +
- ); + ) } -export default AlgoliaSearch; \ No newline at end of file +export default AlgoliaSearch diff --git a/src/components/algolia/hits/default.tsx b/src/components/algolia/hits/default.tsx index 57c81fad..af38079d 100644 --- a/src/components/algolia/hits/default.tsx +++ b/src/components/algolia/hits/default.tsx @@ -1,7 +1,7 @@ -import {H2} from "@components/elements/headers"; -import Link from "@components/elements/link"; -import Image from "next/image"; -import {Hit as HitType} from "instantsearch.js"; +import {H2} from "@components/elements/headers" +import Link from "@components/elements/link" +import Image from "next/image" +import {Hit as HitType} from "instantsearch.js" export type DefaultAlgoliaHit = { url: string @@ -11,32 +11,31 @@ export type DefaultAlgoliaHit = { updated?: number } -const DefaultHit = ({hit}: { hit: HitType }) => { - const hitUrl = new URL(hit.url); +const DefaultHit = ({hit}: {hit: HitType}) => { + const hitUrl = new URL(hit.url) return ( -
+

- - {hit.title} - + {hit.title}

{hit.summary}

- {hit.updated && + {hit.updated && (
- Last Updated: {new Date(hit.updated * 1000).toLocaleDateString("en-us", { - month: "long", - day: "numeric", - year: "numeric" - })} + Last Updated:{" "} + {new Date(hit.updated * 1000).toLocaleDateString("en-us", { + month: "long", + day: "numeric", + year: "numeric", + })}
- } + )}
- {hit.photo && -
+ {hit.photo && ( +
}) => { fill />
- } + )}
) } -export default DefaultHit; \ No newline at end of file +export default DefaultHit diff --git a/src/components/config-pages/global-message.tsx b/src/components/config-pages/global-message.tsx index 27117359..16412111 100644 --- a/src/components/config-pages/global-message.tsx +++ b/src/components/config-pages/global-message.tsx @@ -1,19 +1,12 @@ -import {BellIcon, CheckCircleIcon, ExclamationTriangleIcon, InformationCircleIcon} from "@heroicons/react/20/solid"; -import {H2} from "@components/elements/headers"; -import Wysiwyg from "@components/elements/wysiwyg"; -import Link from "@components/elements/link"; -import {clsx} from "clsx"; -import {StanfordGlobalMessage} from "@lib/gql/__generated__/drupal.d"; +import {BellIcon, CheckCircleIcon, ExclamationTriangleIcon, InformationCircleIcon} from "@heroicons/react/20/solid" +import {H2} from "@components/elements/headers" +import Wysiwyg from "@components/elements/wysiwyg" +import Link from "@components/elements/link" +import {clsx} from "clsx" +import {StanfordGlobalMessage} from "@lib/gql/__generated__/drupal.d" -const GlobalMessage = ({ - suGlobalMsgEnabled, - suGlobalMsgType, - suGlobalMsgLabel, - suGlobalMsgHeader, - suGlobalMsgLink, - suGlobalMsgMessage -}: StanfordGlobalMessage) => { - if (!suGlobalMsgEnabled) return; +const GlobalMessage = ({suGlobalMsgEnabled, suGlobalMsgType, suGlobalMsgLabel, suGlobalMsgHeader, suGlobalMsgLink, suGlobalMsgMessage}: StanfordGlobalMessage) => { + if (!suGlobalMsgEnabled) return const wrapperClasses = clsx({ "bg-digital-blue-dark text-white": suGlobalMsgType === "info", @@ -21,41 +14,44 @@ const GlobalMessage = ({ "bg-digital-green text-white": suGlobalMsgType === "success", "bg-foggy-light": suGlobalMsgType === "plain", "bg-digital-red text-white": suGlobalMsgType === "error", - }); + }) return (
-
-
- +
+
+ {suGlobalMsgLabel}:
-
+
{suGlobalMsgHeader &&

{suGlobalMsgHeader}

} - + - {suGlobalMsgLink?.url && - + {suGlobalMsgLink?.url && ( + {suGlobalMsgLink.title} - } + )}
) } -const MessageIcon = ({messageType}: { messageType: StanfordGlobalMessage["suGlobalMsgType"] }) => { +const MessageIcon = ({messageType}: {messageType: StanfordGlobalMessage["suGlobalMsgType"]}) => { switch (messageType) { case "info": - return + return case "success": - return + return case "plain": - return ; + return } - return ; + return } -export default GlobalMessage; \ No newline at end of file +export default GlobalMessage diff --git a/src/components/config-pages/local-footer.tsx b/src/components/config-pages/local-footer.tsx index be5332c0..6ab93c56 100644 --- a/src/components/config-pages/local-footer.tsx +++ b/src/components/config-pages/local-footer.tsx @@ -1,51 +1,29 @@ -import Address from "@components/elements/address"; -import Link from "@components/elements/link"; -import Wysiwyg from "@components/elements/wysiwyg"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import LockupA from "@components/elements/lockup/lockup-a"; -import LockupB from "@components/elements/lockup/lockup-b"; -import LockupD from "@components/elements/lockup/lockup-d"; -import LockupE from "@components/elements/lockup/lockup-e"; -import LockupH from "@components/elements/lockup/lockup-h"; -import LockupI from "@components/elements/lockup/lockup-i"; -import LockupM from "@components/elements/lockup/lockup-m"; -import LockupO from "@components/elements/lockup/lockup-o"; -import LockupP from "@components/elements/lockup/lockup-p"; -import LockupR from "@components/elements/lockup/lockup-r"; -import LockupS from "@components/elements/lockup/lockup-s"; -import LockupT from "@components/elements/lockup/lockup-t"; -import {JSX} from "react"; -import {H2} from "@components/elements/headers"; -import TwitterIcon from "@components/elements/icons/TwitterIcon"; -import YoutubeIcon from "@components/elements/icons/YoutubeIcon"; -import FacebookIcon from "@components/elements/icons/FacebookIcon"; -import { Maybe, StanfordLocalFooter} from "@lib/gql/__generated__/drupal.d"; -import {buildUrl} from "@lib/drupal/utils"; - -const LocalFooter = ({ - suFooterEnabled, - suLocalFootAction, - suLocalFootAddress, - suLocalFootLine1, - suLocalFootLine2, - suLocalFootLine3, - suLocalFootLine4, - suLocalFootLine5, - suLocalFootLocImg, - suLocalFootLocOp, - suLocalFootPrCo, - suLocalFootPrimary, - suLocalFootPrimeH, - suLocalFootSeCo, - suLocalFootSecond, - suLocalFootSecondH, - suLocalFootSocial, - suLocalFootTr2Co, - suLocalFootTrCo, - suLocalFootUseLoc, - suLocalFootUseLogo, -}: StanfordLocalFooter) => { - if (!suFooterEnabled) return; +import Address from "@components/elements/address" +import Link from "@components/elements/link" +import Wysiwyg from "@components/elements/wysiwyg" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import LockupA from "@components/elements/lockup/lockup-a" +import LockupB from "@components/elements/lockup/lockup-b" +import LockupD from "@components/elements/lockup/lockup-d" +import LockupE from "@components/elements/lockup/lockup-e" +import LockupH from "@components/elements/lockup/lockup-h" +import LockupI from "@components/elements/lockup/lockup-i" +import LockupM from "@components/elements/lockup/lockup-m" +import LockupO from "@components/elements/lockup/lockup-o" +import LockupP from "@components/elements/lockup/lockup-p" +import LockupR from "@components/elements/lockup/lockup-r" +import LockupS from "@components/elements/lockup/lockup-s" +import LockupT from "@components/elements/lockup/lockup-t" +import {JSX} from "react" +import {H2} from "@components/elements/headers" +import TwitterIcon from "@components/elements/icons/TwitterIcon" +import YoutubeIcon from "@components/elements/icons/YoutubeIcon" +import FacebookIcon from "@components/elements/icons/FacebookIcon" +import {Maybe, StanfordLocalFooter} from "@lib/gql/__generated__/drupal.d" +import {buildUrl} from "@lib/drupal/utils" + +const LocalFooter = ({suFooterEnabled, suLocalFootAction, suLocalFootAddress, suLocalFootLine1, suLocalFootLine2, suLocalFootLine3, suLocalFootLine4, suLocalFootLine5, suLocalFootLocImg, suLocalFootLocOp, suLocalFootPrCo, suLocalFootPrimary, suLocalFootPrimeH, suLocalFootSeCo, suLocalFootSecond, suLocalFootSecondH, suLocalFootSocial, suLocalFootTr2Co, suLocalFootTrCo, suLocalFootUseLoc, suLocalFootUseLogo}: StanfordLocalFooter) => { + if (!suFooterEnabled) return const lockupProps = { useDefault: suLocalFootUseLoc, @@ -65,105 +43,90 @@ const LocalFooter = ({
-
+
+ {suLocalFootAddress &&
} - {suLocalFootAddress && -
- } - - {suLocalFootAction && + {suLocalFootAction && (
    {suLocalFootAction.map((link, index) => { - if (!link.url) return; + if (!link.url) return return (
  • - - {link.title} - + {link.title}
  • ) })}
- } + )} - {suLocalFootSocial && + {suLocalFootSocial && (
    {suLocalFootSocial.map((link, index) => { - if (!link.url) return; + if (!link.url) return return (
  • - + {link.title}
  • ) })}
- } + )} - +
- {suLocalFootPrimeH && -

{suLocalFootPrimeH}

} - {suLocalFootPrimary && + {suLocalFootPrimeH &&

{suLocalFootPrimeH}

} + {suLocalFootPrimary && (
    {suLocalFootPrimary.map((link, index) => { - if (!link.url) return; + if (!link.url) return return (
  • - - {link.title} - + {link.title}
  • ) })}
- } - - + )} +
- {suLocalFootSecondH && -

{suLocalFootSecondH}

} + {suLocalFootSecondH &&

{suLocalFootSecondH}

} - {suLocalFootSecond && + {suLocalFootSecond && (
    {suLocalFootSecond.map((link, index) => { - if (!link.url) return; + if (!link.url) return return (
  • - - {link.title} - + {link.title}
  • ) })}
- } - - + )} +
- - +
) } -const SocialIcon = ({url}: { url: string }) => { - if (url.includes("twitter.com")) return - if (url.includes("youtube.com")) return - if (url.includes("facebook")) return - return null; +const SocialIcon = ({url}: {url: string}) => { + if (url.includes("twitter.com")) return + if (url.includes("youtube.com")) return + if (url.includes("facebook")) return + return null } export interface FooterLockupProps { @@ -180,7 +143,7 @@ export interface FooterLockupProps { const FooterLockup = ({useDefault = true, siteName, lockupOption, ...props}: FooterLockupProps): JSX.Element => { const lockupProps = { - ...props + ...props, } lockupOption = useDefault ? "default" : lockupOption @@ -189,63 +152,64 @@ const FooterLockup = ({useDefault = true, siteName, lockupOption, ...props}: Foo case "none": return (
- - + +
) case "a": - return ; + return case "b": - return ; + return case "d": - return ; + return case "e": - return ; + return case "h": - return ; + return case "i": - return ; + return case "m": - return ; + return case "o": - return ; + return case "p": - return ; + return case "r": - return ; + return case "s": - return ; + return case "t": - return ; + return } - return (
- - - -
-
- {siteName || "University"} -
+ + + +
+
{siteName || "University"}
) - } -export default LocalFooter; \ No newline at end of file +export default LocalFooter diff --git a/src/components/config-pages/super-footer.tsx b/src/components/config-pages/super-footer.tsx index 396362f9..be6fc327 100644 --- a/src/components/config-pages/super-footer.tsx +++ b/src/components/config-pages/super-footer.tsx @@ -1,54 +1,56 @@ -import Wysiwyg from "@components/elements/wysiwyg"; -import Link from "@components/elements/link"; -import {LockClosedIcon} from "@heroicons/react/24/outline"; -import {H2} from "@components/elements/headers"; -import {StanfordSuperFooter} from "@lib/gql/__generated__/drupal.d"; +import Wysiwyg from "@components/elements/wysiwyg" +import Link from "@components/elements/link" +import {LockClosedIcon} from "@heroicons/react/24/outline" +import {H2} from "@components/elements/headers" +import {StanfordSuperFooter} from "@lib/gql/__generated__/drupal.d" -const SuperFooter = ({suSuperFootEnabled, suSuperFootTitle, suSuperFootText, suSuperFootLink, suSuperFootIntranet}: StanfordSuperFooter ) => { +const SuperFooter = ({suSuperFootEnabled, suSuperFootTitle, suSuperFootText, suSuperFootLink, suSuperFootIntranet}: StanfordSuperFooter) => { if (!suSuperFootEnabled) return return ( -
+
- {suSuperFootTitle && -

{suSuperFootTitle}

- } + {suSuperFootTitle &&

{suSuperFootTitle}

} - +
- {suSuperFootLink && + {suSuperFootLink && ( <> {suSuperFootLink.map((link, index) => { - if (!link.url) return; + if (!link.url) return return ( {link.title} ) })} - } + )} - {suSuperFootIntranet?.url && + {suSuperFootIntranet?.url && ( {suSuperFootIntranet.title} - + - } + )}
) } -export default SuperFooter; \ No newline at end of file +export default SuperFooter diff --git a/src/components/elements/accordion.tsx b/src/components/elements/accordion.tsx index 65ae70a0..8c5a4ae4 100644 --- a/src/components/elements/accordion.tsx +++ b/src/components/elements/accordion.tsx @@ -1,11 +1,11 @@ -"use client"; +"use client" -import {HTMLAttributes, JSX, useId} from "react"; -import {useBoolean} from "usehooks-ts"; -import {H2, H3, H4} from "@components/elements/headers"; -import {ChevronDownIcon} from "@heroicons/react/20/solid"; -import {clsx} from "clsx"; -import {twMerge} from "tailwind-merge"; +import {HTMLAttributes, JSX, useId} from "react" +import {useBoolean} from "usehooks-ts" +import {H2, H3, H4} from "@components/elements/headers" +import {ChevronDownIcon} from "@heroicons/react/20/solid" +import {clsx} from "clsx" +import {twMerge} from "tailwind-merge" type Props = HTMLAttributes & { /** @@ -38,41 +38,37 @@ type Props = HTMLAttributes & { panelProps?: HTMLAttributes } -const Accordion = ({ - button, - children, - headingLevel = "h2", - onClick, - isVisible, - initiallyVisible = false, - buttonProps, - panelProps, - ...props -}: Props) => { +const Accordion = ({button, children, headingLevel = "h2", onClick, isVisible, initiallyVisible = false, buttonProps, panelProps, ...props}: Props) => { const {value: expanded, toggle: toggleExpanded} = useBoolean(initiallyVisible) - const id = useId(); + const id = useId() const onButtonClick = () => { onClick ? onClick() : toggleExpanded() } // When the accordion is externally controlled. - const isExpanded = onClick ? isVisible : expanded; + const isExpanded = onClick ? isVisible : expanded - const Heading = headingLevel === "h2" ? H2 : headingLevel === "h3" ? H3 : H4; + const Heading = headingLevel === "h2" ? H2 : headingLevel === "h3" ? H3 : H4 return ( -
+
@@ -88,4 +84,4 @@ const Accordion = ({
) } -export default Accordion; \ No newline at end of file +export default Accordion diff --git a/src/components/elements/action-link.tsx b/src/components/elements/action-link.tsx index 7d8ec90b..738d5f01 100644 --- a/src/components/elements/action-link.tsx +++ b/src/components/elements/action-link.tsx @@ -1,7 +1,7 @@ -import Link from "@components/elements/link"; -import {ChevronRightIcon} from "@heroicons/react/20/solid"; -import {HtmlHTMLAttributes} from "react"; -import {twMerge} from "tailwind-merge"; +import Link from "@components/elements/link" +import {ChevronRightIcon} from "@heroicons/react/20/solid" +import {HtmlHTMLAttributes} from "react" +import {twMerge} from "tailwind-merge" type Props = HtmlHTMLAttributes & { /** @@ -12,10 +12,16 @@ type Props = HtmlHTMLAttributes & { const ActionLink = ({children, ...props}: Props) => { return ( - + {children} - + ) } -export default ActionLink; \ No newline at end of file +export default ActionLink diff --git a/src/components/elements/address.tsx b/src/components/elements/address.tsx index b1c4f6a1..28ba7311 100644 --- a/src/components/elements/address.tsx +++ b/src/components/elements/address.tsx @@ -1,51 +1,29 @@ -import {Address as AddressType} from "@lib/gql/__generated__/drupal.d"; -import {HTMLAttributes} from "react"; +import {Address as AddressType} from "@lib/gql/__generated__/drupal.d" +import {HTMLAttributes} from "react" -type Props = AddressType & HTMLAttributes & { - singleLine?: boolean -} - -const Address = ({ - additionalName: _a, - addressLine1, - addressLine2, - administrativeArea, - country, - locality, - organization, - postalCode, - dependentLocality: _d, - familyName: _f, - givenName: _g, - langcode: _l, - sortingCode: _s, - singleLine = false, - ...props -}: Props) => { +type Props = AddressType & + HTMLAttributes & { + singleLine?: boolean + } +const Address = ({additionalName: _a, addressLine1, addressLine2, administrativeArea, country, locality, organization, postalCode, dependentLocality: _d, familyName: _f, givenName: _g, langcode: _l, sortingCode: _s, singleLine = false, ...props}: Props) => { if (singleLine) { - const parts = [ - organization, - addressLine1, - addressLine2, - locality, - `${administrativeArea} ${postalCode}`, - `${country?.code}` - ]; - return ( -
{parts.filter(part => !!part).join(", ")}
- ) + const parts = [organization, addressLine1, addressLine2, locality, `${administrativeArea} ${postalCode}`, `${country?.code}`] + return
{parts.filter(part => !!part).join(", ")}
} return (
{organization &&
{organization}
} - {(addressLine1) &&
{addressLine1}
} - {(addressLine2) &&
{addressLine2}
} - {(locality && (administrativeArea) && (postalCode)) && -
{locality}, {administrativeArea} {postalCode}
} - {(country?.code) &&
{country?.code}
} + {addressLine1 &&
{addressLine1}
} + {addressLine2 &&
{addressLine2}
} + {locality && administrativeArea && postalCode && ( +
+ {locality}, {administrativeArea} {postalCode} +
+ )} + {country?.code &&
{country?.code}
}
) } -export default Address; \ No newline at end of file +export default Address diff --git a/src/components/elements/back-to-top.tsx b/src/components/elements/back-to-top.tsx index bf7b0d96..c16e9897 100644 --- a/src/components/elements/back-to-top.tsx +++ b/src/components/elements/back-to-top.tsx @@ -1,16 +1,16 @@ -"use client"; +"use client" -import Button from "@components/elements/button"; -import {ChevronUpIcon} from "@heroicons/react/20/solid"; -import {useBoolean, useDebounceCallback, useEventListener} from "usehooks-ts"; -import {useCallback} from "react"; +import Button from "@components/elements/button" +import {ChevronUpIcon} from "@heroicons/react/20/solid" +import {useBoolean, useDebounceCallback, useEventListener} from "usehooks-ts" +import {useCallback} from "react" const BackToTop = () => { const {value, setFalse, setTrue} = useBoolean(false) const onScroll = useCallback(() => { - if (window.scrollY > 1500) setTrue(); - if (window.scrollY <= 1500) setFalse(); + if (window.scrollY > 1500) setTrue() + if (window.scrollY <= 1500) setFalse() }, [setTrue, setFalse]) useEventListener("scroll", useDebounceCallback(onScroll, 200)) @@ -18,17 +18,20 @@ const BackToTop = () => { return ( ) } -export default BackToTop; \ No newline at end of file +export default BackToTop diff --git a/src/components/elements/button.tsx b/src/components/elements/button.tsx index 6b907455..1ba55b26 100644 --- a/src/components/elements/button.tsx +++ b/src/components/elements/button.tsx @@ -1,8 +1,8 @@ -import Link from "@components/elements/link"; +import Link from "@components/elements/link" import {twMerge} from "tailwind-merge" -import {HtmlHTMLAttributes, MouseEventHandler} from "react"; -import {Maybe} from "@lib/gql/__generated__/drupal.d"; -import {clsx} from "clsx"; +import {HtmlHTMLAttributes, MouseEventHandler} from "react" +import {Maybe} from "@lib/gql/__generated__/drupal.d" +import {clsx} from "clsx" type Props = HtmlHTMLAttributes & { /** @@ -43,27 +43,15 @@ type Props = HtmlHTMLAttributes & { disabled?: boolean } -export const Button = ({ - href, - buttonElem = false, - big = false, - secondary = false, - centered = false, - children, - className, - ...props -}: Props) => { - - const standardClasses = clsx( - { - "flex items-center w-fit mx-auto": centered, - "inline-block text-center w-fit": !centered, - "btn btn--big transition text-5xl text-white hocus:text-white bg-digital-red hocus:bg-black no-underline hocus:underline py-6 px-12 font-normal": big && !secondary, - "btn btn--secondary transition text-digital-red border-2 border-digital-red hocus:border-black no-underline hocus:underline py-4 px-8 font-normal": !big && secondary, - "btn btn--big btn--secondary transition text-5xl text-digital-red border-2 border-digital-red hocus:border-black no-underline hocus:underline py-6 px-12 font-normal": big && secondary, - "btn bg-digital-red font-normal text-white hocus:bg-black hocus:text-white py-4 px-8 no-underline hocus:underline transition": !big && !secondary, - } - ) +export const Button = ({href, buttonElem = false, big = false, secondary = false, centered = false, children, className, ...props}: Props) => { + const standardClasses = clsx({ + "flex items-center w-fit mx-auto": centered, + "inline-block text-center w-fit": !centered, + "btn btn--big transition text-5xl text-white hocus:text-white bg-digital-red hocus:bg-black no-underline hocus:underline py-6 px-12 font-normal": big && !secondary, + "btn btn--secondary transition text-digital-red border-2 border-digital-red hocus:border-black no-underline hocus:underline py-4 px-8 font-normal": !big && secondary, + "btn btn--big btn--secondary transition text-5xl text-digital-red border-2 border-digital-red hocus:border-black no-underline hocus:underline py-6 px-12 font-normal": big && secondary, + "btn bg-digital-red font-normal text-white hocus:bg-black hocus:text-white py-4 px-8 no-underline hocus:underline transition": !big && !secondary, + }) if (!href || buttonElem) { return ( @@ -88,4 +76,4 @@ export const Button = ({ ) } -export default Button \ No newline at end of file +export default Button diff --git a/src/components/elements/drupal-window-sync.tsx b/src/components/elements/drupal-window-sync.tsx index bc7a8125..2f722dee 100644 --- a/src/components/elements/drupal-window-sync.tsx +++ b/src/components/elements/drupal-window-sync.tsx @@ -1,25 +1,22 @@ -"use client"; +"use client" -import {usePathname} from "next/navigation"; -import {useIsClient} from "usehooks-ts"; +import {usePathname} from "next/navigation" +import {useIsClient} from "usehooks-ts" const DrupalWindowSync = () => { - const pathname = usePathname(); - if (!useIsClient()) return; + const pathname = usePathname() + if (!useIsClient()) return - if ( - pathname && - !pathname?.startsWith("/gallery/") && - !pathname?.startsWith("/preview") && - window && - window.top !== window.self - ) { - window.parent.postMessage({ - type: "NEXT_DRUPAL_ROUTE_SYNC", - path: pathname - }, process.env.NEXT_PUBLIC_DRUPAL_BASE_URL as string) + if (pathname && !pathname?.startsWith("/gallery/") && !pathname?.startsWith("/preview") && window && window.top !== window.self) { + window.parent.postMessage( + { + type: "NEXT_DRUPAL_ROUTE_SYNC", + path: pathname, + }, + process.env.NEXT_PUBLIC_DRUPAL_BASE_URL as string + ) } - return null; + return null } -export default DrupalWindowSync \ No newline at end of file +export default DrupalWindowSync diff --git a/src/components/elements/email.tsx b/src/components/elements/email.tsx index fb31e728..5b8779c9 100644 --- a/src/components/elements/email.tsx +++ b/src/components/elements/email.tsx @@ -1,7 +1,7 @@ "use client" -import {HtmlHTMLAttributes} from "react"; -import {useIsClient} from "usehooks-ts"; +import {HtmlHTMLAttributes} from "react" +import {useIsClient} from "usehooks-ts" type Props = HtmlHTMLAttributes & { /** @@ -11,13 +11,16 @@ type Props = HtmlHTMLAttributes & { } const Email = ({email, ...props}: Props) => { - const isClient = useIsClient(); - if (!isClient) return; + const isClient = useIsClient() + if (!isClient) return return ( - + {email} ) } -export default Email \ No newline at end of file +export default Email diff --git a/src/components/elements/headers.tsx b/src/components/elements/headers.tsx index 5f5a0734..971be2ee 100644 --- a/src/components/elements/headers.tsx +++ b/src/components/elements/headers.tsx @@ -1,13 +1,16 @@ -import {HtmlHTMLAttributes} from "react"; -import {twMerge} from "tailwind-merge"; +import {HtmlHTMLAttributes} from "react" +import {twMerge} from "tailwind-merge" type Props = HtmlHTMLAttributes -const headingLinkClasses = "[&_a]:text-digital-red [&_a]:hocus:text-black [&_a]:hocus:underline"; +const headingLinkClasses = "[&_a]:text-digital-red [&_a]:hocus:text-black [&_a]:hocus:underline" export const H1 = ({children, className, ...props}: Props) => { return ( -

+

{children}

) @@ -15,7 +18,10 @@ export const H1 = ({children, className, ...props}: Props) => { export const H2 = ({children, className, ...props}: Props) => { return ( -

+

{children}

) @@ -23,7 +29,10 @@ export const H2 = ({children, className, ...props}: Props) => { export const H3 = ({children, className, ...props}: Props) => { return ( -

+

{children}

) @@ -31,7 +40,10 @@ export const H3 = ({children, className, ...props}: Props) => { export const H4 = ({children, className, ...props}: Props) => { return ( -

+

{children}

) @@ -39,7 +51,10 @@ export const H4 = ({children, className, ...props}: Props) => { export const H5 = ({children, className, ...props}: Props) => { return ( -
+
{children}
) @@ -47,7 +62,10 @@ export const H5 = ({children, className, ...props}: Props) => { export const H6 = ({children, className, ...props}: Props) => { return ( -
+
{children}
) @@ -76,4 +94,4 @@ const Heading = ({children, level = 1, ...props}: HeadingProps) => { return
{children}
} } -export default Heading; \ No newline at end of file +export default Heading diff --git a/src/components/elements/icons/FacebookIcon.tsx b/src/components/elements/icons/FacebookIcon.tsx index 75105df6..1815fbdf 100644 --- a/src/components/elements/icons/FacebookIcon.tsx +++ b/src/components/elements/icons/FacebookIcon.tsx @@ -1,4 +1,4 @@ -import {HTMLAttributes} from "react"; +import {HTMLAttributes} from "react" const FacebookIcon = (props: HTMLAttributes) => ( ) => ( /> ) -export default FacebookIcon; \ No newline at end of file +export default FacebookIcon diff --git a/src/components/elements/icons/InstagramIcon.tsx b/src/components/elements/icons/InstagramIcon.tsx index 2540ed08..a8b395ea 100644 --- a/src/components/elements/icons/InstagramIcon.tsx +++ b/src/components/elements/icons/InstagramIcon.tsx @@ -1,14 +1,18 @@ -import {HTMLAttributes} from "react"; +import {HTMLAttributes} from "react" const InstagramIcon = (props: HTMLAttributes) => { return ( - + Instagram icon + d="M12 0C8.74 0 8.333.015 7.053.072 5.775.132 4.905.333 4.14.63c-.789.306-1.459.717-2.126 1.384S.935 3.35.63 4.14C.333 4.905.131 5.775.072 7.053.012 8.333 0 8.74 0 12s.015 3.667.072 4.947c.06 1.277.261 2.148.558 2.913.306.788.717 1.459 1.384 2.126.667.666 1.336 1.079 2.126 1.384.766.296 1.636.499 2.913.558C8.333 23.988 8.74 24 12 24s3.667-.015 4.947-.072c1.277-.06 2.148-.262 2.913-.558.788-.306 1.459-.718 2.126-1.384.666-.667 1.079-1.335 1.384-2.126.296-.765.499-1.636.558-2.913.06-1.28.072-1.687.072-4.947s-.015-3.667-.072-4.947c-.06-1.277-.262-2.149-.558-2.913-.306-.789-.718-1.459-1.384-2.126C21.319 1.347 20.651.935 19.86.63c-.765-.297-1.636-.499-2.913-.558C15.667.012 15.26 0 12 0zm0 2.16c3.203 0 3.585.016 4.85.071 1.17.055 1.805.249 2.227.415.562.217.96.477 1.382.896.419.42.679.819.896 1.381.164.422.36 1.057.413 2.227.057 1.266.07 1.646.07 4.85s-.015 3.585-.074 4.85c-.061 1.17-.256 1.805-.421 2.227-.224.562-.479.96-.899 1.382-.419.419-.824.679-1.38.896-.42.164-1.065.36-2.235.413-1.274.057-1.649.07-4.859.07-3.211 0-3.586-.015-4.859-.074-1.171-.061-1.816-.256-2.236-.421-.569-.224-.96-.479-1.379-.899-.421-.419-.69-.824-.9-1.38-.165-.42-.359-1.065-.42-2.235-.045-1.26-.061-1.649-.061-4.844 0-3.196.016-3.586.061-4.861.061-1.17.255-1.814.42-2.234.21-.57.479-.96.9-1.381.419-.419.81-.689 1.379-.898.42-.166 1.051-.361 2.221-.421 1.275-.045 1.65-.06 4.859-.06l.045.03zm0 3.678c-3.405 0-6.162 2.76-6.162 6.162 0 3.405 2.76 6.162 6.162 6.162 3.405 0 6.162-2.76 6.162-6.162 0-3.405-2.76-6.162-6.162-6.162zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm7.846-10.405c0 .795-.646 1.44-1.44 1.44-.795 0-1.44-.646-1.44-1.44 0-.794.646-1.439 1.44-1.439.793-.001 1.44.645 1.44 1.439z" + /> ) } -export default InstagramIcon; \ No newline at end of file +export default InstagramIcon diff --git a/src/components/elements/icons/LinkedInIcon.tsx b/src/components/elements/icons/LinkedInIcon.tsx index f5ff42c0..af4fd4b6 100644 --- a/src/components/elements/icons/LinkedInIcon.tsx +++ b/src/components/elements/icons/LinkedInIcon.tsx @@ -1,4 +1,4 @@ -import {HTMLAttributes} from "react"; +import {HTMLAttributes} from "react" const LinkedInIcon = (props: HTMLAttributes) => ( ) => ( /> ) -export default LinkedInIcon; \ No newline at end of file +export default LinkedInIcon diff --git a/src/components/elements/icons/TwitterIcon.tsx b/src/components/elements/icons/TwitterIcon.tsx index 404776b5..aee1eb42 100644 --- a/src/components/elements/icons/TwitterIcon.tsx +++ b/src/components/elements/icons/TwitterIcon.tsx @@ -1,4 +1,4 @@ -import {HTMLAttributes} from "react"; +import {HTMLAttributes} from "react" const TwitterIcon = (props: HTMLAttributes) => ( ) => ( /> ) -export default TwitterIcon; \ No newline at end of file +export default TwitterIcon diff --git a/src/components/elements/icons/YoutubeIcon.tsx b/src/components/elements/icons/YoutubeIcon.tsx index db9e0d68..d88d6397 100644 --- a/src/components/elements/icons/YoutubeIcon.tsx +++ b/src/components/elements/icons/YoutubeIcon.tsx @@ -1,12 +1,17 @@ -import {HTMLAttributes} from "react"; +import {HTMLAttributes} from "react" const YoutubeIcon = (props: HTMLAttributes) => { return ( - + + d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z" + /> ) } -export default YoutubeIcon; \ No newline at end of file +export default YoutubeIcon diff --git a/src/components/elements/interception-modal.tsx b/src/components/elements/interception-modal.tsx index a9ace618..4fbbfb54 100644 --- a/src/components/elements/interception-modal.tsx +++ b/src/components/elements/interception-modal.tsx @@ -1,41 +1,47 @@ -"use client"; +"use client" -import React, {HtmlHTMLAttributes, useCallback, useRef} from "react"; -import {useRouter} from "next/navigation"; -import ReactFocusLock from "react-focus-lock"; -import {XMarkIcon} from "@heroicons/react/20/solid"; -import {useEventListener, useScrollLock} from "usehooks-ts"; -import {twMerge} from "tailwind-merge"; +import React, {HtmlHTMLAttributes, useCallback, useRef} from "react" +import {useRouter} from "next/navigation" +import ReactFocusLock from "react-focus-lock" +import {XMarkIcon} from "@heroicons/react/20/solid" +import {useEventListener, useScrollLock} from "usehooks-ts" +import {twMerge} from "tailwind-merge" const InterceptionModal = ({children, ...props}: HtmlHTMLAttributes) => { - const overlay = useRef(null); - const wrapper = useRef(null); - const router = useRouter(); + const overlay = useRef(null) + const wrapper = useRef(null) + const router = useRouter() useScrollLock() - const onDismiss = useCallback(() => router.back(), [router]); + const onDismiss = useCallback(() => router.back(), [router]) - const onClick = useCallback((e: React.MouseEvent) => { - if (e.target === overlay.current || e.target === wrapper.current) onDismiss(); - }, [onDismiss, overlay, wrapper]); + const onClick = useCallback( + (e: React.MouseEvent) => { + if (e.target === overlay.current || e.target === wrapper.current) onDismiss() + }, + [onDismiss, overlay, wrapper] + ) - const onKeyDown = useCallback((e: KeyboardEvent) => { - if (e.key === "Escape") onDismiss(); - }, [onDismiss]); + const onKeyDown = useCallback( + (e: KeyboardEvent) => { + if (e.key === "Escape") onDismiss() + }, + [onDismiss] + ) useEventListener("keydown", onKeyDown) return (
{children}
@@ -43,16 +49,17 @@ const InterceptionModal = ({children, ...props}: HtmlHTMLAttributes Close Overlay - + - - ); + ) } - -export default InterceptionModal; \ No newline at end of file +export default InterceptionModal diff --git a/src/components/elements/link.tsx b/src/components/elements/link.tsx index e754e9af..f5ecc9f6 100644 --- a/src/components/elements/link.tsx +++ b/src/components/elements/link.tsx @@ -1,29 +1,33 @@ -import {HtmlHTMLAttributes} from "react"; -import Link from "next/link"; -import {EnvelopeIcon} from "@heroicons/react/24/outline"; -import ActionLink from "@components/elements/action-link"; -import Button from "@components/elements/button"; -import {LinkProps} from "next/dist/client/link"; +import {HtmlHTMLAttributes} from "react" +import Link from "next/link" +import {EnvelopeIcon} from "@heroicons/react/24/outline" +import ActionLink from "@components/elements/action-link" +import Button from "@components/elements/button" +import {LinkProps} from "next/dist/client/link" -type Props = HtmlHTMLAttributes & LinkProps & { - /** - * Link URL. - */ - href: string -} +type Props = HtmlHTMLAttributes & + LinkProps & { + /** + * Link URL. + */ + href: string + } const DrupalLink = ({href, className, children, ...props}: Props) => { // Make sure all links have a href. href = href || "#" - const drupalBase: string = (process.env.NEXT_PUBLIC_DRUPAL_BASE_URL || "").replace(/\/$/, ""); + const drupalBase: string = (process.env.NEXT_PUBLIC_DRUPAL_BASE_URL || "").replace(/\/$/, "") if (!href.indexOf("/files/")) { - href = href.replace(drupalBase, "").replace("", "/"); + href = href.replace(drupalBase, "").replace("", "/") } if (className?.includes("link--action")) { return ( - + {children} ) @@ -43,13 +47,20 @@ const DrupalLink = ({href, className, children, ...props}: Props) => { } return ( - + {children} - {href.startsWith("mailto") && - - } + {href.startsWith("mailto") && ( + + )} ) } -export default DrupalLink as typeof Link; +export default DrupalLink as typeof Link diff --git a/src/components/elements/load-more-list.tsx b/src/components/elements/load-more-list.tsx index 48ec2ee0..5c0d8738 100644 --- a/src/components/elements/load-more-list.tsx +++ b/src/components/elements/load-more-list.tsx @@ -1,10 +1,10 @@ -"use client"; +"use client" -import {useLayoutEffect, useRef, HtmlHTMLAttributes, JSX, useId, useState} from "react"; -import Button from "@components/elements/button"; -import {useAutoAnimate} from "@formkit/auto-animate/react"; -import {useBoolean, useCounter} from "usehooks-ts"; -import useFocusOnRender from "@lib/hooks/useFocusOnRender"; +import {useLayoutEffect, useRef, HtmlHTMLAttributes, JSX, useId, useState} from "react" +import Button from "@components/elements/button" +import {useAutoAnimate} from "@formkit/auto-animate/react" +import {useBoolean, useCounter} from "usehooks-ts" +import useFocusOnRender from "@lib/hooks/useFocusOnRender" type Props = HtmlHTMLAttributes & { /** @@ -34,37 +34,39 @@ type Props = HtmlHTMLAttributes & { } const LoadMoreList = ({buttonText, children, ulProps, liProps, loadPage, ...props}: Props) => { - const id = useId(); + const id = useId() const {count: page, increment: incrementPage} = useCounter(0) const [items, setItems] = useState(children) const {value: hasMore, setValue: setHasMore} = useBoolean(!!loadPage) const {value: focusOnElement, setTrue: enableFocusElement, setFalse: disableFocusElement} = useBoolean(false) - const focusItemRef = useRef(null); - const [animationParent] = useAutoAnimate(); + const focusItemRef = useRef(null) + const [animationParent] = useAutoAnimate() const showMoreItems = async () => { if (loadPage) { - const results = await loadPage(page + 1); + const results = await loadPage(page + 1) if (results.props.children.length < 30) setHasMore(false) setItems([...items, ...results.props.children]) } - enableFocusElement(); + enableFocusElement() incrementPage() } - const setFocusOnItem = useFocusOnRender(focusItemRef, false); + const setFocusOnItem = useFocusOnRender(focusItemRef, false) useLayoutEffect(() => { if (focusOnElement) setFocusOnItem() - }, [focusOnElement, setFocusOnItem]); + }, [focusOnElement, setFocusOnItem]) return (
-
    - - {items.map((item, i) => +
      + {items.map((item, i) => (
    • {item}
    • - )} + ))}
    - + Showing {items.length} items. - {hasMore && - - } + )}
) } -export default LoadMoreList; \ No newline at end of file +export default LoadMoreList diff --git a/src/components/elements/lockup/lockup-a.tsx b/src/components/elements/lockup/lockup-a.tsx index a117b138..cc5eba18 100644 --- a/src/components/elements/lockup/lockup-a.tsx +++ b/src/components/elements/lockup/lockup-a.tsx @@ -1,29 +1,29 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupA = ({line1, line5, siteName, logoUrl}: FooterLockupProps) => { return (
- -
+ +
- +
-
-
- {line1 || siteName} -
+
+
{line1 || siteName}
- {line5 && -
- {line5} -
- } + {line5 &&
{line5}
}
) } -export default LockupA; \ No newline at end of file +export default LockupA diff --git a/src/components/elements/lockup/lockup-b.tsx b/src/components/elements/lockup/lockup-b.tsx index 9529d61b..0ac3514d 100644 --- a/src/components/elements/lockup/lockup-b.tsx +++ b/src/components/elements/lockup/lockup-b.tsx @@ -1,17 +1,23 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupB = ({line1, line2, siteName, logoUrl}: FooterLockupProps) => { return (
- -
+ +
- +
-
+
{line1 || siteName}
{line2}
@@ -21,4 +27,4 @@ const LockupB = ({line1, line2, siteName, logoUrl}: FooterLockupProps) => {
) } -export default LockupB; \ No newline at end of file +export default LockupB diff --git a/src/components/elements/lockup/lockup-d.tsx b/src/components/elements/lockup/lockup-d.tsx index 949bbc53..a8ee596e 100644 --- a/src/components/elements/lockup/lockup-d.tsx +++ b/src/components/elements/lockup/lockup-d.tsx @@ -1,17 +1,23 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupD = ({line1, line3, siteName, logoUrl}: FooterLockupProps) => { return (
- -
+ +
- +
-
+
{line1 || siteName}
{line3}
@@ -21,4 +27,4 @@ const LockupD = ({line1, line3, siteName, logoUrl}: FooterLockupProps) => {
) } -export default LockupD; \ No newline at end of file +export default LockupD diff --git a/src/components/elements/lockup/lockup-e.tsx b/src/components/elements/lockup/lockup-e.tsx index 8c530f62..5b0dad59 100644 --- a/src/components/elements/lockup/lockup-e.tsx +++ b/src/components/elements/lockup/lockup-e.tsx @@ -1,17 +1,23 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupE = ({line1, line2, line3, siteName, logoUrl}: FooterLockupProps) => { return (
- -
+ +
- +
-
+
{line1 || siteName}
{line2 || siteName}
@@ -22,4 +28,4 @@ const LockupE = ({line1, line2, line3, siteName, logoUrl}: FooterLockupProps) =>
) } -export default LockupE; \ No newline at end of file +export default LockupE diff --git a/src/components/elements/lockup/lockup-h.tsx b/src/components/elements/lockup/lockup-h.tsx index 056888c2..4e7058a4 100644 --- a/src/components/elements/lockup/lockup-h.tsx +++ b/src/components/elements/lockup/lockup-h.tsx @@ -1,19 +1,25 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupH = ({line1, line3, line4, siteName, logoUrl}: FooterLockupProps) => { return (
- -
+ +
- -
{line4}
+ +
{line4}
-
-
+
+
{line1 || siteName}
{line3}
@@ -22,4 +28,4 @@ const LockupH = ({line1, line3, line4, siteName, logoUrl}: FooterLockupProps) =>
) } -export default LockupH; \ No newline at end of file +export default LockupH diff --git a/src/components/elements/lockup/lockup-i.tsx b/src/components/elements/lockup/lockup-i.tsx index 45ea75f8..fba8427e 100644 --- a/src/components/elements/lockup/lockup-i.tsx +++ b/src/components/elements/lockup/lockup-i.tsx @@ -1,19 +1,25 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupI = ({line1, line3, line4, siteName, logoUrl}: FooterLockupProps) => { return (
- -
+ +
- -
{line4}
+ +
{line4}
-
-
+
+
{line1 || siteName}
{line3}
@@ -22,4 +28,4 @@ const LockupI = ({line1, line3, line4, siteName, logoUrl}: FooterLockupProps) =>
) } -export default LockupI; \ No newline at end of file +export default LockupI diff --git a/src/components/elements/lockup/lockup-logo.tsx b/src/components/elements/lockup/lockup-logo.tsx index d8b755b8..ef29b1bb 100644 --- a/src/components/elements/lockup/lockup-logo.tsx +++ b/src/components/elements/lockup/lockup-logo.tsx @@ -1,23 +1,21 @@ -import {Maybe} from "@lib/gql/__generated__/drupal.d"; -import StanfordWordMark from "@components/images/stanford-wordmark"; +import {Maybe} from "@lib/gql/__generated__/drupal.d" +import StanfordWordMark from "@components/images/stanford-wordmark" -const LockupLogo = ({logoUrl, siteName = ""}: { logoUrl?: Maybe, siteName?: Maybe }) => { +const LockupLogo = ({logoUrl, siteName = ""}: {logoUrl?: Maybe; siteName?: Maybe}) => { return ( <> - {logoUrl && + {logoUrl && ( {`${siteName} - } - {!logoUrl && - - } + )} + {!logoUrl && } ) } -export default LockupLogo; \ No newline at end of file +export default LockupLogo diff --git a/src/components/elements/lockup/lockup-m.tsx b/src/components/elements/lockup/lockup-m.tsx index 8ff84fec..092e79da 100644 --- a/src/components/elements/lockup/lockup-m.tsx +++ b/src/components/elements/lockup/lockup-m.tsx @@ -1,18 +1,24 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupM = ({line1, line2, siteName, logoUrl}: FooterLockupProps) => { return (
- -
+ +
- +
-
-
+
+
{line1 || siteName}
{line2}
@@ -21,4 +27,4 @@ const LockupM = ({line1, line2, siteName, logoUrl}: FooterLockupProps) => {
) } -export default LockupM; \ No newline at end of file +export default LockupM diff --git a/src/components/elements/lockup/lockup-o.tsx b/src/components/elements/lockup/lockup-o.tsx index e046f0b1..33295695 100644 --- a/src/components/elements/lockup/lockup-o.tsx +++ b/src/components/elements/lockup/lockup-o.tsx @@ -1,15 +1,21 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupO = ({line4, siteName, logoUrl}: FooterLockupProps) => { return (
- - -
{line4}
+ + +
{line4}
) } -export default LockupO; \ No newline at end of file +export default LockupO diff --git a/src/components/elements/lockup/lockup-p.tsx b/src/components/elements/lockup/lockup-p.tsx index fe46c83f..15936307 100644 --- a/src/components/elements/lockup/lockup-p.tsx +++ b/src/components/elements/lockup/lockup-p.tsx @@ -1,24 +1,28 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupP = ({line1, line4, siteName, logoUrl}: FooterLockupProps) => { return (
- -
+ +
- -
{line4}
+ +
{line4}
-
-
- {line1 || siteName} -
+
+
{line1 || siteName}
) } -export default LockupP; \ No newline at end of file +export default LockupP diff --git a/src/components/elements/lockup/lockup-r.tsx b/src/components/elements/lockup/lockup-r.tsx index 085d7097..c0f285d1 100644 --- a/src/components/elements/lockup/lockup-r.tsx +++ b/src/components/elements/lockup/lockup-r.tsx @@ -1,19 +1,25 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupR = ({line5, siteName, logoUrl}: FooterLockupProps) => { return (
- -
+ +
- -
{line5}
+ +
{line5}
) } -export default LockupR; \ No newline at end of file +export default LockupR diff --git a/src/components/elements/lockup/lockup-s.tsx b/src/components/elements/lockup/lockup-s.tsx index 5c889fb5..8e74bbd9 100644 --- a/src/components/elements/lockup/lockup-s.tsx +++ b/src/components/elements/lockup/lockup-s.tsx @@ -1,21 +1,25 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupS = ({line1, line2, line4, siteName, logoUrl}: FooterLockupProps) => { return (
- - - -
{line4}
+ + +
{line4}
{line1 || siteName}
{line2}
-
) } -export default LockupS; \ No newline at end of file +export default LockupS diff --git a/src/components/elements/lockup/lockup-t.tsx b/src/components/elements/lockup/lockup-t.tsx index 4eba4c70..fbc20c61 100644 --- a/src/components/elements/lockup/lockup-t.tsx +++ b/src/components/elements/lockup/lockup-t.tsx @@ -1,22 +1,26 @@ -import Link from "@components/elements/link"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {FooterLockupProps} from "@components/config-pages/local-footer"; +import Link from "@components/elements/link" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {FooterLockupProps} from "@components/config-pages/local-footer" const LockupT = ({line1, line2, line3, line4, siteName, logoUrl}: FooterLockupProps) => { return (
- - - -
{line4}
+ + +
{line4}
{line1 || siteName}
{line2}
{line3}
-
) } -export default LockupT; \ No newline at end of file +export default LockupT diff --git a/src/components/elements/lockup/lockup.tsx b/src/components/elements/lockup/lockup.tsx index 3723b767..f1583a21 100644 --- a/src/components/elements/lockup/lockup.tsx +++ b/src/components/elements/lockup/lockup.tsx @@ -1,36 +1,23 @@ -import Link from "@components/elements/link"; -import LockupA from "@components/elements/lockup/lockup-a"; -import LockupB from "@components/elements/lockup/lockup-b"; -import LockupD from "@components/elements/lockup/lockup-d"; -import LockupE from "@components/elements/lockup/lockup-e"; -import LockupH from "@components/elements/lockup/lockup-h"; -import LockupI from "@components/elements/lockup/lockup-i"; -import LockupM from "@components/elements/lockup/lockup-m"; -import LockupO from "@components/elements/lockup/lockup-o"; -import LockupP from "@components/elements/lockup/lockup-p"; -import LockupR from "@components/elements/lockup/lockup-r"; -import LockupS from "@components/elements/lockup/lockup-s"; -import LockupT from "@components/elements/lockup/lockup-t"; -import LockupLogo from "@components/elements/lockup/lockup-logo"; -import {LockupSetting, StanfordBasicSiteSetting} from "@lib/gql/__generated__/drupal.d"; - -type Props = - Omit & - Omit - -export const Lockup = ({ - suLockupEnabled, - suUseThemeLogo, - suUploadLogoImage, - suSiteName, - suLine1, - suLine2, - suLine3, - suLine4, - suLine5, - suLockupOptions -}: Props) => { - const logoUrl = !suUseThemeLogo ? suUploadLogoImage?.url : undefined; +import Link from "@components/elements/link" +import LockupA from "@components/elements/lockup/lockup-a" +import LockupB from "@components/elements/lockup/lockup-b" +import LockupD from "@components/elements/lockup/lockup-d" +import LockupE from "@components/elements/lockup/lockup-e" +import LockupH from "@components/elements/lockup/lockup-h" +import LockupI from "@components/elements/lockup/lockup-i" +import LockupM from "@components/elements/lockup/lockup-m" +import LockupO from "@components/elements/lockup/lockup-o" +import LockupP from "@components/elements/lockup/lockup-p" +import LockupR from "@components/elements/lockup/lockup-r" +import LockupS from "@components/elements/lockup/lockup-s" +import LockupT from "@components/elements/lockup/lockup-t" +import LockupLogo from "@components/elements/lockup/lockup-logo" +import {LockupSetting, StanfordBasicSiteSetting} from "@lib/gql/__generated__/drupal.d" + +type Props = Omit & Omit + +export const Lockup = ({suLockupEnabled, suUseThemeLogo, suUploadLogoImage, suSiteName, suLine1, suLine2, suLine3, suLine4, suLine5, suLockupOptions}: Props) => { + const logoUrl = !suUseThemeLogo ? suUploadLogoImage?.url : undefined const lockupProps = { line1: suLine1, line2: suLine2, @@ -44,15 +31,15 @@ export const Lockup = ({ if (!suLockupEnabled) { return (
- +
-
- -
-
- {suSiteName || "University"} +
+
+
{suSiteName || "University"}
@@ -61,51 +48,53 @@ export const Lockup = ({ switch (suLockupOptions) { case "a": - return ; + return case "b": - return ; + return case "d": - return ; + return case "e": - return ; + return case "h": - return ; + return case "i": - return ; + return case "m": - return ; + return case "o": - return ; + return case "p": - return ; + return case "r": - return ; + return case "s": - return ; + return case "t": - return ; + return case "none": default: return (
- - + +
) } } -export default Lockup; \ No newline at end of file +export default Lockup diff --git a/src/components/elements/ombed.tsx b/src/components/elements/ombed.tsx index 1c82c4a1..b6fefc35 100644 --- a/src/components/elements/ombed.tsx +++ b/src/components/elements/ombed.tsx @@ -1,10 +1,10 @@ -"use client"; +"use client" -import {SignalIcon} from "@heroicons/react/20/solid"; -import Embed from "react-tiny-oembed"; -import {HtmlHTMLAttributes} from "react"; -import {useIntersectionObserver} from "usehooks-ts"; -import {twMerge} from "tailwind-merge"; +import {SignalIcon} from "@heroicons/react/20/solid" +import Embed from "react-tiny-oembed" +import {HtmlHTMLAttributes} from "react" +import {useIntersectionObserver} from "usehooks-ts" +import {twMerge} from "tailwind-merge" type Props = HtmlHTMLAttributes & { /** @@ -16,18 +16,31 @@ type Props = HtmlHTMLAttributes & { const Oembed = ({url, ...props}: Props) => { const {isIntersecting, ref} = useIntersectionObserver({freezeOnceVisible: true}) return ( -
- {isIntersecting && }/>} +
+ {isIntersecting && ( + } + /> + )}
) } const Loading = () => { return ( -
- +
+
) } -export default Oembed; \ No newline at end of file +export default Oembed diff --git a/src/components/elements/paged-list.tsx b/src/components/elements/paged-list.tsx index d17191dd..85ec7a38 100644 --- a/src/components/elements/paged-list.tsx +++ b/src/components/elements/paged-list.tsx @@ -1,11 +1,11 @@ -"use client"; +"use client" -import {useLayoutEffect, useRef, HtmlHTMLAttributes, useEffect, useId, JSX, useState} from "react"; -import {useAutoAnimate} from "@formkit/auto-animate/react"; -import {useBoolean, useCounter} from "usehooks-ts"; -import {useRouter, useSearchParams} from "next/navigation"; -import usePagination from "@lib/hooks/usePagination"; -import useFocusOnRender from "@lib/hooks/useFocusOnRender"; +import {useLayoutEffect, useRef, HtmlHTMLAttributes, useEffect, useId, JSX, useState} from "react" +import {useAutoAnimate} from "@formkit/auto-animate/react" +import {useBoolean, useCounter} from "usehooks-ts" +import {useRouter, useSearchParams} from "next/navigation" +import usePagination from "@lib/hooks/usePagination" +import useFocusOnRender from "@lib/hooks/useFocusOnRender" type Props = HtmlHTMLAttributes & { /** @@ -15,7 +15,7 @@ type Props = HtmlHTMLAttributes & { /** * Attributes for each
  • element. */ - liProps?: HtmlHTMLAttributes, + liProps?: HtmlHTMLAttributes /** * URL parameter used to save the users page position. */ @@ -34,20 +34,10 @@ type Props = HtmlHTMLAttributes & { loadPage?: (_page: number) => Promise } -const PagedList = ({ - children, - ulProps, - liProps, - pageKey = "page", - totalPages, - pagerSiblingCount = 2, - loadPage, - ...props -}: Props) => { - - const id = useId(); +const PagedList = ({children, ulProps, liProps, pageKey = "page", totalPages, pagerSiblingCount = 2, loadPage, ...props}: Props) => { + const id = useId() const [items, setItems] = useState(Array.isArray(children) ? children : [children]) - const router = useRouter(); + const router = useRouter() const searchParams = useSearchParams() // Use the GET param for page, but make sure that it is between 1 and the last page. If it's a string or a number @@ -56,8 +46,8 @@ const PagedList = ({ const {value: focusOnElement, setTrue: enableFocusElement, setFalse: disableFocusElement} = useBoolean(false) - const focusItemRef = useRef(null); - const [animationParent] = useAutoAnimate(); + const focusItemRef = useRef(null) + const [animationParent] = useAutoAnimate() const goToPage = async (page: number) => { if (loadPage) { @@ -65,21 +55,21 @@ const PagedList = ({ setItems(newView.props.children) } - enableFocusElement(); - setPage(page); + enableFocusElement() + setPage(page) } - const setFocusOnItem = useFocusOnRender(focusItemRef, false); + const setFocusOnItem = useFocusOnRender(focusItemRef, false) useLayoutEffect(() => { if (focusOnElement) setFocusOnItem() - }, [focusOnElement, setFocusOnItem]); + }, [focusOnElement, setFocusOnItem]) useEffect(() => { - if (!pageKey || !loadPage) return; + if (!pageKey || !loadPage) return // Use search params to retain any other parameters. - const params = new URLSearchParams(searchParams.toString()); + const params = new URLSearchParams(searchParams.toString()) if (currentPage > 1) { params.set(pageKey, `${currentPage}`) } else { @@ -87,10 +77,9 @@ const PagedList = ({ } router.replace(`?${params.toString()}`, {scroll: false}) - }, [loadPage, router, currentPage, pageKey, searchParams]); + }, [loadPage, router, currentPage, pageKey, searchParams]) useEffect(() => { - const updateInitialContents = async (initialPage: number) => { if (loadPage) { const newView = await loadPage(initialPage - 1) @@ -98,17 +87,19 @@ const PagedList = ({ } } - const initialPage = parseInt(searchParams.get(pageKey || "") || ""); + const initialPage = parseInt(searchParams.get(pageKey || "") || "") if (initialPage > 1) updateInitialContents(initialPage) }, [searchParams, pageKey, loadPage]) - - const paginationButtons = usePagination(totalPages * items.length, currentPage, items.length, pagerSiblingCount); + const paginationButtons = usePagination(totalPages * items.length, currentPage, items.length, pagerSiblingCount) return (
    -
      - {items.map((item, i) => +
        + {items.map((item, i) => (
      • {item}
      • - )} + ))}
      - {(loadPage && paginationButtons.length > 1) && -
    ) } -const PaginationButton = ({page, currentPage, total, onClick}: { - page: number | string - currentPage: number - total: number - onClick: () => void -}) => { +const PaginationButton = ({page, currentPage, total, onClick}: {page: number | string; currentPage: number; total: number; onClick: () => void}) => { if (page === 0) { return ( -
  • +
  • More pages available ...
  • ) } - const isCurrent = page == currentPage; + const isCurrent = page == currentPage return (
  • ) } -export default PagedList; \ No newline at end of file +export default PagedList diff --git a/src/components/elements/select-list.tsx b/src/components/elements/select-list.tsx index 63ec36b1..9c0891b1 100644 --- a/src/components/elements/select-list.tsx +++ b/src/components/elements/select-list.tsx @@ -1,172 +1,123 @@ -"use client"; - -import { - useSelect, - SelectOptionDefinition, - SelectProvider, - SelectValue, -} from "@mui/base/useSelect"; -import { useOption } from "@mui/base/useOption"; -import { - FocusEvent, - KeyboardEvent, - MouseEvent, - ReactNode, - RefObject, - useEffect, - useId, - useLayoutEffect, - useRef, - useState, -} from "react"; -import { ChevronDownIcon } from "@heroicons/react/20/solid"; -import { Maybe } from "@lib/gql/__generated__/drupal.d"; +"use client" + +import {useSelect, SelectOptionDefinition, SelectProvider, SelectValue} from "@mui/base/useSelect" +import {useOption} from "@mui/base/useOption" +import {FocusEvent, KeyboardEvent, MouseEvent, ReactNode, RefObject, useEffect, useId, useLayoutEffect, useRef, useState} from "react" +import {ChevronDownIcon} from "@heroicons/react/20/solid" +import {Maybe} from "@lib/gql/__generated__/drupal.d" interface OptionProps { - rootRef: RefObject; - children?: ReactNode; - value: string; - disabled?: boolean; + rootRef: RefObject + children?: ReactNode + value: string + disabled?: boolean } -const renderSelectedValue = ( - value: SelectValue, - options: SelectOptionDefinition[], -) => { +const renderSelectedValue = (value: SelectValue, options: SelectOptionDefinition[]) => { if (Array.isArray(value)) { - return value.map((item) => ( + return value.map(item => ( {renderSelectedValue(item, options)} - )); + )) } - const selectedOption = options.find((option) => option.value === value); - return selectedOption ? selectedOption.label : null; -}; + const selectedOption = options.find(option => option.value === value) + return selectedOption ? selectedOption.label : null +} function CustomOption(props: OptionProps) { - const { children, value, rootRef, disabled = false } = props; - const { getRootProps, highlighted, selected } = useOption({ + const {children, value, rootRef, disabled = false} = props + const {getRootProps, highlighted, selected} = useOption({ rootRef: rootRef, value, disabled, label: children, - }); + }) - const { id, ...otherProps }: { id: string } = getRootProps(); - const selectedStyles = - "bg-archway text-white " + (highlighted ? "underline" : ""); - const highlightedStyles = "bg-black-10 text-black underline"; + const {id, ...otherProps}: {id: string} = getRootProps() + const selectedStyles = "bg-archway text-white " + (highlighted ? "underline" : "") + const highlightedStyles = "bg-black-10 text-black underline" useEffect(() => { if (highlighted && id && rootRef?.current?.parentElement) { - const item = document.getElementById(id); + const item = document.getElementById(id) if (item) { - const itemTop = item?.offsetTop; - const itemHeight = item?.offsetHeight; - const parentScrollTop = rootRef.current.parentElement.scrollTop; - const parentHeight = rootRef.current.parentElement.offsetHeight; + const itemTop = item?.offsetTop + const itemHeight = item?.offsetHeight + const parentScrollTop = rootRef.current.parentElement.scrollTop + const parentHeight = rootRef.current.parentElement.offsetHeight if (itemTop < parentScrollTop) { - rootRef.current.parentElement.scrollTop = itemTop; + rootRef.current.parentElement.scrollTop = itemTop } if (itemTop + itemHeight > parentScrollTop + parentHeight) { - rootRef.current.parentElement.scrollTop = - itemTop - parentHeight + itemHeight; + rootRef.current.parentElement.scrollTop = itemTop - parentHeight + itemHeight } } } - }, [rootRef, id, highlighted]); + }, [rootRef, id, highlighted]) return (
  • {children}
  • - ); + ) } interface Props { - options: SelectOptionDefinition[]; - label?: Maybe; - ariaLabelledby?: Maybe; - defaultValue?: SelectValue; - onChange?: ( - _event: MouseEvent | KeyboardEvent | FocusEvent | null, - _value: SelectValue, - ) => void; - multiple?: boolean; - disabled?: boolean; - value?: SelectValue; - required?: boolean; - emptyValue?: Maybe; - emptyLabel?: Maybe; - name?: Maybe; + options: SelectOptionDefinition[] + label?: Maybe + ariaLabelledby?: Maybe + defaultValue?: SelectValue + onChange?: (_event: MouseEvent | KeyboardEvent | FocusEvent | null, _value: SelectValue) => void + multiple?: boolean + disabled?: boolean + value?: SelectValue + required?: boolean + emptyValue?: Maybe + emptyLabel?: Maybe + name?: Maybe } -const SelectList = ({ - options = [], - label, - multiple, - ariaLabelledby, - required, - defaultValue, - name, - emptyValue, - emptyLabel = "- None -", - ...props -}: Props) => { - const labelId = useId(); - const labeledBy = ariaLabelledby || labelId; - - const inputRef = useRef(null); - const listboxRef = useRef(null); - const [listboxVisible, setListboxVisible] = useState(false); - - const { getButtonProps, getListboxProps, contextValue, value } = useSelect< - string, - boolean - >({ +const SelectList = ({options = [], label, multiple, ariaLabelledby, required, defaultValue, name, emptyValue, emptyLabel = "- None -", ...props}: Props) => { + const labelId = useId() + const labeledBy = ariaLabelledby || labelId + + const inputRef = useRef(null) + const listboxRef = useRef(null) + const [listboxVisible, setListboxVisible] = useState(false) + + const {getButtonProps, getListboxProps, contextValue, value} = useSelect({ listboxRef, onOpenChange: setListboxVisible, open: listboxVisible, defaultValue, multiple, ...props, - }); + }) - useEffect(() => listboxRef.current?.focus(), [listboxVisible]); + useEffect(() => listboxRef.current?.focus(), [listboxVisible]) useLayoutEffect(() => { - const parentContainer = - listboxRef.current?.parentElement?.getBoundingClientRect(); - if ( - parentContainer && - (parentContainer.bottom > window.innerHeight || parentContainer.top < 0) - ) { + const parentContainer = listboxRef.current?.parentElement?.getBoundingClientRect() + if (parentContainer && (parentContainer.bottom > window.innerHeight || parentContainer.top < 0)) { listboxRef.current?.parentElement?.scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest", - }); + }) } - }, [listboxVisible, value]); + }, [listboxVisible, value]) - const optionChosen = multiple && value ? value.length > 0 : !!value; + const optionChosen = multiple && value ? value.length > 0 : !!value return (
    @@ -177,33 +128,25 @@ const SelectList = ({ >
    {label && ( -
    -
    +
    +
    {label}
    )} - {optionChosen && ( -
    - {renderSelectedValue(value, options)} -
    - )} + {optionChosen &&
    {renderSelectedValue(value, options)}
    } - +
    -
    +
      {!required && !multiple && ( - + {emptyLabel} )} - {options.map((option) => { + {options.map(option => { return ( {option.label} - ); + ) })}
    {name && ( - + )}
    - ); -}; + ) +} -export default SelectList; +export default SelectList diff --git a/src/components/elements/slideshow.tsx b/src/components/elements/slideshow.tsx index cda836c0..2a48a709 100644 --- a/src/components/elements/slideshow.tsx +++ b/src/components/elements/slideshow.tsx @@ -1,43 +1,42 @@ -"use client"; - -import {HTMLAttributes, JSX} from "react"; -import Slider, {CustomArrowProps, Settings} from "react-slick"; -import {ArrowLeftIcon, ArrowRightIcon} from "@heroicons/react/16/solid"; -import {twMerge} from "tailwind-merge"; -import {clsx} from "clsx"; +"use client" +import {HTMLAttributes, JSX} from "react" +import Slider, {CustomArrowProps, Settings} from "react-slick" +import {ArrowLeftIcon, ArrowRightIcon} from "@heroicons/react/16/solid" +import {twMerge} from "tailwind-merge" +import {clsx} from "clsx" const NextArrow = ({className, onClick}: CustomArrowProps) => { - const slickDisabled = !!(className && className?.indexOf("slick-disabled") > 0); + const slickDisabled = !!(className && className?.indexOf("slick-disabled") > 0) return ( - ); -}; + ) +} const PrevArrow = ({className, onClick}: CustomArrowProps) => { - const slickDisabled = !!(className && className?.indexOf("slick-disabled") > 0); + const slickDisabled = !!(className && className?.indexOf("slick-disabled") > 0) return ( - ); -}; + ) +} type SlideshowProps = HTMLAttributes & { - children: JSX.Element | JSX.Element[]; - slideshowProps?: Omit; + children: JSX.Element | JSX.Element[] + slideshowProps?: Omit } const Slideshow = ({children, slideshowProps, ...props}: SlideshowProps) => { @@ -48,8 +47,8 @@ const Slideshow = ({children, slideshowProps, ...props}: SlideshowProps) => { dots: false, infinite: false, initialSlide: 0, - nextArrow: , - prevArrow: , + nextArrow: , + prevArrow: , slidesToScroll: 1, slidesToShow: 3, speed: 500, @@ -64,14 +63,15 @@ const Slideshow = ({children, slideshowProps, ...props}: SlideshowProps) => { }, ], ...slideshowProps, - }; + } return ( -
    - - {children} - +
    + {children}
    - ); -}; + ) +} -export default Slideshow; +export default Slideshow diff --git a/src/components/elements/string-with-lines.tsx b/src/components/elements/string-with-lines.tsx index 1c18949b..4fbd0049 100644 --- a/src/components/elements/string-with-lines.tsx +++ b/src/components/elements/string-with-lines.tsx @@ -11,12 +11,10 @@ type Props = { const StringWithLines = ({text, key}: Props) => { return ( <> - {text.split("\n").map((line, i) => -

    - {line} -

    - )} + {text.split("\n").map((line, i) => ( +

    {line}

    + ))} ) } -export default StringWithLines; \ No newline at end of file +export default StringWithLines diff --git a/src/components/elements/tabs.tsx b/src/components/elements/tabs.tsx index 3f7d8cc7..73c95f2d 100644 --- a/src/components/elements/tabs.tsx +++ b/src/components/elements/tabs.tsx @@ -1,17 +1,17 @@ -"use client"; +"use client" -import {TabsProvider, useTabs} from "@mui/base/useTabs"; -import {useTab} from "@mui/base/useTab"; -import {useTabPanel} from "@mui/base/useTabPanel"; -import {TabsListProvider, useTabsList} from "@mui/base/useTabsList"; -import {HTMLAttributes, ReactNode, SyntheticEvent, useRef} from "react"; -import {UseTabParameters} from "@mui/base/useTab/useTab.types"; -import {clsx} from "clsx"; -import {twMerge} from "tailwind-merge"; -import {UseTabsParameters} from "@mui/base/useTabs/useTabs.types"; -import {UseTabsListParameters} from "@mui/base/useTabsList/useTabsList.types"; -import {UseTabPanelParameters} from "@mui/base/useTabPanel/useTabPanel.types"; -import {useRouter, useSearchParams} from "next/navigation"; +import {TabsProvider, useTabs} from "@mui/base/useTabs" +import {useTab} from "@mui/base/useTab" +import {useTabPanel} from "@mui/base/useTabPanel" +import {TabsListProvider, useTabsList} from "@mui/base/useTabsList" +import {HTMLAttributes, ReactNode, SyntheticEvent, useRef} from "react" +import {UseTabParameters} from "@mui/base/useTab/useTab.types" +import {clsx} from "clsx" +import {twMerge} from "tailwind-merge" +import {UseTabsParameters} from "@mui/base/useTabs/useTabs.types" +import {UseTabsListParameters} from "@mui/base/useTabsList/useTabsList.types" +import {UseTabPanelParameters} from "@mui/base/useTabPanel/useTabPanel.types" +import {useRouter, useSearchParams} from "next/navigation" // View the API for all the tab components here: https://mui.com/base-ui/react-tabs/hooks-api/. type TabsProps = HTMLAttributes & { @@ -30,11 +30,11 @@ type TabsProps = HTMLAttributes & { } export const Tabs = ({paramId = "tab", orientation, defaultTab, children, ...props}: TabsProps) => { - const searchParams = useSearchParams(); - const router = useRouter(); + const searchParams = useSearchParams() + const router = useRouter() const onChange = (_e: SyntheticEvent | null, value: number | string | null) => { - const params = new URLSearchParams(searchParams); - value ? params.set(paramId, `${value}`) : params.delete(paramId); + const params = new URLSearchParams(searchParams) + value ? params.set(paramId, `${value}`) : params.delete(paramId) router.replace(`?${params.toString()}`, {scroll: false}) } const paramValue = searchParams.get(paramId) @@ -44,9 +44,7 @@ export const Tabs = ({paramId = "tab", orientation, defaultTab, children, ...pro return ( -
    - {children} -
    +
    {children}
    ) } @@ -67,9 +65,9 @@ type TabsListProps = Omit & { } export const TabsList = ({containerProps, className, children, ...props}: TabsListProps) => { - const rootRef = useRef(null); - const {contextValue, orientation, getRootProps} = useTabsList({...props, rootRef}); - const isVertical = orientation === "vertical"; + const rootRef = useRef(null) + const {contextValue, orientation, getRootProps} = useTabsList({...props, rootRef}) + const isVertical = orientation === "vertical" return (
    { - const rootRef = useRef(null); - const {selected, getRootProps} = useTab({...props, rootRef}); + const rootRef = useRef(null) + const {selected, getRootProps} = useTab({...props, rootRef}) return ( @@ -129,11 +127,16 @@ type TabPanelProps = UseTabPanelParameters & { } export const TabPanel = ({panelProps, className, children}: TabPanelProps) => { - const rootRef = useRef(null); - const {getRootProps} = useTabPanel({rootRef}); + const rootRef = useRef(null) + const {getRootProps} = useTabPanel({rootRef}) return ( -
    +
    {children}
    ) -} \ No newline at end of file +} diff --git a/src/components/elements/telephone.tsx b/src/components/elements/telephone.tsx index fdf3cc8d..0fc1f9f2 100644 --- a/src/components/elements/telephone.tsx +++ b/src/components/elements/telephone.tsx @@ -1,7 +1,7 @@ "use client" -import {HtmlHTMLAttributes} from "react"; -import {useIsClient} from "usehooks-ts"; +import {HtmlHTMLAttributes} from "react" +import {useIsClient} from "usehooks-ts" type Props = HtmlHTMLAttributes & { /** @@ -11,13 +11,15 @@ type Props = HtmlHTMLAttributes & { } const Telephone = ({tel, ...props}: Props) => { - const isClient = useIsClient(); - if (!isClient) return; + const isClient = useIsClient() + if (!isClient) return return ( - - + {tel} ) } -export default Telephone \ No newline at end of file +export default Telephone diff --git a/src/components/elements/unpublished-banner.tsx b/src/components/elements/unpublished-banner.tsx index 2a6b019f..6da8579f 100644 --- a/src/components/elements/unpublished-banner.tsx +++ b/src/components/elements/unpublished-banner.tsx @@ -1,6 +1,6 @@ -import {HTMLAttributes} from "react"; -import {twMerge} from "tailwind-merge"; -import {ExclamationTriangleIcon} from "@heroicons/react/20/solid"; +import {HTMLAttributes} from "react" +import {twMerge} from "tailwind-merge" +import {ExclamationTriangleIcon} from "@heroicons/react/20/solid" type Props = HTMLAttributes & { /** @@ -9,14 +9,17 @@ type Props = HTMLAttributes & { status?: boolean } const UnpublishedBanner = ({status, children, ...props}: Props) => { - if (status !== false) return; + if (status !== false) return return ( -
    +
    - + {children}
    ) } -export default UnpublishedBanner; \ No newline at end of file +export default UnpublishedBanner diff --git a/src/components/elements/user-analytics.tsx b/src/components/elements/user-analytics.tsx index 0aa59633..d049eda0 100644 --- a/src/components/elements/user-analytics.tsx +++ b/src/components/elements/user-analytics.tsx @@ -1,18 +1,21 @@ -import {getConfigPage} from "@lib/gql/gql-queries"; -import {StanfordBasicSiteSetting} from "@lib/gql/__generated__/drupal"; -import Script from "next/script"; -import {GoogleAnalytics} from "@next/third-parties/google"; -import {isPreviewMode} from "@lib/drupal/utils"; +import {getConfigPage} from "@lib/gql/gql-queries" +import {StanfordBasicSiteSetting} from "@lib/gql/__generated__/drupal" +import Script from "next/script" +import {GoogleAnalytics} from "@next/third-parties/google" +import {isPreviewMode} from "@lib/drupal/utils" const UserAnalytics = async () => { - if (isPreviewMode()) return; + if (isPreviewMode()) return const siteSettingsConfig = await getConfigPage("StanfordBasicSiteSetting") - if (!siteSettingsConfig?.suGoogleAnalytics || !process.env.NEXT_PUBLIC_DOMAIN) return; + if (!siteSettingsConfig?.suGoogleAnalytics || !process.env.NEXT_PUBLIC_DOMAIN) return return ( <> -