@moises.ai/design-system 3.7.3 → 3.8.0

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": "@moises.ai/design-system",
3
- "version": "3.7.3",
3
+ "version": "3.8.0",
4
4
  "description": "Design System package based on @radix-ui/themes with custom defaults",
5
5
  "private": false,
6
6
  "type": "module",
@@ -0,0 +1,71 @@
1
+ import { useCallback } from 'react'
2
+ import { Flex } from '@radix-ui/themes'
3
+ import { MinusIcon, PlusIcon } from '../../icons'
4
+ import { IconButton } from '../IconButton/IconButton'
5
+ import { Text } from '../Text/Text'
6
+
7
+ export const NumberPicker = ({
8
+ label,
9
+ value = 0,
10
+ min = 0,
11
+ max = 10,
12
+ onChange,
13
+ }) => {
14
+ const onIncrement = useCallback((e) => {
15
+ e.stopPropagation()
16
+ if (max != null && value >= max) return
17
+ onChange(value + 1)
18
+ }, [max, onChange, value])
19
+
20
+ const onDecrement = useCallback((e) => {
21
+ e.stopPropagation()
22
+ if (min != null && value <= min) return
23
+ onChange(value - 1)
24
+ }, [min, onChange, value])
25
+
26
+ return (
27
+ <Flex direction="row" gap="1" align="center" justify="center">
28
+ {label && (
29
+ <Text size="2" weight="medium">
30
+ {label}
31
+ </Text>
32
+ )}
33
+ <Flex direction="row" gap="1" align="center" justify="center">
34
+ <IconButton
35
+ type="button"
36
+ aria-label="increment"
37
+ onClick={onDecrement}
38
+ style={{
39
+ backgroundColor: 'var(--neutral-alpha-3 )',
40
+ }}
41
+ >
42
+ <MinusIcon width={16} height={16} />
43
+ </IconButton>
44
+
45
+ <Flex
46
+ align="center"
47
+ justify="center"
48
+ style={{
49
+ height: '24px',
50
+ minWidth: '42px',
51
+ borderRadius: 'var(--radius-2)',
52
+ backgroundColor: 'var(--neutral-alpha-3 )',
53
+ }}
54
+ >
55
+ <Text size="2">{value > 0 ? `+${value}` : value}</Text>
56
+ </Flex>
57
+
58
+ <IconButton
59
+ type="button"
60
+ aria-label="decrement"
61
+ onClick={onIncrement}
62
+ style={{
63
+ backgroundColor: 'var(--neutral-alpha-3 )',
64
+ }}
65
+ >
66
+ <PlusIcon width={16} height={16} />
67
+ </IconButton>
68
+ </Flex>
69
+ </Flex>
70
+ )
71
+ }
@@ -0,0 +1,63 @@
1
+ import { useState } from 'react'
2
+ import { NumberPicker } from './NumberPicker'
3
+
4
+ export default {
5
+ title: 'Components/NumberPicker',
6
+ component: NumberPicker,
7
+ tags: ['autodocs'],
8
+ argTypes: {
9
+ label: { control: 'text' },
10
+ value: { control: 'number' },
11
+ min: { control: 'number' },
12
+ max: { control: 'number' },
13
+ },
14
+ }
15
+
16
+ export const Default = {
17
+ args: {
18
+ label: 'Number',
19
+ value: 0,
20
+ min: -10,
21
+ max: 10,
22
+ },
23
+ render: (args) => {
24
+ const [value, setValue] = useState(args.value)
25
+ const handleChange = (newValue) => {
26
+ console.log('handleChange. new value:', newValue)
27
+ setValue(parseInt(newValue))
28
+ }
29
+ return (
30
+ <NumberPicker
31
+ label={args.label}
32
+ value={value}
33
+ min={args.min}
34
+ max={args.max}
35
+ onChange={handleChange}
36
+ />
37
+ )
38
+ },
39
+ }
40
+
41
+ export const WithoutLabel = {
42
+ args: {
43
+ value: 0,
44
+ min: -10,
45
+ max: 10,
46
+ },
47
+ render: (args) => {
48
+ const [value, setValue] = useState(args.value)
49
+ const handleChange = (newValue) => {
50
+ console.log('handleChange. new value:', newValue)
51
+ setValue(parseInt(newValue))
52
+ }
53
+ return (
54
+ <NumberPicker
55
+ label={args.label}
56
+ value={value}
57
+ min={args.min}
58
+ max={args.max}
59
+ onChange={handleChange}
60
+ />
61
+ )
62
+ },
63
+ }
@@ -69,9 +69,17 @@ const ProjectItem = ({
69
69
  <ProductsBrandPattern type={type} cover={cover} size="48px" />
70
70
  </Flex>
71
71
 
72
- <Flex direction="column" gap="1" align="start" justify="center">
73
- <Text size="2" className={styles.projectTitle}>
74
- {title}
72
+ <Flex
73
+ direction="column"
74
+ gap="1"
75
+ align="start"
76
+ justify="center"
77
+ style={{ flex: 1, minWidth: 0 }}
78
+ >
79
+ <Text size="2" asChild>
80
+ <span className={styles.projectTitle}>
81
+ {title}
82
+ </span>
75
83
  </Text>
76
84
 
77
85
  {failed ? (
@@ -80,8 +88,10 @@ const ProjectItem = ({
80
88
  <Text size="1">Failed</Text>
81
89
  </Flex>
82
90
  ) : artist && (
83
- <Text size="1" className={styles.projectArtist}>
84
- {artist}
91
+ <Text size="1" asChild>
92
+ <span className={styles.projectArtist}>
93
+ {artist}
94
+ </span>
85
95
  </Text>
86
96
  )}
87
97
  </Flex>
@@ -1,10 +1,22 @@
1
1
  .projectTitle {
2
2
  color: var(--neutral-12);
3
3
  padding-right: var(--space-2);
4
+ display: block;
5
+ width: 100%;
6
+ min-width: 0;
7
+ overflow: hidden;
8
+ text-overflow: ellipsis;
9
+ white-space: nowrap;
4
10
  }
5
11
 
6
12
  .projectArtist {
7
13
  color: var(--neutral-alpha-9);
14
+ display: block;
15
+ width: 100%;
16
+ min-width: 0;
17
+ overflow: hidden;
18
+ text-overflow: ellipsis;
19
+ white-space: nowrap;
8
20
  }
9
21
 
10
22
  .projectFailed {
@@ -31,9 +31,17 @@ const ProjectTrack = ({
31
31
  <ArrowLeftIcon width={16} height={16} className={styles.iconArrowLeft} />
32
32
  </div>
33
33
 
34
- <Flex direction="column" gap="1" align="start" justify="center">
35
- <Text size="2" className={styles.trackTitle}>
36
- {title}
34
+ <Flex
35
+ direction="column"
36
+ gap="1"
37
+ align="start"
38
+ justify="center"
39
+ style={{ flex: 1, minWidth: 0 }}
40
+ >
41
+ <Text size="2" asChild>
42
+ <span className={styles.trackTitle}>
43
+ {title}
44
+ </span>
37
45
  </Text>
38
46
  </Flex>
39
47
  </Flex>
@@ -22,6 +22,12 @@
22
22
 
23
23
  .trackTitle {
24
24
  color: var(--neutral-alpha-12);
25
+ display: block;
26
+ width: 100%;
27
+ min-width: 0;
28
+ overflow: hidden;
29
+ text-overflow: ellipsis;
30
+ white-space: nowrap;
25
31
  }
26
32
 
27
33
  .icon {
@@ -32,4 +38,5 @@
32
38
  justify-content: center;
33
39
  background: var(--neutral-alpha-2);
34
40
  border-radius: var(--radius-3);
41
+ color: var(--neutral-alpha-10);
35
42
  }
@@ -0,0 +1,88 @@
1
+ import { Flex, Text } from '@radix-ui/themes'
2
+ import { useCallback, useContext, useMemo, useState } from 'react'
3
+ import { ArrowLeftIcon } from '../../../icons'
4
+ import { ProjectsListContext } from '../context'
5
+ import { NumberPicker } from '../../NumberPicker/NumberPicker'
6
+ import { UserIcon } from '../../../icons'
7
+ import styles from './ProjectTrackVoice.module.css'
8
+
9
+ const ProjectTrackVoice = ({
10
+ ...props
11
+ }) => {
12
+ const { onClickTrack } = useContext(ProjectsListContext)
13
+ const { id, title, cover, transfers, audioUrl, onChangeTransfer } = props
14
+
15
+ const hasTransfers = useMemo(() => transfers && transfers.length > 0, [transfers])
16
+
17
+ const [pitchShiftSelected, setpitchShiftSelected] = useState(hasTransfers ? parseInt(transfers?.[0]?.pitchShift ?? 0) : 0)
18
+ const min = useMemo(() => hasTransfers ? Math.min(...transfers?.map((transfer) => parseInt(transfer.pitchShift))) : 0, [transfers])
19
+ const max = useMemo(() => hasTransfers ? Math.max(...transfers?.map((transfer) => parseInt(transfer.pitchShift))) : 0, [transfers])
20
+
21
+ const getAudioUrl = useCallback((pitchShift) => {
22
+ return hasTransfers ? transfers?.find((transfer) => parseInt(transfer.pitchShift) === pitchShift)?.audioUrl : audioUrl
23
+ }, [hasTransfers, transfers, audioUrl])
24
+
25
+ const handleChangeTransfer = useCallback((value) => {
26
+ setpitchShiftSelected(value)
27
+ onChangeTransfer?.({
28
+ id,
29
+ title,
30
+ audioUrl: getAudioUrl(value),
31
+ })
32
+ }, [onChangeTransfer, id, title, transfers])
33
+
34
+ const handleClickTrack = useCallback((e) => {
35
+ e.stopPropagation()
36
+ onClickTrack?.({
37
+ id,
38
+ title,
39
+ audioUrl: getAudioUrl(pitchShiftSelected),
40
+ })
41
+ }, [onClickTrack, id, title, getAudioUrl, pitchShiftSelected])
42
+
43
+ return (
44
+ <Flex direction="column" gap="1">
45
+ <Flex
46
+ direction="row"
47
+ gap="3"
48
+ className={styles.itemTrack}
49
+ onClick={handleClickTrack}
50
+ >
51
+ <div className={styles.cover}>
52
+ <Flex className={styles.coverImage}>
53
+ {cover
54
+ ? <img src={cover} alt={title} width={48} height={48} />
55
+ : <UserIcon width={16} height={16} />
56
+ }
57
+ </Flex>
58
+ <ArrowLeftIcon width={16} height={16} className={styles.iconArrowLeft} />
59
+ </div>
60
+
61
+ <Flex
62
+ direction="column"
63
+ gap="1"
64
+ align="start"
65
+ justify="center"
66
+ style={{ flex: 1, minWidth: 0 }}
67
+ >
68
+ <Text size="2" asChild>
69
+ <span className={styles.trackTitle}>
70
+ {title}
71
+ </span>
72
+ </Text>
73
+ </Flex>
74
+
75
+ {hasTransfers && (
76
+ <NumberPicker
77
+ min={min}
78
+ max={max}
79
+ value={pitchShiftSelected}
80
+ onChange={handleChangeTransfer}
81
+ />
82
+ )}
83
+ </Flex>
84
+ </Flex>
85
+ )
86
+ }
87
+
88
+ export default ProjectTrackVoice
@@ -0,0 +1,60 @@
1
+ .itemTrack {
2
+ cursor: pointer;
3
+ border-radius: var(--radius-3);
4
+ overflow: hidden;
5
+
6
+ .iconArrowLeft {
7
+ display: none;
8
+ }
9
+
10
+ &:hover {
11
+ background: var(--neutral-alpha-2);
12
+ box-shadow: 0 24px 24px -16px rgba(0, 0, 0, 0.40);
13
+
14
+ .iconArrowLeft {
15
+ display: block;
16
+ }
17
+
18
+ .coverImage {
19
+ display: none;
20
+ }
21
+ }
22
+ }
23
+
24
+ .trackTitle {
25
+ color: var(--neutral-alpha-12);
26
+ display: block;
27
+ width: 100%;
28
+ min-width: 0;
29
+ overflow: hidden;
30
+ text-overflow: ellipsis;
31
+ white-space: nowrap;
32
+ }
33
+
34
+ .cover {
35
+ width: 48px;
36
+ height: 48px;
37
+ display: flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ background: var(--neutral-alpha-2);
41
+ border-radius: var(--radius-3);
42
+ }
43
+
44
+ .coverImage {
45
+ width: 48px;
46
+ height: 48px;
47
+ border-radius: var(--radius-3);
48
+ overflow: hidden;
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ color: var(--neutral-alpha-10);
53
+
54
+ img {
55
+ width: 100%;
56
+ height: 100%;
57
+ object-fit: cover;
58
+ pointer-events: none;
59
+ }
60
+ }
@@ -1,8 +1,9 @@
1
1
  import { Flex } from '@radix-ui/themes'
2
2
  import { useState } from 'react'
3
3
  import { ProjectsListContext } from './context'
4
- import ProjectTrack from './ProjectTrack/ProjectTrack'
5
4
  import ProjectItem from './ProjectItem/ProjectItem'
5
+ import ProjectTrack from './ProjectTrack/ProjectTrack'
6
+ import ProjectTrackVoice from './ProjectTrackVoice/ProjectTrackVoice'
6
7
 
7
8
  export const ProjectsList = ({
8
9
  children,
@@ -36,3 +37,4 @@ export const ProjectsList = ({
36
37
  }
37
38
 
38
39
  ProjectsList.Track = ProjectTrack
40
+ ProjectsList.TrackVoice = ProjectTrackVoice
@@ -1,5 +1,6 @@
1
+ import { Flex } from '@radix-ui/themes'
1
2
  import { ProjectsList } from './ProjectsList'
2
- import { projects } from './utils-stories'
3
+ import { projects, projectsVoiceStudio } from './utils-stories'
3
4
 
4
5
  export default {
5
6
  title: 'Components/ProjectsList',
@@ -28,18 +29,20 @@ export const Default = {
28
29
  },
29
30
  render: (args) => {
30
31
  return (
31
- <ProjectsList
32
- projects={args.projects}
33
- onClickTrack={args.onClickTrack}
34
- onInsertAllTracks={args.onInsertAllTracks}
35
- onProjectClick={args.onProjectClick}
36
- >
37
- {(tracks) =>
38
- tracks.map((track) => (
39
- <ProjectsList.Track key={track.id} {...track} />
40
- ))
41
- }
42
- </ProjectsList>
32
+ <Flex width="300px">
33
+ <ProjectsList
34
+ projects={args.projects}
35
+ onClickTrack={args.onClickTrack}
36
+ onInsertAllTracks={args.onInsertAllTracks}
37
+ onProjectClick={args.onProjectClick}
38
+ >
39
+ {(tracks) =>
40
+ tracks.map((track) => (
41
+ <ProjectsList.Track key={track.id} {...track} />
42
+ ))
43
+ }
44
+ </ProjectsList>
45
+ </Flex>
43
46
  )
44
47
  },
45
48
  }
@@ -74,18 +77,20 @@ export const WithEmptyProjects = {
74
77
  },
75
78
  render: (args) => {
76
79
  return (
77
- <ProjectsList
78
- projects={args.projects}
79
- onClickTrack={args.onClickTrack}
80
- onInsertAllTracks={args.onInsertAllTracks}
81
- onProjectClick={args.onProjectClick}
82
- >
83
- {(tracks) =>
84
- tracks.map((track) => (
85
- <ProjectsList.Track key={track.id} {...track} />
86
- ))
87
- }
88
- </ProjectsList>
80
+ <Flex width="300px">
81
+ <ProjectsList
82
+ projects={args.projects}
83
+ onClickTrack={args.onClickTrack}
84
+ onInsertAllTracks={args.onInsertAllTracks}
85
+ onProjectClick={args.onProjectClick}
86
+ >
87
+ {(tracks) =>
88
+ tracks.map((track) => (
89
+ <ProjectsList.Track key={track.id} {...track} />
90
+ ))
91
+ }
92
+ </ProjectsList>
93
+ </Flex>
89
94
  )
90
95
  },
91
96
  }
@@ -121,18 +126,20 @@ export const WithProjectLoading = {
121
126
  },
122
127
  render: (args) => {
123
128
  return (
124
- <ProjectsList
125
- projects={args.projects}
126
- onClickTrack={args.onClickTrack}
127
- onInsertAllTracks={args.onInsertAllTracks}
128
- onProjectClick={args.onProjectClick}
129
- >
130
- {(tracks) =>
131
- tracks.map((track) => (
132
- <ProjectsList.Track key={track.id} {...track} />
133
- ))
134
- }
135
- </ProjectsList>
129
+ <Flex width="300px">
130
+ <ProjectsList
131
+ projects={args.projects}
132
+ onClickTrack={args.onClickTrack}
133
+ onInsertAllTracks={args.onInsertAllTracks}
134
+ onProjectClick={args.onProjectClick}
135
+ >
136
+ {(tracks) =>
137
+ tracks.map((track) => (
138
+ <ProjectsList.Track key={track.id} {...track} />
139
+ ))
140
+ }
141
+ </ProjectsList>
142
+ </Flex>
136
143
  )
137
144
  },
138
145
  }
@@ -168,18 +175,61 @@ export const WithProjectFailed = {
168
175
  },
169
176
  render: (args) => {
170
177
  return (
171
- <ProjectsList
172
- projects={args.projects}
173
- onClickTrack={args.onClickTrack}
174
- onInsertAllTracks={args.onInsertAllTracks}
175
- onProjectClick={args.onProjectClick}
176
- >
177
- {(tracks) =>
178
- tracks.map((track) => (
179
- <ProjectsList.Track key={track.id} {...track} />
180
- ))
181
- }
182
- </ProjectsList>
178
+ <Flex width="300px">
179
+ <ProjectsList
180
+ projects={args.projects}
181
+ onClickTrack={args.onClickTrack}
182
+ onInsertAllTracks={args.onInsertAllTracks}
183
+ onProjectClick={args.onProjectClick}
184
+ >
185
+ {(tracks) =>
186
+ tracks.map((track) => (
187
+ <ProjectsList.Track key={track.id} {...track} />
188
+ ))
189
+ }
190
+ </ProjectsList>
191
+ </Flex>
192
+ )
193
+ },
194
+ }
195
+
196
+ export const WithTrackVoice = {
197
+ args: {
198
+ projects: projectsVoiceStudio,
199
+ onProjectClick: (project, opened) => {
200
+ console.log('project', project)
201
+ console.log('opened', opened)
202
+ },
203
+ onClickTrack: (track) => {
204
+ console.log('track', track)
205
+ },
206
+ onInsertAllTracks: (tracks) => {
207
+ console.log('insert-all-tracks', tracks)
208
+ },
209
+ onChangeTransfer: (track) => {
210
+ console.log('change-transfer', track)
211
+ },
212
+ },
213
+ render: (args) => {
214
+ return (
215
+ <Flex width="300px">
216
+ <ProjectsList
217
+ projects={args.projects}
218
+ onClickTrack={args.onClickTrack}
219
+ onInsertAllTracks={args.onInsertAllTracks}
220
+ onProjectClick={args.onProjectClick}
221
+ >
222
+ {(tracks) =>
223
+ tracks.map((track) => (
224
+ <ProjectsList.TrackVoice
225
+ key={track.id}
226
+ {...track}
227
+ onChangeTransfer={args.onChangeTransfer}
228
+ />
229
+ ))
230
+ }
231
+ </ProjectsList>
232
+ </Flex>
183
233
  )
184
234
  },
185
235
  }