omnira-ui 0.1.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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +145 -0
  3. package/cli/omnira-init.mjs +260 -0
  4. package/cli/presets.mjs +386 -0
  5. package/components/ui/AppStoreButton/AppStoreButton.module.css +87 -0
  6. package/components/ui/AppStoreButton/AppStoreButton.tsx +114 -0
  7. package/components/ui/AppStoreButton/index.ts +2 -0
  8. package/components/ui/Avatar/Avatar.module.css +76 -0
  9. package/components/ui/Avatar/Avatar.tsx +102 -0
  10. package/components/ui/Avatar/index.ts +2 -0
  11. package/components/ui/Badge/Badge.module.css +120 -0
  12. package/components/ui/Badge/Badge.tsx +25 -0
  13. package/components/ui/Badge/index.ts +2 -0
  14. package/components/ui/BadgeGroup/BadgeGroup.module.css +214 -0
  15. package/components/ui/BadgeGroup/BadgeGroup.tsx +88 -0
  16. package/components/ui/BadgeGroup/index.ts +2 -0
  17. package/components/ui/Browser/Browser.module.css +105 -0
  18. package/components/ui/Browser/Browser.tsx +54 -0
  19. package/components/ui/Browser/index.ts +2 -0
  20. package/components/ui/Button/Button.module.css +188 -0
  21. package/components/ui/Button/Button.tsx +74 -0
  22. package/components/ui/Button/index.ts +2 -0
  23. package/components/ui/ButtonUtility/ButtonUtility.module.css +154 -0
  24. package/components/ui/ButtonUtility/ButtonUtility.tsx +65 -0
  25. package/components/ui/ButtonUtility/index.ts +2 -0
  26. package/components/ui/Card/Card.module.css +80 -0
  27. package/components/ui/Card/Card.tsx +39 -0
  28. package/components/ui/Card/index.ts +2 -0
  29. package/components/ui/Checkbox/Checkbox.module.css +92 -0
  30. package/components/ui/Checkbox/Checkbox.tsx +95 -0
  31. package/components/ui/Checkbox/index.ts +2 -0
  32. package/components/ui/Collapse/Collapse.module.css +60 -0
  33. package/components/ui/Collapse/Collapse.tsx +100 -0
  34. package/components/ui/Collapse/index.ts +2 -0
  35. package/components/ui/CreditCard/CreditCard.module.css +117 -0
  36. package/components/ui/CreditCard/CreditCard.tsx +86 -0
  37. package/components/ui/CreditCard/index.ts +2 -0
  38. package/components/ui/Dropdown/Dropdown.module.css +269 -0
  39. package/components/ui/Dropdown/Dropdown.tsx +419 -0
  40. package/components/ui/Dropdown/index.ts +31 -0
  41. package/components/ui/GridLines/GridLines.module.css +95 -0
  42. package/components/ui/GridLines/GridLines.tsx +10 -0
  43. package/components/ui/GridLines/index.ts +1 -0
  44. package/components/ui/Illustration/Illustration.module.css +10 -0
  45. package/components/ui/Illustration/Illustration.tsx +96 -0
  46. package/components/ui/Illustration/index.ts +2 -0
  47. package/components/ui/Input/Input.module.css +217 -0
  48. package/components/ui/Input/Input.tsx +93 -0
  49. package/components/ui/Input/index.ts +2 -0
  50. package/components/ui/Phone/Phone.module.css +104 -0
  51. package/components/ui/Phone/Phone.tsx +54 -0
  52. package/components/ui/Phone/index.ts +2 -0
  53. package/components/ui/PinInput/PinInput.module.css +104 -0
  54. package/components/ui/PinInput/PinInput.tsx +210 -0
  55. package/components/ui/PinInput/index.ts +1 -0
  56. package/components/ui/ProgressBar/ProgressBar.module.css +180 -0
  57. package/components/ui/ProgressBar/ProgressBar.tsx +206 -0
  58. package/components/ui/ProgressBar/index.ts +2 -0
  59. package/components/ui/QRCode/QRCode.module.css +13 -0
  60. package/components/ui/QRCode/QRCode.tsx +128 -0
  61. package/components/ui/QRCode/index.ts +2 -0
  62. package/components/ui/RadioButton/RadioButton.module.css +92 -0
  63. package/components/ui/RadioButton/RadioButton.tsx +134 -0
  64. package/components/ui/RadioButton/index.ts +2 -0
  65. package/components/ui/RadioGroup/RadioGroup.module.css +382 -0
  66. package/components/ui/RadioGroup/RadioGroup.tsx +292 -0
  67. package/components/ui/RadioGroup/index.ts +1 -0
  68. package/components/ui/Rating/Rating.module.css +99 -0
  69. package/components/ui/Rating/Rating.tsx +123 -0
  70. package/components/ui/Rating/index.ts +2 -0
  71. package/components/ui/Select/Select.module.css +371 -0
  72. package/components/ui/Select/Select.tsx +507 -0
  73. package/components/ui/Select/index.ts +2 -0
  74. package/components/ui/SidebarNavigation/SidebarDual.tsx +71 -0
  75. package/components/ui/SidebarNavigation/SidebarFeatureCard.module.css +351 -0
  76. package/components/ui/SidebarNavigation/SidebarFeatureCard.tsx +388 -0
  77. package/components/ui/SidebarNavigation/SidebarNavigation.module.css +610 -0
  78. package/components/ui/SidebarNavigation/SidebarParts.tsx +215 -0
  79. package/components/ui/SidebarNavigation/SidebarSectionDividers.tsx +46 -0
  80. package/components/ui/SidebarNavigation/SidebarSectionHeadings.tsx +52 -0
  81. package/components/ui/SidebarNavigation/SidebarSimple.tsx +46 -0
  82. package/components/ui/SidebarNavigation/SidebarSlim.tsx +48 -0
  83. package/components/ui/SidebarNavigation/index.ts +29 -0
  84. package/components/ui/SidebarNavigation/types.ts +27 -0
  85. package/components/ui/Slider/Slider.module.css +93 -0
  86. package/components/ui/Slider/Slider.tsx +118 -0
  87. package/components/ui/Slider/index.ts +2 -0
  88. package/components/ui/SocialButton/SocialButton.module.css +223 -0
  89. package/components/ui/SocialButton/SocialButton.tsx +185 -0
  90. package/components/ui/SocialButton/index.ts +2 -0
  91. package/components/ui/Tag/Tag.module.css +203 -0
  92. package/components/ui/Tag/Tag.tsx +161 -0
  93. package/components/ui/Tag/index.ts +2 -0
  94. package/components/ui/TextEditor/TextEditor.module.css +182 -0
  95. package/components/ui/TextEditor/TextEditor.tsx +323 -0
  96. package/components/ui/TextEditor/index.ts +1 -0
  97. package/components/ui/Textarea/Textarea.module.css +75 -0
  98. package/components/ui/Textarea/Textarea.tsx +59 -0
  99. package/components/ui/Textarea/index.ts +2 -0
  100. package/components/ui/Toggle/Toggle.module.css +118 -0
  101. package/components/ui/Toggle/Toggle.tsx +77 -0
  102. package/components/ui/Toggle/index.ts +2 -0
  103. package/components/ui/Tooltip/Tooltip.module.css +95 -0
  104. package/components/ui/Tooltip/Tooltip.tsx +55 -0
  105. package/components/ui/Tooltip/index.ts +2 -0
  106. package/components/ui/VideoPlayer/VideoPlayer.module.css +120 -0
  107. package/components/ui/VideoPlayer/VideoPlayer.tsx +229 -0
  108. package/components/ui/VideoPlayer/index.ts +2 -0
  109. package/lib/cn.ts +3 -0
  110. package/lib/copy-to-clipboard.ts +21 -0
  111. package/package.json +61 -0
