@aiready/components 0.1.30 → 0.1.32

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.
Files changed (73) hide show
  1. package/README.md +2 -2
  2. package/dist/charts/ForceDirectedGraph.js +49 -13
  3. package/dist/charts/ForceDirectedGraph.js.map +1 -1
  4. package/dist/components/badge.js.map +1 -1
  5. package/dist/components/button.js.map +1 -1
  6. package/dist/components/card.js.map +1 -1
  7. package/dist/components/checkbox.js.map +1 -1
  8. package/dist/components/container.js.map +1 -1
  9. package/dist/components/grid.js.map +1 -1
  10. package/dist/components/input.d.ts +1 -2
  11. package/dist/components/input.js.map +1 -1
  12. package/dist/components/label.js +1 -8
  13. package/dist/components/label.js.map +1 -1
  14. package/dist/components/radio-group.js.map +1 -1
  15. package/dist/components/select.js.map +1 -1
  16. package/dist/components/separator.js.map +1 -1
  17. package/dist/components/stack.js.map +1 -1
  18. package/dist/components/switch.js +29 -22
  19. package/dist/components/switch.js.map +1 -1
  20. package/dist/components/textarea.d.ts +1 -2
  21. package/dist/components/textarea.js.map +1 -1
  22. package/dist/hooks/useD3.js.map +1 -1
  23. package/dist/hooks/useDebounce.js.map +1 -1
  24. package/dist/hooks/useForceSimulation.d.ts +1 -0
  25. package/dist/hooks/useForceSimulation.js +37 -14
  26. package/dist/hooks/useForceSimulation.js.map +1 -1
  27. package/dist/index.d.ts +5 -5
  28. package/dist/index.js +337 -141
  29. package/dist/index.js.map +1 -1
  30. package/dist/utils/cn.js.map +1 -1
  31. package/dist/utils/colors.js.map +1 -1
  32. package/dist/utils/formatters.js.map +1 -1
  33. package/package.json +2 -2
  34. package/src/__tests__/smoke.test.js +1 -1
  35. package/src/__tests__/smoke.test.ts +3 -3
  36. package/src/charts/ForceDirectedGraph.tsx +583 -517
  37. package/src/charts/GraphControls.tsx +5 -2
  38. package/src/charts/LinkItem.tsx +17 -5
  39. package/src/charts/NodeItem.tsx +17 -2
  40. package/src/code-block/CodeBlock.tsx +53 -16
  41. package/src/code-block/index.ts +1 -1
  42. package/src/components/badge.tsx +3 -2
  43. package/src/components/button.tsx +3 -2
  44. package/src/components/card.tsx +8 -1
  45. package/src/components/checkbox.tsx +6 -4
  46. package/src/components/container.tsx +1 -1
  47. package/src/components/grid.tsx +1 -1
  48. package/src/components/input.tsx +2 -3
  49. package/src/components/label.tsx +4 -7
  50. package/src/components/radio-group.tsx +5 -3
  51. package/src/components/select.tsx +5 -3
  52. package/src/components/separator.tsx +1 -1
  53. package/src/components/stack.tsx +1 -1
  54. package/src/components/switch.tsx +15 -7
  55. package/src/components/textarea.tsx +2 -3
  56. package/src/data-display/ScoreBar.tsx +52 -15
  57. package/src/data-display/index.ts +7 -1
  58. package/src/feedback/ErrorDisplay.tsx +17 -4
  59. package/src/feedback/LoadingSpinner.tsx +8 -3
  60. package/src/feedback/index.ts +12 -2
  61. package/src/hooks/useD3.ts +1 -3
  62. package/src/hooks/useDebounce.ts +1 -1
  63. package/src/hooks/useForceSimulation.ts +142 -44
  64. package/src/index.ts +29 -9
  65. package/src/navigation/Breadcrumb.tsx +17 -8
  66. package/src/navigation/index.ts +5 -1
  67. package/src/theme/ThemeProvider.tsx +11 -3
  68. package/src/theme/index.ts +6 -1
  69. package/src/utils/cn.ts +1 -1
  70. package/src/utils/colors.ts +1 -1
  71. package/src/utils/formatters.ts +1 -1
  72. package/src/utils/score.ts +3 -1
  73. package/tailwind.config.js +1 -1
