@dxos/lit-grid 0.6.13 → 0.6.14-main.2b6a0f3

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 (56) hide show
  1. package/dist/src/dx-grid-axis-resize-handle.d.ts +16 -0
  2. package/dist/src/dx-grid-axis-resize-handle.d.ts.map +1 -0
  3. package/dist/src/dx-grid-axis-resize-handle.js +96 -0
  4. package/dist/src/dx-grid-axis-resize-handle.js.map +1 -0
  5. package/dist/src/dx-grid.d.ts +138 -0
  6. package/dist/src/dx-grid.d.ts.map +1 -0
  7. package/dist/src/dx-grid.js +1224 -0
  8. package/dist/src/dx-grid.js.map +1 -0
  9. package/dist/src/dx-grid.lit-stories.d.ts +42 -0
  10. package/dist/src/dx-grid.lit-stories.d.ts.map +1 -0
  11. package/dist/src/dx-grid.lit-stories.js +166 -0
  12. package/dist/src/dx-grid.lit-stories.js.map +1 -0
  13. package/dist/src/index.d.ts +3 -0
  14. package/dist/src/index.d.ts.map +1 -0
  15. package/dist/src/index.js +6 -0
  16. package/dist/src/index.js.map +1 -0
  17. package/dist/src/types.d.ts +119 -0
  18. package/dist/src/types.d.ts.map +1 -0
  19. package/dist/src/types.js +44 -0
  20. package/dist/src/types.js.map +1 -0
  21. package/dist/src/util.d.ts +9 -0
  22. package/dist/src/util.d.ts.map +1 -0
  23. package/dist/src/util.js +19 -0
  24. package/dist/src/util.js.map +1 -0
  25. package/dist/types/src/dx-grid-axis-resize-handle.d.ts +16 -0
  26. package/dist/types/src/dx-grid-axis-resize-handle.d.ts.map +1 -0
  27. package/dist/types/src/dx-grid-axis-resize-handle.js +96 -0
  28. package/dist/types/src/dx-grid-axis-resize-handle.js.map +1 -0
  29. package/dist/types/src/dx-grid.d.ts +112 -57
  30. package/dist/types/src/dx-grid.d.ts.map +1 -1
  31. package/dist/types/src/dx-grid.js +1224 -0
  32. package/dist/types/src/dx-grid.js.map +1 -0
  33. package/dist/types/src/dx-grid.lit-stories.d.ts +27 -2
  34. package/dist/types/src/dx-grid.lit-stories.d.ts.map +1 -1
  35. package/dist/types/src/dx-grid.lit-stories.js +166 -0
  36. package/dist/types/src/dx-grid.lit-stories.js.map +1 -0
  37. package/dist/types/src/index.js +6 -0
  38. package/dist/types/src/index.js.map +1 -0
  39. package/dist/types/src/types.d.ts +111 -1
  40. package/dist/types/src/types.d.ts.map +1 -1
  41. package/dist/types/src/types.js +44 -0
  42. package/dist/types/src/types.js.map +1 -0
  43. package/dist/types/src/util.d.ts +9 -0
  44. package/dist/types/src/util.d.ts.map +1 -0
  45. package/dist/types/src/util.js +19 -0
  46. package/dist/types/src/util.js.map +1 -0
  47. package/package.json +6 -6
  48. package/src/dx-grid-axis-resize-handle.ts +87 -0
  49. package/src/dx-grid.lit-stories.ts +148 -21
  50. package/src/dx-grid.pcss +68 -69
  51. package/src/dx-grid.ts +1116 -343
  52. package/src/types.ts +161 -1
  53. package/src/util.ts +28 -0
  54. package/dist/lib/browser/index.mjs +0 -578
  55. package/dist/lib/browser/index.mjs.map +0 -7
  56. package/dist/lib/browser/meta.json +0 -1
