Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use react compiler #1434

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading