@dxos/react-ui-list 0.8.4-main.d05539e30a → 0.8.4-main.d9fc60f731

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-list",
3
- "version": "0.8.4-main.d05539e30a",
3
+ "version": "0.8.4-main.d9fc60f731",
4
4
  "description": "A list component.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -33,33 +33,33 @@
33
33
  "@radix-ui/react-context": "1.1.1",
34
34
  "@radix-ui/react-slot": "1.1.2",
35
35
  "@radix-ui/react-use-controllable-state": "1.1.0",
36
- "@dxos/debug": "0.8.4-main.d05539e30a",
37
- "@dxos/echo": "0.8.4-main.d05539e30a",
38
- "@dxos/invariant": "0.8.4-main.d05539e30a",
39
- "@dxos/log": "0.8.4-main.d05539e30a",
40
- "@dxos/react-ui": "0.8.4-main.d05539e30a",
41
- "@dxos/react-list": "0.8.4-main.d05539e30a",
42
- "@dxos/react-ui-text-tooltip": "0.8.4-main.d05539e30a",
43
- "@dxos/util": "0.8.4-main.d05539e30a",
44
- "@dxos/ui-types": "0.8.4-main.d05539e30a",
45
- "@dxos/ui-theme": "0.8.4-main.d05539e30a"
36
+ "@dxos/debug": "0.8.4-main.d9fc60f731",
37
+ "@dxos/echo": "0.8.4-main.d9fc60f731",
38
+ "@dxos/invariant": "0.8.4-main.d9fc60f731",
39
+ "@dxos/log": "0.8.4-main.d9fc60f731",
40
+ "@dxos/react-ui": "0.8.4-main.d9fc60f731",
41
+ "@dxos/react-list": "0.8.4-main.d9fc60f731",
42
+ "@dxos/react-ui-text-tooltip": "0.8.4-main.d9fc60f731",
43
+ "@dxos/ui-theme": "0.8.4-main.d9fc60f731",
44
+ "@dxos/ui-types": "0.8.4-main.d9fc60f731",
45
+ "@dxos/util": "0.8.4-main.d9fc60f731"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/react": "~19.2.7",
49
49
  "@types/react-dom": "~19.2.3",
50
- "effect": "3.20.0",
50
+ "effect": "3.21.2",
51
51
  "react": "~19.2.3",
52
52
  "react-dom": "~19.2.3",
53
- "vite": "^8.0.13",
54
- "@dxos/random": "0.8.4-main.d05539e30a",
55
- "@dxos/storybook-utils": "0.8.4-main.d05539e30a"
53
+ "vite": "^8.0.14",
54
+ "@dxos/random": "0.8.4-main.d9fc60f731",
55
+ "@dxos/storybook-utils": "0.8.4-main.d9fc60f731"
56
56
  },
57
57
  "peerDependencies": {
58
- "effect": "3.20.0",
58
+ "effect": "3.21.2",
59
59
  "react": "~19.2.3",
60
60
  "react-dom": "~19.2.3",
61
- "@dxos/ui-theme": "0.8.4-main.d05539e30a",
62
- "@dxos/react-ui": "0.8.4-main.d05539e30a"
61
+ "@dxos/react-ui": "0.8.4-main.d9fc60f731",
62
+ "@dxos/ui-theme": "0.8.4-main.d9fc60f731"
63
63
  },
