@dxos/react-ui-list 0.8.4-main.f9ba587 → 0.8.4-main.fd6878d

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/dist/lib/browser/index.mjs +61 -55
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +61 -55
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/Accordion/Accordion.stories.d.ts +1 -1
  8. package/dist/types/src/components/Accordion/Accordion.stories.d.ts.map +1 -1
  9. package/dist/types/src/components/Accordion/AccordionItem.d.ts.map +1 -1
  10. package/dist/types/src/components/List/List.d.ts +6 -6
  11. package/dist/types/src/components/List/List.d.ts.map +1 -1
  12. package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
  13. package/dist/types/src/components/List/ListItem.d.ts +4 -7
  14. package/dist/types/src/components/List/ListItem.d.ts.map +1 -1
  15. package/dist/types/src/components/List/ListRoot.d.ts.map +1 -1
  16. package/dist/types/src/components/Tree/Tree.stories.d.ts +1 -1
  17. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Tree/TreeItem.d.ts +8 -7
  19. package/dist/types/src/components/Tree/TreeItem.d.ts.map +1 -1
  20. package/dist/types/src/components/Tree/TreeItemHeading.d.ts.map +1 -1
  21. package/dist/types/src/components/Tree/TreeItemToggle.d.ts.map +1 -1
  22. package/dist/types/tsconfig.tsbuildinfo +1 -1
  23. package/package.json +17 -16
  24. package/src/components/Accordion/Accordion.stories.tsx +1 -1
  25. package/src/components/Accordion/Accordion.tsx +1 -1
  26. package/src/components/Accordion/AccordionItem.tsx +2 -1
  27. package/src/components/List/List.stories.tsx +1 -1
  28. package/src/components/List/List.tsx +2 -5
  29. package/src/components/List/ListItem.tsx +44 -27
  30. package/src/components/List/ListRoot.tsx +1 -1
  31. package/src/components/Tree/Tree.stories.tsx +5 -4
  32. package/src/components/Tree/TreeItem.tsx +16 -16
  33. package/src/components/Tree/TreeItemHeading.tsx +3 -4
  34. package/src/components/Tree/TreeItemToggle.tsx +2 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-list",
3
- "version": "0.8.4-main.f9ba587",
3
+ "version": "0.8.4-main.fd6878d",
4
4
  "description": "A list component.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -9,6 +9,7 @@
9
9
  "type": "module",
