Skip to content

Commit

Permalink
feat: use react compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan committed Nov 11, 2024
1 parent d200eba commit 01d5edb
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 269 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ module.exports = {
'react/prop-types': 'off',
'react-hooks/exhaustive-deps': 'error', // Checks effect dependencies
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
'react-compiler/react-compiler': ['warn', {__unstable_donotuse_reportAllBailouts: true}], // Set to error once existing warnings are fixed
'react-compiler/react-compiler': ['error', {__unstable_donotuse_reportAllBailouts: true}],
'react/no-unescaped-entities': 'off',
'no-restricted-imports': [
'error',
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- run: pnpm install
- name: Register Problem Matcher for ESLint that handles -f compact and shows warnings and errors inline on PRs
run: echo "::add-matcher::.github/eslint-compact.json"
- run: "pnpm lint -f compact --rule 'no-warning-comments: [off]' --max-warnings 33"
- run: "pnpm lint -f compact --rule 'no-warning-comments: [off]' --max-warnings 0"

test:
needs: [build]
Expand Down
20 changes: 19 additions & 1 deletion package.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,23 @@ export default defineConfig({
},
tsconfig: 'tsconfig.dist.json',
babel: {reactCompiler: true},
reactCompilerOptions: {target: '18'},
reactCompilerOptions: {
target: '18',
logger: {
logEvent(filename, event) {
/* eslint-disable no-console */
if (event.kind === 'CompileError') {
console.group(`[${filename}] ${event.kind}`)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const {reason, description, severity, loc, suggestions} = event.detail as any

console.error(`[${severity}] ${reason}`)
console.log(`${filename}:${loc.start?.line}:${loc.start?.column} ${description}`)
console.log(suggestions)

console.groupEnd()
}
},
},
},
})
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sanity/ui",
"version": "2.8.23",
"version": "2.9.0-canary.6",
"keywords": [
"sanity",
"ui",
Expand Down
82 changes: 35 additions & 47 deletions src/core/components/breadcrumbs/breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
import {
Children,
forwardRef,
Fragment,
isValidElement,
useCallback,
useMemo,
useRef,
useState,
} from 'react'
import {Children, forwardRef, Fragment, isValidElement, useCallback, useRef, useState} from 'react'
import {useArrayProp, useClickOutsideEvent} from '../../hooks'
import {Box, Popover, Stack, Text} from '../../primitives'
import {ExpandButton, Root} from './breadcrumbs.styles'
Expand Down Expand Up @@ -39,46 +30,43 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs(

useClickOutsideEvent(collapse, () => [expandElementRef.current, popoverElementRef.current])

const rawItems = useMemo(() => Children.toArray(children).filter(isValidElement), [children])
const rawItems = Children.toArray(children).filter(isValidElement)

const items = useMemo(() => {
const len = rawItems.length
let items = rawItems
const len = rawItems.length

if (maxLength && len > maxLength) {
const beforeLength = Math.ceil(maxLength / 2)
const afterLength = Math.floor(maxLength / 2)
if (maxLength && rawItems.length > maxLength) {
const beforeLength = Math.ceil(maxLength / 2)
const afterLength = Math.floor(maxLength / 2)

return [
...rawItems.slice(0, beforeLength - 1),
<Popover
constrainSize
content={
<Stack as="ol" overflow="auto" padding={space} space={space}>
{rawItems.slice(beforeLength - 1, len - afterLength)}
</Stack>
}
key="button"
open={open}
placement="top"
portal
ref={popoverElementRef}
>
<ExpandButton
fontSize={1}
mode="bleed"
onClick={open ? collapse : expand}
padding={1}
ref={expandElementRef}
selected={open}
text="…"
/>
</Popover>,
...rawItems.slice(len - afterLength),
]
}

return rawItems
}, [collapse, expand, maxLength, open, rawItems, space])
items = [
...rawItems.slice(0, beforeLength - 1),
<Popover
constrainSize
content={
<Stack as="ol" overflow="auto" padding={space} space={space}>
{rawItems.slice(beforeLength - 1, len - afterLength)}
</Stack>
}
key="button"
open={open}
placement="top"
portal
ref={popoverElementRef}
>
<ExpandButton
fontSize={1}
mode="bleed"
onClick={open ? collapse : expand}
padding={1}
ref={expandElementRef}
selected={open}
text="…"
/>
</Popover>,
...rawItems.slice(len - afterLength),
]
}

return (
<Root data-ui="Breadcrumbs" {...restProps} ref={ref}>
Expand Down
39 changes: 18 additions & 21 deletions src/core/components/menu/useMenuController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,28 @@ export function useMenuController(props: {
activeIndexRef.current = nextActiveIndex
}, [])

const mount = useCallback(
(element: HTMLElement | null, selected?: boolean): (() => void) => {
if (!element) return () => undefined
const mount = (element: HTMLElement | null, selected?: boolean): (() => void) => {
if (!element) return () => undefined

if (elementsRef.current.indexOf(element) === -1) {
elementsRef.current.push(element)
_sortElements(rootElementRef.current, elementsRef.current)
}
if (elementsRef.current.indexOf(element) === -1) {
elementsRef.current.push(element)
_sortElements(rootElementRef.current, elementsRef.current)
}

if (selected) {
const selectedIndex = elementsRef.current.indexOf(element)
if (selected) {
const selectedIndex = elementsRef.current.indexOf(element)

setActiveIndex(selectedIndex)
}
setActiveIndex(selectedIndex)
}

return () => {
const idx = elementsRef.current.indexOf(element)
return () => {
const idx = elementsRef.current.indexOf(element)

if (idx > -1) {
elementsRef.current.splice(idx, 1)
}
if (idx > -1) {
elementsRef.current.splice(idx, 1)
}
},
[rootElementRef, setActiveIndex],
)
}
}

const handleKeyDown = useCallback(
(event: React.KeyboardEvent<HTMLDivElement>) => {
Expand Down Expand Up @@ -170,15 +167,15 @@ export function useMenuController(props: {
[setActiveIndex],
)

const handleItemMouseLeave = useCallback(() => {
const handleItemMouseLeave = () => {
// Set the active index to -2 to deactivate all menu items
// when the user moves the mouse away from the menu item.
// We avoid using -1 because it would focus the first menu item,
// which would be incorrect when the user hovers over a gap
// between two menu items or a menu divider.
setActiveIndex(-2)
rootElementRef.current?.focus()
}, [rootElementRef, setActiveIndex])
}

// Set focus on the currently active element
useEffect(() => {
Expand Down
33 changes: 18 additions & 15 deletions src/core/components/tree/treeItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ToggleArrowRightIcon} from '@sanity/icons'
import {ThemeFontWeightKey} from '@sanity/ui/theme'
import {memo, useCallback, useEffect, useId, useMemo, useRef} from 'react'
import {memo, useCallback, useEffect, useId, useMemo, useRef, useState} from 'react'
import {styled} from 'styled-components'
import {Box, BoxProps, Flex, Text} from '../../primitives'
import {
Expand Down Expand Up @@ -64,18 +64,21 @@ export const TreeItem = memo(function TreeItem(
weight,
...restProps
} = props
const rootRef = useRef<HTMLLIElement | null>(null)
const [rootElement, setRootElement] = useState<HTMLLIElement | null>(null)
const treeitemRef = useRef<HTMLDivElement | null>(null)
const tree = useTree()
const {path, registerItem, setExpanded, setFocusedElement} = tree
const _id = useId()
const id = idProp || _id
const itemPath = useMemo(() => path.concat([id || '']), [id, path])
const itemKey = itemPath.join('/')
const [itemPath, itemKey] = useMemo(() => {
const result = path.concat([id || ''])

return [result, result.join('/')]
}, [id, path])
const itemState = tree.state[itemKey]
const focused = tree.focusedElement === rootRef.current
const focused = tree.focusedElement === rootElement
const expanded = itemState?.expanded === undefined ? expandedProp : itemState?.expanded || false
const tabIndex = tree.focusedElement && tree.focusedElement === rootRef.current ? 0 : -1
const tabIndex = tree.focusedElement && tree.focusedElement === rootElement ? 0 : -1
const contextValue = useMemo(
() => ({...tree, level: tree.level + 1, path: itemPath}),
[itemPath, tree],
Expand All @@ -94,28 +97,28 @@ export const TreeItem = memo(function TreeItem(
) {
event.stopPropagation()
setExpanded(itemKey, !expanded)
setFocusedElement(rootRef.current)
setFocusedElement(rootElement)
}
},
[expanded, itemKey, onClick, setExpanded, setFocusedElement],
[expanded, itemKey, onClick, rootElement, setExpanded, setFocusedElement],
)

const handleKeyDown = useCallback(
(event: React.KeyboardEvent<HTMLElement>) => {
if (focused && event.key === 'Enter') {
const el = treeitemRef.current || rootRef.current
const el = treeitemRef.current || rootElement

el?.click()
}
},
[focused],
[focused, rootElement],
)

useEffect(() => {
if (!rootRef.current) return
if (!rootElement) return

return registerItem(rootRef.current, itemPath.join('/'), expanded, selected)
}, [expanded, itemPath, registerItem, selected])
return registerItem(rootElement, itemPath.join('/'), expanded, selected)
}, [expanded, itemPath, registerItem, rootElement, selected])

const content = (
<Flex padding={padding}>
Expand Down Expand Up @@ -154,7 +157,7 @@ export const TreeItem = memo(function TreeItem(
data-ui="TreeItem"
{...restProps}
onClick={handleClick}
ref={rootRef}
ref={setRootElement}
role="none"
>
<TreeItemBox
Expand Down Expand Up @@ -187,7 +190,7 @@ export const TreeItem = memo(function TreeItem(
aria-expanded={expanded}
onClick={handleClick}
onKeyDown={handleKeyDown}
ref={rootRef}
ref={setRootElement}
role="treeitem"
tabIndex={tabIndex}
>
Expand Down
34 changes: 12 additions & 22 deletions src/core/hooks/useMatchMedia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,24 @@ export function useMatchMedia(
mediaQueryString: `(${string})`,
getServerSnapshot?: () => boolean,
): boolean {
/**
* `subscribe` and `getSnapshot` are only called on the client and both need access to the same `matchMedia` instance
* we don't want to eagerly instantiate it to ensure it's only created when actually used
*/
const cachedMatchMedia = useMemo(
() => (typeof window === 'undefined' ? null : window.matchMedia(mediaQueryString)),
[mediaQueryString],
)
const {subscribe, getSnapshot} = useMemo(() => {
/**
* `subscribe` and `getSnapshot` are only called on the client and both need access to the same `matchMedia` instance
* we don't want to eagerly instantiate it to ensure it's only created when actually used
*/
let MEDIA_QUERY_CACHE: MediaQueryList | undefined

const getMatchMedia = (): MediaQueryList => {
if (!MEDIA_QUERY_CACHE) {
// As this function is only called during `subscribe` and `getSnapshot`, we can assume that the
// the `window` global is available and we're in a browser environment
MEDIA_QUERY_CACHE = window.matchMedia(mediaQueryString)
}

return MEDIA_QUERY_CACHE
}

return {
subscribe: (onStoreChange: () => void): (() => void) => {
const matchMedia = getMatchMedia()

matchMedia.addEventListener('change', onStoreChange)
cachedMatchMedia!.addEventListener('change', onStoreChange)

return () => matchMedia.removeEventListener('change', onStoreChange)
return () => cachedMatchMedia!.removeEventListener('change', onStoreChange)
},
getSnapshot: () => getMatchMedia().matches,
getSnapshot: () => cachedMatchMedia!.matches,
}
}, [mediaQueryString])
}, [cachedMatchMedia])

useDebugValue(mediaQueryString)

Expand Down
Loading

0 comments on commit 01d5edb

Please sign in to comment.