@moises.ai/design-system 3.9.14 → 3.9.16

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.9.14",
3
+ "version": "3.9.16",
4
4
  "description": "Design System package based on @radix-ui/themes with custom defaults",
5
5
  "private": false,
6
6
  "type": "module",
@@ -23,7 +23,12 @@
23
23
  position: absolute;
24
24
  top: 4px;
25
25
  right: 4px;
26
-
26
+
27
+
28
+ width: 24px;
29
+ height: 24px;
30
+ border-radius: 50% !important;
31
+ background: #11111366 !important;
27
32
  }
28
33
 
29
34
  .children {
@@ -27,23 +27,25 @@ const withFlexContainer = (Story) => (
27
27
 
28
28
  export const FeatureAnnouncement = {
29
29
  render: (args) => (
30
- <BannerAnnouncement {...args}>
31
- <Flex direction="column" gap="2">
32
- <Heading size="3" weight="bold">
33
- Moises AI Studio
34
- </Heading>
35
- <Text size="2">
36
- Step into the future of music creation. Record, separate, generate,
37
- convert voice, mix, and master with our all-in-one essential AI tool
38
- for musicians.
39
- </Text>
40
- </Flex>
41
- </BannerAnnouncement>
30
+ <Flex justify="center" align="center" style={{ padding: '40px', marginTop: '100px' }}>
31
+ <BannerAnnouncement {...args}>
32
+ <Flex direction="column" gap="2">
33
+ <Heading size="3" weight="bold">
34
+ Moises AI Studio
35
+ </Heading>
36
+ <Text size="2">
37
+ Step into the future of music creation. Record, separate, generate,
38
+ convert voice, mix, and master with our all-in-one essential AI tool
39
+ for musicians.
40
+ </Text>
41
+ </Flex>
42
+ </BannerAnnouncement>
43
+ </Flex>
42
44
  ),
43
45
  args: {
44
46
  badge: { label: 'New', color: 'green' },
45
47
  image:
46
- 'https://storage.googleapis.com/moises-cms/1_day_discount_banner_2d5990f994/1_day_discount_banner_2d5990f994.png',
48
+ 'https://storage.googleapis.com/moises-cms/image_3x_f0971a1e8e/image_3x_f0971a1e8e.png',
47
49
  link: 'https://www.google.com',
48
50
  buttonText: 'Learn More',
49
51
  buttonColor: 'gray',
@@ -92,21 +94,23 @@ export const DayOne = {
92
94
  }, [])
93
95
 
94
96
  return (
95
- <BannerAnnouncement {...args}>
96
- <Flex direction="column" gap="3">
97
- <Text size="2">Up to 30% off any individual plan for the next:</Text>
98
- <Countdown
99
- show={true}
100
- days={timeLeft.days}
101
- hours={timeLeft.hours}
102
- minutes={timeLeft.minutes}
103
- seconds={timeLeft.seconds}
104
- theme="default"
105
- variant="lg"
106
- showDays={false}
107
- />
108
- </Flex>
109
- </BannerAnnouncement>
97
+ <Flex justify="center" align="center" style={{ padding: '40px', marginTop: '100px' }}>
98
+ <BannerAnnouncement {...args}>
99
+ <Flex direction="column" gap="3">
100
+ <Text size="2">Up to 30% off any individual plan for the next:</Text>
101
+ <Countdown
102
+ show={true}
103
+ days={timeLeft.days}
104
+ hours={timeLeft.hours}
105
+ minutes={timeLeft.minutes}
106
+ seconds={timeLeft.seconds}
107
+ theme="default"
108
+ variant="lg"
109
+ showDays={false}
110
+ />
111
+ </Flex>
112
+ </BannerAnnouncement>
113
+ </Flex>
110
114
  )
111
115
  },
112
116
  args: {
@@ -1,16 +1,16 @@
1
- import React from 'react'
1
+ import { StarFilledIcon, StarIcon } from '@radix-ui/react-icons'
2
2
  import {
3
- RadioCards,
4
- Flex,
5
3
  Avatar,
6
4
  Box,
7
- Text,
5
+ Flex,
6
+ RadioCards,
8
7
  ScrollArea,
8
+ Text,
9
9
  } from '@radix-ui/themes'
10
- import styles from './ListCards.module.css'
11
10
  import classNames from 'classnames'
12
- import { StarIcon, StarFilledIcon } from '@radix-ui/react-icons'
11
+ import React from 'react'
13
12
  import { ThumbnailPicker } from '../ThumbnailPicker/ThumbnailPicker'
13
+ import styles from './ListCards.module.css'
14
14
 
15
15
  const Card = ({
16
16
  className,
@@ -25,6 +25,7 @@ const Card = ({
25
25
  checked,
26
26
  onClick,
27
27
  size = '1',
28
+ style,
28
29
  ...props
29
30
  }) => {
30
31
  // Use item properties if the item object is provided
@@ -63,7 +64,7 @@ const Card = ({
63
64
  styles.listCardsItem,
64
65
  styles[`listCardsItemSize${size}`],
65
66
  )}
66
- style={{ '--color-surface': 'transparent' }}
67
+ style={{ '--color-surface': 'transparent', ...style }}
67
68
  data-state={checked ? 'checked' : 'unchecked'}
68
69
  onClick={handleClick}
69
70
  {...props}
@@ -138,6 +139,7 @@ const CardDetails = ({
138
139
  avatarContent,
139
140
  seeDetailsText = 'Details',
140
141
  children,
142
+ style,
141
143
  ...props
142
144
  }) => {
143
145
  // Use item properties if the item object is provided
@@ -160,6 +162,7 @@ const CardDetails = ({
160
162
  '--color-surface': 'transparent',
161
163
  width: '100%',
162
164
  height: '68px',
165
+ ...style,
163
166
  }}
164
167
  {...props}
165
168
  >
@@ -269,6 +272,7 @@ export const ListCards = ({
269
272
  className,
270
273
  children,
271
274
  alwaysShowScrollbar = true,
275
+ style,
272
276
  ...props
273
277
  }) => {
274
278
  return (
@@ -278,7 +282,7 @@ export const ListCards = ({
278
282
  scrollbars="vertical"
279
283
  type={alwaysShowScrollbar ? 'auto' : 'hover'}
280
284
  >
281
- <Box className={styles.gridContainer} pr="3">
285
+ <Box className={styles.gridContainer} pr="3" style={style}>
282
286
  <RadioCards.Root
283
287
  defaultValue={undefined}
284
288
  className={className}
@@ -1,5 +1,5 @@
1
- import { useState, useCallback, useRef, useEffect } from 'react'
2
- import { Text, Flex } from '../../index'
1
+ import { useCallback, useEffect, useRef, useState } from 'react'
2
+ import { Flex, Text } from '../../index'
3
3
 
4
4
  /**
5
5
  * @typedef {import('zod').ZodObject} ZodSchema
@@ -55,13 +55,17 @@ import { Text, Flex } from '../../index'
55
55
 
56
56
  /** @param {{ name: string, errorsRef: React.MutableRefObject<Object>, children: React.ReactNode }} props */
57
57
  function FieldView({ name, errorsRef, children }) {
58
- const msg = errorsRef.current[name]
59
- return (
60
- <Flex direction="column" gap="1">
61
- {children}
62
- {msg && <Text size="1" color="red">{msg}</Text>}
63
- </Flex>
64
- )
58
+ const msg = errorsRef.current[name]
59
+ return (
60
+ <Flex direction="column" gap="1">
61
+ {children}
62
+ {msg && (
63
+ <Text size="1" color="red">
64
+ {msg}
65
+ </Text>
66
+ )}
67
+ </Flex>
68
+ )
65
69
  }
66
70
 
67
71
  /**
@@ -97,108 +101,130 @@ function FieldView({ name, errorsRef, children }) {
97
101
  * }
98
102
  */
99
103
  export function useForm({ schema }) {
100
- const [values, setValues] = useState(() => schema.parse({}))
101
- const [errors, setErrors] = useState({})
102
- const errorsRef = useRef(errors)
103
- errorsRef.current = errors
104
- const listenersRef = useRef([])
105
-
106
- const mountedRef = useRef(false)
107
- useEffect(() => {
108
- if (!mountedRef.current) {
109
- mountedRef.current = true
110
- return
111
- }
112
- for (const cb of listenersRef.current) cb(values)
113
- }, [values])
114
-
115
- /** @type {(name: string, value: *) => void} */
116
- const set = useCallback((name, value) => {
117
- setValues((prev) => ({ ...prev, [name]: value }))
118
- setErrors((prev) => ({ ...prev, [name]: null }))
119
- }, [])
120
-
121
- /**
122
- * Returns spread-ready props for a form control.
123
- *
124
- * - Default (no type): returns `{ value, onChange }` for text inputs and selects.
125
- * - `'checkbox'` / `'switch'`: returns `{ checked, onCheckedChange }`.
126
- *
127
- * @param {string} name - Field name matching a key in the schema.
128
- * @param {ToggleFieldType} [type] - Control type hint.
129
- * @returns {TextFieldProps | ToggleFieldProps}
130
- */
131
- const connectField = (name, type) => {
132
- const val = values[name]
133
- const update = (v) => set(name, v)
134
- if (type === 'checkbox' || type === 'switch') {
135
- return { checked: !!val, onCheckedChange: update }
136
- }
137
- return { value: val ?? '', onChange: (e) => update(e?.target?.value ?? e) }
104
+ const [values, setValues] = useState(() => schema.parse({}))
105
+ const [errors, setErrors] = useState({})
106
+ const errorsRef = useRef(errors)
107
+ errorsRef.current = errors
108
+ const listenersRef = useRef([])
109
+
110
+ const mountedRef = useRef(false)
111
+ useEffect(() => {
112
+ if (!mountedRef.current) {
113
+ mountedRef.current = true
114
+ return
138
115
  }
139
-
140
- /**
141
- * Validate the current values against the schema.
142
- *
143
- * @returns {FormResult} `{ isValid: true, data }` on success, or
144
- * `{ isValid: false, data }` on failure (with field errors set).
145
- */
146
- const getValues = () => {
147
- const result = schema.safeParse(values)
148
- if (result.success) {
149
- setErrors({})
150
- return { isValid: true, data: result.data }
151
- }
152
- const fieldErrors = {}
153
- for (const issue of result.error.issues) {
154
- const name = issue.path.join('.')
155
- if (!fieldErrors[name]) fieldErrors[name] = issue.message
156
- }
157
- setErrors(fieldErrors)
158
- return { isValid: false, data: values }
116
+ for (const cb of listenersRef.current) cb(values)
117
+ }, [values])
118
+
119
+ /** @type {((name: string, value: *) => void) | ((values: Object) => void)} */
120
+ const set = useCallback((name, value) => {
121
+ if (typeof name === 'string') {
122
+ setValues((prev) => ({ ...prev, [name]: value }))
123
+ setErrors((prev) => ({ ...prev, [name]: null }))
159
124
  }
160
125
 
161
- /**
162
- * Subscribe to value changes. The callback fires after every state
163
- * update (skipping the initial mount).
164
- *
165
- * @param {(values: Object) => void} cb - Listener called with the latest values.
166
- * @returns {() => void} Unsubscribe function (safe to return from `useEffect`).
167
- */
168
- const watchValues = useCallback((cb) => {
169
- listenersRef.current.push(cb)
170
- return () => {
171
- listenersRef.current = listenersRef.current.filter((l) => l !== cb)
172
- }
173
- }, [])
174
-
175
- /**
176
- * Returns the error message element for a field, or `null` if valid.
177
- *
178
- * @param {string} name - Field name.
179
- * @returns {React.ReactNode | null}
180
- */
181
- const error = (name) => {
182
- const msg = errors[name]
183
- if (!msg) return null
184
- return <Text size="1" color="red">{msg}</Text>
126
+ const values = name
127
+ const errors = Object.fromEntries(
128
+ Object.entries(values).map(([key]) => ({ [key]: null })),
129
+ )
130
+ setValues((prev) => ({ ...prev, ...values }))
131
+ setErrors((prev) => ({ ...prev, ...errors }))
132
+ }, [])
133
+
134
+ /**
135
+ * Returns spread-ready props for a form control.
136
+ *
137
+ * - Default (no type): returns `{ value, onChange }` for text inputs and selects.
138
+ * - `'checkbox'` / `'switch'`: returns `{ checked, onCheckedChange }`.
139
+ *
140
+ * @param {string} name - Field name matching a key in the schema.
141
+ * @param {ToggleFieldType} [type] - Control type hint.
142
+ * @returns {TextFieldProps | ToggleFieldProps}
143
+ */
144
+ const connectField = (name, type) => {
145
+ const val = values[name]
146
+ const update = (v) => set(name, v)
147
+ if (type === 'checkbox' || type === 'switch') {
148
+ return { checked: !!val, onCheckedChange: update }
185
149
  }
186
-
187
- /**
188
- * Reset all values and clear errors.
189
- *
190
- * @param {Object} [vals] - Optional values to reset to. Defaults to schema defaults.
191
- */
192
- const reset = (vals) => {
193
- setValues(vals ?? schema.parse({}))
194
- setErrors({})
150
+ return { value: val ?? '', onChange: (e) => update(e?.target?.value ?? e) }
151
+ }
152
+
153
+ /**
154
+ * Validate the current values against the schema.
155
+ *
156
+ * @returns {FormResult} `{ isValid: true, data }` on success, or
157
+ * `{ isValid: false, data }` on failure (with field errors set).
158
+ */
159
+ const getValues = () => {
160
+ const result = schema.safeParse(values)
161
+ if (result.success) {
162
+ setErrors({})
163
+ return { isValid: true, data: result.data }
195
164
  }
196
-
197
- /** @type {React.FC<FieldProps>} */
198
- const Field = useCallback(
199
- (props) => <FieldView {...props} errorsRef={errorsRef} />,
200
- []
165
+ const fieldErrors = {}
166
+ for (const issue of result.error.issues) {
167
+ const name = issue.path.join('.')
168
+ if (!fieldErrors[name]) fieldErrors[name] = issue.message
169
+ }
170
+ setErrors(fieldErrors)
171
+ return { isValid: false, data: values }
172
+ }
173
+
174
+ /**
175
+ * Subscribe to value changes. The callback fires after every state
176
+ * update (skipping the initial mount).
177
+ *
178
+ * @param {(values: Object) => void} cb - Listener called with the latest values.
179
+ * @returns {() => void} Unsubscribe function (safe to return from `useEffect`).
180
+ */
181
+ const watchValues = useCallback((cb) => {
182
+ listenersRef.current.push(cb)
183
+ return () => {
184
+ listenersRef.current = listenersRef.current.filter((l) => l !== cb)
185
+ }
186
+ }, [])
187
+
188
+ /**
189
+ * Returns the error message element for a field, or `null` if valid.
190
+ *
191
+ * @param {string} name - Field name.
192
+ * @returns {React.ReactNode | null}
193
+ */
194
+ const error = (name) => {
195
+ const msg = errors[name]
196
+ if (!msg) return null
197
+ return (
198
+ <Text size="1" color="red">
199
+ {msg}
200
+ </Text>
201
201
  )
202
-
203
- return { connectField, Field, error, values, set, reset, getValues, watchValues }
202
+ }
203
+
204
+ /**
205
+ * Reset all values and clear errors.
206
+ *
207
+ * @param {Object} [vals] - Optional values to reset to. Defaults to schema defaults.
208
+ */
209
+ const reset = (vals) => {
210
+ setValues(vals ?? schema.parse({}))
211
+ setErrors({})
212
+ }
213
+
214
+ /** @type {React.FC<FieldProps>} */
215
+ const Field = useCallback(
216
+ (props) => <FieldView {...props} errorsRef={errorsRef} />,
217
+ [],
218
+ )
219
+
220
+ return {
221
+ connectField,
222
+ Field,
223
+ error,
224
+ values,
225
+ set,
226
+ reset,
227
+ getValues,
228
+ watchValues,
229
+ }
204
230
  }