@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
@@ -1 +1 @@
1
- {"version":3,"file":"data-grid-field.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid-field.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport i18next from 'i18next'\nimport { css, html, LitElement, PropertyValues, TemplateResult } from 'lit'\n// import { guard } from 'lit/directives/guard.js'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { TooltipReactiveController } from '@operato/utils'\n\nimport { ZERO_COLUMN } from '../configure/zero-config.js'\nimport { editorOpensPopup } from '../editors/registry.js'\nimport { ColumnConfig, GristRecord } from '../types.js'\n\nconst DEFAULT_TEXT_ALIGN = 'left'\n\n@customElement('ox-grid-field')\nexport class DataGridField extends LitElement {\n static styles = [\n css`\n :host {\n display: flex;\n\n align-items: center;\n justify-content: var(--data-grid-field-justify-content, flex-start);\n position: relative;\n\n white-space: nowrap;\n background-color: var(--grid-record-background-color);\n padding: var(--grid-record-padding);\n border: 1px solid transparent;\n border-width: 1px 0;\n border-bottom: var(--grid-record-border-bottom);\n\n font-size: var(--grid-record-wide-fontsize);\n min-height: 30px;\n box-sizing: border-box;\n }\n\n /*\n * ── 팝업으로 고치는 칸에는 **표식이 있다** ──────────────────────────────\n *\n * 그런 칸은 글자 칸과 똑같이 생겼다. 열어 보기 전에는 고칠 수 있는지도, 어떻게 고치는지도\n * 모른다 — 「실제 더블클릭을 하기 전에는 모르는 막막함」(사용자, 2026-09-05).\n *\n * **마우스를 올렸을 때 보인다.** 늘 보이게 두었더니 한 화면에 54개가 깔려 표가 시끄러웠다\n * (2026-09-05 · 사용자 판단). 값을 읽으러 온 눈에 장치가 줄마다 끼어든다.\n *\n * **손가락 화면에서는 늘 보인다.** 거기엔 올리는 동작이 없어서 감추면 길이 아예 없어진다.\n * 그 화면들은 표가 성기므로 늘 보여도 시끄럽지 않다.\n *\n * ── 네모와 펜을 쓴다 ─────────────────────────────────────────────────\n * 처음에 삼각형(arrow_drop_down)을 썼다. 참조 칸만 생각한 선택이었다 — 「목록에서 고른다」.\n *\n * 그런데 이 표식은 **팝업으로 여는 편집기 전부**에 붙는다. JSON · 코드 · 권한 편집기도\n * 그렇고, 거기서 삼각형은 거짓말이다. 고를 목록이 없다.\n *\n * ── 모양이 **어디서 고치는지**를 말한다 ────────────────────────────────\n *\n * edit 칸 안에서 고친다\n * edit_square 팝업이 열린다\n *\n * 표식이 있으면 고칠 수 있는 칸이고, 없으면 못 고치는 칸이다. **읽기 전용에는 붙지 않는다.**\n *\n * 처음에 삼각형(arrow_drop_down)을 썼다 — 참조 칸만 생각한 선택이었다. 이 표식은 JSON ·\n * 코드 · 권한 편집기에도 붙고, 거기서 삼각형은 고를 목록이 있다는 거짓말이 된다.\n *\n * 누를 자리는 22px 이다. 33px 줄에서 더블클릭을 겨누는 것보다 한 번 누르는 편이 쉽다.\n */\n /* 마우스 화면 — 칸에 올렸을 때만. 자리는 늘 잡아 두므로 글자가 밀리지 않는다. */\n @media (pointer: fine) {\n [popup-hint] {\n opacity: 0;\n transition: opacity 0.12s ease;\n }\n\n :host(:hover) [popup-hint] {\n opacity: 1;\n }\n }\n\n /*\n * 손가락 화면 — **고른 칸에만 보인다.**\n *\n * 올리는 동작이 없으니 호버로는 아무것도 못 보여 준다. 그렇다고 늘 보이게 두면 좁은\n * 화면이 표식으로 뒤덮인다 — 시끄러우면 정작 필요한 표식도 안 보인다.\n *\n * 고른 칸 하나에만 두면 둘 다 풀린다. 두드려 고르는 것이 그 화면의 첫 동작이므로,\n * 고르는 순간 「이 칸은 이렇게 고친다」가 나타난다.\n */\n @media (pointer: coarse) {\n [popup-hint] {\n display: none;\n }\n\n :host([focused]) [popup-hint] {\n display: flex;\n }\n }\n\n /*\n * ── 표식은 늘 **칸의 끝**에 있다. 정렬을 따라가지 않는다 (2026-09-05) ──────\n *\n * 찾는 데 드는 값이 커진다 정렬은 열마다 다르다(이름은 왼쪽, 수량은 오른쪽). 표식이\n * 그것을 따라가면 자리가 열마다 달라져 눈이 매번 찾아야 한다.\n * 끝에 고정하면 규칙이 하나다 — 「손잡이는 칸 끝에 있다」\n * 남의 칸처럼 보인다 오른쪽 정렬 칸의 값 **앞**에 표식을 두면 왼쪽 칸의 값 뒤에\n * 붙어 보인다. 어느 칸의 손잡이인지 흐려진다\n *\n * ── **값이 없는 쪽**에 붙는다 ──────────────────────────────────────\n * 왼쪽으로 붙인 칸의 빈자리는 오른쪽이고, 오른쪽으로 붙인 칸(수량 · 금액)의 빈자리는\n * 왼쪽이다. 정렬의 반대쪽에 두면 표식이 값 위에 얹히는 일 자체가 없어진다.\n *\n * 자리를 비워 두는 방법도 해 봤다 — 칸의 오른쪽을 24px 늘 비우는 것. 되돌렸다.\n * **자료가 먼저다**(사용자, 2026-09-05): 마우스를 올렸을 때만 보이는 안내 때문에 고칠 수\n * 있는 열 전부가 영구히 좁아지는 것은 값을 잘못 매긴 거래다.\n *\n * 가운데 정렬 칸은 양쪽이 다 비므로 끝에 둔다.\n */\n [popup-hint] {\n position: absolute;\n inset-inline-end: 2px;\n top: 50%;\n transform: translateY(-50%);\n\n --md-icon-size: 16px;\n font-size: 16px;\n width: 16px;\n height: 16px;\n padding: 3px;\n border-radius: 50%;\n\n /*\n * ── 채우지 않는다 (2026-09-05) ──────────────────────────────────\n * md-icon 이 물려주는 값은 FILL 1 이라 글리프가 통짜로 나온다. 두 가지가 어긋난다.\n *\n * 뜻 채운 글리프는 「지금 그 상태다」를 말한다(고른 것 · 켠 것). 이 표식이 말하는\n * 것은 상태가 아니라 **누르면 할 수 있는 일**이다. 그건 윤곽선의 몫이다\n * 밀도 표는 글자밭이다. 같은 16px 에서 채운 글리프는 잉크가 몇 곱절이라 값보다\n * 먼저 눈에 들어온다. 안내가 자료보다 진해서는 안 된다\n *\n * edit_square 는 특히 그렇다 — 채우면 네모가 덩어리가 되어 「종이 위의 연필」이라는\n * 그림이 뭉개진다. 진하기는 색으로 조절한다(아래 :hover).\n */\n /*\n * 굵기는 한 단 올린다. 16px 에서 400 짜리 윤곽선은 획이 배경에 묻는다 — 채움을 뺀 만큼\n * 획으로 되받는다. 잉크가 늘지 않으면서 형태는 또렷해진다.\n */\n font-variation-settings:\n 'FILL' 0,\n 'wght' 500,\n 'opsz' 20;\n\n /*\n * ── 값 **위에 그려지되, 값보다 앞서지 않는다** ──────────────────\n * 자리가 겹치면 표식이 위에 얹힌다. 그래도 이것은 거들어 주는 것이지 읽을 것이 아니다 —\n * 본문 색으로 두었더니 값과 같은 무게가 되어 눈이 먼저 표식으로 갔다(사용자, 2026-09-05).\n * 한 단 낮춰 라벨 색으로 둔다. 손이 표식 위에 오면 그때 본문 색이 된다.\n */\n color: var(--ui-muted, #57676f);\n cursor: pointer;\n\n transition:\n background-color 0.12s ease,\n color 0.12s ease;\n }\n\n /* 오른쪽으로 붙인 칸 — 값이 오른쪽 끝에 있으므로 표식은 왼쪽의 빈자리로 간다. */\n :host([mark-start]) [popup-hint] {\n inset-inline-end: auto;\n inset-inline-start: 2px;\n }\n\n [popup-hint]:hover {\n color: var(--ui-ink, #17272f);\n background-color: var(--ui-hover, color-mix(in srgb, currentColor 12%, transparent));\n }\n\n :host([multiline]) {\n white-space: pre-line;\n }\n\n /*\n * ── 칸이 쓸 수 있는 용어 (2026-08-31) ──────────────────────────────────\n * 렌더러가 그린 것은 이 부품의 shadow DOM 안에 들어간다. 그래서 **화면의 CSS 가 닿지 않는다.**\n * 두 줄 칸이나 상태 알약을 그리려던 화면들이 그 벽에 막혀, 값에 인라인 style 을 박거나 칸마다\n * 부품을 새로 만들었다.\n *\n * 목록이면 어디서나 같은 것을 필요로 하므로 여기서 준다. 이름은 뜻으로 짓는다 —\n * 「늦었다」가 아니라 「심각하다(crit)」다. 늦은 것은 이 표의 일이 아니고 화면의 일이다.\n *\n * .sub 둘째 줄. 「1,200 EA」 아래의 「BOLT-8」처럼 딸린 사실\n * .mono 고정폭. 번호·시각·수량처럼 자릿수를 비교하는 값\n * .none 값이 없음. 빈 칸으로 두면 「아직 안 읽었다」와 구별되지 않는다\n * .pill 알약. good·warn·crit·info 로 뜻을 준다\n * .crit · .warn · .good 글자 강조\n *\n * 값은 --ui-* 토큰에서 오고 폴백을 둔다 — 테마가 없어도 무너지지 않는다.\n */\n :host([twoline]) {\n display: block;\n white-space: normal;\n line-height: 1.35;\n }\n\n .sub {\n display: block;\n margin-top: 2px;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-faint, #8a959c);\n }\n\n .mono {\n font-family: var(--ui-mono, ui-monospace, Menlo, monospace);\n font-variant-numeric: tabular-nums;\n }\n\n /*\n * 그 줄이 무엇인지 가리키는 값 — 작업지시 번호, 설비 이름처럼. 두 줄 칸의 첫 줄이 이것이고\n * 둘째 줄(.sub)이 딸린 사실이다. 굵기만 올린다. 고정폭은 쓰지 않는다 — 자릿수를 세로로 견줄\n * 값이 아니고, 같은 글자 수에도 폭이 넓어져 옆 칸을 밀어낸다.\n */\n .id {\n font-weight: 620;\n }\n\n .none {\n color: var(--ui-faint, #8a959c);\n }\n\n .crit {\n color: var(--ui-crit, #c93f30);\n font-weight: 640;\n }\n\n .warn {\n color: var(--ui-warn, #9f5e02);\n font-weight: 640;\n }\n\n .good {\n color: var(--ui-good, #297d39);\n font-weight: 640;\n }\n\n /*\n * 값과 표식을 한 줄에 담는 영역이다. **간격과 높이를 여기서 정한다.**\n *\n * 처음에는 :not(.pill) + .pill { margin-left } 로 띄우려 했는데 안 걸렸다. 렌더러가 값을\n * 텍스트 노드로 내므로 알약의 앞 형제가 **요소가 아니고**, CSS 형제 선택자는 텍스트 노드를 보지\n * 못한다. 알약이 첫 요소이기도 해서 :first-child 로도 가려지지 않는다(실측 확인).\n *\n * 높이도 같은 자리에서 잡는다. baseline 으로 두면 14px 글자와 11.5px 알약의 기준선을 맞추느라\n * 알약이 내려앉는다.\n */\n /* 값이 있지만 눈에 걸릴 것은 아닌 것 — 「보통」 같은 기본값. .none(값 없음)과 구별한다. */\n .quiet {\n color: var(--ui-muted, #57676f);\n }\n\n /*\n * 별 같은 작은 기호를 글자 크기로 맞춘다. md-icon 의 기본은 24px 이라 줄 높이를 밀어낸다.\n * 색은 물려받는다 — 개수가 크기를 말하고 색은 담는 쪽이 정한다.\n */\n .star {\n --md-icon-size: 15px;\n font-size: 15px;\n width: 15px;\n height: 15px;\n color: inherit;\n }\n\n /* 별처럼 여럿이 붙는 기호는 사이를 좁게 둔다. 단어 사이의 6px 은 여기서 너무 넓다. */\n .line:has(.star) {\n gap: 1px;\n }\n\n /*\n * 셀 안의 아이콘 버튼. 그 줄에 하는 동작(들어가기 · 열기)을 담는다.\n *\n * 셀의 클릭 경로를 타지 않고 스스로 받으려는 렌더러가 쓴다. 그 경로에는 동작이 견딜 수 없는 관문이\n * 둘 있다.\n *\n * data-grid-body-click-handler.ts if (this.editTarget) return\n * data-grid-body-click-handler.ts (e.target).closest(\"ox-grid-field\")\n *\n * 앞은 다른 칸이 편집 중이면 첫 누름을 먹고, 뒤는 셀 경계를 스치면 칸을 못 찾는다. 진짜 button 을\n * 그리면 둘을 다 피하고 키보드로도 닿는다.\n *\n * 이 규칙이 여기 있는 이유: 렌더러의 결과는 이 셀의 그림자 안에 그려지므로 **페이지의 스타일이\n * 닿지 않는다.** 셀 안의 어휘는 셀이 갖는다.\n *\n * host 자식으로 적은 이유: 이 파일 아래의 host 자식 button 규칙이 채운 버튼을 그리고, 특이도가\n * 같으면 **뒤에 오는 쪽이 이긴다.** 그것 없이 두면 이 버튼이 채운 버튼의 모양으로 나왔다\n * (어두운 바탕 · 흰 글자, 실측 rgb(38, 46, 56)).\n *\n * 둘의 뜻이 다르다. 채운 버튼은 **실행하는 동작**이고, 이 버튼은 **이동**이다. 그래서 평소에는\n * 흐리고 배경이 없다.\n *\n * 배경은 **칸을 채우지 않고 동그라미로** 그린다. 칸을 다 채우면 「이 셀이 골라졌다」로 읽힌다 —\n * 표에서 채워진 사각형은 선택의 뜻이다. 동그라미는 버튼의 뜻이다.\n */\n :host > button.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n flex: none;\n /*\n * 누를 자리는 26px 로 두되 **줄 높이는 밀지 않는다.**\n *\n * 이 버튼이 들어간 칸 하나 때문에 표의 모든 줄이 46px 이 됐다(글자만 있는 줄은 38px). 스무 줄이면\n * 240px 을 잃는다. [확인함] grid-template-rows: 46px 34px\n *\n * 그렇다고 26px 아래로 줄이면 손가락으로 못 누른다(가로세로 24px 이 최소다). 그래서 상자는 26px\n * 로 두고 위아래 3px 씩을 여백에서 되돌려, 자리는 20px 만 차지하게 한다 — 글자 한 줄과 같다.\n */\n margin-top: -3px;\n margin-bottom: -3px;\n border: none;\n border-radius: 50%;\n background: transparent;\n padding: 0;\n color: var(--ui-faint, #8a959c);\n cursor: pointer;\n transition:\n background-color 0.12s ease,\n color 0.12s ease;\n }\n\n :host > button.icon:hover {\n background-color: var(--ui-hover, color-mix(in srgb, currentColor 12%, transparent));\n color: var(--ui-ink, #17272f);\n }\n\n :host > button.icon:active {\n background-color: var(--ui-active, color-mix(in srgb, currentColor 22%, transparent));\n }\n\n /* 키보드로 온 초점만 테를 보인다. 선택해서 온 초점에는 보이지 않는다. */\n :host > button.icon:focus-visible {\n outline: 2px solid var(--ui-accent, #00727e);\n outline-offset: -2px;\n }\n\n /*\n * 값을 함께 담는 버튼. 「4 ›」처럼 숫자와 화살이 나란히 놓인다.\n *\n * 아이콘만으로는 그 줄에 무엇이 있는지 말하지 못한다. 값이 뜻을 나르고 화살이 「누를 수 있다」를\n * 말한다. 그래서 동그라미가 아니라 알약 모양이다.\n */\n :host > button.icon.wide {\n width: auto;\n min-width: 44px;\n gap: 0;\n padding: 0 2px 0 7px;\n border-radius: 999px;\n font: inherit;\n font-size: var(--grid-record-wide-fontsize);\n font-variant-numeric: tabular-nums;\n }\n\n :host > button.icon.wide md-icon {\n --md-icon-size: 16px;\n font-size: 16px;\n width: 16px;\n height: 16px;\n }\n\n :host > button.icon md-icon {\n --md-icon-size: 18px;\n font-size: 18px;\n width: 18px;\n height: 18px;\n }\n\n .line {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n }\n\n /* 값이 길면 값이 줄고 표식은 그대로 남는다 — 표식이 먼저 잘리면 읽을 수 없다. */\n .line > :first-child {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* 표식 — 상태 같은 짧은 값에 두른다. 점이 색을 나르고 글자가 뜻을 나른다. */\n .pill {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 1px 8px;\n border: 1px solid var(--ui-line, #d5dce0);\n border-radius: 999px;\n font-size: var(--ui-t-small, 11.5px);\n font-weight: 400;\n color: var(--ui-muted, #57676f);\n white-space: nowrap;\n }\n\n /*\n * 색만으로 뜻을 전하지 않는다 — 알약 안의 글자가 함께 말한다. 점은 거드는 것이다.\n *\n * align-self: center 가 필요하다. 알약은 flex 이고 점은 그 안의 항목인데, 높이를 6px 로\n * 주어도 교차축에서 늘어나 **6×11.5 짜리 세로 타원**이 됐다(원이 아니라 길쭉했다).\n * .pill 의 align-items: center 는 부모 쪽 값이라 이 항목의 stretch 를 막지 못한다.\n */\n .pill .dot {\n align-self: center;\n width: 6px;\n height: 6px;\n /*\n * 이 파일 아래에 span, pre 의 min-height: 1em 이 있다. 값이 빈 칸에서도 줄 높이를\n * 유지하려는 규칙인데, 점도 span 이라 거기 걸려 **높이가 1em(11.5px)까지 늘어났다** —\n * 그래서 6px 을 줘도 6×11.5 세로 타원이 됐다. 여기서 되돌린다.\n */\n min-height: 0;\n border-radius: 50%;\n background: currentColor;\n flex: none;\n }\n\n .pill.good {\n color: var(--ui-good, #297d39);\n border-color: color-mix(in srgb, var(--ui-good, #297d39) 40%, transparent);\n font-weight: 400;\n }\n\n .pill.info {\n color: var(--ui-accent, #00727e);\n border-color: color-mix(in srgb, var(--ui-accent, #00727e) 40%, transparent);\n font-weight: 400;\n }\n\n .pill.warn {\n color: var(--ui-warn, #9f5e02);\n border-color: color-mix(in srgb, var(--ui-warn, #9f5e02) 40%, transparent);\n font-weight: 400;\n }\n\n .pill.crit {\n color: var(--ui-crit, #c93f30);\n border-color: color-mix(in srgb, var(--ui-crit, #c93f30) 40%, transparent);\n font-weight: 400;\n }\n\n .pill.quiet {\n color: var(--ui-faint, #8a959c);\n }\n\n :host([gutter]) {\n padding: var(--grid-gutter-padding);\n text-align: center;\n }\n\n :host([gutter]) * {\n cursor: default;\n overflow: hidden;\n }\n\n :host([editing]) {\n border-top: var(--grid-record-editing-border);\n border-bottom: var(--grid-record-editing-border);\n }\n\n /*\n * 초점이 갔다고 **줄을 나누는 선을 바꾸지 않는다.**\n *\n * 전에는 여기서 --grid-record-border-bottom 을 초점 표식 값으로 덮어썼다. 그래서 표식을\n * 감추려고 그 토큰을 none 이나 투명으로 두면 **그 셀만 줄 선이 사라졌다.** 한 토큰이 「초점\n * 표식」과 「줄을 나누는 선」 두 가지를 겸하고 있었던 것이다.\n *\n * 초점 표식은 outline 이 그린다(data-grid-body-style.ts). 줄 선은 줄 선으로 남는다.\n */\n\n :host([dirty])::after {\n content: '';\n position: absolute;\n right: 0;\n top: 0;\n\n width: 0px;\n height: 0px;\n border-top: 9px solid red;\n border-left: 9px solid transparent;\n }\n\n span,\n pre {\n display: block;\n text-overflow: ellipsis;\n overflow: hidden;\n min-height: 1em;\n }\n\n :host([multiline]) span,\n :host([multiline]) pre {\n text-overflow: initial;\n overflow: visible;\n white-space: pre-line;\n word-break: break-word;\n overflow-wrap: anywhere;\n }\n\n * {\n margin: 0;\n text-align: var(--data-grid-field-text-align);\n }\n\n *[center] {\n flex: none;\n margin: 0 auto;\n }\n\n :host > button {\n display: flex;\n gap: var(--spacing-small);\n border: 0;\n align-items: center;\n padding: var(--spacing-small);\n\n color: var(--md-sys-color-on-primary);\n background-color: var(--md-sys-color-primary);\n border-radius: var(--data-card-item-btn-border-radius, var(--md-sys-shape-corner-tiny));\n\n font-size: 0.8rem;\n line-height: 0.8rem;\n\n md-icon {\n border: 0;\n padding: 0;\n background-color: unset;\n }\n }\n\n :host([danger]) > button {\n color: var(--md-sys-color-on-primary);\n background-color: var(--md-sys-color-error);\n border-color: var(--md-sys-color-error);\n }\n\n :host([danger]) > button:hover {\n color: var(--md-sys-color-on-secondary);\n background-color: var(--md-sys-color-secondary);\n border-color: var(--md-sys-color-secondary);\n }\n `\n ]\n\n @property({ type: String, attribute: true }) align = DEFAULT_TEXT_ALIGN\n @property({ type: Object }) record: GristRecord = {}\n @property({ type: Object }) column: ColumnConfig = ZERO_COLUMN\n @property({ type: Number }) rowIndex = 0\n @property({ type: Number }) columnIndex = 0\n @property({ type: Boolean }) editing = false\n @property({ type: Boolean, reflect: true }) multiline = false\n @property({ type: Object }) value = {}\n @property({ type: String }) valueWith: string | null = null\n @property({ attribute: false }) emphasized: any = false\n @property({ type: String, attribute: true }) fixed?: string\n @property({ type: String }) type?: string\n @property({ type: Boolean }) isWorking: boolean = false\n\n /* check in tree의 변화에 대응하기 위함임. 만일, record control 오브젝트로 통일되면 대체될 것임. */\n @property({ type: String }) checked?: string\n\n private _editCancelled?: boolean\n private _onFieldChange: (e: Event) => void = e => {}\n private _onKeydownInEditingMode: (e: KeyboardEvent) => void = e => {}\n\n private tooltipController?: TooltipReactiveController = new TooltipReactiveController(this)\n\n render(): TemplateResult {\n if (!this.column) {\n return html``\n }\n\n var { value, column, record, rowIndex } = this\n var { renderer, editor } = column.record\n\n return html`\n ${this.editing\n ? editor?.call(this, value, column, record, rowIndex, this)\n : renderer?.call(this, value, column, record, rowIndex, this)}\n <!--\n **편집 중에도 표식을 남긴다.**\n\n 칸을 누르면 편집 상태가 되고, 그때는 렌더러 대신 편집기가 그려진다. 표식을 !editing 으로\n 묶어 두었더니 **칸에 들어간 순간 사라졌다** — 들어간 사람에게 여는 길이 없어지는 셈이고,\n 다시 더블클릭이나 Enter 를 짐작해야 한다. 그 짐작을 없애려고 만든 표식이다.\n\n 팝업 편집기에만 붙으므로(opensPopup) 글자를 치는 편집기를 가릴 일은 없다.\n -->\n <!--\n ── 칸 안에서 고치는 중에는 표식을 걷는다 ────────────────────────────────\n 입력칸이 이미 그 자리에 있다. 펜을 겹쳐 두면 글자를 가리고, 고치는 중인 사람에게\n 「고칠 수 있다」를 다시 말할 이유도 없다.\n\n 팝업 쪽은 남긴다 — 편집 상태에 들어가도 팝업은 아직 안 열렸고, 그 표식이 여는 길이다.\n -->\n ${this.editMark && !(this.editing && this.editMark === 'inline')\n ? html`<md-icon\n popup-hint\n ?inline=${this.editMark === 'inline'}\n title=${i18next.t('text.grid-open-editor', { defaultValue: 'press to edit' })}\n @pointerdown=${async (e: Event) => {\n /*\n * **click 이 아니라 pointerdown 이다.**\n *\n * 이 표에서는 click 이벤트가 나지 않는다 — 몸통이 pointer 단계에서 기본 동작을\n * 막는다. document 에 capture 로 click 을 걸어 두고 표식을 선택해 봐도 한 번도\n * 울리지 않았다(2026-09-05 계측).\n */\n e.stopPropagation()\n e.preventDefault()\n\n /*\n * ── 포커스는 여기서 변경하지 않는다 ──────────────────────────────\n *\n * 팝업이 닫히면 오버레이가 **열릴 때 포커스가 있던 자리**로 돌려준다. 그런데 위에서\n * preventDefault 를 하므로 브라우저가 이 칸으로 포커스를 옮겨 주지 않고, 그래서\n * 팝업을 닫으면 엉뚱한 곳으로 간다(페이지 검색창이었다).\n *\n * 두 가지를 해 봤고 **둘 다 팝업이 안 열리게 만들었다.**\n *\n * focus-change 이벤트 몸통이 그 갱신에서 editTarget 을 지운다(shouldUpdate)\n * ime-buffer 에 직접 focus 같은 결과\n *\n * 이 표는 포커스를 ime-buffer 라는 숨은 입력칸에 담아 두고, 편집 상태를 그 갱신\n * 주기에 얹고 있다. 그 둘이 얽혀 있어서 밖에서 포커스를 옮기면 편집이 취소된다.\n *\n * 표의 포커스 모델을 손대야 풀리는 문제라 여기서 우회하지 않는다.\n * [확인함] 2026-09-05 · 두 방법 모두 팝업이 안 열림\n */\n\n this.dispatchEvent(\n new CustomEvent('start-edit', {\n bubbles: true,\n composed: true,\n detail: { row: this.rowIndex, column: this.columnIndex }\n })\n )\n\n /*\n * 칸 안에서 고치는 편집기는 여기서 끝난다 — 편집이 열리면 그 자리에 입력칸이 뜬다.\n * 팝업 편집기는 한 걸음 더 필요하다.\n */\n if (this.editMark !== 'popup') {\n return\n }\n\n /*\n * ── 편집을 열고, **그다음** 더블클릭을 편집기에 보낸다 ──────────────\n *\n * 사람이 더블클릭할 때의 순서를 계측해 보면 이렇다.\n *\n * startEditTarget 첫 클릭이 편집을 연다 → 편집기가 그려진다\n * dblclick 그다음에 도착해 **이미 있는 편집기**가 받아 팝업을 연다\n *\n * 편집기마다 여는 메서드 이름이 달라서 부품이 직접 부를 수는 없다. 사람이 하던\n * 동작을 같은 순서로 보내면 경로가 하나로 남는다.\n */\n for (let i = 0; i < 5 && !this.editing; i++) {\n await new Promise(resolve => requestAnimationFrame(resolve))\n }\n\n await this.updateComplete\n\n const editor = this.renderRoot.firstElementChild as HTMLElement | null\n editor?.dispatchEvent(new MouseEvent('dblclick', { bubbles: true, composed: true }))\n }}\n >${this.editMark === 'popup' ? 'edit_square' : 'edit'}</md-icon\n >`\n : ''}\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('editing')) {\n if (this.editing) {\n this._onKeydownInEditingMode = ((e: KeyboardEvent) => {\n if (e.key === 'Esc' || e.key === 'Escape') {\n /* 편집 취소 */\n this._editCancelled = true\n }\n }).bind(this)\n\n this._onFieldChange = ((e: Event) => {\n this._editCancelled && e.stopPropagation()\n }).bind(this)\n\n delete this._editCancelled\n this.addEventListener('field-change', this._onFieldChange)\n this.addEventListener('keydown', this._onKeydownInEditingMode)\n } else {\n this.removeEventListener('field-change', this._onFieldChange)\n this.removeEventListener('keydown', this._onKeydownInEditingMode)\n }\n }\n\n if (changes.has('column')) {\n /*\n * 정렬은 **넣을 때만이 아니라 되돌릴 때도** 손대야 한다.\n *\n * 이 요소는 재사용된다. 전에는 기본값이 아닐 때만 인라인 값을 넣고 지우지 않았다. 그래서 한 번\n * 오른쪽 정렬 칸을 그린 셀이 다음에 왼쪽 정렬 칸을 그려도 오른쪽에 남았다.\n *\n * [확인함] 품질 화면 「판단」 칸에서 머리글은 x=380(왼쪽)인데 값은 x=452(flex-end)였다. 숫자 칸을\n * 오른쪽으로 바꾼 뒤 드러났다 — 오른쪽 정렬 칸이 드물던 동안은 눈에 안 띄었다. 2026-09-02\n */\n var align = this.column.record.align || DEFAULT_TEXT_ALIGN\n\n if (align == DEFAULT_TEXT_ALIGN) {\n this.style.removeProperty('--data-grid-field-justify-content')\n this.style.removeProperty('--data-grid-field-text-align')\n } else {\n let justify = 'center'\n switch (align) {\n case 'right':\n justify = 'flex-end'\n break\n }\n this.style.setProperty('--data-grid-field-justify-content', justify)\n this.style.setProperty('--data-grid-field-text-align', align)\n }\n\n /* 표식은 값의 반대쪽 빈자리에 선다 — 위 :host([mark-start]) 주석 참고. */\n this.toggleAttribute('mark-start', align === 'right')\n\n const { danger } = this.column\n if (danger) {\n this.setAttribute('danger', '')\n } else {\n this.removeAttribute('danger')\n }\n }\n\n if (changes.has('fixed')) {\n if (this.fixed) {\n this.style.left = this.fixed + 'px'\n } else {\n this.style.left = 'unset'\n }\n }\n\n let disabled = this.column.record.disabled || false\n if (typeof disabled === 'function') {\n disabled = disabled.call(this, this.record[this.column.name], this.column, this.record, this.rowIndex, this)\n }\n\n if (!!disabled) {\n // 비황성화 여부 표시\n this.setAttribute('disabled', '')\n } else {\n // 비황성화 여부 제거\n this.removeAttribute('disabled')\n }\n\n const emphasized =\n /*\n * classifier 는 없을 수 있다. 열 빌더가 채워 주지만 손으로 만든 열에는 없고, 그때 여기서\n * 던진다. 갱신 중에 나는 예외라 화면이 오류보고없이 멈춘다.\n *\n * [확인함] 2026-09-05 · wtr 에서 Cannot read properties of undefined (reading 'call')\n * 팝업 표식을 넣어 칸이 전보다 자주 갱신되면서 드러났다. 원래 있던 자리다.\n */\n this.column.record.classifier?.call(this, this.record, this.rowIndex)?.emphasized || this.emphasized\n\n if (!!emphasized) {\n this.setAttribute('emphasized-row', '')\n\n if (Symbol.iterator in Object(emphasized)) {\n const [backgroundColor, foregroundColor] = emphasized as string[]\n backgroundColor && this.style.setProperty('--grid-record-emphasized-background-color', backgroundColor)\n foregroundColor && this.style.setProperty('--grid-record-emphasized-color', foregroundColor)\n }\n } else {\n this.removeAttribute('emphasized-row')\n }\n }\n\n /**\n * 이 칸에 **팝업 표식**을 붙이나 — 팝업으로 고쳐지고, 지금 고칠 수 있을 때만.\n *\n * 고칠 수 있는지는 열이 함수로 정할 수도 있다(줄마다 다른 경우). 그때는 몸통이 편집을 열 때\n * 하는 것과 같은 방식으로 물어본다. 표식은 있는데 선택해도 안 열리면 그것이 더 나쁘다.\n */\n get opensPopup(): boolean {\n return this.editMark === 'popup'\n }\n\n /**\n * 이 칸을 **고칠 수 있나, 그리고 어디서 고치나.**\n *\n * popup 팝업이 열린다 — 네모와 펜\n * inline 칸 안에서 고친다 — 펜\n * null 못 고친다 — 표식 없음\n *\n * 표식이 있으면 고칠 수 있는 칸이고, 모양이 어디서 고치는지를 말한다.\n *\n * 고칠 수 있는지는 열이 함수로 정할 수도 있다(줄마다 다른 경우). 그때는 몸통이 편집을 열 때\n * 하는 것과 같은 방식으로 물어본다. 표식은 있는데 선택해도 안 열리면 그것이 더 나쁘다.\n */\n get editMark(): 'popup' | 'inline' | null {\n const column = this.column\n\n if (!column) {\n return null\n }\n\n /* 거터에는 붙이지 않는다 — 순번과 고르기 칸은 고치는 자리가 아니다. */\n if (column.type === 'gutter') {\n return null\n }\n\n /*\n * 표 오른쪽의 **빈 채움 열**에도 붙이지 않는다. 남는 자리를 메우는 20px 짜리 빈 열이라\n * 이름도 타입도 없다 — 고칠 것이 없는데 표식만 떴다.\n *\n * [확인함] 2026-09-05 · 인원 화면 맨 끝 칸 · { type: '', name: '', label: false } · 폭 20\n */\n if (!column.name) {\n return null\n }\n\n let { editable } = column.record || ({} as any)\n\n if (typeof editable === 'function') {\n editable = editable.call(this, this.value, column, this.record, this.rowIndex, this)\n }\n\n /*\n * **밝히지 않은 열에는 붙이지 않는다.**\n *\n * 표 전체가 고칠 수 있는지를 판단하는 자리가 같은 기준을 쓴다.\n *\n * [읽었음] data-grid.ts · editableGrid = columns.some(c => !!c.record?.editable)\n *\n * 참일 때만 고칠 수 있는 열로 본다. 선언하지 않은 열까지 세면 **고르기만 하는 표**에도\n * 표식이 깔린다 — 참조 팝업의 목록이 그랬다(2026-09-05). 그 표의 칸은 고르는 자리이지\n * 고치는 자리가 아니다.\n */\n if (!editable) {\n return null\n }\n\n /*\n * 편집기를 **함수로 직접 준 열**은 타입으로 판단할 수 없다. 그리기를 다른 렌더러로 하려고\n * 타입을 바꾼 열이 그렇다 — 관계를 여럿 다는 칸이 `ops-list` 로 그려지면서 편집은 참조\n * 팝업으로 한다(ops-master 의 reference-list).\n *\n * 그런 열은 `record.opensPopup` 으로 스스로 밝힌다. 밝히지 않으면 타입으로 본다.\n *\n * [확인함] 2026-09-05 · 보유 자격 · 타입 ops-list · 팝업으로 열리는데 표식이 inline 이었다\n */\n const declared = (column.record as any)?.opensPopup\n\n if (typeof declared === 'boolean') {\n return declared ? 'popup' : 'inline'\n }\n\n return editorOpensPopup(column.type) ? 'popup' : 'inline'\n }\n\n get editableOnClick() {\n const renderer = this.renderRoot.firstElementChild as HTMLElement\n //@ts-ignore\n return renderer && 'editableOnClick' in renderer ? renderer.editableOnClick : true\n }\n}\n"]}
1
+ {"version":3,"file":"data-grid-field.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid-field.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport i18next from 'i18next'\nimport { css, html, LitElement, PropertyValues, TemplateResult } from 'lit'\n// import { guard } from 'lit/directives/guard.js'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { TooltipReactiveController } from '@operato/utils'\n\nimport { ZERO_COLUMN } from '../configure/zero-config.js'\nimport { editorOpensPopup } from '../editors/registry.js'\nimport { ColumnConfig, GristRecord } from '../types.js'\n\nconst DEFAULT_TEXT_ALIGN = 'left'\n\n@customElement('ox-grid-field')\nexport class DataGridField extends LitElement {\n static styles = [\n css`\n :host {\n display: flex;\n\n align-items: center;\n justify-content: var(--data-grid-field-justify-content, flex-start);\n position: relative;\n\n white-space: nowrap;\n background-color: var(--grid-record-background-color);\n padding: var(--grid-record-padding);\n border: 1px solid transparent;\n border-width: 1px 0;\n border-bottom: var(--grid-record-border-bottom);\n\n font-size: var(--grid-record-wide-fontsize);\n min-height: 30px;\n box-sizing: border-box;\n }\n\n /*\n * ── 팝업으로 고치는 칸에는 **표식이 있다** ──────────────────────────────\n *\n * 그런 칸은 글자 칸과 똑같이 생겼다. 열어 보기 전에는 고칠 수 있는지도, 어떻게 고치는지도\n * 모른다 — 「실제 더블클릭을 하기 전에는 모르는 막막함」(사용자, 2026-09-05).\n *\n * **마우스를 올렸을 때 보인다.** 늘 보이게 두었더니 한 화면에 54개가 깔려 표가 시끄러웠다\n * (2026-09-05 · 사용자 판단). 값을 읽으러 온 눈에 장치가 줄마다 끼어든다.\n *\n * **손가락 화면에서는 늘 보인다.** 거기엔 올리는 동작이 없어서 감추면 길이 아예 없어진다.\n * 그 화면들은 표가 성기므로 늘 보여도 시끄럽지 않다.\n *\n * ── 네모와 펜을 쓴다 ─────────────────────────────────────────────────\n * 처음에 삼각형(arrow_drop_down)을 썼다. 참조 칸만 생각한 선택이었다 — 「목록에서 고른다」.\n *\n * 그런데 이 표식은 **팝업으로 여는 편집기 전부**에 붙는다. JSON · 코드 · 권한 편집기도\n * 그렇고, 거기서 삼각형은 거짓말이다. 고를 목록이 없다.\n *\n * ── 모양이 **어디서 고치는지**를 말한다 ────────────────────────────────\n *\n * edit 칸 안에서 고친다\n * edit_square 팝업이 열린다\n *\n * 표식이 있으면 고칠 수 있는 칸이고, 없으면 못 고치는 칸이다. **읽기 전용에는 붙지 않는다.**\n *\n * 처음에 삼각형(arrow_drop_down)을 썼다 — 참조 칸만 생각한 선택이었다. 이 표식은 JSON ·\n * 코드 · 권한 편집기에도 붙고, 거기서 삼각형은 고를 목록이 있다는 거짓말이 된다.\n *\n * 누를 자리는 22px 이다. 33px 줄에서 더블클릭을 겨누는 것보다 한 번 누르는 편이 쉽다.\n */\n /* 마우스 화면 — 칸에 올렸을 때만. 자리는 늘 잡아 두므로 글자가 밀리지 않는다. */\n @media (pointer: fine) {\n [popup-hint] {\n opacity: 0;\n transition: opacity 0.12s ease;\n }\n\n :host(:hover) [popup-hint] {\n opacity: 1;\n }\n }\n\n /*\n * 손가락 화면 — **고른 칸에만 보인다.**\n *\n * 올리는 동작이 없으니 호버로는 아무것도 못 보여 준다. 그렇다고 늘 보이게 두면 좁은\n * 화면이 표식으로 뒤덮인다 — 시끄러우면 정작 필요한 표식도 안 보인다.\n *\n * 고른 칸 하나에만 두면 둘 다 풀린다. 두드려 고르는 것이 그 화면의 첫 동작이므로,\n * 고르는 순간 「이 칸은 이렇게 고친다」가 나타난다.\n */\n @media (pointer: coarse) {\n [popup-hint] {\n display: none;\n }\n\n :host([focused]) [popup-hint] {\n display: flex;\n }\n }\n\n /*\n * ── 표식은 늘 **칸의 끝**에 있다. 정렬을 따라가지 않는다 (2026-09-05) ──────\n *\n * 찾는 데 드는 값이 커진다 정렬은 열마다 다르다(이름은 왼쪽, 수량은 오른쪽). 표식이\n * 그것을 따라가면 자리가 열마다 달라져 눈이 매번 찾아야 한다.\n * 끝에 고정하면 규칙이 하나다 — 「손잡이는 칸 끝에 있다」\n * 남의 칸처럼 보인다 오른쪽 정렬 칸의 값 **앞**에 표식을 두면 왼쪽 칸의 값 뒤에\n * 붙어 보인다. 어느 칸의 손잡이인지 흐려진다\n *\n * ── **값이 없는 쪽**에 붙는다 ──────────────────────────────────────\n * 왼쪽으로 붙인 칸의 빈자리는 오른쪽이고, 오른쪽으로 붙인 칸(수량 · 금액)의 빈자리는\n * 왼쪽이다. 정렬의 반대쪽에 두면 표식이 값 위에 얹히는 일 자체가 없어진다.\n *\n * 자리를 비워 두는 방법도 해 봤다 — 칸의 오른쪽을 24px 늘 비우는 것. 되돌렸다.\n * **자료가 먼저다**(사용자, 2026-09-05): 마우스를 올렸을 때만 보이는 안내 때문에 고칠 수\n * 있는 열 전부가 영구히 좁아지는 것은 값을 잘못 매긴 거래다.\n *\n * 가운데 정렬 칸은 양쪽이 다 비므로 끝에 둔다.\n */\n [popup-hint] {\n position: absolute;\n inset-inline-end: 2px;\n top: 50%;\n transform: translateY(-50%);\n\n --md-icon-size: 16px;\n font-size: 16px;\n width: 16px;\n height: 16px;\n padding: 3px;\n border-radius: 50%;\n\n /*\n * ── 채우지 않는다 (2026-09-05) ──────────────────────────────────\n * md-icon 이 물려주는 값은 FILL 1 이라 글리프가 통짜로 나온다. 두 가지가 어긋난다.\n *\n * 뜻 채운 글리프는 「지금 그 상태다」를 말한다(고른 것 · 켠 것). 이 표식이 말하는\n * 것은 상태가 아니라 **누르면 할 수 있는 일**이다. 그건 윤곽선의 몫이다\n * 밀도 표는 글자밭이다. 같은 16px 에서 채운 글리프는 잉크가 몇 곱절이라 값보다\n * 먼저 눈에 들어온다. 안내가 자료보다 진해서는 안 된다\n *\n * edit_square 는 특히 그렇다 — 채우면 네모가 덩어리가 되어 「종이 위의 연필」이라는\n * 그림이 뭉개진다. 진하기는 색으로 조절한다(아래 :hover).\n */\n /*\n * 굵기는 한 단 올린다. 16px 에서 400 짜리 윤곽선은 획이 배경에 묻는다 — 채움을 뺀 만큼\n * 획으로 되받는다. 잉크가 늘지 않으면서 형태는 또렷해진다.\n */\n font-variation-settings:\n 'FILL' 0,\n 'wght' 500,\n 'opsz' 20;\n\n /*\n * ── 값 **위에 그려지되, 값보다 앞서지 않는다** ──────────────────\n * 자리가 겹치면 표식이 위에 얹힌다. 그래도 이것은 거들어 주는 것이지 읽을 것이 아니다 —\n * 본문 색으로 두었더니 값과 같은 무게가 되어 눈이 먼저 표식으로 갔다(사용자, 2026-09-05).\n * 한 단 낮춰 라벨 색으로 둔다. 손이 표식 위에 오면 그때 본문 색이 된다.\n */\n color: var(--ui-muted, #57676f);\n cursor: pointer;\n\n transition:\n background-color 0.12s ease,\n color 0.12s ease;\n }\n\n /* 오른쪽으로 붙인 칸 — 값이 오른쪽 끝에 있으므로 표식은 왼쪽의 빈자리로 간다. */\n :host([mark-start]) [popup-hint] {\n inset-inline-end: auto;\n inset-inline-start: 2px;\n }\n\n [popup-hint]:hover {\n color: var(--ui-ink, #17272f);\n background-color: var(--ui-hover, color-mix(in srgb, currentColor 12%, transparent));\n }\n\n :host([multiline]) {\n white-space: pre-line;\n }\n\n /*\n * ── 칸이 쓸 수 있는 용어 (2026-08-31) ──────────────────────────────────\n * 렌더러가 그린 것은 이 부품의 shadow DOM 안에 들어간다. 그래서 **화면의 CSS 가 닿지 않는다.**\n * 두 줄 칸이나 상태 알약을 그리려던 화면들이 그 벽에 막혀, 값에 인라인 style 을 박거나 칸마다\n * 부품을 새로 만들었다.\n *\n * 목록이면 어디서나 같은 것을 필요로 하므로 여기서 준다. 이름은 뜻으로 짓는다 —\n * 「늦었다」가 아니라 「심각하다(crit)」다. 늦은 것은 이 표의 일이 아니고 화면의 일이다.\n *\n * .sub 둘째 줄. 「1,200 EA」 아래의 「BOLT-8」처럼 딸린 사실\n * .mono 고정폭. 번호·시각·수량처럼 자릿수를 비교하는 값\n * .none 값이 없음. 빈 칸으로 두면 「아직 안 읽었다」와 구별되지 않는다\n * .pill 알약. good·warn·crit·info 로 뜻을 준다\n * .crit · .warn · .good 글자 강조\n *\n * 값은 --ui-* 토큰에서 오고 폴백을 둔다 — 테마가 없어도 무너지지 않는다.\n */\n :host([twoline]) {\n display: block;\n white-space: normal;\n line-height: 1.35;\n }\n\n .sub {\n display: block;\n margin-top: 2px;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-faint, #8a959c);\n }\n\n .mono {\n font-family: var(--ui-mono, ui-monospace, Menlo, monospace);\n font-variant-numeric: tabular-nums;\n }\n\n /*\n * 그 줄이 무엇인지 가리키는 값 — 작업지시 번호, 설비 이름처럼. 두 줄 칸의 첫 줄이 이것이고\n * 둘째 줄(.sub)이 딸린 사실이다. 굵기만 올린다. 고정폭은 쓰지 않는다 — 자릿수를 세로로 견줄\n * 값이 아니고, 같은 글자 수에도 폭이 넓어져 옆 칸을 밀어낸다.\n */\n .id {\n font-weight: 620;\n }\n\n .none {\n color: var(--ui-faint, #8a959c);\n }\n\n .crit {\n color: var(--ui-crit, #c93f30);\n font-weight: 640;\n }\n\n .warn {\n color: var(--ui-warn, #9f5e02);\n font-weight: 640;\n }\n\n .good {\n color: var(--ui-good, #297d39);\n font-weight: 640;\n }\n\n /*\n * 값과 표식을 한 줄에 담는 영역이다. **간격과 높이를 여기서 정한다.**\n *\n * 처음에는 :not(.pill) + .pill { margin-left } 로 띄우려 했는데 안 걸렸다. 렌더러가 값을\n * 텍스트 노드로 내므로 알약의 앞 형제가 **요소가 아니고**, CSS 형제 선택자는 텍스트 노드를 보지\n * 못한다. 알약이 첫 요소이기도 해서 :first-child 로도 가려지지 않는다(실측 확인).\n *\n * 높이도 같은 자리에서 잡는다. baseline 으로 두면 14px 글자와 11.5px 알약의 기준선을 맞추느라\n * 알약이 내려앉는다.\n */\n /* 값이 있지만 눈에 걸릴 것은 아닌 것 — 「보통」 같은 기본값. .none(값 없음)과 구별한다. */\n .quiet {\n color: var(--ui-muted, #57676f);\n }\n\n /*\n * 별 같은 작은 기호를 글자 크기로 맞춘다. md-icon 의 기본은 24px 이라 줄 높이를 밀어낸다.\n * 색은 물려받는다 — 개수가 크기를 말하고 색은 담는 쪽이 정한다.\n */\n .star {\n --md-icon-size: 15px;\n font-size: 15px;\n width: 15px;\n height: 15px;\n color: inherit;\n }\n\n /* 별처럼 여럿이 붙는 기호는 사이를 좁게 둔다. 단어 사이의 6px 은 여기서 너무 넓다. */\n .line:has(.star) {\n gap: 1px;\n }\n\n /*\n * 셀 안의 아이콘 버튼. 그 줄에 하는 동작(들어가기 · 열기)을 담는다.\n *\n * 셀의 클릭 경로를 타지 않고 스스로 받으려는 렌더러가 쓴다. 그 경로에는 동작이 견딜 수 없는 관문이\n * 둘 있다.\n *\n * data-grid-body-click-handler.ts if (this.editTarget) return\n * data-grid-body-click-handler.ts (e.target).closest(\"ox-grid-field\")\n *\n * 앞은 다른 칸이 편집 중이면 첫 누름을 먹고, 뒤는 셀 경계를 스치면 칸을 못 찾는다. 진짜 button 을\n * 그리면 둘을 다 피하고 키보드로도 닿는다.\n *\n * 이 규칙이 여기 있는 이유: 렌더러의 결과는 이 셀의 그림자 안에 그려지므로 **페이지의 스타일이\n * 닿지 않는다.** 셀 안의 어휘는 셀이 갖는다.\n *\n * host 자식으로 적은 이유: 이 파일 아래의 host 자식 button 규칙이 채운 버튼을 그리고, 특이도가\n * 같으면 **뒤에 오는 쪽이 이긴다.** 그것 없이 두면 이 버튼이 채운 버튼의 모양으로 나왔다\n * (어두운 바탕 · 흰 글자, 실측 rgb(38, 46, 56)).\n *\n * 둘의 뜻이 다르다. 채운 버튼은 **실행하는 동작**이고, 이 버튼은 **이동**이다. 그래서 평소에는\n * 흐리고 배경이 없다.\n *\n * 배경은 **칸을 채우지 않고 동그라미로** 그린다. 칸을 다 채우면 「이 셀이 골라졌다」로 읽힌다 —\n * 표에서 채워진 사각형은 선택의 뜻이다. 동그라미는 버튼의 뜻이다.\n */\n :host > button.icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n flex: none;\n /*\n * 누를 자리는 26px 로 두되 **줄 높이는 밀지 않는다.**\n *\n * 이 버튼이 들어간 칸 하나 때문에 표의 모든 줄이 46px 이 됐다(글자만 있는 줄은 38px). 스무 줄이면\n * 240px 을 잃는다. [확인함] grid-template-rows: 46px 34px\n *\n * 그렇다고 26px 아래로 줄이면 손가락으로 못 누른다(가로세로 24px 이 최소다). 그래서 상자는 26px\n * 로 두고 위아래 3px 씩을 여백에서 되돌려, 자리는 20px 만 차지하게 한다 — 글자 한 줄과 같다.\n */\n margin-top: -3px;\n margin-bottom: -3px;\n border: none;\n border-radius: 50%;\n background: transparent;\n padding: 0;\n color: var(--ui-faint, #8a959c);\n cursor: pointer;\n transition:\n background-color 0.12s ease,\n color 0.12s ease;\n }\n\n :host > button.icon:hover {\n background-color: var(--ui-hover, color-mix(in srgb, currentColor 12%, transparent));\n color: var(--ui-ink, #17272f);\n }\n\n :host > button.icon:active {\n background-color: var(--ui-active, color-mix(in srgb, currentColor 22%, transparent));\n }\n\n /* 키보드로 온 초점만 테를 보인다. 선택해서 온 초점에는 보이지 않는다. */\n :host > button.icon:focus-visible {\n outline: 2px solid var(--ui-accent, #00727e);\n outline-offset: -2px;\n }\n\n /*\n * 값을 함께 담는 버튼. 「4 ›」처럼 숫자와 화살이 나란히 놓인다.\n *\n * 아이콘만으로는 그 줄에 무엇이 있는지 말하지 못한다. 값이 뜻을 나르고 화살이 「누를 수 있다」를\n * 말한다. 그래서 동그라미가 아니라 알약 모양이다.\n */\n :host > button.icon.wide {\n width: auto;\n min-width: 44px;\n gap: 0;\n padding: 0 2px 0 7px;\n border-radius: 999px;\n font: inherit;\n font-size: var(--grid-record-wide-fontsize);\n font-variant-numeric: tabular-nums;\n }\n\n :host > button.icon.wide md-icon {\n --md-icon-size: 16px;\n font-size: 16px;\n width: 16px;\n height: 16px;\n }\n\n :host > button.icon md-icon {\n --md-icon-size: 18px;\n font-size: 18px;\n width: 18px;\n height: 18px;\n }\n\n .line {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n }\n\n /* 값이 길면 값이 줄고 표식은 그대로 남는다 — 표식이 먼저 잘리면 읽을 수 없다. */\n .line > :first-child {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* 표식 — 상태 같은 짧은 값에 두른다. 점이 색을 나르고 글자가 뜻을 나른다. */\n .pill {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 1px 8px;\n border: 1px solid var(--ui-line, #d5dce0);\n border-radius: 999px;\n font-size: var(--ui-t-small, 11.5px);\n font-weight: 400;\n color: var(--ui-muted, #57676f);\n white-space: nowrap;\n }\n\n /*\n * 색만으로 뜻을 전하지 않는다 — 알약 안의 글자가 함께 말한다. 점은 거드는 것이다.\n *\n * align-self: center 가 필요하다. 알약은 flex 이고 점은 그 안의 항목인데, 높이를 6px 로\n * 주어도 교차축에서 늘어나 **6×11.5 짜리 세로 타원**이 됐다(원이 아니라 길쭉했다).\n * .pill 의 align-items: center 는 부모 쪽 값이라 이 항목의 stretch 를 막지 못한다.\n */\n .pill .dot {\n align-self: center;\n width: 6px;\n height: 6px;\n /*\n * 이 파일 아래에 span, pre 의 min-height: 1em 이 있다. 값이 빈 칸에서도 줄 높이를\n * 유지하려는 규칙인데, 점도 span 이라 거기 걸려 **높이가 1em(11.5px)까지 늘어났다** —\n * 그래서 6px 을 줘도 6×11.5 세로 타원이 됐다. 여기서 되돌린다.\n */\n min-height: 0;\n border-radius: 50%;\n background: currentColor;\n flex: none;\n }\n\n .pill.good {\n color: var(--ui-good, #297d39);\n border-color: color-mix(in srgb, var(--ui-good, #297d39) 40%, transparent);\n font-weight: 400;\n }\n\n .pill.info {\n color: var(--ui-accent, #00727e);\n border-color: color-mix(in srgb, var(--ui-accent, #00727e) 40%, transparent);\n font-weight: 400;\n }\n\n .pill.warn {\n color: var(--ui-warn, #9f5e02);\n border-color: color-mix(in srgb, var(--ui-warn, #9f5e02) 40%, transparent);\n font-weight: 400;\n }\n\n .pill.crit {\n color: var(--ui-crit, #c93f30);\n border-color: color-mix(in srgb, var(--ui-crit, #c93f30) 40%, transparent);\n font-weight: 400;\n }\n\n .pill.quiet {\n color: var(--ui-faint, #8a959c);\n }\n\n :host([gutter]) {\n padding: var(--grid-gutter-padding);\n text-align: center;\n }\n\n :host([gutter]) * {\n cursor: default;\n overflow: hidden;\n }\n\n :host([editing]) {\n border-top: var(--grid-record-editing-border);\n border-bottom: var(--grid-record-editing-border);\n }\n\n /*\n * 초점이 갔다고 **줄을 나누는 선을 바꾸지 않는다.**\n *\n * 전에는 여기서 --grid-record-border-bottom 을 초점 표식 값으로 덮어썼다. 그래서 표식을\n * 감추려고 그 토큰을 none 이나 투명으로 두면 **그 셀만 줄 선이 사라졌다.** 한 토큰이 「초점\n * 표식」과 「줄을 나누는 선」 두 가지를 겸하고 있었던 것이다.\n *\n * 초점 표식은 outline 이 그린다(data-grid-body-style.ts). 줄 선은 줄 선으로 남는다.\n */\n\n :host([dirty])::after {\n content: '';\n position: absolute;\n right: 0;\n top: 0;\n\n width: 0px;\n height: 0px;\n border-top: 9px solid red;\n border-left: 9px solid transparent;\n }\n\n span,\n pre {\n display: block;\n text-overflow: ellipsis;\n overflow: hidden;\n min-height: 1em;\n }\n\n :host([multiline]) span,\n :host([multiline]) pre {\n text-overflow: initial;\n overflow: visible;\n white-space: pre-line;\n word-break: break-word;\n overflow-wrap: anywhere;\n }\n\n * {\n margin: 0;\n text-align: var(--data-grid-field-text-align);\n }\n\n *[center] {\n flex: none;\n margin: 0 auto;\n }\n\n :host > button {\n display: flex;\n gap: var(--spacing-small);\n border: 0;\n align-items: center;\n padding: var(--spacing-small);\n\n color: var(--md-sys-color-on-primary);\n background-color: var(--md-sys-color-primary);\n border-radius: var(--data-card-item-btn-border-radius, var(--md-sys-shape-corner-tiny));\n\n font-size: 0.8rem;\n line-height: 0.8rem;\n\n md-icon {\n border: 0;\n padding: 0;\n background-color: unset;\n }\n }\n\n :host([danger]) > button {\n color: var(--md-sys-color-on-primary);\n background-color: var(--md-sys-color-error);\n border-color: var(--md-sys-color-error);\n }\n\n :host([danger]) > button:hover {\n color: var(--md-sys-color-on-secondary);\n background-color: var(--md-sys-color-secondary);\n border-color: var(--md-sys-color-secondary);\n }\n `\n ]\n\n @property({ type: String, attribute: true }) align = DEFAULT_TEXT_ALIGN\n @property({ type: Object }) record: GristRecord = {}\n @property({ type: Object }) column: ColumnConfig = ZERO_COLUMN\n @property({ type: Number }) rowIndex = 0\n @property({ type: Number }) columnIndex = 0\n @property({ type: Boolean }) editing = false\n @property({ type: Boolean, reflect: true }) multiline = false\n @property({ type: Object }) value = {}\n @property({ type: String }) valueWith: string | null = null\n @property({ attribute: false }) emphasized: any = false\n @property({ type: String, attribute: true }) fixed?: string\n @property({ type: String }) type?: string\n @property({ type: Boolean }) isWorking: boolean = false\n\n /* check in tree의 변화에 대응하기 위함임. 만일, record control 오브젝트로 통일되면 대체될 것임. */\n @property({ type: String }) checked?: string\n\n private _editCancelled?: boolean\n private _onFieldChange: (e: Event) => void = e => {}\n private _onKeydownInEditingMode: (e: KeyboardEvent) => void = e => {}\n\n private tooltipController?: TooltipReactiveController = new TooltipReactiveController(this)\n\n render(): TemplateResult {\n if (!this.column) {\n return html``\n }\n\n var { value, column, record, rowIndex } = this\n var { renderer, editor } = column.record\n\n return html`\n ${this.editing\n ? editor?.call(this, value, column, record, rowIndex, this)\n : renderer?.call(this, value, column, record, rowIndex, this)}\n <!--\n **편집 중에도 표식을 남긴다.**\n\n 칸을 누르면 편집 상태가 되고, 그때는 렌더러 대신 편집기가 그려진다. 표식을 !editing 으로\n 묶어 두었더니 **칸에 들어간 순간 사라졌다** — 들어간 사람에게 여는 길이 없어지는 셈이고,\n 다시 더블클릭이나 Enter 를 짐작해야 한다. 그 짐작을 없애려고 만든 표식이다.\n\n 팝업 편집기에만 붙으므로(opensPopup) 글자를 치는 편집기를 가릴 일은 없다.\n -->\n <!--\n ── 칸 안에서 고치는 중에는 표식을 걷는다 ────────────────────────────────\n 입력칸이 이미 그 자리에 있다. 펜을 겹쳐 두면 글자를 가리고, 고치는 중인 사람에게\n 「고칠 수 있다」를 다시 말할 이유도 없다.\n\n 팝업 쪽은 남긴다 — 편집 상태에 들어가도 팝업은 아직 안 열렸고, 그 표식이 여는 길이다.\n -->\n ${this.editMark && !(this.editing && this.editMark === 'inline')\n ? html`<md-icon\n popup-hint\n ?inline=${this.editMark === 'inline'}\n title=${i18next.t('text.grid-open-editor', { defaultValue: 'press to edit' })}\n @pointerdown=${async (e: Event) => {\n /*\n * **click 이 아니라 pointerdown 이다.**\n *\n * 이 표에서는 click 이벤트가 나지 않는다 — 몸통이 pointer 단계에서 기본 동작을\n * 막는다. document 에 capture 로 click 을 걸어 두고 표식을 선택해 봐도 한 번도\n * 울리지 않았다(2026-09-05 계측).\n */\n e.stopPropagation()\n e.preventDefault()\n\n /*\n * ── 포커스는 여기서 변경하지 않는다 ──────────────────────────────\n *\n * 팝업이 닫히면 오버레이가 **열릴 때 포커스가 있던 자리**로 돌려준다. 그런데 위에서\n * preventDefault 를 하므로 브라우저가 이 칸으로 포커스를 옮겨 주지 않고, 그래서\n * 팝업을 닫으면 엉뚱한 곳으로 간다(페이지 검색창이었다).\n *\n * 두 가지를 해 봤고 **둘 다 팝업이 안 열리게 만들었다.**\n *\n * focus-change 이벤트 몸통이 그 갱신에서 editTarget 을 지운다(shouldUpdate)\n * ime-buffer 에 직접 focus 같은 결과\n *\n * 이 표는 포커스를 ime-buffer 라는 숨은 입력칸에 담아 두고, 편집 상태를 그 갱신\n * 주기에 얹고 있다. 그 둘이 얽혀 있어서 밖에서 포커스를 옮기면 편집이 취소된다.\n *\n * 표의 포커스 모델을 손대야 풀리는 문제라 여기서 우회하지 않는다.\n * [확인함] 2026-09-05 · 두 방법 모두 팝업이 안 열림\n */\n\n this.dispatchEvent(\n new CustomEvent('start-edit', {\n bubbles: true,\n composed: true,\n detail: { row: this.rowIndex, column: this.columnIndex }\n })\n )\n\n /*\n * 칸 안에서 고치는 편집기는 여기서 끝난다 — 편집이 열리면 그 자리에 입력칸이 뜬다.\n * 팝업 편집기는 한 걸음 더 필요하다.\n */\n if (this.editMark !== 'popup') {\n return\n }\n\n /*\n * ── 편집을 열고, **그다음** 더블클릭을 편집기에 보낸다 ──────────────\n *\n * 사람이 더블클릭할 때의 순서를 계측해 보면 이렇다.\n *\n * startEditTarget 첫 클릭이 편집을 연다 → 편집기가 그려진다\n * dblclick 그다음에 도착해 **이미 있는 편집기**가 받아 팝업을 연다\n *\n * 편집기마다 여는 메서드 이름이 달라서 부품이 직접 부를 수는 없다. 사람이 하던\n * 동작을 같은 순서로 보내면 경로가 하나로 남는다.\n */\n for (let i = 0; i < 5 && !this.editing; i++) {\n await new Promise(resolve => requestAnimationFrame(resolve))\n }\n\n await this.updateComplete\n\n /*\n * Both events, in the order a browser sends them.\n *\n * The editors split on which one they open from, and sending only `dblclick`\n * reached two of the eight:\n *\n * _onclick json5 · code · resource-code · privilege · json · resource-id\n * _ondblclick resource-object · resource-object-legacy\n *\n * Those last two define `_onclick` as a no-op, so nothing opens twice.\n * [확인함] 2026-09-07 · 사용자 보고 — 코드 편집기가 아이콘으로 안 열렸다\n */\n const editor = this.renderRoot.firstElementChild as HTMLElement | null\n editor?.dispatchEvent(new MouseEvent('click', { bubbles: true, composed: true }))\n editor?.dispatchEvent(new MouseEvent('dblclick', { bubbles: true, composed: true }))\n }}\n >${this.editMark === 'popup' ? 'edit_square' : 'edit'}</md-icon\n >`\n : ''}\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('editing')) {\n if (this.editing) {\n this._onKeydownInEditingMode = ((e: KeyboardEvent) => {\n if (e.key === 'Esc' || e.key === 'Escape') {\n /* 편집 취소 */\n this._editCancelled = true\n }\n }).bind(this)\n\n this._onFieldChange = ((e: Event) => {\n this._editCancelled && e.stopPropagation()\n }).bind(this)\n\n delete this._editCancelled\n this.addEventListener('field-change', this._onFieldChange)\n this.addEventListener('keydown', this._onKeydownInEditingMode)\n } else {\n this.removeEventListener('field-change', this._onFieldChange)\n this.removeEventListener('keydown', this._onKeydownInEditingMode)\n }\n }\n\n if (changes.has('column')) {\n /*\n * 정렬은 **넣을 때만이 아니라 되돌릴 때도** 손대야 한다.\n *\n * 이 요소는 재사용된다. 전에는 기본값이 아닐 때만 인라인 값을 넣고 지우지 않았다. 그래서 한 번\n * 오른쪽 정렬 칸을 그린 셀이 다음에 왼쪽 정렬 칸을 그려도 오른쪽에 남았다.\n *\n * [확인함] 품질 화면 「판단」 칸에서 머리글은 x=380(왼쪽)인데 값은 x=452(flex-end)였다. 숫자 칸을\n * 오른쪽으로 바꾼 뒤 드러났다 — 오른쪽 정렬 칸이 드물던 동안은 눈에 안 띄었다. 2026-09-02\n */\n var align = this.column.record.align || DEFAULT_TEXT_ALIGN\n\n if (align == DEFAULT_TEXT_ALIGN) {\n this.style.removeProperty('--data-grid-field-justify-content')\n this.style.removeProperty('--data-grid-field-text-align')\n } else {\n let justify = 'center'\n switch (align) {\n case 'right':\n justify = 'flex-end'\n break\n }\n this.style.setProperty('--data-grid-field-justify-content', justify)\n this.style.setProperty('--data-grid-field-text-align', align)\n }\n\n /* 표식은 값의 반대쪽 빈자리에 선다 — 위 :host([mark-start]) 주석 참고. */\n this.toggleAttribute('mark-start', align === 'right')\n\n const { danger } = this.column\n if (danger) {\n this.setAttribute('danger', '')\n } else {\n this.removeAttribute('danger')\n }\n }\n\n if (changes.has('fixed')) {\n if (this.fixed) {\n this.style.left = this.fixed + 'px'\n } else {\n this.style.left = 'unset'\n }\n }\n\n let disabled = this.column.record.disabled || false\n if (typeof disabled === 'function') {\n disabled = disabled.call(this, this.record[this.column.name], this.column, this.record, this.rowIndex, this)\n }\n\n if (!!disabled) {\n // 비황성화 여부 표시\n this.setAttribute('disabled', '')\n } else {\n // 비황성화 여부 제거\n this.removeAttribute('disabled')\n }\n\n const emphasized =\n /*\n * classifier 는 없을 수 있다. 열 빌더가 채워 주지만 손으로 만든 열에는 없고, 그때 여기서\n * 던진다. 갱신 중에 나는 예외라 화면이 오류보고없이 멈춘다.\n *\n * [확인함] 2026-09-05 · wtr 에서 Cannot read properties of undefined (reading 'call')\n * 팝업 표식을 넣어 칸이 전보다 자주 갱신되면서 드러났다. 원래 있던 자리다.\n */\n this.column.record.classifier?.call(this, this.record, this.rowIndex)?.emphasized || this.emphasized\n\n if (!!emphasized) {\n this.setAttribute('emphasized-row', '')\n\n if (Symbol.iterator in Object(emphasized)) {\n const [backgroundColor, foregroundColor] = emphasized as string[]\n backgroundColor && this.style.setProperty('--grid-record-emphasized-background-color', backgroundColor)\n foregroundColor && this.style.setProperty('--grid-record-emphasized-color', foregroundColor)\n }\n } else {\n this.removeAttribute('emphasized-row')\n }\n }\n\n /**\n * 이 칸에 **팝업 표식**을 붙이나 — 팝업으로 고쳐지고, 지금 고칠 수 있을 때만.\n *\n * 고칠 수 있는지는 열이 함수로 정할 수도 있다(줄마다 다른 경우). 그때는 몸통이 편집을 열 때\n * 하는 것과 같은 방식으로 물어본다. 표식은 있는데 선택해도 안 열리면 그것이 더 나쁘다.\n */\n get opensPopup(): boolean {\n return this.editMark === 'popup'\n }\n\n /**\n * 이 칸을 **고칠 수 있나, 그리고 어디서 고치나.**\n *\n * popup 팝업이 열린다 — 네모와 펜\n * inline 칸 안에서 고친다 — 펜\n * null 못 고친다 — 표식 없음\n *\n * 표식이 있으면 고칠 수 있는 칸이고, 모양이 어디서 고치는지를 말한다.\n *\n * 고칠 수 있는지는 열이 함수로 정할 수도 있다(줄마다 다른 경우). 그때는 몸통이 편집을 열 때\n * 하는 것과 같은 방식으로 물어본다. 표식은 있는데 선택해도 안 열리면 그것이 더 나쁘다.\n */\n get editMark(): 'popup' | 'inline' | null {\n const column = this.column\n\n if (!column) {\n return null\n }\n\n /* 거터에는 붙이지 않는다 — 순번과 고르기 칸은 고치는 자리가 아니다. */\n if (column.type === 'gutter') {\n return null\n }\n\n /*\n * 표 오른쪽의 **빈 채움 열**에도 붙이지 않는다. 남는 자리를 메우는 20px 짜리 빈 열이라\n * 이름도 타입도 없다 — 고칠 것이 없는데 표식만 떴다.\n *\n * [확인함] 2026-09-05 · 인원 화면 맨 끝 칸 · { type: '', name: '', label: false } · 폭 20\n */\n if (!column.name) {\n return null\n }\n\n let { editable } = column.record || ({} as any)\n\n if (typeof editable === 'function') {\n editable = editable.call(this, this.value, column, this.record, this.rowIndex, this)\n }\n\n /*\n * **밝히지 않은 열에는 붙이지 않는다.**\n *\n * 표 전체가 고칠 수 있는지를 판단하는 자리가 같은 기준을 쓴다.\n *\n * [읽었음] data-grid.ts · editableGrid = columns.some(c => !!c.record?.editable)\n *\n * 참일 때만 고칠 수 있는 열로 본다. 선언하지 않은 열까지 세면 **고르기만 하는 표**에도\n * 표식이 깔린다 — 참조 팝업의 목록이 그랬다(2026-09-05). 그 표의 칸은 고르는 자리이지\n * 고치는 자리가 아니다.\n */\n if (!editable) {\n return null\n }\n\n /*\n * 편집기를 **함수로 직접 준 열**은 타입으로 판단할 수 없다. 그리기를 다른 렌더러로 하려고\n * 타입을 바꾼 열이 그렇다 — 관계를 여럿 다는 칸이 `ops-list` 로 그려지면서 편집은 참조\n * 팝업으로 한다(ops-master 의 reference-list).\n *\n * 그런 열은 `record.opensPopup` 으로 스스로 밝힌다. 밝히지 않으면 타입으로 본다.\n *\n * [확인함] 2026-09-05 · 보유 자격 · 타입 ops-list · 팝업으로 열리는데 표식이 inline 이었다\n */\n const declared = (column.record as any)?.opensPopup\n\n if (typeof declared === 'boolean') {\n return declared ? 'popup' : 'inline'\n }\n\n return editorOpensPopup(column.type) ? 'popup' : 'inline'\n }\n\n get editableOnClick() {\n const renderer = this.renderRoot.firstElementChild as HTMLElement\n //@ts-ignore\n return renderer && 'editableOnClick' in renderer ? renderer.editableOnClick : true\n }\n}\n"]}
@@ -21,14 +21,14 @@ export declare class DataGridHeader extends LitElement {
21
21
  updated(changes: PropertyValues): void;
22
22
  _renderHeader(column: ColumnConfig): TemplateResult<1>;
23
23
  /**
24
- * 이 열이 지금 어떻게 정렬되어 있나 — 화살표가 말하는 것을 글자로도 말한다.
24
+ * How this column is sorted right now — the arrow said in text as well.
25
25
  *
26
- * 화살표(keyboard_arrow_up/down)는 그림이라 눈으로만 읽힌다. aria-sort 가 있으면 스크린 리더가
27
- * 열 이름 뒤에 「오름차순」을 붙여 읽고, 정렬을 바꿨을 때 바뀌었다는 것도 전해진다.
26
+ * keyboard_arrow_up/down is a picture and reaches the eye only. With aria-sort a screen reader
27
+ * appends "ascending" to the column name, and a change in sort order is announced as a change.
28
28
  *
29
- * 정렬할 수 없는 열에는 붙이지 않는다 — none 은 「지금은 정렬 안 됨」이라는 뜻이라
30
- * 정렬 자체가 없는 열에 쓰면 있지도 않은 기능을 있다고 말하게 된다.
31
- * 묶음 머리도 마찬가지다(그 자리는 누를 수 없다).
29
+ * Columns that cannot be sorted get nothing: `none` means "sortable, not currently sorted", so
30
+ * putting it on a non-sortable column announces a control that is not there. Same for group
31
+ * headers, which are not clickable.
32
32
  */
33
33
  private _ariaSort;
34
34
  _renderSortHeader(column: ColumnConfig): TemplateResult<1>;
@@ -63,14 +63,14 @@ let DataGridHeader = class DataGridHeader extends LitElement {
63
63
  }
64
64
  }
