@iyulab/editor-components 0.1.1 → 0.2.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,42 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.1] - 2026-08-02
4
+
5
+ ### Fixed
6
+
7
+ - **`--u-txt-color-weak` 폴백 리터럴을 시트 값에 맞췄다** (`#9E9E9E` → `#757575`, 2곳).
8
+ 업스트림이 이 토큰의 라이트 매핑을 WCAG AA 미달(2.68)에서 neutral-600(4.61)으로
9
+ 고쳤다. 폴백은 **토큰 시트가 없을 때만** 쓰이므로 시트를 로드하는 환경에서는 변화가
10
+ 없지만, 어긋난 채로 두면 시트 유무에 따라 색이 갈린다.
11
+
12
+ ## [0.2.0] - 2026-08-01
13
+
14
+ ### Added
15
+
16
+ - **툴바 강조색이 브랜드를 따라온다** — 종전에는 `--u-blue-600` 에 하드와이어돼 있어
17
+ 소비자가 브랜드를 다른 색으로 잡아도 편집기 툴바만 파랑으로 남았다. 이제 역할 토큰
18
+ (`--u-primary-color`)을 읽으므로 재브랜딩이 한 줄로 끝난다.
19
+
20
+ ### Fixed
21
+
22
+ - ★**코드 편집기가 시스템 테마에서 항상 밝은 테마로 렌더되던 문제 수정** —
23
+ 테마 판정에 `Theme.get()`(사용자 **선호**)을 써서 기본값 `'system'` 이 `'dark'` 와 같지
24
+ 않다는 이유로 밝은 테마를 골랐다. **OS 가 다크여도 마찬가지였고, 이 설정이 기본이다.**
25
+ `Theme.resolved()`(실효 테마)로 고쳤다.
26
+ - **시스템 테마에서 OS 테마를 바꿔도 코드 편집기가 반응하지 않던 문제 수정** — 감시
27
+ 대상이 `data-theme` 뿐이었다. system 선호에서는 그 값이 `"system"` 그대로이고 실효
28
+ 테마는 `theme` 속성에만 반영되므로 관찰자가 발화하지 않았다.
29
+
30
+ ### Changed
31
+
32
+ - **텍스트 편집기의 색 선언이 팔레트에서 시맨틱 토큰으로 바뀌었다**(25 → 9).
33
+ 기계적으로 뒤집히는 팔레트 단 대신 테마별로 조율된 단을 쓴다.
34
+ - ⚠**`u-text-editor` 의 `theme` 프로퍼티가 제거됐다.** 지정해도 동작한 적이 없다 —
35
+ 값이 연결 시점에 덮어써졌고, 그 값이 구동하던 CSS 규칙은 속성이 반영되지 않아
36
+ **한 번도 매치되지 않았다**. 편집기는 종전과 같이 문서 테마를 따라간다(그 동작은
37
+ 팔레트 반전이 담당하고 있었고, 이제 시맨틱 토큰이 담당한다).
38
+ - **`@iyulab/components` 최소 버전이 `^1.14.0`** — `Theme.resolved()` 를 쓴다.
39
+
3
40
  ## [0.1.1] - 2026-07-19
4
41
 
5
42
  ### Added
package/README.md CHANGED
@@ -71,7 +71,6 @@ Quill.js 기반 리치 텍스트(WYSIWYG) 에디터 컴포넌트입니다.
71
71
  |----------|------|---------|------|
72
72
  | `headless` | `boolean` | `false` | 헤더(라벨 영역) 숨김 |
73
73
  | `label` | `string` | `"Rich Text Editor"` | 헤더 라벨 텍스트 |
74
- | `theme` | `"light" \| "dark" \| "system"` | 시스템 테마 추적 | 에디터 테마 |
75
74
  | `readOnly` | `boolean` | `false` | 읽기 전용 모드 |
76
75
  | `placeholder` | `string` | `"Start writing..."` | 플레이스홀더 텍스트 |
