@dxos/react-ui-grid 0.6.13 → 0.6.14-main.1366248

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.
@@ -1,20 +1,297 @@
1
- // packages/ui/react-ui-grid/src/Grid.tsx
1
+ // packages/ui/react-ui-grid/src/Grid/Grid.tsx
2
2
  import "@dxos/lit-grid/dx-grid.pcss";
3
3
  import { createComponent } from "@lit/react";
4
- import React from "react";
4
+ import { createContextScope } from "@radix-ui/react-context";
5
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
6
+ import React, { forwardRef, useCallback, useEffect, useState } from "react";
5
7
  import { DxGrid as NaturalDxGrid } from "@dxos/lit-grid";
8
+ import { colToA1Notation, rowToA1Notation, closestCell, commentedClassName } from "@dxos/lit-grid";
6
9
  var DxGrid = createComponent({
7
10
  tagName: "dx-grid",
8
11
  elementClass: NaturalDxGrid,
9
12
  react: React,
10
13
  events: {
11
- onAxisResize: "dx-axis-resize"
14
+ onAxisResize: "dx-axis-resize",
15
+ onEdit: "dx-edit-request",
16
+ onSelect: "dx-grid-cells-select"
12
17
  }
13
18
  });
14
- var Grid = (props) => {
15
- return /* @__PURE__ */ React.createElement(DxGrid, props);
19
+ var initialBox = {
20
+ insetInlineStart: 0,
21
+ insetBlockStart: 0,
22
+ inlineSize: 0,
23
+ blockSize: 0
24
+ };
25
+ var GRID_NAME = "Grid";
26
+ var [createGridContext, createGridScope] = createContextScope(GRID_NAME, []);
27
+ var [GridProvider, useGridContext] = createGridContext(GRID_NAME);
28
+ var GridRoot = ({ id, editing: propsEditing, defaultEditing, onEditingChange, children, __gridScope }) => {
29
+ const [editing = null, setEditing] = useControllableState({
30
+ prop: propsEditing,
31
+ defaultProp: defaultEditing,
32
+ onChange: onEditingChange
33
+ });
34
+ const [editBox, setEditBox] = useState(initialBox);
35
+ return /* @__PURE__ */ React.createElement(GridProvider, {
36
+ id,
37
+ editing,
38
+ setEditing,
39
+ editBox,
40
+ setEditBox,
41
+ scope: __gridScope
42
+ }, /* @__PURE__ */ React.createElement("div", {
43
+ className: "dx-grid-host",
44
+ style: {
45
+ display: "contents"
46
+ }
47
+ }, children));
48
+ };
49
+ GridRoot.displayName = GRID_NAME;
50
+ var GRID_CONTENT_NAME = "GridContent";
51
+ var GridContent = /* @__PURE__ */ forwardRef((props, forwardedRef) => {
52
+ const { id, editing, setEditBox, setEditing } = useGridContext(GRID_CONTENT_NAME, props.__gridScope);
53
+ const [dxGrid, setDxGridInternal] = useState(null);
54
+ const setDxGrid = useCallback((nextDxGrid) => {
55
+ setDxGridInternal(nextDxGrid);
56
+ if (forwardedRef) {
57
+ if (typeof forwardedRef === "function") {
58
+ forwardedRef?.(nextDxGrid);
59
+ } else {
60
+ forwardedRef.current = nextDxGrid;
61
+ }
62
+ }
63
+ }, [
64
+ forwardedRef,
65
+ dxGrid
66
+ ]);
67
+ useEffect(() => {
68
+ if (dxGrid && props.getCells) {
69
+ dxGrid.getCells = props.getCells;
70
+ dxGrid.requestUpdate("initialCells");
71
+ }
72
+ }, [
73
+ props.getCells,
74
+ dxGrid
75
+ ]);
76
+ const handleEdit = useCallback((event) => {
77
+ setEditBox(event.cellBox);
78
+ setEditing({
79
+ index: event.cellIndex,
80
+ initialContent: event.initialContent
81
+ });
82
+ }, []);
83
+ return /* @__PURE__ */ React.createElement(DxGrid, {
84
+ ...props,
85
+ gridId: id,
86
+ mode: editing ? "edit" : "browse",
87
+ onEdit: handleEdit,
88
+ ref: setDxGrid
89
+ });
90
+ });
91
+ GridContent.displayName = GRID_CONTENT_NAME;
92
+ var Grid = {
93
+ Root: GridRoot,
94
+ Content: GridContent
95
+ };
96
+
97
+ // packages/ui/react-ui-grid/src/CellEditor/CellEditor.tsx
98
+ import { completionStatus } from "@codemirror/autocomplete";
99
+ import { EditorView, keymap } from "@codemirror/view";
100
+ import React2 from "react";
101
+ import { useThemeContext } from "@dxos/react-ui";
102
+ import { createBasicExtensions, createThemeExtensions, preventNewline, useTextEditor } from "@dxos/react-ui-editor";
103
+ var editorKeys = ({ onNav, onClose }) => {
104
+ return keymap.of([
105
+ {
106
+ key: "ArrowUp",
107
+ run: (editor) => {
108
+ const value = editor.state.doc.toString();
109
+ onNav?.(value, {
110
+ key: "ArrowUp"
111
+ });
112
+ return !!onNav;
113
+ }
114
+ },
115
+ {
116
+ key: "ArrowDown",
117
+ run: (editor) => {
118
+ const value = editor.state.doc.toString();
119
+ onNav?.(value, {
120
+ key: "ArrowDown"
121
+ });
122
+ return !!onNav;
123
+ }
124
+ },
125
+ {
126
+ key: "ArrowLeft",
127
+ run: (editor) => {
128
+ const value = editor.state.doc.toString();
129
+ onNav?.(value, {
130
+ key: "ArrowLeft"
131
+ });
132
+ return !!onNav;
133
+ }
134
+ },
135
+ {
136
+ key: "ArrowRight",
137
+ run: (editor) => {
138
+ const value = editor.state.doc.toString();
139
+ onNav?.(value, {
140
+ key: "ArrowRight"
141
+ });
142
+ return !!onNav;
143
+ }
144
+ },
145
+ {
146
+ key: "Enter",
147
+ run: (editor) => {
148
+ if (completionStatus(editor.state)) {
149
+ return false;
150
+ } else {
151
+ onClose(editor.state.doc.toString(), {
152
+ key: "Enter"
153
+ });
154
+ return true;
155
+ }
156
+ },
157
+ shift: (editor) => {
158
+ if (completionStatus(editor.state)) {
159
+ return false;
160
+ } else {
161
+ onClose(editor.state.doc.toString(), {
162
+ key: "Enter",
163
+ shift: true
164
+ });
165
+ return true;
166
+ }
167
+ }
168
+ },
169
+ {
170
+ key: "Tab",
171
+ run: (editor) => {
172
+ if (completionStatus(editor.state)) {
173
+ return false;
174
+ } else {
175
+ onClose(editor.state.doc.toString(), {
176
+ key: "Tab"
177
+ });
178
+ return true;
179
+ }
180
+ },
181
+ shift: (editor) => {
182
+ if (completionStatus(editor.state)) {
183
+ return false;
184
+ } else {
185
+ onClose(editor.state.doc.toString(), {
186
+ key: "Tab",
187
+ shift: true
188
+ });
189
+ return true;
190
+ }
191
+ }
192
+ },
193
+ {
194
+ key: "Escape",
195
+ run: () => {
196
+ onClose(void 0, {
197
+ key: "Escape"
198
+ });
199
+ return true;
200
+ }
201
+ }
202
+ ]);
203
+ };
204
+ var editorVariants = {
205
+ // TODO(thure): remove when legacy is no longer used.
206
+ legacy: {
207
+ root: "flex w-full",
208
+ editor: "flex w-full [&>.cm-scroller]:scrollbar-none",
209
+ content: "!px-2 !py-1"
210
+ },
211
+ grid: {
212
+ root: "absolute z-[1]",
213
+ editor: "[&>.cm-scroller]:scrollbar-none tabular-nums",
214
+ // This must match cell styling in `dx-grid.pcss`.
215
+ content: "!border !border-transparent !pli-[3px] !plb-0.5"
216
+ }
217
+ };
218
+ var CellEditor = ({ value, extension, autoFocus, onBlur, variant = "legacy", box, gridId }) => {
219
+ const { themeMode } = useThemeContext();
220
+ const { parentRef } = useTextEditor(() => {
221
+ return {
222
+ autoFocus,
223
+ initialValue: value,
224
+ selection: {
225
+ anchor: value?.length ?? 0
226
+ },
227
+ extensions: [
228
+ extension ?? [],
229
+ preventNewline,
230
+ EditorView.focusChangeEffect.of((state, focusing) => {
231
+ if (!focusing) {
232
+ onBlur?.(state.doc.toString());
233
+ }
234
+ return null;
235
+ }),
236
+ createBasicExtensions({
237
+ lineWrapping: false
238
+ }),
239
+ createThemeExtensions({
240
+ themeMode,
241
+ slots: {
242
+ editor: {
243
+ className: editorVariants[variant].editor
244
+ },
245
+ content: {
246
+ className: editorVariants[variant].content
247
+ }
248
+ }
249
+ })
250
+ ]
251
+ };
252
+ }, [
253
+ extension,
254
+ autoFocus,
255
+ value,
256
+ variant,
257
+ onBlur
258
+ ]);
259
+ return /* @__PURE__ */ React2.createElement("div", {
260
+ ref: parentRef,
261
+ className: editorVariants[variant].root,
262
+ style: box,
263
+ ...gridId && {
264
+ "data-grid": gridId
265
+ }
266
+ });
267
+ };
268
+
269
+ // packages/ui/react-ui-grid/src/CellEditor/GridCellEditor.tsx
270
+ import React3 from "react";
271
+ var GridCellEditor = ({ extension, getCellContent, onBlur, __gridScope }) => {
272
+ const { id, editing, editBox } = useGridContext("GridSheetCellEditor", __gridScope);
273
+ return editing ? /* @__PURE__ */ React3.createElement(CellEditor, {
274
+ variant: "grid",
275
+ value: editing.initialContent ?? getCellContent(editing.index),
276
+ autoFocus: true,
277
+ box: editBox,
278
+ onBlur,
279
+ extension,
280
+ gridId: id
281
+ }) : null;
16
282
  };
17
283
  export {
18
- Grid
284
+ CellEditor,
285
+ Grid,
286
+ GridCellEditor,
287
+ GridContent,
288
+ GridRoot,
289
+ closestCell,
290
+ colToA1Notation,
291
+ commentedClassName,
292
+ createGridScope,
293
+ editorKeys,
294
+ rowToA1Notation,
295
+ useGridContext
19
296
  };
20
297
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../src/Grid.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\nimport '@dxos/lit-grid/dx-grid.pcss';\n\nimport { createComponent, type EventName } from '@lit/react';\nimport React from 'react';\n\nimport { type DxAxisResize, DxGrid as NaturalDxGrid, type DxGridProps } from '@dxos/lit-grid';\n\nconst DxGrid = createComponent({\n tagName: 'dx-grid',\n elementClass: NaturalDxGrid,\n react: React,\n events: {\n onAxisResize: 'dx-axis-resize' as EventName<DxAxisResize>,\n },\n});\n\nexport type GridProps = DxGridProps & {\n onAxisResize: (event: DxAxisResize) => void;\n};\n\nexport const Grid = (props: GridProps) => {\n return <DxGrid {...props} />;\n};\n"],
5
- "mappings": ";AAGA,OAAO;AAEP,SAASA,uBAAuC;AAChD,OAAOC,WAAW;AAElB,SAA4BC,UAAUC,qBAAuC;AAE7E,IAAMC,SAASC,gBAAgB;EAC7BC,SAAS;EACTC,cAAcC;EACdC,OAAOC;EACPC,QAAQ;IACNC,cAAc;EAChB;AACF,CAAA;AAMO,IAAMC,OAAO,CAACC,UAAAA;AACnB,SAAO,sBAAA,cAACV,QAAWU,KAAAA;AACrB;",
6
- "names": ["createComponent", "React", "DxGrid", "NaturalDxGrid", "DxGrid", "createComponent", "tagName", "elementClass", "NaturalDxGrid", "react", "React", "events", "onAxisResize", "Grid", "props"]
3
+ "sources": ["../../../src/Grid/Grid.tsx", "../../../src/CellEditor/CellEditor.tsx", "../../../src/CellEditor/GridCellEditor.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport '@dxos/lit-grid/dx-grid.pcss';\n\nimport { createComponent, type EventName } from '@lit/react';\nimport { createContextScope, type Scope } from '@radix-ui/react-context';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, {\n type ComponentProps,\n forwardRef,\n type PropsWithChildren,\n useCallback,\n useEffect,\n useState,\n} from 'react';\n\nimport { type DxAxisResize, type DxEditRequest, type DxGridCellsSelect, DxGrid as NaturalDxGrid } from '@dxos/lit-grid';\n\ntype DxGridElement = NaturalDxGrid;\n\nconst DxGrid = createComponent({\n tagName: 'dx-grid',\n elementClass: NaturalDxGrid,\n react: React,\n events: {\n onAxisResize: 'dx-axis-resize' as EventName<DxAxisResize>,\n onEdit: 'dx-edit-request' as EventName<DxEditRequest>,\n onSelect: 'dx-grid-cells-select' as EventName<DxGridCellsSelect>,\n },\n});\n\ntype GridEditBox = DxEditRequest['cellBox'];\n\nconst initialBox = {\n insetInlineStart: 0,\n insetBlockStart: 0,\n inlineSize: 0,\n blockSize: 0,\n} satisfies GridEditBox;\n\ntype GridEditing = { index: DxEditRequest['cellIndex']; initialContent: DxEditRequest['initialContent'] } | null;\n\ntype GridContextValue = {\n id: string;\n editing: GridEditing;\n setEditing: (nextEditing: GridEditing) => void;\n editBox: GridEditBox;\n setEditBox: (nextEditBox: GridEditBox) => void;\n};\n\ntype GridScopedProps<P> = P & { __gridScope?: Scope };\n\nconst GRID_NAME = 'Grid';\n\nconst [createGridContext, createGridScope] = createContextScope(GRID_NAME, []);\n\nconst [GridProvider, useGridContext] = createGridContext<GridContextValue>(GRID_NAME);\n\ntype GridRootProps = PropsWithChildren<\n { id: string } & Partial<{\n editing: GridEditing;\n defaultEditing: GridEditing;\n onEditingChange: (nextEditing: GridEditing) => void;\n }>\n>;\n\nconst GridRoot = ({\n id,\n editing: propsEditing,\n defaultEditing,\n onEditingChange,\n children,\n __gridScope,\n}: GridScopedProps<GridRootProps>) => {\n const [editing = null, setEditing] = useControllableState({\n prop: propsEditing,\n defaultProp: defaultEditing,\n onChange: onEditingChange,\n });\n const [editBox, setEditBox] = useState<GridEditBox>(initialBox);\n return (\n <GridProvider\n id={id}\n editing={editing}\n setEditing={setEditing}\n editBox={editBox}\n setEditBox={setEditBox}\n scope={__gridScope}\n >\n <div className='dx-grid-host' style={{ display: 'contents' }}>\n {children}\n </div>\n </GridProvider>\n );\n};\n\nGridRoot.displayName = GRID_NAME;\n\ntype GridContentProps = Omit<ComponentProps<typeof DxGrid>, 'onEdit'> & {\n getCells?: NonNullable<NaturalDxGrid['getCells']>;\n activeRefs?: string;\n};\n\nconst GRID_CONTENT_NAME = 'GridContent';\n\nconst GridContent = forwardRef<NaturalDxGrid, GridScopedProps<GridContentProps>>((props, forwardedRef) => {\n const { id, editing, setEditBox, setEditing } = useGridContext(GRID_CONTENT_NAME, props.__gridScope);\n const [dxGrid, setDxGridInternal] = useState<NaturalDxGrid | null>(null);\n\n // NOTE(thure): using `useState` instead of `useRef` works with refs provided by `@lit/react` and gives us a reliable dependency for `useEffect` whereas `useLayoutEffect` does not guarantee the element will be defined.\n const setDxGrid = useCallback(\n (nextDxGrid: NaturalDxGrid | null) => {\n setDxGridInternal(nextDxGrid);\n if (forwardedRef) {\n if (typeof forwardedRef === 'function') {\n forwardedRef?.(nextDxGrid);\n } else {\n forwardedRef.current = nextDxGrid;\n }\n }\n },\n [forwardedRef, dxGrid],\n );\n\n useEffect(() => {\n if (dxGrid && props.getCells) {\n dxGrid.getCells = props.getCells;\n dxGrid.requestUpdate('initialCells');\n }\n }, [props.getCells, dxGrid]);\n\n const handleEdit = useCallback((event: DxEditRequest) => {\n setEditBox(event.cellBox);\n setEditing({ index: event.cellIndex, initialContent: event.initialContent });\n }, []);\n\n return <DxGrid {...props} gridId={id} mode={editing ? 'edit' : 'browse'} onEdit={handleEdit} ref={setDxGrid} />;\n});\n\nGridContent.displayName = GRID_CONTENT_NAME;\n\nexport const Grid = {\n Root: GridRoot,\n Content: GridContent,\n};\n\nexport { GridRoot, GridContent, useGridContext, createGridScope };\n\nexport type { GridRootProps, GridContentProps, GridEditing, GridEditBox, GridScopedProps, DxGridElement };\n\nexport { colToA1Notation, rowToA1Notation, closestCell, commentedClassName } from '@dxos/lit-grid';\n\nexport type {\n DxGridRange,\n DxGridAxisMeta,\n DxAxisResize,\n DxGridCells,\n DxGridPlaneRange,\n DxGridPlaneCells,\n DxGridCellIndex,\n DxGridCellValue,\n DxGridPlane,\n DxGridPosition,\n DxGridAxis,\n} from '@dxos/lit-grid';\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { completionStatus } from '@codemirror/autocomplete';\nimport { type Extension } from '@codemirror/state';\nimport { EditorView, keymap } from '@codemirror/view';\nimport React, { type KeyboardEvent } from 'react';\n\nimport { useThemeContext } from '@dxos/react-ui';\nimport {\n type UseTextEditorProps,\n createBasicExtensions,\n createThemeExtensions,\n preventNewline,\n useTextEditor,\n} from '@dxos/react-ui-editor';\n\nimport { type GridEditBox } from '../Grid';\n\nexport type EditorKeyEvent = Pick<KeyboardEvent<HTMLInputElement>, 'key'> & { shift?: boolean };\n\nexport type EditorKeysProps = {\n onClose: (value: string | undefined, event: EditorKeyEvent) => void;\n onNav?: (value: string | undefined, event: EditorKeyEvent) => void;\n};\n// TODO(Zan): Should each consumer be responsible for defining these?\nexport const editorKeys = ({ onNav, onClose }: EditorKeysProps): Extension => {\n return keymap.of([\n {\n key: 'ArrowUp',\n run: (editor) => {\n const value = editor.state.doc.toString();\n onNav?.(value, { key: 'ArrowUp' });\n return !!onNav;\n },\n },\n {\n key: 'ArrowDown',\n run: (editor) => {\n const value = editor.state.doc.toString();\n onNav?.(value, { key: 'ArrowDown' });\n return !!onNav;\n },\n },\n {\n key: 'ArrowLeft',\n run: (editor) => {\n const value = editor.state.doc.toString();\n onNav?.(value, { key: 'ArrowLeft' });\n return !!onNav;\n },\n },\n {\n key: 'ArrowRight',\n run: (editor) => {\n const value = editor.state.doc.toString();\n onNav?.(value, { key: 'ArrowRight' });\n return !!onNav;\n },\n },\n {\n key: 'Enter',\n run: (editor) => {\n if (completionStatus(editor.state)) {\n return false;\n } else {\n onClose(editor.state.doc.toString(), { key: 'Enter' });\n return true;\n }\n },\n shift: (editor) => {\n if (completionStatus(editor.state)) {\n return false;\n } else {\n onClose(editor.state.doc.toString(), { key: 'Enter', shift: true });\n return true;\n }\n },\n },\n {\n key: 'Tab',\n run: (editor) => {\n if (completionStatus(editor.state)) {\n return false;\n } else {\n onClose(editor.state.doc.toString(), { key: 'Tab' });\n return true;\n }\n },\n shift: (editor) => {\n if (completionStatus(editor.state)) {\n return false;\n } else {\n onClose(editor.state.doc.toString(), { key: 'Tab', shift: true });\n return true;\n }\n },\n },\n {\n key: 'Escape',\n run: () => {\n onClose(undefined, { key: 'Escape' });\n return true;\n },\n },\n ]);\n};\n\nexport type CellEditorProps = {\n value?: string;\n extension?: Extension;\n variant?: keyof typeof editorVariants;\n box?: GridEditBox;\n gridId?: string;\n} & Pick<UseTextEditorProps, 'autoFocus'> & { onBlur?: (value?: string) => void };\n\nconst editorVariants = {\n // TODO(thure): remove when legacy is no longer used.\n legacy: {\n root: 'flex w-full',\n editor: 'flex w-full [&>.cm-scroller]:scrollbar-none',\n content: '!px-2 !py-1',\n },\n grid: {\n root: 'absolute z-[1]',\n editor: '[&>.cm-scroller]:scrollbar-none tabular-nums',\n // This must match cell styling in `dx-grid.pcss`.\n content: '!border !border-transparent !pli-[3px] !plb-0.5',\n },\n};\n\nexport const CellEditor = ({\n value,\n extension,\n autoFocus,\n onBlur,\n variant = 'legacy',\n box,\n gridId,\n}: CellEditorProps) => {\n const { themeMode } = useThemeContext();\n const { parentRef } = useTextEditor(() => {\n return {\n autoFocus,\n initialValue: value,\n selection: { anchor: value?.length ?? 0 },\n extensions: [\n extension ?? [],\n preventNewline,\n EditorView.focusChangeEffect.of((state, focusing) => {\n if (!focusing) {\n onBlur?.(state.doc.toString());\n }\n return null;\n }),\n createBasicExtensions({ lineWrapping: false }),\n createThemeExtensions({\n themeMode,\n slots: {\n editor: {\n className: editorVariants[variant].editor,\n },\n content: {\n className: editorVariants[variant].content,\n },\n },\n }),\n ],\n };\n }, [extension, autoFocus, value, variant, onBlur]);\n\n return (\n <div\n ref={parentRef}\n className={editorVariants[variant].root}\n style={box}\n {...(gridId && { 'data-grid': gridId })}\n />\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport React from 'react';\n\nimport { CellEditor, type CellEditorProps } from './CellEditor';\nimport { type GridScopedProps, useGridContext } from '../Grid';\n\nexport const GridCellEditor = ({\n extension,\n getCellContent,\n onBlur,\n __gridScope,\n}: GridScopedProps<\n Pick<CellEditorProps, 'extension' | 'onBlur'> & { getCellContent: (index: string) => string | undefined }\n>) => {\n const { id, editing, editBox } = useGridContext('GridSheetCellEditor', __gridScope);\n\n return editing ? (\n <CellEditor\n variant='grid'\n value={editing.initialContent ?? getCellContent(editing.index)}\n autoFocus\n box={editBox}\n onBlur={onBlur}\n extension={extension}\n gridId={id}\n />\n ) : null;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["createComponent", "createContextScope", "useControllableState", "React", "forwardRef", "useCallback", "useEffect", "useState", "DxGrid", "NaturalDxGrid", "colToA1Notation", "rowToA1Notation", "closestCell", "commentedClassName", "DxGrid", "createComponent", "tagName", "elementClass", "NaturalDxGrid", "react", "React", "events", "onAxisResize", "onEdit", "onSelect", "initialBox", "insetInlineStart", "insetBlockStart", "inlineSize", "blockSize", "GRID_NAME", "createGridContext", "createGridScope", "createContextScope", "GridProvider", "useGridContext", "GridRoot", "id", "editing", "propsEditing", "defaultEditing", "onEditingChange", "children", "__gridScope", "setEditing", "useControllableState", "prop", "defaultProp", "onChange", "editBox", "setEditBox", "useState", "scope", "div", "className", "style", "display", "displayName", "GRID_CONTENT_NAME", "GridContent", "forwardRef", "props", "forwardedRef", "dxGrid", "setDxGridInternal", "setDxGrid", "useCallback", "nextDxGrid", "current", "useEffect", "getCells", "requestUpdate", "handleEdit", "event", "cellBox", "index", "cellIndex", "initialContent", "gridId", "mode", "ref", "Grid", "Root", "Content", "completionStatus", "EditorView", "keymap", "React", "useThemeContext", "createBasicExtensions", "createThemeExtensions", "preventNewline", "useTextEditor", "editorKeys", "onNav", "onClose", "keymap", "of", "key", "run", "editor", "value", "state", "doc", "toString", "completionStatus", "shift", "undefined", "editorVariants", "legacy", "root", "content", "grid", "CellEditor", "extension", "autoFocus", "onBlur", "variant", "box", "gridId", "themeMode", "useThemeContext", "parentRef", "useTextEditor", "initialValue", "selection", "anchor", "length", "extensions", "preventNewline", "EditorView", "focusChangeEffect", "focusing", "createBasicExtensions", "lineWrapping", "createThemeExtensions", "slots", "className", "React", "div", "ref", "style", "React", "GridCellEditor", "extension", "getCellContent", "onBlur", "__gridScope", "id", "editing", "editBox", "useGridContext", "React", "CellEditor", "variant", "value", "initialContent", "index", "autoFocus", "box", "gridId"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/ui/react-ui-grid/src/Grid.tsx":{"bytes":2180,"imports":[{"path":"@dxos/lit-grid/dx-grid.pcss","kind":"import-statement","external":true},{"path":"@lit/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/lit-grid","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-grid/src/index.ts":{"bytes":489,"imports":[{"path":"packages/ui/react-ui-grid/src/Grid.tsx","kind":"import-statement","original":"./Grid"}],"format":"esm"}},"outputs":{"packages/ui/react-ui-grid/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":1186},"packages/ui/react-ui-grid/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/lit-grid/dx-grid.pcss","kind":"import-statement","external":true},{"path":"@lit/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/lit-grid","kind":"import-statement","external":true}],"exports":["Grid"],"entryPoint":"packages/ui/react-ui-grid/src/index.ts","inputs":{"packages/ui/react-ui-grid/src/Grid.tsx":{"bytesInOutput":412},"packages/ui/react-ui-grid/src/index.ts":{"bytesInOutput":0}},"bytes":508}}}
1
+ {"inputs":{"packages/ui/react-ui-grid/src/Grid/Grid.tsx":{"bytes":14220,"imports":[{"path":"@dxos/lit-grid/dx-grid.pcss","kind":"import-statement","external":true},{"path":"@lit/react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/lit-grid","kind":"import-statement","external":true},{"path":"@dxos/lit-grid","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-grid/src/Grid/index.ts":{"bytes":494,"imports":[{"path":"packages/ui/react-ui-grid/src/Grid/Grid.tsx","kind":"import-statement","original":"./Grid"}],"format":"esm"},"packages/ui/react-ui-grid/src/CellEditor/CellEditor.tsx":{"bytes":16671,"imports":[{"path":"@codemirror/autocomplete","kind":"import-statement","external":true},{"path":"@codemirror/view","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-editor","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-grid/src/CellEditor/GridCellEditor.tsx":{"bytes":2833,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-grid/src/CellEditor/CellEditor.tsx","kind":"import-statement","original":"./CellEditor"},{"path":"packages/ui/react-ui-grid/src/Grid/index.ts","kind":"import-statement","original":"../Grid"}],"format":"esm"},"packages/ui/react-ui-grid/src/CellEditor/index.ts":{"bytes":620,"imports":[{"path":"packages/ui/react-ui-grid/src/CellEditor/CellEditor.tsx","kind":"import-statement","original":"./CellEditor"},{"path":"packages/ui/react-ui-grid/src/CellEditor/GridCellEditor.tsx","kind":"import-statement","original":"./GridCellEditor"}],"format":"esm"},"packages/ui/react-ui-grid/src/index.ts":{"bytes":583,"imports":[{"path":"packages/ui/react-ui-grid/src/Grid/index.ts","kind":"import-statement","original":"./Grid"},{"path":"packages/ui/react-ui-grid/src/CellEditor/index.ts","kind":"import-statement","original":"./CellEditor"}],"format":"esm"}},"outputs":{"packages/ui/react-ui-grid/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":17395},"packages/ui/react-ui-grid/dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/lit-grid/dx-grid.pcss","kind":"import-statement","external":true},{"path":"@lit/react","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/lit-grid","kind":"import-statement","external":true},{"path":"@dxos/lit-grid","kind":"import-statement","external":true},{"path":"@codemirror/autocomplete","kind":"import-statement","external":true},{"path":"@codemirror/view","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-editor","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true}],"exports":["CellEditor","Grid","GridCellEditor","GridContent","GridRoot","closestCell","colToA1Notation","commentedClassName","createGridScope","editorKeys","rowToA1Notation","useGridContext"],"entryPoint":"packages/ui/react-ui-grid/src/index.ts","inputs":{"packages/ui/react-ui-grid/src/Grid/Grid.tsx":{"bytesInOutput":2829},"packages/ui/react-ui-grid/src/Grid/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-grid/src/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-grid/src/CellEditor/CellEditor.tsx":{"bytesInOutput":4072},"packages/ui/react-ui-grid/src/CellEditor/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-grid/src/CellEditor/GridCellEditor.tsx":{"bytesInOutput":450}},"bytes":7761}}}
@@ -0,0 +1,36 @@
1
+ import { type Extension } from '@codemirror/state';
2
+ import React, { type KeyboardEvent } from 'react';
3
+ import { type UseTextEditorProps } from '@dxos/react-ui-editor';
4
+ import { type GridEditBox } from '../Grid';
5
+ export type EditorKeyEvent = Pick<KeyboardEvent<HTMLInputElement>, 'key'> & {
6
+ shift?: boolean;
7
+ };
8
+ export type EditorKeysProps = {
9
+ onClose: (value: string | undefined, event: EditorKeyEvent) => void;
10
+ onNav?: (value: string | undefined, event: EditorKeyEvent) => void;
11
+ };
12
+ export declare const editorKeys: ({ onNav, onClose }: EditorKeysProps) => Extension;
13
+ export type CellEditorProps = {
14
+ value?: string;
15
+ extension?: Extension;
16
+ variant?: keyof typeof editorVariants;
17
+ box?: GridEditBox;
18
+ gridId?: string;
19
+ } & Pick<UseTextEditorProps, 'autoFocus'> & {
20
+ onBlur?: (value?: string) => void;
21
+ };
22
+ declare const editorVariants: {
23
+ legacy: {
24
+ root: string;
25
+ editor: string;
26
+ content: string;
27
+ };
28
+ grid: {
29
+ root: string;
30
+ editor: string;
31
+ content: string;
32
+ };
33
+ };
34
+ export declare const CellEditor: ({ value, extension, autoFocus, onBlur, variant, box, gridId, }: CellEditorProps) => React.JSX.Element;
35
+ export {};
36
+ //# sourceMappingURL=CellEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CellEditor.d.ts","sourceRoot":"","sources":["../../../../src/CellEditor/CellEditor.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,KAAK,EAAE,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,EACL,KAAK,kBAAkB,EAKxB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,EAAE,KAAK,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhG,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACpE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CACpE,CAAC;AAEF,eAAO,MAAM,UAAU,uBAAwB,eAAe,KAAG,SAgFhE,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,OAAO,cAAc,CAAC;IACtC,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAAC;AAElF,QAAA,MAAM,cAAc;;;;;;;;;;;CAanB,CAAC;AAEF,eAAO,MAAM,UAAU,mEAQpB,eAAe,sBAwCjB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { type CellEditorProps } from './CellEditor';
3
+ import { type GridScopedProps } from '../Grid';
4
+ export declare const GridCellEditor: ({ extension, getCellContent, onBlur, __gridScope, }: GridScopedProps<Pick<CellEditorProps, "extension" | "onBlur"> & {
5
+ getCellContent: (index: string) => string | undefined;
6
+ }>) => React.JSX.Element | null;
7
+ //# sourceMappingURL=GridCellEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GridCellEditor.d.ts","sourceRoot":"","sources":["../../../../src/CellEditor/GridCellEditor.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,KAAK,eAAe,EAAkB,MAAM,SAAS,CAAC;AAE/D,eAAO,MAAM,cAAc,wDAKxB,eAAe,CAChB,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,QAAQ,CAAC,GAAG;IAAE,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;CAAE,CAC1G,6BAcA,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './CellEditor';
2
+ export * from './GridCellEditor';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/CellEditor/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,56 @@
1
+ import '@dxos/lit-grid/dx-grid.pcss';
2
+ import { type EventName } from '@lit/react';
3
+ import { type Scope } from '@radix-ui/react-context';
4
+ import React, { type ComponentProps, type PropsWithChildren } from 'react';
5
+ import { type DxAxisResize, type DxEditRequest, type DxGridCellsSelect, DxGrid as NaturalDxGrid } from '@dxos/lit-grid';
6
+ type DxGridElement = NaturalDxGrid;
7
+ declare const DxGrid: import("@lit/react").ReactWebComponent<NaturalDxGrid, {
8
+ onAxisResize: EventName<DxAxisResize>;
9
+ onEdit: EventName<DxEditRequest>;
10
+ onSelect: EventName<DxGridCellsSelect>;
11
+ }>;
12
+ type GridEditBox = DxEditRequest['cellBox'];
13
+ type GridEditing = {
14
+ index: DxEditRequest['cellIndex'];
15
+ initialContent: DxEditRequest['initialContent'];
16
+ } | null;
17
+ type GridContextValue = {
18
+ id: string;
19
+ editing: GridEditing;
20
+ setEditing: (nextEditing: GridEditing) => void;
21
+ editBox: GridEditBox;
22
+ setEditBox: (nextEditBox: GridEditBox) => void;
23
+ };
24
+ type GridScopedProps<P> = P & {
25
+ __gridScope?: Scope;
26
+ };
27
+ declare const createGridScope: import("@radix-ui/react-context").CreateScope;
28
+ declare const useGridContext: (consumerName: string, scope: Scope<GridContextValue | undefined>) => GridContextValue;
29
+ type GridRootProps = PropsWithChildren<{
30
+ id: string;
31
+ } & Partial<{
32
+ editing: GridEditing;
33
+ defaultEditing: GridEditing;
34
+ onEditingChange: (nextEditing: GridEditing) => void;
35
+ }>>;
36
+ declare const GridRoot: {
37
+ ({ id, editing: propsEditing, defaultEditing, onEditingChange, children, __gridScope, }: GridScopedProps<GridRootProps>): React.JSX.Element;
38
+ displayName: string;
39
+ };
40
+ type GridContentProps = Omit<ComponentProps<typeof DxGrid>, 'onEdit'> & {
41
+ getCells?: NonNullable<NaturalDxGrid['getCells']>;
42
+ activeRefs?: string;
43
+ };
44
+ declare const GridContent: React.ForwardRefExoticComponent<Omit<GridScopedProps<GridContentProps>, "ref"> & React.RefAttributes<NaturalDxGrid>>;
45
+ export declare const Grid: {
46
+ Root: {
47
+ ({ id, editing: propsEditing, defaultEditing, onEditingChange, children, __gridScope, }: GridScopedProps<GridRootProps>): React.JSX.Element;
48
+ displayName: string;
49
+ };
50
+ Content: React.ForwardRefExoticComponent<Omit<GridScopedProps<GridContentProps>, "ref"> & React.RefAttributes<NaturalDxGrid>>;
51
+ };
52
+ export { GridRoot, GridContent, useGridContext, createGridScope };
53
+ export type { GridRootProps, GridContentProps, GridEditing, GridEditBox, GridScopedProps, DxGridElement };
54
+ export { colToA1Notation, rowToA1Notation, closestCell, commentedClassName } from '@dxos/lit-grid';
55
+ export type { DxGridRange, DxGridAxisMeta, DxAxisResize, DxGridCells, DxGridPlaneRange, DxGridPlaneCells, DxGridCellIndex, DxGridCellValue, DxGridPlane, DxGridPosition, DxGridAxis, } from '@dxos/lit-grid';
56
+ //# sourceMappingURL=Grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Grid.d.ts","sourceRoot":"","sources":["../../../../src/Grid/Grid.tsx"],"names":[],"mappings":"AAIA,OAAO,6BAA6B,CAAC;AAErC,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAsB,KAAK,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAEzE,OAAO,KAAK,EAAE,EACZ,KAAK,cAAc,EAEnB,KAAK,iBAAiB,EAIvB,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAExH,KAAK,aAAa,GAAG,aAAa,CAAC;AAEnC,QAAA,MAAM,MAAM;kBAK0B,SAAS,CAAC,YAAY,CAAC;YAC5B,SAAS,CAAC,aAAa,CAAC;cACjB,SAAS,CAAC,iBAAiB,CAAC;EAElE,CAAC;AAEH,KAAK,WAAW,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;AAS5C,KAAK,WAAW,GAAG;IAAE,KAAK,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAAC,cAAc,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAA;CAAE,GAAG,IAAI,CAAC;AAEjH,KAAK,gBAAgB,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;IAC/C,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;CAChD,CAAC;AAEF,KAAK,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAItD,QAAA,MAA0B,eAAe,+CAAqC,CAAC;AAE/E,QAAA,MAAqB,cAAc,wFAAkD,CAAC;AAEtF,KAAK,aAAa,GAAG,iBAAiB,CACpC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,cAAc,EAAE,WAAW,CAAC;IAC5B,eAAe,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;CACrD,CAAC,CACH,CAAC;AAEF,QAAA,MAAM,QAAQ;6FAOX,eAAe,CAAC,aAAa,CAAC;;CAqBhC,CAAC;AAIF,KAAK,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,QAAQ,CAAC,GAAG;IACtE,QAAQ,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAIF,QAAA,MAAM,WAAW,sHAgCf,CAAC;AAIH,eAAO,MAAM,IAAI;;iGApEd,eAAe,CAAC,aAAa,CAAC;;;;CAuEhC,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;AAElE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC;AAE1G,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEnG,YAAY,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,WAAW,EACX,cAAc,EACd,UAAU,GACX,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import '@dxos-theme';
2
+ import { type StoryObj } from '@storybook/react';
3
+ import React from 'react';
4
+ import { type GridContentProps, type GridRootProps } from './Grid';
5
+ type StoryGridProps = GridContentProps & Pick<GridRootProps, 'onEditingChange'>;
6
+ declare const _default: {
7
+ title: string;
8
+ component: ({ onEditingChange, ...props }: StoryGridProps) => React.JSX.Element;
9
+ decorators: import("@storybook/react/*").Decorator[];
10
+ parameters: {
11
+ layout: string;
12
+ };
13
+ };
14
+ export default _default;
15
+ export declare const Basic: StoryObj<StoryGridProps>;
16
+ //# sourceMappingURL=Grid.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Grid.stories.d.ts","sourceRoot":"","sources":["../../../../src/Grid/Grid.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,aAAa,CAAC;AAErB,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAgF,MAAM,OAAO,CAAC;AAOrG,OAAO,EAAQ,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEzE,KAAK,cAAc,GAAG,gBAAgB,GAAG,IAAI,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;;;+CAiB9B,cAAc;;;;;;AAiEhE,wBAKE;AAEF,eAAO,MAAM,KAAK,EAAE,QAAQ,CAAC,cAAc,CA+B1C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './Grid';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Grid/index.ts"],"names":[],"mappings":"AAIA,cAAc,QAAQ,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export * from './Grid';
2
+ export * from './CellEditor';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-grid",
3
- "version": "0.6.13",
3
+ "version": "0.6.14-main.1366248",
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",
7
7
  "license": "MIT",
8
8
  "author": "DXOS.org",
9
+ "sideEffects": true,
9
10
  "exports": {
10
11
  ".": {
11
- "browser": "./dist/lib/browser/index.mjs",
12
- "types": "./dist/types/src/index.d.ts"
12
+ "types": "./dist/types/src/index.d.ts",
13
+ "browser": "./dist/lib/browser/index.mjs"
13
14
  }
14
15
  },
15
16
  "types": "dist/types/src/index.d.ts",
@@ -21,23 +22,34 @@
21
22
  "src"
22
23
  ],
23
24
  "dependencies": {
25
+ "@codemirror/autocomplete": "^6.18.1",
26
+ "@codemirror/state": "^6.4.1",
27
+ "@codemirror/view": "^6.34.1",
24
28
  "@lit/react": "^1.0.5",
25
- "@dxos/lit-grid": "0.6.13",
26
- "@dxos/react-ui": "0.6.13",
27
- "@dxos/util": "0.6.13",
28
- "@dxos/react-ui-theme": "0.6.13"
29
+ "@radix-ui/react-context": "^1.0.0",
30
+ "@radix-ui/react-popper": "^1.1.2",
31
+ "@radix-ui/react-use-controllable-state": "^1.0.0",
32
+ "@dxos/lit-grid": "0.6.14-main.1366248",
33
+ "@dxos/react-ui-editor": "0.6.14-main.1366248",
34
+ "@dxos/util": "0.6.14-main.1366248"
29
35
  },
30
36
  "devDependencies": {
31
37
  "@types/react": "~18.2.0",
32
38
  "@types/react-dom": "~18.2.0",
33
39
  "react": "~18.2.0",
34
40
  "react-dom": "~18.2.0",
35
- "vite": "^5.3.4",
36
- "@dxos/storybook-utils": "0.6.13"
41
+ "vite": "5.4.7",
42
+ "@dxos/random": "0.6.14-main.1366248",
43
+ "@dxos/react-ui": "0.6.14-main.1366248",
44
+ "@dxos/react-ui-searchlist": "0.6.14-main.1366248",
45
+ "@dxos/react-ui-theme": "0.6.14-main.1366248",
46
+ "@dxos/storybook-utils": "0.6.14-main.1366248"
37
47
  },
38
48
  "peerDependencies": {
39
- "react": "^18.0.0",
40
- "react-dom": "^18.0.0"
49
+ "react": "~18.2.0",
50
+ "react-dom": "~18.2.0",
51
+ "@dxos/react-ui": "0.6.14-main.1366248",
52
+ "@dxos/react-ui-theme": "0.6.14-main.1366248"
41
53
  },
42
54
  "publishConfig": {
43
55
  "access": "public"
@@ -0,0 +1,181 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { completionStatus } from '@codemirror/autocomplete';
6
+ import { type Extension } from '@codemirror/state';
7
+ import { EditorView, keymap } from '@codemirror/view';
8
+ import React, { type KeyboardEvent } from 'react';
9
+
10
+ import { useThemeContext } from '@dxos/react-ui';
11
+ import {
12
+ type UseTextEditorProps,
13
+ createBasicExtensions,
14
+ createThemeExtensions,
15
+ preventNewline,
16
+ useTextEditor,
17
+ } from '@dxos/react-ui-editor';
18
+
19
+ import { type GridEditBox } from '../Grid';
20
+
21
+ export type EditorKeyEvent = Pick<KeyboardEvent<HTMLInputElement>, 'key'> & { shift?: boolean };
22
+
23
+ export type EditorKeysProps = {
24
+ onClose: (value: string | undefined, event: EditorKeyEvent) => void;
25
+ onNav?: (value: string | undefined, event: EditorKeyEvent) => void;
26
+ };
27
+ // TODO(Zan): Should each consumer be responsible for defining these?
28
+ export const editorKeys = ({ onNav, onClose }: EditorKeysProps): Extension => {
29
+ return keymap.of([
30
+ {
31
+ key: 'ArrowUp',
32
+ run: (editor) => {
33
+ const value = editor.state.doc.toString();
34
+ onNav?.(value, { key: 'ArrowUp' });
35
+ return !!onNav;
36
+ },
37
+ },
38
+ {
39
+ key: 'ArrowDown',
40
+ run: (editor) => {
41
+ const value = editor.state.doc.toString();
42
+ onNav?.(value, { key: 'ArrowDown' });
43
+ return !!onNav;
44
+ },
45
+ },
46
+ {
47
+ key: 'ArrowLeft',
48
+ run: (editor) => {
49
+ const value = editor.state.doc.toString();
50
+ onNav?.(value, { key: 'ArrowLeft' });
51
+ return !!onNav;
52
+ },
53
+ },
54
+ {
55
+ key: 'ArrowRight',
56
+ run: (editor) => {
57
+ const value = editor.state.doc.toString();
58
+ onNav?.(value, { key: 'ArrowRight' });
59
+ return !!onNav;
60
+ },
61
+ },
62
+ {
63
+ key: 'Enter',
64
+ run: (editor) => {
65
+ if (completionStatus(editor.state)) {
66
+ return false;
67
+ } else {
68
+ onClose(editor.state.doc.toString(), { key: 'Enter' });
69
+ return true;
70
+ }
71
+ },
72
+ shift: (editor) => {
73
+ if (completionStatus(editor.state)) {
74
+ return false;
75
+ } else {
76
+ onClose(editor.state.doc.toString(), { key: 'Enter', shift: true });
77
+ return true;
78
+ }
79
+ },
80
+ },
81
+ {
82
+ key: 'Tab',
83
+ run: (editor) => {
84
+ if (completionStatus(editor.state)) {
85
+ return false;
86
+ } else {
87
+ onClose(editor.state.doc.toString(), { key: 'Tab' });
88
+ return true;
89
+ }
90
+ },
91
+ shift: (editor) => {
92
+ if (completionStatus(editor.state)) {
93
+ return false;
94
+ } else {
95
+ onClose(editor.state.doc.toString(), { key: 'Tab', shift: true });
96
+ return true;
97
+ }
98
+ },
99
+ },
100
+ {
101
+ key: 'Escape',
102
+ run: () => {
103
+ onClose(undefined, { key: 'Escape' });
104
+ return true;
105
+ },
106
+ },
107
+ ]);
108
+ };
109
+
110
+ export type CellEditorProps = {
111
+ value?: string;
112
+ extension?: Extension;
113
+ variant?: keyof typeof editorVariants;
114
+ box?: GridEditBox;
115
+ gridId?: string;
116
+ } & Pick<UseTextEditorProps, 'autoFocus'> & { onBlur?: (value?: string) => void };
117
+
118
+ const editorVariants = {
119
+ // TODO(thure): remove when legacy is no longer used.
120
+ legacy: {
121
+ root: 'flex w-full',
122
+ editor: 'flex w-full [&>.cm-scroller]:scrollbar-none',
123
+ content: '!px-2 !py-1',
124
+ },
125
+ grid: {
126
+ root: 'absolute z-[1]',
127
+ editor: '[&>.cm-scroller]:scrollbar-none tabular-nums',
128
+ // This must match cell styling in `dx-grid.pcss`.
129
+ content: '!border !border-transparent !pli-[3px] !plb-0.5',
130
+ },
131
+ };
132
+
133
+ export const CellEditor = ({
134
+ value,
135
+ extension,
136
+ autoFocus,
137
+ onBlur,
138
+ variant = 'legacy',
139
+ box,
140
+ gridId,
141
+ }: CellEditorProps) => {
142
+ const { themeMode } = useThemeContext();
143
+ const { parentRef } = useTextEditor(() => {
144
+ return {
145
+ autoFocus,
146
+ initialValue: value,
147
+ selection: { anchor: value?.length ?? 0 },
148
+ extensions: [
149
+ extension ?? [],
150
+ preventNewline,
151
+ EditorView.focusChangeEffect.of((state, focusing) => {
152
+ if (!focusing) {
153
+ onBlur?.(state.doc.toString());
154
+ }
155
+ return null;
156
+ }),
157
+ createBasicExtensions({ lineWrapping: false }),
158
+ createThemeExtensions({
159
+ themeMode,
160
+ slots: {
161
+ editor: {
162
+ className: editorVariants[variant].editor,
163
+ },
164
+ content: {
165
+ className: editorVariants[variant].content,
166
+ },
167
+ },
168
+ }),
169
+ ],
170
+ };
171
+ }, [extension, autoFocus, value, variant, onBlur]);
172
+
173
+ return (
174
+ <div
175
+ ref={parentRef}
176
+ className={editorVariants[variant].root}
177
+ style={box}
178
+ {...(gridId && { 'data-grid': gridId })}
179
+ />
180
+ );
181
+ };
@@ -0,0 +1,31 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { CellEditor, type CellEditorProps } from './CellEditor';
8
+ import { type GridScopedProps, useGridContext } from '../Grid';
9
+
10
+ export const GridCellEditor = ({
11
+ extension,
12
+ getCellContent,
13
+ onBlur,
14
+ __gridScope,
15
+ }: GridScopedProps<
16
+ Pick<CellEditorProps, 'extension' | 'onBlur'> & { getCellContent: (index: string) => string | undefined }
17
+ >) => {
18
+ const { id, editing, editBox } = useGridContext('GridSheetCellEditor', __gridScope);
19
+
20
+ return editing ? (
21
+ <CellEditor
22
+ variant='grid'
23
+ value={editing.initialContent ?? getCellContent(editing.index)}
24
+ autoFocus
25
+ box={editBox}
26
+ onBlur={onBlur}
27
+ extension={extension}
28
+ gridId={id}
29
+ />
30
+ ) : null;
31
+ };
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './CellEditor';
6
+ export * from './GridCellEditor';
@@ -0,0 +1,137 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type StoryObj } from '@storybook/react';
8
+ import React, { type MouseEvent, type MutableRefObject, useCallback, useRef, useState } from 'react';
9
+
10
+ import { faker } from '@dxos/random';
11
+ import { DropdownMenu } from '@dxos/react-ui';
12
+ import { PopoverCombobox } from '@dxos/react-ui-searchlist';
13
+ import { withTheme } from '@dxos/storybook-utils';
14
+
15
+ import { Grid, type GridContentProps, type GridRootProps } from './Grid';
16
+
17
+ type StoryGridProps = GridContentProps & Pick<GridRootProps, 'onEditingChange'>;
18
+
19
+ const storybookItems = faker.helpers.uniqueArray(faker.commerce.productName, 16);
20
+
21
+ const storybookInitialCells = (value?: string) => ({
22
+ grid: {
23
+ '1,1': {
24
+ accessoryHtml:
25
+ '<button class="ch-button is-6 pli-0.5 min-bs-0 absolute inset-block-1 inline-end-1" data-story-action="menu"><svg><use href="/icons.svg#ph--arrow-right--regular"/></svg></button>',
26
+ value: 'Weekly sales report',
27
+ },
28
+ '2,2': {
29
+ accessoryHtml: `<dx-grid-multiselect-cell ${value ? `values='${JSON.stringify([{ label: value }])}'` : ''} placeholder="Select…"></dx-grid-multiselect-cell>`,
30
+ },
31
+ },
32
+ });
33
+
34
+ const StoryGrid = ({ onEditingChange, ...props }: StoryGridProps) => {
35
+ const [menuOpen, setMenuOpen] = useState(false);
36
+ const [popoverOpen, setPopoverOpen] = useState(false);
37
+ const [multiSelectValue, setInternalMultiselectValue] = useState('');
38
+ const triggerRef = useRef<HTMLButtonElement>(null) as MutableRefObject<HTMLButtonElement>;
39
+
40
+ const handleClick = useCallback((event: MouseEvent) => {
41
+ const closestStoryAction = (event.target as HTMLElement).closest('button[data-story-action]');
42
+ if (closestStoryAction) {
43
+ triggerRef.current = closestStoryAction as HTMLButtonElement;
44
+ return setMenuOpen(true);
45
+ }
46
+ const closestAccessory = (event.target as HTMLElement).closest('[data-dx-grid-accessory]');
47
+ if (closestAccessory) {
48
+ const action = closestAccessory.getAttribute('data-dx-grid-accessory');
49
+ switch (action) {
50
+ case 'invoke-multiselect':
51
+ triggerRef.current = closestAccessory as HTMLButtonElement;
52
+ return setPopoverOpen(true);
53
+ }
54
+ }
55
+ }, []);
56
+
57
+ const [initialCells, setInitialCells] = useState<GridContentProps['initialCells']>(storybookInitialCells());
58
+
59
+ const setMultiselectValue = useCallback((nextValue: string) => {
60
+ const nextInitialCells = storybookInitialCells(nextValue);
61
+ console.log('[set initial cells]', nextInitialCells);
62
+ setInitialCells(nextInitialCells);
63
+ setInternalMultiselectValue(nextValue);
64
+ }, []);
65
+
66
+ return (
67
+ <>
68
+ <Grid.Root id='story' onEditingChange={onEditingChange}>
69
+ <Grid.Content {...props} initialCells={initialCells} onClick={handleClick} />
70
+ </Grid.Root>
71
+ <DropdownMenu.Root open={menuOpen} onOpenChange={setMenuOpen}>
72
+ <DropdownMenu.VirtualTrigger virtualRef={triggerRef} />
73
+ <DropdownMenu.Content>
74
+ <DropdownMenu.Item onClick={() => console.log('[Click on dropdown menu item]')}>Hello</DropdownMenu.Item>
75
+ <DropdownMenu.Arrow />
76
+ </DropdownMenu.Content>
77
+ </DropdownMenu.Root>
78
+ <PopoverCombobox.Root
79
+ open={popoverOpen}
80
+ onOpenChange={setPopoverOpen}
81
+ value={multiSelectValue}
82
+ onValueChange={setMultiselectValue}
83
+ >
84
+ <PopoverCombobox.VirtualTrigger virtualRef={triggerRef} />
85
+ <PopoverCombobox.Content filter={(value, search) => (value.includes(search) ? 1 : 0)}>
86
+ <PopoverCombobox.Input placeholder='Search...' />
87
+ <PopoverCombobox.List>
88
+ {storybookItems.map((value) => (
89
+ <PopoverCombobox.Item key={value}>{value}</PopoverCombobox.Item>
90
+ ))}
91
+ </PopoverCombobox.List>
92
+ <PopoverCombobox.Arrow />
93
+ </PopoverCombobox.Content>
94
+ </PopoverCombobox.Root>
95
+ </>
96
+ );
97
+ };
98
+
99
+ export default {
100
+ title: 'ui/react-ui-grid/Grid',
101
+ component: StoryGrid,
102
+ decorators: [withTheme],
103
+ parameters: { layout: 'fullscreen' },
104
+ };
105
+
106
+ export const Basic: StoryObj<StoryGridProps> = {
107
+ args: {
108
+ id: 'story',
109
+ columnDefault: {
110
+ grid: {
111
+ size: 180,
112
+ resizeable: true,
113
+ },
114
+ },
115
+ rowDefault: {
116
+ grid: {
117
+ size: 32,
118
+ resizeable: true,
119
+ },
120
+ },
121
+ columns: {
122
+ grid: {
123
+ 0: { size: 200 },
124
+ 1: { size: 210 },
125
+ 2: { size: 230 },
126
+ 3: { size: 250 },
127
+ 4: { size: 270 },
128
+ },
129
+ },
130
+ onAxisResize: (event) => {
131
+ console.log('[axis resize]', event);
132
+ },
133
+ onEditingChange: (event) => {
134
+ console.log('[edit]', event);
135
+ },
136
+ },
137
+ };
@@ -0,0 +1,167 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import '@dxos/lit-grid/dx-grid.pcss';
6
+
7
+ import { createComponent, type EventName } from '@lit/react';
8
+ import { createContextScope, type Scope } from '@radix-ui/react-context';
9
+ import { useControllableState } from '@radix-ui/react-use-controllable-state';
10
+ import React, {
11
+ type ComponentProps,
12
+ forwardRef,
13
+ type PropsWithChildren,
14
+ useCallback,
15
+ useEffect,
16
+ useState,
17
+ } from 'react';
18
+
19
+ import { type DxAxisResize, type DxEditRequest, type DxGridCellsSelect, DxGrid as NaturalDxGrid } from '@dxos/lit-grid';
20
+
21
+ type DxGridElement = NaturalDxGrid;
22
+
23
+ const DxGrid = createComponent({
24
+ tagName: 'dx-grid',
25
+ elementClass: NaturalDxGrid,
26
+ react: React,
27
+ events: {
28
+ onAxisResize: 'dx-axis-resize' as EventName<DxAxisResize>,
29
+ onEdit: 'dx-edit-request' as EventName<DxEditRequest>,
30
+ onSelect: 'dx-grid-cells-select' as EventName<DxGridCellsSelect>,
31
+ },
32
+ });
33
+
34
+ type GridEditBox = DxEditRequest['cellBox'];
35
+
36
+ const initialBox = {
37
+ insetInlineStart: 0,
38
+ insetBlockStart: 0,
39
+ inlineSize: 0,
40
+ blockSize: 0,
41
+ } satisfies GridEditBox;
42
+
43
+ type GridEditing = { index: DxEditRequest['cellIndex']; initialContent: DxEditRequest['initialContent'] } | null;
44
+
45
+ type GridContextValue = {
46
+ id: string;
47
+ editing: GridEditing;
48
+ setEditing: (nextEditing: GridEditing) => void;
49
+ editBox: GridEditBox;
50
+ setEditBox: (nextEditBox: GridEditBox) => void;
51
+ };
52
+
53
+ type GridScopedProps<P> = P & { __gridScope?: Scope };
54
+
55
+ const GRID_NAME = 'Grid';
56
+
57
+ const [createGridContext, createGridScope] = createContextScope(GRID_NAME, []);
58
+
59
+ const [GridProvider, useGridContext] = createGridContext<GridContextValue>(GRID_NAME);
60
+
61
+ type GridRootProps = PropsWithChildren<
62
+ { id: string } & Partial<{
63
+ editing: GridEditing;
64
+ defaultEditing: GridEditing;
65
+ onEditingChange: (nextEditing: GridEditing) => void;
66
+ }>
67
+ >;
68
+
69
+ const GridRoot = ({
70
+ id,
71
+ editing: propsEditing,
72
+ defaultEditing,
73
+ onEditingChange,
74
+ children,
75
+ __gridScope,
76
+ }: GridScopedProps<GridRootProps>) => {
77
+ const [editing = null, setEditing] = useControllableState({
78
+ prop: propsEditing,
79
+ defaultProp: defaultEditing,
80
+ onChange: onEditingChange,
81
+ });
82
+ const [editBox, setEditBox] = useState<GridEditBox>(initialBox);
83
+ return (
84
+ <GridProvider
85
+ id={id}
86
+ editing={editing}
87
+ setEditing={setEditing}
88
+ editBox={editBox}
89
+ setEditBox={setEditBox}
90
+ scope={__gridScope}
91
+ >
92
+ <div className='dx-grid-host' style={{ display: 'contents' }}>
93
+ {children}
94
+ </div>
95
+ </GridProvider>
96
+ );
97
+ };
98
+
99
+ GridRoot.displayName = GRID_NAME;
100
+
101
+ type GridContentProps = Omit<ComponentProps<typeof DxGrid>, 'onEdit'> & {
102
+ getCells?: NonNullable<NaturalDxGrid['getCells']>;
103
+ activeRefs?: string;
104
+ };
105
+
106
+ const GRID_CONTENT_NAME = 'GridContent';
107
+
108
+ const GridContent = forwardRef<NaturalDxGrid, GridScopedProps<GridContentProps>>((props, forwardedRef) => {
109
+ const { id, editing, setEditBox, setEditing } = useGridContext(GRID_CONTENT_NAME, props.__gridScope);
110
+ const [dxGrid, setDxGridInternal] = useState<NaturalDxGrid | null>(null);
111
+
112
+ // NOTE(thure): using `useState` instead of `useRef` works with refs provided by `@lit/react` and gives us a reliable dependency for `useEffect` whereas `useLayoutEffect` does not guarantee the element will be defined.
113
+ const setDxGrid = useCallback(
114
+ (nextDxGrid: NaturalDxGrid | null) => {
115
+ setDxGridInternal(nextDxGrid);
116
+ if (forwardedRef) {
117
+ if (typeof forwardedRef === 'function') {
118
+ forwardedRef?.(nextDxGrid);
119
+ } else {
120
+ forwardedRef.current = nextDxGrid;
121
+ }
122
+ }
123
+ },
124
+ [forwardedRef, dxGrid],
125
+ );
126
+
127
+ useEffect(() => {
128
+ if (dxGrid && props.getCells) {
129
+ dxGrid.getCells = props.getCells;
130
+ dxGrid.requestUpdate('initialCells');
131
+ }
132
+ }, [props.getCells, dxGrid]);
133
+
134
+ const handleEdit = useCallback((event: DxEditRequest) => {
135
+ setEditBox(event.cellBox);
136
+ setEditing({ index: event.cellIndex, initialContent: event.initialContent });
137
+ }, []);
138
+
139
+ return <DxGrid {...props} gridId={id} mode={editing ? 'edit' : 'browse'} onEdit={handleEdit} ref={setDxGrid} />;
140
+ });
141
+
142
+ GridContent.displayName = GRID_CONTENT_NAME;
143
+
144
+ export const Grid = {
145
+ Root: GridRoot,
146
+ Content: GridContent,
147
+ };
148
+
149
+ export { GridRoot, GridContent, useGridContext, createGridScope };
150
+
151
+ export type { GridRootProps, GridContentProps, GridEditing, GridEditBox, GridScopedProps, DxGridElement };
152
+
153
+ export { colToA1Notation, rowToA1Notation, closestCell, commentedClassName } from '@dxos/lit-grid';
154
+
155
+ export type {
156
+ DxGridRange,
157
+ DxGridAxisMeta,
158
+ DxAxisResize,
159
+ DxGridCells,
160
+ DxGridPlaneRange,
161
+ DxGridPlaneCells,
162
+ DxGridCellIndex,
163
+ DxGridCellValue,
164
+ DxGridPlane,
165
+ DxGridPosition,
166
+ DxGridAxis,
167
+ } from '@dxos/lit-grid';
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './Grid';
package/src/index.ts CHANGED
@@ -3,3 +3,4 @@
3
3
  //
4
4
 
5
5
  export * from './Grid';
6
+ export * from './CellEditor';
@@ -1,8 +0,0 @@
1
- import '@dxos/lit-grid/dx-grid.pcss';
2
- import React from 'react';
3
- import { type DxAxisResize, type DxGridProps } from '@dxos/lit-grid';
4
- export type GridProps = DxGridProps & {
5
- onAxisResize: (event: DxAxisResize) => void;
6
- };
7
- export declare const Grid: (props: GridProps) => React.JSX.Element;
8
- //# sourceMappingURL=Grid.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Grid.d.ts","sourceRoot":"","sources":["../../../src/Grid.tsx"],"names":[],"mappings":"AAGA,OAAO,6BAA6B,CAAC;AAGrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,KAAK,YAAY,EAA2B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAW9F,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG;IACpC,YAAY,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;CAC7C,CAAC;AAEF,eAAO,MAAM,IAAI,UAAW,SAAS,sBAEpC,CAAC"}
@@ -1,43 +0,0 @@
1
- import { type GridProps } from './Grid';
2
- declare const _default: {
3
- title: string;
4
- component: (props: GridProps) => import("react").JSX.Element;
5
- decorators: import("@storybook/react/*").Decorator[];
6
- };
7
- export default _default;
8
- export declare const Basic: {
9
- args: {
10
- cells: {
11
- '1,1': {
12
- value: string;
13
- };
14
- };
15
- columnDefault: {
16
- size: number;
17
- resizeable: true;
18
- };
19
- rowDefault: {
20
- size: number;
21
- resizeable: true;
22
- };
23
- columns: {
24
- 0: {
25
- size: number;
26
- };
27
- 1: {
28
- size: number;
29
- };
30
- 2: {
31
- size: number;
32
- };
33
- 3: {
34
- size: number;
35
- };
36
- 4: {
37
- size: number;
38
- };
39
- };
40
- onAxisResize: (event: import("packages/ui/lit-grid/dist/types/src").DxAxisResize) => void;
41
- };
42
- };
43
- //# sourceMappingURL=Grid.stories.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Grid.stories.d.ts","sourceRoot":"","sources":["../../../src/Grid.stories.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;;;;;;AAE9C,wBAIE;AAEF,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BjB,CAAC"}
@@ -1,42 +0,0 @@
1
- //
2
- // Copyright 2024 DXOS.org
3
- //
4
-
5
- import { withTheme } from '@dxos/storybook-utils';
6
-
7
- import { Grid, type GridProps } from './Grid';
8
-
9
- export default {
10
- title: 'react-ui-grid/Grid',
11
- component: Grid,
12
- decorators: [withTheme],
13
- };
14
-
15
- export const Basic = {
16
- args: {
17
- cells: {
18
- '1,1': {
19
- // end: '8,1',
20
- value: 'Weekly sales report',
21
- },
22
- },
23
- columnDefault: {
24
- size: 180,
25
- resizeable: true,
26
- },
27
- rowDefault: {
28
- size: 32,
29
- resizeable: true,
30
- },
31
- columns: {
32
- 0: { size: 200 },
33
- 1: { size: 210 },
34
- 2: { size: 230 },
35
- 3: { size: 250 },
36
- 4: { size: 270 },
37
- },
38
- onAxisResize: (event) => {
39
- console.log('[axis resize]', event);
40
- },
41
- } satisfies GridProps,
42
- };
package/src/Grid.tsx DELETED
@@ -1,26 +0,0 @@
1
- //
2
- // Copyright 2024 DXOS.org
3
- //
4
- import '@dxos/lit-grid/dx-grid.pcss';
5
-
6
- import { createComponent, type EventName } from '@lit/react';
7
- import React from 'react';
8
-
9
- import { type DxAxisResize, DxGrid as NaturalDxGrid, type DxGridProps } from '@dxos/lit-grid';
10
-
11
- const DxGrid = createComponent({
12
- tagName: 'dx-grid',
13
- elementClass: NaturalDxGrid,
14
- react: React,
15
- events: {
16
- onAxisResize: 'dx-axis-resize' as EventName<DxAxisResize>,
17
- },
18
- });
19
-
20
- export type GridProps = DxGridProps & {
21
- onAxisResize: (event: DxAxisResize) => void;
22
- };
23
-
24
- export const Grid = (props: GridProps) => {
25
- return <DxGrid {...props} />;
26
- };