Replace the composer textarea with a Tiptap markdown editor
The composer now writes markdown with bold, italic, strike, code, links, quotes and lists, from shortcuts, markdown typing or a bubble over the selection. @ mentions a bot and # a workspace, shown as chips and saved as [bot:ID] / [workspace:ID]. Text selected in a message can be quoted into the composer. User messages render as markdown, and replies tell the bot who and what the user mentioned. Adds an ESM stand-in for use-sync-external-store, since bunext keeps React external in page bundles and the CommonJS original requires it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* React 18+ has `useSyncExternalStore`; the shim only re-exports it.
|
||||
*/
|
||||
export { useSyncExternalStore } from "react";
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "use-sync-external-store",
|
||||
"version": "1.7.0-esm",
|
||||
"description": "ESM stand-in for use-sync-external-store on React 19, which has useSyncExternalStore built in. The page bundler keeps react external, so the upstream CommonJS require(\"react\") can't load in the browser.",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./with-selector": "./with-selector.js",
|
||||
"./with-selector.js": "./with-selector.js",
|
||||
"./shim": "./index.js",
|
||||
"./shim/index.js": "./index.js",
|
||||
"./shim/with-selector": "./with-selector.js",
|
||||
"./shim/with-selector.js": "./with-selector.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { useSyncExternalStore } from "../index.js";
|
||||
@@ -0,0 +1 @@
|
||||
export { useSyncExternalStoreWithSelector } from "../with-selector.js";
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* `useSyncExternalStoreWithSelector` from React's use-sync-external-store
|
||||
* (MIT, Meta Platforms, Inc. and affiliates), as an ES module: it reads a
|
||||
* store through a selector and only re-renders when the selection
|
||||
* changes (`isEqual`).
|
||||
*/
|
||||
import { useDebugValue, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
|
||||
|
||||
export function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnapshot, selector, isEqual) {
|
||||
const instRef = useRef(null);
|
||||
|
||||
if (instRef.current === null) instRef.current = { hasValue: false, value: null };
|
||||
|
||||
const inst = instRef.current;
|
||||
|
||||
const [getSelection, getServerSelection] = useMemo(() => {
|
||||
let hasMemo = false;
|
||||
let memoizedSnapshot;
|
||||
let memoizedSelection;
|
||||
|
||||
const memoizedSelector = (nextSnapshot) => {
|
||||
if (!hasMemo) {
|
||||
hasMemo = true;
|
||||
memoizedSnapshot = nextSnapshot;
|
||||
|
||||
const nextSelection = selector(nextSnapshot);
|
||||
|
||||
if (isEqual !== undefined && inst.hasValue && isEqual(inst.value, nextSelection)) {
|
||||
memoizedSelection = inst.value;
|
||||
return memoizedSelection;
|
||||
}
|
||||
|
||||
memoizedSelection = nextSelection;
|
||||
return nextSelection;
|
||||
}
|
||||
|
||||
const currentSelection = memoizedSelection;
|
||||
|
||||
if (Object.is(memoizedSnapshot, nextSnapshot)) return currentSelection;
|
||||
|
||||
const nextSelection = selector(nextSnapshot);
|
||||
|
||||
if (isEqual !== undefined && isEqual(currentSelection, nextSelection)) {
|
||||
memoizedSnapshot = nextSnapshot;
|
||||
return currentSelection;
|
||||
}
|
||||
|
||||
memoizedSnapshot = nextSnapshot;
|
||||
memoizedSelection = nextSelection;
|
||||
return nextSelection;
|
||||
};
|
||||
|
||||
return [
|
||||
() => memoizedSelector(getSnapshot()),
|
||||
getServerSnapshot === undefined ? undefined : () => memoizedSelector(getServerSnapshot()),
|
||||
];
|
||||
}, [getSnapshot, getServerSnapshot, selector, isEqual]);
|
||||
|
||||
const value = useSyncExternalStore(subscribe, getSelection, getServerSelection);
|
||||
|
||||
useEffect(() => {
|
||||
inst.hasValue = true;
|
||||
inst.value = value;
|
||||
}, [value]);
|
||||
|
||||
useDebugValue(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
Reference in New Issue
Block a user