Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
411 changes: 95 additions & 316 deletions package-lock.json

Large diffs are not rendered by default.

28 changes: 18 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "roamjs-components",
"description": "Expansive toolset, utilities, & components for developing RoamJS extensions.",
"version": "0.85.1",
"version": "0.86.0-alpha.3",
"main": "index.js",
"types": "index.d.ts",
"scripts": {
Expand All @@ -26,8 +26,8 @@
"@types/jsdom": "^20.0.1",
"@types/marked": "^4.0.3",
"@types/nanoid": "2.0.0",
"@types/react": "17.0.39",
"@types/react-dom": "17.0.13",
"@types/react": "18.2.0",
"@types/react-dom": "18.2.0",
Comment on lines +29 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

React and TypeScript definitions upgraded consistently.

The upgrade to React 18.2.0 with matching TypeScript definitions is properly coordinated.

Also applies to: 43-44


🌐 Web query:

Is React 18.2.0 the latest stable version of React, and are there any known security vulnerabilities?

💡 Result:

As of August 3, 2025, the latest stable version of React is 19.1.0, released on March 28, 2025. (github.com) React 18.2.0, released on June 14, 2022, is not the latest stable version.

Regarding security vulnerabilities, Snyk reports that the latest version, 19.1.1, has no known vulnerabilities. (security.snyk.io) However, earlier versions, such as 0.0.1 to 0.13.0, have been identified with cross-site scripting (XSS) vulnerabilities. It's important to note that these vulnerabilities are present in older versions and have been addressed in subsequent releases.

Therefore, to ensure your application remains secure, it's recommended to use the latest stable version of React, which currently is 19.1.0.

Citations:


Upgrade React and TypeScript definitions to latest stable (19.1.0)

React 18.2.0 is no longer the latest stable release. As of August 2025, React 19.1.0 is the current stable version with no known security vulnerabilities. Please update both React and its TypeScript definitions to keep dependencies secure and up-to-date.

Areas to update in package.json:

  • Lines 29–30 ("@types/react", "@types/react-dom")
  • Lines 43–44 ("react", "react-dom")

Suggested diff:

-    "react": "18.2.0",
-    "react-dom": "18.2.0",
+    "react": "19.1.0",
+    "react-dom": "19.1.0",
 
-    "@types/react": "18.2.0",
-    "@types/react-dom": "18.2.0",
+    "@types/react": "19.1.0",
+    "@types/react-dom": "19.1.0",
📝 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.

Suggested change
"@types/react": "18.2.0",
"@types/react-dom": "18.2.0",
// … other dependencies …
"react": "19.1.0",
"react-dom": "19.1.0",
// … other devDependencies …
"@types/react": "19.1.0",
"@types/react-dom": "19.1.0",
// …
🤖 Prompt for AI Agents
In package.json around lines 29 to 30 and 43 to 44, update the versions of
"@types/react" and "@types/react-dom" from "18.2.0" to "19.1.0", and also update
"react" and "react-dom" dependencies to version "19.1.0". This ensures both
React and its TypeScript definitions are upgraded to the latest stable release.

"@types/use-sync-external-store": "^0.0.3",
"chrono-node": "2.3.0",
"crypto-js": "3.1.9-1",
Expand All @@ -40,14 +40,13 @@
"marked": "4.0.16",
"marked-react": "1.1.2",
"nanoid": "2.0.4",
"react": "17.0.2",
"react-dom": "17.0.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"tslib": "2.2.0",
"use-sync-external-store": "^1.2.0"
},
"dependencies": {
"@samepage/scripts": "^0.74.2",
"aws-sdk-plus": "^0.5.3",
"color": "^4.0.1",
"date-fns": "^2.27.0",
"edn-data": "^1.0.0",
Expand All @@ -68,7 +67,8 @@
"http-server": "^14.1.1",
"prettier": "^2.3.1",
"tslint-config-prettier": "^1.18.0",
"tslint-react-hooks": "^2.2.2"
"tslint-react-hooks": "^2.2.2",
"dotenv": "16.3.1"
},
"engines": {
"npm": ">=7.0.0",
Expand All @@ -78,9 +78,17 @@
"roamjs": "./scripts/index.js"
},
"overrides": {
"@testing-library/react": {
"react": "17.0.2",
"react-dom": "17.0.2"
"@blueprintjs/core": {
"react": "18.2.0",
"react-dom": "18.2.0"
},
"@blueprintjs/datetime": {
"react": "18.2.0",
"react-dom": "18.2.0"
},
"@blueprintjs/select": {
"react": "18.2.0",
"react-dom": "18.2.0"
}
},
"samepage": {
Expand Down
48 changes: 48 additions & 0 deletions patches/@blueprintjs+core+3.50.4.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
diff --git a/node_modules/@blueprintjs/core/lib/esm/components/alert/alert.d.ts b/node_modules/@blueprintjs/core/lib/esm/components/alert/alert.d.ts
index 09b06be..f74f6a3 100644
--- a/node_modules/@blueprintjs/core/lib/esm/components/alert/alert.d.ts
+++ b/node_modules/@blueprintjs/core/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/node_modules/@blueprintjs/core/lib/esm/components/dialog/dialog.d.ts b/node_modules/@blueprintjs/core/lib/esm/components/dialog/dialog.d.ts
index e90ee31..3e4f4ef 100644
--- a/node_modules/@blueprintjs/core/lib/esm/components/dialog/dialog.d.ts
+++ b/node_modules/@blueprintjs/core/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/node_modules/@blueprintjs/core/lib/esm/components/tabs/tabs.d.ts b/node_modules/@blueprintjs/core/lib/esm/components/tabs/tabs.d.ts
index 2ca5fe5..870a32e 100644
--- a/node_modules/@blueprintjs/core/lib/esm/components/tabs/tabs.d.ts
+++ b/node_modules/@blueprintjs/core/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/node_modules/@blueprintjs/core/lib/esm/components/tooltip/tooltip.d.ts b/node_modules/@blueprintjs/core/lib/esm/components/tooltip/tooltip.d.ts
index 94f4af9..4db48a9 100644
--- a/node_modules/@blueprintjs/core/lib/esm/components/tooltip/tooltip.d.ts
+++ b/node_modules/@blueprintjs/core/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.
*/
12 changes: 12 additions & 0 deletions patches/@blueprintjs+select+3.18.6.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
diff --git a/node_modules/@blueprintjs/select/lib/esm/components/select/select.d.ts b/node_modules/@blueprintjs/select/lib/esm/components/select/select.d.ts
index f8b9bc6..ee0b6da 100644
--- a/node_modules/@blueprintjs/select/lib/esm/components/select/select.d.ts
+++ b/node_modules/@blueprintjs/select/lib/esm/components/select/select.d.ts
@@ -4,6 +4,7 @@ import { IListItemsProps } from "../../common";
export declare type SelectProps<T> = ISelectProps<T>;
/** @deprecated use SelectProps */
export interface ISelectProps<T> extends IListItemsProps<T> {
+ children?: React.ReactNode;
/**
* Whether the component should take up the full width of its container.
* This overrides `popoverProps.fill`. You also have to ensure that the child
43 changes: 43 additions & 0 deletions src/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import runExtension from "./util/runExtension";

import { createBlock } from "./writes";
import MenuItemSelect from "./components/MenuItemSelect";
import TimePanel from "./components/ConfigPanels/TimePanel";

// const blockRender = (Component: React.FC) => {
// const block = window.roamAlphaAPI.ui.getFocusedBlock();
Expand Down Expand Up @@ -214,6 +215,47 @@ const components = [
}),
label: "PageInput",
},
{
callback: () =>
rootRender(() => {
const [value] = useState(new Date());
const [uid, setUid] = useState<string>("");

React.useEffect(() => {
const createUid = async () => {
const currentPageUid =
(await window.roamAlphaAPI.ui.mainWindow.getOpenPageOrBlockUid()) ||
window.roamAlphaAPI.util.dateToPageUid(new Date());

if (!currentPageUid) throw new Error("No current page uid");
console.log(currentPageUid);
const newUid = await createBlock({
parentUid: currentPageUid,
node: { text: "time-field" },
});
setUid(newUid);
};
createUid();
}, []);
Comment on lines +224 to +239
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for block creation.

The async block creation should handle potential failures gracefully.

        React.useEffect(() => {
          const createUid = async () => {
+           try {
              const currentPageUid =
                (await window.roamAlphaAPI.ui.mainWindow.getOpenPageOrBlockUid()) ||
                window.roamAlphaAPI.util.dateToPageUid(new Date());

              if (!currentPageUid) throw new Error("No current page uid");
              const newUid = await createBlock({
                parentUid: currentPageUid,
                node: { text: "time-field" },
              });
              setUid(newUid);
+           } catch (error) {
+             console.error("Failed to create block:", error);
+             // Consider setting an error state or fallback behavior
+           }
          };
          createUid();
        }, []);
📝 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.

Suggested change
React.useEffect(() => {
const createUid = async () => {
const currentPageUid =
(await window.roamAlphaAPI.ui.mainWindow.getOpenPageOrBlockUid()) ||
window.roamAlphaAPI.util.dateToPageUid(new Date());
if (!currentPageUid) throw new Error("No current page uid");
console.log(currentPageUid);
const newUid = await createBlock({
parentUid: currentPageUid,
node: { text: "time-field" },
});
setUid(newUid);
};
createUid();
}, []);
React.useEffect(() => {
const createUid = async () => {
try {
const currentPageUid =
(await window.roamAlphaAPI.ui.mainWindow.getOpenPageOrBlockUid()) ||
window.roamAlphaAPI.util.dateToPageUid(new Date());
if (!currentPageUid) throw new Error("No current page uid");
console.log(currentPageUid);
const newUid = await createBlock({
parentUid: currentPageUid,
node: { text: "time-field" },
});
setUid(newUid);
} catch (error) {
console.error("Failed to create block:", error);
// Consider setting an error state or fallback behavior
}
};
createUid();
}, []);
🤖 Prompt for AI Agents
In src/components.tsx around lines 224 to 239, the async function createUid does
not handle errors from the createBlock call, which may cause unhandled promise
rejections. Wrap the createBlock call and subsequent setUid in a try-catch block
to catch any errors, and handle them appropriately, such as logging the error or
showing a user-friendly message, to ensure graceful failure.


if (!uid) return <div>Loading...</div>;

return (
<>
<div>Selected time: {value.toLocaleTimeString()}</div>
<TimePanel
title="time-field"
uid={uid}
parentUid="test-parent-uid"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace hardcoded test value with dynamic or configurable value.

The hardcoded "test-parent-uid" appears to be a placeholder and should be replaced with a proper dynamic value or made configurable.

-              parentUid="test-parent-uid"
+              parentUid={currentPageUid}
📝 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.

Suggested change
parentUid="test-parent-uid"
parentUid={currentPageUid}
🤖 Prompt for AI Agents
In src/components.tsx at line 249, replace the hardcoded string
"test-parent-uid" with a dynamic value passed as a prop or derived from
component state or context. Alternatively, make it configurable via component
props or environment variables to avoid using a fixed placeholder.

order={0}
description="Select a time"
defaultValue={value}
/>
</>
);
}),
label: "TimePanel",
},
];

export default runExtension(async (args) => {
Expand All @@ -229,6 +271,7 @@ export default runExtension(async (args) => {
FormDialog,
PageInput,
renderToast,
TimePanel,
},
util: {
renderOverlay,
Expand Down
6 changes: 5 additions & 1 deletion src/components/BlockErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from "react";
import createBlock from "../writes/createBlock";

type BlockErrorBoundaryProps = { blockUid: string; message: string };
type BlockErrorBoundaryProps = {
blockUid: string;
message: string;
children: React.ReactNode;
};
type BlockErrorBoundaryState = { hasError: boolean };

class BlockErrorBoundary extends React.Component<
Expand Down
1 change: 1 addition & 0 deletions src/components/ComponentContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { OnloadArgs } from "../types/native";
const ComponentContainer: React.FunctionComponent<{
blockId?: string;
className?: string;
children?: React.ReactNode;
}> = ({ blockId, className, children }) => {
const [showIcons, setShowIcons] = useState(false);
const appear = useCallback(() => setShowIcons(true), [setShowIcons]);
Expand Down
2 changes: 1 addition & 1 deletion src/components/ConfigPanels/OauthPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const OauthPanel: FieldPanel<OauthField> = ({ uid, parentUid, options }) => {
: []
);
const onCheck = useCallback(
(e) => {
(e: React.ChangeEvent<HTMLInputElement>) => {
const checked = (e.target as HTMLInputElement).checked;
setUseLocal(checked);
if (checked) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/CursorMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ const CursorMenu = <T extends Record<string, string>>({
[filter, initialItems]
);
const onSelect = useCallback(
(item) => {
(item: { text: string; id: string } & T) => {
if (menuRef.current) {
onItemSelect(item);
onClose();
Expand Down
9 changes: 7 additions & 2 deletions src/components/MenuItemSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Button, ButtonProps, MenuItem } from "@blueprintjs/core";
import { SelectProps, Select, ICreateNewItem } from "@blueprintjs/select";
import {
SelectProps,
Select,
ICreateNewItem,
isCreateNewItem,
} from "@blueprintjs/select";
import React, { ReactText, ButtonHTMLAttributes, ReactNode } from "react";

type ActiveItem<T> = T | ICreateNewItem | null | undefined;
Expand Down Expand Up @@ -38,7 +43,7 @@ const MenuItemSelect = <T extends ReactText>(
const defaultButton = (
<Button
text={
activeItem ? (
activeItem && !isCreateNewItem(activeItem) ? (
transformItem ? (
transformItem(activeItem as T)
) : (
Expand Down