77
76
  | `value` | `string` | `""` | 에디터 HTML 내용 |
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorate.js
1
+ //#region \0@oxc-project+runtime@0.142.0/helpers/esm/decorate.js
2
2
  function __decorate(decorators, target, key, desc) {
3
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorateMetadata.js
1
+ //#region \0@oxc-project+runtime@0.142.0/helpers/esm/decorateMetadata.js
2
2
  function __decorateMetadata(k, v) {
3
3
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4
4
  }
@@ -11,7 +11,7 @@ export declare class UCodeEditor extends UElement {
11
11
  headless: boolean;
12
12
  /** The label text displayed in the header of the code editor. @default "Editor" */
13
13
  label: string;
14
- /** The visual theme of the code editor. Can be "light" or "dark". @default "light" */
14
+ /** 편집기 테마. 문서 테마를 따라 자동으로 동기화된다(직접 지정해도 덮어쓰인다). */
15
15
  theme: "light" | "dark";
16
16
  /** Whether the editor should be in read-only mode, preventing user input. @default false */
17
17
  readOnly: boolean;
@@ -1,7 +1,7 @@
1
1
  import "./UCodeEditor.worker.js";
2
2
  import { styles } from "./UCodeEditor.styles.js";
3
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/decorateMetadata.js";
4
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/decorate.js";
3
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorateMetadata.js";
4
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorate.js";
5
5
  import { html, unsafeCSS } from "lit";
6
6
  import { customElement, property } from "lit/decorators.js";
7
7
  import { createRef, ref } from "lit/directives/ref.js";
@@ -23,7 +23,7 @@ var UCodeEditor = class UCodeEditor extends UElement {
23
23
  this.container = createRef();
24
24
  this.syncingValue = false;
25
25
  this.observer = new MutationObserver(() => {
26
- const theme = Theme.get() === "dark" ? "dark" : "light";
26
+ const theme = Theme.resolved();
27
27
  if (this.theme !== theme) this.theme = theme;
28
28
  });
29
29
  }
@@ -36,10 +36,10 @@ var UCodeEditor = class UCodeEditor extends UElement {
36
36
  }
37
37
  connectedCallback() {
38
38
  super.connectedCallback();
39
- this.theme = Theme.get() === "dark" ? "dark" : "light";
39
+ this.theme = Theme.resolved();
40
40
  this.observer.observe(document.documentElement, {
41
41
  attributes: true,
42
- attributeFilter: ["data-theme"]
42
+ attributeFilter: ["data-theme", "theme"]
43
43
  });
44
44
  }
45
45
  disconnectedCallback() {
@@ -15,8 +15,6 @@ export declare class UTextEditor extends UElement {
15
15
  headless: boolean;
16
16
  /** The label text displayed in the header of the rich text editor. @default "Rich Text Editor" */
17
17
  label: string;
18
- /** The visual theme of the editor. Can be "light" or "dark". @default "light" */
19
- theme?: "light" | "dark" | "system";
20
18
  /** Whether the editor should be in read-only mode, preventing user input. @default false */
21
19
  readOnly: boolean;
22
20
  /** The placeholder text shown when the editor is empty. @default "Start writing..." */
@@ -29,8 +27,6 @@ export declare class UTextEditor extends UElement {
29
27
  toolbar?: string[][];
30
28
  private container;
31
29
  private quill;
32
- private observer;
33
- connectedCallback(): void;
34
30
  disconnectedCallback(): void;
35
31
  protected firstUpdated(changedProperties: PropertyValues): Promise<void>;
36
32
  protected updated(changedProperties: PropertyValues): Promise<void>;
@@ -1,10 +1,9 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/decorate.js";
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorate.js";
3
3
  import { styles } from "./UTextEditor.styles.js";
4
4
  import { html, unsafeCSS } from "lit";
5
5
  import { customElement, property } from "lit/decorators.js";
6
6
  import { createRef, ref } from "lit/directives/ref.js";
7
- import { Theme } from "@iyulab/components/dist/utilities/Theme.js";
8
7
  import { UElement } from "@iyulab/components/dist/components/UElement.js";
9
8
  import Quill from "quill";
10
9
  import quillStyles from "quill/dist/quill.snow.css?inline";
@@ -14,17 +13,12 @@ var UTextEditor = class UTextEditor extends UElement {
14
13
  super(..._args);
15
14
  this.headless = false;
16
15
  this.label = "Rich Text Editor";
17
- this.theme = "light";
18
16
  this.readOnly = false;
19
17
  this.placeholder = "Start writing...";
20
18
  this.value = "";
21
19
  this.height = 300;
22
20
  this.container = createRef();
23
21
  this.quill = null;
24
- this.observer = new MutationObserver(() => {
25
- const theme = Theme.get();
26
- if (this.theme !== theme) this.theme = theme;
27
- });
28
22
  }
29
23
  static {
30
24
  this.styles = [
@@ -33,17 +27,8 @@ var UTextEditor = class UTextEditor extends UElement {
33
27
  styles
34
28
  ];
35
29
  }
36
- connectedCallback() {
37
- super.connectedCallback();
38
- this.theme = Theme.get();
39
- this.observer.observe(document.documentElement, {
40
- attributes: true,
41
- attributeFilter: ["data-theme"]
42
- });
43
- }
44
30
  disconnectedCallback() {
45
31
  if (this.quill) this.quill = null;
46
- this.observer.disconnect();
47
32
  super.disconnectedCallback();
48
33
  }
49
34
  async firstUpdated(changedProperties) {
@@ -195,7 +180,6 @@ __decorate([property({
195
180
  reflect: true
196
181
  }), __decorateMetadata("design:type", Boolean)], UTextEditor.prototype, "headless", void 0);
197
182
  __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextEditor.prototype, "label", void 0);
198
- __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextEditor.prototype, "theme", void 0);
199
183
  __decorate([property({ type: Boolean }), __decorateMetadata("design:type", Boolean)], UTextEditor.prototype, "readOnly", void 0);
200
184
  __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextEditor.prototype, "placeholder", void 0);
201
185
  __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextEditor.prototype, "value", void 0);
@@ -1 +1,22 @@
1
+ /**
2
+ * 색은 전부 **역할 토큰**으로 읽는다.
3
+ *
4
+ * 종전에는 팔레트(`--u-neutral-*`)를 읽고 다크 테마를 `:host([theme="dark"])` 블록
5
+ * 8쌍으로 따로 구현했다. ★**그 블록들은 한 번도 매치되지 않는 죽은 코드였다** — 세 겹으로:
6
+ *
7
+ * ⑴ `theme` 프로퍼티가 `reflect` 되지 않아 **속성이 생기지 않았다**(작성자가 마크업에
8
+ * 직접 적은 경우에만 매치됐다).
9
+ * ⑵ 그마저도 `connectedCallback` 이 프로퍼티를 덮어써 소비자 지정이 무시됐다.
10
+ * ⑶ `Theme.get()` 은 선호를 돌려주므로 기본값 `'system'` 에서 `theme="system"` 이 됐다.
11
+ *
12
+ * ⚠**매치되지 않은 것이 다행이었다.** 그 블록들은 팔레트가 테마에 따라 뒤집히지
13
+ * **않는다**고 가정하고 쓰였다 — 다크 배경으로 `--u-neutral-900` 을 지정하는데, 그 토큰은
14
+ * 다크 시트에서 **#D4D4D4(밝은 회색)** 다. 매치됐다면 다크 모드가 깨졌을 것이다.
15
+ * 기반 규칙(`--u-neutral-0` 등)은 팔레트 반전 덕에 이미 테마를 따라가고 있었다.
16
+ *
17
+ * ⇒ 이 변경으로 실제로 달라지는 것은 **⒜ 강조색이 `--u-primary-color` 를 따라와
18
+ * 재브랜딩이 가능해진 것**(종전에는 `--u-blue-600` 하드와이어)과 **⒝ 기계적으로 뒤집힌
19
+ * 팔레트 단 대신 테마별로 조율된 시맨틱 단을 쓰는 것**이다. 죽은 코드 제거는 부수 효과다.
20
+ * 색 선언 수 25 → 9.
21
+ */
1
22
  export declare const styles: import('lit').CSSResult;
@@ -1,41 +1,48 @@
1
1
  import { css } from "lit";
2
2
  //#region src/components/text-editor/UTextEditor.styles.ts
3
+ /**
4
+ * 색은 전부 **역할 토큰**으로 읽는다.
5
+ *
6
+ * 종전에는 팔레트(`--u-neutral-*`)를 읽고 다크 테마를 `:host([theme="dark"])` 블록
7
+ * 8쌍으로 따로 구현했다. ★**그 블록들은 한 번도 매치되지 않는 죽은 코드였다** — 세 겹으로:
8
+ *
9
+ * ⑴ `theme` 프로퍼티가 `reflect` 되지 않아 **속성이 생기지 않았다**(작성자가 마크업에
10
+ * 직접 적은 경우에만 매치됐다).
11
+ * ⑵ 그마저도 `connectedCallback` 이 프로퍼티를 덮어써 소비자 지정이 무시됐다.
12
+ * ⑶ `Theme.get()` 은 선호를 돌려주므로 기본값 `'system'` 에서 `theme="system"` 이 됐다.
13
+ *
14
+ * ⚠**매치되지 않은 것이 다행이었다.** 그 블록들은 팔레트가 테마에 따라 뒤집히지
15
+ * **않는다**고 가정하고 쓰였다 — 다크 배경으로 `--u-neutral-900` 을 지정하는데, 그 토큰은
16
+ * 다크 시트에서 **#D4D4D4(밝은 회색)** 다. 매치됐다면 다크 모드가 깨졌을 것이다.
17
+ * 기반 규칙(`--u-neutral-0` 등)은 팔레트 반전 덕에 이미 테마를 따라가고 있었다.
18
+ *
19
+ * ⇒ 이 변경으로 실제로 달라지는 것은 **⒜ 강조색이 `--u-primary-color` 를 따라와
20
+ * 재브랜딩이 가능해진 것**(종전에는 `--u-blue-600` 하드와이어)과 **⒝ 기계적으로 뒤집힌
21
+ * 팔레트 단 대신 테마별로 조율된 시맨틱 단을 쓰는 것**이다. 죽은 코드 제거는 부수 효과다.
22
+ * 색 선언 수 25 → 9.
23
+ */
3
24
  var styles = css`
4
25
  :host {
5
26
  display: block;
6
- border: 1px solid var(--u-neutral-300);
7
- border-radius: 4px;
8
- background: var(--u-neutral-0);
27
+ border: 1px solid var(--u-border-color, #E0E0E0);
28
+ border-radius: var(--u-radius-md, 4px);
29
+ background: var(--u-panel-bg-color, #FFFFFF);
9
30
  overflow: hidden;
10
31
  }
11
32
 
12
- :host([theme="dark"]) {
13
- border-color: var(--u-neutral-700);
14
- background: var(--u-neutral-900);
15
- }
16
-
17
33
  .header {
18
34
  display: flex;
19
35
  align-items: center;
20
36
  padding: 12px 20px;
21
- border-bottom: 1px solid var(--u-neutral-200);
22
- background: var(--u-neutral-50);
37
+ border-bottom: 1px solid var(--u-border-color-weak, #EEEEEE);
38
+ background: var(--u-bg-color-hover, #F5F5F5);
23
39
  min-height: 48px;
24
40
  gap: 12px;
25
41
  }
26
42
 
27
- :host([theme="dark"]) .header {
28
- border-bottom-color: var(--u-neutral-700);
29
- background: var(--u-neutral-800);
30
- }
31
-
32
43
  .title {
33
44
  font-weight: 600;
34
- color: var(--u-neutral-700);
35
- }
36
-
37
- :host([theme="dark"]) .title {
38
- color: var(--u-neutral-300);
45
+ color: var(--u-txt-color, #212121);
39
46
  }
40
47
 
41
48
  .flex {
@@ -59,13 +66,8 @@ var styles = css`
59
66
 
60
67
  .ql-toolbar {
61
68
  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
+ border-bottom: 1px solid var(--u-border-color-weak, #EEEEEE) !important;
70
+ background: var(--u-bg-color-hover, #F5F5F5);
69
71
  }
70
72
 
71
73
  .ql-container {
@@ -75,44 +77,26 @@ var styles = css`
75
77
 
76
78
  .ql-editor {
77
79
  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);
80
+ color: var(--u-txt-color, #212121);
84
81
  }
85
82
 
86
83
  .ql-toolbar .ql-stroke {
87
- stroke: var(--u-neutral-600);
84
+ stroke: var(--u-txt-color-weak, #757575);
88
85
  }
89
86
 
90
87
  .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);
88
+ fill: var(--u-txt-color-weak, #757575);
108
89
  }
109
90
 
91
+ /* 강조는 역할 토큰 경유 — 소비자가 브랜드를 바꾸면 함께 따라온다. */
92
+ .ql-toolbar button:hover .ql-stroke,
110
93
  .ql-toolbar button.ql-active .ql-stroke {
111
- stroke: var(--u-blue-600);
94
+ stroke: var(--u-primary-color, #1E88E5);
112
95
  }
113
96
 
97
+ .ql-toolbar button:hover .ql-fill,
114
98
  .ql-toolbar button.ql-active .ql-fill {
115
- fill: var(--u-blue-600);
99
+ fill: var(--u-primary-color, #1E88E5);
116
100
  }
117
101
  `;
118
102
  //#endregion
@@ -2,7 +2,10 @@ import React from 'react';
2
2
  import { UCodeEditor as UCodeEditorElement } from '../components/code-editor/UCodeEditor';
3
3
 
4
4
  export declare const UCodeEditor: React.ForwardRefExoticComponent<
5
- Partial<UCodeEditorElement> & React.HTMLAttributes<UCodeEditorElement> & {
5
+ Omit<Partial<UCodeEditorElement>, keyof React.HTMLAttributes<UCodeEditorElement>>
6
+ & Omit<React.HTMLAttributes<UCodeEditorElement>, 'onChange'>
7
+ & React.RefAttributes<UCodeEditorElement>
8
+ & {
6
9
  onChange?: (event: CustomEvent) => void;
7
10
  }
8
11
  >;
@@ -2,7 +2,10 @@ import React from 'react';
2
2
  import { UTextEditor as UTextEditorElement } from '../components/text-editor/UTextEditor';
3
3
 
4
4
  export declare const UTextEditor: React.ForwardRefExoticComponent<
5
- Partial<UTextEditorElement> & React.HTMLAttributes<UTextEditorElement> & {
5
+ Omit<Partial<UTextEditorElement>, keyof React.HTMLAttributes<UTextEditorElement>>
6
+ & Omit<React.HTMLAttributes<UTextEditorElement>, 'onChange'>
7
+ & React.RefAttributes<UTextEditorElement>
8
+ & {
6
9
  onChange?: (event: CustomEvent) => void;
7
10
  }
8
11
  >;
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.1.1",
4
+ "version": "0.2.1",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "web-components",
@@ -44,7 +44,7 @@
44
44
  "build": "eslint && vite build"
45
45
  },
46
46
  "dependencies": {
47
- "@iyulab/components": "^1.5.1",
47
+ "@iyulab/components": "^1.15.0",
48
48
  "lit": "^3.3.3",
49
49
  "monaco-editor": "^0.55.1",
50
50
  "quill": "^2.0.3"