@@ -0,0 +1,87 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
6
+ import { disableNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview';
7
+ import { preventUnhandled } from '@atlaskit/pragmatic-drag-and-drop/prevent-unhandled';
8
+ import { type CleanupFn, type DragLocationHistory } from '@atlaskit/pragmatic-drag-and-drop/types';
9
+ import { html, LitElement } from 'lit';
10
+ import { customElement, property } from 'lit/decorators.js';
11
+ import { ref } from 'lit/directives/ref.js';
12
+
13
+ import { DxAxisResizeInternal, type DxGridAxis, type DxGridFrozenPlane } from './types';
14
+
15
+ @customElement('dx-grid-axis-resize-handle')
16
+ export class DxGridAxisResizeHandle extends LitElement {
17
+ @property({ type: String })
18
+ axis: DxGridAxis = 'row';
19
+
20
+ @property({ type: String })
21
+ plane: 'grid' | DxGridFrozenPlane = 'grid';
22
+
23
+ @property({ type: String })
24
+ index: string = '-1';
25
+
26
+ @property({ type: Number })
27
+ size: number = 128;
28
+
29
+ private dragStartSize: number = 128;
30
+
31
+ override render() {
32
+ return html`<button class="dx-grid__resize-handle" data-dx-grid-axis=${this.axis} ${ref(this.mount)}>
33
+ <span class="sr-only">Resize</span>
34
+ </button>`;
35
+ }
36
+
37
+ private cleanup: CleanupFn | null = null;
38
+
39
+ private dispatchResize(location: DragLocationHistory, state: 'dragging' | 'dropped') {
40
+ const client = this.axis === 'row' ? 'clientY' : 'clientX';
41
+ const event = new DxAxisResizeInternal({
42
+ axis: this.axis,
43
+ plane: this.plane,
44
+ size: this.dragStartSize,
45
+ index: this.index,
46
+ delta: location.current.input[client] - location.initial.input[client],
47
+ state,
48
+ });
49
+ this.dispatchEvent(event);
50
+ }
51
+
52
+ private mount(element?: Element) {
53
+ this.cleanup?.();
54
+ const host = this;
55
+ if (element) {
56
+ this.cleanup = draggable({
57
+ element: element as HTMLButtonElement,
58
+ onGenerateDragPreview: ({ nativeSetDragImage }) => {
59
+ // we will be moving the line to indicate a drag
60
+ // we can disable the native drag preview
61
+ disableNativeDragPreview({ nativeSetDragImage });
62
+ // we don't want any native drop animation for when the user
63
+ // does not drop on a drop target. we want the drag to finish immediately
64
+ preventUnhandled.start();
65
+ },
66
+ onDragStart() {
67
+ host.dragStartSize = host.size;
68
+ },
69
+ onDrag({ location }) {
70
+ host.dispatchResize(location, 'dragging');
71
+ },
72
+ onDrop({ location }) {
73
+ host.dispatchResize(location, 'dropped');
74
+ },
75
+ });
76
+ }
77
+ }
78
+
79
+ override disconnectedCallback() {
80
+ super.disconnectedCallback();
81
+ this.cleanup?.();
82
+ }
83
+
84
+ override createRenderRoot() {
85
+ return this;
86
+ }
87
+ }
@@ -7,41 +7,168 @@ import './dx-grid.pcss';
7
7
 
8
8
  import { html, nothing } from 'lit';
9
9
 
10
- import { type DxGridProps } from './dx-grid';
10
+ import { type DxGridFrozenPlane, type DxGridPlaneCells, type DxGridProps } from './types';
11
+ import { colToA1Notation, rowToA1Notation } from './util';
11
12
 
12
13
  export default {
13
14
  title: 'dx-grid',
15
+ parameters: { layout: 'fullscreen' },
14
16
  };
15
17
 
16
18
  export const Basic = (props: DxGridProps) => {
17
- return html`<dx-grid
18
- cells=${props.cells ?? nothing}
19
- columnDefault=${props.columnDefault ?? nothing}
20
- rowDefault=${props.rowDefault ?? nothing}
21
- columns=${props.columns ?? nothing}
22
- ></dx-grid>`;
19
+ return html`<div class="dark" style="position:fixed;inset:0;">
20
+ <dx-grid
21
+ initialCells=${props.initialCells ?? nothing}
22
+ columnDefault=${props.columnDefault ?? nothing}
23
+ rowDefault=${props.rowDefault ?? nothing}
24
+ columns=${props.columns ?? nothing}
25
+ frozen=${props.frozen ?? nothing}
26
+ ></dx-grid>
27
+ </div>`;
23
28
  };
24
29
 
30
+ const initialLabels = {
31
+ fixedStartStart: {
32
+ '0,0': { value: '', resizeHandle: 'col' },
33
+ },
34
+ frozenColsStart: [...Array(64)].reduce((acc, _, i) => {
35
+ acc[`0,${i}`] = { value: rowToA1Notation(i), className: 'text-end !pie-1', resizeHandle: 'row' };
36
+ return acc;
37
+ }, {}),
38
+ frozenRowsStart: [...Array(12)].reduce((acc, _, i) => {
39
+ acc[`${i},0`] = { value: colToA1Notation(i), resizeHandle: 'col' };
40
+ return acc;
41
+ }, {}),
42
+ } satisfies Partial<Record<DxGridFrozenPlane | 'fixedStartStart', DxGridPlaneCells>>;
43
+
25
44
  Basic.args = {
26
- cells: JSON.stringify({
27
- '1,1': {
28
- // end: '8,1',
29
- value: 'Weekly sales report',
45
+ initialCells: JSON.stringify({
46
+ grid: {
47
+ '1,1': {
48
+ // end: '8,1',
49
+ value: 'Weekly sales report',
50
+ },
30
51
  },
31
- } satisfies DxGridProps['cells']),
52
+ ...initialLabels,
53
+ } satisfies DxGridProps['initialCells']),
32
54
  columnDefault: JSON.stringify({
33
- size: 180,
34
- resizeable: true,
55
+ grid: {
56
+ size: 180,
57
+ resizeable: true,
58
+ },
59
+ frozenColsStart: {
60
+ size: 64,
61
+ resizeable: true,
62
+ },
35
63
  } satisfies DxGridProps['columnDefault']),
36
64
  rowDefault: JSON.stringify({
37
- size: 32,
38
- resizeable: true,
65
+ grid: {
66
+ size: 32,
67
+ resizeable: true,
68
+ },
69
+ frozenRowsStart: {
70
+ size: 32,
71
+ resizeable: true,
72
+ },
39
73
  } satisfies DxGridProps['rowDefault']),
40
74
  columns: JSON.stringify({
41
- 0: { size: 200 },
42
- 1: { size: 210 },
43
- 2: { size: 230 },
44
- 3: { size: 250 },
45
- 4: { size: 270 },
75
+ grid: {
76
+ 0: { size: 200 },
77
+ 1: { size: 210 },
78
+ 2: { size: 230 },
79
+ 3: { size: 250 },
80
+ 4: { size: 270 },
81
+ },
82
+ } satisfies DxGridProps['columns']),
83
+ frozen: JSON.stringify({
84
+ frozenColsStart: 1,
85
+ frozenRowsStart: 1,
86
+ } satisfies DxGridProps['frozen']),
87
+ };
88
+
89
+ export const Frozen = (props: DxGridProps) => {
90
+ return html`<div class="dark" style="position:fixed;inset:0;">
91
+ <dx-grid
92
+ initialCells=${props.initialCells ?? nothing}
93
+ columnDefault=${props.columnDefault ?? nothing}
94
+ rowDefault=${props.rowDefault ?? nothing}
95
+ columns=${props.columns ?? nothing}
96
+ frozen=${props.frozen ?? nothing}
97
+ ></dx-grid>
98
+ </div>`;
99
+ };
100
+
101
+ Frozen.args = {
102
+ initialCells: JSON.stringify({
103
+ grid: {},
104
+ ...initialLabels,
105
+ } satisfies DxGridProps['initialCells']),
106
+ columnDefault: JSON.stringify({
107
+ grid: {
108
+ size: 32,
109
+ },
110
+ frozenColsStart: {
111
+ size: 32,
112
+ },
113
+ frozenColsEnd: {
114
+ size: 32,
115
+ },
116
+ } satisfies DxGridProps['columnDefault']),
117
+ rowDefault: JSON.stringify({
118
+ grid: {
119
+ size: 32,
120
+ },
121
+ frozenRowsStart: {
122
+ size: 32,
123
+ },
124
+ frozenRowsEnd: {
125
+ size: 32,
126
+ },
127
+ } satisfies DxGridProps['rowDefault']),
128
+ columns: JSON.stringify({ grid: {} } satisfies DxGridProps['columns']),
129
+ rows: JSON.stringify({ grid: {} } satisfies DxGridProps['rows']),
130
+ frozen: JSON.stringify({
131
+ frozenColsStart: 2,
132
+ frozenRowsStart: 2,
133
+ frozenColsEnd: 2,
134
+ frozenRowsEnd: 2,
135
+ } satisfies DxGridProps['frozen']),
136
+ };
137
+
138
+ export const Limits = (props: DxGridProps) => {
139
+ return html`<div style="position:fixed;inset:0;">
140
+ <dx-grid
141
+ limitRows=${props.limitRows ?? nothing}
142
+ limitColumns=${props.limitColumns ?? nothing}
143
+ columnDefault=${props.columnDefault ?? nothing}
144
+ rowDefault=${props.rowDefault ?? nothing}
145
+ columns=${props.columns ?? nothing}
146
+ ></dx-grid>
147
+ </div>`;
148
+ };
149
+
150
+ Limits.args = {
151
+ limitRows: JSON.stringify(10 satisfies DxGridProps['limitRows']),
152
+ limitColumns: JSON.stringify(3 satisfies DxGridProps['limitColumns']),
153
+ columnDefault: JSON.stringify({
154
+ grid: {
155
+ size: 180,
156
+ resizeable: true,
157
+ },
158
+ } satisfies DxGridProps['columnDefault']),
159
+ rowDefault: JSON.stringify({
160
+ grid: {
161
+ size: 32,
162
+ resizeable: true,
163
+ },
164
+ } satisfies DxGridProps['rowDefault']),
165
+ columns: JSON.stringify({
166
+ grid: {
167
+ 0: { size: 200 },
168
+ 1: { size: 210 },
169
+ 2: { size: 230 },
170
+ 3: { size: 250 },
171
+ 4: { size: 270 },
172
+ },
46
173
  } satisfies DxGridProps['columns']),
47
174
  };
package/src/dx-grid.pcss CHANGED
@@ -1,55 +1,35 @@
1
- dx-grid {
1
+ dx-grid, dx-grid-axis-resize-handle {
2
2
  display: contents;
3
3
  }
4
4
 
5
- .sr-only {
6
- position: absolute;
7
- width: 1px;
8
- height: 1px;
9
- padding: 0;
10
- margin: -1px;
11
- overflow: hidden;
12
- clip: rect(0, 0, 0, 0);
13
- white-space: nowrap;
14
- border-width: 0;
15
- }
16
-
17
5
  .dx-grid {
18
- position: fixed;
19
- inset: 0;
6
+ --dx-grid-gap: 1px;
7
+ --dx-plane-gap: 2px;
8
+
20
9
  display: grid;
10
+ gap: var(--dx-plane-gap);
21
11
  grid-template-columns: min-content 1fr min-content;
22
12
  grid-template-rows: min-content 1fr min-content;
23
13
  font-variant-numeric: tabular-nums;
24
- --dx-grid-gap: 1px;
25
- }
26
14
 
27
- .dx-grid__scrollbar__thumb {
28
- height: 1rem;
29
- width: 1rem;
30
- background: var(--dx-grid-thumb, var(--dx-separator));
31
- }
15
+ min-inline-size: 4rem;
16
+ min-block-size: 4rem;
17
+ inline-size: 100%;
18
+ block-size: 100%;
19
+ max-inline-size: 100dvw;
20
+ max-block-size: 100dvh;
32
21
 
33
- .dx-grid__corner,
34
- .dx-grid__scrollbar {
35
- background: var(--dx-grid-corner, var(--dx-hoverSurface));
36
- }
22
+ user-select: none;
37
23
 
38
- .dx-grid__columnheader__content,
39
- .dx-grid__rowheader__content,
40
- .dx-grid__content {
41
- display: grid;
42
- gap: var(--dx-grid-gap);
43
24
  background: var(--dx-grid-lines, var(--dx-separator));
44
- inline-size: min-content;
45
- block-size: min-content;
46
25
  }
47
26
 
48
- .dx-grid__columnheader,
49
- .dx-grid__rowheader,
50
- .dx-grid__viewport {
27
+ .dx-grid__plane--frozen-row,
28
+ .dx-grid__plane--frozen-col,
29
+ .dx-grid__plane--grid {
51
30
  overflow: hidden;
52
31
  position: relative;
32
+ display: grid;
53
33
  &:focus-visible {
54
34
  outline: none;
55
35
  }
@@ -62,60 +42,79 @@ dx-grid {
62
42
  }
63
43
  }
64
44
 
65
- .dx-grid__columnheader__content {
66
- border-block-end: 2px solid var(--dx-grid-lines, var(--dx-separator));
67
- }
68
-
69
- .dx-grid__rowheader__content {
70
- border-inline-end: 2px solid var(--dx-grid-lines, var(--dx-separator));
71
- grid-template-columns: min-content;
72
- text-align: end;
45
+ .dx-grid__plane--fixed,
46
+ .dx-grid__plane--frozen-row__content,
47
+ .dx-grid__plane--frozen-col__content,
48
+ .dx-grid__plane--grid__content {
49
+ display: grid;
50
+ gap: var(--dx-grid-gap);
73
51
  }
74
52
 
75
53
  .dx-grid {
76
54
  [role='gridcell'], [role='columnheader'], [role='rowheader'] {
55
+ position: relative;
77
56
  background: var(--dx-grid-base, var(--dx-base));
78
57
  padding: 2px;
79
58
  box-sizing: border-box;
80
59
  cursor: pointer;
81
60
  border: 1px solid transparent;
61
+ overflow: hidden;
62
+ text-overflow: ellipsis;
63
+ white-space: nowrap;
64
+ align-content: center;
82
65
  &[inert] {
83
66
  visibility: hidden;
84
67
  }
85
- &:focus, &:focus-visible {
86
- cursor: text;
87
- position: relative;
68
+ &:focus, &:focus-visible, &[data-dx-active] {
88
69
  z-index: 2;
89
70
  border-color: var(--dx-accentSurface);
90
71
  outline: none;
72
+ &:not([aria-readonly]) {
73
+ cursor: text;
74
+ }
75
+ }
76
+ &.dx-grid__cell--commented {
77
+ background: var(--dx-grid-commented, var(--dx-gridCommented));
91
78
  }
92
79
  }
93
- }
94
-
95
- .dx-grid__columnheader__content,
96
- .dx-grid__rowheader__content {
97
- & > [role='columnheader'], &> [role='rowheader'] {
98
- position: relative;
99
- & > button.dx-grid__resize-handle {
100
- position: absolute;
101
- background: transparent;
102
- &:hover {
103
- background: var(--dx-grid-resizeHandleHover, var(--dx-hoverSurface));
80
+ &[data-grid-select] {
81
+ [role='gridcell'], [role='columnheader'], [role='rowheader'] {
82
+ &[aria-selected] {
83
+ background: var(--dx-gridSelectionOverlay);
104
84
  }
105
85
  }
106
86
  }
107
87
  }
108
88
 
109
- .dx-grid__columnheader__content > [role='columnheader'] > button.dx-grid__resize-handle {
110
- inset-block: 0;
111
- inset-inline-end: 0;
112
- inline-size: .5rem;
113
- cursor: col-resize;
89
+ .dx-grid__resize-handle {
90
+ position: absolute;
91
+ background: transparent;
92
+ &:hover {
93
+ background: var(--dx-grid-resizeHandleHover, var(--dx-hoverSurface));
94
+ }
95
+ &[data-dx-grid-axis='col'] {
96
+ inset-block: 0;
97
+ inset-inline-end: 0;
98
+ inline-size: .5rem;
99
+ cursor: col-resize;
100
+ }
101
+ &[data-dx-grid-axis='row'] {
102
+ inset-inline: 0;
103
+ inset-block-end: 0;
104
+ block-size: .5rem;
105
+ cursor: row-resize;
106
+ }
114
107
  }
115
108
 
116
- .dx-grid__rowheader__content > [role='rowheader'] > button.dx-grid__resize-handle {
117
- inset-inline: 0;
118
- inset-block-end: 0;
119
- block-size: .5rem;
120
- cursor: row-resize;
121
- }
109
+ // todo(thure): Move this somewhere better.
110
+ .sr-only {
111
+ position: absolute;
112
+ width: 1px;
113
+ height: 1px;
114
+ padding: 0;
115
+ margin: -1px;
116
+ overflow: hidden;
117
+ clip: rect(0, 0, 0, 0);
118
+ white-space: nowrap;
119
+ border-width: 0;
120
+ }