@iyulab/editor-components 0.5.0 → 0.5.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,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.1] - 2026-09-15
4
+
5
+ ### Fixed
6
+
7
+ - **A link could not be edited or removed from the keyboard in `u-text-editor`.** The link
8
+ tooltip's **Edit**/**Save** and **Remove** controls are anchors without `href`, drawn by Quill, so
9
+ they took no focus. They are now exposed as buttons in the tab order, and Enter or Space activates
10
+ them (Quill's own click handling is unchanged).
11
+
3
12
  ## [0.5.0] - 2026-09-13
4
13
 
5
14
  ### Changed
package/README.md CHANGED
@@ -96,6 +96,18 @@ Quill.js 기반 리치 텍스트(WYSIWYG) 에디터 컴포넌트입니다.
96
96
  - `clear()`: 모든 내용 삭제 (프로그램적 — `change` 미발화)
97
97
  - `focus()`: 에디터에 포커스
98
98
 
99
+ ## 접근성
100
+
101
+ 기준판은 **WCAG 2.2** 입니다. 아래는 이 패키지가 **테스트로 재서 보장하는 것**이고, 그 밖의
102
+ 성공 기준까지 포함한 전체 준수 선언이 아닙니다.
103
+
104
+ | 성공 기준 | 보장 | 어디서 재는가 |
105
+ |---|---|---|
106
+ | SC 2.5.8 타깃 크기(최소) | `u-text-editor` 의 포인터 타깃이 24×24 CSS px 이상이거나 간격 예외(중심 간 24px)를 충족하고, 그 좌표에서 실제로 눌린다 — Quill 이 그리는 툴바(선택기가 열린 상태·색 견본·링크 툴팁 포함)도 잰다 | `tests/browser/target-size.browser.test.ts`(실제 크로미움) |
107
+ | SC 2.1.1 키보드(포인터 커서 검사) | 포인터 커서를 보이면서 상호작용 요소가 아닌 것이 없다 — Quill 이 `href` 없는 앵커로 그리는 링크 툴팁의 편집·제거도 버튼 역할로 포커스를 받고 Enter/Space 로 눌린다 | `tests/browser/target-size.browser.test.ts` · `tests/browser/text-editor-link-tooltip-keyboard.browser.test.ts` |
108
+
109
+ `u-code-editor` 는 스스로 렌더하는 조작부가 없어(액션은 소비자가 `header-actions` 슬롯으로 넣는다) 이 게이트의 대상이 아닙니다 — 슬롯에 넣는 버튼의 크기는 넣는 쪽이 정합니다.
110
+
99
111
  ## 이벤트
100
112
 
101
113
  `change`는 네이티브 폼 컨트롤 규약을 따라 **사용자 편집에서만** 발화합니다. 프로그램적 `value` 세팅·`setHTML()`/`setDelta()`/`clear()`는 발화하지 않으므로, React 등 controlled 래퍼에서 에코 루프 없이 안전하게 바인딩할 수 있습니다.
@@ -39,6 +39,12 @@ export declare class UTextEditor extends UElement {
39
39
  private quill;
40
40
  disconnectedCallback(): void;
41
41
  protected firstUpdated(changedProperties: PropertyValues): Promise<void>;
42
+ /**
43
+ * snow 테마의 링크 툴팁은 «Edit/Save» 와 «Remove» 를 `href` 없는 `<a>` 로 그린다 — 포커스를 받지 못하고 Enter 로 눌리지
44
+ * 않아 키보드로는 링크를 편집·제거할 수 없었다(Quill 마크업이라 우리 템플릿 밖이다). Quill 이 붙인 클릭 처리는 그대로 두고,
45
+ * 두 앵커를 버튼 역할·탭 정지로 드러내고 Enter/Space 를 클릭으로 옮긴다. 이름은 테마 시트의 생성 콘텐츠(`Edit`·`Remove`)다.
46
+ */
47
+ private enhanceLinkTooltipKeyboard;
42
48
  protected updated(changedProperties: PropertyValues): Promise<void>;
43
49
  /** HTML을 Quill Delta로 변환해 silent source로 주입한다 — 프로그램적 콘텐츠 세팅이
44
50
  * text-change(→ change 이벤트)로 위장되지 않도록 하기 위함. */
@@ -74,6 +74,7 @@ var UTextEditor = class UTextEditor extends UElement {
74
74
  placeholder: this.placeholder,
75
75
  modules: { toolbar: this.toolbar || defaultToolbar }
76
76
  });
77
+ this.enhanceLinkTooltipKeyboard(this.quill);
77
78
  if (this.value) this.setQuillContents(this.value);
78
79
  const quill = this.quill;
79
80
  quill.on("text-change", (_delta, _oldDelta, source) => {
@@ -91,6 +92,27 @@ var UTextEditor = class UTextEditor extends UElement {
91
92
  }));
92
93
  });
