Skip to content

Commit

Permalink
Improve compatibility for browsers that do not support `ResizeObserve…
Browse files Browse the repository at this point in the history
…r` or `:where` selector (#5265)

* Add fallback for default styles when `:where` selector is not supported

* Add polyfill for ResizeObserver

* Add changeset
  • Loading branch information
kylemclean authored Jan 30, 2023
1 parent 2ab56c3 commit 3cf51f4
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/witty-tips-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'slate-react': patch
---

Improve compatibility for browsers that do not support ResizeObserver or :where selector
1 change: 1 addition & 0 deletions packages/slate-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"dist/"
],
"dependencies": {
"@juggle/resize-observer": "^3.4.0",
"@types/is-hotkey": "^0.1.1",
"@types/lodash": "^4.14.149",
"direction": "^1.0.3",
Expand Down
11 changes: 6 additions & 5 deletions packages/slate-react/src/components/editable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import {
NODE_TO_ELEMENT,
PLACEHOLDER_SYMBOL,
} from '../utils/weak-maps'
import { whereIfSupported } from '../utils/where-if-supported'
import { RestoreDOM } from './restore-dom/restore-dom'
import { useAndroidInputManager } from '../hooks/android-input-manager/use-android-input-manager'
import { useTrackUserInput } from '../hooks/use-track-user-input'
Expand Down Expand Up @@ -812,18 +813,18 @@ export const Editable = (props: EditableProps) => {
// Set global default styles for editors.
const defaultStylesElement = document.createElement('style')
defaultStylesElement.setAttribute('data-slate-default-styles', 'true')
defaultStylesElement.innerHTML =
// :where is used to give these rules lower specificity so user stylesheets can override them.
`:where([data-slate-editor]) {` +
const selector = '[data-slate-editor]'
const defaultStyles =
// Allow positioning relative to the editable element.
`position: relative;` +
// Prevent the default outline styles.
`outline: none;` +
// Preserve adjacent whitespace and new lines.
`white-space: pre-wrap;` +
// Allow words to break if they are too long.
`word-wrap: break-word;` +
`}`
`word-wrap: break-word;`
defaultStylesElement.innerHTML = whereIfSupported(selector, defaultStyles)

document.head.appendChild(defaultStylesElement)
}

Expand Down
8 changes: 6 additions & 2 deletions packages/slate-react/src/components/leaf.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useRef, useEffect } from 'react'
import { Element, Text } from 'slate'
import { ResizeObserver as ResizeObserverPolyfill } from '@juggle/resize-observer'
import String from './string'
import {
PLACEHOLDER_SYMBOL,
Expand All @@ -8,6 +9,7 @@ import {
} from '../utils/weak-maps'
import { RenderLeafProps, RenderPlaceholderProps } from './editable'
import { useSlateStatic } from '../hooks/use-slate-static'
import { whereIfSupported } from '../utils/where-if-supported'

/**
* Individual leaves in a text node with unique formatting.
Expand Down Expand Up @@ -59,12 +61,14 @@ const Leaf = (props: {
placeholderResizeObserver.current.observe(placeholderEl)
} else if (placeholderEl) {
// Create a new observer and observe the placeholder element.
const ResizeObserver = window.ResizeObserver || ResizeObserverPolyfill
placeholderResizeObserver.current = new ResizeObserver(([{ target }]) => {
const styleElement = EDITOR_TO_STYLE_ELEMENT.get(editor)
if (styleElement) {
// Make the min-height the height of the placeholder.
const minHeight = `${target.clientHeight}px`
styleElement.innerHTML = `:where([data-slate-editor-id="${editor.id}"]) { min-height: ${minHeight}; }`
const selector = `[data-slate-editor-id="${editor.id}"]`
const styles = `min-height: ${target.clientHeight}px;`
styleElement.innerHTML = whereIfSupported(selector, styles)
}
})

Expand Down
22 changes: 22 additions & 0 deletions packages/slate-react/src/utils/where-if-supported.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Returns a set of rules that use the `:where` selector if it is supported,
* otherwise it falls back to the provided selector on its own.
*
* The `:where` selector is used to give a selector a lower specificity,
* allowing the rule to be overridden by a user-defined stylesheet.
*
* Older browsers do not support the `:where` selector.
* If it is not supported, the selector will be used without `:where`,
* which means that the rule will have a higher specificity and a user-defined
* stylesheet will not be able to override it easily.
*/
export function whereIfSupported(selector: string, styles: string): string {
return (
`@supports (selector(:where(${selector}))) {` +
`:where(${selector}) { ${styles} }` +
`}` +
`@supports not (selector(:where(${selector}))) {` +
`${selector} { ${styles} }` +
`}`
)
}
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2268,6 +2268,13 @@ __metadata:
languageName: node
linkType: hard

"@juggle/resize-observer@npm:^3.4.0":
version: 3.4.0
resolution: "@juggle/resize-observer@npm:3.4.0"
checksum: 2505028c05cc2e17639fcad06218b1c4b60f932a4ebb4b41ab546ef8c157031ae377e3f560903801f6d01706dbefd4943b6c4704bf19ed86dfa1c62f1473a570
languageName: node
linkType: hard

"@lerna/add@npm:3.21.0":
version: 3.21.0
resolution: "@lerna/add@npm:3.21.0"
Expand Down Expand Up @@ -13904,6 +13911,7 @@ resolve@^2.0.0-next.3:
resolution: "slate-react@workspace:packages/slate-react"
dependencies:
"@babel/runtime": ^7.7.4
"@juggle/resize-observer": ^3.4.0
"@types/is-hotkey": ^0.1.1
"@types/jest": ^27.4.1
"@types/jsdom": ^16.2.14
Expand Down

0 comments on commit 3cf51f4

Please sign in to comment.