@jusankar/moon 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 (41) hide show
  1. package/README.md +44 -0
  2. package/dist/icons.d.ts +2 -0
  3. package/dist/icons.js +30051 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +3389 -0
  6. package/dist/src/components/alert/alert.d.ts +11 -0
  7. package/dist/src/components/alert/alert.story.d.ts +9 -0
  8. package/dist/src/components/alert/alert.test.d.ts +1 -0
  9. package/dist/src/components/alert/index.d.ts +1 -0
  10. package/dist/src/components/badge/badge.d.ts +10 -0
  11. package/dist/src/components/badge/badge.story.d.ts +10 -0
  12. package/dist/src/components/badge/badge.test.d.ts +1 -0
  13. package/dist/src/components/badge/index.d.ts +1 -0
  14. package/dist/src/components/card/card.d.ts +11 -0
  15. package/dist/src/components/card/card.story.d.ts +9 -0
  16. package/dist/src/components/card/card.test.d.ts +1 -0
  17. package/dist/src/components/card/index.d.ts +1 -0
  18. package/dist/src/icons.d.ts +1 -0
  19. package/dist/src/index.d.ts +3 -0
  20. package/dist/src/tests/vitest.setup.d.ts +7 -0
  21. package/dist/src/utils.d.ts +2 -0
  22. package/dist/vite.config.d.ts +3 -0
  23. package/package.json +132 -0
  24. package/src/components/alert/alert.story.tsx +58 -0
  25. package/src/components/alert/alert.test.tsx +299 -0
  26. package/src/components/alert/alert.tsx +65 -0
  27. package/src/components/alert/index.ts +1 -0
  28. package/src/components/badge/badge.story.tsx +82 -0
  29. package/src/components/badge/badge.test.tsx +189 -0
  30. package/src/components/badge/badge.tsx +43 -0
  31. package/src/components/badge/index.ts +1 -0
  32. package/src/components/card/card.story.tsx +123 -0
  33. package/src/components/card/card.test.tsx +231 -0
  34. package/src/components/card/card.tsx +85 -0
  35. package/src/components/card/index.ts +1 -0
  36. package/src/icons.ts +1 -0
  37. package/src/index.ts +3 -0
  38. package/src/styles/index.css +123 -0
  39. package/src/styles/storybook-only.css +20 -0
  40. package/src/tests/vitest.setup.ts +76 -0
  41. package/src/utils.ts +6 -0
