@smallwebco/tinypivot-react 1.0.79 → 1.0.81
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/README.md +91 -1
- package/dist/index.cjs +14 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -5
- package/dist/index.d.ts +7 -5
- package/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/dist/style.css +727 -900
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -45,6 +45,96 @@ export default function App() {
|
|
|
45
45
|
}
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
## Theming
|
|
49
|
+
|
|
50
|
+
TinyPivot ships 22 themes — 2 neutral (`light`, `dark`) plus 10 brand themes each with a light and dark variant. Themes are applied via the `theme` prop on `DataGrid`.
|
|
51
|
+
|
|
52
|
+
### Quick start
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
<DataGrid data={data} theme="slate-dark" />
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`theme="auto"` resolves to `'light'` or `'dark'` based on the user's system preference (`prefers-color-scheme`).
|
|
59
|
+
|
|
60
|
+
### Available themes
|
|
61
|
+
|
|
62
|
+
| Theme | Accent | Vibe |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `light` / `dark` / `auto` | indigo / violet | TinyPivot defaults — neutral cool grays |
|
|
65
|
+
| `slate` / `slate-dark` | `#4f46e5` indigo | Linear / Stripe — cool neutral |
|
|
66
|
+
| `zinc` / `zinc-dark` | near-mono | Vercel / Anthropic — minimalist |
|
|
67
|
+
| `indigo` / `indigo-dark` | `#6366f1` vivid indigo | Premium SaaS |
|
|
68
|
+
| `violet` / `violet-dark` | `#8b5cf6` purple | Data viz / AI tools |
|
|
69
|
+
| `emerald` / `emerald-dark` | `#10b981` green | Fintech / finance |
|
|
70
|
+
| `sky` / `sky-dark` | `#0ea5e9` light blue | Productivity / airy |
|
|
71
|
+
| `rose` / `rose-dark` | `#f43f5e` warm pink | Friendly / creator |
|
|
72
|
+
| `amber` / `amber-dark` | `#f59e0b` warm orange | Energy / wellness |
|
|
73
|
+
| `solar` / `solar-dark` | `#b58900` mustard | Solarized-inspired warm cream + dark teal |
|
|
74
|
+
| `mono` / `mono-dark` | `#000` / `#fff` | Editorial — pure grayscale, high contrast |
|
|
75
|
+
|
|
76
|
+
### Custom themes
|
|
77
|
+
|
|
78
|
+
Brand themes redefine ~25 CSS custom property tokens at the grid root. You can override these in your own CSS to create a custom theme:
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import './my-brand.css'
|
|
82
|
+
|
|
83
|
+
<DataGrid data={data} theme="light" className="my-brand" />
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```css
|
|
87
|
+
/* my-brand.css */
|
|
88
|
+
.vpg-data-grid.my-brand {
|
|
89
|
+
--vpg-accent: #ff6b35;
|
|
90
|
+
--vpg-accent-hover: #e55426;
|
|
91
|
+
--vpg-surface-bg: #fafaf7;
|
|
92
|
+
--vpg-surface-panel: #f0eee7;
|
|
93
|
+
/* …override any of the tokens below */
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Token reference** — these are the variables you can override:
|
|
98
|
+
|
|
99
|
+
- **Surfaces**: `--vpg-surface-bg`, `--vpg-surface-panel`, `--vpg-surface-elevated`, `--vpg-surface-hover`, `--vpg-surface-selected`, `--vpg-surface-striped`
|
|
100
|
+
- **Text**: `--vpg-text-primary`, `--vpg-text-secondary`, `--vpg-text-muted`, `--vpg-text-inverse`
|
|
101
|
+
- **Borders**: `--vpg-border-default`, `--vpg-border-strong`, `--vpg-border-subtle`
|
|
102
|
+
- **Accent**: `--vpg-accent`, `--vpg-accent-hover`, `--vpg-accent-soft-bg`, `--vpg-accent-soft-text`, `--vpg-focus-ring`
|
|
103
|
+
- **States**: `--vpg-state-error`, `--vpg-state-warning`, `--vpg-state-success`, `--vpg-state-info`
|
|
104
|
+
- **Scrollbar**: `--vpg-scrollbar-thumb`, `--vpg-scrollbar-track`
|
|
105
|
+
|
|
106
|
+
Custom theme classes layer on top of any preset, so you can start from `theme="dark"` and tweak just the accent, for example.
|
|
107
|
+
|
|
108
|
+
### Adding a theme switcher
|
|
109
|
+
|
|
110
|
+
Let users pick their own theme — bind a state value to a `<select>`:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { DataGrid } from '@smallwebco/tinypivot-react'
|
|
114
|
+
import '@smallwebco/tinypivot-react/style.css'
|
|
115
|
+
import { useState } from 'react'
|
|
116
|
+
|
|
117
|
+
type Theme = 'light' | 'dark' | 'slate' | 'slate-dark' | 'emerald' | 'emerald-dark'
|
|
118
|
+
|
|
119
|
+
export function MyGrid({ data }) {
|
|
120
|
+
const [theme, setTheme] = useState<Theme>('dark')
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<>
|
|
124
|
+
<select value={theme} onChange={e => setTheme(e.target.value as Theme)}>
|
|
125
|
+
<option value="light">Light</option>
|
|
126
|
+
<option value="dark">Dark</option>
|
|
127
|
+
<option value="slate-dark">Slate (dark)</option>
|
|
128
|
+
<option value="emerald-dark">Emerald (dark)</option>
|
|
129
|
+
{/* …add more themes */}
|
|
130
|
+
</select>
|
|
131
|
+
|
|
132
|
+
<DataGrid data={data} theme={theme} />
|
|
133
|
+
</>
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
48
138
|
## Features
|
|
49
139
|
|
|
50
140
|
| Feature | Free | Pro |
|
|
@@ -79,7 +169,7 @@ export default function App() {
|
|
|
79
169
|
| `pageSize` | `number` | `50` | Rows per page |
|
|
80
170
|
| `enableColumnResize` | `boolean` | `true` | Drag to resize columns |
|
|
81
171
|
| `enableClipboard` | `boolean` | `true` | Ctrl+C to copy cells |
|
|
82
|
-
| `theme` | `
|
|
172
|
+
| `theme` | `string` | `'light'` | Color theme — see [Theming](#theming) for the full list (22 presets) |
|
|
83
173
|
| `numberFormat` | `'us' \| 'eu' \| 'plain'` | `'us'` | Number display format: US (1,234.56), EU (1.234,56), plain (1234.56) |
|
|
84
174
|
| `dateFormat` | `'us' \| 'eu' \| 'iso'` | `'iso'` | Date display format: US (MM/DD/YYYY), EU (DD/MM/YYYY), ISO (YYYY-MM-DD) |
|
|
85
175
|
| `fieldRoleOverrides` | `Record<string, FieldRole>` | `undefined` | Override auto-detected chart field roles per column (`'dimension'` \| `'measure'` \| `'temporal'`) |
|
package/dist/index.cjs
CHANGED
|
@@ -832,6 +832,7 @@ var AIAnalyst = (0, import_react2.forwardRef)(({
|
|
|
832
832
|
onQueryExecuted,
|
|
833
833
|
onError
|
|
834
834
|
});
|
|
835
|
+
const isDarkTheme = theme === "dark" || typeof theme === "string" && theme.endsWith("-dark");
|
|
835
836
|
(0, import_react2.useImperativeHandle)(ref, () => ({
|
|
836
837
|
loadFullData,
|
|
837
838
|
selectedDataSource
|
|
@@ -993,7 +994,7 @@ var AIAnalyst = (0, import_react2.forwardRef)(({
|
|
|
993
994
|
return !!message.metadata?.data && message.metadata.data.length > 0;
|
|
994
995
|
};
|
|
995
996
|
if (!selectedDataSource) {
|
|
996
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `vpg-ai-analyst ${
|
|
997
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `vpg-ai-analyst ${isDarkTheme ? "vpg-theme-dark" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "vpg-ai-picker-fullscreen", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "vpg-ai-picker-content", children: [
|
|
997
998
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "vpg-ai-picker-header", children: [
|
|
998
999
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "vpg-ai-icon-lg", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
999
1000
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2z" }),
|
|
@@ -1065,7 +1066,7 @@ var AIAnalyst = (0, import_react2.forwardRef)(({
|
|
|
1065
1066
|
] })
|
|
1066
1067
|
] }) }) });
|
|
1067
1068
|
}
|
|
1068
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `vpg-ai-analyst ${
|
|
1069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `vpg-ai-analyst ${isDarkTheme ? "vpg-theme-dark" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "vpg-ai-split-layout", children: [
|
|
1069
1070
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "vpg-ai-chat-panel", children: [
|
|
1070
1071
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "vpg-ai-chat-header", children: [
|
|
1071
1072
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1795,7 +1796,7 @@ function ChartBuilder({
|
|
|
1795
1796
|
return val.toFixed(dec);
|
|
1796
1797
|
}, []);
|
|
1797
1798
|
const chartOptions = (0, import_react4.useMemo)(() => {
|
|
1798
|
-
const isDark = theme === "dark";
|
|
1799
|
+
const isDark = theme === "dark" || typeof theme === "string" && theme.endsWith("-dark");
|
|
1799
1800
|
const config = chartConfig;
|
|
1800
1801
|
const options = config.options || {};
|
|
1801
1802
|
const baseOptions = {
|
|
@@ -3884,7 +3885,8 @@ function PivotConfig({
|
|
|
3884
3885
|
onAddColumnField,
|
|
3885
3886
|
onAddCalculatedField,
|
|
3886
3887
|
onRemoveCalculatedField,
|
|
3887
|
-
onUpdateCalculatedField
|
|
3888
|
+
onUpdateCalculatedField,
|
|
3889
|
+
theme
|
|
3888
3890
|
}) {
|
|
3889
3891
|
const [fieldSearch, setFieldSearch] = (0, import_react12.useState)("");
|
|
3890
3892
|
const [showCalcModal, setShowCalcModal] = (0, import_react12.useState)(false);
|
|
@@ -4010,7 +4012,7 @@ function PivotConfig({
|
|
|
4010
4012
|
setShowCalcModal(false);
|
|
4011
4013
|
setEditingCalcField(null);
|
|
4012
4014
|
}, []);
|
|
4013
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className:
|
|
4015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `vpg-pivot-config ${theme ? `vpg-theme-${theme}` : ""}`, children: [
|
|
4014
4016
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "vpg-config-header", children: [
|
|
4015
4017
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("h3", { className: "vpg-config-title", children: [
|
|
4016
4018
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -4278,7 +4280,8 @@ function PivotSkeleton({
|
|
|
4278
4280
|
onAddValueField,
|
|
4279
4281
|
onRemoveValueField,
|
|
4280
4282
|
onReorderRowFields,
|
|
4281
|
-
onReorderColumnFields
|
|
4283
|
+
onReorderColumnFields,
|
|
4284
|
+
theme
|
|
4282
4285
|
}) {
|
|
4283
4286
|
const { showWatermark, canUsePivot, isDemo } = useLicense();
|
|
4284
4287
|
const getValueFieldDisplayName = (0, import_react13.useCallback)((field) => {
|
|
@@ -4644,7 +4647,7 @@ function PivotSkeleton({
|
|
|
4644
4647
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
4645
4648
|
"div",
|
|
4646
4649
|
{
|
|
4647
|
-
className: `vpg-pivot-skeleton vpg-font-${currentFontSize} ${draggingField ? "vpg-is-dragging" : ""}`,
|
|
4650
|
+
className: `vpg-pivot-skeleton vpg-font-${currentFontSize} ${theme ? `vpg-theme-${theme}` : ""} ${draggingField ? "vpg-is-dragging" : ""}`,
|
|
4648
4651
|
children: [
|
|
4649
4652
|
showCopyToast && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "vpg-toast", children: [
|
|
4650
4653
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { className: "vpg-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }),
|
|
@@ -6195,7 +6198,8 @@ function DataGrid({
|
|
|
6195
6198
|
onRemoveValueField: removeValueField,
|
|
6196
6199
|
onAddCalculatedField: addCalculatedField,
|
|
6197
6200
|
onRemoveCalculatedField: removeCalculatedField,
|
|
6198
|
-
onUpdateCalculatedField: addCalculatedField
|
|
6201
|
+
onUpdateCalculatedField: addCalculatedField,
|
|
6202
|
+
theme: currentTheme
|
|
6199
6203
|
}
|
|
6200
6204
|
) }),
|
|
6201
6205
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `vpg-pivot-main ${!showPivotConfig ? "vpg-full-width" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
@@ -6220,7 +6224,8 @@ function DataGrid({
|
|
|
6220
6224
|
onRemoveValueField: removeValueField,
|
|
6221
6225
|
onUpdateAggregation: updateValueFieldAggregation,
|
|
6222
6226
|
onReorderRowFields: setRowFields,
|
|
6223
|
-
onReorderColumnFields: setColumnFields
|
|
6227
|
+
onReorderColumnFields: setColumnFields,
|
|
6228
|
+
theme: currentTheme
|
|
6224
6229
|
}
|
|
6225
6230
|
) })
|
|
6226
6231
|
] }),
|