93
94
  }
95
+ /**
96
+ * snow 테마의 링크 툴팁은 «Edit/Save» 와 «Remove» 를 `href` 없는 `<a>` 로 그린다 — 포커스를 받지 못하고 Enter 로 눌리지
97
+ * 않아 키보드로는 링크를 편집·제거할 수 없었다(Quill 마크업이라 우리 템플릿 밖이다). Quill 이 붙인 클릭 처리는 그대로 두고,
98
+ * 두 앵커를 버튼 역할·탭 정지로 드러내고 Enter/Space 를 클릭으로 옮긴다. 이름은 테마 시트의 생성 콘텐츠(`Edit`·`Remove`)다.
99
+ */
100
+ enhanceLinkTooltipKeyboard(quill) {
101
+ const root = quill.theme.tooltip?.root;
102
+ if (!root) return;
103
+ const ACTIONS = "a.ql-action, a.ql-remove";
104
+ for (const a of Array.from(root.querySelectorAll(ACTIONS))) {
105
+ a.setAttribute("role", "button");
106
+ a.setAttribute("tabindex", "0");
107
+ }
108
+ root.addEventListener("keydown", (e) => {
109
+ const target = e.target;
110
+ if ((e.key === "Enter" || e.key === " ") && target.matches(ACTIONS)) {
111
+ e.preventDefault();
112
+ target.click();
113
+ }
114
+ });
115
+ }
94
116
  async updated(changedProperties) {
95
117
  super.updated(changedProperties);
96
118
  await this.updateComplete;
@@ -25,7 +25,7 @@ var styles = css`
25
25
  /* 호스트는 자르지 않는다 — Quill 의 떠 있는 UI(선택기 목록 · 링크 툴팁)는 편집기 상자 밖으로 나갈 수 있어야 한다.
26
26
  종전 overflow: hidden 은 짧은 편집기에서 그것들을 잘라 누를 수 없게 만들었다. 둥근 모서리는 배경을 칠하는
27
27
  머리글(과 머리글이 없을 때의 툴바)이 자기 위 모서리를 둥글게 해서 지킨다. */
28
- /* 세로 flex 인 이유 — 호스트 상자가 높이의 주인이다(형제 u-code-editor 와 같은 계약, HD-60).
28
+ /* 세로 flex 인 이유 — 호스트 상자가 높이의 주인이다(형제 u-code-editor 와 같은 계약).
29
29
  소비자가 호스트에 CSS 높이를 주면 머리글은 고정이고 편집 영역이 나머지를 채운다. 주지 않으면
30
30
  편집 영역은 자기 기본 높이(height 프로퍼티)로 서고 호스트는 그 합만큼 자란다 — 종전과 같은 모습이다. */
31
31
  :host {
@@ -124,7 +124,7 @@ var styles = css`
124
124
  color: var(--u-txt-color, #212121);
125
125
  }
126
126
 
127
- /* 🔴Quill 이 그리는 타깃의 치수 — 우리가 덮어쓴다(사람 결정 HD-58 ⒜). 소비자가 보는 것은 우리 컴포넌트이고,
127
+ /* 🔴Quill 이 그리는 타깃의 치수 — 우리가 덮어쓴다. 소비자가 보는 것은 우리 컴포넌트이고,
128
128
  WCAG 2.2 SC 2.5.8 은 «누가 그렸는가» 를 묻지 않는다.
129
129
  ⑴ 색 견본 16×16(붙어 있어 간격 예외도 서지 않는다) → 24×24 · 한 줄 일곱 칸이라 목록 폭도 함께(7×(24+4)+10).
130
130
  ⑵ 링크 툴팁의 Edit·Remove 는 줄 높이가 26 인데 인라인이라 실제 높이가 19 였다 → inline-block 으로 26. */
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.5.0",
4
+ "version": "0.5.1",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "web-components",
@@ -76,7 +76,7 @@
76
76
  "devDependencies": {
77
77
  "@eslint/js": "^10.0.1",
78
78
  "@types/node": "^26.1.1",
79
- "@vitest/browser-playwright": "^4.1.10",
79
+ "@vitest/browser-playwright": "^5.0.0",
80
80
  "eslint": "^10.1.0",
81
81
  "glob": "^13.0.6",
82
82
  "globals": "^17.7.0",
@@ -85,7 +85,7 @@
85
85
  "typescript-eslint": "^8.64.0",
86
86
  "vite": "^8.1.4",
87
87
  "vite-plugin-dts": "^5.0.3",
88
- "vitest": "^4.1.10"
88
+ "vitest": "^5.0.0"
89
89
  },
90
90
  "overrides": {
91
91
  "dompurify": "^3.4.13"