@@ -1,2 +1,12 @@
1
- export { LoadingSpinner, LoadingOverlay, type LoadingSpinnerProps, type LoadingOverlayProps } from './LoadingSpinner';
2
- export { ErrorDisplay, EmptyState, type ErrorDisplayProps, type EmptyStateProps } from './ErrorDisplay';
1
+ export {
2
+ LoadingSpinner,
3
+ LoadingOverlay,
4
+ type LoadingSpinnerProps,
5
+ type LoadingOverlayProps,
6
+ } from './LoadingSpinner';
7
+ export {
8
+ ErrorDisplay,
9
+ EmptyState,
10
+ type ErrorDisplayProps,
11
+ type EmptyStateProps,
12
+ } from './ErrorDisplay';
@@ -59,7 +59,6 @@ export function useD3<T extends SVGSVGElement | HTMLDivElement>(
59
59
  const selection = d3.select(ref.current);
60
60
  renderFn(selection);
61
61
  }
62
- // eslint-disable-next-line react-hooks/exhaustive-deps
63
62
  }, dependencies);
64
63
 
65
64
  return ref;
@@ -118,8 +117,7 @@ export function useD3WithResize<T extends SVGSVGElement | HTMLDivElement>(
118
117
  return () => {
119
118
  resizeObserver.disconnect();
120
119
  };
121
- // eslint-disable-next-line react-hooks/exhaustive-deps
122
120
  }, dependencies);
123
121
 
124
122
  return ref;
125
- }
123
+ }
@@ -41,4 +41,4 @@ export function useDebounce<T>(value: T, delay: number = 300): T {
41
41
  }, [value, delay]);
42
42
 
43
43
  return debouncedValue;
44
- }
44
+ }
@@ -95,6 +95,13 @@ export interface ForceSimulationOptions {
95
95
  */
96
96
  stabilizeOnStop?: boolean;
97
97
 
98
+ /**
99
+ * Throttle for tick updates in milliseconds to reduce update frequency
100
+ * (helps avoid excessive React re-renders).
101
+ * @default 33
102
+ */
103
+ tickThrottleMs?: number;
104
+
98
105
  /**
99
106
  * Maximum time (ms) to allow the simulation to run after creation/restart.
100
107
  * If the simulation hasn't cooled by this time, it will be force-stopped
@@ -112,7 +119,11 @@ export interface ForceSimulationOptions {
112
119
  /**
113
120
  * Optional tick callback invoked on each simulation tick with current nodes/links and the simulation instance
114
121
  */
115
- onTick?: (nodes: SimulationNode[], links: SimulationLink[], sim: d3.Simulation<SimulationNode, SimulationLink>) => void;
122
+ onTick?: (
123
+ nodes: SimulationNode[],
124
+ links: SimulationLink[],
125
+ sim: d3.Simulation<SimulationNode, SimulationLink>
126
+ ) => void;
116
127
  }
117
128
 
