@kanunilabs/datagrid-react 1.7.0 → 1.8.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/styles.css CHANGED
@@ -630,7 +630,11 @@
630
630
  border-color: var(--dg-primary);
631
631
  }
632
632
 
633
+ /* Commands: an icon and a label side by side (toolbarIcons.ts). */
633
634
  .kanuni-datagrid-toolbar > button {
635
+ display: inline-flex;
636
+ align-items: center;
637
+ gap: 5px;
634
638
  padding: 3px 10px;
635
639
  border: 1px solid var(--dg-border-strong);
636
640
  border-radius: var(--dg-radius-control);
@@ -641,6 +645,10 @@
641
645
  cursor: pointer;
642
646
  }
643
647
 
648
+ .kanuni-datagrid-icon {
649
+ flex: none;
650
+ }
651
+
644
652
  .kanuni-datagrid-toolbar > button:hover:not(:disabled) {
645
653
  background: var(--dg-surface-hover);
646
654
  }
@@ -1038,9 +1046,8 @@
1038
1046
  color: var(--dg-text);
1039
1047
  }
1040
1048
 
1041
- /* The panel is sized in whole rows by the component (span x rowHeight); this
1042
- rule only styles it. Overriding the height here would desync it from the
1043
- filler slots the virtualizer reserved. */
1049
+ /* The panel's height is the component's (the height index reserves it);
1050
+ overriding it here would desync the rows below from their offsets. */
1044
1051
  .kanuni-datagrid-detail-row {
1045
1052
  background: var(--dg-surface);
1046
1053
  border-bottom: 1px solid var(--dg-border);
@@ -1050,7 +1057,9 @@
1050
1057
  position: sticky;
1051
1058
  inset-inline-start: 0;
1052
1059
  box-sizing: border-box;
1053
- width: 100%;
1060
+ /* The VIEWPORT's width, like the edit form below: the row is as wide as
1061
+ every column, and at 100% a panel under a wide grid ran off screen. */
1062
+ width: var(--dg-viewport-width, 100%);
1054
1063
  height: 100%;
1055
1064
  padding: 8px 12px;
1056
1065
  overflow: auto;
@@ -1695,6 +1704,17 @@
1695
1704
  }
1696
1705
 
1697
1706
  /* ── Search highlight (P2.4) ──────────────────────────────── */
1707
+ /* A highlighted cell's text and marks sit in ONE span: side by side in the
1708
+ flex cell, each part was a flex item and lost the spaces at its edges. The
1709
+ span carries the cell's single-line ellipsis itself, since a flex item does
1710
+ not inherit it. */
1711
+ .kanuni-datagrid-cell-text {
1712
+ min-width: 0;
1713
+ overflow: hidden;
1714
+ text-overflow: ellipsis;
1715
+ white-space: inherit;
1716
+ }
1717
+
1698
1718
  /* A <mark>, so the match is in the accessibility tree as emphasis rather than
1699
1719
  as a colour only. The browser default is a hard yellow that fights every
1700
1720
  theme; these follow the accent instead. */
@@ -2151,6 +2171,14 @@
2151
2171
  padding: 4px;
2152
2172
  }
2153
2173
 
2174
+ /* The chooser says what it is: an untitled box of checkboxes read as nothing
2175
+ having opened (2026-10-14). */
2176
+ .kanuni-datagrid-chooser-title {
2177
+ padding: 2px 4px 0;
2178
+ font-weight: 600;
2179
+ color: var(--dg-text);
2180
+ }
2181
+
2154
2182
  .kanuni-datagrid-chooser-empty {
2155
2183
  padding: 8px 4px;
2156
2184
  color: var(--dg-text-muted);
@@ -3153,6 +3181,279 @@
3153
3181
  }
3154
3182
  }
3155
3183
 
