@dynostack/react-grid 0.4.0 → 0.5.1

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/dist/index.d.cts CHANGED
@@ -118,6 +118,54 @@ declare function tokensToCssBlock(tokens?: DataTableTokens): string;
118
118
  */
119
119
  declare const themePresets: {
120
120
  neutral: DataTableModedTheme;
121
+ graphite: {
122
+ light: {
123
+ background: string;
124
+ card: string;
125
+ border: string;
126
+ radius: string;
127
+ fontFamily: string;
128
+ foreground?: string;
129
+ cardForeground?: string;
130
+ popover?: string;
131
+ popoverForeground?: string;
132
+ primary?: string;
133
+ primaryForeground?: string;
134
+ secondary?: string;
135
+ secondaryForeground?: string;
136
+ muted?: string;
137
+ mutedForeground?: string;
138
+ accent?: string;
139
+ accentForeground?: string;
140
+ destructive?: string;
141
+ destructiveForeground?: string;
142
+ input?: string;
143
+ ring?: string;
144
+ };
145
+ dark: {
146
+ background: string;
147
+ card: string;
148
+ popover: string;
149
+ border: string;
150
+ input: string;
151
+ muted: string;
152
+ mutedForeground: string;
153
+ accent: string;
154
+ primary: string;
155
+ primaryForeground: string;
156
+ ring: string;
157
+ destructive: string;
158
+ radius: string;
159
+ fontFamily: string;
160
+ foreground?: string;
161
+ cardForeground?: string;
162
+ popoverForeground?: string;
163
+ secondary?: string;
164
+ secondaryForeground?: string;
165
+ accentForeground?: string;
166
+ destructiveForeground?: string;
167
+ };
168
+ };
121
169
  light: {
122
170
  light: DataTableTokens | undefined;
123
171
  };
package/dist/index.d.ts CHANGED
@@ -118,6 +118,54 @@ declare function tokensToCssBlock(tokens?: DataTableTokens): string;
118
118
  */
119
119
  declare const themePresets: {
120
120
  neutral: DataTableModedTheme;
121
+ graphite: {
122
+ light: {
123
+ background: string;
124
+ card: string;
125
+ border: string;
126
+ radius: string;
127
+ fontFamily: string;
128
+ foreground?: string;
129
+ cardForeground?: string;
130
+ popover?: string;
131
+ popoverForeground?: string;
132
+ primary?: string;
133
+ primaryForeground?: string;
134
+ secondary?: string;
135
+ secondaryForeground?: string;
136
+ muted?: string;
137
+ mutedForeground?: string;
138
+ accent?: string;
139
+ accentForeground?: string;
140
+ destructive?: string;
141
+ destructiveForeground?: string;
142
+ input?: string;
143
+ ring?: string;
144
+ };
145
+ dark: {
146
+ background: string;
147
+ card: string;
148
+ popover: string;
149
+ border: string;
150
+ input: string;
151
+ muted: string;
152
+ mutedForeground: string;
153
+ accent: string;
154
+ primary: string;
155
+ primaryForeground: string;
156
+ ring: string;
157
+ destructive: string;
158
+ radius: string;
159
+ fontFamily: string;
160
+ foreground?: string;
161
+ cardForeground?: string;
162
+ popoverForeground?: string;
163
+ secondary?: string;
164
+ secondaryForeground?: string;
165
+ accentForeground?: string;
166
+ destructiveForeground?: string;
167
+ };
168
+ };
121
169
  light: {
122
170
  light: DataTableTokens | undefined;
123
171
  };
package/dist/index.js CHANGED
@@ -1912,7 +1912,7 @@ function EditableCell({
1912
1912
  {
1913
1913
  className: cn(
1914
1914
  "flex h-7 items-center gap-1.5 rounded px-1.5 text-sm",
1915
- isEditable && "cursor-text outline-1 outline-transparent transition-colors hover:bg-muted/60 hover:outline-border",
1915
+ isEditable && "cursor-text transition-colors hover:bg-muted/60",
1916
1916
  align === "right" && "justify-end",
1917
1917
  align === "center" && "justify-center"
1918
1918
  ),
@@ -1935,6 +1935,7 @@ function EditableCell({
1935
1935
  return /* @__PURE__ */ jsx(
1936
1936
  "select",
1937
1937
  {
1938
+ "data-cell-editor": "",
1938
1939
  value: String(local ?? ""),
1939
1940
  onChange: (e) => {
1940
1941
  setLocal(e.target.value);
@@ -1956,7 +1957,15 @@ function EditableCell({
1956
1957
  value: String(local ?? ""),
1957
1958
  onValueChange: (v) => commit(v),
1958
1959
  children: [
1959
- /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "h-7 w-full text-xs", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
1960
+ /* @__PURE__ */ jsx(
1961
+ SelectTrigger,
1962
+ {
1963
+ "data-cell-editor": "",
1964
+ size: "sm",
1965
+ className: "h-7 w-full text-xs focus-visible:ring-0",
1966
+ children: /* @__PURE__ */ jsx(SelectValue, {})
1967
+ }
1968
+ ),
1960
1969
  /* @__PURE__ */ jsx(SelectContent, { children: opts.map((o) => /* @__PURE__ */ jsx(SelectItem, { value: o.value, children: o.label }, o.value)) })
1961
1970
  ]
1962
1971
  }
@@ -1966,6 +1975,8 @@ function EditableCell({
1966
1975
  return /* @__PURE__ */ jsx("div", { className: "flex h-7 items-center justify-center", children: /* @__PURE__ */ jsx(
1967
1976
  Checkbox,
1968
1977
  {
1978
+ "data-cell-editor": "",
1979
+ className: "focus-visible:ring-0",
1969
1980
  checked: !!local,
1970
1981
  onCheckedChange: (c) => commit(!!c),
1971
1982
  autoFocus: true
@@ -1975,6 +1986,7 @@ function EditableCell({
1975
1986
  return /* @__PURE__ */ jsx(
1976
1987
  Input,
1977
1988
  {
1989
+ "data-cell-editor": "",
1978
1990
  ref: inputRef,
1979
1991
  type: editor === "number" || editor === "currency" ? "number" : editor === "date" ? "date" : "text",
1980
1992
  value: local == null ? "" : String(local),
@@ -1988,7 +2000,7 @@ function EditableCell({
1988
2000
  onBlur: () => commit(local),
1989
2001
  onKeyDown: handleKey,
1990
2002
  className: cn(
1991
- "h-7 px-1.5 text-sm",
2003
+ "h-7 px-1.5 text-sm focus-visible:ring-0",
1992
2004
  align === "right" && "text-right",
1993
2005
  align === "center" && "text-center"
1994
2006
  )
@@ -2105,7 +2117,7 @@ function buildPreset(hue, chroma = 0.03) {
2105
2117
  border: `oklch(0.9 ${c * 0.8} ${hue})`,
2106
2118
  input: `oklch(0.9 ${c * 0.8} ${hue})`,
2107
2119
  ring: `oklch(0.55 0.2 ${hue} / 0.5)`,
2108
- radius: "0.625rem"
2120
+ radius: "0.375rem"
2109
2121
  },
2110
2122
  dark: {
2111
2123
  background: `oklch(0.16 ${c * 0.6} ${hue})`,
@@ -2127,7 +2139,7 @@ function buildPreset(hue, chroma = 0.03) {
2127
2139
  border: `oklch(0.27 ${c * 0.8} ${hue})`,
2128
2140
  input: `oklch(0.27 ${c * 0.8} ${hue})`,
2129
2141
  ring: `oklch(0.7 0.18 ${hue} / 0.5)`,
2130
- radius: "0.625rem"
2142
+ radius: "0.375rem"
2131
2143
  }
2132
2144
  };
2133
2145
  }
@@ -2167,7 +2179,7 @@ var neutral = {
2167
2179
  border: "oklch(0.922 0 0)",
2168
2180
  input: "oklch(0.922 0 0)",
2169
2181
  ring: "oklch(0.708 0 0)",
2170
- radius: "0.625rem"
2182
+ radius: "0.375rem"
2171
2183
  },
2172
2184
  dark: {
2173
2185
  background: "oklch(0.145 0 0)",
@@ -2189,11 +2201,38 @@ var neutral = {
2189
2201
  border: "oklch(0.269 0 0)",
2190
2202
  input: "oklch(0.269 0 0)",
2191
2203
  ring: "oklch(0.439 0 0)",
2192
- radius: "0.625rem"
2204
+ radius: "0.375rem"
2193
2205
  }
2194
2206
  };
2195
2207
  var themePresets = {
2196
2208
  neutral,
2209
+ graphite: {
2210
+ light: {
2211
+ ...neutral.light,
2212
+ background: "#fafafa",
2213
+ card: "#ffffff",
2214
+ border: "#e5e5e5",
2215
+ radius: "0.375rem",
2216
+ fontFamily: "'Geist', sans-serif"
2217
+ },
2218
+ dark: {
2219
+ ...neutral.dark,
2220
+ background: "#101112",
2221
+ card: "#101112",
2222
+ popover: "#17191b",
2223
+ border: "#292c2f",
2224
+ input: "#303438",
2225
+ muted: "#1b1e21",
2226
+ mutedForeground: "#9ba2aa",
2227
+ accent: "#24282d",
2228
+ primary: "#edf0f3",
2229
+ primaryForeground: "#101112",
2230
+ ring: "#84b8ff",
2231
+ destructive: "#fb7185",
2232
+ radius: "0.375rem",
2233
+ fontFamily: "'Geist', sans-serif"
2234
+ }
2235
+ },
2197
2236
  light: { light: neutral.light },
2198
2237
  dark: { light: neutral.dark },
2199
2238
  violet: buildPreset(285),
@@ -2557,9 +2596,7 @@ function getPinningStyles(column) {
2557
2596
  boxShadow: isLast ? "1px 0 0 0 var(--border)" : isFirst ? "-1px 0 0 0 var(--border)" : void 0
2558
2597
  };
2559
2598
  }
2560
- var DataTableEditingContext = createContext(
2561
- null
2562
- );
2599
+ var DataTableEditingContext = createContext(null);
2563
2600
  function useEditingContext() {
2564
2601
  const ctx = useContext(DataTableEditingContext);
2565
2602
  if (!ctx) throw new Error("DataTable editing context missing");
@@ -2570,13 +2607,7 @@ function DefaultCellHost(ctx) {
2570
2607
  return value == null ? null : String(value);
2571
2608
  }
2572
2609
  function EditableCellHost(ctx) {
2573
- const {
2574
- editingCell,
2575
- editingRowId,
2576
- setEditingCell,
2577
- setRowDraft,
2578
- onCellEdit
2579
- } = useEditingContext();
2610
+ const { editingCell, editingRowId, setEditingCell, setRowDraft, onCellEdit } = useEditingContext();
2580
2611
  const colId = ctx.column.id;
2581
2612
  const rowId = ctx.row.id;
2582
2613
  const isCellEdit = editingCell?.rowId === rowId && editingCell.colId === colId;
@@ -2753,12 +2784,13 @@ function DataTable({
2753
2784
  () => `dyno-grid-${rawInstanceId.replace(/[^a-zA-Z0-9]/g, "")}`,
2754
2785
  [rawInstanceId]
2755
2786
  );
2756
- const { lightStyle, darkCss } = useMemo(() => {
2787
+ const { lightStyle, lightCss, darkCss } = useMemo(() => {
2757
2788
  const { light, dark } = splitTheme(theme);
2758
2789
  const lightTokens = isolate ? { ...ISOLATE_LIGHT_TOKENS, ...light ?? {} } : light;
2759
2790
  const darkTokens = isolate ? { ...ISOLATE_DARK_TOKENS, ...dark ?? light ?? {} } : dark;
2760
2791
  return {
2761
2792
  lightStyle: tokensToStyle(lightTokens),
2793
+ lightCss: tokensToCssBlock(lightTokens),
2762
2794
  darkCss: darkTokens ? tokensToCssBlock(darkTokens) : null
2763
2795
  };
2764
2796
  }, [theme, isolate]);
@@ -2808,19 +2840,17 @@ function DataTable({
2808
2840
  const [columnVisibility, setColumnVisibility] = useState(
2809
2841
  initialColumnVisibility ?? {}
2810
2842
  );
2811
- const [columnPinning, setColumnPinning] = useState(
2812
- () => {
2813
- const base = initialColumnPinning ?? { left: [], right: [] };
2814
- const left = [...base.left ?? []];
2815
- const right = [...base.right ?? []];
2816
- const hasExpandColumn = !!(renderSubRow || getSubRows);
2817
- if (hasExpandColumn && left.includes("__select") && !left.includes("__expand")) {
2818
- const idx = left.indexOf("__select");
2819
- left.splice(idx + 1, 0, "__expand");
2820
- }
2821
- return { left, right };
2843
+ const [columnPinning, setColumnPinning] = useState(() => {
2844
+ const base = initialColumnPinning ?? { left: [], right: [] };
2845
+ const left = [...base.left ?? []];
2846
+ const right = [...base.right ?? []];
2847
+ const hasExpandColumn = !!(renderSubRow || getSubRows);
2848
+ if (hasExpandColumn && left.includes("__select") && !left.includes("__expand")) {
2849
+ const idx = left.indexOf("__select");
2850
+ left.splice(idx + 1, 0, "__expand");
2822
2851
  }
2823
- );
2852
+ return { left, right };
2853
+ });
2824
2854
  const [columnSizing, setColumnSizing] = useState({});
2825
2855
  const [rowSelection, setRowSelection] = useState({});
2826
2856
  const [expanded, setExpanded] = useState({});
@@ -3006,7 +3036,9 @@ function DataTable({
3006
3036
  customRowActions?.length
3007
3037
  ]);
3008
3038
  const [columnOrder, setColumnOrder] = useState(
3009
- () => augmentedColumns.map((c) => c.id ?? c.accessorKey ?? "")
3039
+ () => augmentedColumns.map(
3040
+ (c) => c.id ?? c.accessorKey ?? ""
3041
+ )
3010
3042
  );
3011
3043
  useEffect(() => {
3012
3044
  const next = augmentedColumns.map(
@@ -3144,7 +3176,9 @@ function DataTable({
3144
3176
  const selectionCallback = useRef(onSelectionChange);
3145
3177
  selectionCallback.current = onSelectionChange;
3146
3178
  useEffect(() => {
3147
- selectionCallback.current?.(table.getSelectedRowModel().flatRows.map((row) => row.original));
3179
+ selectionCallback.current?.(
3180
+ table.getSelectedRowModel().flatRows.map((row) => row.original)
3181
+ );
3148
3182
  }, [rowSelection, mergedData, table]);
3149
3183
  const visibleLeafCount = table.getVisibleLeafColumns().length;
3150
3184
  const editingContextValue = useMemo(
@@ -3196,12 +3230,15 @@ function DataTable({
3196
3230
  DENSITY_CLASS[density],
3197
3231
  className
3198
3232
  ),
3199
- style: lightStyle,
3233
+ style: darkCss ? void 0 : lightStyle,
3200
3234
  children: [
3201
3235
  darkCss && /* @__PURE__ */ jsxs("style", { children: [
3236
+ `[data-dyno-grid="${instanceId}"]{${lightCss}}`,
3202
3237
  `@media (prefers-color-scheme: dark){[data-dyno-grid="${instanceId}"]{${darkCss}}}`,
3203
3238
  `.dark [data-dyno-grid="${instanceId}"]{${darkCss}}`,
3204
- `[data-dyno-grid="${instanceId}"].dark{${darkCss}}`
3239
+ `.light [data-dyno-grid="${instanceId}"]{${lightCss}}`,
3240
+ `[data-dyno-grid="${instanceId}"].dark{${darkCss}}`,
3241
+ `[data-dyno-grid="${instanceId}"].light{${lightCss}}`
3205
3242
  ] }),
3206
3243
  /* @__PURE__ */ jsx(
3207
3244
  DataTableToolbar,
@@ -3228,71 +3265,83 @@ function DataTable({
3228
3265
  "table",
3229
3266
  {
3230
3267
  "aria-label": ariaLabel,
3231
- className: cn("w-full caption-bottom text-sm", striped && "[&_tbody>tr:nth-child(even)]:bg-muted/25"),
3268
+ className: cn(
3269
+ "w-full caption-bottom text-sm",
3270
+ striped && "[&_tbody>tr:nth-child(even)]:bg-muted/25"
3271
+ ),
3232
3272
  style: {
3233
3273
  width: table.getCenterTotalSize() ? void 0 : "100%",
3234
3274
  minWidth: "100%"
3235
3275
  },
3236
3276
  children: [
3237
- /* @__PURE__ */ jsx("thead", { className: cn("bg-card", stickyHeader && "sticky top-0 z-10"), children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsx("tr", { className: "border-b", children: hg.headers.map((header) => {
3238
- const meta = header.column.columnDef.meta;
3239
- const isUtility = header.column.id === "__select" || header.column.id === "__expand" || header.column.id === "__actions";
3240
- const isPinned = !!header.column.getIsPinned();
3241
- const canReorder = !isUtility && f.reordering;
3242
- const isDropTarget = canReorder && dragOverColId === header.column.id;
3243
- const isBeingDragged = canReorder && activeReorderId === header.column.id;
3244
- return /* @__PURE__ */ jsxs(
3245
- "th",
3246
- {
3247
- colSpan: header.colSpan,
3248
- "data-col-id": header.column.id,
3249
- onPointerDown: canReorder ? onHeaderPointerDown(header.column.id) : void 0,
3250
- onPointerMove: canReorder ? onHeaderPointerMove : void 0,
3251
- onPointerUp: canReorder ? onHeaderPointerUp : void 0,
3252
- onPointerCancel: canReorder ? onHeaderPointerUp : void 0,
3253
- style: {
3254
- width: header.getSize(),
3255
- ...getPinningStyles(header.column),
3256
- ...isPinned ? { zIndex: 2 } : {}
3257
- },
3258
- className: cn(
3259
- "group/th relative h-9 px-2 text-left align-middle text-xs font-medium text-muted-foreground select-none",
3260
- canReorder && "cursor-grab active:cursor-grabbing",
3261
- isPinned && "bg-card",
3262
- isBeingDragged && "opacity-50",
3263
- isDropTarget && "bg-primary/10 ring-2 ring-inset ring-primary/40",
3264
- meta?.headerClassName
3265
- ),
3266
- children: [
3267
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
3268
- canReorder && /* @__PURE__ */ jsx(
3269
- GripVerticalIcon,
3270
- {
3271
- className: "-ml-1 size-3 shrink-0 text-muted-foreground/40 opacity-0 transition group-hover/th:opacity-100",
3272
- "aria-hidden": "true"
3273
- }
3277
+ /* @__PURE__ */ jsx(
3278
+ "thead",
3279
+ {
3280
+ className: cn("bg-card", stickyHeader && "sticky top-0 z-10"),
3281
+ children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsx("tr", { className: "border-b", children: hg.headers.map((header) => {
3282
+ const meta = header.column.columnDef.meta;
3283
+ const isUtility = header.column.id === "__select" || header.column.id === "__expand" || header.column.id === "__actions";
3284
+ const isPinned = !!header.column.getIsPinned();
3285
+ const canReorder = !isUtility && f.reordering;
3286
+ const isDropTarget = canReorder && dragOverColId === header.column.id;
3287
+ const isBeingDragged = canReorder && activeReorderId === header.column.id;
3288
+ return /* @__PURE__ */ jsxs(
3289
+ "th",
3290
+ {
3291
+ colSpan: header.colSpan,
3292
+ "data-col-id": header.column.id,
3293
+ onPointerDown: canReorder ? onHeaderPointerDown(header.column.id) : void 0,
3294
+ onPointerMove: canReorder ? onHeaderPointerMove : void 0,
3295
+ onPointerUp: canReorder ? onHeaderPointerUp : void 0,
3296
+ onPointerCancel: canReorder ? onHeaderPointerUp : void 0,
3297
+ style: {
3298
+ width: header.getSize(),
3299
+ ...getPinningStyles(header.column),
3300
+ ...isPinned ? { zIndex: 2 } : {}
3301
+ },
3302
+ className: cn(
3303
+ "group/th relative h-9 px-2 text-left align-middle text-xs font-medium text-muted-foreground select-none",
3304
+ canReorder && "cursor-grab active:cursor-grabbing",
3305
+ isPinned && "bg-card",
3306
+ isBeingDragged && "opacity-50",
3307
+ isDropTarget && "bg-primary/10 ring-2 ring-primary/40 ring-inset",
3308
+ meta?.headerClassName
3274
3309
  ),
3275
- /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()) })
3276
- ] }),
3277
- header.column.getCanResize() && /* @__PURE__ */ jsx(
3278
- "span",
3279
- {
3280
- "data-no-drag": true,
3281
- onPointerDown: (e) => e.stopPropagation(),
3282
- onMouseDown: header.getResizeHandler(),
3283
- onTouchStart: header.getResizeHandler(),
3284
- onDoubleClick: () => header.column.resetSize(),
3285
- className: cn(
3286
- "absolute top-0 right-0 h-full w-1 cursor-col-resize touch-none select-none bg-transparent transition-colors hover:bg-primary/40",
3287
- header.column.getIsResizing() && "bg-primary"
3310
+ children: [
3311
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
3312
+ canReorder && /* @__PURE__ */ jsx(
3313
+ GripVerticalIcon,
3314
+ {
3315
+ className: "-ml-1 size-3 shrink-0 text-muted-foreground/40 opacity-0 transition group-hover/th:opacity-100",
3316
+ "aria-hidden": "true"
3317
+ }
3318
+ ),
3319
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: header.isPlaceholder ? null : flexRender(
3320
+ header.column.columnDef.header,
3321
+ header.getContext()
3322
+ ) })
3323
+ ] }),
3324
+ header.column.getCanResize() && /* @__PURE__ */ jsx(
3325
+ "span",
3326
+ {
3327
+ "data-no-drag": true,
3328
+ onPointerDown: (e) => e.stopPropagation(),
3329
+ onMouseDown: header.getResizeHandler(),
3330
+ onTouchStart: header.getResizeHandler(),
3331
+ onDoubleClick: () => header.column.resetSize(),
3332
+ className: cn(
3333
+ "absolute top-0 right-0 h-full w-1 cursor-col-resize touch-none bg-transparent transition-colors select-none hover:bg-primary/40",
3334
+ header.column.getIsResizing() && "bg-primary"
3335
+ )
3336
+ }
3288
3337
  )
3289
- }
3290
- )
3291
- ]
3292
- },
3293
- header.id
3294
- );
3295
- }) }, hg.id)) }),
3338
+ ]
3339
+ },
3340
+ header.id
3341
+ );
3342
+ }) }, hg.id))
3343
+ }
3344
+ ),
3296
3345
  /* @__PURE__ */ jsx("tbody", { children: effectiveIsLoading ? renderSkeleton(visibleLeafCount, pagination.pageSize) : sourceError && rows.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
3297
3346
  "td",
3298
3347
  {
@@ -3336,7 +3385,13 @@ function DataTable({
3336
3385
  labels.refreshing
3337
3386
  ] })
3338
3387
  ] }),
3339
- f.pagination && /* @__PURE__ */ jsx(DataTablePagination, { table, pageSizeOptions }),
3388
+ f.pagination && /* @__PURE__ */ jsx(
3389
+ DataTablePagination,
3390
+ {
3391
+ table,
3392
+ pageSizeOptions
3393
+ }
3394
+ ),
3340
3395
  /* @__PURE__ */ jsx(
3341
3396
  DataTableViewSheet,
3342
3397
  {