@moontra/moonui 3.3.0 → 4.0.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": "@moontra/moonui",
3
- "version": "3.3.0",
3
+ "version": "4.0.0",
4
4
  "description": "Premium React component library with modern design and customization",
5
5
  "author": "MoonUI",
6
6
  "license": "MIT",
@@ -75,9 +75,9 @@ describe('Alert Components', () => {
75
75
  it('renders info variant correctly', () => {
76
76
  render(<Alert variant="info" data-testid="alert">Test</Alert>)
77
77
  const alert = screen.getByTestId('alert')
78
- expect(alert).toHaveClass('bg-blue-500/10')
79
- expect(alert).toHaveClass('text-blue-500')
80
- expect(alert).toHaveClass('border-blue-500/30')
78
+ expect(alert).toHaveClass('bg-info/10')
79
+ expect(alert).toHaveClass('text-info')
80
+ expect(alert).toHaveClass('border-info/30')
81
81
  })
82
82
 
83
83
  it('uses default variant as default', () => {
@@ -222,7 +222,7 @@ describe('Alert Components', () => {
222
222
  const alert = screen.getByTestId('alert')
223
223
  const closeButton = alert.querySelector('button')
224
224
  expect(closeButton).toBeInTheDocument()
225
- expect(closeButton).toHaveAttribute('aria-label', 'Kapat')
225
+ expect(closeButton).toHaveAttribute('aria-label', 'Close alert')
226
226
  })
227
227
 
228
228
  it('does not render close button when closable is true but onClose is not provided', () => {
@@ -281,7 +281,7 @@ describe('Alert Components', () => {
281
281
  render(<Alert closable onClose={handleClose} data-testid="alert">Test</Alert>)
282
282
  const alert = screen.getByTestId('alert')
283
283
  const closeButton = alert.querySelector('button')
284
- expect(closeButton).toHaveAttribute('aria-label', 'Kapat')
284
+ expect(closeButton).toHaveAttribute('aria-label', 'Close alert')
285
285
  })
286
286
  })
287
287
  })
@@ -300,8 +300,8 @@ describe('Avatar Component', () => {
300
300
  <Avatar key="5"><AvatarFallback>A5</AvatarFallback></Avatar>,
301
301
  ]
302
302
 
303
- it('renders all avatars when no limit is set', () => {
304
- render(<AvatarGroup avatars={mockAvatars} />)
303
+ it('renders all avatars when no max is set', () => {
304
+ render(<AvatarGroup>{mockAvatars}</AvatarGroup>)
305
305
  expect(screen.getByText('A1')).toBeInTheDocument()
306
306
  expect(screen.getByText('A2')).toBeInTheDocument()
307
307
  expect(screen.getByText('A3')).toBeInTheDocument()
@@ -309,8 +309,8 @@ describe('Avatar Component', () => {
309
309
  expect(screen.getByText('A5')).toBeInTheDocument()
310
310
  })
311
311
 
312
- it('limits avatars when limit is set', () => {
313
- render(<AvatarGroup avatars={mockAvatars} limit={3} />)
312
+ it('limits avatars when max is set', () => {
313
+ render(<AvatarGroup max={3}>{mockAvatars}</AvatarGroup>)
314
314
  expect(screen.getByText('A1')).toBeInTheDocument()
315
315
  expect(screen.getByText('A2')).toBeInTheDocument()
316
316
  expect(screen.getByText('A3')).toBeInTheDocument()
@@ -318,31 +318,31 @@ describe('Avatar Component', () => {
318
318
  expect(screen.queryByText('A5')).not.toBeInTheDocument()
319
319
  })
320
320
 
321
- it('shows remaining count when limit is exceeded', () => {
322
- render(<AvatarGroup avatars={mockAvatars} limit={3} />)
321
+ it('shows remaining count when max is exceeded', () => {
322
+ render(<AvatarGroup max={3}>{mockAvatars}</AvatarGroup>)
323
323
  expect(screen.getByText('+2')).toBeInTheDocument()
324
324
  })
325
325
 
326
326
  it('applies custom className', () => {
327
- render(<AvatarGroup avatars={mockAvatars} className="custom-group" />)
327
+ render(<AvatarGroup className="custom-group">{mockAvatars}</AvatarGroup>)
328
328
  const group = screen.getByText('A1').closest('.custom-group')
329
329
  expect(group).toBeInTheDocument()
330
330
  })
331
331
 
332
332
  it('forwards ref correctly', () => {
333
333
  const ref = React.createRef<HTMLDivElement>()
334
- render(<AvatarGroup ref={ref} avatars={mockAvatars} />)
334
+ render(<AvatarGroup ref={ref}>{mockAvatars}</AvatarGroup>)
335
335
  expect(ref.current).toBeInstanceOf(HTMLDivElement)
336
336
  })
337
337
 
338
338
  it('applies custom overlap offset', () => {
339
- render(<AvatarGroup avatars={mockAvatars} overlapOffset={-12} />)
339
+ render(<AvatarGroup overlapOffset={-12}>{mockAvatars}</AvatarGroup>)
340
340
  // This test verifies the component renders without error with custom offset
341
341
  expect(screen.getByText('A1')).toBeInTheDocument()
342
342
  })
343
343
 
344
- it('handles empty avatars array', () => {
345
- render(<AvatarGroup avatars={[]} data-testid="avatar-group" />)
344
+ it('handles empty children', () => {
345
+ render(<AvatarGroup data-testid="avatar-group" />)
346
346
  const group = screen.getByTestId('avatar-group')
347
347
  expect(group).toBeInTheDocument()
348
348
  expect(group).toHaveClass('flex')
@@ -351,7 +351,7 @@ describe('Avatar Component', () => {
351
351
 
352
352
  it('handles single avatar', () => {
353
353
  const singleAvatar = [<Avatar key="1"><AvatarFallback>SA</AvatarFallback></Avatar>]
354
- render(<AvatarGroup avatars={singleAvatar} />)
354
+ render(<AvatarGroup>{singleAvatar}</AvatarGroup>)
355
355
  expect(screen.getByText('SA')).toBeInTheDocument()
356
356
  expect(screen.queryByText('+')).not.toBeInTheDocument()
357
357
  })
@@ -357,8 +357,24 @@ describe('Badge Component', () => {
357
357
 
358
358
  const badge = screen.getByText('Focusable').parentElement!
359
359
  fireEvent.focus(badge)
360
-
360
+
361
361
  expect(onFocus).toHaveBeenCalledTimes(1)
362
362
  })
363
363
  })
364
+
365
+ describe('forwardRef (#261)', () => {
366
+ it('ref kök elemana iletilir', () => {
367
+ // Regresyon: Badge düz `function Badge(...)` idi — batch'teki diğer 7
368
+ // bileşen forwardRef kullanırken Badge ref alamıyordu.
369
+ const ref = React.createRef<HTMLDivElement>()
370
+ render(<Badge ref={ref}>Etiket</Badge>)
371
+
372
+ expect(ref.current).toBeInstanceOf(HTMLDivElement)
373
+ expect(ref.current).toHaveTextContent('Etiket')
374
+ })
375
+
376
+ it('displayName tanımlı', () => {
377
+ expect(Badge.displayName).toBe('Badge')
378
+ })
379
+ })
364
380
  })
@@ -193,22 +193,28 @@ describe('Checkbox Components', () => {
193
193
  it('renders indeterminate state correctly', () => {
194
194
  render(<Checkbox indeterminate data-testid="checkbox" />)
195
195
  const checkbox = screen.getByTestId('checkbox')
196
- expect(checkbox).toHaveAttribute('aria-checked', 'false')
197
- expect(checkbox).toHaveAttribute('data-state', 'unchecked')
196
+ // Radix'in "indeterminate" CheckedState'i `aria-checked="mixed"` üretir —
197
+ // ekran okuyucu "kısmen seçili" durumunu ancak böyle duyurabilir.
198
+ expect(checkbox).toHaveAttribute('aria-checked', 'mixed')
199
+ expect(checkbox).toHaveAttribute('data-state', 'indeterminate')
198
200
  })
199
201
 
200
202
  it('shows minus icon when indeterminate and checked', () => {
201
203
  render(<Checkbox indeterminate checked data-testid="checkbox" />)
202
204
  const checkbox = screen.getByTestId('checkbox')
203
- // Even with checked=true, indeterminate overrides to false
204
- expect(checkbox).toHaveAttribute('aria-checked', 'false')
205
- expect(checkbox).toHaveAttribute('data-state', 'unchecked')
205
+ // indeterminate, checked'i ezer: durum "mixed" olur.
206
+ expect(checkbox).toHaveAttribute('aria-checked', 'mixed')
207
+ expect(checkbox).toHaveAttribute('data-state', 'indeterminate')
208
+ // Radix Indicator yalnızca checked VEYA indeterminate durumda render edilir.
209
+ // Eskiden state "unchecked" kaldığı için Minus ikonu hiç görünmüyordu —
210
+ // bu assertion o regresyonu bir daha geçirmez.
211
+ expect(checkbox.querySelector('svg')).toBeInTheDocument()
206
212
  })
207
213
 
208
214
  it('overrides checked state when indeterminate', () => {
209
215
  render(<Checkbox checked indeterminate data-testid="checkbox" />)
210
216
  const checkbox = screen.getByTestId('checkbox')
211
- expect(checkbox).toHaveAttribute('aria-checked', 'false')
217
+ expect(checkbox).toHaveAttribute('aria-checked', 'mixed')
212
218
  })
213
219
 
214
220
  it('updates indeterminate state via prop', () => {
@@ -218,7 +224,7 @@ describe('Checkbox Components', () => {
218
224
 
219
225
  rerender(<Checkbox indeterminate={true} data-testid="checkbox" />)
220
226
  checkbox = screen.getByTestId('checkbox')
221
- expect(checkbox).toHaveAttribute('aria-checked', 'false')
227
+ expect(checkbox).toHaveAttribute('aria-checked', 'mixed')
222
228
  })
223
229
  })
224
230
 
@@ -244,12 +250,10 @@ describe('Checkbox Components', () => {
244
250
  />
245
251
  )
246
252
  expect(screen.queryByTestId('custom-icon')).not.toBeInTheDocument()
247
-
253
+
248
254
  const checkbox = screen.getByTestId('checkbox')
249
- // Check that custom icon is not rendered
250
- expect(screen.queryByTestId('custom-icon')).not.toBeInTheDocument()
251
- // Indeterminate state should show as unchecked
252
- expect(checkbox).toHaveAttribute('aria-checked', 'false')
255
+ // indeterminate, özel ikonu bastırır ve durumu "mixed" yapar.
256
+ expect(checkbox).toHaveAttribute('aria-checked', 'mixed')
253
257
  })
254
258
  })
255
259