10
10
  "exports": {
11
11
  ".": {
12
+ "source": "./src/index.ts",
12
13
  "types": "./dist/types/src/index.d.ts",
13
14
  "browser": "./dist/lib/browser/index.mjs",
14
15
  "node": "./dist/lib/node-esm/index.mjs"
@@ -29,33 +30,33 @@
29
30
  "@preact/signals-core": "^1.9.0",
30
31
  "@radix-ui/react-accordion": "1.2.3",
31
32
  "@radix-ui/react-context": "1.1.1",
32
- "@dxos/debug": "0.8.4-main.f9ba587",
33
- "@dxos/echo-schema": "0.8.4-main.f9ba587",
34
- "@dxos/invariant": "0.8.4-main.f9ba587",
35
- "@dxos/live-object": "0.8.4-main.f9ba587",
36
- "@dxos/log": "0.8.4-main.f9ba587",
37
- "@dxos/react-ui": "0.8.4-main.f9ba587",
38
- "@dxos/react-ui-text-tooltip": "0.8.4-main.f9ba587",
39
- "@dxos/react-ui-theme": "0.8.4-main.f9ba587",
40
- "@dxos/util": "0.8.4-main.f9ba587",
41
- "@dxos/react-ui-types": "0.8.4-main.f9ba587"
33
+ "@dxos/debug": "0.8.4-main.fd6878d",
34
+ "@dxos/echo-schema": "0.8.4-main.fd6878d",
35
+ "@dxos/invariant": "0.8.4-main.fd6878d",
36
+ "@dxos/react-ui": "0.8.4-main.fd6878d",
37
+ "@dxos/live-object": "0.8.4-main.fd6878d",
38
+ "@dxos/react-ui-text-tooltip": "0.8.4-main.fd6878d",
39
+ "@dxos/log": "0.8.4-main.fd6878d",
40
+ "@dxos/react-ui-theme": "0.8.4-main.fd6878d",
41
+ "@dxos/react-ui-types": "0.8.4-main.fd6878d",
42
+ "@dxos/util": "0.8.4-main.fd6878d"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@types/react": "~18.2.0",
45
46
  "@types/react-dom": "~18.2.0",
46
- "effect": "3.16.13",
47
+ "effect": "3.17.7",
47
48
  "react": "~18.2.0",
48
49
  "react-dom": "~18.2.0",
49
50
  "vite": "5.4.7",
50
- "@dxos/random": "0.8.4-main.f9ba587",
51
- "@dxos/storybook-utils": "0.8.4-main.f9ba587"
51
+ "@dxos/random": "0.8.4-main.fd6878d",
52
+ "@dxos/storybook-utils": "0.8.4-main.fd6878d"
52
53
  },
53
54
  "peerDependencies": {
54
55
  "effect": "^3.13.3",
55
56
  "react": "~18.2.0",
56
57
  "react-dom": "~18.2.0",
57
- "@dxos/react-ui": "0.8.4-main.f9ba587",
58
- "@dxos/react-ui-theme": "0.8.4-main.f9ba587"
58
+ "@dxos/react-ui": "0.8.4-main.fd6878d",
59
+ "@dxos/react-ui-theme": "0.8.4-main.fd6878d"
59
60
  },
60
61
  "publishConfig": {
61
62
  "access": "public"
@@ -4,7 +4,7 @@
4
4
 
5
5
  import '@dxos-theme';
6
6
 
7
- import { type StoryObj, type Meta } from '@storybook/react-vite';
7
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
8
  import React from 'react';
9
9
 
10
10
  import { faker } from '@dxos/random';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { AccordionItem, AccordionItemHeader, AccordionItemBody } from './AccordionItem';
5
+ import { AccordionItem, AccordionItemBody, AccordionItemHeader } from './AccordionItem';
6
6
  import { AccordionRoot } from './AccordionRoot';
7
7
 
8
8
  // TODO(burdon): Next iteration should be based on Radix UI Accordion:
@@ -9,9 +9,10 @@ import React, { type PropsWithChildren } from 'react';
9
9
  import { Icon, type ThemedClassName } from '@dxos/react-ui';
10
10
  import { mx } from '@dxos/react-ui-theme';
11
11
 
12
- import { useAccordionContext } from './AccordionRoot';
13
12
  import { type ListItemRecord } from '../List';
14
13
 
14
+ import { useAccordionContext } from './AccordionRoot';
15
+
15
16
  const ACCORDION_ITEM_NAME = 'AccordionItem';
16
17
 
17
18
  type AccordionItemContext<T extends ListItemRecord> = {
@@ -14,7 +14,7 @@ import { withLayout, withTheme } from '@dxos/storybook-utils';
14
14
  import { arrayMove } from '@dxos/util';
15
15
 
16
16
  import { List, type ListRootProps } from './List';
17
- import { createList, TestItemSchema, type TestItemType } from './testing';
17
+ import { TestItemSchema, type TestItemType, createList } from './testing';
18
18
 
19
19
  // TODO(burdon): var-icon-size.
20
20
  const grid = 'grid grid-cols-[32px_1fr_32px] min-bs-[2rem] rounded';
@@ -3,11 +3,9 @@
3
3
  //
4
4
 
5
5
  import {
6
- IconButton,
7
- type IconButtonProps,
8
6
  ListItem,
9
- ListItemDeleteButton,
10
7
  ListItemButton,
8
+ ListItemDeleteButton,
11
9
  ListItemDragHandle,
12
10
  ListItemDragPreview,
13
11
  type ListItemProps,
@@ -38,9 +36,8 @@ export const List = {
38
36
  ItemDeleteButton: ListItemDeleteButton,
39
37
  ItemButton: ListItemButton,
40
38
  ItemTitle: ListItemTitle,
41
- IconButton,
42
39
  };
43
40
 
44
41
  type ListItem = ListItemRecord;
45
42
 
46
- export type { ListRootProps, ListItemProps, IconButtonProps, ListItem, ListItemRecord };
43
+ export type { ListRootProps, ListItemProps, ListItem, ListItemRecord };
@@ -17,7 +17,6 @@ import React, {
17
17
  type MutableRefObject,
18
18
  type PropsWithChildren,
19
19
  type ReactNode,
20
- forwardRef,
21
20
  useEffect,
22
21
  useRef,
23
22
  useState,
@@ -25,7 +24,13 @@ import React, {
25
24
  import { createPortal } from 'react-dom';
26
25
 
27
26
  import { invariant } from '@dxos/invariant';
28
- import { Icon, type ThemedClassName, ListItem as NaturalListItem } from '@dxos/react-ui';
27
+ import {
28
+ IconButton,
29
+ type IconButtonProps,
30
+ ListItem as NaturalListItem,
31
+ type ThemedClassName,
32
+ useTranslation,
33
+ } from '@dxos/react-ui';
29
34
  import { mx } from '@dxos/react-ui-theme';
30
35
 
31
36
  import { useListContext } from './ListRoot';
@@ -165,15 +170,13 @@ export const ListItem = <T extends ListItemRecord>({ children, classNames, item,
165
170
 
166
171
  return (
167
172
  <ListItemProvider item={item} dragHandleRef={dragHandleRef}>
168
- <div role='none' className='relative'>
169
- <div
170
- ref={ref}
171
- role='listitem'
172
- className={mx('flex overflow-hidden', classNames, stateStyles[state.type])}
173
- {...props}
174
- >
175
- {children}
176
- </div>
173
+ <div
174
+ ref={ref}
175
+ role='listitem'
176
+ className={mx('flex overflow-hidden relative', classNames, stateStyles[state.type])}
177
+ {...props}
178
+ >
179
+ {children}
177
180
  {state.type === 'is-dragging-over' && state.closestEdge && (
178
181
  <NaturalListItem.DropIndicator edge={state.closestEdge} />
179
182
  )}
@@ -186,51 +189,65 @@ export const ListItem = <T extends ListItemRecord>({ children, classNames, item,
186
189
  // List item components
187
190
  //
188
191
 
189
- export type IconButtonProps = ThemedClassName<ComponentProps<'button'>> & { icon: string };
190
-
191
- export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
192
- ({ classNames, icon, ...props }, forwardedRef) => {
193
- return (
194
- <button ref={forwardedRef} className={mx('flex items-center justify-center', classNames)} {...props}>
195
- <Icon icon={icon} classNames='cursor-pointer' size={4} />
196
- </button>
197
- );
198
- },
199
- );
200
-
201
192
  export const ListItemDeleteButton = ({
202
193
  autoHide = true,
203
194
  classNames,
204
195
  disabled,
205
196
  icon = 'ph--x--regular',
197
+ label,
206
198
  ...props
207
- }: Partial<Pick<IconButtonProps, 'icon'>> & Omit<IconButtonProps, 'icon'> & { autoHide?: boolean }) => {
199
+ }: Partial<Pick<IconButtonProps, 'icon'>> &
200
+ Omit<IconButtonProps, 'icon' | 'label'> & { autoHide?: boolean; label?: string }) => {
208
201
  const { state } = useListContext('DELETE_BUTTON');
209
202
  const isDisabled = state.type !== 'idle' || disabled;
203
+ const { t } = useTranslation('os');
210
204
  return (
211
205
  <IconButton
206
+ iconOnly
207
+ variant='ghost'
208
+ {...props}
212
209
  icon={icon}
213
210
  disabled={isDisabled}
211
+ label={label ?? t('delete label')}
214
212
  classNames={[classNames, autoHide && disabled && 'hidden']}
215
- {...props}
216
213
  />
217
214
  );
218
215
  };
219
216
 
220
217
  export const ListItemButton = ({
221
218
  autoHide = true,
219
+ iconOnly = true,
220
+ variant = 'ghost',
222
221
  classNames,
223
222
  disabled,
224
223
  ...props
225
224
  }: IconButtonProps & { autoHide?: boolean }) => {
226
225
  const { state } = useListContext('ITEM_BUTTON');
227
226
  const isDisabled = state.type !== 'idle' || disabled;
228
- return <IconButton disabled={isDisabled} classNames={[classNames, autoHide && disabled && 'hidden']} {...props} />;
227
+ return (
228
+ <IconButton
229
+ {...props}
230
+ disabled={isDisabled}
231
+ iconOnly={iconOnly}
232
+ variant={variant}
233
+ classNames={[classNames, autoHide && disabled && 'hidden']}
234
+ />
235
+ );
229
236
  };
230
237
 
231
238
  export const ListItemDragHandle = ({ disabled }: Pick<IconButtonProps, 'disabled'>) => {
232
239
  const { dragHandleRef } = useListItemContext('DRAG_HANDLE');
233
- return <IconButton ref={dragHandleRef as any} icon='ph--dots-six-vertical--regular' disabled={disabled} />;
240
+ const { t } = useTranslation('os');
241
+ return (
242
+ <IconButton
243
+ iconOnly
244
+ variant='ghost'
245
+ label={t('drag handle label')}
246
+ ref={dragHandleRef as any}
247
+ icon='ph--dots-six-vertical--regular'
248
+ disabled={disabled}
249
+ />
250
+ );
234
251
  };
235
252
 
236
253
  export const ListItemDragPreview = <T extends ListItemRecord>({
@@ -8,7 +8,7 @@ import { getReorderDestinationIndex } from '@atlaskit/pragmatic-drag-and-drop-hi
8
8
  import { createContext } from '@radix-ui/react-context';
9
9
  import React, { type ReactNode, useCallback, useEffect, useState } from 'react';
10
10
 
11
- import { idle, type ItemDragState, type ListItemRecord } from './ListItem';
11
+ import { type ItemDragState, type ListItemRecord, idle } from './ListItem';
12
12
 
13
13
  type ListContext<T extends ListItemRecord> = {
14
14
  // TODO(burdon): Rename drag state.
@@ -5,19 +5,20 @@
5
5
  import '@dxos-theme';
6
6
 
7
7
  import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
8
- import { extractInstruction, type Instruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
8
+ import { type Instruction, extractInstruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
9
9
  import { type Meta, type StoryObj } from '@storybook/react-vite';
10
10
  import React, { useEffect } from 'react';
11
11
 
12
- import { live, type Live } from '@dxos/live-object';
12
+ import { type Live, live } from '@dxos/live-object';
13
13
  import { faker } from '@dxos/random';
14
14
  import { Icon } from '@dxos/react-ui';
15
15
  import { withLayout, withTheme } from '@dxos/storybook-utils';
16
16
 
17
+ import { Path } from '../../util';
18
+
19
+ import { type TestItem, createTree, updateState } from './testing';
17
20
  import { Tree } from './Tree';
18
21
  import { type TreeData } from './TreeItem';
19
- import { createTree, updateState, type TestItem } from './testing';
20
- import { Path } from '../../util';
21
22
 
22
23
  faker.seed(1234);
23
24
 
@@ -5,29 +5,28 @@
5
5
  import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
6
6
  import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
7
7
  import {
8
- attachInstruction,
9
- extractInstruction,
10
8
  type Instruction,
11
9
  type ItemMode,
10
+ attachInstruction,
11
+ extractInstruction,
12
12
  } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
13
13
  import { Schema } from 'effect';
14
- import React, { memo, useCallback, useEffect, useMemo, useRef, useState, type FC, type KeyboardEvent } from 'react';
14
+ import React, { type FC, type KeyboardEvent, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
15
15
 
16
16
  import { type HasId } from '@dxos/echo-schema';
17
17
  import { invariant } from '@dxos/invariant';
18
- import { Treegrid, TreeItem as NaturalTreeItem } from '@dxos/react-ui';
18
+ import { TreeItem as NaturalTreeItem, Treegrid } from '@dxos/react-ui';
19
19
  import {
20
20
  ghostHover,
21
21
  hoverableControls,
22
22
  hoverableFocusedKeyboardControls,
23
23
  hoverableFocusedWithinControls,
24
- mx,
25
24
  } from '@dxos/react-ui-theme';
26
25
 
26
+ import { DEFAULT_INDENTATION, paddingIndentation } from './helpers';
27
27
  import { useTree } from './TreeContext';
28
28
  import { TreeItemHeading } from './TreeItemHeading';
29
29
  import { TreeItemToggle } from './TreeItemToggle';
30
- import { DEFAULT_INDENTATION, paddingIndentation } from './helpers';
31
30
 
32
31
  type TreeItemState = 'idle' | 'dragging' | 'preview' | 'parent-of-instruction';
33
32
 
@@ -41,22 +40,23 @@ export const TreeDataSchema = Schema.Struct({
41
40
  });
42
41
 
43
42
  export type TreeData = Schema.Schema.Type<typeof TreeDataSchema>;
44
-
45
43
  export const isTreeData = (data: unknown): data is TreeData => Schema.is(TreeDataSchema)(data);
46
44
 
45
+ export type ColumnRenderer<T extends HasId = any> = FC<{
46
+ item: T;
47
+ path: string[];
48
+ open: boolean;
49
+ menuOpen: boolean;
50
+ setMenuOpen: (open: boolean) => void;
51
+ }>;
52
+
47
53
  export type TreeItemProps<T extends HasId = any> = {
48
54
  item: T;
49
55
  path: string[];
50
56
  levelOffset?: number;
51
57
  last: boolean;
52
58
  draggable?: boolean;
53
- renderColumns?: FC<{
54
- item: T;
55
- path: string[];
56
- open: boolean;
57
- menuOpen: boolean;
58
- setMenuOpen: (open: boolean) => void;
59
- }>;
59
+ renderColumns?: ColumnRenderer<T>;
60
60
  canDrop?: (params: { source: TreeData; target: TreeData }) => boolean;
61
61
  onOpenChange?: (params: { item: T; path: string[]; open: boolean }) => void;
62
62
  onSelect?: (params: { item: T; path: string[]; current: boolean; option: boolean }) => void;
@@ -223,7 +223,7 @@ const RawTreeItem = <T extends HasId = any>({
223
223
  id={id}
224
224
  aria-labelledby={`${id}__label`}
225
225
  parentOf={parentOf?.join(Treegrid.PARENT_OF_SEPARATOR)}
226
- classNames={mx(
226
+ classNames={[
227
227
  'grid grid-cols-subgrid col-[tree-row] mbs-0.5 aria-[current]:bg-activeSurface',
228
228
  hoverableControls,
229
229
  hoverableFocusedKeyboardControls,
@@ -231,7 +231,7 @@ const RawTreeItem = <T extends HasId = any>({
231
231
  hoverableDescriptionIcons,
232
232
  ghostHover,
233
233
  className,
234
- )}
234
+ ]}
235
235
  data-itemid={id}
236
236
  data-testid={testId}
237
237
  // NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
@@ -4,9 +4,8 @@
4
4
 
5
5
  import React, { type KeyboardEvent, type MouseEvent, forwardRef, memo, useCallback } from 'react';
6
6
 
7
- import { Button, Icon, toLocalizedString, useTranslation, type Label } from '@dxos/react-ui';
7
+ import { Button, Icon, type Label, toLocalizedString, useTranslation } from '@dxos/react-ui';
8
8
  import { TextTooltip } from '@dxos/react-ui-text-tooltip';
9
- import { mx } from '@dxos/react-ui-theme';
10
9
 
11
10
  // TODO(wittjosiah): Consider whether there should be a separate disabled prop which was visually distinct
12
11
  // rather than just making the item unselectable.
@@ -55,11 +54,11 @@ export const TreeItemHeading = memo(
55
54
  data-testid='treeItem.heading'
56
55
  variant='ghost'
57
56
  density='fine'
58
- classNames={mx(
57
+ classNames={[
59
58
  'grow gap-2 pis-0.5 hover:bg-transparent dark:hover:bg-transparent',
60
59
  'disabled:cursor-default disabled:opacity-100',
61
60
  className,
62
- )}
61
+ ]}
63
62
  disabled={disabled}
64
63
  onClick={handleSelect}
65
64
  onKeyDown={handleButtonKeydown}
@@ -5,7 +5,6 @@
5
5
  import React, { forwardRef, memo } from 'react';
6
6
 
7
7
  import { Button, Icon } from '@dxos/react-ui';
8
- import { mx } from '@dxos/react-ui-theme';
9
8
 
10
9
  export type TreeItemToggleProps = {
11
10
  open?: boolean;
@@ -23,10 +22,10 @@ export const TreeItemToggle = memo(
23
22
  aria-expanded={open}
24
23
  variant='ghost'
25
24
  density='fine'
26
- classNames={mx('is-6 pli-0 dx-focus-ring-inset', hidden ? 'hidden' : !isBranch && 'invisible')}
25
+ classNames={['is-6 pli-0 dx-focus-ring-inset', hidden ? 'hidden' : !isBranch && 'invisible']}
27
26
  onClick={onToggle}
28
27
  >
29
- <Icon icon='ph--caret-right--bold' size={3} classNames={mx('transition duration-200', open && 'rotate-90')} />
28
+ <Icon icon='ph--caret-right--bold' size={3} classNames={['transition duration-200', open && 'rotate-90']} />
30
29
  </Button>
31
30
  );
32
31
  }),