@operato/data-grist 10.6.0 → 10.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -513,13 +513,21 @@ DataGridHeader.styles = [
513
513
  * 고치는 표에서는 1 로 되돌린다(data-grid.ts 의 editable-grid 한 벌). 거기서는 칸 끝에 폭 조절
514
514
  * 손잡이가 서 있어서, 표식이 그 옆에 모여 있는 편이 낫다.
515
515
  *
516
- * 늘어남만 토큰으로 받고 **줄어듦은 항상 1 이다.** 이름이 줄어들 있어야 말줄임으로
517
- * 잘린다 줄어들지 못하면 칸을 넘어가 그냥 잘린다.
516
+ * **조건은 손잡이가 보이는지다.** 표식이 오른쪽 끝에 있는데 오른쪽에 선이 없으면 눈이
517
+ * 다음 칸의 것으로 읽는다. 손잡이가 있으면 선이 「여기까지가 이 칸」이라고 말해 주므로 끝에
518
+ * 있어도 자기 칸의 것으로 읽힌다.
518
519
  *
519
- * 축약형(flex)에 var 쓰면 「0 1 auto」 「none」 으로 해석되는 일이 있었다(실측 0 0 auto).
520
- * 낱개 속성으로 적으면 함정이 없다.
520
+ * 그래서 손잡이 토큰에서 직접 파생시킨다. 전에는 편집 여부에 걸고 토큰을 자리에서 함께
521
+ * 정했는데, 그러면 테마가 한쪽만 건드릴 때 어긋난다.
522
+ *
523
+ * 기본은 **붙는 쪽**이다. 스타일 질의를 모르는 브라우저에서는 이 값이 남는데, 읽기 전용 표가
524
+ * 다수라 그쪽이 옳은 기본이다(고치는 표에서는 표식이 이름 옆에 붙을 뿐이고 그건 흠이 아니다).
525
+ *
526
+ * 줄어듦은 항상 1 이다. 긴 이름이 줄어들 수 있어야 말줄임으로 잘린다 — 줄어들지 못하면 칸을
527
+ * 넘어가 그냥 잘린다. 축약형(flex)에 var 을 쓰면 「0 1 auto」 가 「none」 으로 해석되는 일이
528
+ * 있어서(실측 0 0 auto) 낱개 속성으로 적는다.
521
529
  */
522
- flex-grow: var(--grid-header-title-grow, 0);
530
+ flex-grow: 0;
523
531
  flex-shrink: 1;
524
532
  flex-basis: auto;
525
533
  /* 표식 무리와 이름 사이를 벌린다 — 붙어 있으면 이름의 일부처럼 읽힌다. */
@@ -532,6 +540,19 @@ DataGridHeader.styles = [
532
540
  align-self: center;
533
541
  }
534
542
 
543
+ /*
544
+ * 손잡이가 보이면 이름이 칸을 채워 표식을 오른쪽 끝으로 민다 — 거기에는 손잡이가 서 있으므로
545
+ * 표식이 그 옆에 모인다.
546
+ *
547
+ * none 이 아닌 값을 묻는다. 이 저장소에서 「보임」은 flex 뿐이지만, 테마가 inline-flex 나
548
+ * block 을 쓸 수도 있다. 감춤은 none 하나뿐이라 그쪽을 부정하는 편이 좁다.
549
+ */
550
+ @container not style(--grid-header-splitter-display: none) {
551
+ span[for-title] {
552
+ flex-grow: 1;
553
+ }
554
+ }
555
+
535
556
  span[for-title] * {
536
557
  vertical-align: middle;
537
558
  }
@@ -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 * 늘어남만 토큰으로 받고 **줄어듦은 항상 1 이다.** 긴 이름이 줄어들 수 있어야 말줄임으로\n * 잘린다 — 줄어들지 못하면 칸을 넘어가 그냥 잘린다.\n *\n * 축약형(flex)에 var 을 쓰면 「0 1 auto」 가 「none」 으로 해석되는 일이 있었다(실측 0 0 auto).\n * 낱개 속성으로 적으면 그 함정이 없다.\n */\n flex-grow: var(--grid-header-title-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 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 * 머리의 표식은 **알림이지 버튼이 아니다.** 머리에서 읽어야 할 것은 열 이름이다.\n *\n * ── 연필이 지저분해 보이던 이유 셋 ──────────────────────────────────\n * 크기가 글자만 했고(1.2em), 획이 본문과 같은 굵기였고, 열 이름 바로 옆에 붙어 있었다.\n * 편집용 표에서는 거의 모든 열이 고칠 수 있어서 그 셋이 열 수만큼 반복됐다.\n *\n * 셋을 각각 낮춘다.\n *\n * 크기 14px — 정렬 표식과 같게 맞춘다. 전에는 연필 12px, 화살표 18px 로 따로 놀았다\n * 획 가변 글꼴의 굵기 축을 200 으로. 채운 글리프가 아니라 가는 선이 된다\n * 자리 정렬 표식과 한 무리로 오른쪽에 모은다. 이름과 표식 사이가 갈린다\n *\n * 글리프는 연필(edit)이다. text_fields · edit_square 와 나란히 놓고 견주었고 사용자가 골랐다 —\n * 「고칠 수 있다」는 뜻이 가장 바로 오는 것이 연필이다.\n *\n * 연필이 지저분해 보였던 것은 글리프 탓이 아니라 크기(15px)와 획 굵기 탓이었다. 14px 에\n * 굵기 200 으로 두면 가는 선이 되어 이름을 방해하지 않는다.\n *\n * ── 정렬 표식 ──────────────────────────────────────────────────────\n * 정렬할 수 있다는 것은 아주 흐리게, 지금 정렬 중인 것만 한 단계 진하게 둔다.\n *\n * 색은 토큰으로 받되 currentColor 를 섞은 폴백을 둔다 — 테마가 값을 정하지 않아도 흐려지고\n * 라이트·다크 어느 쪽에서도 배경 대비가 유지된다.\n */\n md-icon[editable-mark] {\n align-self: center;\n font-size: var(--grid-header-mark-size, 14px);\n /* 가변 글꼴의 굵기·명암 축. 정적 글꼴이면 조용히 무시된다. */\n font-variation-settings: 'wght' 200, 'GRAD' -25, 'opsz' 20;\n color: var(--grid-header-editable-color, color-mix(in srgb, currentColor 34%, transparent));\n }\n\n md-icon[sortable-mark] {\n color: var(--grid-header-sortable-color, color-mix(in srgb, currentColor 18%, transparent));\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 52%, 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 .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 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 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 render() {\n const clazz = this.row2.length > 0 ? 'span-both' : undefined\n\n return html`\n ${this.row1.map(({ column, clazz, start, size, align, index, group }) =>\n this.renderHeaderColumn({ column, clazz, start, size, align, index, group })\n )}\n\n <div column class=${ifDefined(clazz)}></div>\n\n ${this.row2.map(({ column, index }) => this.renderHeaderColumn({ column, index }))}\n `\n }\n\n renderHeaderColumn({ column, clazz, start, size, align, index, group }: 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 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 ${column.record?.editable ? html`<md-icon editable-mark title=${i18next.t('text.grid-column-editable', { defaultValue: 'editable' })}>edit</md-icon>` : nothing}\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 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 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 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 _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 * 머리의 표식은 **알림이지 버튼이 아니다.** 머리에서 읽어야 할 것은 열 이름이다.\n *\n * ── 연필이 지저분해 보이던 이유 셋 ──────────────────────────────────\n * 크기가 글자만 했고(1.2em), 획이 본문과 같은 굵기였고, 열 이름 바로 옆에 붙어 있었다.\n * 편집용 표에서는 거의 모든 열이 고칠 수 있어서 그 셋이 열 수만큼 반복됐다.\n *\n * 셋을 각각 낮춘다.\n *\n * 크기 14px — 정렬 표식과 같게 맞춘다. 전에는 연필 12px, 화살표 18px 로 따로 놀았다\n * 획 가변 글꼴의 굵기 축을 200 으로. 채운 글리프가 아니라 가는 선이 된다\n * 자리 정렬 표식과 한 무리로 오른쪽에 모은다. 이름과 표식 사이가 갈린다\n *\n * 글리프는 연필(edit)이다. text_fields · edit_square 와 나란히 놓고 견주었고 사용자가 골랐다 —\n * 「고칠 수 있다」는 뜻이 가장 바로 오는 것이 연필이다.\n *\n * 연필이 지저분해 보였던 것은 글리프 탓이 아니라 크기(15px)와 획 굵기 탓이었다. 14px 에\n * 굵기 200 으로 두면 가는 선이 되어 이름을 방해하지 않는다.\n *\n * ── 정렬 표식 ──────────────────────────────────────────────────────\n * 정렬할 수 있다는 것은 아주 흐리게, 지금 정렬 중인 것만 한 단계 진하게 둔다.\n *\n * 색은 토큰으로 받되 currentColor 를 섞은 폴백을 둔다 — 테마가 값을 정하지 않아도 흐려지고\n * 라이트·다크 어느 쪽에서도 배경 대비가 유지된다.\n */\n md-icon[editable-mark] {\n align-self: center;\n font-size: var(--grid-header-mark-size, 14px);\n /* 가변 글꼴의 굵기·명암 축. 정적 글꼴이면 조용히 무시된다. */\n font-variation-settings: 'wght' 200, 'GRAD' -25, 'opsz' 20;\n color: var(--grid-header-editable-color, color-mix(in srgb, currentColor 34%, transparent));\n }\n\n md-icon[sortable-mark] {\n color: var(--grid-header-sortable-color, color-mix(in srgb, currentColor 18%, transparent));\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 52%, 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 .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 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 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 render() {\n const clazz = this.row2.length > 0 ? 'span-both' : undefined\n\n return html`\n ${this.row1.map(({ column, clazz, start, size, align, index, group }) =>\n this.renderHeaderColumn({ column, clazz, start, size, align, index, group })\n )}\n\n <div column class=${ifDefined(clazz)}></div>\n\n ${this.row2.map(({ column, index }) => this.renderHeaderColumn({ column, index }))}\n `\n }\n\n renderHeaderColumn({ column, clazz, start, size, align, index, group }: 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 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 ${column.record?.editable ? html`<md-icon editable-mark title=${i18next.t('text.grid-column-editable', { defaultValue: 'editable' })}>edit</md-icon>` : nothing}\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 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 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 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 _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"]}
@@ -260,15 +260,16 @@ DataGrid.styles = [
260
260
  */
261
261
  :host([editable-grid]) {
262
262
  --grid-record-focused-cell-border: 1px dashed var(--ui-faint, #8a959c);
263
+ /*
264
+ * 정렬 표식의 자리는 이 값에서 **파생된다** — 손잡이가 보이면 표식이 칸 오른쪽 끝으로 가고,
265
+ * 안 보이면 이름에 붙는다(data-grid-header.ts 의 스타일 질의). 여기서 따로 정하지 않는다.
266
+ */
263
267
  --grid-header-splitter-display: flex;
264
268
  /*
265
- * 이름이 칸을 차지하게 두어 정렬 표식을 오른쪽 끝으로 민다. 거기에는 폭 조절 손잡이가
266
- * 있으므로 표식이 옆에 모인다.
267
- *
268
- * 읽기 전용 표에는 손잡이가 없어서, 표식이 칸 끝에 홀로 떠 이름과 멀어진다. 그래서 기본은
269
- * 이름에 붙는 쪽이다(data-grid-header.ts).
269
+ * 지나는 표시를 비운다. 여기서는 점선 테두리가 이미 「지금 여기」를 말하고, 배경까지
270
+ * 함께 움직이면 눈이 둘을 따라가야 한다.
270
271
  */
271
- --grid-header-title-grow: 1;
272
+ --grid-record-hover-background-color: transparent;
272
273
  }
273
274
 
274
275
  :host {
@@ -1 +1 @@
1
- {"version":3,"file":"data-grid.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid.ts"],"names":[],"mappings":"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","sourcesContent":["import i18next from 'i18next'\nimport '../empty-note.js'\nimport './data-grid-header.js'\nimport './data-grid-body.js'\nimport './data-grid-footer.js'\n\nimport { css, html, LitElement, PropertyValues, nothing} from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles.js'\n\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { DataManipulator } from '../data-manipulator.js'\nimport { ColumnConfig, GristRecord, PaginationConfig } from '../types.js'\n// import { supportsPassive } from '../utils/index.js'\nimport { DataGridHeader } from './data-grid-header.js'\n\n/**\n * DataGrid\n */\n@customElement('ox-grid')\nexport class DataGrid extends DataManipulator {\n static styles = [\n MDTypeScaleStyles,\n ScrollbarStyles,\n css`\n /*\n * ── 고치는 표만 셀을 겨눈다 ─────────────────────────────────────────\n *\n * 셀 하나를 가리키는 점선과 열 폭 조절 손잡이는 **고칠 셀을 겨누는 장치**다. 기본 겉모습에서는\n * 둘을 두지 않는다(data-grist.ts 의 한 벌). 고칠 수 있는 열이 하나라도 있으면 여기서 되살린다.\n *\n * 화면이 고르는 모드가 아니다 — 표가 스스로 아는 사실이다(위 editableGrid 주석 참조).\n */\n :host([editable-grid]) {\n --grid-record-focused-cell-border: 1px dashed var(--ui-faint, #8a959c);\n --grid-header-splitter-display: flex;\n /*\n * 열 이름이 칸을 다 차지하게 두어 정렬 표식을 칸 오른쪽 끝으로 민다. 거기에는 폭 조절 손잡이가\n * 서 있으므로 표식이 그 옆에 모인다.\n *\n * 읽기 전용 표에는 손잡이가 없어서, 표식이 칸 끝에 홀로 떠 이름과 멀어진다. 그래서 기본은\n * 이름에 붙는 쪽이다(data-grid-header.ts).\n */\n --grid-header-title-grow: 1;\n }\n\n :host {\n display: flex;\n flex-direction: column;\n\n /* div[setting] 의 절대 좌표 기준. */\n position: relative;\n overflow: hidden;\n\n border-width: var(--grid-container-border-width);\n }\n\n ox-grid-body {\n flex: 1;\n position: relative;\n\n font-variation-settings: 'FILL' 1;\n }\n\n ox-grid-header {\n font-variation-settings: 'FILL' 1;\n }\n\n ox-grid-footer {\n font-variation-settings: 'FILL' 1;\n }\n\n ox-empty-note {\n display: block;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n }\n\n /*\n * 컬럼 설정 단추는 **헤더에 마우스를 올릴 때만** 보인다.\n *\n * 늘 보이면 목록 화면마다 오른쪽 위에 눈에 걸리는 것이 하나 생긴다. 자주 쓰는 것도 아니다.\n *\n * 감춰 있는 동안에는 pointer-events 도 끈다 — 안 보이는데 눌리는 자리가 있으면, 헤더의 마지막\n * 컬럼을 누르려던 사람이 엉뚱한 팝업을 만난다.\n *\n * 세 갈래로 켠다.\n * 헤더에 올렸을 때 :has(ox-grid-header:hover)\n * 단추 자체에 올렸을 때 단추가 헤더 위에 떠 있으므로, 커서가 단추로 옮겨오면 헤더는 더 이상\n * hover 가 아니다. 이 갈래가 없으면 커서 아래에서 사라진다\n * 키보드 초점 focus-within\n */\n div[setting] {\n /*\n * 크기 없이 호스트의 오른쪽 위에 붙는다. 안에 들어오는 단추가 [slot='setting'] 규칙으로\n * top: -3px · right: 0 을 스스로 잡으므로, 이 div 는 기준점 노릇만 한다.\n */\n position: absolute;\n top: 0;\n right: 0;\n width: 0;\n height: 0;\n z-index: 5;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.12s ease-out;\n }\n\n /*\n * 단추 자체에 올렸을 때도 켜 둔다 — 단추가 헤더 위에 떠 있어서, 커서가 단추로 옮겨오면 헤더는\n * 더 이상 hover 가 아니다. 이 갈래가 없으면 커서 아래에서 사라진다.\n */\n ox-grid-header:hover + div[setting],\n div[setting]:hover,\n div[setting]:focus-within {\n opacity: 1;\n pointer-events: auto;\n }\n\n /*\n * 손가락으로 쓰는 장치 — hover 가 없으므로 감추면 닿을 방법이 없다. 늘 두고 평소에는 흐리게,\n * 누르는 동안 선명하게 한다.\n *\n * 화면 폭이 아니라 입력 장치로 가른다. 창을 좁힌 데스크톱은 여기에 걸리지 않고, 큰 태블릿은\n * 폭이 넓어도 걸린다.\n */\n @media (pointer: coarse) {\n div[setting] {\n opacity: 0.35;\n pointer-events: auto;\n }\n\n div[setting]:active,\n div[setting]:focus-within {\n opacity: 1;\n }\n }\n\n @media print {\n :host {\n zoom: 80%;\n }\n }\n `\n ]\n\n @property({ type: Object }) focused?: { row: number; column: number }\n @property({ type: Boolean }) empty?: boolean\n\n /**\n * 이 표에 고칠 수 있는 열이 하나라도 있나 — **겉모습이 이것으로 갈린다.**\n *\n * 셀 하나를 가리키는 점선과 열 폭 조절 손잡이는 **고칠 셀을 겨누는 장치**다. 고치지 않는 목록에서는\n * 셀 하나가 뜻을 갖지 않아, 줄을 고르려고 누른 자리에 점선이 남고 세로 선이 줄 읽기를 방해한다.\n *\n * 그래서 모드를 따로 두지 않는다. 화면이 고를 일이 아니라 **표가 스스로 아는 사실**이다 —\n * 열에 `record.editable` 이 있으면 고치는 표다.\n */\n @property({ type: Boolean, reflect: true, attribute: 'editable-grid' }) editableGrid: boolean = false\n\n @query('ox-grid-body', true) body!: LitElement\n @query('ox-grid-header', true) header!: DataGridHeader\n @query('ox-grid-footer', true) footer!: LitElement\n\n @state() fixedLefts: number[] = []\n\n firstUpdated() {\n /* header and body scroll synchronization */\n this.header.addEventListener('scroll', e => {\n if (this.body.scrollLeft !== this.header.scrollLeft) {\n this.body.scrollLeft = this.header.scrollLeft\n }\n })\n\n this.body.addEventListener('scroll', e => {\n if (this.body.scrollLeft !== this.header.scrollLeft) {\n this.header.scrollLeft = this.body.scrollLeft\n }\n })\n\n this.header.addEventListener('wheel', this.onWheelEvent.bind(this))\n this.footer && this.footer.addEventListener('wheel', this.onWheelEvent.bind(this))\n\n /* record selection processing */\n this.addEventListener('select-all-change', e => {\n if (this.data.records.length == 0) {\n return\n }\n\n var { selected } = (e as CustomEvent).detail\n var { records } = this.data\n\n records.forEach(record => (record['__selected__'] = selected))\n\n this.header.requestUpdate()\n this.body.requestUpdate()\n })\n\n this.addEventListener('focus-change', e => {\n const { row, column } = (e as CustomEvent).detail || {}\n if (!this.focused || this.focused.row != row || this.focused.column != column) {\n this.focused = { row, column }\n this.focus()\n this.requestUpdate()\n }\n })\n }\n\n onWheelEvent(e: WheelEvent) {\n if (this.body.scrollWidth > this.body.clientWidth) {\n var delta = Math.max(-1, Math.min(1, e.deltaY || 0))\n this.body.scrollLeft = Math.max(0, this.body.scrollLeft - delta * 30)\n\n var maxScrollLeft = this.body.scrollWidth - this.body.clientWidth\n\n var atStart = this.body.scrollLeft === 0\n var atEnd = this.body.scrollLeft === maxScrollLeft\n\n // 스크롤이 맨 앞으로 와 있는 상태에서 휠을 올리는 경우 또는\n // 스크롤이 맨 끝으로 가 있는 상태에서 휠을 내리는 경우에만 디폴트 동작 허용\n if ((atStart && delta > 0) || (atEnd && delta < 0)) {\n return true\n }\n\n e.preventDefault()\n }\n }\n\n onSelectRecordChanged({\n selectedRecords,\n added,\n removed\n }: {\n selectedRecords: GristRecord[]\n added: GristRecord[]\n removed: GristRecord[]\n }): void {\n super.onSelectRecordChanged({ selectedRecords, added, removed })\n\n this.header.requestUpdate()\n this.body.requestUpdate()\n }\n\n onRecordChanged(\n recordData: GristRecord,\n row: number,\n column: ColumnConfig | null /* TODO column should be removed */\n ) {\n /* record-viewer 등 grid 외에서 변경되는 경우에도 header와 body를 refresh 하도록 한다. */\n super.onRecordChanged(recordData, row, column)\n\n this.header.requestUpdate()\n this.body.requestUpdate()\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('data')) {\n /*\n * 데이타 내용에 따라 동적으로 컬럼의 폭이 달라지는 경우(예를 들면, sequence field)가 있으므로,\n * data의 변동에 대해서도 다시 계산되어야 한다.\n */\n this.calculateWidths(this.config.columns)\n\n if (this.focused && 'row' in this.focused) {\n var { row = 0, column = 0 } = this.focused\n var { records: oldrecords = [] } = changes.get('data') || {}\n var { records: newrecords } = this.data\n\n var oldrecord = oldrecords[row]\n\n if (oldrecord && oldrecord !== newrecords[row]) {\n var newrecord = newrecords.find(\n record =>\n /* TODO keyfields를 정의하고, keyfields의 동일성으로 확정해야 한다. */\n oldrecord === record ||\n ('id' in oldrecord\n ? record.id == oldrecord.id\n : 'name' in oldrecord\n ? record.name == oldrecord.name\n : false)\n )\n\n this.focused = {\n row: newrecord ? newrecords.indexOf(newrecord) : row,\n column\n }\n }\n }\n } else if (changes.has('config')) {\n this.calculateWidths(this.config.columns)\n }\n\n /* grid fetch 후에 grid로 focus를 주어야 하는 지 검토가 필요하다. */\n // this.focus()\n }\n\n calculateWidths(columns: ColumnConfig[]) {\n /*\n * 컬럼 모델 마지막에 'auto' cell을 추가하여, 자투리 영역을 꽉 채워서 표시한다.\n *\n * 숫자로 준 폭은 **그 폭 그대로** 쓴다. 합이 보이는 폭보다 크면 표는 가로로 넘치고, 나머지는\n * 가로 스크롤로 본다 — 표의 정상 거동이다.\n *\n * 한때 minmax(0, Npx) 로 두어 넘칠 때 열들이 함께 줄게 했다가 되돌렸다. 그렇게 하면 어떤 표도\n * 가로로 넘치지 않으므로 **가로 스크롤이 아예 사라진다.** 열 열다섯 개를 700px 에 밀어 넣으면\n * 모든 열이 못 읽을 만큼 좁아지고, 화면은 그것을 알릴 방법이 없다.\n *\n * 열이 좁아 잘리는 것은 화면이 열 폭을 정해서 풀 일이다 — 부품이 대신 줄이면 화면의 뜻이 사라진다.\n */\n const widths = columns\n .filter(column => !column.hidden)\n .map(column => {\n switch (typeof column.width) {\n case 'number':\n return `${column.width}px`\n case 'string':\n return column.width\n case 'function':\n return column.width.call(this, column)\n default:\n return 'auto'\n }\n })\n .concat(['auto'])\n .join(' ')\n\n /* 겉모습이 이 사실로 갈린다(위 editableGrid 주석 참조). 열이 정해지는 이 시점이 그 자리다. */\n this.editableGrid = columns.some(column => !column.hidden && !column.gutterName && !!column.record?.editable)\n\n this.style.setProperty('--grid-template-columns', widths)\n /* 인쇄는 종이 폭에 맞춰 비율로 나눈다. `220px` → `220fr` 로 바뀐다. */\n this.style.setProperty('--grid-template-print-columns', widths.replace(/px/gi, 'fr'))\n }\n\n render() {\n var { pagination = {} as PaginationConfig, columns = [], filters } = this.config\n\n var paginatable = !pagination.infinite\n var data = this.data\n\n return html`\n <ox-grid-header\n class=\"md-typescale-label-medium-prominent\"\n .columns=${columns}\n .sorters=${this.sorters}\n .filters=${this.filters}\n .data=${data}\n ?filtering-feature=${filters?.header}\n @column-width-change=${(e: CustomEvent) => {\n let { idx, width } = e.detail\n columns[idx].width = width\n this.calculateWidths(columns)\n }}\n @fixed-lefts-change=${(e: CustomEvent) => (this.fixedLefts = e.detail)}\n >\n </ox-grid-header>\n\n <!--\n 헤더 **다음**에 둔다. CSS 로 「헤더에 올렸을 때만」을 표현하려면 형제 선택자가 필요하고, 형제\n 선택자는 뒤쪽 형제만 고를 수 있다.\n\n :host(:has(ox-grid-header:hover)) 로는 안 된다 — :host() 의 인수는 바깥 트리에서 평가되므로\n 섀도 트리 안의 ox-grid-header 를 보지 못한다. 실제로 그렇게 써 봤고 hover 에 반응하지 않았다.\n\n 순서를 바꿔도 보이는 자리는 같다 — 아래 스타일에서 호스트의 오른쪽 위에 절대 좌표로 붙인다.\n -->\n <div setting>\n <slot name=\"setting\"></slot>\n </div>\n\n <ox-grid-body\n class=\"md-typescale-body-medium\"\n .config=${this.config}\n .columns=${columns}\n .data=${data}\n .focused=${this.focused!}\n .fixedLefts=${this.fixedLefts}\n >\n ${this.empty\n ? html`\n <!--\n 아직 아무것도 없을 때 **화면이 자기 말을 넣을 수 있다.**\n\n 전에는 「NO RECORDS」가 박혀 있었다. 그 문장은 다음에 무엇을 할지 알려 주지 않는다 —\n 비어 있는 화면이야말로 「여기서 무엇을 만들 수 있고 그것이 무엇에 쓰이나」를 말해야 하는\n 자리다. 처음 오는 사람이 가장 먼저 보는 화면이기도 하다.\n\n 화면이 config.emptyNote 로 말하고, 말하지 않으면 예전 문장이 그대로 나온다.\n -->\n <ox-empty-note\n icon=${this.config?.emptyNote?.icon ?? nothing}\n title=${this.config?.emptyNote?.title ?? i18next.t('text.grid-no-records', { defaultValue: 'NO RECORDS' })}\n description=${this.config?.emptyNote?.description ?? nothing}\n ></ox-empty-note>\n `\n : html``}\n </ox-grid-body>\n ${paginatable\n ? html`\n <!--\n 푸터에는 본문 타이프스케일을 씌우지 않는다.\n\n 그 클래스는 font 축약형으로 0.875rem 를 넣는데, **바깥 트리의 규칙이라 푸터의\n :host { font-size } 를 이긴다**(그림자 캐스케이드에서 호스트 요소는 바깥 트리 규칙이\n 우선한다). 그래서 푸터가 자기 크기를 못 정하고 본문과 같은 14px 로 남아 있었다.\n [재봤음] 리터럴 :host { font-size: 7px } 도 안 먹었다. 2026-09-02\n\n 푸터는 본문이 아니다. 크기는 --grid-footer-font-size 가 정한다.\n -->\n <ox-grid-footer\n .data=${data}\n .pagination=${this.pagination}\n ></ox-grid-footer>\n `\n : html``}\n `\n }\n\n focus() {\n super.focus()\n\n this.body.focus()\n }\n\n get pullToRefreshTarget() {\n return this.body\n }\n}\n"]}
1
+ {"version":3,"file":"data-grid.js","sourceRoot":"","sources":["../../../src/data-grid/data-grid.ts"],"names":[],"mappings":"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","sourcesContent":["import i18next from 'i18next'\nimport '../empty-note.js'\nimport './data-grid-header.js'\nimport './data-grid-body.js'\nimport './data-grid-footer.js'\n\nimport { css, html, LitElement, PropertyValues, nothing} from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles.js'\n\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { DataManipulator } from '../data-manipulator.js'\nimport { ColumnConfig, GristRecord, PaginationConfig } from '../types.js'\n// import { supportsPassive } from '../utils/index.js'\nimport { DataGridHeader } from './data-grid-header.js'\n\n/**\n * DataGrid\n */\n@customElement('ox-grid')\nexport class DataGrid extends DataManipulator {\n static styles = [\n MDTypeScaleStyles,\n ScrollbarStyles,\n css`\n /*\n * ── 고치는 표만 셀을 겨눈다 ─────────────────────────────────────────\n *\n * 셀 하나를 가리키는 점선과 열 폭 조절 손잡이는 **고칠 셀을 겨누는 장치**다. 기본 겉모습에서는\n * 둘을 두지 않는다(data-grist.ts 의 한 벌). 고칠 수 있는 열이 하나라도 있으면 여기서 되살린다.\n *\n * 화면이 고르는 모드가 아니다 — 표가 스스로 아는 사실이다(위 editableGrid 주석 참조).\n */\n :host([editable-grid]) {\n --grid-record-focused-cell-border: 1px dashed var(--ui-faint, #8a959c);\n /*\n * 정렬 표식의 자리는 이 값에서 **파생된다** — 손잡이가 보이면 표식이 칸 오른쪽 끝으로 가고,\n * 안 보이면 이름에 붙는다(data-grid-header.ts 의 스타일 질의). 여기서 따로 정하지 않는다.\n */\n --grid-header-splitter-display: flex;\n /*\n * 지나는 줄 표시를 비운다. 여기서는 점선 셀 테두리가 이미 「지금 여기」를 말하고, 줄 배경까지\n * 함께 움직이면 눈이 둘을 따라가야 한다.\n */\n --grid-record-hover-background-color: transparent;\n }\n\n :host {\n display: flex;\n flex-direction: column;\n\n /* div[setting] 의 절대 좌표 기준. */\n position: relative;\n overflow: hidden;\n\n border-width: var(--grid-container-border-width);\n }\n\n ox-grid-body {\n flex: 1;\n position: relative;\n\n font-variation-settings: 'FILL' 1;\n }\n\n ox-grid-header {\n font-variation-settings: 'FILL' 1;\n }\n\n ox-grid-footer {\n font-variation-settings: 'FILL' 1;\n }\n\n ox-empty-note {\n display: block;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n }\n\n /*\n * 컬럼 설정 단추는 **헤더에 마우스를 올릴 때만** 보인다.\n *\n * 늘 보이면 목록 화면마다 오른쪽 위에 눈에 걸리는 것이 하나 생긴다. 자주 쓰는 것도 아니다.\n *\n * 감춰 있는 동안에는 pointer-events 도 끈다 — 안 보이는데 눌리는 자리가 있으면, 헤더의 마지막\n * 컬럼을 누르려던 사람이 엉뚱한 팝업을 만난다.\n *\n * 세 갈래로 켠다.\n * 헤더에 올렸을 때 :has(ox-grid-header:hover)\n * 단추 자체에 올렸을 때 단추가 헤더 위에 떠 있으므로, 커서가 단추로 옮겨오면 헤더는 더 이상\n * hover 가 아니다. 이 갈래가 없으면 커서 아래에서 사라진다\n * 키보드 초점 focus-within\n */\n div[setting] {\n /*\n * 크기 없이 호스트의 오른쪽 위에 붙는다. 안에 들어오는 단추가 [slot='setting'] 규칙으로\n * top: -3px · right: 0 을 스스로 잡으므로, 이 div 는 기준점 노릇만 한다.\n */\n position: absolute;\n top: 0;\n right: 0;\n width: 0;\n height: 0;\n z-index: 5;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.12s ease-out;\n }\n\n /*\n * 단추 자체에 올렸을 때도 켜 둔다 — 단추가 헤더 위에 떠 있어서, 커서가 단추로 옮겨오면 헤더는\n * 더 이상 hover 가 아니다. 이 갈래가 없으면 커서 아래에서 사라진다.\n */\n ox-grid-header:hover + div[setting],\n div[setting]:hover,\n div[setting]:focus-within {\n opacity: 1;\n pointer-events: auto;\n }\n\n /*\n * 손가락으로 쓰는 장치 — hover 가 없으므로 감추면 닿을 방법이 없다. 늘 두고 평소에는 흐리게,\n * 누르는 동안 선명하게 한다.\n *\n * 화면 폭이 아니라 입력 장치로 가른다. 창을 좁힌 데스크톱은 여기에 걸리지 않고, 큰 태블릿은\n * 폭이 넓어도 걸린다.\n */\n @media (pointer: coarse) {\n div[setting] {\n opacity: 0.35;\n pointer-events: auto;\n }\n\n div[setting]:active,\n div[setting]:focus-within {\n opacity: 1;\n }\n }\n\n @media print {\n :host {\n zoom: 80%;\n }\n }\n `\n ]\n\n @property({ type: Object }) focused?: { row: number; column: number }\n @property({ type: Boolean }) empty?: boolean\n\n /**\n * 이 표에 고칠 수 있는 열이 하나라도 있나 — **겉모습이 이것으로 갈린다.**\n *\n * 셀 하나를 가리키는 점선과 열 폭 조절 손잡이는 **고칠 셀을 겨누는 장치**다. 고치지 않는 목록에서는\n * 셀 하나가 뜻을 갖지 않아, 줄을 고르려고 누른 자리에 점선이 남고 세로 선이 줄 읽기를 방해한다.\n *\n * 그래서 모드를 따로 두지 않는다. 화면이 고를 일이 아니라 **표가 스스로 아는 사실**이다 —\n * 열에 `record.editable` 이 있으면 고치는 표다.\n */\n @property({ type: Boolean, reflect: true, attribute: 'editable-grid' }) editableGrid: boolean = false\n\n @query('ox-grid-body', true) body!: LitElement\n @query('ox-grid-header', true) header!: DataGridHeader\n @query('ox-grid-footer', true) footer!: LitElement\n\n @state() fixedLefts: number[] = []\n\n firstUpdated() {\n /* header and body scroll synchronization */\n this.header.addEventListener('scroll', e => {\n if (this.body.scrollLeft !== this.header.scrollLeft) {\n this.body.scrollLeft = this.header.scrollLeft\n }\n })\n\n this.body.addEventListener('scroll', e => {\n if (this.body.scrollLeft !== this.header.scrollLeft) {\n this.header.scrollLeft = this.body.scrollLeft\n }\n })\n\n this.header.addEventListener('wheel', this.onWheelEvent.bind(this))\n this.footer && this.footer.addEventListener('wheel', this.onWheelEvent.bind(this))\n\n /* record selection processing */\n this.addEventListener('select-all-change', e => {\n if (this.data.records.length == 0) {\n return\n }\n\n var { selected } = (e as CustomEvent).detail\n var { records } = this.data\n\n records.forEach(record => (record['__selected__'] = selected))\n\n this.header.requestUpdate()\n this.body.requestUpdate()\n })\n\n this.addEventListener('focus-change', e => {\n const { row, column } = (e as CustomEvent).detail || {}\n if (!this.focused || this.focused.row != row || this.focused.column != column) {\n this.focused = { row, column }\n this.focus()\n this.requestUpdate()\n }\n })\n }\n\n onWheelEvent(e: WheelEvent) {\n if (this.body.scrollWidth > this.body.clientWidth) {\n var delta = Math.max(-1, Math.min(1, e.deltaY || 0))\n this.body.scrollLeft = Math.max(0, this.body.scrollLeft - delta * 30)\n\n var maxScrollLeft = this.body.scrollWidth - this.body.clientWidth\n\n var atStart = this.body.scrollLeft === 0\n var atEnd = this.body.scrollLeft === maxScrollLeft\n\n // 스크롤이 맨 앞으로 와 있는 상태에서 휠을 올리는 경우 또는\n // 스크롤이 맨 끝으로 가 있는 상태에서 휠을 내리는 경우에만 디폴트 동작 허용\n if ((atStart && delta > 0) || (atEnd && delta < 0)) {\n return true\n }\n\n e.preventDefault()\n }\n }\n\n onSelectRecordChanged({\n selectedRecords,\n added,\n removed\n }: {\n selectedRecords: GristRecord[]\n added: GristRecord[]\n removed: GristRecord[]\n }): void {\n super.onSelectRecordChanged({ selectedRecords, added, removed })\n\n this.header.requestUpdate()\n this.body.requestUpdate()\n }\n\n onRecordChanged(\n recordData: GristRecord,\n row: number,\n column: ColumnConfig | null /* TODO column should be removed */\n ) {\n /* record-viewer 등 grid 외에서 변경되는 경우에도 header와 body를 refresh 하도록 한다. */\n super.onRecordChanged(recordData, row, column)\n\n this.header.requestUpdate()\n this.body.requestUpdate()\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('data')) {\n /*\n * 데이타 내용에 따라 동적으로 컬럼의 폭이 달라지는 경우(예를 들면, sequence field)가 있으므로,\n * data의 변동에 대해서도 다시 계산되어야 한다.\n */\n this.calculateWidths(this.config.columns)\n\n if (this.focused && 'row' in this.focused) {\n var { row = 0, column = 0 } = this.focused\n var { records: oldrecords = [] } = changes.get('data') || {}\n var { records: newrecords } = this.data\n\n var oldrecord = oldrecords[row]\n\n if (oldrecord && oldrecord !== newrecords[row]) {\n var newrecord = newrecords.find(\n record =>\n /* TODO keyfields를 정의하고, keyfields의 동일성으로 확정해야 한다. */\n oldrecord === record ||\n ('id' in oldrecord\n ? record.id == oldrecord.id\n : 'name' in oldrecord\n ? record.name == oldrecord.name\n : false)\n )\n\n this.focused = {\n row: newrecord ? newrecords.indexOf(newrecord) : row,\n column\n }\n }\n }\n } else if (changes.has('config')) {\n this.calculateWidths(this.config.columns)\n }\n\n /* grid fetch 후에 grid로 focus를 주어야 하는 지 검토가 필요하다. */\n // this.focus()\n }\n\n calculateWidths(columns: ColumnConfig[]) {\n /*\n * 컬럼 모델 마지막에 'auto' cell을 추가하여, 자투리 영역을 꽉 채워서 표시한다.\n *\n * 숫자로 준 폭은 **그 폭 그대로** 쓴다. 합이 보이는 폭보다 크면 표는 가로로 넘치고, 나머지는\n * 가로 스크롤로 본다 — 표의 정상 거동이다.\n *\n * 한때 minmax(0, Npx) 로 두어 넘칠 때 열들이 함께 줄게 했다가 되돌렸다. 그렇게 하면 어떤 표도\n * 가로로 넘치지 않으므로 **가로 스크롤이 아예 사라진다.** 열 열다섯 개를 700px 에 밀어 넣으면\n * 모든 열이 못 읽을 만큼 좁아지고, 화면은 그것을 알릴 방법이 없다.\n *\n * 열이 좁아 잘리는 것은 화면이 열 폭을 정해서 풀 일이다 — 부품이 대신 줄이면 화면의 뜻이 사라진다.\n */\n const widths = columns\n .filter(column => !column.hidden)\n .map(column => {\n switch (typeof column.width) {\n case 'number':\n return `${column.width}px`\n case 'string':\n return column.width\n case 'function':\n return column.width.call(this, column)\n default:\n return 'auto'\n }\n })\n .concat(['auto'])\n .join(' ')\n\n /* 겉모습이 이 사실로 갈린다(위 editableGrid 주석 참조). 열이 정해지는 이 시점이 그 자리다. */\n this.editableGrid = columns.some(column => !column.hidden && !column.gutterName && !!column.record?.editable)\n\n this.style.setProperty('--grid-template-columns', widths)\n /* 인쇄는 종이 폭에 맞춰 비율로 나눈다. `220px` → `220fr` 로 바뀐다. */\n this.style.setProperty('--grid-template-print-columns', widths.replace(/px/gi, 'fr'))\n }\n\n render() {\n var { pagination = {} as PaginationConfig, columns = [], filters } = this.config\n\n var paginatable = !pagination.infinite\n var data = this.data\n\n return html`\n <ox-grid-header\n class=\"md-typescale-label-medium-prominent\"\n .columns=${columns}\n .sorters=${this.sorters}\n .filters=${this.filters}\n .data=${data}\n ?filtering-feature=${filters?.header}\n @column-width-change=${(e: CustomEvent) => {\n let { idx, width } = e.detail\n columns[idx].width = width\n this.calculateWidths(columns)\n }}\n @fixed-lefts-change=${(e: CustomEvent) => (this.fixedLefts = e.detail)}\n >\n </ox-grid-header>\n\n <!--\n 헤더 **다음**에 둔다. CSS 로 「헤더에 올렸을 때만」을 표현하려면 형제 선택자가 필요하고, 형제\n 선택자는 뒤쪽 형제만 고를 수 있다.\n\n :host(:has(ox-grid-header:hover)) 로는 안 된다 — :host() 의 인수는 바깥 트리에서 평가되므로\n 섀도 트리 안의 ox-grid-header 를 보지 못한다. 실제로 그렇게 써 봤고 hover 에 반응하지 않았다.\n\n 순서를 바꿔도 보이는 자리는 같다 — 아래 스타일에서 호스트의 오른쪽 위에 절대 좌표로 붙인다.\n -->\n <div setting>\n <slot name=\"setting\"></slot>\n </div>\n\n <ox-grid-body\n class=\"md-typescale-body-medium\"\n .config=${this.config}\n .columns=${columns}\n .data=${data}\n .focused=${this.focused!}\n .fixedLefts=${this.fixedLefts}\n >\n ${this.empty\n ? html`\n <!--\n 아직 아무것도 없을 때 **화면이 자기 말을 넣을 수 있다.**\n\n 전에는 「NO RECORDS」가 박혀 있었다. 그 문장은 다음에 무엇을 할지 알려 주지 않는다 —\n 비어 있는 화면이야말로 「여기서 무엇을 만들 수 있고 그것이 무엇에 쓰이나」를 말해야 하는\n 자리다. 처음 오는 사람이 가장 먼저 보는 화면이기도 하다.\n\n 화면이 config.emptyNote 로 말하고, 말하지 않으면 예전 문장이 그대로 나온다.\n -->\n <ox-empty-note\n icon=${this.config?.emptyNote?.icon ?? nothing}\n title=${this.config?.emptyNote?.title ?? i18next.t('text.grid-no-records', { defaultValue: 'NO RECORDS' })}\n description=${this.config?.emptyNote?.description ?? nothing}\n ></ox-empty-note>\n `\n : html``}\n </ox-grid-body>\n ${paginatable\n ? html`\n <!--\n 푸터에는 본문 타이프스케일을 씌우지 않는다.\n\n 그 클래스는 font 축약형으로 0.875rem 를 넣는데, **바깥 트리의 규칙이라 푸터의\n :host { font-size } 를 이긴다**(그림자 캐스케이드에서 호스트 요소는 바깥 트리 규칙이\n 우선한다). 그래서 푸터가 자기 크기를 못 정하고 본문과 같은 14px 로 남아 있었다.\n [재봤음] 리터럴 :host { font-size: 7px } 도 안 먹었다. 2026-09-02\n\n 푸터는 본문이 아니다. 크기는 --grid-footer-font-size 가 정한다.\n -->\n <ox-grid-footer\n .data=${data}\n .pagination=${this.pagination}\n ></ox-grid-footer>\n `\n : html``}\n `\n }\n\n focus() {\n super.focus()\n\n this.body.focus()\n }\n\n get pullToRefreshTarget() {\n return this.body\n }\n}\n"]}
@@ -1108,6 +1108,28 @@ DataGrist.styles = [
1108
1108
  --grid-record-padding: 7px 10px;
1109
1109
  --grid-record-color: var(--ui-ink, #17242c);
1110
1110
  --grid-record-border-bottom: 1px solid var(--ui-line-soft, #e6eaed);
1111
+ /*
1112
+ * 마우스가 지나는 줄. **고른 줄보다 훨씬 옅다** — 지나는 것은 사실이 아니라 눈이 어디 있는지
1113
+ * 알려 주는 것뿐이다.
1114
+ *
1115
+ * 읽기 전용 표에만 쓴다. 고치는 표는 점선 셀 테두리가 그 일을 하고, 거기서는 이 값을 비운다
1116
+ * (data-grid.ts) — 둘이 함께 있으면 시끄럽다.
1117
+ *
1118
+ * ── 면의 단계에서 가져온다 ───────────────────────────────────────────
1119
+ * 줄은 흰 바탕이고 표 바깥은 회색이다. 그 사이에 자리를 잡아야 한다 — 흰 줄과 구별되면서 「줄이
1120
+ * 없는 자리」로도 안 읽혀야 한다.
1121
+ *
1122
+ * 흰 줄 255 255 255
1123
+ * surface-container-low 247 248 250 이것 — 줄보다 살짝 눌리고
1124
+ * 표 바깥(surface-container) 240 242 244 바깥보다는 밝다
1125
+ *
1126
+ * 잉크를 얹는 방식으로도 해 봤는데, 겹치지 않을 만큼 진하게 하면(10%) 232 233 234 로 **바깥보다
1127
+ * 어두워져** 무겁게 느껴졌다. 옅게 하면(6%) 바깥과 정확히 겹쳤다. [재봤음] 2026-09-02
1128
+ *
1129
+ * 면 단계를 쓰면 그 사이에 자리가 잡히고, **어두운 모드에서 함께 뒤집힌다** — 색을 직접 적으면
1130
+ * 어두운 줄에 잉크를 얹어 보이지 않게 된다.
1131
+ */
1132
+ --grid-record-hover-background-color: var(--md-sys-color-surface-container-low, #f7f8fa);
1111
1133
  /* 초점 표식을 없앤다. outline 으로 그리므로 줄 선은 그대로 남는다. */
1112
1134
  --grid-record-focused-cell-border: none;
1113
1135
  --grid-record-focused-box-shadow: none;