@operato/data-grist 10.10.0 → 10.10.2

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/coverage/lcov-report/base.css +224 -0
  3. package/coverage/lcov-report/block-navigation.js +87 -0
  4. package/coverage/lcov-report/favicon.png +0 -0
  5. package/coverage/lcov-report/index.html +866 -0
  6. package/coverage/lcov-report/prettify.css +1 -0
  7. package/coverage/lcov-report/prettify.js +2 -0
  8. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  9. package/coverage/lcov-report/sorter.js +210 -0
  10. package/coverage/lcov-report/webpack/bootstrap.html +118 -0
  11. package/coverage/lcov-report/webpack/index.html +116 -0
  12. package/coverage/lcov-report/webpack/runtime/define property getters.html +118 -0
  13. package/coverage/lcov-report/webpack/runtime/global.html +118 -0
  14. package/coverage/lcov-report/webpack/runtime/hasOwnProperty shorthand.html +118 -0
  15. package/coverage/lcov-report/webpack/runtime/index.html +161 -0
  16. package/coverage/lcov-report/webpack/runtime/make namespace object.html +118 -0
  17. package/coverage/lcov.info +53451 -0
  18. package/dist/src/configure/column-builder.js +6 -7
  19. package/dist/src/configure/column-builder.js.map +1 -1
  20. package/dist/src/data-grid/data-grid-body-style.js +4 -4
  21. package/dist/src/data-grid/data-grid-body-style.js.map +1 -1
  22. package/dist/src/data-grid/data-grid-body.d.ts +11 -11
  23. package/dist/src/data-grid/data-grid-body.js +33 -35
  24. package/dist/src/data-grid/data-grid-body.js.map +1 -1
  25. package/dist/src/data-grid/data-grid-field.js +13 -0
  26. package/dist/src/data-grid/data-grid-field.js.map +1 -1
  27. package/dist/src/data-grid/data-grid-header.d.ts +6 -6
  28. package/dist/src/data-grid/data-grid-header.js +22 -21
  29. package/dist/src/data-grid/data-grid-header.js.map +1 -1
  30. package/dist/src/data-grid/data-grid.d.ts +4 -4
  31. package/dist/src/data-grid/data-grid.js +24 -24
  32. package/dist/src/data-grid/data-grid.js.map +1 -1
  33. package/dist/src/data-grist.d.ts +3 -3
  34. package/dist/src/data-grist.js.map +1 -1
  35. package/dist/src/editors/ox-grist-editor.d.ts +9 -7
  36. package/dist/src/editors/ox-grist-editor.js +9 -7
  37. package/dist/src/editors/ox-grist-editor.js.map +1 -1
  38. package/dist/src/filters/filter-input.js +6 -5
  39. package/dist/src/filters/filter-input.js.map +1 -1
  40. package/dist/src/filters/filter-range-date.js +3 -3
  41. package/dist/src/filters/filter-range-date.js.map +1 -1
  42. package/dist/src/filters/filter-range-number.js +3 -3
  43. package/dist/src/filters/filter-range-number.js.map +1 -1
  44. package/dist/src/gutters/gutter-row-selector.js +6 -6
  45. package/dist/src/gutters/gutter-row-selector.js.map +1 -1
  46. package/dist/src/renderers/ox-grist-renderer-boolean.js +3 -3
  47. package/dist/src/renderers/ox-grist-renderer-boolean.js.map +1 -1
  48. package/dist/src/types.d.ts +5 -5
  49. package/dist/src/types.js.map +1 -1
  50. package/dist/src/utils/column-text.d.ts +10 -10
  51. package/dist/src/utils/column-text.js +10 -10
  52. package/dist/src/utils/column-text.js.map +1 -1
  53. package/dist/test/accessible-name.test.js +84 -86
  54. package/dist/test/accessible-name.test.js.map +1 -1
  55. package/dist/tsconfig.tsbuildinfo +1 -1
  56. package/package.json +3 -3
  57. package/test/accessible-name.test.ts +84 -86
