intable 0.0.7 → 0.0.8
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/.github/copilot-instructions.md +102 -0
- package/docs/index-BaMALNy6.css +1 -1
- package/docs/index-CDN48t9E.js +2 -2
- package/index.html +13 -14
- package/package.json +9 -4
- package/packages/intable/package.json +1 -1
- package/packages/intable/src/index.tsx +25 -17
- package/packages/intable/src/plugins/CopyPastePlugin.tsx +49 -13
- package/packages/intable/src/plugins/DiffPlugin.tsx +31 -18
- package/packages/intable/src/theme/dark.scss +46 -0
- package/packages/intable/src/theme/github.scss +80 -0
- package/packages/intable/src/theme/material.scss +73 -0
- package/packages/intable/src/theme/shadcn.scss +66 -0
- package/packages/intable/src/theme/stripe.scss +57 -0
- package/packages/react/package.json +13 -8
- package/packages/react/src/index.ts +1 -1
- package/packages/vue/package.json +1 -1
- package/scripts/publish.js +1 -1
- package/src/index.tsx +20 -0
- package/src/pages/demo/BasicDemo.tsx +19 -0
- package/src/pages/demo/CellMergeDemo.tsx +41 -0
- package/src/pages/demo/CellSelectionDemo.tsx +24 -0
- package/src/pages/demo/CompositeDemo.tsx +60 -0
- package/src/pages/demo/CopyPasteDemo.tsx +26 -0
- package/src/pages/demo/DiffDemo.tsx +33 -0
- package/src/pages/demo/DragDemo.tsx +25 -0
- package/src/pages/demo/EditableDemo.tsx +58 -0
- package/src/pages/demo/ExpandDemo.tsx +32 -0
- package/src/pages/demo/HeaderGroupDemo.tsx +36 -0
- package/src/pages/demo/HistoryDemo.tsx +28 -0
- package/src/pages/demo/ReactDemo.tsx +59 -0
- package/src/pages/demo/ResizeDemo.tsx +24 -0
- package/src/pages/demo/RowGroupDemo.tsx +43 -0
- package/src/pages/demo/RowSelectionDemo.tsx +27 -0
- package/src/pages/demo/TreeDemo.tsx +45 -0
- package/src/pages/demo/VirtualScrollDemo.tsx +21 -0
- package/src/pages/demo/helpers.tsx +39 -0
- package/src/pages/demo/index.tsx +180 -0
- package/src/pages/index.tsx +2 -0
- package/src/pages/website.scss +37 -0
- package/src/pages/website.tsx +651 -0
- package/vite.config.ts +70 -63
- package/src/demo.tsx +0 -107
|
@@ -2,10 +2,10 @@ import { createContext, createMemo, createSignal, For, useContext, createEffect,
|
|
|
2
2
|
import { createMutable, reconcile } from 'solid-js/store'
|
|
3
3
|
import { combineProps } from '@solid-primitives/props'
|
|
4
4
|
import { createLazyMemo } from '@solid-primitives/memo'
|
|
5
|
-
import { createElementSize, createResizeObserver } from '@solid-primitives/resize-observer'
|
|
5
|
+
import { createElementSize, createResizeObserver, makeResizeObserver } from '@solid-primitives/resize-observer'
|
|
6
6
|
import { createScrollPosition } from '@solid-primitives/scroll'
|
|
7
7
|
import { difference, mapValues, memoize, sumBy } from 'es-toolkit'
|
|
8
|
-
import { toReactive, useMemo
|
|
8
|
+
import { toReactive, useMemo } from './hooks'
|
|
9
9
|
import { log, unFn } from './utils'
|
|
10
10
|
|
|
11
11
|
import 'virtual:uno.css'
|
|
@@ -240,24 +240,26 @@ function BasePlugin(): Plugin$0 {
|
|
|
240
240
|
priority: Infinity,
|
|
241
241
|
store: (store) => {
|
|
242
242
|
// 共享一个 ResizeObserver 观察所有 th,回调按 index 分发,替代每列独立 createElementSize
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
const thObs = makeResizeObserver((es) => {
|
|
244
|
+
for (const e of es) {
|
|
245
|
+
const el = e.target
|
|
246
246
|
const { inlineSize: width, blockSize: height } = e.borderBoxSize[0]
|
|
247
|
-
const
|
|
248
|
-
if (
|
|
247
|
+
const h = store.ths.indexOf(el)
|
|
248
|
+
if (h >= 0 && el.parentElement) store.thSizes[h] = { width, height }
|
|
249
249
|
}
|
|
250
|
-
)
|
|
250
|
+
})
|
|
251
251
|
// 共享一个 ResizeObserver 观察所有 tr,回调按 index 分发,替代每行独立 createElementSize
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
252
|
+
const trObs = makeResizeObserver((es) => {
|
|
253
|
+
for (const e of es) {
|
|
254
|
+
const el = e.target
|
|
255
255
|
const { inlineSize: width, blockSize: height } = e.borderBoxSize[0]
|
|
256
|
-
const y = store.trs
|
|
256
|
+
const y = store.trs.indexOf(el)
|
|
257
257
|
if (y >= 0 && el.parentElement) store.trSizes[y] = { width, height }
|
|
258
258
|
}
|
|
259
|
-
)
|
|
259
|
+
})
|
|
260
260
|
return {
|
|
261
|
+
thObs,
|
|
262
|
+
trObs,
|
|
261
263
|
ths: [],
|
|
262
264
|
thSizes: [],
|
|
263
265
|
trs: [],
|
|
@@ -296,7 +298,11 @@ function BasePlugin(): Plugin$0 {
|
|
|
296
298
|
const { y } = o
|
|
297
299
|
if (y == null) return
|
|
298
300
|
store.trs[y] = el()
|
|
299
|
-
|
|
301
|
+
store.trObs.observe(el())
|
|
302
|
+
onCleanup(() => {
|
|
303
|
+
store.trSizes[y] = store.trs[y] = void 0
|
|
304
|
+
store.trObs.unobserve(el())
|
|
305
|
+
})
|
|
300
306
|
})
|
|
301
307
|
|
|
302
308
|
return <Tr {...o} />
|
|
@@ -318,7 +324,11 @@ function BasePlugin(): Plugin$0 {
|
|
|
318
324
|
if ((o.colspan ?? 1) != 1) return
|
|
319
325
|
const { x } = o
|
|
320
326
|
store.ths[x] = el()
|
|
321
|
-
|
|
327
|
+
store.thObs.observe(el())
|
|
328
|
+
onCleanup(() => {
|
|
329
|
+
store.thSizes[x] = store.ths[x] = void 0
|
|
330
|
+
store.thObs.unobserve(el())
|
|
331
|
+
})
|
|
322
332
|
})
|
|
323
333
|
|
|
324
334
|
return <Th {...mProps}>{o.children}</Th>
|
|
@@ -330,8 +340,6 @@ function BasePlugin(): Plugin$0 {
|
|
|
330
340
|
{ get class() { return unFn(props.cellClass, o) }, get style() { return unFn(props.cellStyle, o) } },
|
|
331
341
|
{ get class() { return o.col.class }, get style() { return o.col.style } },
|
|
332
342
|
{ get style() { return o.col.width ? `width: ${o.col.width}px` : '' } },
|
|
333
|
-
// todo
|
|
334
|
-
() => store.props.tdProps?.(o) || {}
|
|
335
343
|
)
|
|
336
344
|
return <Td {...mProps}>{o.children}</Td>
|
|
337
345
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createEffect } from 'solid-js'
|
|
2
|
-
import {
|
|
2
|
+
import { type Plugin } from '..'
|
|
3
3
|
|
|
4
4
|
declare module '../index' {
|
|
5
5
|
interface TableProps {
|
|
@@ -37,26 +37,62 @@ export const ClipboardPlugin: Plugin = {
|
|
|
37
37
|
commands: store => ({
|
|
38
38
|
copy: () => {
|
|
39
39
|
const { start, end } = store.selected
|
|
40
|
-
if (start
|
|
40
|
+
if (!start?.length) return
|
|
41
41
|
const [x1, x2] = [start[0], end[0]].sort((a, b) => a - b)
|
|
42
42
|
const [y1, y2] = [start[1], end[1]].sort((a, b) => a - b)
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
const
|
|
43
|
+
// Skip internal columns (index, row-selection, etc.)
|
|
44
|
+
const cols = store.props!.columns!.slice(x1, x2 + 1).filter(col => !col[store.internal])
|
|
45
|
+
const rows = store.props!.data!.slice(y1, y2 + 1)
|
|
46
|
+
const text = rows.map(row =>
|
|
47
|
+
cols.map(col => {
|
|
48
|
+
const val = row[col.id as string] ?? ''
|
|
49
|
+
// Escape in-cell tabs/newlines so TSV structure is preserved
|
|
50
|
+
return String(val).replace(/[\t\r\n]/g, ' ')
|
|
51
|
+
}).join('\t')
|
|
52
|
+
).join('\n')
|
|
46
53
|
navigator.clipboard.writeText(text)
|
|
47
54
|
},
|
|
48
55
|
paste: async () => {
|
|
49
56
|
const { start, end } = store.selected
|
|
50
|
-
if (start
|
|
57
|
+
if (!start?.length) return
|
|
51
58
|
const text = await navigator.clipboard.readText()
|
|
52
|
-
|
|
53
|
-
const
|
|
59
|
+
// Normalise CRLF (Excel) and CR (old Mac) line endings; trim trailing newline
|
|
60
|
+
const arr2 = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').replace(/\n$/, '').split('\n').map(r => r.split('\t'))
|
|
61
|
+
const clipH = arr2.length
|
|
62
|
+
const clipW = arr2[0].length
|
|
63
|
+
|
|
64
|
+
const [x1, x2] = [start[0], end[0]].sort((a, b) => a - b)
|
|
65
|
+
const [y1, y2] = [start[1], end[1]].sort((a, b) => a - b)
|
|
66
|
+
const selH = y2 - y1 + 1
|
|
67
|
+
const selW = x2 - x1 + 1
|
|
68
|
+
// Tile clipboard to fill the selection when it is an exact multiple
|
|
69
|
+
const pasteH = selH > clipH && selH % clipH === 0 ? selH : clipH
|
|
70
|
+
const pasteW = selW > clipW && selW % clipW === 0 ? selW : clipW
|
|
71
|
+
|
|
72
|
+
// Collect target user columns starting from x1 (skip internals), up to pasteW
|
|
73
|
+
const allCols = store.props!.columns!
|
|
74
|
+
const targetCols: typeof allCols = []
|
|
75
|
+
for (let i = x1; i < allCols.length && targetCols.length < pasteW; i++) {
|
|
76
|
+
if (!allCols[i][store.internal]) targetCols.push(allCols[i])
|
|
77
|
+
}
|
|
78
|
+
|
|
54
79
|
const data = store.props!.data!.slice()
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
80
|
+
const maxY = Math.min(y1 + pasteH - 1, data.length - 1)
|
|
81
|
+
for (let dy = 0; dy <= maxY - y1; dy++) {
|
|
82
|
+
const patch: Record<string, any> = {}
|
|
83
|
+
targetCols.forEach((col, dx) => {
|
|
84
|
+
patch[col.id as string] = arr2[dy % clipH][dx % clipW]
|
|
85
|
+
})
|
|
86
|
+
data[y1 + dy] = { ...data[y1 + dy], ...patch }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Expand selection to cover the pasted region
|
|
90
|
+
let endX = x1
|
|
91
|
+
let userCount = 0
|
|
92
|
+
for (let i = x1; i < allCols.length && userCount < targetCols.length; i++) {
|
|
93
|
+
if (!allCols[i][store.internal]) { endX = i; userCount++ }
|
|
94
|
+
}
|
|
95
|
+
store.selected.end = [endX, maxY]
|
|
60
96
|
store.props!.onDataChange?.(data)
|
|
61
97
|
},
|
|
62
98
|
})
|
|
@@ -10,9 +10,15 @@ import { log } from '../utils'
|
|
|
10
10
|
declare module '../index' {
|
|
11
11
|
interface TableProps {
|
|
12
12
|
diff?: {
|
|
13
|
-
/** @default
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
/** @default false */
|
|
14
|
+
enable?: boolean
|
|
15
|
+
data?: any[]
|
|
16
|
+
/** @default true */
|
|
17
|
+
added?: boolean
|
|
18
|
+
/** @default true */
|
|
19
|
+
removed?: boolean
|
|
20
|
+
/** @default true */
|
|
21
|
+
changed?: boolean
|
|
16
22
|
onCommit?: (data: any, opt: { added: any[], removed: any[], changed: any[] }) => any
|
|
17
23
|
}
|
|
18
24
|
}
|
|
@@ -35,7 +41,8 @@ export const DiffPlugin: Plugin = {
|
|
|
35
41
|
data.forEach(row => unwrap(row)[store.rawProps.rowKey] ??= uuid())
|
|
36
42
|
return {
|
|
37
43
|
diffData: structuredClone(unwrap(data || [])),
|
|
38
|
-
|
|
44
|
+
diffData2: () => store.props.diff?.data ?? store.diffData,
|
|
45
|
+
diffDataKeyed: createLazyMemo(() => keyBy(store.diffData2(), e => e[store.props!.rowKey]))
|
|
39
46
|
}
|
|
40
47
|
},
|
|
41
48
|
commands: store => ({
|
|
@@ -50,7 +57,7 @@ export const DiffPlugin: Plugin = {
|
|
|
50
57
|
if (!old) added.push(e)
|
|
51
58
|
else if (!isEqual(e, old)) changed.push(e)
|
|
52
59
|
}
|
|
53
|
-
for (const e of store.
|
|
60
|
+
for (const e of store.diffData2()) {
|
|
54
61
|
!keyed[e[rowKey]] && removed.push(e)
|
|
55
62
|
}
|
|
56
63
|
await store.props!.diff?.onCommit?.(data, { added, removed, changed })
|
|
@@ -60,14 +67,17 @@ export const DiffPlugin: Plugin = {
|
|
|
60
67
|
}),
|
|
61
68
|
rewriteProps: {
|
|
62
69
|
diff: ({ diff }) => ({
|
|
70
|
+
enable: false,
|
|
63
71
|
added: true,
|
|
64
72
|
removed: true,
|
|
65
73
|
changed: true,
|
|
66
74
|
...diff
|
|
67
75
|
}),
|
|
68
76
|
data: ({ data }, { store }) => {
|
|
77
|
+
if (!store.props.diff?.enable) return data
|
|
78
|
+
|
|
69
79
|
const { rowKey, diff } = store.props || {}
|
|
70
|
-
const diffData = store.
|
|
80
|
+
const diffData = store.diffData2() || []
|
|
71
81
|
|
|
72
82
|
// Fast path: same number of rows, same keys in same order (edit-only, no add/delete/move).
|
|
73
83
|
// Skips the O(n²) diffArrays call which is the common case when only cell values changae.
|
|
@@ -88,18 +98,21 @@ export const DiffPlugin: Plugin = {
|
|
|
88
98
|
e.value
|
|
89
99
|
))
|
|
90
100
|
},
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
Td: ({ Td }, { store }) => !store.props.diff?.enable ? Td : o => {
|
|
102
|
+
o = combineProps(o, {
|
|
103
|
+
get class() {
|
|
104
|
+
const { diff } = store.props
|
|
105
|
+
const id = o.data[store.props!.rowKey]
|
|
106
|
+
return [
|
|
107
|
+
o.data[NEW] ? 'bg-#dafaea!' :
|
|
108
|
+
o.data[DEL] ? 'bg-#ffe8e8!' :
|
|
109
|
+
o.data[store.internal] ? '' :
|
|
110
|
+
diff!.changed && o.data[o.col.id] != store.diffDataKeyed()[id]?.[o.col.id] ? 'bg-#dafaea!' : ''
|
|
111
|
+
].join(' ')
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
return <Td {...o} />
|
|
115
|
+
},
|
|
103
116
|
},
|
|
104
117
|
keybindings: (store) => ({
|
|
105
118
|
'$mod+S': () => store.commands.diffCommit(),
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* intable — Dark (OLED) Theme
|
|
3
|
+
* Deep black background, high contrast, WCAG AAA compliant
|
|
4
|
+
* Best for: developer tools, night mode, coding platforms
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.data-table {
|
|
8
|
+
--bg: #0d1117;
|
|
9
|
+
--c-primary: #388bfd;
|
|
10
|
+
|
|
11
|
+
--menu-bg: #161b22;
|
|
12
|
+
--li-hover-bg: rgba(177, 186, 196, 0.12);
|
|
13
|
+
|
|
14
|
+
--table-b: 1px solid var(--table-b-c);
|
|
15
|
+
--table-b-c: #30363d;
|
|
16
|
+
--table-c: #e6edf3;
|
|
17
|
+
--table-bg: #0d1117;
|
|
18
|
+
|
|
19
|
+
--table-header-c: #8b949e;
|
|
20
|
+
--table-header-bg: #161b22;
|
|
21
|
+
|
|
22
|
+
--table-row-hover-bg: #161b22;
|
|
23
|
+
|
|
24
|
+
--select-area-bg: #388bfd1f;
|
|
25
|
+
|
|
26
|
+
color-scheme: dark;
|
|
27
|
+
font-size: 13px;
|
|
28
|
+
|
|
29
|
+
th, td {
|
|
30
|
+
padding: 8px 12px;
|
|
31
|
+
line-height: 20px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&--small {
|
|
35
|
+
font-size: 12px;
|
|
36
|
+
|
|
37
|
+
th, td {
|
|
38
|
+
padding: 4px 8px;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
thead th {
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
letter-spacing: 0.01em;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* intable — GitHub Theme
|
|
3
|
+
* Matches GitHub's Primer design system — light & dark surfaces
|
|
4
|
+
* Best for: developer tools, docs sites, code-adjacent UIs
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.data-table {
|
|
8
|
+
--bg: #ffffff;
|
|
9
|
+
--c-primary: #0969da;
|
|
10
|
+
|
|
11
|
+
--menu-bg: #ffffff;
|
|
12
|
+
--li-hover-bg: #f3f4f6;
|
|
13
|
+
|
|
14
|
+
--table-b: 1px solid var(--table-b-c);
|
|
15
|
+
--table-b-c: #d0d7de;
|
|
16
|
+
--table-c: #1f2328;
|
|
17
|
+
--table-bg: #ffffff;
|
|
18
|
+
|
|
19
|
+
--table-header-c: #636c76;
|
|
20
|
+
--table-header-bg: #f6f8fa;
|
|
21
|
+
|
|
22
|
+
--table-row-hover-bg: #f6f8fa;
|
|
23
|
+
|
|
24
|
+
--select-area-bg: #0969da1a;
|
|
25
|
+
|
|
26
|
+
font-size: 14px;
|
|
27
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
|
|
28
|
+
|
|
29
|
+
th, td {
|
|
30
|
+
padding: 8px 12px;
|
|
31
|
+
line-height: 1.5;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
thead th {
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
white-space: nowrap;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
tbody tr:nth-child(even) td {
|
|
40
|
+
background-color: #f6f8fa;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
tbody tr:nth-child(even):hover td {
|
|
44
|
+
background-color: var(--table-row-hover-bg);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
&--small {
|
|
48
|
+
font-size: 12px;
|
|
49
|
+
|
|
50
|
+
th, td {
|
|
51
|
+
padding: 4px 8px;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Dark (GitHub Dark Default)
|
|
56
|
+
&.dark, [data-theme="dark"] & {
|
|
57
|
+
--bg: #0d1117;
|
|
58
|
+
--c-primary: #388bfd;
|
|
59
|
+
|
|
60
|
+
--menu-bg: #161b22;
|
|
61
|
+
--li-hover-bg: rgba(177, 186, 196, 0.12);
|
|
62
|
+
|
|
63
|
+
--table-b-c: #30363d;
|
|
64
|
+
--table-c: #e6edf3;
|
|
65
|
+
--table-bg: #0d1117;
|
|
66
|
+
|
|
67
|
+
--table-header-c: #8b949e;
|
|
68
|
+
--table-header-bg: #161b22;
|
|
69
|
+
|
|
70
|
+
--table-row-hover-bg: #161b22;
|
|
71
|
+
|
|
72
|
+
--select-area-bg: #388bfd1f;
|
|
73
|
+
|
|
74
|
+
color-scheme: dark;
|
|
75
|
+
|
|
76
|
+
tbody tr:nth-child(even) td {
|
|
77
|
+
background-color: #161b22;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* intable — Material Design 3 Theme
|
|
3
|
+
* Google Material You / M3 surface tones and typography
|
|
4
|
+
* Best for: Android-style web apps, admin panels, data management UIs
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.data-table {
|
|
8
|
+
--bg: #fffbfe;
|
|
9
|
+
--c-primary: #6750a4;
|
|
10
|
+
|
|
11
|
+
--menu-bg: #ece6f0;
|
|
12
|
+
--li-hover-bg: rgba(103, 80, 164, 0.08);
|
|
13
|
+
|
|
14
|
+
--table-b: 1px solid var(--table-b-c);
|
|
15
|
+
--table-b-c: #cac4d0;
|
|
16
|
+
--table-c: #1c1b1f;
|
|
17
|
+
--table-bg: #fffbfe;
|
|
18
|
+
|
|
19
|
+
--table-header-c: #49454f;
|
|
20
|
+
--table-header-bg: #fffbfe;
|
|
21
|
+
|
|
22
|
+
--table-row-hover-bg: rgba(103, 80, 164, 0.08);
|
|
23
|
+
|
|
24
|
+
--select-area-bg: rgba(103, 80, 164, 0.12);
|
|
25
|
+
|
|
26
|
+
font-size: 14px;
|
|
27
|
+
font-family: 'Roboto', sans-serif;
|
|
28
|
+
|
|
29
|
+
th, td {
|
|
30
|
+
padding: 10px 16px;
|
|
31
|
+
line-height: 20px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
thead th {
|
|
35
|
+
font-size: 12px;
|
|
36
|
+
font-weight: 500;
|
|
37
|
+
letter-spacing: 0.02em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
tr:not(:last-child) td {
|
|
41
|
+
border-bottom: 1px solid var(--table-b-c);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&--small {
|
|
45
|
+
font-size: 12px;
|
|
46
|
+
|
|
47
|
+
th, td {
|
|
48
|
+
padding: 6px 12px;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Dark variant (M3 dark)
|
|
53
|
+
&.dark, [data-theme="dark"] & {
|
|
54
|
+
--bg: #1c1b1f;
|
|
55
|
+
--c-primary: #d0bcff;
|
|
56
|
+
|
|
57
|
+
--menu-bg: #2b2930;
|
|
58
|
+
--li-hover-bg: rgba(208, 188, 255, 0.08);
|
|
59
|
+
|
|
60
|
+
--table-b-c: #49454f;
|
|
61
|
+
--table-c: #e6e1e5;
|
|
62
|
+
--table-bg: #1c1b1f;
|
|
63
|
+
|
|
64
|
+
--table-header-c: #cac4d0;
|
|
65
|
+
--table-header-bg: #1c1b1f;
|
|
66
|
+
|
|
67
|
+
--table-row-hover-bg: rgba(208, 188, 255, 0.08);
|
|
68
|
+
|
|
69
|
+
--select-area-bg: rgba(208, 188, 255, 0.12);
|
|
70
|
+
|
|
71
|
+
color-scheme: dark;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* intable — Shadcn/Zinc Theme
|
|
3
|
+
* Neutral zinc/slate tones, clean minimal, matches shadcn/ui palette
|
|
4
|
+
* Best for: modern SaaS dashboards, admin panels, clean productivity tools
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.data-table {
|
|
8
|
+
--bg: #ffffff;
|
|
9
|
+
--c-primary: #18181b;
|
|
10
|
+
|
|
11
|
+
--menu-bg: #ffffff;
|
|
12
|
+
--li-hover-bg: #f4f4f5;
|
|
13
|
+
|
|
14
|
+
--table-b: 1px solid var(--table-b-c);
|
|
15
|
+
--table-b-c: #e4e4e7;
|
|
16
|
+
--table-c: #09090b;
|
|
17
|
+
--table-bg: #ffffff;
|
|
18
|
+
|
|
19
|
+
--table-header-c: #71717a;
|
|
20
|
+
--table-header-bg: #ffffff;
|
|
21
|
+
|
|
22
|
+
--table-row-hover-bg: #fafafa;
|
|
23
|
+
|
|
24
|
+
--select-area-bg: #18181b14;
|
|
25
|
+
|
|
26
|
+
font-size: 14px;
|
|
27
|
+
|
|
28
|
+
th, td {
|
|
29
|
+
padding: 10px 12px;
|
|
30
|
+
line-height: 20px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
thead th {
|
|
34
|
+
font-weight: 500;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&--small {
|
|
38
|
+
font-size: 13px;
|
|
39
|
+
|
|
40
|
+
th, td {
|
|
41
|
+
padding: 6px 10px;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Dark mode variant
|
|
46
|
+
&.dark, [data-theme="dark"] & {
|
|
47
|
+
--bg: #09090b;
|
|
48
|
+
--c-primary: #fafafa;
|
|
49
|
+
|
|
50
|
+
--menu-bg: #09090b;
|
|
51
|
+
--li-hover-bg: #27272a;
|
|
52
|
+
|
|
53
|
+
--table-b-c: #27272a;
|
|
54
|
+
--table-c: #fafafa;
|
|
55
|
+
--table-bg: #09090b;
|
|
56
|
+
|
|
57
|
+
--table-header-c: #71717a;
|
|
58
|
+
--table-header-bg: #09090b;
|
|
59
|
+
|
|
60
|
+
--table-row-hover-bg: #18181b;
|
|
61
|
+
|
|
62
|
+
--select-area-bg: #ffffff14;
|
|
63
|
+
|
|
64
|
+
color-scheme: dark;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* intable — Stripe Theme
|
|
3
|
+
* Ultra-clean minimal white, tight spacing, strong typographic hierarchy
|
|
4
|
+
* Best for: fintech, e-commerce, financial dashboards, data-dense UIs
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.data-table {
|
|
8
|
+
--bg: #ffffff;
|
|
9
|
+
--c-primary: #635bff;
|
|
10
|
+
|
|
11
|
+
--menu-bg: #ffffff;
|
|
12
|
+
--li-hover-bg: #f6f8fa;
|
|
13
|
+
|
|
14
|
+
--table-b: 1px solid var(--table-b-c);
|
|
15
|
+
--table-b-c: #e3e8ee;
|
|
16
|
+
--table-c: #0a2540;
|
|
17
|
+
--table-bg: #ffffff;
|
|
18
|
+
|
|
19
|
+
--table-header-c: #425466;
|
|
20
|
+
--table-header-bg: #f7fafc;
|
|
21
|
+
|
|
22
|
+
--table-row-hover-bg: #f7fafc;
|
|
23
|
+
|
|
24
|
+
--select-area-bg: #635bff1a;
|
|
25
|
+
|
|
26
|
+
font-size: 13.5px;
|
|
27
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
28
|
+
|
|
29
|
+
th, td {
|
|
30
|
+
padding: 9px 14px;
|
|
31
|
+
line-height: 20px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
thead th {
|
|
35
|
+
font-size: 11.5px;
|
|
36
|
+
font-weight: 600;
|
|
37
|
+
text-transform: uppercase;
|
|
38
|
+
letter-spacing: 0.04em;
|
|
39
|
+
color: var(--table-header-c);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&--small {
|
|
43
|
+
font-size: 12.5px;
|
|
44
|
+
|
|
45
|
+
th, td {
|
|
46
|
+
padding: 5px 10px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
thead th {
|
|
50
|
+
font-size: 11px;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.row-selection {
|
|
55
|
+
width: 38px;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intable/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
|
+
"license": "MIT",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"main": "./dist/index.js",
|
|
6
7
|
"module": "./dist/index.js",
|
|
7
8
|
"types": "./dist/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
|
-
".":
|
|
10
|
-
|
|
11
|
-
"import": "./dist
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
".": "./dist/index.js",
|
|
11
|
+
"./*": {
|
|
12
|
+
"import": "./dist/*.js",
|
|
13
|
+
"types": "./dist/*.d.ts"
|
|
14
|
+
}
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
17
|
"dist"
|
|
@@ -20,12 +21,16 @@
|
|
|
20
21
|
"solid-js": "^1.9.9"
|
|
21
22
|
},
|
|
22
23
|
"peerDependencies": {
|
|
23
|
-
"react": "^18
|
|
24
|
-
"react-dom": "^18
|
|
24
|
+
"react": "^18.0.0 || ^19.0.0 || ^20.0.0",
|
|
25
|
+
"react-dom": "^18.0.0 || ^19.0.0 || ^20.0.0"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@types/react": "^18",
|
|
28
29
|
"@types/react-dom": "^18",
|
|
29
30
|
"antd": "^5.22.5"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public",
|
|
34
|
+
"registry": "https://registry.npmjs.org/"
|
|
30
35
|
}
|
|
31
36
|
}
|
package/scripts/publish.js
CHANGED
|
@@ -57,7 +57,7 @@ function publishPackage(pkg) {
|
|
|
57
57
|
console.log(`\n📤 Publishing ${pkg.name}...`)
|
|
58
58
|
|
|
59
59
|
try {
|
|
60
|
-
execSync(`pnpm publish --no-git-checks --filter ${pkg.name}`, { stdio: 'inherit' })
|
|
60
|
+
execSync(`pnpm publish --no-git-checks --filter ${pkg.name}`, { cwd: rootDir, stdio: 'inherit' })
|
|
61
61
|
console.log(` ✅ ${pkg.name} published successfully!`)
|
|
62
62
|
} catch (error) {
|
|
63
63
|
console.error(` ❌ Failed to publish ${pkg.name}:`, error.message)
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { render, Suspense } from 'solid-js/web'
|
|
2
|
+
import { HashRouter } from '@solidjs/router'
|
|
3
|
+
import routes from '~solid-pages'
|
|
4
|
+
|
|
5
|
+
render(
|
|
6
|
+
() => {
|
|
7
|
+
return (
|
|
8
|
+
<HashRouter
|
|
9
|
+
root={props => (
|
|
10
|
+
<Suspense>
|
|
11
|
+
{props.children}
|
|
12
|
+
</Suspense>
|
|
13
|
+
)}
|
|
14
|
+
>
|
|
15
|
+
{routes}
|
|
16
|
+
</HashRouter>
|
|
17
|
+
)
|
|
18
|
+
},
|
|
19
|
+
document.getElementById('root') as HTMLElement,
|
|
20
|
+
)
|