@iyulab/editor-components 0.0.2 → 0.1.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 CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.1] - 2026-07-19
4
+
5
+ ### Added
6
+ - **테스트 인프라 도입** — 이 패키지에는 자동 테스트가 없었다(`tests/` 는 수동 preview 앱). 모노레포의 다른 컴포넌트 패키지와 동일한 vitest + playwright 브라우저 스택을 붙이고 `UTextEditor` 생명주기 계약 테스트 5건을 추가했다(mount → 편집 → detach → re-attach, 공개 접근자의 teardown 후 안전성). 기존 `npm test`(preview 앱 실행)는 `npm run preview` 로 이름을 옮겼다.
7
+
8
+ ### Documentation
9
+ - 0.1.0 의 `UTextEditor` 항목 서술을 정정 — "해제 후 접근에서 깨질 수 있던" 이라 썼으나 **실제로는 런타임에 도달하지 않는 경로**였다(호출부가 이미 `if (this.quill)` 로 감싸여 있었다). 타입 정직성 개선의 값은 예방에 있지 live-bug 수정이 아니다. 테스트로 확인한 사실에 맞게 문구를 바로잡았다.
10
+
11
+ ## [0.1.0] - 2026-07-19
12
+
13
+ ### Fixed
14
+ - **`UTextEditor` 의 타입 거짓말 제거(예방적)** — `quill` 필드가 `Quill`(non-null 단언)로 선언돼 있는데 `disconnectedCallback` 은 `null as any` 로 null 을 대입하고 있었다. 두 거짓말이 상쇄되어 null 가드 없는 역참조 5곳이 타입 검사를 통과하고 있었다. 필드를 `Quill | null` 로 정직하게 선언하고, `text-change` 핸들러는 생성 시점 지역 참조를 캡처하도록, `setQuillContents` 는 방어 가드를 갖도록 고쳤다. **다만 이는 런타임 버그 수정이 아니다** — 해당 호출부는 모두 `updated()` 의 `if (this.quill)` 안에 있어 실제로는 도달하지 않았다. 값은 앞으로 가드 없는 호출이 추가될 때 tsc 가 즉시 잡아준다는 데 있다.
15
+
16
+ ### Changed
17
+ - **이 패키지의 eslint 가 실제로 동작하기 시작했다.** `files` 패턴의 확장자 누락과 배열 프리셋 객체 스프레드 결함을 수정했다. `build` 스크립트의 `eslint &&` 게이트는 매칭 파일이 0개라 항상 통과하고 있었다. 위 null 결함은 이 복구로 처음 드러났다.
18
+ - `npm run lint` / `npm run lint:fix` 스크립트 추가.
19
+ - **Delta 타입 정밀화(소비자 영향 가능)**: `getDelta()` 가 `any` → `QuillDelta | null`, `setDelta()` 파라미터가 `any` → `QuillDeltaInput` 으로 좁혀졌다. 두 타입은 `quill-delta` 를 새 의존성으로 들이지 않고 Quill 자체 시그니처(`ReturnType<Quill['getContents']>` 등)에서 유도하므로 Quill 버전 변화를 자동으로 따라간다. `getDelta()` 가 `null` 을 반환할 수 있음이 이제 타입에 드러난다.
20
+ - Lit 생명주기 파라미터(`firstUpdated`/`updated`)의 `any` 를 `PropertyValues` 로, Monaco worker 의 `(self as any)` 를 명시적 인터페이스로 교체.
21
+
3
22
  ## [0.0.2] - 2026-07-17
4
23
 
5
24
  ### Fixed
@@ -1,3 +1,4 @@
1
+ import { PropertyValues } from 'lit';
1
2
  import { UElement } from '@iyulab/components/dist/components/UElement.js';
2
3
  /**
3
4
  * code editor component used by monaco-editor
@@ -28,8 +29,8 @@ export declare class UCodeEditor extends UElement {
28
29
  private observer;
29
30
  connectedCallback(): void;
30
31
  disconnectedCallback(): void;
31
- protected firstUpdated(changedProperties: any): Promise<void>;
32
- protected updated(changedProperties: any): Promise<void>;
32
+ protected firstUpdated(changedProperties: PropertyValues): Promise<void>;
33
+ protected updated(changedProperties: PropertyValues): Promise<void>;
33
34
  render(): import('lit-html').TemplateResult<1>;
34
35
  }
35
36
  declare global {
@@ -1,4 +1,9 @@
1
+ import { PropertyValues } from 'lit';
2
+ import { default as Quill } from 'quill';
1
3
  import { UElement } from '@iyulab/components/dist/components/UElement.js';
4
+ /** Quill 의 Delta 타입. quill-delta 를 직접 의존하지 않고 Quill 시그니처에서 유도한다. */
5
+ type QuillDelta = ReturnType<Quill["getContents"]>;
6
+ type QuillDeltaInput = Parameters<Quill["setContents"]>[0];
2
7
  /**
3
8
  * A rich text editor component built using Quill.js, providing a customizable and user-friendly interface for text editing. It supports various formatting options, themes, and can be configured to be read-only or editable.
4
9
  *
@@ -27,8 +32,8 @@ export declare class UTextEditor extends UElement {
27
32
  private observer;
28
33
  connectedCallback(): void;
29
34
  disconnectedCallback(): void;
30
- protected firstUpdated(changedProperties: any): Promise<void>;
31
- protected updated(changedProperties: any): Promise<void>;
35
+ protected firstUpdated(changedProperties: PropertyValues): Promise<void>;
36
+ protected updated(changedProperties: PropertyValues): Promise<void>;
32
37
  /** HTML을 Quill Delta로 변환해 silent source로 주입한다 — 프로그램적 콘텐츠 세팅이
33
38
  * text-change(→ change 이벤트)로 위장되지 않도록 하기 위함. */