@@ -21,15 +21,14 @@ export const buildColumn = (column) => {
21
21
  var { name, header, record, handlers, label, filter } = compiled;
22
22
  /* header */
23
23
  /*
24
- * 이름을 글자로도 남긴다 — renderer 하나만 두면 이름이 여기서 사라진다.
24
+ * Keep the name as text too — with only a renderer, the name disappears here.
25
25
  *
26
- * 설정이 header: '상태' 처럼 문자열로 들어와도 여기를 지나면 () => '상태' 한 개만 남는다.
27
- * 그 함수가 돌려주는 것은 화면에 그릴 조각(대개 lit template)이라 되읽을 수 없다. 그래서 화면 밖에서
28
- * 이름이 필요한 곳 — 스크린 리더가 읽을 이름, filter 입력칸의 이름 — 이 이름을 구할 데가 없었고,
29
- * 결국 각자 다시 적어 두는 수밖에 없었다. 한 사실에 출처가 둘이 되면 header 를 고쳐도 나머지가
30
- * 그대로 남는다.
26
+ * `header: 'Status'` leaves this block as `() => 'Status'` and nothing else. That function returns
27
+ * a lit template, which cannot be read back, so everything that needs the name outside of
28
+ * rendering — accessible names, header filter inputs — had nowhere to get it and ended up
29
+ * spelling it out again. Two sources for one fact means editing `header` leaves the rest behind.
31
30
  *
32
- * 그리는 것과 이름을 함께 남긴다. columnText() 가 이것을 읽는다.
31
+ * Store what to draw and what it is called. `columnText()` reads this.
33
32
  */
34
33
  if (typeof header == 'string') {
35
34
  compiled.header = {
@@ -1 +1 @@
1
- {"version":3,"file":"column-builder.js","sourceRoot":"","sources":["../../../src/configure/column-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import { FilterConfigObject, FilterOperator } from '../index.js'\nimport { NOOP } from '../const.js'\nimport { getEditor } from '../editors/index.js'\nimport { generateGutterColumn } from '../gutters/index.js'\nimport { getGristEventHandler } from '../handlers/index.js'\nimport { getRenderer } from '../renderers/index.js'\nimport { ColumnConfig } from '../types.js'\n\n/**\n * 값을 오른쪽에 붙이는 칸.\n *\n * 자릿수가 세로로 맞아야 값을 견줄 수 있다. 왼쪽으로 두면 24 와 1,200 이 시작점만 같고 끝이 어긋나서\n * 어느 쪽이 큰지 눈으로 읽히지 않는다.\n *\n * progress 는 뺀다 — 막대로 그리므로 정렬이 뜻을 갖지 않는다.\n */\nconst RIGHT_ALIGNED_TYPES = ['integer', 'float', 'number']\n\nexport const buildColumn = (column: any): ColumnConfig => {\n var compiled: ColumnConfig = { ...column }\n\n if (column.type == 'gutter') {\n compiled = generateGutterColumn(column)\n }\n\n var { name, header, record, handlers, label, filter } = compiled\n\n /* header */\n\n /*\n * 이름을 글자로도 남긴다 — renderer 하나만 두면 이름이 여기서 사라진다.\n *\n * 설정이 header: '상태' 처럼 문자열로 들어와도 여기를 지나면 () => '상태' 한 개만 남는다.\n * 그 함수가 돌려주는 것은 화면에 그릴 조각(대개 lit template)이라 되읽을 수 없다. 그래서 화면 밖에서\n * 이름이 필요한 곳 — 스크린 리더가 읽을 이름, filter 입력칸의 이름 — 이 이름을 구할 데가 없었고,\n * 결국 각자 다시 적어 두는 수밖에 없었다. 한 사실에 출처가 둘이 되면 header 를 고쳐도 나머지가\n * 그대로 남는다.\n *\n * 그리는 것과 이름을 함께 남긴다. columnText() 가 이것을 읽는다.\n */\n if (typeof header == 'string') {\n compiled.header = {\n text: header,\n renderer: () => header\n }\n }\n\n if (typeof compiled.header?.renderer == 'string') {\n const text = compiled.header.renderer\n compiled.header = {\n ...compiled.header,\n text,\n renderer: () => text\n }\n }\n\n /* label */\n if (label) {\n let type = typeof label\n switch (type) {\n case 'boolean':\n compiled.label = {\n text: compiled.header?.text || name,\n renderer: compiled.header?.renderer || (() => name)\n }\n break\n case 'string':\n compiled.label = {\n text: label as string,\n renderer: () => label\n }\n break\n default:\n compiled.label = label\n }\n } else {\n compiled.label = false\n }\n\n /*\n * record\n */\n var { renderer: recordRenderer, editor, editable, classifier } = record || {}\n\n recordRenderer = getRenderer(recordRenderer || column.type)\n\n if (editable !== false && typeof editor !== 'function') {\n editor = getEditor(column.type)\n }\n\n if (typeof classifier !== 'function') {\n classifier = NOOP\n }\n\n compiled.record = {\n /*\n * 숫자 칸의 기본 정렬. 화면이 align 을 주면 그것이 이긴다 — 자릿수를 견줄 값이 아닌 숫자\n * (전화번호 · 우편번호 같은 것)는 화면이 따로 정한다.\n *\n * 머리글도 따라온다. data-grid-header 가 열 제목을 그릴 때 record.align 을 본다.\n */\n ...(RIGHT_ALIGNED_TYPES.includes(column.type) ? { align: 'right' } : {}),\n ...record,\n classifier,\n renderer: recordRenderer,\n editor\n }\n\n /* filter */\n if (filter) {\n let type = typeof filter\n switch (type) {\n case 'boolean':\n compiled.filter = {\n type: column.type,\n operator: 'eq'\n }\n break\n case 'string':\n compiled.filter = {\n type: column.type,\n operator: filter as FilterOperator\n }\n break\n default:\n compiled.filter = {\n //@ts-ignore\n type: column.type,\n operator: 'eq',\n ...(filter as FilterConfigObject)\n }\n }\n }\n\n /* handler */\n var { click, dblclick, focus, contextmenu } = handlers || {}\n\n compiled.handlers = {\n click: click && getGristEventHandler(click),\n dblclick: dblclick && getGristEventHandler(dblclick),\n focus: focus && getGristEventHandler(focus),\n contextmenu: contextmenu && getGristEventHandler(contextmenu)\n }\n\n return compiled\n}\n"]}
1
+ {"version":3,"file":"column-builder.js","sourceRoot":"","sources":["../../../src/configure/column-builder.ts"],"names":[],"mappings":"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","sourcesContent":["import { FilterConfigObject, FilterOperator } from '../index.js'\nimport { NOOP } from '../const.js'\nimport { getEditor } from '../editors/index.js'\nimport { generateGutterColumn } from '../gutters/index.js'\nimport { getGristEventHandler } from '../handlers/index.js'\nimport { getRenderer } from '../renderers/index.js'\nimport { ColumnConfig } from '../types.js'\n\n/**\n * 값을 오른쪽에 붙이는 칸.\n *\n * 자릿수가 세로로 맞아야 값을 견줄 수 있다. 왼쪽으로 두면 24 와 1,200 이 시작점만 같고 끝이 어긋나서\n * 어느 쪽이 큰지 눈으로 읽히지 않는다.\n *\n * progress 는 뺀다 — 막대로 그리므로 정렬이 뜻을 갖지 않는다.\n */\nconst RIGHT_ALIGNED_TYPES = ['integer', 'float', 'number']\n\nexport const buildColumn = (column: any): ColumnConfig => {\n var compiled: ColumnConfig = { ...column }\n\n if (column.type == 'gutter') {\n compiled = generateGutterColumn(column)\n }\n\n var { name, header, record, handlers, label, filter } = compiled\n\n /* header */\n\n /*\n * Keep the name as text too — with only a renderer, the name disappears here.\n *\n * `header: 'Status'` leaves this block as `() => 'Status'` and nothing else. That function returns\n * a lit template, which cannot be read back, so everything that needs the name outside of\n * rendering — accessible names, header filter inputs — had nowhere to get it and ended up\n * spelling it out again. Two sources for one fact means editing `header` leaves the rest behind.\n *\n * Store what to draw and what it is called. `columnText()` reads this.\n */\n if (typeof header == 'string') {\n compiled.header = {\n text: header,\n renderer: () => header\n }\n }\n\n if (typeof compiled.header?.renderer == 'string') {\n const text = compiled.header.renderer\n compiled.header = {\n ...compiled.header,\n text,\n renderer: () => text\n }\n }\n\n /* label */\n if (label) {\n let type = typeof label\n switch (type) {\n case 'boolean':\n compiled.label = {\n text: compiled.header?.text || name,\n renderer: compiled.header?.renderer || (() => name)\n }\n break\n case 'string':\n compiled.label = {\n text: label as string,\n renderer: () => label\n }\n break\n default:\n compiled.label = label\n }\n } else {\n compiled.label = false\n }\n\n /*\n * record\n */\n var { renderer: recordRenderer, editor, editable, classifier } = record || {}\n\n recordRenderer = getRenderer(recordRenderer || column.type)\n\n if (editable !== false && typeof editor !== 'function') {\n editor = getEditor(column.type)\n }\n\n if (typeof classifier !== 'function') {\n classifier = NOOP\n }\n\n compiled.record = {\n /*\n * 숫자 칸의 기본 정렬. 화면이 align 을 주면 그것이 이긴다 — 자릿수를 견줄 값이 아닌 숫자\n * (전화번호 · 우편번호 같은 것)는 화면이 따로 정한다.\n *\n * 머리글도 따라온다. data-grid-header 가 열 제목을 그릴 때 record.align 을 본다.\n */\n ...(RIGHT_ALIGNED_TYPES.includes(column.type) ? { align: 'right' } : {}),\n ...record,\n classifier,\n renderer: recordRenderer,\n editor\n }\n\n /* filter */\n if (filter) {\n let type = typeof filter\n switch (type) {\n case 'boolean':\n compiled.filter = {\n type: column.type,\n operator: 'eq'\n }\n break\n case 'string':\n compiled.filter = {\n type: column.type,\n operator: filter as FilterOperator\n }\n break\n default:\n compiled.filter = {\n //@ts-ignore\n type: column.type,\n operator: 'eq',\n ...(filter as FilterConfigObject)\n }\n }\n }\n\n /* handler */\n var { click, dblclick, focus, contextmenu } = handlers || {}\n\n compiled.handlers = {\n click: click && getGristEventHandler(click),\n dblclick: dblclick && getGristEventHandler(dblclick),\n focus: focus && getGristEventHandler(focus),\n contextmenu: contextmenu && getGristEventHandler(contextmenu)\n }\n\n return compiled\n}\n"]}
@@ -24,11 +24,11 @@ export const dataGridBodyStyle = css `
24
24
  }
25
25
 
26
26
  /*
27
- * 줄 감싸개 — 상자를 만들지 않는다.
27
+ * Row wrapper — generates no box.
28
28
  *
29
- * role=row 를 담기 위한 요소일 뿐이라 배치에는 끼어들면 안 된다. display: contents 면 이 요소는
30
- * 상자를 만들지 않고 자식이 그대로 바깥 grid 의 항목이 된다 — 열 폭 · 고정 열 · 묶음 머리의
31
- * grid-column 배치가 그대로다.
29
+ * It exists only to carry role=row, so it must stay out of layout. With display: contents the
30
+ * element produces no box and its children remain items of the outer grid — column widths, fixed
31
+ * columns and the grid-column placement of group headers are untouched.
32
32
  */
33
33
  div[grid-row] {
34
34
  display: contents;
@@ -1 +1 @@
1
- {"version":3,"file":"data-grid-body-style.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid-body-style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsJnC,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport const dataGridBodyStyle = css`\n :host {\n display: grid;\n grid-template-columns: var(--grid-template-columns);\n grid-auto-rows: var(--grid-record-height, min-content);\n\n overflow: auto;\n /*\n * 세로 스크롤바 자리를 늘 비워 둔다 — 머리와 가로 스크롤 범위를 같게 만들기 위해서다.\n *\n * 머리는 overflow: hidden 이라 스크롤바에 자리를 내주지 않고, 몸은 긴 목록에서 스크롤바 폭만큼\n * 좁아진다. 그래서 갈 수 있는 거리가 몸이 그만큼 더 길었고, 오른쪽 끝에서 몸만 더 갔다.\n * 확인해 보니 정확히 --scrollbar-width 만큼(5px)이었다.\n *\n * 자리를 늘 비워 두면 목록 길이와 무관하게 두 폭이 같다. 목록이 길어질 때 열이 움찔하는 것도\n * 함께 없어진다 — 스크롤바가 생기는 순간 폭이 바뀌지 않는다.\n */\n scrollbar-gutter: stable;\n outline: none;\n color: var(--grid-record-color);\n position: relative;\n border-bottom: var(--grid-body-bottom-border);\n }\n\n /*\n * 줄 감싸개 — 상자를 만들지 않는다.\n *\n * role=row 를 담기 위한 요소일 뿐이라 배치에는 끼어들면 안 된다. display: contents 면 이 요소는\n * 상자를 만들지 않고 자식이 그대로 바깥 grid 의 항목이 된다 — 열 폭 · 고정 열 · 묶음 머리의\n * grid-column 배치가 그대로다.\n */\n div[grid-row] {\n display: contents;\n }\n\n ox-grid-field[odd] {\n background-color: var(--grid-record-odd-background-color);\n }\n\n ox-grid-field[disabled] {\n background-color: var(--grid-record-disabled-background-color, var(--grid-record-background-color));\n color: var(--grid-record-disabled-color, var(--grid-record-color));\n opacity: var(--grid-record-disabled-opacity, 1);\n }\n ox-grid-field[odd][disabled] {\n background-color: var(\n --grid-odd-record-disabled-background-color,\n var(--grid-record-disabled-background-color, var(--grid-record-odd-background-color))\n );\n color: var(--grid-odd-record-disabled-color, var(--grid-record-disabled-color, var(--grid-record-color)));\n opacity: var(--grid-odd-record-disabled-opacity, var(--grid-record-disabled-opacity, 1));\n }\n\n ox-grid-field[selected-row] {\n background-color: var(--grid-record-selected-background-color);\n color: var(--grid-record-selected-color);\n }\n\n /*\n * 마우스가 지나는 줄.\n *\n * 고른 줄보다 **훨씬 옅다.** 지나는 것은 사실이 아니고 눈이 어디 있는지 알려 주는 것뿐이라, 고른\n * 줄과 같은 무게로 그리면 무엇이 골라졌는지 헷갈린다. 그래서 고른 줄 규칙 뒤에 둔다 — 둘이 겹칠\n * 때는 고른 쪽이 이겨야 하므로 색을 옅게 두고 순서로 다투지 않는다.\n *\n * 값은 표가 정한다. 고치는 표에서는 비운다(data-grid.ts) — 거기서는 점선 셀 테두리가 이미 자리를\n * 말하고, 둘이 함께 있으면 시끄럽다.\n */\n @media (hover: hover) {\n ox-grid-field[hovered-row]:not([selected-row]) {\n background-color: var(--grid-record-hover-background-color, transparent);\n }\n }\n\n ox-grid-field[focused-row] {\n box-shadow: var(--grid-record-focused-box-shadow);\n font-weight: bold;\n color: var(--grid-record-focused-color);\n background-image: var(--focused-background-image);\n background-blend-mode: darken;\n }\n\n /*\n * 초점 셀 표식 — border 가 아니라 outline 으로 그린다.\n *\n * border 로 그리면 두 가지가 깨진다.\n * · 네 면 테두리가 셀 크기를 바꿔 줄이 어긋난다\n * · 아래 면이 **줄을 나누는 선 자리**를 차지해, 그 셀만 줄 선이 사라진다\n *\n * outline 은 자리를 차지하지 않는다. outline-offset: -1px 로 안쪽에 그려 옆 셀과 겹치지 않게 한다.\n * 표식을 감추고 싶은 화면은 토큰을 none 으로 두면 되고, 그래도 줄 선은 남는다.\n */\n ox-grid-field[focused] {\n outline: var(--grid-record-focused-cell-border);\n outline-offset: -1px;\n }\n\n ox-grid-field[emphasized-row],\n ox-grid-field[emphasized-row][focused] {\n background-color: var(--grid-record-emphasized-background-color);\n color: var(--grid-record-emphasized-color);\n }\n\n ox-grid-field[editing] {\n background-color: var(--grid-record-editing-background-color);\n }\n\n @media print {\n :host {\n grid-template-columns: var(--grid-template-print-columns);\n }\n ox-grid-field[focused] {\n outline: none;\n }\n\n ox-grid-field[selected-row] {\n background-color: transparent;\n }\n\n /* 종이에는 마우스가 없다. */\n ox-grid-field[hovered-row] {\n background-color: transparent;\n }\n\n ox-grid-field[emphasized-row] {\n background-color: transparent;\n color: initial;\n }\n\n ox-grid-field[focused-row] {\n background-color: transparent;\n color: initial;\n }\n\n ox-grid-field[editing] {\n background-color: transparent;\n }\n }\n\n @media (prefers-color-scheme: dark) {\n ox-grid-field[focused-row] {\n background-blend-mode: lighten;\n }\n }\n\n @media (prefers-color-scheme: light) {\n ox-grid-field[focused-row] {\n background-blend-mode: darken;\n }\n }\n`\n"]}
1
+ {"version":3,"file":"data-grid-body-style.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid-body-style.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsJnC,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport const dataGridBodyStyle = css`\n :host {\n display: grid;\n grid-template-columns: var(--grid-template-columns);\n grid-auto-rows: var(--grid-record-height, min-content);\n\n overflow: auto;\n /*\n * 세로 스크롤바 자리를 늘 비워 둔다 — 머리와 가로 스크롤 범위를 같게 만들기 위해서다.\n *\n * 머리는 overflow: hidden 이라 스크롤바에 자리를 내주지 않고, 몸은 긴 목록에서 스크롤바 폭만큼\n * 좁아진다. 그래서 갈 수 있는 거리가 몸이 그만큼 더 길었고, 오른쪽 끝에서 몸만 더 갔다.\n * 확인해 보니 정확히 --scrollbar-width 만큼(5px)이었다.\n *\n * 자리를 늘 비워 두면 목록 길이와 무관하게 두 폭이 같다. 목록이 길어질 때 열이 움찔하는 것도\n * 함께 없어진다 — 스크롤바가 생기는 순간 폭이 바뀌지 않는다.\n */\n scrollbar-gutter: stable;\n outline: none;\n color: var(--grid-record-color);\n position: relative;\n border-bottom: var(--grid-body-bottom-border);\n }\n\n /*\n * Row wrapper — generates no box.\n *\n * It exists only to carry role=row, so it must stay out of layout. With display: contents the\n * element produces no box and its children remain items of the outer grid — column widths, fixed\n * columns and the grid-column placement of group headers are untouched.\n */\n div[grid-row] {\n display: contents;\n }\n\n ox-grid-field[odd] {\n background-color: var(--grid-record-odd-background-color);\n }\n\n ox-grid-field[disabled] {\n background-color: var(--grid-record-disabled-background-color, var(--grid-record-background-color));\n color: var(--grid-record-disabled-color, var(--grid-record-color));\n opacity: var(--grid-record-disabled-opacity, 1);\n }\n ox-grid-field[odd][disabled] {\n background-color: var(\n --grid-odd-record-disabled-background-color,\n var(--grid-record-disabled-background-color, var(--grid-record-odd-background-color))\n );\n color: var(--grid-odd-record-disabled-color, var(--grid-record-disabled-color, var(--grid-record-color)));\n opacity: var(--grid-odd-record-disabled-opacity, var(--grid-record-disabled-opacity, 1));\n }\n\n ox-grid-field[selected-row] {\n background-color: var(--grid-record-selected-background-color);\n color: var(--grid-record-selected-color);\n }\n\n /*\n * 마우스가 지나는 줄.\n *\n * 고른 줄보다 **훨씬 옅다.** 지나는 것은 사실이 아니고 눈이 어디 있는지 알려 주는 것뿐이라, 고른\n * 줄과 같은 무게로 그리면 무엇이 골라졌는지 헷갈린다. 그래서 고른 줄 규칙 뒤에 둔다 — 둘이 겹칠\n * 때는 고른 쪽이 이겨야 하므로 색을 옅게 두고 순서로 다투지 않는다.\n *\n * 값은 표가 정한다. 고치는 표에서는 비운다(data-grid.ts) — 거기서는 점선 셀 테두리가 이미 자리를\n * 말하고, 둘이 함께 있으면 시끄럽다.\n */\n @media (hover: hover) {\n ox-grid-field[hovered-row]:not([selected-row]) {\n background-color: var(--grid-record-hover-background-color, transparent);\n }\n }\n\n ox-grid-field[focused-row] {\n box-shadow: var(--grid-record-focused-box-shadow);\n font-weight: bold;\n color: var(--grid-record-focused-color);\n background-image: var(--focused-background-image);\n background-blend-mode: darken;\n }\n\n /*\n * 초점 셀 표식 — border 가 아니라 outline 으로 그린다.\n *\n * border 로 그리면 두 가지가 깨진다.\n * · 네 면 테두리가 셀 크기를 바꿔 줄이 어긋난다\n * · 아래 면이 **줄을 나누는 선 자리**를 차지해, 그 셀만 줄 선이 사라진다\n *\n * outline 은 자리를 차지하지 않는다. outline-offset: -1px 로 안쪽에 그려 옆 셀과 겹치지 않게 한다.\n * 표식을 감추고 싶은 화면은 토큰을 none 으로 두면 되고, 그래도 줄 선은 남는다.\n */\n ox-grid-field[focused] {\n outline: var(--grid-record-focused-cell-border);\n outline-offset: -1px;\n }\n\n ox-grid-field[emphasized-row],\n ox-grid-field[emphasized-row][focused] {\n background-color: var(--grid-record-emphasized-background-color);\n color: var(--grid-record-emphasized-color);\n }\n\n ox-grid-field[editing] {\n background-color: var(--grid-record-editing-background-color);\n }\n\n @media print {\n :host {\n grid-template-columns: var(--grid-template-print-columns);\n }\n ox-grid-field[focused] {\n outline: none;\n }\n\n ox-grid-field[selected-row] {\n background-color: transparent;\n }\n\n /* 종이에는 마우스가 없다. */\n ox-grid-field[hovered-row] {\n background-color: transparent;\n }\n\n ox-grid-field[emphasized-row] {\n background-color: transparent;\n color: initial;\n }\n\n ox-grid-field[focused-row] {\n background-color: transparent;\n color: initial;\n }\n\n ox-grid-field[editing] {\n background-color: transparent;\n }\n }\n\n @media (prefers-color-scheme: dark) {\n ox-grid-field[focused-row] {\n background-blend-mode: lighten;\n }\n }\n\n @media (prefers-color-scheme: light) {\n ox-grid-field[focused-row] {\n background-blend-mode: darken;\n }\n }\n`\n"]}
@@ -14,10 +14,10 @@ export declare class DataGridBody extends LitElement {
14
14
  column: number;
15
15
  };
16
16
  /**
17
- * 이 판의 첫 줄이 표 전체에서 몇 번째인가(1부터).
17
+ * Where this body's first row sits in the whole table, counting from 1.
18
18
  *
19
- * 머리줄 수와 페이지 자리를 합한 값이라 ox-grid 가 계산해서 내려 준다 — 여기서 다시 세면
20
- * 머리가 한 줄인지 두 줄인지(묶음 머리)를 몸이 알아야 한다.
19
+ * It combines header row count and page offset, so ox-grid computes it and passes it down —
20
+ * working it out here would mean the body has to know whether the header is one row or two.
21
21
  */
22
22
  ariaRowIndexBase: number;
23
23
  editTarget: {
@@ -55,13 +55,13 @@ export declare class DataGridBody extends LitElement {
55
55
  /** 지나는 줄을 옮긴다. 같은 줄이면 아무것도 하지 않는다. */
56
56
  private setHoveredRow;
57
57
  /**
58
- * 줄 하나 — 그 줄의 칸을 담고 있는 요소.
58
+ * One row — the element holding that row's cells.
59
59
  *
60
- * ── 자식을 세지 않는다 (2026-09-06) ────────────────────────────────────
61
- * 전에는 `renderRoot.children` 을 `줄번호 * (칸수 + 1)` 로 셌다. 「+1」은 남는 폭을 메우는
62
- * 빈 칸이고, 그 앞의 주석은 그 셈이 왜 필요한지를 설명하고 있었다 — 셈이 맞아야만 도는 코드였다.
60
+ * This used to index `renderRoot.children` at `rowIndex * (columns + 1)`, where the +1 was the
61
+ * width filler; the comment above it existed to explain why that arithmetic was necessary. The
62
+ * code only worked while the count stayed correct.
63
63
  *
64
- * 지금은 줄이 **실제 요소**다(role=row). 셀 필요가 없다.
64
+ * Rows are real elements now (role=row), so there is nothing to count.
65
65
  */
66
66
  private rowElementAt;
67
67
  private markRow;
@@ -90,10 +90,10 @@ export declare class DataGridBody extends LitElement {
90
90
  setSelectBlock(start?: DataGridField, end?: DataGridField): void;
91
91
  buildAccumulatorRecord(): GristRecord;
92
92
  /**
93
- * IME buffer 가 지금 어느 칸을 대신하고 있는지 — 스크린 리더가 읽을 이름.
93
+ * Which cell the IME buffer currently stands in for — the name a screen reader reads.
94
94
  *
95
- * 이름의 출처는 column 정의 하나다(columnText). 포커스가 아직 아무 칸에도 없거나 이름을 구할 수
96
- * 없으면 「칸 입력」으로 물러난다 — 이름을 지어내지 않고, 그렇다고 이름을 비우지도 않는다.
95
+ * The name comes from the column definition alone (columnText). When focus is on no cell, or the
96
+ * column yields no name, it falls back to "cell input" — no invented name, and no empty one.
97
97
  */
98
98
  private _imeBufferLabel;
99
99
  /** IME buffer를 포커스된 셀 위에 위치시킨다 */
@@ -89,10 +89,10 @@ let DataGridBody = class DataGridBody extends LitElement {
89
89
  this.data = ZERO_DATA;
90
90
  this.focused = ZERO_FOCUS;
91
91
  /**
92
- * 이 판의 첫 줄이 표 전체에서 몇 번째인가(1부터).
92
+ * Where this body's first row sits in the whole table, counting from 1.
93
93
  *
94
- * 머리줄 수와 페이지 자리를 합한 값이라 ox-grid 가 계산해서 내려 준다 — 여기서 다시 세면
95
- * 머리가 한 줄인지 두 줄인지(묶음 머리)를 몸이 알아야 한다.
94
+ * It combines header row count and page offset, so ox-grid computes it and passes it down —
95
+ * working it out here would mean the body has to know whether the header is one row or two.
96
96
  */
97
97
  this.ariaRowIndexBase = 2;
98
98
  this.editTarget = null;
@@ -133,11 +133,11 @@ let DataGridBody = class DataGridBody extends LitElement {
133
133
  var { appendable, classifier, accumulator } = this.config.rows;
134
134
  const { start, end } = this._selectBlock || {};
135
135
  /*
136
- * 줄을 고를 수 있는 표에서만 aria-selected 를 낸다.
136
+ * Only emit aria-selected where rows can actually be selected.
137
137
  *
138
- * 이 속성은 「고를 수 있는데 지금은 안 골랐다」는 뜻이라, 고를 수 없는 표의 모든 줄에 false 를
139
- * 달면 있지도 않은 기능을 있다고 말하게 된다. 고르는 장치가 있는지는 표가 스스로 안다 —
140
- * 줄 선택 거터가 있느냐다.
138
+ * The attribute means "selectable, currently not selected", so putting false on every row of a
139
+ * grid without selection announces a control that is not there. Whether selection exists is
140
+ * something the grid already knows: it has a row-selector gutter or it does not.
141
141
  */
142
142
  const selectable = columns.some(column => column.gutterName === 'row-selector');
143
143
  /*
@@ -152,13 +152,12 @@ let DataGridBody = class DataGridBody extends LitElement {
152
152
  var accumRecord = this.buildAccumulatorRecord();
153
153
  }
154
154
  /*
155
- * ── 줄이 몇 번째인가 ──────────────────────────────────────────────────
155
+ * aria-rowindex is the position in the whole table, not within the page on screen. The first
156
+ * row of page 2 is row 22, not row 1 again — otherwise every page turn resets the count and
157
+ * there is no way to tell how far through the data you are.
156
158
  *
157
- * aria-rowindex 는 **표 전체에서의 자리**다 — 지금 페이지 안의 자리가 아니다. 2페이지 첫 줄은
158
- * 21번째 줄이지 이 페이지의 1번째 줄이 아니다. 그렇게 읽어 주지 않으면 페이지를 넘길 때마다
159
- * 「1번째 줄」로 돌아가서 어디까지 봤는지 알 수 없다.
160
- *
161
- * 머리줄도 센다(1부터). 묶음 머리가 있으면 머리가 두 줄이라 본문은 3번부터 시작한다.
159
+ * Header rows count too, from 1. With a grouped header that is two rows, so the body starts
160
+ * at 3.
162
161
  */
163
162
  const rowIndexBase = this.ariaRowIndexBase;
164
163
  return html `
@@ -202,8 +201,8 @@ let DataGridBody = class DataGridBody extends LitElement {
202
201
  ></ox-grid-field>
203
202
  `)}
204
203
  <!--
205
- 남는 폭을 메우는 칸 — 읽을 것이 없다. 줄 안에는 두되(색이 함께 바뀌어야 한다) 표의
206
- 칸으로는 세지 않는다.
204
+ Width filler — nothing to read. It stays inside the row so hover and selection colour it
205
+ with the rest, but it is not counted as a cell.
207
206
  -->
208
207
  <ox-grid-field
209
208
  role="presentation"
@@ -247,16 +246,16 @@ let DataGridBody = class DataGridBody extends LitElement {
247
246
  : nothing}
248
247
  ${start && end && start !== end ? html ` <div select-block></div> ` : html ``}
249
248
  <!--
250
- 이 grid 의 키 입력은 이 입력칸이 받는다 — 칸을 눌러 편집을 열기 전까지 포커스가 여기에 있고,
251
- 한글 IME 의 조합 중간 글자도 여기에 쌓인다. 곧 **포커스가 실제로 놓이는 자리**다.
249
+ This input takes the grid's keystrokes. Focus rests here until a cell opens for editing, and
250
+ IME composition builds up in it — this is where focus actually lives.
252
251
 
253
- 전에는 이름이 없었다. 눈에 보이지 않으니(opacity: 0) 문제가 아니라고 볼 수 있는데, 그렇지 않다.
254
- 보이지 않는 것과 없는 것은 다르다 — 포커스를 받고 글자를 받는 입력칸이므로 스크린 리더는 이것을
255
- 읽는다. 이름이 없으면 「편집 텍스트」 하나로만 읽히고, grid 안에서 화살표로 아무리 옮겨 다녀도
256
- 읽히는 것이 바뀌지 않는다. 어느 칸에 서 있는지 알 방법이 없다.
252
+ It had no name. opacity: 0 makes that look harmless, but invisible is not the same as absent:
253
+ it receives focus and receives text, so a screen reader reads it. Unnamed, it reads as one
254
+ "edit text" and never changes, no matter how far the arrow keys travel — there is no way to
255
+ tell which cell you are on.
257
256
 
258
- aria-hidden 으로 감추는 것은 답이 아니다. 포커스를 받는 것을 보조기술에서 지우면 포커스가
259
- 허공으로 사라진 것처럼 된다. 감추는 대신 **지금 서 있는 칸의 이름**을 말한다.
257
+ aria-hidden is not the fix. Hiding the thing that holds focus makes focus vanish into
258
+ nothing. Instead of hiding it, name it after the cell it currently stands in for.
260
259
  -->
261
260
  <input
262
261
  id="ime-buffer"
@@ -472,13 +471,13 @@ let DataGridBody = class DataGridBody extends LitElement {
472
471
  this._hoveredRow = rowIndex;
473
472
  }
474
473
  /**
475
- * 줄 하나 — 그 줄의 칸을 담고 있는 요소.
474
+ * One row — the element holding that row's cells.
476
475
  *
477
- * ── 자식을 세지 않는다 (2026-09-06) ────────────────────────────────────
478
- * 전에는 `renderRoot.children` 을 `줄번호 * (칸수 + 1)` 로 셌다. 「+1」은 남는 폭을 메우는
479
- * 빈 칸이고, 그 앞의 주석은 그 셈이 왜 필요한지를 설명하고 있었다 — 셈이 맞아야만 도는 코드였다.
476
+ * This used to index `renderRoot.children` at `rowIndex * (columns + 1)`, where the +1 was the
477
+ * width filler; the comment above it existed to explain why that arithmetic was necessary. The
478
+ * code only worked while the count stayed correct.
480
479
  *
481
- * 지금은 줄이 **실제 요소**다(role=row). 셀 필요가 없다.
480
+ * Rows are real elements now (role=row), so there is nothing to count.
482
481
  */
483
482
  rowElementAt(rowIndex) {
484
483
  var _a;
@@ -493,9 +492,8 @@ let DataGridBody = class DataGridBody extends LitElement {
493
492
  return;
494
493
  }
495
494
  /*
496
- * 줄 안의 칸을 모두 바꾼다 — 남는 폭을 메우는 빈 칸까지.
497
- *
498
- * 전에는 그 빈 칸이 빠져서, 표가 화면보다 좁으면 줄 오른쪽이 잘려 보였다.
495
+ * Mark every cell in the row, width filler included. It used to be left out, so on a grid
496
+ * narrower than the viewport the right end of the row stayed uncoloured.
499
497
  */
500
498
  Array.from(row.children).forEach(cell => cell.toggleAttribute('hovered-row', on));
501
499
  }
@@ -508,7 +506,7 @@ let DataGridBody = class DataGridBody extends LitElement {
508
506
  if (!residue && columnIndex >= columns) {
509
507
  return;
510
508
  }
511
- /* 열 번호는 감는다 — 끝에서 오른쪽으로 가면 첫 열로 돌아온다(residue). */
509
+ /* Column index wraps: moving right from the last column returns to the first (residue). */
512
510
  return row.children.item((columnIndex + columns) % columns);
513
511
  }
514
512
  /**
@@ -1050,10 +1048,10 @@ let DataGridBody = class DataGridBody extends LitElement {
1050
1048
  }, {});
1051
1049
  }
1052
1050
  /**
1053
- * IME buffer 가 지금 어느 칸을 대신하고 있는지 — 스크린 리더가 읽을 이름.
1051
+ * Which cell the IME buffer currently stands in for — the name a screen reader reads.
1054
1052
  *
1055
- * 이름의 출처는 column 정의 하나다(columnText). 포커스가 아직 아무 칸에도 없거나 이름을 구할 수
1056
- * 없으면 「칸 입력」으로 물러난다 — 이름을 지어내지 않고, 그렇다고 이름을 비우지도 않는다.
1053
+ * The name comes from the column definition alone (columnText). When focus is on no cell, or the
1054
+ * column yields no name, it falls back to "cell input" — no invented name, and no empty one.
1057
1055
  */
1058
1056
  _imeBufferLabel(column) {
1059
1057
  const name = columnText(column);