@nautui/core 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 (54) hide show
  1. package/README.md +148 -0
  2. package/package.json +35 -0
  3. package/src/components/Accordion.astro +24 -0
  4. package/src/components/AccordionItem.astro +172 -0
  5. package/src/components/Background.astro +75 -0
  6. package/src/components/Badge.astro +140 -0
  7. package/src/components/Bento.astro +37 -0
  8. package/src/components/BentoItem.astro +26 -0
  9. package/src/components/Box.astro +189 -0
  10. package/src/components/Breadcrumb.astro +62 -0
  11. package/src/components/Button.astro +273 -0
  12. package/src/components/Card.astro +228 -0
  13. package/src/components/Container.astro +76 -0
  14. package/src/components/Divider.astro +85 -0
  15. package/src/components/Drawer.astro +139 -0
  16. package/src/components/Flex.astro +150 -0
  17. package/src/components/Flow.astro +119 -0
  18. package/src/components/Grid.astro +335 -0
  19. package/src/components/GridItem.astro +225 -0
  20. package/src/components/Group.astro +106 -0
  21. package/src/components/Image.astro +191 -0
  22. package/src/components/Link.astro +118 -0
  23. package/src/components/List.astro +57 -0
  24. package/src/components/ListItem.astro +31 -0
  25. package/src/components/Mark.astro +161 -0
  26. package/src/components/Marquee.astro +193 -0
  27. package/src/components/Masonry.astro +75 -0
  28. package/src/components/MasonryItem.astro +28 -0
  29. package/src/components/Menu.astro +71 -0
  30. package/src/components/MenuItem.astro +93 -0
  31. package/src/components/NavBar.astro +211 -0
  32. package/src/components/Section.astro +108 -0
  33. package/src/components/Space.astro +400 -0
  34. package/src/components/Stack.astro +237 -0
  35. package/src/components/Text.astro +270 -0
  36. package/src/components/Theme.astro +37 -0
  37. package/src/components/ThemeToggle.astro +141 -0
  38. package/src/components/Title.astro +141 -0
  39. package/src/index.d.ts +80 -0
  40. package/src/index.ts +77 -0
  41. package/src/lib/border.ts +92 -0
  42. package/src/lib/pattern.ts +37 -0
  43. package/src/lib/spacing.ts +48 -0
  44. package/src/styles/border.css +180 -0
  45. package/src/styles/colors.css +99 -0
  46. package/src/styles/global.css +57 -0
  47. package/src/styles/radius.css +22 -0
  48. package/src/styles/shadow.css +11 -0
  49. package/src/styles/spacing/display.css +198 -0
  50. package/src/styles/spacing/gap.css +19 -0
  51. package/src/styles/spacing/margin.css +157 -0
  52. package/src/styles/spacing/padding.css +154 -0
  53. package/src/styles/spacing/spacing.css +2 -0
  54. package/src/types.ts +10 -0
