@haklex/rich-ext-code-snippet 0.0.40 → 0.0.42

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.
@@ -0,0 +1,431 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { createRendererDecoration } from "@haklex/rich-editor";
5
+ import { DecoratorNode } from "lexical";
6
+ import { jsxs, jsx } from "react/jsx-runtime";
7
+ import { normalizeLanguage } from "@haklex/rich-renderer-codeblock/constants";
8
+ import { FileIcon } from "@haklex/rich-renderer-codeblock/icons";
9
+ import { getHighlighterWithLang, SHIKI_DUAL_THEMES } from "@haklex/rich-renderer-codeblock/shiki";
10
+ import { Check, Copy } from "lucide-react";
11
+ import { useState, useEffect, useRef, useCallback } from "react";
12
+ function toPrimitive(t, r) {
13
+ if ("object" != typeof t || !t) return t;
14
+ var e = t[Symbol.toPrimitive];
15
+ if (void 0 !== e) {
16
+ var i = e.call(t, r);
17
+ if ("object" != typeof i) return i;
18
+ throw new TypeError("@@toPrimitive must return a primitive value.");
19
+ }
20
+ return ("string" === r ? String : Number)(t);
21
+ }
22
+ function toPropertyKey(t) {
23
+ var i = toPrimitive(t, "string");
24
+ return "symbol" == typeof i ? i : String(i);
25
+ }
26
+ function _defineProperty(obj, key, value) {
27
+ key = toPropertyKey(key);
28
+ if (key in obj) {
29
+ Object.defineProperty(obj, key, {
30
+ value,
31
+ enumerable: true,
32
+ configurable: true,
33
+ writable: true
34
+ });
35
+ } else {
36
+ obj[key] = value;
37
+ }
38
+ return obj;
39
+ }
40
+ function ownKeys(e, r) {
41
+ var t = Object.keys(e);
42
+ if (Object.getOwnPropertySymbols) {
43
+ var o = Object.getOwnPropertySymbols(e);
44
+ r && (o = o.filter(function(r2) {
45
+ return Object.getOwnPropertyDescriptor(e, r2).enumerable;
46
+ })), t.push.apply(t, o);
47
+ }
48
+ return t;
49
+ }
50
+ function _objectSpread2(e) {
51
+ for (var r = 1; r < arguments.length; r++) {
52
+ var t = null != arguments[r] ? arguments[r] : {};
53
+ r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
54
+ _defineProperty(e, r2, t[r2]);
55
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
56
+ Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
57
+ });
58
+ }
59
+ return e;
60
+ }
61
+ function mapValues(input, fn) {
62
+ var result = {};
63
+ for (var _key in input) {
64
+ result[_key] = fn(input[_key], _key);
65
+ }
66
+ return result;
67
+ }
68
+ var shouldApplyCompound = (compoundCheck, selections, defaultVariants) => {
69
+ for (var key of Object.keys(compoundCheck)) {
70
+ var _selections$key;
71
+ if (compoundCheck[key] !== ((_selections$key = selections[key]) !== null && _selections$key !== void 0 ? _selections$key : defaultVariants[key])) {
72
+ return false;
73
+ }
74
+ }
75
+ return true;
76
+ };
77
+ var createRuntimeFn = (config) => {
78
+ var runtimeFn = (options) => {
79
+ var className = config.defaultClassName;
80
+ var selections = _objectSpread2(_objectSpread2({}, config.defaultVariants), options);
81
+ for (var variantName in selections) {
82
+ var _selections$variantNa;
83
+ var variantSelection = (_selections$variantNa = selections[variantName]) !== null && _selections$variantNa !== void 0 ? _selections$variantNa : config.defaultVariants[variantName];
84
+ if (variantSelection != null) {
85
+ var selection = variantSelection;
86
+ if (typeof selection === "boolean") {
87
+ selection = selection === true ? "true" : "false";
88
+ }
89
+ var selectionClassName = (
90
+ // @ts-expect-error
91
+ config.variantClassNames[variantName][selection]
92
+ );
93
+ if (selectionClassName) {
94
+ className += " " + selectionClassName;
95
+ }
96
+ }
97
+ }
98
+ for (var [compoundCheck, compoundClassName] of config.compoundVariants) {
99
+ if (shouldApplyCompound(compoundCheck, selections, config.defaultVariants)) {
100
+ className += " " + compoundClassName;
101
+ }
102
+ }
103
+ return className;
104
+ };
105
+ runtimeFn.variants = () => Object.keys(config.variantClassNames);
106
+ runtimeFn.classNames = {
107
+ get base() {
108
+ return config.defaultClassName.split(" ")[0];
109
+ },
110
+ get variants() {
111
+ return mapValues(config.variantClassNames, (classNames) => mapValues(classNames, (className) => className.split(" ")[0]));
112
+ }
113
+ };
114
+ return runtimeFn;
115
+ };
116
+ var semanticClassNames = { container: "rcs-container", header: "rcs-header", tabs: "rcs-tabs", tab: "rcs-tab", tabActive: "rcs-tab-active", titleBar: "rcs-title-bar", headerActions: "rcs-header-actions", copyButton: "rcs-copy-btn", separator: "rcs-separator", codePanel: "rcs-code-panel", codeScroll: "rcs-code-scroll", codeBody: "rcs-code-body", fileIcon: "rcs-file-icon", editContainer: "rcs-edit-container", editOverlay: "rcs-edit-overlay", editLabel: "rcs-edit-label", modal: "rcs-modal", modalTitlebar: "rcs-modal-titlebar", modalTitle: "rcs-modal-title", modalIconButton: "rcs-modal-icon-btn", modalBody: "rcs-modal-body", modalSidebar: "rcs-modal-sidebar", sidebarHeader: "rcs-sidebar-header", sidebarAddButton: "rcs-sidebar-add-btn", fileList: "rcs-file-list", fileItem: "rcs-file-item", fileItemActive: "rcs-file-item-active", fileItemDragging: "rcs-file-item-dragging", fileDragHandle: "rcs-file-drag-handle", fileName: "rcs-file-name", fileDelete: "rcs-file-delete", renameInput: "rcs-rename-input", modalEditor: "rcs-modal-editor", breadcrumb: "rcs-breadcrumb", breadcrumbLeft: "rcs-breadcrumb-left", breadcrumbName: "rcs-breadcrumb-name", breadcrumbLang: "rcs-breadcrumb-lang", editorContainer: "rcs-editor-container", dragOverlay: "rcs-drag-overlay" };
117
+ var container = "hjkryc0";
118
+ var header = "hjkryc1";
119
+ var tabs = "hjkryc2";
120
+ var tab = createRuntimeFn({ defaultClassName: "hjkryc4 hjkryc3", variantClassNames: { active: { true: "hjkryc5", false: "hjkryc6" } }, defaultVariants: { active: false }, compoundVariants: [] });
121
+ var titleBar = "hjkryc7";
122
+ var headerActions = "hjkryc8";
123
+ var copyButton = "hjkryc9";
124
+ var separator = "hjkryca";
125
+ var codeScroll = "hjkrycb";
126
+ var codeBody = "hjkrycc";
127
+ var fileIcon = "hjkrycd";
128
+ var editContainer = "hjkryce";
129
+ var editOverlay = "hjkrycf";
130
+ var editLabel = "hjkrycg";
131
+ var codeSnippetDialogPopup = "hjkrych";
132
+ var modal = "hjkryci";
133
+ var modalTitlebar = "hjkrycj";
134
+ var modalTitle = "hjkryck";
135
+ var modalIconButton = "hjkrycl";
136
+ var modalBody = "hjkrycm";
137
+ var modalSidebar = "hjkrycn";
138
+ var sidebarHeader = "hjkryco";
139
+ var sidebarAddButton = "hjkrycp";
140
+ var fileList = "hjkrycq";
141
+ var fileItem = createRuntimeFn({ defaultClassName: "hjkrycs hjkrycr", variantClassNames: { active: { true: "hjkryct", false: "hjkrycu" }, dragging: { true: "hjkrycv", false: "hjkrycw" } }, defaultVariants: { active: false, dragging: false }, compoundVariants: [] });
142
+ var fileDragHandle = "hjkrycx";
143
+ var fileName = "hjkrycy";
144
+ var fileDelete = "hjkrycz";
145
+ var renameInput = "hjkryc10";
146
+ var modalEditor = "hjkryc11";
147
+ var breadcrumb = "hjkryc12";
148
+ var breadcrumbLeft = "hjkryc13";
149
+ var breadcrumbName = "hjkryc14";
150
+ var breadcrumbLang = "hjkryc15";
151
+ var editorContainer = "hjkryc16";
152
+ var dragOverlay = "hjkryc17";
153
+ const EXT_TO_LANG = {
154
+ ts: "typescript",
155
+ tsx: "tsx",
156
+ js: "javascript",
157
+ jsx: "jsx",
158
+ py: "python",
159
+ rs: "rust",
160
+ go: "go",
161
+ java: "java",
162
+ html: "html",
163
+ css: "css",
164
+ scss: "scss",
165
+ json: "json",
166
+ md: "markdown",
167
+ sh: "bash",
168
+ yml: "yaml",
169
+ yaml: "yaml",
170
+ sql: "sql",
171
+ c: "c",
172
+ cpp: "cpp",
173
+ swift: "swift",
174
+ kt: "kotlin",
175
+ rb: "ruby",
176
+ php: "php",
177
+ vue: "vue",
178
+ svelte: "svelte",
179
+ toml: "toml",
180
+ xml: "xml",
181
+ graphql: "graphql",
182
+ gql: "graphql",
183
+ dockerfile: "dockerfile",
184
+ lua: "lua",
185
+ zig: "zig"
186
+ };
187
+ function getLanguageFromFilename(filename) {
188
+ const ext = filename.split(".").pop()?.toLowerCase() ?? "";
189
+ return EXT_TO_LANG[ext] ?? "text";
190
+ }
191
+ const CopyButton = ({ text }) => {
192
+ const [copied, setCopied] = useState(false);
193
+ const timerRef = useRef(void 0);
194
+ const handleCopy = useCallback(() => {
195
+ navigator.clipboard.writeText(text);
196
+ setCopied(true);
197
+ clearTimeout(timerRef.current);
198
+ timerRef.current = setTimeout(() => setCopied(false), 2e3);
199
+ }, [text]);
200
+ return /* @__PURE__ */ jsx(
201
+ "button",
202
+ {
203
+ type: "button",
204
+ className: `${copyButton} ${semanticClassNames.copyButton}`,
205
+ onClick: handleCopy,
206
+ "aria-label": copied ? "Copied" : "Copy code",
207
+ children: copied ? /* @__PURE__ */ jsx(Check, { size: 14 }) : /* @__PURE__ */ jsx(Copy, { size: 14 })
208
+ }
209
+ );
210
+ };
211
+ const CodeSnippetRenderer = ({
212
+ files
213
+ }) => {
214
+ const [activeIndex, setActiveIndex] = useState(0);
215
+ const [htmlMap, setHtmlMap] = useState({});
216
+ const activeFile = files[activeIndex] ?? files[0];
217
+ const isMultiFile = files.length > 1;
218
+ useEffect(() => {
219
+ let cancelled = false;
220
+ (async () => {
221
+ const newHtmlMap = {};
222
+ for (const file of files) {
223
+ const lang = normalizeLanguage(
224
+ file.language ?? getLanguageFromFilename(file.filename)
225
+ );
226
+ const highlighter = await getHighlighterWithLang(lang);
227
+ if (cancelled) return;
228
+ const loaded = highlighter.getLoadedLanguages();
229
+ const resolvedLang = loaded.includes(lang) ? lang : "text";
230
+ newHtmlMap[file.filename] = highlighter.codeToHtml(file.code, {
231
+ lang: resolvedLang,
232
+ themes: SHIKI_DUAL_THEMES
233
+ });
234
+ }
235
+ if (!cancelled) setHtmlMap(newHtmlMap);
236
+ })();
237
+ return () => {
238
+ cancelled = true;
239
+ };
240
+ }, [files]);
241
+ if (!activeFile) return null;
242
+ return /* @__PURE__ */ jsxs(
243
+ "div",
244
+ {
245
+ className: `${container} ${semanticClassNames.container}`,
246
+ role: "region",
247
+ "aria-label": "Code snippet",
248
+ children: [
249
+ /* @__PURE__ */ jsxs("div", { className: `${header} ${semanticClassNames.header}`, children: [
250
+ isMultiFile ? /* @__PURE__ */ jsx(
251
+ "div",
252
+ {
253
+ className: `${tabs} ${semanticClassNames.tabs}`,
254
+ role: "tablist",
255
+ "aria-label": "Code file tabs",
256
+ children: files.map((file, index) => /* @__PURE__ */ jsxs(
257
+ "button",
258
+ {
259
+ type: "button",
260
+ role: "tab",
261
+ "aria-selected": index === activeIndex,
262
+ onClick: () => setActiveIndex(index),
263
+ className: `${tab({ active: index === activeIndex })} ${semanticClassNames.tab} ${index === activeIndex ? semanticClassNames.tabActive : ""}`.trim(),
264
+ children: [
265
+ /* @__PURE__ */ jsx(
266
+ FileIcon,
267
+ {
268
+ filename: file.filename,
269
+ size: 14,
270
+ className: `${fileIcon} ${semanticClassNames.fileIcon}`
271
+ }
272
+ ),
273
+ /* @__PURE__ */ jsx("span", { children: file.filename })
274
+ ]
275
+ },
276
+ file.filename
277
+ ))
278
+ }
279
+ ) : /* @__PURE__ */ jsxs(
280
+ "div",
281
+ {
282
+ className: `${titleBar} ${semanticClassNames.titleBar}`,
283
+ children: [
284
+ /* @__PURE__ */ jsx(
285
+ FileIcon,
286
+ {
287
+ filename: activeFile.filename,
288
+ size: 14,
289
+ className: `${fileIcon} ${semanticClassNames.fileIcon}`
290
+ }
291
+ ),
292
+ /* @__PURE__ */ jsx("span", { children: activeFile.filename })
293
+ ]
294
+ }
295
+ ),
296
+ /* @__PURE__ */ jsx(
297
+ "div",
298
+ {
299
+ className: `${headerActions} ${semanticClassNames.headerActions}`,
300
+ children: /* @__PURE__ */ jsx(CopyButton, { text: activeFile.code })
301
+ }
302
+ )
303
+ ] }),
304
+ /* @__PURE__ */ jsx(
305
+ "div",
306
+ {
307
+ className: `${separator} ${semanticClassNames.separator}`
308
+ }
309
+ ),
310
+ files.map((file, index) => {
311
+ const html = htmlMap[file.filename];
312
+ return /* @__PURE__ */ jsx(
313
+ "div",
314
+ {
315
+ role: isMultiFile ? "tabpanel" : void 0,
316
+ className: semanticClassNames.codePanel,
317
+ style: { display: index === activeIndex ? "block" : "none" },
318
+ children: /* @__PURE__ */ jsx(
319
+ "div",
320
+ {
321
+ className: `${codeScroll} ${semanticClassNames.codeScroll}`,
322
+ children: html ? /* @__PURE__ */ jsx(
323
+ "div",
324
+ {
325
+ className: `${codeBody} ${semanticClassNames.codeBody}`,
326
+ dangerouslySetInnerHTML: { __html: html }
327
+ }
328
+ ) : /* @__PURE__ */ jsx(
329
+ "pre",
330
+ {
331
+ className: `${codeBody} ${semanticClassNames.codeBody}`,
332
+ children: /* @__PURE__ */ jsx("code", { children: file.code.split("\n").map((line, i) => /* @__PURE__ */ jsx("span", { className: "line", children: line }, i)) })
333
+ }
334
+ )
335
+ }
336
+ )
337
+ },
338
+ file.filename
339
+ );
340
+ })
341
+ ]
342
+ }
343
+ );
344
+ };
345
+ class CodeSnippetNode extends DecoratorNode {
346
+ constructor(files, key) {
347
+ super(key);
348
+ __publicField(this, "__files");
349
+ this.__files = files;
350
+ }
351
+ static getType() {
352
+ return "code-snippet";
353
+ }
354
+ static clone(node) {
355
+ return new CodeSnippetNode(node.__files, node.__key);
356
+ }
357
+ createDOM(_config) {
358
+ const div = document.createElement("div");
359
+ div.className = "rich-code-snippet";
360
+ return div;
361
+ }
362
+ updateDOM() {
363
+ return false;
364
+ }
365
+ isInline() {
366
+ return false;
367
+ }
368
+ static importJSON(serializedNode) {
369
+ return $createCodeSnippetNode(serializedNode.files);
370
+ }
371
+ exportJSON() {
372
+ return {
373
+ ...super.exportJSON(),
374
+ type: "code-snippet",
375
+ files: this.__files,
376
+ version: 1
377
+ };
378
+ }
379
+ getFiles() {
380
+ return this.getLatest().__files;
381
+ }
382
+ setFiles(files) {
383
+ const writable = this.getWritable();
384
+ writable.__files = files;
385
+ }
386
+ decorate(_editor, _config) {
387
+ return createRendererDecoration("CodeSnippet", CodeSnippetRenderer, {
388
+ files: this.__files
389
+ });
390
+ }
391
+ }
392
+ function $createCodeSnippetNode(files) {
393
+ return new CodeSnippetNode(files);
394
+ }
395
+ function $isCodeSnippetNode(node) {
396
+ return node instanceof CodeSnippetNode;
397
+ }
398
+ export {
399
+ $isCodeSnippetNode as $,
400
+ editOverlay as A,
401
+ editLabel as B,
402
+ CodeSnippetRenderer as C,
403
+ CodeSnippetNode as D,
404
+ $createCodeSnippetNode as E,
405
+ modalTitlebar as a,
406
+ modalTitle as b,
407
+ modalIconButton as c,
408
+ modalBody as d,
409
+ modalSidebar as e,
410
+ sidebarHeader as f,
411
+ getLanguageFromFilename as g,
412
+ sidebarAddButton as h,
413
+ fileList as i,
414
+ dragOverlay as j,
415
+ fileIcon as k,
416
+ fileName as l,
417
+ modal as m,
418
+ fileItem as n,
419
+ modalEditor as o,
420
+ breadcrumb as p,
421
+ breadcrumbLeft as q,
422
+ breadcrumbName as r,
423
+ semanticClassNames as s,
424
+ breadcrumbLang as t,
425
+ editorContainer as u,
426
+ fileDragHandle as v,
427
+ renameInput as w,
428
+ fileDelete as x,
429
+ codeSnippetDialogPopup as y,
430
+ editContainer as z
431
+ };
package/dist/index.mjs CHANGED
@@ -1,11 +1,13 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { g as getLanguageFromFilename, m as modal, s as semanticClassNames, a as modalTitlebar, b as modalTitle, c as modalIconButton, d as modalBody, e as modalSidebar, f as sidebarHeader, h as sidebarAddButton, i as fileList, j as dragOverlay, k as fileIcon, l as fileName, n as fileItem, o as modalEditor, p as breadcrumb, q as breadcrumbLeft, r as breadcrumbName, t as breadcrumbLang, u as editorContainer, v as fileDragHandle, w as renameInput, x as fileDelete, y as codeSnippetDialogPopup, z as editContainer, C as CodeSnippetRenderer, A as editOverlay, B as editLabel, $ as $isCodeSnippetNode, D as CodeSnippetNode } from "./CodeSnippetNode-BQ5spMAM.js";
5
+ import { E } from "./CodeSnippetNode-BQ5spMAM.js";
4
6
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
5
- import { useColorScheme, createRendererDecoration } from "@haklex/rich-editor";
7
+ import { useColorScheme } from "@haklex/rich-editor";
6
8
  import { presentDialog } from "@haklex/rich-editor-ui";