@@ -0,0 +1,85 @@
1
+ import * as React from "react"
2
+ import { cn } from "~/src/utils"
3
+ function Card({
4
+ className,
5
+ size = "default",
6
+ ...props
7
+ }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
8
+ return (
9
+ <div
10
+ data-slot="card"
11
+ data-size={size}
12
+ className={cn("ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className)}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
18
+ return (
19
+ <div
20
+ data-slot="card-header"
21
+ className={cn(
22
+ "gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",
23
+ className
24
+ )}
25
+ {...props}
26
+ />
27
+ )
28
+ }
29
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
30
+ return (
31
+ <div
32
+ data-slot="card-title"
33
+ className={cn("text-base leading-snug font-medium group-data-[size=sm]/card:text-sm", className)}
34
+ {...props}
35
+ />
36
+ )
37
+ }
38
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
39
+ return (
40
+ <div
41
+ data-slot="card-description"
42
+ className={cn("text-muted-foreground text-sm", className)}
43
+ {...props}
44
+ />
45
+ )
46
+ }
47
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
48
+ return (
49
+ <div
50
+ data-slot="card-action"
51
+ className={cn(
52
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
53
+ className
54
+ )}
55
+ {...props}
56
+ />
57
+ )
58
+ }
59
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
60
+ return (
61
+ <div
62
+ data-slot="card-content"
63
+ className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
64
+ {...props}
65
+ />
66
+ )
67
+ }
68
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
69
+ return (
70
+ <div
71
+ data-slot="card-footer"
72
+ className={cn("bg-muted/50 rounded-b-xl border-t p-4 group-data-[size=sm]/card:p-3 flex items-center", className)}
73
+ {...props}
74
+ />
75
+ )
76
+ }
77
+ export {
78
+ Card,
79
+ CardHeader,
80
+ CardFooter,
81
+ CardTitle,
82
+ CardAction,
83
+ CardDescription,
84
+ CardContent,
85
+ }
@@ -0,0 +1 @@
1
+ export * from './card'
package/src/icons.ts ADDED
@@ -0,0 +1 @@
1
+ export * from '@tabler/icons-react'
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './components/alert'
2
+ export * from './components/badge'
3
+ export * from './components/card'
@@ -0,0 +1,123 @@
1
+ @import 'tailwindcss';
2
+ @import 'tw-animate-css';
3
+
4
+ @custom-variant dark (&:is(.dark *));
5
+
6
+ :root {
7
+ --radius: 0.625rem;
8
+ --background: oklch(1 0 0);
9
+ --foreground: oklch(0.145 0 0);
10
+ --card: oklch(1 0 0);
11
+ --card-foreground: oklch(0.145 0 0);
12
+ --popover: oklch(1 0 0);
13
+ --popover-foreground: oklch(0.145 0 0);
14
+ --primary: oklch(0.205 0 0);
15
+ --primary-foreground: oklch(0.985 0 0);
16
+ --secondary: oklch(0.97 0 0);
17
+ --secondary-foreground: oklch(0.205 0 0);
18
+ --muted: oklch(0.97 0 0);
19
+ --muted-foreground: oklch(0.556 0 0);
20
+ --accent: oklch(0.97 0 0);
21
+ --accent-foreground: oklch(0.205 0 0);
22
+ --destructive: oklch(0.577 0.245 27.325);
23
+ --destructive-foreground: oklch(0.985 0 0);
24
+ --border: oklch(0.922 0 0);
25
+ --input: oklch(0.922 0 0);
26
+ --ring: oklch(0.708 0 0);
27
+ --chart-1: oklch(0.646 0.222 41.116);
28
+ --chart-2: oklch(0.6 0.118 184.704);
29
+ --chart-3: oklch(0.398 0.07 227.392);
30
+ --chart-4: oklch(0.828 0.189 84.429);
31
+ --chart-5: oklch(0.769 0.188 70.08);
32
+ --sidebar: oklch(0.985 0 0);
33
+ --sidebar-foreground: oklch(0.145 0 0);
34
+ --sidebar-primary: oklch(0.205 0 0);
35
+ --sidebar-primary-foreground: oklch(0.985 0 0);
36
+ --sidebar-accent: oklch(0.97 0 0);
37
+ --sidebar-accent-foreground: oklch(0.205 0 0);
38
+ --sidebar-border: oklch(0.922 0 0);
39
+ --sidebar-ring: oklch(0.708 0 0);
40
+ }
41
+
42
+ .dark {
43
+ --background: oklch(0.145 0 0);
44
+ --foreground: oklch(0.985 0 0);
45
+ --card: oklch(0.205 0 0);
46
+ --card-foreground: oklch(0.985 0 0);
47
+ --popover: oklch(0.205 0 0);
48
+ --popover-foreground: oklch(0.985 0 0);
49
+ --primary: oklch(0.922 0 0);
50
+ --primary-foreground: oklch(0.205 0 0);
51
+ --secondary: oklch(0.269 0 0);
52
+ --secondary-foreground: oklch(0.985 0 0);
53
+ --muted: oklch(0.269 0 0);
54
+ --muted-foreground: oklch(0.708 0 0);
55
+ --accent: oklch(0.269 0 0);
56
+ --accent-foreground: oklch(0.985 0 0);
57
+ --destructive: oklch(0.704 0.191 22.216);
58
+ --destructive-foreground: oklch(0.985 0 0);
59
+ --border: oklch(1 0 0 / 10%);
60
+ --input: oklch(1 0 0 / 15%);
61
+ --ring: oklch(0.556 0 0);
62
+ --chart-1: oklch(0.488 0.243 264.376);
63
+ --chart-2: oklch(0.696 0.17 162.48);
64
+ --chart-3: oklch(0.769 0.188 70.08);
65
+ --chart-4: oklch(0.627 0.265 303.9);
66
+ --chart-5: oklch(0.645 0.246 16.439);
67
+ --sidebar: oklch(0.205 0 0);
68
+ --sidebar-foreground: oklch(0.985 0 0);
69
+ --sidebar-primary: oklch(0.488 0.243 264.376);
70
+ --sidebar-primary-foreground: oklch(0.985 0 0);
71
+ --sidebar-accent: oklch(0.269 0 0);
72
+ --sidebar-accent-foreground: oklch(0.985 0 0);
73
+ --sidebar-border: oklch(1 0 0 / 10%);
74
+ --sidebar-ring: oklch(0.556 0 0);
75
+ }
76
+
77
+ @theme inline {
78
+ --color-background: var(--background);
79
+ --color-foreground: var(--foreground);
80
+ --color-card: var(--card);
81
+ --color-card-foreground: var(--card-foreground);
82
+ --color-popover: var(--popover);
83
+ --color-popover-foreground: var(--popover-foreground);
84
+ --color-primary: var(--primary);
85
+ --color-primary-foreground: var(--primary-foreground);
86
+ --color-secondary: var(--secondary);
87
+ --color-secondary-foreground: var(--secondary-foreground);
88
+ --color-muted: var(--muted);
89
+ --color-muted-foreground: var(--muted-foreground);
90
+ --color-accent: var(--accent);
91
+ --color-accent-foreground: var(--accent-foreground);
92
+ --color-destructive: var(--destructive);
93
+ --color-destructive-foreground: var(--destructive-foreground);
94
+ --color-border: var(--border);
95
+ --color-input: var(--input);
96
+ --color-ring: var(--ring);
97
+ --color-chart-1: var(--chart-1);
98
+ --color-chart-2: var(--chart-2);
99
+ --color-chart-3: var(--chart-3);
100
+ --color-chart-4: var(--chart-4);
101
+ --color-chart-5: var(--chart-5);
102
+ --radius-sm: calc(var(--radius) - 4px);
103
+ --radius-md: calc(var(--radius) - 2px);
104
+ --radius-lg: var(--radius);
105
+ --radius-xl: calc(var(--radius) + 4px);
106
+ --color-sidebar: var(--sidebar);
107
+ --color-sidebar-foreground: var(--sidebar-foreground);
108
+ --color-sidebar-primary: var(--sidebar-primary);
109
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
110
+ --color-sidebar-accent: var(--sidebar-accent);
111
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
112
+ --color-sidebar-border: var(--sidebar-border);
113
+ --color-sidebar-ring: var(--sidebar-ring);
114
+ }
115
+
116
+ @layer base {
117
+ * {
118
+ @apply border-border outline-ring/50;
119
+ }
120
+ body {
121
+ @apply bg-background text-foreground;
122
+ }
123
+ }
@@ -0,0 +1,20 @@
1
+ @import './index.css';
2
+ @source "../sandbox";
3
+
4
+ /* -------------------------------------------------------------------------- */
5
+ /* Storybook-only layout helpers */
6
+ /* -------------------------------------------------------------------------- */
7
+
8
+ /* Give stories breathing room so "outside" UI isn't clipped/off-canvas */
9
+ .sb-show-main {
10
+ padding-inline: 3rem;
11
+ }
12
+
13
+ /* Carousel nav buttons: position outside slides (Storybook only) */
14
+ .sb-show-main [data-slot='carousel-previous'] {
15
+ left: -3rem !important; /* matches Tailwind -left-12 */
16
+ }
17
+
18
+ .sb-show-main [data-slot='carousel-next'] {
19
+ right: -3rem !important; /* matches Tailwind -right-12 */
20
+ }
@@ -0,0 +1,76 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { expect, afterEach, vi } from 'vitest'
3
+ import { cleanup } from '@testing-library/react'
4
+ import * as matchers from '@testing-library/jest-dom/matchers'
5
+ import * as axeMatchers from 'vitest-axe/matchers'
6
+ import 'vitest-axe/extend-expect'
7
+ import type { AxeMatchers } from 'vitest-axe'
8
+ import '@testing-library/jest-dom'
9
+
10
+ declare module 'vitest' {
11
+ interface Assertion<T = any> extends AxeMatchers {}
12
+ interface AsymmetricMatchersContaining extends AxeMatchers {}
13
+ }
14
+
15
+ expect.extend(matchers)
16
+ expect.extend(axeMatchers)
17
+
18
+ // clean up the DOM after every test to prevent memory leaks
19
+ afterEach(() => {
20
+ cleanup()
21
+ })
22
+
23
+ // mock ResizeObserver (commonly needed for responsive components like Modals/Drawers)
24
+ class ResizeObserverMock {
25
+ observe() {}
26
+ unobserve() {}
27
+ disconnect() {}
28
+ }
29
+
30
+ class MockIntersectionObserver implements IntersectionObserver {
31
+ readonly root: Element | null = null
32
+ readonly rootMargin: string = ''
33
+ readonly thresholds: ReadonlyArray<number> = []
34
+
35
+ constructor(_callback: IntersectionObserverCallback, _options?: IntersectionObserverInit) {}
36
+
37
+ disconnect() {}
38
+ observe(_target: Element) {}
39
+ unobserve(_target: Element) {}
40
+ takeRecords(): IntersectionObserverEntry[] {
41
+ return []
42
+ }
43
+ }
44
+
45
+ global.IntersectionObserver = MockIntersectionObserver
46
+
47
+ global.ResizeObserver = ResizeObserverMock
48
+
49
+ // mock ScrollTo (Jsdom doesn't implement this, often used in Nav/Select components)
50
+ window.scrollTo = vi.fn()
51
+
52
+ Object.defineProperty(window, 'matchMedia', {
53
+ writable: true,
54
+ value: vi.fn().mockImplementation(query => ({
55
+ matches: false,
56
+ media: query,
57
+ onchange: null,
58
+ addListener: vi.fn(),
59
+ removeListener: vi.fn(),
60
+ addEventListener: vi.fn(),
61
+ removeEventListener: vi.fn(),
62
+ dispatchEvent: vi.fn(),
63
+ })),
64
+ })
65
+
66
+ if (!Element.prototype.setPointerCapture) {
67
+ Element.prototype.setPointerCapture = function () {}
68
+ }
69
+ if (!Element.prototype.releasePointerCapture) {
70
+ Element.prototype.releasePointerCapture = function () {}
71
+ }
72
+ if (!Element.prototype.hasPointerCapture) {
73
+ Element.prototype.hasPointerCapture = function () {
74
+ return false
75
+ }
76
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from 'clsx'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }