@devslab/dds-table 0.11.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.
- package/LICENSE +74 -0
- package/README.ko.md +155 -0
- package/README.md +153 -0
- package/dist/columns.d.ts +89 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/data-table.d.ts +22 -0
- package/dist/data-table.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +226 -0
- package/dist/index.js.map +1 -0
- package/dist/server.js +279 -0
- package/dist/server.js.map +1 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
DevsLab Source-Available License 1.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DevsLab. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This license governs the DDS software, design tokens, components, icons,
|
|
6
|
+
documentation, and other materials distributed with this license (the
|
|
7
|
+
"Software").
|
|
8
|
+
|
|
9
|
+
1. Permitted use
|
|
10
|
+
|
|
11
|
+
Subject to this license, DevsLab grants you a limited, worldwide,
|
|
12
|
+
non-exclusive, non-transferable, revocable, royalty-free right to:
|
|
13
|
+
|
|
14
|
+
- download and install unmodified copies of the Software;
|
|
15
|
+
- use and execute the Software for internal or commercial applications;
|
|
16
|
+
- compile, minify, tree-shake, and bundle unmodified Software solely as a
|
|
17
|
+
technical part of building an application; and
|
|
18
|
+
- distribute the resulting object code only as an inseparable part of that
|
|
19
|
+
application and not as a standalone library, design system, component kit,
|
|
20
|
+
template, or asset collection.
|
|
21
|
+
|
|
22
|
+
Normal application configuration through documented public APIs, design-token
|
|
23
|
+
overrides, CSS custom properties, and component properties is permitted and is
|
|
24
|
+
not considered modification of the Software.
|
|
25
|
+
|
|
26
|
+
2. Restrictions
|
|
27
|
+
|
|
28
|
+
Except where applicable law does not allow the restriction, you may not:
|
|
29
|
+
|
|
30
|
+
- modify, adapt, translate, reverse engineer, or create derivative works of the
|
|
31
|
+
Software itself;
|
|
32
|
+
- publish, republish, sublicense, sell, rent, host, or redistribute the
|
|
33
|
+
Software or any modified version as a standalone package or downloadable
|
|
34
|
+
collection;
|
|
35
|
+
- use the Software or a substantial portion of it to create or operate a
|
|
36
|
+
competing general-purpose design system, UI kit, component library, icon
|
|
37
|
+
library, token library, template marketplace, or hosted equivalent;
|
|
38
|
+
- remove or alter copyright, license, attribution, or provenance notices; or
|
|
39
|
+
- use DevsLab names, logos, product marks, or trade dress except to make a
|
|
40
|
+
truthful statement that an application uses the Software.
|
|
41
|
+
|
|
42
|
+
No patent, trademark, design, or branding rights are granted except the
|
|
43
|
+
copyright permissions stated in Section 1.
|
|
44
|
+
|
|
45
|
+
3. Ownership and feedback
|
|
46
|
+
|
|
47
|
+
The Software is licensed, not sold. DevsLab and its licensors retain all
|
|
48
|
+
right, title, and interest in the Software. You grant DevsLab a perpetual,
|
|
49
|
+
worldwide, irrevocable, royalty-free right to use feedback you voluntarily
|
|
50
|
+
provide about the Software.
|
|
51
|
+
|
|
52
|
+
4. Termination
|
|
53
|
+
|
|
54
|
+
This license terminates automatically if you breach it. Upon termination, you
|
|
55
|
+
must stop using and distributing the Software and delete all copies under your
|
|
56
|
+
control. Sections 2, 3, 5, and 6 survive termination.
|
|
57
|
+
|
|
58
|
+
5. Disclaimer and limitation of liability
|
|
59
|
+
|
|
60
|
+
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|
61
|
+
EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
62
|
+
PURPOSE, TITLE, AND NON-INFRINGEMENT. TO THE MAXIMUM EXTENT PERMITTED BY LAW,
|
|
63
|
+
DEVSLAB WILL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
|
64
|
+
CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES, OR FOR LOSS OF DATA, PROFITS,
|
|
65
|
+
REVENUE, OR BUSINESS, ARISING FROM OR RELATED TO THE SOFTWARE.
|
|
66
|
+
|
|
67
|
+
6. Governing law
|
|
68
|
+
|
|
69
|
+
This license is governed by the laws of the Republic of Korea, excluding
|
|
70
|
+
conflict-of-law rules. The Seoul Central District Court has exclusive
|
|
71
|
+
jurisdiction over disputes arising from this license.
|
|
72
|
+
|
|
73
|
+
This is a source-available license, not an open-source license approved by the
|
|
74
|
+
Open Source Initiative.
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# @devslab/dds-table
|
|
2
|
+
|
|
3
|
+
TanStack Table 기반 DDS 데이터 테이블 패키지(정확히 `9.2.4` 버전에 고정 —
|
|
4
|
+
고정 이유는 `docs/decisions.md` D-021 참고). `DataTable` 컴포넌트 하나와
|
|
5
|
+
이를 기술하는 `Column<T>`·`DataTableLabels` 타입만 제공한다. 테이블 자체는
|
|
6
|
+
어떤 단어도, 어떤 경로도, "다음 페이지"가 무엇을 뜻하는지도 정하지 않는다
|
|
7
|
+
— 방문자가 읽는 모든 문자열은 prop이다.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pnpm add @devslab/dds-table
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
이 패키지는 자체 스타일시트를 내지 않는다 — 애플리케이션 셸에서
|
|
14
|
+
`@devslab/dds-css`의 테이블 스타일을, 그것이 의존하는 토큰 CSS와 함께 한 번
|
|
15
|
+
불러온다:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import "@devslab/dds-tokens/tokens.css";
|
|
19
|
+
import "@devslab/dds-css/components/table.css";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
불러오지 않으면 `<DataTable>`은 스타일 없이 렌더링된다 — `fold`는 아무
|
|
23
|
+
효과가 없고(컬럼 접기는 전적으로 `table.css`의 미디어 쿼리다), 시각적으로
|
|
24
|
+
숨겨져야 할 caption과 액션 컬럼 헤더가 눈에 보이게 렌더링된다.
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { DataTable, type Column, type DataTableLabels } from "@devslab/dds-table";
|
|
28
|
+
|
|
29
|
+
type Job = { id: string; name: string; count: number };
|
|
30
|
+
|
|
31
|
+
const columns: Column<Job>[] = [
|
|
32
|
+
{ id: "name", label: "Name", cell: (row) => row.name, sortBy: (row) => row.name, rowHeader: true },
|
|
33
|
+
{ id: "count", label: "Count", cell: (row) => String(row.count), sortBy: (row) => row.count, numeric: true, fold: true },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const labels: DataTableLabels = {
|
|
37
|
+
sortBy: "Sort by {column}",
|
|
38
|
+
actions: "Actions",
|
|
39
|
+
nextPage: "Next page",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
<DataTable rows={jobs} columns={columns} caption="Jobs" labels={labels} sort="client" />;
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## `DataTable` props
|
|
46
|
+
|
|
47
|
+
| Prop | 타입 | 필수/기본값 | 의미 |
|
|
48
|
+
| --- | --- | --- | --- |
|
|
49
|
+
| `rows` | `readonly T[]` | 필수 | 데이터(어떤 순서로 렌더링할지는 아래 정렬 절에서 누가 책임지는지 설명). |
|
|
50
|
+
| `columns` | `readonly Column<T>[]` | 필수 | 컬럼 선언 — 아래 `Column<T>` 참고. |
|
|
51
|
+
| `caption` | `string` | 필수 | 테이블의 접근성 이름, 시각적으로 숨겨져 렌더링(`<caption class="dds-visually-hidden">`). |
|
|
52
|
+
| `labels` | `DataTableLabels` | 필수 | 컴포넌트가 렌더링할 수 있는 모든 문구 — 아래 "라벨은 필수다" 참고. |
|
|
53
|
+
| `sort` | `"client" \| { statedOrder: string }` | 선택, 생략 시 정렬 버튼도 순서 문구도 없음 | 아래 정렬 절 참고. |
|
|
54
|
+
| `density` | `"comfortable" \| "dense"` | 선택, 기본값 `"comfortable"`(40px 행) | `"dense"`는 `.dds-table--dense`를 붙인다(36px 행, 셀 패딩 축소). |
|
|
55
|
+
| `scroll` | `"auto" \| "tall"` | 선택, 기본값 `"auto"` | `"tall"`은 `.dds-table-wrap--tall`을 붙인다 — `max-block-size: 70vh`로 스크롤되는 본문 + 고정(sticky) 헤더, 페이지를 밀어내면 안 되는 긴 인페이지 목록용. |
|
|
56
|
+
| `minWidth` | `string`(CSS 길이) | 선택 | `<table>`의 `min-inline-size`를 정한다 — 좁은 화면에서 컬럼이 짓눌리는 대신 `.dds-table-wrap` 안에서 가로 스크롤된다. |
|
|
57
|
+
| `actions` | `(row: T) => JSX.Element` | 선택 | 행마다 트레일링 셀을 렌더링(예: 행 단위 버튼); `labels.actions`로부터 시각적으로 숨겨진 헤더 셀을 추가한다. |
|
|
58
|
+
| `detail` | `(row: T) => JSX.Element` | 선택 | 주어진 행 아래에 펼침 행을 렌더링한다. `null`을 반환하면(예: 펼쳐지지 않은 행) 그 행에는 빈 행이 아니라 아예 detail `<tr>`이 생기지 않는다. |
|
|
59
|
+
| `page` | `{ nextHref?: string }` | 선택 | 아래 페이징 절 참고. |
|
|
60
|
+
| `empty` | `JSX.Element` | 선택 | `rows`가 비어 있을 때 `<table>` 대신 렌더링된다. 순서 문구와(있다면) 페이징 링크는 그대로 렌더링된다 — 커서 페이징 목록의 빈 페이지도 순서가 있고 여전히 다음으로 갈 방법이 필요하기 때문이다. |
|
|
61
|
+
|
|
62
|
+
## `Column<T>`
|
|
63
|
+
|
|
64
|
+
| 필드 | 타입 | 의미 |
|
|
65
|
+
| --- | --- | --- |
|
|
66
|
+
| `id` | `string` | 컬럼 고유 식별자 — 정렬 키와 `data-fold`/`data-column` 속성에 쓰인다. |
|
|
67
|
+
| `label` | `string` | 헤더 텍스트(정렬 버튼의 화면 표시 라벨이기도 하다). |
|
|
68
|
+
| `cell` | `(row: T) => JSX.Element` | 셀 본문을 렌더링한다. 시각적 마크업은 소비자 몫이고, TanStack이 보는 컬럼 정의에는 정렬 접근자 외 아무것도 담기지 않는다. |
|
|
69
|
+
| `sortBy?` | `(row: T) => string \| number \| null` | 있으면 → (오직 `sort="client"` 모드에서만) 정렬 가능해지고 정렬 버튼이 붙는다. 없으면 → 평범한 헤더, 버튼이 절대 안 붙는다. "값 없음"은 `null`을 반환하면 되고, 그 행들은 맨 뒤로 정렬된다(`sortUndefined: "last"`) — 맨 앞이 아니다. |
|
|
70
|
+
| `width?` | `string` | CSS 너비. 아무 컬럼이든 이 값을 주는 순간 테이블 전체가 `table-layout: fixed`로 바뀌고 `<colgroup>`이 생성된다. |
|
|
71
|
+
| `fold?` | `boolean` | 좁은 화면에서 뺄 수 있는 컬럼으로 표시한다(아래 "컬럼 접기" 참고). |
|
|
72
|
+
| `numeric?` | `boolean` | 오른쪽 정렬 + 고정폭 숫자체를 적용한다. |
|
|
73
|
+
| `rowHeader?` | `boolean` | 이 컬럼의 셀을 `<td>` 대신 `<th scope="row">`로 렌더링한다 — 테이블당 정확히 한 컬럼만 이 값을 켜야 한다. |
|
|
74
|
+
|
|
75
|
+
## 정렬: `sort`
|
|
76
|
+
|
|
77
|
+
`sort`는 두 모양 중 하나를 받는다 — 이 타입은 내보내지지 않는다(값을 그대로
|
|
78
|
+
써넣으면 된다, import할 것이 없다):
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
"client" | { statedOrder: string }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- **`sort="client"`** — 테이블이 전체 목록을 메모리에 들고 있는 경우. `sortBy`가
|
|
85
|
+
있는 컬럼에 정렬 버튼이 렌더링되고, 누르면 TanStack Table이 이미 손에 쥔 행을
|
|
86
|
+
재정렬한다. 이게 안전한 이유는 정확히 "전체 행"과 "화면에 보이는 행"이 같은
|
|
87
|
+
집합이기 때문이다.
|
|
88
|
+
- **`sort={{ statedOrder: "…" }}`** — 서버가 정렬해 커서로 페이징한 한 페이지를
|
|
89
|
+
보여주는 테이블일 때. 이 모드에서는 `sortBy`가 있어도 어떤 컬럼도 정렬 버튼을
|
|
90
|
+
렌더링하지 않는다 — 클라이언트 정렬은 현재 페이지에 있는 행만 재배열할 수
|
|
91
|
+
있는데, 테이블의 진짜 순서는 브라우저가 아직 본 적 없는 여러 페이지에 걸쳐
|
|
92
|
+
백엔드 쿼리가 만든 순서이기 때문이다. 그런 버튼은 데이터를 정렬한 것처럼
|
|
93
|
+
보이지만 실제로는 잘못 보고하는 것이다. 대신 테이블은 자기 위에 실제 순서를
|
|
94
|
+
텍스트로 찍는다(`.dds-table__order`) — `statedOrder`가 그 문장이다(예:
|
|
95
|
+
"최신순"). 백엔드의 정렬 어휘를 DDS는 모르므로 이 문장은 소비자가 넘긴다.
|
|
96
|
+
|
|
97
|
+
서버 정렬 테이블이 "이 컬럼만" 클라이언트 정렬을 허용하도록 하는 세 번째
|
|
98
|
+
모드는 없다 — 컬럼이 몇 개든 실패 양상(페이지 하나의 순서를 전체 목록의
|
|
99
|
+
순서인 양 조용히 보고하는 것)은 동일하기 때문이다.
|
|
100
|
+
|
|
101
|
+
## 페이징: `page`
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
page?: { nextHref?: string }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`nextHref`는 다음 페이지 컨트롤을 `<a class="dds-btn dds-btn--secondary" href="…">`
|
|
108
|
+
(라벨이 붙은 `<nav>` 안)로 렌더링한다 — `<button onClick>`이 아니다. 커서
|
|
109
|
+
페이징 목록은 결국 쿼리 문자열만 다른 URL이고, 진짜 링크여야 JavaScript가
|
|
110
|
+
꺼져 있을 때·하이드레이션 전 느린 연결 상태에서·브라우저의 "새 탭에서 열기"에서
|
|
111
|
+
그대로 동작한다. `nextHref`(또는 `page` prop 전체)를 생략하면 페이징 `<nav>`는
|
|
112
|
+
비활성 컨트롤을 그리지 않고 아예 사라진다.
|
|
113
|
+
|
|
114
|
+
## 컬럼 접기: `fold`
|
|
115
|
+
|
|
116
|
+
`fold: true`로 표시한 컬럼은 고정된 분기점(`dds-css`의 `table.css`에 있는
|
|
117
|
+
`@media (max-width: 56.25rem)`) 아래에서 `[data-fold]`에 걸린 순수 CSS
|
|
118
|
+
규칙으로 사라진다 — JavaScript로 만든 컬럼 표시 상태도, resize observer도,
|
|
119
|
+
뷰포트별 재렌더도 없다. 컬럼은 DOM에 항상 존재하고 그릴지 말지는 브라우저가
|
|
120
|
+
정한다. 그 덕에 접기는 SSR에서도 그대로 작동하고(스크립트가 돌기 전에도
|
|
121
|
+
서버가 렌더한 좁은 화면은 이미 올바르게 그 컬럼을 숨긴 상태다), 정렬·페이징
|
|
122
|
+
상태와 맞춰야 할 상태 자체가 없으므로 동기화 비용이 없다.
|
|
123
|
+
|
|
124
|
+
## 라벨은 필수다, 기본값이 없다
|
|
125
|
+
|
|
126
|
+
`DataTableLabels`에는 선택 필드가 하나도 없고 `DataTable`은 대체 문자열을
|
|
127
|
+
전혀 갖고 있지 않다:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
type DataTableLabels = {
|
|
131
|
+
sortBy: string; // "{column}"이 컬럼 라벨로 치환된다
|
|
132
|
+
actions: string; // 트레일링 액션 컬럼의 헤더(시각적으로 숨김)
|
|
133
|
+
nextPage: string; // 다음 페이지 링크의 접근성 이름이자 표시 텍스트
|
|
134
|
+
};
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
DDS는 소비자의 사용자가 어떤 언어를 읽는지 정하지 않으므로, 화면 낭독기가
|
|
138
|
+
읽을 영어(또는 다른 어떤 언어의) 문구도 대신 실어 보내지 않는다. 라벨을
|
|
139
|
+
빠뜨린 소비자는 조용히 영어가 나가거나 빈칸이 나가는 대신 TypeScript
|
|
140
|
+
에러를 받는다.
|
|
141
|
+
|
|
142
|
+
## 이 패키지가 내보내지 않는 것
|
|
143
|
+
|
|
144
|
+
`DataTable`이 유일한 컴포넌트다. TanStack Table 자체 문서가 테이블을
|
|
145
|
+
조립하는 재료로 쓰는 행/셀 프리미티브(`Th`, `Td`, `useDataTable` 훅)는
|
|
146
|
+
의도적으로 미노출이다 — 오늘 소비자는 정확히 하나이고, 유지해야 할 API
|
|
147
|
+
표면을 두 벌 두는 비용은 필요해지기 전에 미리 치를 이유가 없다. `DataTable`의
|
|
148
|
+
props로 표현할 수 없는 테이블 모양이 필요한 두 번째 소비자가 나타나면 그때
|
|
149
|
+
프리미티브를 내보낸다.
|
|
150
|
+
|
|
151
|
+
클라이언트 페이징·필터링(TanStack Table의 `getPaginationRowModel` 등)도
|
|
152
|
+
마찬가지로 배선하지 않았다: 이 컴포넌트를 부르는 곳은 언제나 메모리에 다
|
|
153
|
+
올라가는 작은 목록(`sort="client"`)이거나 이미 페이지가 나뉜 서버 응답
|
|
154
|
+
(`page.nextHref`)이라, 그 기능은 발화할 일이 없이 모든 소비자의 번들에
|
|
155
|
+
얹히기만 할 것이다.
|
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# @devslab/dds-table
|
|
2
|
+
|
|
3
|
+
Declarative data table for DDS, built on TanStack Table (pinned to the exact
|
|
4
|
+
version `9.2.4` — see `docs/decisions.md` D-021 for why an exact pin). One
|
|
5
|
+
component, `DataTable`, plus the `Column<T>` and `DataTableLabels` types used
|
|
6
|
+
to describe it. The table itself decides nothing about words, routes, or
|
|
7
|
+
what "next page" means — every string a visitor can read is a prop.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pnpm add @devslab/dds-table
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This package ships no stylesheet of its own — import `@devslab/dds-css`'s
|
|
14
|
+
table styles once in the application shell, alongside the tokens CSS it
|
|
15
|
+
depends on:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import "@devslab/dds-tokens/tokens.css";
|
|
19
|
+
import "@devslab/dds-css/components/table.css";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Without it, `<DataTable>` renders an unstyled table: `fold` does nothing
|
|
23
|
+
(folding is entirely the CSS media query in `table.css`), and the
|
|
24
|
+
visually-hidden caption and actions-column header render visible.
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { DataTable, type Column, type DataTableLabels } from "@devslab/dds-table";
|
|
28
|
+
|
|
29
|
+
type Job = { id: string; name: string; count: number };
|
|
30
|
+
|
|
31
|
+
const columns: Column<Job>[] = [
|
|
32
|
+
{ id: "name", label: "Name", cell: (row) => row.name, sortBy: (row) => row.name, rowHeader: true },
|
|
33
|
+
{ id: "count", label: "Count", cell: (row) => String(row.count), sortBy: (row) => row.count, numeric: true, fold: true },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const labels: DataTableLabels = {
|
|
37
|
+
sortBy: "Sort by {column}",
|
|
38
|
+
actions: "Actions",
|
|
39
|
+
nextPage: "Next page",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
<DataTable rows={jobs} columns={columns} caption="Jobs" labels={labels} sort="client" />;
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## `DataTable` props
|
|
46
|
+
|
|
47
|
+
| Prop | Type | Required / default | Meaning |
|
|
48
|
+
| --- | --- | --- | --- |
|
|
49
|
+
| `rows` | `readonly T[]` | required | The data, in the order to render (see Sorting for who is responsible for that order). |
|
|
50
|
+
| `columns` | `readonly Column<T>[]` | required | Column declarations — see `Column<T>` below. |
|
|
51
|
+
| `caption` | `string` | required | The table's accessible name, rendered visually hidden (`<caption class="dds-visually-hidden">`). |
|
|
52
|
+
| `labels` | `DataTableLabels` | required | Every word the component can render — see "Labels are required" below. |
|
|
53
|
+
| `sort` | `"client" \| { statedOrder: string }` | optional, no sort buttons or order text when omitted | See Sorting below. |
|
|
54
|
+
| `density` | `"comfortable" \| "dense"` | optional, default `"comfortable"` (40px rows) | `"dense"` adds `.dds-table--dense` (36px rows, tighter cell padding). |
|
|
55
|
+
| `scroll` | `"auto" \| "tall"` | optional, default `"auto"` | `"tall"` adds `.dds-table-wrap--tall`: a `max-block-size: 70vh` scrolling body with a sticky header, for a long in-page list that shouldn't push the rest of the page down. |
|
|
56
|
+
| `minWidth` | `string` (a CSS length) | optional | Sets the `<table>`'s `min-inline-size`, so narrow viewports scroll the table horizontally (inside `.dds-table-wrap`) instead of crushing its columns. |
|
|
57
|
+
| `actions` | `(row: T) => JSX.Element` | optional | Renders a trailing cell per row (e.g. row-level buttons); adds a visually-hidden header cell from `labels.actions`. |
|
|
58
|
+
| `detail` | `(row: T) => JSX.Element` | optional | Renders an expandable row under a given row. Returning `null` (e.g. for a row that is not expanded) renders no detail `<tr>` for that row at all — not an empty one. |
|
|
59
|
+
| `page` | `{ nextHref?: string }` | optional | See Paging below. |
|
|
60
|
+
| `empty` | `JSX.Element` | optional | Rendered instead of the `<table>` when `rows` is empty. The stated-order text and the pagination link (if any) still render — an empty page of a cursor-paginated list still has an order and still needs a way forward. |
|
|
61
|
+
|
|
62
|
+
## `Column<T>`
|
|
63
|
+
|
|
64
|
+
| Field | Type | Meaning |
|
|
65
|
+
| --- | --- | --- |
|
|
66
|
+
| `id` | `string` | Stable column identity — used for the sort key and the `data-fold`/`data-column` attributes. |
|
|
67
|
+
| `label` | `string` | Header text (and the sort button's visible label). |
|
|
68
|
+
| `cell` | `(row: T) => JSX.Element` | Renders the cell body. Visual markup stays yours; the column def TanStack sees carries nothing but the sort accessor. |
|
|
69
|
+
| `sortBy?` | `(row: T) => string \| number \| null` | Present → the column is sortable (in `sort="client"` mode only) and gets a sort button. Absent → a plain header, never a button. Return `null` for "no value"; those rows sort last (`sortUndefined: "last"`), never first. |
|
|
70
|
+
| `width?` | `string` | A CSS width. Setting it on any column switches the whole table to `table-layout: fixed` and emits a `<colgroup>`. |
|
|
71
|
+
| `fold?` | `boolean` | Marks the column droppable on narrow viewports (see Folding below). |
|
|
72
|
+
| `numeric?` | `boolean` | Right-aligns the column and applies tabular figures. |
|
|
73
|
+
| `rowHeader?` | `boolean` | Renders this column's cell as `<th scope="row">` instead of `<td>` — exactly one column per table should set it. |
|
|
74
|
+
|
|
75
|
+
## Sorting: `sort`
|
|
76
|
+
|
|
77
|
+
`sort` accepts one of two shapes — this type is not exported (write the
|
|
78
|
+
values inline; there is nothing to import):
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
"client" | { statedOrder: string }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- **`sort="client"`** — the table holds its whole list in memory. Columns
|
|
85
|
+
with `sortBy` render a sort button; clicking one asks TanStack Table to
|
|
86
|
+
reorder the rows already in hand. This is safe precisely because "all the
|
|
87
|
+
rows" and "the rows shown" are the same set.
|
|
88
|
+
- **`sort={{ statedOrder: "…" }}`** — for a table that shows a server-ordered,
|
|
89
|
+
cursor-paged slice. No column renders a sort button in this mode, even if
|
|
90
|
+
its `sortBy` is set: a client-side sort could only reorder the rows on the
|
|
91
|
+
current page, while the table's real order is whatever the backend query
|
|
92
|
+
produced across pages the browser has never seen. A button that did that
|
|
93
|
+
would look like it sorted the data and would actually misreport it. Instead
|
|
94
|
+
the table prints the actual order as text above itself (`.dds-table__order`)
|
|
95
|
+
— `statedOrder` is that sentence, e.g. `"Newest first"`, supplied by the
|
|
96
|
+
consumer because DDS does not know the backend's ordering vocabulary.
|
|
97
|
+
|
|
98
|
+
There is no third mode that lets a server-ordered table opt into client
|
|
99
|
+
sorting for "just this column" — the failure mode (silently reporting a
|
|
100
|
+
per-page order as the whole list's order) is the same regardless of how many
|
|
101
|
+
columns are involved.
|
|
102
|
+
|
|
103
|
+
## Paging: `page`
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
page?: { nextHref?: string }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`nextHref` renders the next-page control as `<a class="dds-btn dds-btn--secondary" href="…">`, wrapped in a labeled `<nav>` — never a `<button onClick>`. A cursor-paginated list is just a URL with a different query string, and a real link keeps that working with JavaScript disabled, on a slow connection before hydration, and in a browser's native "open in new tab". Omitting `nextHref` (or the whole `page` prop) hides the pagination `<nav>` entirely rather than rendering a disabled control.
|
|
110
|
+
|
|
111
|
+
## Folding: `fold`
|
|
112
|
+
|
|
113
|
+
Columns marked `fold: true` disappear below a fixed breakpoint
|
|
114
|
+
(`@media (max-width: 56.25rem)` in `dds-css`'s `table.css`) via a plain CSS
|
|
115
|
+
rule on `[data-fold]` — there is no JavaScript column-visibility state, no
|
|
116
|
+
resize observer, and no per-viewport re-render. The column is always present
|
|
117
|
+
in the DOM; the browser decides whether to paint it. This means folding
|
|
118
|
+
survives SSR (a server-rendered narrow viewport already hides the column,
|
|
119
|
+
correctly, before any script runs) and costs nothing to keep in sync with
|
|
120
|
+
sorting or paging state, because there is no state to keep in sync.
|
|
121
|
+
|
|
122
|
+
## Labels are required, not defaulted
|
|
123
|
+
|
|
124
|
+
`DataTableLabels` has no optional fields and `DataTable` ships no fallback
|
|
125
|
+
strings:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
type DataTableLabels = {
|
|
129
|
+
sortBy: string; // "{column}" is replaced with the column's label
|
|
130
|
+
actions: string; // header of the trailing actions column (visually hidden)
|
|
131
|
+
nextPage: string; // accessible name and text of the next-page link
|
|
132
|
+
};
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
DDS does not choose the language a consumer's users read in, so it does not
|
|
136
|
+
ship English (or any other) copy for a screen reader to announce. A consumer
|
|
137
|
+
that forgets a label gets a TypeScript error, not a silently English or
|
|
138
|
+
silently blank control.
|
|
139
|
+
|
|
140
|
+
## What this package does not export
|
|
141
|
+
|
|
142
|
+
`DataTable` is the only component. The row/cell primitives TanStack Table's
|
|
143
|
+
own docs build tables from (a `Th`, a `Td`, a `useDataTable` hook) are
|
|
144
|
+
deliberately unexported — there is exactly one consumer today, and a second
|
|
145
|
+
API surface to keep stable is a cost paid before anything needs it. When a
|
|
146
|
+
second consumer needs a table shape `DataTable`'s props cannot express,
|
|
147
|
+
export the primitives then.
|
|
148
|
+
|
|
149
|
+
Client-side pagination and filtering (TanStack Table's `getPaginationRowModel`
|
|
150
|
+
et al.) are similarly not wired in: this component's callers are always
|
|
151
|
+
either a small in-memory list (`sort="client"`) or an already-paged server
|
|
152
|
+
response (`page.nextHref`), so neither feature would ever fire — it would only
|
|
153
|
+
sit in every consumer's bundle.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { JSX } from "solid-js";
|
|
2
|
+
import { createSortedRowModel, sortFn_alphanumeric, sortFn_text, type ColumnDef } from "@tanstack/solid-table";
|
|
3
|
+
export type Column<T> = {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
cell: (row: T) => JSX.Element;
|
|
7
|
+
sortBy?: (row: T) => string | number | null;
|
|
8
|
+
width?: string;
|
|
9
|
+
fold?: boolean;
|
|
10
|
+
numeric?: boolean;
|
|
11
|
+
rowHeader?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type DataTableLabels = {
|
|
14
|
+
/** Accessible name for a sort button; `{column}` is replaced with the column label. */
|
|
15
|
+
sortBy: string;
|
|
16
|
+
/** Header of the trailing actions column, rendered visually hidden. */
|
|
17
|
+
actions: string;
|
|
18
|
+
/** Label of the next-page link. */
|
|
19
|
+
nextPage: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The feature set every `DataTable` instance is built from: the core row
|
|
23
|
+
* model plus client-side sorting. Built once (per `tableFeatures`'
|
|
24
|
+
* recommendation to use it statically outside a component) so `toColumnDefs`
|
|
25
|
+
* and `createTable` agree on the same `TFeatures` type.
|
|
26
|
+
*/
|
|
27
|
+
declare const baseFeatures: {
|
|
28
|
+
coreTablesFeature: import("@tanstack/solid-table").TableFeature;
|
|
29
|
+
coreRowsFeature: import("@tanstack/solid-table").TableFeature;
|
|
30
|
+
coreColumnsFeature: import("@tanstack/solid-table").TableFeature;
|
|
31
|
+
coreHeadersFeature: import("@tanstack/solid-table").TableFeature;
|
|
32
|
+
coreCellsFeature: import("@tanstack/solid-table").TableFeature;
|
|
33
|
+
coreRowModelsFeature: import("@tanstack/solid-table").TableFeature;
|
|
34
|
+
rowSortingFeature: import("@tanstack/solid-table").TableFeature;
|
|
35
|
+
};
|
|
36
|
+
/** The `TFeatures` type used everywhere a table/column type needs one. Kept
|
|
37
|
+
* separate from the `sortedRowModel` factory below: `createSortedRowModel`'s
|
|
38
|
+
* return type embeds `Table<TFeatures, TData>`, so folding it into the very
|
|
39
|
+
* type it closes over makes `TFeatures` self-referential — TypeScript's
|
|
40
|
+
* structural comparison of that recursive shape (observed while wiring this
|
|
41
|
+
* up) reports unrelated `ColumnDef`/`Column`/`HeaderContext` instantiations
|
|
42
|
+
* a few frames down a completely unrelated diff, because it can't resolve
|
|
43
|
+
* the cycle. Naming the narrower, non-recursive type here and using it as
|
|
44
|
+
* the explicit `TFeatures` argument everywhere avoids that. */
|
|
45
|
+
export type TableFeatureSet = typeof baseFeatures;
|
|
46
|
+
/**
|
|
47
|
+
* Registering `rowSortingFeature` alone is not enough for sorting to reach
|
|
48
|
+
* the screen — `sortedRowModel` is the factory `table.getRowModel()` actually
|
|
49
|
+
* calls to produce sorted rows; without it, `state.sorting` changes but the
|
|
50
|
+
* rendered row order never does. Added here, after `TableFeatureSet` is
|
|
51
|
+
* already named, so its function type closes over the narrow type instead of
|
|
52
|
+
* over itself.
|
|
53
|
+
*
|
|
54
|
+
* `sortFns` registers the names `sortFn: "auto"` (the default every column
|
|
55
|
+
* gets — see `toColumnDefs`) can actually resolve to for a `Column<T>` whose
|
|
56
|
+
* `sortBy` returns `string | number | null`: plain strings resolve to
|
|
57
|
+
* `"text"`, strings containing digit runs (`"Row 10"`, `"SKU100"`) resolve to
|
|
58
|
+
* `"alphanumeric"`, and numbers/`null` never set a name at all and fall
|
|
59
|
+
* straight to the always-available `sortFn_basic` — so `"datetime"` is never
|
|
60
|
+
* reachable and is deliberately not registered. Leaving either reachable name
|
|
61
|
+
* unregistered means `"auto"` silently falls back to `sortFn_basic`, which
|
|
62
|
+
* compares raw values instead of lowercasing first: a case-sensitive sort
|
|
63
|
+
* that also warns on every column in development
|
|
64
|
+
* (`rowSortingFeature.utils.js`'s `column_getAutoSortFn`). Importing the two
|
|
65
|
+
* named functions (rather than the `sortFns` barrel export, whose own
|
|
66
|
+
* docstring says registering it "opts out of tree-shaking") keeps every
|
|
67
|
+
* other built-in sorting function — including the case-sensitive and
|
|
68
|
+
* datetime variants this component never produces — out of the bundle.
|
|
69
|
+
*/
|
|
70
|
+
export declare const tableFeatureSet: TableFeatureSet & {
|
|
71
|
+
sortedRowModel: ReturnType<typeof createSortedRowModel<TableFeatureSet, Record<string, unknown>>>;
|
|
72
|
+
sortFns: {
|
|
73
|
+
text: typeof sortFn_text;
|
|
74
|
+
alphanumeric: typeof sortFn_alphanumeric;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
/** Turns our declarations into TanStack column defs. Sorting is enabled per
|
|
78
|
+
* column by the presence of `sortBy`; everything visual stays in our own
|
|
79
|
+
* markup, so the def carries only what the model needs.
|
|
80
|
+
*
|
|
81
|
+
* `Column<T>` deliberately leaves `T` unconstrained (any row shape a
|
|
82
|
+
* consumer wants to render), but TanStack's `RowData` requires
|
|
83
|
+
* `Record<string, any> | Array<any>`. Every real row is one of those at
|
|
84
|
+
* runtime, so the helper is instantiated at `Record<string, unknown>` and
|
|
85
|
+
* the accessor casts its parameter back to `T` — a boundary cast, not a
|
|
86
|
+
* behavior change. */
|
|
87
|
+
export declare function toColumnDefs<T>(columns: readonly Column<T>[]): ColumnDef<TableFeatureSet, Record<string, unknown>, unknown>[];
|
|
88
|
+
export {};
|
|
89
|
+
//# sourceMappingURL=columns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columns.d.ts","sourceRoot":"","sources":["../src/columns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAQL,oBAAoB,EAEpB,mBAAmB,EACnB,WAAW,EAEX,KAAK,SAAS,EACf,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC;IAC9B,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,uFAAuF;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,YAAY;;;;;;;;CAQhB,CAAC;AAEH;;;;;;;;gEAQgE;AAChE,MAAM,MAAM,eAAe,GAAG,OAAO,YAAY,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,eAAe,EAAE,eAAe,GAAG;IAC9C,cAAc,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAClG,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,WAAW,CAAC;QAAC,YAAY,EAAE,OAAO,mBAAmB,CAAA;KAAE,CAAC;CAKjF,CAAC;AAEF;;;;;;;;;uBASuB;AACvB,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,CAsB7H"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type JSX } from "solid-js";
|
|
2
|
+
import { type Column, type DataTableLabels } from "./columns";
|
|
3
|
+
export type SortMode = "client" | {
|
|
4
|
+
statedOrder: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function DataTable<T>(props: {
|
|
7
|
+
rows: readonly T[];
|
|
8
|
+
columns: readonly Column<T>[];
|
|
9
|
+
caption: string;
|
|
10
|
+
labels: DataTableLabels;
|
|
11
|
+
sort?: SortMode;
|
|
12
|
+
density?: "comfortable" | "dense";
|
|
13
|
+
scroll?: "auto" | "tall";
|
|
14
|
+
minWidth?: string;
|
|
15
|
+
actions?: (row: T) => JSX.Element;
|
|
16
|
+
detail?: (row: T) => JSX.Element;
|
|
17
|
+
page?: {
|
|
18
|
+
nextHref?: string | undefined;
|
|
19
|
+
};
|
|
20
|
+
empty?: JSX.Element;
|
|
21
|
+
}): JSX.Element;
|
|
22
|
+
//# sourceMappingURL=data-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../src/data-table.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,GAAG,EAAE,MAAM,UAAU,CAAC;AAE3D,OAAO,EAAiC,KAAK,MAAM,EAAE,KAAK,eAAe,EAAwB,MAAM,WAAW,CAAC;AAEnH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAW1D,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE;IAClC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;IACnB,OAAO,EAAE,SAAS,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC;IAClC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC;IACjC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACzC,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CACrB,GAAG,GAAG,CAAC,OAAO,CA4Gd"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { className as e, createComponent as t, delegateEvents as n, effect as r, getNextElement as i, getNextMarker as a, insert as o, memo as s, runHydrationEvents as c, setAttribute as l, setProperty as u, style as d, template as f } from "solid-js/web";
|
|
2
|
+
import { For as p, Show as m, createMemo as h } from "solid-js";
|
|
3
|
+
import { coreCellsFeature as g, coreColumnsFeature as _, coreHeadersFeature as v, coreRowModelsFeature as y, coreRowsFeature as b, coreTablesFeature as x, createColumnHelper as S, createSortedRowModel as C, createTable as w, rowSortingFeature as T, sortFn_alphanumeric as E, sortFn_text as D, tableFeatures as O } from "@tanstack/solid-table";
|
|
4
|
+
var k = {
|
|
5
|
+
...O({
|
|
6
|
+
coreTablesFeature: x,
|
|
7
|
+
coreRowsFeature: b,
|
|
8
|
+
coreColumnsFeature: _,
|
|
9
|
+
coreHeadersFeature: v,
|
|
10
|
+
coreCellsFeature: g,
|
|
11
|
+
coreRowModelsFeature: y,
|
|
12
|
+
rowSortingFeature: T
|
|
13
|
+
}),
|
|
14
|
+
sortedRowModel: C(),
|
|
15
|
+
sortFns: {
|
|
16
|
+
text: D,
|
|
17
|
+
alphanumeric: E
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
function A(e) {
|
|
21
|
+
let t = S();
|
|
22
|
+
return e.map((e) => t.accessor((t) => e.sortBy ? e.sortBy(t) ?? void 0 : void 0, {
|
|
23
|
+
id: e.id,
|
|
24
|
+
enableSorting: !!e.sortBy,
|
|
25
|
+
sortUndefined: "last"
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/data-table.tsx
|
|
30
|
+
var j = /*#__PURE__*/ f("<col>"), M = /*#__PURE__*/ f("<colgroup><!$><!/><!$><!/>"), N = /*#__PURE__*/ f("<th scope=col><span class=dds-visually-hidden>"), P = /*#__PURE__*/ f("<div><table><caption class=dds-visually-hidden></caption><!$><!/><thead><tr><!$><!/><!$><!/></tr></thead><tbody>"), F = /*#__PURE__*/ f("<nav class=dds-table__pagination>"), I = /*#__PURE__*/ f("<p class=dds-table__order>"), L = /*#__PURE__*/ f("<button type=button class=dds-table__sort data-action=sort><!$><!/><span class=dds-table__sort-mark aria-hidden=true>"), R = /*#__PURE__*/ f("<th scope=col>"), z = /*#__PURE__*/ f("<tr><!$><!/><!$><!/>"), B = /*#__PURE__*/ f("<th scope=row>"), V = /*#__PURE__*/ f("<td>"), H = /*#__PURE__*/ f("<td><div class=dds-table__actions>"), U = /*#__PURE__*/ f("<tr><td>"), W = /*#__PURE__*/ f("<a class=\"dds-btn dds-btn--secondary\">");
|
|
31
|
+
function G(e, t) {
|
|
32
|
+
return e.replace("{column}", () => t);
|
|
33
|
+
}
|
|
34
|
+
function K(n) {
|
|
35
|
+
let f = () => n.sort === "client", g = () => typeof n.sort == "object" ? n.sort.statedOrder : void 0, _ = () => n.columns.some((e) => e.width !== void 0), v = h(() => A(n.columns)), y = w({
|
|
36
|
+
features: k,
|
|
37
|
+
get data() {
|
|
38
|
+
return n.rows;
|
|
39
|
+
},
|
|
40
|
+
get columns() {
|
|
41
|
+
return v();
|
|
42
|
+
},
|
|
43
|
+
enableSorting: !0
|
|
44
|
+
}), b = h(() => f() ? y.getRowModel().rows.map((e) => e.original) : [...n.rows]), x = (e) => {
|
|
45
|
+
let t = y.store.state.sorting?.[0];
|
|
46
|
+
return !t || t.id !== e ? "none" : t.desc ? "descending" : "ascending";
|
|
47
|
+
};
|
|
48
|
+
return [
|
|
49
|
+
t(m, {
|
|
50
|
+
get when() {
|
|
51
|
+
return g();
|
|
52
|
+
},
|
|
53
|
+
children: (e) => (() => {
|
|
54
|
+
var t = i(I);
|
|
55
|
+
return o(t, e), t;
|
|
56
|
+
})()
|
|
57
|
+
}),
|
|
58
|
+
t(m, {
|
|
59
|
+
get when() {
|
|
60
|
+
return n.rows.length > 0;
|
|
61
|
+
},
|
|
62
|
+
get fallback() {
|
|
63
|
+
return n.empty;
|
|
64
|
+
},
|
|
65
|
+
get children() {
|
|
66
|
+
var u = i(P), h = u.firstChild, g = h.firstChild, v = g.nextSibling, [S, C] = a(v.nextSibling), w = S.nextSibling, T = w.firstChild, E = T.firstChild, [D, O] = a(E.nextSibling), k = D.nextSibling, [A, F] = a(k.nextSibling), I = w.nextSibling;
|
|
67
|
+
return o(g, () => n.caption), o(h, t(m, {
|
|
68
|
+
get when() {
|
|
69
|
+
return _();
|
|
70
|
+
},
|
|
71
|
+
get children() {
|
|
72
|
+
var e = i(M), s = e.firstChild, [c, u] = a(s.nextSibling), f = c.nextSibling, [h, g] = a(f.nextSibling);
|
|
73
|
+
return o(e, t(p, {
|
|
74
|
+
get each() {
|
|
75
|
+
return n.columns;
|
|
76
|
+
},
|
|
77
|
+
children: (e) => (() => {
|
|
78
|
+
var t = i(j);
|
|
79
|
+
return r((n) => {
|
|
80
|
+
var r = e.fold ? "" : void 0, i = e.width ? { width: e.width } : void 0;
|
|
81
|
+
return r !== n.e && l(t, "data-fold", n.e = r), n.t = d(t, i, n.t), n;
|
|
82
|
+
}, {
|
|
83
|
+
e: void 0,
|
|
84
|
+
t: void 0
|
|
85
|
+
}), t;
|
|
86
|
+
})()
|
|
87
|
+
}), c, u), o(e, t(m, {
|
|
88
|
+
get when() {
|
|
89
|
+
return n.actions;
|
|
90
|
+
},
|
|
91
|
+
get children() {
|
|
92
|
+
return i(j);
|
|
93
|
+
}
|
|
94
|
+
}), h, g), e;
|
|
95
|
+
}
|
|
96
|
+
}), S, C), o(T, t(p, {
|
|
97
|
+
get each() {
|
|
98
|
+
return n.columns;
|
|
99
|
+
},
|
|
100
|
+
children: (e) => (() => {
|
|
101
|
+
var u = i(R);
|
|
102
|
+
return o(u, t(m, {
|
|
103
|
+
get when() {
|
|
104
|
+
return s(() => !!f())() && e.sortBy;
|
|
105
|
+
},
|
|
106
|
+
get fallback() {
|
|
107
|
+
return e.label;
|
|
108
|
+
},
|
|
109
|
+
get children() {
|
|
110
|
+
var t = i(L), s = t.firstChild, [u, d] = a(s.nextSibling), f = u.nextSibling;
|
|
111
|
+
return t.$$click = () => y.getColumn(e.id)?.toggleSorting(), o(t, () => e.label, u, d), r((r) => {
|
|
112
|
+
var i = G(n.labels.sortBy, e.label), a = x(e.id);
|
|
113
|
+
return i !== r.e && l(t, "aria-label", r.e = i), a !== r.t && l(f, "data-sort-state", r.t = a), r;
|
|
114
|
+
}, {
|
|
115
|
+
e: void 0,
|
|
116
|
+
t: void 0
|
|
117
|
+
}), c(), t;
|
|
118
|
+
}
|
|
119
|
+
})), r((t) => {
|
|
120
|
+
var n = e.id, r = e.fold ? "" : void 0, i = e.numeric ? "" : void 0, a = f() && e.sortBy ? x(e.id) : void 0;
|
|
121
|
+
return n !== t.e && l(u, "data-column", t.e = n), r !== t.t && l(u, "data-fold", t.t = r), i !== t.a && l(u, "data-numeric", t.a = i), a !== t.o && l(u, "aria-sort", t.o = a), t;
|
|
122
|
+
}, {
|
|
123
|
+
e: void 0,
|
|
124
|
+
t: void 0,
|
|
125
|
+
a: void 0,
|
|
126
|
+
o: void 0
|
|
127
|
+
}), u;
|
|
128
|
+
})()
|
|
129
|
+
}), D, O), o(T, t(m, {
|
|
130
|
+
get when() {
|
|
131
|
+
return n.actions;
|
|
132
|
+
},
|
|
133
|
+
get children() {
|
|
134
|
+
var e = i(N), t = e.firstChild;
|
|
135
|
+
return o(t, () => n.labels.actions), e;
|
|
136
|
+
}
|
|
137
|
+
}), A, F), o(I, t(p, {
|
|
138
|
+
get each() {
|
|
139
|
+
return b();
|
|
140
|
+
},
|
|
141
|
+
children: (e) => [(() => {
|
|
142
|
+
var s = i(z), c = s.firstChild, [u, d] = a(c.nextSibling), f = u.nextSibling, [h, g] = a(f.nextSibling);
|
|
143
|
+
return o(s, t(p, {
|
|
144
|
+
get each() {
|
|
145
|
+
return n.columns;
|
|
146
|
+
},
|
|
147
|
+
children: (n) => t(m, {
|
|
148
|
+
get when() {
|
|
149
|
+
return n.rowHeader;
|
|
150
|
+
},
|
|
151
|
+
get fallback() {
|
|
152
|
+
return (() => {
|
|
153
|
+
var t = i(V);
|
|
154
|
+
return o(t, () => n.cell(e)), r((e) => {
|
|
155
|
+
var r = n.fold ? "" : void 0, i = n.numeric ? "" : void 0;
|
|
156
|
+
return r !== e.e && l(t, "data-fold", e.e = r), i !== e.t && l(t, "data-numeric", e.t = i), e;
|
|
157
|
+
}, {
|
|
158
|
+
e: void 0,
|
|
159
|
+
t: void 0
|
|
160
|
+
}), t;
|
|
161
|
+
})();
|
|
162
|
+
},
|
|
163
|
+
get children() {
|
|
164
|
+
var t = i(B);
|
|
165
|
+
return o(t, () => n.cell(e)), r((e) => {
|
|
166
|
+
var r = n.fold ? "" : void 0, i = n.numeric ? "" : void 0;
|
|
167
|
+
return r !== e.e && l(t, "data-fold", e.e = r), i !== e.t && l(t, "data-numeric", e.t = i), e;
|
|
168
|
+
}, {
|
|
169
|
+
e: void 0,
|
|
170
|
+
t: void 0
|
|
171
|
+
}), t;
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
}), u, d), o(s, t(m, {
|
|
175
|
+
get when() {
|
|
176
|
+
return n.actions;
|
|
177
|
+
},
|
|
178
|
+
children: (t) => (() => {
|
|
179
|
+
var n = i(H), r = n.firstChild;
|
|
180
|
+
return o(r, () => t()(e)), n;
|
|
181
|
+
})()
|
|
182
|
+
}), h, g), s;
|
|
183
|
+
})(), t(m, {
|
|
184
|
+
get when() {
|
|
185
|
+
return n.detail?.(e);
|
|
186
|
+
},
|
|
187
|
+
children: (e) => (() => {
|
|
188
|
+
var t = i(U), a = t.firstChild;
|
|
189
|
+
return o(a, e), r(() => l(a, "colspan", n.columns.length + +!!n.actions)), t;
|
|
190
|
+
})()
|
|
191
|
+
})]
|
|
192
|
+
})), r((t) => {
|
|
193
|
+
var r = n.scroll === "tall" ? "dds-table-wrap dds-table-wrap--tall" : "dds-table-wrap", i = `dds-table${n.density === "dense" ? " dds-table--dense" : ""}${_() ? " dds-table--fixed" : ""}`, a = n.minWidth ? { "min-inline-size": n.minWidth } : void 0;
|
|
194
|
+
return r !== t.e && e(u, t.e = r), i !== t.t && e(h, t.t = i), t.a = d(h, a, t.a), t;
|
|
195
|
+
}, {
|
|
196
|
+
e: void 0,
|
|
197
|
+
t: void 0,
|
|
198
|
+
a: void 0
|
|
199
|
+
}), u;
|
|
200
|
+
}
|
|
201
|
+
}),
|
|
202
|
+
(() => {
|
|
203
|
+
var e = i(F);
|
|
204
|
+
return o(e, t(m, {
|
|
205
|
+
get when() {
|
|
206
|
+
return n.page?.nextHref;
|
|
207
|
+
},
|
|
208
|
+
children: (e) => (() => {
|
|
209
|
+
var t = i(W);
|
|
210
|
+
return o(t, () => n.labels.nextPage), r(() => l(t, "href", e())), t;
|
|
211
|
+
})()
|
|
212
|
+
})), r((t) => {
|
|
213
|
+
var r = !n.page?.nextHref, i = n.labels.nextPage;
|
|
214
|
+
return r !== t.e && u(e, "hidden", t.e = r), i !== t.t && l(e, "aria-label", t.t = i), t;
|
|
215
|
+
}, {
|
|
216
|
+
e: void 0,
|
|
217
|
+
t: void 0
|
|
218
|
+
}), e;
|
|
219
|
+
})()
|
|
220
|
+
];
|
|
221
|
+
}
|
|
222
|
+
n(["click"]);
|
|
223
|
+
//#endregion
|
|
224
|
+
export { K as DataTable };
|
|
225
|
+
|
|
226
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["createMemo","For","Show","JSX","createTable","tableFeatureSet","toColumnDefs","Column","DataTableLabels","TableFeatureSet","SortMode","statedOrder","fillLabel","template","value","replace","DataTable","props","rows","T","columns","caption","labels","sort","density","scroll","minWidth","actions","row","Element","detail","page","nextHref","empty","clientSorted","undefined","fixed","some","column","width","columnDefs","table","Record","features","data","enableSorting","ordered","getRowModel","map","original","sortState","id","current","store","state","sorting","desc","_$createComponent","when","children","order","_el$20","_$getNextElement","_tmpl$6","_$insert","length","fallback","_el$","_tmpl$4","_el$2","firstChild","_el$3","_el$17","nextSibling","_el$18","_co$5","_$getNextMarker","_el$0","_el$1","_el$12","_el$13","_co$3","_el$14","_el$15","_co$4","_el$16","_el$4","_tmpl$2","_el$6","_el$7","_co$","_el$8","_el$9","_co$2","each","_el$21","_tmpl$","_$effect","_p$","_v$6","fold","_v$7","e","_$setAttribute","t","_$style","_el$22","_tmpl$8","_$memo","sortBy","label","_el$23","_tmpl$7","_el$25","_el$26","_co$6","_el$24","$$click","getColumn","toggleSorting","_v$8","_v$9","_$runHydrationEvents","_v$0","_v$1","_v$10","numeric","_v$11","a","o","_el$10","_tmpl$3","_el$11","_el$27","_tmpl$9","_el$28","_el$29","_co$7","_el$30","_el$31","_co$8","rowHeader","_el$33","_tmpl$1","cell","_v$14","_v$15","_el$32","_tmpl$0","_v$12","_v$13","_el$34","_tmpl$10","_el$35","node","_el$36","_tmpl$11","_el$37","_v$","_v$2","_v$3","_$className","_el$19","_tmpl$5","href","_el$38","_tmpl$12","nextPage","_v$4","_v$5","_$setProperty","_$delegateEvents"],"sources":["../src/columns.ts","../src/data-table.tsx"],"sourcesContent":["import type { JSX } from \"solid-js\";\nimport {\n coreCellsFeature,\n coreColumnsFeature,\n coreHeadersFeature,\n coreRowModelsFeature,\n coreRowsFeature,\n coreTablesFeature,\n createColumnHelper,\n createSortedRowModel,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n type ColumnDef,\n} from \"@tanstack/solid-table\";\n\nexport type Column<T> = {\n id: string;\n label: string;\n cell: (row: T) => JSX.Element;\n sortBy?: (row: T) => string | number | null;\n width?: string;\n fold?: boolean;\n numeric?: boolean;\n rowHeader?: boolean;\n};\n\nexport type DataTableLabels = {\n /** Accessible name for a sort button; `{column}` is replaced with the column label. */\n sortBy: string;\n /** Header of the trailing actions column, rendered visually hidden. */\n actions: string;\n /** Label of the next-page link. */\n nextPage: string;\n};\n\n/**\n * The feature set every `DataTable` instance is built from: the core row\n * model plus client-side sorting. Built once (per `tableFeatures`'\n * recommendation to use it statically outside a component) so `toColumnDefs`\n * and `createTable` agree on the same `TFeatures` type.\n */\nconst baseFeatures = tableFeatures({\n coreTablesFeature,\n coreRowsFeature,\n coreColumnsFeature,\n coreHeadersFeature,\n coreCellsFeature,\n coreRowModelsFeature,\n rowSortingFeature,\n});\n\n/** The `TFeatures` type used everywhere a table/column type needs one. Kept\n * separate from the `sortedRowModel` factory below: `createSortedRowModel`'s\n * return type embeds `Table<TFeatures, TData>`, so folding it into the very\n * type it closes over makes `TFeatures` self-referential — TypeScript's\n * structural comparison of that recursive shape (observed while wiring this\n * up) reports unrelated `ColumnDef`/`Column`/`HeaderContext` instantiations\n * a few frames down a completely unrelated diff, because it can't resolve\n * the cycle. Naming the narrower, non-recursive type here and using it as\n * the explicit `TFeatures` argument everywhere avoids that. */\nexport type TableFeatureSet = typeof baseFeatures;\n\n/**\n * Registering `rowSortingFeature` alone is not enough for sorting to reach\n * the screen — `sortedRowModel` is the factory `table.getRowModel()` actually\n * calls to produce sorted rows; without it, `state.sorting` changes but the\n * rendered row order never does. Added here, after `TableFeatureSet` is\n * already named, so its function type closes over the narrow type instead of\n * over itself.\n *\n * `sortFns` registers the names `sortFn: \"auto\"` (the default every column\n * gets — see `toColumnDefs`) can actually resolve to for a `Column<T>` whose\n * `sortBy` returns `string | number | null`: plain strings resolve to\n * `\"text\"`, strings containing digit runs (`\"Row 10\"`, `\"SKU100\"`) resolve to\n * `\"alphanumeric\"`, and numbers/`null` never set a name at all and fall\n * straight to the always-available `sortFn_basic` — so `\"datetime\"` is never\n * reachable and is deliberately not registered. Leaving either reachable name\n * unregistered means `\"auto\"` silently falls back to `sortFn_basic`, which\n * compares raw values instead of lowercasing first: a case-sensitive sort\n * that also warns on every column in development\n * (`rowSortingFeature.utils.js`'s `column_getAutoSortFn`). Importing the two\n * named functions (rather than the `sortFns` barrel export, whose own\n * docstring says registering it \"opts out of tree-shaking\") keeps every\n * other built-in sorting function — including the case-sensitive and\n * datetime variants this component never produces — out of the bundle.\n */\nexport const tableFeatureSet: TableFeatureSet & {\n sortedRowModel: ReturnType<typeof createSortedRowModel<TableFeatureSet, Record<string, unknown>>>;\n sortFns: { text: typeof sortFn_text; alphanumeric: typeof sortFn_alphanumeric };\n} = {\n ...baseFeatures,\n sortedRowModel: createSortedRowModel<TableFeatureSet, Record<string, unknown>>(),\n sortFns: { text: sortFn_text, alphanumeric: sortFn_alphanumeric },\n};\n\n/** Turns our declarations into TanStack column defs. Sorting is enabled per\n * column by the presence of `sortBy`; everything visual stays in our own\n * markup, so the def carries only what the model needs.\n *\n * `Column<T>` deliberately leaves `T` unconstrained (any row shape a\n * consumer wants to render), but TanStack's `RowData` requires\n * `Record<string, any> | Array<any>`. Every real row is one of those at\n * runtime, so the helper is instantiated at `Record<string, unknown>` and\n * the accessor casts its parameter back to `T` — a boundary cast, not a\n * behavior change. */\nexport function toColumnDefs<T>(columns: readonly Column<T>[]): ColumnDef<TableFeatureSet, Record<string, unknown>, unknown>[] {\n const helper = createColumnHelper<TableFeatureSet, Record<string, unknown>>();\n return columns.map((column) =>\n // `TValue` is invariant on `ColumnDef` (it shows up contravariantly via\n // `footer`'s `HeaderContext`, covariantly via `accessorFn`'s return), so\n // a heterogeneous array of columns can only be typed uniformly at\n // `unknown` — the array element type `ColumnDef<..., unknown>` is not a\n // supertype of `ColumnDef<..., string | number | null>`. The return type\n // annotation below is what makes TanStack infer `TValue = unknown`\n // instead of narrowing to the ternary's actual `string | number | null`.\n //\n // `?? undefined` is the adapter boundary translating our declared\n // contract (`sortBy` returns `null` for \"no value\") into TanStack's:\n // `createSortedRowModel`'s comparator only consults `sortUndefined`\n // after testing `=== void 0`, so a bare `null` would never trigger it —\n // `sortUndefined: \"last\"` would be a promise the code doesn't keep.\n helper.accessor((row): unknown => (column.sortBy ? column.sortBy(row as T) ?? undefined : undefined), {\n id: column.id,\n enableSorting: Boolean(column.sortBy),\n sortUndefined: \"last\",\n }),\n );\n}\n","import { createMemo, For, Show, type JSX } from \"solid-js\";\nimport { createTable } from \"@tanstack/solid-table\";\nimport { tableFeatureSet, toColumnDefs, type Column, type DataTableLabels, type TableFeatureSet } from \"./columns\";\n\nexport type SortMode = \"client\" | { statedOrder: string };\n\n/** Fills the `{column}` placeholder in a consumer-supplied label template.\n * A function replacer, not `template.replace(\"{column}\", value)` — a\n * string replacement value is subject to special `$&`/`$$`/`` $` ``/`$'`\n * patterns, and this console has currency columns whose labels can contain\n * a literal `$`. */\nfunction fillLabel(template: string, value: string): string {\n return template.replace(\"{column}\", () => value);\n}\n\nexport function DataTable<T>(props: {\n rows: readonly T[];\n columns: readonly Column<T>[];\n caption: string;\n labels: DataTableLabels;\n sort?: SortMode;\n density?: \"comfortable\" | \"dense\";\n scroll?: \"auto\" | \"tall\";\n minWidth?: string;\n actions?: (row: T) => JSX.Element;\n detail?: (row: T) => JSX.Element;\n page?: { nextHref?: string | undefined };\n empty?: JSX.Element;\n}): JSX.Element {\n const clientSorted = () => props.sort === \"client\";\n const statedOrder = () => (typeof props.sort === \"object\" ? props.sort.statedOrder : undefined);\n const fixed = () => props.columns.some((column) => column.width !== undefined);\n\n /* `toColumnDefs` builds fresh column objects on every read; a table model\n that sees a new column identity on every access can lose sorting state\n or re-render in a loop, so the defs are memoized on `props.columns`. */\n const columnDefs = createMemo(() => toColumnDefs(props.columns));\n\n /* TanStack's `RowData` requires `Record<string, any> | Array<any>`, which\n an unconstrained `T` can't satisfy structurally. Every row is one of\n those at runtime, so the table is instantiated at `Record<string,\n unknown>` and cast back to `T` where rows come back out (in `ordered`). */\n const table = createTable<TableFeatureSet, Record<string, unknown>>({\n features: tableFeatureSet,\n get data() { return props.rows as readonly Record<string, unknown>[]; },\n get columns() { return columnDefs(); },\n enableSorting: true,\n });\n\n /* The model sorts; our own markup renders. A server-ordered table never\n reaches this path — `sort` is then an object and no header is a button. */\n const ordered = createMemo(() => (clientSorted() ? table.getRowModel().rows.map((row) => row.original as T) : [...props.rows]));\n\n const sortState = (id: string) => {\n const current = table.store.state.sorting?.[0];\n if (!current || current.id !== id) return \"none\";\n return current.desc ? \"descending\" : \"ascending\";\n };\n\n return (\n <>\n {/* The stated order and the pagination link are not part of the \"is\n there a table to show\" question — a cursor-paged list can land on\n an empty page and still needs to say what order it was in and\n offer a way forward. Only the table itself (and its wrap) falls\n back to `empty` when there are no rows. */}\n <Show when={statedOrder()}>{(order) => <p class=\"dds-table__order\">{order()}</p>}</Show>\n <Show when={props.rows.length > 0} fallback={props.empty}>\n <div class={props.scroll === \"tall\" ? \"dds-table-wrap dds-table-wrap--tall\" : \"dds-table-wrap\"}>\n <table\n class={`dds-table${props.density === \"dense\" ? \" dds-table--dense\" : \"\"}${fixed() ? \" dds-table--fixed\" : \"\"}`}\n style={props.minWidth ? { \"min-inline-size\": props.minWidth } : undefined}\n >\n <caption class=\"dds-visually-hidden\">{props.caption}</caption>\n <Show when={fixed()}>\n <colgroup>\n <For each={props.columns}>{(column) => <col data-fold={column.fold ? \"\" : undefined} style={column.width ? { width: column.width } : undefined} />}</For>\n <Show when={props.actions}><col /></Show>\n </colgroup>\n </Show>\n <thead>\n <tr>\n <For each={props.columns}>{(column) => (\n <th scope=\"col\" data-column={column.id} data-fold={column.fold ? \"\" : undefined} data-numeric={column.numeric ? \"\" : undefined} aria-sort={clientSorted() && column.sortBy ? sortState(column.id) : undefined}>\n <Show when={clientSorted() && column.sortBy} fallback={column.label}>\n <button\n type=\"button\"\n class=\"dds-table__sort\"\n data-action=\"sort\"\n aria-label={fillLabel(props.labels.sortBy, column.label)}\n onClick={() => table.getColumn(column.id)?.toggleSorting()}\n >\n {column.label}\n <span class=\"dds-table__sort-mark\" aria-hidden=\"true\" data-sort-state={sortState(column.id)} />\n </button>\n </Show>\n </th>\n )}</For>\n <Show when={props.actions}>\n <th scope=\"col\"><span class=\"dds-visually-hidden\">{props.labels.actions}</span></th>\n </Show>\n </tr>\n </thead>\n <tbody>\n <For each={ordered()}>{(row) => (\n <>\n <tr>\n <For each={props.columns}>{(column) => (\n <Show\n when={column.rowHeader}\n fallback={<td data-fold={column.fold ? \"\" : undefined} data-numeric={column.numeric ? \"\" : undefined}>{column.cell(row)}</td>}\n >\n <th scope=\"row\" data-fold={column.fold ? \"\" : undefined} data-numeric={column.numeric ? \"\" : undefined}>{column.cell(row)}</th>\n </Show>\n )}</For>\n <Show when={props.actions}>{(actions) => <td><div class=\"dds-table__actions\">{actions()(row)}</div></td>}</Show>\n </tr>\n {/* Test the detail CONTENT, not the prop: a caller renders\n an expandable panel as\n `detail={(row) => expanded() === row.id ? <Panel/> : null}`,\n so a non-expanded row must produce no detail <tr> at\n all rather than a blank bordered one. */}\n <Show when={props.detail?.(row)}>{(node) => (\n <tr><td colSpan={props.columns.length + (props.actions ? 1 : 0)}>{node()}</td></tr>\n )}</Show>\n </>\n )}</For>\n </tbody>\n </table>\n </div>\n </Show>\n <nav class=\"dds-table__pagination\" hidden={!props.page?.nextHref} aria-label={props.labels.nextPage}>\n <Show when={props.page?.nextHref}>{(href) => <a class=\"dds-btn dds-btn--secondary\" href={href()}>{props.labels.nextPage}</a>}</Show>\n </nav>\n </>\n );\n}\n"],"mappings":"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"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { createComponent, escape, memo, ssr, ssrAttribute, ssrHydrationKey, ssrStyle } from "solid-js/web";
|
|
2
|
+
import { For, Show, createMemo } from "solid-js";
|
|
3
|
+
import { coreCellsFeature, coreColumnsFeature, coreHeadersFeature, coreRowModelsFeature, coreRowsFeature, coreTablesFeature, createColumnHelper, createSortedRowModel, createTable, rowSortingFeature, sortFn_alphanumeric, sortFn_text, tableFeatures } from "@tanstack/solid-table";
|
|
4
|
+
/**
|
|
5
|
+
* Registering `rowSortingFeature` alone is not enough for sorting to reach
|
|
6
|
+
* the screen — `sortedRowModel` is the factory `table.getRowModel()` actually
|
|
7
|
+
* calls to produce sorted rows; without it, `state.sorting` changes but the
|
|
8
|
+
* rendered row order never does. Added here, after `TableFeatureSet` is
|
|
9
|
+
* already named, so its function type closes over the narrow type instead of
|
|
10
|
+
* over itself.
|
|
11
|
+
*
|
|
12
|
+
* `sortFns` registers the names `sortFn: "auto"` (the default every column
|
|
13
|
+
* gets — see `toColumnDefs`) can actually resolve to for a `Column<T>` whose
|
|
14
|
+
* `sortBy` returns `string | number | null`: plain strings resolve to
|
|
15
|
+
* `"text"`, strings containing digit runs (`"Row 10"`, `"SKU100"`) resolve to
|
|
16
|
+
* `"alphanumeric"`, and numbers/`null` never set a name at all and fall
|
|
17
|
+
* straight to the always-available `sortFn_basic` — so `"datetime"` is never
|
|
18
|
+
* reachable and is deliberately not registered. Leaving either reachable name
|
|
19
|
+
* unregistered means `"auto"` silently falls back to `sortFn_basic`, which
|
|
20
|
+
* compares raw values instead of lowercasing first: a case-sensitive sort
|
|
21
|
+
* that also warns on every column in development
|
|
22
|
+
* (`rowSortingFeature.utils.js`'s `column_getAutoSortFn`). Importing the two
|
|
23
|
+
* named functions (rather than the `sortFns` barrel export, whose own
|
|
24
|
+
* docstring says registering it "opts out of tree-shaking") keeps every
|
|
25
|
+
* other built-in sorting function — including the case-sensitive and
|
|
26
|
+
* datetime variants this component never produces — out of the bundle.
|
|
27
|
+
*/
|
|
28
|
+
var tableFeatureSet = {
|
|
29
|
+
...tableFeatures({
|
|
30
|
+
coreTablesFeature,
|
|
31
|
+
coreRowsFeature,
|
|
32
|
+
coreColumnsFeature,
|
|
33
|
+
coreHeadersFeature,
|
|
34
|
+
coreCellsFeature,
|
|
35
|
+
coreRowModelsFeature,
|
|
36
|
+
rowSortingFeature
|
|
37
|
+
}),
|
|
38
|
+
sortedRowModel: createSortedRowModel(),
|
|
39
|
+
sortFns: {
|
|
40
|
+
text: sortFn_text,
|
|
41
|
+
alphanumeric: sortFn_alphanumeric
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/** Turns our declarations into TanStack column defs. Sorting is enabled per
|
|
45
|
+
* column by the presence of `sortBy`; everything visual stays in our own
|
|
46
|
+
* markup, so the def carries only what the model needs.
|
|
47
|
+
*
|
|
48
|
+
* `Column<T>` deliberately leaves `T` unconstrained (any row shape a
|
|
49
|
+
* consumer wants to render), but TanStack's `RowData` requires
|
|
50
|
+
* `Record<string, any> | Array<any>`. Every real row is one of those at
|
|
51
|
+
* runtime, so the helper is instantiated at `Record<string, unknown>` and
|
|
52
|
+
* the accessor casts its parameter back to `T` — a boundary cast, not a
|
|
53
|
+
* behavior change. */
|
|
54
|
+
function toColumnDefs(columns) {
|
|
55
|
+
const helper = createColumnHelper();
|
|
56
|
+
return columns.map((column) => helper.accessor((row) => column.sortBy ? column.sortBy(row) ?? void 0 : void 0, {
|
|
57
|
+
id: column.id,
|
|
58
|
+
enableSorting: Boolean(column.sortBy),
|
|
59
|
+
sortUndefined: "last"
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/data-table.tsx
|
|
64
|
+
var _tmpl$ = ["<col", ">"];
|
|
65
|
+
var _tmpl$2 = [
|
|
66
|
+
"<colgroup",
|
|
67
|
+
"><!--$-->",
|
|
68
|
+
"<!--/--><!--$-->",
|
|
69
|
+
"<!--/--></colgroup>"
|
|
70
|
+
];
|
|
71
|
+
var _tmpl$3 = [
|
|
72
|
+
"<th",
|
|
73
|
+
" scope=\"col\"><span class=\"dds-visually-hidden\">",
|
|
74
|
+
"</span></th>"
|
|
75
|
+
];
|
|
76
|
+
var _tmpl$4 = [
|
|
77
|
+
"<div",
|
|
78
|
+
"><table class=\"",
|
|
79
|
+
"\" style=\"",
|
|
80
|
+
"\"><caption class=\"dds-visually-hidden\">",
|
|
81
|
+
"</caption><!--$-->",
|
|
82
|
+
"<!--/--><thead><tr><!--$-->",
|
|
83
|
+
"<!--/--><!--$-->",
|
|
84
|
+
"<!--/--></tr></thead><tbody>",
|
|
85
|
+
"</tbody></table></div>"
|
|
86
|
+
];
|
|
87
|
+
var _tmpl$5 = [
|
|
88
|
+
"<nav",
|
|
89
|
+
" class=\"dds-table__pagination\"",
|
|
90
|
+
">",
|
|
91
|
+
"</nav>"
|
|
92
|
+
];
|
|
93
|
+
var _tmpl$6 = [
|
|
94
|
+
"<p",
|
|
95
|
+
" class=\"dds-table__order\">",
|
|
96
|
+
"</p>"
|
|
97
|
+
];
|
|
98
|
+
var _tmpl$7 = [
|
|
99
|
+
"<col",
|
|
100
|
+
" style=\"",
|
|
101
|
+
"\">"
|
|
102
|
+
];
|
|
103
|
+
var _tmpl$8 = [
|
|
104
|
+
"<button",
|
|
105
|
+
" type=\"button\" class=\"dds-table__sort\" data-action=\"sort\"",
|
|
106
|
+
"><!--$-->",
|
|
107
|
+
"<!--/--><span class=\"dds-table__sort-mark\" aria-hidden=\"true\"",
|
|
108
|
+
"></span></button>"
|
|
109
|
+
];
|
|
110
|
+
var _tmpl$9 = [
|
|
111
|
+
"<th",
|
|
112
|
+
" scope=\"col\"",
|
|
113
|
+
">",
|
|
114
|
+
"</th>"
|
|
115
|
+
];
|
|
116
|
+
var _tmpl$0 = [
|
|
117
|
+
"<tr",
|
|
118
|
+
"><!--$-->",
|
|
119
|
+
"<!--/--><!--$-->",
|
|
120
|
+
"<!--/--></tr>"
|
|
121
|
+
];
|
|
122
|
+
var _tmpl$1 = [
|
|
123
|
+
"<th",
|
|
124
|
+
" scope=\"row\"",
|
|
125
|
+
">",
|
|
126
|
+
"</th>"
|
|
127
|
+
];
|
|
128
|
+
var _tmpl$10 = [
|
|
129
|
+
"<td",
|
|
130
|
+
">",
|
|
131
|
+
"</td>"
|
|
132
|
+
];
|
|
133
|
+
var _tmpl$11 = [
|
|
134
|
+
"<td",
|
|
135
|
+
"><div class=\"dds-table__actions\">",
|
|
136
|
+
"</div></td>"
|
|
137
|
+
];
|
|
138
|
+
var _tmpl$12 = [
|
|
139
|
+
"<tr",
|
|
140
|
+
"><td",
|
|
141
|
+
">",
|
|
142
|
+
"</td></tr>"
|
|
143
|
+
];
|
|
144
|
+
var _tmpl$13 = [
|
|
145
|
+
"<a",
|
|
146
|
+
" class=\"dds-btn dds-btn--secondary\"",
|
|
147
|
+
">",
|
|
148
|
+
"</a>"
|
|
149
|
+
];
|
|
150
|
+
/** Fills the `{column}` placeholder in a consumer-supplied label template.
|
|
151
|
+
* A function replacer, not `template.replace("{column}", value)` — a
|
|
152
|
+
* string replacement value is subject to special `$&`/`$$`/`` $` ``/`$'`
|
|
153
|
+
* patterns, and this console has currency columns whose labels can contain
|
|
154
|
+
* a literal `$`. */
|
|
155
|
+
function fillLabel(template, value) {
|
|
156
|
+
return template.replace("{column}", () => value);
|
|
157
|
+
}
|
|
158
|
+
function DataTable(props) {
|
|
159
|
+
const clientSorted = () => props.sort === "client";
|
|
160
|
+
const statedOrder = () => typeof props.sort === "object" ? props.sort.statedOrder : void 0;
|
|
161
|
+
const fixed = () => props.columns.some((column) => column.width !== void 0);
|
|
162
|
+
const columnDefs = createMemo(() => toColumnDefs(props.columns));
|
|
163
|
+
const table = createTable({
|
|
164
|
+
features: tableFeatureSet,
|
|
165
|
+
get data() {
|
|
166
|
+
return props.rows;
|
|
167
|
+
},
|
|
168
|
+
get columns() {
|
|
169
|
+
return columnDefs();
|
|
170
|
+
},
|
|
171
|
+
enableSorting: true
|
|
172
|
+
});
|
|
173
|
+
const ordered = createMemo(() => clientSorted() ? table.getRowModel().rows.map((row) => row.original) : [...props.rows]);
|
|
174
|
+
const sortState = (id) => {
|
|
175
|
+
const current = table.store.state.sorting?.[0];
|
|
176
|
+
if (!current || current.id !== id) return "none";
|
|
177
|
+
return current.desc ? "descending" : "ascending";
|
|
178
|
+
};
|
|
179
|
+
return [
|
|
180
|
+
createComponent(Show, {
|
|
181
|
+
get when() {
|
|
182
|
+
return statedOrder();
|
|
183
|
+
},
|
|
184
|
+
children: (order) => ssr(_tmpl$6, ssrHydrationKey(), escape(order()))
|
|
185
|
+
}),
|
|
186
|
+
createComponent(Show, {
|
|
187
|
+
get when() {
|
|
188
|
+
return props.rows.length > 0;
|
|
189
|
+
},
|
|
190
|
+
get fallback() {
|
|
191
|
+
return props.empty;
|
|
192
|
+
},
|
|
193
|
+
get children() {
|
|
194
|
+
return ssr(_tmpl$4, ssrHydrationKey() + ssrAttribute("class", props.scroll === "tall" ? "dds-table-wrap dds-table-wrap--tall" : "dds-table-wrap", false), `dds-table${props.density === "dense" ? " dds-table--dense" : ""}${fixed() ? " dds-table--fixed" : ""}`, ssrStyle(props.minWidth ? { "min-inline-size": props.minWidth } : void 0), escape(props.caption), escape(createComponent(Show, {
|
|
195
|
+
get when() {
|
|
196
|
+
return fixed();
|
|
197
|
+
},
|
|
198
|
+
get children() {
|
|
199
|
+
return ssr(_tmpl$2, ssrHydrationKey(), escape(createComponent(For, {
|
|
200
|
+
get each() {
|
|
201
|
+
return props.columns;
|
|
202
|
+
},
|
|
203
|
+
children: (column) => ssr(_tmpl$7, ssrHydrationKey() + ssrAttribute("data-fold", column.fold ? "" : escape(void 0, true), false), ssrStyle(column.width ? { width: column.width } : void 0))
|
|
204
|
+
})), escape(createComponent(Show, {
|
|
205
|
+
get when() {
|
|
206
|
+
return props.actions;
|
|
207
|
+
},
|
|
208
|
+
get children() {
|
|
209
|
+
return ssr(_tmpl$, ssrHydrationKey());
|
|
210
|
+
}
|
|
211
|
+
})));
|
|
212
|
+
}
|
|
213
|
+
})), escape(createComponent(For, {
|
|
214
|
+
get each() {
|
|
215
|
+
return props.columns;
|
|
216
|
+
},
|
|
217
|
+
children: (column) => ssr(_tmpl$9, ssrHydrationKey(), ssrAttribute("data-column", escape(column.id, true), false) + ssrAttribute("data-fold", column.fold ? "" : escape(void 0, true), false) + ssrAttribute("data-numeric", column.numeric ? "" : escape(void 0, true), false) + ssrAttribute("aria-sort", clientSorted() && column.sortBy ? escape(sortState(column.id), true) : escape(void 0, true), false), escape(createComponent(Show, {
|
|
218
|
+
get when() {
|
|
219
|
+
return memo(() => !!clientSorted())() && column.sortBy;
|
|
220
|
+
},
|
|
221
|
+
get fallback() {
|
|
222
|
+
return column.label;
|
|
223
|
+
},
|
|
224
|
+
get children() {
|
|
225
|
+
return ssr(_tmpl$8, ssrHydrationKey(), ssrAttribute("aria-label", escape(fillLabel(props.labels.sortBy, column.label), true), false), escape(column.label), ssrAttribute("data-sort-state", escape(sortState(column.id), true), false));
|
|
226
|
+
}
|
|
227
|
+
})))
|
|
228
|
+
})), escape(createComponent(Show, {
|
|
229
|
+
get when() {
|
|
230
|
+
return props.actions;
|
|
231
|
+
},
|
|
232
|
+
get children() {
|
|
233
|
+
return ssr(_tmpl$3, ssrHydrationKey(), escape(props.labels.actions));
|
|
234
|
+
}
|
|
235
|
+
})), escape(createComponent(For, {
|
|
236
|
+
get each() {
|
|
237
|
+
return ordered();
|
|
238
|
+
},
|
|
239
|
+
children: (row) => [ssr(_tmpl$0, ssrHydrationKey(), escape(createComponent(For, {
|
|
240
|
+
get each() {
|
|
241
|
+
return props.columns;
|
|
242
|
+
},
|
|
243
|
+
children: (column) => createComponent(Show, {
|
|
244
|
+
get when() {
|
|
245
|
+
return column.rowHeader;
|
|
246
|
+
},
|
|
247
|
+
get fallback() {
|
|
248
|
+
return ssr(_tmpl$10, ssrHydrationKey() + ssrAttribute("data-fold", column.fold ? "" : escape(void 0, true), false) + ssrAttribute("data-numeric", column.numeric ? "" : escape(void 0, true), false), escape(column.cell(row)));
|
|
249
|
+
},
|
|
250
|
+
get children() {
|
|
251
|
+
return ssr(_tmpl$1, ssrHydrationKey(), ssrAttribute("data-fold", column.fold ? "" : escape(void 0, true), false) + ssrAttribute("data-numeric", column.numeric ? "" : escape(void 0, true), false), escape(column.cell(row)));
|
|
252
|
+
}
|
|
253
|
+
})
|
|
254
|
+
})), escape(createComponent(Show, {
|
|
255
|
+
get when() {
|
|
256
|
+
return props.actions;
|
|
257
|
+
},
|
|
258
|
+
children: (actions) => ssr(_tmpl$11, ssrHydrationKey(), escape(actions()(row)))
|
|
259
|
+
}))), createComponent(Show, {
|
|
260
|
+
get when() {
|
|
261
|
+
return props.detail?.(row);
|
|
262
|
+
},
|
|
263
|
+
children: (node) => ssr(_tmpl$12, ssrHydrationKey(), ssrAttribute("colspan", escape(props.columns.length, true) + (props.actions ? 1 : 0), false), escape(node()))
|
|
264
|
+
})]
|
|
265
|
+
})));
|
|
266
|
+
}
|
|
267
|
+
}),
|
|
268
|
+
ssr(_tmpl$5, ssrHydrationKey(), ssrAttribute("hidden", !props.page?.nextHref, true) + ssrAttribute("aria-label", escape(props.labels.nextPage, true), false), escape(createComponent(Show, {
|
|
269
|
+
get when() {
|
|
270
|
+
return props.page?.nextHref;
|
|
271
|
+
},
|
|
272
|
+
children: (href) => ssr(_tmpl$13, ssrHydrationKey(), ssrAttribute("href", escape(href(), true), false), escape(props.labels.nextPage))
|
|
273
|
+
})))
|
|
274
|
+
];
|
|
275
|
+
}
|
|
276
|
+
//#endregion
|
|
277
|
+
export { DataTable };
|
|
278
|
+
|
|
279
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","names":["createMemo","For","Show","JSX","createTable","tableFeatureSet","toColumnDefs","Column","DataTableLabels","TableFeatureSet","SortMode","statedOrder","fillLabel","template","value","replace","DataTable","props","rows","T","columns","caption","labels","sort","density","scroll","minWidth","actions","row","Element","detail","page","nextHref","empty","clientSorted","undefined","fixed","some","column","width","columnDefs","table","Record","features","data","enableSorting","ordered","getRowModel","map","original","sortState","id","current","store","state","sorting","desc","_$createComponent","when","children","order","_$ssr","_tmpl$6","_$ssrHydrationKey","_$escape","length","fallback","_tmpl$4","_$ssrAttribute","_$ssrStyle","_tmpl$2","each","_tmpl$7","fold","_tmpl$","_tmpl$9","numeric","sortBy","_$memo","label","_tmpl$8","_tmpl$3","_tmpl$0","rowHeader","_tmpl$10","cell","_tmpl$1","_tmpl$11","node","_tmpl$12","_tmpl$5","nextPage","href","_tmpl$13"],"sources":["../src/columns.ts","../src/data-table.tsx"],"sourcesContent":["import type { JSX } from \"solid-js\";\nimport {\n coreCellsFeature,\n coreColumnsFeature,\n coreHeadersFeature,\n coreRowModelsFeature,\n coreRowsFeature,\n coreTablesFeature,\n createColumnHelper,\n createSortedRowModel,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_text,\n tableFeatures,\n type ColumnDef,\n} from \"@tanstack/solid-table\";\n\nexport type Column<T> = {\n id: string;\n label: string;\n cell: (row: T) => JSX.Element;\n sortBy?: (row: T) => string | number | null;\n width?: string;\n fold?: boolean;\n numeric?: boolean;\n rowHeader?: boolean;\n};\n\nexport type DataTableLabels = {\n /** Accessible name for a sort button; `{column}` is replaced with the column label. */\n sortBy: string;\n /** Header of the trailing actions column, rendered visually hidden. */\n actions: string;\n /** Label of the next-page link. */\n nextPage: string;\n};\n\n/**\n * The feature set every `DataTable` instance is built from: the core row\n * model plus client-side sorting. Built once (per `tableFeatures`'\n * recommendation to use it statically outside a component) so `toColumnDefs`\n * and `createTable` agree on the same `TFeatures` type.\n */\nconst baseFeatures = tableFeatures({\n coreTablesFeature,\n coreRowsFeature,\n coreColumnsFeature,\n coreHeadersFeature,\n coreCellsFeature,\n coreRowModelsFeature,\n rowSortingFeature,\n});\n\n/** The `TFeatures` type used everywhere a table/column type needs one. Kept\n * separate from the `sortedRowModel` factory below: `createSortedRowModel`'s\n * return type embeds `Table<TFeatures, TData>`, so folding it into the very\n * type it closes over makes `TFeatures` self-referential — TypeScript's\n * structural comparison of that recursive shape (observed while wiring this\n * up) reports unrelated `ColumnDef`/`Column`/`HeaderContext` instantiations\n * a few frames down a completely unrelated diff, because it can't resolve\n * the cycle. Naming the narrower, non-recursive type here and using it as\n * the explicit `TFeatures` argument everywhere avoids that. */\nexport type TableFeatureSet = typeof baseFeatures;\n\n/**\n * Registering `rowSortingFeature` alone is not enough for sorting to reach\n * the screen — `sortedRowModel` is the factory `table.getRowModel()` actually\n * calls to produce sorted rows; without it, `state.sorting` changes but the\n * rendered row order never does. Added here, after `TableFeatureSet` is\n * already named, so its function type closes over the narrow type instead of\n * over itself.\n *\n * `sortFns` registers the names `sortFn: \"auto\"` (the default every column\n * gets — see `toColumnDefs`) can actually resolve to for a `Column<T>` whose\n * `sortBy` returns `string | number | null`: plain strings resolve to\n * `\"text\"`, strings containing digit runs (`\"Row 10\"`, `\"SKU100\"`) resolve to\n * `\"alphanumeric\"`, and numbers/`null` never set a name at all and fall\n * straight to the always-available `sortFn_basic` — so `\"datetime\"` is never\n * reachable and is deliberately not registered. Leaving either reachable name\n * unregistered means `\"auto\"` silently falls back to `sortFn_basic`, which\n * compares raw values instead of lowercasing first: a case-sensitive sort\n * that also warns on every column in development\n * (`rowSortingFeature.utils.js`'s `column_getAutoSortFn`). Importing the two\n * named functions (rather than the `sortFns` barrel export, whose own\n * docstring says registering it \"opts out of tree-shaking\") keeps every\n * other built-in sorting function — including the case-sensitive and\n * datetime variants this component never produces — out of the bundle.\n */\nexport const tableFeatureSet: TableFeatureSet & {\n sortedRowModel: ReturnType<typeof createSortedRowModel<TableFeatureSet, Record<string, unknown>>>;\n sortFns: { text: typeof sortFn_text; alphanumeric: typeof sortFn_alphanumeric };\n} = {\n ...baseFeatures,\n sortedRowModel: createSortedRowModel<TableFeatureSet, Record<string, unknown>>(),\n sortFns: { text: sortFn_text, alphanumeric: sortFn_alphanumeric },\n};\n\n/** Turns our declarations into TanStack column defs. Sorting is enabled per\n * column by the presence of `sortBy`; everything visual stays in our own\n * markup, so the def carries only what the model needs.\n *\n * `Column<T>` deliberately leaves `T` unconstrained (any row shape a\n * consumer wants to render), but TanStack's `RowData` requires\n * `Record<string, any> | Array<any>`. Every real row is one of those at\n * runtime, so the helper is instantiated at `Record<string, unknown>` and\n * the accessor casts its parameter back to `T` — a boundary cast, not a\n * behavior change. */\nexport function toColumnDefs<T>(columns: readonly Column<T>[]): ColumnDef<TableFeatureSet, Record<string, unknown>, unknown>[] {\n const helper = createColumnHelper<TableFeatureSet, Record<string, unknown>>();\n return columns.map((column) =>\n // `TValue` is invariant on `ColumnDef` (it shows up contravariantly via\n // `footer`'s `HeaderContext`, covariantly via `accessorFn`'s return), so\n // a heterogeneous array of columns can only be typed uniformly at\n // `unknown` — the array element type `ColumnDef<..., unknown>` is not a\n // supertype of `ColumnDef<..., string | number | null>`. The return type\n // annotation below is what makes TanStack infer `TValue = unknown`\n // instead of narrowing to the ternary's actual `string | number | null`.\n //\n // `?? undefined` is the adapter boundary translating our declared\n // contract (`sortBy` returns `null` for \"no value\") into TanStack's:\n // `createSortedRowModel`'s comparator only consults `sortUndefined`\n // after testing `=== void 0`, so a bare `null` would never trigger it —\n // `sortUndefined: \"last\"` would be a promise the code doesn't keep.\n helper.accessor((row): unknown => (column.sortBy ? column.sortBy(row as T) ?? undefined : undefined), {\n id: column.id,\n enableSorting: Boolean(column.sortBy),\n sortUndefined: \"last\",\n }),\n );\n}\n","import { createMemo, For, Show, type JSX } from \"solid-js\";\nimport { createTable } from \"@tanstack/solid-table\";\nimport { tableFeatureSet, toColumnDefs, type Column, type DataTableLabels, type TableFeatureSet } from \"./columns\";\n\nexport type SortMode = \"client\" | { statedOrder: string };\n\n/** Fills the `{column}` placeholder in a consumer-supplied label template.\n * A function replacer, not `template.replace(\"{column}\", value)` — a\n * string replacement value is subject to special `$&`/`$$`/`` $` ``/`$'`\n * patterns, and this console has currency columns whose labels can contain\n * a literal `$`. */\nfunction fillLabel(template: string, value: string): string {\n return template.replace(\"{column}\", () => value);\n}\n\nexport function DataTable<T>(props: {\n rows: readonly T[];\n columns: readonly Column<T>[];\n caption: string;\n labels: DataTableLabels;\n sort?: SortMode;\n density?: \"comfortable\" | \"dense\";\n scroll?: \"auto\" | \"tall\";\n minWidth?: string;\n actions?: (row: T) => JSX.Element;\n detail?: (row: T) => JSX.Element;\n page?: { nextHref?: string | undefined };\n empty?: JSX.Element;\n}): JSX.Element {\n const clientSorted = () => props.sort === \"client\";\n const statedOrder = () => (typeof props.sort === \"object\" ? props.sort.statedOrder : undefined);\n const fixed = () => props.columns.some((column) => column.width !== undefined);\n\n /* `toColumnDefs` builds fresh column objects on every read; a table model\n that sees a new column identity on every access can lose sorting state\n or re-render in a loop, so the defs are memoized on `props.columns`. */\n const columnDefs = createMemo(() => toColumnDefs(props.columns));\n\n /* TanStack's `RowData` requires `Record<string, any> | Array<any>`, which\n an unconstrained `T` can't satisfy structurally. Every row is one of\n those at runtime, so the table is instantiated at `Record<string,\n unknown>` and cast back to `T` where rows come back out (in `ordered`). */\n const table = createTable<TableFeatureSet, Record<string, unknown>>({\n features: tableFeatureSet,\n get data() { return props.rows as readonly Record<string, unknown>[]; },\n get columns() { return columnDefs(); },\n enableSorting: true,\n });\n\n /* The model sorts; our own markup renders. A server-ordered table never\n reaches this path — `sort` is then an object and no header is a button. */\n const ordered = createMemo(() => (clientSorted() ? table.getRowModel().rows.map((row) => row.original as T) : [...props.rows]));\n\n const sortState = (id: string) => {\n const current = table.store.state.sorting?.[0];\n if (!current || current.id !== id) return \"none\";\n return current.desc ? \"descending\" : \"ascending\";\n };\n\n return (\n <>\n {/* The stated order and the pagination link are not part of the \"is\n there a table to show\" question — a cursor-paged list can land on\n an empty page and still needs to say what order it was in and\n offer a way forward. Only the table itself (and its wrap) falls\n back to `empty` when there are no rows. */}\n <Show when={statedOrder()}>{(order) => <p class=\"dds-table__order\">{order()}</p>}</Show>\n <Show when={props.rows.length > 0} fallback={props.empty}>\n <div class={props.scroll === \"tall\" ? \"dds-table-wrap dds-table-wrap--tall\" : \"dds-table-wrap\"}>\n <table\n class={`dds-table${props.density === \"dense\" ? \" dds-table--dense\" : \"\"}${fixed() ? \" dds-table--fixed\" : \"\"}`}\n style={props.minWidth ? { \"min-inline-size\": props.minWidth } : undefined}\n >\n <caption class=\"dds-visually-hidden\">{props.caption}</caption>\n <Show when={fixed()}>\n <colgroup>\n <For each={props.columns}>{(column) => <col data-fold={column.fold ? \"\" : undefined} style={column.width ? { width: column.width } : undefined} />}</For>\n <Show when={props.actions}><col /></Show>\n </colgroup>\n </Show>\n <thead>\n <tr>\n <For each={props.columns}>{(column) => (\n <th scope=\"col\" data-column={column.id} data-fold={column.fold ? \"\" : undefined} data-numeric={column.numeric ? \"\" : undefined} aria-sort={clientSorted() && column.sortBy ? sortState(column.id) : undefined}>\n <Show when={clientSorted() && column.sortBy} fallback={column.label}>\n <button\n type=\"button\"\n class=\"dds-table__sort\"\n data-action=\"sort\"\n aria-label={fillLabel(props.labels.sortBy, column.label)}\n onClick={() => table.getColumn(column.id)?.toggleSorting()}\n >\n {column.label}\n <span class=\"dds-table__sort-mark\" aria-hidden=\"true\" data-sort-state={sortState(column.id)} />\n </button>\n </Show>\n </th>\n )}</For>\n <Show when={props.actions}>\n <th scope=\"col\"><span class=\"dds-visually-hidden\">{props.labels.actions}</span></th>\n </Show>\n </tr>\n </thead>\n <tbody>\n <For each={ordered()}>{(row) => (\n <>\n <tr>\n <For each={props.columns}>{(column) => (\n <Show\n when={column.rowHeader}\n fallback={<td data-fold={column.fold ? \"\" : undefined} data-numeric={column.numeric ? \"\" : undefined}>{column.cell(row)}</td>}\n >\n <th scope=\"row\" data-fold={column.fold ? \"\" : undefined} data-numeric={column.numeric ? \"\" : undefined}>{column.cell(row)}</th>\n </Show>\n )}</For>\n <Show when={props.actions}>{(actions) => <td><div class=\"dds-table__actions\">{actions()(row)}</div></td>}</Show>\n </tr>\n {/* Test the detail CONTENT, not the prop: a caller renders\n an expandable panel as\n `detail={(row) => expanded() === row.id ? <Panel/> : null}`,\n so a non-expanded row must produce no detail <tr> at\n all rather than a blank bordered one. */}\n <Show when={props.detail?.(row)}>{(node) => (\n <tr><td colSpan={props.columns.length + (props.actions ? 1 : 0)}>{node()}</td></tr>\n )}</Show>\n </>\n )}</For>\n </tbody>\n </table>\n </div>\n </Show>\n <nav class=\"dds-table__pagination\" hidden={!props.page?.nextHref} aria-label={props.labels.nextPage}>\n <Show when={props.page?.nextHref}>{(href) => <a class=\"dds-btn dds-btn--secondary\" href={href()}>{props.labels.nextPage}</a>}</Show>\n </nav>\n </>\n );\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@devslab/dds-table",
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "Declarative data table for the DevsLab Design System",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/devslab-kr/dds.git",
|
|
10
|
+
"directory": "packages/dds-table"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"registry": "https://registry.npmjs.org",
|
|
14
|
+
"access": "public",
|
|
15
|
+
"provenance": true
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"README.ko.md"
|
|
21
|
+
],
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"worker": "./dist/server.js",
|
|
28
|
+
"workerd": "./dist/server.js",
|
|
29
|
+
"node": "./dist/server.js",
|
|
30
|
+
"browser": "./dist/index.js",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@devslab/dds-css": "0.11.0",
|
|
36
|
+
"@devslab/dds-tokens": "0.11.0",
|
|
37
|
+
"@tanstack/solid-table": "9.2.4"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"solid-js": "1.9.15"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "26.3.0",
|
|
44
|
+
"axe-core": "4.13.0",
|
|
45
|
+
"jsdom": "30.0.1",
|
|
46
|
+
"solid-js": "1.9.15",
|
|
47
|
+
"@testing-library/jest-dom": "6.9.1",
|
|
48
|
+
"typescript": "7.0.2",
|
|
49
|
+
"vite": "8.2.1",
|
|
50
|
+
"vite-plugin-solid": "2.11.14",
|
|
51
|
+
"vitest": "4.1.1"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://devslab.kr/brand/",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/devslab-kr/dds/issues"
|
|
56
|
+
},
|
|
57
|
+
"keywords": [
|
|
58
|
+
"solidjs",
|
|
59
|
+
"table",
|
|
60
|
+
"design-system",
|
|
61
|
+
"devslab"
|
|
62
|
+
],
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "vite build && vite build --config vite.server.config.ts && tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
65
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
66
|
+
"test": "vitest run --config vitest.config.ts && vitest run --config vitest.ssr.config.ts",
|
|
67
|
+
"test:a11y": "vitest run --config vitest.config.ts src/__tests__/a11y.test.tsx"
|
|
68
|
+
}
|
|
69
|
+
}
|