@siyahi/ui 0.1.9-next.2 → 0.1.9-next.21
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/DESIGN.md +30 -0
- package/README.md +82 -176
- package/THIRD_PARTY_NOTICES.md +11 -11
- package/agents/examples/accordion.tsx +39 -0
- package/agents/examples/alert.tsx +23 -0
- package/agents/examples/app-sidebar.tsx +38 -0
- package/agents/examples/avatar.tsx +14 -0
- package/agents/examples/badge.tsx +18 -0
- package/agents/examples/bar-list-labels.tsx +22 -0
- package/agents/examples/bar-list-sides.tsx +38 -0
- package/agents/examples/bar-list.tsx +24 -0
- package/agents/examples/breadcrumb.tsx +28 -0
- package/agents/examples/button-states.tsx +23 -0
- package/agents/examples/button.tsx +21 -0
- package/agents/examples/calendar.tsx +15 -0
- package/agents/examples/callout.tsx +33 -0
- package/agents/examples/card.tsx +34 -0
- package/agents/examples/change-bar.tsx +104 -0
- package/agents/examples/chart-area.tsx +39 -0
- package/agents/examples/chart-bar-flows.tsx +32 -0
- package/agents/examples/chart-bar-hourly.tsx +28 -0
- package/agents/examples/chart-bar-losses.tsx +29 -0
- package/agents/examples/chart-bar-sectors.tsx +72 -0
- package/agents/examples/chart-bar-years.tsx +40 -0
- package/agents/examples/chart-bar.tsx +56 -0
- package/agents/examples/chart-category-ticks.tsx +50 -0
- package/agents/examples/chart-line-events.tsx +47 -0
- package/agents/examples/chart-line-timeline.tsx +41 -0
- package/agents/examples/chart-line.tsx +57 -0
- package/agents/examples/code-block.tsx +38 -0
- package/agents/examples/collapsible.tsx +16 -0
- package/agents/examples/command.tsx +27 -0
- package/agents/examples/context-menu.tsx +15 -0
- package/agents/examples/copy-button.tsx +8 -0
- package/agents/examples/data-bar.tsx +121 -0
- package/agents/examples/data-table-compact.tsx +95 -0
- package/agents/examples/data-table-filters.tsx +103 -0
- package/agents/examples/data-table.tsx +98 -0
- package/agents/examples/delta.tsx +13 -0
- package/agents/examples/dialog.tsx +28 -0
- package/agents/examples/distribution-bar-budget.tsx +30 -0
- package/agents/examples/distribution-bar-tug.tsx +72 -0
- package/agents/examples/dropdown-menu.tsx +31 -0
- package/agents/examples/formatters.tsx +42 -0
- package/agents/examples/heatmap-calendar.tsx +60 -0
- package/agents/examples/heatmap-status.tsx +57 -0
- package/agents/examples/heatmap-weekday.tsx +75 -0
- package/agents/examples/input-states.tsx +33 -0
- package/agents/examples/input.tsx +17 -0
- package/agents/examples/local-time.tsx +14 -0
- package/agents/examples/metric-strip.tsx +46 -0
- package/agents/examples/overview-dashboard.tsx +18 -0
- package/agents/examples/page-hero.tsx +38 -0
- package/agents/examples/page-section.tsx +52 -0
- package/agents/examples/popover.tsx +23 -0
- package/agents/examples/price-chart.tsx +32 -0
- package/agents/examples/progress-tone.tsx +28 -0
- package/agents/examples/progress.tsx +10 -0
- package/agents/examples/range-position-table.tsx +101 -0
- package/agents/examples/range-position.tsx +53 -0
- package/agents/examples/scroll-area.tsx +20 -0
- package/agents/examples/section-cards-select.tsx +30 -0
- package/agents/examples/section-cards-trend.tsx +30 -0
- package/agents/examples/section-cards.tsx +48 -0
- package/agents/examples/select.tsx +27 -0
- package/agents/examples/separator.tsx +13 -0
- package/agents/examples/sheet.tsx +15 -0
- package/agents/examples/skeleton.tsx +11 -0
- package/agents/examples/slider.tsx +5 -0
- package/agents/examples/surfaces.tsx +116 -0
- package/agents/examples/table.tsx +50 -0
- package/agents/examples/tabs.tsx +16 -0
- package/agents/examples/target-rows.tsx +70 -0
- package/agents/examples/toggle-group.tsx +12 -0
- package/agents/examples/toggle.tsx +11 -0
- package/agents/examples/tooltip.tsx +13 -0
- package/agents/examples/treemap.tsx +88 -0
- package/agents/manifest.json +1081 -0
- package/agents/report-rules.json +7 -0
- package/dist/components/registry/charts/area-chart-card.js +25 -7
- package/dist/components/registry/charts/bar-chart-card.d.ts +0 -1
- package/dist/components/registry/charts/bar-chart-card.js +40 -26
- package/dist/components/registry/charts/line-chart-card.js +2 -2
- package/dist/components/registry/dashboard-01/section-cards.d.ts +2 -0
- package/dist/components/registry/dashboard-01/section-cards.js +42 -35
- package/dist/components/registry/dashboardcn/bar-list.js +18 -11
- package/dist/components/registry/dashboardcn/distribution-bar.js +1 -1
- package/dist/components/registry/dashboardcn/kpi-row-card.d.ts +29 -0
- package/dist/components/registry/dashboardcn/kpi-row-card.js +81 -0
- package/dist/components/registry/dashboardcn/sparkline.d.ts +22 -0
- package/dist/components/registry/dashboardcn/sparkline.js +117 -0
- package/dist/components/registry/heatmap/calendar-heatmap.d.ts +4 -2
- package/dist/components/registry/heatmap/calendar-heatmap.js +74 -33
- package/dist/components/registry/heatmap/status-heatmap.d.ts +5 -3
- package/dist/components/registry/heatmap/status-heatmap.js +37 -15
- package/dist/components/registry/heatmap/weekday-heatmap.d.ts +9 -3
- package/dist/components/registry/heatmap/weekday-heatmap.js +82 -47
- package/dist/components/registry/niko-table/core/data-table-context.d.ts +18 -1
- package/dist/components/registry/niko-table/core/data-table-context.js +7 -1
- package/dist/components/registry/niko-table/core/data-table-grouped-row.js +3 -1
- package/dist/components/registry/niko-table/core/data-table-root.js +39 -4
- package/dist/components/registry/niko-table/core/data-table-structure.js +17 -12
- package/dist/components/registry/niko-table/core/data-table.d.ts +2 -2
- package/dist/components/registry/niko-table/core/data-table.js +5 -1
- package/dist/components/registry/niko-table/filters/table-faceted-filter.js +4 -4
- package/dist/components/registry/niko-table/filters/table-search-filter.js +1 -1
- package/dist/components/registry/niko-table/lib/flex-columns.d.ts +1 -1
- package/dist/components/registry/niko-table/lib/flex-columns.js +3 -3
- package/dist/components/registry/niko-table/lib/styles.d.ts +1 -1
- package/dist/components/registry/niko-table/lib/styles.js +3 -3
- package/dist/components/registry/niko-table/types/index.d.ts +9 -0
- package/dist/components/registry/niko-table/ui/table.js +2 -2
- package/dist/components/registry/sidebar-07/app-sidebar.d.ts +1 -1
- package/dist/components/registry/sidebar-07/app-sidebar.js +3 -1
- package/dist/components/registry/sidebar-07/nav-main.d.ts +2 -1
- package/dist/components/registry/sidebar-07/nav-main.js +16 -3
- package/dist/components/siyahi/callout.d.ts +24 -0
- package/dist/components/siyahi/callout.js +40 -0
- package/dist/components/siyahi/change-bar.d.ts +21 -0
- package/dist/components/siyahi/change-bar.js +35 -0
- package/dist/components/siyahi/data-bar.d.ts +19 -0
- package/dist/components/siyahi/data-bar.js +29 -0
- package/dist/components/siyahi/data-table-compact-columns-toggle.d.ts +4 -0
- package/dist/components/siyahi/data-table-compact-columns-toggle.js +19 -0
- package/dist/components/siyahi/data-table-footnote.d.ts +12 -0
- package/dist/components/siyahi/data-table-footnote.js +35 -0
- package/dist/components/siyahi/default-sidebar-open.d.ts +8 -0
- package/dist/components/siyahi/default-sidebar-open.js +13 -0
- package/dist/components/siyahi/page-hero.d.ts +25 -0
- package/dist/components/siyahi/page-hero.js +41 -0
- package/dist/components/siyahi/page-section.d.ts +4 -1
- package/dist/components/siyahi/page-section.js +6 -3
- package/dist/components/siyahi/page-toc.d.ts +20 -0
- package/dist/components/siyahi/page-toc.js +76 -0
- package/dist/components/siyahi/panel-grid.d.ts +22 -0
- package/dist/components/siyahi/panel-grid.js +34 -0
- package/dist/components/siyahi/quote.d.ts +12 -0
- package/dist/components/siyahi/quote.js +23 -0
- package/dist/components/siyahi/range-position.d.ts +24 -0
- package/dist/components/siyahi/range-position.js +105 -0
- package/dist/components/siyahi/siyahi-provider.d.ts +13 -2
- package/dist/components/siyahi/siyahi-provider.js +17 -4
- package/dist/components/siyahi/target-rows.d.ts +34 -0
- package/dist/components/siyahi/target-rows.js +97 -0
- package/dist/components/siyahi/treemap.d.ts +4 -1
- package/dist/components/siyahi/treemap.js +78 -28
- package/dist/components/siyahi/warning-alert.d.ts +10 -0
- package/dist/components/siyahi/warning-alert.js +20 -0
- package/dist/components/ui/accordion.js +5 -5
- package/dist/components/ui/alert.js +2 -2
- package/dist/components/ui/badge.js +1 -1
- package/dist/components/ui/breadcrumb.js +2 -2
- package/dist/components/ui/button.js +10 -10
- package/dist/components/ui/calendar.js +1 -1
- package/dist/components/ui/card.js +4 -4
- package/dist/components/ui/chart.js +1 -1
- package/dist/components/ui/code-block.js +13 -12
- package/dist/components/ui/command.js +7 -6
- package/dist/components/ui/context-menu.js +7 -7
- package/dist/components/ui/dialog.js +5 -5
- package/dist/components/ui/dropdown-menu.js +8 -8
- package/dist/components/ui/input-group.js +11 -11
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/popover.js +3 -3
- package/dist/components/ui/progress.js +1 -1
- package/dist/components/ui/select.js +6 -6
- package/dist/components/ui/sheet.js +5 -5
- package/dist/components/ui/sidebar.js +17 -18
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/slider.js +2 -2
- package/dist/components/ui/table.js +2 -2
- package/dist/components/ui/tabs.js +2 -2
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/toggle-group.js +2 -2
- package/dist/components/ui/toggle.js +4 -4
- package/dist/components/ui/tooltip.js +2 -2
- package/dist/index.d.ts +21 -7
- package/dist/index.js +18 -4
- package/dist/lib/chart-frame.d.ts +25 -7
- package/dist/lib/chart-frame.js +251 -127
- package/dist/lib/chart-series.d.ts +12 -6
- package/dist/lib/compact-columns.d.ts +19 -0
- package/dist/lib/compact-columns.js +55 -0
- package/dist/lib/format.d.ts +7 -2
- package/dist/lib/format.js +54 -16
- package/dist/lib/heatmap-navigation.d.ts +8 -0
- package/dist/lib/heatmap-navigation.js +49 -0
- package/dist/lib/treemap.js +6 -1
- package/dist/lib/use-element-width.d.ts +5 -0
- package/dist/lib/use-element-width.js +15 -0
- package/package.json +4 -1
- package/registry.lock.json +16 -0
- package/report.css +33 -32
- package/styles/siyahi.css +221 -39
- package/dist/lib/recharts.d.ts +0 -2
- package/dist/lib/recharts.js +0 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
|
+
import { useHeatmapNavigation } from "../../../lib/heatmap-navigation.js";
|
|
3
|
+
import { useElementWidth } from "../../../lib/use-element-width.js";
|
|
2
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
5
|
import { Fragment as Fragment$1, createContext, use, useMemo } from "react";
|
|
4
6
|
import { format } from "date-fns";
|
|
@@ -47,6 +49,10 @@ const generateWeekdayLabels = (locale) => Array.from({ length: 7 }, (_, i) => {
|
|
|
47
49
|
});
|
|
48
50
|
const EMPTY_STYLE = {};
|
|
49
51
|
const LABEL_MARGIN = 8;
|
|
52
|
+
const LEGEND_SWATCH = 12;
|
|
53
|
+
const MIN_FITTED_BLOCK = 14;
|
|
54
|
+
const MAX_FITTED_BLOCK = 44;
|
|
55
|
+
const DEFAULT_BLOCK = 24;
|
|
50
56
|
const WeekdayHeatmapContext = createContext(null);
|
|
51
57
|
const useWeekdayHeatmap = () => {
|
|
52
58
|
const context = use(WeekdayHeatmapContext);
|
|
@@ -84,8 +90,10 @@ const useWeekdayHeatmap = () => {
|
|
|
84
90
|
* @param extraRow - Appends an aggregated row below the grid. `compute` receives all activities and must return 24 values (one per hour). Rendered through `renderExtraRow` on the body, or falls back to `children`.
|
|
85
91
|
* @param extraColumn - Appends an aggregated column to the right of the grid. `compute` receives all activities and must return 7 values indexed by weekday 0–6. Rendered through `renderExtraColumn` on the body, or falls back to `children`.
|
|
86
92
|
*/
|
|
87
|
-
const WeekdayHeatmap = ({ data, weekStart = 0, use12Hour = false, blockSize
|
|
93
|
+
const WeekdayHeatmap = ({ data, weekStart = 0, hours = HOURS, weekdays: displayedWeekdays, use12Hour = false, blockSize: blockSizeProp, blockMargin = 4, blockRadius = 2, blockAspectRatio = 1, levels: levelsProp = 5, isNormalized = false, colors, locale, labels: labelsProp, fontSize = 14, emptyState, totalCount: totalCountProp, extraRow, extraColumn, style = EMPTY_STYLE, className, children, ...props }) => {
|
|
88
94
|
const levels = Math.max(1, levelsProp);
|
|
95
|
+
const [rootRef, rootWidth] = useElementWidth();
|
|
96
|
+
const weekdays = useMemo(() => displayedWeekdays ?? Array.from({ length: 7 }, (_, i) => (weekStart + i) % 7), [displayedWeekdays, weekStart]);
|
|
89
97
|
const dataWithLevels = useMemo(() => {
|
|
90
98
|
if (data.length === 0) return [];
|
|
91
99
|
const maxRegular = data.reduce((m, d) => Math.max(m, d.value), 1);
|
|
@@ -141,7 +149,7 @@ const WeekdayHeatmap = ({ data, weekStart = 0, use12Hour = false, blockSize = 24
|
|
|
141
149
|
const weekdayLabels = locale ? generateWeekdayLabels(locale) : DEFAULT_WEEKDAY_LABELS;
|
|
142
150
|
return {
|
|
143
151
|
hours: use12Hour ? TWELVE_HOUR_LABELS : DEFAULT_HOUR_LABELS,
|
|
144
|
-
endHour: use12Hour ? "12" : "00",
|
|
152
|
+
endHour: hours.at(-1) === 23 ? use12Hour ? "12" : "00" : (use12Hour ? TWELVE_HOUR_LABELS : DEFAULT_HOUR_LABELS)[(hours.at(-1) ?? -1) + 1],
|
|
145
153
|
weekdays: weekdayLabels,
|
|
146
154
|
cellLabel: "{{weekday}} {{hour}}: {{value}}",
|
|
147
155
|
heatmapLabel: "Activity heatmap by weekday and hour",
|
|
@@ -152,16 +160,20 @@ const WeekdayHeatmap = ({ data, weekStart = 0, use12Hour = false, blockSize = 24
|
|
|
152
160
|
}, [
|
|
153
161
|
locale,
|
|
154
162
|
use12Hour,
|
|
155
|
-
labelsProp
|
|
163
|
+
labelsProp,
|
|
164
|
+
hours
|
|
156
165
|
]);
|
|
157
166
|
const labelWidth = fontSize * 3.5 + LABEL_MARGIN;
|
|
158
167
|
const totalCount = typeof totalCountProp === "number" ? totalCountProp : dataWithLevels.reduce((sum, a) => sum + a.value, 0);
|
|
168
|
+
const hasExtraColumn = resolvedExtraColumn !== null;
|
|
169
|
+
const columns = hours.length + (hasExtraColumn ? 2 : 0);
|
|
170
|
+
const fitted = (rootWidth - 24 - labelWidth - columns * blockMargin + (hasExtraColumn ? 0 : blockMargin)) / (columns + (hasExtraColumn ? 1 / (2 * blockAspectRatio) : 0));
|
|
171
|
+
const blockSize = blockSizeProp ?? (rootWidth > 0 ? Math.min(MAX_FITTED_BLOCK, Math.max(MIN_FITTED_BLOCK, fitted)) / blockAspectRatio : DEFAULT_BLOCK);
|
|
159
172
|
const blockWidth = blockSize * blockAspectRatio;
|
|
160
173
|
const labelHeight = fontSize + LABEL_MARGIN;
|
|
161
|
-
const hasExtraColumn = resolvedExtraColumn !== null;
|
|
162
174
|
const hasExtraRow = resolvedExtraRow !== null;
|
|
163
|
-
const width =
|
|
164
|
-
const rowCount = hasExtraRow ?
|
|
175
|
+
const width = hours.length * (blockWidth + blockMargin) + (hasExtraColumn ? blockSize / 2 + (blockWidth + blockMargin) * 2 : 0) - blockMargin + labelWidth;
|
|
176
|
+
const rowCount = weekdays.length + (hasExtraRow ? 1 : 0);
|
|
165
177
|
const extraRowGap = hasExtraRow ? blockSize + blockMargin : 0;
|
|
166
178
|
const height = rowCount * (blockSize + blockMargin) + extraRowGap - blockMargin + labelHeight;
|
|
167
179
|
const contextValue = useMemo(() => ({
|
|
@@ -183,6 +195,8 @@ const WeekdayHeatmap = ({ data, weekStart = 0, use12Hour = false, blockSize = 24
|
|
|
183
195
|
width,
|
|
184
196
|
height,
|
|
185
197
|
weekStart,
|
|
198
|
+
hours,
|
|
199
|
+
weekdays,
|
|
186
200
|
colors
|
|
187
201
|
}), [
|
|
188
202
|
dataWithLevels,
|
|
@@ -203,14 +217,17 @@ const WeekdayHeatmap = ({ data, weekStart = 0, use12Hour = false, blockSize = 24
|
|
|
203
217
|
width,
|
|
204
218
|
height,
|
|
205
219
|
weekStart,
|
|
220
|
+
hours,
|
|
221
|
+
weekdays,
|
|
206
222
|
colors
|
|
207
223
|
]);
|
|
208
224
|
if (data.length === 0) return emptyState ? emptyState : null;
|
|
209
225
|
return /* @__PURE__ */ jsx(WeekdayHeatmapContext, {
|
|
210
226
|
value: contextValue,
|
|
211
227
|
children: /* @__PURE__ */ jsx("div", {
|
|
228
|
+
ref: rootRef,
|
|
212
229
|
"data-slot": "weekday-heatmap",
|
|
213
|
-
className: cn("flex
|
|
230
|
+
className: cn("flex flex-col gap-2", blockSizeProp === void 0 ? "w-full" : "w-max max-w-full", className),
|
|
214
231
|
style: {
|
|
215
232
|
fontSize,
|
|
216
233
|
...style
|
|
@@ -220,16 +237,18 @@ const WeekdayHeatmap = ({ data, weekStart = 0, use12Hour = false, blockSize = 24
|
|
|
220
237
|
})
|
|
221
238
|
});
|
|
222
239
|
};
|
|
223
|
-
const WeekdayHeatmapBlock = ({ ref, activity, extra, highlighted = false, onCellClick, onCellHover, onClick, onKeyDown, onMouseEnter, onMouseLeave, className, style: styleProp, ...props }) => {
|
|
224
|
-
const { blockSize, blockWidth, blockMargin, blockRadius, labelWidth, labelHeight, levels, isNormalized,
|
|
240
|
+
const WeekdayHeatmapBlock = ({ ref, activity, extra, highlighted = false, selected = false, onCellClick, onCellHover, onClick, onKeyDown, onMouseEnter, onMouseLeave, className, style: styleProp, ...props }) => {
|
|
241
|
+
const { blockSize, blockWidth, blockMargin, blockRadius, labelWidth, labelHeight, levels, isNormalized, hours, weekdays, labels, colors } = useWeekdayHeatmap();
|
|
225
242
|
const level = Math.max(0, Math.min(colorStepCount(levels, isNormalized), activity.level));
|
|
226
243
|
const isExtraRow = extra === "row";
|
|
227
244
|
const isExtraColumn = extra === "column";
|
|
228
|
-
const rowIndex = isExtraRow ?
|
|
245
|
+
const rowIndex = isExtraRow ? weekdays.length : weekdays.findIndex((day) => day === activity.weekday);
|
|
246
|
+
const hourIndex = isExtraColumn ? hours.length : hours.findIndex((hour) => hour === activity.hour);
|
|
247
|
+
if (rowIndex < 0 || hourIndex < 0) return null;
|
|
229
248
|
const extraRowGap = isExtraRow ? blockSize + blockMargin : 0;
|
|
230
249
|
const yPosition = labelHeight + (blockSize + blockMargin) * rowIndex + extraRowGap;
|
|
231
250
|
const extraColumnGap = isExtraColumn ? blockWidth + blockMargin : 0;
|
|
232
|
-
const xPosition = isExtraColumn ? labelWidth +
|
|
251
|
+
const xPosition = isExtraColumn ? labelWidth + hours.length * (blockWidth + blockMargin) + blockSize / 2 + extraColumnGap : labelWidth + (blockWidth + blockMargin) * hourIndex;
|
|
233
252
|
const weekdayToken = isExtraRow ? "extra" : labels.weekdays?.[activity.weekday] ?? String(activity.weekday);
|
|
234
253
|
const hourToken = isExtraColumn ? "extra" : `${String(activity.hour).padStart(2, "0")}:00`;
|
|
235
254
|
const ariaLabel = (labels.cellLabel ?? "{{weekday}} {{hour}}: {{value}}").replace("{{weekday}}", weekdayToken).replace("{{hour}}", hourToken).replace("{{value}}", String(activity.value));
|
|
@@ -237,6 +256,7 @@ const WeekdayHeatmapBlock = ({ ref, activity, extra, highlighted = false, onCell
|
|
|
237
256
|
ref,
|
|
238
257
|
"data-slot": "weekday-heatmap-block",
|
|
239
258
|
role: onCellClick ? "button" : "img",
|
|
259
|
+
"aria-pressed": onCellClick ? selected : void 0,
|
|
240
260
|
tabIndex: onCellClick ? 0 : -1,
|
|
241
261
|
"aria-label": ariaLabel,
|
|
242
262
|
className: cn("motion-safe:transition-opacity motion-safe:hover:opacity-70", onCellClick && "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", className),
|
|
@@ -245,6 +265,7 @@ const WeekdayHeatmapBlock = ({ ref, activity, extra, highlighted = false, onCell
|
|
|
245
265
|
"data-hour": isExtraColumn ? "extra" : activity.hour,
|
|
246
266
|
"data-level": level,
|
|
247
267
|
"data-highlighted": highlighted || void 0,
|
|
268
|
+
"data-selected": selected || void 0,
|
|
248
269
|
height: blockSize,
|
|
249
270
|
rx: blockRadius,
|
|
250
271
|
ry: blockRadius,
|
|
@@ -253,6 +274,10 @@ const WeekdayHeatmapBlock = ({ ref, activity, extra, highlighted = false, onCell
|
|
|
253
274
|
y: yPosition,
|
|
254
275
|
style: {
|
|
255
276
|
fill: getLevelFill(level, levels, isNormalized, highlighted, colors),
|
|
277
|
+
...selected ? {
|
|
278
|
+
stroke: "var(--foreground)",
|
|
279
|
+
strokeWidth: 2
|
|
280
|
+
} : {},
|
|
256
281
|
...styleProp
|
|
257
282
|
},
|
|
258
283
|
onClick: (event) => {
|
|
@@ -279,7 +304,8 @@ const WeekdayHeatmapBlock = ({ ref, activity, extra, highlighted = false, onCell
|
|
|
279
304
|
};
|
|
280
305
|
WeekdayHeatmapBlock.displayName = "WeekdayHeatmapBlock";
|
|
281
306
|
const WeekdayHeatmapBody = ({ hideHourLabels = false, hideWeekdayLabels = false, className, labelClassName, children, renderExtraRow, renderExtraColumn, ...props }) => {
|
|
282
|
-
const
|
|
307
|
+
const navigation = useHeatmapNavigation();
|
|
308
|
+
const { data, extraRow, extraColumn, blockSize, blockWidth, blockMargin, labels, labelWidth, labelHeight, fontSize, hours, weekdays } = useWeekdayHeatmap();
|
|
283
309
|
const hasExtraRow = extraRow !== null;
|
|
284
310
|
const hasExtraColumn = extraColumn !== null;
|
|
285
311
|
const activityMap = useMemo(() => {
|
|
@@ -299,24 +325,24 @@ const WeekdayHeatmapBody = ({ hideHourLabels = false, hideWeekdayLabels = false,
|
|
|
299
325
|
}, [extraColumn]);
|
|
300
326
|
const regularActivities = useMemo(() => {
|
|
301
327
|
const activities = [];
|
|
302
|
-
for (
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
weekdayIndex: di
|
|
312
|
-
});
|
|
313
|
-
}
|
|
328
|
+
for (const [di, weekday] of weekdays.entries()) for (const hour of hours) activities.push({
|
|
329
|
+
activity: activityMap.get(`${weekday}-${hour}`) ?? {
|
|
330
|
+
weekday,
|
|
331
|
+
hour,
|
|
332
|
+
value: 0,
|
|
333
|
+
level: 0
|
|
334
|
+
},
|
|
335
|
+
weekdayIndex: di
|
|
336
|
+
});
|
|
314
337
|
return activities;
|
|
315
|
-
}, [
|
|
338
|
+
}, [
|
|
339
|
+
activityMap,
|
|
340
|
+
weekdays,
|
|
341
|
+
hours
|
|
342
|
+
]);
|
|
316
343
|
const extraColumnActivities = useMemo(() => {
|
|
317
344
|
if (!extraColumnMap) return [];
|
|
318
|
-
return
|
|
319
|
-
const weekday = (weekStart + di) % 7;
|
|
345
|
+
return weekdays.map((weekday, di) => {
|
|
320
346
|
const entry = extraColumnMap.get(weekday);
|
|
321
347
|
return entry ? {
|
|
322
348
|
activity: {
|
|
@@ -328,44 +354,53 @@ const WeekdayHeatmapBody = ({ hideHourLabels = false, hideWeekdayLabels = false,
|
|
|
328
354
|
weekdayIndex: di
|
|
329
355
|
} : null;
|
|
330
356
|
}).filter((a) => a !== null);
|
|
331
|
-
}, [extraColumnMap,
|
|
357
|
+
}, [extraColumnMap, weekdays]);
|
|
332
358
|
const extraRowActivities = useMemo(() => {
|
|
333
359
|
if (!extraRow) return [];
|
|
334
|
-
return extraRow.values.map(({ hour, value, level }) => ({
|
|
360
|
+
return extraRow.values.filter(({ hour }) => hours.includes(hour)).map(({ hour, value, level }) => ({
|
|
335
361
|
activity: {
|
|
336
362
|
weekday: 0,
|
|
337
363
|
hour,
|
|
338
364
|
value,
|
|
339
365
|
level
|
|
340
366
|
},
|
|
341
|
-
weekdayIndex:
|
|
367
|
+
weekdayIndex: weekdays.length
|
|
342
368
|
}));
|
|
343
|
-
}, [
|
|
344
|
-
|
|
369
|
+
}, [
|
|
370
|
+
extraRow,
|
|
371
|
+
hours,
|
|
372
|
+
weekdays.length
|
|
373
|
+
]);
|
|
374
|
+
const rowCount = weekdays.length + (hasExtraRow ? 1 : 0);
|
|
345
375
|
const extraRowGap = hasExtraRow ? blockSize + blockMargin : 0;
|
|
346
376
|
const svgHeight = rowCount * (blockSize + blockMargin) + extraRowGap - blockMargin + labelHeight;
|
|
347
377
|
const extraColumnGap = hasExtraColumn ? blockWidth + blockMargin : 0;
|
|
348
|
-
const svgWidth = hasExtraColumn ? labelWidth +
|
|
349
|
-
const orderedWeekdayIndices =
|
|
378
|
+
const svgWidth = hasExtraColumn ? labelWidth + hours.length * (blockWidth + blockMargin) + blockSize / 2 + (blockWidth + blockMargin) + extraColumnGap : labelWidth + hours.length * (blockWidth + blockMargin) - blockMargin;
|
|
379
|
+
const orderedWeekdayIndices = weekdays;
|
|
350
380
|
return /* @__PURE__ */ jsx("div", {
|
|
351
381
|
"data-slot": "weekday-heatmap-body",
|
|
382
|
+
ref: navigation.ref,
|
|
352
383
|
className: cn("max-w-full overflow-x-auto overflow-y-hidden", className),
|
|
353
384
|
...props,
|
|
385
|
+
onKeyDown: (event) => {
|
|
386
|
+
props.onKeyDown?.(event);
|
|
387
|
+
if (!event.defaultPrevented) navigation.onKeyDown(event);
|
|
388
|
+
},
|
|
354
389
|
children: /* @__PURE__ */ jsxs("svg", {
|
|
355
390
|
role: "img",
|
|
356
391
|
"aria-label": labels.heatmapLabel ?? "Activity heatmap by weekday and hour",
|
|
357
392
|
className: "block overflow-visible rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
358
|
-
height: svgHeight +
|
|
359
|
-
viewBox: `-
|
|
360
|
-
width: svgWidth +
|
|
393
|
+
height: svgHeight + 24,
|
|
394
|
+
viewBox: `-12 -12 ${svgWidth + 24} ${svgHeight + 24}`,
|
|
395
|
+
width: svgWidth + 24,
|
|
361
396
|
children: [
|
|
362
397
|
!hideHourLabels && /* @__PURE__ */ jsxs("g", {
|
|
363
398
|
className: cn("fill-current font-mono", labelClassName),
|
|
364
399
|
children: [
|
|
365
|
-
|
|
400
|
+
hours.map((hour, index) => {
|
|
366
401
|
const label = labels.hours?.[hour] ?? "";
|
|
367
402
|
return /* @__PURE__ */ jsx("text", {
|
|
368
|
-
x: labelWidth + (blockWidth + blockMargin) *
|
|
403
|
+
x: labelWidth + (blockWidth + blockMargin) * index,
|
|
369
404
|
y: 0,
|
|
370
405
|
textAnchor: "middle",
|
|
371
406
|
dominantBaseline: "hanging",
|
|
@@ -374,7 +409,7 @@ const WeekdayHeatmapBody = ({ hideHourLabels = false, hideWeekdayLabels = false,
|
|
|
374
409
|
}, `hour-${hour}`);
|
|
375
410
|
}),
|
|
376
411
|
labels.endHour != null && /* @__PURE__ */ jsx("text", {
|
|
377
|
-
x: labelWidth + (blockWidth + blockMargin) *
|
|
412
|
+
x: labelWidth + (blockWidth + blockMargin) * hours.length,
|
|
378
413
|
y: 0,
|
|
379
414
|
textAnchor: "middle",
|
|
380
415
|
dominantBaseline: "hanging",
|
|
@@ -382,7 +417,7 @@ const WeekdayHeatmapBody = ({ hideHourLabels = false, hideWeekdayLabels = false,
|
|
|
382
417
|
children: labels.endHour
|
|
383
418
|
}, "hour-end"),
|
|
384
419
|
hasExtraColumn && /* @__PURE__ */ jsx("text", {
|
|
385
|
-
x: labelWidth +
|
|
420
|
+
x: labelWidth + hours.length * (blockWidth + blockMargin) + blockSize / 2 + (blockWidth + blockMargin) + blockWidth / 2,
|
|
386
421
|
y: 0,
|
|
387
422
|
textAnchor: "middle",
|
|
388
423
|
dominantBaseline: "hanging",
|
|
@@ -406,7 +441,7 @@ const WeekdayHeatmapBody = ({ hideHourLabels = false, hideWeekdayLabels = false,
|
|
|
406
441
|
}, `weekday-${weekday}`);
|
|
407
442
|
}), hasExtraRow && /* @__PURE__ */ jsx("text", {
|
|
408
443
|
x: labelWidth - 8,
|
|
409
|
-
y: labelHeight + (blockSize + blockMargin) *
|
|
444
|
+
y: labelHeight + (blockSize + blockMargin) * weekdays.length + (blockSize + blockMargin) + blockSize / 2,
|
|
410
445
|
dominantBaseline: "middle",
|
|
411
446
|
textAnchor: "end",
|
|
412
447
|
style: { fontSize: `${fontSize * .75}px` },
|
|
@@ -450,7 +485,7 @@ const WeekdayHeatmapStat = ({ compute, label, className, children, ...props }) =
|
|
|
450
485
|
});
|
|
451
486
|
};
|
|
452
487
|
const WeekdayHeatmapLegend = ({ labels: labelsProp, className, children, ...props }) => {
|
|
453
|
-
const { levels, isNormalized,
|
|
488
|
+
const { levels, isNormalized, blockRadius, colors, labels } = useWeekdayHeatmap();
|
|
454
489
|
const lessLabel = labelsProp?.less ?? "Less";
|
|
455
490
|
const moreLabel = labelsProp?.more ?? "More";
|
|
456
491
|
const legendLevels = Array.from({ length: levels }, (_, i) => isNormalized ? i + 1 : i);
|
|
@@ -467,14 +502,14 @@ const WeekdayHeatmapLegend = ({ labels: labelsProp, className, children, ...prop
|
|
|
467
502
|
legendLevels.map((level) => children ? /* @__PURE__ */ jsx(Fragment$1, { children: children({ level }) }, `legend-level-${level}`) : /* @__PURE__ */ jsx("svg", {
|
|
468
503
|
role: "img",
|
|
469
504
|
"aria-label": (labels.legendLevelLabel ?? "{{level}} contributions").replace("{{level}}", String(level)),
|
|
470
|
-
height:
|
|
471
|
-
width:
|
|
505
|
+
height: LEGEND_SWATCH,
|
|
506
|
+
width: LEGEND_SWATCH,
|
|
472
507
|
children: /* @__PURE__ */ jsx("rect", {
|
|
473
508
|
"data-level": level,
|
|
474
|
-
height:
|
|
509
|
+
height: LEGEND_SWATCH,
|
|
475
510
|
rx: blockRadius,
|
|
476
511
|
ry: blockRadius,
|
|
477
|
-
width:
|
|
512
|
+
width: LEGEND_SWATCH,
|
|
478
513
|
style: { fill: getLevelFill(level, levels, isNormalized, false, colors) }
|
|
479
514
|
})
|
|
480
515
|
}, `legend-level-${level}`)),
|
|
@@ -91,6 +91,13 @@ type DataTableContextProps<TData extends RowData> = DataTableContextState & {
|
|
|
91
91
|
* `null` until the container mounts (or when no `<DataTable>` is used).
|
|
92
92
|
*/
|
|
93
93
|
scrollContainer: HTMLElement | null;
|
|
94
|
+
/** True below 40rem of table space; use for compact toolbar and record layouts. */
|
|
95
|
+
isCompact: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Set while some columns do not fit and the table has `meta.compact`
|
|
98
|
+
* columns: they hide, rightmost first, until the reader asks for all.
|
|
99
|
+
*/
|
|
100
|
+
compactColumns: CompactColumns | null;
|
|
94
101
|
/** Internal: `<DataTable>` registers its scroll container element here. */
|
|
95
102
|
registerScrollContainer: (el: HTMLElement | null) => void;
|
|
96
103
|
/**
|
|
@@ -146,12 +153,22 @@ export declare enum DataTableActions {
|
|
|
146
153
|
SET = 0,
|
|
147
154
|
SET_IS_LOADING = 1
|
|
148
155
|
}
|
|
156
|
+
export interface CompactColumns {
|
|
157
|
+
/** True while columns are hidden to fit; false once the reader shows them all. */
|
|
158
|
+
collapsed: boolean;
|
|
159
|
+
/** The columns hidden to fit right now, for a cell to fold one under a kept figure. */
|
|
160
|
+
hidden: ReadonlySet<string>;
|
|
161
|
+
setCollapsed: (collapsed: boolean) => void;
|
|
162
|
+
}
|
|
149
163
|
interface DataTableProviderProps<TData extends RowData> {
|
|
150
164
|
children: React.ReactNode;
|
|
151
165
|
table: DataTableInstance<TData>;
|
|
152
166
|
columns?: DataTableColumnDef<TData>[];
|
|
153
167
|
isLoading?: boolean;
|
|
168
|
+
isCompact: boolean;
|
|
169
|
+
onWidthChange: (width: number) => void;
|
|
170
|
+
compactColumns: CompactColumns | null;
|
|
154
171
|
}
|
|
155
|
-
export declare function DataTableProvider<TData extends RowData>({ children, table, columns, isLoading: externalIsLoading }: DataTableProviderProps<TData>): React.JSX.Element;
|
|
172
|
+
export declare function DataTableProvider<TData extends RowData>({ children, table, columns, isLoading: externalIsLoading, isCompact, onWidthChange, compactColumns }: DataTableProviderProps<TData>): React.JSX.Element;
|
|
156
173
|
//#endregion
|
|
157
174
|
export { DataTableContext };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { useTableWidth } from "../../../../lib/compact-columns.js";
|
|
2
3
|
import { useGeneratedOptions } from "../hooks/use-generated-options.js";
|
|
3
4
|
import { useHeaderMinWidths } from "../lib/use-header-min-widths.js";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -113,7 +114,7 @@ function useFlashSet() {
|
|
|
113
114
|
}
|
|
114
115
|
}, [])];
|
|
115
116
|
}
|
|
116
|
-
function DataTableProvider({ children, table, columns, isLoading: externalIsLoading }) {
|
|
117
|
+
function DataTableProvider({ children, table, columns, isLoading: externalIsLoading, isCompact, onWidthChange, compactColumns }) {
|
|
117
118
|
const [state, dispatch] = useReducer(dataTableReducer, deriveInitialState(externalIsLoading));
|
|
118
119
|
const setIsLoading = useCallback((value) => {
|
|
119
120
|
dispatch({
|
|
@@ -127,6 +128,7 @@ function DataTableProvider({ children, table, columns, isLoading: externalIsLoad
|
|
|
127
128
|
}, []);
|
|
128
129
|
const [scrollContainer, setScrollContainer] = React.useState(null);
|
|
129
130
|
const registerScrollContainer = useCallback((el) => setScrollContainer(el), []);
|
|
131
|
+
useTableWidth(scrollContainer, onWidthChange);
|
|
130
132
|
const scrollRowIntoView = useCallback((index, opts) => {
|
|
131
133
|
if (rowScrollerRef.current) {
|
|
132
134
|
rowScrollerRef.current(index, opts);
|
|
@@ -269,6 +271,8 @@ function DataTableProvider({ children, table, columns, isLoading: externalIsLoad
|
|
|
269
271
|
scrollRowIntoView,
|
|
270
272
|
registerRowScroller,
|
|
271
273
|
scrollContainer,
|
|
274
|
+
isCompact,
|
|
275
|
+
compactColumns,
|
|
272
276
|
registerScrollContainer,
|
|
273
277
|
headerMinWidths,
|
|
274
278
|
setColumnResizePreview: setManualResizePreview,
|
|
@@ -286,6 +290,8 @@ function DataTableProvider({ children, table, columns, isLoading: externalIsLoad
|
|
|
286
290
|
scrollRowIntoView,
|
|
287
291
|
registerRowScroller,
|
|
288
292
|
scrollContainer,
|
|
293
|
+
isCompact,
|
|
294
|
+
compactColumns,
|
|
289
295
|
registerScrollContainer,
|
|
290
296
|
headerMinWidths,
|
|
291
297
|
setManualResizePreview,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Button } from "../../../ui/button.js";
|
|
2
2
|
import { cn } from "../../../../lib/utils.js";
|
|
3
|
+
import { useDataTable } from "./data-table-context.js";
|
|
3
4
|
import { DataTableGroupRowProvider, useDataTableGroupRow } from "../components/data-table-grouped-rows.js";
|
|
4
5
|
import { TableCell, TableRow } from "../ui/table.js";
|
|
5
6
|
import { isInteractiveClickTarget } from "../lib/row-click.js";
|
|
@@ -18,12 +19,13 @@ import { flexRender } from "@tanstack/react-table";
|
|
|
18
19
|
* groups you don't want to special-case.
|
|
19
20
|
*/
|
|
20
21
|
function DataTableGroupedRowCells() {
|
|
22
|
+
const { isCompact } = useDataTable();
|
|
21
23
|
const { row, groupLabel, count, isExpanded, toggle, columnWidths } = useDataTableGroupRow();
|
|
22
24
|
const countLabel = `${count} ${count === 1 ? "row" : "rows"}`;
|
|
23
25
|
return /* @__PURE__ */ jsx(Fragment, { children: row.getVisibleCells().map((cell) => {
|
|
24
26
|
const cellStyle = {
|
|
25
27
|
width: columnWidths.get(cell.column.id),
|
|
26
|
-
...getCommonPinningStyles(cell.column, false)
|
|
28
|
+
...getCommonPinningStyles(cell.column, false, !isCompact)
|
|
27
29
|
};
|
|
28
30
|
let content = null;
|
|
29
31
|
if (cell.getIsGrouped()) content = /* @__PURE__ */ jsxs("div", {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TooltipProvider } from "../../../ui/tooltip.js";
|
|
2
2
|
import { cn } from "../../../../lib/utils.js";
|
|
3
|
+
import { fitColumns, isCompactWidth } from "../../../../lib/compact-columns.js";
|
|
3
4
|
import { FILTER_VARIANTS, SYSTEM_COLUMN_IDS, SYSTEM_COLUMN_ID_LIST } from "../lib/constants.js";
|
|
4
5
|
import { DataTableProvider } from "./data-table-context.js";
|
|
5
6
|
import { detectFeaturesFromChildren } from "../config/feature-detection.js";
|
|
@@ -216,7 +217,23 @@ function DataTableRootInternal({ columns, data, children, className, config, get
|
|
|
216
217
|
...detectFeatures.enableColumnResizing ? { minSize: 40 } : {}
|
|
217
218
|
}), [detectFeatures.enableColumnResizing, detectFeatures.enableSorting]);
|
|
218
219
|
const controlledSorting = restState?.sorting ?? sorting;
|
|
219
|
-
const
|
|
220
|
+
const [tableWidth, setTableWidth] = React.useState(0);
|
|
221
|
+
const isCompact = isCompactWidth(tableWidth);
|
|
222
|
+
const [showAllColumns, setShowAllColumns] = React.useState(false);
|
|
223
|
+
const requestedColumnVisibility = restState?.columnVisibility ?? columnVisibility;
|
|
224
|
+
const requestedColumnOrder = restState?.columnOrder ?? columnOrder;
|
|
225
|
+
const fitted = React.useMemo(() => fitColumns(columns, requestedColumnOrder, requestedColumnVisibility, tableWidth), [
|
|
226
|
+
columns,
|
|
227
|
+
requestedColumnOrder,
|
|
228
|
+
requestedColumnVisibility,
|
|
229
|
+
tableWidth
|
|
230
|
+
]);
|
|
231
|
+
const controlledColumnVisibility = fitted && !showAllColumns ? fitted.visibility : requestedColumnVisibility;
|
|
232
|
+
const compactColumns = React.useMemo(() => fitted && fitted.hidden.size > 0 ? {
|
|
233
|
+
collapsed: !showAllColumns,
|
|
234
|
+
hidden: showAllColumns ? NOTHING_HIDDEN : fitted.hidden,
|
|
235
|
+
setCollapsed: (value) => setShowAllColumns(!value)
|
|
236
|
+
} : null, [fitted, showAllColumns]);
|
|
220
237
|
const controlledRowSelection = restState?.rowSelection ?? rowSelection;
|
|
221
238
|
const controlledColumnFilters = restState?.columnFilters ?? columnFilters;
|
|
222
239
|
const controlledGlobalFilter = restState?.globalFilter !== void 0 ? restState.globalFilter : globalFilter$1;
|
|
@@ -369,6 +386,9 @@ function DataTableRootInternal({ columns, data, children, className, config, get
|
|
|
369
386
|
table,
|
|
370
387
|
columns: processedColumns,
|
|
371
388
|
isLoading,
|
|
389
|
+
isCompact,
|
|
390
|
+
onWidthChange: setTableWidth,
|
|
391
|
+
compactColumns,
|
|
372
392
|
children: /* @__PURE__ */ jsx(TooltipProvider, {
|
|
373
393
|
...tooltipProviderDelay,
|
|
374
394
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -378,11 +398,16 @@ function DataTableRootInternal({ columns, data, children, className, config, get
|
|
|
378
398
|
})
|
|
379
399
|
});
|
|
380
400
|
}
|
|
381
|
-
function
|
|
382
|
-
|
|
383
|
-
|
|
401
|
+
function ExternalTableRoot({ table, columns, children, className, isLoading }) {
|
|
402
|
+
const [tableWidth, setTableWidth] = React.useState(0);
|
|
403
|
+
const isCompact = isCompactWidth(tableWidth);
|
|
404
|
+
return /* @__PURE__ */ jsx(DataTableProvider, {
|
|
405
|
+
table,
|
|
384
406
|
columns,
|
|
385
407
|
isLoading,
|
|
408
|
+
isCompact,
|
|
409
|
+
onWidthChange: setTableWidth,
|
|
410
|
+
compactColumns: null,
|
|
386
411
|
children: /* @__PURE__ */ jsx(TooltipProvider, {
|
|
387
412
|
...tooltipProviderDelay,
|
|
388
413
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -391,6 +416,16 @@ function DataTableRoot({ table: externalTable, columns, data, children, classNam
|
|
|
391
416
|
})
|
|
392
417
|
})
|
|
393
418
|
});
|
|
419
|
+
}
|
|
420
|
+
const NOTHING_HIDDEN = /* @__PURE__ */ new Set();
|
|
421
|
+
function DataTableRoot({ table: externalTable, columns, data, children, className, isLoading, ...rest }) {
|
|
422
|
+
if (externalTable) return /* @__PURE__ */ jsx(ExternalTableRoot, {
|
|
423
|
+
table: externalTable,
|
|
424
|
+
columns,
|
|
425
|
+
className,
|
|
426
|
+
isLoading,
|
|
427
|
+
children
|
|
428
|
+
});
|
|
394
429
|
if (!columns || !data) throw new Error("DataTableRoot: Either provide a 'table' prop or both 'columns' and 'data' props");
|
|
395
430
|
return /* @__PURE__ */ jsx(DataTableRootInternal, {
|
|
396
431
|
columns,
|
|
@@ -20,11 +20,11 @@ import React from "react";
|
|
|
20
20
|
import { flexRender } from "@tanstack/react-table";
|
|
21
21
|
//#region src/components/registry/niko-table/core/data-table-structure.tsx
|
|
22
22
|
const DataTableHeader = React.memo(function DataTableHeader({ className, sticky = true }) {
|
|
23
|
-
const { table, headerMinWidths, setColumnResizePreview } = useDataTable();
|
|
23
|
+
const { table, headerMinWidths, setColumnResizePreview, isCompact } = useDataTable();
|
|
24
24
|
const resizing = table?.options.enableColumnResizing ?? false;
|
|
25
25
|
const headerGroups = table?.getHeaderGroups() ?? [];
|
|
26
26
|
if (headerGroups.length === 0) return null;
|
|
27
|
-
const flexColumnIds = resolveFlexColumnIds(table);
|
|
27
|
+
const flexColumnIds = resolveFlexColumnIds(table, !isCompact);
|
|
28
28
|
const columnSizing = table.state.columnSizing;
|
|
29
29
|
return /* @__PURE__ */ jsx(TableHeader, {
|
|
30
30
|
className: cn(sticky && "sticky top-0 z-30 bg-card", sticky && "after:absolute after:right-0 after:bottom-0 after:left-0 after:h-px after:bg-border", className),
|
|
@@ -37,12 +37,13 @@ const DataTableHeader = React.memo(function DataTableHeader({ className, sticky
|
|
|
37
37
|
columnSizing,
|
|
38
38
|
headerMinWidths
|
|
39
39
|
}),
|
|
40
|
-
...getCommonPinningStyles(header.column, true)
|
|
40
|
+
...getCommonPinningStyles(header.column, true, !isCompact)
|
|
41
41
|
};
|
|
42
42
|
return /* @__PURE__ */ jsxs(TableHead, {
|
|
43
43
|
"data-col-id": header.column.id,
|
|
44
|
+
"data-numeric": header.column.columnDef.meta?.variant === "number" || void 0,
|
|
44
45
|
style: headerStyle,
|
|
45
|
-
className: cn(header.column.getIsPinned() && "bg-background", resizing && "relative overflow-hidden"),
|
|
46
|
+
className: cn(!isCompact && header.column.getIsPinned() && "bg-background", resizing && "relative overflow-hidden"),
|
|
46
47
|
children: [header.isPlaceholder ? null : /* @__PURE__ */ jsx(DataTableColumnHeaderRoot, {
|
|
47
48
|
column: header.column,
|
|
48
49
|
children: resizing && typeof header.column.columnDef.header === "string" ? /* @__PURE__ */ jsx("span", {
|
|
@@ -61,7 +62,7 @@ const DataTableHeader = React.memo(function DataTableHeader({ className, sticky
|
|
|
61
62
|
DataTableHeader.displayName = "DataTableHeader";
|
|
62
63
|
/** Fade-pulse animation applied to a flashing cell (keyframe in the provider). */
|
|
63
64
|
const FLASH_ANIMATION = "niko-row-flash 1.2s ease-out";
|
|
64
|
-
const BodyRow = React.memo(function BodyRow({ row, displayIndex, expandColumnId, isClickable, isExpanded, isSelected, columnWidths, isRowFlashing, flashingCellKeys, renderRowContextMenu }) {
|
|
65
|
+
const BodyRow = React.memo(function BodyRow({ row, displayIndex, expandColumnId, isCompact, isClickable, isExpanded, isSelected, columnWidths, isRowFlashing, flashingCellKeys, renderRowContextMenu }) {
|
|
65
66
|
const expandCell = isExpanded && expandColumnId ? row.getAllCells().find((c) => c.column.id === expandColumnId) : void 0;
|
|
66
67
|
const visibleCells = row.getVisibleCells();
|
|
67
68
|
const rowElement = /* @__PURE__ */ jsx(TableRow, {
|
|
@@ -76,14 +77,15 @@ const BodyRow = React.memo(function BodyRow({ row, displayIndex, expandColumnId,
|
|
|
76
77
|
const flashing = isRowFlashing || flashingCellKeys.has(flashCellKey(row.id, cell.column.id));
|
|
77
78
|
const cellStyle = {
|
|
78
79
|
width: columnWidths.get(cell.column.id),
|
|
79
|
-
...getCommonPinningStyles(cell.column, false),
|
|
80
|
+
...getCommonPinningStyles(cell.column, false, !isCompact),
|
|
80
81
|
...flashing ? { animation: FLASH_ANIMATION } : {}
|
|
81
82
|
};
|
|
82
83
|
return /* @__PURE__ */ jsx(TableCell, {
|
|
83
84
|
"data-flash": flashing ? "true" : void 0,
|
|
84
85
|
"data-col-id": cell.column.id,
|
|
86
|
+
"data-numeric": cell.column.columnDef.meta?.variant === "number" || void 0,
|
|
85
87
|
style: cellStyle,
|
|
86
|
-
className: cn(!cell.getIsGrouped() && "truncate", cell.column.getIsPinned() && "bg-linear-to-r group-hover:from-muted/50 group-hover:to-muted/50 group-data-[context-menu-open]:from-muted/50 group-data-[context-menu-open]:to-muted/50 group-data-[state=selected]:from-muted group-data-[state=selected]:to-muted"),
|
|
88
|
+
className: cn(!cell.getIsGrouped() && "truncate", !isCompact && cell.column.getIsPinned() && "bg-linear-to-r group-hover:from-muted/50 group-hover:to-muted/50 group-data-[context-menu-open]:from-muted/50 group-data-[context-menu-open]:to-muted/50 group-data-[state=selected]:from-muted group-data-[state=selected]:to-muted"),
|
|
87
89
|
children: renderCellContent(cell)
|
|
88
90
|
}, cell.id);
|
|
89
91
|
})
|
|
@@ -101,7 +103,7 @@ const BodyRow = React.memo(function BodyRow({ row, displayIndex, expandColumnId,
|
|
|
101
103
|
});
|
|
102
104
|
BodyRow.displayName = "BodyRow";
|
|
103
105
|
function DataTableBody({ children, className, onScroll, onScrolledTop, onScrolledBottom, scrollThreshold = 50, onRowClick, getRowMemoKey, renderRowContextMenu }) {
|
|
104
|
-
const { table, columns, isLoading, flashingRowIds, flashingCellKeys, registerRowScroller, headerMinWidths } = useDataTable();
|
|
106
|
+
const { table, columns, isLoading, flashingRowIds, flashingCellKeys, registerRowScroller, headerMinWidths, isCompact } = useDataTable();
|
|
105
107
|
const { rows } = table.getRowModel();
|
|
106
108
|
const containerRef = React.useRef(null);
|
|
107
109
|
React.useEffect(() => {
|
|
@@ -139,13 +141,14 @@ function DataTableBody({ children, className, onScroll, onScrolledTop, onScrolle
|
|
|
139
141
|
const expandColumnId = React.useMemo(() => table.getAllColumns().find((col) => col.columnDef.meta?.expandedContent)?.id, [table, columns]);
|
|
140
142
|
const { columnVisibility, columnOrder, columnPinning, columnSizing } = table.state;
|
|
141
143
|
const resizing = table.options.enableColumnResizing ?? false;
|
|
142
|
-
const flexColumnIds = React.useMemo(() => resolveFlexColumnIds(table), [
|
|
144
|
+
const flexColumnIds = React.useMemo(() => resolveFlexColumnIds(table, !isCompact), [
|
|
143
145
|
table,
|
|
144
146
|
columnVisibility,
|
|
145
147
|
columnOrder,
|
|
146
148
|
columnPinning,
|
|
147
149
|
columnSizing,
|
|
148
|
-
resizing
|
|
150
|
+
resizing,
|
|
151
|
+
isCompact
|
|
149
152
|
]);
|
|
150
153
|
const columnWidths = React.useMemo(() => {
|
|
151
154
|
const widths = /* @__PURE__ */ new Map();
|
|
@@ -166,14 +169,15 @@ function DataTableBody({ children, className, onScroll, onScrolledTop, onScrolle
|
|
|
166
169
|
resizing
|
|
167
170
|
]);
|
|
168
171
|
const columnLayoutSignature = React.useMemo(() => table.getVisibleLeafColumns().map((c) => {
|
|
169
|
-
const pinned = c.getIsPinned();
|
|
172
|
+
const pinned = !isCompact && c.getIsPinned();
|
|
170
173
|
const base = pinned ? `${c.id}:${pinned}` : c.id;
|
|
171
174
|
return resizing ? `${base}:${columnWidths.get(c.id) ?? "flex"}` : base;
|
|
172
175
|
}).join(","), [
|
|
173
176
|
table,
|
|
174
177
|
columns,
|
|
175
178
|
columnWidths,
|
|
176
|
-
resizing
|
|
179
|
+
resizing,
|
|
180
|
+
isCompact
|
|
177
181
|
]);
|
|
178
182
|
const isClickable = !!onRowClick;
|
|
179
183
|
const resolvedRenderRowContextMenu = useResolvedRowContextMenuRenderer(renderRowContextMenu, children);
|
|
@@ -232,6 +236,7 @@ function DataTableBody({ children, className, onScroll, onScrolledTop, onScrolle
|
|
|
232
236
|
row,
|
|
233
237
|
displayIndex,
|
|
234
238
|
expandColumnId,
|
|
239
|
+
isCompact,
|
|
235
240
|
isClickable,
|
|
236
241
|
isExpanded: row.getIsExpanded(),
|
|
237
242
|
isSelected: row.getIsSelected(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
//#region src/components/registry/niko-table/core/data-table.d.ts
|
|
3
|
-
export interface DataTableContainerProps {
|
|
3
|
+
export interface DataTableContainerProps extends React.AriaAttributes {
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
/**
|
|
6
6
|
* Additional CSS classes for the container.
|
|
@@ -23,7 +23,7 @@ export interface DataTableContainerProps {
|
|
|
23
23
|
*/
|
|
24
24
|
maxHeight?: number | string;
|
|
25
25
|
}
|
|
26
|
-
export declare function DataTable({ children, className, height, maxHeight }: DataTableContainerProps): React.JSX.Element;
|
|
26
|
+
export declare function DataTable({ children, className, height, maxHeight, "aria-label": label, "aria-labelledby": labelledBy }: DataTableContainerProps): React.JSX.Element;
|
|
27
27
|
export declare namespace DataTable {
|
|
28
28
|
var displayName: string;
|
|
29
29
|
}
|
|
@@ -105,7 +105,7 @@ function ColumnResizePreviewLine() {
|
|
|
105
105
|
}
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
|
-
function DataTable({ children, className, height, maxHeight }) {
|
|
108
|
+
function DataTable({ children, className, height, maxHeight, "aria-label": label = "Data table", "aria-labelledby": labelledBy }) {
|
|
109
109
|
const parsed = React.useMemo(() => parseHeightFromClassName(className), [className]);
|
|
110
110
|
const finalHeight = height ?? parsed.height;
|
|
111
111
|
const finalMaxHeight = maxHeight ?? parsed.maxHeight ?? finalHeight;
|
|
@@ -113,6 +113,10 @@ function DataTable({ children, className, height, maxHeight }) {
|
|
|
113
113
|
return /* @__PURE__ */ jsxs("div", {
|
|
114
114
|
ref: registerScrollContainer,
|
|
115
115
|
"data-slot": "table-container",
|
|
116
|
+
role: "region",
|
|
117
|
+
"aria-label": labelledBy ? void 0 : label,
|
|
118
|
+
"aria-labelledby": labelledBy,
|
|
119
|
+
tabIndex: 0,
|
|
116
120
|
className: cn("relative isolate w-full overflow-auto rounded-lg border", "[&::-webkit-scrollbar]:h-2.5 [&::-webkit-scrollbar]:w-2.5", "[&::-webkit-scrollbar-track]:bg-transparent", "[&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-border/40", "hover:[&::-webkit-scrollbar-thumb]:bg-border", "[&::-webkit-scrollbar-thumb:hover]:bg-border/80!", "scrollbar-thin scrollbar-thumb-border/40 scrollbar-track-transparent", "hover:scrollbar-thumb-border", parsed.safeClassName),
|
|
117
121
|
style: {
|
|
118
122
|
height: finalHeight,
|