@dxos/react-ui-grid 0.8.4-main.8360d9e660 → 0.8.4-main.8baae0fced

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-grid",
3
- "version": "0.8.4-main.8360d9e660",
3
+ "version": "0.8.4-main.8baae0fced",
4
4
  "description": "React component which manages a `dx-grid` Lit web component.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -8,7 +8,7 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/dxos/dxos"
10
10
  },
11
- "license": "MIT",
11
+ "license": "FSL-1.1-Apache-2.0",
12
12
  "author": "DXOS.org",
13
13
  "sideEffects": false,
14
14
  "type": "module",
@@ -16,13 +16,11 @@
16
16
  ".": {
17
17
  "source": "./src/index.ts",
18
18
  "types": "./dist/types/src/index.d.ts",
19
- "browser": "./dist/lib/browser/index.mjs"
19
+ "browser": "./dist/lib/browser/index.mjs",
20
+ "node": "./dist/lib/browser/index.mjs"
20
21
  }
21
22
  },
22
23
  "types": "dist/types/src/index.d.ts",
23
- "typesVersions": {
24
- "*": {}
25
- },
26
24
  "files": [
27
25
  "dist",
28
26
  "src"
@@ -30,33 +28,34 @@
30
28
  "dependencies": {
31
29
  "@codemirror/autocomplete": "^6.19.0",
32
30
  "@codemirror/state": "^6.5.2",
33
- "@codemirror/view": "^6.38.4",
31
+ "@codemirror/view": "^6.38.5",
34
32
  "@lit/react": "^1.0.8",
35
33
  "@radix-ui/react-context": "1.1.1",
36
34
  "@radix-ui/react-popper": "1.2.2",
37
35
  "@radix-ui/react-use-controllable-state": "1.1.0",
38
- "@dxos/lit-grid": "0.8.4-main.8360d9e660",
39
- "@dxos/react-ui-editor": "0.8.4-main.8360d9e660",
40
- "@dxos/ui-editor": "0.8.4-main.8360d9e660",
41
- "@dxos/util": "0.8.4-main.8360d9e660"
36
+ "@dxos/lit-grid": "0.8.4-main.8baae0fced",
37
+ "@dxos/react-ui-editor": "0.8.4-main.8baae0fced",
38
+ "@dxos/ui-editor": "0.8.4-main.8baae0fced",
39
+ "@dxos/util": "0.8.4-main.8baae0fced"
42
40
  },
43
41
  "devDependencies": {
44
42
  "@types/react": "~19.2.7",
45
43
  "@types/react-dom": "~19.2.3",
46
44
  "react": "~19.2.3",
47
45
  "react-dom": "~19.2.3",
48
- "vite": "^7.1.11",
49
- "@dxos/react-ui": "0.8.4-main.8360d9e660",
50
- "@dxos/react-ui-searchlist": "0.8.4-main.8360d9e660",
51
- "@dxos/storybook-utils": "0.8.4-main.8360d9e660",
52
- "@dxos/ui-theme": "0.8.4-main.8360d9e660",
53
- "@dxos/random": "0.8.4-main.8360d9e660"
46
+ "vite": "^8.0.13",
47
+ "@dxos/random": "0.8.4-main.8baae0fced",
48
+ "@dxos/react-ui": "0.8.4-main.8baae0fced",
49
+ "@dxos/react-ui-list": "0.8.4-main.8baae0fced",
50
+ "@dxos/storybook-utils": "0.8.4-main.8baae0fced",
51
+ "@dxos/react-ui-search": "0.8.4-main.8baae0fced",
52
+ "@dxos/ui-theme": "0.8.4-main.8baae0fced"
54
53
  },
55
54
  "peerDependencies": {
56
55
  "react": "~19.2.3",
57
56
  "react-dom": "~19.2.3",
58
- "@dxos/react-ui": "0.8.4-main.8360d9e660",
59
- "@dxos/ui-theme": "0.8.4-main.8360d9e660"
57
+ "@dxos/react-ui": "0.8.4-main.8baae0fced",
58
+ "@dxos/ui-theme": "0.8.4-main.8baae0fced"
60
59
  },
61
60
  "publishConfig": {
62
61
  "access": "public"
@@ -132,11 +132,22 @@ export const CellEditor = ({ value, extensions, box, gridId, autoFocus, slots, o
132
132
  extensions: [
133
133
  extensions ?? [],
134
134
  filterChars(/[\n\r]+/),
135
- EditorView.focusChangeEffect.of((state, focusing) => {
136
- if (!focusing) {
137
- onBlur?.(state.doc.toString());
138
- }
139
- return null;
135
+ // Observe the underlying blur DOM event rather than `EditorView.focusChangeEffect`. The
136
+ // focus-change facet fires asynchronously (CodeMirror schedules it on a 10ms setTimeout),
137
+ // which means in React strict mode the destroy → blur of the first EditorView runs the
138
+ // callback after the second view has mounted — committing stale data and closing the
139
+ // editor on the user's first keystroke. Deferring via `queueMicrotask` runs the check
140
+ // *after* `view.destroy()` finishes its synchronous body (which calls `dom.remove()`),
141
+ // so `view.dom.isConnected === false` reliably distinguishes a programmatic teardown
142
+ // from a real user blur. Pass `undefined` on teardown so downstream handlers can consume
143
+ // any pending suppress-next-blur flag without committing stale data.
144
+ EditorView.domEventObservers({
145
+ blur: (_event, view) => {
146
+ const doc = view.state.doc.toString();
147
+ queueMicrotask(() => {
148
+ onBlur?.(view.dom.isConnected ? doc : undefined);
149
+ });
150
+ },
140
151
  }),
141
152
  createBasicExtensions({ lineWrapping: true }),
142
153
  createThemeExtensions({
@@ -148,10 +159,10 @@ export const CellEditor = ({ value, extensions, box, gridId, autoFocus, slots, o
148
159
  slots?.editor?.className,
149
160
  ),
150
161
  },
151
- scroll: {
162
+ scroller: {
152
163
  className: mx(
153
164
  'overflow-x-hidden! !py-[max(0,calc(var(--dx-grid-cell-editor-padding-block)-1px))] pe-0! !pl-(--dx-grid-cell-editor-padding-inline)',
154
- slots?.scroll?.className,
165
+ slots?.scroller?.className,
155
166
  ),
156
167
  },
157
168
  content: {
@@ -5,7 +5,6 @@
5
5
  import React, { useCallback } from 'react';
6
6
 
7
7
  import { type DxGridCellIndex, type GridScopedProps, useGridContext } from '../Grid';
8
-
9
8
  import { CellEditor, type CellEditorProps } from './CellEditor';
10
9
 
11
10
  export type GridCellEditorProps = GridScopedProps<
@@ -7,15 +7,16 @@ import React, { type MouseEvent, type MutableRefObject, useCallback, useRef, use
7
7
 
8
8
  import { defaultRowSize } from '@dxos/lit-grid';
9
9
  import { type DxGridPlaneCells } from '@dxos/lit-grid';
10
- import { faker } from '@dxos/random';
10
+ import { random } from '@dxos/random';
11
11
  import { DropdownMenu } from '@dxos/react-ui';
12
- import { withLayout, withTheme } from '@dxos/react-ui/testing';
13
12
  import { toPlaneCellIndex } from '@dxos/react-ui-grid';
14
- import { Combobox, type ComboboxRootProps, useSearchListResults } from '@dxos/react-ui-searchlist';
13
+ import { Combobox, type ComboboxRootProps } from '@dxos/react-ui-list';
14
+ import { useSearchListResults } from '@dxos/react-ui-search';
15
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
15
16
 
16
17
  import { Grid, type GridContentProps, type GridEditing, type GridRootProps } from './Grid';
17
18
 
18
- const storybookItems = faker.helpers.uniqueArray(faker.commerce.productName, 16);
19
+ const storybookItems = random.helpers.uniqueArray(random.commerce.productName, 16);
19
20
 
20
21
  type GridStoryProps = GridContentProps & Pick<GridRootProps, 'onEditingChange'>;
21
22
 
@@ -64,7 +65,7 @@ const GridStory = ({ initialCells, ...props }: GridStoryProps) => {
64
65
  }, []);
65
66
 
66
67
  return (
67
- <div role='none' className='contents'>
68
+ <div className='contents'>
68
69
  <Grid.Root id='story' editing={editing} onEditingChange={handleEditingChange}>
69
70
  {/* TODO(burdon): Why is this property not just "cells" or "values" */}
70
71
  <Grid.Content {...props} initialCells={cells} onClick={handleClick} />
@@ -94,13 +95,13 @@ const GridStory = ({ initialCells, ...props }: GridStoryProps) => {
94
95
  };
95
96
 
96
97
  const ComboboxContentWithFiltering = () => {
97
- const { results, handleSearch } = useSearchListResults({
98
+ const { results, query, handleSearch } = useSearchListResults({
98
99
  items: storybookItems,
99
100
  });
100
101
 
101
102
  return (
102
- <Combobox.Content onSearch={handleSearch}>
103
- <Combobox.Input placeholder='Search...' />
103
+ <Combobox.Content>
104
+ <Combobox.Input placeholder='Search...' value={query} onValueChange={handleSearch} />
104
105
  <Combobox.List>
105
106
  {results.map((value) => (
106
107
  <Combobox.Item key={value} value={value} label={value} />
@@ -126,6 +127,29 @@ type Story = StoryObj<typeof meta>;
126
127
 
127
128
  export const Default: Story = {};
128
129
 
130
+ /**
131
+ * Single focusable cell — for verifying focus-ring alignment with grid lines.
132
+ */
133
+ export const SingleCell: Story = {
134
+ args: {
135
+ id: 'story',
136
+ limitColumns: 1,
137
+ limitRows: 1,
138
+ columnDefault: { grid: { size: 200, resizeable: false } },
139
+ rowDefault: { grid: { size: 32, resizeable: false } },
140
+ initialCells: {
141
+ grid: {
142
+ '0,0': { value: 'Focus me' },
143
+ },
144
+ },
145
+ },
146
+ render: (args) => (
147
+ <div className='h-full grid place-items-center'>
148
+ <GridStory {...args} />
149
+ </div>
150
+ ),
151
+ };
152
+
129
153
  export const Basic: Story = {
130
154
  args: {
131
155
  id: 'story',
package/src/Grid/Grid.tsx CHANGED
@@ -2,8 +2,6 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos/lit-grid/dx-grid.pcss';
6
-
7
5
  import { type EventName, createComponent } from '@lit/react';
8
6
  import { type Scope, createContextScope } from '@radix-ui/react-context';
9
7
  import { useControllableState } from '@radix-ui/react-use-controllable-state';
@@ -16,6 +14,7 @@ import React, {
16
14
  useState,
17
15
  } from 'react';
18
16
 
17
+ import '@dxos/lit-grid/dx-grid.pcss';
19
18
  import { type DxAxisResize, type DxEditRequest, type DxGridCellsSelect, DxGrid as NaturalDxGrid } from '@dxos/lit-grid';
20
19
 
21
20
  type DxGridElement = NaturalDxGrid;