65
65
  /*
66
- * ── 머리줄을 **줄이라고 말한다** ──────────────────────────────────────────
66
+ * Say that the header is a row.
67
67
  *
68
- * 이 머리는 CSS grid 라 칸들이 평평하게 놓여 있었다 — 보기에는 한 줄(묶음이 있으면 두 줄)이지만
69
- * DOM 에는 줄이 없다. 눈으로는 같은 높이에 있는 것이 한 줄로 읽히는데, 그것은 그림일 뿐이다.
68
+ * The header is a CSS grid, so its cells sat flat: one row on screen (two when grouped), but no
69
+ * row in the DOM. Equal height reads as a row to the eye, and that is all it was — a picture.
70
70
  *
71
- * role=row 를 담을 자리가 필요해서 감싸개를 둔다. `display: contents` 라 상자를 만들지 않으므로
72
- * 칸들은 그대로 grid 의 항목으로 남는다 — 열 폭 · 고정 열 · 묶음 머리의 grid-column 배치가 하나도
73
- * 바뀌지 않는다.
71
+ * The wrapper exists to carry role=row. display: contents generates no box, so the cells stay
72
+ * items of the outer grid and nothing about column widths, fixed columns or group-header
73
+ * grid-column placement changes.
74
74
  */
75
75
  render() {
76
76
  const grouped = this.row2.length > 0;
@@ -80,8 +80,8 @@ let DataGridHeader = class DataGridHeader extends LitElement {
80
80
  ${this.row1.map(({ column, clazz, start, size, align, index, group, colIndex }) => this.renderHeaderColumn({ column, clazz, start, size, align, index, group, colIndex, grouped }))}
81
81
 
82
82
  <!--
83
- 남는 폭을 메우는 칸이다. 읽을 것이 없으므로 표의 칸으로 세지 않는다 — 세면 열 수가 하나
84
- 더 많다고 말하게 된다.
83
+ Width filler. Nothing to read, so it is not counted as a cell — counting it would
84
+ announce one column more than the grid has.
85
85
  -->
86
86
  <div column role="presentation" class=${ifDefined(clazz)}></div>
87
87
  </div>
@@ -187,10 +187,11 @@ let DataGridHeader = class DataGridHeader extends LitElement {
187
187
  var isColumnWidthChangePossible = false;
188
188
  if (changes.has('columns')) {
189
189
  /*
190
- * 보이는 열의 번호 — aria-colindex 는 **숨긴 열을 세지 않는다**(1부터).
190
+ * Visible column numbers, from 1 — aria-colindex does not count hidden columns.
191
191
  *
192
- * 아래 reduce 의 index 는 this.columns 안의 자리라 숨긴 열까지 센 값이다. 그것을 그대로
193
- * 내보내면 열을 하나 숨긴 표에서 「3번째 열」이라고 읽히는 칸이 실제로는 두 번째가 된다.
192
+ * The `index` in the reduces below is the position within this.columns, hidden ones included.
193
+ * Passing that through means a grid with one column hidden announces "column 3" for what is
194
+ * actually the second column.
194
195
  */
195
196
  const colIndexOf = new Map();
196
197
  this.columns.forEach((column, index) => {
@@ -264,14 +265,14 @@ let DataGridHeader = class DataGridHeader extends LitElement {
264
265
  return html `${((_a = column === null || column === void 0 ? void 0 : column.record) === null || _a === void 0 ? void 0 : _a.mandatory) ? '*' : ''} ${title} `;
265
266
  }
266
267
  /**
267
- * 이 열이 지금 어떻게 정렬되어 있나 — 화살표가 말하는 것을 글자로도 말한다.
268
+ * How this column is sorted right now — the arrow said in text as well.
268
269
  *
269
- * 화살표(keyboard_arrow_up/down)는 그림이라 눈으로만 읽힌다. aria-sort 가 있으면 스크린 리더가
270
- * 열 이름 뒤에 「오름차순」을 붙여 읽고, 정렬을 바꿨을 때 바뀌었다는 것도 전해진다.
270
+ * keyboard_arrow_up/down is a picture and reaches the eye only. With aria-sort a screen reader
271
+ * appends "ascending" to the column name, and a change in sort order is announced as a change.
271
272
  *
272
- * 정렬할 수 없는 열에는 붙이지 않는다 — none 은 「지금은 정렬 안 됨」이라는 뜻이라
273
- * 정렬 자체가 없는 열에 쓰면 있지도 않은 기능을 있다고 말하게 된다.
274
- * 묶음 머리도 마찬가지다(그 자리는 누를 수 없다).
273
+ * Columns that cannot be sorted get nothing: `none` means "sortable, not currently sorted", so
274
+ * putting it on a non-sortable column announces a control that is not there. Same for group
275
+ * headers, which are not clickable.
275
276
  */
276
277
  _ariaSort(column, group) {
277
278
  if (group || !column.sortable) {
@@ -741,11 +742,11 @@ DataGridHeader.styles = [
741
742
  }
742
743
 
743
744
  /*
744
- * 줄 감싸개 — 상자를 만들지 않는다.
745
+ * Row wrapper — generates no box.
745
746
  *
746
- * role=row 를 담기 위한 요소일 뿐이라 배치에는 끼어들면 안 된다. display: contents 면 이 요소는
747
- * 상자를 만들지 않고 자식이 그대로 바깥 grid 의 항목이 된다 — 열 폭 · 고정 열 · 묶음 머리의
748
- * grid-column 배치가 그대로다.
747
+ * It exists only to carry role=row, so it must stay out of layout. With display: contents the
748
+ * element produces no box and its children remain items of the outer grid — column widths, fixed
749
+ * columns and the grid-column placement of group headers are untouched.
749
750
  */
750
751
  div[grid-row] {
751
752
  display: contents;
@@ -1 +1 @@
1
- {"version":3,"file":"data-grid-header.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid-header.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/popup/ox-popup.js'\nimport '@material/web/icon/icon.js'\n\nimport i18next from 'i18next'\nimport { css, html, LitElement, PropertyValues, nothing, TemplateResult } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport throttle from 'lodash-es/throttle.js'\n\nimport { OxPopup } from '@operato/popup'\nimport { TooltipReactiveController, closestElement } from '@operato/utils'\n\nimport { ZERO_COLUMNS, ZERO_DATA } from '../configure/zero-config.js'\nimport { FilterStyles } from '../filters/filter-styles.js'\nimport { getFilterRenderer } from '../filters/registry.js'\nimport { ColumnConfig, FilterConfigObject, FilterValue, GristData, SortersConfig } from '../types.js'\n\n/** 칸의 정렬 선언(record.align)을 flex 의 말로 옮긴다. */\nconst ALIGN_JUSTIFY = {\n left: 'flex-start',\n center: 'center',\n right: 'flex-end'\n} as const\n\n@customElement('ox-grid-header')\nexport class DataGridHeader extends LitElement {\n static styles = [\n FilterStyles,\n css`\n :host {\n position: relative;\n display: grid;\n grid-template-columns: var(--grid-template-columns);\n\n border-top: var(--grid-header-top-border);\n\n /*\n * 가로는 감춘다 — 머리를 사람이 직접 끌지는 않는다. 몸을 따라 프로그램이 옮긴다.\n *\n * 세로는 몸과 같은 만큼 자리를 비운다. 몸만 스크롤바에 자리를 내주면 갈 수 있는 거리가\n * 달라져서, 오른쪽 끝에서 몸이 그 폭만큼 더 간다(몸의 scrollbar-gutter 주석 참조).\n * 머리에는 세로로 넘칠 것이 없으므로 손잡이는 그려지지 않고 자리만 남는다.\n */\n overflow-x: hidden;\n overflow-y: scroll;\n scrollbar-gutter: stable;\n\n font-variation-settings: 'FILL' 1;\n\n user-select: none;\n }\n\n :host([raised]) [fixed] {\n /* 고정 컬럼이 살짝 올라와 있는 느낌을 표현 */\n box-shadow: 3px 0 3px rgba(0, 0, 0, 0.1);\n }\n\n div[column] {\n display: flex;\n\n white-space: nowrap;\n overflow: hidden;\n background-color: var(--grid-header-background-color);\n border-bottom: var(--grid-header-bottom-border);\n padding: var(--grid-header-padding);\n\n text-overflow: ellipsis;\n font: var(--grid-header-font);\n /*\n * 글꼴은 따로 받는다 — 기본은 물려받는다(본문과 같은 글꼴).\n *\n * font 축약형은 글꼴 이름을 반드시 요구해서, 토큰 하나로 쓰면 굵기 · 크기와 글꼴이 묶인다.\n * 그 탓에 머리글이 고정폭으로 그려졌는데, **고정폭에는 한글 글자가 없다.** 대체 글꼴로 떨어지므로\n * 「ISA-95 계층 단」 한 줄 안에서 라틴과 한글이 서로 다른 글꼴이 됐다.\n *\n * 테마가 글꼴까지 정하고 싶으면 --grid-header-font-family 를 준다.\n */\n font-family: var(--grid-header-font-family, inherit);\n color: var(--grid-header-color);\n }\n\n /*\n * 거터 칸(순번 · 선택 · 더러움 표식)은 몸과 **같은 자리**에 있어야 한다. 머리의 체크박스와 각 줄의\n * 체크박스가 한 줄로 서지 않으면 표가 어긋나 보인다.\n *\n * 전에는 두 가지가 어긋나 있었다.\n * · text-align: center 로 가운데를 맞추려 했지만 이 칸은 display: flex 다 —\n * flex 안에서 text-align 은 항목을 옮기지 못한다. 그래서 왼쪽에 붙었다\n * · 여백을 몸(--grid-gutter-padding)과 **다른 토큰**(--spacing-small)에서 읽었다\n *\n * 그래서 정렬은 flex 로 하고, 여백은 몸과 같은 토큰을 본다.\n */\n div[gutter] {\n padding: var(--grid-gutter-padding);\n /*\n * 기본은 가운데. 거터마다 자기 정렬이 있으면 renderHeaderColumn 이 인라인으로 덮는다 —\n * 순번은 오른쪽이다(몸의 숫자가 오른쪽이므로 머리의 # 도 오른쪽이어야 자릿수가 맞아 보인다).\n */\n justify-content: center;\n }\n\n /*\n * 거터 칸의 내용물은 span[for-title] 안에 들어간다 — 열 제목이 쓰는 그 span 이다. 그래서 제목용\n * 규칙 둘을 함께 물려받는데, 거터에는 제목도 정렬 표식도 없으므로 둘 다 체크박스를 밀기만 한다.\n *\n * flex: 1 칸을 다 채워서, 칸의 justify-content 가 나눌 여백이 남지 않는다\n * margin-right 제목과 표식 사이를 벌리려던 값이라, 내용물이 그만큼 왼쪽으로 간다\n *\n * 둘을 거두면 span 이 내용물 크기로 줄고, 칸이 그것을 가운데로 놓는다. 입력의 기본 여백도 없애야\n * 몸의 체크박스와 정확히 같은 자리에 선다 — 몸은 여백 없이 가운데에 있다.\n */\n div[gutter] span[for-title] {\n flex: none;\n margin-right: 0;\n }\n\n div[gutter] input {\n margin: 0;\n }\n\n span {\n display: block;\n white-space: nowrap;\n overflow: hidden;\n }\n\n span[for-title] {\n /*\n * 이름이 자기 길이만큼만 차지한다 — 그러면 정렬 표식이 이름 바로 오른쪽에 붙는다.\n *\n * 고치는 표에서는 1 로 되돌린다(data-grid.ts 의 editable-grid 와 같은 값). 거기서는 칸 끝에 폭 조절\n * 손잡이가 서 있어서, 표식이 그 옆에 모여 있는 편이 낫다.\n *\n * **조건은 손잡이가 보이는지다.** 표식이 칸 오른쪽 끝에 있는데 그 오른쪽에 선이 없으면 눈이\n * 다음 칸의 것으로 읽는다. 손잡이가 있으면 그 선이 「여기까지가 이 칸」이라고 말해 주므로 끝에\n * 있어도 자기 칸의 것으로 읽힌다.\n *\n * 그래서 손잡이 토큰에서 직접 파생시킨다. 전에는 편집 여부에 걸고 두 토큰을 한 자리에서 함께\n * 정했는데, 그러면 테마가 한쪽만 건드릴 때 어긋난다.\n *\n * 기본은 **붙는 쪽**이다. 스타일 질의를 모르는 브라우저에서는 이 값이 남는데, 읽기 전용 표가\n * 다수라 그쪽이 옳은 기본이다(고치는 표에서는 표식이 이름 옆에 붙을 뿐이고 그건 흠이 아니다).\n *\n * 줄어듦은 항상 1 이다. 긴 이름이 줄어들 수 있어야 말줄임으로 잘린다 — 줄어들지 못하면 칸을\n * 넘어가 그냥 잘린다. 축약형(flex)에 var 을 쓰면 「0 1 auto」 가 「none」 으로 해석되는 일이\n * 있어서(실측 0 0 auto) 낱개 속성으로 적는다.\n */\n flex-grow: 0;\n flex-shrink: 1;\n flex-basis: auto;\n /* 표식 무리와 이름 사이를 벌린다 — 붙어 있으면 이름의 일부처럼 읽힌다. */\n margin-right: 6px;\n /* 작은 대문자 라벨로 쓸 때 자간이 필요하다. 테마가 정하지 않으면 0 이다. */\n letter-spacing: var(--grid-header-letter-spacing, normal);\n text-overflow: ellipsis;\n line-height: 1.6;\n text-transform: var(--grid-header-text-transform, capitalize);\n align-self: center;\n }\n\n /*\n * 손잡이가 보이면 이름이 칸을 채워 표식을 오른쪽 끝으로 민다 — 거기에는 손잡이가 서 있으므로\n * 표식이 그 옆에 모인다.\n *\n * none 이 아닌 값을 묻는다. 이 저장소에서 「보임」은 flex 뿐이지만, 테마가 inline-flex 나\n * block 을 쓸 수도 있다. 감춤은 none 하나뿐이라 그쪽을 부정하는 편이 좁다.\n */\n @container not style(--grid-header-splitter-display: none) {\n span[for-title] {\n flex-grow: 1;\n }\n }\n\n span[for-title] * {\n vertical-align: middle;\n }\n\n span[for-title] md-icon {\n font-size: 1.2em;\n }\n\n span[sorter],\n span[filter] {\n display: flex;\n align-self: center;\n\n padding: 0;\n border: 0;\n }\n\n span[sorter] md-icon {\n font-size: var(--grid-header-sorter-size);\n }\n\n /*\n * ── 머리에는 「고칠 수 있다」 표식을 두지 않는다 (2026-09-05) ────────\n * 칸마다 표식이 생긴 뒤로 머리의 연필은 같은 말을 두 번 하는 자리가 됐다. 게다가 머리의\n * 것은 **틀린 말을 할 수 있다** — editable 이 함수인 열에서 머리는 참·거짓을 가리지 못해\n * 늘 「고칠 수 있다」고 하고, 실제로는 한 줄도 못 고치는 표가 나온다. 칸의 표식은 그 함수를\n * 줄마다 불러 보고 정한다.\n *\n * 머리는 이름·정렬·거르기의 자리로 두고, 고치기는 고치는 자리에서 알린다.\n *\n * ── 정렬 표식 ──────────────────────────────────────────────────────\n * 정렬할 수 있다는 것은 아주 흐리게, 지금 정렬 중인 것만 한 단계 진하게 둔다.\n *\n * 색은 토큰으로 받되 currentColor 를 섞은 폴백을 둔다 — 테마가 값을 정하지 않아도 흐려지고\n * 라이트·다크 어느 쪽에서도 배경 대비가 유지된다.\n */\n md-icon[sortable-mark] {\n color: var(--grid-header-sortable-color, color-mix(in srgb, currentColor 18%, transparent));\n }\n\n /*\n * 지금 정렬 중이라는 표시는 **상태**다 — 흐리게 두면 무엇으로 정렬됐는지 화면이 말하지 않는\n * 것과 같다. 52% 로는 어두운 화면에서 2.86:1 이었다(실측 2026-09-05). 60% 면 밝은 화면\n * 4.7 · 어두운 화면 5.4 로 UI 요소 기준(3:1)을 넘는다.\n *\n * 「정렬할 수 있다」(sortable-mark)는 그 옆에서 계속 흐리게 둔다. 그것은 상태가 아니라\n * 곁들이는 안내이고, 머리글 자체가 눌리는 자리라 길은 따로 있다.\n */\n span[sorter] md-icon:not([sortable-mark]),\n span[sorter] sub {\n color: var(--grid-header-sorted-color, color-mix(in srgb, currentColor 60%, transparent));\n }\n\n span[filter] > md-icon {\n font-size: var(--fontsize-default);\n line-height: 20px;\n }\n\n /*\n * 열 폭 조절 손잡이 — **세로 선을 그리는 것이 이것이다.**\n *\n * 표 안의 세로 선은 이 손잡이의 오른쪽 테두리다(칸 자체는 위아래 테두리만 갖는다). 그래서 이\n * 손잡이를 감추면 열 폭 조절과 세로 격자가 함께 사라진다 — 그 둘은 원래 한 물건이다.\n *\n * 고치지 않는 목록에서는 열 폭을 끌어 옮길 일이 없고, 세로 선이 없으면 표가 격자가 아니라\n * 줄로 읽힌다. 그럴 때 테마가 이렇게 정한다.\n *\n * --grid-header-splitter-display: none\n *\n * 값을 정하지 않으면 예전 그대로다 — 편집용 표는 손잡이가 있어야 한다.\n */\n span[splitter] {\n display: var(--grid-header-splitter-display, flex);\n cursor: col-resize;\n border-right: var(--grid-header-splitter-border);\n margin-right: 0;\n }\n\n /*\n * 손잡이가 있는 칸은 오른쪽 여백을 두지 않는다.\n *\n * 손잡이는 flex 항목이라 칸의 padding 안쪽에 놓인다. 좌우 여백이 2px 이던 동안에는 그 차이가\n * 안 보였지만, 여백을 10px 로 올리자 손잡이가 열 경계에서 10px 당겨졌다 — 세로 선이 경계가\n * 아닌 자리에 그려진 것이다.\n *\n * 그래서 손잡이가 있을 때만 오른쪽 여백을 거둔다. 손잡이가 없는 칸(거터 · 폭을 못 바꾸는 열)은\n * 여백을 그대로 둬야 글자가 경계에 닿지 않는다.\n *\n * 세로 길이는 손대지 않는다 — flex 가 늘려 주는 그대로, 칸의 위아래 여백만큼 들어간 짧은 선이다.\n */\n div[column]:has(span[splitter]) {\n padding-right: 0;\n }\n\n span[splitter]:hover {\n border-right: var(--grid-header-splitter-border-hover);\n }\n\n [filter-title] {\n color: var(--grid-header-filter-title-color);\n font: var(--grid-header-filter-title-font);\n text-transform: capitalize;\n }\n\n [filter-title] * {\n vertical-align: middle;\n }\n\n [filter-title] md-icon {\n opacity: 0.7;\n color: var(--grid-header-filter-title-icon-color);\n }\n\n [filter] input[type='checkbox'] {\n margin-left: var(--spacing-medium);\n margin-bottom: var(--spacing-small);\n }\n\n [fixed] {\n position: sticky;\n z-index: 2;\n }\n\n .span-both {\n grid-row: 1 / span 2; /* 1단과 2단에 걸쳐 표시 */\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 .group-header {\n grid-row: 1; /* 1행에 배치 */\n grid-column: var(--group-start) / span var(--group-size); /* 2열부터 시작하여 2열에 걸쳐 표시 */\n }\n\n @media print {\n :host {\n grid-template-columns: var(--grid-template-print-columns);\n }\n }\n\n @media (max-width: 768px) {\n /* 모바일에서는 그리드에서 고정된 열 해제 */\n [fixed] {\n position: static;\n z-index: 0;\n box-shadow: none !important;\n }\n }\n `\n ]\n\n @property({ type: Array }) columns: ColumnConfig[] = ZERO_COLUMNS\n @property({ type: Object }) data: GristData = ZERO_DATA\n @property({ type: Array }) sorters: SortersConfig = []\n @property({ type: Array }) filters: FilterValue[] = []\n @property({ type: Boolean, attribute: 'filtering-feature' }) filteringFeature: boolean = false\n\n @state() private row1: {\n index: number\n /** 보이는 열 중 몇 번째인가(1부터) — aria-colindex 가 이 값을 쓴다. */\n colIndex?: number\n column: ColumnConfig\n clazz?: string\n start?: number\n size?: number\n align?: string\n group?: string\n }[] = []\n\n @state() private row2: {\n index: number\n /** 보이는 열 중 몇 번째인가(1부터) — aria-colindex 가 이 값을 쓴다. */\n colIndex?: number\n column: ColumnConfig\n }[] = []\n\n private _lastAccVal?: number\n private _throttledNotifier?: any\n\n private tooltipController?: TooltipReactiveController = new TooltipReactiveController(this)\n\n connectedCallback() {\n super.connectedCallback()\n\n const grid = closestElement('ox-grist', this)\n\n this.addEventListener('scroll', function () {\n this.scrollLeft == 0 ? this.removeAttribute('raised') : this.setAttribute('raised', '')\n })\n\n if (this.filteringFeature) {\n this?.addEventListener('filter-change', (e: Event) => {\n const { name, operator, value } = (e as CustomEvent).detail\n const filters = this.filters instanceof Array ? [...this.filters] : []\n\n if (value == null) {\n const index = filters.findIndex(filter => filter.name === name)\n if (index === -1) {\n return\n }\n\n filters.splice(index, 1)\n } else {\n const index = filters.findIndex(filter => filter.name === name)\n if (index === -1) {\n filters.push({ name, operator, value })\n } else {\n filters.splice(index, 1, { name, operator, value })\n }\n }\n\n grid?.dispatchEvent(\n new CustomEvent('fetch-params-change', {\n detail: {\n filters,\n from: 'data-grid-header'\n }\n })\n )\n })\n }\n }\n\n /*\n * ── 머리줄을 **줄이라고 말한다** ──────────────────────────────────────────\n *\n * 이 머리는 CSS grid 라 칸들이 평평하게 놓여 있었다 — 보기에는 한 줄(묶음이 있으면 두 줄)이지만\n * DOM 에는 줄이 없다. 눈으로는 같은 높이에 있는 것이 한 줄로 읽히는데, 그것은 그림일 뿐이다.\n *\n * role=row 를 담을 자리가 필요해서 감싸개를 둔다. `display: contents` 라 상자를 만들지 않으므로\n * 칸들은 그대로 grid 의 항목으로 남는다 — 열 폭 · 고정 열 · 묶음 머리의 grid-column 배치가 하나도\n * 바뀌지 않는다.\n */\n render() {\n const grouped = this.row2.length > 0\n const clazz = grouped ? 'span-both' : undefined\n\n return html`\n <div grid-row role=\"row\" aria-rowindex=\"1\">\n ${this.row1.map(({ column, clazz, start, size, align, index, group, colIndex }) =>\n this.renderHeaderColumn({ column, clazz, start, size, align, index, group, colIndex, grouped })\n )}\n\n <!--\n 남는 폭을 메우는 칸이다. 읽을 것이 없으므로 표의 칸으로 세지 않는다 — 세면 열 수가 하나\n 더 많다고 말하게 된다.\n -->\n <div column role=\"presentation\" class=${ifDefined(clazz)}></div>\n </div>\n\n ${grouped\n ? html`\n <div grid-row role=\"row\" aria-rowindex=\"2\">\n ${this.row2.map(({ column, index, colIndex }) =>\n this.renderHeaderColumn({ column, index, colIndex, grouped })\n )}\n </div>\n `\n : nothing}\n `\n }\n\n renderHeaderColumn({ column, clazz, start, size, align, index, group, colIndex, grouped }: any): TemplateResult {\n if (column.hidden) {\n return html`${nothing}`\n }\n\n /*\n * 거터 머리는 flex 로 정렬한다.\n *\n * 아래 span 의 `text-align` 은 거터에서 듣지 않는다 — 그 span 이 내용물 크기로 줄어 있어서\n * (위 div[gutter] 머리말 참조) 글자를 밀 여백이 span 안에 없다. 그래서 칸이 밀어야 한다.\n *\n * 값은 그 거터가 이미 선언한 것을 본다. 순번은 right, 선택과 더러움 표식은 center 다. 여기에 따로\n * 적으면 거터를 하나 더할 때 두 곳을 맞춰야 한다.\n */\n /*\n * 정렬은 **칸이 flex 로 민다.** 아래 span 의 text-align 에 기대지 않는다.\n *\n * 그 span 은 이름 길이만큼만 차지하므로(위 span[for-title] 머리말) 안에 글자를 밀 여백이 없다.\n * 그래서 text-align 이 아무 일도 하지 않는다 — 숫자 칸의 값은 오른쪽인데 머리글만 왼쪽에\n * 남았다. [확인함] 「수량」 머리 x=391 · 값 오른쪽 끝 x=402. 2026-09-02\n *\n * 칸이 밀면 이름과 표식이 **함께** 그 방향으로 간다. 그래서 오른쪽 정렬 칸에서도 표식이 이름\n * 옆에 붙어 있다.\n *\n * 거터의 기본은 가운데(체크박스 · 더러움 표식), 보통 칸의 기본은 왼쪽이다.\n */\n const fallback = column.type == 'gutter' ? 'center' : 'flex-start'\n const justify = `justify-content:${ALIGN_JUSTIFY[(align || column.record?.align) as keyof typeof ALIGN_JUSTIFY] || fallback};`\n\n return html`\n <div\n ?gutter=${column.type == 'gutter'}\n ?fixed=${column.fixed}\n column\n role=\"columnheader\"\n aria-colindex=${ifDefined(group ? start : colIndex)}\n aria-colspan=${ifDefined(group ? size : undefined)}\n aria-rowspan=${ifDefined(clazz === 'span-both' ? 2 : undefined)}\n aria-sort=${ifDefined(this._ariaSort(column, group))}\n class=${ifDefined(clazz)}\n style=${group\n ? `--group-start:${start};--group-size:${size};${justify}${column.header?.style || ''}`\n : `${justify}${column.header?.style || ''}`}\n >\n <span\n for-title\n data-reactive-tooltip\n style=\"text-align:${align || column.record.align || 'left'};\"\n @click=${(e: MouseEvent) => this._changeSort(column)}\n >${this._renderHeader(column)}\n </span>\n\n ${!group && column.sortable\n ? html`\n <span sorter @click=${(e: MouseEvent) => this._changeSort(column)}>\n ${this._renderSortHeader(column)}\n </span>\n `\n : nothing}\n ${!group &&\n this.filteringFeature &&\n column.filter &&\n (column.filter as FilterConfigObject).operator !== 'search'\n ? html` <span filter> ${this._renderFilterHeader(column)} </span> `\n : nothing}\n ${column.resizable !== false\n ? html`\n <span splitter draggable=\"false\" @pointerdown=${(e: PointerEvent) => this._pointerdown(e, index)}\n >&nbsp;</span\n >\n `\n : nothing}\n </div>\n `\n }\n\n notifyFixedLeftChange() {\n const fixedHeaders = Array.from(this.renderRoot.querySelectorAll('div[fixed]')) as HTMLElement[]\n const fixedLefts = [] as number[]\n var left = 0\n fixedHeaders.forEach((header: HTMLElement) => {\n header.style.left = left + 'px'\n fixedLefts.push(left)\n\n const width = header.offsetWidth\n left += width\n })\n\n this.dispatchEvent(\n new CustomEvent('fixed-lefts-change', {\n detail: fixedLefts\n })\n )\n }\n\n updated(changes: PropertyValues) {\n var isColumnWidthChangePossible = false\n\n if (changes.has('columns')) {\n /*\n * 보이는 열의 번호 — aria-colindex 는 **숨긴 열을 세지 않는다**(1부터).\n *\n * 아래 reduce 의 index 는 this.columns 안의 자리라 숨긴 열까지 센 값이다. 그것을 그대로\n * 내보내면 열을 하나 숨긴 표에서 「3번째 열」이라고 읽히는 칸이 실제로는 두 번째가 된다.\n */\n const colIndexOf = new Map<number, number>()\n this.columns.forEach((column, index) => {\n if (!column.hidden) {\n colIndexOf.set(index, colIndexOf.size + 1)\n }\n })\n\n this.row2 = this.columns.reduce((row2, column, index) => {\n if (column.hidden || !column.header?.group) {\n return row2\n }\n return row2.concat({\n index,\n colIndex: colIndexOf.get(index),\n column\n } as any)\n }, [] as any[])\n\n const clazz = this.row2.length > 0 ? 'span-both' : undefined\n\n var columnNo = 0\n\n this.row1 = this.columns.reduce((row1, column, index) => {\n if (column.hidden) {\n return row1\n }\n\n columnNo++\n if (!column.header?.group) {\n return row1.concat({\n index,\n colIndex: colIndexOf.get(index),\n column,\n clazz\n } as any)\n }\n const { group, groupStyle } = column.header\n const last = row1[row1.length - 1] as any\n\n if (!last || group !== last.group) {\n return row1.concat({\n index,\n column: {\n ...column,\n header: {\n renderer: () => group,\n style: groupStyle\n }\n },\n group,\n align: 'center',\n clazz: 'group-header',\n start: columnNo,\n size: 1\n } as any)\n }\n\n last.size++\n\n return row1\n }, [] as any[])\n\n isColumnWidthChangePossible = true\n }\n\n if (changes.has('data')) {\n isColumnWidthChangePossible = true\n }\n\n if (isColumnWidthChangePossible) {\n // requestAnimationFrame(() => this.notifyFixedLeftChange())\n this.notifyFixedLeftChange()\n }\n }\n\n _renderHeader(column: ColumnConfig) {\n var { renderer } = column.header || {}\n var title = renderer.call(this, column)\n\n return html`${column?.record?.mandatory ? '*' : ''} ${title} `\n }\n\n /**\n * 이 열이 지금 어떻게 정렬되어 있나 — 화살표가 말하는 것을 글자로도 말한다.\n *\n * 화살표(keyboard_arrow_up/down)는 그림이라 눈으로만 읽힌다. aria-sort 가 있으면 스크린 리더가\n * 열 이름 뒤에 「오름차순」을 붙여 읽고, 정렬을 바꿨을 때 바뀌었다는 것도 전해진다.\n *\n * 정렬할 수 없는 열에는 붙이지 않는다 — none 은 「지금은 정렬 안 됨」이라는 뜻이라\n * 정렬 자체가 없는 열에 쓰면 있지도 않은 기능을 있다고 말하게 된다.\n * 묶음 머리도 마찬가지다(그 자리는 누를 수 없다).\n */\n private _ariaSort(column: ColumnConfig, group?: string): 'ascending' | 'descending' | 'none' | undefined {\n if (group || !column.sortable) {\n return undefined\n }\n\n const sorter = (this.sorters || []).find(sorter => column.type !== 'gutter' && column.name == sorter.name)\n\n if (!sorter) {\n return 'none'\n }\n\n return sorter.desc ? 'descending' : 'ascending'\n }\n\n _renderSortHeader(column: ColumnConfig) {\n var sorters = this.sorters || []\n\n var sorter = sorters.find(sorter => column.type !== 'gutter' && column.name == sorter.name)\n if (!sorter) {\n return html`<md-icon sortable-mark>unfold_more</md-icon>`\n }\n\n if (sorters.length > 1) {\n var rank = sorters.indexOf(sorter) + 1\n return sorter.desc\n ? html` <md-icon>keyboard_arrow_down</md-icon><sub>${rank}</sub> `\n : html` <md-icon>keyboard_arrow_up</md-icon><sub>${rank}</sub> `\n } else {\n return sorter.desc ? html` <md-icon>keyboard_arrow_down</md-icon> ` : html` <md-icon>keyboard_arrow_up</md-icon> `\n }\n }\n\n _renderFilterHeader(column: ColumnConfig) {\n const name = column.name\n const filter = column.filter as FilterConfigObject\n const type = filter.type\n const value = this.filters.find(filter => filter.name === name)?.value\n const idx = filter!.operator === 'between' ? 1 : 0\n const renderer = getFilterRenderer(type)[idx]\n\n return html`\n <md-icon\n @click=${(e: Event) => {\n const parent = (e.target as HTMLElement).closest('[column]') as HTMLElement\n const popup = parent.querySelector('ox-popup, ox-popup-list') as OxPopup | null\n // const popup = (e.target as HTMLElement).nextSibling as OxPopupList | null\n\n // absolute position인 popup의 위치 부모는 grist 이므로,\n // data-grid-header 의 포지션 부모(grist)의 위치로부터 계산해야함.\n // this의 position을 relative로 하지 못하는 이유 : ox-popup-list가 grid body에 덮히기 때문.\n // const top = parent.offsetTop + parent.offsetHeight\n // const right = this.clientWidth - (parent.offsetLeft + parent.offsetWidth - this.scrollLeft)\n\n popup?.open({\n right: 0,\n top: parent.offsetHeight,\n fixed: true\n })\n }}\n >filter_alt</md-icon\n >\n\n ${!renderer\n ? html``\n : type !== 'select'\n ? html` <ox-popup\n ><div filter-title><md-icon>filter_alt</md-icon> filter by <strong>${column.name}</strong></div>\n ${renderer(column, value, this)}</ox-popup\n >`\n : filter!.operator === 'in'\n ? html`<ox-popup-list\n multiple\n attr-selected=\"checked\"\n .value=${value}\n with-search\n @select=${(e: CustomEvent) =>\n e.target?.dispatchEvent(\n new CustomEvent('filter-change', {\n bubbles: true,\n composed: true,\n detail: {\n name,\n operator: filter!.operator,\n value: !e.detail\n ? undefined\n : e.detail instanceof Array && e.detail.length === 0\n ? undefined\n : e.detail\n }\n })\n )}\n ><div filter-title slot=\"header\">\n <md-icon>filter_alt</md-icon> filter by <strong>${column.name}</strong>\n </div>\n ${renderer(column, value, this)}</ox-popup-list\n >`\n : html`<ox-popup-list\n .value=${value}\n with-search\n @select=${(e: CustomEvent) =>\n e.target?.dispatchEvent(\n new CustomEvent('filter-change', {\n bubbles: true,\n composed: true,\n detail: {\n name,\n operator: filter!.operator,\n value: e.detail ? e.detail : undefined\n }\n })\n )}\n ><div filter-title slot=\"header\">\n <md-icon>filter_alt</md-icon> filter by <strong>${column.name}</strong>\n </div>\n ${renderer(column, value, this)}</ox-popup-list\n >`}\n `\n }\n\n _changeSort(column: ColumnConfig) {\n if (!column.sortable) {\n return\n }\n\n var sorters = [...this.sorters]\n\n var idx = sorters.findIndex(sorter => sorter.name == column.name)\n if (idx !== -1) {\n let sorter = sorters[idx]\n if (sorter.desc) {\n sorters.splice(idx, 1)\n } else {\n sorters.splice(idx, 1, {\n ...sorter,\n desc: true\n })\n }\n } else {\n var sorter = {\n name: column.name,\n desc: false\n }\n\n sorters.push(sorter)\n }\n\n this.sorters = sorters\n\n this.dispatchEvent(\n new CustomEvent('fetch-params-change', {\n bubbles: true,\n composed: true,\n detail: {\n sorters: this.sorters,\n from: 'data-grid-header'\n }\n })\n )\n }\n\n _accumalate(x: number) {\n this._lastAccVal = (this._lastAccVal ?? 0) + x\n return this._lastAccVal\n }\n\n _notifyWidthChange(idx: number, width: number) {\n if (!this._throttledNotifier) {\n this._throttledNotifier = throttle((idx: number, width: number) => {\n this.dispatchEvent(\n new CustomEvent('column-width-change', {\n bubbles: true,\n composed: true,\n detail: {\n idx,\n width\n }\n })\n )\n\n this.notifyFixedLeftChange()\n\n this._lastAccVal = 0\n }, 100)\n }\n\n this._throttledNotifier(idx, width)\n }\n\n _pointerdown(e: PointerEvent, idx: number) {\n e.stopPropagation()\n e.preventDefault()\n ;(e.target as HTMLElement).setPointerCapture(e.pointerId)\n\n var pointermoveHandler = ((e: PointerEvent) => {\n e.stopPropagation()\n e.preventDefault()\n let column = this.columns[idx]\n\n let width = Math.max(0, Number(column.width || 100) + this._accumalate(e.movementX))\n if (width == 0) {\n /* CLARIFY-ME 왜 마지막 이벤트의 offsetX로 음수 값이 오는가 */\n return\n }\n\n this._notifyWidthChange(idx, width)\n }).bind(this)\n\n var pointerupHandler = ((e: PointerEvent) => {\n ;(e.target as HTMLElement).releasePointerCapture(e.pointerId)\n\n document.removeEventListener('pointermove', pointermoveHandler)\n document.removeEventListener('pointerup', pointerupHandler)\n\n pointermoveHandler(e)\n }).bind(this)\n\n document.addEventListener('pointermove', pointermoveHandler)\n document.addEventListener('pointerup', pointerupHandler)\n }\n}\n"]}
1
+ {"version":3,"file":"data-grid-header.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid-header.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/popup/ox-popup.js'\nimport '@material/web/icon/icon.js'\n\nimport i18next from 'i18next'\nimport { css, html, LitElement, PropertyValues, nothing, TemplateResult } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport throttle from 'lodash-es/throttle.js'\n\nimport { OxPopup } from '@operato/popup'\nimport { TooltipReactiveController, closestElement } from '@operato/utils'\n\nimport { ZERO_COLUMNS, ZERO_DATA } from '../configure/zero-config.js'\nimport { FilterStyles } from '../filters/filter-styles.js'\nimport { getFilterRenderer } from '../filters/registry.js'\nimport { ColumnConfig, FilterConfigObject, FilterValue, GristData, SortersConfig } from '../types.js'\n\n/** 칸의 정렬 선언(record.align)을 flex 의 말로 옮긴다. */\nconst ALIGN_JUSTIFY = {\n left: 'flex-start',\n center: 'center',\n right: 'flex-end'\n} as const\n\n@customElement('ox-grid-header')\nexport class DataGridHeader extends LitElement {\n static styles = [\n FilterStyles,\n css`\n :host {\n position: relative;\n display: grid;\n grid-template-columns: var(--grid-template-columns);\n\n border-top: var(--grid-header-top-border);\n\n /*\n * 가로는 감춘다 — 머리를 사람이 직접 끌지는 않는다. 몸을 따라 프로그램이 옮긴다.\n *\n * 세로는 몸과 같은 만큼 자리를 비운다. 몸만 스크롤바에 자리를 내주면 갈 수 있는 거리가\n * 달라져서, 오른쪽 끝에서 몸이 그 폭만큼 더 간다(몸의 scrollbar-gutter 주석 참조).\n * 머리에는 세로로 넘칠 것이 없으므로 손잡이는 그려지지 않고 자리만 남는다.\n */\n overflow-x: hidden;\n overflow-y: scroll;\n scrollbar-gutter: stable;\n\n font-variation-settings: 'FILL' 1;\n\n user-select: none;\n }\n\n :host([raised]) [fixed] {\n /* 고정 컬럼이 살짝 올라와 있는 느낌을 표현 */\n box-shadow: 3px 0 3px rgba(0, 0, 0, 0.1);\n }\n\n div[column] {\n display: flex;\n\n white-space: nowrap;\n overflow: hidden;\n background-color: var(--grid-header-background-color);\n border-bottom: var(--grid-header-bottom-border);\n padding: var(--grid-header-padding);\n\n text-overflow: ellipsis;\n font: var(--grid-header-font);\n /*\n * 글꼴은 따로 받는다 — 기본은 물려받는다(본문과 같은 글꼴).\n *\n * font 축약형은 글꼴 이름을 반드시 요구해서, 토큰 하나로 쓰면 굵기 · 크기와 글꼴이 묶인다.\n * 그 탓에 머리글이 고정폭으로 그려졌는데, **고정폭에는 한글 글자가 없다.** 대체 글꼴로 떨어지므로\n * 「ISA-95 계층 단」 한 줄 안에서 라틴과 한글이 서로 다른 글꼴이 됐다.\n *\n * 테마가 글꼴까지 정하고 싶으면 --grid-header-font-family 를 준다.\n */\n font-family: var(--grid-header-font-family, inherit);\n color: var(--grid-header-color);\n }\n\n /*\n * 거터 칸(순번 · 선택 · 더러움 표식)은 몸과 **같은 자리**에 있어야 한다. 머리의 체크박스와 각 줄의\n * 체크박스가 한 줄로 서지 않으면 표가 어긋나 보인다.\n *\n * 전에는 두 가지가 어긋나 있었다.\n * · text-align: center 로 가운데를 맞추려 했지만 이 칸은 display: flex 다 —\n * flex 안에서 text-align 은 항목을 옮기지 못한다. 그래서 왼쪽에 붙었다\n * · 여백을 몸(--grid-gutter-padding)과 **다른 토큰**(--spacing-small)에서 읽었다\n *\n * 그래서 정렬은 flex 로 하고, 여백은 몸과 같은 토큰을 본다.\n */\n div[gutter] {\n padding: var(--grid-gutter-padding);\n /*\n * 기본은 가운데. 거터마다 자기 정렬이 있으면 renderHeaderColumn 이 인라인으로 덮는다 —\n * 순번은 오른쪽이다(몸의 숫자가 오른쪽이므로 머리의 # 도 오른쪽이어야 자릿수가 맞아 보인다).\n */\n justify-content: center;\n }\n\n /*\n * 거터 칸의 내용물은 span[for-title] 안에 들어간다 — 열 제목이 쓰는 그 span 이다. 그래서 제목용\n * 규칙 둘을 함께 물려받는데, 거터에는 제목도 정렬 표식도 없으므로 둘 다 체크박스를 밀기만 한다.\n *\n * flex: 1 칸을 다 채워서, 칸의 justify-content 가 나눌 여백이 남지 않는다\n * margin-right 제목과 표식 사이를 벌리려던 값이라, 내용물이 그만큼 왼쪽으로 간다\n *\n * 둘을 거두면 span 이 내용물 크기로 줄고, 칸이 그것을 가운데로 놓는다. 입력의 기본 여백도 없애야\n * 몸의 체크박스와 정확히 같은 자리에 선다 — 몸은 여백 없이 가운데에 있다.\n */\n div[gutter] span[for-title] {\n flex: none;\n margin-right: 0;\n }\n\n div[gutter] input {\n margin: 0;\n }\n\n span {\n display: block;\n white-space: nowrap;\n overflow: hidden;\n }\n\n span[for-title] {\n /*\n * 이름이 자기 길이만큼만 차지한다 — 그러면 정렬 표식이 이름 바로 오른쪽에 붙는다.\n *\n * 고치는 표에서는 1 로 되돌린다(data-grid.ts 의 editable-grid 와 같은 값). 거기서는 칸 끝에 폭 조절\n * 손잡이가 서 있어서, 표식이 그 옆에 모여 있는 편이 낫다.\n *\n * **조건은 손잡이가 보이는지다.** 표식이 칸 오른쪽 끝에 있는데 그 오른쪽에 선이 없으면 눈이\n * 다음 칸의 것으로 읽는다. 손잡이가 있으면 그 선이 「여기까지가 이 칸」이라고 말해 주므로 끝에\n * 있어도 자기 칸의 것으로 읽힌다.\n *\n * 그래서 손잡이 토큰에서 직접 파생시킨다. 전에는 편집 여부에 걸고 두 토큰을 한 자리에서 함께\n * 정했는데, 그러면 테마가 한쪽만 건드릴 때 어긋난다.\n *\n * 기본은 **붙는 쪽**이다. 스타일 질의를 모르는 브라우저에서는 이 값이 남는데, 읽기 전용 표가\n * 다수라 그쪽이 옳은 기본이다(고치는 표에서는 표식이 이름 옆에 붙을 뿐이고 그건 흠이 아니다).\n *\n * 줄어듦은 항상 1 이다. 긴 이름이 줄어들 수 있어야 말줄임으로 잘린다 — 줄어들지 못하면 칸을\n * 넘어가 그냥 잘린다. 축약형(flex)에 var 을 쓰면 「0 1 auto」 가 「none」 으로 해석되는 일이\n * 있어서(실측 0 0 auto) 낱개 속성으로 적는다.\n */\n flex-grow: 0;\n flex-shrink: 1;\n flex-basis: auto;\n /* 표식 무리와 이름 사이를 벌린다 — 붙어 있으면 이름의 일부처럼 읽힌다. */\n margin-right: 6px;\n /* 작은 대문자 라벨로 쓸 때 자간이 필요하다. 테마가 정하지 않으면 0 이다. */\n letter-spacing: var(--grid-header-letter-spacing, normal);\n text-overflow: ellipsis;\n line-height: 1.6;\n text-transform: var(--grid-header-text-transform, capitalize);\n align-self: center;\n }\n\n /*\n * 손잡이가 보이면 이름이 칸을 채워 표식을 오른쪽 끝으로 민다 — 거기에는 손잡이가 서 있으므로\n * 표식이 그 옆에 모인다.\n *\n * none 이 아닌 값을 묻는다. 이 저장소에서 「보임」은 flex 뿐이지만, 테마가 inline-flex 나\n * block 을 쓸 수도 있다. 감춤은 none 하나뿐이라 그쪽을 부정하는 편이 좁다.\n */\n @container not style(--grid-header-splitter-display: none) {\n span[for-title] {\n flex-grow: 1;\n }\n }\n\n span[for-title] * {\n vertical-align: middle;\n }\n\n span[for-title] md-icon {\n font-size: 1.2em;\n }\n\n span[sorter],\n span[filter] {\n display: flex;\n align-self: center;\n\n padding: 0;\n border: 0;\n }\n\n span[sorter] md-icon {\n font-size: var(--grid-header-sorter-size);\n }\n\n /*\n * ── 머리에는 「고칠 수 있다」 표식을 두지 않는다 (2026-09-05) ────────\n * 칸마다 표식이 생긴 뒤로 머리의 연필은 같은 말을 두 번 하는 자리가 됐다. 게다가 머리의\n * 것은 **틀린 말을 할 수 있다** — editable 이 함수인 열에서 머리는 참·거짓을 가리지 못해\n * 늘 「고칠 수 있다」고 하고, 실제로는 한 줄도 못 고치는 표가 나온다. 칸의 표식은 그 함수를\n * 줄마다 불러 보고 정한다.\n *\n * 머리는 이름·정렬·거르기의 자리로 두고, 고치기는 고치는 자리에서 알린다.\n *\n * ── 정렬 표식 ──────────────────────────────────────────────────────\n * 정렬할 수 있다는 것은 아주 흐리게, 지금 정렬 중인 것만 한 단계 진하게 둔다.\n *\n * 색은 토큰으로 받되 currentColor 를 섞은 폴백을 둔다 — 테마가 값을 정하지 않아도 흐려지고\n * 라이트·다크 어느 쪽에서도 배경 대비가 유지된다.\n */\n md-icon[sortable-mark] {\n color: var(--grid-header-sortable-color, color-mix(in srgb, currentColor 18%, transparent));\n }\n\n /*\n * 지금 정렬 중이라는 표시는 **상태**다 — 흐리게 두면 무엇으로 정렬됐는지 화면이 말하지 않는\n * 것과 같다. 52% 로는 어두운 화면에서 2.86:1 이었다(실측 2026-09-05). 60% 면 밝은 화면\n * 4.7 · 어두운 화면 5.4 로 UI 요소 기준(3:1)을 넘는다.\n *\n * 「정렬할 수 있다」(sortable-mark)는 그 옆에서 계속 흐리게 둔다. 그것은 상태가 아니라\n * 곁들이는 안내이고, 머리글 자체가 눌리는 자리라 길은 따로 있다.\n */\n span[sorter] md-icon:not([sortable-mark]),\n span[sorter] sub {\n color: var(--grid-header-sorted-color, color-mix(in srgb, currentColor 60%, transparent));\n }\n\n span[filter] > md-icon {\n font-size: var(--fontsize-default);\n line-height: 20px;\n }\n\n /*\n * 열 폭 조절 손잡이 — **세로 선을 그리는 것이 이것이다.**\n *\n * 표 안의 세로 선은 이 손잡이의 오른쪽 테두리다(칸 자체는 위아래 테두리만 갖는다). 그래서 이\n * 손잡이를 감추면 열 폭 조절과 세로 격자가 함께 사라진다 — 그 둘은 원래 한 물건이다.\n *\n * 고치지 않는 목록에서는 열 폭을 끌어 옮길 일이 없고, 세로 선이 없으면 표가 격자가 아니라\n * 줄로 읽힌다. 그럴 때 테마가 이렇게 정한다.\n *\n * --grid-header-splitter-display: none\n *\n * 값을 정하지 않으면 예전 그대로다 — 편집용 표는 손잡이가 있어야 한다.\n */\n span[splitter] {\n display: var(--grid-header-splitter-display, flex);\n cursor: col-resize;\n border-right: var(--grid-header-splitter-border);\n margin-right: 0;\n }\n\n /*\n * 손잡이가 있는 칸은 오른쪽 여백을 두지 않는다.\n *\n * 손잡이는 flex 항목이라 칸의 padding 안쪽에 놓인다. 좌우 여백이 2px 이던 동안에는 그 차이가\n * 안 보였지만, 여백을 10px 로 올리자 손잡이가 열 경계에서 10px 당겨졌다 — 세로 선이 경계가\n * 아닌 자리에 그려진 것이다.\n *\n * 그래서 손잡이가 있을 때만 오른쪽 여백을 거둔다. 손잡이가 없는 칸(거터 · 폭을 못 바꾸는 열)은\n * 여백을 그대로 둬야 글자가 경계에 닿지 않는다.\n *\n * 세로 길이는 손대지 않는다 — flex 가 늘려 주는 그대로, 칸의 위아래 여백만큼 들어간 짧은 선이다.\n */\n div[column]:has(span[splitter]) {\n padding-right: 0;\n }\n\n span[splitter]:hover {\n border-right: var(--grid-header-splitter-border-hover);\n }\n\n [filter-title] {\n color: var(--grid-header-filter-title-color);\n font: var(--grid-header-filter-title-font);\n text-transform: capitalize;\n }\n\n [filter-title] * {\n vertical-align: middle;\n }\n\n [filter-title] md-icon {\n opacity: 0.7;\n color: var(--grid-header-filter-title-icon-color);\n }\n\n [filter] input[type='checkbox'] {\n margin-left: var(--spacing-medium);\n margin-bottom: var(--spacing-small);\n }\n\n [fixed] {\n position: sticky;\n z-index: 2;\n }\n\n .span-both {\n grid-row: 1 / span 2; /* 1단과 2단에 걸쳐 표시 */\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 .group-header {\n grid-row: 1; /* 1행에 배치 */\n grid-column: var(--group-start) / span var(--group-size); /* 2열부터 시작하여 2열에 걸쳐 표시 */\n }\n\n @media print {\n :host {\n grid-template-columns: var(--grid-template-print-columns);\n }\n }\n\n @media (max-width: 768px) {\n /* 모바일에서는 그리드에서 고정된 열 해제 */\n [fixed] {\n position: static;\n z-index: 0;\n box-shadow: none !important;\n }\n }\n `\n ]\n\n @property({ type: Array }) columns: ColumnConfig[] = ZERO_COLUMNS\n @property({ type: Object }) data: GristData = ZERO_DATA\n @property({ type: Array }) sorters: SortersConfig = []\n @property({ type: Array }) filters: FilterValue[] = []\n @property({ type: Boolean, attribute: 'filtering-feature' }) filteringFeature: boolean = false\n\n @state() private row1: {\n index: number\n /** Position among visible columns, from 1 — this is what aria-colindex carries. */\n colIndex?: number\n column: ColumnConfig\n clazz?: string\n start?: number\n size?: number\n align?: string\n group?: string\n }[] = []\n\n @state() private row2: {\n index: number\n /** Position among visible columns, from 1 — this is what aria-colindex carries. */\n colIndex?: number\n column: ColumnConfig\n }[] = []\n\n private _lastAccVal?: number\n private _throttledNotifier?: any\n\n private tooltipController?: TooltipReactiveController = new TooltipReactiveController(this)\n\n connectedCallback() {\n super.connectedCallback()\n\n const grid = closestElement('ox-grist', this)\n\n this.addEventListener('scroll', function () {\n this.scrollLeft == 0 ? this.removeAttribute('raised') : this.setAttribute('raised', '')\n })\n\n if (this.filteringFeature) {\n this?.addEventListener('filter-change', (e: Event) => {\n const { name, operator, value } = (e as CustomEvent).detail\n const filters = this.filters instanceof Array ? [...this.filters] : []\n\n if (value == null) {\n const index = filters.findIndex(filter => filter.name === name)\n if (index === -1) {\n return\n }\n\n filters.splice(index, 1)\n } else {\n const index = filters.findIndex(filter => filter.name === name)\n if (index === -1) {\n filters.push({ name, operator, value })\n } else {\n filters.splice(index, 1, { name, operator, value })\n }\n }\n\n grid?.dispatchEvent(\n new CustomEvent('fetch-params-change', {\n detail: {\n filters,\n from: 'data-grid-header'\n }\n })\n )\n })\n }\n }\n\n /*\n * Say that the header is a row.\n *\n * The header is a CSS grid, so its cells sat flat: one row on screen (two when grouped), but no\n * row in the DOM. Equal height reads as a row to the eye, and that is all it was — a picture.\n *\n * The wrapper exists to carry role=row. display: contents generates no box, so the cells stay\n * items of the outer grid and nothing about column widths, fixed columns or group-header\n * grid-column placement changes.\n */\n render() {\n const grouped = this.row2.length > 0\n const clazz = grouped ? 'span-both' : undefined\n\n return html`\n <div grid-row role=\"row\" aria-rowindex=\"1\">\n ${this.row1.map(({ column, clazz, start, size, align, index, group, colIndex }) =>\n this.renderHeaderColumn({ column, clazz, start, size, align, index, group, colIndex, grouped })\n )}\n\n <!--\n Width filler. Nothing to read, so it is not counted as a cell — counting it would\n announce one column more than the grid has.\n -->\n <div column role=\"presentation\" class=${ifDefined(clazz)}></div>\n </div>\n\n ${grouped\n ? html`\n <div grid-row role=\"row\" aria-rowindex=\"2\">\n ${this.row2.map(({ column, index, colIndex }) =>\n this.renderHeaderColumn({ column, index, colIndex, grouped })\n )}\n </div>\n `\n : nothing}\n `\n }\n\n renderHeaderColumn({ column, clazz, start, size, align, index, group, colIndex, grouped }: any): TemplateResult {\n if (column.hidden) {\n return html`${nothing}`\n }\n\n /*\n * 거터 머리는 flex 로 정렬한다.\n *\n * 아래 span 의 `text-align` 은 거터에서 듣지 않는다 — 그 span 이 내용물 크기로 줄어 있어서\n * (위 div[gutter] 머리말 참조) 글자를 밀 여백이 span 안에 없다. 그래서 칸이 밀어야 한다.\n *\n * 값은 그 거터가 이미 선언한 것을 본다. 순번은 right, 선택과 더러움 표식은 center 다. 여기에 따로\n * 적으면 거터를 하나 더할 때 두 곳을 맞춰야 한다.\n */\n /*\n * 정렬은 **칸이 flex 로 민다.** 아래 span 의 text-align 에 기대지 않는다.\n *\n * 그 span 은 이름 길이만큼만 차지하므로(위 span[for-title] 머리말) 안에 글자를 밀 여백이 없다.\n * 그래서 text-align 이 아무 일도 하지 않는다 — 숫자 칸의 값은 오른쪽인데 머리글만 왼쪽에\n * 남았다. [확인함] 「수량」 머리 x=391 · 값 오른쪽 끝 x=402. 2026-09-02\n *\n * 칸이 밀면 이름과 표식이 **함께** 그 방향으로 간다. 그래서 오른쪽 정렬 칸에서도 표식이 이름\n * 옆에 붙어 있다.\n *\n * 거터의 기본은 가운데(체크박스 · 더러움 표식), 보통 칸의 기본은 왼쪽이다.\n */\n const fallback = column.type == 'gutter' ? 'center' : 'flex-start'\n const justify = `justify-content:${ALIGN_JUSTIFY[(align || column.record?.align) as keyof typeof ALIGN_JUSTIFY] || fallback};`\n\n return html`\n <div\n ?gutter=${column.type == 'gutter'}\n ?fixed=${column.fixed}\n column\n role=\"columnheader\"\n aria-colindex=${ifDefined(group ? start : colIndex)}\n aria-colspan=${ifDefined(group ? size : undefined)}\n aria-rowspan=${ifDefined(clazz === 'span-both' ? 2 : undefined)}\n aria-sort=${ifDefined(this._ariaSort(column, group))}\n class=${ifDefined(clazz)}\n style=${group\n ? `--group-start:${start};--group-size:${size};${justify}${column.header?.style || ''}`\n : `${justify}${column.header?.style || ''}`}\n >\n <span\n for-title\n data-reactive-tooltip\n style=\"text-align:${align || column.record.align || 'left'};\"\n @click=${(e: MouseEvent) => this._changeSort(column)}\n >${this._renderHeader(column)}\n </span>\n\n ${!group && column.sortable\n ? html`\n <span sorter @click=${(e: MouseEvent) => this._changeSort(column)}>\n ${this._renderSortHeader(column)}\n </span>\n `\n : nothing}\n ${!group &&\n this.filteringFeature &&\n column.filter &&\n (column.filter as FilterConfigObject).operator !== 'search'\n ? html` <span filter> ${this._renderFilterHeader(column)} </span> `\n : nothing}\n ${column.resizable !== false\n ? html`\n <span splitter draggable=\"false\" @pointerdown=${(e: PointerEvent) => this._pointerdown(e, index)}\n >&nbsp;</span\n >\n `\n : nothing}\n </div>\n `\n }\n\n notifyFixedLeftChange() {\n const fixedHeaders = Array.from(this.renderRoot.querySelectorAll('div[fixed]')) as HTMLElement[]\n const fixedLefts = [] as number[]\n var left = 0\n fixedHeaders.forEach((header: HTMLElement) => {\n header.style.left = left + 'px'\n fixedLefts.push(left)\n\n const width = header.offsetWidth\n left += width\n })\n\n this.dispatchEvent(\n new CustomEvent('fixed-lefts-change', {\n detail: fixedLefts\n })\n )\n }\n\n updated(changes: PropertyValues) {\n var isColumnWidthChangePossible = false\n\n if (changes.has('columns')) {\n /*\n * Visible column numbers, from 1 — aria-colindex does not count hidden columns.\n *\n * The `index` in the reduces below is the position within this.columns, hidden ones included.\n * Passing that through means a grid with one column hidden announces \"column 3\" for what is\n * actually the second column.\n */\n const colIndexOf = new Map<number, number>()\n this.columns.forEach((column, index) => {\n if (!column.hidden) {\n colIndexOf.set(index, colIndexOf.size + 1)\n }\n })\n\n this.row2 = this.columns.reduce((row2, column, index) => {\n if (column.hidden || !column.header?.group) {\n return row2\n }\n return row2.concat({\n index,\n colIndex: colIndexOf.get(index),\n column\n } as any)\n }, [] as any[])\n\n const clazz = this.row2.length > 0 ? 'span-both' : undefined\n\n var columnNo = 0\n\n this.row1 = this.columns.reduce((row1, column, index) => {\n if (column.hidden) {\n return row1\n }\n\n columnNo++\n if (!column.header?.group) {\n return row1.concat({\n index,\n colIndex: colIndexOf.get(index),\n column,\n clazz\n } as any)\n }\n const { group, groupStyle } = column.header\n const last = row1[row1.length - 1] as any\n\n if (!last || group !== last.group) {\n return row1.concat({\n index,\n column: {\n ...column,\n header: {\n renderer: () => group,\n style: groupStyle\n }\n },\n group,\n align: 'center',\n clazz: 'group-header',\n start: columnNo,\n size: 1\n } as any)\n }\n\n last.size++\n\n return row1\n }, [] as any[])\n\n isColumnWidthChangePossible = true\n }\n\n if (changes.has('data')) {\n isColumnWidthChangePossible = true\n }\n\n if (isColumnWidthChangePossible) {\n // requestAnimationFrame(() => this.notifyFixedLeftChange())\n this.notifyFixedLeftChange()\n }\n }\n\n _renderHeader(column: ColumnConfig) {\n var { renderer } = column.header || {}\n var title = renderer.call(this, column)\n\n return html`${column?.record?.mandatory ? '*' : ''} ${title} `\n }\n\n /**\n * How this column is sorted right now — the arrow said in text as well.\n *\n * keyboard_arrow_up/down is a picture and reaches the eye only. With aria-sort a screen reader\n * appends \"ascending\" to the column name, and a change in sort order is announced as a change.\n *\n * Columns that cannot be sorted get nothing: `none` means \"sortable, not currently sorted\", so\n * putting it on a non-sortable column announces a control that is not there. Same for group\n * headers, which are not clickable.\n */\n private _ariaSort(column: ColumnConfig, group?: string): 'ascending' | 'descending' | 'none' | undefined {\n if (group || !column.sortable) {\n return undefined\n }\n\n const sorter = (this.sorters || []).find(sorter => column.type !== 'gutter' && column.name == sorter.name)\n\n if (!sorter) {\n return 'none'\n }\n\n return sorter.desc ? 'descending' : 'ascending'\n }\n\n _renderSortHeader(column: ColumnConfig) {\n var sorters = this.sorters || []\n\n var sorter = sorters.find(sorter => column.type !== 'gutter' && column.name == sorter.name)\n if (!sorter) {\n return html`<md-icon sortable-mark>unfold_more</md-icon>`\n }\n\n if (sorters.length > 1) {\n var rank = sorters.indexOf(sorter) + 1\n return sorter.desc\n ? html` <md-icon>keyboard_arrow_down</md-icon><sub>${rank}</sub> `\n : html` <md-icon>keyboard_arrow_up</md-icon><sub>${rank}</sub> `\n } else {\n return sorter.desc ? html` <md-icon>keyboard_arrow_down</md-icon> ` : html` <md-icon>keyboard_arrow_up</md-icon> `\n }\n }\n\n _renderFilterHeader(column: ColumnConfig) {\n const name = column.name\n const filter = column.filter as FilterConfigObject\n const type = filter.type\n const value = this.filters.find(filter => filter.name === name)?.value\n const idx = filter!.operator === 'between' ? 1 : 0\n const renderer = getFilterRenderer(type)[idx]\n\n return html`\n <md-icon\n @click=${(e: Event) => {\n const parent = (e.target as HTMLElement).closest('[column]') as HTMLElement\n const popup = parent.querySelector('ox-popup, ox-popup-list') as OxPopup | null\n // const popup = (e.target as HTMLElement).nextSibling as OxPopupList | null\n\n // absolute position인 popup의 위치 부모는 grist 이므로,\n // data-grid-header 의 포지션 부모(grist)의 위치로부터 계산해야함.\n // this의 position을 relative로 하지 못하는 이유 : ox-popup-list가 grid body에 덮히기 때문.\n // const top = parent.offsetTop + parent.offsetHeight\n // const right = this.clientWidth - (parent.offsetLeft + parent.offsetWidth - this.scrollLeft)\n\n popup?.open({\n right: 0,\n top: parent.offsetHeight,\n fixed: true\n })\n }}\n >filter_alt</md-icon\n >\n\n ${!renderer\n ? html``\n : type !== 'select'\n ? html` <ox-popup\n ><div filter-title><md-icon>filter_alt</md-icon> filter by <strong>${column.name}</strong></div>\n ${renderer(column, value, this)}</ox-popup\n >`\n : filter!.operator === 'in'\n ? html`<ox-popup-list\n multiple\n attr-selected=\"checked\"\n .value=${value}\n with-search\n @select=${(e: CustomEvent) =>\n e.target?.dispatchEvent(\n new CustomEvent('filter-change', {\n bubbles: true,\n composed: true,\n detail: {\n name,\n operator: filter!.operator,\n value: !e.detail\n ? undefined\n : e.detail instanceof Array && e.detail.length === 0\n ? undefined\n : e.detail\n }\n })\n )}\n ><div filter-title slot=\"header\">\n <md-icon>filter_alt</md-icon> filter by <strong>${column.name}</strong>\n </div>\n ${renderer(column, value, this)}</ox-popup-list\n >`\n : html`<ox-popup-list\n .value=${value}\n with-search\n @select=${(e: CustomEvent) =>\n e.target?.dispatchEvent(\n new CustomEvent('filter-change', {\n bubbles: true,\n composed: true,\n detail: {\n name,\n operator: filter!.operator,\n value: e.detail ? e.detail : undefined\n }\n })\n )}\n ><div filter-title slot=\"header\">\n <md-icon>filter_alt</md-icon> filter by <strong>${column.name}</strong>\n </div>\n ${renderer(column, value, this)}</ox-popup-list\n >`}\n `\n }\n\n _changeSort(column: ColumnConfig) {\n if (!column.sortable) {\n return\n }\n\n var sorters = [...this.sorters]\n\n var idx = sorters.findIndex(sorter => sorter.name == column.name)\n if (idx !== -1) {\n let sorter = sorters[idx]\n if (sorter.desc) {\n sorters.splice(idx, 1)\n } else {\n sorters.splice(idx, 1, {\n ...sorter,\n desc: true\n })\n }\n } else {\n var sorter = {\n name: column.name,\n desc: false\n }\n\n sorters.push(sorter)\n }\n\n this.sorters = sorters\n\n this.dispatchEvent(\n new CustomEvent('fetch-params-change', {\n bubbles: true,\n composed: true,\n detail: {\n sorters: this.sorters,\n from: 'data-grid-header'\n }\n })\n )\n }\n\n _accumalate(x: number) {\n this._lastAccVal = (this._lastAccVal ?? 0) + x\n return this._lastAccVal\n }\n\n _notifyWidthChange(idx: number, width: number) {\n if (!this._throttledNotifier) {\n this._throttledNotifier = throttle((idx: number, width: number) => {\n this.dispatchEvent(\n new CustomEvent('column-width-change', {\n bubbles: true,\n composed: true,\n detail: {\n idx,\n width\n }\n })\n )\n\n this.notifyFixedLeftChange()\n\n this._lastAccVal = 0\n }, 100)\n }\n\n this._throttledNotifier(idx, width)\n }\n\n _pointerdown(e: PointerEvent, idx: number) {\n e.stopPropagation()\n e.preventDefault()\n ;(e.target as HTMLElement).setPointerCapture(e.pointerId)\n\n var pointermoveHandler = ((e: PointerEvent) => {\n e.stopPropagation()\n e.preventDefault()\n let column = this.columns[idx]\n\n let width = Math.max(0, Number(column.width || 100) + this._accumalate(e.movementX))\n if (width == 0) {\n /* CLARIFY-ME 왜 마지막 이벤트의 offsetX로 음수 값이 오는가 */\n return\n }\n\n this._notifyWidthChange(idx, width)\n }).bind(this)\n\n var pointerupHandler = ((e: PointerEvent) => {\n ;(e.target as HTMLElement).releasePointerCapture(e.pointerId)\n\n document.removeEventListener('pointermove', pointermoveHandler)\n document.removeEventListener('pointerup', pointerupHandler)\n\n pointermoveHandler(e)\n }).bind(this)\n\n document.addEventListener('pointermove', pointermoveHandler)\n document.addEventListener('pointerup', pointerupHandler)\n }\n}\n"]}
@@ -47,11 +47,11 @@ export declare class DataGrid extends DataManipulator {
47
47
  updated(changes: PropertyValues<this>): void;
48
48
  calculateWidths(columns: ColumnConfig[]): void;
49
49
  /**
50
- * 이 표의 이름 — `<ox-grid aria-label="입고 대기 목록">` 처럼 쓰는 쪽이 정한다.
50
+ * The grid's name, set by the caller as `<ox-grid aria-label="Inbound queue">`.
51
51
  *
52
- * role=grid 는 안쪽 감싸개에 걸려 있어서 호스트에 적은 aria-label 이 거기까지 닿지 않는다.
53
- * 그래서 값을 받아 넘긴다. 이름을 여기서 지어내지는 않는다 — 한 화면에 표가 여럿일 때
54
- * 무엇을 보는 표인지는 화면이 아는 것이고, 부품이 지어낼 수 있는 것이 아니다.
52
+ * role=grid sits on the inner wrapper, and an aria-label on the host does not reach it, so the
53
+ * value is taken and forwarded. No name is invented here: with several grids on one screen, which
54
+ * one this is belongs to the screen, not to the component.
55
55
  */
56
56
  gridLabel?: string;
57
57
  render(): import("lit-html").TemplateResult<1>;