@iyulab/flex-table 0.48.4 → 0.48.5

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,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.48.5] - 2026-10-06
4
+
5
+ ### Fixed
6
+
7
+ - **The form controls the grid draws are named.** Cell editors (text, number, select, date and the
8
+ autocomplete input) had no name and are now named by the column header; the autocomplete editor
9
+ is a combobox whose suggestions are a listbox of options, with the highlighted one announced. In
10
+ the filter dropdown — now a group named "Filter {column}" — the match-mode select, the filter text,
11
+ each numeric condition's operator and value, the condition join and the blank-cells select are
12
+ named (the blank-cells label sat next to its select without being tied to it). The find and
13
+ replace boxes were named only by their placeholder. New locale keys: `findInput`,
14
+ `replaceInput`, `filterFor`, `filterMatchMode`, `filterText`, `conditionOperator`,
15
+ `conditionValue`, `conditionJoin`.
16
+
3
17
  ## [0.48.4] - 2026-10-06
4
18
 
5
19
  ### Fixed
@@ -1119,6 +1119,14 @@ O.register("en", {
1119
1119
  replaceWithPlaceholder: "Replace with...",
1120
1120
  replace: "Replace",
1121
1121
  replaceAll: "Replace all",
1122
+ findInput: "Find",
1123
+ replaceInput: "Replace with",
1124
+ filterFor: "Filter {header}",
1125
+ filterMatchMode: "Match",
1126
+ filterText: "Filter text",
1127
+ conditionOperator: "Condition {n}",
1128
+ conditionValue: "Condition {n} value",
1129
+ conditionJoin: "Combine conditions",
1122
1130
  sortAscending: "Sort ascending",
1123
1131
  sortDescending: "Sort descending",
1124
1132
  filter: "Filter…",
@@ -1179,6 +1187,14 @@ O.register("en", {
1179
1187
  replaceWithPlaceholder: "바꿀 내용...",
1180
1188
  replace: "바꾸기",
1181
1189
  replaceAll: "모두 바꾸기",
1190
+ findInput: "찾을 내용",
1191
+ replaceInput: "바꿀 내용",
1192
+ filterFor: "{header} 필터",
1193
+ filterMatchMode: "일치 방식",
1194
+ filterText: "필터 텍스트",
1195
+ conditionOperator: "조건 {n}",
1196
+ conditionValue: "조건 {n} 값",
1197
+ conditionJoin: "조건 결합",
1182
1198
  sortAscending: "오름차순 정렬",
1183
1199
  sortDescending: "내림차순 정렬",
1184
1200
  filter: "필터…",
@@ -3527,7 +3543,8 @@ var K = {
3527
3543
  _renderFilterDropdown(e) {
3528
3544
  let t = e.type ?? "text";
3529
3545
  return i`
3530
- <div class="ft-filter-dropdown" @click=${(e) => e.stopPropagation()}>
3546
+ <div class="ft-filter-dropdown" role="group" aria-label=${k("filterFor", { header: e.label })}
3547
+ @click=${(e) => e.stopPropagation()}>
3531
3548
  ${t === "boolean" ? this._renderBooleanFilter(e) : t === "number" ? this._renderNumberFilter(e) : t === "date" || t === "datetime" ? this._renderDateFilter(e) : this._renderTextFilter(e)}
3532
3549
  <div class="ft-filter-actions">
3533
3550
  <button class="ft-filter-clear" @click=${() => this._clearColumnFilter(e.key)}>${k("clear")}</button>
@@ -3564,7 +3581,7 @@ var K = {
3564
3581
  return i`
3565
3582
  <div class="ft-filter-empty-row">
3566
3583
  <label>${k("blankCells")}</label>
3567
- <select class="ft-filter-mode-select"
3584
+ <select class="ft-filter-mode-select" aria-label=${k("blankCells")}
3568
3585
  .value=${n}
3569
3586
  @change=${(n) => {
3570
3587
  let r = n.target.value;
@@ -3636,7 +3653,7 @@ var K = {
3636
3653
  };
3637
3654
  return i`
3638
3655
  <div class="ft-filter-mode-row">
3639
- <select class="ft-filter-mode-select"
3656
+ <select class="ft-filter-mode-select" aria-label=${k("filterMatchMode")}
3640
3657
  .value=${t.mode}
3641
3658
  @change=${(t) => {
3642
3659
  let n = t.target.value, r = this._textFilterState.get(e.key) ?? {
@@ -3657,7 +3674,7 @@ var K = {
3657
3674
  <option value="wildcard">${k("wildcard")}</option>
3658
3675
  </select>
3659
3676
  </div>
3660
- <input class="ft-filter-input" type="text" placeholder=${k("searchPlaceholder")}
3677
+ <input class="ft-filter-input" type="text" placeholder=${k("searchPlaceholder")} aria-label=${k("filterText")}
3661
3678
  .value=${t.value}
3662
3679
  @input=${(t) => {
3663
3680
  let n = t.target.value, r = this._textFilterState.get(e.key) ?? {
@@ -3694,7 +3711,7 @@ var K = {
3694
3711
  let n = (this._numberFilterState.get(e) ?? this._defaultNumState())[t];
3695
3712
  return i`
3696
3713
  <div class="ft-num-cond-row">
3697
- <select class="ft-filter-mode-select ft-num-op-select"
3714
+ <select class="ft-filter-mode-select ft-num-op-select" aria-label=${k("conditionOperator", { n: t === "cond1" ? 1 : 2 })}
3698
3715
  .value=${n.op}
3699
3716
  @change=${(n) => {
3700
3717
  let r = n.target.value, i = this._numberFilterState.get(e) ?? this._defaultNumState();
@@ -3709,6 +3726,7 @@ var K = {
3709
3726
  ${Object.keys(K).map((e) => i`<option value=${e}>${K[e]}</option>`)}
3710
3727
  </select>
3711
3728
  <input class="ft-filter-input ft-num-cond-input" type="text" inputmode="decimal" placeholder=${k("valuePlaceholder")}
3729
+ aria-label=${k("conditionValue", { n: t === "cond1" ? 1 : 2 })}
3712
3730
  .value=${n.text ?? (n.value == null ? "" : N(n.value))}
3713
3731
  aria-invalid=${n.text && n.value == null ? "true" : "false"}
3714
3732
  @input=${(n) => {
@@ -3730,7 +3748,7 @@ var K = {
3730
3748
  return i`
3731
3749
  ${this._renderNumCondRow(e.key, "cond1")}
3732
3750
  <div class="ft-filter-mode-row">
3733
- <select class="ft-filter-mode-select"
3751
+ <select class="ft-filter-mode-select" aria-label=${k("conditionJoin")}
3734
3752
  .value=${t.join}
3735
3753
  @change=${(t) => {
3736
3754
  let n = t.target.value, r = this._numberFilterState.get(e.key) ?? this._defaultNumState();
@@ -3795,7 +3813,7 @@ var K = {
3795
3813
  }
3796
3814
  _renderBooleanFilter(e) {
3797
3815
  return i`
3798
- <select class="ft-filter-input"
3816
+ <select class="ft-filter-input" aria-label=${k("filterFor", { header: e.label })}
3799
3817
  @change=${(t) => {
3800
3818
  let n = t.target.value;
3801
3819
  n === "all" ? this.removeFilter(e.key) : this.setFilter(e.key, (e) => !!e == (n === "true"));
@@ -4225,7 +4243,7 @@ var K = {
4225
4243
  e.key === "Enter" && !_(e) && e.target instanceof HTMLInputElement && e.target.classList.contains("ft-find-input") && (e.shiftKey ? this._findPrev() : this._findNext());
4226
4244
  }}>
4227
4245
  <div class="ft-find-row">
4228
- <input class="ft-find-input" type="text" placeholder=${k("findPlaceholder")}
4246
+ <input class="ft-find-input" type="text" placeholder=${k("findPlaceholder")} aria-label=${k("findInput")}
4229
4247
  .value=${t}
4230
4248
  @input=${(e) => {
4231
4249
  this._findState.query = e.target.value, this._findSearch();
@@ -4244,7 +4262,7 @@ var K = {
4244
4262
  </div>
4245
4263
  ${e === "replace" ? i`
4246
4264
  <div class="ft-find-row">
4247
- <input class="ft-find-replace-input" type="text" placeholder=${k("replaceWithPlaceholder")}
4265
+ <input class="ft-find-replace-input" type="text" placeholder=${k("replaceWithPlaceholder")} aria-label=${k("replaceInput")}
4248
4266
  .value=${n}
4249
4267
  @input=${(e) => {
4250
4268
  this._findState.replaceWith = e.target.value;
@@ -4474,7 +4492,7 @@ var K = {
4474
4492
  if (t.editor) return t.editor(e[t.key], e, t);
4475
4493
  let n = e[t.key], r = n == null ? "" : String(n);
4476
4494
  if (t.type === "number") return i`
4477
- <input class="ft-editor ft-editor-number" type="text" inputmode="decimal"
4495
+ <input class="ft-editor ft-editor-number" type="text" inputmode="decimal" aria-label=${t.label}
4478
4496
  .value=${typeof n == "number" ? N(n) : r}
4479
4497
  @keydown=${this._onEditorKeyDown}
4480
4498
  @blur=${() => this._commitEdit()}>
@@ -4482,7 +4500,7 @@ var K = {
4482
4500
  if (t.type === "date" || t.type === "datetime") {
4483
4501
  let e = t.type === "datetime";
4484
4502
  return i`
4485
- <u-date-picker class="ft-editor ft-editor-${t.type}" size="sm"
4503
+ <u-date-picker class="ft-editor ft-editor-${t.type}" size="sm" aria-label=${t.label}
4486
4504
  mode=${e ? "datetime" : "date"} ?confirm=${e}
4487
4505
  .value=${Qe(n, e)}
4488
4506
  @keydown=${this._onEditorKeyDown}
@@ -4493,7 +4511,7 @@ var K = {
4493
4511
  if (t.type === "select" && t.options && t.options.length > 0) {
4494
4512
  let e = t.options, r = typeof e[0] == "string";
4495
4513
  return i`
4496
- <select class="ft-editor"
4514
+ <select class="ft-editor" aria-label=${t.label}
4497
4515
  @keydown=${this._onEditorKeyDown}
4498
4516
  @blur=${() => this._commitEdit()}
4499
4517
  @change=${() => this._commitEdit()}>
@@ -4504,15 +4522,20 @@ var K = {
4504
4522
  if (t.autocomplete) {
4505
4523
  let e = this._autocompleteState?.candidates ?? [], n = this._autocompleteState?.activeIndex ?? -1;
4506
4524
  return i`
4507
- <input class="ft-editor" type="text"
4525
+ <input class="ft-editor" type="text" aria-label=${t.label}
4526
+ role="combobox" aria-autocomplete="list"
4527
+ aria-expanded=${e.length > 0 ? "true" : "false"}
4528
+ aria-controls="ft-autocomplete-list"
4529
+ aria-activedescendant=${n >= 0 && e.length > 0 ? `ft-autocomplete-${n}` : a}
4508
4530
  .value=${r}
4509
4531
  @input=${(e) => this._onAutocompleteInput(e, t)}
4510
4532
  @keydown=${this._onEditorKeyDown}
4511
4533
  @blur=${() => this._commitEdit()}>
4512
4534
  ${e.length > 0 ? i`
4513
- <div class="ft-autocomplete-dropdown">
4535
+ <div class="ft-autocomplete-dropdown" id="ft-autocomplete-list" role="listbox" aria-label=${t.label}>
4514
4536
  ${e.map((e, t) => i`
4515
4537
  <div class="ft-autocomplete-item ${t === n ? "ft-autocomplete-active" : ""}"
4538
+ id=${`ft-autocomplete-${t}`} role="option" aria-selected=${t === n ? "true" : "false"}
4516
4539
  @mousedown=${(t) => {
4517
4540
  t.preventDefault(), this._selectAutocompleteCandidate(e);
4518
4541
  }}>
@@ -4524,7 +4547,7 @@ var K = {
4524
4547
  `;
4525
4548
  }
4526
4549
  return i`
4527
- <input class="ft-editor" type="text"
4550
+ <input class="ft-editor" type="text" aria-label=${t.label}
4528
4551
  .value=${r}
4529
4552
  @keydown=${this._onEditorKeyDown}
4530
4553
  @blur=${() => this._commitEdit()}>
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./flex-table-Do-AzEj5.js";
1
+ import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./flex-table-CL29tbBZ.js";
2
2
  export { o as FlexTable, e as RowSelectionState, t as UndoStack, n as effectiveAlign, i as exportData, r as flexTableLocale, a as renderCell };
package/dist/locale.d.ts CHANGED
@@ -25,7 +25,7 @@
25
25
  * (아이콘 자리의 글리프)는 어느 로케일에서도 같은 것을 뜻하며, 번역하면 오히려 읽히지 않는다.
26
26
  * 그 판단은 «번역하지 않기로 한 것»이지 «빠뜨린 것»이 아니다.
27
27
  */
28
- export type FlexTableMessageKey = 'showHiddenColumns' | 'columnMenu' | 'cellActions' | 'noColumnsDefined' | 'addCommentPlaceholder' | 'cancel' | 'save' | 'clear' | 'blankCells' | 'emptyOnly' | 'nonEmptyOnly' | 'blankAll' | 'all' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'searchPlaceholder' | 'valuePlaceholder' | 'fromPlaceholder' | 'toPlaceholder' | 'findPlaceholder' | 'findPrevious' | 'findNext' | 'matchCase' | 'wholeCell' | 'closeFind' | 'findNoResults' | 'replaceWithPlaceholder' | 'replace' | 'replaceAll' | 'sortAscending' | 'sortDescending' | 'filter' | 'clearFilter' | 'hideColumn' | 'showColumn' | 'autoFitWidth' | 'wider' | 'narrower' | 'columnMenuFor' | 'columnMenuRegion' | 'copy' | 'insertRowAbove' | 'insertRowBelow' | 'deleteRow' | 'selectRow' | 'selectAllRows' | 'filterByThisValue' | 'addComment' | 'editComment' | 'deleteComment' | 'booleanTrue' | 'booleanFalse' | 'dropFileToImport' | 'notANumber' | 'notADate' | 'notADateTime' | 'notInList';
28
+ export type FlexTableMessageKey = 'showHiddenColumns' | 'columnMenu' | 'cellActions' | 'noColumnsDefined' | 'addCommentPlaceholder' | 'cancel' | 'save' | 'clear' | 'blankCells' | 'emptyOnly' | 'nonEmptyOnly' | 'blankAll' | 'all' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'searchPlaceholder' | 'valuePlaceholder' | 'fromPlaceholder' | 'toPlaceholder' | 'findPlaceholder' | 'findPrevious' | 'findNext' | 'matchCase' | 'wholeCell' | 'closeFind' | 'findNoResults' | 'replaceWithPlaceholder' | 'replace' | 'replaceAll' | 'findInput' | 'replaceInput' | 'filterFor' | 'filterMatchMode' | 'filterText' | 'conditionOperator' | 'conditionValue' | 'conditionJoin' | 'sortAscending' | 'sortDescending' | 'filter' | 'clearFilter' | 'hideColumn' | 'showColumn' | 'autoFitWidth' | 'wider' | 'narrower' | 'columnMenuFor' | 'columnMenuRegion' | 'copy' | 'insertRowAbove' | 'insertRowBelow' | 'deleteRow' | 'selectRow' | 'selectAllRows' | 'filterByThisValue' | 'addComment' | 'editComment' | 'deleteComment' | 'booleanTrue' | 'booleanFalse' | 'dropFileToImport' | 'notANumber' | 'notADate' | 'notADateTime' | 'notInList';
29
29
  /** 이 패키지의 chrome 문자열 묶음. 소비자가 `register()` 로 언어를 더하거나 문구를 덮을 수 있다. */
30
30
  export declare const flexTableLocale: import("@iyulab/components/dist/utilities/Locale.js").LocaleNamespace<FlexTableMessageKey>;
31
31
  /** 짧은 조회 별칭 — 렌더 코드가 읽히게 유지한다. */
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as e } from "./flex-table-Do-AzEj5.js";
1
+ import { t as e } from "./flex-table-CL29tbBZ.js";
2
2
  import { i as t, t as n } from "./query-Dw4iO0ir.js";
3
3
  import { t as r } from "./view-DiLr-TdY.js";
4
4
  import i, { useCallback as a, useEffect as o, useMemo as s, useRef as c, useState as l } from "react";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/flex-table",
3
- "version": "0.48.4",
3
+ "version": "0.48.5",
4
4
  "description": "A minimalist, input-centric data grid web component",
5
5
  "type": "module",
6
6
  "main": "./dist/flex-table.js",