trix-ui 0.2.0 → 0.2.2

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 (84) hide show
  1. package/README.md +110 -19
  2. package/dist/commands/add/__tests__/add.test.js +18 -6
  3. package/dist/commands/add/__tests__/add.test.js.map +1 -1
  4. package/dist/commands/add/analysis.js +6 -1
  5. package/dist/commands/add/analysis.js.map +1 -1
  6. package/dist/commands/add/command.js +6 -0
  7. package/dist/commands/add/command.js.map +1 -1
  8. package/dist/commands/add/types.d.ts +1 -0
  9. package/dist/commands/add/ui.js +4 -0
  10. package/dist/commands/add/ui.js.map +1 -1
  11. package/dist/commands/add-composite.d.ts +2 -0
  12. package/dist/commands/add-composite.js +202 -0
  13. package/dist/commands/add-composite.js.map +1 -0
  14. package/dist/commands/add-section.js +6 -0
  15. package/dist/commands/add-section.js.map +1 -1
  16. package/dist/commands/add-wrapper.js +7 -1
  17. package/dist/commands/add-wrapper.js.map +1 -1
  18. package/dist/commands/doctor.js +9 -4
  19. package/dist/commands/doctor.js.map +1 -1
  20. package/dist/commands/init/config.js +1 -0
  21. package/dist/commands/init/config.js.map +1 -1
  22. package/dist/commands/list-sections.js +2 -7
  23. package/dist/commands/list-sections.js.map +1 -1
  24. package/dist/commands/list-wrappers.js +2 -7
  25. package/dist/commands/list-wrappers.js.map +1 -1
  26. package/dist/commands/list.js +51 -8
  27. package/dist/commands/list.js.map +1 -1
  28. package/dist/commands/remove-section.js +9 -34
  29. package/dist/commands/remove-section.js.map +1 -1
  30. package/dist/commands/remove-wrapper.js +9 -34
  31. package/dist/commands/remove-wrapper.js.map +1 -1
  32. package/dist/commands/remove.js +71 -38
  33. package/dist/commands/remove.js.map +1 -1
  34. package/dist/commands/shared/add-collection.d.ts +2 -1
  35. package/dist/commands/shared/add-collection.js +10 -13
  36. package/dist/commands/shared/add-collection.js.map +1 -1
  37. package/dist/commands/shared/list-entries.d.ts +6 -0
  38. package/dist/commands/shared/list-entries.js +13 -0
  39. package/dist/commands/shared/list-entries.js.map +1 -0
  40. package/dist/commands/shared/name-utils.d.ts +1 -0
  41. package/dist/commands/shared/name-utils.js +14 -0
  42. package/dist/commands/shared/name-utils.js.map +1 -0
  43. package/dist/commands/shared/remove-entries.d.ts +16 -0
  44. package/dist/commands/shared/remove-entries.js +42 -0
  45. package/dist/commands/shared/remove-entries.js.map +1 -0
  46. package/dist/index.js +11 -8
  47. package/dist/index.js.map +1 -1
  48. package/dist/lib/config.d.ts +1 -0
  49. package/dist/lib/config.js +1 -0
  50. package/dist/lib/config.js.map +1 -1
  51. package/dist/lib/install.js +14 -7
  52. package/dist/lib/install.js.map +1 -1
  53. package/dist/lib/lockfile.d.ts +6 -5
  54. package/dist/lib/lockfile.js +26 -7
  55. package/dist/lib/lockfile.js.map +1 -1
  56. package/dist/lib/paths.d.ts +1 -0
  57. package/dist/lib/paths.js +1 -0
  58. package/dist/lib/paths.js.map +1 -1
  59. package/dist/lib/registry.d.ts +3 -0
  60. package/dist/lib/registry.js +15 -0
  61. package/dist/lib/registry.js.map +1 -1
  62. package/package.json +12 -12
  63. package/registry/index.json +67 -128
  64. package/templates/components/ui/avatar.tsx +109 -0
  65. package/templates/components/ui/button.tsx +48 -44
  66. package/templates/components/ui/label.tsx +24 -0
  67. package/templates/composites/feature-collection-card.tsx +113 -0
  68. package/templates/composites/music-player-card.tsx +221 -0
  69. package/templates/composites/user-profile-card.tsx +145 -0
  70. package/templates/sections/modern-hero.tsx +1226 -0
  71. package/templates/wrappers/Interative-wrapper.tsx +555 -0
  72. package/LICENSE.md +0 -21
  73. package/templates/components/ui/checkbox.tsx +0 -33
  74. package/templates/components/ui/dialog.tsx +0 -92
  75. package/templates/components/ui/dropdown.tsx +0 -75
  76. package/templates/components/ui/select.tsx +0 -24
  77. package/templates/components/ui/switch.tsx +0 -27
  78. package/templates/components/ui/toast.tsx +0 -100
  79. package/templates/sections/cta.tsx +0 -22
  80. package/templates/sections/feature-grid.tsx +0 -62
  81. package/templates/sections/hero.tsx +0 -63
  82. package/templates/wrappers/border-wrapper.tsx +0 -34
  83. package/templates/wrappers/glow-wrapper.tsx +0 -31
  84. package/templates/wrappers/lift-wrapper.tsx +0 -27
