@marktiderman/genesis-ui 2.12.0 → 2.12.2
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/dist/{AppShell-DpQdcLE-.d.ts → AppShell-HCXpi6nv.d.ts} +3 -2
- package/dist/chunk-424PT5DM.js +21 -0
- package/dist/chunk-424PT5DM.js.map +1 -0
- package/dist/chunk-J45FHL7D.js +46 -0
- package/dist/chunk-J45FHL7D.js.map +1 -0
- package/dist/{chunk-SZMXNC5Q.js → chunk-MLZEKXV2.js} +3 -3
- package/dist/{chunk-SZMXNC5Q.js.map → chunk-MLZEKXV2.js.map} +1 -1
- package/dist/{chunk-XGG5RUDE.js → chunk-PMCUHSZS.js} +3 -3
- package/dist/{chunk-XGG5RUDE.js.map → chunk-PMCUHSZS.js.map} +1 -1
- package/dist/{chunk-3TWCZYZY.js → chunk-STZVZUYO.js} +3 -3
- package/dist/{chunk-3TWCZYZY.js.map → chunk-STZVZUYO.js.map} +1 -1
- package/dist/chunk-WALJMVEF.js +10 -0
- package/dist/chunk-WALJMVEF.js.map +1 -0
- package/dist/components/data/index.d.ts +7 -6
- package/dist/components/data/index.js +14 -13
- package/dist/components/data/index.js.map +1 -1
- package/dist/components/layout/dashboard-page.js +1 -0
- package/dist/components/layout/detail-page.js +1 -0
- package/dist/components/layout/form-page.js +1 -0
- package/dist/components/layout/index.d.ts +3 -2
- package/dist/components/layout/index.js +3 -2
- package/dist/components/layout/settings-page.js +1 -0
- package/dist/components/patterns/empty-state.js +1 -0
- package/dist/components/patterns/form-field.js +1 -0
- package/dist/components/patterns/index.js +1 -0
- package/dist/components/patterns/page-loading.js +1 -0
- package/dist/components/patterns/settings-row.js +1 -0
- package/dist/components/patterns/sortable-list.js +1 -0
- package/dist/components/patterns/status-badge.js +1 -0
- package/dist/components/patterns/toggle-row.js +1 -0
- package/dist/components/patterns/user-avatar.js +1 -0
- package/dist/components/rich-text/rich-text-editor.js +1 -0
- package/dist/components/rich-text/rich-text-editor.js.map +1 -1
- package/dist/components/rich-text/rich-text.js +1 -0
- package/dist/components/sheet-grid/sheet-grid.js +1 -0
- package/dist/components/sheet-grid/sheet-grid.js.map +1 -1
- package/dist/components/ui/accessible-icon.js +1 -0
- package/dist/components/ui/accordion.js +1 -0
- package/dist/components/ui/alert-dialog.js +1 -0
- package/dist/components/ui/alert.js +1 -0
- package/dist/components/ui/aspect-ratio.js +1 -0
- package/dist/components/ui/avatar.js +1 -0
- package/dist/components/ui/badge.js +1 -0
- package/dist/components/ui/breadcrumb.js +1 -0
- package/dist/components/ui/button-group.js +1 -0
- package/dist/components/ui/button.js +1 -0
- package/dist/components/ui/calendar.js +1 -0
- package/dist/components/ui/card.js +1 -0
- package/dist/components/ui/carousel.js +1 -0
- package/dist/components/ui/chart.js +1 -0
- package/dist/components/ui/checkbox.js +1 -0
- package/dist/components/ui/collapsible.js +1 -0
- package/dist/components/ui/command-palette.js +1 -0
- package/dist/components/ui/command.js +1 -0
- package/dist/components/ui/context-menu.js +1 -0
- package/dist/components/ui/date-picker.js +1 -0
- package/dist/components/ui/dialog.js +1 -0
- package/dist/components/ui/drawer.js +1 -0
- package/dist/components/ui/dropdown-menu.js +1 -0
- package/dist/components/ui/hover-card.js +1 -0
- package/dist/components/ui/input-group.js +1 -0
- package/dist/components/ui/input-otp.js +1 -0
- package/dist/components/ui/input.js +1 -0
- package/dist/components/ui/kbd.js +1 -0
- package/dist/components/ui/label.js +1 -0
- package/dist/components/ui/menubar.js +1 -0
- package/dist/components/ui/navigation-menu.js +1 -0
- package/dist/components/ui/pagination.js +1 -0
- package/dist/components/ui/password-toggle-field.js +1 -0
- package/dist/components/ui/popover.js +1 -0
- package/dist/components/ui/progress.js +1 -0
- package/dist/components/ui/radio-group.js +1 -0
- package/dist/components/ui/resizable.js +1 -0
- package/dist/components/ui/scroll-area.js +1 -0
- package/dist/components/ui/select.js +1 -0
- package/dist/components/ui/separator.js +1 -0
- package/dist/components/ui/sheet.js +1 -0
- package/dist/components/ui/skeleton.js +1 -0
- package/dist/components/ui/slider.js +1 -0
- package/dist/components/ui/sonner.js +1 -0
- package/dist/components/ui/spinner.js +1 -0
- package/dist/components/ui/switch.js +1 -0
- package/dist/components/ui/table.js +1 -0
- package/dist/components/ui/tabs.js +1 -0
- package/dist/components/ui/textarea.js +1 -0
- package/dist/components/ui/toggle-group.js +1 -0
- package/dist/components/ui/toggle.js +1 -0
- package/dist/components/ui/toolbar.js +1 -0
- package/dist/components/ui/tooltip.js +1 -0
- package/dist/components/ui/typography.js +1 -0
- package/dist/components/ui/visually-hidden.js +1 -0
- package/dist/hooks/index.d.ts +3 -3
- package/dist/hooks/index.js +4 -3
- package/dist/hooks/use-data-filters.d.ts +1 -1
- package/dist/hooks/use-data-filters.js +3 -2
- package/dist/hooks/use-keyboard-navigation.js +1 -0
- package/dist/hooks/use-mobile.js +1 -0
- package/dist/hooks/use-prefetch.js +1 -0
- package/dist/hooks/use-resource-page.js +1 -0
- package/dist/hooks/use-resource-url-state.d.ts +1 -1
- package/dist/hooks/use-resource-url-state.js +1 -0
- package/dist/hooks/use-saved-views.js +1 -0
- package/dist/hooks/use-view-preference.js +1 -0
- package/dist/hooks/use-view-settings.js +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +360 -2
- package/dist/index.js.map +1 -1
- package/dist/navigation-vmFJ6r1m.d.ts +90 -0
- package/dist/router/react-router.d.ts +1 -1
- package/dist/router/react-router.js +1 -0
- package/dist/router/react-router.js.map +1 -1
- package/dist/router/tanstack-router.d.ts +1 -1
- package/dist/router/tanstack-router.js +2 -1
- package/dist/router/tanstack-router.js.map +1 -1
- package/dist/status-colors.js +2 -0
- package/dist/status-colors.js.map +1 -1
- package/dist/{use-resource-table-DrTkD5O1.d.ts → use-resource-table-easmRDQI.d.ts} +2 -2
- package/dist/utils.js +1 -0
- package/package.json +4 -4
- package/dist/chunk-7S7LKQBD.js +0 -12
- package/dist/chunk-7S7LKQBD.js.map +0 -1
- package/dist/chunk-KC43CNMA.js +0 -141
- package/dist/chunk-KC43CNMA.js.map +0 -1
- package/dist/navigation-By1DrzaM.d.ts +0 -190
- package/dist/slots-tR0wf89f.d.ts +0 -60
|
@@ -2,5 +2,6 @@ export { DetailPage } from '../../chunk-AFZ76Q26.js';
|
|
|
2
2
|
import '../../chunk-D2LIXA2Y.js';
|
|
3
3
|
import '../../chunk-AVFZ4P4B.js';
|
|
4
4
|
import '../../chunk-NZ5WBA4R.js';
|
|
5
|
+
import '../../chunk-424PT5DM.js';
|
|
5
6
|
//# sourceMappingURL=detail-page.js.map
|
|
6
7
|
//# sourceMappingURL=detail-page.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { A as AppShell, a as AppShellOptions, b as AppShellPageHeader, c as AppShellProps, d as AppShellSubNavEnd, N as NavItem, P as ParentNavigation, S as SubNavItem, e as SubNavMode, f as SubNavTabs, g as SubNavTabsProps, U as UseAppShellSubNavOptions, u as useAppShellSubNav } from '../../AppShell-
|
|
2
|
-
export { G as GenesisLinkProps, L as LinkComponent
|
|
1
|
+
export { A as AppShell, a as AppShellOptions, b as AppShellPageHeader, c as AppShellProps, d as AppShellSubNavEnd, N as NavItem, P as ParentNavigation, S as SubNavItem, e as SubNavMode, f as SubNavTabs, g as SubNavTabsProps, U as UseAppShellSubNavOptions, u as useAppShellSubNav } from '../../AppShell-HCXpi6nv.js';
|
|
2
|
+
export { G as GenesisLinkProps, L as LinkComponent } from '../../navigation-vmFJ6r1m.js';
|
|
3
3
|
export { P as PageHeader, a as PageHeaderOptions, b as PageHeaderProps } from '../../PageHeader-V9lVkZtF.js';
|
|
4
4
|
export { DetailPage, DetailPageProps } from './detail-page.js';
|
|
5
5
|
export { FormPage, FormPageProps } from './form-page.js';
|
|
@@ -7,6 +7,7 @@ export { D as DashboardPage, a as DashboardPageProps, G as Grid, b as GridProps,
|
|
|
7
7
|
export { SettingsPage, SettingsPageProps, SettingsPageSection } from './settings-page.js';
|
|
8
8
|
export { C as Container, a as ContainerProps, G as GAP_CLASSES, S as Section, b as SectionProps, c as SpaceToken, d as Stack, e as StackProps, f as containerVariants, s as sectionHeadingVariants, g as spaceScale, h as stackVariants } from '../../spacing-BS6qECD4.js';
|
|
9
9
|
export { S as Split, a as SplitBreakpoint, b as SplitProps, c as SplitRatio, s as splitVariants } from '../../split-Dk9f4Mi0.js';
|
|
10
|
+
export { NavigationNode, ResolvedNavigation, resolveNavigation } from '@marktiderman/genesis-core/navigation';
|
|
10
11
|
import 'react';
|
|
11
12
|
import 'lucide-react';
|
|
12
13
|
import '../../view-toggle-CahQ87PW.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AppShell, AppShellPageHeader, AppShellSubNavEnd, PageHeader, SubNavTabs, useAppShellSubNav } from '../../chunk-
|
|
1
|
+
export { AppShell, AppShellPageHeader, AppShellSubNavEnd, PageHeader, SubNavTabs, useAppShellSubNav } from '../../chunk-MLZEKXV2.js';
|
|
2
2
|
import '../../chunk-46TZGMFW.js';
|
|
3
3
|
export { Container, Stack, containerVariants, stackVariants } from '../../chunk-4CQHPWJD.js';
|
|
4
4
|
import '../../chunk-B2GIBUQD.js';
|
|
@@ -18,6 +18,7 @@ export { GAP_CLASSES, spaceScale } from '../../chunk-AVFZ4P4B.js';
|
|
|
18
18
|
import '../../chunk-NWSCYLPT.js';
|
|
19
19
|
import '../../chunk-F47U5KNW.js';
|
|
20
20
|
import '../../chunk-NZ5WBA4R.js';
|
|
21
|
-
export { resolveNavigation } from '../../chunk-
|
|
21
|
+
export { resolveNavigation } from '../../chunk-J45FHL7D.js';
|
|
22
|
+
import '../../chunk-424PT5DM.js';
|
|
22
23
|
//# sourceMappingURL=index.js.map
|
|
23
24
|
//# sourceMappingURL=index.js.map
|
|
@@ -2,5 +2,6 @@ export { SettingsPage } from '../../chunk-P64MFQXZ.js';
|
|
|
2
2
|
import '../../chunk-D2LIXA2Y.js';
|
|
3
3
|
import '../../chunk-AVFZ4P4B.js';
|
|
4
4
|
import '../../chunk-NZ5WBA4R.js';
|
|
5
|
+
import '../../chunk-424PT5DM.js';
|
|
5
6
|
//# sourceMappingURL=settings-page.js.map
|
|
6
7
|
//# sourceMappingURL=settings-page.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { EmptyState, NoFeaturesFound, NoFeedbackFound, NoSearchResults } from '../../chunk-65SPT7EA.js';
|
|
2
2
|
import '../../chunk-NWSCYLPT.js';
|
|
3
3
|
import '../../chunk-NZ5WBA4R.js';
|
|
4
|
+
import '../../chunk-424PT5DM.js';
|
|
4
5
|
//# sourceMappingURL=empty-state.js.map
|
|
5
6
|
//# sourceMappingURL=empty-state.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { FormDescription, FormError, FormField, FormLabel } from '../../chunk-R7QFP6EL.js';
|
|
2
2
|
import '../../chunk-F47U5KNW.js';
|
|
3
3
|
import '../../chunk-NZ5WBA4R.js';
|
|
4
|
+
import '../../chunk-424PT5DM.js';
|
|
4
5
|
//# sourceMappingURL=form-field.js.map
|
|
5
6
|
//# sourceMappingURL=form-field.js.map
|
|
@@ -17,5 +17,6 @@ import '../../chunk-NWSCYLPT.js';
|
|
|
17
17
|
export { FormDescription, FormError, FormField, FormLabel } from '../../chunk-R7QFP6EL.js';
|
|
18
18
|
import '../../chunk-F47U5KNW.js';
|
|
19
19
|
import '../../chunk-NZ5WBA4R.js';
|
|
20
|
+
import '../../chunk-424PT5DM.js';
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
|
21
22
|
//# sourceMappingURL=index.js.map
|
|
@@ -2,5 +2,6 @@ export { SettingsRow } from '../../chunk-A7AHVDG7.js';
|
|
|
2
2
|
import '../../chunk-R7QFP6EL.js';
|
|
3
3
|
import '../../chunk-F47U5KNW.js';
|
|
4
4
|
import '../../chunk-NZ5WBA4R.js';
|
|
5
|
+
import '../../chunk-424PT5DM.js';
|
|
5
6
|
//# sourceMappingURL=settings-row.js.map
|
|
6
7
|
//# sourceMappingURL=settings-row.js.map
|
|
@@ -2,5 +2,6 @@ export { SortableList } from '../../chunk-25XEXYGC.js';
|
|
|
2
2
|
import '../../chunk-I4NBE2KL.js';
|
|
3
3
|
import '../../chunk-QJ6P2DW6.js';
|
|
4
4
|
import '../../chunk-NZ5WBA4R.js';
|
|
5
|
+
import '../../chunk-424PT5DM.js';
|
|
5
6
|
//# sourceMappingURL=sortable-list.js.map
|
|
6
7
|
//# sourceMappingURL=sortable-list.js.map
|
|
@@ -9,6 +9,7 @@ import { Popover, PopoverTrigger, PopoverContent } from '../../chunk-22XB3Q6H.js
|
|
|
9
9
|
import { Button } from '../../chunk-NWSCYLPT.js';
|
|
10
10
|
import { Label } from '../../chunk-F47U5KNW.js';
|
|
11
11
|
import { cn } from '../../chunk-NZ5WBA4R.js';
|
|
12
|
+
import '../../chunk-424PT5DM.js';
|
|
12
13
|
import * as React from 'react';
|
|
13
14
|
import { Node, Extension } from '@tiptap/core';
|
|
14
15
|
import { useEditor, useEditorState, EditorContent } from '@tiptap/react';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/rich-text/video-embed.ts","../../../src/components/rich-text/rich-text-editor.tsx"],"names":["RichTextEditor","LinkIcon"],"mappings":"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","file":"rich-text-editor.js","sourcesContent":["\"use client\";\n\n/**\n * VideoEmbed — a Tiptap node for YouTube, Vimeo and Loom players.\n *\n * The node stores only `{ provider, id, hash?, title? }`, never a URL, and\n * rebuilds the player URL from those validated parts every time it renders.\n * A pasted `<iframe>` is accepted only when its `src` parses as one of the\n * three hosts; any other iframe is dropped by the editor's schema.\n *\n * Exported for apps that assemble their own Tiptap editor and want the same\n * embed node `RichTextEditor` uses.\n */\nimport { Node } from \"@tiptap/core\";\nimport {\n type VideoEmbedAttrs,\n VIDEO_IFRAME_ATTRS,\n parseVideoUrl,\n sanitizeVideoEmbedAttrs,\n videoEmbedSrc,\n videoEmbedTitle,\n} from \"./rich-text-doc\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n videoEmbed: {\n /**\n * Insert a video embed from a YouTube, Vimeo or Loom URL. Fails (returns\n * false, inserts nothing) for any other URL.\n */\n setVideoEmbed: (options: { url: string; title?: string }) => ReturnType;\n };\n }\n}\n\nconst noRender = { renderHTML: () => ({}) };\n\n/**\n * Tiptap node for YouTube, Vimeo and Loom players, stored as\n * `{ provider, id, hash?, title? }` and rebuilt from those parts on render.\n * Adds the `setVideoEmbed({ url, title })` command.\n *\n * @stability Beta\n */\nexport const VideoEmbed = Node.create({\n name: \"videoEmbed\",\n group: \"block\",\n atom: true,\n draggable: true,\n selectable: true,\n\n addAttributes() {\n return {\n provider: { default: null, ...noRender },\n id: { default: null, ...noRender },\n hash: { default: null, ...noRender },\n title: { default: null, ...noRender },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"div[data-video-embed]\",\n priority: 60,\n getAttrs: (el) => {\n const attrs = sanitizeVideoEmbedAttrs({\n provider: el.getAttribute(\"data-provider\"),\n id: el.getAttribute(\"data-id\"),\n hash: el.getAttribute(\"data-hash\") ?? undefined,\n title: el.getAttribute(\"data-title\") ?? undefined,\n });\n return attrs ? { ...attrs } : false;\n },\n },\n {\n tag: \"iframe[src]\",\n getAttrs: (el) => {\n const parsed = parseVideoUrl(el.getAttribute(\"src\") ?? \"\");\n if (!parsed) return false;\n const attrs = sanitizeVideoEmbedAttrs({ ...parsed, title: el.getAttribute(\"title\") ?? undefined });\n return attrs ? { ...attrs } : false;\n },\n },\n ];\n },\n\n renderHTML({ node }) {\n const attrs = sanitizeVideoEmbedAttrs(node.attrs);\n if (!attrs) return [\"div\", { \"data-video-embed-invalid\": \"\" }];\n const title = videoEmbedTitle(attrs);\n return [\n \"div\",\n {\n \"data-video-embed\": \"\",\n \"data-provider\": attrs.provider,\n \"data-id\": attrs.id,\n ...(attrs.hash ? { \"data-hash\": attrs.hash } : {}),\n ...(attrs.title ? { \"data-title\": attrs.title } : {}),\n },\n [\n \"iframe\",\n {\n src: videoEmbedSrc(attrs),\n title,\n allow: VIDEO_IFRAME_ATTRS.allow,\n allowfullscreen: \"true\",\n loading: VIDEO_IFRAME_ATTRS.loading,\n referrerpolicy: VIDEO_IFRAME_ATTRS.referrerPolicy,\n sandbox: VIDEO_IFRAME_ATTRS.sandbox,\n // Inside the editor the frame is not a tab stop: the node is\n // selected and deleted as a whole, and playback happens in the\n // read-only view.\n tabindex: \"-1\",\n },\n ],\n ];\n },\n\n addCommands() {\n return {\n setVideoEmbed:\n ({ url, title }) =>\n ({ commands, state }) => {\n const parsed = parseVideoUrl(url);\n if (!parsed) return false;\n const attrs: VideoEmbedAttrs | null = sanitizeVideoEmbedAttrs({ ...parsed, title });\n if (!attrs) return false;\n const node = { type: this.name, attrs: { ...attrs } };\n // Insert BETWEEN top-level blocks rather than at the caret, which\n // would split the paragraph or heading the caret is in. An empty\n // paragraph is replaced instead of being left behind.\n const { $from } = state.selection;\n if ($from.depth === 0) return commands.insertContent(node);\n const block = $from.node(1);\n if (block.type.name === \"paragraph\" && block.content.size === 0) {\n return commands.insertContentAt({ from: $from.before(1), to: $from.after(1) }, node);\n }\n return commands.insertContentAt($from.after(1), node);\n },\n };\n },\n});\n","\"use client\";\n\n/**\n * RichTextEditor — a WYSIWYG editor for formatted content (headings, bold,\n * italic, underline, lists, links, quotes and optional video embeds), built\n * on Tiptap 3 (ProseMirror) with a Genesis `Toolbar`.\n *\n * Lives on its own subpath, `@marktiderman/genesis-ui/rich-text-editor`, so\n * only apps that import it need the `@tiptap/*` peers. The read-only\n * renderer and the server-safe helpers are on `/rich-text`.\n *\n * @stability Beta\n */\nimport * as React from \"react\";\nimport { Extension } from \"@tiptap/core\";\nimport { EditorContent, useEditor, useEditorState, type Editor } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport { CharacterCount, Placeholder } from \"@tiptap/extensions\";\nimport {\n Bold,\n Heading2,\n Heading3,\n Heading4,\n Italic,\n Link as LinkIcon,\n List,\n ListOrdered,\n Quote,\n Redo2,\n Underline,\n Undo2,\n Video,\n} from \"lucide-react\";\n\nimport { cn } from \"../../utils\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { Kbd } from \"../ui/kbd\";\nimport { Label } from \"../ui/label\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/popover\";\nimport {\n Toolbar,\n ToolbarButton,\n ToolbarSeparator,\n ToolbarToggleGroup,\n ToolbarToggleItem,\n} from \"../ui/toolbar\";\nimport { Tooltip } from \"../ui/tooltip\";\nimport {\n type RichTextDoc,\n type RichTextHeadingLevel,\n type SanitizeRichTextOptions,\n isRichTextDoc,\n isRichTextEmpty,\n isSafeUrl,\n normalizeLinkUrl,\n parseVideoUrl,\n richTextToHtml,\n richTextToPlainText,\n sanitizeRichTextDoc,\n} from \"./rich-text-doc\";\nimport { RichText, richTextClassName } from \"./rich-text\";\nimport { VideoEmbed } from \"./video-embed\";\n\nexport { VideoEmbed } from \"./video-embed\";\nexport type { RichTextDoc, RichTextHeadingLevel } from \"./rich-text-doc\";\n\n/**\n * What the editor accepts as a value: the document JSON (canonical), or an\n * HTML string. HTML is parsed by the editor in the browser and reduced to\n * the editor's schema, so it is a migration convenience, not a storage\n * format. Output is always JSON plus derived, sanitized HTML.\n */\nexport type RichTextEditorValue = RichTextDoc | string;\n\n/** Derived forms of the document, computed on first read. */\nexport interface RichTextChangeDetails {\n /** Sanitized HTML from `richTextToHtml`. */\n readonly html: string;\n /** Plain text from `richTextToPlainText`. */\n readonly text: string;\n /** True when there is no visible text and no embed. */\n readonly isEmpty: boolean;\n /** Character count of the text (what `maxLength` limits). */\n readonly characters: number;\n}\n\nexport type RichTextToolbarItem =\n | \"heading2\"\n | \"heading3\"\n | \"heading4\"\n | \"bold\"\n | \"italic\"\n | \"underline\"\n | \"bulletList\"\n | \"orderedList\"\n | \"blockquote\"\n | \"link\"\n | \"video\"\n | \"undo\"\n | \"redo\";\n\nexport interface RichTextEditorLabels {\n toolbar: string;\n blockGroup: string;\n markGroup: string;\n heading2: string;\n heading3: string;\n heading4: string;\n bold: string;\n italic: string;\n underline: string;\n bulletList: string;\n orderedList: string;\n blockquote: string;\n link: string;\n video: string;\n undo: string;\n redo: string;\n linkUrl: string;\n linkApply: string;\n linkRemove: string;\n linkInvalid: string;\n videoUrl: string;\n videoTitle: string;\n videoInsert: string;\n videoInvalid: string;\n cancel: string;\n characterCount: (count: number, max: number | undefined) => string;\n}\n\nconst DEFAULT_LABELS: RichTextEditorLabels = {\n toolbar: \"Formatting\",\n blockGroup: \"Paragraph style\",\n markGroup: \"Text style\",\n heading2: \"Heading 2\",\n heading3: \"Heading 3\",\n heading4: \"Heading 4\",\n bold: \"Bold\",\n italic: \"Italic\",\n underline: \"Underline\",\n bulletList: \"Bulleted list\",\n orderedList: \"Numbered list\",\n blockquote: \"Quote\",\n link: \"Link\",\n video: \"Embed video\",\n undo: \"Undo\",\n redo: \"Redo\",\n linkUrl: \"Link address\",\n linkApply: \"Apply\",\n linkRemove: \"Remove link\",\n linkInvalid: \"Enter a web address (https://…), an email address or a relative path.\",\n videoUrl: \"YouTube, Vimeo or Loom link\",\n videoTitle: \"Title (read by screen readers)\",\n videoInsert: \"Insert\",\n videoInvalid: \"Paste a YouTube, Vimeo or Loom video link.\",\n cancel: \"Cancel\",\n characterCount: (count, max) =>\n max ? `${count.toLocaleString()} / ${max.toLocaleString()} characters` : `${count.toLocaleString()} characters`,\n};\n\n/** Imperative handle exposed through `ref`. */\nexport interface RichTextEditorHandle {\n /** Move focus into the editable area. */\n focus: () => void;\n /** Replace the content with an empty document (fires `onChange`). */\n clear: () => void;\n /** The current document, sanitized. */\n getJSON: () => RichTextDoc;\n /** The current document as sanitized HTML. */\n getHTML: () => string;\n /** The underlying Tiptap editor, once mounted (null during SSR/first paint). */\n readonly editor: Editor | null;\n}\n\nexport interface RichTextEditorProps {\n /**\n * Controlled value. Pass back the `doc` from `onChange` synchronously; any\n * other document (including an older one from a debounced or deferred\n * parent) replaces the content and resets the selection.\n */\n value?: RichTextEditorValue;\n /** Initial value for an uncontrolled editor. */\n defaultValue?: RichTextEditorValue;\n /**\n * Called on every edit with the sanitized document. `details` derives HTML\n * and text lazily, so reading only `doc` costs no serialization.\n */\n onChange?: (doc: RichTextDoc, details: RichTextChangeDetails) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n /**\n * `id` of the editable element. A `<label htmlFor={id}>` names the editor\n * (wired as `aria-labelledby`, since a contenteditable is not a labelable\n * element) and clicking it focuses the editor.\n */\n id?: string;\n /**\n * Form field name. When set, a hidden input carries the document as JSON\n * so a native `<form>` submission includes it.\n */\n name?: string;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n /** Marks the field invalid (`aria-invalid`, destructive border). */\n invalid?: boolean;\n /** Placeholder shown while the document is empty. */\n placeholder?: string;\n /** Content is visible and selectable but not editable; the toolbar is hidden. */\n readOnly?: boolean;\n /** Not editable, toolbar disabled, dimmed. */\n disabled?: boolean;\n autoFocus?: boolean;\n /** Heading levels offered in the toolbar and kept in the document. Default `[2, 3]`. Read at mount. */\n headingLevels?: readonly RichTextHeadingLevel[];\n /** Enable YouTube / Vimeo / Loom embeds (toolbar button and schema). Default `false`. Read at mount. */\n embeds?: boolean;\n /** Maximum characters. Typing and pasting stop at the limit. Read at mount. */\n maxLength?: number;\n /** Show the character count under the editor. On by default when `maxLength` is set. */\n showCharacterCount?: boolean;\n /** Toolbar items, in groups as listed. `false` hides the toolbar (shortcuts still work). */\n toolbar?: false | readonly RichTextToolbarItem[];\n /** Override any user-facing string (for translation). */\n labels?: Partial<RichTextEditorLabels>;\n /** Classes for the outer frame. */\n className?: string;\n /** Classes for the editable area (for example a taller `min-h-*`). */\n contentClassName?: string;\n /** Stable test/automation selector (emitted as `data-testid` on the frame). */\n testID?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Toolbar definitions\n// ---------------------------------------------------------------------------\n\ntype Keys = readonly string[];\n\ninterface ToggleDef {\n id: RichTextToolbarItem;\n icon: React.ComponentType<{ className?: string }>;\n keys: Keys;\n isActive: (e: Editor) => boolean;\n run: (e: Editor) => void;\n}\n\nconst MARKS: ToggleDef[] = [\n {\n id: \"bold\",\n icon: Bold,\n keys: [\"Mod\", \"B\"],\n isActive: (e) => e.isActive(\"bold\"),\n run: (e) => e.chain().focus().toggleBold().run(),\n },\n {\n id: \"italic\",\n icon: Italic,\n keys: [\"Mod\", \"I\"],\n isActive: (e) => e.isActive(\"italic\"),\n run: (e) => e.chain().focus().toggleItalic().run(),\n },\n {\n id: \"underline\",\n icon: Underline,\n keys: [\"Mod\", \"U\"],\n isActive: (e) => e.isActive(\"underline\"),\n run: (e) => e.chain().focus().toggleUnderline().run(),\n },\n];\n\nconst heading = (level: RichTextHeadingLevel, icon: ToggleDef[\"icon\"]): ToggleDef => ({\n id: `heading${level}` as RichTextToolbarItem,\n icon,\n keys: [\"Mod\", \"Alt\", String(level)],\n isActive: (e) => e.isActive(\"heading\", { level }),\n run: (e) => e.chain().focus().toggleHeading({ level }).run(),\n});\n\nconst BLOCKS: ToggleDef[] = [\n heading(2, Heading2),\n heading(3, Heading3),\n heading(4, Heading4),\n {\n id: \"bulletList\",\n icon: List,\n keys: [\"Mod\", \"Shift\", \"8\"],\n isActive: (e) => e.isActive(\"bulletList\"),\n run: (e) => e.chain().focus().toggleBulletList().run(),\n },\n {\n id: \"orderedList\",\n icon: ListOrdered,\n keys: [\"Mod\", \"Shift\", \"7\"],\n isActive: (e) => e.isActive(\"orderedList\"),\n run: (e) => e.chain().focus().toggleOrderedList().run(),\n },\n {\n id: \"blockquote\",\n icon: Quote,\n keys: [\"Mod\", \"Shift\", \"B\"],\n isActive: (e) => e.isActive(\"blockquote\"),\n run: (e) => e.chain().focus().toggleBlockquote().run(),\n },\n];\n\nconst ALL_TOGGLES = [...MARKS, ...BLOCKS];\n\n// The rules Tiptap would inject as a <style> tag (`injectCSS: false` turns\n// that off for strict CSPs), as classes on the editable element. The gap\n// cursor uses the foreground token instead of black and does not blink.\nconst PROSEMIRROR_BASE = cn(\n \"relative break-words whitespace-break-spaces [font-variant-ligatures:none] [font-feature-settings:'liga'_0]\",\n \"[&_[contenteditable=false]]:whitespace-normal [&_[contenteditable=false]_[contenteditable=true]]:whitespace-pre-wrap [&_pre]:whitespace-pre-wrap\",\n \"[&_img.ProseMirror-separator]:!inline [&_img.ProseMirror-separator]:!m-0 [&_img.ProseMirror-separator]:!h-0 [&_img.ProseMirror-separator]:!w-0 [&_img.ProseMirror-separator]:!border-0\",\n \"[&_.ProseMirror-gapcursor]:pointer-events-none [&_.ProseMirror-gapcursor]:absolute [&_.ProseMirror-gapcursor]:m-0 [&_.ProseMirror-gapcursor]:hidden [&.ProseMirror-focused_.ProseMirror-gapcursor]:block\",\n \"[&_.ProseMirror-gapcursor]:after:absolute [&_.ProseMirror-gapcursor]:after:-top-0.5 [&_.ProseMirror-gapcursor]:after:block [&_.ProseMirror-gapcursor]:after:w-5 [&_.ProseMirror-gapcursor]:after:border-t [&_.ProseMirror-gapcursor]:after:border-foreground [&_.ProseMirror-gapcursor]:after:content-['']\",\n \"[&.ProseMirror-hideselection_*]:caret-transparent [&.ProseMirror-hideselection_*]:selection:bg-transparent\",\n);\n\nconst PRESSED_CLASS =\"h-8 w-8 px-0 aria-pressed:bg-accent aria-pressed:text-accent-foreground\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Detect Apple platforms after mount, so SSR and first paint agree (\"Ctrl\"). */\nfunction useIsApple(): boolean {\n const [apple, setApple] = React.useState(false);\n React.useEffect(() => {\n const nav = navigator as Navigator & { userAgentData?: { platform?: string } };\n const platform = nav.userAgentData?.platform ?? nav.platform ?? \"\";\n setApple(/mac|iphone|ipad|ipod/i.test(platform));\n }, []);\n return apple;\n}\n\nfunction keyLabel(key: string, apple: boolean): string {\n if (key === \"Mod\") return apple ? \"⌘\" : \"Ctrl\";\n if (key === \"Alt\") return apple ? \"⌥\" : \"Alt\";\n if (key === \"Shift\") return apple ? \"⇧\" : \"Shift\";\n return key;\n}\n\nfunction ariaKeys(keys: Keys, apple: boolean): string {\n return keys\n .map((k) => (k === \"Mod\" ? (apple ? \"Meta\" : \"Control\") : k))\n .join(\"+\");\n}\n\nfunction ShortcutHint({ label, keys, apple }: { label: string; keys?: Keys; apple: boolean }) {\n return (\n <span className=\"inline-flex items-center gap-2\">\n {label}\n {keys && (\n <span className=\"inline-flex items-center gap-0.5\">\n {keys.map((k) => (\n <Kbd key={k}>{keyLabel(k, apple)}</Kbd>\n ))}\n </span>\n )}\n </span>\n );\n}\n\nfunction initialContent(\n value: RichTextEditorValue | undefined,\n opts: SanitizeRichTextOptions,\n): RichTextDoc | string {\n if (typeof value === \"string\") return value;\n return sanitizeRichTextDoc(value ?? null, opts);\n}\n\nfunction detailsFor(doc: RichTextDoc, characters: () => number, opts: SanitizeRichTextOptions): RichTextChangeDetails {\n let html: string | undefined;\n let text: string | undefined;\n return {\n get html() {\n return (html ??= richTextToHtml(doc, opts));\n },\n get text() {\n return (text ??= richTextToPlainText(doc));\n },\n get isEmpty() {\n return isRichTextEmpty(doc);\n },\n get characters() {\n return characters();\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * RichTextEditor — formatted text input for lessons, notes and other\n * long-form content.\n *\n * - **Value:** JSON is canonical (`RichTextDoc`). `onChange` hands you the\n * sanitized document plus lazily derived `html`/`text`. Store the JSON;\n * on the server re-run `sanitizeRichTextDoc` and derive HTML with\n * `richTextToHtml` (both from `/rich-text`, no DOM needed).\n * - **Security:** output goes through the same allow-list as `RichText`;\n * links keep only http(s)/mailto/tel/relative URLs; embeds are rebuilt\n * from a validated YouTube/Vimeo/Loom id.\n * - **SSR:** the editor mounts on the client only (Tiptap\n * `immediatelyRender: false`). Until then a JSON value renders read-only,\n * so server HTML shows the content instead of an empty box.\n * - **Keyboard:** standard shortcuts (⌘/Ctrl+B, I, U, K for link,\n * ⌘/Ctrl+Alt+2/3 for headings, ⌘/Ctrl+Shift+7/8 for lists, ⌘/Ctrl+Shift+B\n * for quote, ⌘/Ctrl+Z / Shift+Z), shown in each toolbar tooltip. The\n * toolbar is one tab stop with arrow-key navigation (Radix Toolbar).\n *\n * @stability Beta\n */\nexport const RichTextEditor = React.forwardRef<RichTextEditorHandle, RichTextEditorProps>(\n function RichTextEditor(props, ref) {\n const {\n value,\n defaultValue,\n onChange,\n onFocus,\n onBlur,\n id: idProp,\n name,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n invalid = false,\n placeholder,\n readOnly = false,\n disabled = false,\n autoFocus = false,\n headingLevels = [2, 3],\n embeds = false,\n maxLength,\n showCharacterCount,\n toolbar,\n labels: labelsProp,\n className,\n contentClassName,\n testID,\n } = props;\n\n const labels = React.useMemo(() => ({ ...DEFAULT_LABELS, ...labelsProp }), [labelsProp]);\n const generatedId = React.useId();\n const editorId = idProp ?? `rte-${generatedId}`;\n const countId = `${editorId}-count`;\n const apple = useIsApple();\n\n // Mount-time configuration. The schema (heading levels, embeds) and the\n // character limit are fixed for the editor's lifetime; changing them\n // means remounting (give the component a new `key`).\n const [config] = React.useState(() => ({\n opts: { headingLevels, embeds } satisfies SanitizeRichTextOptions,\n maxLength,\n }));\n const { opts } = config;\n\n const onChangeRef = React.useRef(onChange);\n const onFocusRef = React.useRef(onFocus);\n const onBlurRef = React.useRef(onBlur);\n const placeholderRef = React.useRef(placeholder);\n const stringControlledRef = React.useRef(typeof value === \"string\");\n const openLinkRef = React.useRef<() => boolean>(() => false);\n React.useEffect(() => {\n onChangeRef.current = onChange;\n onFocusRef.current = onFocus;\n onBlurRef.current = onBlur;\n placeholderRef.current = placeholder;\n stringControlledRef.current = typeof value === \"string\";\n });\n\n // The last document we emitted (reference and HTML), so a controlled\n // parent echoing it back does not reset the selection.\n const lastEmitted = React.useRef<{ doc: RichTextDoc | null; html: string | null }>({\n doc: null,\n html: null,\n });\n const [initial] = React.useState(() => initialContent(value ?? defaultValue, opts));\n const [formValue, setFormValue] = React.useState(() =>\n isRichTextDoc(initial) ? JSON.stringify(initial) : \"\",\n );\n\n const extensions = React.useMemo(\n () => [\n StarterKit.configure({\n code: false,\n codeBlock: false,\n strike: false,\n horizontalRule: false,\n heading: { levels: [...opts.headingLevels] },\n link: {\n openOnClick: false,\n autolink: true,\n linkOnPaste: true,\n defaultProtocol: \"https\",\n // Same rule as the sanitizer, so a link the editor shows is a link\n // that survives `onChange`.\n isAllowedUri: (url, ctx) => ctx.defaultValidate(url) && isSafeUrl(url),\n },\n }),\n Placeholder.configure({ placeholder: () => placeholderRef.current ?? \"\" }),\n CharacterCount.configure({ limit: config.maxLength ?? null }),\n ...(opts.embeds ? [VideoEmbed] : []),\n Extension.create({\n name: \"genesisLinkShortcut\",\n addKeyboardShortcuts: () => ({\n // Only claims the shortcut when the link control is there to open.\n \"Mod-k\": () => openLinkRef.current(),\n }),\n }),\n ],\n // Mount-time only, by design (see `config` above).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n const editor = useEditor({\n extensions,\n content: initial,\n immediatelyRender: false,\n // Tiptap's base styles are in PROSEMIRROR_BASE instead of an injected\n // <style> tag, so the editor works under a strict style-src CSP.\n injectCSS: false,\n shouldRerenderOnTransaction: false,\n editable: !readOnly && !disabled,\n autofocus: autoFocus ? \"end\" : false,\n onUpdate: ({ editor: e }) => {\n const doc = sanitizeRichTextDoc(e.getJSON(), opts);\n const details = detailsFor(doc, () => e.storage.characterCount.characters(), opts);\n lastEmitted.current = { doc, html: null };\n if (name) setFormValue(JSON.stringify(doc));\n const cb = onChangeRef.current;\n if (cb) {\n cb(doc, details);\n // Only serialize HTML for string-controlled parents.\n if (stringControlledRef.current) lastEmitted.current.html = details.html;\n }\n },\n onFocus: () => onFocusRef.current?.(),\n onBlur: () => onBlurRef.current?.(),\n });\n\n const state = useEditorState({\n editor,\n // Reads the `editor` from this render rather than the snapshot's: the\n // snapshot only refreshes on a transaction, so right after mount it\n // still holds `null` and the toolbar (and count) would start blank.\n selector: () => {\n const e = editor;\n if (!e) return null;\n const active: Partial<Record<RichTextToolbarItem, boolean>> = {};\n for (const def of ALL_TOGGLES) active[def.id] = def.isActive(e);\n return {\n active,\n link: e.isActive(\"link\"),\n canUndo: e.can().undo(),\n canRedo: e.can().redo(),\n characters: e.storage.characterCount.characters() as number,\n };\n },\n });\n\n // Once mounted: the hidden form value reflects the parsed document (an\n // HTML defaultValue is only parsed now), and a string-controlled value is\n // recorded as already applied so the first render does not reset the caret.\n React.useEffect(() => {\n if (!editor) return;\n if (typeof initial === \"string\") {\n lastEmitted.current = { doc: null, html: initial };\n setFormValue(JSON.stringify(sanitizeRichTextDoc(editor.getJSON(), opts)));\n }\n }, [editor, initial, opts]);\n\n // `<label htmlFor={id}>`: name the editor and focus it on click.\n const [labelId, setLabelId] = React.useState<string | undefined>(undefined);\n React.useEffect(() => {\n if (!editor || ariaLabel || ariaLabelledBy || typeof document === \"undefined\") return;\n const label = document.querySelector<HTMLLabelElement>(`label[for=\"${CSS.escape(editorId)}\"]`);\n if (!label) return;\n if (!label.id) label.id = `${editorId}-label`;\n setLabelId(label.id);\n const onClick = (event: MouseEvent) => {\n event.preventDefault();\n editor.commands.focus();\n };\n label.addEventListener(\"click\", onClick);\n return () => label.removeEventListener(\"click\", onClick);\n }, [editor, editorId, ariaLabel, ariaLabelledBy]);\n\n // Editable follows readOnly/disabled.\n React.useEffect(() => {\n editor?.setEditable(!readOnly && !disabled, false);\n }, [editor, readOnly, disabled]);\n\n // Controlled value: apply only values that differ from what we emitted.\n React.useEffect(() => {\n if (!editor || value === undefined) return;\n const last = lastEmitted.current;\n if (typeof value === \"string\") {\n if (value === last.html) return;\n } else if (value === last.doc) {\n return;\n }\n const next = initialContent(value, opts);\n if (\n typeof next !== \"string\" &&\n JSON.stringify(sanitizeRichTextDoc(editor.getJSON(), opts)) === JSON.stringify(next)\n ) {\n return;\n }\n editor.commands.setContent(next, { emitUpdate: false });\n const doc = sanitizeRichTextDoc(editor.getJSON(), opts);\n lastEmitted.current = { doc: typeof value === \"string\" ? null : value, html: typeof value === \"string\" ? value : null };\n if (name) setFormValue(JSON.stringify(doc));\n }, [editor, value, opts, name]);\n\n // ARIA and classes on the editable element follow props.\n const countVisible = showCharacterCount ?? config.maxLength !== undefined;\n const describedBy = [ariaDescribedBy, countVisible ? countId : null].filter(Boolean).join(\" \") || undefined;\n const contentClasses = cn(\n richTextClassName,\n PROSEMIRROR_BASE,\n \"min-h-32 px-3 py-2 outline-none\",\n // Placeholder (Tiptap marks the empty first node with data-placeholder).\n \"[&_.is-editor-empty:first-child]:before:pointer-events-none [&_.is-editor-empty:first-child]:before:float-left [&_.is-editor-empty:first-child]:before:h-0 [&_.is-editor-empty:first-child]:before:text-muted-foreground [&_.is-editor-empty:first-child]:before:content-[attr(data-placeholder)]\",\n // Embeds are selected and deleted as a whole while editing.\n \"[&_[data-video-embed]_iframe]:pointer-events-none [&_.ProseMirror-selectednode]:ring-2 [&_.ProseMirror-selectednode]:ring-ring\",\n contentClassName,\n );\n React.useEffect(() => {\n if (!editor) return;\n const attributes: Record<string, string> = {\n id: editorId,\n role: \"textbox\",\n \"aria-multiline\": \"true\",\n class: contentClasses,\n };\n if (ariaLabel) attributes[\"aria-label\"] = ariaLabel;\n if (ariaLabelledBy ?? labelId) attributes[\"aria-labelledby\"] = (ariaLabelledBy ?? labelId)!;\n if (describedBy) attributes[\"aria-describedby\"] = describedBy;\n if (invalid) attributes[\"aria-invalid\"] = \"true\";\n if (readOnly) attributes[\"aria-readonly\"] = \"true\";\n if (disabled) attributes[\"aria-disabled\"] = \"true\";\n if (placeholder) attributes[\"aria-placeholder\"] = placeholder;\n editor.setOptions({ editorProps: { ...editor.options.editorProps, attributes } });\n }, [editor, editorId, contentClasses, ariaLabel, ariaLabelledBy, labelId, describedBy, invalid, readOnly, disabled, placeholder]);\n\n React.useImperativeHandle(\n ref,\n () => ({\n focus: () => editor?.commands.focus(),\n clear: () => {\n editor?.commands.clearContent(true);\n },\n getJSON: () => sanitizeRichTextDoc(editor?.getJSON() ?? initial, opts),\n getHTML: () => richTextToHtml(editor?.getJSON() ?? initial, opts),\n get editor() {\n return editor;\n },\n }),\n [editor, initial, opts],\n );\n\n // ----- Link and video popovers ---------------------------------------\n const [linkOpen, setLinkOpen] = React.useState(false);\n // Opened with Mod-K from the text: Escape should return there too.\n const [linkFromShortcut, setLinkFromShortcut] = React.useState(false);\n const [videoOpen, setVideoOpen] = React.useState(false);\n const interactive = !!editor && !readOnly && !disabled;\n\n const items = React.useMemo(() => {\n const levels = opts.headingLevels as readonly number[];\n const defaults: RichTextToolbarItem[] = [\n \"heading2\",\n \"heading3\",\n \"heading4\",\n \"bold\",\n \"italic\",\n \"underline\",\n \"bulletList\",\n \"orderedList\",\n \"blockquote\",\n \"link\",\n \"video\",\n \"undo\",\n \"redo\",\n ];\n return new Set(\n (toolbar || defaults).filter((item) => {\n if (item.startsWith(\"heading\")) return levels.includes(Number(item.slice(7)));\n if (item === \"video\") return opts.embeds;\n return true;\n }),\n );\n }, [toolbar, opts]);\n\n const renderToggleGroup = (defs: ToggleDef[], groupLabel: string) => {\n const shown = defs.filter((d) => items.has(d.id));\n if (shown.length === 0) return null;\n const activeIds = shown.filter((d) => state?.active[d.id]).map((d) => d.id);\n return (\n <ToolbarToggleGroup\n type=\"multiple\"\n aria-label={groupLabel}\n value={activeIds}\n disabled={!interactive}\n onValueChange={(next: string[]) => {\n if (!editor) return;\n for (const def of shown) {\n if (next.includes(def.id) !== activeIds.includes(def.id)) def.run(editor);\n }\n }}\n >\n {shown.map((def) => {\n const Icon = def.icon;\n const label = labels[def.id as keyof RichTextEditorLabels] as string;\n return (\n <Tooltip key={def.id} delayDuration={300} content={<ShortcutHint label={label} keys={def.keys} apple={apple} />}>\n <ToolbarToggleItem\n value={def.id}\n aria-label={label}\n aria-keyshortcuts={ariaKeys(def.keys, apple)}\n // Pressed styling keys off aria-pressed, not data-state:\n // the Tooltip trigger wrapping this item writes its own\n // data-state (closed / delayed-open) over the toggle's.\n className={PRESSED_CLASS}\n >\n <Icon className=\"size-4\" aria-hidden />\n </ToolbarToggleItem>\n </Tooltip>\n );\n })}\n </ToolbarToggleGroup>\n );\n };\n\n const groups: React.ReactNode[] = [];\n const blockGroup = renderToggleGroup(BLOCKS, labels.blockGroup);\n const markGroup = renderToggleGroup(MARKS, labels.markGroup);\n if (blockGroup) groups.push(<React.Fragment key=\"blocks\">{blockGroup}</React.Fragment>);\n if (markGroup) groups.push(<React.Fragment key=\"marks\">{markGroup}</React.Fragment>);\n if (items.has(\"link\") || items.has(\"video\")) {\n groups.push(\n <div key=\"insert\" className=\"flex items-center gap-1\">\n {items.has(\"link\") && (\n <LinkPopover\n editor={editor}\n open={linkOpen}\n onOpenChange={setLinkOpen}\n returnToEditor={linkFromShortcut}\n onClosed={() => setLinkFromShortcut(false)}\n disabled={!interactive}\n pressed={!!state?.link}\n labels={labels}\n apple={apple}\n />\n )}\n {items.has(\"video\") && (\n <VideoPopover\n editor={editor}\n open={videoOpen}\n onOpenChange={setVideoOpen}\n disabled={!interactive}\n labels={labels}\n />\n )}\n </div>,\n );\n }\n if (items.has(\"undo\") || items.has(\"redo\")) {\n groups.push(\n <div key=\"history\" className=\"flex items-center gap-1\">\n {items.has(\"undo\") && (\n <Tooltip delayDuration={300} content={<ShortcutHint label={labels.undo} keys={[\"Mod\", \"Z\"]} apple={apple} />}>\n <ToolbarButton\n aria-label={labels.undo}\n aria-keyshortcuts={ariaKeys([\"Mod\", \"Z\"], apple)}\n className=\"h-8 w-8 px-0\"\n disabled={!interactive || !state?.canUndo}\n onClick={() => editor?.chain().focus().undo().run()}\n >\n <Undo2 className=\"size-4\" aria-hidden />\n </ToolbarButton>\n </Tooltip>\n )}\n {items.has(\"redo\") && (\n <Tooltip\n delayDuration={300}\n content={<ShortcutHint label={labels.redo} keys={[\"Mod\", \"Shift\", \"Z\"]} apple={apple} />}\n >\n <ToolbarButton\n aria-label={labels.redo}\n aria-keyshortcuts={ariaKeys([\"Mod\", \"Shift\", \"Z\"], apple)}\n className=\"h-8 w-8 px-0\"\n disabled={!interactive || !state?.canRedo}\n onClick={() => editor?.chain().focus().redo().run()}\n >\n <Redo2 className=\"size-4\" aria-hidden />\n </ToolbarButton>\n </Tooltip>\n )}\n </div>,\n );\n }\n\n const showToolbar = toolbar !== false && !readOnly && groups.length > 0;\n const linkAvailable = interactive && showToolbar && items.has(\"link\");\n React.useLayoutEffect(() => {\n openLinkRef.current = () => {\n if (!linkAvailable) return false;\n setLinkFromShortcut(true);\n setLinkOpen(true);\n return true;\n };\n }, [linkAvailable]);\n\n return (\n <div\n data-testid={testID}\n data-disabled={disabled ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n className={cn(\n \"w-full overflow-hidden rounded-md border border-input bg-background ring-offset-background\",\n \"focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2\",\n invalid && \"border-destructive\",\n disabled && \"cursor-not-allowed opacity-50\",\n readOnly && \"border-transparent\",\n className,\n )}\n >\n {showToolbar && (\n <Toolbar\n aria-label={labels.toolbar}\n aria-controls={editorId}\n className=\"flex-wrap rounded-none border-0 border-b border-border\"\n >\n {groups.flatMap((group, i) =>\n i === 0 ? [group] : [<ToolbarSeparator key={`sep-${i}`} />, group],\n )}\n </Toolbar>\n )}\n {editor ? (\n <EditorContent editor={editor} />\n ) : (\n // Server render and first client paint: show the content read-only\n // so the page is not blank (or shifting) while the editor mounts.\n <RichText\n value={isRichTextDoc(initial) ? initial : null}\n aria-busy=\"true\"\n className={cn(\"min-h-32 px-3 py-2\", contentClassName)}\n />\n )}\n {countVisible && (\n <div id={countId} className=\"border-t border-border px-3 py-1 text-right text-xs text-muted-foreground\">\n {labels.characterCount(state?.characters ?? 0, config.maxLength)}\n </div>\n )}\n {name && <input type=\"hidden\" name={name} value={formValue} />}\n </div>\n );\n },\n);\n\n// ---------------------------------------------------------------------------\n// Popovers\n// ---------------------------------------------------------------------------\n\ninterface PopoverProps {\n editor: Editor | null;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n disabled: boolean;\n labels: RichTextEditorLabels;\n}\n\nfunction LinkPopover({\n editor,\n open,\n onOpenChange,\n disabled,\n pressed,\n labels,\n apple,\n returnToEditor,\n onClosed,\n}: PopoverProps & { pressed: boolean; apple: boolean; returnToEditor: boolean; onClosed: () => void }) {\n const inputId = React.useId();\n const errorId = `${inputId}-error`;\n const [url, setUrl] = React.useState(\"\");\n const [error, setError] = React.useState(false);\n\n React.useEffect(() => {\n if (open && editor) {\n setUrl((editor.getAttributes(\"link\").href as string | undefined) ?? \"\");\n setError(false);\n }\n }, [open, editor]);\n\n // After Apply / Remove / Cancel focus returns to the text; after Escape or\n // a click outside, Radix returns it to the toolbar button as usual.\n const toEditor = React.useRef(false);\n const finish = () => {\n toEditor.current = true;\n onOpenChange(false);\n };\n const onCloseAutoFocus = (event: Event) => {\n onClosed();\n if (!toEditor.current && !returnToEditor) return;\n toEditor.current = false;\n event.preventDefault();\n editor?.commands.focus();\n };\n\n const apply = (event: React.FormEvent) => {\n event.preventDefault();\n event.stopPropagation();\n if (!editor) return;\n const href = normalizeLinkUrl(url);\n if (!href) {\n setError(true);\n return;\n }\n const chain = editor.chain().focus().extendMarkRange(\"link\");\n if (editor.state.selection.empty && !editor.isActive(\"link\")) {\n chain.insertContent({ type: \"text\", text: url.trim(), marks: [{ type: \"link\", attrs: { href } }] }).run();\n } else {\n chain.setLink({ href }).run();\n }\n finish();\n };\n\n const remove = () => {\n editor?.chain().focus().extendMarkRange(\"link\").unsetLink().run();\n finish();\n };\n\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <Tooltip delayDuration={300} content={<ShortcutHint label={labels.link} keys={[\"Mod\", \"K\"]} apple={apple} />}>\n <PopoverTrigger asChild>\n <ToolbarButton\n aria-label={labels.link}\n aria-pressed={pressed}\n aria-keyshortcuts={ariaKeys([\"Mod\", \"K\"], apple)}\n className={PRESSED_CLASS}\n disabled={disabled}\n >\n <LinkIcon className=\"size-4\" aria-hidden />\n </ToolbarButton>\n </PopoverTrigger>\n </Tooltip>\n <PopoverContent align=\"start\" className=\"w-80\" onCloseAutoFocus={onCloseAutoFocus}>\n <form onSubmit={apply} className=\"space-y-3\" noValidate>\n <div className=\"space-y-1.5\">\n <Label htmlFor={inputId}>{labels.linkUrl}</Label>\n <Input\n id={inputId}\n value={url}\n autoFocus\n inputMode=\"url\"\n autoComplete=\"off\"\n placeholder=\"https://\"\n aria-invalid={error || undefined}\n aria-describedby={error ? errorId : undefined}\n onChange={(e) => {\n setUrl(e.target.value);\n setError(false);\n }}\n />\n {error && (\n <p id={errorId} role=\"alert\" className=\"text-xs text-destructive\">\n {labels.linkInvalid}\n </p>\n )}\n </div>\n <div className=\"flex justify-end gap-2\">\n {pressed && (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={remove}>\n {labels.linkRemove}\n </Button>\n )}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={finish}>\n {labels.cancel}\n </Button>\n <Button type=\"submit\" size=\"sm\">\n {labels.linkApply}\n </Button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction VideoPopover({ editor, open, onOpenChange, disabled, labels }: PopoverProps) {\n const urlId = React.useId();\n const titleId = React.useId();\n const errorId = `${urlId}-error`;\n const [url, setUrl] = React.useState(\"\");\n const [title, setTitle] = React.useState(\"\");\n const [error, setError] = React.useState(false);\n\n React.useEffect(() => {\n if (open) {\n setUrl(\"\");\n setTitle(\"\");\n setError(false);\n }\n }, [open]);\n\n // After Apply / Remove / Cancel focus returns to the text; after Escape or\n // a click outside, Radix returns it to the toolbar button as usual.\n const toEditor = React.useRef(false);\n const finish = () => {\n toEditor.current = true;\n onOpenChange(false);\n };\n const onCloseAutoFocus = (event: Event) => {\n if (!toEditor.current) return;\n toEditor.current = false;\n event.preventDefault();\n editor?.commands.focus();\n };\n\n const insert = (event: React.FormEvent) => {\n event.preventDefault();\n event.stopPropagation();\n if (!editor) return;\n if (!parseVideoUrl(url)) {\n setError(true);\n return;\n }\n const ok = editor\n .chain()\n .focus()\n .setVideoEmbed({ url, ...(title.trim() ? { title: title.trim() } : {}) })\n .run();\n if (!ok) {\n setError(true);\n return;\n }\n finish();\n };\n\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <Tooltip delayDuration={300} content={labels.video}>\n <PopoverTrigger asChild>\n <ToolbarButton aria-label={labels.video} className=\"h-8 w-8 px-0\" disabled={disabled}>\n <Video className=\"size-4\" aria-hidden />\n </ToolbarButton>\n </PopoverTrigger>\n </Tooltip>\n <PopoverContent align=\"start\" className=\"w-80\" onCloseAutoFocus={onCloseAutoFocus}>\n <form onSubmit={insert} className=\"space-y-3\" noValidate>\n <div className=\"space-y-1.5\">\n <Label htmlFor={urlId}>{labels.videoUrl}</Label>\n <Input\n id={urlId}\n value={url}\n autoFocus\n inputMode=\"url\"\n autoComplete=\"off\"\n placeholder=\"https://\"\n aria-invalid={error || undefined}\n aria-describedby={error ? errorId : undefined}\n onChange={(e) => {\n setUrl(e.target.value);\n setError(false);\n }}\n />\n {error && (\n <p id={errorId} role=\"alert\" className=\"text-xs text-destructive\">\n {labels.videoInvalid}\n </p>\n )}\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor={titleId}>{labels.videoTitle}</Label>\n <Input id={titleId} value={title} maxLength={200} onChange={(e) => setTitle(e.target.value)} />\n </div>\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={finish}>\n {labels.cancel}\n </Button>\n <Button type=\"submit\" size=\"sm\">\n {labels.videoInsert}\n </Button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rich-text/video-embed.ts","../../../src/components/rich-text/rich-text-editor.tsx"],"names":["RichTextEditor","LinkIcon"],"mappings":"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","file":"rich-text-editor.js","sourcesContent":["\"use client\";\n\n/**\n * VideoEmbed — a Tiptap node for YouTube, Vimeo and Loom players.\n *\n * The node stores only `{ provider, id, hash?, title? }`, never a URL, and\n * rebuilds the player URL from those validated parts every time it renders.\n * A pasted `<iframe>` is accepted only when its `src` parses as one of the\n * three hosts; any other iframe is dropped by the editor's schema.\n *\n * Exported for apps that assemble their own Tiptap editor and want the same\n * embed node `RichTextEditor` uses.\n */\nimport { Node } from \"@tiptap/core\";\nimport {\n type VideoEmbedAttrs,\n VIDEO_IFRAME_ATTRS,\n parseVideoUrl,\n sanitizeVideoEmbedAttrs,\n videoEmbedSrc,\n videoEmbedTitle,\n} from \"./rich-text-doc\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n videoEmbed: {\n /**\n * Insert a video embed from a YouTube, Vimeo or Loom URL. Fails (returns\n * false, inserts nothing) for any other URL.\n */\n setVideoEmbed: (options: { url: string; title?: string }) => ReturnType;\n };\n }\n}\n\nconst noRender = { renderHTML: () => ({}) };\n\n/**\n * Tiptap node for YouTube, Vimeo and Loom players, stored as\n * `{ provider, id, hash?, title? }` and rebuilt from those parts on render.\n * Adds the `setVideoEmbed({ url, title })` command.\n *\n * @stability Beta\n */\nexport const VideoEmbed = Node.create({\n name: \"videoEmbed\",\n group: \"block\",\n atom: true,\n draggable: true,\n selectable: true,\n\n addAttributes() {\n return {\n provider: { default: null, ...noRender },\n id: { default: null, ...noRender },\n hash: { default: null, ...noRender },\n title: { default: null, ...noRender },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"div[data-video-embed]\",\n priority: 60,\n getAttrs: (el) => {\n const attrs = sanitizeVideoEmbedAttrs({\n provider: el.getAttribute(\"data-provider\"),\n id: el.getAttribute(\"data-id\"),\n hash: el.getAttribute(\"data-hash\") ?? undefined,\n title: el.getAttribute(\"data-title\") ?? undefined,\n });\n return attrs ? { ...attrs } : false;\n },\n },\n {\n tag: \"iframe[src]\",\n getAttrs: (el) => {\n const parsed = parseVideoUrl(el.getAttribute(\"src\") ?? \"\");\n if (!parsed) return false;\n const attrs = sanitizeVideoEmbedAttrs({ ...parsed, title: el.getAttribute(\"title\") ?? undefined });\n return attrs ? { ...attrs } : false;\n },\n },\n ];\n },\n\n renderHTML({ node }) {\n const attrs = sanitizeVideoEmbedAttrs(node.attrs);\n if (!attrs) return [\"div\", { \"data-video-embed-invalid\": \"\" }];\n const title = videoEmbedTitle(attrs);\n return [\n \"div\",\n {\n \"data-video-embed\": \"\",\n \"data-provider\": attrs.provider,\n \"data-id\": attrs.id,\n ...(attrs.hash ? { \"data-hash\": attrs.hash } : {}),\n ...(attrs.title ? { \"data-title\": attrs.title } : {}),\n },\n [\n \"iframe\",\n {\n src: videoEmbedSrc(attrs),\n title,\n allow: VIDEO_IFRAME_ATTRS.allow,\n allowfullscreen: \"true\",\n loading: VIDEO_IFRAME_ATTRS.loading,\n referrerpolicy: VIDEO_IFRAME_ATTRS.referrerPolicy,\n sandbox: VIDEO_IFRAME_ATTRS.sandbox,\n // Inside the editor the frame is not a tab stop: the node is\n // selected and deleted as a whole, and playback happens in the\n // read-only view.\n tabindex: \"-1\",\n },\n ],\n ];\n },\n\n addCommands() {\n return {\n setVideoEmbed:\n ({ url, title }) =>\n ({ commands, state }) => {\n const parsed = parseVideoUrl(url);\n if (!parsed) return false;\n const attrs: VideoEmbedAttrs | null = sanitizeVideoEmbedAttrs({ ...parsed, title });\n if (!attrs) return false;\n const node = { type: this.name, attrs: { ...attrs } };\n // Insert BETWEEN top-level blocks rather than at the caret, which\n // would split the paragraph or heading the caret is in. An empty\n // paragraph is replaced instead of being left behind.\n const { $from } = state.selection;\n if ($from.depth === 0) return commands.insertContent(node);\n const block = $from.node(1);\n if (block.type.name === \"paragraph\" && block.content.size === 0) {\n return commands.insertContentAt({ from: $from.before(1), to: $from.after(1) }, node);\n }\n return commands.insertContentAt($from.after(1), node);\n },\n };\n },\n});\n","\"use client\";\n\n/**\n * RichTextEditor — a WYSIWYG editor for formatted content (headings, bold,\n * italic, underline, lists, links, quotes and optional video embeds), built\n * on Tiptap 3 (ProseMirror) with a Genesis `Toolbar`.\n *\n * Lives on its own subpath, `@marktiderman/genesis-ui/rich-text-editor`, so\n * only apps that import it need the `@tiptap/*` peers. The read-only\n * renderer and the server-safe helpers are on `/rich-text`.\n *\n * @stability Beta\n */\nimport * as React from \"react\";\nimport { Extension } from \"@tiptap/core\";\nimport { EditorContent, useEditor, useEditorState, type Editor } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport { CharacterCount, Placeholder } from \"@tiptap/extensions\";\nimport {\n Bold,\n Heading2,\n Heading3,\n Heading4,\n Italic,\n Link as LinkIcon,\n List,\n ListOrdered,\n Quote,\n Redo2,\n Underline,\n Undo2,\n Video,\n} from \"lucide-react\";\n\nimport { cn } from \"../../utils\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { Kbd } from \"../ui/kbd\";\nimport { Label } from \"../ui/label\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/popover\";\nimport {\n Toolbar,\n ToolbarButton,\n ToolbarSeparator,\n ToolbarToggleGroup,\n ToolbarToggleItem,\n} from \"../ui/toolbar\";\nimport { Tooltip } from \"../ui/tooltip\";\nimport {\n type RichTextDoc,\n type RichTextHeadingLevel,\n type SanitizeRichTextOptions,\n isRichTextDoc,\n isRichTextEmpty,\n isSafeUrl,\n normalizeLinkUrl,\n parseVideoUrl,\n richTextToHtml,\n richTextToPlainText,\n sanitizeRichTextDoc,\n} from \"./rich-text-doc\";\nimport { RichText, richTextClassName } from \"./rich-text\";\nimport { VideoEmbed } from \"./video-embed\";\n\nexport { VideoEmbed } from \"./video-embed\";\nexport type { RichTextDoc, RichTextHeadingLevel } from \"./rich-text-doc\";\n\n/**\n * What the editor accepts as a value: the document JSON (canonical), or an\n * HTML string. HTML is parsed by the editor in the browser and reduced to\n * the editor's schema, so it is a migration convenience, not a storage\n * format. Output is always JSON plus derived, sanitized HTML.\n */\nexport type RichTextEditorValue = RichTextDoc | string;\n\n/** Derived forms of the document, computed on first read. */\nexport interface RichTextChangeDetails {\n /** Sanitized HTML from `richTextToHtml`. */\n readonly html: string;\n /** Plain text from `richTextToPlainText`. */\n readonly text: string;\n /** True when there is no visible text and no embed. */\n readonly isEmpty: boolean;\n /** Character count of the text (what `maxLength` limits). */\n readonly characters: number;\n}\n\nexport type RichTextToolbarItem =\n | \"heading2\"\n | \"heading3\"\n | \"heading4\"\n | \"bold\"\n | \"italic\"\n | \"underline\"\n | \"bulletList\"\n | \"orderedList\"\n | \"blockquote\"\n | \"link\"\n | \"video\"\n | \"undo\"\n | \"redo\";\n\nexport interface RichTextEditorLabels {\n toolbar: string;\n blockGroup: string;\n markGroup: string;\n heading2: string;\n heading3: string;\n heading4: string;\n bold: string;\n italic: string;\n underline: string;\n bulletList: string;\n orderedList: string;\n blockquote: string;\n link: string;\n video: string;\n undo: string;\n redo: string;\n linkUrl: string;\n linkApply: string;\n linkRemove: string;\n linkInvalid: string;\n videoUrl: string;\n videoTitle: string;\n videoInsert: string;\n videoInvalid: string;\n cancel: string;\n characterCount: (count: number, max: number | undefined) => string;\n}\n\nconst DEFAULT_LABELS: RichTextEditorLabels = {\n toolbar: \"Formatting\",\n blockGroup: \"Paragraph style\",\n markGroup: \"Text style\",\n heading2: \"Heading 2\",\n heading3: \"Heading 3\",\n heading4: \"Heading 4\",\n bold: \"Bold\",\n italic: \"Italic\",\n underline: \"Underline\",\n bulletList: \"Bulleted list\",\n orderedList: \"Numbered list\",\n blockquote: \"Quote\",\n link: \"Link\",\n video: \"Embed video\",\n undo: \"Undo\",\n redo: \"Redo\",\n linkUrl: \"Link address\",\n linkApply: \"Apply\",\n linkRemove: \"Remove link\",\n linkInvalid: \"Enter a web address (https://…), an email address or a relative path.\",\n videoUrl: \"YouTube, Vimeo or Loom link\",\n videoTitle: \"Title (read by screen readers)\",\n videoInsert: \"Insert\",\n videoInvalid: \"Paste a YouTube, Vimeo or Loom video link.\",\n cancel: \"Cancel\",\n characterCount: (count, max) =>\n max ? `${count.toLocaleString()} / ${max.toLocaleString()} characters` : `${count.toLocaleString()} characters`,\n};\n\n/** Imperative handle exposed through `ref`. */\nexport interface RichTextEditorHandle {\n /** Move focus into the editable area. */\n focus: () => void;\n /** Replace the content with an empty document (fires `onChange`). */\n clear: () => void;\n /** The current document, sanitized. */\n getJSON: () => RichTextDoc;\n /** The current document as sanitized HTML. */\n getHTML: () => string;\n /** The underlying Tiptap editor, once mounted (null during SSR/first paint). */\n readonly editor: Editor | null;\n}\n\nexport interface RichTextEditorProps {\n /**\n * Controlled value. Pass back the `doc` from `onChange` synchronously; any\n * other document (including an older one from a debounced or deferred\n * parent) replaces the content and resets the selection.\n */\n value?: RichTextEditorValue;\n /** Initial value for an uncontrolled editor. */\n defaultValue?: RichTextEditorValue;\n /**\n * Called on every edit with the sanitized document. `details` derives HTML\n * and text lazily, so reading only `doc` costs no serialization.\n */\n onChange?: (doc: RichTextDoc, details: RichTextChangeDetails) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n /**\n * `id` of the editable element. A `<label htmlFor={id}>` names the editor\n * (wired as `aria-labelledby`, since a contenteditable is not a labelable\n * element) and clicking it focuses the editor.\n */\n id?: string;\n /**\n * Form field name. When set, a hidden input carries the document as JSON\n * so a native `<form>` submission includes it.\n */\n name?: string;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n /** Marks the field invalid (`aria-invalid`, destructive border). */\n invalid?: boolean;\n /** Placeholder shown while the document is empty. */\n placeholder?: string;\n /** Content is visible and selectable but not editable; the toolbar is hidden. */\n readOnly?: boolean;\n /** Not editable, toolbar disabled, dimmed. */\n disabled?: boolean;\n autoFocus?: boolean;\n /** Heading levels offered in the toolbar and kept in the document. Default `[2, 3]`. Read at mount. */\n headingLevels?: readonly RichTextHeadingLevel[];\n /** Enable YouTube / Vimeo / Loom embeds (toolbar button and schema). Default `false`. Read at mount. */\n embeds?: boolean;\n /** Maximum characters. Typing and pasting stop at the limit. Read at mount. */\n maxLength?: number;\n /** Show the character count under the editor. On by default when `maxLength` is set. */\n showCharacterCount?: boolean;\n /** Toolbar items, in groups as listed. `false` hides the toolbar (shortcuts still work). */\n toolbar?: false | readonly RichTextToolbarItem[];\n /** Override any user-facing string (for translation). */\n labels?: Partial<RichTextEditorLabels>;\n /** Classes for the outer frame. */\n className?: string;\n /** Classes for the editable area (for example a taller `min-h-*`). */\n contentClassName?: string;\n /** Stable test/automation selector (emitted as `data-testid` on the frame). */\n testID?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Toolbar definitions\n// ---------------------------------------------------------------------------\n\ntype Keys = readonly string[];\n\ninterface ToggleDef {\n id: RichTextToolbarItem;\n icon: React.ComponentType<{ className?: string }>;\n keys: Keys;\n isActive: (e: Editor) => boolean;\n run: (e: Editor) => void;\n}\n\nconst MARKS: ToggleDef[] = [\n {\n id: \"bold\",\n icon: Bold,\n keys: [\"Mod\", \"B\"],\n isActive: (e) => e.isActive(\"bold\"),\n run: (e) => e.chain().focus().toggleBold().run(),\n },\n {\n id: \"italic\",\n icon: Italic,\n keys: [\"Mod\", \"I\"],\n isActive: (e) => e.isActive(\"italic\"),\n run: (e) => e.chain().focus().toggleItalic().run(),\n },\n {\n id: \"underline\",\n icon: Underline,\n keys: [\"Mod\", \"U\"],\n isActive: (e) => e.isActive(\"underline\"),\n run: (e) => e.chain().focus().toggleUnderline().run(),\n },\n];\n\nconst heading = (level: RichTextHeadingLevel, icon: ToggleDef[\"icon\"]): ToggleDef => ({\n id: `heading${level}` as RichTextToolbarItem,\n icon,\n keys: [\"Mod\", \"Alt\", String(level)],\n isActive: (e) => e.isActive(\"heading\", { level }),\n run: (e) => e.chain().focus().toggleHeading({ level }).run(),\n});\n\nconst BLOCKS: ToggleDef[] = [\n heading(2, Heading2),\n heading(3, Heading3),\n heading(4, Heading4),\n {\n id: \"bulletList\",\n icon: List,\n keys: [\"Mod\", \"Shift\", \"8\"],\n isActive: (e) => e.isActive(\"bulletList\"),\n run: (e) => e.chain().focus().toggleBulletList().run(),\n },\n {\n id: \"orderedList\",\n icon: ListOrdered,\n keys: [\"Mod\", \"Shift\", \"7\"],\n isActive: (e) => e.isActive(\"orderedList\"),\n run: (e) => e.chain().focus().toggleOrderedList().run(),\n },\n {\n id: \"blockquote\",\n icon: Quote,\n keys: [\"Mod\", \"Shift\", \"B\"],\n isActive: (e) => e.isActive(\"blockquote\"),\n run: (e) => e.chain().focus().toggleBlockquote().run(),\n },\n];\n\nconst ALL_TOGGLES = [...MARKS, ...BLOCKS];\n\n// The rules Tiptap would inject as a <style> tag (`injectCSS: false` turns\n// that off for strict CSPs), as classes on the editable element. The gap\n// cursor uses the foreground token instead of black and does not blink.\nconst PROSEMIRROR_BASE = cn(\n \"relative break-words whitespace-break-spaces [font-variant-ligatures:none] [font-feature-settings:'liga'_0]\",\n \"[&_[contenteditable=false]]:whitespace-normal [&_[contenteditable=false]_[contenteditable=true]]:whitespace-pre-wrap [&_pre]:whitespace-pre-wrap\",\n \"[&_img.ProseMirror-separator]:!inline [&_img.ProseMirror-separator]:!m-0 [&_img.ProseMirror-separator]:!h-0 [&_img.ProseMirror-separator]:!w-0 [&_img.ProseMirror-separator]:!border-0\",\n \"[&_.ProseMirror-gapcursor]:pointer-events-none [&_.ProseMirror-gapcursor]:absolute [&_.ProseMirror-gapcursor]:m-0 [&_.ProseMirror-gapcursor]:hidden [&.ProseMirror-focused_.ProseMirror-gapcursor]:block\",\n \"[&_.ProseMirror-gapcursor]:after:absolute [&_.ProseMirror-gapcursor]:after:-top-0.5 [&_.ProseMirror-gapcursor]:after:block [&_.ProseMirror-gapcursor]:after:w-5 [&_.ProseMirror-gapcursor]:after:border-t [&_.ProseMirror-gapcursor]:after:border-foreground [&_.ProseMirror-gapcursor]:after:content-['']\",\n \"[&.ProseMirror-hideselection_*]:caret-transparent [&.ProseMirror-hideselection_*]:selection:bg-transparent\",\n);\n\nconst PRESSED_CLASS =\"h-8 w-8 px-0 aria-pressed:bg-accent aria-pressed:text-accent-foreground\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Detect Apple platforms after mount, so SSR and first paint agree (\"Ctrl\"). */\nfunction useIsApple(): boolean {\n const [apple, setApple] = React.useState(false);\n React.useEffect(() => {\n const nav = navigator as Navigator & { userAgentData?: { platform?: string } };\n const platform = nav.userAgentData?.platform ?? nav.platform ?? \"\";\n setApple(/mac|iphone|ipad|ipod/i.test(platform));\n }, []);\n return apple;\n}\n\nfunction keyLabel(key: string, apple: boolean): string {\n if (key === \"Mod\") return apple ? \"⌘\" : \"Ctrl\";\n if (key === \"Alt\") return apple ? \"⌥\" : \"Alt\";\n if (key === \"Shift\") return apple ? \"⇧\" : \"Shift\";\n return key;\n}\n\nfunction ariaKeys(keys: Keys, apple: boolean): string {\n return keys\n .map((k) => (k === \"Mod\" ? (apple ? \"Meta\" : \"Control\") : k))\n .join(\"+\");\n}\n\nfunction ShortcutHint({ label, keys, apple }: { label: string; keys?: Keys; apple: boolean }) {\n return (\n <span className=\"inline-flex items-center gap-2\">\n {label}\n {keys && (\n <span className=\"inline-flex items-center gap-0.5\">\n {keys.map((k) => (\n <Kbd key={k}>{keyLabel(k, apple)}</Kbd>\n ))}\n </span>\n )}\n </span>\n );\n}\n\nfunction initialContent(\n value: RichTextEditorValue | undefined,\n opts: SanitizeRichTextOptions,\n): RichTextDoc | string {\n if (typeof value === \"string\") return value;\n return sanitizeRichTextDoc(value ?? null, opts);\n}\n\nfunction detailsFor(doc: RichTextDoc, characters: () => number, opts: SanitizeRichTextOptions): RichTextChangeDetails {\n let html: string | undefined;\n let text: string | undefined;\n return {\n get html() {\n return (html ??= richTextToHtml(doc, opts));\n },\n get text() {\n return (text ??= richTextToPlainText(doc));\n },\n get isEmpty() {\n return isRichTextEmpty(doc);\n },\n get characters() {\n return characters();\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * RichTextEditor — formatted text input for lessons, notes and other\n * long-form content.\n *\n * - **Value:** JSON is canonical (`RichTextDoc`). `onChange` hands you the\n * sanitized document plus lazily derived `html`/`text`. Store the JSON;\n * on the server re-run `sanitizeRichTextDoc` and derive HTML with\n * `richTextToHtml` (both from `/rich-text`, no DOM needed).\n * - **Security:** output goes through the same allow-list as `RichText`;\n * links keep only http(s)/mailto/tel/relative URLs; embeds are rebuilt\n * from a validated YouTube/Vimeo/Loom id.\n * - **SSR:** the editor mounts on the client only (Tiptap\n * `immediatelyRender: false`). Until then a JSON value renders read-only,\n * so server HTML shows the content instead of an empty box.\n * - **Keyboard:** standard shortcuts (⌘/Ctrl+B, I, U, K for link,\n * ⌘/Ctrl+Alt+2/3 for headings, ⌘/Ctrl+Shift+7/8 for lists, ⌘/Ctrl+Shift+B\n * for quote, ⌘/Ctrl+Z / Shift+Z), shown in each toolbar tooltip. The\n * toolbar is one tab stop with arrow-key navigation (Radix Toolbar).\n *\n * @stability Beta\n */\nexport const RichTextEditor = React.forwardRef<RichTextEditorHandle, RichTextEditorProps>(\n function RichTextEditor(props, ref) {\n const {\n value,\n defaultValue,\n onChange,\n onFocus,\n onBlur,\n id: idProp,\n name,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n invalid = false,\n placeholder,\n readOnly = false,\n disabled = false,\n autoFocus = false,\n headingLevels = [2, 3],\n embeds = false,\n maxLength,\n showCharacterCount,\n toolbar,\n labels: labelsProp,\n className,\n contentClassName,\n testID,\n } = props;\n\n const labels = React.useMemo(() => ({ ...DEFAULT_LABELS, ...labelsProp }), [labelsProp]);\n const generatedId = React.useId();\n const editorId = idProp ?? `rte-${generatedId}`;\n const countId = `${editorId}-count`;\n const apple = useIsApple();\n\n // Mount-time configuration. The schema (heading levels, embeds) and the\n // character limit are fixed for the editor's lifetime; changing them\n // means remounting (give the component a new `key`).\n const [config] = React.useState(() => ({\n opts: { headingLevels, embeds } satisfies SanitizeRichTextOptions,\n maxLength,\n }));\n const { opts } = config;\n\n const onChangeRef = React.useRef(onChange);\n const onFocusRef = React.useRef(onFocus);\n const onBlurRef = React.useRef(onBlur);\n const placeholderRef = React.useRef(placeholder);\n const stringControlledRef = React.useRef(typeof value === \"string\");\n const openLinkRef = React.useRef<() => boolean>(() => false);\n React.useEffect(() => {\n onChangeRef.current = onChange;\n onFocusRef.current = onFocus;\n onBlurRef.current = onBlur;\n placeholderRef.current = placeholder;\n stringControlledRef.current = typeof value === \"string\";\n });\n\n // The last document we emitted (reference and HTML), so a controlled\n // parent echoing it back does not reset the selection.\n const lastEmitted = React.useRef<{ doc: RichTextDoc | null; html: string | null }>({\n doc: null,\n html: null,\n });\n const [initial] = React.useState(() => initialContent(value ?? defaultValue, opts));\n const [formValue, setFormValue] = React.useState(() =>\n isRichTextDoc(initial) ? JSON.stringify(initial) : \"\",\n );\n\n const extensions = React.useMemo(\n () => [\n StarterKit.configure({\n code: false,\n codeBlock: false,\n strike: false,\n horizontalRule: false,\n heading: { levels: [...opts.headingLevels] },\n link: {\n openOnClick: false,\n autolink: true,\n linkOnPaste: true,\n defaultProtocol: \"https\",\n // Same rule as the sanitizer, so a link the editor shows is a link\n // that survives `onChange`.\n isAllowedUri: (url, ctx) => ctx.defaultValidate(url) && isSafeUrl(url),\n },\n }),\n Placeholder.configure({ placeholder: () => placeholderRef.current ?? \"\" }),\n CharacterCount.configure({ limit: config.maxLength ?? null }),\n ...(opts.embeds ? [VideoEmbed] : []),\n Extension.create({\n name: \"genesisLinkShortcut\",\n addKeyboardShortcuts: () => ({\n // Only claims the shortcut when the link control is there to open.\n \"Mod-k\": () => openLinkRef.current(),\n }),\n }),\n ],\n // Mount-time only, by design (see `config` above).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n const editor = useEditor({\n extensions,\n content: initial,\n immediatelyRender: false,\n // Tiptap's base styles are in PROSEMIRROR_BASE instead of an injected\n // <style> tag, so the editor works under a strict style-src CSP.\n injectCSS: false,\n shouldRerenderOnTransaction: false,\n editable: !readOnly && !disabled,\n autofocus: autoFocus ? \"end\" : false,\n onUpdate: ({ editor: e }) => {\n const doc = sanitizeRichTextDoc(e.getJSON(), opts);\n const details = detailsFor(doc, () => e.storage.characterCount.characters(), opts);\n lastEmitted.current = { doc, html: null };\n if (name) setFormValue(JSON.stringify(doc));\n const cb = onChangeRef.current;\n if (cb) {\n cb(doc, details);\n // Only serialize HTML for string-controlled parents.\n if (stringControlledRef.current) lastEmitted.current.html = details.html;\n }\n },\n onFocus: () => onFocusRef.current?.(),\n onBlur: () => onBlurRef.current?.(),\n });\n\n const state = useEditorState({\n editor,\n // Reads the `editor` from this render rather than the snapshot's: the\n // snapshot only refreshes on a transaction, so right after mount it\n // still holds `null` and the toolbar (and count) would start blank.\n selector: () => {\n const e = editor;\n if (!e) return null;\n const active: Partial<Record<RichTextToolbarItem, boolean>> = {};\n for (const def of ALL_TOGGLES) active[def.id] = def.isActive(e);\n return {\n active,\n link: e.isActive(\"link\"),\n canUndo: e.can().undo(),\n canRedo: e.can().redo(),\n characters: e.storage.characterCount.characters() as number,\n };\n },\n });\n\n // Once mounted: the hidden form value reflects the parsed document (an\n // HTML defaultValue is only parsed now), and a string-controlled value is\n // recorded as already applied so the first render does not reset the caret.\n React.useEffect(() => {\n if (!editor) return;\n if (typeof initial === \"string\") {\n lastEmitted.current = { doc: null, html: initial };\n setFormValue(JSON.stringify(sanitizeRichTextDoc(editor.getJSON(), opts)));\n }\n }, [editor, initial, opts]);\n\n // `<label htmlFor={id}>`: name the editor and focus it on click.\n const [labelId, setLabelId] = React.useState<string | undefined>(undefined);\n React.useEffect(() => {\n if (!editor || ariaLabel || ariaLabelledBy || typeof document === \"undefined\") return;\n const label = document.querySelector<HTMLLabelElement>(`label[for=\"${CSS.escape(editorId)}\"]`);\n if (!label) return;\n if (!label.id) label.id = `${editorId}-label`;\n setLabelId(label.id);\n const onClick = (event: MouseEvent) => {\n event.preventDefault();\n editor.commands.focus();\n };\n label.addEventListener(\"click\", onClick);\n return () => label.removeEventListener(\"click\", onClick);\n }, [editor, editorId, ariaLabel, ariaLabelledBy]);\n\n // Editable follows readOnly/disabled.\n React.useEffect(() => {\n editor?.setEditable(!readOnly && !disabled, false);\n }, [editor, readOnly, disabled]);\n\n // Controlled value: apply only values that differ from what we emitted.\n React.useEffect(() => {\n if (!editor || value === undefined) return;\n const last = lastEmitted.current;\n if (typeof value === \"string\") {\n if (value === last.html) return;\n } else if (value === last.doc) {\n return;\n }\n const next = initialContent(value, opts);\n if (\n typeof next !== \"string\" &&\n JSON.stringify(sanitizeRichTextDoc(editor.getJSON(), opts)) === JSON.stringify(next)\n ) {\n return;\n }\n editor.commands.setContent(next, { emitUpdate: false });\n const doc = sanitizeRichTextDoc(editor.getJSON(), opts);\n lastEmitted.current = { doc: typeof value === \"string\" ? null : value, html: typeof value === \"string\" ? value : null };\n if (name) setFormValue(JSON.stringify(doc));\n }, [editor, value, opts, name]);\n\n // ARIA and classes on the editable element follow props.\n const countVisible = showCharacterCount ?? config.maxLength !== undefined;\n const describedBy = [ariaDescribedBy, countVisible ? countId : null].filter(Boolean).join(\" \") || undefined;\n const contentClasses = cn(\n richTextClassName,\n PROSEMIRROR_BASE,\n \"min-h-32 px-3 py-2 outline-none\",\n // Placeholder (Tiptap marks the empty first node with data-placeholder).\n \"[&_.is-editor-empty:first-child]:before:pointer-events-none [&_.is-editor-empty:first-child]:before:float-left [&_.is-editor-empty:first-child]:before:h-0 [&_.is-editor-empty:first-child]:before:text-muted-foreground [&_.is-editor-empty:first-child]:before:content-[attr(data-placeholder)]\",\n // Embeds are selected and deleted as a whole while editing.\n \"[&_[data-video-embed]_iframe]:pointer-events-none [&_.ProseMirror-selectednode]:ring-2 [&_.ProseMirror-selectednode]:ring-ring\",\n contentClassName,\n );\n React.useEffect(() => {\n if (!editor) return;\n const attributes: Record<string, string> = {\n id: editorId,\n role: \"textbox\",\n \"aria-multiline\": \"true\",\n class: contentClasses,\n };\n if (ariaLabel) attributes[\"aria-label\"] = ariaLabel;\n if (ariaLabelledBy ?? labelId) attributes[\"aria-labelledby\"] = (ariaLabelledBy ?? labelId)!;\n if (describedBy) attributes[\"aria-describedby\"] = describedBy;\n if (invalid) attributes[\"aria-invalid\"] = \"true\";\n if (readOnly) attributes[\"aria-readonly\"] = \"true\";\n if (disabled) attributes[\"aria-disabled\"] = \"true\";\n if (placeholder) attributes[\"aria-placeholder\"] = placeholder;\n editor.setOptions({ editorProps: { ...editor.options.editorProps, attributes } });\n }, [editor, editorId, contentClasses, ariaLabel, ariaLabelledBy, labelId, describedBy, invalid, readOnly, disabled, placeholder]);\n\n React.useImperativeHandle(\n ref,\n () => ({\n focus: () => editor?.commands.focus(),\n clear: () => {\n editor?.commands.clearContent(true);\n },\n getJSON: () => sanitizeRichTextDoc(editor?.getJSON() ?? initial, opts),\n getHTML: () => richTextToHtml(editor?.getJSON() ?? initial, opts),\n get editor() {\n return editor;\n },\n }),\n [editor, initial, opts],\n );\n\n // ----- Link and video popovers ---------------------------------------\n const [linkOpen, setLinkOpen] = React.useState(false);\n // Opened with Mod-K from the text: Escape should return there too.\n const [linkFromShortcut, setLinkFromShortcut] = React.useState(false);\n const [videoOpen, setVideoOpen] = React.useState(false);\n const interactive = !!editor && !readOnly && !disabled;\n\n const items = React.useMemo(() => {\n const levels = opts.headingLevels as readonly number[];\n const defaults: RichTextToolbarItem[] = [\n \"heading2\",\n \"heading3\",\n \"heading4\",\n \"bold\",\n \"italic\",\n \"underline\",\n \"bulletList\",\n \"orderedList\",\n \"blockquote\",\n \"link\",\n \"video\",\n \"undo\",\n \"redo\",\n ];\n return new Set(\n (toolbar || defaults).filter((item) => {\n if (item.startsWith(\"heading\")) return levels.includes(Number(item.slice(7)));\n if (item === \"video\") return opts.embeds;\n return true;\n }),\n );\n }, [toolbar, opts]);\n\n const renderToggleGroup = (defs: ToggleDef[], groupLabel: string) => {\n const shown = defs.filter((d) => items.has(d.id));\n if (shown.length === 0) return null;\n const activeIds = shown.filter((d) => state?.active[d.id]).map((d) => d.id);\n return (\n <ToolbarToggleGroup\n type=\"multiple\"\n aria-label={groupLabel}\n value={activeIds}\n disabled={!interactive}\n onValueChange={(next: string[]) => {\n if (!editor) return;\n for (const def of shown) {\n if (next.includes(def.id) !== activeIds.includes(def.id)) def.run(editor);\n }\n }}\n >\n {shown.map((def) => {\n const Icon = def.icon;\n const label = labels[def.id as keyof RichTextEditorLabels] as string;\n return (\n <Tooltip key={def.id} delayDuration={300} content={<ShortcutHint label={label} keys={def.keys} apple={apple} />}>\n <ToolbarToggleItem\n value={def.id}\n aria-label={label}\n aria-keyshortcuts={ariaKeys(def.keys, apple)}\n // Pressed styling keys off aria-pressed, not data-state:\n // the Tooltip trigger wrapping this item writes its own\n // data-state (closed / delayed-open) over the toggle's.\n className={PRESSED_CLASS}\n >\n <Icon className=\"size-4\" aria-hidden />\n </ToolbarToggleItem>\n </Tooltip>\n );\n })}\n </ToolbarToggleGroup>\n );\n };\n\n const groups: React.ReactNode[] = [];\n const blockGroup = renderToggleGroup(BLOCKS, labels.blockGroup);\n const markGroup = renderToggleGroup(MARKS, labels.markGroup);\n if (blockGroup) groups.push(<React.Fragment key=\"blocks\">{blockGroup}</React.Fragment>);\n if (markGroup) groups.push(<React.Fragment key=\"marks\">{markGroup}</React.Fragment>);\n if (items.has(\"link\") || items.has(\"video\")) {\n groups.push(\n <div key=\"insert\" className=\"flex items-center gap-1\">\n {items.has(\"link\") && (\n <LinkPopover\n editor={editor}\n open={linkOpen}\n onOpenChange={setLinkOpen}\n returnToEditor={linkFromShortcut}\n onClosed={() => setLinkFromShortcut(false)}\n disabled={!interactive}\n pressed={!!state?.link}\n labels={labels}\n apple={apple}\n />\n )}\n {items.has(\"video\") && (\n <VideoPopover\n editor={editor}\n open={videoOpen}\n onOpenChange={setVideoOpen}\n disabled={!interactive}\n labels={labels}\n />\n )}\n </div>,\n );\n }\n if (items.has(\"undo\") || items.has(\"redo\")) {\n groups.push(\n <div key=\"history\" className=\"flex items-center gap-1\">\n {items.has(\"undo\") && (\n <Tooltip delayDuration={300} content={<ShortcutHint label={labels.undo} keys={[\"Mod\", \"Z\"]} apple={apple} />}>\n <ToolbarButton\n aria-label={labels.undo}\n aria-keyshortcuts={ariaKeys([\"Mod\", \"Z\"], apple)}\n className=\"h-8 w-8 px-0\"\n disabled={!interactive || !state?.canUndo}\n onClick={() => editor?.chain().focus().undo().run()}\n >\n <Undo2 className=\"size-4\" aria-hidden />\n </ToolbarButton>\n </Tooltip>\n )}\n {items.has(\"redo\") && (\n <Tooltip\n delayDuration={300}\n content={<ShortcutHint label={labels.redo} keys={[\"Mod\", \"Shift\", \"Z\"]} apple={apple} />}\n >\n <ToolbarButton\n aria-label={labels.redo}\n aria-keyshortcuts={ariaKeys([\"Mod\", \"Shift\", \"Z\"], apple)}\n className=\"h-8 w-8 px-0\"\n disabled={!interactive || !state?.canRedo}\n onClick={() => editor?.chain().focus().redo().run()}\n >\n <Redo2 className=\"size-4\" aria-hidden />\n </ToolbarButton>\n </Tooltip>\n )}\n </div>,\n );\n }\n\n const showToolbar = toolbar !== false && !readOnly && groups.length > 0;\n const linkAvailable = interactive && showToolbar && items.has(\"link\");\n React.useLayoutEffect(() => {\n openLinkRef.current = () => {\n if (!linkAvailable) return false;\n setLinkFromShortcut(true);\n setLinkOpen(true);\n return true;\n };\n }, [linkAvailable]);\n\n return (\n <div\n data-testid={testID}\n data-disabled={disabled ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n className={cn(\n \"w-full overflow-hidden rounded-md border border-input bg-background ring-offset-background\",\n \"focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2\",\n invalid && \"border-destructive\",\n disabled && \"cursor-not-allowed opacity-50\",\n readOnly && \"border-transparent\",\n className,\n )}\n >\n {showToolbar && (\n <Toolbar\n aria-label={labels.toolbar}\n aria-controls={editorId}\n className=\"flex-wrap rounded-none border-0 border-b border-border\"\n >\n {groups.flatMap((group, i) =>\n i === 0 ? [group] : [<ToolbarSeparator key={`sep-${i}`} />, group],\n )}\n </Toolbar>\n )}\n {editor ? (\n <EditorContent editor={editor} />\n ) : (\n // Server render and first client paint: show the content read-only\n // so the page is not blank (or shifting) while the editor mounts.\n <RichText\n value={isRichTextDoc(initial) ? initial : null}\n aria-busy=\"true\"\n className={cn(\"min-h-32 px-3 py-2\", contentClassName)}\n />\n )}\n {countVisible && (\n <div id={countId} className=\"border-t border-border px-3 py-1 text-right text-xs text-muted-foreground\">\n {labels.characterCount(state?.characters ?? 0, config.maxLength)}\n </div>\n )}\n {name && <input type=\"hidden\" name={name} value={formValue} />}\n </div>\n );\n },\n);\n\n// ---------------------------------------------------------------------------\n// Popovers\n// ---------------------------------------------------------------------------\n\ninterface PopoverProps {\n editor: Editor | null;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n disabled: boolean;\n labels: RichTextEditorLabels;\n}\n\nfunction LinkPopover({\n editor,\n open,\n onOpenChange,\n disabled,\n pressed,\n labels,\n apple,\n returnToEditor,\n onClosed,\n}: PopoverProps & { pressed: boolean; apple: boolean; returnToEditor: boolean; onClosed: () => void }) {\n const inputId = React.useId();\n const errorId = `${inputId}-error`;\n const [url, setUrl] = React.useState(\"\");\n const [error, setError] = React.useState(false);\n\n React.useEffect(() => {\n if (open && editor) {\n setUrl((editor.getAttributes(\"link\").href as string | undefined) ?? \"\");\n setError(false);\n }\n }, [open, editor]);\n\n // After Apply / Remove / Cancel focus returns to the text; after Escape or\n // a click outside, Radix returns it to the toolbar button as usual.\n const toEditor = React.useRef(false);\n const finish = () => {\n toEditor.current = true;\n onOpenChange(false);\n };\n const onCloseAutoFocus = (event: Event) => {\n onClosed();\n if (!toEditor.current && !returnToEditor) return;\n toEditor.current = false;\n event.preventDefault();\n editor?.commands.focus();\n };\n\n const apply = (event: React.FormEvent) => {\n event.preventDefault();\n event.stopPropagation();\n if (!editor) return;\n const href = normalizeLinkUrl(url);\n if (!href) {\n setError(true);\n return;\n }\n const chain = editor.chain().focus().extendMarkRange(\"link\");\n if (editor.state.selection.empty && !editor.isActive(\"link\")) {\n chain.insertContent({ type: \"text\", text: url.trim(), marks: [{ type: \"link\", attrs: { href } }] }).run();\n } else {\n chain.setLink({ href }).run();\n }\n finish();\n };\n\n const remove = () => {\n editor?.chain().focus().extendMarkRange(\"link\").unsetLink().run();\n finish();\n };\n\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <Tooltip delayDuration={300} content={<ShortcutHint label={labels.link} keys={[\"Mod\", \"K\"]} apple={apple} />}>\n <PopoverTrigger asChild>\n <ToolbarButton\n aria-label={labels.link}\n aria-pressed={pressed}\n aria-keyshortcuts={ariaKeys([\"Mod\", \"K\"], apple)}\n className={PRESSED_CLASS}\n disabled={disabled}\n >\n <LinkIcon className=\"size-4\" aria-hidden />\n </ToolbarButton>\n </PopoverTrigger>\n </Tooltip>\n <PopoverContent align=\"start\" className=\"w-80\" onCloseAutoFocus={onCloseAutoFocus}>\n <form onSubmit={apply} className=\"space-y-3\" noValidate>\n <div className=\"space-y-1.5\">\n <Label htmlFor={inputId}>{labels.linkUrl}</Label>\n <Input\n id={inputId}\n value={url}\n autoFocus\n inputMode=\"url\"\n autoComplete=\"off\"\n placeholder=\"https://\"\n aria-invalid={error || undefined}\n aria-describedby={error ? errorId : undefined}\n onChange={(e) => {\n setUrl(e.target.value);\n setError(false);\n }}\n />\n {error && (\n <p id={errorId} role=\"alert\" className=\"text-xs text-destructive\">\n {labels.linkInvalid}\n </p>\n )}\n </div>\n <div className=\"flex justify-end gap-2\">\n {pressed && (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={remove}>\n {labels.linkRemove}\n </Button>\n )}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={finish}>\n {labels.cancel}\n </Button>\n <Button type=\"submit\" size=\"sm\">\n {labels.linkApply}\n </Button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction VideoPopover({ editor, open, onOpenChange, disabled, labels }: PopoverProps) {\n const urlId = React.useId();\n const titleId = React.useId();\n const errorId = `${urlId}-error`;\n const [url, setUrl] = React.useState(\"\");\n const [title, setTitle] = React.useState(\"\");\n const [error, setError] = React.useState(false);\n\n React.useEffect(() => {\n if (open) {\n setUrl(\"\");\n setTitle(\"\");\n setError(false);\n }\n }, [open]);\n\n // After Apply / Remove / Cancel focus returns to the text; after Escape or\n // a click outside, Radix returns it to the toolbar button as usual.\n const toEditor = React.useRef(false);\n const finish = () => {\n toEditor.current = true;\n onOpenChange(false);\n };\n const onCloseAutoFocus = (event: Event) => {\n if (!toEditor.current) return;\n toEditor.current = false;\n event.preventDefault();\n editor?.commands.focus();\n };\n\n const insert = (event: React.FormEvent) => {\n event.preventDefault();\n event.stopPropagation();\n if (!editor) return;\n if (!parseVideoUrl(url)) {\n setError(true);\n return;\n }\n const ok = editor\n .chain()\n .focus()\n .setVideoEmbed({ url, ...(title.trim() ? { title: title.trim() } : {}) })\n .run();\n if (!ok) {\n setError(true);\n return;\n }\n finish();\n };\n\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <Tooltip delayDuration={300} content={labels.video}>\n <PopoverTrigger asChild>\n <ToolbarButton aria-label={labels.video} className=\"h-8 w-8 px-0\" disabled={disabled}>\n <Video className=\"size-4\" aria-hidden />\n </ToolbarButton>\n </PopoverTrigger>\n </Tooltip>\n <PopoverContent align=\"start\" className=\"w-80\" onCloseAutoFocus={onCloseAutoFocus}>\n <form onSubmit={insert} className=\"space-y-3\" noValidate>\n <div className=\"space-y-1.5\">\n <Label htmlFor={urlId}>{labels.videoUrl}</Label>\n <Input\n id={urlId}\n value={url}\n autoFocus\n inputMode=\"url\"\n autoComplete=\"off\"\n placeholder=\"https://\"\n aria-invalid={error || undefined}\n aria-describedby={error ? errorId : undefined}\n onChange={(e) => {\n setUrl(e.target.value);\n setError(false);\n }}\n />\n {error && (\n <p id={errorId} role=\"alert\" className=\"text-xs text-destructive\">\n {labels.videoInvalid}\n </p>\n )}\n </div>\n <div className=\"space-y-1.5\">\n <Label htmlFor={titleId}>{labels.videoTitle}</Label>\n <Input id={titleId} value={title} maxLength={200} onChange={(e) => setTitle(e.target.value)} />\n </div>\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={finish}>\n {labels.cancel}\n </Button>\n <Button type=\"submit\" size=\"sm\">\n {labels.videoInsert}\n </Button>\n </div>\n </form>\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { RichText, RichTextLimitError, VIDEO_IFRAME_ATTRS, emptyRichTextDoc, escapeHtml, isRichTextDoc, isRichTextEmpty, isSafeUrl, normalizeLinkUrl, parseVideoUrl, richTextClassName, richTextToHtml, richTextToPlainText, sanitizeRichTextDoc, sanitizeVideoEmbedAttrs, videoEmbedSrc, videoEmbedTitle, videoWatchUrl } from '../../chunk-ZDHWNQTR.js';
|
|
2
2
|
import '../../chunk-NZ5WBA4R.js';
|
|
3
|
+
import '../../chunk-424PT5DM.js';
|
|
3
4
|
//# sourceMappingURL=rich-text.js.map
|
|
4
5
|
//# sourceMappingURL=rich-text.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Spinner } from '../../chunk-OVU3Z2MT.js';
|
|
3
3
|
import { cn } from '../../chunk-NZ5WBA4R.js';
|
|
4
|
+
import '../../chunk-424PT5DM.js';
|
|
4
5
|
import * as React from 'react';
|
|
5
6
|
import { useRef, useState, useCallback, useMemo, useEffect } from 'react';
|
|
6
7
|
import { useVirtualizer } from '@tanstack/react-virtual';
|