64
64
  "publishConfig": {
65
65
  "access": "public"
@@ -37,7 +37,8 @@ import {
37
37
  type ThemedClassName,
38
38
  useId,
39
39
  } from '@dxos/react-ui';
40
- import { composable, composableProps, mx } from '@dxos/ui-theme';
40
+ import { composable, composableProps } from '@dxos/react-ui';
41
+ import { mx } from '@dxos/ui-theme';
41
42
 
42
43
  import { Picker, type PickerInputProps, type PickerItemProps } from '../Picker';
43
44
 
@@ -79,7 +79,7 @@ import React, { type FocusEvent, type ForwardedRef, type MouseEvent, type PropsW
79
79
 
80
80
  import { List, ListItem } from '@dxos/react-list';
81
81
  import { ScrollArea, type ScrollAreaRootProps } from '@dxos/react-ui';
82
- import { composable, composableProps } from '@dxos/ui-theme';
82
+ import { composable, composableProps } from '@dxos/react-ui';
83
83
 
84
84
  const ROW_LIST_NAME = 'RowList';
85
85
  const ROW_LIST_ROOT_NAME = 'RowList.Root';
@@ -93,6 +93,9 @@ const DefaultStory = ({ draggable }: { draggable?: boolean }) => {
93
93
  icon: parent.icon,
94
94
  ...((parent.items?.length ?? 0) > 0 && {
95
95
  parentOf: parent.items!.map(({ id }) => id),
96
+ count: parent.items!.length,
97
+ // Demonstrate the rose "new/modified" badge on a subset of branches (replaces the neutral count).
98
+ ...(parent.name.length % 3 === 0 && { modifiedCount: (parent.name.length % 5) + 1 }),
96
99
  }),
97
100
  };
98
101
  }).pipe(Atom.keepAlive);
