@texion/react 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +34 -2
- package/dist/RichMarkdownEditor-OAHLD4XC.js +9 -0
- package/dist/RichMarkdownEditor-OAHLD4XC.js.map +1 -0
- package/dist/chunk-JZO3KR6A.js +169 -0
- package/dist/chunk-JZO3KR6A.js.map +1 -0
- package/dist/chunk-LSFUTTAB.js +390 -0
- package/dist/chunk-LSFUTTAB.js.map +1 -0
- package/dist/chunk-T56S7VW3.js +52 -0
- package/dist/chunk-T56S7VW3.js.map +1 -0
- package/dist/csv-COGONMFA.js +36 -0
- package/dist/csv-COGONMFA.js.map +1 -0
- package/dist/image-TKOV52M6.js +61 -0
- package/dist/image-TKOV52M6.js.map +1 -0
- package/dist/index.d.ts +1126 -0
- package/dist/index.js +1304 -0
- package/dist/index.js.map +1 -0
- package/dist/json-BEWG6XTV.js +46 -0
- package/dist/json-BEWG6XTV.js.map +1 -0
- package/dist/markdown-QTRYMUXO.js +10 -0
- package/dist/markdown-QTRYMUXO.js.map +1 -0
- package/dist/markdown.d.ts +7 -0
- package/dist/markdown.js +9 -0
- package/dist/markdown.js.map +1 -0
- package/dist/rich.d.ts +7 -0
- package/dist/rich.js +8 -0
- package/dist/rich.js.map +1 -0
- package/dist/styles.css +243 -0
- package/dist/types-D4zTiC0I.d.ts +21 -0
- package/dist/types-DRXx1QAT.d.ts +10 -0
- package/package.json +77 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/editors/rich/RichMarkdownEditor.tsx","../src/editors/rich/compatibility.ts","../src/editors/rich/extension.ts","../src/editors/rich/link-policy.ts","../src/editors/rich/RichEditorBridge.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport { LexicalExtensionComposer } from '@lexical/react/LexicalExtensionComposer';\nimport { ContentEditable } from '@lexical/react/LexicalContentEditable';\nimport { ListPlugin } from '@lexical/react/LexicalListPlugin';\nimport { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';\nimport {\n DEFAULT_TRANSFORMERS,\n MarkdownShortcutPlugin,\n} from '@lexical/react/LexicalMarkdownShortcutPlugin';\nimport { safeUrl } from '@texion/core';\nimport { richImportIssue } from './compatibility';\nimport { createRichExtension } from './extension';\nimport { RichEditorBridge } from './RichEditorBridge';\nimport type { RichMarkdownEditorProps } from './types';\n\nexport type { RichMarkdownEditorProps } from './types';\n\nconst validateUrl = (url: string) => safeUrl(url) !== undefined;\n\nexport function RichMarkdownEditor(props: RichMarkdownEditorProps) {\n const [error, setError] = useState('');\n const [importIssue, setImportIssue] = useState(() =>\n richImportIssue(props.value, props.maxCharacters ?? 50_000),\n );\n useEffect(() => {\n if (importIssue) {\n setImportIssue(\n richImportIssue(props.value, props.maxCharacters ?? 50_000),\n );\n }\n }, [props.value, props.maxCharacters, importIssue]);\n const initialValue = useRef(props.value);\n initialValue.current = props.value;\n const currentLimit = useRef(props.maxCharacters ?? 50_000);\n currentLimit.current = props.maxCharacters ?? 50_000;\n const maxCharacters = props.maxCharacters ?? 50_000;\n\n if (!Number.isSafeInteger(maxCharacters) || maxCharacters < 1) {\n throw new RangeError('maxCharacters must be a positive safe integer');\n }\n const extension = useMemo(\n () =>\n createRichExtension({\n getSource: () => initialValue.current,\n getLimit: () => currentLimit.current,\n onError: (error) => setError(error.message),\n }),\n [],\n );\n\n if (props.value.length > maxCharacters || importIssue) {\n return (\n <div>\n <p role=\"status\">\n {importIssue ??\n 'This content exceeds the rich editor limit. Use source mode to edit the complete source.'}\n </p>\n {props.onRequestSource && (\n <button type=\"button\" onClick={props.onRequestSource}>\n Edit source\n </button>\n )}\n </div>\n );\n }\n const placeholder = props.placeholder ?? 'Write something…';\n\n return (\n <div className=\"texion-rich-editor\">\n <LexicalExtensionComposer extension={extension} contentEditable={null}>\n <ContentEditable\n id={props.id}\n role=\"textbox\"\n aria-label={props.label ?? 'Message'}\n aria-multiline=\"true\"\n aria-placeholder={placeholder}\n placeholder={\n <span className=\"texion-rich-placeholder\">{placeholder}</span>\n }\n className=\"texion-rich-content\"\n onCompositionStart={() => props.onCompositionChange?.(true)}\n onCompositionEnd={() => props.onCompositionChange?.(false)}\n />\n <RichEditorBridge\n options={props}\n reportError={setError}\n reportImportIssue={setImportIssue}\n />\n <ListPlugin />\n <LinkPlugin validateUrl={validateUrl} />\n {props.live !== false && (\n <MarkdownShortcutPlugin transformers={DEFAULT_TRANSFORMERS} />\n )}\n </LexicalExtensionComposer>\n {error && <p role=\"alert\">{error}</p>}\n {error && props.onRequestSource && (\n <button type=\"button\" onClick={props.onRequestSource}>\n Edit source\n </button>\n )}\n </div>\n );\n}\n\nexport default RichMarkdownEditor;\n","import { inspectMarkdownSource } from '@texion/core';\n\nconst sourceOnlyNodes = new Set([\n 'yaml',\n 'toml',\n 'table',\n 'footnoteDefinition',\n 'footnoteReference',\n 'definition',\n 'linkReference',\n 'imageReference',\n 'taskList',\n]);\n\nexport function richImportIssue(\n source: string,\n maxCharacters = 50_000,\n): string | undefined {\n const features = inspectMarkdownSource(source, maxCharacters);\n\n if (features.limited) {\n return 'This content exceeds the rich editor complexity limits. Use source mode.';\n }\n if (features.nodeTypes.some((type) => sourceOnlyNodes.has(type))) {\n return 'This Markdown uses syntax that requires source mode to preserve its meaning.';\n }\n return undefined;\n}\n","import { defineExtension } from 'lexical';\nimport { $convertFromMarkdownString } from '@lexical/markdown';\nimport { HistoryExtension } from '@lexical/history';\nimport { CodeNode } from '@lexical/code';\nimport { LinkNode } from '@lexical/link';\nimport { ListItemNode, ListNode } from '@lexical/list';\nimport { HeadingNode, QuoteNode, RichTextExtension } from '@lexical/rich-text';\nimport { DEFAULT_TRANSFORMERS } from '@lexical/react/LexicalMarkdownShortcutPlugin';\nimport { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';\nimport { richImportIssue } from './compatibility';\nimport { registerLinkPolicy } from './link-policy';\n\ninterface RichExtensionOptions {\n readonly getSource: () => string;\n readonly getLimit: () => number;\n readonly onError: (error: Error) => void;\n}\n\nexport function createRichExtension(options: RichExtensionOptions) {\n return defineExtension({\n name: '@texion/rich-markdown',\n namespace: 'Texion Markdown',\n dependencies: [RichTextExtension, HistoryExtension],\n nodes: [\n HeadingNode,\n QuoteNode,\n ListNode,\n ListItemNode,\n CodeNode,\n LinkNode,\n HorizontalRuleNode,\n ],\n theme: {\n text: {\n bold: 'texion-rich-bold',\n italic: 'texion-rich-italic',\n code: 'texion-rich-inline-code',\n strikethrough: 'texion-rich-strikethrough',\n },\n code: 'texion-rich-code',\n },\n onError: options.onError,\n $initialEditorState() {\n const source = options.getSource();\n const limit = options.getLimit();\n const exceedsLimit = source.length > limit;\n const isUnsupported = richImportIssue(source, limit);\n const initialSource = exceedsLimit || isUnsupported ? '' : source;\n\n $convertFromMarkdownString(initialSource, DEFAULT_TRANSFORMERS);\n },\n register: registerLinkPolicy,\n });\n}\n","import { $getNodeByKey, mergeRegister } from 'lexical';\nimport type { LexicalEditor } from 'lexical';\nimport { LinkNode } from '@lexical/link';\nimport { safeUrl } from '@texion/core';\n\nfunction normalizeLink(node: LinkNode): void {\n const url = safeUrl(node.getURL());\n\n if (!url) {\n for (const child of node.getChildren()) {\n node.insertBefore(child);\n }\n\n node.remove();\n\n return;\n }\n\n if (node.getURL() !== url) {\n node.setURL(url);\n }\n\n if (node.getRel() !== 'noopener noreferrer') {\n node.setRel('noopener noreferrer');\n }\n}\n\nexport function registerLinkPolicy(editor: LexicalEditor): () => void {\n const removeTransform = editor.registerNodeTransform(LinkNode, normalizeLink);\n const removeListener = editor.registerMutationListener(\n LinkNode,\n (mutations) => {\n editor.getEditorState().read(() => {\n for (const [key, change] of mutations) {\n if (change === 'destroyed') {\n continue;\n }\n\n const node = $getNodeByKey(key);\n const element = editor.getElementByKey(key);\n\n if (!(node instanceof LinkNode) || !element) {\n continue;\n }\n\n // Apply core's relative-URL rules instead of Lexical's URL guessing.\n const url = safeUrl(node.getURL());\n\n if (url) {\n element.setAttribute('href', url);\n } else {\n element.removeAttribute('href');\n }\n }\n });\n },\n );\n\n return mergeRegister(removeTransform, removeListener);\n}\n","import { useEffect, useRef } from 'react';\nimport {\n $addUpdateTag,\n $createTextNode,\n $getRoot,\n $getSelection,\n $insertNodes,\n $isRangeSelection,\n COMMAND_PRIORITY_HIGH,\n HISTORY_PUSH_TAG,\n KEY_ENTER_COMMAND,\n PASTE_COMMAND,\n mergeRegister,\n} from 'lexical';\nimport type { UpdateListener, PasteCommandType } from 'lexical';\nimport {\n $convertFromMarkdownString,\n $convertToMarkdownString,\n $generateNodesFromMarkdownString,\n} from '@lexical/markdown';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport { DEFAULT_TRANSFORMERS } from '@lexical/react/LexicalMarkdownShortcutPlugin';\nimport { $createCodeNode } from '@lexical/code';\nimport { detectTextFormat } from '@texion/core';\nimport { richImportIssue } from './compatibility';\nimport type { RichMarkdownEditorProps } from './types';\n\nconst externalUpdateTag = 'texion:external';\n\nexport function RichEditorBridge({\n options,\n reportError,\n reportImportIssue,\n}: {\n readonly options: RichMarkdownEditorProps;\n readonly reportError: (message: string) => void;\n readonly reportImportIssue: (message: string | undefined) => void;\n}) {\n const [editor] = useLexicalComposerContext();\n const current = useRef(options);\n current.current = options;\n const lastValue = useRef(options.value);\n useEffect(() => {\n const handleUpdate: UpdateListener = ({\n editorState,\n dirtyElements,\n dirtyLeaves,\n tags,\n }) => {\n if (\n tags.has(externalUpdateTag) ||\n (!dirtyElements.size && !dirtyLeaves.size)\n ) {\n return;\n }\n const source = editorState.read(() =>\n $convertToMarkdownString(DEFAULT_TRANSFORMERS),\n );\n\n if (source === lastValue.current) {\n return;\n }\n lastValue.current = source;\n current.current.onChange(source);\n };\n const handlePaste = (event: PasteCommandType) => {\n if (editor.isComposing()) {\n return false;\n }\n const clipboard = 'clipboardData' in event ? event.clipboardData : null;\n\n if (!clipboard) {\n return false;\n }\n event.preventDefault();\n\n if (clipboard.files.length) {\n if (current.current.onFiles) {\n current.current.onFiles(Array.from(clipboard.files));\n } else {\n reportError('Use source mode or the attachment picker for files.');\n }\n return true;\n }\n\n const text = clipboard.getData('text/plain');\n\n if (!text) {\n return true;\n }\n if (\n $getRoot().getTextContentSize() + text.length >\n (current.current.maxCharacters ?? 50_000)\n ) {\n reportError(\n 'This paste exceeds the rich editor limit. Use source mode to edit it.',\n );\n\n return true;\n }\n\n const wasEmpty = $getRoot().getTextContentSize() === 0;\n const recognized = detectTextFormat(text, current.current.formats);\n if (recognized !== 'markdown') {\n if (wasEmpty && current.current.onRequestSource) {\n current.current.onImport?.(text);\n current.current.onChange(text);\n current.current.onRequestSource();\n } else {\n if (!$isRangeSelection($getSelection())) {\n $getRoot().selectEnd();\n }\n $addUpdateTag(HISTORY_PUSH_TAG);\n $insertNodes([\n $createCodeNode(recognized).append($createTextNode(text)),\n ]);\n }\n return true;\n }\n const issue = richImportIssue(\n text,\n current.current.maxCharacters ?? 50_000,\n );\n\n if (issue) {\n if (wasEmpty && current.current.onRequestSource) {\n current.current.onImport?.(text);\n current.current.onChange(text);\n current.current.onRequestSource();\n } else {\n reportError(issue + ' Paste it in source mode.');\n }\n return true;\n }\n\n if (!$isRangeSelection($getSelection())) {\n $getRoot().selectEnd();\n }\n $addUpdateTag(HISTORY_PUSH_TAG);\n\n if (current.current.live === false) {\n const selection = $getSelection();\n\n if ($isRangeSelection(selection)) {\n selection.insertRawText(text);\n }\n } else {\n $insertNodes(\n $generateNodesFromMarkdownString(text, DEFAULT_TRANSFORMERS),\n );\n }\n if (wasEmpty) {\n current.current.onImport?.(text);\n }\n reportError('');\n\n return true;\n };\n const handleEnter = (event: KeyboardEvent | null) => {\n if (\n !event ||\n editor.isComposing() ||\n event.isComposing ||\n event.keyCode === 229 ||\n event.shiftKey ||\n !current.current.onSubmit\n ) {\n return false;\n }\n const submit = current.current.submitOnEnter\n ? !event.altKey && !event.ctrlKey && !event.metaKey\n : (event.ctrlKey || event.metaKey) && !event.altKey;\n\n if (!submit) {\n return false;\n }\n event.preventDefault();\n current.current.onSubmit();\n\n return true;\n };\n\n return mergeRegister(\n editor.registerUpdateListener(handleUpdate),\n editor.registerCommand(PASTE_COMMAND, handlePaste, COMMAND_PRIORITY_HIGH),\n editor.registerCommand(\n KEY_ENTER_COMMAND,\n handleEnter,\n COMMAND_PRIORITY_HIGH,\n ),\n () => current.current.onCompositionChange?.(false),\n );\n }, [editor, reportError]);\n\n useEffect(() => {\n if (options.value === lastValue.current) {\n return;\n }\n const issue = richImportIssue(\n options.value,\n options.maxCharacters ?? 50_000,\n );\n\n if (issue) {\n reportImportIssue(issue);\n\n return;\n }\n\n lastValue.current = options.value;\n editor.update(\n () => $convertFromMarkdownString(options.value, DEFAULT_TRANSFORMERS),\n {\n tag: externalUpdateTag,\n },\n );\n }, [editor, options.value, options.maxCharacters, reportImportIssue]);\n useEffect(() => {\n editor.setEditable(!options.readOnly);\n }, [editor, options.readOnly]);\n\n return null;\n}\n"],"mappings":"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","names":["useEffect","useRef","DEFAULT_TRANSFORMERS","safeUrl","LinkNode","LinkNode","mergeRegister","$convertFromMarkdownString","DEFAULT_TRANSFORMERS","DEFAULT_TRANSFORMERS","mergeRegister","$convertFromMarkdownString","safeUrl","useEffect","useRef","error","DEFAULT_TRANSFORMERS"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// src/rendering/HighlightOverlay.tsx
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var highlightColors = {
|
|
5
|
+
keyword: "var(--texion-highlight-keyword, #1d4ed8)",
|
|
6
|
+
comment: "var(--texion-highlight-comment, #64748b)",
|
|
7
|
+
property: "var(--texion-highlight-property, #7e22ce)",
|
|
8
|
+
string: "var(--texion-highlight-string, #047857)",
|
|
9
|
+
number: "var(--texion-highlight-number, #b45309)",
|
|
10
|
+
boolean: "var(--texion-highlight-boolean, #1d4ed8)",
|
|
11
|
+
null: "var(--texion-highlight-null, #a21caf)",
|
|
12
|
+
punctuation: "var(--texion-highlight-punctuation, #64748b)",
|
|
13
|
+
heading: "var(--texion-highlight-heading, #1d4ed8)",
|
|
14
|
+
bold: "var(--texion-highlight-bold, #7e22ce)",
|
|
15
|
+
italic: "var(--texion-highlight-italic, #a21caf)",
|
|
16
|
+
code: "var(--texion-highlight-code, #047857)",
|
|
17
|
+
link: "var(--texion-highlight-link, #0369a1)",
|
|
18
|
+
strikethrough: "var(--texion-highlight-strikethrough, #64748b)",
|
|
19
|
+
"list-marker": "var(--texion-highlight-marker, #b45309)",
|
|
20
|
+
blockquote: "var(--texion-highlight-quote, #64748b)",
|
|
21
|
+
frontmatter: "var(--texion-highlight-frontmatter, #64748b)",
|
|
22
|
+
"thematic-break": "var(--texion-highlight-marker, #b45309)"
|
|
23
|
+
};
|
|
24
|
+
var HighlightOverlay = forwardRef(function HighlightOverlay2({ model, style }, ref) {
|
|
25
|
+
return /* @__PURE__ */ jsxs(
|
|
26
|
+
"div",
|
|
27
|
+
{
|
|
28
|
+
ref,
|
|
29
|
+
className: "texion-highlight-overlay",
|
|
30
|
+
"data-texion-highlight-overlay": "",
|
|
31
|
+
style,
|
|
32
|
+
children: [
|
|
33
|
+
model.segments.map((segment) => /* @__PURE__ */ jsx(
|
|
34
|
+
"span",
|
|
35
|
+
{
|
|
36
|
+
"data-highlight-kind": segment.kind,
|
|
37
|
+
style: segment.kind ? { color: highlightColors[segment.kind] } : void 0,
|
|
38
|
+
children: model.text.slice(segment.start, segment.end)
|
|
39
|
+
},
|
|
40
|
+
segment.start
|
|
41
|
+
)),
|
|
42
|
+
/* @__PURE__ */ jsx("span", { "data-texion-highlight-sentinel": "", children: "\u200B" })
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
highlightColors,
|
|
50
|
+
HighlightOverlay
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=chunk-T56S7VW3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/rendering/HighlightOverlay.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport type { CSSProperties } from 'react';\nimport type { HighlightKind, HighlightModel } from '@texion/core';\n\nexport const highlightColors: Record<HighlightKind, string> = {\n keyword: 'var(--texion-highlight-keyword, #1d4ed8)',\n comment: 'var(--texion-highlight-comment, #64748b)',\n property: 'var(--texion-highlight-property, #7e22ce)',\n string: 'var(--texion-highlight-string, #047857)',\n number: 'var(--texion-highlight-number, #b45309)',\n boolean: 'var(--texion-highlight-boolean, #1d4ed8)',\n null: 'var(--texion-highlight-null, #a21caf)',\n punctuation: 'var(--texion-highlight-punctuation, #64748b)',\n heading: 'var(--texion-highlight-heading, #1d4ed8)',\n bold: 'var(--texion-highlight-bold, #7e22ce)',\n italic: 'var(--texion-highlight-italic, #a21caf)',\n code: 'var(--texion-highlight-code, #047857)',\n link: 'var(--texion-highlight-link, #0369a1)',\n strikethrough: 'var(--texion-highlight-strikethrough, #64748b)',\n 'list-marker': 'var(--texion-highlight-marker, #b45309)',\n blockquote: 'var(--texion-highlight-quote, #64748b)',\n frontmatter: 'var(--texion-highlight-frontmatter, #64748b)',\n 'thematic-break': 'var(--texion-highlight-marker, #b45309)',\n};\n\nexport const HighlightOverlay = forwardRef<\n HTMLDivElement,\n { readonly model: HighlightModel; readonly style: CSSProperties }\n>(function HighlightOverlay({ model, style }, ref) {\n return (\n <div\n ref={ref}\n className=\"texion-highlight-overlay\"\n data-texion-highlight-overlay=\"\"\n style={style}\n >\n {model.segments.map((segment) => (\n <span\n key={segment.start}\n data-highlight-kind={segment.kind}\n style={\n segment.kind ? { color: highlightColors[segment.kind] } : undefined\n }\n >\n {model.text.slice(segment.start, segment.end)}\n </span>\n ))}\n {/* A zero-width sentinel gives a trailing newline the same final line as the textarea. */}\n <span data-texion-highlight-sentinel=\"\">{'\\u200b'}</span>\n </div>\n );\n});\n"],"mappings":";AAAA,SAAS,kBAAkB;AA8BvB,SAOI,KAPJ;AA1BG,IAAM,kBAAiD;AAAA,EAC5D,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,aAAa;AAAA,EACb,SAAS;AAAA,EACT,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AAAA,EACN,eAAe;AAAA,EACf,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,kBAAkB;AACpB;AAEO,IAAM,mBAAmB,WAG9B,SAASA,kBAAiB,EAAE,OAAO,MAAM,GAAG,KAAK;AACjD,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAU;AAAA,MACV,iCAA8B;AAAA,MAC9B;AAAA,MAEC;AAAA,cAAM,SAAS,IAAI,CAAC,YACnB;AAAA,UAAC;AAAA;AAAA,YAEC,uBAAqB,QAAQ;AAAA,YAC7B,OACE,QAAQ,OAAO,EAAE,OAAO,gBAAgB,QAAQ,IAAI,EAAE,IAAI;AAAA,YAG3D,gBAAM,KAAK,MAAM,QAAQ,OAAO,QAAQ,GAAG;AAAA;AAAA,UANvC,QAAQ;AAAA,QAOf,CACD;AAAA,QAED,oBAAC,UAAK,kCAA+B,IAAI,oBAAS;AAAA;AAAA;AAAA,EACpD;AAEJ,CAAC;","names":["HighlightOverlay"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/renderers/csv/index.tsx
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
function CsvRenderer({ preview }) {
|
|
4
|
+
const table = preview.nodes.find((node) => node.type === "csv-table");
|
|
5
|
+
if (!table) {
|
|
6
|
+
return /* @__PURE__ */ jsx("pre", { children: preview.nodes.map((node) => node.value ?? "").join("") });
|
|
7
|
+
}
|
|
8
|
+
const rows = table.children ?? [];
|
|
9
|
+
const columns = rows.reduce(
|
|
10
|
+
(maximum, row) => Math.max(maximum, row.children?.length ?? 0),
|
|
11
|
+
0
|
|
12
|
+
);
|
|
13
|
+
return /* @__PURE__ */ jsx(
|
|
14
|
+
"div",
|
|
15
|
+
{
|
|
16
|
+
className: "texion-csv-viewer",
|
|
17
|
+
tabIndex: 0,
|
|
18
|
+
role: "region",
|
|
19
|
+
"aria-label": "Scrollable CSV table",
|
|
20
|
+
children: /* @__PURE__ */ jsxs("table", { children: [
|
|
21
|
+
/* @__PURE__ */ jsx("caption", { children: "CSV data" }),
|
|
22
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: Array.from({ length: columns }, (_, index) => /* @__PURE__ */ jsxs("th", { scope: "col", children: [
|
|
23
|
+
"Column ",
|
|
24
|
+
index + 1
|
|
25
|
+
] }, index)) }) }),
|
|
26
|
+
/* @__PURE__ */ jsx("tbody", { children: rows.map((row, index) => /* @__PURE__ */ jsx("tr", { children: row.children?.map((cell, column) => /* @__PURE__ */ jsx("td", { children: cell.children?.map((child) => child.value ?? "").join("") ?? cell.value ?? "" }, column)) }, index)) })
|
|
27
|
+
] })
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
var csv_default = CsvRenderer;
|
|
32
|
+
export {
|
|
33
|
+
CsvRenderer,
|
|
34
|
+
csv_default as default
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=csv-COGONMFA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/renderers/csv/index.tsx"],"sourcesContent":["import type { PreviewRendererProps } from '../types';\n\nexport function CsvRenderer({ preview }: PreviewRendererProps) {\n const table = preview.nodes.find((node) => node.type === 'csv-table');\n if (!table) {\n return <pre>{preview.nodes.map((node) => node.value ?? '').join('')}</pre>;\n }\n const rows = table.children ?? [];\n const columns = rows.reduce(\n (maximum, row) => Math.max(maximum, row.children?.length ?? 0),\n 0,\n );\n return (\n <div\n className=\"texion-csv-viewer\"\n tabIndex={0}\n role=\"region\"\n aria-label=\"Scrollable CSV table\"\n >\n <table>\n <caption>CSV data</caption>\n <thead>\n <tr>\n {Array.from({ length: columns }, (_, index) => (\n <th scope=\"col\" key={index}>\n Column {index + 1}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, index) => (\n <tr key={index}>\n {row.children?.map((cell, column) => (\n <td key={column}>\n {cell.children?.map((child) => child.value ?? '').join('') ??\n cell.value ??\n ''}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\nexport default CsvRenderer;\n"],"mappings":";AAKW,cAmBG,YAnBH;AAHJ,SAAS,YAAY,EAAE,QAAQ,GAAyB;AAC7D,QAAM,QAAQ,QAAQ,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,WAAW;AACpE,MAAI,CAAC,OAAO;AACV,WAAO,oBAAC,SAAK,kBAAQ,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,KAAK,EAAE,GAAE;AAAA,EACtE;AACA,QAAM,OAAO,MAAM,YAAY,CAAC;AAChC,QAAM,UAAU,KAAK;AAAA,IACnB,CAAC,SAAS,QAAQ,KAAK,IAAI,SAAS,IAAI,UAAU,UAAU,CAAC;AAAA,IAC7D;AAAA,EACF;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,UAAU;AAAA,MACV,MAAK;AAAA,MACL,cAAW;AAAA,MAEX,+BAAC,WACC;AAAA,4BAAC,aAAQ,sBAAQ;AAAA,QACjB,oBAAC,WACC,8BAAC,QACE,gBAAM,KAAK,EAAE,QAAQ,QAAQ,GAAG,CAAC,GAAG,UACnC,qBAAC,QAAG,OAAM,OAAkB;AAAA;AAAA,UAClB,QAAQ;AAAA,aADG,KAErB,CACD,GACH,GACF;AAAA,QACA,oBAAC,WACE,eAAK,IAAI,CAAC,KAAK,UACd,oBAAC,QACE,cAAI,UAAU,IAAI,CAAC,MAAM,WACxB,oBAAC,QACE,eAAK,UAAU,IAAI,CAAC,UAAU,MAAM,SAAS,EAAE,EAAE,KAAK,EAAE,KACvD,KAAK,SACL,MAHK,MAIT,CACD,KAPM,KAQT,CACD,GACH;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;AACA,IAAO,cAAQ;","names":[]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/renderers/image/index.tsx
|
|
2
|
+
import { useState as useState2 } from "react";
|
|
3
|
+
|
|
4
|
+
// src/renderers/image/useObjectUrl.ts
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
function useObjectUrl(blob, mimeType) {
|
|
7
|
+
const [current, setCurrent] = useState();
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (!blob || typeof URL.createObjectURL !== "function") {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const typed = mimeType && blob.type !== mimeType ? blob.slice(0, blob.size, mimeType) : blob;
|
|
13
|
+
const url = URL.createObjectURL(typed);
|
|
14
|
+
setCurrent({ blob, url });
|
|
15
|
+
return () => URL.revokeObjectURL(url);
|
|
16
|
+
}, [blob, mimeType]);
|
|
17
|
+
return current?.blob === blob ? current?.url : void 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/renderers/image/index.tsx
|
|
21
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
22
|
+
function ImageRenderer({ document, preview }) {
|
|
23
|
+
const image = preview.image;
|
|
24
|
+
const url = useObjectUrl(image ? document?.blob : void 0, image?.mimeType);
|
|
25
|
+
const [failedUrl, setFailedUrl] = useState2();
|
|
26
|
+
if (!image) {
|
|
27
|
+
return /* @__PURE__ */ jsx("p", { role: "status", children: "Image preview is unavailable." });
|
|
28
|
+
}
|
|
29
|
+
if (!url) {
|
|
30
|
+
return /* @__PURE__ */ jsx("p", { role: "status", children: "Preparing local image preview\u2026" });
|
|
31
|
+
}
|
|
32
|
+
if (failedUrl === url) {
|
|
33
|
+
return /* @__PURE__ */ jsx("p", { role: "alert", children: "This image could not be decoded. The original attachment is retained." });
|
|
34
|
+
}
|
|
35
|
+
return /* @__PURE__ */ jsxs("figure", { className: "texion-image-viewer", children: [
|
|
36
|
+
/* @__PURE__ */ jsx(
|
|
37
|
+
"img",
|
|
38
|
+
{
|
|
39
|
+
src: url,
|
|
40
|
+
alt: document?.name ?? "Uploaded image",
|
|
41
|
+
width: image.width,
|
|
42
|
+
height: image.height,
|
|
43
|
+
decoding: "async",
|
|
44
|
+
onError: () => setFailedUrl(url)
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
/* @__PURE__ */ jsxs("figcaption", { children: [
|
|
48
|
+
image.width,
|
|
49
|
+
" \xD7 ",
|
|
50
|
+
image.height,
|
|
51
|
+
" \xB7 ",
|
|
52
|
+
image.mimeType
|
|
53
|
+
] })
|
|
54
|
+
] });
|
|
55
|
+
}
|
|
56
|
+
var image_default = ImageRenderer;
|
|
57
|
+
export {
|
|
58
|
+
ImageRenderer,
|
|
59
|
+
image_default as default
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=image-TKOV52M6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/renderers/image/index.tsx","../src/renderers/image/useObjectUrl.ts"],"sourcesContent":["import { useState } from 'react';\nimport type { PreviewRendererProps } from '../types';\nimport { useObjectUrl } from './useObjectUrl';\n\nexport function ImageRenderer({ document, preview }: PreviewRendererProps) {\n const image = preview.image;\n const url = useObjectUrl(image ? document?.blob : undefined, image?.mimeType);\n const [failedUrl, setFailedUrl] = useState<string>();\n if (!image) {\n return <p role=\"status\">Image preview is unavailable.</p>;\n }\n if (!url) {\n return <p role=\"status\">Preparing local image preview…</p>;\n }\n if (failedUrl === url) {\n return (\n <p role=\"alert\">\n This image could not be decoded. The original attachment is retained.\n </p>\n );\n }\n return (\n <figure className=\"texion-image-viewer\">\n <img\n src={url}\n alt={document?.name ?? 'Uploaded image'}\n width={image.width}\n height={image.height}\n decoding=\"async\"\n onError={() => setFailedUrl(url)}\n />\n <figcaption>\n {image.width} × {image.height} · {image.mimeType}\n </figcaption>\n </figure>\n );\n}\nexport default ImageRenderer;\n","import { useEffect, useState } from 'react';\n\nexport function useObjectUrl(\n blob?: Blob,\n mimeType?: string,\n): string | undefined {\n const [current, setCurrent] = useState<{ blob: Blob; url: string }>();\n useEffect(() => {\n if (!blob || typeof URL.createObjectURL !== 'function') {\n return;\n }\n const typed =\n mimeType && blob.type !== mimeType\n ? blob.slice(0, blob.size, mimeType)\n : blob;\n const url = URL.createObjectURL(typed);\n setCurrent({ blob, url });\n return () => URL.revokeObjectURL(url);\n }, [blob, mimeType]);\n return current?.blob === blob ? current?.url : undefined;\n}\n"],"mappings":";AAAA,SAAS,YAAAA,iBAAgB;;;ACAzB,SAAS,WAAW,gBAAgB;AAE7B,SAAS,aACd,MACA,UACoB;AACpB,QAAM,CAAC,SAAS,UAAU,IAAI,SAAsC;AACpE,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ,OAAO,IAAI,oBAAoB,YAAY;AACtD;AAAA,IACF;AACA,UAAM,QACJ,YAAY,KAAK,SAAS,WACtB,KAAK,MAAM,GAAG,KAAK,MAAM,QAAQ,IACjC;AACN,UAAM,MAAM,IAAI,gBAAgB,KAAK;AACrC,eAAW,EAAE,MAAM,IAAI,CAAC;AACxB,WAAO,MAAM,IAAI,gBAAgB,GAAG;AAAA,EACtC,GAAG,CAAC,MAAM,QAAQ,CAAC;AACnB,SAAO,SAAS,SAAS,OAAO,SAAS,MAAM;AACjD;;;ADXW,cAsBL,YAtBK;AALJ,SAAS,cAAc,EAAE,UAAU,QAAQ,GAAyB;AACzE,QAAM,QAAQ,QAAQ;AACtB,QAAM,MAAM,aAAa,QAAQ,UAAU,OAAO,QAAW,OAAO,QAAQ;AAC5E,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAiB;AACnD,MAAI,CAAC,OAAO;AACV,WAAO,oBAAC,OAAE,MAAK,UAAS,2CAA6B;AAAA,EACvD;AACA,MAAI,CAAC,KAAK;AACR,WAAO,oBAAC,OAAE,MAAK,UAAS,iDAA8B;AAAA,EACxD;AACA,MAAI,cAAc,KAAK;AACrB,WACE,oBAAC,OAAE,MAAK,SAAQ,mFAEhB;AAAA,EAEJ;AACA,SACE,qBAAC,YAAO,WAAU,uBAChB;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,KAAK,UAAU,QAAQ;AAAA,QACvB,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM;AAAA,QACd,UAAS;AAAA,QACT,SAAS,MAAM,aAAa,GAAG;AAAA;AAAA,IACjC;AAAA,IACA,qBAAC,gBACE;AAAA,YAAM;AAAA,MAAM;AAAA,MAAI,MAAM;AAAA,MAAO;AAAA,MAAI,MAAM;AAAA,OAC1C;AAAA,KACF;AAEJ;AACA,IAAO,gBAAQ;","names":["useState","useState"]}
|