@duro-app/ui 5.34.1 → 5.34.3

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,34 +1,49 @@
1
1
  [
2
+ "archive",
3
+ "arrow-arc-left",
2
4
  "arrow-circle-down",
3
5
  "arrow-circle-right",
4
6
  "arrow-circle-up",
5
7
  "arrow-clockwise",
6
8
  "arrow-down",
9
+ "arrow-elbow-down-left",
7
10
  "arrow-elbow-down-right",
8
11
  "arrow-left",
9
12
  "arrow-right",
10
13
  "arrow-square-out",
14
+ "arrow-up",
11
15
  "arrows-clockwise",
12
16
  "arrows-down-up",
17
+ "arrows-in",
13
18
  "arrows-left-right",
14
19
  "arrows-out",
15
20
  "article",
16
21
  "at",
22
+ "atom",
23
+ "backspace",
17
24
  "bell",
18
25
  "bell-slash",
26
+ "book",
27
+ "book-bookmark",
19
28
  "bookmark",
20
29
  "books",
21
30
  "browsers",
22
31
  "bug",
23
32
  "calendar",
33
+ "camera",
24
34
  "caret-down",
25
35
  "caret-left",
36
+ "caret-right",
37
+ "caret-up",
38
+ "chart-bar",
26
39
  "chart-line",
27
40
  "chat",
41
+ "chat-circle",
28
42
  "chat-circle-dots",
29
43
  "chat-dots",
30
44
  "chats-circle",
31
45
  "check",
46
+ "check-square",
32
47
  "checks",
33
48
  "circle",
34
49
  "circle-half",
@@ -42,27 +57,45 @@
42
57
  "code",
43
58
  "copy",
44
59
  "cpu",
60
+ "credit-card",
45
61
  "crosshair",
46
62
  "cube",
63
+ "currency-dollar",
47
64
  "desktop",
48
65
  "device-mobile",
66
+ "discord-logo",
67
+ "dots-six-vertical",
68
+ "dots-three",
49
69
  "download",
50
70
  "envelope",
71
+ "envelope-open",
51
72
  "envelope-simple-open",
52
73
  "eye",
53
74
  "eye-slash",
75
+ "file",
54
76
  "file-arrow-down",
55
77
  "file-arrow-up",
78
+ "file-code",
56
79
  "files",
80
+ "fingerprint",
57
81
  "first-aid-kit",
82
+ "flame",
58
83
  "flask",
59
84
  "floppy-disk",
60
85
  "folder",
61
86
  "folder-open",
62
87
  "funnel-simple",
88
+ "game-controller",
89
+ "gear",
90
+ "gif",
91
+ "gift",
92
+ "git-commit",
63
93
  "git-diff",
94
+ "git-merge",
95
+ "git-pull-request",
64
96
  "github-logo",
65
97
  "globe",
98
+ "google-logo",
66
99
  "graph",
67
100
  "grid-four",
68
101
  "hammer",
@@ -71,17 +104,36 @@
71
104
  "hard-drives",
72
105
  "heart",
73
106
  "hourglass",
107
+ "house",
108
+ "images",
109
+ "infinity",
74
110
  "info",
75
111
  "laptop",
76
112
  "leaf",
113
+ "lifebuoy",
77
114
  "lightbulb",
78
115
  "lightning",
79
116
  "link",
117
+ "link-break",
80
118
  "list",
119
+ "list-bullets",
120
+ "list-checks",
121
+ "list-numbers",
81
122
  "magnifying-glass",
123
+ "mailbox",
124
+ "map-pin",
125
+ "markdown-logo",
82
126
  "microphone",
127
+ "microphone-slash",
128
+ "minus",
83
129
  "minus-circle",
130
+ "music-notes",
84
131
  "navigation-arrow",
132
+ "newspaper",
133
+ "note",
134
+ "note-pencil",
135
+ "octagon-x",
136
+ "paint-brush",
85
137
  "palette",
86
138
  "paper-plane",
87
139
  "paper-plane-tilt",
@@ -90,22 +142,34 @@
90
142
  "pencil",
91
143
  "pencil-simple",
92
144
  "person",
145
+ "phone",
93
146
  "play-circle",
94
147
  "plus",
95
148
  "plus-circle",
96
149
  "pulse",
97
150
  "push-pin",
151
+ "push-pin-slash",
98
152
  "puzzle-piece",
99
153
  "qr-code",
100
154
  "question",
155
+ "quotes",
156
+ "radio",
101
157
  "radio-button",
102
158
  "resize",
103
159
  "robot",
104
160
  "rocket",
161
+ "rocket-launch",
162
+ "scissors",
105
163
  "share",
164
+ "shuffle",
165
+ "sidebar-left-close",
166
+ "sidebar-left-open",
106
167
  "sign-in",
107
168
  "sign-out",
169
+ "skip-back",
170
+ "skip-forward",
108
171
  "sliders-horizontal",
172
+ "smiley",
109
173
  "sparkle",
110
174
  "speaker-high",
111
175
  "speaker-slash",
@@ -114,14 +178,23 @@
114
178
  "stack",
115
179
  "stack-simple",
116
180
  "star",
181
+ "stop",
182
+ "stop-circle",
117
183
  "terminal",
118
184
  "text-aa",
185
+ "text-b",
186
+ "text-h",
187
+ "text-italic",
188
+ "text-strikethrough",
189
+ "text-underline",
119
190
  "timer",
120
191
  "toggle-right",
121
192
  "translate",
122
193
  "trash",
123
194
  "tray",
124
195
  "user-circle",
196
+ "user-minus",
197
+ "video-camera",
125
198
  "warning",
126
199
  "warning-circle",
127
200
  "wifi-high",
@@ -7,6 +7,7 @@ import {clickLink} from '../../docs/clickLink'
7
7
  import {onThemeSurface} from '../../docs/themedSurface'
8
8
  import type {OnNavigate} from '../../shared/navigate'
9
9
  import {Icon} from '../Icon/Icon'
10
+ import {Card} from '../Card/Card'
10
11
  import {Badge} from '../Badge/Badge'
11
12
  import {Button} from '../Button/Button'
12
13
  import {Checkbox} from '../Checkbox/Checkbox'
@@ -365,3 +366,45 @@ export const LinkItems: StoryObj<{onNavigate: OnNavigate}> = {
365
366
  await expect(canvas.queryByRole('link', {name: 'Usage'})).toBeNull()
366
367
  },
367
368
  }