@@ -179,7 +182,7 @@ const DefaultStory = ({ draggable }: { draggable?: boolean }) => {
179
182
  draggable={draggable}
180
183
  renderColumns={() => (
181
184
  <div className='flex items-center'>
182
- <Icon icon='ph--placeholder--regular' />
185
+ <Icon icon='ph--circle-dashed--regular' />
183
186
  </div>
184
187
  )}
185
188
  onOpenChange={handleOpenChange}
@@ -35,7 +35,7 @@ export const Tree = <T extends { id: string } = any>({
35
35
  path,
36
36
  id,
37
37
  draggable = false,
38
- gridTemplateColumns = '[tree-row-start] 1fr min-content [tree-row-end]',
38
+ gridTemplateColumns = '[tree-row-start] minmax(0, 1fr) min-content [tree-row-end]',
39
39
  levelOffset,
40
40
  renderColumns,
41
41
  blockInstruction,
@@ -22,6 +22,10 @@ export type TreeItemDataProps = {
22
22
  iconHue?: string;
23
23
  disabled?: boolean;
24
24
  testId?: string;
25
+ /** Optional item count rendered as a neutral badge directly after the label. */
26
+ count?: number;
27
+ /** Optional count of new/modified items; when greater than zero it shows as a rose badge in place of `count`. */
28
+ modifiedCount?: number;
25
29
  };
26
30
 
27
31
  export interface TreeModel<T extends { id: string } = any> {
@@ -119,6 +119,8 @@ const RawTreeItem = <T extends { id: string } = any>({
119
119
  iconHue,
120
120
  disabled,
121
121
  testId,
122
+ count,
123
+ modifiedCount,
122
124
  } = useAtomValue(itemPropsAtom(path));
123
125
  const childIds = useAtomValue(childIdsAtom(item.id));
124
126
  const open = useAtomValue(itemOpenAtom(path));
@@ -336,6 +338,8 @@ const RawTreeItem = <T extends { id: string } = any>({
336
338
  className={headingClassName}
337
339
  icon={icon}
338
340
  iconHue={iconHue}
341
+ count={count}
342
+ modifiedCount={modifiedCount}
339
343
  onSelect={handleSelect}
340
344
  ref={buttonRef}
341
345
  />
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React, { type KeyboardEvent, type MouseEvent, forwardRef, memo, useCallback } from 'react';
6
6
 
7
- import { Button, Icon, type Label, toLocalizedString, useTranslation } from '@dxos/react-ui';
7
+ import { Button, Icon, type Label, Tag, toLocalizedString, useTranslation } from '@dxos/react-ui';
8
8
  import { TextTooltip } from '@dxos/react-ui-text-tooltip';
9
9
  import { getStyles } from '@dxos/ui-theme';
10
10
 
@@ -17,12 +17,16 @@ export type TreeItemHeadingProps = {
17
17
  iconHue?: string;
18
18
  disabled?: boolean;
19
19
  current?: boolean;
20
+ /** Optional item count rendered as a neutral badge directly after the label. */
21
+ count?: number;
22
+ /** Optional count of new/modified items; when greater than zero it replaces {@link count} with a rose badge. */
23
+ modifiedCount?: number;
20
24
  onSelect?: (option: boolean) => void;
21
25
  };
22
26
 
23
27
  export const TreeItemHeading = memo(
24
28
  forwardRef<HTMLButtonElement, TreeItemHeadingProps>(
25
- ({ label, className, icon, iconHue, disabled, current, onSelect }, forwardedRef) => {
29
+ ({ label, className, icon, iconHue, disabled, current, count, modifiedCount, onSelect }, forwardedRef) => {
26
30
  const { t } = useTranslation();
27
31
  const styles = iconHue ? getStyles(iconHue) : undefined;
28
32
 
@@ -57,7 +61,7 @@ export const TreeItemHeading = memo(
57
61
  data-testid='treeItem.heading'
58
62
  variant='ghost'
59
63
  classNames={[
60
- 'grow gap-2 ps-0.5 hover:bg-transparent dark:hover:bg-transparent',
64
+ 'grow shrink min-w-0 justify-start gap-2 ps-0.5 hover:bg-transparent dark:hover:bg-transparent',
61
65
  'disabled:cursor-default disabled:opacity-100',
62
66
  className,
63
67
  ]}
@@ -66,15 +70,38 @@ export const TreeItemHeading = memo(
66
70
  onKeyDown={handleButtonKeydown}
67
71
  {...(current && { 'aria-current': 'location' })}
68
72
  >
69
- {icon && (
70
- <Icon size={5} icon={icon ?? 'ph--placeholder--regular'} classNames={['my-1', styles?.foreground]} />
71
- )}
72
- <span className='flex-1 w-0 truncate text-start font-normal' data-tooltip>
73
+ {icon && <Icon size={5} icon={icon ?? 'ph--circle-dashed--regular'} classNames={['my-1', styles?.text]} />}
74
+ <span className='min-w-0 truncate text-start font-normal' data-tooltip>
73
75
  {toLocalizedString(label, t)}
74
76
  </span>
77
+ <CountBadge count={count} modifiedCount={modifiedCount} />
75
78
  </Button>
76
79
  </TextTooltip>
77
80
  );
78
81
  },
79
82
  ),
80
83
  );
84
+
85
+ /**
86
+ * Renders the count badge after a tree item label.
87
+ * A positive `modifiedCount` (e.g. new/unread items) shows as a rose badge in place of the neutral total `count`.
88
+ */
89
+ const CountBadge = ({ count, modifiedCount }: Pick<TreeItemHeadingProps, 'count' | 'modifiedCount'>) => {
90
+ if (typeof modifiedCount === 'number' && modifiedCount > 0) {
91
+ return (
92
+ <Tag palette='rose' classNames='shrink-0 text-center [min-inline-size:1.5rem] tabular-nums'>
93
+ {modifiedCount}
94
+ </Tag>
95
+ );
96
+ }
97
+
98
+ if (typeof count === 'number') {
99
+ return (
100
+ <Tag palette='neutral' classNames='shrink-0 text-center [min-inline-size:1.5rem] tabular-nums'>
101
+ {count}
102
+ </Tag>
103
+ );
104
+ }
105
+
106
+ return null;
107
+ };
@@ -21,7 +21,7 @@ export const TreeItemToggle = memo(
21
21
  data-testid='treeItem.toggle'
22
22
  aria-expanded={open}
23
23
  variant='ghost'
24
- density='fine'
24
+ density='md'
25
25
  classNames={[
26
26
  'h-full w-6 px-0',
27
27
  '[&_svg]:transition-transform [&_svg]:duration-200',