@iyulab/editor-components 0.3.3 → 0.5.0

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,12 +1,12 @@
1
1
  import "./UCodeEditor.worker.js";
2
+ import _virtual_monaco_structure_css_default from "../../_virtual/_virtual_monaco-structure-css.js";
2
3
  import { styles } from "./UCodeEditor.styles.js";
3
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/decorateMetadata.js";
4
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/decorate.js";
4
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
5
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
5
6
  import { html, unsafeCSS } from "lit";
6
7
  import { customElement, property } from "lit/decorators.js";
7
8
  import { createRef, ref } from "lit/directives/ref.js";
8
9
  import * as monaco from "monaco-editor";
9
- import monacoStyles from "monaco-editor/min/vs/editor/editor.main.css?inline";
10
10
  import { Theme } from "@iyulab/components/dist/utilities/Theme.js";
11
11
  import { UElement } from "@iyulab/components/dist/components/UElement.js";
12
12
  //#region src/components/code-editor/UCodeEditor.ts
@@ -30,7 +30,7 @@ var UCodeEditor = class UCodeEditor extends UElement {
30
30
  static {
31
31
  this.styles = [
32
32
  super.styles,
33
- unsafeCSS(monacoStyles),
33
+ unsafeCSS(_virtual_monaco_structure_css_default),
34
34
  styles
35
35
  ];
36
36
  }
@@ -1,20 +1,23 @@
1
1
  import { css } from "lit";
2
2
  //#region src/components/code-editor/UCodeEditor.styles.ts
3
3
  var styles = css`
4
+ /* 크기는 «호스트 상자» 가 정한다 — monaco 는 automaticLayout 으로 컨테이너를 따라온다.
5
+ ⚠부모가 auto 높이면 height:100% 가 무효라 편집 영역이 0 이 된다(계약으로 문서에 적었다).
6
+ 머리글 높이를 숫자로 가정하지 않는다 — 세로 flex 가 «머리글을 뺀 나머지» 를 편집 영역에 준다.
7
+ 종전에는 --header-height: 32px 를 빼는 계산이었는데 실제 머리글은 24px 라 8px 을 못 쓰고 있었다
8
+ (형제 u-text-editor 에서 같은 부류의 «툴바 높이를 숫자로 가정» 을 걷어낸 것과 같은 이유). */
4
9
  :host {
5
10
  position: relative;
6
- display: block;
11
+ display: flex;
12
+ flex-direction: column;
7
13
  width: 100%;
8
14
  height: 100%;
9
15
  overflow: hidden;
10
- --header-height: 32px;
11
- }
12
- :host([headless]) {
13
- --header-height: 0px;
14
16
  }
15
17
 
16
18
  .header {
17
19
  position: relative;
20
+ flex: none;
18
21
  display: flex;
19
22
  flex-direction: row;
20
23
  align-items: center;
@@ -38,9 +41,10 @@ var styles = css`
38
41
  }
39
42
 