@@ -0,0 +1,228 @@
1
+ ---
2
+ import "../styles/spacing/padding.css";
3
+ import "../styles/border.css";
4
+ import "../styles/shadow.css";
5
+ import { type Border, createBorder } from "../lib/border";
6
+ import {
7
+ extractSpacingProps,
8
+ getSpacingClasses,
9
+ PaddingProps,
10
+ } from "../lib/spacing";
11
+ import type { Base, Radius } from "../types";
12
+
13
+ export interface CardProps extends Base, PaddingProps {
14
+ border?: Border;
15
+ fluid?: boolean;
16
+ hover?:
17
+ | "surface"
18
+ | "primary"
19
+ | "outline"
20
+ | "outline-primary"
21
+ | "elevate"
22
+ | "elevate-lg"
23
+ | "elevate-xl";
24
+ radius?: Radius | "none";
25
+ shadow?: "sm" | "md" | "lg" | "xl";
26
+ size?: "sm" | "md" | "lg";
27
+ variant?:
28
+ | "ghost"
29
+ | "surface"
30
+ | "light"
31
+ | "dark"
32
+ | "primary"
33
+ | "outline-primary"
34
+ | "rainbow";
35
+ }
36
+
37
+ const { padding, nonSpacing } = extractSpacingProps(Astro.props as CardProps);
38
+
39
+ const {
40
+ class: className,
41
+ border,
42
+ shadow,
43
+ radius,
44
+ size = "sm",
45
+ fluid = false,
46
+ variant = "ghost",
47
+ hover,
48
+ ...rest
49
+ } = nonSpacing;
50
+ const p = Object.keys(padding).length === 0 ? "md" : padding.p;
51
+ const paddingClasses = getSpacingClasses({ ...padding, p });
52
+ const config = typeof border === "string" ? { width: border } : border || {};
53
+ const { borderClasses, borderColors } = createBorder(config);
54
+ ---
55
+
56
+ <div
57
+ class:list={[
58
+ "naut-card",
59
+ size && `size-${size}`,
60
+ fluid && "fluid",
61
+ variant !== "ghost" && `variant-${variant}`,
62
+ hover && `hover-${hover}`,
63
+ radius && `radius-${radius}`,
64
+ shadow && `shadow-${shadow}`,
65
+ ...borderClasses,
66
+ className
67
+ ]}
68
+ {...rest}
69
+ >
70
+ <div class="naut-card--header"><slot name="header" /></div>
71
+ <div class:list={["naut-card--body", ...paddingClasses]}><slot /></div>
72
+ <div class="naut-card--footer"><slot name="footer" /></div>
73
+ </div>
74
+
75
+ <style define:vars={{ ...borderColors }}>
76
+ .naut-card {
77
+ --radius-scale: 1.575;
78
+ position: relative;
79
+ box-sizing: border-box;
80
+
81
+ display: flex;
82
+ flex-direction: column;
83
+ overflow: hidden;
84
+ transition: 0.15s ease-in-out;
85
+
86
+ &.size-sm:not(.fluid) {
87
+ max-width: 20rem;
88
+ }
89
+
90
+ &.size-md:not(.fluid) {
91
+ max-width: 30rem;
92
+ }
93
+
94
+ &.size-lg:not(.fluid) {
95
+ max-width: 40rem;
96
+ }
97
+
98
+ &.fluid {
99
+ width: 100%;
100
+ height: 100%;
101
+ }
102
+
103
+ .naut-card--body {
104
+ position: relative;
105
+ }
106
+
107
+ .naut-card--header:empty {
108
+ display: none;
109
+ }
110
+
111
+ .naut-card--footer:empty {
112
+ display: none;
113
+ }
114
+
115
+ &.radius-none {
116
+ border-radius: 0;
117
+ }
118
+
119
+ &.radius-sm {
120
+ border-radius: calc(var(--naut-border-radius-sm) * var(--radius-scale));
121
+ }
122
+
123
+ &.radius-md {
124
+ border-radius: calc(var(--naut-border-radius-md) * var(--radius-scale));
125
+ }
126
+
127
+ &.radius-lg {
128
+ border-radius: calc(var(--naut-border-radius-lg) * var(--radius-scale));
129
+ }
130
+
131
+ &.shadow-sm {
132
+ box-shadow: var(--naut-shadow-sm);
133
+ }
134
+
135
+ &.shadow-md {
136
+ box-shadow: var(--naut-shadow-md);
137
+ }
138
+
139
+ &.shadow-lg {
140
+ box-shadow: var(--naut-shadow-lg);
141
+ }
142
+
143
+ &.shadow-xl {
144
+ box-shadow: var(--naut-shadow-xl);
145
+ }
146
+
147
+ /* variant */
148
+ &.variant-surface {
149
+ background-color: var(--naut-color-surface);
150
+ }
151
+
152
+ &.variant-primary {
153
+ color: var(--naut-color-primary-content);
154
+ background-color: var(--naut-color-primary);
155
+ }
156
+
157
+ &.variant-light {
158
+ background-color: var(--naut-color-light);
159
+ }
160
+
161
+ &.variant-dark {
162
+ color: var(--naut-color-base);
163
+ background-color: var(--naut-color-base-content);
164
+ }
165
+
166
+ &.variant-outline-primary {
167
+ border-color: var(--naut-color-primary);
168
+ border-width: var(--naut-border-width-lg);
169
+ }
170
+
171
+ &.variant-outline-dark {
172
+ border-color: var(--naut-color-text);
173
+ border-width: var(--naut-border-width-lg);
174
+ }
175
+
176
+ &.variant-rainbow {
177
+ background:
178
+ linear-gradient(var(--naut-color-base), var(--naut-color-base))
179
+ padding-box,
180
+ conic-gradient(
181
+ from 0turn,
182
+ hsl(110 90% 50%),
183
+ hsl(210 90% 60%),
184
+ hsl(220 70% 60%),
185
+ hsl(30 70% 60%),
186
+ hsl(100 90% 50%)
187
+ )
188
+ border-box;
189
+ border-color: transparent;
190
+ border-style: solid;
191
+ border-width: var(--naut-border-width-lg);
192
+ }
193
+
194
+ /* --- hover --- */
195
+
196
+ &.hover-primary:hover {
197
+ color: var(--naut-color-base);
198
+ background-color: var(--naut-color-primary);
199
+ }
200
+
201
+ &.hover-outline:hover {
202
+ border-color: var(--naut-color-border-outline);
203
+ }
204
+
205
+ &.hover-outline-primary:hover {
206
+ border-color: var(--naut-color-primary);
207
+ }
208
+
209
+ &.hover-surface:hover {
210
+ background-color: var(--naut-color-base-100);
211
+ }
212
+
213
+ &.hover-elevate:hover {
214
+ box-shadow: var(--naut-shadow-md);
215
+ transform: translateY(-5px);
216
+ }
217
+
218
+ &.hover-elevate-lg:hover {
219
+ box-shadow: var(--naut-shadow-lg);
220
+ transform: translateY(-5px);
221
+ }
222
+
223
+ &.hover-elevate-xl:hover {
224
+ box-shadow: var(--naut-shadow-xl);
225
+ transform: translateY(-10px);
226
+ }
227
+ }
228
+ </style>
@@ -0,0 +1,76 @@
1
+ ---
2
+ import type { Base } from "../types";
3
+
4
+ export interface ContainerProps extends Base {
5
+ flex?: string | number; // allows custom flex values (e.g. "0 1 100%")
6
+ fluid?: boolean; // if true, the container will take the full width of the viewport
7
+ maxWidth?: number;
8
+ }
9
+
10
+ const {
11
+ class: className,
12
+ fluid = false,
13
+ flex,
14
+ maxWidth,
15
+ ...rest
16
+ } = Astro.props as ContainerProps;
17
+
18
+ const isMax = maxWidth !== undefined;
19
+ const maxWidthVar = maxWidth ? maxWidth : "none";
20
+ const flexVar = flex ? flex : "none";
21
+ ---
22
+
23
+ <div
24
+ class:list={[
25
+ "naut-container",
26
+ isMax && "max",
27
+ fluid && "fluid",
28
+ flex && "flex",
29
+ className
30
+ ]}
31
+ {...rest}
32
+ >
33
+ <slot />
34
+ </div>
35
+
36
+ <style define:vars={{ maxWidthVar, flexVar }}>
37
+ .naut-container {
38
+ display: flow-root; /* Prevents margin collapsing */
39
+ padding: 0 var(--naut-spacing-md);
40
+
41
+ &.fluid {
42
+ width: 100%;
43
+ }
44
+
45
+ &.flex {
46
+ flex: var(--flexVar);
47
+ }
48
+
49
+ &:not(.fluid) {
50
+ margin: 0 auto;
51
+ /*Mobile*/
52
+ @media only screen and (min-width: 576px) and (max-width: 817px) {
53
+ max-width: 576px;
54
+ }
55
+
56
+ /* Tablet */
57
+ @media only screen and (min-width: 818px) and (max-width: 1041px) {
58
+ max-width: 768px;
59
+ }
60
+
61
+ /* Desktop */
62
+ @media only screen and (min-width: 1042px) and (max-width: 1249px) {
63
+ max-width: 992px;
64
+ }
65
+
66
+ /* Large Desktop */
67
+ @media only screen and (min-width: 1250px) {
68
+ max-width: 1200px;
69
+ }
70
+ }
71
+
72
+ &.max {
73
+ max-width: var(--maxWidthVar);
74
+ }
75
+ }
76
+ </style>
@@ -0,0 +1,85 @@
1
+ ---
2
+ import "../styles/spacing/margin.css";
3
+ import {
4
+ extractSpacingProps,
5
+ getSpacingClasses,
6
+ MarginProps,
7
+ } from "../lib/spacing";
8
+ import type { Base } from "../types";
9
+
10
+ export interface DividerProps extends Base, MarginProps {
11
+ label?: string;
12
+ orientation?: "horizontal" | "vertical";
13
+ size?: "sm" | "md" | "lg" | "xl";
14
+ variant?: "solid" | "dotted" | "dashed";
15
+ }
16
+
17
+ const { margin, nonSpacing } = extractSpacingProps(Astro.props as DividerProps);
18
+
19
+ const {
20
+ class: className,
21
+ label,
22
+ orientation = "horizontal",
23
+ size = "md",
24
+ variant = "solid",
25
+ } = nonSpacing;
26
+
27
+ const my = margin.my || margin.mt || margin.mb ? undefined : "md";
28
+ const marginClasses = getSpacingClasses({ ...margin, my });
29
+ const borderVar = `var(--naut-border-width-${size}) ${variant} var(--naut-color-border)`;
30
+ ---
31
+
32
+ <div
33
+ class:list={[
34
+ "naut-divider",
35
+ orientation && `${orientation}`,
36
+ size && `size--${size}`,
37
+ variant && `${variant}`,
38
+ label && "with-label",
39
+ ...marginClasses,
40
+ className,
41
+ ]}
42
+ >
43
+ {label && <span class="label">{label}</span>}
44
+ </div>
45
+
46
+ <style define:vars={{ borderVar, margin }}>
47
+ .naut-divider {
48
+ display: flex;
49
+ align-items: center;
50
+
51
+ &::before {
52
+ flex: 1;
53
+ content: "";
54
+ border-top: var(--borderVar);
55
+ }
56
+
57
+ &::after {
58
+ flex: 1;
59
+ content: "";
60
+ border-top: var(--borderVar);
61
+ }
62
+
63
+ &.with-label {
64
+ &::before {
65
+ margin-inline-end: var(--naut-spacing-md);
66
+ }
67
+ &::after {
68
+ margin-inline-start: var(--naut-spacing-md);
69
+ }
70
+ }
71
+
72
+ &.horizontal {
73
+ height: 1px;
74
+ }
75
+
76
+ &.vertical {
77
+ width: 1px;
78
+ }
79
+
80
+ .label {
81
+ font-size: var(--naut-font-size-sm);
82
+ color: var(--naut-color-content-soft);
83
+ }
84
+ }
85
+ </style>
@@ -0,0 +1,139 @@
1
+ ---
2
+ import type { Base } from "../types";
3
+ import Button from "./Button.astro";
4
+
5
+ export interface DrawerProps extends Base {
6
+ hidden?: "mobile" | "tablet" | "desktop" | "large-desktop";
7
+ zIndex?: number;
8
+ }
9
+
10
+ const { hidden = "desktop", zIndex = 999 } = Astro.props as DrawerProps;
11
+ ---
12
+
13
+ <div class:list={["naut-drawer-toggle", `hidden--${hidden}`]}>
14
+ <Button variant="ghost" onclick="toggleMenu()">
15
+ <svg
16
+ xmlns="http://www.w3.org/2000/svg"
17
+ width="24"
18
+ height="24"
19
+ viewBox="0 0 24 24"
20
+ fill="none"
21
+ stroke="currentColor"
22
+ stroke-width="1.7"
23
+ stroke-linecap="round"
24
+ stroke-linejoin="round"
25
+ class="lucide lucide-menu-icon lucide-menu"
26
+ >
27
+ <title>Menu</title>
28
+ <g class="menu-icon">
29
+ <path d="M4 5h16" />
30
+ <path d="M4 12h16" />
31
+ <path d="M4 19h16" />
32
+ </g>
33
+ </svg>
34
+ </Button>
35
+ </div>
36
+ <div id="naut-drawer">
37
+ <header class="naut-drawer-header">
38
+ <Button variant="ghost" id="close-btn" onclick="toggleMenu()">
39
+ <svg
40
+ xmlns="http://www.w3.org/2000/svg"
41
+ width="24"
42
+ height="24"
43
+ viewBox="0 0 24 24"
44
+ fill="none"
45
+ stroke="currentColor"
46
+ stroke-width="1.7"
47
+ stroke-linecap="round"
48
+ stroke-linejoin="round"
49
+ class="lucide lucide-x"
50
+ >
51
+ <title>Close</title>
52
+ <path d="M18 6 6 18" />
53
+ <path d="m6 6 12 12" />
54
+ </svg>
55
+ </Button>
56
+ </header>
57
+ <div class="naut-drawer-content"><slot /></div>
58
+ </div>
59
+
60
+ <script is:inline>
61
+ const toggleMenu = () => {
62
+ const drawer = document.querySelector("#naut-drawer");
63
+ if (drawer) {
64
+ drawer.classList.toggle("active");
65
+ document.body.appendChild(drawer);
66
+ // disable scroll
67
+ document.body.style.overflow =
68
+ document.body.style.overflow === "hidden" ? "auto" : "hidden";
69
+ }
70
+ };
71
+ </script>
72
+
73
+ <style define:vars={{ zIndex }}>
74
+ .naut-drawer-toggle {
75
+ display: inline-block;
76
+
77
+ &.hidden--mobile {
78
+ @media only screen and (min-width: 576px) {
79
+ display: none;
80
+ }
81
+ }
82
+
83
+ &.hidden--tablet {
84
+ @media only screen and (min-width: 818px) {
85
+ display: none;
86
+ }
87
+ }
88
+
89
+ &.hidden--desktop {
90
+ @media only screen and (min-width: 1042px) {
91
+ display: none;
92
+ }
93
+ }
94
+
95
+ &.only--desktop-large {
96
+ @media only screen and (min-width: 1250px) {
97
+ display: none;
98
+ }
99
+ }
100
+ }
101
+
102
+ #naut-drawer {
103
+ position: fixed;
104
+ top: 0;
105
+ right: 0;
106
+ bottom: 0;
107
+ left: 0;
108
+ z-index: var(--zIndex);
109
+ visibility: hidden;
110
+ overflow: hidden;
111
+ color: var(--naut-color-content);
112
+ background: rgb(
113
+ from var(--naut-color-base) r g b /
114
+ 0.7
115
+ ); /* Semi-transparent color */
116
+ opacity: 0;
117
+ -webkit-backdrop-filter: blur(5px); /* Required for Safari support */
118
+ backdrop-filter: blur(5px); /* Blurs what's behind this box */
119
+ transition:
120
+ opacity 0.4s ease-in-out,
121
+ visibility 0.4s ease-in-out;
122
+
123
+ &.active {
124
+ visibility: visible;
125
+ opacity: 1;
126
+ }
127
+
128
+ #close-btn {
129
+ position: absolute;
130
+ top: 1rem;
131
+ right: 1.2rem;
132
+ z-index: 12;
133
+ }
134
+
135
+ .naut-drawer-content {
136
+ padding: var(--naut-spacing-md);
137
+ }
138
+ }
139
+ </style>
@@ -0,0 +1,150 @@
1
+ ---
2
+ import "../styles/spacing/gap.css";
3
+ import { Base, Gap, Responsive } from "../types";
4
+
5
+ type Direction = "row" | "column";
6
+ type ResponsiveDirection = {
7
+ [key in Responsive]: Direction;
8
+ };
9
+
10
+ export interface FlexProps extends Base {
11
+ align?: "start" | "center" | "end" | "baseline" | "stretch";
12
+ direction?: Direction | ResponsiveDirection;
13
+ gap?: Gap;
14
+ justify?: "start" | "center" | "end" | "between" | "around" | "evenly";
15
+ wrap?: "nowrap" | "wrap" | "wrap-reverse";
16
+ }
17
+
18
+ const {
19
+ class: className,
20
+ direction = "row",
21
+ justify = "start",
22
+ align = "start",
23
+ wrap,
24
+ gap,
25
+ } = Astro.props as FlexProps;
26
+
27
+ const dir =
28
+ typeof direction === "string"
29
+ ? ({ base: direction } as ResponsiveDirection)
30
+ : direction;
31
+ ---
32
+
33
+ <div
34
+ class:list={[
35
+ "naut-flex",
36
+ `justify-${justify}`,
37
+ `align-${align}`,
38
+ `gap-${gap}`,
39
+ dir.base && `dir-${dir}`,
40
+ dir.sm && `sm-dir-${dir.sm}`,
41
+ dir.md && `md-dir-${dir.md}`,
42
+ dir.lg && `lg-dir-${dir.lg}`,
43
+ dir.xl && `xl-dir-${dir.xl}`,
44
+ wrap && `wrap-${wrap}`,
45
+ ]}
46
+ >
47
+ <slot />
48
+ </div>
49
+
50
+ <style>
51
+ .naut-flex {
52
+ display: flex;
53
+
54
+ &.dir-column {
55
+ flex-direction: column;
56
+ }
57
+
58
+ @media only screen and (max-width: 817px) {
59
+ &.sm-dir-row {
60
+ flex-direction: row;
61
+ }
62
+ &.sm-dir-column {
63
+ flex-direction: column;
64
+ }
65
+ }
66
+
67
+ @media only screen and (min-width: 818px) and (max-width: 1041px) {
68
+ &.md-dir-row {
69
+ flex-direction: row;
70
+ }
71
+ &.md-dir-column {
72
+ flex-direction: column;
73
+ }
74
+ }
75
+
76
+ @media only screen and (min-width: 1042px) {
77
+ &.lg-dir-row {
78
+ flex-direction: row;
79
+ }
80
+ &.lg-dir-column {
81
+ flex-direction: column;
82
+ }
83
+ }
84
+
85
+ @media only screen and (min-width: 1250px) {
86
+ &.xl-dir-row {
87
+ flex-direction: row;
88
+ }
89
+ &.xl-dir-column {
90
+ flex-direction: column;
91
+ }
92
+ }
93
+
94
+ &.justify-start {
95
+ justify-content: flex-start;
96
+ }
97
+
98
+ &.justify-center {
99
+ justify-content: center;
100
+ }
101
+
102
+ &.justify-end {
103
+ justify-content: flex-end;
104
+ }
105
+
106
+ &.justify-between {
107
+ justify-content: space-between;
108
+ }
109
+
110
+ &.justify-around {
111
+ justify-content: space-around;
112
+ }
113
+
114
+ &.justify-evenly {
115
+ justify-content: space-evenly;
116
+ }
117
+
118
+ &.align-start {
119
+ align-items: flex-start;
120
+ }
121
+
122
+ &.align-center {
123
+ align-items: center;
124
+ }
125
+
126
+ &.align-end {
127
+ align-items: flex-end;
128
+ }
129
+
130
+ &.align-baseline {
131
+ align-items: baseline;
132
+ }
133
+
134
+ &.align-stretch {
135
+ align-items: stretch;
136
+ }
137
+
138
+ &.wrap-nowrap {
139
+ flex-wrap: nowrap;
140
+ }
141
+
142
+ &.wrap-wrap {
143
+ flex-wrap: wrap;
144
+ }
145
+
146
+ &.wrap-wrap-reverse {
147
+ flex-wrap: wrap-reverse;
148
+ }
149
+ }
150
+ </style>