369
+
370
+ /**
371
+ * A settings group: the rows in a flush Card, reaching its rounded edge, with a divider between
372
+ * rows and none under the last (a hidden conditional row does not count).
373
+ */
374
+ export const InFlushCard: StoryObj<{showHidden: boolean}> = {
375
+ decorators: [onThemeSurface],
376
+ args: {showHidden: false},
377
+ render: (args) => (
378
+ <Card variant="outlined" size="flush">
379
+ <List.Root aria-label="General">
380
+ <List.Item href="#updates">
381
+ <List.Content>
382
+ <List.Text>Updates</List.Text>
383
+ </List.Content>
384
+ </List.Item>
385
+ <List.Item href="#appearance">
386
+ <List.Content>
387
+ <List.Text>Appearance</List.Text>
388
+ </List.Content>
389
+ </List.Item>
390
+ {args.showHidden ? (
391
+ <List.Item>
392
+ <List.Content>
393
+ <List.Text>Hidden</List.Text>
394
+ </List.Content>
395
+ </List.Item>
396
+ ) : null}
397
+ </List.Root>
398
+ </Card>
399
+ ),
400
+ play: async ({canvas}) => {
401
+ const list = canvas.getByRole('list', {name: 'General'})
402
+ const items = canvas.getAllByRole('listitem')
403
+ await expect(items).toHaveLength(2)
404
+ await expect(getComputedStyle(items[0]).borderBottomWidth).toBe('1px')
405
+ await expect(getComputedStyle(items[1]).borderBottomWidth).toBe('0px')
406
+ const card = list.parentElement as HTMLElement
407
+ await expect(getComputedStyle(card).paddingTop).toBe('0px')
408
+ await expect(getComputedStyle(card).overflow).toBe('hidden')
409
+ },
410
+ }
@@ -1,4 +1,13 @@
1
- import {type ReactNode, createContext, useContext, useId, useMemo, useState} from 'react'
1
+ import {
2
+ Children,
3
+ type ReactNode,
4
+ createContext,
5
+ isValidElement,
6
+ useContext,
7
+ useId,
8
+ useMemo,
9
+ useState,
10
+ } from 'react'
2
11
  import {html} from 'react-strict-dom'
3
12
  import type {OnNavigate} from '../../shared/navigate'
4
13
  import {
@@ -22,6 +31,9 @@ interface ListContextValue {
22
31
 
23
32
  const ListContext = createContext<ListContextValue>({selectionMode: 'none'})
24
33
 
34
+ // The Root's last item draws no divider below it: the list (or the card around it) ends there.
35
+ const LastItemContext = createContext(false)
36
+
25
37
  function useList() {
26
38
  return useContext(ListContext)
27
39
  }
@@ -56,7 +68,7 @@ function Root({
56
68
  aria-labelledby={hasTitle ? titleId : undefined}
57
69
  style={styles.root}
58
70
  >
59
- {children}
71
+ {markLastItem(children)}
60
72
  </html.div>
61
73
  )
62
74
  return (
@@ -78,6 +90,20 @@ function Root({
78
90
  )
79
91
  }
80
92
 
93
+ /** The Root's children, the last one told it is last (a hidden conditional row is not counted). */
94
+ function markLastItem(children: ReactNode): ReactNode {
95
+ const items = Children.toArray(children)
96
+ return items.map((child, index) =>
97
+ index === items.length - 1 ? (
98
+ <LastItemContext.Provider key={isValidElement(child) ? child.key : index} value={true}>
99
+ {child}
100
+ </LastItemContext.Provider>
101
+ ) : (
102
+ child
103
+ ),
104
+ )
105
+ }
106
+
81
107
  // --- Item ---
82
108
 
83
109
  interface ItemBaseProps {
@@ -130,6 +156,7 @@ function Item({children, selected, disabled, onClick, href, onNavigate}: ItemPro
130
156
  const {selectionMode} = useList()
131
157
  const isSelectable = selectionMode !== 'none'
132
158
  const isDisabled = disabled === true
159
+ const isLast = useContext(LastItemContext)
133
160
  const [linkState] = useState(createItemLinkState)
134
161
  const action = useMemo<ItemAction | null>(() => {
135
162
  if (href !== undefined) return {kind: 'link', href, onNavigate, disabled: isDisabled, linkState}
@@ -155,6 +182,7 @@ function Item({children, selected, disabled, onClick, href, onNavigate}: ItemPro
155
182
  styles.item,
156
183
  (onClick != null || href !== undefined) && !disabled && styles.itemClickable,
157
184
  selected && styles.itemSelected,
185
+ isLast && styles.itemLast,
158
186
  disabled && styles.itemDisabled,
159
187
  ]}
160
188
  >