118
129
  export interface UseForceSimulationReturn {
@@ -226,14 +237,11 @@ export function useForceSimulation(
226
237
  alphaTarget = 0,
227
238
  warmAlpha = 0.3,
228
239
  alphaMin = 0.01,
229
- // @ts-ignore allow extra option
230
- stabilizeOnStop = true,
231
240
  onTick,
232
241
  // Optional throttle in milliseconds for tick updates (reduce React re-renders)
233
242
  // Lower values = smoother but more CPU; default ~30ms (~33fps)
234
- // @ts-ignore allow extra option
243
+ stabilizeOnStop = true,
235
244
  tickThrottleMs = 33,
236
- // @ts-ignore allow extra option
237
245
  maxSimulationTimeMs = 3000,
238
246
  } = options;
239
247
 
@@ -242,18 +250,23 @@ export function useForceSimulation(
242
250
  const [isRunning, setIsRunning] = useState(false);
243
251
  const [alpha, setAlpha] = useState(1);
244
252
 
245
- const simulationRef = useRef<d3.Simulation<SimulationNode, SimulationLink> | null>(null);
253
+ const simulationRef = useRef<d3.Simulation<
254
+ SimulationNode,
255
+ SimulationLink
256
+ > | null>(null);
246
257
  const stopTimeoutRef = useRef<number | null>(null);
247
258
 
248
259
  // Create lightweight keys for nodes/links so we only recreate the simulation
249
260
  // when the actual identity/content of inputs change (not when parent passes
250
261
  // new array references on each render).
251
262
  const nodesKey = initialNodes.map((n) => n.id).join('|');
252
- const linksKey = (initialLinks || []).map((l) => {
253
- const s = typeof l.source === 'string' ? l.source : (l.source as any)?.id;
254
- const t = typeof l.target === 'string' ? l.target : (l.target as any)?.id;
255
- return `${s}->${t}:${(l as any).type || ''}`;
256
- }).join('|');
263
+ const linksKey = (initialLinks || [])
264
+ .map((l) => {
265
+ const s = typeof l.source === 'string' ? l.source : (l.source as any)?.id;
266
+ const t = typeof l.target === 'string' ? l.target : (l.target as any)?.id;
267
+ return `${s}->${t}:${(l as any).type || ''}`;
268
+ })
269
+ .join('|');
257
270
 
258
271
  useEffect(() => {
259
272
  // Create a copy of nodes and links to avoid mutating the original data
@@ -277,6 +290,7 @@ export function useForceSimulation(
277
290
  (n as any).vy = (Math.random() - 0.5) * 2;
278
291
  });
279
292
  } catch (e) {
293
+ void e;
280
294
  // If error, fall back to random positions
281
295
  nodesCopy.forEach((n) => {
282
296
  n.x = Math.random() * width;
@@ -287,35 +301,75 @@ export function useForceSimulation(
287
301
  }
288
302
 
289
303
  // Create the simulation
290
- const simulation = (d3.forceSimulation(nodesCopy as any) as unknown) as d3.Simulation<SimulationNode, SimulationLink>;
304
+ const simulation = d3.forceSimulation(
305
+ nodesCopy as any
306
+ ) as unknown as d3.Simulation<SimulationNode, SimulationLink>;
291
307
 
292
308
  // Configure link force separately to avoid using generic type args on d3 helpers
293
309
  try {
294
- const linkForce = (d3.forceLink(linksCopy as any) as unknown) as d3.ForceLink<SimulationNode, SimulationLink>;
295
- linkForce.id((d: any) => d.id).distance((d: any) => (d && d.distance != null ? d.distance : linkDistance)).strength(linkStrength);
310
+ const linkForce = d3.forceLink(
311
+ linksCopy as any
312
+ ) as unknown as d3.ForceLink<SimulationNode, SimulationLink>;
313
+ linkForce
314
+ .id((d: any) => d.id)
315
+ .distance((d: any) =>
316
+ d && d.distance != null ? d.distance : linkDistance
317
+ )
318
+ .strength(linkStrength);
296
319
  simulation.force('link', linkForce as any);
297
320
  } catch (e) {
321
+ void e;
298
322
  // fallback: attach a plain link force
299
- try { simulation.force('link', d3.forceLink(linksCopy as any) as any); } catch (e) {}
323
+ try {
324
+ simulation.force('link', d3.forceLink(linksCopy as any) as any);
325
+ } catch (e) {
326
+ void e;
327
+ }
300
328
  }
301
- ;
302
-
303
329
  try {
304
- simulation.force('charge', d3.forceManyBody().strength(chargeStrength) as any);
305
- simulation.force('center', d3.forceCenter(width / 2, height / 2).strength(centerStrength) as any);
306
- const collide = d3.forceCollide().radius((d: any) => {
307
- const nodeSize = (d && d.size) ? d.size : 10;
308
- return nodeSize + collisionRadius;
309
- }).strength(collisionStrength as any) as any;
330
+ simulation.force(
331
+ 'charge',
332
+ d3.forceManyBody().strength(chargeStrength) as any
333
+ );
334
+ simulation.force(
335
+ 'center',
336
+ d3.forceCenter(width / 2, height / 2).strength(centerStrength) as any
337
+ );
338
+ const collide = d3
339
+ .forceCollide()
340
+ .radius((d: any) => {
341
+ const nodeSize = d && d.size ? d.size : 10;
342
+ return nodeSize + collisionRadius;
343
+ })
344
+ .strength(collisionStrength as any) as any;
310
345
  simulation.force('collision', collide);
311
- simulation.force('x', d3.forceX(width / 2).strength(Math.max(0.02, centerStrength * 0.5)) as any);
312
- simulation.force('y', d3.forceY(height / 2).strength(Math.max(0.02, centerStrength * 0.5)) as any);
346
+ simulation.force(
347
+ 'x',
348
+ d3
349
+ .forceX(width / 2)
350
+ .strength(Math.max(0.02, centerStrength * 0.5)) as any
351
+ );
352
+ simulation.force(
353
+ 'y',
354
+ d3
355
+ .forceY(height / 2)
356
+ .strength(Math.max(0.02, centerStrength * 0.5)) as any
357
+ );
313
358
  simulation.alphaDecay(alphaDecay);
314
359
  simulation.velocityDecay(velocityDecay);
315
360
  simulation.alphaMin(alphaMin);
316
- try { simulation.alphaTarget(alphaTarget); } catch (e) {}
317
- try { simulation.alpha(warmAlpha); } catch (e) {}
361
+ try {
362
+ simulation.alphaTarget(alphaTarget);
363
+ } catch (e) {
364
+ void e;
365
+ }
366
+ try {
367
+ simulation.alpha(warmAlpha);
368
+ } catch (e) {
369
+ void e;
370
+ }
318
371
  } catch (e) {
372
+ void e;
319
373
  // ignore force configuration errors
320
374
  }
321
375
 
@@ -323,7 +377,11 @@ export function useForceSimulation(
323
377
 
324
378
  // Force-stop timeout to ensure simulation doesn't run forever.
325
379
  if (stopTimeoutRef.current != null) {
326
- try { (globalThis.clearTimeout as any)(stopTimeoutRef.current); } catch (e) {}
380
+ try {
381
+ (globalThis.clearTimeout as any)(stopTimeoutRef.current);
382
+ } catch (e) {
383
+ void e;
384
+ }
327
385
  stopTimeoutRef.current = null;
328
386
  }
329
387
  if (maxSimulationTimeMs && maxSimulationTimeMs > 0) {
@@ -339,7 +397,9 @@ export function useForceSimulation(
339
397
  }
340
398
  simulation.alpha(0);
341
399
  simulation.stop();
342
- } catch (e) {}
400
+ } catch (e) {
401
+ void e;
402
+ }
343
403
  setIsRunning(false);
344
404
  setNodes([...nodesCopy]);
345
405
  setLinks([...linksCopy]);
@@ -352,9 +412,10 @@ export function useForceSimulation(
352
412
  let lastUpdate = 0;
353
413
  const tickHandler = () => {
354
414
  try {
355
- if (typeof onTick === 'function') onTick(nodesCopy, linksCopy, simulation);
415
+ if (typeof onTick === 'function')
416
+ onTick(nodesCopy, linksCopy, simulation);
356
417
  } catch (e) {
357
- // ignore user tick errors
418
+ void e;
358
419
  }
359
420
 
360
421
  // If simulation alpha has cooled below the configured minimum, stop it to
@@ -371,7 +432,9 @@ export function useForceSimulation(
371
432
  });
372
433
  }
373
434
  simulation.stop();
374
- } catch (e) {}
435
+ } catch (e) {
436
+ void e;
437
+ }
375
438
  setAlpha(simulation.alpha());
376
439
  setIsRunning(false);
377
440
  setNodes([...nodesCopy]);
@@ -379,13 +442,16 @@ export function useForceSimulation(
379
442
  return;
380
443
  }
381
444
  } catch (e) {
382
- // ignore
445
+ void e;
383
446
  }
384
447
 
385
448
  const now = Date.now();
386
449
  const shouldUpdate = now - lastUpdate >= (tickThrottleMs as number);
387
450
  if (rafId == null && shouldUpdate) {
388
- rafId = (globalThis.requestAnimationFrame || ((cb: FrameRequestCallback) => setTimeout(cb, 16)))(() => {
451
+ rafId = (
452
+ globalThis.requestAnimationFrame ||
453
+ ((cb: FrameRequestCallback) => setTimeout(cb, 16))
454
+ )(() => {
389
455
  rafId = null;
390
456
  lastUpdate = Date.now();
391
457
  setNodes([...nodesCopy]);
@@ -406,13 +472,26 @@ export function useForceSimulation(
406
472
  return () => {
407
473
  try {
408
474
  simulation.on('tick', null as any);
409
- } catch (e) {}
475
+ } catch (e) {
476
+ void e;
477
+ }
410
478
  if (stopTimeoutRef.current != null) {
411
- try { (globalThis.clearTimeout as any)(stopTimeoutRef.current); } catch (e) {}
479
+ try {
480
+ (globalThis.clearTimeout as any)(stopTimeoutRef.current);
481
+ } catch (e) {
482
+ void e;
483
+ }
412
484
  stopTimeoutRef.current = null;
413
485
  }
414
486
  if (rafId != null) {
415
- try { (globalThis.cancelAnimationFrame || ((id: number) => clearTimeout(id)))(rafId); } catch (e) {}
487
+ try {
488
+ (
489
+ globalThis.cancelAnimationFrame ||
490
+ ((id: number) => clearTimeout(id))
491
+ )(rafId);
492
+ } catch (e) {
493
+ void e;
494
+ }
416
495
  rafId = null;
417
496
  }
418
497
  simulation.stop();
@@ -441,16 +520,29 @@ export function useForceSimulation(
441
520
  if (simulationRef.current) {
442
521
  // Reheat the simulation to a modest alpha target rather than forcing
443
522
  // full heat; this matches the Observable pattern and helps stability.
444
- try { simulationRef.current.alphaTarget(warmAlpha).restart(); } catch (e) { simulationRef.current.restart(); }
523
+ try {
524
+ simulationRef.current.alphaTarget(warmAlpha).restart();
525
+ } catch {
526
+ simulationRef.current.restart();
527
+ }
445
528
  setIsRunning(true);
446
529
  // Reset safety timeout when simulation is manually restarted
447
530
  if (stopTimeoutRef.current != null) {
448
- try { (globalThis.clearTimeout as any)(stopTimeoutRef.current); } catch (e) {}
531
+ try {
532
+ (globalThis.clearTimeout as any)(stopTimeoutRef.current);
533
+ } catch (e) {
534
+ void e;
535
+ }
449
536
  stopTimeoutRef.current = null;
450
537
  }
451
538
  if (maxSimulationTimeMs && maxSimulationTimeMs > 0) {
452
539
  stopTimeoutRef.current = (globalThis.setTimeout as any)(() => {
453
- try { simulationRef.current?.alpha(0); simulationRef.current?.stop(); } catch (e) {}
540
+ try {
541
+ simulationRef.current?.alpha(0);
542
+ simulationRef.current?.stop();
543
+ } catch (e) {
544
+ void e;
545
+ }
454
546
  setIsRunning(false);
455
547
  }, maxSimulationTimeMs) as unknown as number;
456
548
  }
@@ -464,7 +556,11 @@ export function useForceSimulation(
464
556
  }
465
557
  };
466
558
 
467
- const originalForcesRef = useRef({ charge: chargeStrength, link: linkStrength, collision: collisionStrength });
559
+ const originalForcesRef = useRef({
560
+ charge: chargeStrength,
561
+ link: linkStrength,
562
+ collision: collisionStrength,
563
+ });
468
564
  const forcesEnabledRef = useRef(true);
469
565
 
470
566
  const setForcesEnabled = (enabled: boolean) => {
@@ -486,7 +582,7 @@ export function useForceSimulation(
486
582
  link.strength(enabled ? originalForcesRef.current.link : 0);
487
583
  }
488
584
  } catch (e) {
489
- // ignore
585
+ void e;
490
586
  }
491
587
  };
492
588
 
@@ -530,7 +626,9 @@ export function useForceSimulation(
530
626
  * }
531
627
  * ```
532
628
  */
533
- export function useDrag(simulation: d3.Simulation<SimulationNode, any> | null | undefined) {
629
+ export function useDrag(
630
+ simulation: d3.Simulation<SimulationNode, any> | null | undefined
631
+ ) {
534
632
  const dragStarted = (event: any, node: SimulationNode) => {
535
633
  if (!simulation) return;
536
634
  if (!event.active) simulation.alphaTarget(0.3).restart();
@@ -555,4 +653,4 @@ export function useDrag(simulation: d3.Simulation<SimulationNode, any> | null |
555
653
  onDrag: dragged,
556
654
  onDragEnd: dragEnded,
557
655
  };
558
- }
656
+ }
package/src/index.ts CHANGED
@@ -20,19 +20,37 @@ export { Separator, type SeparatorProps } from './components/separator';
20
20
 
21
21
  // Form Components
22
22
  export { Checkbox, type CheckboxProps } from './components/checkbox';
23
- export { RadioGroup, type RadioGroupProps, type RadioOption } from './components/radio-group';
23
+ export {
24
+ RadioGroup,
25
+ type RadioGroupProps,
26
+ type RadioOption,
27
+ } from './components/radio-group';
24
28
  export { Switch, type SwitchProps } from './components/switch';
25
29
  export { Textarea, type TextareaProps } from './components/textarea';
26
- export { Select, type SelectProps, type SelectOption } from './components/select';
30
+ export {
31
+ Select,
32
+ type SelectProps,
33
+ type SelectOption,
34
+ } from './components/select';
27
35
 
28
36
  // Code Block
29
37
  export { CodeBlock, InlineCode, type CodeBlockProps } from './code-block';
30
38
 
31
39
  // Navigation
32
- export { Breadcrumb, type BreadcrumbProps, type BreadcrumbItem } from './navigation';
40
+ export {
41
+ Breadcrumb,
42
+ type BreadcrumbProps,
43
+ type BreadcrumbItem,
44
+ } from './navigation';
33
45
 
34
46
  // Data Display
35
- export { ScoreBar, ScoreCard, type ScoreBarProps, type ScoreCardProps, type ScoreRating } from './data-display';
47
+ export {
48
+ ScoreBar,
49
+ ScoreCard,
50
+ type ScoreBarProps,
51
+ type ScoreCardProps,
52
+ type ScoreRating,
53
+ } from './data-display';
36
54
 
37
55
  // Feedback
38
56
  export {
@@ -47,7 +65,12 @@ export {
47
65
  } from './feedback';
48
66
 
49
67
  // Theme
50
- export { ThemeProvider, useTheme, type Theme, type EffectiveTheme } from './theme';
68
+ export {
69
+ ThemeProvider,
70
+ useTheme,
71
+ type Theme,
72
+ type EffectiveTheme,
73
+ } from './theme';
51
74
 
52
75
  // Utils
53
76
  export { cn } from './utils/cn';
@@ -76,7 +99,4 @@ export {
76
99
  type ForceDirectedGraphHandle,
77
100
  type LayoutType,
78
101
  } from './charts/ForceDirectedGraph';
79
- export {
80
- GraphControls,
81
- type GraphControlsProps,
82
- } from './charts/GraphControls';
102
+ export { GraphControls, type GraphControlsProps } from './charts/GraphControls';
@@ -22,7 +22,11 @@ const DefaultSeparator = () => (
22
22
  strokeWidth="1.5"
23
23
  stroke="currentColor"
24
24
  >
25
- <path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
25
+ <path
26
+ strokeLinecap="round"
27
+ strokeLinejoin="round"
28
+ d="M8.25 4.5l7.5 7.5-7.5 7.5"
29
+ />
26
30
  </svg>
27
31
  );
28
32
 
@@ -30,16 +34,17 @@ export function Breadcrumb({ items, separator, className }: BreadcrumbProps) {
30
34
  const Separator = separator || <DefaultSeparator />;
31
35
 
32
36
  return (
33
- <nav className={cn('flex items-center gap-1 text-sm', className)} aria-label="Breadcrumb">
37
+ <nav
38
+ className={cn('flex items-center gap-1 text-sm', className)}
39
+ aria-label="Breadcrumb"
40
+ >
34
41
  <ol className="flex items-center gap-1">
35
42
  {items.map((item, index) => {
36
43
  const isLast = index === items.length - 1;
37
-
44
+
38
45
  return (
39
46
  <li key={index} className="flex items-center gap-1">
40
- {index > 0 && (
41
- <span className="flex-shrink-0">{Separator}</span>
42
- )}
47
+ {index > 0 && <span className="flex-shrink-0">{Separator}</span>}
43
48
  {item.href && !isLast ? (
44
49
  <a
45
50
  href={item.href}
@@ -48,7 +53,11 @@ export function Breadcrumb({ items, separator, className }: BreadcrumbProps) {
48
53
  {item.label}
49
54
  </a>
50
55
  ) : (
51
- <span className={isLast ? 'font-medium text-slate-900' : 'text-slate-600'}>
56
+ <span
57
+ className={
58
+ isLast ? 'font-medium text-slate-900' : 'text-slate-600'
59
+ }
60
+ >
52
61
  {item.label}
53
62
  </span>
54
63
  )}
@@ -58,4 +67,4 @@ export function Breadcrumb({ items, separator, className }: BreadcrumbProps) {
58
67
  </ol>
59
68
  </nav>
60
69
  );
61
- }
70
+ }
@@ -1 +1,5 @@
1
- export { Breadcrumb, type BreadcrumbProps, type BreadcrumbItem } from './Breadcrumb';
1
+ export {
2
+ Breadcrumb,
3
+ type BreadcrumbProps,
4
+ type BreadcrumbItem,
5
+ } from './Breadcrumb';
@@ -17,7 +17,9 @@ const STORAGE_KEY = 'aiready-theme';
17
17
 
18
18
  function getSystemTheme(): EffectiveTheme {
19
19
  if (typeof window === 'undefined') return 'light';
20
- return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
20
+ return window.matchMedia('(prefers-color-scheme: dark)').matches
21
+ ? 'dark'
22
+ : 'light';
21
23
  }
22
24
 
23
25
  function getStoredTheme(): Theme {
@@ -102,7 +104,13 @@ export function ThemeProvider({
102
104
  // Prevent hydration mismatch
103
105
  if (!mounted) {
104
106
  return (
105
- <ThemeContext.Provider value={{ theme: defaultTheme, setTheme: () => {}, effectiveTheme: 'light' }}>
107
+ <ThemeContext.Provider
108
+ value={{
109
+ theme: defaultTheme,
110
+ setTheme: () => {},
111
+ effectiveTheme: 'light',
112
+ }}
113
+ >
106
114
  {children}
107
115
  </ThemeContext.Provider>
108
116
  );
@@ -121,4 +129,4 @@ export function useTheme(): ThemeContextValue {
121
129
  throw new Error('useTheme must be used within a ThemeProvider');
122
130
  }
123
131
  return context;
124
- }
132
+ }
@@ -1 +1,6 @@
1
- export { ThemeProvider, useTheme, type Theme, type EffectiveTheme } from './ThemeProvider';
1
+ export {
2
+ ThemeProvider,
3
+ useTheme,
4
+ type Theme,
5
+ type EffectiveTheme,
6
+ } from './ThemeProvider';
package/src/utils/cn.ts CHANGED
@@ -8,4 +8,4 @@ import { twMerge } from 'tailwind-merge';
8
8
  */
9
9
  export function cn(...inputs: ClassValue[]) {
10
10
  return twMerge(clsx(inputs));
11
- }
11
+ }
@@ -55,4 +55,4 @@ export function hexToRgba(hex: string, alpha: number): string {
55
55
  const g = parseInt(hex.slice(3, 5), 16);
56
56
  const b = parseInt(hex.slice(5, 7), 16);
57
57
  return `rgba(${r}, ${g}, ${b}, ${alpha})`;
58
- }
58
+ }
@@ -158,4 +158,4 @@ export function formatRange(min: number, max: number): string {
158
158
  */
159
159
  export function formatDecimal(value: number, decimals: number = 2): string {
160
160
  return value.toFixed(decimals);
161
- }
161
+ }
@@ -46,7 +46,9 @@ export function scoreGlow(score: number | null | undefined): string {
46
46
  /**
47
47
  * Get rating from score (for use with ScoreBar component)
48
48
  */
49
- export function getScoreRating(score: number | null | undefined): 'excellent' | 'good' | 'fair' | 'needs-work' | 'critical' {
49
+ export function getScoreRating(
50
+ score: number | null | undefined
51
+ ): 'excellent' | 'good' | 'fair' | 'needs-work' | 'critical' {
50
52
  if (score == null) return 'critical';
51
53
  if (score >= 90) return 'excellent';
52
54
  if (score >= 75) return 'good';
@@ -43,4 +43,4 @@ export default {
43
43
  },
44
44
  },
45
45
  plugins: [],
46
- };
46
+ };