[improvement] rename onEvent to onUiEvent (#1358)

This PR:
- renames `onEvent` to `onUiEvent`
- adds docs for `onUiEvent` to the docs site
- splits the `EventsExample` into `UiEventsExample` and
`StoreEventsExample`

### Change Type

- [x] `major` — Breaking Change

### Release Notes

- [docs] Adds docs for ui events
- [tldraw] Renames `onEvent` to `onUiEvent`
This commit is contained in:
Steve Ruiz 2023-05-12 10:05:56 +01:00 committed by GitHub
parent 8b6b244194
commit 9ccd0f480f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 84 additions and 19 deletions

View file

@ -15,6 +15,24 @@ keywords:
- styles
---
Coming soon.
## Events
The `<Tldraw>` component has a prop, `onUiEvent`, that the user interface will call when certain events occur.
```tsx
function Example() {
function handleEvent(name, data) {
// do something with the event
}
return (
<Tldraw onUiEvent={handleEvent}/>
)
}
```
The `onUiEvent` callback is called with the name of the event as a string and an object with information about the event's source (e.g. `menu` or `context-menu`) and possibly other data specific to each event, such as the direction in an `align-shapes` event.
Note that `onUiEvent` is only called when interacting with the user interface. It is not called when running commands manually against the app, e.g. `app.alignShapes()` will not call `onUiEvent`.
See the [tldraw repository](https://github.com/tldraw/tldraw) for an example of how to customize tldraw's user interface.

View file

@ -0,0 +1,41 @@
import { TLUiEventHandler, Tldraw } from '@tldraw/tldraw'
import '@tldraw/tldraw/editor.css'
import '@tldraw/tldraw/ui.css'
import { useCallback, useState } from 'react'
export default function UiEventsExample() {
const [uiEvents, setUiEvents] = useState<string[]>([])
const handleUiEvent = useCallback<TLUiEventHandler>((name, data) => {
setUiEvents((events) => [`${name} ${JSON.stringify(data)}`, ...events])
}, [])
return (
<div style={{ display: 'flex' }}>
<div style={{ width: '60vw', height: '100vh' }}>
<Tldraw autoFocus onUiEvent={handleUiEvent} />
</div>
<div>
<div
style={{
width: '40vw',
height: '100vh',
padding: 8,
background: '#eee',
border: 'none',
fontFamily: 'monospace',
fontSize: 12,
borderLeft: 'solid 2px #333',
display: 'flex',
flexDirection: 'column-reverse',
overflow: 'auto',
}}
>
{uiEvents.map((t, i) => (
<div key={i}>{t}</div>
))}
</div>
</div>
</div>
)
}

View file

@ -1,27 +1,22 @@
import { App, TLEventMapHandler, Tldraw } from '@tldraw/tldraw'
import '@tldraw/tldraw/editor.css'
import '@tldraw/tldraw/ui.css'
import { TLUiEventHandler } from '@tldraw/ui/src/lib/hooks/useEventsProvider'
import { useCallback, useEffect, useState } from 'react'
export default function Example() {
export default function StoreEventsExample() {
const [app, setApp] = useState<App>()
const setAppToState = useCallback((app: App) => {
setApp(app)
}, [])
const [uiEvents, setUiEvents] = useState<string[]>([])
const handleEvent = useCallback<TLUiEventHandler>((name, data) => {
setUiEvents((events) => [`${name} ${JSON.stringify(data)}`, ...events])
}, [])
const [storeEvents, setStoreEvents] = useState<string[]>([])
useEffect(() => {
if (!app) return
function logChangeEvent(eventName: string) {
setUiEvents((events) => [eventName, ...events])
setStoreEvents((events) => [eventName, ...events])
}
// This is the fire hose, it will be called at the end of every transaction
@ -64,7 +59,7 @@ export default function Example() {
return (
<div style={{ display: 'flex' }}>
<div style={{ width: '60vw', height: '100vh' }}>
<Tldraw autoFocus onMount={setAppToState} onEvent={handleEvent} />
<Tldraw autoFocus onMount={setAppToState} />
</div>
<div>
<div
@ -82,7 +77,7 @@ export default function Example() {
overflow: 'auto',
}}
>
{uiEvents.map((t, i) => (
{storeEvents.map((t, i) => (
<div key={i}>{t}</div>
))}
</div>

View file

@ -11,7 +11,8 @@ import { RouterProvider, createBrowserRouter } from 'react-router-dom'
import ExampleBasic from './1-basic/BasicExample'
import CustomComponentsExample from './10-custom-components/CustomComponentsExample'
import UserPresenceExample from './11-user-presence/UserPresenceExample'
import EventsExample from './12-events/EventsExample'
import UiEventsExample from './12-ui-events/UiEventsExample'
import StoreEventsExample from './13-store/StoreEventsExample'
import ExampleApi from './2-api/APIExample'
import CustomConfigExample from './3-custom-config/CustomConfigExample'
import CustomUiExample from './4-custom-ui/CustomUiExample'
@ -73,8 +74,12 @@ export const allExamples: Example[] = [
element: <CustomComponentsExample />,
},
{
path: '/events',
element: <EventsExample />,
path: '/ui-events',
element: <UiEventsExample />,
},
{
path: '/store-events',
element: <StoreEventsExample />,
},
{
path: '/user-presence',

View file

@ -636,7 +636,7 @@ export const TldrawUi: React_2.NamedExoticComponent<{
export const TldrawUiContent: React_2.NamedExoticComponent<TldrawUiContentProps>;
// @public (undocumented)
export function TldrawUiContextProvider({ overrides, assetUrls, onEvent, children, }: TldrawUiContextProviderProps): JSX.Element;
export function TldrawUiContextProvider({ overrides, assetUrls, onUiEvent, children, }: TldrawUiContextProviderProps): JSX.Element;
// @public (undocumented)
export interface TldrawUiContextProviderProps {
@ -645,7 +645,7 @@ export interface TldrawUiContextProviderProps {
// (undocumented)
children?: any;
// (undocumented)
onEvent?: TLUiEventHandler;
onUiEvent?: TLUiEventHandler;
// (undocumented)
overrides?: TldrawUiOverrides | TldrawUiOverrides[];
}
@ -728,6 +728,11 @@ export type TLTranslationMessages = Record<TLTranslationKey, string>;
// @public (undocumented)
export type TLTranslations = TLTranslation[];
// @public (undocumented)
export type TLUiEventHandler<T extends keyof TLUiEventMap = keyof TLUiEventMap> = (name: T, data: Join<{
source: TLUiEventSource;
}, TLUiEventMap[T]>) => void;
// @public (undocumented)
export type TLUiIconType = 'align-bottom-center' | 'align-bottom-left' | 'align-bottom-right' | 'align-bottom' | 'align-center-center' | 'align-center-horizontal' | 'align-center-left' | 'align-center-right' | 'align-center-vertical' | 'align-left' | 'align-right' | 'align-top-center' | 'align-top-left' | 'align-top-right' | 'align-top' | 'arrow-left' | 'arrowhead-arrow' | 'arrowhead-bar' | 'arrowhead-diamond' | 'arrowhead-dot' | 'arrowhead-none' | 'arrowhead-square' | 'arrowhead-triangle-inverted' | 'arrowhead-triangle' | 'aspect-ratio' | 'avatar' | 'blob' | 'bring-forward' | 'bring-to-front' | 'check' | 'checkbox-checked' | 'checkbox-empty' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'chevrons-ne' | 'chevrons-sw' | 'clipboard-copy' | 'code' | 'collab' | 'color' | 'comment' | 'cross-2' | 'cross' | 'dash-dashed' | 'dash-dotted' | 'dash-draw' | 'dash-solid' | 'discord' | 'distribute-horizontal' | 'distribute-vertical' | 'dot' | 'dots-horizontal' | 'dots-vertical' | 'drag-handle-dots' | 'duplicate' | 'edit' | 'external-link' | 'file' | 'fill-none' | 'fill-pattern' | 'fill-semi' | 'fill-solid' | 'follow' | 'following' | 'font-draw' | 'font-mono' | 'font-sans' | 'font-serif' | 'geo-arrow-down' | 'geo-arrow-left' | 'geo-arrow-right' | 'geo-arrow-up' | 'geo-check-box' | 'geo-diamond' | 'geo-ellipse' | 'geo-hexagon' | 'geo-octagon' | 'geo-oval' | 'geo-pentagon' | 'geo-rectangle' | 'geo-rhombus-2' | 'geo-rhombus' | 'geo-star' | 'geo-trapezoid' | 'geo-triangle' | 'geo-x-box' | 'github' | 'group' | 'hidden' | 'image' | 'info-circle' | 'leading' | 'link' | 'lock-small' | 'lock' | 'menu' | 'minus' | 'mixed' | 'pack' | 'page' | 'plus' | 'question-mark-circle' | 'question-mark' | 'redo' | 'reset-zoom' | 'rotate-ccw' | 'rotate-cw' | 'ruler' | 'search' | 'send-backward' | 'send-to-back' | 'settings-horizontal' | 'settings-vertical-1' | 'settings-vertical' | 'share-1' | 'share-2' | 'size-extra-large' | 'size-large' | 'size-medium' | 'size-small' | 'spline-cubic' | 'spline-line' | 'stack-horizontal' | 'stack-vertical' | 'stretch-horizontal' | 'stretch-vertical' | 'text-align-center' | 'text-align-justify' | 'text-align-left' | 'text-align-right' | 'tool-arrow' | 'tool-embed' | 'tool-eraser' | 'tool-frame' | 'tool-hand' | 'tool-highlighter' | 'tool-line' | 'tool-media' | 'tool-note' | 'tool-pencil' | 'tool-pointer' | 'tool-text' | 'trash' | 'triangle-down' | 'triangle-up' | 'twitter' | 'undo' | 'ungroup' | 'unlock-small' | 'unlock' | 'visible' | 'warning-triangle' | 'zoom-in' | 'zoom-out';

View file

@ -79,6 +79,7 @@ export {
type DialogsProviderProps,
type TLDialog,
} from './lib/hooks/useDialogsProvider'
export { type TLUiEventHandler } from './lib/hooks/useEventsProvider'
export { useExportAs } from './lib/hooks/useExportAs'
export {
HelpMenuSchemaContext,

View file

@ -19,7 +19,7 @@ import { TldrawUiOverrides, useMergedOverrides, useMergedTranslationOverrides }
export interface TldrawUiContextProviderProps {
assetUrls?: UiAssetUrls
overrides?: TldrawUiOverrides | TldrawUiOverrides[]
onEvent?: TLUiEventHandler
onUiEvent?: TLUiEventHandler
children?: any
}
@ -27,7 +27,7 @@ export interface TldrawUiContextProviderProps {
export function TldrawUiContextProvider({
overrides,
assetUrls,
onEvent,
onUiEvent,
children,
}: TldrawUiContextProviderProps) {
return (
@ -36,7 +36,7 @@ export function TldrawUiContextProvider({
<ToastsProvider>
<DialogsProvider>
<BreakPointProvider>
<EventsProvider onEvent={onEvent}>
<EventsProvider onEvent={onUiEvent}>
<InternalProviders overrides={overrides}>{children}</InternalProviders>
</EventsProvider>
</BreakPointProvider>