diff --git a/.gitignore b/.gitignore index 9fe02d4..53491ca 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ dist .yalc yalc.lock .vite +.idea diff --git a/biome.json b/biome.json index 8e21310..66da343 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "$schema": "https://biomejs.dev/schemas/2.0.6/schema.json", "vcs": { "enabled": false, "clientKind": "git", @@ -7,8 +7,7 @@ }, "files": { "ignoreUnknown": false, - "ignore": [], - "include": ["src", "test"] + "includes": ["**/src/**", "**/test/**"] }, "formatter": { "enabled": true, @@ -21,18 +20,15 @@ "attributePosition": "auto", "bracketSpacing": true }, - "organizeImports": { - "enabled": true - }, + "assist": { "actions": { "source": { "organizeImports": "on" } } }, "linter": { "enabled": true, "rules": { "recommended": false, - "a11y": { "noBlankTarget": "error" }, + "a11y": {}, "complexity": { "noBannedTypes": "error", "noExtraBooleanCast": "error", - "noMultipleSpacesInRegularExpressionLiterals": "error", "noStaticOnlyClass": "error", "noUselessCatch": "error", "noUselessConstructor": "error", @@ -43,10 +39,11 @@ "noUselessTypeConstraint": "error", "noUselessUndefinedInitialization": "error", "noVoid": "error", - "noWith": "error", "useLiteralKeys": "error", "useOptionalChain": "error", - "useRegexLiterals": "error" + "useRegexLiterals": "error", + "noAdjacentSpacesInRegex": "error", + "noCommaOperator": "error" }, "correctness": { "noChildrenProp": "error", @@ -57,7 +54,6 @@ "noGlobalObjectCalls": "error", "noInvalidConstructorSuper": "error", "noInvalidUseBeforeDeclaration": "error", - "noNewSymbol": "error", "noPrecisionLoss": "error", "noSelfAssign": "error", "noSwitchDeclarations": "error", @@ -66,21 +62,21 @@ "noUnreachableSuper": "error", "noUnsafeFinally": "error", "noUnusedVariables": "error", - "useArrayLiterals": "off", "useExhaustiveDependencies": "off", "useHookAtTopLevel": "error", "useIsNan": "error", - "useJsxKeyInIterable": "error" + "useJsxKeyInIterable": "error", + "noInvalidBuiltinInstantiation": "error", + "useValidTypeof": "error" }, "security": { "noDangerouslySetInnerHtmlWithChildren": "error", - "noGlobalEval": "error" + "noGlobalEval": "error", + "noBlankTarget": "error" }, "style": { - "noCommaOperator": "error", "noNamespace": "error", "noNonNullAssertion": "error", - "noVar": "warn", "noYodaExpression": "error", "useBlockStatements": "off", "useConsistentArrayType": { @@ -94,7 +90,8 @@ "useNamingConvention": "off", "useShorthandFunctionType": "error", "useSingleVarDeclarator": "error", - "useThrowOnlyError": "off" + "useThrowOnlyError": "off", + "useArrayLiterals": "off" }, "suspicious": { "noAssignInExpressions": "error", @@ -129,10 +126,11 @@ "noSparseArray": "error", "noUnsafeNegation": "error", "useDefaultSwitchClauseLast": "error", - "useValidTypeof": "error" + "noWith": "error", + "noVar": "warn" } }, - "ignore": ["**/vitest.config.js", "**/tsup.config.ts"] + "includes": ["**", "!**/vitest.config.js", "!**/tsup.config.ts"] }, "javascript": { "formatter": { diff --git a/example-ssr/package-lock.json b/example-ssr/package-lock.json index c02eeba..f07f185 100644 --- a/example-ssr/package-lock.json +++ b/example-ssr/package-lock.json @@ -26,8 +26,11 @@ } }, ".yalc/react-modal-sheet": { - "version": "4.0.1", + "version": "5.1.1", "license": "MIT", + "dependencies": { + "react-use-measure": "2.1.7" + }, "engines": { "node": ">=18" }, @@ -4060,6 +4063,21 @@ "resolved": ".yalc/react-modal-sheet", "link": true }, + "node_modules/react-use-measure": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz", + "integrity": "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.13", + "react-dom": ">=16.13" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", diff --git a/example/biome.json b/example/biome.json index a6933d2..f716348 100644 --- a/example/biome.json +++ b/example/biome.json @@ -1,7 +1,23 @@ { + "root": false, "extends": ["../biome.json"], "files": { - "ignore": ["dist"], - "include": ["src", "index.html", "vite.config.mts"] + "includes": ["**/src/**", "**/index.html", "**/vite.config.mts", "!**/dist"] + }, + "linter": { + "rules": { + "style": { + "noParameterAssign": "error", + "useAsConstAssertion": "error", + "useDefaultParameterLast": "error", + "useEnumInitializers": "error", + "useSelfClosingElements": "error", + "useSingleVarDeclarator": "error", + "noUnusedTemplateLiteral": "error", + "useNumberNamespace": "error", + "noInferrableTypes": "error", + "noUselessElse": "error" + } + } } } diff --git a/example/package-lock.json b/example/package-lock.json index babe862..5293194 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -32,8 +32,11 @@ } }, ".yalc/react-modal-sheet": { - "version": "4.4.0", + "version": "5.1.1", "license": "MIT", + "dependencies": { + "react-use-measure": "2.1.7" + }, "engines": { "node": ">=18" }, @@ -7728,6 +7731,21 @@ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/react-use-measure": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz", + "integrity": "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.13", + "react-dom": ">=16.13" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", diff --git a/example/src/assets.d.ts b/example/src/assets.d.ts index 8b4b997..ce1873a 100644 --- a/example/src/assets.d.ts +++ b/example/src/assets.d.ts @@ -1,16 +1,16 @@ -declare module '*.jpg' { - const src: string; - export default src; +declare module "*.jpg" { + const src: string; + export default src; } -declare module '*.jpeg' { - const src: string; - export default src; +declare module "*.jpeg" { + const src: string; + export default src; } -declare module '*.png' { - const src: string; - export default src; +declare module "*.png" { + const src: string; + export default src; } -declare module '*.svg' { - const src: string; - export default src; +declare module "*.svg" { + const src: string; + export default src; } diff --git a/example/src/components/App.tsx b/example/src/components/App.tsx index f804233..3b221f6 100644 --- a/example/src/components/App.tsx +++ b/example/src/components/App.tsx @@ -1,275 +1,275 @@ -import { MdAccessibility as A11yIcon } from 'react-icons/md'; -import { Link, Route, Routes } from 'react-router'; -import { styled } from 'styled-components'; +import { MdAccessibility as A11yIcon } from "react-icons/md"; +import { Link, Route, Routes } from "react-router"; +import { styled } from "styled-components"; import { - FaMap as AppleMapIcon, - FaMusic as AppleMusicIcon, - FaMobile, - FaWalking, - FaKeyboard as KeyboardIcon, - FaLock as LockIcon, - FaMoon as MoonIcon, - FaPaintBrush as PaintIcon, - FaScroll as ScrollIcon -} from 'react-icons/fa'; + FaMap as AppleMapIcon, + FaMusic as AppleMusicIcon, + FaMobile, + FaWalking, + FaKeyboard as KeyboardIcon, + FaLock as LockIcon, + FaMoon as MoonIcon, + FaPaintBrush as PaintIcon, + FaScroll as ScrollIcon, +} from "react-icons/fa"; import { - AiOutlineColumnHeight as HeightIcon, - AiOutlineSlack as SlackIcon, - AiOutlineControl as SnapIcon, -} from 'react-icons/ai'; + AiOutlineColumnHeight as HeightIcon, + AiOutlineSlack as SlackIcon, + AiOutlineControl as SnapIcon, +} from "react-icons/ai"; -import { AvoidKeyboard } from './AvoidKeyboard'; -import { ContentHeight } from './ContentHeight'; -import { CustomStyles } from './CustomStyles'; -import { DisableDrag } from './DisableDrag'; -import { FullScreen } from './FullScreen'; -import { ReducedMotion } from './ReducedMotion'; -import { Scrollable } from './Scrollable'; -import { ScrollableSnapPoints } from './ScrollableSnapPoints'; -import { ShadowDOM } from './ShadowDOM'; -import { SnapPoints } from './SnapPoints'; -import { A11y } from './a11y'; -import { AppleMaps } from './apple-maps'; -import { AppleMusic } from './apple-music'; -import { DarkMode, Screen, ScrollView } from './common'; -import { SlackMessage } from './slack-message'; +import { AvoidKeyboard } from "./AvoidKeyboard"; +import { ContentHeight } from "./ContentHeight"; +import { CustomStyles } from "./CustomStyles"; +import { DisableDrag } from "./DisableDrag"; +import { FullScreen } from "./FullScreen"; +import { ReducedMotion } from "./ReducedMotion"; +import { Scrollable } from "./Scrollable"; +import { ScrollableSnapPoints } from "./ScrollableSnapPoints"; +import { ShadowDOM } from "./ShadowDOM"; +import { SnapPoints } from "./SnapPoints"; +import { A11y } from "./a11y"; +import { AppleMaps } from "./apple-maps"; +import { AppleMusic } from "./apple-music"; +import { DarkMode, Screen, ScrollView } from "./common"; +import { SlackMessage } from "./slack-message"; export function App() { - return ( - - - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - ); + return ( + + + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + ); } const ExampleSelector = () => { - return ( - -
  • - - - Snap points - -
  • + return ( + +
  • + + + Snap points + +
  • -
  • - - - Use Content Height - -
  • +
  • + + + Use Content Height + +
  • -
  • - - - Custom Styles - -
  • +
  • + + + Custom Styles + +
  • -
  • - - - Scrollable - -
  • +
  • + + + Scrollable + +
  • -
  • - - - Avoid keyboard - -
  • +
  • + + + Avoid keyboard + +
  • -
  • - - - Scrollable (with snap points) - -
  • +
  • + + + Scrollable (with snap points) + +
  • -
  • - - - Disable drag - -
  • +
  • + + + Disable drag + +
  • -
  • - - - Apple Music - -
  • +
  • + + + Apple Music + +
  • -
  • - - - Apple Maps - -
  • +
  • + + + Apple Maps + +
  • -
  • - - - Slack Message - -
  • +
  • + + + Slack Message + +
  • -
  • - - - Accessible Sheet - -
  • +
  • + + + Accessible Sheet + +
  • -
  • - - - Reduced Motion - -
  • +
  • + + + Reduced Motion + +
  • -
  • - - - Full screen - -
  • +
  • + + + Full screen + +
  • -
  • - - - Shadow DOM - -
  • -
    - ); +
  • + + + Shadow DOM + +
  • +
    + ); }; const ExampleLinks = styled.ul` diff --git a/example/src/components/AvoidKeyboard.tsx b/example/src/components/AvoidKeyboard.tsx index 5cf96f9..5e128a5 100644 --- a/example/src/components/AvoidKeyboard.tsx +++ b/example/src/components/AvoidKeyboard.tsx @@ -1,48 +1,48 @@ -import { useRef } from 'react'; -import { Sheet, type SheetRef } from 'react-modal-sheet'; -import { styled } from 'styled-components'; +import { useRef } from "react"; +import { Sheet, type SheetRef } from "react-modal-sheet"; +import { styled } from "styled-components"; -import { ExampleLayout } from './ExampleLayout'; -import { Button } from './common'; +import { ExampleLayout } from "./ExampleLayout"; +import { Button } from "./common"; export function AvoidKeyboard() { - const sheetRef = useRef(null); - const formRef = useRef(null); + const sheetRef = useRef(null); + const formRef = useRef(null); - return ( - - {({ isOpen, close }) => ( - - - - - -
    { - e.preventDefault(); - alert('Form submitted!'); - }} - > - - - - - - - -
    -
    -
    -
    - -
    - )} -
    - ); + return ( + + {({ isOpen, close }) => ( + + + + + +
    { + e.preventDefault(); + alert("Form submitted!"); + }} + > + + + + + + + +
    +
    +
    +
    + +
    + )} +
    + ); } const Content = styled.div` display: flex; diff --git a/example/src/components/BoxList.tsx b/example/src/components/BoxList.tsx index 9cc24f4..a719a02 100644 --- a/example/src/components/BoxList.tsx +++ b/example/src/components/BoxList.tsx @@ -1,15 +1,22 @@ -import { styled } from 'styled-components'; +import { styled } from "styled-components"; export function BoxList({ count = 50 }: { count?: number }) { - return ( - - {Array.from({ length: count }) - .fill(1) - .map((_, i) => ( - {i + 1} - ))} - - ); + return ( + + {Array.from({ length: count }) + .fill(1) + .map((_, i) => ( + + {i + 1} + + ))} + + ); } const Wrapper = styled.div` diff --git a/example/src/components/ContentHeight.tsx b/example/src/components/ContentHeight.tsx index eba990f..59c06fe 100644 --- a/example/src/components/ContentHeight.tsx +++ b/example/src/components/ContentHeight.tsx @@ -1,60 +1,67 @@ -import { useRef, useState } from 'react'; -import { Sheet, type SheetRef } from 'react-modal-sheet'; -import { styled } from 'styled-components'; +import { useRef, useState } from "react"; +import { Sheet, type SheetRef } from "react-modal-sheet"; +import { styled } from "styled-components"; -import { ExampleLayout } from './ExampleLayout'; -import { Button } from './common'; +import { ExampleLayout } from "./ExampleLayout"; +import { Button } from "./common"; const snapPoints = [0, 200, 1]; const lastSnap = snapPoints.length - 1; export function ContentHeight() { - const [boxes, setBoxes] = useState(1); - const sheetRef = useRef(null); - const snapTo = (i: number) => sheetRef.current?.snapTo(i); + const [boxes, setBoxes] = useState(1); + const sheetRef = useRef(null); + const snapTo = (i: number) => sheetRef.current?.snapTo(i); - return ( - - {({ isOpen, close }) => ( - - - - state.currentSnap !== lastSnap} - > - - - - - + return ( + + {({ isOpen, close }) => ( + + + + state.currentSnap !== lastSnap} + > + + + + + - {Array.from({ length: boxes }).map((_, i) => ( - {i} - ))} - - - - - - )} - - ); + {Array.from({ length: boxes }).map((_, i) => ( + + {i} + + ))} + + + + + + )} + + ); } const BoxList = styled.div` diff --git a/example/src/components/CustomStyles.tsx b/example/src/components/CustomStyles.tsx index 6f9ab2a..e06ec72 100644 --- a/example/src/components/CustomStyles.tsx +++ b/example/src/components/CustomStyles.tsx @@ -1,43 +1,43 @@ -import { Sheet } from 'react-modal-sheet'; -import { styled } from 'styled-components'; +import { Sheet } from "react-modal-sheet"; +import { styled } from "styled-components"; -import { ExampleLayout } from './ExampleLayout'; -import { Button } from './common'; +import { ExampleLayout } from "./ExampleLayout"; +import { Button } from "./common"; export function CustomStyles() { - return ( - - {({ isOpen, close }) => ( - - - - - - - - - - - Custom styles - - This sheet has totally custom styles and its height is dynamic - based on the size of its content. - - - Cancel - - - - - - - - )} - - ); + return ( + + {({ isOpen, close }) => ( + + + + + + + + + + + Custom styles + + This sheet has totally custom styles and its height is dynamic + based on the size of its content. + + + Cancel + + + + + + + + )} + + ); } const SheetContainer = styled(Sheet.Container)` diff --git a/example/src/components/DisableDrag.tsx b/example/src/components/DisableDrag.tsx index a1c2825..dbcd539 100644 --- a/example/src/components/DisableDrag.tsx +++ b/example/src/components/DisableDrag.tsx @@ -1,57 +1,64 @@ -import { useRef, useState } from 'react'; -import { styled } from 'styled-components'; -import { Sheet } from 'react-modal-sheet'; +import { useRef, useState } from "react"; +import { styled } from "styled-components"; +import { Sheet } from "react-modal-sheet"; -import { ExampleLayout } from './ExampleLayout'; +import { ExampleLayout } from "./ExampleLayout"; export function DisableDrag() { - const { isScrolling, onScroll } = useScrolling(); + const { isScrolling, onScroll } = useScrolling(); - return ( - - {({ isOpen, close }) => ( - - - - - -
    - {isScrolling - ? 'Scrolling (drag disabled)' - : 'Not scrolling (drag enabled)'} -
    + return ( + + {({ isOpen, close }) => ( + + + + + +
    + {isScrolling + ? "Scrolling (drag disabled)" + : "Not scrolling (drag enabled)"} +
    - - {Array.from({ length: 20 }) - .fill(1) - .map((_, i) => ( - {i} - ))} - -
    -
    -
    - -
    - )} -
    - ); + + {Array.from({ length: 20 }) + .fill(1) + .map((_, i) => ( + + {i} + + ))} + +
    +
    +
    + +
    + )} +
    + ); } function useScrolling() { - const [isScrolling, setScrolling] = useState(false); - const timeout = useRef(undefined); + const [isScrolling, setScrolling] = useState(false); + const timeout = useRef(undefined); - const onScroll = () => { - setScrolling(true); - clearTimeout(timeout.current); - timeout.current = setTimeout(() => setScrolling(false), 150); - }; + const onScroll = () => { + setScrolling(true); + clearTimeout(timeout.current); + timeout.current = setTimeout(() => setScrolling(false), 150); + }; - return { onScroll, isScrolling }; + return { onScroll, isScrolling }; } const Content = styled.div` diff --git a/example/src/components/ExampleLayout.tsx b/example/src/components/ExampleLayout.tsx index 093f9a1..0ef8387 100644 --- a/example/src/components/ExampleLayout.tsx +++ b/example/src/components/ExampleLayout.tsx @@ -1,138 +1,138 @@ -import { motion, useScroll, useTransform } from 'motion/react'; -import { type ReactNode, useRef } from 'react'; -import { FiChevronLeft } from 'react-icons/fi'; -import { Link } from 'react-router'; +import { motion, useScroll, useTransform } from "motion/react"; +import { type ReactNode, useRef } from "react"; +import { FiChevronLeft } from "react-icons/fi"; +import { Link } from "react-router"; import { - type OverlayTriggerState, - useOverlayTriggerState, -} from 'react-stately'; -import { createGlobalStyle, styled } from 'styled-components'; + type OverlayTriggerState, + useOverlayTriggerState, +} from "react-stately"; +import { createGlobalStyle, styled } from "styled-components"; -import { Button, ScrollView } from './common'; +import { Button, ScrollView } from "./common"; type Props = { - title: string; - description?: string; - children: (state: OverlayTriggerState) => ReactNode; + title: string; + description?: string; + children: (state: OverlayTriggerState) => ReactNode; }; export function ExampleLayout({ title, description, children }: Props) { - const state = useOverlayTriggerState({}); - const scrollRef = useRef(null); - const { scrollY } = useScroll({ axis: 'y', container: scrollRef }); - const fabOpacity = useTransform(scrollY, [200, 220], [0, 1]); - const fabTranslateY = useTransform(scrollY, [200, 220], [20, 0]); - - return ( - - - - - Back - - - {title} - - {description && {description}} - - - - - Example content to make the page scrollable... - - - Lorem, ipsum dolor sit amet consectetur adipisicing elit. Recusandae - sint cupiditate eum quibusdam consequuntur quae! Rem error alias - placeat aliquid qui facere dicta veniam tenetur suscipit? Quibusdam - eos est similique excepturi officiis sequi maxime sunt blanditiis - nulla aperiam rem cum totam eligendi eius voluptatem, dolores - repellendus! Iste accusantium vero, sint ipsam dicta saepe - laudantium blanditiis et corporis aliquid deleniti quae vitae - nostrum, repellat illo explicabo accusamus odit pariatur ex. Placeat - dolorum in laboriosam repudiandae maiores aut incidunt eos sequi - consectetur, autem nihil. - - - Quae corrupti veritatis voluptates molestiae ipsam beatae sit quia - aperiam rem! Natus earum quas, quos rerum nisi nostrum deserunt - voluptatibus perspiciatis? Hic, animi harum quam, fugit explicabo ab - accusantium laborum iste rem omnis obcaecati quis earum eligendi in - inventore, mollitia asperiores numquam amet architecto porro at! - Minus, non porro. Harum dolor nihil nemo quisquam! Omnis ipsum - deleniti id laborum incidunt temporibus, ipsa suscipit eius dolorum - voluptatem aut, voluptas a provident tempore. Voluptas asperiores ea - delectus. Ipsa laborum error numquam perferendis similique - voluptates animi suscipit dolore at modi dicta minima, asperiores - corporis nemo, voluptate repellendus, aspernatur illo quo. Aliquid - voluptatem excepturi odio accusamus dignissimos expedita eveniet, - impedit consequatur. Illo fugit placeat possimus est doloremque? - Veritatis quidem, similique sed non sint architecto aliquam - doloribus accusamus aspernatur fugit corporis quae voluptates maxime - at. - - - Aut praesentium, quia architecto ea natus dicta nihil laborum - tempora animi quas voluptas recusandae adipisci nostrum vero amet, - nisi temporibus fugit sequi beatae. Natus fugiat ullam nemo neque - laborum nesciunt, iure totam aut doloribus ea! Fugiat similique eos - vel dicta maxime? Cumque hic perferendis accusantium molestias - laboriosam quod consequuntur, cupiditate fuga accusamus cum - explicabo, magni enim nobis velit numquam atque! Maxime et explicabo - velit distinctio! Quis ad, ipsa eaque iusto adipisci laboriosam - fugiat nihil blanditiis explicabo fugit repudiandae. Quaerat odio - porro doloribus? Perferendis, sit blanditiis. Ab, eligendi impedit. - Consectetur, officia provident! Sed dignissimos suscipit - consequuntur fugit ullam odio incidunt quo sint enim. Ratione modi - aperiam rem non quaerat consectetur, natus maiores impedit et - exercitationem, suscipit facilis debitis, mollitia in molestiae sunt - sit cum optio laboriosam? Fugit officia consequuntur eos voluptate, - quo dicta quas! In nulla sapiente cupiditate sequi! - - - Animi culpa cumque, et voluptas, autem odio tenetur iusto quas amet - quidem ipsam quos dicta dolorem libero, expedita minima maiores - exercitationem esse eos. Vero cumque molestias porro iusto neque, - officiis quaerat nemo. Sunt atque corrupti nobis id sapiente quidem. - Animi officiis corrupti dicta, excepturi, quod, reprehenderit nam - sint accusamus deserunt obcaecati beatae illum ipsum minus nisi - necessitatibus omnis aspernatur eligendi saepe aliquid aperiam. - Ipsam, perspiciatis? Temporibus iure cumque optio accusamus itaque - laboriosam nemo facilis earum, asperiores libero. Quia eveniet - inventore asperiores fuga impedit deserunt iure magni ipsam tenetur. - Eos omnis officia unde quisquam natus eius beatae aperiam. Facilis - vitae veniam aut ducimus consequatur excepturi labore modi dolorum - eveniet? Ex maxime placeat dolore minima hic at necessitatibus - similique voluptatem facilis, ipsa nisi nihil tempora nemo mollitia - nulla dolorum dolor fuga cupiditate veniam assumenda, voluptas, - aspernatur nobis! Minima magni perspiciatis doloribus officia - veritatis, ratione, quas dolore eos impedit numquam doloremque ex - delectus! - - - - - - - - {children(state)} - - -

    - Made in Finland ๐Ÿ‡ซ๐Ÿ‡ฎ by{' '} - - Teemu Taskula - -

    -
    - - -
    -
    - ); + const state = useOverlayTriggerState({}); + const scrollRef = useRef(null); + const { scrollY } = useScroll({ axis: "y", container: scrollRef }); + const fabOpacity = useTransform(scrollY, [200, 220], [0, 1]); + const fabTranslateY = useTransform(scrollY, [200, 220], [20, 0]); + + return ( + + + + + Back + + + {title} + + {description && {description}} + + + + + Example content to make the page scrollable... + + + Lorem, ipsum dolor sit amet consectetur adipisicing elit. Recusandae + sint cupiditate eum quibusdam consequuntur quae! Rem error alias + placeat aliquid qui facere dicta veniam tenetur suscipit? Quibusdam + eos est similique excepturi officiis sequi maxime sunt blanditiis + nulla aperiam rem cum totam eligendi eius voluptatem, dolores + repellendus! Iste accusantium vero, sint ipsam dicta saepe + laudantium blanditiis et corporis aliquid deleniti quae vitae + nostrum, repellat illo explicabo accusamus odit pariatur ex. Placeat + dolorum in laboriosam repudiandae maiores aut incidunt eos sequi + consectetur, autem nihil. + + + Quae corrupti veritatis voluptates molestiae ipsam beatae sit quia + aperiam rem! Natus earum quas, quos rerum nisi nostrum deserunt + voluptatibus perspiciatis? Hic, animi harum quam, fugit explicabo ab + accusantium laborum iste rem omnis obcaecati quis earum eligendi in + inventore, mollitia asperiores numquam amet architecto porro at! + Minus, non porro. Harum dolor nihil nemo quisquam! Omnis ipsum + deleniti id laborum incidunt temporibus, ipsa suscipit eius dolorum + voluptatem aut, voluptas a provident tempore. Voluptas asperiores ea + delectus. Ipsa laborum error numquam perferendis similique + voluptates animi suscipit dolore at modi dicta minima, asperiores + corporis nemo, voluptate repellendus, aspernatur illo quo. Aliquid + voluptatem excepturi odio accusamus dignissimos expedita eveniet, + impedit consequatur. Illo fugit placeat possimus est doloremque? + Veritatis quidem, similique sed non sint architecto aliquam + doloribus accusamus aspernatur fugit corporis quae voluptates maxime + at. + + + Aut praesentium, quia architecto ea natus dicta nihil laborum + tempora animi quas voluptas recusandae adipisci nostrum vero amet, + nisi temporibus fugit sequi beatae. Natus fugiat ullam nemo neque + laborum nesciunt, iure totam aut doloribus ea! Fugiat similique eos + vel dicta maxime? Cumque hic perferendis accusantium molestias + laboriosam quod consequuntur, cupiditate fuga accusamus cum + explicabo, magni enim nobis velit numquam atque! Maxime et explicabo + velit distinctio! Quis ad, ipsa eaque iusto adipisci laboriosam + fugiat nihil blanditiis explicabo fugit repudiandae. Quaerat odio + porro doloribus? Perferendis, sit blanditiis. Ab, eligendi impedit. + Consectetur, officia provident! Sed dignissimos suscipit + consequuntur fugit ullam odio incidunt quo sint enim. Ratione modi + aperiam rem non quaerat consectetur, natus maiores impedit et + exercitationem, suscipit facilis debitis, mollitia in molestiae sunt + sit cum optio laboriosam? Fugit officia consequuntur eos voluptate, + quo dicta quas! In nulla sapiente cupiditate sequi! + + + Animi culpa cumque, et voluptas, autem odio tenetur iusto quas amet + quidem ipsam quos dicta dolorem libero, expedita minima maiores + exercitationem esse eos. Vero cumque molestias porro iusto neque, + officiis quaerat nemo. Sunt atque corrupti nobis id sapiente quidem. + Animi officiis corrupti dicta, excepturi, quod, reprehenderit nam + sint accusamus deserunt obcaecati beatae illum ipsum minus nisi + necessitatibus omnis aspernatur eligendi saepe aliquid aperiam. + Ipsam, perspiciatis? Temporibus iure cumque optio accusamus itaque + laboriosam nemo facilis earum, asperiores libero. Quia eveniet + inventore asperiores fuga impedit deserunt iure magni ipsam tenetur. + Eos omnis officia unde quisquam natus eius beatae aperiam. Facilis + vitae veniam aut ducimus consequatur excepturi labore modi dolorum + eveniet? Ex maxime placeat dolore minima hic at necessitatibus + similique voluptatem facilis, ipsa nisi nihil tempora nemo mollitia + nulla dolorum dolor fuga cupiditate veniam assumenda, voluptas, + aspernatur nobis! Minima magni perspiciatis doloribus officia + veritatis, ratione, quas dolore eos impedit numquam doloremque ex + delectus! + + + + + + + + {children(state)} + + +

    + Made in Finland ๐Ÿ‡ซ๐Ÿ‡ฎ by{" "} + + Teemu Taskula + +

    +
    + + +
    +
    + ); } const maxWidth = 720; diff --git a/example/src/components/FullScreen.tsx b/example/src/components/FullScreen.tsx index 87a8828..8c3b0b9 100644 --- a/example/src/components/FullScreen.tsx +++ b/example/src/components/FullScreen.tsx @@ -1,27 +1,27 @@ -import { Sheet } from 'react-modal-sheet'; -import { styled } from 'styled-components'; +import { Sheet } from "react-modal-sheet"; +import { styled } from "styled-components"; -import { BoxList } from './BoxList'; -import { ExampleLayout } from './ExampleLayout'; +import { BoxList } from "./BoxList"; +import { ExampleLayout } from "./ExampleLayout"; export function FullScreen() { - return ( - - {({ isOpen, close }) => ( - - - - - - - - - )} - - ); + return ( + + {({ isOpen, close }) => ( + + + + + + + + + )} + + ); } const SheetContainer = styled(Sheet.Container)` diff --git a/example/src/components/ReducedMotion.tsx b/example/src/components/ReducedMotion.tsx index ac5f032..8d8437d 100644 --- a/example/src/components/ReducedMotion.tsx +++ b/example/src/components/ReducedMotion.tsx @@ -1,33 +1,40 @@ -import { Sheet } from 'react-modal-sheet'; -import { styled } from 'styled-components'; +import { Sheet } from "react-modal-sheet"; +import { styled } from "styled-components"; -import { ExampleLayout } from './ExampleLayout'; +import { ExampleLayout } from "./ExampleLayout"; export function ReducedMotion() { - return ( - - {({ isOpen, close }) => ( - - - - - - {Array.from({ length: 50 }) - .fill(1) - .map((_, i) => ( - {i} - ))} - - - - - - )} - - ); + return ( + + {({ isOpen, close }) => ( + + + + + + {Array.from({ length: 50 }) + .fill(1) + .map((_, i) => ( + + {i} + + ))} + + + + + + )} + + ); } const BoxList = styled.div` diff --git a/example/src/components/Scrollable.tsx b/example/src/components/Scrollable.tsx index 311bd29..ee96265 100644 --- a/example/src/components/Scrollable.tsx +++ b/example/src/components/Scrollable.tsx @@ -1,29 +1,29 @@ -import { Sheet } from 'react-modal-sheet'; +import { Sheet } from "react-modal-sheet"; -import { BoxList } from './BoxList'; -import { ExampleLayout } from './ExampleLayout'; +import { BoxList } from "./BoxList"; +import { ExampleLayout } from "./ExampleLayout"; export function Scrollable() { - return ( - - {({ isOpen, close }) => ( - - - - - - - - - - )} - - ); + return ( + + {({ isOpen, close }) => ( + + + + + + + + + + )} + + ); } diff --git a/example/src/components/ScrollableSnapPoints.tsx b/example/src/components/ScrollableSnapPoints.tsx index 3a61a99..3f66a8c 100644 --- a/example/src/components/ScrollableSnapPoints.tsx +++ b/example/src/components/ScrollableSnapPoints.tsx @@ -1,68 +1,68 @@ -import { useRef, useState } from 'react'; -import { Sheet, type SheetRef } from 'react-modal-sheet'; -import { styled } from 'styled-components'; +import { useRef, useState } from "react"; +import { Sheet, type SheetRef } from "react-modal-sheet"; +import { styled } from "styled-components"; -import { BoxList } from './BoxList'; -import { ExampleLayout } from './ExampleLayout'; -import { Button } from './common'; +import { BoxList } from "./BoxList"; +import { ExampleLayout } from "./ExampleLayout"; +import { Button } from "./common"; const snapPoints = [0, 170, 0.5, -200, 1]; const initialSnap = 1; const lastSnap = snapPoints.length - 1; export function ScrollableSnapPoints() { - const [currentSnap, setCurrentSnap] = useState(initialSnap); - const sheetRef = useRef(null); - const snapTo = (i: number) => sheetRef.current?.snapTo(i); + const [currentSnap, setCurrentSnap] = useState(initialSnap); + const sheetRef = useRef(null); + const snapTo = (i: number) => sheetRef.current?.snapTo(i); - return ( - - {({ isOpen, close }) => ( - - - + return ( + + {({ isOpen, close }) => ( + + + - state.currentSnap !== lastSnap} - > -
    - - Current snap point: {currentSnap} - - Content is only scrollable at the upmost snap point - - -
    + state.currentSnap !== lastSnap} + > +
    + + Current snap point: {currentSnap} + + Content is only scrollable at the upmost snap point + + +
    - -
    + +
    -
    - - - - - - - -
    -
    - -
    - )} -
    - ); +
    + + + + + + + +
    +
    + +
    + )} +
    + ); } const Header = styled.div` diff --git a/example/src/components/ShadowDOM.tsx b/example/src/components/ShadowDOM.tsx index 8aaff33..b6690bc 100644 --- a/example/src/components/ShadowDOM.tsx +++ b/example/src/components/ShadowDOM.tsx @@ -1,92 +1,95 @@ -import { useEffect, useState } from 'react'; -import { Sheet } from 'react-modal-sheet'; +import { useEffect, useState } from "react"; +import { Sheet } from "react-modal-sheet"; -import { ExampleLayout } from './ExampleLayout'; +import { ExampleLayout } from "./ExampleLayout"; export function ShadowDOM() { - const shadowRoot = useShadowRoot(); + const shadowRoot = useShadowRoot(); - return ( - - {({ isOpen, close }) => ( - <> - {/* Render the Sheet only when the shadowRoot is ready */} - {shadowRoot && ( - - - - - {/* We used inline styles because the CSS in document.head is outside the shadow DOM */} -
    - {Array.from({ length: 50 }).map((_, i) => ( -
    - {i} -
    - ))} -
    -
    -
    - -
    - )} - - )} -
    - ); + return ( + + {({ isOpen, close }) => ( + <> + {/* Render the Sheet only when the shadowRoot is ready */} + {shadowRoot && ( + + + + + {/* We used inline styles because the CSS in document.head is outside the shadow DOM */} +
    + {Array.from({ length: 50 }).map((_, i) => ( +
    + {i} +
    + ))} +
    +
    +
    + +
    + )} + + )} +
    + ); } -const SHADOW_ROOT_ID = 'react-modal-sheet-shadow-root'; +const SHADOW_ROOT_ID = "react-modal-sheet-shadow-root"; function useShadowRoot() { - const [shadowRoot, setShadowRoot] = useState(null); + const [shadowRoot, setShadowRoot] = useState(null); - useEffect(() => { - // Create a shadow DOM root dynamically if it doesn't already exist - let shadowRootContainer = document.getElementById(SHADOW_ROOT_ID); + useEffect(() => { + // Create a shadow DOM root dynamically if it doesn't already exist + let shadowRootContainer = document.getElementById(SHADOW_ROOT_ID); - if (!shadowRootContainer) { - shadowRootContainer = document.createElement('div'); - shadowRootContainer.id = SHADOW_ROOT_ID; - document.body.appendChild(shadowRootContainer); - } + if (!shadowRootContainer) { + shadowRootContainer = document.createElement("div"); + shadowRootContainer.id = SHADOW_ROOT_ID; + document.body.appendChild(shadowRootContainer); + } - // Attach shadow root and update state - if (!shadowRoot) { - const root = shadowRootContainer.attachShadow({ mode: 'open' }); - setShadowRoot(root); - } + // Attach shadow root and update state + if (!shadowRoot) { + const root = shadowRootContainer.attachShadow({ mode: "open" }); + setShadowRoot(root); + } - return () => { - // Clean up the shadow root when the component is unmounted - if (shadowRoot) { - shadowRoot.host.remove(); - setShadowRoot(null); - } - }; - }, [shadowRoot]); + return () => { + // Clean up the shadow root when the component is unmounted + if (shadowRoot) { + shadowRoot.host.remove(); + setShadowRoot(null); + } + }; + }, [shadowRoot]); - return shadowRoot as HTMLElement | null; + return shadowRoot as HTMLElement | null; } diff --git a/example/src/components/SnapPoints.tsx b/example/src/components/SnapPoints.tsx index 1d44914..162f6f9 100644 --- a/example/src/components/SnapPoints.tsx +++ b/example/src/components/SnapPoints.tsx @@ -1,55 +1,55 @@ -import { useEffect, useRef, useState } from 'react'; -import { Sheet, type SheetRef } from 'react-modal-sheet'; -import { styled } from 'styled-components'; +import { useEffect, useRef, useState } from "react"; +import { Sheet, type SheetRef } from "react-modal-sheet"; +import { styled } from "styled-components"; -import { ExampleLayout } from './ExampleLayout'; -import { Button } from './common'; +import { ExampleLayout } from "./ExampleLayout"; +import { Button } from "./common"; const snapPoints = [0, 100, 0.5, -100, 1]; const initialSnap = 1; // Initial snap point when sheet is opened export function SnapPoints() { - const sheetRef = useRef(null); - const [snapPoint, setSnapPoint] = useState(initialSnap); - const snapTo = (i: number) => sheetRef.current?.snapTo(i); + const sheetRef = useRef(null); + const [snapPoint, setSnapPoint] = useState(initialSnap); + const snapTo = (i: number) => sheetRef.current?.snapTo(i); - useEffect(() => { - console.log('> Current snap point is', snapPoint); - }, [snapPoint]); + useEffect(() => { + console.log("> Current snap point is", snapPoint); + }, [snapPoint]); - return ( - - {({ isOpen, close }) => ( - - - - - - - - - - - - - - - - - - )} - - ); + return ( + + {({ isOpen, close }) => ( + + + + + + + + + + + + + + + + + + )} + + ); } const SheetContentWrapper = styled.div` diff --git a/example/src/components/a11y/A11ySheet.tsx b/example/src/components/a11y/A11ySheet.tsx index 2783c93..62070bc 100644 --- a/example/src/components/a11y/A11ySheet.tsx +++ b/example/src/components/a11y/A11ySheet.tsx @@ -1,74 +1,74 @@ -import { useRef, type PropsWithChildren } from 'react'; -import { type OverlayTriggerState } from 'react-stately'; -import { Sheet } from 'react-modal-sheet'; +import { useRef, type PropsWithChildren } from "react"; +import type { OverlayTriggerState } from "react-stately"; +import { Sheet } from "react-modal-sheet"; import { - FocusScope, - useDialog, - useOverlay, - useModal, - OverlayProvider, -} from 'react-aria'; + FocusScope, + useDialog, + useOverlay, + useModal, + OverlayProvider, +} from "react-aria"; type SheetProps = { - state: OverlayTriggerState; - label: string; + state: OverlayTriggerState; + label: string; }; export function A11ySheet({ - state, - label, - children, - ...rest + state, + label, + children, + ...rest }: PropsWithChildren) { - return ( - - - - - {children} - - - - - ); + return ( + + + + + {children} + + + + + ); } const A11ySheetContent = ({ - state, - label, - children, + state, + label, + children, }: PropsWithChildren) => { - const a11yProps = useA11ySheet(state, label); + const a11yProps = useA11ySheet(state, label); - return ( - <> - - - {children} - - - - ); + return ( + <> + + + {children} + + + + ); }; const useA11ySheet = (state: OverlayTriggerState, label: string) => { - const ref = useRef(null); - const dialog = useDialog({ 'aria-label': label }, ref); - const overlay = useOverlay( - { - onClose: state.close, - isOpen: true, - isDismissable: true, - }, - ref - ); + const ref = useRef(null); + const dialog = useDialog({ "aria-label": label }, ref); + const overlay = useOverlay( + { + onClose: state.close, + isOpen: true, + isDismissable: true, + }, + ref, + ); - useModal(); + useModal(); - return { - ref, - ...overlay.overlayProps, - ...dialog.dialogProps, - } as any; // HACK: fix type conflicts with Framer Motion + return { + ref, + ...overlay.overlayProps, + ...dialog.dialogProps, + } as any; // HACK: fix type conflicts with Framer Motion }; diff --git a/example/src/components/a11y/index.tsx b/example/src/components/a11y/index.tsx index 9a391aa..216265b 100644 --- a/example/src/components/a11y/index.tsx +++ b/example/src/components/a11y/index.tsx @@ -1,24 +1,24 @@ -import { styled } from 'styled-components'; +import { styled } from "styled-components"; -import { A11ySheet } from './A11ySheet'; -import { ExampleLayout } from '../ExampleLayout'; +import { A11ySheet } from "./A11ySheet"; +import { ExampleLayout } from "../ExampleLayout"; export function A11y() { - return ( - - {(state) => ( - - - This is a simple a11y sheet ๐Ÿฆพ -

    Your content goes here...

    -
    -
    - )} -
    - ); + return ( + + {(state) => ( + + + This is a simple a11y sheet ๐Ÿฆพ +

    Your content goes here...

    +
    +
    + )} +
    + ); } const SheetContent = styled.div` diff --git a/example/src/components/apple-maps/index.tsx b/example/src/components/apple-maps/index.tsx index ddf5569..d137ed8 100644 --- a/example/src/components/apple-maps/index.tsx +++ b/example/src/components/apple-maps/index.tsx @@ -1,139 +1,139 @@ import { - AnimatePresence, - interpolate, - motion, - useMotionTemplate, - useScroll, - useTransform, -} from 'motion/react'; -import { useRef, useState } from 'react'; -import { FiChevronLeft, FiSearch } from 'react-icons/fi'; -import { Sheet, type SheetRef } from 'react-modal-sheet'; -import { Link } from 'react-router'; -import styled from 'styled-components'; -import bgImg from './map-bg.jpeg'; + AnimatePresence, + interpolate, + motion, + useMotionTemplate, + useScroll, + useTransform, +} from "motion/react"; +import { useRef, useState } from "react"; +import { FiChevronLeft, FiSearch } from "react-icons/fi"; +import { Sheet, type SheetRef } from "react-modal-sheet"; +import { Link } from "react-router"; +import styled from "styled-components"; +import bgImg from "./map-bg.jpeg"; const snapPoints = [100, 0.5, 1]; const initialSnap = 0; const lastSnap = snapPoints.length - 1; export function AppleMaps() { - const [sheetRef, setSheetRef] = useState(null); - const inputRef = useRef(null); - const scrollRef = useRef(null); - const [isOpen, setOpen] = useState(true); - const [inputValue, setInputValue] = useState(''); - const [snapPoint, setSnapPoint] = useState(initialSnap); - const close = () => setOpen(false); - const { scrollY } = useScroll({ container: scrollRef }); - const contentBorderColor = useMotionTemplate`rgba(255, 255, 255, ${useTransform(scrollY, [0, 40], [0, 0.1])})`; - - function handleSheetRef(ref: SheetRef | null) { - if (!sheetRef && ref) { - setSheetRef(ref); - } - } - - function handleInputFocus() { - if (snapPoint !== lastSnap) { - sheetRef?.snapTo(lastSnap); - } - } - - return ( - - - {snapPoint < lastSnap && ( - - - - Back - - - )} - - - - - - - - - - - - - setInputValue(e.target.value)} - onFocus={handleInputFocus} - /> - - - - - - state.currentSnap !== lastSnap} - scrollRef={scrollRef} - style={{ borderTopColor: contentBorderColor }} - > - {!!sheetRef && } - - - - {snapPoint === lastSnap && } - - - ); + const [sheetRef, setSheetRef] = useState(null); + const inputRef = useRef(null); + const scrollRef = useRef(null); + const [isOpen, setOpen] = useState(true); + const [inputValue, setInputValue] = useState(""); + const [snapPoint, setSnapPoint] = useState(initialSnap); + const close = () => setOpen(false); + const { scrollY } = useScroll({ container: scrollRef }); + const contentBorderColor = useMotionTemplate`rgba(255, 255, 255, ${useTransform(scrollY, [0, 40], [0, 0.1])})`; + + function handleSheetRef(ref: SheetRef | null) { + if (!sheetRef && ref) { + setSheetRef(ref); + } + } + + function handleInputFocus() { + if (snapPoint !== lastSnap) { + sheetRef?.snapTo(lastSnap); + } + } + + return ( + + + {snapPoint < lastSnap && ( + + + + Back + + + )} + + + + + + + + + + + + + setInputValue(e.target.value)} + onFocus={handleInputFocus} + /> + + + + + + state.currentSnap !== lastSnap} + scrollRef={scrollRef} + style={{ borderTopColor: contentBorderColor }} + > + {!!sheetRef && } + + + + {snapPoint === lastSnap && } + + + ); } function SheetSuggestions({ sheetRef }: { sheetRef: SheetRef }) { - const mix = interpolate([100, 150], [0, 1]); - - const contentOpacity = useTransform(() => { - return mix(sheetRef.yInverted.get()); - }); - - return ( - - Suggestions - - {places.map((place) => ( - - - {place.icon} - - - {place.name} - {place.address} - - - ))} - - - ); + const mix = interpolate([100, 150], [0, 1]); + + const contentOpacity = useTransform(() => { + return mix(sheetRef.yInverted.get()); + }); + + return ( + + Suggestions + + {places.map((place) => ( + + + {place.icon} + + + {place.name} + {place.address} + + + ))} + + + ); } const SheetContainer = styled(Sheet.Container)` @@ -310,109 +310,109 @@ const ResultAddress = styled.span` `; const places = [ - { - id: 1, - name: 'Helsinki Central Station', - address: 'Kaivokatu 1, 00100 Helsinki', - icon: '๐Ÿ“', - bgColor: '#ffe6e6', - }, - { - id: 2, - name: 'Senate Square', - address: 'Senaatintori, 00170 Helsinki', - icon: '๐Ÿ›๏ธ', - bgColor: '#f5f5f5', - }, - { - id: 3, - name: 'Suomenlinna', - address: '00190 Helsinki', - icon: '๐Ÿฐ', - bgColor: '#f4e6a1', - }, - { - id: 4, - name: 'Market Square', - address: 'Kauppatori, 00170 Helsinki', - icon: '๐Ÿช', - bgColor: '#ffe4d6', - }, - { - id: 5, - name: 'Temppeliaukio Church', - address: 'Lutherinkatu 3, 00100 Helsinki', - icon: 'โ›ช', - bgColor: '#e6d3c7', - }, - { - id: 6, - name: 'Kamppi Center', - address: 'Urho Kekkosen katu 1, 00100 Helsinki', - icon: '๐Ÿข', - bgColor: '#e1ecf4', - }, - { - id: 7, - name: 'Finnish National Opera', - address: 'Helsinginkatu 58, 00260 Helsinki', - icon: '๐ŸŽญ', - bgColor: '#f0e6f0', - }, - { - id: 8, - name: 'Ateneum Art Museum', - address: 'Kaivokatu 2, 00100 Helsinki', - icon: '๐Ÿ›๏ธ', - bgColor: '#f5f5f5', - }, - { - id: 9, - name: 'Esplanadi Park', - address: 'Pohjoisesplanadi, 00170 Helsinki', - icon: '๐ŸŒณ', - bgColor: '#e6f4e6', - }, - { - id: 10, - name: 'Hietaniemi Beach', - address: 'Hietaranta, 00100 Helsinki', - icon: '๐Ÿ–๏ธ', - bgColor: '#fdf4e6', - }, - { - id: 11, - name: 'Stockmann Helsinki Center', - address: 'Aleksanterinkatu 52, 00100 Helsinki', - icon: '๐Ÿช', - bgColor: '#ffe4d6', - }, - { - id: 12, - name: 'Kiasma Museum', - address: 'Mannerheiminaukio 2, 00100 Helsinki', - icon: '๐Ÿข', - bgColor: '#e1ecf4', - }, - { - id: 13, - name: 'Kaivopuisto Park', - address: 'Kaivopuisto, 00140 Helsinki', - icon: '๐ŸŒŠ', - bgColor: '#e6f3ff', - }, - { - id: 14, - name: 'Helsinki Cathedral', - address: 'Unioninkatu 29, 00170 Helsinki', - icon: '๐Ÿ›๏ธ', - bgColor: '#f5f5f5', - }, - { - id: 15, - name: 'Old Market Hall', - address: 'Etelรคranta 1, 00130 Helsinki', - icon: '๐Ÿบ', - bgColor: '#faf3e0', - }, + { + id: 1, + name: "Helsinki Central Station", + address: "Kaivokatu 1, 00100 Helsinki", + icon: "๐Ÿ“", + bgColor: "#ffe6e6", + }, + { + id: 2, + name: "Senate Square", + address: "Senaatintori, 00170 Helsinki", + icon: "๐Ÿ›๏ธ", + bgColor: "#f5f5f5", + }, + { + id: 3, + name: "Suomenlinna", + address: "00190 Helsinki", + icon: "๐Ÿฐ", + bgColor: "#f4e6a1", + }, + { + id: 4, + name: "Market Square", + address: "Kauppatori, 00170 Helsinki", + icon: "๐Ÿช", + bgColor: "#ffe4d6", + }, + { + id: 5, + name: "Temppeliaukio Church", + address: "Lutherinkatu 3, 00100 Helsinki", + icon: "โ›ช", + bgColor: "#e6d3c7", + }, + { + id: 6, + name: "Kamppi Center", + address: "Urho Kekkosen katu 1, 00100 Helsinki", + icon: "๐Ÿข", + bgColor: "#e1ecf4", + }, + { + id: 7, + name: "Finnish National Opera", + address: "Helsinginkatu 58, 00260 Helsinki", + icon: "๐ŸŽญ", + bgColor: "#f0e6f0", + }, + { + id: 8, + name: "Ateneum Art Museum", + address: "Kaivokatu 2, 00100 Helsinki", + icon: "๐Ÿ›๏ธ", + bgColor: "#f5f5f5", + }, + { + id: 9, + name: "Esplanadi Park", + address: "Pohjoisesplanadi, 00170 Helsinki", + icon: "๐ŸŒณ", + bgColor: "#e6f4e6", + }, + { + id: 10, + name: "Hietaniemi Beach", + address: "Hietaranta, 00100 Helsinki", + icon: "๐Ÿ–๏ธ", + bgColor: "#fdf4e6", + }, + { + id: 11, + name: "Stockmann Helsinki Center", + address: "Aleksanterinkatu 52, 00100 Helsinki", + icon: "๐Ÿช", + bgColor: "#ffe4d6", + }, + { + id: 12, + name: "Kiasma Museum", + address: "Mannerheiminaukio 2, 00100 Helsinki", + icon: "๐Ÿข", + bgColor: "#e1ecf4", + }, + { + id: 13, + name: "Kaivopuisto Park", + address: "Kaivopuisto, 00140 Helsinki", + icon: "๐ŸŒŠ", + bgColor: "#e6f3ff", + }, + { + id: 14, + name: "Helsinki Cathedral", + address: "Unioninkatu 29, 00170 Helsinki", + icon: "๐Ÿ›๏ธ", + bgColor: "#f5f5f5", + }, + { + id: 15, + name: "Old Market Hall", + address: "Etelรคranta 1, 00130 Helsinki", + icon: "๐Ÿบ", + bgColor: "#faf3e0", + }, ]; diff --git a/example/src/components/apple-music/Album.tsx b/example/src/components/apple-music/Album.tsx index 9cd608d..c013c0c 100644 --- a/example/src/components/apple-music/Album.tsx +++ b/example/src/components/apple-music/Album.tsx @@ -1,77 +1,77 @@ -import { styled } from 'styled-components'; -import { FaPlay, FaForward, FaRandom } from 'react-icons/fa'; -import { motion } from 'motion/react'; +import { styled } from "styled-components"; +import { FaPlay, FaForward, FaRandom } from "react-icons/fa"; +import { motion } from "motion/react"; -import { type Album as AlbumType } from './data'; -import { MoreButton } from './common'; +import type { Album as AlbumType } from "./data"; +import { MoreButton } from "./common"; export function Album({ - album, - currentSong, - isPlayerOpen, - onSongClick, - onMiniPlayerClick, + album, + currentSong, + isPlayerOpen, + onSongClick, + onMiniPlayerClick, }: { - album: AlbumType; - currentSong: string; - isPlayerOpen: boolean; - onSongClick: (song: string) => void; - onMiniPlayerClick: () => void; + album: AlbumType; + currentSong: string; + isPlayerOpen: boolean; + onSongClick: (song: string) => void; + onMiniPlayerClick: () => void; }) { - return ( - - -
    - - - - -
    - {album.name} - {album.artist} - - {album.genre} · {album.year} - -
    - -
    -
    - - - - - Play - - - - - Shuffle - - - - - {album.songs.map((song, index) => ( - onSongClick(song)}> - {index + 1} -
    {song}
    -
    - ))} -
    -
    - - {!isPlayerOpen && ( - - - - {currentSong} - -
    - - - - )} - - ); + return ( + + +
    + + + + +
    + {album.name} + {album.artist} + + {album.genre} · {album.year} + +
    + +
    +
    + + + + + Play + + + + + Shuffle + + + + + {album.songs.map((song, index) => ( + onSongClick(song)}> + {index + 1} +
    {song}
    +
    + ))} +
    +
    + + {!isPlayerOpen && ( + + + + {currentSong} + +
    + + + + )} + + ); } const Wrapper = styled.div` diff --git a/example/src/components/apple-music/Player.tsx b/example/src/components/apple-music/Player.tsx index 72b5e0f..e79a085 100644 --- a/example/src/components/apple-music/Player.tsx +++ b/example/src/components/apple-music/Player.tsx @@ -1,71 +1,71 @@ -import { styled } from 'styled-components'; +import { styled } from "styled-components"; import { - FaPlay, - FaForward, - FaBackward, - FaVolumeOff, - FaVolumeUp, - FaListUl, - FaPodcast, - FaFire, -} from 'react-icons/fa'; - -import { type Album as AlbumType } from './data'; -import { MoreButton } from './common'; + FaPlay, + FaForward, + FaBackward, + FaVolumeOff, + FaVolumeUp, + FaListUl, + FaPodcast, + FaFire, +} from "react-icons/fa"; + +import type { Album as AlbumType } from "./data"; +import { MoreButton } from "./common"; export function Player({ song, album }: { song: string; album: AlbumType }) { - return ( - - - - - - - - - - - {song} - {album.artist} - - - - - - - - 0.00 - -4.00 - - - - - console.log('Prev song')}> - - - console.log('Play / Pause')}> - - - console.log('Next song')}> - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + {song} + {album.artist} + + + + + + + + 0.00 + -4.00 + + + + + console.log("Prev song")}> + + + console.log("Play / Pause")}> + + + console.log("Next song")}> + + + + + + + + + + + + + + + + + + ); } const Wrapper = styled.div` diff --git a/example/src/components/apple-music/common.tsx b/example/src/components/apple-music/common.tsx index a9734cb..952df97 100644 --- a/example/src/components/apple-music/common.tsx +++ b/example/src/components/apple-music/common.tsx @@ -1,12 +1,12 @@ -import { styled } from 'styled-components'; -import { FaEllipsisH } from 'react-icons/fa'; +import { styled } from "styled-components"; +import { FaEllipsisH } from "react-icons/fa"; export function MoreButton() { - return ( - - - - ); + return ( + + + + ); } const AlbumMoreButton = styled.div` diff --git a/example/src/components/apple-music/data.ts b/example/src/components/apple-music/data.ts index 46a45b4..392eff6 100644 --- a/example/src/components/apple-music/data.ts +++ b/example/src/components/apple-music/data.ts @@ -1,40 +1,40 @@ export interface Album { - name: string; - year: string; - artist: string; - genre: string; - image: string; - songs: string[]; + name: string; + year: string; + artist: string; + genre: string; + image: string; + songs: string[]; } export const album: Album = { - name: 'Gamification Burn Rate', - year: '2020', - artist: 'Niche Market', - genre: 'Indie Techno', - image: 'https://picsum.photos/400', - songs: [ - 'Gamification investor seed money', - 'Gen-z iPad', - 'Bandwidth influencer', - 'Paradigm shift', - 'Buzz entrepreneur', - 'Android disruptive', - 'Marketing rockstar', - 'Focus', - 'Gen-z return', - 'Accelerator ownership', - 'Termsheet iteration incubator', - 'Pivot seed', - ], + name: "Gamification Burn Rate", + year: "2020", + artist: "Niche Market", + genre: "Indie Techno", + image: "https://picsum.photos/400", + songs: [ + "Gamification investor seed money", + "Gen-z iPad", + "Bandwidth influencer", + "Paradigm shift", + "Buzz entrepreneur", + "Android disruptive", + "Marketing rockstar", + "Focus", + "Gen-z return", + "Accelerator ownership", + "Termsheet iteration incubator", + "Pivot seed", + ], }; export const preloadImages = () => { - const link = document.createElement('link'); - link.rel = 'preload'; - link.as = 'image'; - link.href = album.image; - document.head.appendChild(link); + const link = document.createElement("link"); + link.rel = "preload"; + link.as = "image"; + link.href = album.image; + document.head.appendChild(link); }; // This is for better animation perf on Safari diff --git a/example/src/components/apple-music/index.tsx b/example/src/components/apple-music/index.tsx index f6ce7ec..33b2784 100644 --- a/example/src/components/apple-music/index.tsx +++ b/example/src/components/apple-music/index.tsx @@ -1,48 +1,48 @@ -import { useState } from 'react'; -import { Sheet } from 'react-modal-sheet'; -import { styled } from 'styled-components'; +import { useState } from "react"; +import { Sheet } from "react-modal-sheet"; +import { styled } from "styled-components"; -import { useMetaThemeColor } from '../hooks'; -import { Album } from './Album'; -import { Player } from './Player'; -import { album } from './data'; +import { useMetaThemeColor } from "../hooks"; +import { Album } from "./Album"; +import { Player } from "./Player"; +import { album } from "./data"; export function AppleMusic() { - const [isPlayerOpen, setPlayerOpen] = useState(false); - // biome-ignore lint/style/noNonNullAssertion: songs are static - const [currentSong, setCurrentSong] = useState(album.songs[0]!); - - const openPlayer = () => setPlayerOpen(true); - const closePlayer = () => setPlayerOpen(false); - - useMetaThemeColor({ when: isPlayerOpen, from: '#111', to: '#000' }); - useMetaThemeColor({ to: '#111' }); - - return ( - <> - - - - - - - - - - - - - ); + const [isPlayerOpen, setPlayerOpen] = useState(false); + // biome-ignore lint/style/noNonNullAssertion: songs are static + const [currentSong, setCurrentSong] = useState(album.songs[0]!); + + const openPlayer = () => setPlayerOpen(true); + const closePlayer = () => setPlayerOpen(false); + + useMetaThemeColor({ when: isPlayerOpen, from: "#111", to: "#000" }); + useMetaThemeColor({ to: "#111" }); + + return ( + <> + + + + + + + + + + + + + ); } const PlayerSheet = styled(Sheet)` diff --git a/example/src/components/common.tsx b/example/src/components/common.tsx index 1a72250..87790bc 100644 --- a/example/src/components/common.tsx +++ b/example/src/components/common.tsx @@ -1,22 +1,22 @@ -import { useRef } from 'react'; -import { type AriaButtonProps, useButton } from 'react-aria'; -import styled, { createGlobalStyle } from 'styled-components'; +import { useRef } from "react"; +import { type AriaButtonProps, useButton } from "react-aria"; +import styled, { createGlobalStyle } from "styled-components"; export function Button({ - children, - className, - ...rest + children, + className, + ...rest }: AriaButtonProps & { - className?: string; + className?: string; }) { - const buttonRef = useRef(null); - const { buttonProps } = useButton(rest, buttonRef); + const buttonRef = useRef(null); + const { buttonProps } = useButton(rest, buttonRef); - return ( - - {children} - - ); + return ( + + {children} + + ); } const ButtonBase = styled.button` diff --git a/example/src/components/hooks.tsx b/example/src/components/hooks.tsx index 2549925..91aff9a 100644 --- a/example/src/components/hooks.tsx +++ b/example/src/components/hooks.tsx @@ -1,82 +1,84 @@ -import { animate, useMotionValue } from 'motion/react'; -import { useEffect, useLayoutEffect, useState } from 'react'; +import { animate, useMotionValue } from "motion/react"; +import { useEffect, useLayoutEffect, useState } from "react"; export function useMetaThemeColor({ - when = true, - from, - to, + when = true, + from, + to, }: { - when?: boolean; - from?: string; - to: string; + when?: boolean; + from?: string; + to: string; }) { - useLayoutEffect(() => { - const meta = document.querySelector('meta[name="theme-color"]'); - if (!meta) return; + // biome-ignore lint/correctness/useExhaustiveDependencies: It was here before Biome 2 + useLayoutEffect(() => { + const meta = document.querySelector('meta[name="theme-color"]'); + if (!meta) return; - const current = from || (meta.getAttribute('content') as string); + const current = from || (meta.getAttribute("content") as string); - if (when) { - meta.setAttribute('content', to); + if (when) { + meta.setAttribute("content", to); - return () => { - meta.setAttribute('content', current); - }; - } - }, [when]); // eslint-disable-line react-hooks/exhaustive-deps + return () => { + meta.setAttribute("content", current); + }; + } + }, [when]); } export function useVirtualKeyboard() { - const [isKeyboardOpen, setKeyboardOpen] = useState(false); - const [keyboardHeight, setKeyboardHeight] = useState(0); - - useEffect(() => { - const visualViewport = window.visualViewport; - - if (visualViewport) { - const onResize = () => { - const focusedElement = document.activeElement as HTMLElement | null; - - // Bail if no element is focused as that also means no input is focused - if (!focusedElement) return; - - const isInputFocused = - focusedElement.tagName === 'INPUT' || - focusedElement.tagName === 'TEXTAREA'; - - // Virtual keyboard should only be visible if an input is focused - if (isInputFocused && visualViewport.height < window.innerHeight) { - setKeyboardOpen(true); - setKeyboardHeight(window.innerHeight - visualViewport.height); - } else if (isKeyboardOpen) { - // Reset keyboard height if it was open - setKeyboardOpen(false); - setKeyboardHeight(0); - } - }; - - visualViewport.addEventListener('resize', onResize); - - return () => { - visualViewport.removeEventListener('resize', onResize); - }; - } - }, [isKeyboardOpen]); - - return { keyboardHeight, isKeyboardOpen }; + const [isKeyboardOpen, setKeyboardOpen] = useState(false); + const [keyboardHeight, setKeyboardHeight] = useState(0); + + useEffect(() => { + const visualViewport = window.visualViewport; + + if (visualViewport) { + const onResize = () => { + const focusedElement = document.activeElement as HTMLElement | null; + + // Bail if no element is focused as that also means no input is focused + if (!focusedElement) return; + + const isInputFocused = + focusedElement.tagName === "INPUT" || + focusedElement.tagName === "TEXTAREA"; + + // Virtual keyboard should only be visible if an input is focused + if (isInputFocused && visualViewport.height < window.innerHeight) { + setKeyboardOpen(true); + setKeyboardHeight(window.innerHeight - visualViewport.height); + } else if (isKeyboardOpen) { + // Reset keyboard height if it was open + setKeyboardOpen(false); + setKeyboardHeight(0); + } + }; + + visualViewport.addEventListener("resize", onResize); + + return () => { + visualViewport.removeEventListener("resize", onResize); + }; + } + }, [isKeyboardOpen]); + + return { keyboardHeight, isKeyboardOpen }; } export function useAnimatedVirtualKeyboard() { - const { isKeyboardOpen, keyboardHeight } = useVirtualKeyboard(); - const animatedKeyboardHeight = useMotionValue(keyboardHeight); - - useEffect(() => { - if (isKeyboardOpen) { - animate(animatedKeyboardHeight, keyboardHeight); - } else { - animate(animatedKeyboardHeight, 0); - } - }, [isKeyboardOpen, keyboardHeight]); // eslint-disable-line react-hooks/exhaustive-deps - - return { keyboardHeight: animatedKeyboardHeight, isKeyboardOpen }; + const { isKeyboardOpen, keyboardHeight } = useVirtualKeyboard(); + const animatedKeyboardHeight = useMotionValue(keyboardHeight); + + // biome-ignore lint/correctness/useExhaustiveDependencies: It was here before Biome 2 + useEffect(() => { + if (isKeyboardOpen) { + animate(animatedKeyboardHeight, keyboardHeight); + } else { + animate(animatedKeyboardHeight, 0); + } + }, [isKeyboardOpen, keyboardHeight]); + + return { keyboardHeight: animatedKeyboardHeight, isKeyboardOpen }; } diff --git a/example/src/components/slack-message/NewMessageContent.tsx b/example/src/components/slack-message/NewMessageContent.tsx index 02735af..5d14f94 100644 --- a/example/src/components/slack-message/NewMessageContent.tsx +++ b/example/src/components/slack-message/NewMessageContent.tsx @@ -1,53 +1,53 @@ -import { type RefObject } from 'react'; -import { Sheet } from 'react-modal-sheet'; -import { styled } from 'styled-components'; +import type { RefObject } from "react"; +import { Sheet } from "react-modal-sheet"; +import { styled } from "styled-components"; const people = [ - 'john', - 'hannah', - 'trevor', - 'greg', - 'mary', - 'gigi', - 'kendal', - 'mark', - 'fiona', - 'herman', - 'juno', - 'beatrice', + "john", + "hannah", + "trevor", + "greg", + "mary", + "gigi", + "kendal", + "mark", + "fiona", + "herman", + "juno", + "beatrice", ].map((name, i) => ({ - id: i, - name, - image: (i: number) => `https://picsum.photos/${i}/200`, + id: i, + name, + image: (i: number) => `https://picsum.photos/${i}/200`, })); export function NewMessageContent({ - inputRef, + inputRef, }: { - inputRef: RefObject; + inputRef: RefObject; }) { - return ( - <> - - To: - - + return ( + <> + + To: + + - - {people.map(({ id, name, image }) => ( - - - {name} - - {name} - - ))} - - - ); + + {people.map(({ id, name, image }) => ( + + + {name} + + {name} + + ))} + + + ); } const Search = styled.label` @@ -110,7 +110,7 @@ const PersonImage = styled.img` `; const PersonName = styled.span<{ dimmed?: boolean }>` - color: ${(p) => (p.dimmed ? '#888' : '#fff')}; + color: ${(p) => (p.dimmed ? "#888" : "#fff")}; font-weight: ${(p) => (p.dimmed ? 400 : 600)}; `; @@ -118,6 +118,6 @@ const PersonStatus = styled.div<{ online?: boolean }>` width: 10px; height: 10px; border-radius: 50%; - border: 1px solid ${(p) => (p.online ? 'green' : '#888')}; - background-color: ${(p) => (p.online ? 'green' : 'transparent')}; + border: 1px solid ${(p) => (p.online ? "green" : "#888")}; + background-color: ${(p) => (p.online ? "green" : "transparent")}; `; diff --git a/example/src/components/slack-message/NewMessageHeader.tsx b/example/src/components/slack-message/NewMessageHeader.tsx index 245c342..700bcad 100644 --- a/example/src/components/slack-message/NewMessageHeader.tsx +++ b/example/src/components/slack-message/NewMessageHeader.tsx @@ -1,30 +1,30 @@ -import { useRef } from 'react'; -import { styled } from 'styled-components'; -import { FiX as CloseIcon } from 'react-icons/fi'; -import { useButton } from 'react-aria'; +import { useRef } from "react"; +import { styled } from "styled-components"; +import { FiX as CloseIcon } from "react-icons/fi"; +import { useButton } from "react-aria"; export function NewMessageHeader({ - sheetState, - titleProps, + sheetState, + titleProps, }: { - sheetState: any; - titleProps: any; + sheetState: any; + titleProps: any; }) { - const ref = useRef(null); - const closeButton = useButton( - { onPress: sheetState.close, 'aria-label': 'Close bottom sheet' }, - ref - ); // prettier-ignore + const ref = useRef(null); + const closeButton = useButton( + { onPress: sheetState.close, "aria-label": "Close bottom sheet" }, + ref, + ); // prettier-ignore - return ( - - - - + return ( + + + + - New Message - - ); + New Message + + ); } const Wrapper = styled.div` diff --git a/example/src/components/slack-message/index.tsx b/example/src/components/slack-message/index.tsx index 082ef81..c3e5f42 100644 --- a/example/src/components/slack-message/index.tsx +++ b/example/src/components/slack-message/index.tsx @@ -1,104 +1,104 @@ -import { useRef } from 'react'; -import { FiEdit as MessageIcon, FiSearch as SearchIcon } from 'react-icons/fi'; -import { Sheet } from 'react-modal-sheet'; -import { useOverlayTriggerState } from 'react-stately'; -import { styled } from 'styled-components'; +import { useRef } from "react"; +import { FiEdit as MessageIcon, FiSearch as SearchIcon } from "react-icons/fi"; +import { Sheet } from "react-modal-sheet"; +import { useOverlayTriggerState } from "react-stately"; +import { styled } from "styled-components"; import { - FocusScope, - OverlayProvider, - useButton, - useDialog, - useModal, - useOverlay, -} from 'react-aria'; - -import { ScrollView } from '../common'; -import { useMetaThemeColor } from '../hooks'; -import { NewMessageContent } from './NewMessageContent'; -import { NewMessageHeader } from './NewMessageHeader'; + FocusScope, + OverlayProvider, + useButton, + useDialog, + useModal, + useOverlay, +} from "react-aria"; + +import { ScrollView } from "../common"; +import { useMetaThemeColor } from "../hooks"; +import { NewMessageContent } from "./NewMessageContent"; +import { NewMessageHeader } from "./NewMessageHeader"; // A11y added with React Aria: https://react-spectrum.adobe.com/react-aria/useDialog.html export function SlackMessage() { - const sheetState = useOverlayTriggerState({}); - const inputRef = useRef(null); - const openButtonRef = useRef(null); - const openButton = useButton({ onPress: sheetState.open }, openButtonRef); - const focusInput = () => inputRef.current?.focus(); - - useMetaThemeColor({ when: sheetState.isOpen, from: '#111', to: '#000' }); - useMetaThemeColor({ to: '#111' }); - - return ( - - - - - A11y Workspace - - - - - - - - - - - - - - - - - - - ); + const sheetState = useOverlayTriggerState({}); + const inputRef = useRef(null); + const openButtonRef = useRef(null); + const openButton = useButton({ onPress: sheetState.open }, openButtonRef); + const focusInput = () => inputRef.current?.focus(); + + useMetaThemeColor({ when: sheetState.isOpen, from: "#111", to: "#000" }); + useMetaThemeColor({ to: "#111" }); + + return ( + + + + + A11y Workspace + + + + + + + + + + + + + + + + + + + ); } const MessageSheetComp = ({ - sheetState, - inputRef, + sheetState, + inputRef, }: { - sheetState: any; - inputRef: any; + sheetState: any; + inputRef: any; }) => { - const ref = useRef(null); - const dialog = useDialog({}, ref); - const overlay = useOverlay( - { onClose: sheetState.close, isOpen: true, isDismissable: true }, - ref - ); - - useModal(); - - // HACK: some props from React Aria need to be cast to `any` - // since they conflict with the Motion props - return ( - <> - - - - - - - - - - ); + const ref = useRef(null); + const dialog = useDialog({}, ref); + const overlay = useOverlay( + { onClose: sheetState.close, isOpen: true, isDismissable: true }, + ref, + ); + + useModal(); + + // HACK: some props from React Aria need to be cast to `any` + // since they conflict with the Motion props + return ( + <> + + + + + + + + + + ); }; const Wrapper = styled.div` diff --git a/example/src/index.css b/example/src/index.css index a337ca3..627a895 100644 --- a/example/src/index.css +++ b/example/src/index.css @@ -1,80 +1,80 @@ :root { - --vh: 1vh; + --vh: 1vh; } /* Support the new `dvh` unit so that dynamically shrinking iOS Safari UI works */ @supports (height: 1dvh) { - :root { - --vh: 1dvh; - } + :root { + --vh: 1dvh; + } } /* However when the app is installed as PWA use the `vh` unit to avoid weird layout issues */ @media all and (display-mode: standalone) { - :root { - --vh: 1vh; - } + :root { + --vh: 1vh; + } } html { - background-color: #fff; - height: 100%; + background-color: #fff; + height: 100%; } body { - margin: 0; - font-size: 16px; - font-family: "Inter", sans-serif; - font-optical-sizing: auto; - font-weight: 400; - font-style: normal; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-overflow-scrolling: touch; - -webkit-tap-highlight-color: transparent; - -webkit-touch-callout: none; + margin: 0; + font-size: 16px; + font-family: "Inter", sans-serif; + font-optical-sizing: auto; + font-weight: 400; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-overflow-scrolling: touch; + -webkit-tap-highlight-color: transparent; + -webkit-touch-callout: none; } #root { - display: flex; - flex-direction: column; - overflow: hidden; - background-color: #000; - height: 100%; - min-height: calc(100 * var(--vh)); + display: flex; + flex-direction: column; + overflow: hidden; + background-color: #000; + height: 100%; + min-height: calc(100 * var(--vh)); } button, input, textarea { - font-size: 16px; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-size: 16px; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; } button { - border: none; - background: none; - margin: 0; - padding: 0; + border: none; + background: none; + margin: 0; + padding: 0; } * { - box-sizing: border-box; + box-sizing: border-box; } ul { - list-style: none; - padding: 0; - margin: 0; + list-style: none; + padding: 0; + margin: 0; } li { - margin: 0; + margin: 0; } a { - text-decoration: none; - color: inherit; + text-decoration: none; + color: inherit; } diff --git a/example/src/index.tsx b/example/src/index.tsx index 9d22f3f..e3e37c4 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -1,27 +1,27 @@ -import './index.css'; +import "./index.css"; -import { StrictMode } from 'react'; -import { createRoot } from 'react-dom/client'; -import { HashRouter } from 'react-router'; -import { OverlayProvider } from 'react-aria'; +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import { HashRouter } from "react-router"; +import { OverlayProvider } from "react-aria"; -import { App } from './components/App'; +import { App } from "./components/App"; // biome-ignore lint/style/noNonNullAssertion: root is always defined -const root = createRoot(document.getElementById('root')!); +const root = createRoot(document.getElementById("root")!); function Root() { - return ( - - - - - - ); + return ( + + + + + + ); } root.render( - - - + + + , ); diff --git a/package-lock.json b/package-lock.json index 635516b..de76d6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ }, "devDependencies": { "@arethetypeswrong/cli": "0.17.4", - "@biomejs/biome": "1.9.4", + "@biomejs/biome": "2.2.3", "@types/react": "19.1.2", "@types/react-dom": "19.1.2", "@vitejs/plugin-react": "4.4.1", @@ -429,11 +429,10 @@ } }, "node_modules/@biomejs/biome": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", - "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.2.3.tgz", + "integrity": "sha512-9w0uMTvPrIdvUrxazZ42Ib7t8Y2yoGLKLdNne93RLICmaHw7mcLv4PPb5LvZLJF3141gQHiCColOh/v6VWlWmg==", "dev": true, - "hasInstallScript": true, "license": "MIT OR Apache-2.0", "bin": { "biome": "bin/biome" @@ -446,20 +445,20 @@ "url": "https://opencollective.com/biome" }, "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "1.9.4", - "@biomejs/cli-darwin-x64": "1.9.4", - "@biomejs/cli-linux-arm64": "1.9.4", - "@biomejs/cli-linux-arm64-musl": "1.9.4", - "@biomejs/cli-linux-x64": "1.9.4", - "@biomejs/cli-linux-x64-musl": "1.9.4", - "@biomejs/cli-win32-arm64": "1.9.4", - "@biomejs/cli-win32-x64": "1.9.4" + "@biomejs/cli-darwin-arm64": "2.2.3", + "@biomejs/cli-darwin-x64": "2.2.3", + "@biomejs/cli-linux-arm64": "2.2.3", + "@biomejs/cli-linux-arm64-musl": "2.2.3", + "@biomejs/cli-linux-x64": "2.2.3", + "@biomejs/cli-linux-x64-musl": "2.2.3", + "@biomejs/cli-win32-arm64": "2.2.3", + "@biomejs/cli-win32-x64": "2.2.3" } }, "node_modules/@biomejs/cli-darwin-arm64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", - "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.3.tgz", + "integrity": "sha512-OrqQVBpadB5eqzinXN4+Q6honBz+tTlKVCsbEuEpljK8ASSItzIRZUA02mTikl3H/1nO2BMPFiJ0nkEZNy3B1w==", "cpu": [ "arm64" ], @@ -474,9 +473,9 @@ } }, "node_modules/@biomejs/cli-darwin-x64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", - "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.3.tgz", + "integrity": "sha512-OCdBpb1TmyfsTgBAM1kPMXyYKTohQ48WpiN9tkt9xvU6gKVKHY4oVwteBebiOqyfyzCNaSiuKIPjmHjUZ2ZNMg==", "cpu": [ "x64" ], @@ -491,9 +490,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", - "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.3.tgz", + "integrity": "sha512-g/Uta2DqYpECxG+vUmTAmUKlVhnGEcY7DXWgKP8ruLRa8Si1QHsWknPY3B/wCo0KgYiFIOAZ9hjsHfNb9L85+g==", "cpu": [ "arm64" ], @@ -508,9 +507,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", - "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.3.tgz", + "integrity": "sha512-q3w9jJ6JFPZPeqyvwwPeaiS/6NEszZ+pXKF+IczNo8Xj6fsii45a4gEEicKyKIytalV+s829ACZujQlXAiVLBQ==", "cpu": [ "arm64" ], @@ -525,9 +524,9 @@ } }, "node_modules/@biomejs/cli-linux-x64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", - "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.3.tgz", + "integrity": "sha512-LEtyYL1fJsvw35CxrbQ0gZoxOG3oZsAjzfRdvRBRHxOpQ91Q5doRVjvWW/wepgSdgk5hlaNzfeqpyGmfSD0Eyw==", "cpu": [ "x64" ], @@ -542,9 +541,9 @@ } }, "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", - "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.3.tgz", + "integrity": "sha512-y76Dn4vkP1sMRGPFlNc+OTETBhGPJ90jY3il6jAfur8XWrYBQV3swZ1Jo0R2g+JpOeeoA0cOwM7mJG6svDz79w==", "cpu": [ "x64" ], @@ -559,9 +558,9 @@ } }, "node_modules/@biomejs/cli-win32-arm64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", - "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.3.tgz", + "integrity": "sha512-Ms9zFYzjcJK7LV+AOMYnjN3pV3xL8Prxf9aWdDVL74onLn5kcvZ1ZMQswE5XHtnd/r/0bnUd928Rpbs14BzVmA==", "cpu": [ "arm64" ], @@ -576,9 +575,9 @@ } }, "node_modules/@biomejs/cli-win32-x64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", - "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.3.tgz", + "integrity": "sha512-gvCpewE7mBwBIpqk1YrUqNR4mCiyJm6UI3YWQQXkedSSEwzRdodRpaKhbdbHw1/hmTWOVXQ+Eih5Qctf4TCVOQ==", "cpu": [ "x64" ], diff --git a/package.json b/package.json index 7aee716..89de99b 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ }, "devDependencies": { "@arethetypeswrong/cli": "0.17.4", - "@biomejs/biome": "1.9.4", + "@biomejs/biome": "2.2.3", "@types/react": "19.1.2", "@types/react-dom": "19.1.2", "@vitejs/plugin-react": "4.4.1",