@medyat/react-data-table 0.0.0-stage → 0.2.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Medyat
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,230 @@
1
- # Temporary Holding Version
1
+ # @medyat/react-data-table
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ React 19 için liste tablosu (`DataTable`). Davranış ve tasarım `@medyat/vue-data-table` ile aynı sözleşmeye dayanır;
4
+ spesifikasyon Vue paketinin `docs/data-table/` klasöründedir, React'e özgü kararlar ve Vue'dan sapmalar
5
+ `docs/react-kararlar.md`'de. Toplu düzenleme (`DataSheet`) ve içe aktarma bu pakette yok (R1).
6
+
7
+ Paket veri çekmez ve kaydetmez (D18): istek nesnesini üretir, uygulama onu kendi sorgu katmanıyla (önerilen TanStack Query)
8
+ çalıştırır ve sonucu tabloya verir.
9
+
10
+ ## Kurulum
11
+
12
+ ```bash
13
+ pnpm add @medyat/react-data-table @base-ui/react @phosphor-icons/react write-excel-file
14
+ ```
15
+
16
+ ```tsx
17
+ import { createLocalStoragePreferences, createLocalStorageViews, DataTableProvider } from '@medyat/react-data-table'
18
+ import '@medyat/react-data-table/style.css'
19
+ import '@medyat/react-data-table/shadcn-bridge.css' // shadcn teması kullanılıyorsa, style.css'ten sonra (HSL tema: shadcn-bridge-hsl.css)
20
+
21
+ ;<DataTableProvider
22
+ locale="tr" // en · tr · ru; verilmezse navigator.language
23
+ viewsAdapter={createLocalStorageViews({ scope: tenantId })} // kişisel görünümler; backend için kendi ViewsAdapter'ınız
24
+ preferences={createLocalStoragePreferences({ scope: tenantId })} // yoğunluk, dikey çizgiler, sayfa boyutu, varsayılan görünüm
25
+ >
26
+ <App />
27
+ </DataTableProvider>
28
+ ```
29
+
30
+ Sağlayıcı isteğe bağlıdır; yoksa paket metinleri ve tarayıcı dili kullanılır, görünüm ve tercih kaydedilmez. `messages`
31
+ ile tek tek metin anahtarı ezilebilir.
32
+
33
+ Backend'e bağlamak (Laravel + Laraql: liste sorgusu, kişisel görünümler, kullanıcı tercihleri) için
34
+ [`docs/backend-integration.md`](docs/backend-integration.md).
35
+
36
+ ## Kullanım
37
+
38
+ `useDataTable` durumu ve isteği tutar, `<DataTable>` çizer (R3). Sütun tanımları feature'ın kendi dosyasında yaşar.
39
+
40
+ ```tsx
41
+ import { keepPreviousData, useQuery } from '@tanstack/react-query'
42
+ import { DataTable, useDataTable, type ColumnDef } from '@medyat/react-data-table'
43
+
44
+ const columns: Array<ColumnDef<Order>> = [
45
+ { id: 'number', header: 'Order no.', type: 'id', primary: true, href: (r) => `/orders/${r.id}` },
46
+ { id: 'customer', header: 'Customer', type: 'string' },
47
+ { id: 'status', header: 'Status', type: 'select', options: statusOptions, suggested: true },
48
+ { id: 'dueAt', header: 'Due date', type: 'date', overdue: (r) => r.status !== 'done' },
49
+ { id: 'value', header: 'Value', type: 'currency', currency: 'TRY' },
50
+ ]
51
+
52
+ export function OrdersScreen() {
53
+ const table = useDataTable({
54
+ id: 'production-orders', // görünümler ve tercihler bu kimlikle saklanır
55
+ columns,
56
+ entityName: { one: 'order', other: 'orders' },
57
+ views: systemViews, // kodda tanımlı system görünümleri; filtresiz "Tümü" hazır gelir (R19), kişisel olanlar viewsAdapter'dan
58
+ count: (query, signal) => api.countOrders(query, signal), // footer'da "Count total"
59
+ })
60
+ const result = useQuery({
61
+ queryKey: ['orders', table.request],
62
+ queryFn: ({ signal }) => api.listOrders(table.request, signal), // → { rows, hasMore, total? }
63
+ placeholderData: keepPreviousData, // yükleme geçişleri için önerilir
64
+ })
65
+ return <DataTable table={table} result={result} toolbarEnd={<NewOrderButton />} />
66
+ }
67
+ ```
68
+
69
+ `table.request` (`TableQuery`): `search`, `filters` (`FilterCondition[]`), `sort` (`[{ column, dir }]`), `page`
70
+ (`{ number, size }`) ve `fields`. Sütun gizlemek, taşımak ya da genişletmek yeni istek üretmez. `result`, `useQuery`
71
+ sonucunun kendisidir; paket TanStack Query'ye bağımlı değildir, aynı alanları (`status`, `data`, `error`,
72
+ `isFetching`, `isPlaceholderData`, `dataUpdatedAt`, `refetch`) taşıyan herhangi bir nesneyi kabul eder. Hata
73
+ nesnesinin `message` ve `id` alanları hata ekranında gösterilir; `refetch` yoksa Refresh ve Retry görünmez.
74
+
75
+ İstemci modu: `useDataTable({ rows })` verilirse paket kendisi süzer, sıralar ve sayfalar; `result` verilmez.
76
+
77
+ ### Durumu adrese bağlamak
78
+
79
+ Durum varsayılan olarak tablonun içindedir. `state` + `onStateChange` ile dışarı açılır (R5); paket adrese kendisi
80
+ dokunmaz. `state` verilince eksik alan varsayılandır (varsayılan görünüm ve onun filtre/sıralaması, sayfa 1). İkinci argüman
81
+ `changed` yalnızca varsayılandan farklı alanları taşır: adrese onu yazın, varsayılan liste temiz adres olur. TanStack Router ile:
82
+
83
+ ```tsx
84
+ const search = Route.useSearch() // { view?, search?, filters?, sort?, page?, pageSize? }
85
+ const navigate = Route.useNavigate()
86
+ const table = useDataTable({
87
+ id: 'production-orders',
88
+ columns,
89
+ state: search,
90
+ onStateChange: (_state, changed) => navigate({ search: changed, replace: true }),
91
+ })
92
+ ```
93
+
94
+ Yalnızca tam filtre koşulları duruma girer; değeri seçilmemiş çip ekranda kalır. Sütun düzeni durumda değildir, görünüme
95
+ ve tercihe gider.
96
+
97
+ ### Satırı açmak
98
+
99
+ Birincil hücre gerçek bir `<a href>`'tir (D6): ⌘/orta tık tarayıcıya kalır, düz tık `onRowOpen`'ı çağırır. Dinleyici
100
+ `preventDefault` yapmazsa tarayıcı bağlantıya gider.
101
+
102
+ ```tsx
103
+ <DataTable
104
+ table={table}
105
+ result={result}
106
+ rowClick="open" // satırın boş yerine tık da açar; "expand" detayı açar; varsayılan "none"
107
+ onRowOpen={({ href, event }) => {
108
+ event.preventDefault()
109
+ navigate({ to: href })
110
+ }}
111
+ />
112
+ ```
113
+
114
+ ### Seçim, aksiyonlar, detay
115
+
116
+ ```tsx
117
+ <DataTable
118
+ table={table}
119
+ result={result}
120
+ selectable // seçim sayfa kapsamlı (D19); durum table.selection, temizlemek için table.clearSelection()
121
+ bulkActions={[
122
+ { id: 'release', label: 'Release', icon: PlayIcon, inBar: true, run: (rows) => release(rows) },
123
+ {
124
+ id: 'cancel',
125
+ label: 'Cancel orders…',
126
+ destructive: true,
127
+ disabled: (rows) => (rows.every(isDone) ? 'All already done' : false), // metin döndürülürse gerekçe olarak gösterilir
128
+ run: (rows) => confirmCancel(rows),
129
+ },
130
+ ]}
131
+ rowActions={[
132
+ { id: 'edit', label: 'Edit', icon: PencilSimpleIcon, inline: true, run: (row) => edit(row) },
133
+ { id: 'archive', label: 'Archive', when: (row) => row.status === 'done', run: (row) => archive(row) }, // yoksa görünmez
134
+ ]}
135
+ renderExpanded={({ row }) => <OrderOperations order={row} />} // detay verisini bileşen kendisi çeker
136
+ rowError={(row) => failures.get(row.id)} // satır hatası (D35): zemin, uyarı ikonu, tooltip
137
+ />
138
+ ```
139
+
140
+ `run` beklenmez (D20): uzun işlemin onayı, ilerlemesi ve sonucu uygulamanındır. Seçim çubuğu varsayılan olarak kartın
141
+ altında yüzer; `bulkActions` ve `selectionActions` yoksa hiç çizilmez (seçim Export'ta ve header checkbox'ında kalır); `selectionBar="toolbar"` onu araç çubuğunun yerine koyar, `selectionActions` içeriğini tümüyle uygulamaya
142
+ bırakır. Seçili satırlar `onSelectionChange` ile de okunabilir.
143
+
144
+ ### Satır sıralama
145
+
146
+ Varsayılan kapalı (R21). `reorder` verilince satırın başında tutamak çıkar; satır tutamaktan sürüklenir ya da klavyeyle
147
+ taşınır (tutamakta `Space` · `↑↓` · `Space`, `Esc` iptal). Paket numara üretmez: taşınan satırı ve yeni komşularını
148
+ bildirir, sırayı sunucu yazar.
149
+
150
+ ```tsx
151
+ <DataTable
152
+ table={table}
153
+ result={result}
154
+ reorder={{
155
+ // Sıra yalnızca sıra kolonuna göre dizilmiş, tek grubun listesinde anlamlıdır; değilse gerekçe tooltip'te.
156
+ disabled: table.request.sort[0]?.column !== 'sq' && 'Sıralamak için sıra kolonuna göre dizin',
157
+ // after: yeni yerde üstte kalan satır, before: altta kalan; liste başı / sonu null.
158
+ onMove: ({ row, after }) => moveField.mutateAsync({ id: row.id, after: after?.id ?? null }),
159
+ }}
160
+ />
161
+ ```
162
+
163
+ Bırakınca yeni sıra hemen çizilir ve yenilenen sonuç gelene kadar korunur. `onMove` Promise dönerse sonuçlanana kadar
164
+ tutamaklar pasiftir; reddedilirse eski sıraya döner, hata mesajı uygulamanındır. Sürükleme kodu yalnızca sıralama
165
+ açıkken yüklenir.
166
+
167
+ ### Diğer
168
+
169
+ - `toolbar`: `'auto'` (varsayılan; görünümler, arama, Filter, Display, ⋯), `'minimal'` (yalnızca arama ve
170
+ `toolbarEnd`) ya da `false`.
171
+ - `autoRefresh={30}`: ⋯ menüsünde Auto-refresh anahtarı; açıkken footer "Live". `onPrint` verilirse ⋯ menüsünde Print.
172
+ - `empty`: hiç kayıt yokken (filtre ve arama da yokken) gövdede gösterilecek içerik.
173
+ - `notice`: araç çubuğu ile sütun başlıkları arasında uygulamanın şeridi (R16), ör. "Yalnızca arşivlenmiş
174
+ kayıtlar listeleniyor". İçerik, rengi ve rolü uygulamanın; paket yer, yatay hiza ve alt çizgiyi verir.
175
+ - Dışa aktarma (D46): ⋯ › **Export 100 rows** › CSV / Excel (.xlsx). Ekranda görünen sütunlar ve satırlar yazılır: seçim
176
+ varsa seçili satırlar, yoksa sayfadaki satırlar (sunucu modunda yüklü sayfa; "tüm eşleşenler" yok). .xlsx için
177
+ `write-excel-file` peer'ı gerekir (`pnpm add write-excel-file`); ilk dışa aktarmada yüklenir. `exportable={false}`
178
+ gizler; `onExport` verilirse paket dosya yazmaz, `{ format, query, selection, rows, visibleColumns }` ile uygulama
179
+ üretir.
180
+
181
+ ## Telefon
182
+
183
+ Kartın kendi genişliği 640 px'in altındaysa (ekranın değil) telefon düzeni açılır: yalnızca birincil sütun sabit, 48 px
184
+ satırlar; filtreler, görünümler, ⋯ ve toplu aksiyonlar alt sayfada. Filters sayfası değişiklikleri taslakta biriktirir,
185
+ **Show results** filtreyi ve sıralamayı tek istekte uygular.
186
+
187
+ ## Erişilebilirlik ve klavye
188
+
189
+ - Kısayollar: `/` arama, `F` filtre, `V` görünümler, `R` yenile, `⌘S` görünümü kaydet, `Alt ←/→` sayfa, `Esc` seçimi
190
+ temizler. Odak bir metin alanındayken tek harfli kısayollar çalışmaz; `shortcuts={false}` onları kapatır.
191
+ - Duyurular `aria-live` bölgelerinden; `forced-colors` ve `prefers-reduced-motion` desteklenir.
192
+ - Playwright'ta axe-core taraması (`e2e/a11y.spec.ts`): WCAG 2.1 A/AA'da kritik ya da ciddi ihlal kabul edilmez.
193
+
194
+ Ayrıntılar Vue spesifikasyonunun `08-accessibility-keyboard.md`'sinde; React'teki farklar `docs/react-kararlar.md`'de.
195
+
196
+ ## Stil
197
+
198
+ Tüm CSS `@layer medyat-dt` içindedir. Tailwind v4'te katmanı `utilities`'den önce bildirin; uygulamanın sınıfları
199
+ paketi ezsin:
200
+
201
+ ```css
202
+ @layer theme, base, medyat-dt, components, utilities;
203
+ ```
204
+
205
+ Tema `.dark` sınıfı ya da `data-theme="dark"` ile değişir. Yoğunluk kullanıcının Display › Density seçiminden gelir;
206
+ `useDataTable({ density })` onu sabitler ve seçiciyi gizler.
207
+
208
+ ## Geliştirme
209
+
210
+ Node 22+ ve pnpm (corepack ile): `corepack enable` bir kez, sonra `pnpm install`. Vue paketi kardeş klasörde
211
+ (`../data-table`) bulunmalıdır: token ve metinler oradaki belgelerden üretilir, karşılaştırma testleri oradan okur
212
+ (yoksa atlanır; başka yerdeyse `DT_SPEC`).
213
+
214
+ | Komut | Ne yapar |
215
+ | ------------------------------ | ------------------------------------------------------------------------------------------- |
216
+ | `pnpm dev` | Playground (`playground/`, http://localhost:5175); sahte API `/api/orders` |
217
+ | `pnpm test` | Vitest: bileşenler, token ↔ 02, kontrast, i18n ↔ 09 |
218
+ | `pnpm test:e2e` | Playwright, kendi playground'una karşı (port 5179); axe taraması |
219
+ | `pnpm typecheck` · `pnpm lint` | tsc, ESLint |
220
+ | `pnpm format` | Prettier |
221
+ | `pnpm build` | `dist/`: `index.js`, `style.css`, köprü CSS'leri, `.d.ts` |
222
+ | `pnpm gen:docs` | 02 → `src/styles/tokens.css`, 09 → `src/core/i18n/{en,tr}.ts` (üretilmiş, elle düzenlenmez) |
223
+ | `pnpm check` | typecheck + lint + format kontrolü + test + build |
224
+
225
+ Token ve metin değişikliği Vue belgesinde yapılır, sonra `pnpm gen:docs`. React'e özgü metin sapmaları
226
+ `scripts/docs.ts` içindeki `REACT_MESSAGES`'tadır; `ru` elle yazılır.
227
+
228
+ ## Lisans
229
+
230
+ MIT · © 2026 Medyat