40
43
  .editor {
41
- position: absolute;
44
+ position: relative;
45
+ flex: 1 1 auto;
46
+ min-height: 0;
42
47
  width: 100%;
43
- height: calc(100% - var(--header-height));
44
48
  overflow: hidden;
45
49
 
46
50
  main {
@@ -1,8 +1,8 @@
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";
1
+ import editorWorker from "monaco-editor/editor/editor.worker.js?worker";
2
+ import jsonWorker from "monaco-editor/language/json/json.worker.js?worker";
3
+ import cssWorker from "monaco-editor/language/css/css.worker.js?worker";
4
+ import htmlWorker from "monaco-editor/language/html/html.worker.js?worker";
5
+ import tsWorker from "monaco-editor/language/typescript/ts.worker.js?worker";
6
6
  //#region src/components/code-editor/UCodeEditor.worker.ts
7
7
  self.MonacoEnvironment = { getWorker(_moduleId, label) {
8
8
  if (label === "json") return new jsonWorker();
@@ -21,7 +21,17 @@ export declare class UTextEditor extends UElement {
21
21
  placeholder: string;
22
22
  /** The current HTML content of the rich text editor. @default "" */
23
23
  value: string;
24
- /** The height of the editor in pixels. @default 300 */
24
+ /**
25
+ * 편집 영역의 **기본** 높이(px) — 호스트에 높이 제약이 없을 때의 값. 그때 호스트 상자는 여기에
26
+ * 머리글이 더해진 크기다(`headless` 면 머리글 없음).
27
+ *
28
+ * **높이의 주인은 호스트 상자다**(형제 `u-code-editor` 와 같은 계약). 호스트에 CSS `height` /
29
+ * `max-height` 를 주면 머리글은 그대로이고 편집 영역이 나머지를 채운다 — 부모를 채우려면
30
+ * `height: 100%` 같은 CSS 로 넘기면 된다. Quill 의 떠 있는 UI(선택기 목록 · 링크 툴팁)는
31
+ * 상자 밖으로 나가도 잘리지 않는다. 계약은 `tests/browser/text-editor-layout.browser.test.ts` 가 고정한다.
32
+ *
33
+ * @default 300
34
+ */
25
35
  height: number;
26
36
  /** Custom toolbar configuration. If not provided, uses default toolbar. */
27
37
  toolbar?: string[][];
@@ -34,7 +44,6 @@ export declare class UTextEditor extends UElement {
34
44
  * text-change(→ change 이벤트)로 위장되지 않도록 하기 위함. */
35
45
  private setQuillContents;
36
46
  render(): import('lit-html').TemplateResult<1>;
37
- private updateEditorHeight;
38
47
  /**
39
48
  * Get the current content as HTML
40
49
  */
@@ -1,5 +1,5 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.147.0/helpers/esm/decorate.js";
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.149.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";
@@ -90,7 +90,6 @@ var UTextEditor = class UTextEditor extends UElement {
90
90
  composed: true
91
91
  }));
92
92
  });
93
- this.updateEditorHeight();
94
93
  }
95
94
  async updated(changedProperties) {
96
95
  super.updated(changedProperties);
@@ -99,7 +98,6 @@ var UTextEditor = class UTextEditor extends UElement {
99
98
  if (changedProperties.has("value") && this.value !== this.quill.root.innerHTML) this.setQuillContents(this.value);
100
99
  if (changedProperties.has("readOnly")) this.quill.enable(!this.readOnly);
101
100
  if (changedProperties.has("placeholder")) this.quill.root.dataset.placeholder = this.placeholder;
102
- if (changedProperties.has("height")) this.updateEditorHeight();
103
101
  }
104
102
  }
105
103
  /** HTML을 Quill Delta로 변환해 silent source로 주입한다 — 프로그램적 콘텐츠 세팅이
@@ -121,12 +119,6 @@ var UTextEditor = class UTextEditor extends UElement {
121
119
  </div>
122
120
  `;
123
121
  }
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
122
  /**
131
123
  * Get the current content as HTML
132
124
  */
@@ -22,15 +22,22 @@ import { css } from "lit";
22
22
  * 색 선언 수 25 → 9.
23
23
  */
24
24
  var styles = css`
25
+ /* 호스트는 자르지 않는다 — Quill 의 떠 있는 UI(선택기 목록 · 링크 툴팁)는 편집기 상자 밖으로 나갈 수 있어야 한다.
26
+ 종전 overflow: hidden 은 짧은 편집기에서 그것들을 잘라 누를 수 없게 만들었다. 둥근 모서리는 배경을 칠하는
27
+ 머리글(과 머리글이 없을 때의 툴바)이 자기 위 모서리를 둥글게 해서 지킨다. */
28
+ /* 세로 flex 인 이유 — 호스트 상자가 높이의 주인이다(형제 u-code-editor 와 같은 계약, HD-60).
29
+ 소비자가 호스트에 CSS 높이를 주면 머리글은 고정이고 편집 영역이 나머지를 채운다. 주지 않으면
30
+ 편집 영역은 자기 기본 높이(height 프로퍼티)로 서고 호스트는 그 합만큼 자란다 — 종전과 같은 모습이다. */
25
31
  :host {
26
- display: block;
32
+ display: flex;
33
+ flex-direction: column;
27
34
  border: 1px solid var(--u-border-color, #E0E0E0);
28
35
  border-radius: var(--u-radius-md, 4px);
29
36
  background: var(--u-panel-bg-color, #FFFFFF);
30
- overflow: hidden;
31
37
  }
32
38
 
33
39
  .header {
40
+ flex: none;
34
41
  display: flex;
35
42
  align-items: center;
36
43
  padding: 12px 20px;
@@ -38,6 +45,11 @@ var styles = css`
38
45
  background: var(--u-bg-color-hover, #F5F5F5);
39
46
  min-height: 48px;
40
47
  gap: 12px;
48
+ border-radius: calc(var(--u-radius-md, 4px) - 1px) calc(var(--u-radius-md, 4px) - 1px) 0 0;
49
+ }
50
+
51
+ :host([headless]) .ql-toolbar {
52
+ border-radius: calc(var(--u-radius-md, 4px) - 1px) calc(var(--u-radius-md, 4px) - 1px) 0 0;
41
53
  }
42
54
 
43
55
  .title {
@@ -51,13 +63,45 @@ var styles = css`
51
63
 
52
64
  .editor {
53
65
  position: relative;
66
+ /* 렌더의 인라인 style 이 height 프로퍼티 값으로 덮는 폴백이다. flex-basis 가 auto 라 그 값은
67
+ «제약이 없을 때의 기본 높이» 가 된다 — 호스트에 높이가 있으면 아래 flex 규칙이 이 값을 이긴다.
68
+ (주석에도 백틱을 쓰지 않는다 — css 템플릿이 그 자리에서 끝난다.) */
54
69
  height: 300px;
70
+ flex: 1 1 auto;
71
+ min-height: 0;
55
72
  }
56
73
 
57
74
  .quill-container {
58
75
  height: 100%;
59
76
  }
60
77
 
78
+ /* 편집 영역은 «높이에서 툴바를 뺀 나머지» 다 — 툴바 높이를 숫자로 가정하지 않는다(좁으면 툴바가 여러 줄로 접힌다).
79
+ 종전에는 편집 영역을 height - 42px 로 줘, 툴바가 접히면 편집 영역이 상자 밖으로 밀려나 아래가 잘렸다.
80
+ ⚠Quill 은 넘겨받은 요소(.quill-container)를 .ql-container 로 만들고, 툴바를 그 «앞 형제» 로 .editor 안에 넣는다 —
81
+ 그래서 세로 배치의 주인은 .editor 다. */
82
+ .editor {
83
+ display: flex;
84
+ flex-direction: column;
85
+ }
86
+
87
+ .editor > .ql-toolbar {
88
+ flex: none;
89
+ }
90
+
91
+ .editor > .ql-container {
92
+ flex: 1 1 auto;
93
+ min-height: 0;
94
+ height: auto;
95
+ display: flex;
96
+ flex-direction: column;
97
+ }
98
+
99
+ .ql-container > .ql-editor {
100
+ flex: 1 1 auto;
101
+ min-height: 0;
102
+ height: auto;
103
+ }
104
+
61
105
  .ql-editor {
62
106
  font-family: var(--u-font-base);
63
107
  font-size: 24px;
@@ -80,12 +124,28 @@ var styles = css`
80
124
  color: var(--u-txt-color, #212121);
81
125
  }
82
126
 
127
+ /* 🔴Quill 이 그리는 타깃의 치수 — 우리가 덮어쓴다(사람 결정 HD-58 ⒜). 소비자가 보는 것은 우리 컴포넌트이고,
128
+ WCAG 2.2 SC 2.5.8 은 «누가 그렸는가» 를 묻지 않는다.
129
+ ⑴ 색 견본 16×16(붙어 있어 간격 예외도 서지 않는다) → 24×24 · 한 줄 일곱 칸이라 목록 폭도 함께(7×(24+4)+10).
130
+ ⑵ 링크 툴팁의 Edit·Remove 는 줄 높이가 26 인데 인라인이라 실제 높이가 19 였다 → inline-block 으로 26. */
131
+ .ql-snow .ql-color-picker .ql-picker-item {
132
+ width: 24px;
133
+ height: 24px;
134
+ }
135
+ .ql-snow .ql-color-picker .ql-picker-options {
136
+ width: 206px;
137
+ }
138
+ .ql-snow .ql-tooltip a.ql-action,
139
+ .ql-snow .ql-tooltip a.ql-remove {
140
+ display: inline-block;
141
+ }
142
+
83
143
  .ql-toolbar .ql-stroke {
84
- stroke: var(--u-txt-color-weak, #757575);
144
+ stroke: var(--u-txt-color-weak, #616161);
85
145
  }
86
146
 
87
147
  .ql-toolbar .ql-fill {
88
- fill: var(--u-txt-color-weak, #757575);
148
+ fill: var(--u-txt-color-weak, #616161);
89
149
  }
90
150
 
91
151
  /* 강조는 역할 토큰 경유 — 소비자가 브랜드를 바꾸면 함께 따라온다. */
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { UCodeEditor as UCodeEditorElement } from '../components/code-editor/UCodeEditor';
2
+ import { UCodeEditor as UCodeEditorElement } from '@iyulab/editor-components/dist/components/code-editor/UCodeEditor.js';
3
3
 
4
4
  export declare const UCodeEditor: React.ForwardRefExoticComponent<
5
5
  Omit<Partial<UCodeEditorElement>, keyof React.HTMLAttributes<UCodeEditorElement>>
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { createComponent } from '@lit/react';
3
- import { UCodeEditor as UCodeEditorElement } from '../components/code-editor/UCodeEditor.js';
3
+ import { UCodeEditor as UCodeEditorElement } from '@iyulab/editor-components/dist/components/code-editor/UCodeEditor.js';
4
4
 
5
5
  export const UCodeEditor = createComponent({
6
6
  react: React,
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { UTextEditor as UTextEditorElement } from '../components/text-editor/UTextEditor';
2
+ import { UTextEditor as UTextEditorElement } from '@iyulab/editor-components/dist/components/text-editor/UTextEditor.js';
3
3
 
4
4
  export declare const UTextEditor: React.ForwardRefExoticComponent<
5
5
  Omit<Partial<UTextEditorElement>, keyof React.HTMLAttributes<UTextEditorElement>>
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { createComponent } from '@lit/react';
3
- import { UTextEditor as UTextEditorElement } from '../components/text-editor/UTextEditor.js';
3
+ import { UTextEditor as UTextEditorElement } from '@iyulab/editor-components/dist/components/text-editor/UTextEditor.js';
4
4
 
5
5
  export const UTextEditor = createComponent({
6
6
  react: React,
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.3.3",
4
+ "version": "0.5.0",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "web-components",
@@ -46,6 +46,7 @@
46
46
  }
47
47
  },
48
48
  "scripts": {
49
+ "preversion": "node -e \"if(require('fs').existsSync('../../scripts/preversion-check.mjs'))require('child_process').execFileSync('node',['../../scripts/preversion-check.mjs'],{stdio:'inherit'})\"",
49
50
  "preview": "vite",
50
51
  "test": "vitest run",
51
52
  "test:watch": "vitest",
@@ -55,14 +56,14 @@
55
56
  "typecheck": "tsc --noEmit"
56
57
  },
57
58
  "dependencies": {
58
- "@iyulab/components": "^1.15.0",
59
59
  "lit": "^3.3.3",
60
- "monaco-editor": "^0.55.1 || ^0.56.0",
61
60
  "quill": "^2.0.3"
62
61
  },
63
62
  "peerDependencies": {
63
+ "@iyulab/components": ">=1.15.0",
64
64
  "@lit/react": ">=1.0.8",
65
- "react": ">=18.0.0"
65
+ "react": ">=18.0.0",
66
+ "monaco-editor": "^0.56.0"
66
67
  },
67
68
  "peerDependenciesMeta": {
68
69
  "@lit/react": {
@@ -73,13 +74,14 @@
73
74
  }
74
75
  },
75
76
  "devDependencies": {
76
- "@eslint/js": "^9.39.4",
77
+ "@eslint/js": "^10.0.1",
77
78
  "@types/node": "^26.1.1",
78
79
  "@vitest/browser-playwright": "^4.1.10",
79
- "eslint": "^9.39.4",
80
+ "eslint": "^10.1.0",
80
81
  "glob": "^13.0.6",
81
82
  "globals": "^17.7.0",
82
- "typescript": "^5.9.3",
83
+ "monaco-editor": "^0.56.0",
84
+ "typescript": "^6.0.2",
83
85
  "typescript-eslint": "^8.64.0",
84
86
  "vite": "^8.1.4",
85
87
  "vite-plugin-dts": "^5.0.3",
@@ -29,6 +29,29 @@ Monaco Editor wrapped as a custom element. Syntax highlighting, per-language con
29
29
  | `fontSize` | `number` | `14` | — | Editor font size in pixels |
30
30
  | `value` | `string` | `''` | — | Current text content |
31
31
 
32
+ ## Sizing
33
+
34
+ **The host box owns the size.** `:host` is `width: 100%; height: 100%`, and the editing area is
35
+ whatever the header leaves — Monaco re-layouts into it (`automaticLayout`). There is no `height`
36
+ property: size the element, or give its parent a height.
37
+
38
+ ```html
39
+ <!-- ✓ the parent has a height, so the editor fills it -->
40
+ <div style="height: 400px"><u-code-editor></u-code-editor></div>
41
+
42
+ <!-- ✓ or size the element itself -->
43
+ <u-code-editor style="height: 400px"></u-code-editor>
44
+ ```
45
+
46
+ ⚠ **In a parent that has no height of its own, `height: 100%` resolves to nothing and the editing
47
+ area collapses to a few pixels** — you get the header and an empty strip, with no error and nothing
48
+ in the console. Give the parent a height, or set one on the element.
49
+
50
+ `headless` removes the header, so the editing area is then the whole host box.
51
+
52
+ `u-text-editor` shares this contract since 0.5.0; its `height` property is only the editing area's default when the host has no constraint.
53
+ other unchanged.
54
+
32
55
  ## Slots
33
56
 
34
57
  | Name | Description |
@@ -43,4 +66,4 @@ Monaco Editor wrapped as a custom element. Syntax highlighting, per-language con
43
66
 
44
67
  ## CSS Custom Properties
45
68
 
46
- None. `UCodeEditor.styles.ts` only sets a private layout variable (`--header-height`, not documented as a consumer override point) and otherwise relies on Monaco's own theme (`vs-light`/`vs-dark`) rather than this library's `--u-*` design tokens.
69
+ None. Layout is plain flexbox — the header keeps its own height and the editing area takes the rest — so there is no layout variable to override (see [Sizing](#sizing) for how the element is sized), and colours come from Monaco's own theme (`vs-light`/`vs-dark`) rather than this library's `--u-*` design tokens.
@@ -26,9 +26,32 @@ Rich text editor built on [Quill](https://quilljs.com/). Reads and writes HTML,
26
26
  | `readOnly` | `boolean` | `false` | — | Prevents user input |
27
27
  | `placeholder` | `string` | `'Start writing...'` | — | Placeholder shown when empty |
28
28
  | `value` | `string` | `''` | — | Current content as HTML |
29
- | `height` | `number` | `300` | — | Editor height in pixels |
29
+ | `height` | `number` | `300` | — | Editing-area height in pixels **when the host has no height constraint** — see [Sizing](#sizing) |
30
30
  | `toolbar` | `string[][]` | `undefined` | — | Custom toolbar configuration. When left unset, falls back at runtime to Quill's default 14-group toolbar (not a declared property default) |
31
31
 
32
+ ## Sizing
33
+
34
+ **The host box owns the height** (since 0.5.0 — the same contract as `u-code-editor`). Give the
35
+ host a CSS `height` or `max-height` and the header stays fixed while the editing area takes the
36
+ rest; `height: 100%` fills a parent. `height` (the property) is the editing area's **default**
37
+ when the host has no constraint: a plain `<u-text-editor>` is about 349px tall (48px header +
38
+ 300px + border), `headless` removes the header.
39
+
40
+ The host never clips — Quill's floating UI (picker lists, the link tooltip) has to be able to
41
+ leave the box.
42
+
43
+ ```html
44
+ <!-- ✓ the parent has a height, so the editor fills it (header + editing area = 400px) -->
45
+ <div style="height: 400px"><u-text-editor style="height: 100%"></u-text-editor></div>
46
+
47
+ <!-- ✓ no constraint: the editing area is 300px by default, or whatever height says -->
48
+ <u-text-editor height="200"></u-text-editor>
49
+ ```
50
+
51
+ ⚠ Until 0.4.x the contract was the opposite (the property was the only way to size the editor and
52
+ host CSS was ignored). A layout that relied on host CSS *not* reaching the editing area changes
53
+ with 0.5.0 — see the CHANGELOG.
54
+
32
55
  ## Methods
33
56
 
34
57
  | Method | Returns | Description |