3184
+ /* ─────────────────────────────────────────────────────────────
3185
+ Editing modes: batch, row, form, popup.
3186
+ ─────────────────────────────────────────────────────────────
3187
+ Moved here from the Enterprise sheet when these modes became Community
3188
+ (owner decision, 2026-10-16). The Enterprise sheet loads after this one,
3189
+ so the Enterprise grid looks exactly as before; the plain-JS grid reads
3190
+ this file too. The command column's rules stay in the Enterprise sheet. */
3191
+
3192
+ /* ── Pending (unsaved) edits ──────────────────────────────── */
3193
+ /* A corner triangle rather than a background tint: the row may already be
3194
+ striped, selected or in-range, and those must stay distinguishable. */
3195
+ .kanuni-datagrid-root .kanuni-datagrid-cell--dirty {
3196
+ position: relative;
3197
+ }
3198
+
3199
+ .kanuni-datagrid-root .kanuni-datagrid-cell--dirty::before {
3200
+ content: '';
3201
+ position: absolute;
3202
+ top: 0;
3203
+ left: 0;
3204
+ border-width: 5px 5px 0 0;
3205
+ border-style: solid;
3206
+ border-color: var(--dg-primary) transparent transparent transparent;
3207
+ pointer-events: none;
3208
+ }
3209
+
3210
+ /* Marked for deletion, not yet saved (batch mode). Still readable, clearly on
3211
+ its way out, and still right-clickable so the delete can be undone. */
3212
+ .kanuni-datagrid-root .kanuni-datagrid-cell--removed {
3213
+ text-decoration: line-through;
3214
+ opacity: 0.55;
3215
+ background: color-mix(in srgb, var(--dg-danger) 10%, transparent);
3216
+ }
3217
+
3218
+ /* ── The Save / Cancel strip (and the Enterprise filter strip) ── */
3219
+ .kanuni-datagrid-filter-bar {
3220
+ display: flex;
3221
+ align-items: center;
3222
+ gap: 8px;
3223
+ padding: 6px 8px;
3224
+ border: 1px solid var(--dg-border);
3225
+ border-bottom: none;
3226
+ border-radius: var(--dg-radius) var(--dg-radius) 0 0;
3227
+ background: var(--dg-surface-header);
3228
+ font-size: var(--dg-chrome-font-size);
3229
+ }
3230
+
3231
+ .kanuni-datagrid-filter-bar button {
3232
+ padding: 2px 8px;
3233
+ border: 1px solid var(--dg-border-strong);
3234
+ border-radius: var(--dg-radius-control);
3235
+ background: var(--dg-surface);
3236
+ color: inherit;
3237
+ font: inherit;
3238
+ font-size: var(--dg-chrome-font-size);
3239
+ cursor: pointer;
3240
+ }
3241
+
3242
+ .kanuni-datagrid-filter-active {
3243
+ color: var(--dg-primary);
3244
+ font-weight: 600;
3245
+ }
3246
+
3247
+ /* Inside the free grid's root, whose own border is the frame: the strip is
3248
+ a band across the top rather than a tab sitting on the grid. */
3249
+ .kanuni-datagrid-root > .kanuni-datagrid-edit-bar {
3250
+ flex: none;
3251
+ border: 0;
3252
+ border-bottom: 1px solid var(--dg-border);
3253
+ border-radius: 0;
3254
+ }
3255
+
3256
+ /* The filter, in words. Truncated rather than wrapped: the strip is one line
3257
+ tall, and a growing bar would push the grid around as conditions are added.
3258
+ The full sentence is on the element's title. */
3259
+ .kanuni-datagrid-filter-active {
3260
+ overflow: hidden;
3261
+ text-overflow: ellipsis;
3262
+ white-space: nowrap;
3263
+ max-width: min(60ch, 50%);
3264
+ }
3265
+
3266
+ /* ── Row / form / popup editing (G2) ──────────────────────── */
3267
+ /*
3268
+ * One panel, two placements: in the row flow (`form`, the `--inline` variant
3269
+ * below, inside a row slot the virtualizer sized) and in a dialog over the
3270
+ * grid (`popup`).
3271
+ */
3272
+ .kanuni-datagrid-edit-form {
3273
+ flex: none;
3274
+ display: flex;
3275
+ flex-direction: column;
3276
+ max-height: 60vh;
3277
+ margin-bottom: 8px;
3278
+ border: 1px solid var(--dg-border-strong);
3279
+ border-radius: var(--dg-radius);
3280
+ background: var(--dg-surface);
3281
+ color: var(--dg-text);
3282
+ box-shadow: var(--dg-shadow-panel);
3283
+ font-size: var(--dg-font-size);
3284
+ }
3285
+
3286
+ /* Drawn inside a row slot: the row is already the card, so the panel drops the
3287
+ chrome that exists to lift a FLOATING panel off the page. `max-height: 100%`
3288
+ rather than 60vh — the slot's height is the budget here, and overflowing it
3289
+ would spill over the rows below, which the virtualizer has already placed. */
3290
+ .kanuni-datagrid-edit-form--inline {
3291
+ height: 100%;
3292
+ max-height: 100%;
3293
+ margin-bottom: 0;
3294
+ border: 0;
3295
+ border-radius: 0;
3296
+ box-shadow: none;
3297
+ background: var(--dg-surface-header);
3298
+ }
3299
+
3300
+ .kanuni-datagrid-edit-form-header {
3301
+ padding: 10px 14px;
3302
+ border-bottom: 1px solid var(--dg-border);
3303
+ background: var(--dg-surface-header);
3304
+ border-radius: var(--dg-radius) var(--dg-radius) 0 0;
3305
+ }
3306
+
3307
+ .kanuni-datagrid-edit-form-fields {
3308
+ flex: 1;
3309
+ overflow: auto;
3310
+ display: grid;
3311
+ /* Two columns on a wide grid, one on a narrow one — without a media query,
3312
+ which would key off the VIEWPORT when what matters is the grid's width. */
3313
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
3314
+ gap: 10px 16px;
3315
+ padding: 14px;
3316
+ }
3317
+
3318
+ .kanuni-datagrid-edit-form-field {
3319
+ display: flex;
3320
+ flex-direction: column;
3321
+ gap: 3px;
3322
+ min-width: 0;
3323
+ }
3324
+
3325
+ .kanuni-datagrid-edit-form-label {
3326
+ font-size: 11px;
3327
+ font-weight: 600;
3328
+ opacity: 0.75;
3329
+ }
3330
+
3331
+ .kanuni-datagrid-edit-form-input {
3332
+ width: 100%;
3333
+ min-width: 0;
3334
+ padding: 4px 6px;
3335
+ border: 1px solid var(--dg-border-strong);
3336
+ border-radius: var(--dg-radius-control);
3337
+ background: var(--dg-surface);
3338
+ color: inherit;
3339
+ font: inherit;
3340
+ font-size: var(--dg-font-size);
3341
+ }
3342
+
3343
+ input[type='checkbox'].kanuni-datagrid-edit-form-input {
3344
+ width: auto;
3345
+ accent-color: var(--dg-primary);
3346
+ }
3347
+
3348
+ .kanuni-datagrid-edit-form-input:focus {
3349
+ outline: 2px solid var(--dg-primary);
3350
+ outline-offset: -1px;
3351
+ }
3352
+
3353
+ .kanuni-datagrid-edit-form-field[data-invalid] .kanuni-datagrid-edit-form-input {
3354
+ border-color: var(--dg-danger);
3355
+ }
3356
+
3357
+ .kanuni-datagrid-edit-form-message {
3358
+ color: var(--dg-danger-text);
3359
+ font-size: 11px;
3360
+ }
3361
+
3362
+ /* A rejected save, above the fields — where the eye already is after pressing
3363
+ Save, rather than beside the button that is about to be pressed again. */
3364
+ .kanuni-datagrid-edit-form-error {
3365
+ margin: 10px 14px 0;
3366
+ padding: 6px 10px;
3367
+ border-radius: var(--dg-radius-control);
3368
+ background: color-mix(in srgb, var(--dg-danger) 12%, transparent);
3369
+ color: var(--dg-danger-text);
3370
+ font-size: var(--dg-chrome-font-size);
3371
+ }
3372
+
3373
+ .kanuni-datagrid-edit-form-footer {
3374
+ display: flex;
3375
+ align-items: center;
3376
+ gap: 8px;
3377
+ padding: 10px 14px;
3378
+ border-top: 1px solid var(--dg-border);
3379
+ background: var(--dg-surface-header);
3380
+ border-radius: 0 0 var(--dg-radius) var(--dg-radius);
3381
+ }
3382
+
3383
+ .kanuni-datagrid-edit-form-hint {
3384
+ margin-inline-end: auto;
3385
+ font-size: 11px;
3386
+ opacity: 0.65;
3387
+ }
3388
+
3389
+ .kanuni-datagrid-edit-form-footer button {
3390
+ padding: 4px 12px;
3391
+ border: 1px solid var(--dg-border-strong);
3392
+ border-radius: var(--dg-radius-control);
3393
+ background: var(--dg-surface);
3394
+ color: inherit;
3395
+ font: inherit;
3396
+ font-size: var(--dg-chrome-font-size);
3397
+ cursor: pointer;
3398
+ }
3399
+
3400
+ .kanuni-datagrid-edit-form-footer button:disabled {
3401
+ opacity: 0.55;
3402
+ cursor: default;
3403
+ }
3404
+
3405
+ .kanuni-datagrid-edit-form-save {
3406
+ border-color: var(--dg-primary) !important;
3407
+ background: var(--dg-primary) !important;
3408
+ color: var(--dg-on-primary) !important;
3409
+ }
3410
+
3411
+ /* ── Popup mode ───────────────────────────────────────────── */
3412
+ .kanuni-datagrid-edit-popup {
3413
+ position: fixed;
3414
+ inset: 0;
3415
+ z-index: 1000;
3416
+ display: flex;
3417
+ align-items: center;
3418
+ justify-content: center;
3419
+ }
3420
+
3421
+ .kanuni-datagrid-edit-popup-overlay {
3422
+ position: absolute;
3423
+ inset: 0;
3424
+ /* Opaque enough to read the form against a dense grid — the see-through
3425
+ overlay was a real bug in PivotGrid's drill-down modal. */
3426
+ background: var(--dg-overlay);
3427
+ }
3428
+
3429
+ .kanuni-datagrid-edit-popup > .kanuni-datagrid-edit-form {
3430
+ position: relative;
3431
+ width: min(720px, 94vw);
3432
+ max-height: 86vh;
3433
+ margin-bottom: 0;
3434
+ box-shadow: var(--dg-shadow-dialog);
3435
+ }
3436
+
3437
+ /* While a row/form/popup session owns the record, the grid behind it must not
3438
+ accept edits: a click that lands on a cell would change a value the user
3439
+ cannot see is changing, in a record they believe is open in the dialog. */
3440
+ /* A modal covers the grid, so nothing under it should react at all. */
3441
+ .kanuni-datagrid-enterprise[data-row-session='popup'] .kanuni-datagrid-scroller,
3442
+ .kanuni-datagrid-root[data-row-session='popup'] .kanuni-datagrid-scroller {
3443
+ pointer-events: none;
3444
+ }
3445
+
3446
+ /* The in-grid form is INSIDE the scroller, so the lock is per row rather than
3447
+ over the whole scroll area. Locking the scroller would take the form's own
3448
+ fields and buttons with it — and the wheel, leaving a form taller than the
3449
+ viewport with a Save nobody could scroll to. */
3450
+ .kanuni-datagrid-enterprise[data-row-session='form']
3451
+ .kanuni-datagrid-row:not(.kanuni-datagrid-editform-row),
3452
+ .kanuni-datagrid-root[data-row-session='form']
3453
+ .kanuni-datagrid-row:not(.kanuni-datagrid-editform-row) {
3454
+ pointer-events: none;
3455
+ }
3456
+
3156
3457
  /* ─────────────────────────────────────────────────────────────
3157
3458
  KANUNILABS DataGrid — packaged themes
3158
3459
  ─────────────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanunilabs/datagrid-react",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "High-performance React data grid — virtualized rows and columns, sticky pinned columns, sorting, filtering and theming",
5
5
  "keywords": [
6
6
  "react",
@@ -57,7 +57,7 @@
57
57
  "access": "public"
58
58
  },
59
59
  "dependencies": {
60
- "@kanunilabs/datagrid-core": "1.9.0"
60
+ "@kanunilabs/datagrid-core": "1.10.1"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "react": ">=18.0.0",