@jbpark/live-editor 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,9 @@
1
1
  import { a as detectTypeScript, r as cn } from "./utils-BwEgY5pe.js";
2
- import { useCallback, useMemo, useRef } from "react";
2
+ import { useCallback, useMemo } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
- import { javascript } from "@codemirror/lang-javascript";
4
+ import CodeEditor from "@jbpark/ui-kit/CodeEditor";
5
5
  import { vscodeLight } from "@uiw/codemirror-theme-vscode";
6
- import CodeMirror from "@uiw/react-codemirror";
7
- import { EditorView } from "codemirror";
6
+ import "@uiw/react-codemirror";
8
7
  //#region src/components/editor/use-format-code.ts
9
8
  const loadPrettier = async () => {
10
9
  const [prettier, babel, estree, typescript] = await Promise.all([
@@ -55,69 +54,24 @@ const useFormatCode = ({ fragment, prettierOptions } = {}) => {
55
54
  };
56
55
  //#endregion
57
56
  //#region src/components/editor/core.tsx
58
- const Core = ({ value, theme, height, className, prettierOptions, fragment, raw, onChange, onSave: _onSave, onError, ...props }) => {
59
- const editorRef = useRef(null);
57
+ const Core = ({ value, theme, height, className, prettierOptions, fragment, raw, onChange, onSave, onError, ...props }) => {
60
58
  const formatCode = useFormatCode({
61
59
  fragment,
62
60
  prettierOptions
63
61
  });
64
- const onSave = useCallback(async (val) => {
65
- try {
66
- const currentView = editorRef.current?.view;
67
- if (!currentView) return;
68
- const currentLength = currentView.state.doc.length;
69
- const cursorPos = currentView.state.selection.main.head;
70
- const formattedCode = raw ? val : await formatCode(val);
71
- if (currentLength === currentView.state.doc.length) {
72
- const newCursorPos = Math.min(cursorPos, formattedCode.length);
73
- const transaction = currentView.state.update({
74
- changes: {
75
- from: 0,
76
- to: currentLength,
77
- insert: formattedCode
78
- },
79
- selection: { anchor: newCursorPos }
80
- });
81
- currentView.dispatch(transaction);
82
- onChange?.(formattedCode);
83
- _onSave?.(formattedCode);
84
- }
85
- onError?.(null);
86
- } catch (e) {
87
- onError?.(e instanceof Error ? e.message : String(e));
88
- }
89
- }, [
90
- raw,
91
- formatCode,
92
- onChange,
93
- _onSave,
94
- onError
95
- ]);
96
- const onKeyDown = useCallback((e) => {
97
- if ((e.metaKey || e.ctrlKey) && e.key === "s") {
98
- e.preventDefault();
99
- const currentValue = editorRef.current?.view?.state.doc.toString() || value;
100
- onSave(currentValue);
101
- }
102
- }, [onSave, value]);
103
- return /* @__PURE__ */ jsx("div", {
62
+ return /* @__PURE__ */ jsx(CodeEditor, {
63
+ value,
64
+ theme: theme ?? vscodeLight,
65
+ height: height || "100%",
104
66
  className: cn(className),
105
- onKeyDown,
106
- children: /* @__PURE__ */ jsx(CodeMirror, {
107
- ref: editorRef,
108
- theme: theme || vscodeLight,
109
- height: height || "100%",
110
- value,
111
- extensions: [javascript({
112
- jsx: true,
113
- typescript: true
114
- }), EditorView.lineWrapping],
115
- onChange,
116
- ...props
117
- })
67
+ formatCode: raw ? void 0 : formatCode,
68
+ onChange,
69
+ onSave,
70
+ onFormatError: onError,
71
+ ...props
118
72
  });
119
73
  };
120
74
  //#endregion
121
75
  export { useFormatCode as n, Core as t };
122
76
 
123
- //# sourceMappingURL=core-CbuS_p_d.js.map
77
+ //# sourceMappingURL=core-CTsQ9LiQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-CTsQ9LiQ.js","names":[],"sources":["../src/components/editor/use-format-code.ts","../src/components/editor/core.tsx"],"sourcesContent":["import { useCallback, useMemo } from 'react';\n\nimport { detectTypeScript } from '~/utils';\n\n// prettier is an optional peer dependency (#282): the editor subpath is the\n// only thing that needs it, so consumers who don't use format-on-save\n// shouldn't have to install ~9.6 MB. It's loaded lazily below and its absence\n// degrades gracefully (the code is returned unformatted) instead of throwing.\nconst loadPrettier = async () => {\n const [prettier, babel, estree, typescript] = await Promise.all([\n import('prettier'),\n import('prettier/plugins/babel'),\n import('prettier/plugins/estree'),\n import('prettier/plugins/typescript'),\n ]);\n\n return {\n format: prettier.format,\n plugins: [babel.default, estree.default, typescript.default],\n };\n};\n\nconst DEFAULT_PRETTIER_OPTIONS: Record<string, unknown> = {\n tabWidth: 2,\n singleQuote: true,\n trailingComma: 'all',\n htmlWhitespaceSensitivity: 'ignore',\n arrowParens: 'avoid',\n printWidth: 60,\n};\n\nexport interface UseFormatCodeOptions {\n fragment?: boolean;\n prettierOptions?: Record<string, unknown>;\n}\n\n// Extracted out of Core so a custom renderEditor (see editor.tsx's\n// renderEditor prop) can reuse the exact same formatting behavior instead\n// of reimplementing prettier wiring from scratch.\nexport const useFormatCode = ({\n fragment,\n prettierOptions,\n}: UseFormatCodeOptions = {}) => {\n const prettierConfig = useMemo(\n () => ({\n ...DEFAULT_PRETTIER_OPTIONS,\n ...prettierOptions,\n }),\n [prettierOptions],\n );\n\n return useCallback(\n async (code: string) => {\n const isTypeScript = detectTypeScript(code);\n const source = fragment ? `<>${code}</>` : code;\n\n // Only a missing prettier is swallowed here; a genuine format error\n // (prettier present, but the code is unparseable) still propagates so\n // the editor's Cmd+S path can surface it via onError.\n let prettier: Awaited<ReturnType<typeof loadPrettier>>;\n try {\n prettier = await loadPrettier();\n } catch {\n return code;\n }\n\n const formatted = await prettier.format(source, {\n parser: isTypeScript ? 'typescript' : 'babel',\n plugins: prettier.plugins,\n ...prettierConfig,\n });\n\n if (fragment) {\n return formatted\n .replace(/^<>\\n?/, '')\n .replace(/\\n?<\\/>;?\\s*$/, '')\n .replace(/^ {2}/gm, '')\n .trim();\n }\n\n return formatted;\n },\n [prettierConfig, fragment],\n );\n};\n","import CodeEditor from '@jbpark/ui-kit/CodeEditor';\nimport { vscodeLight } from '@uiw/codemirror-theme-vscode';\nimport { type Extension } from '@uiw/react-codemirror';\n\nimport { cn } from '~/utils';\n\nimport { useFormatCode } from './use-format-code';\n\nexport interface Props {\n value: string;\n height?: string;\n theme?: Extension | 'light' | 'dark' | 'none';\n prettierOptions?: Record<string, unknown>;\n fragment?: boolean;\n raw?: boolean;\n className?: string;\n onChange?: (value: string) => void;\n onSave?: (value: string) => void;\n onError?: (error: string | null) => void;\n}\n\n// The CodeMirror surface, the Cmd+S save transaction and the JS/TS + line-wrap\n// extensions now live in `@jbpark/ui-kit`'s CodeEditor (#346/#309). This stays\n// only to keep live-editor's own vocabulary: `raw`/`fragment`/`prettierOptions`\n// shape the injected prettier formatter, and `onError` maps to the component's\n// `onFormatError`.\nconst Core = ({\n value,\n theme,\n height,\n className,\n prettierOptions,\n fragment,\n raw,\n onChange,\n onSave,\n onError,\n ...props\n}: Props) => {\n const formatCode = useFormatCode({ fragment, prettierOptions });\n\n return (\n <CodeEditor\n value={value}\n theme={theme ?? vscodeLight}\n height={height || '100%'}\n className={cn(className)}\n // `raw` (e.g. innerHTML) skips prettier; otherwise reuse the shared\n // prettier wiring as the Cmd+S formatter rather than reimplementing it.\n formatCode={raw ? undefined : formatCode}\n onChange={onChange}\n onSave={onSave}\n onFormatError={onError}\n {...props}\n />\n );\n};\n\nexport default Core;\n"],"mappings":";;;;;;;AAQA,MAAM,eAAe,YAAY;CAC/B,MAAM,CAAC,UAAU,OAAO,QAAQ,cAAc,MAAM,QAAQ,IAAI;EAC9D,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;CACT,CAAC;CAED,OAAO;EACL,QAAQ,SAAS;EACjB,SAAS;GAAC,MAAM;GAAS,OAAO;GAAS,WAAW;EAAO;CAC7D;AACF;AAEA,MAAM,2BAAoD;CACxD,UAAU;CACV,aAAa;CACb,eAAe;CACf,2BAA2B;CAC3B,aAAa;CACb,YAAY;AACd;AAUA,MAAa,iBAAiB,EAC5B,UACA,oBACwB,CAAC,MAAM;CAC/B,MAAM,iBAAiB,eACd;EACL,GAAG;EACH,GAAG;CACL,IACA,CAAC,eAAe,CAClB;CAEA,OAAO,YACL,OAAO,SAAiB;EACtB,MAAM,eAAe,iBAAiB,IAAI;EAC1C,MAAM,SAAS,WAAW,KAAK,KAAK,OAAO;EAK3C,IAAI;EACJ,IAAI;GACF,WAAW,MAAM,aAAa;EAChC,QAAQ;GACN,OAAO;EACT;EAEA,MAAM,YAAY,MAAM,SAAS,OAAO,QAAQ;GAC9C,QAAQ,eAAe,eAAe;GACtC,SAAS,SAAS;GAClB,GAAG;EACL,CAAC;EAED,IAAI,UACF,OAAO,UACJ,QAAQ,UAAU,EAAE,CAAC,CACrB,QAAQ,iBAAiB,EAAE,CAAC,CAC5B,QAAQ,WAAW,EAAE,CAAC,CACtB,KAAK;EAGV,OAAO;CACT,GACA,CAAC,gBAAgB,QAAQ,CAC3B;AACF;;;AC1DA,MAAM,QAAQ,EACZ,OACA,OACA,QACA,WACA,iBACA,UACA,KACA,UACA,QACA,SACA,GAAG,YACQ;CACX,MAAM,aAAa,cAAc;EAAE;EAAU;CAAgB,CAAC;CAE9D,OACE,oBAAC,YAAD;EACS;EACP,OAAO,SAAS;EAChB,QAAQ,UAAU;EAClB,WAAW,GAAG,SAAS;EAGvB,YAAY,MAAM,KAAA,IAAY;EACpB;EACF;EACR,eAAe;EACf,GAAI;CACL,CAAA;AAEL"}
package/dist/dnd/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as Panel, c as ICON_OPTIONS, d as useDndPalette, f as useDndPanel, i as Palette, l as useItemsEditor, n as Canvas, o as Field, p as DraggableItem, r as Layout, s as ICON_MAP, t as Dnd, u as useDndLayout } from "../dnd-Bl_oqayG.js";
1
+ import { a as Panel, c as ICON_OPTIONS, d as useDndPalette, f as useDndPanel, i as Palette, l as useItemsEditor, n as Canvas, o as Field, p as DraggableItem, r as Layout, s as ICON_MAP, t as Dnd, u as useDndLayout } from "../dnd-C4iBiSkv.js";
2
2
  export { Canvas, DraggableItem, Field, ICON_MAP, ICON_OPTIONS, Layout, Palette, Panel, Dnd as default, useDndLayout, useDndPalette, useDndPanel, useItemsEditor };
@@ -1,9 +1,9 @@
1
1
  import { C as __toESM, b as DRAGGABLE_ITEMS, f as nanoid, g as BINDING_PROP, m as require_lib, n as createSectionPreviewCache, r as fillSectionIds, y as DEFAULT_TEMPLATE } from "./document-C6bNHl7l.js";
2
2
  import { d as replaceSections, o as extractSections, r as cn, s as generateSection, u as preloadScripts } from "./utils-BwEgY5pe.js";
3
3
  import { i as usePreview } from "./states-Ci1AvoQ9.js";
4
- import { A as parseValue, D as extractObjectProperties, E as extractNodeValue, M as generateCode, S as parseBinding, _ as moveSelectedIndices, a as extract, b as getCurrentValue, c as moveArrayItem, d as removeArrayItems, f as updateArrayItemProperty, g as replaceIds, h as fillIds, k as parseArrayExpression, l as moveArrayItems, o as appendArrayItem, p as updateArrayItemValue, r as update, s as duplicateArrayItems, t as validateBindingValue, v as removeIndices, x as getStructuredValue, y as findEditableChildren } from "./ast-DRg6HV4H.js";
4
+ import { A as parseValue, D as extractObjectProperties, E as extractNodeValue, M as generateCode, S as parseBinding, _ as moveSelectedIndices, a as extract, b as getCurrentValue, c as moveArrayItem, d as removeArrayItems, f as updateArrayItemProperty, g as replaceIds, h as fillIds, k as parseArrayExpression, l as moveArrayItems, o as appendArrayItem, p as updateArrayItemValue, r as update, s as duplicateArrayItems, t as validateBindingValue, v as removeIndices, x as getStructuredValue, y as findEditableChildren } from "./ast-D6R-dsk0.js";
5
5
  import { n as useCompiledModule, r as Frame, t as useDynamicTailwind } from "./use-dynamic-tailwind-C0Onss1A.js";
6
- import { t as Core } from "./core-CbuS_p_d.js";
6
+ import { t as Core } from "./core-CTsQ9LiQ.js";
7
7
  import { n as Error$1, t as ErrorBoundary } from "./boundary-BF7iZp6e.js";
8
8
  import { Children, createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
9
9
  import { Button, Card, Checkbox, ColorPicker, DatePicker, Drawer, Input, RichTextEditor, Select, Space, Splitter, Toast, Typography, Upload } from "@jbpark/ui-kit";
@@ -1725,4 +1725,4 @@ Dnd.Layout = Layout;
1725
1725
  //#endregion
1726
1726
  export { Panel as a, ICON_OPTIONS as c, useDndPalette as d, useDndPanel as f, Palette as i, useItemsEditor as l, Canvas as n, Field as o, DraggableItem as p, Layout as r, ICON_MAP as s, Dnd as t, useDndLayout as u };
1727
1727
 
1728
- //# sourceMappingURL=dnd-Bl_oqayG.js.map
1728
+ //# sourceMappingURL=dnd-C4iBiSkv.js.map