Conversation
…nagement, and improve Tldraw canvas interaction with keyboard shortcuts and maximization styles.
…efaultNodeUtil and Tldraw components to utilize TLShape and TLShapeId for better type safety. Update Roam store handling to ensure correct type parsing for tldraw state.
… and enhance inspector functionality. Add Tailwind CSS version update and adjust styles for node inspector. Implement snapshot sanitization for tldraw state to ensure consistent node properties.
… by adding edit time to search results and improving loading state management. Refactor result handling to limit visible results and ensure consistent user experience during searches.
…debounce search functionality. Introduce a constant for debounce time and enhance state handling to prevent unnecessary updates when the selected target remains unchanged.
…s to return promises for search results. Improve loading state management and prevent unnecessary updates during search requests by implementing request cancellation and debounce logic.
…ng user experience with dynamic panel resizing. Update styles for improved visual feedback on inspector interactions.
…pening blocks in the main window and sidebar. Improve user interaction with dynamic labels and refined styles for better visual feedback in the inspector panel.
- Introduced a Prettier configuration file to enforce consistent code styling. - Added Prettier and Prettier Tailwind CSS plugin as development dependencies. - Updated VSCode settings to integrate Prettier for automatic formatting on save.
…ling and introduce keyboard shortcuts dialog. Refactor TYPE_STYLES to include border properties for improved visual design, and implement a new MainMenu and KeyboardShortcutsDialog for better user interaction.
- Updated Prettier to version 3.8.1 and added prettier-plugin-tailwindcss version 0.6.14 as development dependencies. - Enhanced lockfile with new resolutions and peer dependencies for improved code formatting and compatibility.
…ering of node titles - Introduced RoamRenderedString to handle rendering of node titles with fallback for errors. - Updated getNodeTypeFromRoamRefText to use BLOCK_REF_REGEX for block matching. - Refactored title display in BaseRoamNodeShapeUtil to utilize the new component for better readability.
- Added methods to retrieve block UIDs from DOM elements and handle dropped text. - Implemented drag event listeners to support transferring UIDs during drag-and-drop actions. - Updated external content handling to process dropped text and UIDs effectively, improving user interaction with the canvas.
… styles - Added CSS rules to ensure tldraw cursors are not affected by external styles, specifically for elements with role="button". - Improved user experience by maintaining consistent cursor behavior within the tldraw canvas.
WalkthroughThis PR adds a Tldraw-based canvas integration for Roam (components, styles, store hook, utilities, and entry wiring) and introduces a new esbuild-based build system with scripts (compile, build, dev). It migrates toolchain and CI from npm to pnpm (package.json, GitHub workflows, build.sh), adds editor/format tooling (Prettier, Tailwind, VSCode settings, tsconfig), and includes type/patch updates and pnpm overrides for dependency control. Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| useEffect(() => { | ||
| const container = containerRef.current; | ||
| if (!container) return; | ||
|
|
||
| const onDragOverNative = (e: DragEvent): void => { | ||
| const target = e.target as Node | null; | ||
| if (!target || !container.contains(target)) return; | ||
| e.preventDefault(); | ||
| }; | ||
|
|
||
| const onDropNative = (e: DragEvent): void => { | ||
| const target = e.target as Node | null; | ||
| if (!target || !container.contains(target)) return; | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| (e as Event).stopImmediatePropagation?.(); | ||
| if (!e.dataTransfer) return; | ||
| handleDropPayload({ | ||
| dataTransfer: e.dataTransfer, | ||
| clientX: e.clientX, | ||
| clientY: e.clientY, | ||
| }); | ||
| }; | ||
|
|
||
| container.addEventListener("dragover", onDragOverNative, true); | ||
| container.addEventListener("drop", onDropNative, true); | ||
| return () => { | ||
| container.removeEventListener("dragover", onDragOverNative, true); | ||
| container.removeEventListener("drop", onDropNative, true); | ||
| }; | ||
| }, []); |
There was a problem hiding this comment.
🔴 useEffect called after conditional early return violates React rules of hooks
The useEffect at line 361 is placed after the conditional if (!pageUid) return null; at line 264. This violates React's rules of hooks, which require that hooks are always called in the same order on every render.
Root Cause and Impact
When pageUid is falsy, the component returns null at line 264, and the useEffect at line 361 is never reached. When pageUid is truthy, the useEffect IS reached. This means React sees a different number of hook calls between renders, which will cause a React runtime error:
"Rendered more hooks than during the previous render"
The hooks before line 264 (lines 165-262) total 8 hooks. The useEffect at line 361 would be the 9th hook, but it's only called when pageUid is truthy. If the component first renders with no pageUid (e.g., page not yet created) and then re-renders with a valid pageUid, React will crash.
Impact: The drag-and-drop event listeners for the canvas container will never be registered if the component initially renders without a pageUid, and React may crash if pageUid changes from falsy to truthy.
Prompt for agents
Move the useEffect at line 361-391 (the drag-and-drop event listener setup) to BEFORE the conditional return at line 264. It should be placed alongside the other useEffect hooks (e.g., after the useEffect at line 250-262). The handleDropPayload function it references (defined at line 318) should also be moved before the early return, or the useEffect should be refactored to not depend on it (e.g., by using a ref to hold the handler). The simplest fix is to move both handleDropPayload and this useEffect above line 264.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Fix all issues with AI agents
In `@build.sh`:
- Line 1: Add a POSIX-compatible shebang to the top of the script so the shell
is explicit (e.g., add "#!/usr/bin/env bash" as the first line) and ensure the
script is executable (chmod +x). Keep the existing command "pnpm run build:roam"
unchanged; the shebang will ensure it runs under the intended shell and satisfy
Shellcheck SC2148.
In `@package.json`:
- Line 22: The package.json currently pins the dependency "tldraw" to the
unpublished version "3.15.5"; update the dependency entry for "tldraw" to a
published version such as "3.15.1" (edit the "tldraw" value in package.json),
then reinstall/update lockfile (npm install or yarn install) so the lockfile
reflects the valid version.
In `@scripts/build.ts`:
- Around line 3-7: The build function reassigns process.env to a new object
which can break existing references; instead of replacing process.env in build,
set the specific variable directly (e.g., assign process.env.NODE_ENV =
process.env.NODE_ENV || "production") so existing references remain valid;
update the build function in scripts/build.ts (the build async function) to
mutate process.env rather than overwrite it, mirroring the direct-assignment
pattern used in scripts/dev.ts.
In `@scripts/dev.ts`:
- Around line 7-17: The dev function calls compile(...) but doesn't await or
handle its promise, so initial build errors become unhandled rejections; update
dev to propagate compile failures by either making dev async and awaiting
compile(...) or by adding a reject handler in the returned Promise (e.g., new
Promise<number>((resolve, reject) => { const p = compile(...);
p.then(...).catch(reject); process.on("exit", resolve); })). Ensure you
reference the existing compile(...) invocation and keep the existing builder
logic (esbuild.context(...).then(esb => esb.watch())) while wiring its returned
promise into the dev promise so main()'s try/catch can observe errors.
In `@src/components/canvas/DefaultNodeUtil.tsx`:
- Around line 65-100: The Datalog query interpolation in searchPages (and
similarly in searchBlocks) is vulnerable because escapeRegex does not escape
double quotes, allowing injection when pattern is placed inside a double-quoted
re-pattern; modify the sanitization so double quotes are escaped before
interpolation (either add " to the escapeRegex character class or explicitly
call .replace(/"/g, '\\"') on pattern) and ensure the sanitized pattern is used
in the re-pattern interpolation; mirror the same change in searchBlocks and keep
getNodeTypeFromRoamRefText's quote-escaping approach as the reference.
In `@src/components/canvas/Tldraw.tsx`:
- Around line 494-519: The onMount block registers listeners without cleanup
causing leaks; move the registrations for editor.on(...) and
editor.registerExternalContentHandler("text", ...) into separate useEffect hooks
that run when the editor instance is ready, and in each effect return a cleanup
that calls editor.off(...) for the exact handler registered and
editor.registerExternalContentHandler("text", null) to unregister the external
handler; keep the handler logic (including calls to getNodeTypeFromRoamRefText,
defaultHandleExternalTextContent, createShapeId, and creating a RoamNodeShape)
identical but reference the same handler functions so they can be removed by
editor.off during cleanup.
In `@src/components/canvas/tldrawStyles.ts`:
- Around line 71-74: The global `.roam-main { position: relative; }` rule
affects all pages; narrow its scope so it only applies when the tldraw canvas is
active — update the selector used in tldrawStyles.ts to target `.roam-main` only
when it contains the canvas (e.g.
`.roam-main:has(.roamjs-tldraw-canvas-container) { position: relative; }`) or,
if :has isn’t acceptable, apply a contextual class when maximizing the canvas
(e.g. add/remove `.roamjs-tldraw-maximized` and use `.roamjs-tldraw-maximized
.roam-main { position: relative; }`) and remove the original broad `.roam-main`
rule.
In `@src/components/canvas/uiOverrides.tsx`:
- Around line 81-94: The map in Toolbar violates the Rules of Hooks by calling
useIsToolSelected inside a .map callback; fix by extracting a new child
component (e.g., ToolMenuItem) that accepts the tool descriptor and the tool
data from useTools(), call useIsToolSelected(toolData) inside that component,
and render TldrawUiMenuItem there; then change the map to return <ToolMenuItem
key={tool.id} tool={tool} toolData={tools[tool.id]} /> so hooks are only invoked
at the top level of a React component (referencing Toolbar, DEFAULT_NODE_TOOLS,
useTools, useIsToolSelected, and TldrawUiMenuItem).
In `@src/components/canvas/useRoamStore.ts`:
- Around line 65-82: The setPersistedSnapshot function currently discards errors
by using void on window.roamAlphaAPI.data.page.update; modify
setPersistedSnapshot (and its call sites if needed) to handle promise rejections
— either await the update inside an async function or append a .catch(...) to
the returned promise — and log/report failures (use existing logger or
console.error) including pageUid and the error so write failures to
ROAM_TLDRAW_KEY are visible; ensure you still merge props via
getPageProps(pageUid) and do not change the stored payload shape.
🧹 Nitpick comments (20)
.github/workflows/main.yaml (1)
23-23: Consider upgradingactions/checkoutto v4.Line 23 uses
actions/checkout@v3, which is outdated. The rest of the workflow already uses v4 actions (setup-node@v4,action-setup@v4). While this line wasn't changed in this PR, it's worth aligning for consistency and to pick up Node 20 runtime support..vscode/settings.json (1)
4-4:prettier.prettierPathis unnecessary when the extension auto-resolves Prettier locally.The Prettier VSCode extension automatically resolves Prettier from your project's
node_moduleswithout this setting. Removing it simplifies your configuration.src/components/canvas/useRoamStore.ts (2)
95-111:customShapeUtilsarray inuseMemodeps may cause unnecessary store re-creation.If the caller passes a new array reference on every render (e.g., an inline
[MyUtil]), the store will be re-created each time, losing all local state. Ensure the caller memoizes thecustomShapeUtilsarray, or consider removing it from the dependency array in favor of a ref-based approach.
13-38:sanitizeNodePropsInSnapshothardcodes expected prop shapes — keep in sync with shape utils.The sanitizer whitelists
w,h,uid,titlewith hardcoded defaults. If the shape definition (e.g.,DefaultNodeUtil) adds new props later, this sanitizer will silently strip them. Consider co-locating the default props with the shape util or importing them from a shared constant.src/utils/isCanvasPage.ts (2)
15-18: Wildcard*requires at least one character — intentional?
\*is replaced with.+(one-or-more), soCanvas/*won't match the bare title"Canvas/". If a zero-length suffix should also match, use.*instead. If the current behavior is intentional, this is fine as-is.Regarding the static analysis ReDoS warning: the risk here is negligible since user-supplied
*wildcards are converted to simple.+with no nested quantifiers, and all other special characters are escaped beforehand.
33-42: Regex is recompiled on every call toisCanvasPage.
patternToRegexis called for each pattern on everyisCanvasPageinvocation (which fires on every H1 mutation). Since patterns rarely change, consider caching the compiled regexes (e.g., memoize on the raw settings string).scripts/build.ts (1)
19-26: Redundant outertry/catch—build()already callsprocess.exit(1)on failure.Since
process.exit(1)inbuild()terminates the process, thecatchinmain()is unreachable for compile errors. Consider collapsing into a single function or removing one layer.src/index.ts (1)
67-71: TODO: Migration fromroamjs-query-builder.tldrawtoroamjs-tldraw.There's an open TODO for migrating persisted state from the old key to the new one. Users upgrading from the query-builder extension may lose their existing canvas data without this migration.
Would you like me to draft a migration utility that reads from the old
roamjs-query-builder.tldrawkey and writes toroamjs-tldraw, or open an issue to track this?src/components/canvas/tldrawStyles.ts (1)
77-90: Hardcoded color values for inspector hover/active states.
#dadddfis used in multiple places. Consider extracting it to a CSS variable for easier theming and consistency, especially if Roam supports dark mode.src/components/canvas/Tldraw.tsx (6)
157-162:toggleMaximizedis omitted fromuseMemodeps — safe here but fragile.
toggleMaximized(line 138) is recreated each render, yet it's excluded from theuseMemodeps at line 161. This works today becausetoggleMaximizedonly accesses refs (containerRef,appRef), which are stable across renders. However, if it ever closes over reactive state, this will silently become a stale closure bug.Consider wrapping
toggleMaximizedinuseCallback(with an empty dep array since it only uses refs) and including it in theuseMemodeps for correctness-by-construction.
458-462: Every editor event is cast toTLPointerEventInfoand triggersrefreshInspectorTarget.
editor.on("event", ...)fires for all event types (keyboard, wheel, pointer, etc.). Casting every event toTLPointerEventInfoand callingrefreshInspectorTarget()unconditionally on each event is wasteful. The modifier-key check at line 461 is safe (properties are justundefinedfor non-pointer events) but therefreshInspectorTarget()call queries the editor's selection state on every single event.Consider filtering to pointer events before calling
refreshInspectorTarget:💡 Suggested optimization
editor.on("event", (event) => { - const e = event as TLPointerEventInfo; - refreshInspectorTarget(); - const validModifier = e.shiftKey || e.ctrlKey; - if (!(e.name === "pointer_up" && validModifier)) return; + if (event.name === "pointer_up") { + refreshInspectorTarget(); + const e = event as TLPointerEventInfo; + const validModifier = e.shiftKey || e.ctrlKey; + if (!validModifier) return;Wait —
refreshInspectorTargetlikely needs to run on selection changes too (e.g., keyboard-driven selection). If so, consider listening toeditor.on("change")or the store's selection events instead, which would be more targeted than reacting to every raw input event.
361-391: Drop event listener registered with empty deps — relies on stable refs internally.
handleDropPayload(defined at line 318) is captured once by this effect because of the[]dependency array. This is safe only becausehandleDropPayloadaccesses the editor throughappRef.current(a ref). IfhandleDropPayloadever starts using reactive state directly (not via refs), this will silently become stale. A brief comment noting this invariant would help future maintainers.
250-262: Globaldragstartlistener intercepts all drag events in the document.This registers a document-level
dragstartlistener that callsgetBlockUidFromBulleton any drag target anywhere in the page. If other parts of the Roam UI or extensions also rely ondataTransferdata, this could interfere. The current guard (if (uid)) mitigates this, but it's worth noting the broad scope.
623-624: MenuItemkeymay not be unique across search results.The key
{`${result.uid}-${result.title}`}assumesuidis unique. If it is (which it should be in Roam), thenresult.uidalone suffices. Includingtitleis redundant noise in the key — and in theory, if two different UIDs share the same title, this still works, but if a UID somehow appeared twice in results, the composite key wouldn't help since the title would also match.Minor — no functional issue, just a simplification opportunity.
59-66:getPageUidByPageTitle(title)is called on every render.Line 66 calls
getPageUidByPageTitle(title)directly in the component body, meaning it runs on every render. If this is a synchronous Roam API query, it could be a performance concern. Consider memoizing it:💡 Suggested fix
- const pageUid = getPageUidByPageTitle(title); + const pageUid = useMemo(() => getPageUidByPageTitle(title), [title]);src/components/canvas/uiOverrides.tsx (1)
109-124:ViewMenucomponent defined insideMainMenuis recreated every render.Defining
ViewMenuas an inline component insideMainMenumeans React creates a new component type on each render, causing full unmount/remount of the subtree. For a menu this is likely harmless in practice, but it's better practice to hoist it outside:♻️ Suggested refactor
+const ViewMenu = () => { + const actions = useActions(); + return ( + <TldrawUiMenuSubmenu id="view" label="menu.view"> + <TldrawUiMenuGroup id="view-actions"> + <TldrawUiMenuItem {...actions["zoom-in"]} /> + <TldrawUiMenuItem {...actions["zoom-out"]} /> + <ZoomTo100MenuItem /> + <ZoomToFitMenuItem /> + <ZoomToSelectionMenuItem /> + <TldrawUiMenuItem {...actions["toggle-full-screen"]} /> + </TldrawUiMenuGroup> + </TldrawUiMenuSubmenu> + ); +}; + export const createUiComponents = (): TLUiComponents => ({ // ... MainMenu: () => { - const ViewMenu = () => { - const actions = useActions(); - return ( - <TldrawUiMenuSubmenu id="view" label="menu.view"> - ... - </TldrawUiMenuSubmenu> - ); - }; return ( <DefaultMainMenu> <EditSubmenu /> <ViewMenu />scripts/compile.ts (3)
21-21: Unused variableenvContents.
let envContents = null;is declared but never read or written anywhere in the file.🧹 Remove it
-let envContents = null;
85-90:externalfield in the Zod schema requires a value but has no default.
z.array(z.string())without.default([])meanscliArgs.parse(opts)will throw if a caller provides a customoptswithoutexternal. Sincecompilehas a default foropts(line 124), this only manifests whenoptsis partially overridden. Adding.default([])makes the API more resilient.💡 Suggested fix
const cliArgs = z.object({ out: z.string().optional(), root: z.string().optional(), format: z.enum(["esm"]).optional(), - external: z.array(z.string()), + external: z.array(z.string()).default([]), });
24-72:importAsGlobalsplugin: the file-existence check doubles as a path resolver.Line 56 checks
fs.existsSync(global)whereglobalis the mapping value (e.g.,./node_modules/react/jsx-runtime.js). This is clever but means the mapping value serves dual purpose — it's either a global variable expression or a file path. This could be confusing for future maintainers. A brief inline comment clarifying this behavior would help.src/components/canvas/DefaultNodeUtil.tsx (1)
68-101:searchPagesandsearchBlocksfetch all matching results and sort client-side.When the query is empty (lines 85–91, 120–126), these functions fetch all pages/blocks from Roam and sort them by edit time. For large graphs, this could be very expensive. Consider adding a limit clause in the Datalog query or documenting the expected dataset size.
Also applies to: 103-136
| @@ -1 +1 @@ | |||
| npm run build:roam | |||
| pnpm run build:roam | |||
There was a problem hiding this comment.
Add a shebang line.
The script lacks a shebang, so the shell used to execute it is undefined and platform-dependent. This was also flagged by Shellcheck (SC2148).
Proposed fix
+#!/usr/bin/env bash
pnpm run build:roam📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| pnpm run build:roam | |
| #!/usr/bin/env bash | |
| pnpm run build:roam |
🧰 Tools
🪛 Shellcheck (0.11.0)
[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
(SC2148)
🤖 Prompt for AI Agents
In `@build.sh` at line 1, Add a POSIX-compatible shebang to the top of the script
so the shell is explicit (e.g., add "#!/usr/bin/env bash" as the first line) and
ensure the script is executable (chmod +x). Keep the existing command "pnpm run
build:roam" unchanged; the shebang will ensure it runs under the intended shell
and satisfy Shellcheck SC2148.
| const build = async () => { | ||
| process.env = { | ||
| ...process.env, | ||
| NODE_ENV: process.env.NODE_ENV || "production", | ||
| }; |
There was a problem hiding this comment.
Replacing process.env object can break references held elsewhere.
Assigning a new object to process.env (via spread) means any module that captured a reference to the original process.env will no longer see updates. The dev script at scripts/dev.ts:8 uses the safer direct-assignment pattern.
Proposed fix
const build = async () => {
- process.env = {
- ...process.env,
- NODE_ENV: process.env.NODE_ENV || "production",
- };
+ process.env.NODE_ENV = process.env.NODE_ENV || "production";📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const build = async () => { | |
| process.env = { | |
| ...process.env, | |
| NODE_ENV: process.env.NODE_ENV || "production", | |
| }; | |
| const build = async () => { | |
| process.env.NODE_ENV = process.env.NODE_ENV || "production"; |
🤖 Prompt for AI Agents
In `@scripts/build.ts` around lines 3 - 7, The build function reassigns
process.env to a new object which can break existing references; instead of
replacing process.env in build, set the specific variable directly (e.g., assign
process.env.NODE_ENV = process.env.NODE_ENV || "production") so existing
references remain valid; update the build function in scripts/build.ts (the
build async function) to mutate process.env rather than overwrite it, mirroring
the direct-assignment pattern used in scripts/dev.ts.
| const dev = () => { | ||
| process.env.NODE_ENV = process.env.NODE_ENV || "development"; | ||
| return new Promise<number>((resolve) => { | ||
| compile({ | ||
| opts: args, | ||
| builder: (opts: esbuild.BuildOptions) => | ||
| esbuild.context(opts).then((esb) => esb.watch()), | ||
| }); | ||
| process.on("exit", resolve); | ||
| }); | ||
| }; |
There was a problem hiding this comment.
compile() return value is not awaited — initial build errors will be unhandled rejections.
The promise returned by compile(...) is neither awaited nor .catch()-ed, so if the initial build fails, the error surfaces as an unhandled promise rejection instead of being caught by main()'s try/catch.
Proposed fix
const dev = () => {
process.env.NODE_ENV = process.env.NODE_ENV || "development";
- return new Promise<number>((resolve) => {
- compile({
+ return new Promise<number>((resolve, reject) => {
+ compile({
opts: args,
builder: (opts: esbuild.BuildOptions) =>
esbuild.context(opts).then((esb) => esb.watch()),
- });
+ }).catch(reject);
process.on("exit", resolve);
});
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const dev = () => { | |
| process.env.NODE_ENV = process.env.NODE_ENV || "development"; | |
| return new Promise<number>((resolve) => { | |
| compile({ | |
| opts: args, | |
| builder: (opts: esbuild.BuildOptions) => | |
| esbuild.context(opts).then((esb) => esb.watch()), | |
| }); | |
| process.on("exit", resolve); | |
| }); | |
| }; | |
| const dev = () => { | |
| process.env.NODE_ENV = process.env.NODE_ENV || "development"; | |
| return new Promise<number>((resolve, reject) => { | |
| compile({ | |
| opts: args, | |
| builder: (opts: esbuild.BuildOptions) => | |
| esbuild.context(opts).then((esb) => esb.watch()), | |
| }).catch(reject); | |
| process.on("exit", resolve); | |
| }); | |
| }; |
🤖 Prompt for AI Agents
In `@scripts/dev.ts` around lines 7 - 17, The dev function calls compile(...) but
doesn't await or handle its promise, so initial build errors become unhandled
rejections; update dev to propagate compile failures by either making dev async
and awaiting compile(...) or by adding a reject handler in the returned Promise
(e.g., new Promise<number>((resolve, reject) => { const p = compile(...);
p.then(...).catch(reject); process.on("exit", resolve); })). Ensure you
reference the existing compile(...) invocation and keep the existing builder
logic (esbuild.context(...).then(esb => esb.watch())) while wiring its returned
promise into the dev promise so main()'s try/catch can observe errors.
| editor.registerExternalContentHandler("text", async (content) => { | ||
| if (content.type !== "text") return; | ||
| const trimmedText = content.text.trim(); | ||
| const match = getNodeTypeFromRoamRefText(trimmedText); | ||
| if (!match) { | ||
| await defaultHandleExternalTextContent(editor, { | ||
| point: content.point, | ||
| text: content.text, | ||
| }); | ||
| return; | ||
| } | ||
| const point = | ||
| content.point ?? editor.getViewportPageBounds().center; | ||
| editor.createShape<RoamNodeShape>({ | ||
| id: createShapeId(), | ||
| type: match.type, | ||
| x: point.x, | ||
| y: point.y, | ||
| props: { | ||
| uid: match.uid, | ||
| title: match.title, | ||
| w: 220, | ||
| h: 92, | ||
| }, | ||
| }); | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
tldraw registerExternalContentHandler documentation API
💡 Result:
registerExternalContentHandler is an Editor method in tldraw for customizing how the editor handles external content (paste/drag-drop) for a given content type (e.g. text, image, url, embed). You register (or clear) a handler per type. [1]
API (from docs)
editor.registerExternalContentHandler<T extends TLExternalContent<E>['type'], E>(
type: T,
handler: ((info: /* the matching TLExternalContent payload */) => void) | null
): this- Pass a function to register a handler; pass
nullto remove it. [1]
Docs & examples
- Editor API reference (includes the signature + examples like
editor.registerExternalContentHandler('text', myHandler)and typed'embed'usage). [1] - Example: External content sources shows handling pasted
'text/html'by inspectingsourcesand then creating a custom shape (otherwise falling back to the default handler). [2] - If you want the built-in behavior as a starting point, see
registerDefaultExternalContentHandlers(editor, options)and thedefaultHandleExternal*helpers. [3] [4]
Sources: [1] tldraw Editor reference • registerExternalContentHandler section, [2] “External content sources” example, [3] registerDefaultExternalContentHandlers reference, [4] defaultHandleExternalTextContent reference.
🏁 Script executed:
# First, let's examine the full Tldraw.tsx component to understand the mount/unmount lifecycle
fd "Tldraw.tsx" --type fRepository: RoamJS/tldraw
Length of output: 89
🏁 Script executed:
# Get the full context of the Tldraw.tsx component focusing on hooks and lifecycle
cat -n src/components/canvas/Tldraw.tsx | head -550 | tail -150Repository: RoamJS/tldraw
Length of output: 6368
🏁 Script executed:
# Also check the beginning of the component to find useEffect hooks
cat -n src/components/canvas/Tldraw.tsx | head -100Repository: RoamJS/tldraw
Length of output: 3908
🏁 Script executed:
# Search for useEffect, cleanup, and unmount patterns in Tldraw.tsx
rg "useEffect|cleanup|onUnmount|unmount" src/components/canvas/Tldraw.tsx -nRepository: RoamJS/tldraw
Length of output: 355
🏁 Script executed:
# Check the end of the component file to see if there's any cleanup
tail -100 src/components/canvas/Tldraw.tsxRepository: RoamJS/tldraw
Length of output: 2386
🏁 Script executed:
# Search for any code that might be unregistering the handler or handling Tldraw unmount
rg "registerExternalContentHandler|unregister|null" src/components/canvas/Tldraw.tsx -n -B2 -A2Repository: RoamJS/tldraw
Length of output: 2514
🏁 Script executed:
# Let's examine the useEffect hooks to see if any handle cleanup of the handler
sed -n '165,180p' src/components/canvas/Tldraw.tsxRepository: RoamJS/tldraw
Length of output: 459
🏁 Script executed:
# Also check what happens on component unmount - look for useEffect dependencies
sed -n '361,380p' src/components/canvas/Tldraw.tsxRepository: RoamJS/tldraw
Length of output: 726
🏁 Script executed:
# Let's check how Tldraw component is used - specifically the onUnmount or lifecycle
rg "Tldraw" src/components/canvas/Tldraw.tsx -n -B2 -A10 | grep -A15 "onMount"Repository: RoamJS/tldraw
Length of output: 396
🌐 Web query:
tldraw editor cleanup handlers unmount component lifecycle
💡 Result:
In tldraw, anything you “subscribe” to (events, store listeners, side-effect handlers) should be explicitly unsubscribed/removed in your component’s unmount cleanup.
1) Editor events: editor.on(...) → editor.off(...)
tldraw’s Editor is an EventEmitter; subscribe with on and always unsubscribe with off using the same handler function. (tldraw.dev)
useEffect(() => {
if (!editor) return
const handleChange = (entry: any) => {
// ...
}
editor.on('change', handleChange)
return () => editor.off('change', handleChange)
}, [editor])2) Store subscriptions: editor.store.listen(...) returns a cleanup function
editor.store.listen(...) returns an “unsubscribe” function—call it on unmount. (tldraw.dev)
useEffect(() => {
if (!editor) return
const stop = editor.store.listen((entry) => {
// ...
})
return () => stop()
}, [editor])3) Side-effects (record lifecycle handlers): registration returns a removal function
editor.sideEffects.register*Handler(...) returns () => void that removes the handler—call that on unmount too. (tldraw.dev)
useEffect(() => {
if (!editor) return
const unregister = editor.sideEffects.registerAfterCreateHandler('shape', (shape) => {
// ...
})
return () => unregister()
}, [editor])If you set these up inside Tldraw’s onMount, store the returned cleanup/unregister functions somewhere your React component’s useEffect cleanup can reach (or prefer wiring them in useEffect once you have the editor instance). (tldraw.dev)
Citations:
- 1: https://tldraw.dev/sdk-features/events?utm_source=openai
- 2: https://tldraw.dev/sdk-features/persistence?utm_source=openai
- 3: https://tldraw.dev/reference/store/StoreSideEffects?utm_source=openai
- 4: https://tldraw.dev/docs/editor?utm_source=openai
🏁 Script executed:
# Check if there are any other examples in the codebase of handler cleanup
rg "registerExternalContentHandler" -A5 -B5Repository: RoamJS/tldraw
Length of output: 819
🏁 Script executed:
# Check if registerExternalContentHandler returns a cleanup function or if null is used for removal
# Let's look for any documentation or examples in node_modules or comments
rg "registerExternalContentHandler" -A3 | head -30Repository: RoamJS/tldraw
Length of output: 434
🏁 Script executed:
# Also check if the editor.on("event") handler has cleanup - that's at line 458
sed -n '458,492p' src/components/canvas/Tldraw.tsxRepository: RoamJS/tldraw
Length of output: 1321
Both event listeners and external content handlers registered in onMount require cleanup on unmount.
Line 458: editor.on("event", ...) and line 494: editor.registerExternalContentHandler("text", ...) are registered inside onMount without cleanup. Per tldraw best practices, event listeners must be unsubscribed with editor.off() in a cleanup function, and external content handlers should be unregistered (by passing null) on unmount. Since the component can unmount (via renderWithUnmount), these subscriptions will leak. Move these registrations into useEffect hooks with proper cleanup:
useEffect(() => {
const editor = appRef.current;
if (!editor) return;
const handleEvent = (event) => { /* ... */ };
editor.on("event", handleEvent);
return () => editor.off("event", handleEvent);
}, []);
useEffect(() => {
const editor = appRef.current;
if (!editor) return;
editor.registerExternalContentHandler("text", async (content) => { /* ... */ });
return () => editor.registerExternalContentHandler("text", null);
}, []);🤖 Prompt for AI Agents
In `@src/components/canvas/Tldraw.tsx` around lines 494 - 519, The onMount block
registers listeners without cleanup causing leaks; move the registrations for
editor.on(...) and editor.registerExternalContentHandler("text", ...) into
separate useEffect hooks that run when the editor instance is ready, and in each
effect return a cleanup that calls editor.off(...) for the exact handler
registered and editor.registerExternalContentHandler("text", null) to unregister
the external handler; keep the handler logic (including calls to
getNodeTypeFromRoamRefText, defaultHandleExternalTextContent, createShapeId, and
creating a RoamNodeShape) identical but reference the same handler functions so
they can be removed by editor.off during cleanup.
| /* Roam's main container should be static when tldraw is maximized */ | ||
| .roam-main { | ||
| position: relative; | ||
| } |
There was a problem hiding this comment.
Broad .roam-main rule may cause unintended side-effects.
This selector applies position: relative to all .roam-main elements globally, not only when the tldraw canvas is maximized. If Roam's default positioning for this element is something other than relative, this could break layouts on non-canvas pages. Consider scoping it, e.g., .roam-main:has(.roamjs-tldraw-canvas-container).
💡 Proposed scoping fix
-/* Roam's main container should be static when tldraw is maximized */
-.roam-main {
- position: relative;
-}
+/* Roam's main container should be relative when a tldraw canvas is present */
+.roam-main:has(.roamjs-tldraw-canvas-container) {
+ position: relative;
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /* Roam's main container should be static when tldraw is maximized */ | |
| .roam-main { | |
| position: relative; | |
| } | |
| /* Roam's main container should be relative when a tldraw canvas is present */ | |
| .roam-main:has(.roamjs-tldraw-canvas-container) { | |
| position: relative; | |
| } |
🤖 Prompt for AI Agents
In `@src/components/canvas/tldrawStyles.ts` around lines 71 - 74, The global
`.roam-main { position: relative; }` rule affects all pages; narrow its scope so
it only applies when the tldraw canvas is active — update the selector used in
tldrawStyles.ts to target `.roam-main` only when it contains the canvas (e.g.
`.roam-main:has(.roamjs-tldraw-canvas-container) { position: relative; }`) or,
if :has isn’t acceptable, apply a contextual class when maximizing the canvas
(e.g. add/remove `.roamjs-tldraw-maximized` and use `.roamjs-tldraw-maximized
.roam-main { position: relative; }`) and remove the original broad `.roam-main`
rule.
| Toolbar: () => { | ||
| const tools = useTools(); | ||
| return ( | ||
| <DefaultToolbar> | ||
| {DEFAULT_NODE_TOOLS.map((tool) => ( | ||
| <TldrawUiMenuItem | ||
| key={tool.id} | ||
| {...tools[tool.id]} | ||
| isSelected={useIsToolSelected(tools[tool.id])} | ||
| /> | ||
| ))} | ||
| <DefaultToolbarContent /> | ||
| </DefaultToolbar> | ||
| ); |
There was a problem hiding this comment.
useIsToolSelected called inside .map() violates the Rules of Hooks.
Line 89 calls useIsToolSelected(tools[tool.id]) inside the .map() callback. React hooks must not be called inside loops, conditions, or nested functions. Although DEFAULT_NODE_TOOLS is a fixed-length array (2 items), React's hook ordering contract is still violated, and linters will flag this.
Extract a wrapper component for each tool item:
🔧 Proposed fix
+const ToolbarNodeItem = ({ toolId }: { toolId: string }) => {
+ const tools = useTools();
+ const tool = tools[toolId];
+ const isSelected = useIsToolSelected(tool);
+ return <TldrawUiMenuItem {...tool} isSelected={isSelected} />;
+};
+
export const createUiComponents = (): TLUiComponents => ({
Toolbar: () => {
- const tools = useTools();
return (
<DefaultToolbar>
- {DEFAULT_NODE_TOOLS.map((tool) => (
- <TldrawUiMenuItem
- key={tool.id}
- {...tools[tool.id]}
- isSelected={useIsToolSelected(tools[tool.id])}
- />
+ {DEFAULT_NODE_TOOLS.map((tool) => (
+ <ToolbarNodeItem key={tool.id} toolId={tool.id} />
))}
<DefaultToolbarContent />
</DefaultToolbar>
);
},🤖 Prompt for AI Agents
In `@src/components/canvas/uiOverrides.tsx` around lines 81 - 94, The map in
Toolbar violates the Rules of Hooks by calling useIsToolSelected inside a .map
callback; fix by extracting a new child component (e.g., ToolMenuItem) that
accepts the tool descriptor and the tool data from useTools(), call
useIsToolSelected(toolData) inside that component, and render TldrawUiMenuItem
there; then change the map to return <ToolMenuItem key={tool.id} tool={tool}
toolData={tools[tool.id]} /> so hooks are only invoked at the top level of a
React component (referencing Toolbar, DEFAULT_NODE_TOOLS, useTools,
useIsToolSelected, and TldrawUiMenuItem).
| const setPersistedSnapshot = ({ | ||
| pageUid, | ||
| state, | ||
| }: { | ||
| pageUid: string; | ||
| state: RoamTldrawState; | ||
| }): void => { | ||
| const props = getPageProps(pageUid); | ||
| void window.roamAlphaAPI.data.page.update({ | ||
| page: { | ||
| uid: pageUid, | ||
| props: { | ||
| ...props, | ||
| [ROAM_TLDRAW_KEY]: state, | ||
| }, | ||
| }, | ||
| }); | ||
| }; |
There was a problem hiding this comment.
Unhandled write errors in setPersistedSnapshot.
void discards the promise from window.roamAlphaAPI.data.page.update(...), so any write failure (network error, API error) is silently swallowed. Since this is the persistence path for canvas state, a failed write could cause data loss without any user feedback.
Consider adding a .catch() to at least log failures:
Proposed fix
- void window.roamAlphaAPI.data.page.update({
+ window.roamAlphaAPI.data.page.update({
page: {
uid: pageUid,
props: {
...props,
[ROAM_TLDRAW_KEY]: state,
},
},
- });
+ }).catch((err: unknown) => {
+ console.error("Failed to persist tldraw snapshot:", err);
+ });📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const setPersistedSnapshot = ({ | |
| pageUid, | |
| state, | |
| }: { | |
| pageUid: string; | |
| state: RoamTldrawState; | |
| }): void => { | |
| const props = getPageProps(pageUid); | |
| void window.roamAlphaAPI.data.page.update({ | |
| page: { | |
| uid: pageUid, | |
| props: { | |
| ...props, | |
| [ROAM_TLDRAW_KEY]: state, | |
| }, | |
| }, | |
| }); | |
| }; | |
| const setPersistedSnapshot = ({ | |
| pageUid, | |
| state, | |
| }: { | |
| pageUid: string; | |
| state: RoamTldrawState; | |
| }): void => { | |
| const props = getPageProps(pageUid); | |
| window.roamAlphaAPI.data.page.update({ | |
| page: { | |
| uid: pageUid, | |
| props: { | |
| ...props, | |
| [ROAM_TLDRAW_KEY]: state, | |
| }, | |
| }, | |
| }).catch((err: unknown) => { | |
| console.error("Failed to persist tldraw snapshot:", err); | |
| }); | |
| }; |
🤖 Prompt for AI Agents
In `@src/components/canvas/useRoamStore.ts` around lines 65 - 82, The
setPersistedSnapshot function currently discards errors by using void on
window.roamAlphaAPI.data.page.update; modify setPersistedSnapshot (and its call
sites if needed) to handle promise rejections — either await the update inside
an async function or append a .catch(...) to the returned promise — and
log/report failures (use existing logger or console.error) including pageUid and
the error so write failures to ROAM_TLDRAW_KEY are visible; ensure you still
merge props via getPageProps(pageUid) and do not change the stored payload
shape.
…onfiguration - Downgraded tldraw from version 3.15.5 to 3.15.1 to address compatibility issues. - Updated package.json to include an external dependency for react-dom/client, improving integration with the global ReactDOM object.
… rendering - Simplified the rendering logic by utilizing the BlockString component from roamAlphaAPI. - Replaced the contentRef and innerHTML manipulation with a more straightforward React.createElement approach. - Updated the return structure to use a span for better styling and text handling.
- Removed unnecessary external dependencies from the samepage configuration in package.json. - Added new dependencies for @blueprintjs/core and @juggle/resize-observer in pnpm-lock.yaml to ensure compatibility with React 18. - Updated existing @blueprintjs/core references to the latest version for improved functionality.
| {DEFAULT_NODE_TOOLS.map((tool) => ( | ||
| <TldrawUiMenuItem | ||
| key={tool.id} | ||
| {...tools[tool.id]} | ||
| isSelected={useIsToolSelected(tools[tool.id])} | ||
| /> | ||
| ))} |
There was a problem hiding this comment.
🟡 useIsToolSelected hook called inside .map() loop violates Rules of Hooks
In the Toolbar component returned by createUiComponents, the useIsToolSelected React hook is called inside a .map() callback at line 89, which violates React's Rules of Hooks.
Detailed Explanation
At src/components/canvas/uiOverrides.tsx:85-91, the code does:
{DEFAULT_NODE_TOOLS.map((tool) => (
<TldrawUiMenuItem
key={tool.id}
{...tools[tool.id]}
isSelected={useIsToolSelected(tools[tool.id])}
/>
))}
useIsToolSelected is a React hook (it starts with use and internally calls other hooks). Calling it inside .map() violates the Rules of Hooks, which state hooks must not be called inside loops, conditions, or nested functions.
In this specific case, DEFAULT_NODE_TOOLS is a constant array with exactly 2 elements that never changes, so the number of hook calls is always the same and this won't cause a runtime crash. However, it will trigger ESLint's react-hooks/rules-of-hooks rule and is fragile — if the array ever becomes dynamic, it would break. The proper fix is to extract each tool item into its own component that calls useIsToolSelected at the top level.
Impact: Currently works due to constant array size, but violates React's contract and will break if the array becomes dynamic.
Prompt for agents
In src/components/canvas/uiOverrides.tsx, extract the tool menu items in the Toolbar component (lines 85-91) into a separate component. Create a new component like:
const ToolbarItem = ({ toolId }: { toolId: string }) => {
const tools = useTools();
const tool = tools[toolId];
const isSelected = useIsToolSelected(tool);
return <TldrawUiMenuItem {...tool} isSelected={isSelected} />;
};
Then in the Toolbar component, replace the .map() with:
{DEFAULT_NODE_TOOLS.map((tool) => (
<ToolbarItem key={tool.id} toolId={tool.id} />
))}
This ensures useIsToolSelected is called at the top level of a component, not inside a loop.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@patches/`@blueprintjs__core@3.50.4.patch:
- Around line 1-384: Summary: The esnext build is missing the tooltip type
patch; the ITooltipProps interface in the esnext tooltip declaration lacks
children?: React.ReactNode. Fix: update the esnext tooltip declaration (the
ITooltipProps interface for TooltipProps / ITooltipProps) to include children?:
React.ReactNode exactly like the cjs/esm variants, ensuring the ITooltipProps
declaration for the tooltip component mirrors the other build targets.
🧹 Nitpick comments (5)
tsconfig.json (1)
3-9:"src/types.d.ts"is redundant ininclude.
"src"already covers all files undersrc/, includingsrc/types.d.ts.Proposed fix
"include": [ "src", - "src/types.d.ts", "tailwind.config.ts", "tests", "scripts" ],src/components/canvas/DefaultNodeUtil.tsx (2)
58-126:searchPagesandsearchBlocksare near-duplicates — consider extracting a shared helper.The two functions differ only in the Datalog attribute (
:node/titlevs:block/string) and the binding variable name. A single parameterized helper would eliminate ~30 lines of duplication and ensure future fixes (e.g., pagination, error handling) apply uniformly.Also, in
searchBlocksat line 119, the destructured variable is namedtitlebut it actually represents block string content (?text). This is misleading and could confuse future maintainers.Sketch of a shared helper
+const searchRoamEntities = ( + query: string, + attr: ":node/title" | ":block/string", +): Promise<SearchResult[]> => { + const pattern = escapeRegex(query.trim()); + const binding = attr === ":node/title" ? "?title" : "?text"; + return ( + (pattern + ? window.roamAlphaAPI.data.async.q( + `[:find ?uid ${binding} ?time + :where + [?e ${attr} ${binding}] + [?e :block/uid ?uid] + [(get-else $ ?e :edit/time 0) ?time] + [(re-pattern "(?i)${pattern}") ?re] + [(re-find ?re ${binding})]]`, + ) + : window.roamAlphaAPI.data.async.q( + `[:find ?uid ${binding} ?time + :where + [?e ${attr} ${binding}] + [?e :block/uid ?uid] + [(get-else $ ?e :edit/time 0) ?time]]`, + )) as Promise<[string, string, number][]> + ).then((rows) => + rows + .map(([uid, text, editTime]) => ({ + uid, + title: text, + editTime: editTime || 0, + })) + .sort((a, b) => b.editTime - a.editTime), + ); +}; + +export const searchPages = ({ query }: { query: string }) => + searchRoamEntities(query, ":node/title"); + +export const searchBlocks = ({ query }: { query: string }) => + searchRoamEntities(query, ":block/string");
267-298: Anonymous tool classes created in.map()all share the samedisplayName.Each generated class is named
DefaultNodeToolin the source, but the staticidis correctly set per tool. This means debugging/stack traces will show the same class name for both tools. Not a functional issue, but worth noting.package.json (2)
39-43: Exact-pinned peer dependencies are restrictive.Using exact versions (
18.2.0) forreact/react-dompeers means any host using18.3.xwill get unmet-peer warnings (or errors in strict mode). If this is intentional for Roam Research compatibility, consider adding a comment. Otherwise, use a range like"^18.2.0".
35-35: esbuild@0.17.14 is nearly 3 years old — consider upgrading to the latest version.This exact pin dates to March 26, 2023. Current esbuild (v0.27.3 as of Feb 2026) includes significant performance improvements, bug fixes, security patches, and CSS features. The gap between 0.17.14 and 0.27.3 represents substantial development. If this pin is intentional for compatibility reasons, it's worth documenting.
| diff --git a/lib/cjs/components/alert/alert.d.ts b/lib/cjs/components/alert/alert.d.ts | ||
| index 09b06be01bbe6d22a7dda4aa1652a19b50ff77ec..f74f6a34012e1fa97761bfec2f78fa6ba6dfb0d1 100644 | ||
| --- a/lib/cjs/components/alert/alert.d.ts | ||
| +++ b/lib/cjs/components/alert/alert.d.ts | ||
| @@ -5,6 +5,7 @@ import { IOverlayLifecycleProps } from "../overlay/overlay"; | ||
| export declare type AlertProps = IAlertProps; | ||
| /** @deprecated use AlertProps */ | ||
| export interface IAlertProps extends IOverlayLifecycleProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether pressing <kbd>escape</kbd> when focused on the Alert should cancel the alert. | ||
| * If this prop is enabled, then either `onCancel` or `onClose` must also be defined. | ||
| diff --git a/lib/cjs/components/collapse/collapse.d.ts b/lib/cjs/components/collapse/collapse.d.ts | ||
| index 7f4ef301528cfa44000c9f330dc0e9bd4d26aa63..a93bb0951783f56799a16431110ac280a38ffba9 100644 | ||
| --- a/lib/cjs/components/collapse/collapse.d.ts | ||
| +++ b/lib/cjs/components/collapse/collapse.d.ts | ||
| @@ -4,6 +4,7 @@ import { Props } from "../../common/props"; | ||
| export declare type CollapseProps = ICollapseProps; | ||
| /** @deprecated use CollapseProps */ | ||
| export interface ICollapseProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Component to render as the root element. | ||
| * Useful when rendering a `Collapse` inside a `<table>`, for instance. | ||
| diff --git a/lib/cjs/components/dialog/dialog.d.ts b/lib/cjs/components/dialog/dialog.d.ts | ||
| index e90ee312da59d1e7a404dd029a79af640a9c3ea4..3e4f4ef68fd429fb9e272df3c730e556c163dca4 100644 | ||
| --- a/lib/cjs/components/dialog/dialog.d.ts | ||
| +++ b/lib/cjs/components/dialog/dialog.d.ts | ||
| @@ -6,6 +6,7 @@ import { IBackdropProps, OverlayableProps } from "../overlay/overlay"; | ||
| export declare type DialogProps = IDialogProps; | ||
| /** @deprecated use DialogProps */ | ||
| export interface IDialogProps extends OverlayableProps, IBackdropProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Toggles the visibility of the overlay and its children. | ||
| * This prop is required because the component is controlled. | ||
| diff --git a/lib/cjs/components/drawer/drawer.d.ts b/lib/cjs/components/drawer/drawer.d.ts | ||
| index 301ed2e66dfb42850c5671220b8c5241df560e9a..24d4b161d42d201f9f45f9ab8f1f874746db4430 100644 | ||
| --- a/lib/cjs/components/drawer/drawer.d.ts | ||
| +++ b/lib/cjs/components/drawer/drawer.d.ts | ||
| @@ -12,6 +12,7 @@ export declare enum DrawerSize { | ||
| export declare type DrawerProps = IDrawerProps; | ||
| /** @deprecated use DrawerProps */ | ||
| export interface IDrawerProps extends OverlayableProps, IBackdropProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Name of a Blueprint UI icon (or an icon element) to render in the | ||
| * drawer's header. Note that the header will only be rendered if `title` is | ||
| diff --git a/lib/cjs/components/forms/formGroup.d.ts b/lib/cjs/components/forms/formGroup.d.ts | ||
| index 1b69eeb6f353e44c1400a223c129cba88738e655..961ba5ef85105aed8db86c7d64254d468baa3b7f 100644 | ||
| --- a/lib/cjs/components/forms/formGroup.d.ts | ||
| +++ b/lib/cjs/components/forms/formGroup.d.ts | ||
| @@ -4,6 +4,7 @@ import { IntentProps, Props } from "../../common/props"; | ||
| export declare type FormGroupProps = IFormGroupProps; | ||
| /** @deprecated use FormGroupProps */ | ||
| export interface IFormGroupProps extends IntentProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * A space-delimited list of class names to pass along to the | ||
| * `Classes.FORM_CONTENT` element that contains `children`. | ||
| diff --git a/lib/cjs/components/forms/radioGroup.d.ts b/lib/cjs/components/forms/radioGroup.d.ts | ||
| index 2f21804fca8599d6d98a6be80473d03a52419196..e96697514e15a44aa614e4086503848614956210 100644 | ||
| --- a/lib/cjs/components/forms/radioGroup.d.ts | ||
| +++ b/lib/cjs/components/forms/radioGroup.d.ts | ||
| @@ -4,6 +4,7 @@ import { OptionProps, Props } from "../../common/props"; | ||
| export declare type RadioGroupProps = IRadioGroupProps; | ||
| /** @deprecated use RadioGroupProps */ | ||
| export interface IRadioGroupProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether the group and _all_ its radios are disabled. | ||
| * Individual radios can be disabled using their `disabled` prop. | ||
| diff --git a/lib/cjs/components/popover/popover.d.ts b/lib/cjs/components/popover/popover.d.ts | ||
| index e1490579f16bbc57b9bd37e0d782a4c7c55196fa..f3cdf4a9fe3bd32e19bd9220662115930a94e03f 100644 | ||
| --- a/lib/cjs/components/popover/popover.d.ts | ||
| +++ b/lib/cjs/components/popover/popover.d.ts | ||
| @@ -9,6 +9,7 @@ export declare const PopoverInteractionKind: { | ||
| }; | ||
| export declare type PopoverInteractionKind = typeof PopoverInteractionKind[keyof typeof PopoverInteractionKind]; | ||
| export interface IPopoverProps extends IPopoverSharedProps { | ||
| + children?: React.ReactNode; | ||
| /** HTML props for the backdrop element. Can be combined with `backdropClassName`. */ | ||
| backdropProps?: React.HTMLProps<HTMLDivElement>; | ||
| /** | ||
| diff --git a/lib/cjs/components/portal/portal.d.ts b/lib/cjs/components/portal/portal.d.ts | ||
| index 9e3460b460c48dad99ef04c26261094bb5c4a5d3..5ffb40eeb79c6fc838d63b1261eafc964bd26b14 100644 | ||
| --- a/lib/cjs/components/portal/portal.d.ts | ||
| +++ b/lib/cjs/components/portal/portal.d.ts | ||
| @@ -3,6 +3,7 @@ import { ValidationMap } from "../../common/context"; | ||
| import { Props } from "../../common/props"; | ||
| export declare type PortalProps = IPortalProps; | ||
| export interface IPortalProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Callback invoked when the children of this `Portal` have been added to the DOM. | ||
| */ | ||
| diff --git a/lib/cjs/components/tabs/tabs.d.ts b/lib/cjs/components/tabs/tabs.d.ts | ||
| index 2ca5fe5b4bed0871154292aa3248af1f2ea8331d..870a32ee7d2bd6c934216e268016b4b2d2e2b514 100644 | ||
| --- a/lib/cjs/components/tabs/tabs.d.ts | ||
| +++ b/lib/cjs/components/tabs/tabs.d.ts | ||
| @@ -6,6 +6,7 @@ export declare const Expander: React.FunctionComponent; | ||
| export declare type TabsProps = ITabsProps; | ||
| /** @deprecated use TabsProps */ | ||
| export interface ITabsProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether the selected tab indicator should animate its movement. | ||
| * | ||
| diff --git a/lib/cjs/components/toast/toaster.d.ts b/lib/cjs/components/toast/toaster.d.ts | ||
| index a6c712467c7ac81aed9ea00207aeaaeb14bd9337..353621182cb1c4d8c5ea6430504ab0ed38fec195 100644 | ||
| --- a/lib/cjs/components/toast/toaster.d.ts | ||
| +++ b/lib/cjs/components/toast/toaster.d.ts | ||
| @@ -26,6 +26,7 @@ export interface IToaster { | ||
| * These props can be passed as an argument to the static `Toaster.create(props?, container?)` method. | ||
| */ | ||
| export interface IToasterProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether a toast should acquire application focus when it first opens. | ||
| * This is disabled by default so that toasts do not interrupt the user's flow. | ||
| diff --git a/lib/cjs/components/tooltip/tooltip.d.ts b/lib/cjs/components/tooltip/tooltip.d.ts | ||
| index 94f4af9427a35ad9333f2bfd30ab712499efcd57..4db48a9bc4cac14aacd90535f403f87b76445815 100644 | ||
| --- a/lib/cjs/components/tooltip/tooltip.d.ts | ||
| +++ b/lib/cjs/components/tooltip/tooltip.d.ts | ||
| @@ -6,6 +6,7 @@ import { IPopoverSharedProps } from "../popover/popoverSharedProps"; | ||
| export declare type TooltipProps = ITooltipProps; | ||
| /** @deprecated use TooltipProps */ | ||
| export interface ITooltipProps extends IPopoverSharedProps, IntentProps { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * The content that will be displayed inside of the tooltip. | ||
| */ | ||
| diff --git a/lib/esm/components/alert/alert.d.ts b/lib/esm/components/alert/alert.d.ts | ||
| index 09b06be01bbe6d22a7dda4aa1652a19b50ff77ec..f74f6a34012e1fa97761bfec2f78fa6ba6dfb0d1 100644 | ||
| --- a/lib/esm/components/alert/alert.d.ts | ||
| +++ b/lib/esm/components/alert/alert.d.ts | ||
| @@ -5,6 +5,7 @@ import { IOverlayLifecycleProps } from "../overlay/overlay"; | ||
| export declare type AlertProps = IAlertProps; | ||
| /** @deprecated use AlertProps */ | ||
| export interface IAlertProps extends IOverlayLifecycleProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether pressing <kbd>escape</kbd> when focused on the Alert should cancel the alert. | ||
| * If this prop is enabled, then either `onCancel` or `onClose` must also be defined. | ||
| diff --git a/lib/esm/components/collapse/collapse.d.ts b/lib/esm/components/collapse/collapse.d.ts | ||
| index 7f4ef301528cfa44000c9f330dc0e9bd4d26aa63..a93bb0951783f56799a16431110ac280a38ffba9 100644 | ||
| --- a/lib/esm/components/collapse/collapse.d.ts | ||
| +++ b/lib/esm/components/collapse/collapse.d.ts | ||
| @@ -4,6 +4,7 @@ import { Props } from "../../common/props"; | ||
| export declare type CollapseProps = ICollapseProps; | ||
| /** @deprecated use CollapseProps */ | ||
| export interface ICollapseProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Component to render as the root element. | ||
| * Useful when rendering a `Collapse` inside a `<table>`, for instance. | ||
| diff --git a/lib/esm/components/dialog/dialog.d.ts b/lib/esm/components/dialog/dialog.d.ts | ||
| index e90ee312da59d1e7a404dd029a79af640a9c3ea4..3e4f4ef68fd429fb9e272df3c730e556c163dca4 100644 | ||
| --- a/lib/esm/components/dialog/dialog.d.ts | ||
| +++ b/lib/esm/components/dialog/dialog.d.ts | ||
| @@ -6,6 +6,7 @@ import { IBackdropProps, OverlayableProps } from "../overlay/overlay"; | ||
| export declare type DialogProps = IDialogProps; | ||
| /** @deprecated use DialogProps */ | ||
| export interface IDialogProps extends OverlayableProps, IBackdropProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Toggles the visibility of the overlay and its children. | ||
| * This prop is required because the component is controlled. | ||
| diff --git a/lib/esm/components/drawer/drawer.d.ts b/lib/esm/components/drawer/drawer.d.ts | ||
| index 301ed2e66dfb42850c5671220b8c5241df560e9a..24d4b161d42d201f9f45f9ab8f1f874746db4430 100644 | ||
| --- a/lib/esm/components/drawer/drawer.d.ts | ||
| +++ b/lib/esm/components/drawer/drawer.d.ts | ||
| @@ -12,6 +12,7 @@ export declare enum DrawerSize { | ||
| export declare type DrawerProps = IDrawerProps; | ||
| /** @deprecated use DrawerProps */ | ||
| export interface IDrawerProps extends OverlayableProps, IBackdropProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Name of a Blueprint UI icon (or an icon element) to render in the | ||
| * drawer's header. Note that the header will only be rendered if `title` is | ||
| diff --git a/lib/esm/components/forms/formGroup.d.ts b/lib/esm/components/forms/formGroup.d.ts | ||
| index 1b69eeb6f353e44c1400a223c129cba88738e655..961ba5ef85105aed8db86c7d64254d468baa3b7f 100644 | ||
| --- a/lib/esm/components/forms/formGroup.d.ts | ||
| +++ b/lib/esm/components/forms/formGroup.d.ts | ||
| @@ -4,6 +4,7 @@ import { IntentProps, Props } from "../../common/props"; | ||
| export declare type FormGroupProps = IFormGroupProps; | ||
| /** @deprecated use FormGroupProps */ | ||
| export interface IFormGroupProps extends IntentProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * A space-delimited list of class names to pass along to the | ||
| * `Classes.FORM_CONTENT` element that contains `children`. | ||
| diff --git a/lib/esm/components/forms/radioGroup.d.ts b/lib/esm/components/forms/radioGroup.d.ts | ||
| index 2f21804fca8599d6d98a6be80473d03a52419196..e96697514e15a44aa614e4086503848614956210 100644 | ||
| --- a/lib/esm/components/forms/radioGroup.d.ts | ||
| +++ b/lib/esm/components/forms/radioGroup.d.ts | ||
| @@ -4,6 +4,7 @@ import { OptionProps, Props } from "../../common/props"; | ||
| export declare type RadioGroupProps = IRadioGroupProps; | ||
| /** @deprecated use RadioGroupProps */ | ||
| export interface IRadioGroupProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether the group and _all_ its radios are disabled. | ||
| * Individual radios can be disabled using their `disabled` prop. | ||
| diff --git a/lib/esm/components/popover/popover.d.ts b/lib/esm/components/popover/popover.d.ts | ||
| index e1490579f16bbc57b9bd37e0d782a4c7c55196fa..f3cdf4a9fe3bd32e19bd9220662115930a94e03f 100644 | ||
| --- a/lib/esm/components/popover/popover.d.ts | ||
| +++ b/lib/esm/components/popover/popover.d.ts | ||
| @@ -9,6 +9,7 @@ export declare const PopoverInteractionKind: { | ||
| }; | ||
| export declare type PopoverInteractionKind = typeof PopoverInteractionKind[keyof typeof PopoverInteractionKind]; | ||
| export interface IPopoverProps extends IPopoverSharedProps { | ||
| + children?: React.ReactNode; | ||
| /** HTML props for the backdrop element. Can be combined with `backdropClassName`. */ | ||
| backdropProps?: React.HTMLProps<HTMLDivElement>; | ||
| /** | ||
| diff --git a/lib/esm/components/portal/portal.d.ts b/lib/esm/components/portal/portal.d.ts | ||
| index 9e3460b460c48dad99ef04c26261094bb5c4a5d3..5ffb40eeb79c6fc838d63b1261eafc964bd26b14 100644 | ||
| --- a/lib/esm/components/portal/portal.d.ts | ||
| +++ b/lib/esm/components/portal/portal.d.ts | ||
| @@ -3,6 +3,7 @@ import { ValidationMap } from "../../common/context"; | ||
| import { Props } from "../../common/props"; | ||
| export declare type PortalProps = IPortalProps; | ||
| export interface IPortalProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Callback invoked when the children of this `Portal` have been added to the DOM. | ||
| */ | ||
| diff --git a/lib/esm/components/tabs/tabs.d.ts b/lib/esm/components/tabs/tabs.d.ts | ||
| index 2ca5fe5b4bed0871154292aa3248af1f2ea8331d..870a32ee7d2bd6c934216e268016b4b2d2e2b514 100644 | ||
| --- a/lib/esm/components/tabs/tabs.d.ts | ||
| +++ b/lib/esm/components/tabs/tabs.d.ts | ||
| @@ -6,6 +6,7 @@ export declare const Expander: React.FunctionComponent; | ||
| export declare type TabsProps = ITabsProps; | ||
| /** @deprecated use TabsProps */ | ||
| export interface ITabsProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether the selected tab indicator should animate its movement. | ||
| * | ||
| diff --git a/lib/esm/components/toast/toaster.d.ts b/lib/esm/components/toast/toaster.d.ts | ||
| index a6c712467c7ac81aed9ea00207aeaaeb14bd9337..353621182cb1c4d8c5ea6430504ab0ed38fec195 100644 | ||
| --- a/lib/esm/components/toast/toaster.d.ts | ||
| +++ b/lib/esm/components/toast/toaster.d.ts | ||
| @@ -26,6 +26,7 @@ export interface IToaster { | ||
| * These props can be passed as an argument to the static `Toaster.create(props?, container?)` method. | ||
| */ | ||
| export interface IToasterProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether a toast should acquire application focus when it first opens. | ||
| * This is disabled by default so that toasts do not interrupt the user's flow. | ||
| diff --git a/lib/esm/components/tooltip/tooltip.d.ts b/lib/esm/components/tooltip/tooltip.d.ts | ||
| index 94f4af9427a35ad9333f2bfd30ab712499efcd57..4db48a9bc4cac14aacd90535f403f87b76445815 100644 | ||
| --- a/lib/esm/components/tooltip/tooltip.d.ts | ||
| +++ b/lib/esm/components/tooltip/tooltip.d.ts | ||
| @@ -6,6 +6,7 @@ import { IPopoverSharedProps } from "../popover/popoverSharedProps"; | ||
| export declare type TooltipProps = ITooltipProps; | ||
| /** @deprecated use TooltipProps */ | ||
| export interface ITooltipProps extends IPopoverSharedProps, IntentProps { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * The content that will be displayed inside of the tooltip. | ||
| */ | ||
| diff --git a/lib/esnext/components/alert/alert.d.ts b/lib/esnext/components/alert/alert.d.ts | ||
| index 09b06be01bbe6d22a7dda4aa1652a19b50ff77ec..f74f6a34012e1fa97761bfec2f78fa6ba6dfb0d1 100644 | ||
| --- a/lib/esnext/components/alert/alert.d.ts | ||
| +++ b/lib/esnext/components/alert/alert.d.ts | ||
| @@ -5,6 +5,7 @@ import { IOverlayLifecycleProps } from "../overlay/overlay"; | ||
| export declare type AlertProps = IAlertProps; | ||
| /** @deprecated use AlertProps */ | ||
| export interface IAlertProps extends IOverlayLifecycleProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether pressing <kbd>escape</kbd> when focused on the Alert should cancel the alert. | ||
| * If this prop is enabled, then either `onCancel` or `onClose` must also be defined. | ||
| diff --git a/lib/esnext/components/collapse/collapse.d.ts b/lib/esnext/components/collapse/collapse.d.ts | ||
| index 7f4ef301528cfa44000c9f330dc0e9bd4d26aa63..a93bb0951783f56799a16431110ac280a38ffba9 100644 | ||
| --- a/lib/esnext/components/collapse/collapse.d.ts | ||
| +++ b/lib/esnext/components/collapse/collapse.d.ts | ||
| @@ -4,6 +4,7 @@ import { Props } from "../../common/props"; | ||
| export declare type CollapseProps = ICollapseProps; | ||
| /** @deprecated use CollapseProps */ | ||
| export interface ICollapseProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Component to render as the root element. | ||
| * Useful when rendering a `Collapse` inside a `<table>`, for instance. | ||
| diff --git a/lib/esnext/components/dialog/dialog.d.ts b/lib/esnext/components/dialog/dialog.d.ts | ||
| index e90ee312da59d1e7a404dd029a79af640a9c3ea4..3e4f4ef68fd429fb9e272df3c730e556c163dca4 100644 | ||
| --- a/lib/esnext/components/dialog/dialog.d.ts | ||
| +++ b/lib/esnext/components/dialog/dialog.d.ts | ||
| @@ -6,6 +6,7 @@ import { IBackdropProps, OverlayableProps } from "../overlay/overlay"; | ||
| export declare type DialogProps = IDialogProps; | ||
| /** @deprecated use DialogProps */ | ||
| export interface IDialogProps extends OverlayableProps, IBackdropProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Toggles the visibility of the overlay and its children. | ||
| * This prop is required because the component is controlled. | ||
| diff --git a/lib/esnext/components/drawer/drawer.d.ts b/lib/esnext/components/drawer/drawer.d.ts | ||
| index 301ed2e66dfb42850c5671220b8c5241df560e9a..24d4b161d42d201f9f45f9ab8f1f874746db4430 100644 | ||
| --- a/lib/esnext/components/drawer/drawer.d.ts | ||
| +++ b/lib/esnext/components/drawer/drawer.d.ts | ||
| @@ -12,6 +12,7 @@ export declare enum DrawerSize { | ||
| export declare type DrawerProps = IDrawerProps; | ||
| /** @deprecated use DrawerProps */ | ||
| export interface IDrawerProps extends OverlayableProps, IBackdropProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Name of a Blueprint UI icon (or an icon element) to render in the | ||
| * drawer's header. Note that the header will only be rendered if `title` is | ||
| diff --git a/lib/esnext/components/forms/formGroup.d.ts b/lib/esnext/components/forms/formGroup.d.ts | ||
| index 1b69eeb6f353e44c1400a223c129cba88738e655..961ba5ef85105aed8db86c7d64254d468baa3b7f 100644 | ||
| --- a/lib/esnext/components/forms/formGroup.d.ts | ||
| +++ b/lib/esnext/components/forms/formGroup.d.ts | ||
| @@ -4,6 +4,7 @@ import { IntentProps, Props } from "../../common/props"; | ||
| export declare type FormGroupProps = IFormGroupProps; | ||
| /** @deprecated use FormGroupProps */ | ||
| export interface IFormGroupProps extends IntentProps, Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * A space-delimited list of class names to pass along to the | ||
| * `Classes.FORM_CONTENT` element that contains `children`. | ||
| diff --git a/lib/esnext/components/forms/radioGroup.d.ts b/lib/esnext/components/forms/radioGroup.d.ts | ||
| index 2f21804fca8599d6d98a6be80473d03a52419196..e96697514e15a44aa614e4086503848614956210 100644 | ||
| --- a/lib/esnext/components/forms/radioGroup.d.ts | ||
| +++ b/lib/esnext/components/forms/radioGroup.d.ts | ||
| @@ -4,6 +4,7 @@ import { OptionProps, Props } from "../../common/props"; | ||
| export declare type RadioGroupProps = IRadioGroupProps; | ||
| /** @deprecated use RadioGroupProps */ | ||
| export interface IRadioGroupProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether the group and _all_ its radios are disabled. | ||
| * Individual radios can be disabled using their `disabled` prop. | ||
| diff --git a/lib/esnext/components/popover/popover.d.ts b/lib/esnext/components/popover/popover.d.ts | ||
| index e1490579f16bbc57b9bd37e0d782a4c7c55196fa..f3cdf4a9fe3bd32e19bd9220662115930a94e03f 100644 | ||
| --- a/lib/esnext/components/popover/popover.d.ts | ||
| +++ b/lib/esnext/components/popover/popover.d.ts | ||
| @@ -9,6 +9,7 @@ export declare const PopoverInteractionKind: { | ||
| }; | ||
| export declare type PopoverInteractionKind = typeof PopoverInteractionKind[keyof typeof PopoverInteractionKind]; | ||
| export interface IPopoverProps extends IPopoverSharedProps { | ||
| + children?: React.ReactNode; | ||
| /** HTML props for the backdrop element. Can be combined with `backdropClassName`. */ | ||
| backdropProps?: React.HTMLProps<HTMLDivElement>; | ||
| /** | ||
| diff --git a/lib/esnext/components/portal/portal.d.ts b/lib/esnext/components/portal/portal.d.ts | ||
| index 9e3460b460c48dad99ef04c26261094bb5c4a5d3..5ffb40eeb79c6fc838d63b1261eafc964bd26b14 100644 | ||
| --- a/lib/esnext/components/portal/portal.d.ts | ||
| +++ b/lib/esnext/components/portal/portal.d.ts | ||
| @@ -3,6 +3,7 @@ import { ValidationMap } from "../../common/context"; | ||
| import { Props } from "../../common/props"; | ||
| export declare type PortalProps = IPortalProps; | ||
| export interface IPortalProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Callback invoked when the children of this `Portal` have been added to the DOM. | ||
| */ | ||
| diff --git a/lib/esnext/components/tabs/tabs.d.ts b/lib/esnext/components/tabs/tabs.d.ts | ||
| index 2ca5fe5b4bed0871154292aa3248af1f2ea8331d..870a32ee7d2bd6c934216e268016b4b2d2e2b514 100644 | ||
| --- a/lib/esnext/components/tabs/tabs.d.ts | ||
| +++ b/lib/esnext/components/tabs/tabs.d.ts | ||
| @@ -6,6 +6,7 @@ export declare const Expander: React.FunctionComponent; | ||
| export declare type TabsProps = ITabsProps; | ||
| /** @deprecated use TabsProps */ | ||
| export interface ITabsProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether the selected tab indicator should animate its movement. | ||
| * | ||
| diff --git a/lib/esnext/components/toast/toaster.d.ts b/lib/esnext/components/toast/toaster.d.ts | ||
| index a6c712467c7ac81aed9ea00207aeaaeb14bd9337..353621182cb1c4d8c5ea6430504ab0ed38fec195 100644 | ||
| --- a/lib/esnext/components/toast/toaster.d.ts | ||
| +++ b/lib/esnext/components/toast/toaster.d.ts | ||
| @@ -26,6 +26,7 @@ export interface IToaster { | ||
| * These props can be passed as an argument to the static `Toaster.create(props?, container?)` method. | ||
| */ | ||
| export interface IToasterProps extends Props { | ||
| + children?: React.ReactNode; | ||
| /** | ||
| * Whether a toast should acquire application focus when it first opens. | ||
| * This is disabled by default so that toasts do not interrupt the user's flow. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all tooltip.d.ts files and check for ITooltipProps
echo "=== Finding tooltip.d.ts files ==="
find . -name "tooltip.d.ts" -type f 2>/dev/null | sort
echo -e "\n=== Checking ITooltipProps in each tooltip.d.ts ==="
find . -name "tooltip.d.ts" -type f 2>/dev/null | sort | while read file; do
echo -e "\n$file:"
grep -n "ITooltipProps" "$file" | head -5
doneRepository: RoamJS/tldraw
Length of output: 144
🏁 Script executed:
#!/bin/bash
# Check the patch file for tooltip entries
echo "=== Counting tooltip patches in the patch file ==="
grep -c "lib/.*/components/tooltip/tooltip.d.ts" patches/@blueprintjs__core@3.50.4.patch
echo -e "\n=== All tooltip patches found ==="
grep "lib/.*/components/tooltip/tooltip.d.ts" patches/@blueprintjs__core@3.50.4.patch
echo -e "\n=== Line count of patch file ==="
wc -l patches/@blueprintjs__core@3.50.4.patch
echo -e "\n=== Last 50 lines of patch file to check if it's truncated ==="
tail -50 patches/@blueprintjs__core@3.50.4.patchRepository: RoamJS/tldraw
Length of output: 3438
🏁 Script executed:
#!/bin/bash
# Verify the specific claim about esnext tooltip being missing
echo "=== Searching for esnext tooltip in patch file ==="
grep "esnext.*tooltip" patches/@blueprintjs__core@3.50.4.patch
echo -e "\n=== Listing all esnext files patched ==="
grep "diff --git a/lib/esnext" patches/@blueprintjs__core@3.50.4.patch | sed 's/diff --git a\///' | sed 's/ .*//'
echo -e "\n=== Comparing component counts across build targets ==="
echo "cjs components:"
grep "diff --git a/lib/cjs/components" patches/@blueprintjs__core@3.50.4.patch | wc -l
echo "esm components:"
grep "diff --git a/lib/esm/components" patches/@blueprintjs__core@3.50.4.patch | wc -l
echo "esnext components:"
grep "diff --git a/lib/esnext/components" patches/@blueprintjs__core@3.50.4.patch | wc -lRepository: RoamJS/tldraw
Length of output: 681
Missing esnext variant for tooltip component patch.
This patch correctly adds children?: React.ReactNode to multiple component interfaces for React 18 compatibility. However, lib/esnext/components/tooltip/tooltip.d.ts is missing from this patch.
The cjs and esm build targets include tooltip patches (11 components each), but the esnext variant only patches 10 components, excluding tooltip. Add the esnext tooltip patch to maintain consistency across all build targets:
diff --git a/lib/esnext/components/tooltip/tooltip.d.ts b/lib/esnext/components/tooltip/tooltip.d.ts
index 94f4af9427a35ad9333f2bfd30ab712499efcd57..4db48a9bc4cac14aacd90535f403f87b76445815 100644
--- a/lib/esnext/components/tooltip/tooltip.d.ts
+++ b/lib/esnext/components/tooltip/tooltip.d.ts
@@ -6,6 +6,7 @@ import { IPopoverSharedProps } from "../popover/popoverSharedProps";
export declare type TooltipProps = ITooltipProps;
/** `@deprecated` use TooltipProps */
export interface ITooltipProps extends IPopoverSharedProps, IntentProps {
+ children?: React.ReactNode;
/**
* The content that will be displayed inside of the tooltip.
*/🤖 Prompt for AI Agents
In `@patches/`@blueprintjs__core@3.50.4.patch around lines 1 - 384, Summary: The
esnext build is missing the tooltip type patch; the ITooltipProps interface in
the esnext tooltip declaration lacks children?: React.ReactNode. Fix: update the
esnext tooltip declaration (the ITooltipProps interface for TooltipProps /
ITooltipProps) to include children?: React.ReactNode exactly like the cjs/esm
variants, ensuring the ITooltipProps declaration for the tooltip component
mirrors the other build targets.
Summary by CodeRabbit
New Features
Chores