@iyulab/editor-components 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
4
+ - Initial library version release
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Iyulab, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # @iyulab/editor-components
2
+
3
+ 다양한 에디터 컴포넌트를 제공하는 라이브러리입니다.
4
+
5
+ ## 포함된 컴포넌트
6
+
7
+ ### CodeEditor
8
+ Monaco Editor를 기반으로 한 코드 에디터 컴포넌트입니다.
9
+
10
+ **특징:**
11
+ - 구문 강조 (JavaScript, TypeScript, JSON, CSS, HTML, Python 등)
12
+ - 자동완성 및 IntelliSense
13
+ - 에러 검사 및 린팅
14
+ - 다크/라이트 테마 지원
15
+ - 읽기 전용 모드
16
+ - 커스터마이징 가능한 폰트 크기
17
+
18
+ **사용법:**
19
+ ```html
20
+ <code-editor
21
+ label="My Code Editor"
22
+ language="javascript"
23
+ theme="light"
24
+ font-size="14"
25
+ value="console.log('Hello World!');"
26
+ read-only="false">
27
+ </code-editor>
28
+ ```
29
+
30
+ **Properties:**
31
+ - `noHeader`: 헤더 표시 여부 (boolean, default: false)
32
+ - `label`: 헤더 레이블 텍스트 (string, default: "Editor")
33
+ - `theme`: 테마 ("light" | "dark", default: "light")
34
+ - `readOnly`: 읽기 전용 모드 (boolean, default: false)
35
+ - `language`: 프로그래밍 언어 (string, default: "json")
36
+ - `fontSize`: 폰트 크기 (number, default: 14)
37
+ - `value`: 에디터 내용 (string, default: "")
38
+
39
+ ### RichTextEditor
40
+ Quill.js를 기반으로 한 리치 텍스트 에디터 컴포넌트입니다.
41
+
42
+ **특징:**
43
+ - WYSIWYG 편집 환경
44
+ - 다양한 텍스트 포맷팅 (굵게, 기울임, 밑줄 등)
45
+ - 목록, 헤더, 인용구 지원
46
+ - 링크 및 이미지 삽입
47
+ - 커스터마이징 가능한 툴바
48
+ - 다크/라이트 테마 지원
49
+ - HTML, 텍스트, Delta 형식 지원
50
+
51
+ **사용법:**
52
+ ```html
53
+ <rich-text-editor
54
+ label="My Rich Text Editor"
55
+ theme="light"
56
+ height="300"
57
+ placeholder="Start writing..."
58
+ value="<h2>Hello World!</h2><p>This is <strong>rich text</strong>.</p>"
59
+ read-only="false">
60
+ </rich-text-editor>
61
+ ```
62
+
63
+ **Properties:**
64
+ - `noHeader`: 헤더 표시 여부 (boolean, default: false)
65
+ - `label`: 헤더 레이블 텍스트 (string, default: "Rich Text Editor")
66
+ - `theme`: 테마 ("light" | "dark", default: "light")
67
+ - `readOnly`: 읽기 전용 모드 (boolean, default: false)
68
+ - `placeholder`: 플레이스홀더 텍스트 (string, default: "Start writing...")
69
+ - `value`: 에디터 HTML 내용 (string, default: "")
70
+ - `height`: 에디터 높이 (number, default: 300)
71
+ - `toolbar`: 커스텀 툴바 설정 (array, optional)
72
+
73
+ **Methods:**
74
+ - `getHTML()`: HTML 형식으로 내용 반환
75
+ - `getText()`: 플레인 텍스트로 내용 반환
76
+ - `getDelta()`: Quill Delta 형식으로 내용 반환
77
+ - `setHTML(html)`: HTML 형식으로 내용 설정
78
+ - `setDelta(delta)`: Delta 형식으로 내용 설정
79
+ - `clear()`: 모든 내용 삭제
80
+ - `focus()`: 에디터에 포커스
81
+
82
+ ## 설치
83
+
84
+ ```bash
85
+ npm install @iyulab/editor-components
86
+ ```
87
+
88
+ ## 사용법
89
+
90
+ ```javascript
91
+ import '@iyulab/editor-components';
92
+
93
+ // 또는 개별 컴포넌트만 import
94
+ import { CodeEditor, RichTextEditor } from '@iyulab/editor-components';
95
+ ```
96
+
97
+ ## 이벤트
98
+
99
+ ### CodeEditor
100
+ - `change`: 에디터 내용이 변경될 때 발생 (detail: string)
101
+
102
+ ### RichTextEditor
103
+ - `change`: 에디터 내용이 변경될 때 발생 (detail: { html, text, delta })
104
+ - `copy`: 복사 버튼 클릭 시 발생 (detail: string)
105
+
106
+ ## 데모
107
+
108
+ 프로젝트에 포함된 `demo.html` 파일을 통해 컴포넌트들을 실제로 테스트해볼 수 있습니다.
109
+
110
+ ```bash
111
+ npm run start
112
+ ```
113
+
114
+ ## 라이선스
115
+
116
+ MIT
@@ -0,0 +1,9 @@
1
+ //#region \0@oxc-project+runtime@0.130.0/helpers/decorate.js
2
+ function __decorate(decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ }
8
+ //#endregion
9
+ export { __decorate };
@@ -0,0 +1,6 @@
1
+ //#region \0@oxc-project+runtime@0.130.0/helpers/decorateMetadata.js
2
+ function __decorateMetadata(k, v) {
3
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4
+ }
5
+ //#endregion
6
+ export { __decorateMetadata };
@@ -0,0 +1,34 @@
1
+ import { UElement } from '@iyulab/components/dist/components/UElement.js';
2
+ /**
3
+ * code editor component used by monaco-editor
4
+ */
5
+ export declare class UCodeEditor extends UElement {
6
+ static styles: import('lit').CSSResultGroup[];
7
+ /** Specifies whether the header should be displayed or not. @default false */
8
+ headless: boolean;
9
+ /** The label text displayed in the header of the code editor. @default "Editor" */
10
+ label: string;
11
+ /** The visual theme of the code editor. Can be "light" or "dark". @default "light" */
12
+ theme: "light" | "dark";
13
+ /** Whether the editor should be in read-only mode, preventing user input. @default false */
14
+ readOnly: boolean;
15
+ /** The programming language for syntax highlighting (e.g., "json", "javascript", "typescript"). @default "json" */
16
+ language: string;
17
+ /** The font size in pixels for the text in the editor. @default 14 */
18
+ fontSize: number;
19
+ /** The current text content of the code editor. @default "" */
20
+ value: string;
21
+ private container;
22
+ private editor?;
23
+ private observer;
24
+ connectedCallback(): void;
25
+ disconnectedCallback(): void;
26
+ protected firstUpdated(changedProperties: any): Promise<void>;
27
+ protected updated(changedProperties: any): Promise<void>;
28
+ render(): import('lit-html').TemplateResult<1>;
29
+ }
30
+ declare global {
31
+ interface HTMLElementTagNameMap {
32
+ "u-code-editor": UCodeEditor;
33
+ }
34
+ }
@@ -0,0 +1,103 @@
1
+ import "./UCodeEditor.worker.js";
2
+ import { styles } from "./UCodeEditor.styles.js";
3
+ import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.130.0/helpers/decorateMetadata.js";
4
+ import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.130.0/helpers/decorate.js";
5
+ import { html, unsafeCSS } from "lit";
6
+ import { customElement, property } from "lit/decorators.js";
7
+ import { createRef, ref } from "lit/directives/ref.js";
8
+ import * as monaco from "monaco-editor";
9
+ import monacoStyles from "monaco-editor/min/vs/editor/editor.main.css?inline";
10
+ import { Theme } from "@iyulab/components/dist/utilities/Theme.js";
11
+ import { UElement } from "@iyulab/components/dist/components/UElement.js";
12
+ //#region src/components/code-editor/UCodeEditor.ts
13
+ var UCodeEditor = class UCodeEditor extends UElement {
14
+ constructor(..._args) {
15
+ super(..._args);
16
+ this.headless = false;
17
+ this.label = "Editor";
18
+ this.theme = "light";
19
+ this.readOnly = false;
20
+ this.language = "json";
21
+ this.fontSize = 14;
22
+ this.value = "";
23
+ this.container = createRef();
24
+ this.observer = new MutationObserver(() => {
25
+ const theme = Theme.get() === "dark" ? "dark" : "light";
26
+ if (this.theme !== theme) this.theme = theme;
27
+ });
28
+ }
29
+ static {
30
+ this.styles = [
31
+ super.styles,
32
+ unsafeCSS(monacoStyles),
33
+ styles
34
+ ];
35
+ }
36
+ connectedCallback() {
37
+ super.connectedCallback();
38
+ this.theme = Theme.get() === "dark" ? "dark" : "light";
39
+ this.observer.observe(document.documentElement, {
40
+ attributes: true,
41
+ attributeFilter: ["data-theme"]
42
+ });
43
+ }
44
+ disconnectedCallback() {
45
+ this.observer.disconnect();
46
+ super.disconnectedCallback();
47
+ }
48
+ async firstUpdated(changedProperties) {
49
+ super.firstUpdated(changedProperties);
50
+ await this.updateComplete;
51
+ this.editor = monaco.editor.create(this.container.value, {
52
+ language: this.language,
53
+ theme: this.theme === "light" ? "vs-light" : "vs-dark",
54
+ fontSize: this.fontSize,
55
+ automaticLayout: true,
56
+ minimap: { enabled: false },
57
+ lineNumbersMinChars: 2,
58
+ lineDecorationsWidth: 1,
59
+ readOnly: this.readOnly,
60
+ value: this.value,
61
+ scrollBeyondLastLine: false,
62
+ scrollbar: { alwaysConsumeMouseWheel: false }
63
+ });
64
+ this.editor.onDidChangeModelContent(() => {
65
+ this.value = this.editor.getValue();
66
+ this.dispatchEvent(new Event("change", {
67
+ bubbles: true,
68
+ composed: true
69
+ }));
70
+ });
71
+ }
72
+ async updated(changedProperties) {
73
+ super.updated(changedProperties);
74
+ if (changedProperties.has("value") && this.value !== this.editor?.getValue() && !this.editor?.hasWidgetFocus()) this.editor?.setValue(this.value);
75
+ if (changedProperties.has("theme") && this.editor) this.editor.updateOptions({ theme: this.theme === "light" ? "vs-light" : "vs-dark" });
76
+ if (changedProperties.has("language") && this.editor) monaco.editor.setModelLanguage(this.editor.getModel(), this.language);
77
+ }
78
+ render() {
79
+ return html`
80
+ <div class="header" ?hidden=${this.headless}>
81
+ <div class="title">${this.label}</div>
82
+ <div class="flex"></div>
83
+ <slot name="header-actions"></slot>
84
+ </div>
85
+ <div class="editor">
86
+ <main ${ref(this.container)}></main>
87
+ </div>
88
+ `;
89
+ }
90
+ };
91
+ __decorate([property({
92
+ type: Boolean,
93
+ reflect: true
94
+ }), __decorateMetadata("design:type", Boolean)], UCodeEditor.prototype, "headless", void 0);
95
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UCodeEditor.prototype, "label", void 0);
96
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UCodeEditor.prototype, "theme", void 0);
97
+ __decorate([property({ type: Boolean }), __decorateMetadata("design:type", Boolean)], UCodeEditor.prototype, "readOnly", void 0);
98
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UCodeEditor.prototype, "language", void 0);
99
+ __decorate([property({ type: Number }), __decorateMetadata("design:type", Number)], UCodeEditor.prototype, "fontSize", void 0);
100
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UCodeEditor.prototype, "value", void 0);
101
+ UCodeEditor = __decorate([customElement("u-code-editor")], UCodeEditor);
102
+ //#endregion
103
+ export { UCodeEditor };
@@ -0,0 +1 @@
1
+ export declare const styles: import('lit').CSSResult;
@@ -0,0 +1,53 @@
1
+ import { css } from "lit";
2
+ //#region src/components/code-editor/UCodeEditor.styles.ts
3
+ var styles = css`
4
+ :host {
5
+ position: relative;
6
+ display: block;
7
+ width: 100%;
8
+ height: 100%;
9
+ overflow: hidden;
10
+ --header-height: 32px;
11
+ }
12
+ :host([headless]) {
13
+ --header-height: 0px;
14
+ }
15
+
16
+ .header {
17
+ position: relative;
18
+ display: flex;
19
+ flex-direction: row;
20
+ align-items: center;
21
+ justify-content: space-between;
22
+ height: 24px;
23
+ gap: 4px;
24
+ padding: 4px;
25
+
26
+ .title {
27
+ font-size: 16px;
28
+ line-height: 20px;
29
+ font-weight: 600;
30
+ overflow: hidden;
31
+ text-overflow: ellipsis;
32
+ white-space: nowrap;
33
+ }
34
+
35
+ .flex {
36
+ flex: 1;
37
+ }
38
+ }
39
+
40
+ .editor {
41
+ position: absolute;
42
+ width: 100%;
43
+ height: calc(100% - var(--header-height));
44
+ overflow: hidden;
45
+
46
+ main {
47
+ width: 100%;
48
+ height: 100%;
49
+ }
50
+ }
51
+ `;
52
+ //#endregion
53
+ export { styles };
@@ -0,0 +1,14 @@
1
+ import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
2
+ import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
3
+ import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
4
+ import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
5
+ import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
6
+ //#region src/components/code-editor/UCodeEditor.worker.ts
7
+ self.MonacoEnvironment = { getWorker(_moduleId, label) {
8
+ if (label === "json") return new jsonWorker();
9
+ if (label === "css" || label === "scss" || label === "less") return new cssWorker();
10
+ if (label === "html" || label === "handlebars" || label === "razor") return new htmlWorker();
11
+ if (label === "typescript" || label === "javascript") return new tsWorker();
12
+ return new editorWorker();
13
+ } };
14
+ //#endregion
@@ -0,0 +1,62 @@
1
+ import { UElement } from '@iyulab/components/dist/components/UElement.js';
2
+ export declare class UTextEditor extends UElement {
3
+ static styles: import('lit').CSSResultGroup[];
4
+ /** Specifies whether the header should be displayed or not. @default false */
5
+ headless: boolean;
6
+ /** The label text displayed in the header of the rich text editor. @default "Rich Text Editor" */
7
+ label: string;
8
+ /** The visual theme of the editor. Can be "light" or "dark". @default "light" */
9
+ theme?: "light" | "dark" | "system";
10
+ /** Whether the editor should be in read-only mode, preventing user input. @default false */
11
+ readOnly: boolean;
12
+ /** The placeholder text shown when the editor is empty. @default "Start writing..." */
13
+ placeholder: string;
14
+ /** The current HTML content of the rich text editor. @default "" */
15
+ value: string;
16
+ /** The height of the editor in pixels. @default 300 */
17
+ height: number;
18
+ /** Custom toolbar configuration. If not provided, uses default toolbar. */
19
+ toolbar?: string[][];
20
+ private container;
21
+ private quill;
22
+ private observer;
23
+ connectedCallback(): void;
24
+ disconnectedCallback(): void;
25
+ protected firstUpdated(changedProperties: any): Promise<void>;
26
+ protected updated(changedProperties: any): Promise<void>;
27
+ render(): import('lit-html').TemplateResult<1>;
28
+ private updateEditorHeight;
29
+ /**
30
+ * Get the current content as HTML
31
+ */
32
+ getHTML(): string;
33
+ /**
34
+ * Get the current content as plain text
35
+ */
36
+ getText(): string;
37
+ /**
38
+ * Get the current content as Quill Delta
39
+ */
40
+ getDelta(): any;
41
+ /**
42
+ * Set content from HTML
43
+ */
44
+ setHTML(html: string): void;
45
+ /**
46
+ * Set content from Quill Delta
47
+ */
48
+ setDelta(delta: any): void;
49
+ /**
50
+ * Clear all content
51
+ */
52
+ clear(): void;
53
+ /**
54
+ * Focus the editor
55
+ */
56
+ focus(): void;
57
+ }
58
+ declare global {
59
+ interface HTMLElementTagNameMap {
60
+ "u-text-editor": UTextEditor;
61
+ }
62
+ }
@@ -0,0 +1,186 @@
1
+ import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.130.0/helpers/decorateMetadata.js";
2
+ import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.130.0/helpers/decorate.js";
3
+ import { styles } from "./UTextEditor.styles.js";
4
+ import { html, unsafeCSS } from "lit";
5
+ import { customElement, property } from "lit/decorators.js";
6
+ import { createRef, ref } from "lit/directives/ref.js";
7
+ import { Theme } from "@iyulab/components/dist/utilities/Theme.js";
8
+ import { UElement } from "@iyulab/components/dist/components/UElement.js";
9
+ import Quill from "quill";
10
+ import quillStyles from "quill/dist/quill.snow.css?inline";
11
+ //#region src/components/text-editor/UTextEditor.ts
12
+ var UTextEditor = class UTextEditor extends UElement {
13
+ constructor(..._args) {
14
+ super(..._args);
15
+ this.headless = false;
16
+ this.label = "Rich Text Editor";
17
+ this.theme = "light";
18
+ this.readOnly = false;
19
+ this.placeholder = "Start writing...";
20
+ this.value = "";
21
+ this.height = 300;
22
+ this.container = createRef();
23
+ this.observer = new MutationObserver(() => {
24
+ const theme = Theme.get();
25
+ if (this.theme !== theme) this.theme = theme;
26
+ });
27
+ }
28
+ static {
29
+ this.styles = [
30
+ super.styles,
31
+ unsafeCSS(quillStyles),
32
+ styles
33
+ ];
34
+ }
35
+ connectedCallback() {
36
+ super.connectedCallback();
37
+ this.theme = Theme.get();
38
+ this.observer.observe(document.documentElement, {
39
+ attributes: true,
40
+ attributeFilter: ["data-theme"]
41
+ });
42
+ }
43
+ disconnectedCallback() {
44
+ if (this.quill) this.quill = null;
45
+ this.observer.disconnect();
46
+ super.disconnectedCallback();
47
+ }
48
+ async firstUpdated(changedProperties) {
49
+ super.firstUpdated(changedProperties);
50
+ await this.updateComplete;
51
+ const defaultToolbar = [
52
+ [
53
+ "bold",
54
+ "italic",
55
+ "underline",
56
+ "strike"
57
+ ],
58
+ ["blockquote", "code-block"],
59
+ [{ "header": 1 }, { "header": 2 }],
60
+ [{ "list": "ordered" }, { "list": "bullet" }],
61
+ [{ "script": "sub" }, { "script": "super" }],
62
+ [{ "indent": "-1" }, { "indent": "+1" }],
63
+ [{ "direction": "rtl" }],
64
+ [{ "size": [
65
+ "small",
66
+ false,
67
+ "large",
68
+ "huge"
69
+ ] }],
70
+ [{ "header": [
71
+ 1,
72
+ 2,
73
+ 3,
74
+ 4,
75
+ 5,
76
+ 6,
77
+ false
78
+ ] }],
79
+ [{ "color": [] }, { "background": [] }],
80
+ [{ "font": [] }],
81
+ [{ "align": [] }],
82
+ ["clean"],
83
+ ["link", "image"]
84
+ ];
85
+ this.quill = new Quill(this.container.value, {
86
+ theme: "snow",
87
+ readOnly: this.readOnly,
88
+ placeholder: this.placeholder,
89
+ modules: { toolbar: this.toolbar || defaultToolbar }
90
+ });
91
+ if (this.value) this.quill.root.innerHTML = this.value;
92
+ this.quill.on("text-change", () => {
93
+ const html = this.quill.root.innerHTML;
94
+ this.dispatchEvent(new CustomEvent("change", { detail: {
95
+ html,
96
+ text: this.quill.getText(),
97
+ delta: this.quill.getContents()
98
+ } }));
99
+ });
100
+ this.updateEditorHeight();
101
+ }
102
+ async updated(changedProperties) {
103
+ super.updated(changedProperties);
104
+ await this.updateComplete;
105
+ if (this.quill) {
106
+ if (changedProperties.has("value") && this.value !== this.quill.root.innerHTML) this.quill.root.innerHTML = this.value;
107
+ if (changedProperties.has("readOnly")) this.quill.enable(!this.readOnly);
108
+ if (changedProperties.has("placeholder")) this.quill.root.dataset.placeholder = this.placeholder;
109
+ if (changedProperties.has("height")) this.updateEditorHeight();
110
+ }
111
+ }
112
+ render() {
113
+ return html`
114
+ <div class="header" ?hidden=${this.headless}>
115
+ <div class="title">${this.label}</div>
116
+ <div class="flex"></div>
117
+ <slot name="header-actions"></slot>
118
+ </div>
119
+ <div class="editor" style="height: ${this.height}px;">
120
+ <div class="quill-container" ${ref(this.container)}></div>
121
+ </div>
122
+ `;
123
+ }
124
+ updateEditorHeight() {
125
+ if (this.quill) {
126
+ const editorElement = this.shadowRoot?.querySelector(".ql-editor");
127
+ if (editorElement) editorElement.style.height = `${this.height - 42}px`;
128
+ }
129
+ }
130
+ /**
131
+ * Get the current content as HTML
132
+ */
133
+ getHTML() {
134
+ return this.quill ? this.quill.root.innerHTML : "";
135
+ }
136
+ /**
137
+ * Get the current content as plain text
138
+ */
139
+ getText() {
140
+ return this.quill ? this.quill.getText() : "";
141
+ }
142
+ /**
143
+ * Get the current content as Quill Delta
144
+ */
145
+ getDelta() {
146
+ return this.quill ? this.quill.getContents() : null;
147
+ }
148
+ /**
149
+ * Set content from HTML
150
+ */
151
+ setHTML(html) {
152
+ if (this.quill) this.quill.root.innerHTML = html;
153
+ }
154
+ /**
155
+ * Set content from Quill Delta
156
+ */
157
+ setDelta(delta) {
158
+ if (this.quill) this.quill.setContents(delta);
159
+ }
160
+ /**
161
+ * Clear all content
162
+ */
163
+ clear() {
164
+ if (this.quill) this.quill.setText("");
165
+ }
166
+ /**
167
+ * Focus the editor
168
+ */
169
+ focus() {
170
+ if (this.quill) this.quill.focus();
171
+ }
172
+ };
173
+ __decorate([property({
174
+ type: Boolean,
175
+ reflect: true
176
+ }), __decorateMetadata("design:type", Boolean)], UTextEditor.prototype, "headless", void 0);
177
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextEditor.prototype, "label", void 0);
178
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextEditor.prototype, "theme", void 0);
179
+ __decorate([property({ type: Boolean }), __decorateMetadata("design:type", Boolean)], UTextEditor.prototype, "readOnly", void 0);
180
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextEditor.prototype, "placeholder", void 0);
181
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextEditor.prototype, "value", void 0);
182
+ __decorate([property({ type: Number }), __decorateMetadata("design:type", Number)], UTextEditor.prototype, "height", void 0);
183
+ __decorate([property({ type: Array }), __decorateMetadata("design:type", Array)], UTextEditor.prototype, "toolbar", void 0);
184
+ UTextEditor = __decorate([customElement("u-text-editor")], UTextEditor);
185
+ //#endregion
186
+ export { UTextEditor };
@@ -0,0 +1 @@
1
+ export declare const styles: import('lit').CSSResult;
@@ -0,0 +1,119 @@
1
+ import { css } from "lit";
2
+ //#region src/components/text-editor/UTextEditor.styles.ts
3
+ var styles = css`
4
+ :host {
5
+ display: block;
6
+ border: 1px solid var(--u-neutral-300);
7
+ border-radius: 4px;
8
+ background: var(--u-neutral-0);
9
+ overflow: hidden;
10
+ }
11
+
12
+ :host([theme="dark"]) {
13
+ border-color: var(--u-neutral-700);
14
+ background: var(--u-neutral-900);
15
+ }
16
+
17
+ .header {
18
+ display: flex;
19
+ align-items: center;
20
+ padding: 12px 20px;
21
+ border-bottom: 1px solid var(--u-neutral-200);
22
+ background: var(--u-neutral-50);
23
+ min-height: 48px;
24
+ gap: 12px;
25
+ }
26
+
27
+ :host([theme="dark"]) .header {
28
+ border-bottom-color: var(--u-neutral-700);
29
+ background: var(--u-neutral-800);
30
+ }
31
+
32
+ .title {
33
+ font-weight: 600;
34
+ color: var(--u-neutral-700);
35
+ }
36
+
37
+ :host([theme="dark"]) .title {
38
+ color: var(--u-neutral-300);
39
+ }
40
+
41
+ .flex {
42
+ flex: 1;
43
+ }
44
+
45
+ .editor {
46
+ position: relative;
47
+ height: 300px;
48
+ }
49
+
50
+ .quill-container {
51
+ height: 100%;
52
+ }
53
+
54
+ .ql-editor {
55
+ font-family: var(--u-font-base);
56
+ font-size: 24px;
57
+ line-height: 1.6;
58
+ }
59
+
60
+ .ql-toolbar {
61
+ border: none !important;
62
+ border-bottom: 1px solid var(--u-neutral-200) !important;
63
+ background: var(--u-neutral-50);
64
+ }
65
+
66
+ :host([theme="dark"]) .ql-toolbar {
67
+ border-bottom-color: var(--u-neutral-700) !important;
68
+ background: var(--u-neutral-800);
69
+ }
70
+
71
+ .ql-container {
72
+ border: none !important;
73
+ font-family: var(--u-font-base);
74
+ }
75
+
76
+ .ql-editor {
77
+ padding: 20px;
78
+ color: var(--u-neutral-700);
79
+ }
80
+
81
+ :host([theme="dark"]) .ql-editor {
82
+ color: var(--u-neutral-300);
83
+ background: var(--u-neutral-900);
84
+ }
85
+
86
+ .ql-toolbar .ql-stroke {
87
+ stroke: var(--u-neutral-600);
88
+ }
89
+
90
+ .ql-toolbar .ql-fill {
91
+ fill: var(--u-neutral-600);
92
+ }
93
+
94
+ :host([theme="dark"]) .ql-toolbar .ql-stroke {
95
+ stroke: var(--u-neutral-400);
96
+ }
97
+
98
+ :host([theme="dark"]) .ql-toolbar .ql-fill {
99
+ fill: var(--u-neutral-400);
100
+ }
101
+
102
+ .ql-toolbar button:hover .ql-stroke {
103
+ stroke: var(--u-blue-600);
104
+ }
105
+
106
+ .ql-toolbar button:hover .ql-fill {
107
+ fill: var(--u-blue-600);
108
+ }
109
+
110
+ .ql-toolbar button.ql-active .ql-stroke {
111
+ stroke: var(--u-blue-600);
112
+ }
113
+
114
+ .ql-toolbar button.ql-active .ql-fill {
115
+ fill: var(--u-blue-600);
116
+ }
117
+ `;
118
+ //#endregion
119
+ export { styles };
@@ -0,0 +1,2 @@
1
+ export * from './components/code-editor/UCodeEditor.js';
2
+ export * from './components/text-editor/UTextEditor.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { UCodeEditor } from "./components/code-editor/UCodeEditor.js";
2
+ import { UTextEditor } from "./components/text-editor/UTextEditor.js";
3
+ export { UCodeEditor, UTextEditor };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { UCodeEditor as UCodeEditorElement } from '../components/code-editor/UCodeEditor';
3
+
4
+ export declare const UCodeEditor: React.ForwardRefExoticComponent<
5
+ Partial<UCodeEditorElement> & React.HTMLAttributes<UCodeEditorElement> & {
6
+ }
7
+ >;
8
+
9
+ export type UCodeEditorProps = React.ComponentProps<typeof UCodeEditor>;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { createComponent } from '@lit/react';
3
+ import { UCodeEditor } from '../components/code-editor/UCodeEditor.js';
4
+
5
+ export const UCodeEditor = createComponent({
6
+ react: React,
7
+ tagName: 'u-code-editor',
8
+ elementClass: UCodeEditor,
9
+ events: {},
10
+ });
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { UTextEditor as UTextEditorElement } from '../components/text-editor/UTextEditor';
3
+
4
+ export declare const UTextEditor: React.ForwardRefExoticComponent<
5
+ Partial<UTextEditorElement> & React.HTMLAttributes<UTextEditorElement> & {
6
+ }
7
+ >;
8
+
9
+ export type UTextEditorProps = React.ComponentProps<typeof UTextEditor>;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { createComponent } from '@lit/react';
3
+ import { UTextEditor } from '../components/text-editor/UTextEditor.js';
4
+
5
+ export const UTextEditor = createComponent({
6
+ react: React,
7
+ tagName: 'u-text-editor',
8
+ elementClass: UTextEditor,
9
+ events: {},
10
+ });
@@ -0,0 +1,2 @@
1
+ export { UTextEditor, UTextEditorProps } from './UTextEditor';
2
+ export { UCodeEditor, UCodeEditorProps } from './UCodeEditor';
@@ -0,0 +1,2 @@
1
+ export { UTextEditor } from './UTextEditor.js';
2
+ export { UCodeEditor } from './UCodeEditor.js';
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@iyulab/editor-components",
3
+ "description": "various editor components by iyulab",
4
+ "version": "0.0.1",
5
+ "keywords": [
6
+ "iyulab",
7
+ "web-components",
8
+ "lit-element"
9
+ ],
10
+ "license": "MIT",
11
+ "author": "iyulab",
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/iyulab/node-editor-components.git"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "LICENSE",
22
+ "README.md",
23
+ "CHANGELOG.md",
24
+ "package.json"
25
+ ],
26
+ "type": "module",
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js"
32
+ },
33
+ "./dist/*": {
34
+ "types": "./dist/*.d.ts",
35
+ "import": "./dist/*"
36
+ }
37
+ },
38
+ "scripts": {
39
+ "test": "vite",
40
+ "build": "eslint && vite build"
41
+ },
42
+ "dependencies": {
43
+ "@iyulab/components": "^1.0.6",
44
+ "lit": "^3.3.3",
45
+ "monaco-editor": "^0.55.1",
46
+ "quill": "^2.0.3"
47
+ },
48
+ "peerDependencies": {
49
+ "@lit/react": ">=1.0.8",
50
+ "react": ">=18.0.0"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "@lit/react": {
54
+ "optional": true
55
+ },
56
+ "react": {
57
+ "optional": true
58
+ }
59
+ },
60
+ "devDependencies": {
61
+ "@eslint/js": "^9.39.4",
62
+ "@types/node": "^25.8.0",
63
+ "eslint": "^9.39.4",
64
+ "glob": "^13.0.6",
65
+ "globals": "^17.6.0",
66
+ "typescript": "^5.9.3",
67
+ "typescript-eslint": "^8.59.3",
68
+ "vite": "^8.0.13",
69
+ "vite-plugin-dts": "^5.0.0"
70
+ }
71
+ }