@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,237 @@
1
+ ---
2
+ import "../styles/spacing/gap.css";
3
+ import type { Base, Gap, Responsive } from "../types";
4
+
5
+ type Align = "inherit" | "start" | "center" | "end" | "stretch";
6
+ type Justify =
7
+ | "start"
8
+ | "center"
9
+ | "end"
10
+ | "space-between"
11
+ | "space-around"
12
+ | "space-evenly";
13
+
14
+ type AlignResponsive = {
15
+ [key in Responsive]?: Align;
16
+ };
17
+
18
+ type JustifyResponsive = {
19
+ [key in Responsive]?: Justify;
20
+ };
21
+
22
+ export interface StackProps extends Base {
23
+ align?: AlignResponsive | Align;
24
+ gap?: Gap;
25
+ justify?: JustifyResponsive | Justify;
26
+ }
27
+
28
+ const {
29
+ class: className,
30
+ align,
31
+ justify = "start",
32
+ gap = "md",
33
+ ...rest
34
+ } = Astro.props as StackProps;
35
+ const items = typeof align === "string" ? { base: align } : align;
36
+ const content = typeof justify === "string" ? { base: justify } : justify;
37
+ ---
38
+
39
+ <div
40
+ class:list={[
41
+ "naut-stack",
42
+ `gap-${gap}`,
43
+ items?.base && `items-${items.base}`,
44
+ items?.sm && `sm-items-${items.sm}`,
45
+ items?.md && `md-items-${items.md}`,
46
+ items?.lg && `lg-items-${items.lg}`,
47
+ items?.xl && `xl-items-${items.xl}`,
48
+ content?.base && `content-${content.base}`,
49
+ content?.sm && `sm-content-${content.sm}`,
50
+ content?.md && `md-content-${content.md}`,
51
+ content?.lg && `lg-content-${content.lg}`,
52
+ content?.xl && `xl-content-${content.xl}`,
53
+ className
54
+ ]}
55
+ {...rest}
56
+ >
57
+ <slot />
58
+ </div>
59
+
60
+ <style>
61
+ .naut-stack {
62
+ display: flex;
63
+ flex-direction: column;
64
+
65
+ &.content-start {
66
+ justify-content: flex-start;
67
+ }
68
+
69
+ &.content-center {
70
+ justify-content: center;
71
+ }
72
+
73
+ &.content-end {
74
+ justify-content: flex-end;
75
+ }
76
+
77
+ &.content-space-between {
78
+ justify-content: space-between;
79
+ }
80
+
81
+ &.content-space-around {
82
+ justify-content: space-around;
83
+ }
84
+
85
+ &.content-space-evenly {
86
+ justify-content: space-evenly;
87
+ }
88
+
89
+ &.items-start {
90
+ align-items: flex-start;
91
+ }
92
+
93
+ &.items-center {
94
+ align-items: center;
95
+ }
96
+
97
+ &.items-end {
98
+ align-items: flex-end;
99
+ }
100
+
101
+ &.items-stretch {
102
+ align-items: stretch;
103
+ }
104
+
105
+ @media only screen and (max-width: 817px) {
106
+ &.sm-content-start {
107
+ justify-content: flex-start;
108
+ }
109
+ &.sm-content-center {
110
+ justify-content: center;
111
+ }
112
+ &.sm-content-end {
113
+ justify-content: flex-end;
114
+ }
115
+ &.sm-content-space-between {
116
+ justify-content: space-between;
117
+ }
118
+ &.sm-content-space-around {
119
+ justify-content: space-around;
120
+ }
121
+ &.sm-content-space-evenly {
122
+ justify-content: space-evenly;
123
+ }
124
+ &.sm-items-start {
125
+ align-items: flex-start;
126
+ }
127
+ &.sm-items-center {
128
+ align-items: center;
129
+ }
130
+ &.sm-items-end {
131
+ align-items: flex-end;
132
+ }
133
+ &.sm-items-stretch {
134
+ align-items: stretch;
135
+ }
136
+ }
137
+
138
+ @media only screen and (min-width: 818px) and (max-width: 1041px) {
139
+ &.md-content-start {
140
+ justify-content: flex-start;
141
+ }
142
+ &.md-content-center {
143
+ justify-content: center;
144
+ }
145
+ &.md-content-end {
146
+ justify-content: flex-end;
147
+ }
148
+ &.md-content-space-between {
149
+ justify-content: space-between;
150
+ }
151
+ &.md-content-space-around {
152
+ justify-content: space-around;
153
+ }
154
+ &.md-content-space-evenly {
155
+ justify-content: space-evenly;
156
+ }
157
+ &.md-items-start {
158
+ align-items: flex-start;
159
+ }
160
+ &.md-items-center {
161
+ align-items: center;
162
+ }
163
+ &.md-items-end {
164
+ align-items: flex-end;
165
+ }
166
+ &.md-items-stretch {
167
+ align-items: stretch;
168
+ }
169
+ }
170
+
171
+ @media only screen and (min-width: 1042px) {
172
+ &.lg-content-start {
173
+ justify-content: flex-start;
174
+ }
175
+ &.lg-content-center {
176
+ justify-content: center;
177
+ }
178
+ &.lg-content-end {
179
+ justify-content: flex-end;
180
+ }
181
+ &.lg-content-space-between {
182
+ justify-content: space-between;
183
+ }
184
+ &.lg-content-space-around {
185
+ justify-content: space-around;
186
+ }
187
+ &.lg-content-space-evenly {
188
+ justify-content: space-evenly;
189
+ }
190
+ &.lg-items-start {
191
+ align-items: flex-start;
192
+ }
193
+ &.lg-items-center {
194
+ align-items: center;
195
+ }
196
+ &.lg-items-end {
197
+ align-items: flex-end;
198
+ }
199
+ &.lg-items-stretch {
200
+ align-items: stretch;
201
+ }
202
+ }
203
+
204
+ @media only screen and (min-width: 1250px) {
205
+ &.xl-content-start {
206
+ justify-content: flex-start;
207
+ }
208
+ &.xl-content-center {
209
+ justify-content: center;
210
+ }
211
+ &.xl-content-end {
212
+ justify-content: flex-end;
213
+ }
214
+ &.xl-content-space-between {
215
+ justify-content: space-between;
216
+ }
217
+ &.xl-content-space-around {
218
+ justify-content: space-around;
219
+ }
220
+ &.xl-content-space-evenly {
221
+ justify-content: space-evenly;
222
+ }
223
+ &.xl-items-start {
224
+ align-items: flex-start;
225
+ }
226
+ &.xl-items-center {
227
+ align-items: center;
228
+ }
229
+ &.xl-items-end {
230
+ align-items: flex-end;
231
+ }
232
+ &.xl-items-stretch {
233
+ align-items: stretch;
234
+ }
235
+ }
236
+ }
237
+ </style>
@@ -0,0 +1,270 @@
1
+ ---
2
+ import "../styles/spacing/margin.css";
3
+ import {
4
+ extractSpacingProps,
5
+ getSpacingClasses,
6
+ MarginProps,
7
+ } from "../lib/spacing";
8
+ import type { Base, Size } from "../types";
9
+
10
+ export interface TextProps extends Base, MarginProps {
11
+ align?: "left" | "center" | "right" | "justify";
12
+ decoration?: "underline" | "strikethrough";
13
+ dimmed?: boolean;
14
+ inline?: boolean;
15
+ italic?: boolean;
16
+ maxWidth?: number | string;
17
+ size?: Size;
18
+ transform?: "capitalize" | "uppercase" | "lowercase";
19
+ weight?: "light" | "normal" | "medium" | "bold" | "semi-bold" | "extra-bold";
20
+ }
21
+
22
+ const { margin, nonSpacing } = extractSpacingProps(Astro.props as TextProps);
23
+
24
+ const {
25
+ class: className,
26
+ weight,
27
+ transform,
28
+ decoration,
29
+ size,
30
+ maxWidth,
31
+ italic = false,
32
+ inline = false,
33
+ dimmed = false,
34
+ align,
35
+ ...rest
36
+ } = nonSpacing;
37
+
38
+ const marginClasses = getSpacingClasses(margin);
39
+
40
+ const maxWidthStyle =
41
+ maxWidth === undefined
42
+ ? undefined
43
+ : `max-width: ${typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth}`;
44
+
45
+ const classList = [
46
+ "text",
47
+ italic && "italic",
48
+ dimmed && "dimmed",
49
+ align && `align-${align}`,
50
+ size && `size-${size}`,
51
+ weight && `weight-${weight}`,
52
+ transform && `transform-${transform}`,
53
+ decoration && `decoration-${decoration}`,
54
+ ...marginClasses,
55
+ className,
56
+ ];
57
+ ---
58
+
59
+ {inline && <span class:list={classList} style={maxWidthStyle} {...rest}><slot /></span>}
60
+ {!inline && <p class:list={classList} style={maxWidthStyle} {...rest}><slot /></p>}
61
+
62
+ <style>
63
+ .text {
64
+ font-family: inherit;
65
+ font-size: inherit;
66
+ line-height: inherit;
67
+
68
+ &::selection {
69
+ color: var(--naut-color-content);
70
+ -webkit-text-fill-color: var(--naut-color-content);
71
+ background-color: var(--naut-color-selection);
72
+ }
73
+
74
+ &.inline {
75
+ display: inline-block;
76
+ }
77
+
78
+ &.italic {
79
+ font-style: italic;
80
+ }
81
+
82
+ &.align-left {
83
+ text-align: left;
84
+ }
85
+
86
+ &.align-center {
87
+ text-align: center;
88
+ }
89
+
90
+ &.align-right {
91
+ text-align: right;
92
+ }
93
+
94
+ &.align-justify {
95
+ text-align: justify;
96
+ }
97
+
98
+ &.dimmed {
99
+ color: var(--naut-color-content-soft);
100
+ }
101
+
102
+ &.size-xs {
103
+ font-size: var(--naut-font-size-xs);
104
+ line-height: calc(
105
+ var(--naut-font-size-xs) *
106
+ var(--naut-line-height-ratio)
107
+ );
108
+ }
109
+
110
+ &.size-sm {
111
+ font-size: var(--naut-font-size-sm);
112
+ line-height: calc(
113
+ var(--naut-font-size-sm) *
114
+ var(--naut-line-height-ratio)
115
+ );
116
+ }
117
+
118
+ &.size-md {
119
+ font-size: var(--naut-font-size-md);
120
+ line-height: calc(
121
+ var(--naut-font-size-md) *
122
+ var(--naut-line-height-ratio)
123
+ );
124
+ }
125
+
126
+ &.size-lg {
127
+ font-size: clamp(1.15rem, 1.5vw + 1rem, var(--naut-font-size-lg));
128
+ line-height: clamp(1.8rem, 2.5vw + 1rem, 2.05rem);
129
+ }
130
+
131
+ &.size-xl {
132
+ font-size: clamp(1.3rem, 1.3vw + 1rem, var(--naut-font-size-xl));
133
+ line-height: clamp(2rem, 2.5vw + 1rem, 2.34rem);
134
+ }
135
+
136
+ &.size-xxl {
137
+ font-size: clamp(1.5rem, 1.5vw + 1rem, var(--naut-font-size-xxl));
138
+ line-height: clamp(2.2rem, 2vw + 1rem, 3.25rem);
139
+ }
140
+
141
+ &.weight-light {
142
+ font-weight: 300;
143
+ }
144
+
145
+ &.weight-medium {
146
+ font-weight: 500;
147
+ }
148
+
149
+ &.weight-bold {
150
+ font-weight: 700;
151
+ }
152
+
153
+ &.weight-semi-bold {
154
+ font-weight: 600;
155
+ }
156
+
157
+ &.weight-extra-bold {
158
+ font-weight: 800;
159
+ }
160
+
161
+ &.transform-capitalize {
162
+ text-transform: capitalize;
163
+ }
164
+ &.transform-uppercase {
165
+ text-transform: uppercase;
166
+ }
167
+ &.transform-lowercase {
168
+ text-transform: lowercase;
169
+ }
170
+
171
+ &.decoration-underline {
172
+ text-decoration: underline;
173
+ }
174
+ &.decoration-strikethrough {
175
+ text-decoration: line-through;
176
+ }
177
+
178
+ /* Margins */
179
+ &.mt-0 {
180
+ margin-top: 0;
181
+ }
182
+ &.mb-0 {
183
+ margin-bottom: 0;
184
+ }
185
+ &.ml-0 {
186
+ margin-left: 0;
187
+ }
188
+ &.mr-0 {
189
+ margin-right: 0;
190
+ }
191
+
192
+ &.mt-xs {
193
+ margin-top: var(--naut-spacing-xs);
194
+ }
195
+ &.mb-xs {
196
+ margin-bottom: var(--naut-spacing-xs);
197
+ }
198
+ &.ml-xs {
199
+ margin-left: var(--naut-spacing-xs);
200
+ }
201
+ &.mr-xs {
202
+ margin-right: var(--naut-spacing-xs);
203
+ }
204
+
205
+ &.mt-sm {
206
+ margin-top: var(--naut-spacing-sm);
207
+ }
208
+ &.mb-sm {
209
+ margin-bottom: var(--naut-spacing-sm);
210
+ }
211
+ &.ml-sm {
212
+ margin-left: var(--naut-spacing-sm);
213
+ }
214
+ &.mr-sm {
215
+ margin-right: var(--naut-spacing-sm);
216
+ }
217
+
218
+ &.mt-md {
219
+ margin-top: var(--naut-spacing-md);
220
+ }
221
+ &.mb-md {
222
+ margin-bottom: var(--naut-spacing-md);
223
+ }
224
+ &.ml-md {
225
+ margin-left: var(--naut-spacing-md);
226
+ }
227
+ &.mr-md {
228
+ margin-right: var(--naut-spacing-md);
229
+ }
230
+
231
+ &.mt-lg {
232
+ margin-top: var(--naut-spacing-lg);
233
+ }
234
+ &.mb-lg {
235
+ margin-bottom: var(--naut-spacing-lg);
236
+ }
237
+ &.ml-lg {
238
+ margin-left: var(--naut-spacing-lg);
239
+ }
240
+ &.mr-lg {
241
+ margin-right: var(--naut-spacing-lg);
242
+ }
243
+
244
+ &.mt-xl {
245
+ margin-top: var(--naut-spacing-xl);
246
+ }
247
+ &.mb-xl {
248
+ margin-bottom: var(--naut-spacing-xl);
249
+ }
250
+ &.ml-xl {
251
+ margin-left: var(--naut-spacing-xl);
252
+ }
253
+ &.mr-xl {
254
+ margin-right: var(--naut-spacing-xl);
255
+ }
256
+ }
257
+
258
+ p.text {
259
+ &:first-child {
260
+ margin-top: 0;
261
+ }
262
+ &:last-child {
263
+ margin-bottom: 0;
264
+ }
265
+ }
266
+
267
+ span.text {
268
+ display: inline-block;
269
+ }
270
+ </style>
@@ -0,0 +1,37 @@
1
+ ---
2
+ import "../styles/global.css";
3
+ import "../styles/colors.css";
4
+ import type { Base } from "../types";
5
+
6
+ export interface ThemeProps extends Base {
7
+ dark?: boolean;
8
+ }
9
+
10
+ const { class: className, dark = true } = Astro.props as ThemeProps;
11
+ ---
12
+
13
+ <Fragment class:list={["naut-theme", className]}> <slot /> </Fragment>
14
+
15
+ <script is:inline define:vars={{ dark }}>
16
+ (() => {
17
+ if (dark) {
18
+ if (window.__nautThemeInitialized) {
19
+ return;
20
+ }
21
+ window.__nautThemeInitialized = true;
22
+
23
+ const getTheme = () => {
24
+ const stored = localStorage.getItem("naut-theme");
25
+ if (["dark", "light"].includes(stored)) {
26
+ return stored;
27
+ }
28
+ return window.matchMedia("(prefers-color-scheme: dark)").matches
29
+ ? "dark"
30
+ : "light";
31
+ };
32
+
33
+ const theme = getTheme();
34
+ document.documentElement.setAttribute("data-theme", theme);
35
+ }
36
+ })();
37
+ </script>
@@ -0,0 +1,141 @@
1
+ ---
2
+ import type { Base } from "../types";
3
+ import Button from "./Button.astro";
4
+
5
+ export interface ThemeToggleProps extends Base {}
6
+
7
+ const { class: className } = Astro.props as ThemeToggleProps;
8
+ ---
9
+
10
+ <Button
11
+ variant="ghost"
12
+ aria-label="Toggle theme"
13
+ onclick="toggleTheme()"
14
+ class:list={["naut-theme-toggle", className]}
15
+ title="Toggle theme"
16
+ >
17
+ <svg
18
+ xmlns="http://www.w3.org/2000/svg"
19
+ width="24"
20
+ height="24"
21
+ viewBox="0 0 24 24"
22
+ fill="none"
23
+ stroke="currentColor"
24
+ stroke-width="2"
25
+ stroke-linecap="round"
26
+ stroke-linejoin="round"
27
+ >
28
+ <title>Sun and Moon</title>
29
+ <g class="naut-theme-toggle--sun">
30
+ <circle cx="12" cy="12" r="4" />
31
+ <path d="M12 2v2" />
32
+ <path d="M12 20v2" />
33
+ <path d="m4.93 4.93 1.41 1.41" />
34
+ <path d="m17.66 17.66 1.41 1.41" />
35
+ <path d="M2 12h2" />
36
+ <path d="M20 12h2" />
37
+ <path d="m6.34 17.66-1.41 1.41" />
38
+ <path d="m19.07 4.93-1.41 1.41" />
39
+ </g>
40
+ <g class="naut-theme-toggle--moon">
41
+ <path
42
+ d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"
43
+ />
44
+ </g>
45
+ </svg>
46
+ </Button>
47
+
48
+ <style>
49
+ .naut-theme-toggle--sun {
50
+ display: block;
51
+ }
52
+
53
+ .naut-theme-toggle--moon {
54
+ display: none;
55
+ }
56
+
57
+ :global([data-theme="dark"]) .naut-theme-toggle--sun {
58
+ display: none;
59
+ }
60
+
61
+ :global([data-theme="dark"]) .naut-theme-toggle--moon {
62
+ display: block;
63
+ }
64
+ </style>
65
+
66
+ <script>
67
+ declare global {
68
+ interface Window {
69
+ setTheme: (theme: string) => void;
70
+ toggleTheme: () => void;
71
+ }
72
+ }
73
+
74
+ // Function to apply theme with naut-theme attribute
75
+ const applyTheme = (theme: string, isUserChoice = true) => {
76
+ document.documentElement.setAttribute("data-theme", theme);
77
+ localStorage.setItem("naut-theme", theme);
78
+ localStorage.setItem("themeSourceType", isUserChoice ? "user" : "system");
79
+ };
80
+
81
+ // Function to handle theme change
82
+ const setTheme = (theme: string) => {
83
+ applyTheme(theme);
84
+ };
85
+
86
+ // Initialize theme on load
87
+ const initializeTheme = () => {
88
+ // Ensure themeSourceType is set if missing
89
+ if (!localStorage.getItem("themeSourceType")) {
90
+ localStorage.setItem("themeSourceType", "system");
91
+ }
92
+ };
93
+
94
+ // Main toggle function
95
+ const toggleTheme = () => {
96
+ const currentTheme =
97
+ document.documentElement.getAttribute("data-theme") ||
98
+ localStorage.getItem("naut-theme") ||
99
+ (window.matchMedia("(prefers-color-scheme: dark)").matches
100
+ ? "dark"
101
+ : "light");
102
+
103
+ const newTheme = currentTheme === "dark" ? "light" : "dark";
104
+
105
+ // Check if the new theme matches system preference
106
+ const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
107
+ .matches
108
+ ? "dark"
109
+ : "light";
110
+
111
+ // Only mark as "user" choice if it differs from system preference
112
+ const isOverridingSystem = newTheme !== systemTheme;
113
+ applyTheme(newTheme, isOverridingSystem);
114
+ };
115
+
116
+ // Listen for system preference changes
117
+ const handleSystemThemeChange = (e: MediaQueryListEvent) => {
118
+ const themeSourceType = localStorage.getItem("themeSourceType");
119
+ const systemTheme = e.matches ? "dark" : "light";
120
+ const currentTheme = localStorage.getItem("naut-theme");
121
+
122
+ if (themeSourceType === "system") {
123
+ // Auto-switch because user hasn't overridden
124
+ applyTheme(systemTheme, false);
125
+ } else if (themeSourceType === "user" && currentTheme === systemTheme) {
126
+ // User's override now matches system preference, so re-enable auto-switching
127
+ localStorage.setItem("themeSourceType", "system");
128
+ }
129
+ };
130
+
131
+ // Set up system preference listener
132
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
133
+ mediaQuery.addEventListener("change", handleSystemThemeChange);
134
+
135
+ // Initialize on load
136
+ initializeTheme();
137
+
138
+ // Expose functions to window
139
+ window.toggleTheme = toggleTheme;
140
+ window.setTheme = setTheme;
141
+ </script>