From 75852f8b0d4a68511b7bb25cdcb7657bb8dd6d76 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Tue, 2 Jun 2026 09:54:20 +0100 Subject: [PATCH] refactor: enforce tldraw/no-exported-arrow-const repo-wide (#8947) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to actually enforce `tldraw/no-exported-arrow-const` everywhere it was originally intended, this PR removes the three `.oxlintrc.json` overrides that turned it off for `packages/editor`, `packages/tldraw`, `packages/utils`, `apps/examples`, and `templates`, and converts the 50 violations those overrides were hiding. The pattern is mechanical: `export const fn = (args) => {...}` becomes `export function fn(args) {...}`. Async functions get `export async function`. For React component aliases like `const X: TLErrorFallbackComponent = (...) =>` the form becomes `export const X: TLErrorFallbackComponent = function X(...) {...}` — a named function expression keeps the type alias visible to api-extractor (the rule only fires on arrows, not function expressions). No behavior changes. ### Affected directories | Directory | Files | Violations | | --- | ---: | ---: | | `packages/tldraw` | 14 | 19 | | `apps/examples` | 8 | 16 | | `packages/editor` | 10 | 11 | | `packages/utils` | 4 | 4 | | **Total** | **36** | **50** | ### Background Relates to #7572. The rule was added in #8258 along with the JS plugin, but with these overrides in place it has never fired in the packages it most needed to apply to. The plugin itself works correctly — see commit history for the exploration that confirmed that. ### API changes The shift to function declarations changes how api-extractor renders the affected exports — `const X: (args) => Y` becomes `function X(args): Y`. No call-site changes required; the public signatures are equivalent. Specifically affected `@public` exports: - `@tldraw/editor`: `DefaultSvgDefs`, `isSafeFloat`, `stopEventPropagation` - `@tldraw/tldraw`: `handleNativeOrMenuCopy`, `TldrawUiContextualToolbar`, `TldrawUiToolbarToggleGroup`, `TldrawUiToolbarToggleItem`, `truncateStringWithEllipsis`, `useSelectedShapesAnnouncer`, `interpolateSegments` - `@tldraw/utils`: `Image`, `noop`, `safeParseUrl`, `isAvifAnimated` `DefaultErrorFallback` keeps its `TLErrorFallbackComponent` alias in the api-report — typed as `export const DefaultErrorFallback: TLErrorFallbackComponent = function DefaultErrorFallback(...) {...}` so the alias survives. ### Change type - [x] `improvement` ### Test plan - `yarn oxlint .` — 0 errors. - `yarn typecheck` — passes. - `yarn test run` in `packages/editor`, `packages/tldraw`, `packages/utils` — all green. - `yarn api-check` — passes (api reports are regenerated). - [ ] Unit tests - [ ] End to end tests ### Code changes | Section | LOC change | | --------------- | ---------- | | Core code | +97 / -88 | | Automated files | +12 / -12 | | Documentation | +24 / -18 | | Config/tooling | +0 / -3 | --- .oxlintrc.json | 3 - .../derived-view/DerivedViewExample.tsx | 2 +- .../tools/globs-editor/GlobShapeUtil.tsx | 2 +- .../shapes/tools/globs-editor/shared.ts | 6 +- .../shapes/tools/globs-editor/utils.ts | 14 +-- .../speech-bubble/SpeechBubble/helpers.tsx | 2 +- .../mermaidPipelineBlueprint.ts | 2 +- .../use-cases/slideshow/SlidesManager.tsx | 2 +- .../use-cases/tower-defense/game-state.ts | 12 ++- packages/editor/api-report.api.md | 6 +- .../DefaultErrorFallback.tsx | 5 +- .../DefaultLoadingScreen.tsx | 2 +- .../DefaultShapeErrorFallback.tsx | 7 +- .../default-components/DefaultSvgDefs.tsx | 2 +- .../lib/editor/derivations/bindingsIndex.ts | 2 +- .../editor/derivations/parentsToChildren.ts | 2 +- .../derivations/shapeIdsInCurrentPage.ts | 2 +- .../src/lib/license/LicenseProvider.tsx | 4 +- packages/editor/src/lib/primitives/utils.ts | 2 +- packages/editor/src/lib/utils/dom.ts | 8 +- packages/tldraw/api-report.api.md | 12 +-- .../src/lib/shapes/bookmark/bookmarks.ts | 2 +- .../lib/shapes/shared/interpolate-props.ts | 4 +- .../lib/shapes/shared/useEditablePlainText.ts | 5 +- .../tldraw/src/lib/ui/components/A11y.tsx | 2 +- .../src/lib/ui/components/LoadingScreen.tsx | 2 +- .../components/PageMenu/edit-pages-shared.ts | 4 +- .../components/Toolbar/OverflowingToolbar.tsx | 4 +- .../primitives/TldrawUiContextualToolbar.tsx | 4 +- .../components/primitives/TldrawUiToolbar.tsx | 8 +- .../tldraw/src/lib/ui/hooks/menu-hooks.ts | 8 +- .../src/lib/ui/hooks/useClipboardEvents.ts | 6 +- packages/tldraw/src/lib/utils/text/text.ts | 2 +- packages/tldraw/src/test/TestEditor.ts | 86 ++++++++++--------- packages/tldraw/src/test/getSnapLines.ts | 2 +- packages/tldraw/src/test/roundedBox.ts | 2 +- packages/utils/api-report.api.md | 6 +- packages/utils/src/lib/function.ts | 2 +- packages/utils/src/lib/media/avif.ts | 2 +- packages/utils/src/lib/network.ts | 2 +- packages/utils/src/lib/url.ts | 2 +- 41 files changed, 133 insertions(+), 121 deletions(-) diff --git a/.oxlintrc.json b/.oxlintrc.json index 6ebfe1ddd393..26f76675b492 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -261,7 +261,6 @@ { "files": ["packages/editor/**/*", "packages/tldraw/**/*", "packages/utils/**/*"], "rules": { - "tldraw/no-exported-arrow-const": "off", "no-restricted-globals": [ "error", { @@ -417,7 +416,6 @@ "rules": { "tldraw/no-setter-getter": "off", "tldraw/no-direct-storage": "off", - "tldraw/no-exported-arrow-const": "off", "tldraw/img-referrer-policy": "off" } }, @@ -427,7 +425,6 @@ "tldraw/prefer-class-methods": "off", "tldraw/no-setter-getter": "off", "tldraw/no-direct-storage": "off", - "tldraw/no-exported-arrow-const": "off", "tldraw/img-referrer-policy": "off", "no-console": "off", "tldraw/method-signature-style": "off" diff --git a/apps/examples/src/examples/events/derived-view/DerivedViewExample.tsx b/apps/examples/src/examples/events/derived-view/DerivedViewExample.tsx index 996e07524e43..cb3c5611ee94 100644 --- a/apps/examples/src/examples/events/derived-view/DerivedViewExample.tsx +++ b/apps/examples/src/examples/events/derived-view/DerivedViewExample.tsx @@ -31,7 +31,7 @@ function ShowNumberOfDrawShapesOnPage() { ) } -export const deriveNumberOfDrawShapesInDocument = (editor: Editor) => { +export function deriveNumberOfDrawShapesInDocument(editor: Editor) { const { store } = editor const shapesIndex = store.query.ids('shape') diff --git a/apps/examples/src/examples/shapes/tools/globs-editor/GlobShapeUtil.tsx b/apps/examples/src/examples/shapes/tools/globs-editor/GlobShapeUtil.tsx index 594a68e9288c..6b924ce11585 100644 --- a/apps/examples/src/examples/shapes/tools/globs-editor/GlobShapeUtil.tsx +++ b/apps/examples/src/examples/shapes/tools/globs-editor/GlobShapeUtil.tsx @@ -981,7 +981,7 @@ const getHandleData = (id: string) => { return { edgeType, point } } -export const getNeighborGlobs = (editor: Editor, shape: GlobShape) => { +export function getNeighborGlobs(editor: Editor, shape: GlobShape) { const currentGlobBindings = editor.getBindingsFromShape(shape.id, 'glob') const neighborGlobs: Set = new Set() diff --git a/apps/examples/src/examples/shapes/tools/globs-editor/shared.ts b/apps/examples/src/examples/shapes/tools/globs-editor/shared.ts index 33f66c2978b1..e3d5dd554237 100644 --- a/apps/examples/src/examples/shapes/tools/globs-editor/shared.ts +++ b/apps/examples/src/examples/shapes/tools/globs-editor/shared.ts @@ -4,7 +4,7 @@ import { GlobShape } from './GlobShapeUtil' import { NodeShape } from './NodeShapeUtil' import { getOuterTangentPoints } from './utils' -export const getStartAndEndNodes = (editor: Editor, glob: TLShapeId) => { +export function getStartAndEndNodes(editor: Editor, glob: TLShapeId) { const bindings = editor.getBindingsFromShape(glob, 'glob') if (!bindings.length) return null @@ -35,14 +35,14 @@ export function getGlobBindings(editor: Editor, shape: GlobShape): GlobBindings return { start, end } } -export const getGlobTangentUpdate = ( +export function getGlobTangentUpdate( editor: Editor, globId: TLShapeId, startNodePagePos: VecLike, startRadius: number, endNodePagePos: VecLike, endRadius: number -) => { +) { // Calculate midpoint in page space const midPagePos = Vec.Average([startNodePagePos, endNodePagePos]) diff --git a/apps/examples/src/examples/shapes/tools/globs-editor/utils.ts b/apps/examples/src/examples/shapes/tools/globs-editor/utils.ts index 7cfb8ce57ee7..fb8d58b17c57 100644 --- a/apps/examples/src/examples/shapes/tools/globs-editor/utils.ts +++ b/apps/examples/src/examples/shapes/tools/globs-editor/utils.ts @@ -1,12 +1,12 @@ import { Vec, VecLike, VecModel } from 'tldraw' -export const getOuterTangentPoints = ( +export function getOuterTangentPoints( c0: VecLike, r0: number, c1: VecLike, r1: number, side?: 'edgeA' | 'edgeB' -): VecModel[] => { +): VecModel[] { const offsetAngle = Vec.Angle(c0, c1) const d = Vec.Dist(c0, c1) @@ -43,7 +43,7 @@ export const getOuterTangentPoints = ( ] } -export const getGlobEndPoint = (c: VecModel, d: VecModel, r: number, side: number = 0) => { +export function getGlobEndPoint(c: VecModel, d: VecModel, r: number, side: number = 0) { const angle = Vec.Angle(c, d) const displacement = Vec.Sub(c, d) @@ -62,7 +62,7 @@ export const getGlobEndPoint = (c: VecModel, d: VecModel, r: number, side: numbe return p } -export const getArcFlag = (c: VecModel, e0: VecModel, e1: VecModel) => { +export function getArcFlag(c: VecModel, e0: VecModel, e1: VecModel) { const d0 = Vec.Angle(c, e0) const d1 = Vec.Angle(c, e1) @@ -73,7 +73,7 @@ export const getArcFlag = (c: VecModel, e0: VecModel, e1: VecModel) => { return theta > 0 ? false : true } -export const projectTensionPoint = (lineStart: VecModel, lineEnd: VecModel, handle: VecModel) => { +export function projectTensionPoint(lineStart: VecModel, lineEnd: VecModel, handle: VecModel) { const lineDir = Vec.Sub(lineEnd, lineStart) const lineLength = lineDir.len() @@ -84,12 +84,12 @@ export const projectTensionPoint = (lineStart: VecModel, lineEnd: VecModel, hand return clampedProjection / lineLength } -export const circleCentresOverlap = (c0: VecModel, r0: number, c1: VecModel) => { +export function circleCentresOverlap(c0: VecModel, r0: number, c1: VecModel) { const d = Vec.Dist(c0, c1) return d <= r0 } -export const getClosestPointOnCircle = (c: VecModel, r: number, p: VecModel) => { +export function getClosestPointOnCircle(c: VecModel, r: number, p: VecModel) { const pDirection = Vec.Sub(p, c).uni() return Vec.Add(c, Vec.Mul(pDirection, r + 1)).toJson() diff --git a/apps/examples/src/examples/shapes/tools/speech-bubble/SpeechBubble/helpers.tsx b/apps/examples/src/examples/shapes/tools/speech-bubble/SpeechBubble/helpers.tsx index 8f609612d9ce..bc939814d37d 100644 --- a/apps/examples/src/examples/shapes/tools/speech-bubble/SpeechBubble/helpers.tsx +++ b/apps/examples/src/examples/shapes/tools/speech-bubble/SpeechBubble/helpers.tsx @@ -1,7 +1,7 @@ import { Vec, VecLike, lerp, pointInPolygon } from 'tldraw' import { SpeechBubbleShape } from './SpeechBubbleUtil' -export const getSpeechBubbleVertices = (shape: SpeechBubbleShape): Vec[] => { +export function getSpeechBubbleVertices(shape: SpeechBubbleShape): Vec[] { const { w, tail } = shape.props const fullHeight = shape.props.h + shape.props.growY diff --git a/apps/examples/src/examples/use-cases/custom-shape-mermaids/mermaidPipelineBlueprint.ts b/apps/examples/src/examples/use-cases/custom-shape-mermaids/mermaidPipelineBlueprint.ts index 2169fd9123aa..ceb686367205 100644 --- a/apps/examples/src/examples/use-cases/custom-shape-mermaids/mermaidPipelineBlueprint.ts +++ b/apps/examples/src/examples/use-cases/custom-shape-mermaids/mermaidPipelineBlueprint.ts @@ -2,7 +2,7 @@ import type { MermaidNodeRenderMapper } from '@tldraw/mermaid' import { CUSTOM_SHAPE_TYPE } from './customMermaidShapeUtil' /** Pass to `createMermaidDiagram` → `blueprintRender.mapNodeToRenderSpec`: custom `flowchart-util` + `mermaidNodeId` (layer badges applied after import via `applyPipelineStepIndices`). */ -export const mapNodeToRenderSpec: MermaidNodeRenderMapper = (input) => { +export const mapNodeToRenderSpec: MermaidNodeRenderMapper = function mapNodeToRenderSpec(input) { if (input.diagramKind !== 'flowchart') return undefined return { diff --git a/apps/examples/src/examples/use-cases/slideshow/SlidesManager.tsx b/apps/examples/src/examples/use-cases/slideshow/SlidesManager.tsx index 3d6f902df6f5..ce6e67285885 100644 --- a/apps/examples/src/examples/use-cases/slideshow/SlidesManager.tsx +++ b/apps/examples/src/examples/use-cases/slideshow/SlidesManager.tsx @@ -90,7 +90,7 @@ class SlidesManager { const slidesContext = createContext({} as SlidesManager) -export const SlidesProvider = ({ children }: { children: ReactNode }) => { +export function SlidesProvider({ children }: { children: ReactNode }) { const [slideManager] = useState(() => new SlidesManager()) return {children} } diff --git a/apps/examples/src/examples/use-cases/tower-defense/game-state.ts b/apps/examples/src/examples/use-cases/tower-defense/game-state.ts index a9b97e97b49f..fb7d2abb2ded 100644 --- a/apps/examples/src/examples/use-cases/tower-defense/game-state.ts +++ b/apps/examples/src/examples/use-cases/tower-defense/game-state.ts @@ -60,11 +60,17 @@ export const elapsedMs$ = atom('elapsedMs', 0) export const towerCooldowns = new Map() let _nextEnemyId = 1 -export const nextEnemyId = () => _nextEnemyId++ +export function nextEnemyId() { + return _nextEnemyId++ +} let _nextProjId = 1 -export const nextProjectileId = () => _nextProjId++ +export function nextProjectileId() { + return _nextProjId++ +} let _nextExplosionId = 1 -export const nextExplosionId = () => _nextExplosionId++ +export function nextExplosionId() { + return _nextExplosionId++ +} export function resetGameState() { enemies$.set([]) diff --git a/packages/editor/api-report.api.md b/packages/editor/api-report.api.md index 2a9b69ae7d02..e5687b64055c 100644 --- a/packages/editor/api-report.api.md +++ b/packages/editor/api-report.api.md @@ -712,7 +712,7 @@ export const DefaultShapeWrapper: ForwardRefExoticComponent): JSX.Element; // @public (undocumented) -export const DefaultSvgDefs: () => null; +export function DefaultSvgDefs(): null; // @public (undocumented) export const defaultTldrawOptions: { @@ -2353,7 +2353,7 @@ export function isAccelKey(e: { }): boolean; // @public -export const isSafeFloat: (n: number) => boolean; +export function isSafeFloat(n: number): boolean; // @public export function kickoutOccludedShapes(editor: Editor, shapeIds: TLShapeId[], opts?: { @@ -3286,7 +3286,7 @@ export abstract class StateNode implements Partial { } // @public @deprecated -export const stopEventPropagation: (e: any) => any; +export function stopEventPropagation(e: any): any; // @internal (undocumented) export type StoreName = (typeof Table)[keyof typeof Table]; diff --git a/packages/editor/src/lib/components/default-components/DefaultErrorFallback.tsx b/packages/editor/src/lib/components/default-components/DefaultErrorFallback.tsx index d1bf318ab520..d9192b86f4bd 100644 --- a/packages/editor/src/lib/components/default-components/DefaultErrorFallback.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultErrorFallback.tsx @@ -16,7 +16,10 @@ const BASE_ERROR_URL = 'https://github.com/tldraw/tldraw/issues/new' export type TLErrorFallbackComponent = ComponentType<{ error: unknown; editor?: Editor }> /** @public @react */ -export const DefaultErrorFallback: TLErrorFallbackComponent = ({ error, editor }) => { +export const DefaultErrorFallback: TLErrorFallbackComponent = function DefaultErrorFallback({ + error, + editor, +}) { const containerRef = useRef(null) const [shouldShowError, setShouldShowError] = useState(process.env.NODE_ENV === 'development') const [didCopy, setDidCopy] = useState(false) diff --git a/packages/editor/src/lib/components/default-components/DefaultLoadingScreen.tsx b/packages/editor/src/lib/components/default-components/DefaultLoadingScreen.tsx index 2d44c3d6af53..5607872125c1 100644 --- a/packages/editor/src/lib/components/default-components/DefaultLoadingScreen.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultLoadingScreen.tsx @@ -1,7 +1,7 @@ import { useEditorComponents } from '../../hooks/EditorComponentsContext' /** @public @react */ -export const DefaultLoadingScreen = () => { +export function DefaultLoadingScreen() { const { Spinner } = useEditorComponents() return (
diff --git a/packages/editor/src/lib/components/default-components/DefaultShapeErrorFallback.tsx b/packages/editor/src/lib/components/default-components/DefaultShapeErrorFallback.tsx index 4f8c2e758ed9..d76be8dbdd23 100644 --- a/packages/editor/src/lib/components/default-components/DefaultShapeErrorFallback.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultShapeErrorFallback.tsx @@ -4,6 +4,7 @@ import { ComponentType } from 'react' export type TLShapeErrorFallbackComponent = ComponentType<{ error: any }> /** @internal */ -export const DefaultShapeErrorFallback: TLShapeErrorFallbackComponent = () => { - return
-} +export const DefaultShapeErrorFallback: TLShapeErrorFallbackComponent = + function DefaultShapeErrorFallback() { + return
+ } diff --git a/packages/editor/src/lib/components/default-components/DefaultSvgDefs.tsx b/packages/editor/src/lib/components/default-components/DefaultSvgDefs.tsx index 4c73db50ad36..3dd97d09a754 100644 --- a/packages/editor/src/lib/components/default-components/DefaultSvgDefs.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultSvgDefs.tsx @@ -1,4 +1,4 @@ /** @public @react */ -export const DefaultSvgDefs = () => { +export function DefaultSvgDefs() { return null } diff --git a/packages/editor/src/lib/editor/derivations/bindingsIndex.ts b/packages/editor/src/lib/editor/derivations/bindingsIndex.ts index a700f9ea99ac..02c65525191f 100644 --- a/packages/editor/src/lib/editor/derivations/bindingsIndex.ts +++ b/packages/editor/src/lib/editor/derivations/bindingsIndex.ts @@ -29,7 +29,7 @@ function fromScratch(bindingsQuery: Computed) { return shapesToBindings } -export const bindingsIndex = (editor: Editor): Computed => { +export function bindingsIndex(editor: Editor): Computed { const { store } = editor const bindingsHistory = store.query.filterHistory('binding') const bindingsQuery = store.query.records('binding') diff --git a/packages/editor/src/lib/editor/derivations/parentsToChildren.ts b/packages/editor/src/lib/editor/derivations/parentsToChildren.ts index 8f4add1a6f2b..760a7f6c228a 100644 --- a/packages/editor/src/lib/editor/derivations/parentsToChildren.ts +++ b/packages/editor/src/lib/editor/derivations/parentsToChildren.ts @@ -22,7 +22,7 @@ function fromScratch( return result } -export const parentsToChildren = (store: TLStore) => { +export function parentsToChildren(store: TLStore) { const shapeIdsQuery = store.query.ids<'shape'>('shape') const shapeHistory = store.query.filterHistory('shape') diff --git a/packages/editor/src/lib/editor/derivations/shapeIdsInCurrentPage.ts b/packages/editor/src/lib/editor/derivations/shapeIdsInCurrentPage.ts index 9d4315a4e746..6667eb99f420 100644 --- a/packages/editor/src/lib/editor/derivations/shapeIdsInCurrentPage.ts +++ b/packages/editor/src/lib/editor/derivations/shapeIdsInCurrentPage.ts @@ -33,7 +33,7 @@ const isShapeInPage = (store: TLStore, pageId: TLPageId, shape: TLShape): boolea * @param store - The tldraw store. * @param getCurrentPageId - A function that returns the current page id. */ -export const deriveShapeIdsInCurrentPage = (store: TLStore, getCurrentPageId: () => TLPageId) => { +export function deriveShapeIdsInCurrentPage(store: TLStore, getCurrentPageId: () => TLPageId) { const shapesIndex = store.query.ids('shape') let lastPageId: null | TLPageId = null function fromScratch() { diff --git a/packages/editor/src/lib/license/LicenseProvider.tsx b/packages/editor/src/lib/license/LicenseProvider.tsx index 09e5d548ae17..739d833e2bca 100644 --- a/packages/editor/src/lib/license/LicenseProvider.tsx +++ b/packages/editor/src/lib/license/LicenseProvider.tsx @@ -6,7 +6,9 @@ import { LicenseManager } from './LicenseManager' export const LicenseContext = createContext({} as LicenseManager) /** @internal */ -export const useLicenseContext = () => useContext(LicenseContext) +export function useLicenseContext() { + return useContext(LicenseContext) +} function shouldHideEditorAfterDelay(licenseState: string): boolean { return licenseState === 'expired' || licenseState === 'unlicensed-production' diff --git a/packages/editor/src/lib/primitives/utils.ts b/packages/editor/src/lib/primitives/utils.ts index c1104f47ee7b..e5f5cbf0b69a 100644 --- a/packages/editor/src/lib/primitives/utils.ts +++ b/packages/editor/src/lib/primitives/utils.ts @@ -363,7 +363,7 @@ export function toFixed(v: number) { * Check if a float is safe to use. ie: Not too big or small. * @public */ -export const isSafeFloat = (n: number) => { +export function isSafeFloat(n: number) { return Math.abs(n) < Number.MAX_SAFE_INTEGER } diff --git a/packages/editor/src/lib/utils/dom.ts b/packages/editor/src/lib/utils/dom.ts index 8cf4e7a457e3..76ae30c97644 100644 --- a/packages/editor/src/lib/utils/dom.ts +++ b/packages/editor/src/lib/utils/dom.ts @@ -86,14 +86,16 @@ export function releasePointerCapture( * * @public */ -export const stopEventPropagation = (e: any) => e.stopPropagation() +export function stopEventPropagation(e: any) { + return e.stopPropagation() +} /** @internal */ -export const setStyleProperty = ( +export function setStyleProperty( elm: HTMLElement | null, property: string, value: string | number -) => { +) { if (!elm) return elm.style.setProperty(property, String(value)) } diff --git a/packages/tldraw/api-report.api.md b/packages/tldraw/api-report.api.md index 86c1bed626b5..f528a699c239 100644 --- a/packages/tldraw/api-report.api.md +++ b/packages/tldraw/api-report.api.md @@ -2397,7 +2397,7 @@ export function GroupMenuItem(): JSX.Element | null; export function GroupOrUngroupMenuItem(): JSX.Element; // @public -export const handleNativeOrMenuCopy: (editor: Editor, context?: TLClipboardWriteInfo) => Promise; +export function handleNativeOrMenuCopy(editor: Editor, context?: TLClipboardWriteInfo): Promise; // @public (undocumented) export class HandTool extends StateNode { @@ -4172,7 +4172,7 @@ export function TldrawUiComponentsProvider({ overrides, children }: TLUiComponen export const TldrawUiContextProvider: NamedExoticComponent; // @public -export const TldrawUiContextualToolbar: ({ children, className, isMousingDown, getSelectionBounds, changeOnlyWhenYChanges, label, }: TLUiContextualToolbarProps) => JSX.Element; +export function TldrawUiContextualToolbar({ children, className, isMousingDown, getSelectionBounds, changeOnlyWhenYChanges, label }: TLUiContextualToolbarProps): JSX.Element; // @public (undocumented) export function TldrawUiDialogBody({ className, children, style }: TLUiDialogBodyProps): JSX.Element; @@ -4334,10 +4334,10 @@ export const TldrawUiToolbar: React_3.ForwardRefExoticComponent>; // @public (undocumented) -export const TldrawUiToolbarToggleGroup: ({ children, className, type, asChild, ...props }: TLUiToolbarToggleGroupProps) => JSX.Element; +export function TldrawUiToolbarToggleGroup({ children, className, type, asChild, ...props }: TLUiToolbarToggleGroupProps): JSX.Element; // @public (undocumented) -export const TldrawUiToolbarToggleItem: ({ children, className, type, value, tooltip, ...props }: TLUiToolbarToggleItemProps) => JSX.Element; +export function TldrawUiToolbarToggleItem({ children, className, type, value, tooltip, ...props }: TLUiToolbarToggleItemProps): JSX.Element; // @public (undocumented) export const TldrawUiTooltip: React_3.ForwardRefExoticComponent>; @@ -6273,7 +6273,7 @@ export function TrapezoidToolbarItem(): JSX.Element; export function TriangleToolbarItem(): JSX.Element; // @public (undocumented) -export const truncateStringWithEllipsis: (str: string, maxLength: number) => string; +export function truncateStringWithEllipsis(str: string, maxLength: number): string; // @public (undocumented) export function UndoRedoGroup(): JSX.Element; @@ -6472,7 +6472,7 @@ export function useReadonly(): boolean; export function useRelevantStyles(stylesToCheck?: readonly StyleProp[]): null | ReadonlySharedStyleMap; // @public (undocumented) -export const useSelectedShapesAnnouncer: () => void; +export function useSelectedShapesAnnouncer(): void; // @public (undocumented) export function useShowCollaborationUi(): boolean; diff --git a/packages/tldraw/src/lib/shapes/bookmark/bookmarks.ts b/packages/tldraw/src/lib/shapes/bookmark/bookmarks.ts index 22a4753bf1a0..457ca464d0c7 100644 --- a/packages/tldraw/src/lib/shapes/bookmark/bookmarks.ts +++ b/packages/tldraw/src/lib/shapes/bookmark/bookmarks.ts @@ -40,7 +40,7 @@ export function setBookmarkHeight(editor: Editor, shape: TLBookmarkShape) { } /** @internal */ -export const getHumanReadableAddress = (url: string) => { +export function getHumanReadableAddress(url: string) { try { const objUrl = new URL(url) // we want the hostname without any www diff --git a/packages/tldraw/src/lib/shapes/shared/interpolate-props.ts b/packages/tldraw/src/lib/shapes/shared/interpolate-props.ts index e2cd001cba63..ad799ba7573d 100644 --- a/packages/tldraw/src/lib/shapes/shared/interpolate-props.ts +++ b/packages/tldraw/src/lib/shapes/shared/interpolate-props.ts @@ -1,11 +1,11 @@ import { TLDrawShapeSegment, VecModel, b64Vecs, lerp } from '@tldraw/editor' /** @public */ -export const interpolateSegments = ( +export function interpolateSegments( startSegments: TLDrawShapeSegment[], endSegments: TLDrawShapeSegment[], progress: number -): TLDrawShapeSegment[] => { +): TLDrawShapeSegment[] { const startPoints: VecModel[] = [] const endPoints: VecModel[] = [] diff --git a/packages/tldraw/src/lib/shapes/shared/useEditablePlainText.ts b/packages/tldraw/src/lib/shapes/shared/useEditablePlainText.ts index 01e035ae387c..a10db2862264 100644 --- a/packages/tldraw/src/lib/shapes/shared/useEditablePlainText.ts +++ b/packages/tldraw/src/lib/shapes/shared/useEditablePlainText.ts @@ -3,7 +3,6 @@ import { ExtractShapeByProps, TLShapeId, getPointerInfo, - noop, preventDefault, tlenv, useEditor, @@ -167,8 +166,8 @@ export function useEditableTextCommon(shapeId: TLShapeId) { ) return { - handleFocus: noop, - handleBlur: noop, + handleFocus: (): void => {}, + handleBlur: (): void => {}, handleInputPointerDown, handleDoubleClick: editor.markEventAsHandled, handlePaste, diff --git a/packages/tldraw/src/lib/ui/components/A11y.tsx b/packages/tldraw/src/lib/ui/components/A11y.tsx index a0043a4c78f1..2b2d6dd8094f 100644 --- a/packages/tldraw/src/lib/ui/components/A11y.tsx +++ b/packages/tldraw/src/lib/ui/components/A11y.tsx @@ -134,7 +134,7 @@ export function generateShapeAnnouncementMessage(args: { } /** @public */ -export const useSelectedShapesAnnouncer = () => { +export function useSelectedShapesAnnouncer() { const editor = useMaybeEditor() const a11y = useA11y() const msg = useTranslation() diff --git a/packages/tldraw/src/lib/ui/components/LoadingScreen.tsx b/packages/tldraw/src/lib/ui/components/LoadingScreen.tsx index 3df2c620a9b2..20f0e97502dc 100644 --- a/packages/tldraw/src/lib/ui/components/LoadingScreen.tsx +++ b/packages/tldraw/src/lib/ui/components/LoadingScreen.tsx @@ -1,7 +1,7 @@ import { LoadingScreen as LoadingScreenContainer, useEditorComponents } from '@tldraw/editor' /** @public @react */ -export const LoadingScreen = () => { +export function LoadingScreen() { const { Spinner } = useEditorComponents() return {Spinner ? : null} } diff --git a/packages/tldraw/src/lib/ui/components/PageMenu/edit-pages-shared.ts b/packages/tldraw/src/lib/ui/components/PageMenu/edit-pages-shared.ts index fe9d84d02e4b..ad1bb857d60d 100644 --- a/packages/tldraw/src/lib/ui/components/PageMenu/edit-pages-shared.ts +++ b/packages/tldraw/src/lib/ui/components/PageMenu/edit-pages-shared.ts @@ -8,13 +8,13 @@ import { } from '@tldraw/editor' import { TLUiEventContextType } from '../../context/events' -export const onMovePage = ( +export function onMovePage( editor: Editor, id: TLPageId, from: number, to: number, trackEvent: TLUiEventContextType -) => { +) { if (from === to) return let index: IndexKey diff --git a/packages/tldraw/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx b/packages/tldraw/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx index c4b6760175ca..cdd2758dd464 100644 --- a/packages/tldraw/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +++ b/packages/tldraw/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx @@ -349,11 +349,11 @@ export function OverflowingToolbar({ ) } -export const isActiveTLUiToolItem = ( +export function isActiveTLUiToolItem( item: TLUiToolItem, activeToolId: string | undefined, geoState: string | null | undefined -) => { +) { return item.meta?.geo ? activeToolId === 'geo' && geoState === item.meta?.geo : activeToolId === item.id diff --git a/packages/tldraw/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx b/packages/tldraw/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx index 4058496dd644..434f5e3a9501 100644 --- a/packages/tldraw/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +++ b/packages/tldraw/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx @@ -41,14 +41,14 @@ export interface TLUiContextualToolbarProps { * * @public @react */ -export const TldrawUiContextualToolbar = ({ +export function TldrawUiContextualToolbar({ children, className, isMousingDown, getSelectionBounds, changeOnlyWhenYChanges = false, label, -}: TLUiContextualToolbarProps) => { +}: TLUiContextualToolbarProps) { const editor = useEditor() const toolbarRef = useRef(null) diff --git a/packages/tldraw/src/lib/ui/components/primitives/TldrawUiToolbar.tsx b/packages/tldraw/src/lib/ui/components/primitives/TldrawUiToolbar.tsx index dc0471270d26..4bf6622bfc4c 100644 --- a/packages/tldraw/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +++ b/packages/tldraw/src/lib/ui/components/primitives/TldrawUiToolbar.tsx @@ -99,13 +99,13 @@ export interface TLUiToolbarToggleGroupProps extends React.HTMLAttributes { +}: TLUiToolbarToggleGroupProps) { return ( <_Toolbar.ToggleGroup asChild={asChild} @@ -132,14 +132,14 @@ export interface TLUiToolbarToggleItemProps extends React.HTMLAttributes { +}: TLUiToolbarToggleItemProps) { const toggleItem = ( <_Toolbar.ToggleItem {...props} diff --git a/packages/tldraw/src/lib/ui/hooks/menu-hooks.ts b/packages/tldraw/src/lib/ui/hooks/menu-hooks.ts index d5ef85f7c03d..48bacea01aee 100644 --- a/packages/tldraw/src/lib/ui/hooks/menu-hooks.ts +++ b/packages/tldraw/src/lib/ui/hooks/menu-hooks.ts @@ -18,19 +18,19 @@ function shapesWithUnboundArrows(editor: Editor) { } /** @internal */ -export const useThreeStackableItems = () => { +export function useThreeStackableItems() { const editor = useEditor() return useValue('threeStackableItems', () => shapesWithUnboundArrows(editor).length > 2, [editor]) } /** @internal */ -export const useIsInSelectState = () => { +export function useIsInSelectState() { const editor = useEditor() return useValue('isInSelectState', () => editor.isIn('select'), [editor]) } /** @internal */ -export const useAllowGroup = () => { +export function useAllowGroup() { const editor = useEditor() return useValue( 'allow group', @@ -65,7 +65,7 @@ export const useAllowGroup = () => { } /** @internal */ -export const useAllowUngroup = () => { +export function useAllowUngroup() { const editor = useEditor() return useValue( 'allowUngroup', diff --git a/packages/tldraw/src/lib/ui/hooks/useClipboardEvents.ts b/packages/tldraw/src/lib/ui/hooks/useClipboardEvents.ts index 6e497772d6de..6bfc2c282378 100644 --- a/packages/tldraw/src/lib/ui/hooks/useClipboardEvents.ts +++ b/packages/tldraw/src/lib/ui/hooks/useClipboardEvents.ts @@ -103,7 +103,7 @@ export function extractIframeFromHtml( } /** @public */ -export const isValidHttpURL = (url: string) => { +export function isValidHttpURL(url: string) { try { const u = new URL(url) return u.protocol === 'http:' || u.protocol === 'https:' @@ -697,10 +697,10 @@ async function handleClipboardThings( * * @public */ -export const handleNativeOrMenuCopy = async ( +export async function handleNativeOrMenuCopy( editor: Editor, context: TLClipboardWriteInfo = { operation: 'copy', source: 'menu' } -): Promise => { +): Promise { const nav = editor.getContainerWindow().navigator let content = await editor.resolveAssetsInContent( editor.getContentFromCurrentPage(editor.getSelectedShapeIds()) diff --git a/packages/tldraw/src/lib/utils/text/text.ts b/packages/tldraw/src/lib/utils/text/text.ts index 9dccdaaf465e..fbf00d52a898 100644 --- a/packages/tldraw/src/lib/utils/text/text.ts +++ b/packages/tldraw/src/lib/utils/text/text.ts @@ -81,6 +81,6 @@ export function cleanupText(text: string) { } /** @public */ -export const truncateStringWithEllipsis = (str: string, maxLength: number) => { +export function truncateStringWithEllipsis(str: string, maxLength: number) { return str.length <= maxLength ? str : str.substring(0, maxLength - 3) + '...' } diff --git a/packages/tldraw/src/test/TestEditor.ts b/packages/tldraw/src/test/TestEditor.ts index 09201ed399c2..bdb0273302ca 100644 --- a/packages/tldraw/src/test/TestEditor.ts +++ b/packages/tldraw/src/test/TestEditor.ts @@ -491,48 +491,50 @@ export const defaultShapesIds = { ellipse1: createShapeId('ellipse1'), } -export const createDefaultShapes = (): TLShapePartial[] => [ - { - id: defaultShapesIds.box1, - type: 'geo', - x: 100, - y: 100, - props: { - w: 100, - h: 100, - geo: 'rectangle', +export function createDefaultShapes(): TLShapePartial[] { + return [ + { + id: defaultShapesIds.box1, + type: 'geo', + x: 100, + y: 100, + props: { + w: 100, + h: 100, + geo: 'rectangle', + }, }, - }, - { - id: defaultShapesIds.box2, - type: 'geo', - x: 200, - y: 200, - rotation: HALF_PI / 2, - props: { - w: 100, - h: 100, - color: 'black', - fill: 'none', - dash: 'draw', - size: 'm', - geo: 'rectangle', + { + id: defaultShapesIds.box2, + type: 'geo', + x: 200, + y: 200, + rotation: HALF_PI / 2, + props: { + w: 100, + h: 100, + color: 'black', + fill: 'none', + dash: 'draw', + size: 'm', + geo: 'rectangle', + }, }, - }, - { - id: defaultShapesIds.ellipse1, - type: 'geo', - parentId: defaultShapesIds.box2, - x: 200, - y: 200, - props: { - w: 50, - h: 50, - color: 'black', - fill: 'none', - dash: 'draw', - size: 'm', - geo: 'ellipse', + { + id: defaultShapesIds.ellipse1, + type: 'geo', + parentId: defaultShapesIds.box2, + x: 200, + y: 200, + props: { + w: 50, + h: 50, + color: 'black', + fill: 'none', + dash: 'draw', + size: 'm', + geo: 'ellipse', + }, }, - }, -] + ] +} diff --git a/packages/tldraw/src/test/getSnapLines.ts b/packages/tldraw/src/test/getSnapLines.ts index 36fa903dca6b..1f0d8a2f407e 100644 --- a/packages/tldraw/src/test/getSnapLines.ts +++ b/packages/tldraw/src/test/getSnapLines.ts @@ -6,7 +6,7 @@ const simplifyNumber = (n: number) => { } return n } -export const getSnapLines = (scene: Editor) => { +export function getSnapLines(scene: Editor) { const result = [] for (const snap of scene.snaps.getIndicators()) { if (snap.type !== 'points') { diff --git a/packages/tldraw/src/test/roundedBox.ts b/packages/tldraw/src/test/roundedBox.ts index 3613380944e6..f5870de815ab 100644 --- a/packages/tldraw/src/test/roundedBox.ts +++ b/packages/tldraw/src/test/roundedBox.ts @@ -1,6 +1,6 @@ import { Box } from '@tldraw/editor' -export const roundedBox = (box: Box, accuracy = 0.01) => { +export function roundedBox(box: Box, accuracy = 0.01) { // for some reason jest treats -0 and 0 as not equal, so prevent -0s from appearing const noNegativeZero = (value: number) => (value === 0 ? 0 : value) diff --git a/packages/utils/api-report.api.md b/packages/utils/api-report.api.md index 83c9c01c6999..4b8fb7c21766 100644 --- a/packages/utils/api-report.api.md +++ b/packages/utils/api-report.api.md @@ -210,7 +210,7 @@ export function groupBy(array: ReadonlyArray, keySelecto export function hasOwnProperty(obj: object, key: string): boolean; // @internal -const Image_2: (width?: number | undefined, height?: number | undefined) => HTMLImageElement; +function Image_2(width?: number, height?: number): HTMLImageElement; export { Image_2 as Image } // @public @@ -348,7 +348,7 @@ export function mockUniqueId(fn: (size?: number) => string): void; export function modulate(value: number, rangeA: number[], rangeB: number[], clamp?: boolean): number; // @internal -export const noop: () => void; +export function noop(): void; // @internal export function objectMapEntries(object: Obj): Array<[keyof Obj, Obj[keyof Obj]]>; @@ -472,7 +472,7 @@ export function rng(seed?: string): () => number; export function rotateArray(arr: T[], offset: number): T[]; // @public -export const safeParseUrl: (url: string, baseUrl?: string | undefined | URL) => undefined | URL; +export function safeParseUrl(url: string, baseUrl?: string | URL): undefined | URL; // @internal export function setInLocalStorage(key: string, value: string): void; diff --git a/packages/utils/src/lib/function.ts b/packages/utils/src/lib/function.ts index 3bfdfd9b8b9d..3a434e95b7da 100644 --- a/packages/utils/src/lib/function.ts +++ b/packages/utils/src/lib/function.ts @@ -40,4 +40,4 @@ export function omitFromStackTrace, Return>( * Does nothing, but it's really really good at it. * @internal */ -export const noop: () => void = () => {} +export function noop(): void {} diff --git a/packages/utils/src/lib/media/avif.ts b/packages/utils/src/lib/media/avif.ts index de10dc529240..b2716185a03c 100644 --- a/packages/utils/src/lib/media/avif.ts +++ b/packages/utils/src/lib/media/avif.ts @@ -32,7 +32,7 @@ * * @public */ -export const isAvifAnimated = (buffer: ArrayBuffer) => { +export function isAvifAnimated(buffer: ArrayBuffer) { const view = new Uint8Array(buffer) return view[3] === 44 } diff --git a/packages/utils/src/lib/network.ts b/packages/utils/src/lib/network.ts index 9cad5275630d..1a68fa2e0846 100644 --- a/packages/utils/src/lib/network.ts +++ b/packages/utils/src/lib/network.ts @@ -24,7 +24,7 @@ export async function fetch(input: RequestInfo | URL, init?: RequestInit): Promi * @returns HTMLImageElement with referrerPolicy set to 'strict-origin-when-cross-origin' * @internal */ -export const Image = (width?: number, height?: number) => { +export function Image(width?: number, height?: number) { // eslint-disable-next-line tldraw/no-restricted-properties const img = new window.Image(width, height) img.referrerPolicy = 'strict-origin-when-cross-origin' diff --git a/packages/utils/src/lib/url.ts b/packages/utils/src/lib/url.ts index 60ce3f721ede..e35549ae9abe 100644 --- a/packages/utils/src/lib/url.ts +++ b/packages/utils/src/lib/url.ts @@ -38,7 +38,7 @@ * * @public */ -export const safeParseUrl = (url: string, baseUrl?: string | URL) => { +export function safeParseUrl(url: string, baseUrl?: string | URL) { try { return new URL(url, baseUrl) } catch {