@lindle/linoardo 1.0.49 → 1.0.50

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.
Files changed (41) hide show
  1. package/dist/chunk-3J6Y3EQW.js +538 -0
  2. package/dist/chunk-3J6Y3EQW.js.map +1 -0
  3. package/dist/{chunk-LRWM4ZWZ.js → chunk-DEJ7ZDGL.js} +3 -3
  4. package/dist/chunk-DEJ7ZDGL.js.map +1 -0
  5. package/dist/{chunk-TRR7TDVA.js → chunk-HE44Z7XP.js} +12 -3
  6. package/dist/chunk-HE44Z7XP.js.map +1 -0
  7. package/dist/{chunk-Z5A2OIDI.js → chunk-SM2VNSPP.js} +4 -7
  8. package/dist/chunk-SM2VNSPP.js.map +1 -0
  9. package/dist/{chunk-LSIAP7ZZ.js → chunk-XLA2NCDF.js} +3 -9
  10. package/dist/chunk-XLA2NCDF.js.map +1 -0
  11. package/dist/expansion-panel.cjs +1 -7
  12. package/dist/expansion-panel.cjs.map +1 -1
  13. package/dist/expansion-panel.js +1 -1
  14. package/dist/index.cjs +581 -520
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +5 -6
  19. package/dist/index.js.map +1 -1
  20. package/dist/profileCard.cjs +1 -1
  21. package/dist/profileCard.cjs.map +1 -1
  22. package/dist/profileCard.js +1 -1
  23. package/dist/progress.cjs +2 -5
  24. package/dist/progress.cjs.map +1 -1
  25. package/dist/progress.js +1 -1
  26. package/dist/select.js +1 -2
  27. package/dist/styles.css +254 -187
  28. package/dist/textarea.cjs +484 -423
  29. package/dist/textarea.cjs.map +1 -1
  30. package/dist/textarea.d.cts +27 -23
  31. package/dist/textarea.d.ts +27 -23
  32. package/dist/textarea.js +1 -2
  33. package/package.json +7 -1
  34. package/dist/chunk-67TAA2MA.js +0 -470
  35. package/dist/chunk-67TAA2MA.js.map +0 -1
  36. package/dist/chunk-6SKW43XI.js +0 -14
  37. package/dist/chunk-6SKW43XI.js.map +0 -1
  38. package/dist/chunk-LRWM4ZWZ.js.map +0 -1
  39. package/dist/chunk-LSIAP7ZZ.js.map +0 -1
  40. package/dist/chunk-TRR7TDVA.js.map +0 -1
  41. package/dist/chunk-Z5A2OIDI.js.map +0 -1
package/dist/textarea.cjs CHANGED
@@ -1,485 +1,546 @@
1
1
  'use strict';
2
2
 
3
3
  var React = require('react');
4
- var react = require('@tiptap/react');
4
+ var CodeBlockLowlight = require('@tiptap/extension-code-block-lowlight');
5
5
  var StarterKit = require('@tiptap/starter-kit');
6
- var marked = require('marked');
6
+ var Underline = require('@tiptap/extension-underline');
7
+ var react = require('@tiptap/react');
8
+ var lowlight$1 = require('lowlight');
7
9
  var TurndownService = require('turndown');
10
+ var marked = require('marked');
8
11
  var tailwindMerge = require('tailwind-merge');
9
12
  var jsxRuntime = require('react/jsx-runtime');
10
13
 
11
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
15
 
13
16
  var React__default = /*#__PURE__*/_interopDefault(React);
17
+ var CodeBlockLowlight__default = /*#__PURE__*/_interopDefault(CodeBlockLowlight);
14
18
  var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
19
+ var Underline__default = /*#__PURE__*/_interopDefault(Underline);
15
20
  var TurndownService__default = /*#__PURE__*/_interopDefault(TurndownService);
16
21
 
17
- // src/utils/helpers/randomStr.ts
18
- var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
19
- function generateString(length = 5) {
20
- let result = "";
21
- const charactersLength = characters.length;
22
- for (let i = 0; i < length; i++) {
23
- result += characters.charAt(Math.floor(Math.random() * charactersLength));
24
- }
25
- return result;
26
- }
27
- var baseClass = "textarea-base px-3 py-2 focus-visible:outline-none transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed w-full text-gray-900 dark:text-gray-100 placeholder:text-gray-500 dark:placeholder:text-gray-400";
22
+ // src/Form/TextArea/index.tsx
28
23
  var variantClasses = {
29
- outlined: "rounded border-2 border-black bg-white focus-visible:border-black focus-visible:ring-2 focus-visible:ring-black/30 dark:border-black dark:bg-slate-900 dark:focus-visible:border-black dark:focus-visible:ring-black/40",
30
- filled: "rounded border border-gray-200 bg-gray-100 focus-visible:border-primary focus-visible:ring-2 focus-visible:ring-primary/25 dark:border-gray-700 dark:bg-slate-800 dark:focus-visible:border-primary/60 dark:focus-visible:ring-primary/30",
31
- standard: "rounded-none border-0 border-b border-gray-300 px-0 bg-transparent focus-visible:border-primary focus-visible:ring-0 dark:border-b-gray-700 dark:focus-visible:border-primary/70"
24
+ solid: "rounded border border-gray-400 bg-white shadow-sm focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/30 dark:border-gray-600 dark:bg-slate-900 dark:shadow-black/20 dark:focus-within:border-primary/70 dark:focus-within:ring-primary/40",
25
+ sharp: "rounded-none border border-gray-400 bg-white shadow-sm focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/30 dark:border-gray-600 dark:bg-slate-900 dark:shadow-black/20 dark:focus-within:border-primary/70 dark:focus-within:ring-primary/40",
26
+ outline: "rounded border-2 border-black bg-white focus-within:border-black focus-within:ring-2 focus-within:ring-black/30 dark:border-black dark:bg-transparent dark:focus-within:border-black dark:focus-within:ring-black/40",
27
+ text: "rounded-none border-0 border-b border-transparent px-0 bg-transparent focus-within:border-primary focus-within:ring-0 focus-within:ring-transparent dark:border-b-gray-600 dark:focus-within:border-primary/70",
28
+ ghost: "rounded border border-transparent bg-gray-50 text-gray-900 focus-within:bg-white focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/15 dark:bg-slate-800 dark:text-gray-100 dark:focus-within:bg-slate-700 dark:focus-within:border-primary/60 dark:focus-within:ring-primary/25",
29
+ filled: "rounded border border-gray-200 bg-gray-100 focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/25 dark:border-gray-700 dark:bg-slate-800 dark:focus-within:border-primary/60 dark:focus-within:ring-primary/30",
30
+ underlined: "rounded-none border-0 border-b border-gray-300 px-0 bg-transparent focus-within:border-primary focus-within:ring-0 focus-within:ring-transparent dark:border-b-gray-600 dark:focus-within:border-primary/70"
31
+ };
32
+ var roundedClasses = {
33
+ sm: "rounded-sm",
34
+ md: "rounded-md",
35
+ lg: "rounded-lg",
36
+ xl: "rounded-xl",
37
+ "2xl": "rounded-2xl",
38
+ "3xl": "rounded-3xl"
32
39
  };
