@sckyzo/cosmos-react 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +128 -0
- package/README.md +916 -19
- package/dist/CodeBlock-CY18_3tZ.d.cts +52 -0
- package/dist/CodeBlock-CY18_3tZ.d.ts +52 -0
- package/dist/code/index.cjs +331 -0
- package/dist/code/index.cjs.map +1 -0
- package/dist/code/index.d.cts +29 -0
- package/dist/code/index.d.ts +29 -0
- package/dist/code/index.js +326 -0
- package/dist/code/index.js.map +1 -0
- package/dist/editor/index.cjs +879 -0
- package/dist/editor/index.cjs.map +1 -0
- package/dist/editor/index.d.cts +100 -0
- package/dist/editor/index.d.ts +100 -0
- package/dist/editor/index.js +872 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/fieldRecipe-Cao5uUIK.d.cts +3 -0
- package/dist/fieldRecipe-Cao5uUIK.d.ts +3 -0
- package/dist/index.cjs +18158 -12012
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1631 -243
- package/dist/index.d.ts +1631 -243
- package/dist/index.js +18113 -12005
- package/dist/index.js.map +1 -1
- package/dist/intent-D0bANgYJ.d.cts +12 -0
- package/dist/intent-D0bANgYJ.d.ts +12 -0
- package/dist/map/index.cjs +559 -0
- package/dist/map/index.cjs.map +1 -0
- package/dist/map/index.d.cts +95 -0
- package/dist/map/index.d.ts +95 -0
- package/dist/map/index.js +556 -0
- package/dist/map/index.js.map +1 -0
- package/package.json +82 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useControllableState.ts","../../src/chat/httpUrl.ts","../../src/forms/fieldRecipe.ts","../../src/forms/RequiredMark.tsx","../../src/editor/actions.ts","../../src/editor/blockDirection.ts","../../src/hooks/direction.ts","../../src/ui/mergeRefs.ts","../../src/editor/linkUrl.ts","../../src/editor/LinkForm.tsx","../../src/editor/FormattingToolbar.tsx","../../src/editor/labels.ts","../../src/editor/RichTextEditor.tsx"],"names":["key","directionOf","useState","jsxs","clsx","jsx","useRef","Extension","useId","useMemo","useInsertionEffect","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import { useCallback, useEffect, useInsertionEffect, useRef, useState } from 'react';\n\n/**\n * The value to move to, or a function of the current one, as with `setState`. `S` is the\n * state, which may be empty (`undefined`) before the first set; `T` is what a set moves to.\n */\nexport type ControllableUpdate<T, S = T> = T | ((current: S) => T);\n\nexport type ControllableStateOptions<T, A extends unknown[] = [], D extends T | undefined = T> = {\n /**\n * The value the host controls. Only `undefined` means uncontrolled: `null`, `false`, `0`\n * and `''` are controlled values.\n */\n value: T | undefined;\n /**\n * Starting value while uncontrolled, read on the first render only. May be `undefined` for\n * a state that starts empty (no option picked yet): the state then reads `T | undefined`,\n * while the setter and `onChange` keep to `T`.\n */\n defaultValue: D | (() => D);\n /**\n * Called on every set, controlled or not, with the value to move to and the setter's extra\n * arguments (a field passes its native event).\n */\n onChange?: (value: T, ...args: A) => void;\n /**\n * `Component.prop`, for the console warning when the host switches between controlled and\n * uncontrolled.\n */\n name: string;\n};\n\n/**\n * State a host may control. Returns the current value, a setter and whether the value is\n * controlled.\n *\n * The setter keeps its identity across renders and reads the latest `onChange` and value, so\n * effects and memoized handlers can depend on it without a stale closure. It updates the\n * internal state only while uncontrolled, and always calls `onChange`: a controlled\n * component shows the new value once the host passes it back.\n *\n * Internal to the package, not exported. `T` must not be a function type: a function passed\n * to the setter is an updater, as with `setState`.\n */\nexport function useControllableState<T, A extends unknown[] = [], D extends T | undefined = T>({\n value,\n defaultValue,\n onChange,\n name,\n}: ControllableStateOptions<T, A, D>): [\n value: T | D,\n setValue: (next: ControllableUpdate<T, T | D>, ...args: A) => void,\n isControlled: boolean,\n] {\n const isControlled = value !== undefined;\n const [internal, setInternal] = useState<T | D>(defaultValue);\n const current = isControlled ? value : internal;\n\n // What the setter reads. Refreshed after each render, before any effect or event handler\n // can call the setter.\n const latest = useRef({ current, isControlled, onChange });\n useInsertionEffect(() => {\n latest.current = { current, isControlled, onChange };\n });\n\n const setValue = useCallback((next: ControllableUpdate<T, T | D>, ...args: A) => {\n const state = latest.current;\n const resolved =\n typeof next === 'function' ? (next as (current: T | D) => T)(state.current) : next;\n if (!state.isControlled) {\n // A second set in the same event builds on this one, as with setState.\n state.current = resolved;\n setInternal(resolved);\n }\n state.onChange?.(resolved, ...args);\n }, []);\n\n useModeSwitchWarning(isControlled, name);\n\n return [current, setValue, isControlled];\n}\n\n// Typed here: the package depends on no Node types.\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Whether the host app is a production build. Bundlers (Vite, webpack, Next) replace\n * `process.env.NODE_ENV` at build time, as React's own warnings rely on; without a bundler\n * `process` doesn't exist, and the ReferenceError means \"not a production build\".\n */\nconst isProductionBuild = (() => {\n try {\n return process.env.NODE_ENV === 'production';\n } catch {\n return false;\n }\n})();\n\n/**\n * Warns once per component when its value goes from controlled to uncontrolled or back,\n * usually a host passing `undefined` for an empty value. Development builds only, like\n * React's warnings.\n */\nfunction useModeSwitchWarning(isControlled: boolean, name: string) {\n const initial = useRef(isControlled);\n const warned = useRef(false);\n useEffect(() => {\n if (isProductionBuild || warned.current || initial.current === isControlled) return;\n warned.current = true;\n const from = initial.current ? 'controlled' : 'uncontrolled';\n const to = isControlled ? 'controlled' : 'uncontrolled';\n console.warn(\n `Cosmos: ${name} switched from ${from} to ${to}. Keep it one or the other for the ` +\n 'life of the component: only `undefined` means uncontrolled.'\n );\n }, [isControlled, name]);\n}\n","// http(s) URLs only: other schemes (javascript:, data:) stay plain text.\nexport const URL_PATTERN = /https?:\\/\\/[^\\s<>\"']+/g;\n\n// The same rule as a whole string: what `MessageText` would turn into a link.\nconst WHOLE_URL = new RegExp(`^${URL_PATTERN.source}$`);\n\n/** Whether `value` is an http(s) URL, the only kind that becomes a link in a chat. */\nexport const isHttpUrl = (value: string) => WHOLE_URL.test(value);\n\n/** The host of an http(s) URL (`docs.example.com`), or `undefined` for anything else. */\nexport const hostOf = (value: string) => {\n if (!isHttpUrl(value)) return undefined;\n try {\n return new URL(value).host;\n } catch {\n return undefined;\n }\n};\n\n// Punctuation that ends a sentence rather than the URL. Trimmed with a loop: a regex such as\n// /[.,;:!?)\\]]+$/ backtracks quadratically on a long run of them that isn't at the end.\nconst TRAILING = new Set(['.', ',', ';', ':', '!', '?', ')', ']']);\n\n/** `url` without the punctuation that ends the sentence around it (\"see https://a.b/c.\" → no dot). */\nexport const trimTrailingPunctuation = (url: string) => {\n let end = url.length;\n while (end > 0 && TRAILING.has(url[end - 1])) end -= 1;\n return url.slice(0, end);\n};\n\n// mailto: and the relative forms a link may point at: a path (\"/a\", \"./a\", \"../a\"), a fragment or a\n// query. \"//host\" is protocol-relative, so it is another site, and a backslash is read as a slash by\n// browsers (\"/\\host\"): both stay out.\nconst MAILTO = /^mailto:[^\\s<>\"'\\\\]+$/i;\nconst RELATIVE = /^(?:\\/(?!\\/)|\\.\\.?\\/|#|\\?)[^\\s<>\"'\\\\]*$/;\n\n/**\n * Whether `value` may be the target of a link a user writes: an http(s) URL, a `mailto:` address\n * or a relative URL. The rule of `RichTextEditor`, which extends the chat's (`isHttpUrl`) with the\n * two kinds a form field needs. `javascript:`, `data:` and every other scheme are refused.\n */\nexport const isSafeLinkUrl = (value: string) =>\n isHttpUrl(value) || MAILTO.test(value) || RELATIVE.test(value);\n","import { clsx } from 'clsx';\n\n// The look every form field shares, so no field drifts from the others. A field\n// takes its look from `fieldClass` and its dimensions from the maps below, all\n// keyed by `FieldSize`. The scale follows Button's `sm` / `md` / `lg` (same\n// heights and text sizes); `md` is the default. The heights and the vertical padding are theme\n// tokens, so the page's `data-density` moves them.\n\nexport type FieldSize = 'sm' | 'md' | 'lg';\n\nexport const FIELD_HEIGHT: Record<FieldSize, string> = {\n sm: 'h-ctrl-32',\n md: 'h-ctrl-36',\n lg: 'h-ctrl-44',\n};\n\nexport const FIELD_TEXT: Record<FieldSize, string> = {\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n};\n\n/** Horizontal padding of a text, so a field's text clears its border. */\nexport const FIELD_PAD_X: Record<FieldSize, string> = {\n sm: 'px-2.5',\n md: 'px-3',\n lg: 'px-4',\n};\n\n/** Start and end padding of a field whose other side is free (an icon on one edge). */\nexport const FIELD_PAD_START: Record<FieldSize, string> = {\n sm: 'ps-2.5',\n md: 'ps-3',\n lg: 'ps-4',\n};\n\nexport const FIELD_PAD_END: Record<FieldSize, string> = {\n sm: 'pe-2.5',\n md: 'pe-3',\n lg: 'pe-4',\n};\n\n/** Vertical padding of a field with no fixed height (a Textarea). */\nexport const FIELD_PAD_Y: Record<FieldSize, string> = {\n sm: 'py-row-6',\n md: 'py-row-8',\n lg: 'py-row-10',\n};\n\n/** Start padding that clears an icon drawn over the field's start edge. */\nexport const FIELD_PAD_START_ICON: Record<FieldSize, string> = {\n sm: 'ps-8',\n md: 'ps-9',\n lg: 'ps-11',\n};\n\n/** End padding that clears a chevron drawn over the field's end edge. */\nexport const FIELD_PAD_END_ICON: Record<FieldSize, string> = {\n sm: 'pe-8',\n md: 'pe-9',\n lg: 'pe-10',\n};\n\n/** Where an icon sits on the start edge. */\nexport const FIELD_ICON_START: Record<FieldSize, string> = {\n sm: 'inset-s-2.5',\n md: 'inset-s-3',\n lg: 'inset-s-3.5',\n};\n\n/** Where an icon sits on the end edge. */\nexport const FIELD_ICON_END: Record<FieldSize, string> = {\n sm: 'inset-e-2.5',\n md: 'inset-e-3',\n lg: 'inset-e-3.5',\n};\n\nexport const FIELD_ICON_SIZE: Record<FieldSize, string> = {\n sm: 'h-3.5 w-3.5',\n md: 'h-4 w-4',\n lg: 'h-5 w-5',\n};\n\ntype FieldState = 'neutral' | 'success' | 'invalid';\n\n// Border and focus of each state, so a field and the OTP cells read them from one place.\n// `success` keeps the accent focus: a green border alone would not tell where the focus is.\nconst FIELD_STATE: Record<FieldState, { border: string; focus: string; focusWithin: string }> = {\n neutral: {\n border: 'border-gray-200 dark:border-gray-700',\n focus: 'focus:field-focus',\n focusWithin: 'focus-within:field-focus',\n },\n success: {\n border: 'border-green-600 dark:border-green-500/60',\n focus: 'focus:field-focus',\n focusWithin: 'focus-within:field-focus',\n },\n invalid: {\n border: 'border-red-400 dark:border-red-500/60',\n focus: 'focus:field-focus-error',\n focusWithin: 'focus-within:field-focus-error',\n },\n};\n\ntype FieldStateOptions = {\n /** Red border and halo instead of the neutral border. Wins over `success`. */\n invalid?: boolean;\n /** Green border instead of the neutral one: the value was checked and is valid. */\n success?: boolean;\n /**\n * The border is drawn by a wrapper of the real input (a prefix or a stepper\n * around it): the focus state follows `focus-within` instead of `focus`.\n */\n within?: boolean;\n};\n\n/**\n * Border and focus classes of a field in one of its states: neutral, `success`\n * or `invalid` (exclusive, `invalid` first). Colors only: size, surface and\n * the rest come from `fieldClass`, or from the control itself (the OTP cells).\n */\nexport const fieldStateClass = ({\n invalid = false,\n success = false,\n within = false,\n}: FieldStateOptions) => {\n const state = FIELD_STATE[invalid ? 'invalid' : success ? 'success' : 'neutral'];\n return clsx(state.border, within ? state.focusWithin : state.focus);\n};\n\ntype FieldClassOptions = FieldStateOptions & {\n size: FieldSize;\n /** Muted surface of a field that shows a value but can't be edited. */\n readOnly?: boolean;\n /** `false` for a field that grows with its content (a Textarea). Default `true`. */\n fixedHeight?: boolean;\n};\n\n/**\n * Surface of a field: radius, border, background in light and dark, text size,\n * height, and the focus, disabled, success and invalid states. Padding, width\n * and the text color of a part stay with the field. The state classes are\n * exclusive: `invalid` (first) or `success` swaps the border and the focus\n * together, `readOnly` the background.\n */\nexport const fieldClass = ({\n size,\n invalid = false,\n success = false,\n within = false,\n readOnly = false,\n fixedHeight = true,\n}: FieldClassOptions) =>\n clsx(\n 'rounded-lg border transition-colors disabled:cursor-not-allowed disabled:opacity-50 dark:text-white',\n readOnly ? 'bg-gray-50 dark:bg-gray-900' : 'bg-white dark:bg-gray-800',\n FIELD_TEXT[size],\n fixedHeight && FIELD_HEIGHT[size],\n fieldStateClass({ invalid, success, within })\n );\n\n/**\n * A text field follows the direction of what is typed in it: Arabic aligns and flows right to\n * left, a URL left to right, each paragraph of a Textarea on its own. `plaintext` and not\n * `dir=\"auto\"`, which would also flip the field's own `direction` to left to right for a URL\n * and move its end padding (the room for a trailing icon or button, laid out by the page's\n * direction) to the side opposite the adornment. With `plaintext` the field keeps the page's\n * direction and its padding stays under the adornment.\n */\nexport const FIELD_PLAINTEXT = '[unicode-bidi:plaintext]';\n\n/** Placeholder color of a text field, readable in light and dark. */\nexport const FIELD_PLACEHOLDER = 'placeholder:text-gray-500 dark:placeholder:text-gray-400';\n\n/**\n * The panel a field opens under itself to list its options (Combobox). One\n * surface, whatever the field: the listbox scrolls inside it.\n */\nexport const FIELD_LISTBOX_PANEL =\n 'overflow-auto rounded-lg border border-gray-200 bg-white py-1 shadow-lg focus:outline-none dark:border-gray-700 dark:bg-gray-800';\n","/**\n * Asterisk after a field's label. The control carries the requirement for\n * assistive technology (`required` or `aria-required`), so the mark is hidden\n * from it. `srText` is for a control that can't (a button): it names the\n * requirement in the label instead.\n */\nexport const RequiredMark = ({ srText }: { srText?: string }) => (\n <>\n <span aria-hidden className=\"ms-0.5 text-red-700 dark:text-red-400\">\n *\n </span>\n {srText && <span className=\"sr-only\">{srText}</span>}\n </>\n);\n","import type { Editor } from '@tiptap/react';\nimport {\n Bold,\n Code,\n Heading2,\n Italic,\n Link,\n List,\n ListOrdered,\n Quote,\n Redo2,\n Strikethrough,\n Undo2,\n type LucideIcon,\n} from 'lucide-react';\n\n/** The buttons a toolbar can hold, in the order `RICH_TEXT_ACTIONS` lists them. */\nexport type RichTextAction =\n | 'bold'\n | 'italic'\n | 'strike'\n | 'heading'\n | 'bulletList'\n | 'orderedList'\n | 'blockquote'\n | 'code'\n | 'link'\n | 'undo'\n | 'redo';\n\nexport const RICH_TEXT_ACTIONS: readonly RichTextAction[] = [\n 'bold',\n 'italic',\n 'strike',\n 'heading',\n 'bulletList',\n 'orderedList',\n 'blockquote',\n 'code',\n 'link',\n 'undo',\n 'redo',\n];\n\n/** What the `bubble` variant shows when `toolbar` doesn't say: the inline marks and the link. */\nexport const BUBBLE_ACTIONS: readonly RichTextAction[] = [\n 'bold',\n 'italic',\n 'strike',\n 'code',\n 'link',\n];\n\nexport type ActionSpec = {\n icon: LucideIcon;\n /** The icon points along the line (an indented list, undo): it turns around in right to left. */\n mirror?: boolean;\n label: string;\n /** `Mod` is Cmd on macOS and Ctrl elsewhere. Matches the shortcut Tiptap binds. */\n shortcut: readonly string[];\n isActive: (editor: Editor) => boolean;\n /** Whether the action does nothing right now (nothing to undo). */\n isIdle?: (editor: Editor) => boolean;\n /** Not for `link`, which opens its own field. */\n run?: (editor: Editor) => void;\n};\n\n// Commands run without `.focus()`: a mouse press on a button is kept off the editor's focus\n// (`onMouseDown` prevents it), so the text stays focused, and a keyboard press leaves the focus on\n// the button, as a toolbar does.\nexport const ACTION_SPECS: Record<RichTextAction, ActionSpec> = {\n bold: {\n icon: Bold,\n label: 'Bold',\n shortcut: ['Mod', 'B'],\n isActive: (editor) => editor.isActive('bold'),\n run: (editor) => editor.chain().toggleBold().run(),\n },\n italic: {\n icon: Italic,\n label: 'Italic',\n shortcut: ['Mod', 'I'],\n isActive: (editor) => editor.isActive('italic'),\n run: (editor) => editor.chain().toggleItalic().run(),\n },\n strike: {\n icon: Strikethrough,\n label: 'Strikethrough',\n shortcut: ['Mod', 'Shift', 'S'],\n isActive: (editor) => editor.isActive('strike'),\n run: (editor) => editor.chain().toggleStrike().run(),\n },\n heading: {\n icon: Heading2,\n label: 'Heading',\n shortcut: ['Mod', 'Alt', '2'],\n isActive: (editor) => editor.isActive('heading', { level: 2 }),\n run: (editor) => editor.chain().toggleHeading({ level: 2 }).run(),\n },\n bulletList: {\n icon: List,\n mirror: true,\n label: 'Bulleted list',\n shortcut: ['Mod', 'Shift', '8'],\n isActive: (editor) => editor.isActive('bulletList'),\n run: (editor) => editor.chain().toggleBulletList().run(),\n },\n orderedList: {\n icon: ListOrdered,\n mirror: true,\n label: 'Numbered list',\n shortcut: ['Mod', 'Shift', '7'],\n isActive: (editor) => editor.isActive('orderedList'),\n run: (editor) => editor.chain().toggleOrderedList().run(),\n },\n blockquote: {\n icon: Quote,\n mirror: true,\n label: 'Quote',\n shortcut: ['Mod', 'Shift', 'B'],\n isActive: (editor) => editor.isActive('blockquote'),\n run: (editor) => editor.chain().toggleBlockquote().run(),\n },\n code: {\n icon: Code,\n label: 'Code',\n shortcut: ['Mod', 'E'],\n isActive: (editor) => editor.isActive('code'),\n run: (editor) => editor.chain().toggleCode().run(),\n },\n link: {\n icon: Link,\n label: 'Link',\n shortcut: ['Mod', 'K'],\n isActive: (editor) => editor.isActive('link'),\n },\n undo: {\n icon: Undo2,\n mirror: true,\n label: 'Undo',\n shortcut: ['Mod', 'Z'],\n isActive: () => false,\n isIdle: (editor) => !editor.can().undo(),\n run: (editor) => editor.chain().undo().run(),\n },\n redo: {\n icon: Redo2,\n mirror: true,\n label: 'Redo',\n shortcut: ['Mod', 'Shift', 'Z'],\n isActive: () => false,\n isIdle: (editor) => !editor.can().redo(),\n run: (editor) => editor.chain().redo().run(),\n },\n};\n\nconst isApple = () =>\n typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform);\n\nconst KEY_NAMES: Record<string, [apple: string, other: string]> = {\n Mod: ['⌘', 'Ctrl'],\n Shift: ['⇧', 'Shift'],\n Alt: ['⌥', 'Alt'],\n};\n\n/** The keys of a shortcut as the tooltip shows them on this platform (`['⌘', 'B']`, `['Ctrl', 'B']`). */\nexport const shortcutKeys = (shortcut: readonly string[]) =>\n shortcut.map((key) => (KEY_NAMES[key] ? KEY_NAMES[key][isApple() ? 0 : 1] : key));\n\n/**\n * The shortcut for `aria-keyshortcuts`: both platforms' modifier, since the attribute is read\n * before the platform is known on the server (`Control+B Meta+B`).\n */\nexport const ariaShortcut = (shortcut: readonly string[]) =>\n ['Control', 'Meta']\n .map((mod) => shortcut.map((key) => (key === 'Mod' ? mod : key)).join('+'))\n .join(' ');\n","import { Extension } from '@tiptap/core';\nimport type { Node } from '@tiptap/pm/model';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { Decoration, DecorationSet } from '@tiptap/pm/view';\n\n// The scripts written from right to left; any other letter reads from left to right.\nconst RTL_LETTER =\n /[\\p{Script=Arabic}\\p{Script=Hebrew}\\p{Script=Syriac}\\p{Script=Thaana}\\p{Script=Nko}\\p{Script=Adlam}\\p{Script=Samaritan}\\p{Script=Mandaic}]/u;\nconst LETTER = /\\p{L}/u;\n\n/**\n * The direction of the first letter of `text`, the one `dir=\"auto\"` goes by; `undefined` when it\n * has no letter, so the block keeps the direction around it.\n */\nexport const firstLetterDirection = (text: string): 'ltr' | 'rtl' | undefined => {\n const letter = LETTER.exec(text)?.[0];\n if (letter === undefined) return undefined;\n return RTL_LETTER.test(letter) ? 'rtl' : 'ltr';\n};\n\n// Paragraphs and headings follow their text with `unicode-bidi: plaintext` (`CONTENT_CLASS`), but\n// that moves the text only. The bullet or number of a list item, the indent of a list and the edge\n// of a quote sit on the side their `direction` names, so these get a `dir` of their own.\nconst CONTAINERS = new Set(['bulletList', 'orderedList', 'listItem', 'blockquote']);\n\nconst directionOf = (node: Node) => {\n let direction: 'ltr' | 'rtl' | undefined;\n node.descendants((child) => {\n if (direction) return false;\n if (child.isText) direction = firstLetterDirection(child.text ?? '');\n return !direction;\n });\n return direction;\n};\n\nconst decorate = (doc: Node) => {\n const decorations: Decoration[] = [];\n doc.descendants((node, pos) => {\n if (node.isTextblock) return false;\n if (!CONTAINERS.has(node.type.name)) return true;\n const dir = directionOf(node);\n if (dir) decorations.push(Decoration.node(pos, pos + node.nodeSize, { dir }));\n return true;\n });\n return DecorationSet.create(doc, decorations);\n};\n\nconst key = new PluginKey<DecorationSet>('blockDirection');\n\n/**\n * Lists, list items and quotes take the direction of what is typed in them, as a paragraph does.\n * A decoration, so the `dir` is on the screen only: the value the editor hands back is unchanged.\n */\nexport const BlockDirection = Extension.create({\n name: 'blockDirection',\n addProseMirrorPlugins() {\n return [\n new Plugin<DecorationSet>({\n key,\n state: {\n init: (_, { doc }) => decorate(doc),\n apply: (tr, decorations) => (tr.docChanged ? decorate(tr.doc) : decorations),\n },\n props: { decorations: (state) => key.getState(state) },\n }),\n ];\n },\n});\n","import {\n useCallback,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n type RefCallback,\n} from 'react';\n\n/** The reading direction of an element, from the native `dir` attribute of it or an ancestor. */\nexport type Direction = 'ltr' | 'rtl';\n\n/**\n * The direction `element` is laid out in: `rtl` under `dir=\"rtl\"` (on it, on an ancestor, on\n * `<html>`), else `ltr`. Read from the computed style, so `dir=\"auto\"` and a stylesheet's\n * `direction` count as much as the attribute. `read` is the computed-style reader, there for\n * a test in Node.\n *\n * For the places JavaScript has to know: the alignment of a floating panel, the arrow keys of a\n * horizontal widget, the side a swipe goes to. Everything else mirrors through the logical\n * utilities (`ms-`, `text-start`…) and the `rtl:` variant, which need no JavaScript.\n *\n * Internal to the package, not exported.\n */\nexport const directionOf = (\n element: Element | null | undefined,\n read: (element: Element) => { direction: string } = (el) => getComputedStyle(el)\n): Direction => (element && read(element).direction === 'rtl' ? 'rtl' : 'ltr');\n\n/**\n * The direction a widget sits in, for a library that wants it as a prop (Radix's slider, a\n * calendar) and does not read the page. `ref` goes on the widget's root; `direction` is read\n * from the root's parent, because the root usually carries the `dir` this feeds, and it is\n * measured after every commit so a page whose `dir` changes is followed on the next render.\n * `ltr` until the first measure, which lands before the first paint.\n */\nexport function useParentDirection<T extends Element>(): [Direction, RefCallback<T>] {\n const root = useRef<T | null>(null);\n const [direction, setDirection] = useState<Direction>('ltr');\n const ref = useCallback((node: T | null) => {\n root.current = node;\n }, []);\n // After every commit on purpose: the page's `dir` can change with nothing here changing. The\n // state only moves when the direction does, so this does not loop.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(() => {\n if (root.current) setDirection(directionOf(root.current.parentElement));\n });\n return [direction, ref];\n}\n\nconst subscribeToDocumentDirection = (onChange: () => void) => {\n const observer = new MutationObserver(onChange);\n observer.observe(document.documentElement, { attributes: true, attributeFilter: ['dir'] });\n return () => observer.disconnect();\n};\n\nconst getDocumentDirection = (): Direction => directionOf(document.documentElement);\nconst getServerDirection = (): Direction => 'ltr';\n\n/**\n * The direction of the page, from the `dir` attribute of `<html>`, followed when it changes. For\n * a component that is not inside the page's tree to read it from (a toast stack), or that has\n * to pick a physical value (a corner of the screen) for it. `ltr` on the server.\n *\n * Internal to the package, not exported.\n */\nexport const useDocumentDirection = (): Direction =>\n useSyncExternalStore(subscribeToDocumentDirection, getDocumentDirection, getServerDirection);\n","import type { Ref, RefCallback } from 'react';\n\n/** Point a ref (callback or object) at `node`. */\nexport function setRef<T>(ref: Ref<T> | undefined, node: T | null): void {\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n}\n\n/**\n * Combine several refs (callback or object) into one callback ref, so a\n * component can keep its own ref and still forward the consumer's.\n *\n * It returns a cleanup, as a React 19 callback ref may: React then calls that\n * cleanup on detach instead of the ref with `null`. The cleanup runs the ones\n * the refs returned, and resets the others (`null` to a callback without a\n * cleanup, `current = null` on an object ref).\n */\nexport function mergeRefs<T>(...refs: Array<Ref<T> | undefined>): RefCallback<T> {\n return (node) => {\n const cleanups = refs.map((ref) => {\n if (typeof ref === 'function') {\n const cleanup = ref(node);\n return typeof cleanup === 'function' ? cleanup : () => ref(null);\n }\n setRef(ref, node);\n return () => setRef(ref, null);\n });\n return () => {\n for (const cleanup of cleanups) cleanup();\n };\n };\n}\n","import { isSafeLinkUrl } from '../chat/httpUrl';\n\n// \"docs.example.com/page?x=1\": a host with a dot and a letters-only ending, then an optional path.\nconst BARE_HOST = /^(?:[a-z0-9-]+\\.)+[a-z]{2,}(?:[/?#]\\S*)?$/i;\nconst EMAIL = /^[^\\s@<>\"'\\\\:/]+@(?:[a-z0-9-]+\\.)+[a-z]{2,}$/i;\n\n/**\n * The URL a link field's text stands for, or `undefined` when it can't be a link. Text that\n * already is an allowed URL (http(s), mailto, relative) stays as typed; a bare host\n * (\"example.com\") gets `https://` and an address (\"ops@example.com\") `mailto:`. Anything else,\n * `javascript:` and `data:` first, is refused: the rule is `isSafeLinkUrl`, the one every link of\n * the editor goes through.\n */\nexport const normalizeLinkUrl = (input: string): string | undefined => {\n const value = input.trim();\n if (isSafeLinkUrl(value)) return value;\n if (EMAIL.test(value)) return `mailto:${value}`;\n if (BARE_HOST.test(value)) return `https://${value}`;\n return undefined;\n};\n","import { clsx } from 'clsx';\nimport { useId, useState } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport { Button } from '../ui/Button';\nimport { FIELD_PAD_X, FIELD_PAD_Y, FIELD_PLACEHOLDER, fieldClass } from '../forms/fieldRecipe';\nimport type { ResolvedLabels } from './labels';\nimport { normalizeLinkUrl } from './linkUrl';\n\ntype LinkFormProps = {\n editor: Editor;\n labels: ResolvedLabels;\n /** After the link was applied or removed, or on Escape. */\n onDone: () => void;\n className?: string;\n};\n\n/**\n * The URL field of the link button, in a popover (`toolbar`) or in place of the buttons\n * (`bubble`). Not a `<form>`: it can sit inside the host's own form, and a nested one is invalid.\n * Enter applies, a URL the editor's rule refuses is flagged and never reaches the document.\n */\nexport function LinkForm({ editor, labels, onDone, className }: LinkFormProps) {\n const errorId = useId();\n // The link under the caret, else nothing: read once, when the field opens.\n const [value, setValue] = useState(() => (editor.getAttributes('link').href as string) ?? '');\n const [invalid, setInvalid] = useState(false);\n const hasLink = editor.isActive('link');\n\n const apply = () => {\n const href = normalizeLinkUrl(value);\n if (!href) {\n setInvalid(true);\n return;\n }\n const chain = editor.chain().focus();\n if (editor.state.selection.empty && !hasLink) {\n // No text selected: the address itself becomes the link's text.\n chain.insertContent({ type: 'text', text: href, marks: [{ type: 'link', attrs: { href } }] });\n } else {\n chain.extendMarkRange('link').setLink({ href });\n }\n chain.run();\n onDone();\n };\n\n const remove = () => {\n editor.chain().focus().extendMarkRange('link').unsetLink().run();\n onDone();\n };\n\n return (\n <div\n role=\"group\"\n aria-label={labels.linkDialog}\n className={clsx('flex flex-col gap-2', className)}\n >\n <input\n type=\"text\"\n inputMode=\"url\"\n autoFocus\n autoComplete=\"off\"\n spellCheck={false}\n // An address reads left to right, whatever the page does.\n dir=\"ltr\"\n aria-label={labels.linkUrl}\n aria-invalid={invalid || undefined}\n aria-describedby={invalid ? errorId : undefined}\n placeholder=\"https://\"\n value={value}\n onChange={(e) => {\n setValue(e.target.value);\n setInvalid(false);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n apply();\n } else if (e.key === 'Escape') {\n // The text keeps the focus, as when a bubble or a popover closes.\n e.preventDefault();\n e.stopPropagation();\n onDone();\n editor.commands.focus();\n }\n }}\n className={clsx(\n 'block w-full',\n fieldClass({ size: 'sm', invalid, fixedHeight: false }),\n FIELD_PAD_X.sm,\n FIELD_PAD_Y.sm,\n FIELD_PLACEHOLDER\n )}\n />\n {invalid && (\n <span id={errorId} className=\"text-xs text-red-700 dark:text-red-400\">\n {labels.linkInvalid}\n </span>\n )}\n <div className=\"flex items-center justify-end gap-2\">\n {hasLink && (\n <Button type=\"button\" variant=\"ghost\" size=\"xs\" onClick={remove}>\n {labels.linkRemove}\n </Button>\n )}\n <Button type=\"button\" size=\"xs\" onClick={apply}>\n {labels.linkApply}\n </Button>\n </div>\n </div>\n );\n}\n","import { clsx } from 'clsx';\nimport {\n useMemo,\n useRef,\n useState,\n type KeyboardEvent,\n type MouseEvent,\n type ReactElement,\n type Ref,\n} from 'react';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport { directionOf } from '../hooks/direction';\nimport { mergeRefs } from '../ui/mergeRefs';\nimport { Popover } from '../ui/Popover';\nimport { Tooltip } from '../ui/Tooltip';\nimport { ACTION_SPECS, ariaShortcut, shortcutKeys, type RichTextAction } from './actions';\nimport { LinkForm } from './LinkForm';\nimport type { ResolvedLabels } from './labels';\n\nconst BUTTON =\n 'focus-visible:focus-indicator flex size-ctrl-28 shrink-0 items-center justify-center rounded-md transition-colors aria-disabled:cursor-not-allowed aria-disabled:opacity-40';\nconst PRESSED = 'bg-brand-500/10 text-brand-600 dark:bg-brand-500/15 dark:text-brand-400';\nconst IDLE =\n 'text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800 aria-disabled:hover:bg-transparent dark:aria-disabled:hover:bg-transparent';\n\ntype FormattingToolbarProps = {\n editor: Editor;\n actions: readonly RichTextAction[];\n labels: ResolvedLabels;\n /** Buttons stay, but do nothing. */\n disabled: boolean;\n /**\n * Whether the link field is open. In a popover under the button (`toolbar`), or in place of\n * the buttons (`bubble`).\n */\n linkOpen: boolean;\n onLinkOpenChange: (open: boolean) => void;\n linkMode: 'popover' | 'inline';\n /** Escape in the toolbar: the focus goes back to the text. */\n onEscape?: () => void;\n className?: string;\n ref?: Ref<HTMLDivElement>;\n};\n\n/**\n * The buttons of `RichTextEditor` as one `role=\"toolbar\"` and one Tab stop: the arrow keys, Home\n * and End move between them (roving tabindex). A button reports its state with `aria-pressed`, a\n * button with nothing to do (undo with no history) with `aria-disabled`, so it stays reachable.\n */\nexport function FormattingToolbar({\n editor,\n actions,\n labels,\n disabled,\n linkOpen,\n onLinkOpenChange,\n linkMode,\n onEscape,\n className,\n ref,\n}: FormattingToolbarProps) {\n const root = useRef<HTMLDivElement | null>(null);\n const [stop, setStop] = useState(0);\n const state = useEditorState({\n editor,\n selector: ({ editor: current }) =>\n Object.fromEntries(\n actions.map((action) => [\n action,\n {\n active: ACTION_SPECS[action].isActive(current),\n idle: ACTION_SPECS[action].isIdle?.(current) ?? false,\n },\n ])\n ) as Record<RichTextAction, { active: boolean; idle: boolean }>,\n });\n const rootRef = useMemo(() => mergeRefs(root, ref), [ref]);\n const tabStop = Math.min(stop, actions.length - 1);\n\n const buttons = () =>\n Array.from(root.current?.querySelectorAll<HTMLButtonElement>('button[data-rt-action]') ?? []);\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Escape' && onEscape) {\n event.preventDefault();\n onEscape();\n return;\n }\n // A key typed in the link field is that field's own.\n if (!(event.target instanceof HTMLButtonElement)) return;\n const list = buttons();\n const at = list.indexOf(event.target);\n // The buttons run along the line, so the arrows swap in right to left.\n const toEnd = directionOf(root.current) === 'rtl' ? 'ArrowLeft' : 'ArrowRight';\n const next =\n event.key === toEnd\n ? (at + 1) % list.length\n : event.key === (toEnd === 'ArrowRight' ? 'ArrowLeft' : 'ArrowRight')\n ? (at - 1 + list.length) % list.length\n : event.key === 'Home'\n ? 0\n : event.key === 'End'\n ? list.length - 1\n : -1;\n if (next < 0) return;\n event.preventDefault();\n list[next]?.focus();\n };\n\n const linkField = (\n <LinkForm\n editor={editor}\n labels={labels}\n onDone={() => onLinkOpenChange(false)}\n className={linkMode === 'inline' ? 'w-64 p-2' : undefined}\n />\n );\n\n return (\n <div\n ref={rootRef}\n role=\"toolbar\"\n aria-label={labels.toolbar}\n aria-orientation=\"horizontal\"\n onKeyDown={onKeyDown}\n className={clsx('flex flex-wrap items-center gap-0.5', className)}\n >\n {linkMode === 'inline' && linkOpen\n ? linkField\n : actions.map((action, index) => {\n const spec = ACTION_SPECS[action];\n const { active, idle } = state[action];\n const Icon = spec.icon;\n const inert = disabled || idle;\n const common = {\n 'data-rt-action': action,\n 'aria-label': labels[action],\n 'aria-keyshortcuts': ariaShortcut(spec.shortcut),\n 'aria-pressed': active,\n 'aria-disabled': inert || undefined,\n tabIndex: index === tabStop ? 0 : -1,\n onFocus: () => setStop(index),\n // Keeps the focus, and so the selection, in the text on a mouse press.\n onMouseDown: (e: MouseEvent) => e.preventDefault(),\n className: clsx(BUTTON, active ? PRESSED : IDLE),\n };\n const icon = (\n <Icon aria-hidden className={clsx('h-4 w-4', spec.mirror && 'rtl:-scale-x-100')} />\n );\n\n const tooltip = (child: ReactElement) => (\n <Tooltip\n key={action}\n content={labels[action]}\n shortcut={shortcutKeys(spec.shortcut)}\n position=\"top\"\n >\n {child}\n </Tooltip>\n );\n\n if (action === 'link' && linkMode === 'popover') {\n return (\n <Popover key={action} open={linkOpen && !disabled} onOpenChange={onLinkOpenChange}>\n {tooltip(<Popover.Trigger {...common}>{icon}</Popover.Trigger>)}\n <Popover.Content\n aria-label={labels.linkDialog}\n position=\"bottom\"\n width=\"w-72\"\n padding=\"p-3\"\n >\n {linkField}\n </Popover.Content>\n </Popover>\n );\n }\n if (action === 'link') {\n return tooltip(\n <button\n type=\"button\"\n {...common}\n onClick={() => !disabled && onLinkOpenChange(true)}\n >\n {icon}\n </button>\n );\n }\n return tooltip(\n <button type=\"button\" {...common} onClick={() => !inert && spec.run?.(editor)}>\n {icon}\n </button>\n );\n })}\n </div>\n );\n}\n","import { ACTION_SPECS, type RichTextAction } from './actions';\n\n/** Every text the editor draws itself, so a host can translate it. All optional. */\nexport type RichTextLabels = Partial<Record<RichTextAction, string>> & {\n /** Accessible name of the toolbar. Default `Text formatting`. */\n toolbar?: string;\n /** Accessible name of the field where a link's URL is typed. Default `Link URL`. */\n linkUrl?: string;\n /** Accessible name of the link popover. Default `Edit link`. */\n linkDialog?: string;\n /** Default `Apply`. */\n linkApply?: string;\n /** Default `Remove link`. */\n linkRemove?: string;\n /** Shown when the URL is refused. Default `Enter an http(s), mailto or relative link.` */\n linkInvalid?: string;\n};\n\nexport type ResolvedLabels = Record<RichTextAction, string> &\n Required<Omit<RichTextLabels, RichTextAction>>;\n\nconst DEFAULTS = {\n toolbar: 'Text formatting',\n linkUrl: 'Link URL',\n linkDialog: 'Edit link',\n linkApply: 'Apply',\n linkRemove: 'Remove link',\n linkInvalid: 'Enter an http(s), mailto or relative link.',\n};\n\nexport const resolveLabels = (labels: RichTextLabels = {}): ResolvedLabels => {\n const actions = Object.fromEntries(\n (Object.keys(ACTION_SPECS) as RichTextAction[]).map((action) => [\n action,\n labels[action] ?? ACTION_SPECS[action].label,\n ])\n ) as Record<RichTextAction, string>;\n return {\n ...actions,\n toolbar: labels.toolbar ?? DEFAULTS.toolbar,\n linkUrl: labels.linkUrl ?? DEFAULTS.linkUrl,\n linkDialog: labels.linkDialog ?? DEFAULTS.linkDialog,\n linkApply: labels.linkApply ?? DEFAULTS.linkApply,\n linkRemove: labels.linkRemove ?? DEFAULTS.linkRemove,\n linkInvalid: labels.linkInvalid ?? DEFAULTS.linkInvalid,\n };\n};\n","import { clsx } from 'clsx';\nimport { useEffect, useId, useInsertionEffect, useMemo, useRef, useState } from 'react';\nimport type { KeyboardEvent, ReactNode } from 'react';\nimport { Extension } from '@tiptap/core';\nimport { EditorContent, useEditor, type JSONContent } from '@tiptap/react';\nimport type { Editor } from '@tiptap/react';\nimport { BubbleMenu } from '@tiptap/react/menus';\nimport { CharacterCount, Placeholder } from '@tiptap/extensions';\nimport StarterKit from '@tiptap/starter-kit';\nimport { useControllableState } from '../hooks/useControllableState';\nimport { isSafeLinkUrl } from '../chat/httpUrl';\nimport { fieldClass, type FieldSize } from '../forms/fieldRecipe';\nimport { RequiredMark } from '../forms/RequiredMark';\nimport { BUBBLE_ACTIONS, RICH_TEXT_ACTIONS, type RichTextAction } from './actions';\nimport { BlockDirection } from './blockDirection';\nimport { FormattingToolbar } from './FormattingToolbar';\nimport { resolveLabels, type RichTextLabels } from './labels';\n\n/** What `value` and `onChange` carry: the HTML string, or the ProseMirror JSON document. */\nexport type RichTextFormat = 'html' | 'json';\nexport type RichTextValue<F extends RichTextFormat> = F extends 'json' ? JSONContent : string;\n\n/**\n * `toolbar`: the buttons on top of the text. `bubble`: a small toolbar over the selected text.\n * `minimal`: no toolbar, only the keyboard shortcuts and the Markdown-like input rules.\n */\nexport type RichTextVariant = 'toolbar' | 'bubble' | 'minimal';\n\nexport type RichTextEditorProps<F extends RichTextFormat = 'html'> = {\n /** What `value`, `defaultValue` and `onChange` carry. Default `html`. */\n format?: F;\n /** The content, when the host owns it. HTML is `''` when empty. */\n value?: RichTextValue<F>;\n /** The starting content, when the editor owns it. */\n defaultValue?: RichTextValue<F>;\n /** Called with the new content after every edit, in `format`. An empty document is `''` in HTML. */\n onChange?: (value: RichTextValue<F>) => void;\n /** Default `toolbar`. */\n variant?: RichTextVariant;\n /**\n * The buttons, in order. Default: all of `RICH_TEXT_ACTIONS` for `toolbar`, the inline marks and\n * the link for `bubble`. Ignored by `minimal`.\n */\n toolbar?: readonly RichTextAction[];\n /** Replaces any text the editor draws itself: the buttons, their tooltips, the link field. */\n labels?: RichTextLabels;\n label?: string;\n description?: string;\n /** Message under the editor, in red. The editable text is `aria-invalid` and described by it. */\n error?: string;\n /** Marks the field required: an asterisk after the label and `aria-required` on the text. */\n required?: boolean;\n /** Slot rendered next to the label text (e.g. a TooltipHelp). */\n labelTrailing?: ReactNode;\n /** Text size and padding, aligned on the other fields. Default `md`. */\n size?: FieldSize;\n placeholder?: string;\n /** The text can be selected and its links followed, not changed. The toolbar is hidden. */\n readOnly?: boolean;\n /** Greyed out: the text and the buttons do nothing and are skipped by Tab. */\n disabled?: boolean;\n /**\n * Most characters of text (markup not counted), with a `<used> / <max>` counter. Typing stops\n * at the limit and a paste is cut there. A `defaultValue` or first `value` over it is kept and\n * flagged as invalid (`aria-invalid`, red counter) until it is cut below; a later `value` that\n * puts the text over the limit is not loaded.\n */\n maxLength?: number;\n /** Minimum height, in lines of text. Default `4`. */\n rows?: number;\n /** Focus the text, caret at the end, on mount. Default `false`. */\n autoFocus?: boolean;\n /** Id of the editable text. Default: generated. */\n id?: string;\n /** Posts the content with a native form: a hidden input of this name holds it (JSON as text). */\n name?: string;\n /** Accessible name when there is no `label`. */\n 'aria-label'?: string;\n className?: string;\n};\n\ntype Latest = {\n format: RichTextFormat;\n placeholder?: string;\n setCurrent: (content: Content) => void;\n openLink: () => boolean;\n};\n\nconst NO_PROPS: Latest = { format: 'html', setCurrent: () => {}, openLink: () => false };\n\nconst createStore = <T,>(initial: T) => {\n let value = initial;\n return {\n get: () => value,\n set: (next: T) => {\n value = next;\n },\n };\n};\n\nconst EMPTY_DOC: JSONContent = { type: 'doc', content: [{ type: 'paragraph' }] };\n\ntype Content = string | JSONContent;\n\nconst readContent = (editor: Editor, format: RichTextFormat): Content =>\n format === 'json' ? editor.getJSON() : editor.isEmpty ? '' : editor.getHTML();\n\nconst countCharacters = (editor: Editor) =>\n (editor.storage.characterCount?.characters() as number | undefined) ?? 0;\n\nconst sameContent = (a: Content, b: Content) =>\n typeof a === 'string' || typeof b === 'string'\n ? a === b\n : JSON.stringify(a) === JSON.stringify(b);\n\n// Mod-k, bound only where a link field exists.\nconst LinkShortcut = Extension.create<{ open: () => boolean }>({\n name: 'linkShortcut',\n addOptions: () => ({ open: () => false }),\n addKeyboardShortcuts() {\n return { 'Mod-k': () => this.options.open() };\n },\n});\n\n// The look of the text and of what the schema can hold. The classes sit on the editable element,\n// so a descendant variant reaches the nodes ProseMirror renders there.\n// Written out in full: Tailwind finds a class by reading the source, not by running it.\nconst CONTENT_CLASS = [\n 'min-w-0 outline-hidden break-words',\n '[&>*+*]:mt-2',\n // Each block follows the direction of what is typed in it, as a Textarea's paragraphs do\n // (`FIELD_PLAINTEXT`); lists and quotes take a `dir` from `BlockDirection`.\n '[&_p]:[unicode-bidi:plaintext] [&_h2]:[unicode-bidi:plaintext] [&_h3]:[unicode-bidi:plaintext]',\n '[&_h2]:text-lg [&_h2]:leading-snug [&_h2]:font-semibold',\n '[&_h3]:text-base [&_h3]:leading-snug [&_h3]:font-semibold',\n '[&_ul]:list-disc [&_ul]:ps-5 [&_ol]:list-decimal [&_ol]:ps-5 [&_li>p]:my-0',\n '[&_blockquote]:border-s-4 [&_blockquote]:border-gray-300 [&_blockquote]:ps-3 [&_blockquote]:text-gray-600',\n 'dark:[&_blockquote]:border-gray-600 dark:[&_blockquote]:text-gray-300',\n '[&_code]:rounded-sm [&_code]:bg-gray-100 [&_code]:px-1 [&_code]:font-mono [&_code]:text-[0.9em]',\n 'dark:[&_code]:bg-gray-800',\n '[&_a]:text-brand-600 dark:[&_a]:text-brand-400 [&_a]:underline [&_a]:underline-offset-2',\n '[&_p.is-editor-empty:first-child]:before:pointer-events-none [&_p.is-editor-empty:first-child]:before:float-start [&_p.is-editor-empty:first-child]:before:h-0',\n '[&_p.is-editor-empty:first-child]:before:text-gray-500 dark:[&_p.is-editor-empty:first-child]:before:text-gray-400',\n '[&_p.is-editor-empty:first-child]:before:content-[attr(data-placeholder)]',\n].join(' ');\n\n/**\n * A formatted text field, built on Tiptap: bold, italic, strike, headings, lists, quote, code,\n * links, undo and redo, behind a toolbar, a bubble over the selection, or only keyboard shortcuts.\n * Part of the `@sckyzo/cosmos-react/editor` entry, which needs the optional peer dependencies\n * (`@tiptap/react`, `@tiptap/starter-kit`, `@tiptap/extensions`, `@tiptap/core`, `@tiptap/pm`).\n *\n * The schema holds paragraphs, headings (2 and 3), bullet and numbered lists, quotes, hard\n * breaks and the marks above: nothing else survives a paste or `value`. Links go through\n * `isSafeLinkUrl` (http(s), mailto, relative). That is the editor's guarantee, not the server's:\n * the HTML a host stores has to be sanitised again where it is read back.\n */\nexport function RichTextEditor<F extends RichTextFormat = 'html'>({\n format = 'html' as F,\n value,\n defaultValue,\n onChange,\n variant = 'toolbar',\n toolbar,\n labels: labelProps,\n label,\n description,\n error,\n required,\n labelTrailing,\n size = 'md',\n placeholder,\n readOnly = false,\n disabled = false,\n maxLength,\n rows = 4,\n autoFocus = false,\n id,\n name,\n 'aria-label': ariaLabel,\n className,\n}: RichTextEditorProps<F>) {\n const generatedId = useId();\n const fieldId = id ?? generatedId;\n const labelId = `${fieldId}-label`;\n const descId = `${fieldId}-desc`;\n const labels = useMemo(() => resolveLabels(labelProps), [labelProps]);\n const actions = toolbar ?? (variant === 'bubble' ? BUBBLE_ACTIONS : RICH_TEXT_ACTIONS);\n const hasLinkField = variant !== 'minimal' && actions.includes('link');\n const editable = !readOnly && !disabled;\n\n const [current, setCurrent] = useControllableState<Content>({\n value: value as Content | undefined,\n defaultValue: defaultValue ?? (format === 'json' ? EMPTY_DOC : ''),\n onChange: (next) => onChange?.(next as RichTextValue<F>),\n name: 'RichTextEditor.value',\n });\n const [linkOpen, setLinkOpen] = useState(false);\n // Read from the editor on creation and on every transaction, which the host's `value` shows too.\n const [characters, setCharacters] = useState(0);\n\n // What the editor's callbacks read: they are created once, with the editor, and the latest\n // props must reach them. A store of its own, not a ref, which a render must not read.\n const [latest] = useState(() => createStore(NO_PROPS));\n const [echoes] = useState(() => createStore<Content[]>([]));\n useInsertionEffect(() => {\n latest.set({\n format,\n placeholder,\n setCurrent,\n openLink: () => {\n if (!hasLinkField || !editable) return false;\n setLinkOpen(true);\n return true;\n },\n });\n });\n\n const editor = useEditor(\n {\n // Created after the first render: the server and the first client render agree.\n immediatelyRender: false,\n shouldRerenderOnTransaction: false,\n editable,\n autofocus: autoFocus ? 'end' : false,\n content: current,\n extensions: [\n StarterKit.configure({\n heading: { levels: [2, 3] },\n // What the editor doesn't offer is out of the schema, so no paste or value brings it in.\n codeBlock: false,\n horizontalRule: false,\n underline: false,\n trailingNode: false,\n link: {\n openOnClick: false,\n markdownLinks: true,\n defaultProtocol: 'https',\n isAllowedUri: (url) => isSafeLinkUrl(url),\n },\n }),\n Placeholder.configure({ placeholder: () => latest.get().placeholder ?? '' }),\n ...(maxLength !== undefined ? [CharacterCount.configure({ limit: maxLength })] : []),\n LinkShortcut.configure({ open: () => latest.get().openLink() }),\n BlockDirection,\n ],\n onCreate: ({ editor: created }) => setCharacters(countCharacters(created)),\n onTransaction: ({ editor: changed }) => setCharacters(countCharacters(changed)),\n onUpdate: ({ editor: updated }) => {\n const content = readContent(updated, latest.get().format);\n echoes.get().push(content);\n latest.get().setCurrent(content);\n },\n },\n [maxLength, format]\n );\n\n // The host changed the value (or reset it): the editor shows it, without reporting it back.\n // `echoes` is what the editor reported and the host has not handed back yet. Typing is faster\n // than a render: by the time `value` comes back as \"Do\", the editor holds \"Doc\", and loading\n // \"Do\" would eat the \"c\". A value found in the queue is the echo of an edit, however late;\n // anything else is the host changing the content.\n useEffect(() => {\n if (!editor || editor.isDestroyed) return;\n const queue = echoes.get();\n const echo = queue.findIndex((sent) => sameContent(sent, current));\n if (echo >= 0) {\n queue.splice(0, echo + 1);\n return;\n }\n queue.length = 0;\n if (!sameContent(readContent(editor, format), current)) {\n editor.commands.setContent(current, { emitUpdate: false });\n }\n }, [editor, current, format, echoes]);\n\n useEffect(() => {\n if (editor && !editor.isDestroyed && editor.isEditable !== editable) {\n editor.setEditable(editable, false);\n }\n }, [editor, editable]);\n\n const overLimit = maxLength !== undefined && characters > maxLength;\n const invalid = !!error || overLimit;\n const hasDesc = !!(error || description);\n\n // The attributes of the editable element: its name, its description and its state, read by\n // assistive technology. `role=\"textbox\"` is Tiptap's own.\n const attributes = useMemo(\n () => ({\n id: fieldId,\n class: clsx(CONTENT_CLASS, 'px-3 py-2'),\n style: `min-height: ${rows * 1.5 + 1}em`,\n 'aria-multiline': 'true',\n ...(label ? { 'aria-labelledby': labelId } : ariaLabel ? { 'aria-label': ariaLabel } : {}),\n ...(hasDesc ? { 'aria-describedby': descId } : {}),\n ...(invalid ? { 'aria-invalid': 'true' } : {}),\n ...(required ? { 'aria-required': 'true' } : {}),\n ...(readOnly ? { 'aria-readonly': 'true' } : {}),\n ...(disabled ? { 'aria-disabled': 'true' } : {}),\n // A read-only text is still reachable by keyboard, to scroll it and follow its links.\n ...(!editable && !disabled ? { tabindex: '0' } : {}),\n }),\n [\n fieldId,\n rows,\n label,\n labelId,\n ariaLabel,\n hasDesc,\n descId,\n invalid,\n required,\n readOnly,\n disabled,\n editable,\n ]\n );\n useEffect(() => {\n if (editor && !editor.isDestroyed) editor.setOptions({ editorProps: { attributes } });\n }, [editor, attributes]);\n\n const bubbleRef = useRef<HTMLDivElement | null>(null);\n const onFrameKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n // Alt+F10: into the bubble over the selection. Escape there brings the focus back.\n if (variant !== 'bubble' || !event.altKey || event.key !== 'F10') return;\n const stop = bubbleRef.current?.querySelector<HTMLElement>('button[tabindex=\"0\"]');\n if (!stop) return;\n event.preventDefault();\n stop.focus();\n };\n\n const showToolbar = variant === 'toolbar' && !readOnly && editor;\n const counter = maxLength !== undefined;\n\n return (\n <div className={clsx('block', className)}>\n {label && (\n // The editable text isn't a labelable element, so the label names it by id.\n <span\n id={labelId}\n onClick={() => editor?.commands.focus()}\n className=\"mb-1.5 flex items-center gap-1.5 text-sm font-medium text-gray-700 dark:text-gray-300\"\n >\n {required ? (\n <span>\n {label}\n <RequiredMark />\n </span>\n ) : (\n label\n )}\n {labelTrailing}\n </span>\n )}\n <div\n onKeyDown={onFrameKeyDown}\n className={clsx(\n 'block w-full',\n fieldClass({\n size,\n invalid,\n within: true,\n readOnly: readOnly || disabled,\n fixedHeight: false,\n }),\n disabled && 'cursor-not-allowed opacity-50'\n )}\n >\n {showToolbar && (\n <FormattingToolbar\n editor={editor}\n actions={actions}\n labels={labels}\n disabled={disabled}\n linkOpen={linkOpen}\n onLinkOpenChange={setLinkOpen}\n linkMode=\"popover\"\n className=\"border-b border-gray-200 p-1 dark:border-gray-700\"\n />\n )}\n <EditorContent editor={editor} />\n {variant === 'bubble' && editor && editable && (\n <BubbleMenu\n editor={editor}\n updateDelay={0}\n options={{\n strategy: 'fixed',\n placement: 'top',\n offset: 8,\n onHide: () => setLinkOpen(false),\n }}\n // The z-index scale of floating panels (`FLOATING_PANEL_Z`).\n className=\"z-[9999]\"\n >\n <FormattingToolbar\n ref={bubbleRef}\n editor={editor}\n actions={actions}\n labels={labels}\n disabled={disabled}\n linkOpen={linkOpen}\n onLinkOpenChange={setLinkOpen}\n linkMode=\"inline\"\n onEscape={() => {\n setLinkOpen(false);\n editor.commands.focus();\n }}\n className=\"rounded-lg border border-gray-200 bg-white p-1 shadow-lg dark:border-gray-700 dark:bg-gray-900\"\n />\n </BubbleMenu>\n )}\n </div>\n <div className=\"mt-1 flex items-start justify-between gap-2\">\n <span\n id={descId}\n className={clsx(\n 'block min-h-[1rem] text-xs',\n error ? 'text-red-700 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'\n )}\n >\n {error ?? description ?? ''}\n </span>\n {counter && (\n // A count is a code: \"12 / 100\" reads in this order whatever the page's direction.\n <span\n dir=\"ltr\"\n aria-live=\"polite\"\n className={clsx(\n 'shrink-0 font-mono text-xs tabular-nums',\n overLimit ? 'text-red-700 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'\n )}\n >\n {characters} / {maxLength}\n </span>\n )}\n </div>\n {name && (\n <input\n type=\"hidden\"\n name={name}\n value={typeof current === 'string' ? current : JSON.stringify(current)}\n />\n )}\n </div>\n );\n}\n"]}
|