34
39
  private setQuillContents;
@@ -45,7 +50,7 @@ export declare class UTextEditor extends UElement {
45
50
  /**
46
51
  * Get the current content as Quill Delta
47
52
  */
48
- getDelta(): any;
53
+ getDelta(): QuillDelta | null;
49
54
  /**
50
55
  * Set content from HTML.
51
56
  * 프로그램적 세팅이므로 change 이벤트는 발화하지 않는다 (value 프로퍼티 경로와 동일).
@@ -55,7 +60,7 @@ export declare class UTextEditor extends UElement {
55
60
  * Set content from Quill Delta.
56
61
  * 프로그램적 세팅이므로 change 이벤트는 발화하지 않는다.
57
62
  */
58
- setDelta(delta: any): void;
63
+ setDelta(delta: QuillDeltaInput): void;
59
64
  /**
60
65
  * Clear all content.
61
66
  * 프로그램적 세팅이므로 change 이벤트는 발화하지 않는다.
@@ -71,3 +76,4 @@ declare global {
71
76
  "u-text-editor": UTextEditor;
72
77
  }
73
78
  }
79
+ export {};
@@ -20,6 +20,7 @@ var UTextEditor = class UTextEditor extends UElement {
20
20
  this.value = "";
21
21
  this.height = 300;
22
22
  this.container = createRef();
23
+ this.quill = null;
23
24
  this.observer = new MutationObserver(() => {
24
25
  const theme = Theme.get();
25
26
  if (this.theme !== theme) this.theme = theme;
@@ -89,14 +90,15 @@ var UTextEditor = class UTextEditor extends UElement {
89
90
  modules: { toolbar: this.toolbar || defaultToolbar }
90
91
  });
91
92
  if (this.value) this.setQuillContents(this.value);
92
- this.quill.on("text-change", (_delta, _oldDelta, source) => {
93
+ const quill = this.quill;
94
+ quill.on("text-change", (_delta, _oldDelta, source) => {
93
95
  if (source !== "user") return;
94
- const html = this.quill.root.innerHTML;
96
+ const html = quill.root.innerHTML;
95
97
  this.value = html;
96
98
  this.dispatchEvent(new CustomEvent("change", { detail: {
97
99
  html,
98
- text: this.quill.getText(),
99
- delta: this.quill.getContents()
100
+ text: quill.getText(),
101
+ delta: quill.getContents()
100
102
  } }));
101
103
  });
102
104
  this.updateEditorHeight();
@@ -114,6 +116,7 @@ var UTextEditor = class UTextEditor extends UElement {
114
116
  /** HTML을 Quill Delta로 변환해 silent source로 주입한다 — 프로그램적 콘텐츠 세팅이
115
117
  * text-change(→ change 이벤트)로 위장되지 않도록 하기 위함. */
116
118
  setQuillContents(htmlValue) {
119
+ if (!this.quill) return;
117
120
  const delta = this.quill.clipboard.convert({ html: htmlValue });
118
121
  this.quill.setContents(delta, Quill.sources.SILENT);
119
122
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@iyulab/editor-components",
3
3
  "description": "various editor components by iyulab",
4
- "version": "0.0.2",
4
+ "version": "0.1.1",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "web-components",
@@ -36,7 +36,11 @@
36
36
  }
37
37
  },
38
38
  "scripts": {
39
- "test": "vite",
39
+ "preview": "vite",
40
+ "test": "vitest run",
41
+ "test:watch": "vitest",
42
+ "lint": "eslint src/",
43
+ "lint:fix": "eslint src/ --fix",
40
44
  "build": "eslint && vite build"
41
45
  },
42
46
  "dependencies": {
@@ -60,12 +64,14 @@
60
64
  "devDependencies": {
61
65
  "@eslint/js": "^9.39.4",
62
66
  "@types/node": "^26.1.1",
67
+ "@vitest/browser-playwright": "^4.1.10",
63
68
  "eslint": "^9.39.4",
64
69
  "glob": "^13.0.6",
65
70
  "globals": "^17.7.0",
66
71
  "typescript": "^5.9.3",
67
72
  "typescript-eslint": "^8.64.0",
68
73
  "vite": "^8.1.4",
69
- "vite-plugin-dts": "^5.0.3"
74
+ "vite-plugin-dts": "^5.0.3",
75
+ "vitest": "^4.1.10"
70
76
  }
71
77
  }