@@ -0,0 +1,555 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { Slot } from "@radix-ui/react-slot";
5
+ import { cn } from "../../lib/utils";
6
+
7
+ type AnyElement = HTMLElement;
8
+
9
+ function composeRefs<T>(...refs: Array<React.Ref<T> | undefined>) {
10
+ return (node: T) => {
11
+ for (const ref of refs) {
12
+ if (!ref) continue;
13
+ if (typeof ref === "function") ref(node);
14
+ else (ref as React.MutableRefObject<T | null>).current = node;
15
+ }
16
+ };
17
+ }
18
+
19
+ function usePrefersReducedMotion() {
20
+ const [reduced, setReduced] = React.useState(false);
21
+
22
+ React.useEffect(() => {
23
+ if (typeof window === "undefined") return;
24
+ const media = window.matchMedia("(prefers-reduced-motion: reduce)");
25
+ const onChange = () => setReduced(media.matches);
26
+ onChange();
27
+ media.addEventListener?.("change", onChange);
28
+ return () => media.removeEventListener?.("change", onChange);
29
+ }, []);
30
+
31
+ return reduced;
32
+ }
33
+
34
+ const clamp = (v: number, min: number, max: number) =>
35
+ Math.max(min, Math.min(max, v));
36
+
37
+ const lerp = (a: number, b: number, t: number) => a + (b - a) * t;
38
+
39
+ export type InteractiveWrapProps = {
40
+ asChild?: boolean;
41
+
42
+ /** Disable all interactions */
43
+ disabled?: boolean;
44
+
45
+ /** Press animation (scale) */
46
+ press?: boolean;
47
+
48
+ /** Cursor-follow glow */
49
+ hoverGlow?: boolean;
50
+
51
+ /** Magnetic hover pull */
52
+ magnetic?: boolean;
53
+
54
+ /** Focus ring when any child inside gets focus */
55
+ focusRing?: boolean;
56
+
57
+ /** Clip glow + children to wrapper bounds */
58
+ clip?: boolean;
59
+
60
+ /** Press scale (default 0.98) */
61
+ pressScale?: number;
62
+
63
+ /**
64
+ * Magnetic strength (0 to 1)
65
+ * Recommended range: 0.15 to 0.45
66
+ */
67
+ magneticStrength?: number;
68
+
69
+ /** Max translate in px when magnetic is enabled (default 14) */
70
+ magneticMaxTranslate?: number;
71
+
72
+ /**
73
+ * Smoothing factor for magnetic movement (0..1)
74
+ * Higher = snappier, lower = smoother. Default 0.18
75
+ */
76
+ magneticDamping?: number;
77
+
78
+ /**
79
+ * Glow radius in px
80
+ * Recommended: 180 - 320
81
+ */
82
+ glowSize?: number;
83
+
84
+ /**
85
+ * Glow opacity (0 to 1)
86
+ * Recommended: 0.25 - 0.65
87
+ */
88
+ glowOpacity?: number;
89
+
90
+ /**
91
+ * Glow color (solid color is best)
92
+ * Example: "rgba(124, 58, 237, 1)"
93
+ */
94
+ glowColor?: string;
95
+
96
+ /**
97
+ * Smoothness for glow follow (0..1)
98
+ * Higher = snappier, lower = smoother. Default 0.28
99
+ */
100
+ glowDamping?: number;
101
+
102
+ /** Blend mode for glow layer (default "screen") */
103
+ glowBlendMode?: React.CSSProperties["mixBlendMode"];
104
+
105
+ /**
106
+ * Optional: wrapper-level press handler (pointer + keyboard).
107
+ * If provided (and not asChild), wrapper becomes button-like (role/tabIndex).
108
+ */
109
+ onPress?: (
110
+ e: React.PointerEvent<AnyElement> | React.KeyboardEvent<AnyElement>
111
+ ) => void;
112
+
113
+ className?: string;
114
+ children: React.ReactNode;
115
+ } & React.HTMLAttributes<AnyElement>;
116
+
117
+ export const InteractiveWrap = React.forwardRef<AnyElement, InteractiveWrapProps>(
118
+ (
119
+ {
120
+ asChild,
121
+ disabled = false,
122
+
123
+ press = true,
124
+ hoverGlow = true,
125
+ magnetic = false,
126
+ focusRing = true,
127
+ clip = true,
128
+
129
+ pressScale = 0.98,
130
+
131
+ magneticStrength = 0.32,
132
+ magneticMaxTranslate = 14,
133
+ magneticDamping = 0.18,
134
+
135
+ glowSize = 240,
136
+ glowOpacity = 0.45,
137
+ glowColor = "rgba(124, 58, 237, 1)",
138
+ glowDamping = 0.28,
139
+ glowBlendMode = "screen",
140
+
141
+ onPress,
142
+
143
+ className,
144
+ children,
145
+ style,
146
+ ...props
147
+ },
148
+ forwardedRef
149
+ ) => {
150
+ const Comp = asChild ? Slot : "div";
151
+
152
+ const internalRef = React.useRef<AnyElement | null>(null);
153
+ const ref = composeRefs(forwardedRef, internalRef);
154
+
155
+ const reducedMotion = usePrefersReducedMotion();
156
+ const canAnimate = !disabled && !reducedMotion;
157
+
158
+ const [hovered, setHovered] = React.useState(false);
159
+ const [pressed, setPressed] = React.useState(false);
160
+
161
+ // RAF loop: keeps magnet + glow stable and avoids CSS-transition lag.
162
+ const rafRef = React.useRef<number | null>(null);
163
+ const runningRef = React.useRef(false);
164
+
165
+ const pointerDownRef = React.useRef(false);
166
+ const keyDownRef = React.useRef(false);
167
+
168
+ const stateRef = React.useRef({
169
+ // current
170
+ x: 0,
171
+ y: 0,
172
+ tx: 0,
173
+ ty: 0,
174
+ scale: 1,
175
+
176
+ // targets
177
+ targetX: 0,
178
+ targetY: 0,
179
+ targetTx: 0,
180
+ targetTy: 0,
181
+ targetScale: 1,
182
+ });
183
+
184
+ const applyVars = React.useCallback(() => {
185
+ const el = internalRef.current;
186
+ if (!el) return;
187
+
188
+ const s = stateRef.current;
189
+
190
+ el.style.setProperty("--iw-x", `${s.x}px`);
191
+ el.style.setProperty("--iw-y", `${s.y}px`);
192
+ el.style.setProperty("--iw-tx", `${s.tx}px`);
193
+ el.style.setProperty("--iw-ty", `${s.ty}px`);
194
+ el.style.setProperty("--iw-scale", `${s.scale}`);
195
+ }, []);
196
+
197
+ const startLoop = React.useCallback(() => {
198
+ if (!canAnimate) return;
199
+ if (runningRef.current) return;
200
+ runningRef.current = true;
201
+
202
+ const tick = () => {
203
+ const el = internalRef.current;
204
+ if (!el) {
205
+ runningRef.current = false;
206
+ return;
207
+ }
208
+
209
+ const s = stateRef.current;
210
+
211
+ // smooth follow
212
+ s.x = lerp(s.x, s.targetX, clamp(glowDamping, 0.05, 0.75));
213
+ s.y = lerp(s.y, s.targetY, clamp(glowDamping, 0.05, 0.75));
214
+
215
+ s.tx = lerp(s.tx, s.targetTx, clamp(magneticDamping, 0.06, 0.6));
216
+ s.ty = lerp(s.ty, s.targetTy, clamp(magneticDamping, 0.06, 0.6));
217
+
218
+ // scale can be a bit snappier
219
+ s.scale = lerp(s.scale, s.targetScale, 0.22);
220
+
221
+ applyVars();
222
+
223
+ const near = (a: number, b: number) => Math.abs(a - b) < 0.12;
224
+
225
+ const settled =
226
+ near(s.x, s.targetX) &&
227
+ near(s.y, s.targetY) &&
228
+ near(s.tx, s.targetTx) &&
229
+ near(s.ty, s.targetTy) &&
230
+ Math.abs(s.scale - s.targetScale) < 0.01;
231
+
232
+ // keep running while hovered/pressed, or while returning to rest
233
+ const keepAlive = hovered || pressed || !settled;
234
+
235
+ if (keepAlive) {
236
+ rafRef.current = requestAnimationFrame(tick);
237
+ } else {
238
+ runningRef.current = false;
239
+ rafRef.current = null;
240
+ }
241
+ };
242
+
243
+ rafRef.current = requestAnimationFrame(tick);
244
+ }, [
245
+ canAnimate,
246
+ applyVars,
247
+ glowDamping,
248
+ magneticDamping,
249
+ hovered,
250
+ pressed,
251
+ ]);
252
+
253
+ const setCenterTargets = React.useCallback(() => {
254
+ const el = internalRef.current;
255
+ if (!el) return;
256
+ const rect = el.getBoundingClientRect();
257
+ const cx = rect.width / 2;
258
+ const cy = rect.height / 2;
259
+ const s = stateRef.current;
260
+ s.targetX = cx;
261
+ s.targetY = cy;
262
+
263
+ // also initialize current to avoid jump on first hover
264
+ if (!hovered) {
265
+ s.x = cx;
266
+ s.y = cy;
267
+ }
268
+ }, [hovered]);
269
+
270
+ React.useEffect(() => {
271
+ // init at center so glow looks correct before mouse moves
272
+ setCenterTargets();
273
+ applyVars();
274
+
275
+ const el = internalRef.current;
276
+ if (!el) return;
277
+
278
+ const ro = new ResizeObserver(() => {
279
+ setCenterTargets();
280
+ startLoop();
281
+ });
282
+
283
+ ro.observe(el);
284
+
285
+ return () => {
286
+ ro.disconnect();
287
+ if (rafRef.current) cancelAnimationFrame(rafRef.current);
288
+ rafRef.current = null;
289
+ runningRef.current = false;
290
+ };
291
+ }, [applyVars, setCenterTargets, startLoop]);
292
+
293
+ const setMagnetTargets = React.useCallback(
294
+ (clientX: number, clientY: number, pointerType?: string) => {
295
+ const el = internalRef.current;
296
+ if (!el) return;
297
+
298
+ const rect = el.getBoundingClientRect();
299
+
300
+ // local coords for glow
301
+ const x = clientX - rect.left;
302
+ const y = clientY - rect.top;
303
+
304
+ const s = stateRef.current;
305
+ s.targetX = x;
306
+ s.targetY = y;
307
+
308
+ const isTouch = pointerType === "touch";
309
+ const allowMouseFX = !isTouch;
310
+
311
+ if (canAnimate && magnetic && allowMouseFX) {
312
+ const dx = x - rect.width / 2;
313
+ const dy = y - rect.height / 2;
314
+
315
+ const max = Math.min(rect.width, rect.height) / 2;
316
+ const nx = max > 0 ? dx / max : 0;
317
+ const ny = max > 0 ? dy / max : 0;
318
+
319
+ const cx = clamp(nx, -1, 1);
320
+ const cy = clamp(ny, -1, 1);
321
+
322
+ const translateMax =
323
+ clamp(magneticMaxTranslate, 0, 40) *
324
+ clamp(magneticStrength, 0, 1);
325
+
326
+ s.targetTx = cx * translateMax;
327
+ s.targetTy = cy * translateMax;
328
+ } else {
329
+ s.targetTx = 0;
330
+ s.targetTy = 0;
331
+ }
332
+
333
+ startLoop();
334
+ },
335
+ [
336
+ canAnimate,
337
+ magnetic,
338
+ magneticMaxTranslate,
339
+ magneticStrength,
340
+ startLoop,
341
+ ]
342
+ );
343
+
344
+ const handlePointerEnter = (e: React.PointerEvent<AnyElement>) => {
345
+ if (disabled) return;
346
+ setHovered(true);
347
+ setCenterTargets();
348
+ // start loop so glow fades in smoothly even before move
349
+ startLoop();
350
+ props.onPointerEnter?.(e);
351
+ };
352
+
353
+ const handlePointerLeave = (e: React.PointerEvent<AnyElement>) => {
354
+ if (disabled) return;
355
+
356
+ setHovered(false);
357
+ setPressed(false);
358
+ pointerDownRef.current = false;
359
+
360
+ // return to rest smoothly
361
+ const s = stateRef.current;
362
+ s.targetTx = 0;
363
+ s.targetTy = 0;
364
+ s.targetScale = 1;
365
+ setCenterTargets();
366
+ startLoop();
367
+
368
+ props.onPointerLeave?.(e);
369
+ };
370
+
371
+ const handlePointerMove = (e: React.PointerEvent<AnyElement>) => {
372
+ if (disabled) return;
373
+ setMagnetTargets(e.clientX, e.clientY, e.pointerType);
374
+ props.onPointerMove?.(e);
375
+ };
376
+
377
+ const handlePointerDown = (e: React.PointerEvent<AnyElement>) => {
378
+ if (disabled) return;
379
+
380
+ // only primary button (left click)
381
+ if ("button" in e && e.button !== 0) {
382
+ props.onPointerDown?.(e);
383
+ return;
384
+ }
385
+
386
+ pointerDownRef.current = true;
387
+
388
+ try {
389
+ (e.currentTarget as AnyElement).setPointerCapture?.(e.pointerId);
390
+ } catch {
391
+ // ignore
392
+ }
393
+
394
+ if (canAnimate && press) {
395
+ setPressed(true);
396
+ stateRef.current.targetScale = clamp(pressScale, 0.9, 1);
397
+ startLoop();
398
+ }
399
+
400
+ props.onPointerDown?.(e);
401
+ };
402
+
403
+ const handlePointerUp = (e: React.PointerEvent<AnyElement>) => {
404
+ if (disabled) return;
405
+
406
+ if (press) setPressed(false);
407
+ stateRef.current.targetScale = 1;
408
+ startLoop();
409
+
410
+ // wrapper-level click (only if pointer started here)
411
+ if (onPress && pointerDownRef.current) onPress(e);
412
+ pointerDownRef.current = false;
413
+
414
+ props.onPointerUp?.(e);
415
+ };
416
+
417
+ const handlePointerCancel = (e: React.PointerEvent<AnyElement>) => {
418
+ if (disabled) return;
419
+ setPressed(false);
420
+ pointerDownRef.current = false;
421
+
422
+ const s = stateRef.current;
423
+ s.targetTx = 0;
424
+ s.targetTy = 0;
425
+ s.targetScale = 1;
426
+ startLoop();
427
+
428
+ props.onPointerCancel?.(e);
429
+ };
430
+
431
+ const handleKeyDown = (e: React.KeyboardEvent<AnyElement>) => {
432
+ if (disabled) return;
433
+
434
+ // Space/Enter press feedback (role=button behavior)
435
+ if ((e.key === "Enter" || e.key === " ") && press && canAnimate) {
436
+ if (!keyDownRef.current) {
437
+ keyDownRef.current = true;
438
+ setPressed(true);
439
+ stateRef.current.targetScale = clamp(pressScale, 0.9, 1);
440
+ startLoop();
441
+ }
442
+ }
443
+
444
+ // Prevent scroll on Space when wrapper acts like a button
445
+ if ((e.key === " " || e.key === "Enter") && onPress) {
446
+ if (e.key === " ") e.preventDefault();
447
+ }
448
+
449
+ props.onKeyDown?.(e);
450
+ };
451
+
452
+ const handleKeyUp = (e: React.KeyboardEvent<AnyElement>) => {
453
+ if (disabled) return;
454
+
455
+ if (e.key === "Enter" || e.key === " ") {
456
+ if (keyDownRef.current) {
457
+ keyDownRef.current = false;
458
+ setPressed(false);
459
+ stateRef.current.targetScale = 1;
460
+ startLoop();
461
+ if (onPress) onPress(e);
462
+ }
463
+ }
464
+
465
+ props.onKeyUp?.(e);
466
+ };
467
+
468
+ const buttonLikeProps =
469
+ !asChild && onPress
470
+ ? ({
471
+ role: "button",
472
+ tabIndex: disabled ? -1 : props.tabIndex ?? 0,
473
+ "aria-disabled": disabled ? true : undefined,
474
+ } as const)
475
+ : ({} as const);
476
+
477
+ const userTransform =
478
+ typeof style?.transform === "string" ? style.transform : "";
479
+
480
+ // If you keep CSS transition on transform, magnetic will feel delayed.
481
+ // We rely on RAF smoothing instead, so no transform transition here.
482
+ const baseTransform = canAnimate
483
+ ? `translate3d(var(--iw-tx, 0px), var(--iw-ty, 0px), 0) scale(var(--iw-scale, 1))`
484
+ : "";
485
+
486
+ return (
487
+ <Comp
488
+ ref={ref}
489
+ {...buttonLikeProps}
490
+ {...props}
491
+ onPointerEnter={handlePointerEnter}
492
+ onPointerLeave={handlePointerLeave}
493
+ onPointerMove={handlePointerMove}
494
+ onPointerDown={handlePointerDown}
495
+ onPointerUp={handlePointerUp}
496
+ onPointerCancel={handlePointerCancel}
497
+ onKeyDown={handleKeyDown}
498
+ onKeyUp={handleKeyUp}
499
+ data-hovered={hovered ? "true" : "false"}
500
+ data-pressed={pressed ? "true" : "false"}
501
+ className={cn(
502
+ "relative isolate",
503
+ clip ? "overflow-hidden" : "overflow-visible",
504
+ canAnimate && "will-change-transform",
505
+ disabled ? "pointer-events-none opacity-60" : "pointer-events-auto",
506
+ focusRing &&
507
+ !disabled &&
508
+ "focus-within:outline-none focus-within:ring-2 focus-within:ring-ring/30 focus-within:ring-offset-2 focus-within:ring-offset-background",
509
+ className
510
+ )}
511
+ style={{
512
+ ...style,
513
+ // Better mobile feel when wrapper is clickable
514
+ touchAction: onPress ? "manipulation" : style?.touchAction,
515
+ transform: canAnimate
516
+ ? `${baseTransform}${userTransform ? ` ${userTransform}` : ""}`
517
+ : userTransform || style?.transform,
518
+ }}
519
+ >
520
+ {/* Cursor-follow glow layer */}
521
+ {hoverGlow && (
522
+ <div
523
+ aria-hidden="true"
524
+ className={cn(
525
+ "pointer-events-none absolute inset-0",
526
+ "transition-opacity duration-200 ease-out"
527
+ )}
528
+ style={{
529
+ opacity: hovered && !disabled ? glowOpacity : 0,
530
+ mixBlendMode: glowBlendMode,
531
+ background: `radial-gradient(${glowSize}px circle at var(--iw-x, 50%) var(--iw-y, 50%), ${glowColor}, transparent 62%)`,
532
+ }}
533
+ />
534
+ )}
535
+
536
+ {/* Content */}
537
+ <div className="relative z-[1]">{children}</div>
538
+ </Comp>
539
+ );
540
+ }
541
+ );
542
+
543
+ InteractiveWrap.displayName = "InteractiveWrap";
544
+
545
+ /* -------------------------------- Usage ---------------------------------
546
+
547
+ <InteractiveWrap hoverGlow magnetic press className="rounded-2xl">
548
+ <button className="px-6 py-3 rounded-2xl bg-white/10 text-white">Button</button>
549
+ </InteractiveWrap>
550
+
551
+ <InteractiveWrap onPress={() => console.log("pressed")} className="rounded-xl p-3">
552
+ <div>Card-like clickable wrapper</div>
553
+ </InteractiveWrap>
554
+
555
+ --------------------------------------------------------------------------- */
package/LICENSE.md DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 shadcn
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,33 +0,0 @@
1
- import * as React from "react"
2
- import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
3
-
4
- import { cn } from "@/lib/utils"
5
-
6
- function CheckIcon(props: React.SVGProps<SVGSVGElement>) {
7
- return (
8
- <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" {...props}>
9
- <polyline points="3.5 8.5 6.5 11.5 12.5 4.5" />
10
- </svg>
11
- )
12
- }
13
-
14
- const Checkbox = React.forwardRef<
15
- React.ElementRef<typeof CheckboxPrimitive.Root>,
16
- React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
17
- >(({ className, ...props }, ref) => (
18
- <CheckboxPrimitive.Root
19
- ref={ref}
20
- className={cn(
21
- "peer h-4 w-4 shrink-0 rounded-sm border border-input bg-background shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
22
- className
23
- )}
24
- {...props}
25
- >
26
- <CheckboxPrimitive.Indicator className="flex items-center justify-center text-current">
27
- <CheckIcon className="h-3.5 w-3.5 stroke-[2.5]" />
28
- </CheckboxPrimitive.Indicator>
29
- </CheckboxPrimitive.Root>
30
- ))
31
- Checkbox.displayName = "Checkbox"
32
-
33
- export { Checkbox }
@@ -1,92 +0,0 @@
1
- import * as React from "react"
2
- import * as DialogPrimitive from "@radix-ui/react-dialog"
3
-
4
- import { cn } from "@/lib/utils"
5
-
6
- const Dialog = DialogPrimitive.Root
7
- const DialogTrigger = DialogPrimitive.Trigger
8
- const DialogClose = DialogPrimitive.Close
9
-
10
- const DialogOverlay = React.forwardRef<
11
- React.ElementRef<typeof DialogPrimitive.Overlay>,
12
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
13
- >(({ className, ...props }, ref) => (
14
- <DialogPrimitive.Overlay
15
- ref={ref}
16
- className={cn("fixed inset-0 z-50 bg-black/50", className)}
17
- {...props}
18
- />
19
- ))
20
- DialogOverlay.displayName = "DialogOverlay"
21
-
22
- const DialogContent = React.forwardRef<
23
- React.ElementRef<typeof DialogPrimitive.Content>,
24
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
25
- >(({ className, ...props }, ref) => (
26
- <DialogPrimitive.Portal>
27
- <DialogOverlay />
28
- <DialogPrimitive.Content
29
- ref={ref}
30
- className={cn(
31
- "fixed left-1/2 top-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 rounded-lg border border-border bg-background p-6 shadow-lg focus-visible:outline-none",
32
- className
33
- )}
34
- {...props}
35
- />
36
- </DialogPrimitive.Portal>
37
- ))
38
- DialogContent.displayName = "DialogContent"
39
-
40
- const DialogHeader = ({
41
- className,
42
- ...props
43
- }: React.HTMLAttributes<HTMLDivElement>) => (
44
- <div className={cn("flex flex-col space-y-2 text-left", className)} {...props} />
45
- )
46
- DialogHeader.displayName = "DialogHeader"
47
-
48
- const DialogFooter = ({
49
- className,
50
- ...props
51
- }: React.HTMLAttributes<HTMLDivElement>) => (
52
- <div
53
- className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
54
- {...props}
55
- />
56
- )
57
- DialogFooter.displayName = "DialogFooter"
58
-
59
- const DialogTitle = React.forwardRef<
60
- React.ElementRef<typeof DialogPrimitive.Title>,
61
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
62
- >(({ className, ...props }, ref) => (
63
- <DialogPrimitive.Title
64
- ref={ref}
65
- className={cn("text-lg font-semibold", className)}
66
- {...props}
67
- />
68
- ))
69
- DialogTitle.displayName = "DialogTitle"
70
-
71
- const DialogDescription = React.forwardRef<
72
- React.ElementRef<typeof DialogPrimitive.Description>,
73
- React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
74
- >(({ className, ...props }, ref) => (
75
- <DialogPrimitive.Description
76
- ref={ref}
77
- className={cn("text-sm text-muted-foreground", className)}
78
- {...props}
79
- />
80
- ))
81
- DialogDescription.displayName = "DialogDescription"
82
-
83
- export {
84
- Dialog,
85
- DialogTrigger,
86
- DialogClose,
87
- DialogContent,
88
- DialogHeader,
89
- DialogFooter,
90
- DialogTitle,
91
- DialogDescription
92
- }