33
- var labelBackground = {
34
- outlined: "bg-white/90 dark:bg-slate-900",
35
- filled: "bg-gray-100 dark:bg-slate-800",
36
- standard: "bg-transparent"
40
+ var sizeClasses = {
41
+ "x-small": {
42
+ paddingY: "py-2",
43
+ paddingX: "px-2",
44
+ text: "text-xs"
45
+ },
46
+ small: {
47
+ paddingY: "py-2.5",
48
+ paddingX: "px-2.5",
49
+ text: "text-sm"
50
+ },
51
+ medium: {
52
+ paddingY: "py-3",
53
+ paddingX: "px-3",
54
+ text: "text-base"
55
+ },
56
+ large: {
57
+ paddingY: "py-3.5",
58
+ paddingX: "px-3.5",
59
+ text: "text-lg"
60
+ },
61
+ "x-large": {
62
+ paddingY: "py-4",
63
+ paddingX: "px-4",
64
+ text: "text-xl"
65
+ }
37
66
  };
38
- var advancedContainerVariant = {
39
- outlined: "rounded border-2 border-black bg-white dark:border-black dark:bg-slate-900",
40
- filled: "rounded border border-gray-200 bg-gray-100 dark:border-gray-700 dark:bg-slate-800",
41
- standard: "border-b border-gray-300 bg-transparent dark:border-gray-700"
67
+ var statusClasses = {
68
+ error: "border-red-500 focus:border-red-500 focus:ring-red-400",
69
+ warn: "border-amber-500 focus:border-amber-500 focus:ring-amber-400",
70
+ success: "border-emerald-500 focus:border-emerald-500 focus:ring-emerald-400"
42
71
  };
43
- var renderMarkdown = (value) => marked.marked.parse(value || "", { async: false });
44
- var dispatchInputEvent = (element) => {
45
- const event = new Event("input", { bubbles: true });
46
- element.dispatchEvent(event);
72
+ var statusMessageClasses = {
73
+ error: "text-red-600 dark:text-red-300",
74
+ warn: "text-amber-600 dark:text-amber-300",
75
+ success: "text-emerald-600 dark:text-emerald-300"
47
76
  };
48
- var toolbarButtonBase = "px-3 py-1 text-gray-700 transition-colors hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-slate-700 disabled:cursor-not-allowed disabled:opacity-50";
49
- var toolbarButtonActive = "bg-white text-gray-900 dark:bg-slate-900 dark:text-gray-100";
50
- var handleModeToggle = (wrapperId, mode, textareaName, simpleId, advancedInputId) => {
51
- if (typeof document === "undefined") return;
52
- const wrapper = document.getElementById(wrapperId);
53
- const simple = document.getElementById(simpleId);
54
- const advancedInput = document.getElementById(advancedInputId);
55
- if (wrapper) {
56
- wrapper.dataset.mode = mode;
77
+ var DEFAULT_TOOLBAR = ["bold", "italic", "underline", "strike", "heading", "bulletList", "orderedList", "blockquote", "codeBlock"];
78
+ var CODE_BLOCK_LANGUAGES = ["ts", "json", "python", "bash"];
79
+ var DEFAULT_CODE_BLOCK_LANGUAGE = CODE_BLOCK_LANGUAGES[0];
80
+ var TEXTAREA_TAB_CHARACTER = " ";
81
+ var lowlight = lowlight$1.createLowlight(lowlight$1.common);
82
+ lowlight.registerAlias({ ts: "typescript" });
83
+ var turndown = new TurndownService__default.default({
84
+ codeBlockStyle: "fenced",
85
+ headingStyle: "atx",
86
+ bulletListMarker: "-"
87
+ });
88
+ var markdownToHtml = (markdown) => {
89
+ if (!markdown) {
90
+ return "<p></p>";
57
91
  }
58
- if (simple) {
59
- simple.classList.toggle("hidden", mode !== "simple");
60
- simple.name = mode === "simple" ? textareaName : "";
92
+ return marked.marked.parse(markdown);
93
+ };
94
+ var htmlToMarkdown = (html) => turndown.turndown(html).trim();
95
+ var createChangeEvent = (element) => ({
96
+ target: element,
97
+ currentTarget: element
98
+ });
99
+ var assignRef = (ref, value) => {
100
+ if (typeof ref === "function") {
101
+ ref(value);
102
+ return;
61
103
  }
62
- if (advancedInput) {
63
- advancedInput.classList.toggle("hidden", mode !== "advanced");
64
- advancedInput.name = mode === "advanced" ? textareaName : "";
104
+ if (ref) {
105
+ ref.current = value;
65
106
  }
66
107
  };
67
- var TextArea = ({
68
- variant = "outlined",
69
- label,
70
- className,
71
- wrapperClassName,
72
- id,
73
- name,
74
- placeholder,
75
- rows = 4,
76
- allowModeSwitch = true,
77
- mode,
78
- view = "editor",
79
- value,
80
- defaultValue,
81
- disabled,
82
- readOnly,
83
- onChange,
84
- onInput,
85
- ...props
86
- }) => {
87
- const textareaId = id || name || generateString();
88
- const textareaName = name || textareaId;
89
- const wrapperId = `${textareaId}-wrapper`;
90
- const simpleTextareaId = `${textareaId}-simple`;
91
- const advancedInputId = `${textareaId}-advanced-input`;
92
- const advancedEditorId = `${textareaId}-advanced-editor`;
93
- const advancedLabelId = `${textareaId}-advanced-label`;
94
- const previewId = `${textareaId}-preview`;
95
- const variantClass = variantClasses[variant] ?? variantClasses.outlined;
96
- const labelPadding = label ? "pt-6" : void 0;
97
- const placeholderValue = placeholder ?? (label ? " " : void 0);
98
- const placeholderClass = label ? "placeholder-transparent" : void 0;
99
- const labelBg = labelBackground[variant] ?? labelBackground.outlined;
100
- const focusLabelBg = variant === "filled" ? "peer-focus:bg-gray-100 dark:peer-focus:bg-slate-800" : variant === "standard" ? "peer-focus:bg-transparent" : "peer-focus:bg-white/90 dark:peer-focus:bg-slate-900";
101
- const resolvedMode = allowModeSwitch ? mode ?? "simple" : "simple";
102
- const resolvedView = view ?? "editor";
103
- const showEditor = resolvedView === "editor";
104
- const showPreview = resolvedView === "view";
105
- const contentValue = typeof value === "string" ? value : typeof defaultValue === "string" ? defaultValue : "";
106
- const isControlled = typeof value === "string";
107
- const editorEditable = !(disabled || readOnly);
108
- const modeToggleName = `${textareaId}-mode-toggle`;
109
- const simpleToggleId = `${modeToggleName}-simple`;
110
- const advancedToggleId = `${modeToggleName}-advanced`;
111
- const turndownService = React__default.default.useMemo(() => {
112
- const service = new TurndownService__default.default({
113
- codeBlockStyle: "fenced",
114
- emDelimiter: "*",
115
- strongDelimiter: "**",
116
- bulletListMarker: "-"
117
- });
118
- service.addRule("strikethrough", {
119
- filter: (node) => ["DEL", "S", "STRIKE"].includes(node.nodeName),
120
- replacement: (content) => `~~${content}~~`
121
- });
122
- return service;
123
- }, []);
124
- const hiddenTextareaRef = React__default.default.useRef(null);
125
- const lastMarkdownRef = React__default.default.useRef(contentValue);
126
- const editorContentClass = tailwindMerge.twMerge(
127
- baseClass,
128
- "min-h-45 rounded border-0 bg-transparent outline-none whitespace-pre-wrap wrap-break-words",
129
- "[&_p]:m-0 [&_p]:leading-6",
130
- "[&_ul]:my-0 [&_ul]:list-disc [&_ul]:pl-5",
131
- "[&_ol]:my-0 [&_ol]:list-decimal [&_ol]:pl-5",
132
- "[&_li]:my-0",
133
- "[&_blockquote]:border-l-2 [&_blockquote]:border-gray-300 [&_blockquote]:pl-3 [&_blockquote]:text-gray-600",
134
- "dark:[&_blockquote]:border-gray-600 dark:[&_blockquote]:text-gray-300",
135
- "[&_pre]:bg-gray-100 [&_pre]:rounded [&_pre]:p-3 [&_pre]:text-sm [&_pre]:overflow-x-auto",
136
- "dark:[&_pre]:bg-slate-800",
137
- "[&_code]:font-mono",
138
- className,
139
- !editorEditable ? "cursor-not-allowed opacity-50" : void 0
140
- );
141
- const editor = react.useEditor({
142
- extensions: [StarterKit__default.default],
143
- content: renderMarkdown(contentValue),
144
- immediatelyRender: false,
145
- editable: editorEditable,
146
- editorProps: {
147
- attributes: {
148
- class: editorContentClass,
149
- role: "textbox",
150
- "aria-multiline": "true",
151
- ...label ? { "aria-labelledby": advancedLabelId } : {}
152
- }
153
- },
154
- onUpdate: ({ editor: currentEditor }) => {
155
- const markdown = turndownService.turndown(currentEditor.getHTML());
156
- if (markdown === lastMarkdownRef.current) return;
157
- lastMarkdownRef.current = markdown;
158
- if (!hiddenTextareaRef.current) return;
159
- hiddenTextareaRef.current.value = markdown;
160
- dispatchInputEvent(hiddenTextareaRef.current);
161
- }
162
- });
163
- React__default.default.useEffect(() => {
164
- if (!editor) return;
165
- editor.setEditable(editorEditable);
166
- }, [editor, editorEditable]);
167
- React__default.default.useEffect(() => {
168
- if (!editor) return;
169
- editor.setOptions({
108
+ var updateTextareaValue = (element, nextValue, selectionStart, selectionEnd) => {
109
+ element.value = nextValue;
110
+ element.setSelectionRange(selectionStart, selectionEnd);
111
+ };
112
+ var indentSelectedLines = (value, selectionStart, selectionEnd) => {
113
+ const lineStart = value.lastIndexOf("\n", Math.max(0, selectionStart - 1)) + 1;
114
+ const lineEndIndex = value.indexOf("\n", selectionEnd);
115
+ const lineEnd = lineEndIndex === -1 ? value.length : lineEndIndex;
116
+ const selectedBlock = value.slice(lineStart, lineEnd);
117
+ const lines = selectedBlock.split("\n");
118
+ const indentedBlock = lines.map((line) => `${TEXTAREA_TAB_CHARACTER}${line}`).join("\n");
119
+ return {
120
+ nextValue: `${value.slice(0, lineStart)}${indentedBlock}${value.slice(lineEnd)}`,
121
+ selectionStart: selectionStart + TEXTAREA_TAB_CHARACTER.length,
122
+ selectionEnd: selectionEnd + lines.length * TEXTAREA_TAB_CHARACTER.length
123
+ };
124
+ };
125
+ var outdentSelectedLines = (value, selectionStart, selectionEnd) => {
126
+ const lineStart = value.lastIndexOf("\n", Math.max(0, selectionStart - 1)) + 1;
127
+ const lineEndIndex = value.indexOf("\n", selectionEnd);
128
+ const lineEnd = lineEndIndex === -1 ? value.length : lineEndIndex;
129
+ const selectedBlock = value.slice(lineStart, lineEnd);
130
+ const lines = selectedBlock.split("\n");
131
+ const updatedLines = lines.map((line) => line.startsWith(TEXTAREA_TAB_CHARACTER) ? line.slice(TEXTAREA_TAB_CHARACTER.length) : line);
132
+ const removedBeforeSelectionStart = selectionStart === lineStart && !lines[0].startsWith(TEXTAREA_TAB_CHARACTER) ? 0 : lines[0].startsWith(TEXTAREA_TAB_CHARACTER) ? TEXTAREA_TAB_CHARACTER.length : 0;
133
+ const removedTotal = lines.reduce((count, line) => count + (line.startsWith(TEXTAREA_TAB_CHARACTER) ? TEXTAREA_TAB_CHARACTER.length : 0), 0);
134
+ return {
135
+ nextValue: `${value.slice(0, lineStart)}${updatedLines.join("\n")}${value.slice(lineEnd)}`,
136
+ selectionStart: Math.max(lineStart, selectionStart - removedBeforeSelectionStart),
137
+ selectionEnd: Math.max(lineStart, selectionEnd - removedTotal)
138
+ };
139
+ };
140
+ var isCodeBlockLanguage = (value) => CODE_BLOCK_LANGUAGES.includes(value);
141
+ var ToolbarButton = ({ label, active, disabled, onMouseDown }) => /* @__PURE__ */ jsxRuntime.jsx(
142
+ "button",
143
+ {
144
+ type: "button",
145
+ disabled,
146
+ onMouseDown,
147
+ className: tailwindMerge.twMerge(
148
+ "inline-flex min-w-8 items-center justify-center rounded border px-2 py-1 text-xs font-medium transition-colors",
149
+ active ? "border-primary bg-primary text-white" : "border-gray-300 bg-white text-gray-700 hover:border-gray-400 hover:bg-gray-50 dark:border-slate-600 dark:bg-slate-900 dark:text-gray-200 dark:hover:bg-slate-800",
150
+ disabled && "cursor-not-allowed opacity-50"
151
+ ),
152
+ children: label
153
+ }
154
+ );
155
+ var TextArea = React__default.default.forwardRef(
156
+ ({ variant = "outline", size = "medium", rounded = "md", success, error, warn, className, wrapperClassName, label, prepend, append, rows = 4, richText = false, toolbar = DEFAULT_TOOLBAR, ...props }, ref) => {
157
+ const { placeholder, onFocus, onBlur, onChange, onKeyDown, value, defaultValue, disabled, readOnly, ...textareaProps } = props;
158
+ const reactId = React__default.default.useId();
159
+ const hasLabel = Boolean(label);
160
+ const hasProvidedPlaceholder = typeof placeholder === "string" && placeholder.trim().length > 0;
161
+ const hidePlaceholderUntilFocus = hasLabel && hasProvidedPlaceholder;
162
+ const [isFocused, setIsFocused] = React__default.default.useState(false);
163
+ const classBase = "textarea-base transition-colors duration-200 w-full has-[textarea:disabled]:opacity-50 has-[textarea:disabled]:cursor-not-allowed";
164
+ const textareaBase = "peer block w-full min-w-0 resize-y border-0 bg-transparent p-0 text-gray-900 dark:text-gray-100 placeholder:text-gray-500 dark:placeholder:text-gray-400 focus:outline-none focus:ring-0";
165
+ const proseBase = "ProseMirror min-h-[7rem] w-full border-0 bg-transparent p-0 text-gray-900 dark:text-gray-100 focus:outline-none [&_blockquote]:border-l-4 [&_blockquote]:border-gray-300 [&_blockquote]:pl-3 [&_blockquote]:italic dark:[&_blockquote]:border-slate-600 [&_:not(pre)>code]:rounded [&_:not(pre)>code]:bg-black [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:text-white dark:[&_:not(pre)>code]:bg-black dark:[&_:not(pre)>code]:text-white [&_pre]:overflow-x-auto [&_pre]:rounded [&_pre]:bg-black [&_pre]:p-3 [&_pre]:text-white [&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_pre_code]:text-white [&_ul]:list-disc [&_ul]:pl-5 [&_ol]:list-decimal [&_ol]:pl-5 [&_h1]:text-2xl [&_h1]:font-semibold [&_h2]:text-xl [&_h2]:font-semibold";
166
+ const hiddenTextareaRef = React__default.default.useRef(null);
167
+ const forwardedRef = React__default.default.useRef(null);
168
+ const isControlled = value !== void 0;
169
+ const markdownValue = typeof value === "string" ? value : typeof defaultValue === "string" ? defaultValue : "";
170
+ const [internalMarkdown, setInternalMarkdown] = React__default.default.useState(markdownValue);
171
+ const resolvedMarkdownValue = isControlled ? typeof value === "string" ? value : "" : internalMarkdown;
172
+ const status = error ? { tone: "error", message: error } : warn ? { tone: "warn", message: warn } : success ? { tone: "success", message: success } : void 0;
173
+ const variantClass = variantClasses[variant] ?? variantClasses.outline;
174
+ const toneClass = status ? statusClasses[status.tone] : void 0;
175
+ const hasPrepend = typeof prepend === "string" ? prepend.trim().length > 0 : Boolean(prepend);
176
+ const hasAppend = typeof append === "string" ? append.trim().length > 0 : Boolean(append);
177
+ const sizeConfig = sizeClasses[size] ?? sizeClasses.medium;
178
+ const sizeClass = [sizeConfig.paddingY, sizeConfig.paddingX, sizeConfig.text].join(" ");
179
+ const roundedClass = variant === "sharp" || variant === "text" || variant === "underlined" ? "rounded-none" : roundedClasses[rounded];
180
+ const inputName = textareaProps.name || reactId;
181
+ const basePlaceholder = placeholder ?? (hasLabel ? " " : void 0);
182
+ const placeholderValue = hidePlaceholderUntilFocus ? isFocused ? placeholder : " " : basePlaceholder;
183
+ const placeholderClass = hidePlaceholderUntilFocus ? "placeholder-transparent focus:placeholder-gray-500 focus:dark:placeholder-gray-400" : void 0;
184
+ const editor = react.useEditor({
185
+ extensions: [
186
+ StarterKit__default.default.configure({ heading: { levels: [1, 2] }, codeBlock: false }),
187
+ CodeBlockLowlight__default.default.configure({
188
+ defaultLanguage: DEFAULT_CODE_BLOCK_LANGUAGE,
189
+ enableTabIndentation: true,
190
+ lowlight,
191
+ HTMLAttributes: {
192
+ class: "hljs"
193
+ }
194
+ }),
195
+ Underline__default.default
196
+ ],
197
+ content: markdownToHtml(resolvedMarkdownValue),
198
+ editable: richText && !disabled && !readOnly,
199
+ immediatelyRender: false,
170
200
  editorProps: {
171
- ...editor.options.editorProps,
172
201
  attributes: {
173
- ...editor.options.editorProps?.attributes,
174
- class: editorContentClass,
175
- role: "textbox",
176
- "aria-multiline": "true",
177
- ...label ? { "aria-labelledby": advancedLabelId } : {}
202
+ class: tailwindMerge.twMerge(proseBase, placeholderClass),
203
+ "data-placeholder": placeholderValue ?? ""
204
+ }
205
+ },
206
+ onFocus: () => {
207
+ if (!richText) {
208
+ return;
209
+ }
210
+ if (hidePlaceholderUntilFocus) {
211
+ setIsFocused(true);
178
212
  }
213
+ const target = hiddenTextareaRef.current;
214
+ if (target) {
215
+ onFocus?.(createChangeEvent(target));
216
+ }
217
+ },
218
+ onBlur: () => {
219
+ if (!richText) {
220
+ return;
221
+ }
222
+ if (hidePlaceholderUntilFocus) {
223
+ setIsFocused(false);
224
+ }
225
+ const target = hiddenTextareaRef.current;
226
+ if (target) {
227
+ onBlur?.(createChangeEvent(target));
228
+ }
229
+ },
230
+ onUpdate: ({ editor: currentEditor }) => {
231
+ if (!richText) {
232
+ return;
233
+ }
234
+ const nextMarkdown = htmlToMarkdown(currentEditor.getHTML());
235
+ const target = hiddenTextareaRef.current;
236
+ setInternalMarkdown(nextMarkdown);
237
+ if (!target) {
238
+ return;
239
+ }
240
+ target.value = nextMarkdown;
241
+ onChange?.(createChangeEvent(target));
179
242
  }
180
243
  });
181
- }, [editor, editorContentClass, label, advancedLabelId]);
182
- React__default.default.useEffect(() => {
183
- if (!editor || typeof value !== "string") return;
184
- if (value === lastMarkdownRef.current) return;
185
- editor.commands.setContent(renderMarkdown(value), { emitUpdate: false });
186
- lastMarkdownRef.current = value;
187
- if (hiddenTextareaRef.current) {
188
- hiddenTextareaRef.current.value = value;
189
- }
190
- }, [editor, value]);
191
- React__default.default.useEffect(() => {
192
- if (!hiddenTextareaRef.current) return;
193
- if (hiddenTextareaRef.current.value === contentValue) return;
194
- hiddenTextareaRef.current.value = contentValue;
195
- }, [contentValue]);
196
- const textareaProps = {
197
- ...props,
198
- onChange,
199
- onInput,
200
- disabled,
201
- readOnly
202
- };
203
- const minHeightStyle = rows ? { minHeight: `${rows * 20}px` } : void 0;
204
- return /* @__PURE__ */ jsxRuntime.jsxs(
205
- "div",
206
- {
207
- id: wrapperId,
208
- "data-mode": resolvedMode,
209
- className: tailwindMerge.twMerge("flex flex-col gap-1", wrapperClassName),
210
- children: [
211
- allowModeSwitch && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
212
- /* @__PURE__ */ jsxRuntime.jsx(
213
- "input",
214
- {
215
- type: "radio",
216
- name: modeToggleName,
217
- id: simpleToggleId,
218
- value: "simple",
219
- defaultChecked: resolvedMode === "simple",
220
- className: "peer/simple sr-only",
221
- onChange: () => handleModeToggle(wrapperId, "simple", textareaName, simpleTextareaId, advancedInputId)
222
- }
223
- ),
224
- /* @__PURE__ */ jsxRuntime.jsx(
225
- "input",
226
- {
227
- type: "radio",
228
- name: modeToggleName,
229
- id: advancedToggleId,
230
- value: "advanced",
231
- defaultChecked: resolvedMode === "advanced",
232
- className: "peer/advanced sr-only",
233
- onChange: () => handleModeToggle(
234
- wrapperId,
235
- "advanced",
236
- textareaName,
237
- simpleTextareaId,
238
- advancedInputId
239
- )
240
- }
241
- ),
242
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex overflow-hidden rounded-md border border-gray-200 bg-gray-50 text-xs font-medium dark:border-gray-700 dark:bg-slate-800", children: [
243
- /* @__PURE__ */ jsxRuntime.jsx(
244
- "label",
245
- {
246
- htmlFor: simpleToggleId,
247
- className: tailwindMerge.twMerge(
248
- "cursor-pointer px-3 py-1 transition-colors",
249
- "text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-slate-700",
250
- "peer-checked/simple:bg-white peer-checked/simple:text-gray-900 peer-checked/simple:dark:bg-slate-900 peer-checked/simple:dark:text-gray-100"
251
- ),
252
- children: "Jednoduch\xFD"
253
- }
254
- ),
244
+ const activeCodeBlockLanguage = (() => {
245
+ const language = editor?.getAttributes("codeBlock").language;
246
+ if (typeof language === "string" && isCodeBlockLanguage(language)) {
247
+ return language;
248
+ }
249
+ return DEFAULT_CODE_BLOCK_LANGUAGE;
250
+ })();
251
+ React__default.default.useEffect(() => {
252
+ if (!richText) {
253
+ return;
254
+ }
255
+ const target = hiddenTextareaRef.current;
256
+ if (!target) {
257
+ return;
258
+ }
259
+ target.value = resolvedMarkdownValue;
260
+ forwardedRef.current = target;
261
+ assignRef(ref, target);
262
+ }, [ref, resolvedMarkdownValue, richText]);
263
+ React__default.default.useEffect(() => {
264
+ if (!editor || !richText || !isControlled) {
265
+ return;
266
+ }
267
+ const nextMarkdown = typeof value === "string" ? value : "";
268
+ const currentMarkdown = htmlToMarkdown(editor.getHTML());
269
+ if (currentMarkdown === nextMarkdown) {
270
+ return;
271
+ }
272
+ editor.commands.setContent(markdownToHtml(nextMarkdown), { emitUpdate: false });
273
+ }, [editor, isControlled, richText, value]);
274
+ React__default.default.useEffect(() => {
275
+ if (!isControlled) {
276
+ setInternalMarkdown(typeof defaultValue === "string" ? defaultValue : "");
277
+ }
278
+ }, [defaultValue, isControlled]);
279
+ React__default.default.useEffect(() => {
280
+ if (!editor || !richText) {
281
+ return;
282
+ }
283
+ editor.setEditable(!disabled && !readOnly);
284
+ }, [disabled, editor, readOnly, richText]);
285
+ const renderPrepend = hasPrepend ? typeof prepend === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("text-gray-500 dark:text-gray-400", sizeConfig.text), children: prepend }) : prepend : null;
286
+ const renderAppend = hasAppend ? typeof append === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("text-gray-500 dark:text-gray-400", sizeConfig.text), children: append }) : append : null;
287
+ const handleFocus = (event) => {
288
+ if (hidePlaceholderUntilFocus) setIsFocused(true);
289
+ onFocus?.(event);
290
+ };
291
+ const handleBlur = (event) => {
292
+ if (hidePlaceholderUntilFocus) setIsFocused(false);
293
+ onBlur?.(event);
294
+ };
295
+ const handleKeyDown = (event) => {
296
+ onKeyDown?.(event);
297
+ if (event.defaultPrevented || event.key !== "Tab" || disabled || readOnly) {
298
+ return;
299
+ }
300
+ const target = event.currentTarget;
301
+ const { selectionStart, selectionEnd, value: currentValue } = target;
302
+ event.preventDefault();
303
+ if (selectionStart !== selectionEnd && currentValue.slice(selectionStart, selectionEnd).includes("\n")) {
304
+ const nextState = event.shiftKey ? outdentSelectedLines(currentValue, selectionStart, selectionEnd) : indentSelectedLines(currentValue, selectionStart, selectionEnd);
305
+ updateTextareaValue(target, nextState.nextValue, nextState.selectionStart, nextState.selectionEnd);
306
+ onChange?.(createChangeEvent(target));
307
+ return;
308
+ }
309
+ if (event.shiftKey) {
310
+ const lineStart = currentValue.lastIndexOf("\n", Math.max(0, selectionStart - 1)) + 1;
311
+ if (currentValue.slice(lineStart, selectionStart).endsWith(TEXTAREA_TAB_CHARACTER)) {
312
+ const nextValue2 = `${currentValue.slice(0, selectionStart - TEXTAREA_TAB_CHARACTER.length)}${currentValue.slice(selectionEnd)}`;
313
+ const nextPosition2 = selectionStart - TEXTAREA_TAB_CHARACTER.length;
314
+ updateTextareaValue(target, nextValue2, nextPosition2, nextPosition2);
315
+ onChange?.(createChangeEvent(target));
316
+ }
317
+ return;
318
+ }
319
+ const nextValue = `${currentValue.slice(0, selectionStart)}${TEXTAREA_TAB_CHARACTER}${currentValue.slice(selectionEnd)}`;
320
+ const nextPosition = selectionStart + TEXTAREA_TAB_CHARACTER.length;
321
+ updateTextareaValue(target, nextValue, nextPosition, nextPosition);
322
+ onChange?.(createChangeEvent(target));
323
+ };
324
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("flex flex-col gap-1", wrapperClassName), children: [
325
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("flex w-full items-start gap-2", classBase, variantClass, roundedClass, toneClass, sizeClass, className), children: [
326
+ hasPrepend && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-start pt-0.5", children: renderPrepend }),
327
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-w-0 flex-1", children: [
328
+ richText ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
255
329
  /* @__PURE__ */ jsxRuntime.jsx(
256
- "label",
330
+ "textarea",
257
331
  {
258
- htmlFor: advancedToggleId,
259
- className: tailwindMerge.twMerge(
260
- "cursor-pointer px-3 py-1 transition-colors",
261
- "text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-slate-700",
262
- "peer-checked/advanced:bg-white peer-checked/advanced:text-gray-900 peer-checked/advanced:dark:bg-slate-900 peer-checked/advanced:dark:text-gray-100"
263
- ),
264
- children: "Pokro\u010Dil\xFD"
332
+ ...textareaProps,
333
+ ref: (node) => {
334
+ hiddenTextareaRef.current = node;
335
+ forwardedRef.current = node;
336
+ if (node) {
337
+ assignRef(ref, node);
338
+ }
339
+ },
340
+ id: inputName,
341
+ name: inputName,
342
+ rows,
343
+ value: isControlled ? value : void 0,
344
+ defaultValue: !isControlled ? defaultValue : void 0,
345
+ disabled,
346
+ readOnly: true,
347
+ tabIndex: -1,
348
+ "aria-hidden": true,
349
+ className: "sr-only"
265
350
  }
266
- )
267
- ] }) })
268
- ] }),
269
- (resolvedMode === "simple" || allowModeSwitch) && /* @__PURE__ */ jsxRuntime.jsxs(
270
- "div",
271
- {
272
- className: tailwindMerge.twMerge(
273
- "relative flex items-start",
274
- allowModeSwitch ? "hidden peer-checked/simple:flex peer-checked/advanced:hidden" : void 0
275
351
  ),
276
- children: [
277
- /* @__PURE__ */ jsxRuntime.jsx(
278
- "textarea",
352
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-1 border-b border-gray-200 pb-2 dark:border-slate-700", children: [
353
+ toolbar.includes("bold") && /* @__PURE__ */ jsxRuntime.jsx(
354
+ ToolbarButton,
279
355
  {
280
- ...textareaProps,
281
- id: simpleTextareaId,
282
- name: !allowModeSwitch || resolvedMode === "simple" ? textareaName : "",
283
- rows,
284
- placeholder: placeholderValue,
285
- value,
286
- defaultValue,
287
- className: tailwindMerge.twMerge(
288
- "peer",
289
- baseClass,
290
- variantClass,
291
- labelPadding,
292
- placeholderClass,
293
- className
294
- )
356
+ label: "B",
357
+ disabled: !editor?.isEditable,
358
+ active: editor?.isActive("bold"),
359
+ onMouseDown: (event) => {
360
+ event.preventDefault();
361
+ editor?.chain().focus().toggleBold().run();
362
+ }
295
363
  }
296
364
  ),
297
- label && /* @__PURE__ */ jsxRuntime.jsx(
298
- "label",
365
+ toolbar.includes("italic") && /* @__PURE__ */ jsxRuntime.jsx(
366
+ ToolbarButton,
299
367
  {
300
- htmlFor: simpleTextareaId,
301
- className: tailwindMerge.twMerge(
302
- "absolute transition-all duration-150 pointer-events-none left-3 text-gray-700 dark:text-gray-200",
303
- "top-0 -translate-y-2/3 text-xs px-1",
304
- labelBg,
305
- focusLabelBg,
306
- "peer-focus:top-0 peer-focus:-translate-y-1/2 peer-focus:text-xs peer-focus:px-1 peer-focus:text-gray-600 dark:peer-focus:text-gray-300",
307
- "peer-placeholder-shown:top-3 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:text-sm peer-placeholder-shown:bg-transparent peer-placeholder-shown:text-gray-500 dark:peer-placeholder-shown:text-gray-400"
308
- ),
309
- children: label
368
+ label: "I",
369
+ disabled: !editor?.isEditable,
370
+ active: editor?.isActive("italic"),
371
+ onMouseDown: (event) => {
372
+ event.preventDefault();
373
+ editor?.chain().focus().toggleItalic().run();
374
+ }
310
375
  }
311
- )
312
- ]
313
- }
314
- ),
315
- (resolvedMode === "advanced" || allowModeSwitch) && /* @__PURE__ */ jsxRuntime.jsxs(
316
- "div",
317
- {
318
- className: tailwindMerge.twMerge(
319
- "flex flex-col gap-2",
320
- allowModeSwitch ? "hidden peer-checked/advanced:flex peer-checked/simple:hidden" : void 0
321
- ),
322
- children: [
323
- label && /* @__PURE__ */ jsxRuntime.jsx(
324
- "label",
376
+ ),
377
+ toolbar.includes("underline") && /* @__PURE__ */ jsxRuntime.jsx(
378
+ ToolbarButton,
325
379
  {
326
- id: advancedLabelId,
327
- className: "text-sm font-medium text-gray-700 dark:text-gray-200",
328
- children: label
380
+ label: "U",
381
+ disabled: !editor?.isEditable,
382
+ active: editor?.isActive("underline"),
383
+ onMouseDown: (event) => {
384
+ event.preventDefault();
385
+ editor?.chain().focus().toggleUnderline().run();
386
+ }
329
387
  }
330
388
  ),
331
- showEditor && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center justify-between gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex overflow-hidden rounded-md border border-gray-200 bg-gray-50 text-xs font-medium dark:border-gray-700 dark:bg-slate-800", children: [
332
- /* @__PURE__ */ jsxRuntime.jsx(
333
- "button",
334
- {
335
- type: "button",
336
- className: tailwindMerge.twMerge(
337
- toolbarButtonBase,
338
- editor?.isActive("bold") ? toolbarButtonActive : void 0
339
- ),
340
- onClick: () => editor?.chain().focus().toggleBold().run(),
341
- disabled: !editor || !editorEditable,
342
- children: "B"
343
- }
344
- ),
345
- /* @__PURE__ */ jsxRuntime.jsx(
346
- "button",
347
- {
348
- type: "button",
349
- className: tailwindMerge.twMerge(
350
- toolbarButtonBase,
351
- editor?.isActive("italic") ? toolbarButtonActive : void 0
352
- ),
353
- onClick: () => editor?.chain().focus().toggleItalic().run(),
354
- disabled: !editor || !editorEditable,
355
- children: "I"
389
+ toolbar.includes("strike") && /* @__PURE__ */ jsxRuntime.jsx(
390
+ ToolbarButton,
391
+ {
392
+ label: "S",
393
+ disabled: !editor?.isEditable,
394
+ active: editor?.isActive("strike"),
395
+ onMouseDown: (event) => {
396
+ event.preventDefault();
397
+ editor?.chain().focus().toggleStrike().run();
356
398
  }
357
- ),
399
+ }
400
+ ),
401
+ toolbar.includes("heading") && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
358
402
  /* @__PURE__ */ jsxRuntime.jsx(
359
- "button",
403
+ ToolbarButton,
360
404
  {
361
- type: "button",
362
- className: tailwindMerge.twMerge(
363
- toolbarButtonBase,
364
- editor?.isActive("strike") ? toolbarButtonActive : void 0
365
- ),
366
- onClick: () => editor?.chain().focus().toggleStrike().run(),
367
- disabled: !editor || !editorEditable,
368
- children: "S"
405
+ label: "H1",
406
+ disabled: !editor?.isEditable,
407
+ active: editor?.isActive("heading", { level: 1 }),
408
+ onMouseDown: (event) => {
409
+ event.preventDefault();
410
+ editor?.chain().focus().toggleHeading({ level: 1 }).run();
411
+ }
369
412
  }
370
413
  ),
371
414
  /* @__PURE__ */ jsxRuntime.jsx(
372
- "button",
415
+ ToolbarButton,
373
416
  {
374
- type: "button",
375
- className: tailwindMerge.twMerge(
376
- toolbarButtonBase,
377
- editor?.isActive("bulletList") ? toolbarButtonActive : void 0
378
- ),
379
- onClick: () => editor?.chain().focus().toggleBulletList().run(),
380
- disabled: !editor || !editorEditable,
381
- children: "\u2022 List"
417
+ label: "H2",
418
+ disabled: !editor?.isEditable,
419
+ active: editor?.isActive("heading", { level: 2 }),
420
+ onMouseDown: (event) => {
421
+ event.preventDefault();
422
+ editor?.chain().focus().toggleHeading({ level: 2 }).run();
423
+ }
382
424
  }
383
- ),
384
- /* @__PURE__ */ jsxRuntime.jsx(
385
- "button",
386
- {
387
- type: "button",
388
- className: tailwindMerge.twMerge(
389
- toolbarButtonBase,
390
- editor?.isActive("orderedList") ? toolbarButtonActive : void 0
391
- ),
392
- onClick: () => editor?.chain().focus().toggleOrderedList().run(),
393
- disabled: !editor || !editorEditable,
394
- children: "1. List"
425
+ )
426
+ ] }),
427
+ toolbar.includes("bulletList") && /* @__PURE__ */ jsxRuntime.jsx(
428
+ ToolbarButton,
429
+ {
430
+ label: "List",
431
+ disabled: !editor?.isEditable,
432
+ active: editor?.isActive("bulletList"),
433
+ onMouseDown: (event) => {
434
+ event.preventDefault();
435
+ editor?.chain().focus().toggleBulletList().run();
395
436
  }
396
- ),
397
- /* @__PURE__ */ jsxRuntime.jsx(
398
- "button",
399
- {
400
- type: "button",
401
- className: tailwindMerge.twMerge(
402
- toolbarButtonBase,
403
- editor?.isActive("blockquote") ? toolbarButtonActive : void 0
404
- ),
405
- onClick: () => editor?.chain().focus().toggleBlockquote().run(),
406
- disabled: !editor || !editorEditable,
407
- children: "Quote"
437
+ }
438
+ ),
439
+ toolbar.includes("orderedList") && /* @__PURE__ */ jsxRuntime.jsx(
440
+ ToolbarButton,
441
+ {
442
+ label: "1.",
443
+ disabled: !editor?.isEditable,
444
+ active: editor?.isActive("orderedList"),
445
+ onMouseDown: (event) => {
446
+ event.preventDefault();
447
+ editor?.chain().focus().toggleOrderedList().run();
408
448
  }
409
- ),
410
- /* @__PURE__ */ jsxRuntime.jsx(
411
- "button",
412
- {
413
- type: "button",
414
- className: tailwindMerge.twMerge(
415
- toolbarButtonBase,
416
- editor?.isActive("code") ? toolbarButtonActive : void 0
417
- ),
418
- onClick: () => editor?.chain().focus().toggleCode().run(),
419
- disabled: !editor || !editorEditable,
420
- children: "Code"
449
+ }
450
+ ),
451
+ toolbar.includes("blockquote") && /* @__PURE__ */ jsxRuntime.jsx(
452
+ ToolbarButton,
453
+ {
454
+ label: "Quote",
455
+ disabled: !editor?.isEditable,
456
+ active: editor?.isActive("blockquote"),
457
+ onMouseDown: (event) => {
458
+ event.preventDefault();
459
+ editor?.chain().focus().toggleBlockquote().run();
421
460
  }
422
- ),
461
+ }
462
+ ),
463
+ toolbar.includes("codeBlock") && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
423
464
  /* @__PURE__ */ jsxRuntime.jsx(
424
- "button",
465
+ ToolbarButton,
425
466
  {
426
- type: "button",
427
- className: tailwindMerge.twMerge(
428
- toolbarButtonBase,
429
- editor?.isActive("codeBlock") ? toolbarButtonActive : void 0
430
- ),
431
- onClick: () => editor?.chain().focus().toggleCodeBlock().run(),
432
- disabled: !editor || !editorEditable,
433
- children: "Code block"
434
- }
435
- )
436
- ] }) }),
437
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("overflow-hidden", advancedContainerVariant[variant]), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-3 space-y-3", children: [
438
- showEditor && /* @__PURE__ */ jsxRuntime.jsx(
439
- react.EditorContent,
440
- {
441
- editor,
442
- id: advancedEditorId,
443
- className: "w-full",
444
- style: minHeightStyle
467
+ label: "Code",
468
+ disabled: !editor?.isEditable,
469
+ active: editor?.isActive("codeBlock"),
470
+ onMouseDown: (event) => {
471
+ event.preventDefault();
472
+ editor?.chain().focus().toggleCodeBlock({ language: activeCodeBlockLanguage }).run();
473
+ }
445
474
  }
446
475
  ),
476
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "sr-only", htmlFor: `${inputName}-code-language`, children: "Code language" }),
447
477
  /* @__PURE__ */ jsxRuntime.jsx(
448
- "textarea",
478
+ "select",
449
479
  {
450
- ...textareaProps,
451
- ref: hiddenTextareaRef,
452
- id: advancedInputId,
453
- name: !allowModeSwitch || resolvedMode === "advanced" ? textareaName : "",
454
- rows,
455
- placeholder: placeholderValue,
456
- className: "sr-only",
457
- ...isControlled ? { value } : { defaultValue: contentValue }
458
- }
459
- ),
460
- showPreview && /* @__PURE__ */ jsxRuntime.jsx(
461
- "div",
462
- {
463
- id: previewId,
464
- className: tailwindMerge.twMerge(
465
- baseClass,
466
- "min-h-45 rounded border-0 px-0 focus:outline-none whitespace-pre-wrap wrap-break-words",
467
- className
468
- ),
469
- style: minHeightStyle,
470
- dangerouslySetInnerHTML: {
471
- __html: renderMarkdown(contentValue)
472
- }
480
+ id: `${inputName}-code-language`,
481
+ value: activeCodeBlockLanguage,
482
+ disabled: !editor?.isEditable,
483
+ className: "min-w-24 rounded border border-gray-300 bg-white px-2 py-1 text-xs text-gray-700 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/30 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-600 dark:bg-slate-900 dark:text-gray-200",
484
+ onChange: (event) => {
485
+ const language = event.target.value;
486
+ if (!isCodeBlockLanguage(language)) {
487
+ return;
488
+ }
489
+ editor?.chain().focus().setCodeBlock({ language }).run();
490
+ },
491
+ children: CODE_BLOCK_LANGUAGES.map((language) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: language, children: language }, language))
473
492
  }
474
493
  )
475
- ] }) })
476
- ]
477
- }
478
- )
479
- ]
480
- }
481
- );
482
- };
494
+ ] })
495
+ ] }),
496
+ /* @__PURE__ */ jsxRuntime.jsx(react.EditorContent, { editor, className: "pt-3" })
497
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
498
+ "textarea",
499
+ {
500
+ ...textareaProps,
501
+ ref: (node) => {
502
+ forwardedRef.current = node;
503
+ assignRef(ref, node);
504
+ },
505
+ id: inputName,
506
+ name: inputName,
507
+ rows,
508
+ placeholder: placeholderValue,
509
+ onFocus: handleFocus,
510
+ onBlur: handleBlur,
511
+ onKeyDown: handleKeyDown,
512
+ onChange,
513
+ disabled,
514
+ readOnly,
515
+ value,
516
+ defaultValue,
517
+ className: tailwindMerge.twMerge(textareaBase, placeholderClass)
518
+ }
519
+ ),
520
+ label && /* @__PURE__ */ jsxRuntime.jsx(
521
+ "label",
522
+ {
523
+ htmlFor: inputName,
524
+ className: tailwindMerge.twMerge(
525
+ "absolute left-0 z-10 transition-all duration-150 pointer-events-none text-gray-700 dark:text-gray-200",
526
+ "-top-2 -translate-y-full text-xs bg-white px-1 dark:bg-slate-900",
527
+ !richText && "peer-focus:left-0 peer-focus:-top-5 peer-focus:-translate-y-full peer-focus:text-xs peer-focus:text-gray-600 dark:peer-focus:text-gray-300",
528
+ !richText && "peer-placeholder-shown:top-3 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:text-sm peer-placeholder-shown:bg-transparent peer-placeholder-shown:px-0 peer-placeholder-shown:text-gray-500 dark:peer-placeholder-shown:text-gray-400",
529
+ !richText && "peer-[&:not(:placeholder-shown)]:left-0 peer-[&:not(:placeholder-shown)]:-top-2 peer-[&:not(:placeholder-shown)]:-translate-y-full peer-[&:not(:placeholder-shown)]:text-xs peer-[&:not(:placeholder-shown)]:bg-white peer-[&:not(:placeholder-shown)]:px-1 peer-[&:not(:placeholder-shown)]:text-gray-700 dark:peer-[&:not(:placeholder-shown)]:bg-slate-900 dark:peer-[&:not(:placeholder-shown)]:text-gray-200",
530
+ richText && (isFocused || resolvedMarkdownValue) && "-top-2 -translate-y-full text-xs",
531
+ richText && !(isFocused || resolvedMarkdownValue) && "top-3 translate-y-0 text-sm bg-transparent px-0 text-gray-500 dark:text-gray-400"
532
+ ),
533
+ children: label
534
+ }
535
+ )
536
+ ] }),
537
+ hasAppend && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-start pt-0.5", children: renderAppend })
538
+ ] }),
539
+ status?.message && /* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("text-sm", statusMessageClasses[status.tone]), children: status.message })
540
+ ] });
541
+ }
542
+ );
543
+ TextArea.displayName = "TextArea";
483
544
  var TextArea_default = TextArea;
484
545
 
485
546
  module.exports = TextArea_default;