@dxos/lit-grid 0.8.4-main.fffef41 → 0.8.4-staging.60fe92afc8

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.
Files changed (34) hide show
  1. package/LICENSE +102 -5
  2. package/dist/src/dx-grid-axis-resize-handle.d.ts.map +1 -1
  3. package/dist/src/dx-grid-multiselect-cell.d.ts.map +1 -1
  4. package/dist/src/dx-grid.d.ts +1 -1
  5. package/dist/src/dx-grid.d.ts.map +1 -1
  6. package/dist/src/dx-grid.js +2 -4
  7. package/dist/src/dx-grid.js.map +1 -1
  8. package/dist/src/dx-grid.lit-stories.d.ts +12 -15
  9. package/dist/src/dx-grid.lit-stories.d.ts.map +1 -1
  10. package/dist/src/dx-grid.lit-stories.js +5 -5
  11. package/dist/src/dx-grid.lit-stories.js.map +1 -1
  12. package/dist/src/playwright/dx-grid.spec.js +7 -6
  13. package/dist/src/playwright/dx-grid.spec.js.map +1 -1
  14. package/dist/src/playwright/playwright.config.d.ts.map +1 -1
  15. package/dist/src/playwright/playwright.config.js +1 -1
  16. package/dist/src/playwright/playwright.config.js.map +1 -1
  17. package/dist/src/testing/dx-grid-manager.d.ts.map +1 -1
  18. package/dist/src/testing/dx-grid-manager.js.map +1 -1
  19. package/dist/src/types.d.ts +1 -1
  20. package/dist/src/types.d.ts.map +1 -1
  21. package/dist/src/util.d.ts +8 -6
  22. package/dist/src/util.d.ts.map +1 -1
  23. package/dist/src/util.js +4 -2
  24. package/dist/src/util.js.map +1 -1
  25. package/dist/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +16 -13
  27. package/src/dx-grid-axis-resize-handle.pcss +4 -4
  28. package/src/dx-grid-multiselect-cell.pcss +7 -5
  29. package/src/dx-grid.lit-stories.ts +3 -5
  30. package/src/dx-grid.pcss +58 -32
  31. package/src/dx-grid.ts +3 -4
  32. package/src/playwright/dx-grid.spec.ts +7 -6
  33. package/src/playwright/playwright.config.ts +1 -1
  34. package/src/util.ts +4 -2
