ruler-components 0.1.0 → 0.1.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 (118) hide show
  1. package/dist/index.d.mts +51 -0
  2. package/dist/index.d.ts +51 -0
  3. package/dist/index.js +534 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.mjs +498 -0
  6. package/dist/index.mjs.map +1 -0
  7. package/package.json +21 -2
  8. package/AGENTS.md +0 -9
  9. package/CLAUDE.md +0 -1
  10. package/app/docs/[slug]/page.tsx +0 -147
  11. package/app/docs/layout.tsx +0 -26
  12. package/app/docs/page.tsx +0 -148
  13. package/app/favicon.ico +0 -0
  14. package/app/globals.css +0 -168
  15. package/app/icon.png +0 -0
  16. package/app/layout.tsx +0 -90
  17. package/app/opengraph-image.tsx +0 -10
  18. package/app/page.tsx +0 -34
  19. package/app/twitter-image.tsx +0 -10
  20. package/components/docs/accordion-doc-page.tsx +0 -352
  21. package/components/docs/alert-doc-page.tsx +0 -293
  22. package/components/docs/allinput-doc-page.tsx +0 -183
  23. package/components/docs/avatar-doc-page.tsx +0 -424
  24. package/components/docs/badge-doc-page.tsx +0 -363
  25. package/components/docs/button-doc-page.tsx +0 -406
  26. package/components/docs/card-doc-page.tsx +0 -364
  27. package/components/docs/checkbox-doc-page.tsx +0 -277
  28. package/components/docs/colors-doc-page.tsx +0 -430
  29. package/components/docs/dialog-doc-page.tsx +0 -364
  30. package/components/docs/docs-footer.tsx +0 -11
  31. package/components/docs/docs-mobile-menu-bar.tsx +0 -22
  32. package/components/docs/docs-mobile-nav-context.tsx +0 -27
  33. package/components/docs/docs-page.tsx +0 -263
  34. package/components/docs/docs-search.tsx +0 -303
  35. package/components/docs/docs-sidebar.tsx +0 -165
  36. package/components/docs/docs-topbar.tsx +0 -32
  37. package/components/docs/dropdown-doc-page.tsx +0 -522
  38. package/components/docs/getting-started-doc-page.tsx +0 -205
  39. package/components/docs/label-doc-page.tsx +0 -173
  40. package/components/docs/loaders-doc-page.tsx +0 -244
  41. package/components/docs/menu-doc-page.tsx +0 -373
  42. package/components/docs/modal-doc-page.tsx +0 -436
  43. package/components/docs/next-steps.tsx +0 -53
  44. package/components/docs/pagination-doc-page.tsx +0 -316
  45. package/components/docs/progress-doc-page.tsx +0 -387
  46. package/components/docs/radio-doc-page.tsx +0 -270
  47. package/components/docs/skeleton-doc-page.tsx +0 -230
  48. package/components/docs/stepper-doc-page.tsx +0 -309
  49. package/components/docs/switch-doc-page.tsx +0 -264
  50. package/components/docs/table-doc-page.tsx +0 -689
  51. package/components/docs/tabs-doc-page.tsx +0 -359
  52. package/components/docs/theming-doc-page.tsx +0 -243
  53. package/components/docs/tooltip-doc-page.tsx +0 -357
  54. package/components/docs/usage-section.tsx +0 -21
  55. package/components/icons/discord.tsx +0 -9
  56. package/components/icons/github.tsx +0 -9
  57. package/components/icons/x.tsx +0 -9
  58. package/components/installation-section.tsx +0 -34
  59. package/components/landing/feature-highlights.tsx +0 -105
  60. package/components/landing/footer-strip.tsx +0 -45
  61. package/components/landing/hero-card.tsx +0 -14
  62. package/components/landing/hero-spotlight.tsx +0 -126
  63. package/components/landing/hero.tsx +0 -64
  64. package/components/landing/navbar.tsx +0 -44
  65. package/components/landing/quick-start-section.tsx +0 -59
  66. package/components/landing/site-footer.tsx +0 -55
  67. package/components/theme-provider.tsx +0 -60
  68. package/components/ui/accordion.tsx +0 -174
  69. package/components/ui/alert.tsx +0 -103
  70. package/components/ui/allinput.tsx +0 -210
  71. package/components/ui/avatar.tsx +0 -179
  72. package/components/ui/badge.tsx +0 -52
  73. package/components/ui/button.tsx +0 -75
  74. package/components/ui/card.tsx +0 -105
  75. package/components/ui/checkbox.tsx +0 -130
  76. package/components/ui/code-block.tsx +0 -60
  77. package/components/ui/data-table.tsx +0 -235
  78. package/components/ui/dialog.tsx +0 -173
  79. package/components/ui/dropdown.tsx +0 -78
  80. package/components/ui/feature-card.tsx +0 -38
  81. package/components/ui/input.tsx +0 -44
  82. package/components/ui/label.tsx +0 -110
  83. package/components/ui/loaders.tsx +0 -139
  84. package/components/ui/menu.tsx +0 -118
  85. package/components/ui/modal.tsx +0 -399
  86. package/components/ui/package-manager-tabs.tsx +0 -40
  87. package/components/ui/pagination.tsx +0 -200
  88. package/components/ui/progress.tsx +0 -134
  89. package/components/ui/radio.tsx +0 -262
  90. package/components/ui/skeleton.tsx +0 -102
  91. package/components/ui/steppers.tsx +0 -309
  92. package/components/ui/switch.tsx +0 -153
  93. package/components/ui/table.tsx +0 -58
  94. package/components/ui/tabs.tsx +0 -166
  95. package/components/ui/theme-toggle.tsx +0 -60
  96. package/components/ui/tooltip.tsx +0 -238
  97. package/data/color-palette.ts +0 -35
  98. package/data/docs-nav.ts +0 -84
  99. package/eslint.config.mjs +0 -18
  100. package/index.ts +0 -8
  101. package/lib/cn.ts +0 -4
  102. package/lib/color.ts +0 -85
  103. package/lib/og-image.tsx +0 -138
  104. package/lib/theme.ts +0 -33
  105. package/next.config.ts +0 -7
  106. package/postcss.config.mjs +0 -7
  107. package/public/dark.png +0 -0
  108. package/public/dark1.png +0 -0
  109. package/public/dark2.png +0 -0
  110. package/public/file.svg +0 -1
  111. package/public/globe.svg +0 -1
  112. package/public/light.png +0 -0
  113. package/public/light1.png +0 -0
  114. package/public/next.svg +0 -1
  115. package/public/vercel.svg +0 -1
  116. package/public/video/hero-demo.mp4 +0 -0
  117. package/public/window.svg +0 -1
  118. package/tsconfig.json +0 -34