7
9
  import { usePortalTheme } from "@haklex/rich-style-token";
8
- import { X, Plus, GripVertical, Trash2, Check, Copy, Pencil, FileCode } from "lucide-react";
10
+ import { X, Plus, GripVertical, Trash2, Pencil, FileCode } from "lucide-react";
9
11
  import { useState, useRef, useEffect, useCallback, useMemo, useContext, createContext, createElement } from "react";
10
12
  import { history, defaultKeymap, historyKeymap, indentWithTab } from "@codemirror/commands";
11
13
  import { Compartment, EditorState } from "@codemirror/state";
@@ -17,188 +19,8 @@ import { getThemeExtensions, loadLanguageExtension } from "@haklex/cm-editor";
17
19
  import { normalizeLanguage } from "@haklex/rich-renderer-codeblock/constants";
18
20
  import { FileIcon } from "@haklex/rich-renderer-codeblock/icons";
19
21
  import { createPortal } from "react-dom";
20
- import { getHighlighterWithLang, SHIKI_DUAL_THEMES } from "@haklex/rich-renderer-codeblock/shiki";
21
- import { DecoratorNode, $getNodeByKey, $insertNodes } from "lexical";
22
+ import { $getNodeByKey, $insertNodes } from "lexical";
22
23
  import { CODE_SNIPPET_BLOCK_TRANSFORMER } from "@haklex/rich-headless/transformers";