package/package.json CHANGED
@@ -1,12 +1,19 @@
1
1
  {
2
2
  "name": "@dxos/lit-grid",
3
- "version": "0.8.4-main.fffef41",
3
+ "version": "0.8.4-staging.60fe92afc8",
4
4
  "description": "A grid Web Component using Lit",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
- "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
11
+ "license": "FSL-1.1-Apache-2.0",
8
12
  "author": "DXOS.org",
9
- "sideEffects": true,
13
+ "sideEffects": [
14
+ "*.css",
15
+ "*.pcss"
16
+ ],
10
17
  "type": "module",
11
18
  "exports": {
12
19
  ".": {
@@ -23,23 +30,19 @@
23
30
  },
24
31
  "main": "dist/src/index.js",
25
32
  "types": "dist/src/index.d.ts",
26
- "typesVersions": {
27
- "*": {
28
- "testing": [
29
- "dist/src/testing/index.d.ts"
30
- ]
31
- }
32
- },
33
33
  "files": [
34
34
  "src",
35
35
  "dist"
36
36
  ],
37
37
  "dependencies": {
38
- "@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
38
+ "@atlaskit/pragmatic-drag-and-drop": "1.7.7",
39
39
  "lit": "^3.3.1"
40
40
  },
41
41
  "devDependencies": {
42
- "@dxos/random": "0.8.4-main.fffef41",
43
- "@dxos/test-utils": "0.8.4-main.fffef41"
42
+ "@dxos/random": "0.8.4-staging.60fe92afc8",
43
+ "@dxos/test-utils": "0.8.4-staging.60fe92afc8"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
44
47
  }
45
48
  }
@@ -7,24 +7,24 @@ dx-grid-axis-resize-handle {
7
7
  background: transparent;
8
8
  z-index: 2;
9
9
  &:hover {
10
- background: var(--dx-grid-resizeHandleHover, var(--dx-hoverSurface));
10
+ background: var(--color-hover-surface);
11
11
  }
12
12
  &[data-dx-grid-axis='col'] {
13
13
  inset-block: 0;
14
14
  inset-inline-end: 0;
15
- inline-size: .5rem;
15
+ inline-size: 0.5rem;
16
16
  cursor: col-resize;
17
17
  }
18
18
  &[data-dx-grid-axis='row'] {
19
19
  inset-inline: 0;
20
20
  inset-block-end: 0;
21
- block-size: .5rem;
21
+ block-size: 0.5rem;
22
22
  cursor: row-resize;
23
23
  }
24
24
  &:focus {
25
25
  outline: none;
26
26
  }
27
27
  &:focus-visible {
28
- background: var(--dx-grid-resizeHandleFocus, var(--dx-accentSurface));
28
+ background: var(--color-accent-bg);
29
29
  }
30
30
  }
@@ -1,8 +1,10 @@
1
+ @reference "../../ui-theme/src/main.css";
2
+
1
3
  dx-grid-multiselect-cell {
2
4
  display: contents;
3
5
  }
4
6
 
5
- .dx-grid__cell__multiselect{
7
+ .dx-grid__cell__multiselect {
6
8
  display: flex;
7
9
  flex-flow: row nowrap;
8
10
  gap: 2px;
@@ -14,19 +16,19 @@ dx-grid-multiselect-cell {
14
16
  white-space: nowrap;
15
17
  text-overflow: ellipsis;
16
18
  &.dx-grid__cell__multiselect__value {
17
- @apply bs-full border border-separator text-xs font-semibold pli-2 plb-0.5 rounded cursor-default text-neutral-800 dark:text-neutral-150
19
+ @apply h-full border border-separator text-xs font-semibold px-2 py-0.5 rounded cursor-default text-neutral-800 dark:text-neutral-200;
18
20
  }
19
21
  &.dx-grid__cell__multiselect__placeholder {
20
22
  @apply text-description;
21
23
  }
22
24
  }
23
- & > .dx-grid__cell__multiselect__separator{
25
+ & > .dx-grid__cell__multiselect__separator {
24
26
  flex: 1 0 0;
25
27
  }
26
28
  & > svg {
27
29
  flex: 0 0 auto;
28
- margin-block: .25em;
30
+ margin-block: 0.25em;
29
31
  inline-size: 1em;
30
32
  block-size: 1em;
31
33
  }
32
- }
34
+ }
@@ -3,15 +3,13 @@
3
3
  //
4
4
 
5
5
  import '@dxos-theme';
6
-
7
6
  import './dx-grid.ts';
8
7
  import './dx-grid.pcss';
9
-
10
8
  import './dx-grid-multiselect-cell.ts';
11
9
 
12
10
  import { html, nothing } from 'lit';
13
11
 
14
- import { faker } from '@dxos/random';
12
+ import { random } from '@dxos/random';
15
13
 
16
14
  import { defaultRowSize } from './defs.js';
17
15
  import { type DxGridFrozenPlane, type DxGridPlaneCells, type DxGridProps } from './types';
@@ -39,7 +37,7 @@ const initialLabels = {
39
37
  '0,0': { value: '', resizeHandle: 'col' },
40
38
  },
41
39
  frozenColsStart: [...Array(64)].reduce((acc, _, i) => {
42
- acc[`0,${i}`] = { value: rowToA1Notation(i), className: 'text-end pie-1', resizeHandle: 'row' };
40
+ acc[`0,${i}`] = { value: rowToA1Notation(i), className: 'text-end pe-1', resizeHandle: 'row' };
43
41
  return acc;
44
42
  }, {}),
45
43
  frozenRowsStart: [...Array(12)].reduce((acc, _, i) => {
@@ -53,7 +51,7 @@ Basic.args = {
53
51
  grid: {
54
52
  '1,1': {
55
53
  // end: '8,1',
56
- value: faker.lorem.paragraphs(5),
54
+ value: random.lorem.paragraphs(5),
57
55
  },
58
56
  '2,2': {
59
57
  value: '',
package/src/dx-grid.pcss CHANGED
@@ -4,10 +4,14 @@
4
4
  @layer dx-tokens {
5
5
  :root {
6
6
  --dx-grid-cell-padding-block: 0.2rem;
7
- --dx-grid-cell-content-padding-block: calc(var(--dx-grid-cell-padding-block) - var(--dx-gridFocusIndicatorWidth));
7
+ --dx-grid-cell-content-padding-block: calc(
8
+ var(--dx-grid-cell-padding-block) - var(--dx-grid-focus-indicator-width)
9
+ );
8
10
  --dx-grid-cell-editor-padding-block: var(--dx-grid-cell-content-padding-block);
9
11
  --dx-grid-cell-padding-inline: 0.25rem;
10
- --dx-grid-cell-content-padding-inline: calc(var(--dx-grid-cell-padding-inline) - var(--dx-gridFocusIndicatorWidth));
12
+ --dx-grid-cell-content-padding-inline: calc(
13
+ var(--dx-grid-cell-padding-inline) - var(--dx-grid-focus-indicator-width)
14
+ );
11
15
  --dx-grid-cell-editor-padding-inline: var(--dx-grid-cell-content-padding-inline);
12
16
  }
13
17
  }
@@ -15,8 +19,13 @@
15
19
  @layer dx-components {
16
20
  dx-grid {
17
21
  display: contents;
18
- --dx-grid-gap: 1px;
19
- --dx-plane-gap: 1px;
22
+ /*
23
+ * Cells touch edge-to-edge; lines come from each cell's border-right /
24
+ * border-bottom. Setting either gap to a non-zero value re-introduces the
25
+ * doubled-line artifact at plane seams.
26
+ */
27
+ --dx-grid-gap: 0;
28
+ --dx-plane-gap: 0;
20
29
  }
21
30
 
22
31
  .dx-grid {
@@ -33,8 +42,6 @@
33
42
 
34
43
  touch-action: none;
35
44
  user-select: none;
36
-
37
- background: var(--dx-grid-lines, var(--dx-gridLine));
38
45
  }
39
46
 
40
47
  .dx-grid__plane--frozen-row,
@@ -54,7 +61,7 @@
54
61
  position: absolute;
55
62
  inset: 0;
56
63
  pointer-events: none;
57
- border: var(--dx-gridFocusIndicatorWidth) solid var(--dx-gridFocusIndicatorColor);
64
+ border: var(--dx-grid-focus-indicator-width) solid var(--color-focus-ring);
58
65
  }
59
66
  }
60
67
 
@@ -67,15 +74,28 @@
67
74
  }
68
75
 
69
76
  .dx-grid {
70
- --dx-grid-cell-surface: var(--dx-grid-base, var(--dx-baseSurface));
77
+ --grid-cell-surface: var(--color-grid-surface);
78
+ --grid-cell-fg: var(--color-grid-fg);
71
79
 
72
80
  [role='gridcell'],
73
81
  [role='columnheader'],
74
82
  [role='rowheader'] {
75
- background: var(--dx-grid-cell-surface);
83
+ background: var(--grid-cell-surface);
84
+ color: var(--grid-cell-fg);
76
85
  cursor: pointer;
77
86
  position: relative;
78
87
 
88
+ /*
89
+ * Paint grid lines via inset box-shadow rather than border so the cell's
90
+ * content-box equals its border-box. This lets `.dx-grid__cell__content`
91
+ * (with block-size/inline-size: 100%) fill the cell exactly — including
92
+ * the right/bottom edges. When focused, the cell-content's own border
93
+ * (focus ring) then aligns with the grid lines pixel-for-pixel.
94
+ */
95
+ box-shadow:
96
+ inset calc(-1 * var(--dx-grid-focus-indicator-width)) 0 0 var(--color-grid-line),
97
+ inset 0 calc(-1 * var(--dx-grid-focus-indicator-width)) 0 var(--color-grid-line);
98
+
79
99
  &[aria-readonly='true'] {
80
100
  cursor: default;
81
101
  }
@@ -98,10 +118,11 @@
98
118
  white-space: nowrap;
99
119
  block-size: 100%;
100
120
  position: relative;
101
- border: var(--dx-gridFocusIndicatorWidth) solid transparent;
121
+ border: var(--dx-grid-focus-indicator-width) solid transparent;
102
122
  border-radius: 2px;
103
123
 
104
- &:has(.dx-tag), &:has(dx-tag-picker-item) {
124
+ &:has(.dx-tag),
125
+ &:has(dx-tag-picker-item) {
105
126
  text-overflow: clip;
106
127
  line-height: 0;
107
128
  --dx-grid-cell-content-padding-inline: 1px;
@@ -110,7 +131,7 @@
110
131
  }
111
132
 
112
133
  &.dx-grid__cell--commented {
113
- background: var(--dx-grid-commented, var(--dx-gridCommented));
134
+ background: var(--color-grid-comment);
114
135
  }
115
136
  }
116
137
 
@@ -119,10 +140,12 @@
119
140
  [role='columnheader'],
120
141
  [role='rowheader'] {
121
142
  &[aria-selected] {
122
- --dx-grid-cell-surface: var(--dx-gridSelectionOverlay);
143
+ --grid-cell-surface: var(--color-grid-selection-surface);
144
+ --grid-cell-fg: var(--color-grid-selection-fg);
123
145
 
124
146
  &:focus:not([aria-readonly='true']),
125
- &:focus-visible, &:focus-within {
147
+ &:focus-visible,
148
+ &:focus-within {
126
149
  & > .dx-grid__cell__content {
127
150
  background: transparent;
128
151
  }
@@ -140,7 +163,7 @@
140
163
  }
141
164
 
142
165
  &:has(.dx-grid__row--cta__cell:hover) .dx-grid__row--cta__cell {
143
- background: var(--dx-hoverOverlay);
166
+ background: var(--color-grid-highlight);
144
167
  }
145
168
  }
146
169
 
@@ -149,14 +172,19 @@
149
172
  [role='gridcell'],
150
173
  [role='columnheader'],
151
174
  [role='rowheader'] {
152
- &:not([data-focus-unfurl="false"]):not(.dx-grid__cell--no-focus-unfurl) {
175
+ &:not([data-focus-unfurl='false']):not(.dx-grid__cell--no-focus-unfurl) {
153
176
  &:focus,
154
177
  &:focus-within {
155
178
  & > .dx-grid__cell__content {
156
- min-block-size: 100%;
157
- block-size: min-content;
158
- max-block-size: min(12em, 50vh);
159
-
179
+ /*
180
+ * Inline (horizontal) unfurl: cell-content can grow horizontally
181
+ * to show wider content. Block-size stays clamped to the cell
182
+ * height so the focus ring aligns with the bottom grid line —
183
+ * `block-size: min-content` would let cell-content overshoot the
184
+ * cell when the content's natural height (line-height + padding +
185
+ * border) exceeds the cell track size by even a fraction of a
186
+ * pixel, pushing the focus ring's bottom edge below the grid line.
187
+ */
160
188
  min-inline-size: 100%;
161
189
  inline-size: min-content;
162
190
  max-inline-size: min(60ch, 90vw);
@@ -165,23 +193,20 @@
165
193
  scrollbar-width: thin;
166
194
  overscroll-behavior: contain;
167
195
 
168
- white-space: normal;
169
- hyphens: auto;
170
- overflow-wrap: break-word;
171
-
172
196
  z-index: 1;
173
197
 
174
- background: var(--dx-grid-cell-surface);
198
+ background: var(--grid-cell-surface);
199
+ color: var(--grid-cell-fg);
175
200
  }
176
201
 
177
202
  &:not([aria-readonly='true']) > .dx-grid__cell__content {
178
- border-color: var(--dx-gridFocusIndicatorColor);
203
+ border-color: var(--color-focus-ring);
179
204
  }
180
205
  }
181
206
  }
182
207
 
183
208
  &:focus-visible > .dx-grid__cell__content {
184
- border-color: var(--dx-gridFocusIndicatorColor);
209
+ border-color: var(--color-focus-ring);
185
210
  }
186
211
  }
187
212
  }
@@ -192,8 +217,8 @@
192
217
  hyphens: auto;
193
218
  overflow-wrap: break-word;
194
219
 
195
- background: var(--dx-grid-base, var(--dx-baseSurface));
196
- border: var(--dx-gridFocusIndicatorWidth) solid var(--dx-gridFocusIndicatorColor);
220
+ background: var(--dx-grid-base, var(--color-base-surface));
221
+ border: var(--dx-grid-focus-indicator-width) solid var(--color-focus-ring);
197
222
  border-radius: 2px;
198
223
 
199
224
  --dx-grid-cell-editor-max-block-size: min(12em, 50vh);
@@ -204,7 +229,8 @@
204
229
  inline-size: min-content;
205
230
  max-inline-size: var(--dx-grid-cell-editor-max-inline-size);
206
231
 
207
- &:has(.dx-tag), &:has(dx-tag-picker-item) {
232
+ &:has(.dx-tag),
233
+ &:has(dx-tag-picker-item) {
208
234
  text-overflow: clip;
209
235
  line-height: 0;
210
236
  --dx-grid-cell-editor-padding-inline: 1px;
@@ -218,7 +244,7 @@
218
244
  [role='columnheader'],
219
245
  [role='rowheader'] {
220
246
  &[data-dx-active]:not([aria-readonly='true']) > .dx-grid__cell__content {
221
- border-color: var(--dx-gridFocusIndicatorColor);
247
+ border-color: var(--color-focus-ring);
222
248
  }
223
249
  }
224
250
  }
@@ -246,7 +272,7 @@
246
272
  inline-size: 0;
247
273
  block-size: 0;
248
274
  border-inline-start: 0.5em solid transparent;
249
- border-block-start: 0.5em solid var(--dx-warningText);
275
+ border-block-start: 0.5em solid var(--color-warning-text);
250
276
  z-index: 1;
251
277
  }
252
278
  }
package/src/dx-grid.ts CHANGED
@@ -2,6 +2,8 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import './dx-grid-axis-resize-handle';
6
+
5
7
  import { LitElement, html, nothing } from 'lit';
6
8
  import { customElement, property, state } from 'lit/decorators.js';
7
9
  import { type Ref, createRef, ref } from 'lit/directives/ref.js';
@@ -9,7 +11,6 @@ import { styleMap } from 'lit/directives/style-map.js';
9
11
  import { html as staticHtml, unsafeStatic } from 'lit/static-html.js';
10
12
 
11
13
  import { defaultColSize, defaultRowSize, focusUnfurlDefault } from './defs';
12
- import './dx-grid-axis-resize-handle';
13
14
  import {
14
15
  DxAxisResize,
15
16
  type DxAxisResizeInternal,
@@ -1476,9 +1477,7 @@ export class DxGrid extends LitElement {
1476
1477
  .split(' ')
1477
1478
  .filter((value) => value)
1478
1479
  .map(
1479
- // TODO(burdon): Consistent camelCase?
1480
- (activeRef) =>
1481
- `[data-refs~="${activeRef}"] { background: var(--dx-grid-commented-active, var(--dx-gridCommentedActive)) !important; }`,
1480
+ (activeRef) => `[data-refs~="${activeRef}"] { background: var(--color-grid-comment-active) !important; }`,
1482
1481
  )
1483
1482
  .join('\n')}
1484
1483
  </style>
@@ -12,8 +12,9 @@ import { toPlaneCellIndex } from '../util';
12
12
 
13
13
  const gridPlaneCellSize = 31;
14
14
  const gap = 1;
15
- const nCols = 9;
16
- const nRows = 7;
15
+ // The spec viewport fits one extra column/row beyond the nominal grid plane size.
16
+ const nCols = 10;
17
+ const nRows = 8;
17
18
 
18
19
  test.describe('dx-grid', () => {
19
20
  let page: Page;
@@ -23,8 +24,8 @@ test.describe('dx-grid', () => {
23
24
  const setup = await setupPage(browser, {
24
25
  url: storybookUrl('dx-grid--spec', 9002),
25
26
  viewportSize: {
26
- width: (gridPlaneCellSize + gap) * (nCols + 1.5),
27
- height: (gridPlaneCellSize + gap) * (nRows + 1.5),
27
+ width: (gridPlaneCellSize + gap) * (nCols + 0.5),
28
+ height: (gridPlaneCellSize + gap) * (nRows + 0.5),
28
29
  }, // 336 x 272
29
30
  });
30
31
  page = setup.page;
@@ -46,8 +47,8 @@ test.describe('dx-grid', () => {
46
47
  // Now pan by wheel to the center point of the cell one right and one down from the origin cell of the grid plane.
47
48
  await grid.panByWheel(gridPlaneCellSize * 1.5 + gap, gridPlaneCellSize * 1.5 + gap);
48
49
 
49
- // Confirm that the grid plane is showing only the cells that would be visible.
50
- await grid.expectVirtualizationResult(nCols + 1, nRows + 1, 1, 1);
50
+ // Pan shifts the viewport by one cell; visible cell counts stay the same.
51
+ await grid.expectVirtualizationResult(nCols, nRows, 1, 1);
51
52
  });
52
53
 
53
54
  test('mouse access', async () => {
@@ -10,7 +10,7 @@ export default defineConfig({
10
10
  ...e2ePreset(import.meta.dirname),
11
11
  // TODO(wittjosiah): Avoid hard-coding ports.
12
12
  webServer: {
13
- command: 'moon run lit-storybook:serve-e2e -- --port=9002',
13
+ command: 'pnpm storybook dev --ci --quiet --port=9002 --config-dir=.storybook',
14
14
  port: 9002,
15
15
  reuseExistingServer: false,
16
16
  },
package/src/util.ts CHANGED
@@ -63,9 +63,11 @@ export const rowToA1Notation = (row: number): string => {
63
63
  };
64
64
 
65
65
  /**
66
- * The size in pixels of the gap between cells
66
+ * The size in pixels of the gap between cells.
67
+ * Must match `--dx-grid-gap` / `--dx-plane-gap` in `dx-grid.pcss`. Cells
68
+ * paint their own borders edge-to-edge, so this is 0.
67
69
  */
68
- export const gap = 1;
70
+ export const gap = 0;
69
71
 
70
72
  /**
71
73
  * ResizeObserver notices even subpixel changes, only respond to changes of at least 1px.