@@ -1,134 +0,0 @@
1
- import * as React from "react";
2
- import { cva, type VariantProps } from "class-variance-authority";
3
- import { cn } from "@/lib/cn";
4
-
5
- const progressTrackVariants = cva(
6
- "relative w-full overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800/70",
7
- {
8
- variants: {
9
- size: {
10
- sm: "h-1",
11
- md: "h-1.5",
12
- lg: "h-2",
13
- },
14
- },
15
- defaultVariants: { size: "md" },
16
- },
17
- );
18
-
19
- const progressIndicatorVariants = cva(
20
- "h-full rounded-full transition-[width] duration-500 ease-[cubic-bezier(0.4,0,0.2,1)]",
21
- {
22
- variants: {
23
- variant: {
24
- default: "bg-zinc-900 dark:bg-zinc-100",
25
- success: "bg-[#28A745] dark:bg-[#5CC975]",
26
- warning: "bg-[#E58E00] dark:bg-[#F5B84A]",
27
- error: "bg-[#D93025] dark:bg-[#F06B62]",
28
- },
29
- },
30
- defaultVariants: { variant: "default" },
31
- },
32
- );
33
-
34
- const valuePillVariants = cva(
35
- "inline-flex min-w-[2.25rem] items-center justify-end text-[11px] font-medium tabular-nums text-zinc-400 dark:text-zinc-500",
36
- {
37
- variants: {
38
- variant: {
39
- default: "",
40
- success: "",
41
- warning: "",
42
- error: "",
43
- },
44
- },
45
- defaultVariants: { variant: "default" },
46
- },
47
- );
48
-
49
- export interface ProgressProps
50
- extends Omit<React.HTMLAttributes<HTMLDivElement>, "children">,
51
- VariantProps<typeof progressTrackVariants>,
52
- VariantProps<typeof progressIndicatorVariants> {
53
- value?: number;
54
- max?: number;
55
- label?: string;
56
- showValue?: boolean;
57
- indeterminate?: boolean;
58
- disabled?: boolean;
59
- }
60
-
61
- const Progress = React.forwardRef<HTMLDivElement, ProgressProps>(
62
- (
63
- {
64
- className,
65
- value = 0,
66
- max = 100,
67
- variant,
68
- size,
69
- label,
70
- showValue = false,
71
- indeterminate = false,
72
- disabled = false,
73
- ...props
74
- },
75
- ref,
76
- ) => {
77
- const clamped = Math.min(max, Math.max(0, value));
78
- const percentage = max > 0 ? Math.round((clamped / max) * 100) : 0;
79
-
80
- return (
81
- <div
82
- className={cn(
83
- "flex w-full flex-col gap-2.5",
84
- disabled && "pointer-events-none opacity-50",
85
- className,
86
- )}
87
- >
88
- {(label || showValue) && (
89
- <div className="flex items-center justify-between gap-3">
90
- {label && (
91
- <span className="text-sm text-zinc-600 dark:text-zinc-300">
92
- {label}
93
- </span>
94
- )}
95
- {showValue && !indeterminate && (
96
- <span className={cn(valuePillVariants({ variant }))}>
97
- {percentage}%
98
- </span>
99
- )}
100
- </div>
101
- )}
102
- <div
103
- ref={ref}
104
- role="progressbar"
105
- aria-valuemin={0}
106
- aria-valuemax={max}
107
- aria-valuenow={indeterminate || disabled ? undefined : clamped}
108
- aria-label={label}
109
- aria-valuetext={indeterminate ? "Loading" : `${percentage}%`}
110
- aria-disabled={disabled || undefined}
111
- className={cn(progressTrackVariants({ size }))}
112
- {...props}
113
- >
114
- {indeterminate ? (
115
- <div
116
- className={cn(
117
- progressIndicatorVariants({ variant }),
118
- "w-[40%] animate-[progress-indeterminate_1.5s_ease-in-out_infinite]",
119
- )}
120
- />
121
- ) : (
122
- <div
123
- className={cn(progressIndicatorVariants({ variant }))}
124
- style={{ width: `${percentage}%` }}
125
- />
126
- )}
127
- </div>
128
- </div>
129
- );
130
- },
131
- );
132
- Progress.displayName = "Progress";
133
-
134
- export { Progress, progressTrackVariants, progressIndicatorVariants };
@@ -1,262 +0,0 @@
1
- import * as React from "react";
2
- import { cva, type VariantProps } from "class-variance-authority";
3
- import { cn } from "@/lib/cn";
4
-
5
- const radioControlVariants = cva(
6
- [
7
- "pointer-events-none relative flex shrink-0 items-center justify-center rounded-full border-2 bg-transparent transition-all duration-200",
8
- "border-zinc-500 group-hover:border-zinc-700",
9
- "peer-checked:border-zinc-900",
10
- "peer-focus-visible:outline-none peer-focus-visible:ring-2 peer-focus-visible:ring-zinc-900/30 peer-focus-visible:ring-offset-2",
11
- "peer-disabled:border-zinc-300",
12
- "peer-disabled:peer-checked:border-zinc-300",
13
- "dark:border-zinc-500 dark:group-hover:border-zinc-400",
14
- "dark:peer-checked:border-zinc-100",
15
- "dark:peer-disabled:border-zinc-600 dark:peer-disabled:peer-checked:border-zinc-600",
16
- "peer-checked:[&_.radio-dot]:scale-100 peer-checked:[&_.radio-dot]:opacity-100",
17
- "peer-disabled:peer-checked:[&_.radio-dot]:bg-zinc-300",
18
- "dark:peer-disabled:peer-checked:[&_.radio-dot]:bg-zinc-600",
19
- ],
20
- {
21
- variants: {
22
- size: {
23
- sm: "h-4 w-4 [&_.radio-dot]:h-1.5 [&_.radio-dot]:w-1.5",
24
- md: "h-5 w-5 [&_.radio-dot]:h-2.5 [&_.radio-dot]:w-2.5",
25
- lg: "h-6 w-6 [&_.radio-dot]:h-3 [&_.radio-dot]:w-3",
26
- },
27
- },
28
- defaultVariants: { size: "md" },
29
- },
30
- );
31
-
32
- const radioWrapperVariants = cva("group relative flex w-full transition-colors duration-150", {
33
- variants: {
34
- variant: {
35
- inline: "gap-3",
36
- card: [
37
- "gap-3.5 rounded-lg border border-zinc-200 bg-white px-4 py-3.5",
38
- "hover:border-zinc-300 hover:bg-zinc-50/80",
39
- "has-[:checked]:border-zinc-900",
40
- "dark:border-zinc-800 dark:bg-zinc-900 dark:hover:border-zinc-700",
41
- "dark:has-[:checked]:border-zinc-500",
42
- ],
43
- },
44
- },
45
- defaultVariants: { variant: "inline" },
46
- });
47
-
48
- interface RadioGroupContextValue {
49
- name: string;
50
- value?: string;
51
- onValueChange?: (value: string) => void;
52
- size?: "sm" | "md" | "lg";
53
- variant?: "inline" | "card";
54
- appearance?: "default" | "segmented";
55
- disabled?: boolean;
56
- }
57
-
58
- const RadioGroupContext = React.createContext<RadioGroupContextValue | null>(
59
- null,
60
- );
61
-
62
- export interface RadioGroupProps extends React.HTMLAttributes<HTMLDivElement> {
63
- name: string;
64
- value?: string;
65
- defaultValue?: string;
66
- onValueChange?: (value: string) => void;
67
- size?: "sm" | "md" | "lg";
68
- variant?: "inline" | "card";
69
- appearance?: "default" | "segmented";
70
- disabled?: boolean;
71
- orientation?: "vertical" | "horizontal";
72
- }
73
-
74
- const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>(
75
- (
76
- {
77
- className,
78
- name,
79
- value: controlledValue,
80
- defaultValue,
81
- onValueChange,
82
- size = "md",
83
- variant = "inline",
84
- appearance = "default",
85
- disabled,
86
- orientation = "vertical",
87
- children,
88
- ...props
89
- },
90
- ref,
91
- ) => {
92
- const [uncontrolledValue, setUncontrolledValue] = React.useState(
93
- defaultValue ?? "",
94
- );
95
- const value = controlledValue ?? uncontrolledValue;
96
-
97
- const handleValueChange = (next: string) => {
98
- if (controlledValue === undefined) {
99
- setUncontrolledValue(next);
100
- }
101
- onValueChange?.(next);
102
- };
103
-
104
- return (
105
- <RadioGroupContext.Provider
106
- value={{ name, value, onValueChange: handleValueChange, size, variant, appearance, disabled }}
107
- >
108
- <div
109
- ref={ref}
110
- role="radiogroup"
111
- className={cn(
112
- "flex",
113
- appearance === "segmented"
114
- ? "inline-flex w-fit gap-0.5 rounded-lg border border-zinc-200 p-0.5 dark:border-zinc-800"
115
- : variant === "card"
116
- ? "gap-2.5"
117
- : "gap-2.5",
118
- orientation === "vertical" ? "flex-col" : "flex-row flex-wrap",
119
- className,
120
- )}
121
- {...props}
122
- >
123
- {children}
124
- </div>
125
- </RadioGroupContext.Provider>
126
- );
127
- },
128
- );
129
- RadioGroup.displayName = "RadioGroup";
130
-
131
- export interface RadioProps
132
- extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size">,
133
- VariantProps<typeof radioControlVariants> {
134
- value: string;
135
- label?: string;
136
- description?: string;
137
- variant?: "inline" | "card";
138
- }
139
-
140
- const Radio = React.forwardRef<HTMLInputElement, RadioProps>(
141
- (
142
- {
143
- className,
144
- size: sizeProp,
145
- variant: variantProp,
146
- value,
147
- label,
148
- description,
149
- disabled: disabledProp,
150
- id,
151
- onChange,
152
- checked: checkedProp,
153
- ...inputProps
154
- },
155
- ref,
156
- ) => {
157
- const context = React.useContext(RadioGroupContext);
158
- const generatedId = React.useId();
159
- const inputId = id ?? generatedId;
160
- const size = sizeProp ?? context?.size ?? "md";
161
- const groupVariant = variantProp ?? context?.variant ?? "inline";
162
- const appearance = context?.appearance ?? "default";
163
- const resolvedVariant =
164
- appearance === "segmented"
165
- ? "inline"
166
- : groupVariant === "card" || description
167
- ? "card"
168
- : "inline";
169
- const disabled = disabledProp ?? context?.disabled;
170
- const isControlled = context !== null || checkedProp !== undefined;
171
- const checked = context ? context.value === value : checkedProp;
172
- const alignStart = resolvedVariant === "card" || Boolean(description);
173
-
174
- const input = (
175
- <input
176
- {...inputProps}
177
- ref={ref}
178
- id={inputId}
179
- type="radio"
180
- name={context?.name}
181
- value={value}
182
- disabled={disabled}
183
- checked={isControlled ? checked : undefined}
184
- defaultChecked={!isControlled ? checkedProp : undefined}
185
- onChange={(event) => {
186
- onChange?.(event);
187
- if (event.target.checked) {
188
- context?.onValueChange?.(value);
189
- }
190
- }}
191
- className="peer absolute inset-0 z-10 cursor-pointer opacity-0 disabled:cursor-not-allowed"
192
- />
193
- );
194
-
195
- return (
196
- <label
197
- htmlFor={inputId}
198
- className={cn(
199
- appearance === "segmented"
200
- ? "relative inline-flex items-center rounded-md px-3 py-1.5 text-sm font-medium text-zinc-600 transition-colors duration-150 has-[:checked]:bg-zinc-900 has-[:checked]:text-white dark:text-zinc-400 dark:has-[:checked]:bg-zinc-100 dark:has-[:checked]:text-zinc-900"
201
- : radioWrapperVariants({ variant: resolvedVariant }),
202
- appearance === "segmented" ? "items-center" : alignStart ? "items-start" : "items-center",
203
- disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
204
- className,
205
- )}
206
- >
207
- {appearance === "segmented" ? (
208
- input
209
- ) : (
210
- <span
211
- className={cn(
212
- "relative flex shrink-0 items-center justify-center p-2.5 -m-2.5",
213
- alignStart ? "-mt-[3px]" : undefined,
214
- )}
215
- >
216
- {input}
217
- <span
218
- aria-hidden
219
- className="pointer-events-none absolute inset-0 rounded-full bg-zinc-900/0 transition-colors duration-200 group-hover:bg-zinc-900/[0.08] group-active:bg-zinc-900/[0.12] peer-disabled:group-hover:bg-transparent dark:group-hover:bg-white/[0.08] dark:group-active:bg-white/[0.12]"
220
- />
221
- <span className={radioControlVariants({ size })}>
222
- <span className="radio-dot scale-0 rounded-full bg-zinc-900 opacity-0 transition-all duration-200 dark:bg-zinc-100" />
223
- </span>
224
- </span>
225
- )}
226
- {(label || description) && (
227
- <span
228
- className={cn(
229
- "flex min-w-0 flex-col",
230
- appearance === "segmented" ? "gap-0" : "flex-1 gap-0.5",
231
- )}
232
- >
233
- {label && (
234
- <span
235
- className={cn(
236
- appearance === "segmented"
237
- ? "leading-none"
238
- : cn(
239
- "text-sm leading-snug text-zinc-800 dark:text-zinc-100",
240
- size === "sm" && "text-xs",
241
- size === "md" && "text-sm",
242
- size === "lg" && "text-base",
243
- ),
244
- )}
245
- >
246
- {label}
247
- </span>
248
- )}
249
- {description && (
250
- <span className="text-xs leading-relaxed text-zinc-500 dark:text-zinc-400">
251
- {description}
252
- </span>
253
- )}
254
- </span>
255
- )}
256
- </label>
257
- );
258
- },
259
- );
260
- Radio.displayName = "Radio";
261
-
262
- export { Radio, RadioGroup, radioControlVariants };
@@ -1,102 +0,0 @@
1
- import React from "react";
2
-
3
- const SkeletonBar = ({ className }: { className?: string }) => (
4
- <div className={`animate-pulse rounded bg-zinc-200 dark:bg-zinc-800 ${className}`} />
5
- );
6
-
7
- export function AccordionSkeletonPlus({ count = 3 }: { count?: number }) {
8
- return (
9
- <div className="w-full">
10
- {Array.from({ length: count }).map((_, i) => (
11
- <div key={i} className="flex items-center gap-3 py-4 border-b border-zinc-100 dark:border-zinc-800 last:border-0">
12
- <SkeletonBar className="h-5 w-5 rounded-full shrink-0" />
13
- <SkeletonBar className="h-4 w-2/3" />
14
- </div>
15
- ))}
16
- </div>
17
- );
18
- }
19
-
20
- export function AccordionSkeletonChevron({ count = 3 }: { count?: number }) {
21
- return (
22
- <div className="w-full">
23
- {Array.from({ length: count }).map((_, i) => (
24
- <div key={i} className="flex items-center justify-between py-5 border-b border-zinc-100 dark:border-zinc-800 last:border-0">
25
- <SkeletonBar className="h-4 w-1/2" />
26
- <SkeletonBar className="h-4 w-4 rounded-sm shrink-0" />
27
- </div>
28
- ))}
29
- </div>
30
- );
31
- }
32
-
33
- export function CardSkeletonGrid({ count = 3 }: { count?: number }) {
34
- return (
35
- <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 w-full">
36
- {Array.from({ length: count }).map((_, i) => (
37
- <div key={i} className="flex flex-col gap-3">
38
- <SkeletonBar className="aspect-video w-full rounded-md" />
39
- <SkeletonBar className="h-4 w-full" />
40
- <SkeletonBar className="h-4 w-[60%]" />
41
- </div>
42
- ))}
43
- </div>
44
- );
45
- }
46
-
47
- export function ListSkeleton({ count = 3 }: { count?: number }) {
48
- return (
49
- <div className="w-full space-y-4">
50
- {Array.from({ length: count }).map((_, i) => (
51
- <div key={i} className="flex flex-col gap-4 p-4 border border-zinc-100 dark:border-zinc-800 rounded-lg bg-white dark:bg-zinc-900/50">
52
- <div className="flex items-center gap-3">
53
- <SkeletonBar className="h-10 w-10 rounded-full shrink-0" />
54
- <div className="flex flex-col gap-2">
55
- <SkeletonBar className="h-3 w-24" />
56
- <SkeletonBar className="h-3 w-40" />
57
- </div>
58
- </div>
59
- <div className="flex flex-col gap-2 mt-1">
60
- <SkeletonBar className="h-3 w-full" />
61
- <SkeletonBar className="h-3 w-[92%]" />
62
- </div>
63
- </div>
64
- ))}
65
- </div>
66
- );
67
- }
68
-
69
- export function TableSkeleton({ count = 5 }: { count?: number }) {
70
- return (
71
- <div className="w-full overflow-hidden rounded-lg border border-zinc-100 dark:border-zinc-800">
72
- <div className="overflow-x-auto">
73
- <table className="w-full text-sm text-left">
74
- <thead className="bg-zinc-50/50 dark:bg-zinc-900/50 border-b border-zinc-100 dark:border-zinc-800 text-zinc-500">
75
- <tr>
76
- <th className="px-4 py-3 font-medium">Id</th>
77
- <th className="px-4 py-3 font-medium">Image</th>
78
- <th className="px-4 py-3 font-medium">Name</th>
79
- <th className="px-4 py-3 font-medium">Category</th>
80
- <th className="px-4 py-3 font-medium">Price</th>
81
- <th className="px-4 py-3 font-medium">Stock</th>
82
- <th className="px-4 py-3 font-medium">Description</th>
83
- </tr>
84
- </thead>
85
- <tbody className="divide-y divide-zinc-100 dark:divide-zinc-800">
86
- {Array.from({ length: count }).map((_, i) => (
87
- <tr key={i}>
88
- <td className="px-4 py-4"><SkeletonBar className="h-4 w-8" /></td>
89
- <td className="px-4 py-4"><SkeletonBar className="h-8 w-12 rounded" /></td>
90
- <td className="px-4 py-4"><SkeletonBar className="h-4 w-24" /></td>
91
- <td className="px-4 py-4"><SkeletonBar className="h-4 w-20" /></td>
92
- <td className="px-4 py-4"><SkeletonBar className="h-4 w-12" /></td>
93
- <td className="px-4 py-4"><SkeletonBar className="h-4 w-12" /></td>
94
- <td className="px-4 py-4"><SkeletonBar className="h-4 w-48" /></td>
95
- </tr>
96
- ))}
97
- </tbody>
98
- </table>
99
- </div>
100
- </div>
101
- );
102
- }