23
- function toPrimitive(t, r2) {
24
- if ("object" != typeof t || !t) return t;
25
- var e = t[Symbol.toPrimitive];
26
- if (void 0 !== e) {
27
- var i = e.call(t, r2);
28
- if ("object" != typeof i) return i;
29
- throw new TypeError("@@toPrimitive must return a primitive value.");
30
- }
31
- return ("string" === r2 ? String : Number)(t);
32
- }
33
- function toPropertyKey(t) {
34
- var i = toPrimitive(t, "string");
35
- return "symbol" == typeof i ? i : String(i);
36
- }
37
- function _defineProperty(obj, key, value) {
38
- key = toPropertyKey(key);
39
- if (key in obj) {
40
- Object.defineProperty(obj, key, {
41
- value,
42
- enumerable: true,
43
- configurable: true,
44
- writable: true
45
- });
46
- } else {
47
- obj[key] = value;
48
- }
49
- return obj;
50
- }
51
- function ownKeys(e, r2) {
52
- var t = Object.keys(e);
53
- if (Object.getOwnPropertySymbols) {
54
- var o2 = Object.getOwnPropertySymbols(e);
55
- r2 && (o2 = o2.filter(function(r3) {
56
- return Object.getOwnPropertyDescriptor(e, r3).enumerable;
57
- })), t.push.apply(t, o2);
58
- }
59
- return t;
60
- }
61
- function _objectSpread2(e) {
62
- for (var r2 = 1; r2 < arguments.length; r2++) {
63
- var t = null != arguments[r2] ? arguments[r2] : {};
64
- r2 % 2 ? ownKeys(Object(t), true).forEach(function(r3) {
65
- _defineProperty(e, r3, t[r3]);
66
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r3) {
67
- Object.defineProperty(e, r3, Object.getOwnPropertyDescriptor(t, r3));
68
- });
69
- }
70
- return e;
71
- }
72
- function mapValues(input, fn) {
73
- var result = {};
74
- for (var _key in input) {
75
- result[_key] = fn(input[_key], _key);
76
- }
77
- return result;
78
- }
79
- var shouldApplyCompound = (compoundCheck, selections, defaultVariants) => {
80
- for (var key of Object.keys(compoundCheck)) {
81
- var _selections$key;
82
- if (compoundCheck[key] !== ((_selections$key = selections[key]) !== null && _selections$key !== void 0 ? _selections$key : defaultVariants[key])) {
83
- return false;
84
- }
85
- }
86
- return true;
87
- };
88
- var createRuntimeFn = (config) => {
89
- var runtimeFn = (options) => {
90
- var className = config.defaultClassName;
91
- var selections = _objectSpread2(_objectSpread2({}, config.defaultVariants), options);
92
- for (var variantName in selections) {
93
- var _selections$variantNa;
94
- var variantSelection = (_selections$variantNa = selections[variantName]) !== null && _selections$variantNa !== void 0 ? _selections$variantNa : config.defaultVariants[variantName];
95
- if (variantSelection != null) {
96
- var selection = variantSelection;
97
- if (typeof selection === "boolean") {
98
- selection = selection === true ? "true" : "false";
99
- }
100
- var selectionClassName = (
101
- // @ts-expect-error
102
- config.variantClassNames[variantName][selection]
103
- );
104
- if (selectionClassName) {
105
- className += " " + selectionClassName;
106
- }
107
- }
108
- }
109
- for (var [compoundCheck, compoundClassName] of config.compoundVariants) {
110
- if (shouldApplyCompound(compoundCheck, selections, config.defaultVariants)) {
111
- className += " " + compoundClassName;
112
- }
113
- }
114
- return className;
115
- };
116
- runtimeFn.variants = () => Object.keys(config.variantClassNames);
117
- runtimeFn.classNames = {
118
- get base() {
119
- return config.defaultClassName.split(" ")[0];
120
- },
121
- get variants() {
122
- return mapValues(config.variantClassNames, (classNames) => mapValues(classNames, (className) => className.split(" ")[0]));
123
- }
124
- };
125
- return runtimeFn;
126
- };
127
- var semanticClassNames = { container: "rcs-container", header: "rcs-header", tabs: "rcs-tabs", tab: "rcs-tab", tabActive: "rcs-tab-active", titleBar: "rcs-title-bar", headerActions: "rcs-header-actions", copyButton: "rcs-copy-btn", separator: "rcs-separator", codePanel: "rcs-code-panel", codeScroll: "rcs-code-scroll", codeBody: "rcs-code-body", fileIcon: "rcs-file-icon", editContainer: "rcs-edit-container", editOverlay: "rcs-edit-overlay", editLabel: "rcs-edit-label", modal: "rcs-modal", modalTitlebar: "rcs-modal-titlebar", modalTitle: "rcs-modal-title", modalIconButton: "rcs-modal-icon-btn", modalBody: "rcs-modal-body", modalSidebar: "rcs-modal-sidebar", sidebarHeader: "rcs-sidebar-header", sidebarAddButton: "rcs-sidebar-add-btn", fileList: "rcs-file-list", fileItem: "rcs-file-item", fileItemActive: "rcs-file-item-active", fileItemDragging: "rcs-file-item-dragging", fileDragHandle: "rcs-file-drag-handle", fileName: "rcs-file-name", fileDelete: "rcs-file-delete", renameInput: "rcs-rename-input", modalEditor: "rcs-modal-editor", breadcrumb: "rcs-breadcrumb", breadcrumbLeft: "rcs-breadcrumb-left", breadcrumbName: "rcs-breadcrumb-name", breadcrumbLang: "rcs-breadcrumb-lang", editorContainer: "rcs-editor-container", dragOverlay: "rcs-drag-overlay" };
128
- var container = "hjkryc0";
129
- var header = "hjkryc1";
130
- var tabs = "hjkryc2";
131
- var tab = createRuntimeFn({ defaultClassName: "hjkryc4 hjkryc3", variantClassNames: { active: { true: "hjkryc5", false: "hjkryc6" } }, defaultVariants: { active: false }, compoundVariants: [] });
132
- var titleBar = "hjkryc7";
133
- var headerActions = "hjkryc8";
134
- var copyButton = "hjkryc9";
135
- var separator = "hjkryca";
136
- var codeScroll = "hjkrycb";
137
- var codeBody = "hjkrycc";
138
- var fileIcon = "hjkrycd";
139
- var editContainer = "hjkryce";
140
- var editOverlay = "hjkrycf";
141
- var editLabel = "hjkrycg";
142
- var codeSnippetDialogPopup = "hjkrych";
143
- var modal = "hjkryci";
144
- var modalTitlebar = "hjkrycj";
145
- var modalTitle = "hjkryck";
146
- var modalIconButton = "hjkrycl";
147
- var modalBody = "hjkrycm";
148
- var modalSidebar = "hjkrycn";
149
- var sidebarHeader = "hjkryco";
150
- var sidebarAddButton = "hjkrycp";
151
- var fileList = "hjkrycq";
152
- var fileItem = createRuntimeFn({ defaultClassName: "hjkrycs hjkrycr", variantClassNames: { active: { true: "hjkryct", false: "hjkrycu" }, dragging: { true: "hjkrycv", false: "hjkrycw" } }, defaultVariants: { active: false, dragging: false }, compoundVariants: [] });
153
- var fileDragHandle = "hjkrycx";
154
- var fileName = "hjkrycy";
155
- var fileDelete = "hjkrycz";
156
- var renameInput = "hjkryc10";
157
- var modalEditor = "hjkryc11";
158
- var breadcrumb = "hjkryc12";
159
- var breadcrumbLeft = "hjkryc13";
160
- var breadcrumbName = "hjkryc14";
161
- var breadcrumbLang = "hjkryc15";
162
- var editorContainer = "hjkryc16";
163
- var dragOverlay = "hjkryc17";
164
- const EXT_TO_LANG = {
165
- ts: "typescript",
166
- tsx: "tsx",
167
- js: "javascript",
168
- jsx: "jsx",
169
- py: "python",
170
- rs: "rust",
171
- go: "go",
172
- java: "java",
173
- html: "html",
174
- css: "css",
175
- scss: "scss",
176
- json: "json",
177
- md: "markdown",
178
- sh: "bash",
179
- yml: "yaml",
180
- yaml: "yaml",
181
- sql: "sql",
182
- c: "c",
183
- cpp: "cpp",
184
- swift: "swift",
185
- kt: "kotlin",
186
- rb: "ruby",
187
- php: "php",
188
- vue: "vue",
189
- svelte: "svelte",
190
- toml: "toml",
191
- xml: "xml",
192
- graphql: "graphql",
193
- gql: "graphql",
194
- dockerfile: "dockerfile",
195
- lua: "lua",
196
- zig: "zig"
197
- };
198
- function getLanguageFromFilename(filename) {
199
- const ext = filename.split(".").pop()?.toLowerCase() ?? "";
200
- return EXT_TO_LANG[ext] ?? "text";
201
- }
202
24
  const SortableFileItem = ({
203
25
  file,
204
26
  isActive,
@@ -322,8 +144,8 @@ const CodeEditorModal = ({
322
144
  );
323
145
  };
324
146
  useEffect(() => {
325
- const container2 = containerRef.current;
326
- if (!container2) return;
147
+ const container = containerRef.current;
148
+ if (!container) return;
327
149
  const file = editFilesRef.current.find((f) => f.filename === activeFilename);
328
150
  if (!file) return;
329
151
  let cancelled = false;
@@ -331,7 +153,7 @@ const CodeEditorModal = ({
331
153
  file.language ?? getLanguageFromFilename(file.filename)
332
154
  );
333
155
  const editor = new EditorView({
334
- parent: container2,
156
+ parent: container,
335
157
  state: EditorState.create({
336
158
  doc: file.code,
337
159
  extensions: [
@@ -623,160 +445,6 @@ const CodeEditorModal = ({
623
445
  )
624
446
  ] });
625
447
  };
626
- const CopyButton = ({ text }) => {
627
- const [copied, setCopied] = useState(false);
628
- const timerRef = useRef(void 0);
629
- const handleCopy = useCallback(() => {
630
- navigator.clipboard.writeText(text);
631
- setCopied(true);
632
- clearTimeout(timerRef.current);
633
- timerRef.current = setTimeout(() => setCopied(false), 2e3);
634
- }, [text]);
635
- return /* @__PURE__ */ jsx(
636
- "button",
637
- {
638
- type: "button",
639
- className: `${copyButton} ${semanticClassNames.copyButton}`,
640
- onClick: handleCopy,
641
- "aria-label": copied ? "Copied" : "Copy code",
642
- children: copied ? /* @__PURE__ */ jsx(Check, { size: 14 }) : /* @__PURE__ */ jsx(Copy, { size: 14 })
643
- }
644
- );
645
- };
646
- const CodeSnippetRenderer = ({
647
- files
648
- }) => {
649
- const [activeIndex, setActiveIndex] = useState(0);
650
- const [htmlMap, setHtmlMap] = useState({});
651
- const activeFile = files[activeIndex] ?? files[0];
652
- const isMultiFile = files.length > 1;
653
- useEffect(() => {
654
- let cancelled = false;
655
- (async () => {
656
- const newHtmlMap = {};
657
- for (const file of files) {
658
- const lang = normalizeLanguage(
659
- file.language ?? getLanguageFromFilename(file.filename)
660
- );
661
- const highlighter = await getHighlighterWithLang(lang);
662
- if (cancelled) return;
663
- const loaded = highlighter.getLoadedLanguages();
664
- const resolvedLang = loaded.includes(lang) ? lang : "text";
665
- newHtmlMap[file.filename] = highlighter.codeToHtml(file.code, {
666
- lang: resolvedLang,
667
- themes: SHIKI_DUAL_THEMES
668
- });
669
- }
670
- if (!cancelled) setHtmlMap(newHtmlMap);
671
- })();
672
- return () => {
673
- cancelled = true;
674
- };
675
- }, [files]);
676
- if (!activeFile) return null;
677
- return /* @__PURE__ */ jsxs(
678
- "div",
679
- {
680
- className: `${container} ${semanticClassNames.container}`,
681
- role: "region",
682
- "aria-label": "Code snippet",
683
- children: [
684
- /* @__PURE__ */ jsxs("div", { className: `${header} ${semanticClassNames.header}`, children: [
685
- isMultiFile ? /* @__PURE__ */ jsx(
686
- "div",
687
- {
688
- className: `${tabs} ${semanticClassNames.tabs}`,
689
- role: "tablist",
690
- "aria-label": "Code file tabs",
691
- children: files.map((file, index) => /* @__PURE__ */ jsxs(
692
- "button",
693
- {
694
- type: "button",
695
- role: "tab",
696
- "aria-selected": index === activeIndex,
697
- onClick: () => setActiveIndex(index),
698
- className: `${tab({ active: index === activeIndex })} ${semanticClassNames.tab} ${index === activeIndex ? semanticClassNames.tabActive : ""}`.trim(),
699
- children: [
700
- /* @__PURE__ */ jsx(
701
- FileIcon,
702
- {
703
- filename: file.filename,
704
- size: 14,
705
- className: `${fileIcon} ${semanticClassNames.fileIcon}`
706
- }
707
- ),
708
- /* @__PURE__ */ jsx("span", { children: file.filename })
709
- ]
710
- },
711
- file.filename
712
- ))
713
- }
714
- ) : /* @__PURE__ */ jsxs(
715
- "div",
716
- {
717
- className: `${titleBar} ${semanticClassNames.titleBar}`,
718
- children: [
719
- /* @__PURE__ */ jsx(
720
- FileIcon,
721
- {
722
- filename: activeFile.filename,
723
- size: 14,
724
- className: `${fileIcon} ${semanticClassNames.fileIcon}`
725
- }
726
- ),
727
- /* @__PURE__ */ jsx("span", { children: activeFile.filename })
728
- ]
729
- }
730
- ),
731
- /* @__PURE__ */ jsx(
732
- "div",
733
- {
734
- className: `${headerActions} ${semanticClassNames.headerActions}`,
735
- children: /* @__PURE__ */ jsx(CopyButton, { text: activeFile.code })
736
- }
737
- )
738
- ] }),
739
- /* @__PURE__ */ jsx(
740
- "div",
741
- {
742
- className: `${separator} ${semanticClassNames.separator}`
743
- }
744
- ),
745
- files.map((file, index) => {
746
- const html = htmlMap[file.filename];
747
- return /* @__PURE__ */ jsx(
748
- "div",
749
- {
750
- role: isMultiFile ? "tabpanel" : void 0,
751
- className: semanticClassNames.codePanel,
752
- style: { display: index === activeIndex ? "block" : "none" },
753
- children: /* @__PURE__ */ jsx(
754
- "div",
755
- {
756
- className: `${codeScroll} ${semanticClassNames.codeScroll}`,
757
- children: html ? /* @__PURE__ */ jsx(
758
- "div",
759
- {
760
- className: `${codeBody} ${semanticClassNames.codeBody}`,
761
- dangerouslySetInnerHTML: { __html: html }
762
- }
763
- ) : /* @__PURE__ */ jsx(
764
- "pre",
765
- {
766
- className: `${codeBody} ${semanticClassNames.codeBody}`,
767
- children: /* @__PURE__ */ jsx("code", { children: file.code.split("\n").map((line, i) => /* @__PURE__ */ jsx("span", { className: "line", children: line }, i)) })
768
- }
769
- )
770
- }
771
- )
772
- },
773
- file.filename
774
- );
775
- })
776
- ]
777
- }
778
- );
779
- };
780
448
  const CodeSnippetEditRenderer = ({
781
449
  files,
782
450
  onFilesChange
@@ -828,59 +496,6 @@ function o() {
828
496
  throw r2.search = t.toString(), Error(`Minified Lexical error #${n2}; visit ${r2.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`);
829
497
  })(8), n;
830
498
  }
831
- class CodeSnippetNode extends DecoratorNode {
832
- constructor(files, key) {
833
- super(key);
834
- __publicField(this, "__files");
835
- this.__files = files;
836
- }
837
- static getType() {
838
- return "code-snippet";
839
- }
840
- static clone(node) {
841
- return new CodeSnippetNode(node.__files, node.__key);
842
- }
843
- createDOM(_config) {
844
- const div = document.createElement("div");
845
- div.className = "rich-code-snippet";
846
- return div;
847
- }
848
- updateDOM() {
849
- return false;
850
- }
851
- isInline() {
852
- return false;
853
- }
854
- static importJSON(serializedNode) {
855
- return $createCodeSnippetNode(serializedNode.files);
856
- }
857
- exportJSON() {
858
- return {
859
- ...super.exportJSON(),
860
- type: "code-snippet",
861
- files: this.__files,
862
- version: 1
863
- };
864
- }
865
- getFiles() {
866
- return this.getLatest().__files;
867
- }
868
- setFiles(files) {
869
- const writable = this.getWritable();
870
- writable.__files = files;
871
- }
872
- decorate(_editor, _config) {
873
- return createRendererDecoration("CodeSnippet", CodeSnippetRenderer, {
874
- files: this.__files
875
- });
876
- }
877
- }
878
- function $createCodeSnippetNode(files) {
879
- return new CodeSnippetNode(files);
880
- }
881
- function $isCodeSnippetNode(node) {
882
- return node instanceof CodeSnippetNode;
883
- }
884
499
  const CodeSnippetEditDecorator = ({
885
500
  nodeKey,
886
501
  files
@@ -942,7 +557,7 @@ const codeSnippetNodes = [CodeSnippetNode];
942
557
  const codeSnippetEditNodes = [CodeSnippetEditNode];
943
558
  export {
944
559
  $createCodeSnippetEditNode,
945
- $createCodeSnippetNode,
560
+ E as $createCodeSnippetNode,
946
561
  $isCodeSnippetEditNode,
947
562
  $isCodeSnippetNode,
948
563
  CODE_SNIPPET_BLOCK_TRANSFORMER,
@@ -0,0 +1,12 @@
1
+ import { D as CodeSnippetNode } from "./CodeSnippetNode-BQ5spMAM.js";
2
+ import { E, $, C } from "./CodeSnippetNode-BQ5spMAM.js";
3
+ import { CODE_SNIPPET_BLOCK_TRANSFORMER } from "@haklex/rich-headless/transformers";
4
+ const codeSnippetNodes = [CodeSnippetNode];
5
+ export {
6
+ E as $createCodeSnippetNode,
7
+ $ as $isCodeSnippetNode,
8
+ CODE_SNIPPET_BLOCK_TRANSFORMER,
9
+ CodeSnippetNode,
10
+ C as CodeSnippetRenderer,
11
+ codeSnippetNodes
12
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haklex/rich-ext-code-snippet",
3
- "version": "0.0.40",
3
+ "version": "0.0.42",
4
4
  "description": "Multi-file code snippet extension",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -28,12 +28,12 @@
28
28
  "@dnd-kit/utilities": "^3.2.2",
29
29
  "lucide-react": "^0.574.0",
30
30
  "shiki": "^3.23.0",
31
- "@haklex/cm-editor": "0.0.40",
32
- "@haklex/rich-editor-ui": "0.0.40",
33
- "@haklex/rich-editor": "0.0.40",
34
- "@haklex/rich-renderer-codeblock": "0.0.40",
35
- "@haklex/rich-headless": "0.0.40",
36
- "@haklex/rich-style-token": "0.0.40"
31
+ "@haklex/cm-editor": "0.0.42",
32
+ "@haklex/rich-editor": "0.0.42",
33
+ "@haklex/rich-editor-ui": "0.0.42",
34
+ "@haklex/rich-renderer-codeblock": "0.0.42",
35
+ "@haklex/rich-style-token": "0.0.42",
36
+ "@haklex/rich-headless": "0.0.42"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@lexical/react": "^0.41.0",