@@ -0,0 +1,388 @@
1
+ "use client";
2
+
3
+ import { useState, useCallback } from "react";
4
+ import { CloseCircle, Copy, TickCircle, Calendar, Star1, Flash, MessageText1, Scan, Gift, Headphones, Crown1, Clock } from "iconsax-react";
5
+ import { cn } from "@/lib/cn";
6
+ import { Button } from "@/components/ui/Button";
7
+ import { Badge } from "@/components/ui/Badge";
8
+ import { copyToClipboard } from "@/lib/copy-to-clipboard";
9
+ import styles from "./SidebarFeatureCard.module.css";
10
+
11
+ /* ── 1. Progress ── */
12
+ export function FeatureCardProgress({
13
+ title = "Profile completion",
14
+ percent = 65,
15
+ description = "Complete your profile to unlock all features.",
16
+ }: {
17
+ title?: string;
18
+ percent?: number;
19
+ description?: string;
20
+ }) {
21
+ return (
22
+ <div className={styles.card}>
23
+ <div className={styles.header}>
24
+ <div className={styles.headerLeft}>
25
+ <span className={styles.title}>{title}</span>
26
+ <span className={styles.description}>{description}</span>
27
+ </div>
28
+ </div>
29
+ <div className={styles.progressWrap}>
30
+ <div className={styles.progressTrack}>
31
+ <div className={styles.progressFill} style={{ width: `${percent}%` }} />
32
+ </div>
33
+ <div className={styles.progressMeta}>
34
+ <span className={styles.progressPercent}>{percent}%</span>
35
+ <span className={styles.progressLabel}>completed</span>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ );
40
+ }
41
+
42
+ /* ── 2. Progress with Code ── */
43
+ export function FeatureCardProgressCode({
44
+ title = "Storage used",
45
+ percent = 42,
46
+ used = "4.2 GB",
47
+ total = "10 GB",
48
+ }: {
49
+ title?: string;
50
+ percent?: number;
51
+ used?: string;
52
+ total?: string;
53
+ }) {
54
+ return (
55
+ <div className={styles.card}>
56
+ <span className={styles.title}>{title}</span>
57
+ <div className={styles.progressWrap}>
58
+ <div className={styles.progressTrack}>
59
+ <div className={styles.progressFill} style={{ width: `${percent}%` }} />
60
+ </div>
61
+ <div className={styles.progressMeta}>
62
+ <span className={styles.progressPercent}>{used}</span>
63
+ <span className={styles.progressLabel}>of {total}</span>
64
+ </div>
65
+ </div>
66
+ <Button variant="secondary" size="sm" fullWidth>Manage storage</Button>
67
+ </div>
68
+ );
69
+ }
70
+
71
+ /* ── 3. Image Banner ── */
72
+ export function FeatureCardImage({
73
+ title = "New feature available",
74
+ description = "Check out our latest update with improved performance and new tools.",
75
+ }: {
76
+ title?: string;
77
+ description?: string;
78
+ }) {
79
+ const [dismissed, setDismissed] = useState(false);
80
+ if (dismissed) return null;
81
+
82
+ return (
83
+ <div className={styles.card}>
84
+ <div className={styles.imageBanner} />
85
+ <div className={styles.header}>
86
+ <div className={styles.headerLeft}>
87
+ <span className={styles.title}>{title}</span>
88
+ <span className={styles.description}>{description}</span>
89
+ </div>
90
+ <button className={styles.dismiss} onClick={() => setDismissed(true)} type="button" aria-label="Dismiss">
91
+ <CloseCircle size={16} variant="Bulk" color="currentColor" />
92
+ </button>
93
+ </div>
94
+ <div className={styles.actions}>
95
+ <Button variant="primary" size="sm">Learn more</Button>
96
+ <Button variant="ghost" size="sm" onClick={() => setDismissed(true)}>Dismiss</Button>
97
+ </div>
98
+ </div>
99
+ );
100
+ }
101
+
102
+ /* ── 4. Cookie ── */
103
+ export function FeatureCardCookie() {
104
+ const [dismissed, setDismissed] = useState(false);
105
+ if (dismissed) return null;
106
+
107
+ return (
108
+ <div className={styles.card}>
109
+ <div className={styles.header}>
110
+ <div className={styles.iconWrap}>
111
+ <Scan size={18} variant="Bulk" color="var(--color-lime)" />
112
+ </div>
113
+ <button className={styles.dismiss} onClick={() => setDismissed(true)} type="button" aria-label="Dismiss">
114
+ <CloseCircle size={16} variant="Bulk" color="currentColor" />
115
+ </button>
116
+ </div>
117
+ <span className={styles.title}>Cookie preferences</span>
118
+ <p className={styles.cookieText}>
119
+ We use cookies to improve your experience. Read our{" "}
120
+ <span className={styles.cookieLink}>privacy policy</span>.
121
+ </p>
122
+ <div className={styles.actions}>
123
+ <Button variant="primary" size="sm" onClick={() => setDismissed(true)}>Accept all</Button>
124
+ <Button variant="ghost" size="sm" onClick={() => setDismissed(true)}>Reject</Button>
125
+ </div>
126
+ </div>
127
+ );
128
+ }
129
+
130
+ /* ── 5. Referral Link ── */
131
+ export function FeatureCardReferral({
132
+ code = "https://omnira.space/ref/abc123",
133
+ }: {
134
+ code?: string;
135
+ }) {
136
+ const [copied, setCopied] = useState(false);
137
+
138
+ const handleCopy = useCallback(() => {
139
+ copyToClipboard(code);
140
+ setCopied(true);
141
+ setTimeout(() => setCopied(false), 2000);
142
+ }, [code]);
143
+
144
+ return (
145
+ <div className={styles.card}>
146
+ <div className={styles.header}>
147
+ <div className={cn(styles.iconWrap, styles.iconWrapAccent)}>
148
+ <Gift size={18} variant="Bulk" color="var(--color-lime)" />
149
+ </div>
150
+ </div>
151
+ <span className={styles.title}>Refer a friend</span>
152
+ <span className={styles.description}>Share your link and earn rewards for each signup.</span>
153
+ <div className={styles.codeBox}>
154
+ <span className={styles.codeText}>{code}</span>
155
+ <button className={styles.codeCopy} onClick={handleCopy} type="button" aria-label="Copy link">
156
+ {copied
157
+ ? <TickCircle size={14} variant="Bulk" color="var(--color-lime)" />
158
+ : <Copy size={14} variant="Bulk" color="currentColor" />
159
+ }
160
+ </button>
161
+ </div>
162
+ </div>
163
+ );
164
+ }
165
+
166
+ /* ── 6. Onboarding ── */
167
+ export function FeatureCardOnboarding({
168
+ steps = [
169
+ { label: "Create account", done: true },
170
+ { label: "Set up profile", done: true },
171
+ { label: "Invite team members", done: false },
172
+ { label: "Create first project", done: false },
173
+ ],
174
+ }: {
175
+ steps?: { label: string; done: boolean }[];
176
+ }) {
177
+ const completed = steps.filter((s) => s.done).length;
178
+ const total = steps.length;
179
+
180
+ return (
181
+ <div className={styles.card}>
182
+ <span className={styles.title}>Getting started</span>
183
+ <span className={styles.description}>{completed} of {total} steps completed</span>
184
+ <div className={styles.progressWrap}>
185
+ <div className={styles.progressTrack}>
186
+ <div className={styles.progressFill} style={{ width: `${(completed / total) * 100}%` }} />
187
+ </div>
188
+ </div>
189
+ <div className={styles.steps}>
190
+ {steps.map((step) => (
191
+ <div key={step.label} className={cn(styles.step, step.done && styles.stepDone)}>
192
+ <span className={cn(styles.stepCheck, step.done && styles.stepCheckDone)}>
193
+ {step.done && <TickCircle size={12} variant="Bulk" color="currentColor" />}
194
+ </span>
195
+ {step.label}
196
+ </div>
197
+ ))}
198
+ </div>
199
+ </div>
200
+ );
201
+ }
202
+
203
+ /* ── 7. Upgrade ── */
204
+ export function FeatureCardUpgrade({
205
+ title = "Upgrade to Pro",
206
+ description = "Unlock unlimited projects, advanced analytics, and priority support.",
207
+ }: {
208
+ title?: string;
209
+ description?: string;
210
+ }) {
211
+ return (
212
+ <div className={cn(styles.card, styles.cardAccent)}>
213
+ <div className={cn(styles.iconWrap, styles.iconWrapAccent)}>
214
+ <Crown1 size={18} variant="Bulk" color="var(--color-lime)" />
215
+ </div>
216
+ <span className={styles.title}>{title}</span>
217
+ <span className={styles.description}>{description}</span>
218
+ <Button variant="accent" size="sm" fullWidth>Upgrade now</Button>
219
+ </div>
220
+ );
221
+ }
222
+
223
+ /* ── 8. Support ── */
224
+ export function FeatureCardSupport({
225
+ title = "Need help?",
226
+ description = "Our support team is available 24/7 to assist you.",
227
+ }: {
228
+ title?: string;
229
+ description?: string;
230
+ }) {
231
+ return (
232
+ <div className={styles.card}>
233
+ <div className={styles.iconWrap}>
234
+ <Headphones size={18} variant="Bulk" color="var(--color-lime)" />
235
+ </div>
236
+ <span className={styles.title}>{title}</span>
237
+ <span className={styles.description}>{description}</span>
238
+ <div className={styles.actions}>
239
+ <Button variant="primary" size="sm">Contact us</Button>
240
+ <Button variant="ghost" size="sm">View docs</Button>
241
+ </div>
242
+ </div>
243
+ );
244
+ }
245
+
246
+ /* ── 9. Event CTA ── */
247
+ export function FeatureCardEvent({
248
+ title = "Design Systems Workshop",
249
+ date = "Mar 15, 2026 · 2:00 PM",
250
+ description = "Join us for a live workshop on building scalable design systems.",
251
+ }: {
252
+ title?: string;
253
+ date?: string;
254
+ description?: string;
255
+ }) {
256
+ return (
257
+ <div className={styles.card}>
258
+ <div className={styles.header}>
259
+ <div className={styles.iconWrap}>
260
+ <Calendar size={18} variant="Bulk" color="var(--color-lime)" />
261
+ </div>
262
+ <Badge variant="accent" size="sm">Upcoming</Badge>
263
+ </div>
264
+ <span className={styles.title}>{title}</span>
265
+ <div className={styles.eventDate}>
266
+ <Clock size={12} variant="Bulk" color="var(--color-text-tertiary)" />
267
+ {date}
268
+ </div>
269
+ <span className={styles.description}>{description}</span>
270
+ <Button variant="primary" size="sm" fullWidth>Register now</Button>
271
+ </div>
272
+ );
273
+ }
274
+
275
+ /* ── 10. Message ── */
276
+ export function FeatureCardMessage({
277
+ name = "Sarah Chen",
278
+ initials = "SC",
279
+ time = "2 min ago",
280
+ message = "Hey! Just pushed the new sidebar components. Can you review the PR when you get a chance?",
281
+ }: {
282
+ name?: string;
283
+ initials?: string;
284
+ time?: string;
285
+ message?: string;
286
+ }) {
287
+ return (
288
+ <div className={styles.card}>
289
+ <div className={styles.avatarRow}>
290
+ <div className={styles.avatarCircle}>{initials}</div>
291
+ <div className={styles.avatarInfo}>
292
+ <span className={styles.avatarName}>{name}</span>
293
+ <span className={styles.avatarMeta}>{time}</span>
294
+ </div>
295
+ </div>
296
+ <p className={styles.messagePreview}>{message}</p>
297
+ <div className={styles.actions}>
298
+ <Button variant="primary" size="sm">Reply</Button>
299
+ <Button variant="ghost" size="sm">Mark read</Button>
300
+ </div>
301
+ </div>
302
+ );
303
+ }
304
+
305
+ /* ── 11. Current Project ── */
306
+ export function FeatureCardCurrentProject({
307
+ name = "Omnira UI",
308
+ description = "Component library",
309
+ status = "In progress",
310
+ }: {
311
+ name?: string;
312
+ description?: string;
313
+ status?: string;
314
+ }) {
315
+ return (
316
+ <div className={styles.card}>
317
+ <div className={styles.header}>
318
+ <div className={styles.headerLeft}>
319
+ <span className={styles.label}>Current project</span>
320
+ <span className={styles.title}>{name}</span>
321
+ <span className={styles.description}>{description}</span>
322
+ </div>
323
+ <div className={cn(styles.iconWrap, styles.iconWrapAccent)}>
324
+ <Flash size={18} variant="Bulk" color="var(--color-lime)" />
325
+ </div>
326
+ </div>
327
+ <div className={styles.tagRow}>
328
+ <Badge variant="success" dot size="sm">{status}</Badge>
329
+ <Badge variant="section" size="sm">v2.1.0</Badge>
330
+ </div>
331
+ <Button variant="secondary" size="sm" fullWidth>Open project</Button>
332
+ </div>
333
+ );
334
+ }
335
+
336
+ /* ── 12. Free Trial ── */
337
+ export function FeatureCardFreeTrial({
338
+ daysLeft = 7,
339
+ title = "Free trial ending soon",
340
+ description = "Upgrade now to keep access to all premium features.",
341
+ }: {
342
+ daysLeft?: number;
343
+ title?: string;
344
+ description?: string;
345
+ }) {
346
+ return (
347
+ <div className={cn(styles.card, styles.cardAccent)}>
348
+ <div className={styles.header}>
349
+ <div className={cn(styles.iconWrap, styles.iconWrapAccent)}>
350
+ <Star1 size={18} variant="Bulk" color="var(--color-lime)" />
351
+ </div>
352
+ </div>
353
+ <div className={styles.trialCountdown}>
354
+ <span className={styles.trialNumber}>{daysLeft}</span>
355
+ <span className={styles.trialUnit}>days remaining</span>
356
+ </div>
357
+ <span className={styles.title}>{title}</span>
358
+ <span className={styles.description}>{description}</span>
359
+ <div className={cn(styles.actions, styles.actionsFull)}>
360
+ <Button variant="accent" size="sm" fullWidth>Upgrade to Pro</Button>
361
+ <Button variant="ghost" size="sm" fullWidth>Compare plans</Button>
362
+ </div>
363
+ </div>
364
+ );
365
+ }
366
+
367
+ /* ── 13. QR Code ── */
368
+ export function FeatureCardQRCode({
369
+ title = "Download the app",
370
+ description = "Scan the QR code to get our mobile app.",
371
+ }: {
372
+ title?: string;
373
+ description?: string;
374
+ }) {
375
+ return (
376
+ <div className={styles.card}>
377
+ <span className={styles.title}>{title}</span>
378
+ <span className={styles.description}>{description}</span>
379
+ <div className={styles.qrPlaceholder}>
380
+ <MessageText1 size={32} variant="Bulk" color="var(--color-text-tertiary)" />
381
+ </div>
382
+ <div className={styles.actions}>
383
+ <Button variant="secondary" size="sm" fullWidth>App Store</Button>
384
+ <Button variant="secondary" size="sm" fullWidth>Google Play</Button>
385
+ </div>
386
+ </div>
387
+ );
388
+ }