@adaptive-sm/astro-ui 0.1.1 → 0.3.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 (101) hide show
  1. package/README.md +52 -12
  2. package/lib/badge/Badge.astro +27 -0
  3. package/lib/badge/classesBadge.ts +67 -0
  4. package/lib/button/Button.astro +17 -27
  5. package/lib/button/buttonCva.ts +6 -6
  6. package/lib/button/buttonIconCva.ts +2 -2
  7. package/lib/button/classesButtonClickAnimation.ts +1 -1
  8. package/lib/button/classesButtonClickAnimationPush.ts +1 -1
  9. package/lib/button/classesButtonClickAnimationSquish.ts +1 -1
  10. package/lib/card/CardWrapper.astro +6 -5
  11. package/lib/card/classesBorderWrapper.ts +1 -0
  12. package/lib/card/classesCardWrapper.ts +21 -9
  13. package/lib/card/classesShadow.ts +5 -0
  14. package/lib/details/Details.astro +20 -15
  15. package/lib/dev/TailwindIndicator.astro +2 -2
  16. package/lib/form/Fieldset.astro +8 -5
  17. package/lib/generate_demo_list/DemoList.astro +8 -6
  18. package/lib/generate_demo_list/generateDemoList.ts +2 -2
  19. package/lib/generate_image_list/generateImageList.ts +27 -3
  20. package/lib/grid/FeatureGridSection.astro +73 -0
  21. package/lib/grid/GridFeatureType.ts +5 -0
  22. package/lib/grid/classesGridCols.ts +27 -2
  23. package/lib/header/PageHeader.astro +25 -0
  24. package/lib/header/SectionHeader.astro +37 -0
  25. package/lib/icon/Icon.astro +26 -0
  26. package/lib/icons/iconGithub.ts +4 -0
  27. package/lib/icons/iconGoogle.ts +4 -0
  28. package/lib/icons/iconLinkedin.ts +2 -0
  29. package/lib/icons/iconNpm.ts +2 -0
  30. package/lib/icons/iconTelegram.ts +2 -0
  31. package/lib/icons/iconTrello.ts +2 -0
  32. package/lib/icons/iconXcom.ts +1 -0
  33. package/lib/img/ImageType.ts +1 -0
  34. package/lib/img/Img.astro +10 -7
  35. package/lib/img/TypedImg.astro +15 -13
  36. package/lib/img/TypedImgB2.astro +23 -0
  37. package/lib/img/classInvertBlack.ts +1 -0
  38. package/lib/img/classesImgZoomInOnHover10.ts +1 -0
  39. package/lib/img/classesImgZoomInOnHover5.ts +1 -0
  40. package/lib/layouts/MarkdownPageWrapper.astro +19 -0
  41. package/lib/layouts/MinimalLayout.astro +23 -16
  42. package/lib/layouts/parts/ThemeToggle.astro +10 -10
  43. package/lib/link/LinkButton.astro +18 -19
  44. package/lib/link/LinkText.astro +10 -7
  45. package/lib/link/classesTextLink.ts +1 -1
  46. package/lib/list/BlackBulletPoint.astro +1 -1
  47. package/lib/list/BlackBulletPoints.astro +7 -7
  48. package/lib/list/CheckPoint.astro +3 -3
  49. package/lib/list/CheckPoints.astro +3 -3
  50. package/lib/list/NumberedList.astro +1 -1
  51. package/lib/list/Ps.astro +8 -5
  52. package/lib/list/TextOrLink.astro +3 -9
  53. package/lib/md/MarkdownDiv.astro +18 -0
  54. package/lib/modal/Modal.astro +4 -4
  55. package/lib/modal/ModalButton.astro +24 -11
  56. package/lib/page/PageCentered.astro +5 -3
  57. package/lib/page/PageCenteredCard.astro +7 -5
  58. package/lib/page/{classesBg.ts → classesBg100.ts} +2 -2
  59. package/lib/page/classesBg50.ts +27 -0
  60. package/lib/page/classesPageCentered.ts +1 -1
  61. package/lib/popover/Popover1.astro +4 -4
  62. package/lib/select/Select.astro +14 -10
  63. package/lib/table/Table.astro +2 -2
  64. package/lib/table/TableD.astro +2 -2
  65. package/lib/table/TableM.astro +2 -2
  66. package/lib/table/TableMEntry.astro +2 -2
  67. package/lib/table/tableVisibilityClasses.ts +3 -3
  68. package/lib/utils/HasId.ts +3 -0
  69. package/lib/utils/HasSubtitle.ts +4 -0
  70. package/lib/utils/HasTitle.ts +4 -0
  71. package/lib/utils/MayHaveButtonVariant.ts +5 -0
  72. package/lib/utils/MayHaveClass.ts +3 -0
  73. package/lib/utils/MayHaveIcon.ts +4 -0
  74. package/lib/utils/MayHaveId.ts +3 -0
  75. package/lib/utils/MayHaveInnerClass.ts +3 -0
  76. package/lib/utils/MayHaveSubtitle.ts +4 -0
  77. package/lib/utils/MayHaveTitle.ts +4 -0
  78. package/package.json +19 -14
  79. package/lib/icon/Icon1.astro +0 -21
  80. package/lib/img/classInvertDiagram.ts +0 -1
  81. package/lib/img/classesImgZoomInOnHover.ts +0 -1
  82. package/lib/layouts/MarkdownWrapper.astro +0 -17
  83. package/lib/utils/bun/BunCmd.ts +0 -7
  84. package/lib/utils/bun/cryAndTryAgainLater.ts +0 -6
  85. package/lib/utils/bun/logBunCmd.ts +0 -1
  86. package/lib/utils/bun/runCmdAsync.ts +0 -44
  87. package/lib/utils/bun/runCmdLocally.ts +0 -13
  88. package/lib/utils/obj/objectKeys.ts +0 -21
  89. package/lib/utils/ran/generateId12.ts +0 -7
  90. package/lib/utils/ran/generateId3.ts +0 -7
  91. package/lib/utils/ran/generateId4.ts +0 -7
  92. package/lib/utils/ran/generateId5.ts +0 -7
  93. package/lib/utils/ran/generateId6.ts +0 -7
  94. package/lib/utils/ran/generateId7.ts +0 -7
  95. package/lib/utils/ran/generateReadableId.ts +0 -35
  96. package/lib/utils/ran/urlAlphabet32.ts +0 -8
  97. /package/lib/{layouts/parts → md}/markdown.css +0 -0
  98. /package/lib/utils/{ui/classArr.ts → classArr.ts} +0 -0
  99. /package/lib/utils/{ui/classMerge.ts → classMerge.ts} +0 -0
  100. /package/lib/utils/{ui/isDevEnv.ts → isDevEnv.ts} +0 -0
  101. /package/lib/utils/{ui/tailwindBreakpoint.ts → tailwindBreakpoint.ts} +0 -0
package/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  A library of reusable UI components for Astro projects. Built with TypeScript, Tailwind CSS, and Astro in static output mode. Components are designed to be accessible, customizable, and easy to integrate.
4
4
 
5
5
  Quick link
6
+
6
7
  - code - https://github.com/adaptive-shield-matrix/astro-ui
7
8
  - npm - https://www.npmjs.com/package/@adaptive-sm/astro-ui
8
9
  - component demo - https://adaptive-astro-ui.pages.dev/
@@ -17,7 +18,7 @@ bun add @adaptive-sm/astro-ui
17
18
 
18
19
  ## Tailwind CSS Configuration
19
20
 
20
- To ensure Tailwind scans the library's source files for classes (since components are published as source without a build step), add the following `@source` directive to your project's `src/layouts/global.css` (or equivalent global stylesheet):
21
+ To ensure Tailwind scans the library's source files for classes (since components are published as source without a build step), add the following `@source` directive to your project's `src/layouts/tailwind.css` (or equivalent global stylesheet):
21
22
 
22
23
  ```css
23
24
  @source '/node_modules/@adaptive-sm/astro-ui/lib/**/*.{astro,html,md,mdx,ts,tsx}';
@@ -27,20 +28,38 @@ This tells Tailwind to include classes from the library's `.astro`, `.ts`, and o
27
28
 
28
29
  ## Option configuration: import alias
29
30
 
31
+ ### Typescript
32
+
33
+ In your `tsconfig.json`, set up the `~` alias to point to the library:
34
+
35
+ ```json
36
+ {
37
+ "compilerOptions": {
38
+ "baseUrl": ".",
39
+ "paths": {
40
+ "@/*": ["src/*"],
41
+ "~ui/*": ["node_modules/@adaptive-sm/astro-ui/lib/*"]
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### Astro
48
+
30
49
  In your `astro.config.mjs`, set up the `~` alias to point to the library:
31
50
 
32
51
  ```js
33
- import { defineConfig } from 'astro/config';
52
+ import { defineConfig } from "astro/config"
34
53
 
35
54
  export default defineConfig({
36
55
  vite: {
37
56
  resolve: {
38
57
  alias: {
39
- '~': new URL('./node_modules/@adaptive-sm/astro-ui/lib', import.meta.url).pathname,
58
+ "~": new URL("./node_modules/@adaptive-sm/astro-ui/lib", import.meta.url).pathname,
40
59
  },
41
60
  },
42
61
  },
43
- });
62
+ })
44
63
  ```
45
64
 
46
65
  ## Usage
@@ -62,7 +81,7 @@ Import and use components directly in your Astro files. For example:
62
81
 
63
82
  ```astro
64
83
  ---
65
- import { Button } from '~/button/Button.astro';
84
+ import { Button } from "~ui/button/Button.astro"
66
85
  ---
67
86
 
68
87
  <Button variant="primary">Click me</Button>
@@ -72,19 +91,17 @@ import { Button } from '~/button/Button.astro';
72
91
 
73
92
  ```astro
74
93
  ---
75
- import { CardWrapper } from '~/card/CardWrapper.astro';
94
+ import { CardWrapper } from "~ui/card/CardWrapper.astro"
76
95
  ---
77
96
 
78
- <CardWrapper>
79
- Card content here.
80
- </CardWrapper>
97
+ <CardWrapper> Card content here. </CardWrapper>
81
98
  ```
82
99
 
83
100
  ### Image Component
84
101
 
85
102
  ```astro
86
103
  ---
87
- import { Img } from '~/img/Img.astro';
104
+ import { Img } from "~ui/img/Img.astro"
88
105
  ---
89
106
 
90
107
  <Img src="/path/to/image.jpg" alt="Description" />
@@ -95,20 +112,25 @@ Refer to individual component documentation in the source code for props and var
95
112
  ## Components
96
113
 
97
114
  ### Buttons
115
+
98
116
  - [Button.astro](lib/button/Button.astro)
99
117
  - Button variants and animations via CVAs in `buttonCva.ts`, `buttonIconCva.ts`
100
118
 
101
119
  ### Cards
120
+
102
121
  - [CardWrapper.astro](lib/card/CardWrapper.astro)
103
122
 
104
123
  ### Details
124
+
105
125
  - [Details.astro](lib/details/Details.astro)
106
126
 
107
127
  ### Forms
128
+
108
129
  - [Fieldset.astro](lib/form/Fieldset.astro)
109
130
 
110
131
  ### Icons
111
- - [Icon1.astro](lib/icon/Icon1.astro) (replaces SVG icons)
132
+
133
+ - [Icon.astro](lib/icon/Icon.astro) (replaces SVG icons)
112
134
 
113
135
  usage:
114
136
 
@@ -117,6 +139,7 @@ usage:
117
139
  - Passed on as `path` prop
118
140
 
119
141
  ### Images
142
+
120
143
  - [Img.astro](lib/img/Img.astro)
121
144
 
122
145
  A small wrapper setting loading lazy and decoding to async.
@@ -128,35 +151,44 @@ usage:
128
151
  Generate types using `lib/generate_image_list/generateImageList.ts`
129
152
 
130
153
  ### Layouts
154
+
131
155
  - [MinimalLayout.astro](lib/layouts/MinimalLayout.astro)
132
- - [MarkdownWrapper.astro](lib/layouts/MarkdownWrapper.astro)
156
+ - [MarkdownPageWrapper.astro](lib/layouts/MarkdownPageWrapper.astro)
133
157
 
134
158
  ### Navigation bar
159
+
135
160
  - [ThemeToggle.astro](lib/layouts/parts/ThemeToggle.astro)
136
161
 
137
162
  ### Links
163
+
138
164
  - [LinkText.astro](lib/link/LinkText.astro)
139
165
  - [LinkButton.astro](lib/link/LinkButton.astro)
140
166
 
141
167
  ### Lists
168
+
142
169
  - [BlackBulletPoints.astro](lib/list/BlackBulletPoints.astro)
143
170
  - [CheckPoints.astro](lib/list/CheckPoints.astro)
144
171
  - [NumberedList.astro](lib/list/NumberedList.astro)
145
172
 
146
173
  ### Modals
174
+
147
175
  - [ModalButton.astro](lib/modal/ModalButton.astro)
148
176
 
149
177
  ### Pages
178
+
150
179
  - [PageCentered.astro](lib/page/PageCentered.astro)
151
180
  - [PageCenteredCard.astro](lib/page/PageCenteredCard.astro)
152
181
 
153
182
  ### Popovers
183
+
154
184
  - [Popover1.astro](lib/popover/Popover1.astro)
155
185
 
156
186
  ### Selects
187
+
157
188
  - [Select.astro](lib/select/Select.astro)
158
189
 
159
190
  ### Table
191
+
160
192
  - [Table.astro](lib/table/Table.astro)
161
193
 
162
194
  ## Demos
@@ -201,3 +233,11 @@ Follow the coding rules in `.roo/rules-code/` for style and best practices.
201
233
  ## License
202
234
 
203
235
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
236
+
237
+ ## Acknowledgments
238
+
239
+ - Built on top of [Astro](https://astro.build).
240
+ - Styled with [Tailwind CSS](https://tailwindcss.com/).
241
+ - Icons from [MDI](https://pictogrammers.com/library/mdi/).
242
+
243
+ For more information, visit the [GitHub repository](https://github.com/adaptive-shield-matrix/astro-ui).
@@ -0,0 +1,27 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types"
3
+ import { type BadgeVariant, badgeCva, badgeIconCva, badgeVariant } from "~ui/badge/classesBadge"
4
+ import Icon from "~ui/icon/Icon.astro"
5
+ import type { MayHaveClass } from "~ui/utils/MayHaveClass"
6
+
7
+ interface Props extends MayHaveClass {
8
+ id?: string
9
+ variant?: BadgeVariant
10
+
11
+ icon?: string
12
+ iconRight?: string
13
+ iconClass?: string
14
+
15
+ class?: string
16
+ restProps?: HTMLAttributes<"svg">
17
+ }
18
+
19
+ const p = Astro.props
20
+ const v = p.variant ?? badgeVariant.outline
21
+ ---
22
+
23
+ <span id={p.id} class={badgeCva(v, p.class)} {...p.restProps}>
24
+ {p.icon && <Icon path={p.icon} class={badgeIconCva(v, p.iconClass)} />}
25
+ <slot />
26
+ {p.iconRight && <Icon path={p.iconRight} class={badgeIconCva(v, p.iconClass)} />}
27
+ </span>
@@ -0,0 +1,67 @@
1
+ import { classArr } from "~ui/utils/classArr"
2
+ import { classMerge } from "~ui/utils/classMerge"
3
+
4
+ export type BadgeVariant = keyof typeof badgeVariant
5
+
6
+ export const badgeVariant = {
7
+ base: "base",
8
+ contrast: "contrast",
9
+ outline: "outline",
10
+ } as const
11
+
12
+ export const classesBadgeBase = classArr(
13
+ "inline-flex items-center", // layout
14
+ "text-sm", // text
15
+ "px-2.5 py-0.5 rounded-full", // padding
16
+ "flex gap-2", // layout children
17
+ )
18
+
19
+ export const classesBadgeContrast = classArr(
20
+ classesBadgeBase,
21
+ "text-white dark:text-slate-900 dark:hover:text-slate-900", // text
22
+ "bg-slate-900 dark:bg-slate-50", // bg
23
+ )
24
+
25
+ export const classesBadgeOutline = classArr(
26
+ classesBadgeBase,
27
+ "border border-gray-400 dark:border-gray-500", // border
28
+ )
29
+
30
+ export const classesBadgeVariant = {
31
+ base: classesBadgeBase,
32
+ contrast: classesBadgeContrast,
33
+ outline: classesBadgeOutline,
34
+ } as const satisfies Record<BadgeVariant, string>
35
+
36
+ export function badgeCva(v: BadgeVariant, classes?: string): string {
37
+ return classMerge(classesBadgeVariant[v ?? badgeVariant.base], classes)
38
+ }
39
+
40
+ const classesTextFillBlack = "text-black fill-black"
41
+ const classesTextFillWhite = "text-white fill-white"
42
+
43
+ const classesBlackWhite = classArr(
44
+ classesTextFillBlack,
45
+ "dark:text-white", // dark text
46
+ "dark:fill-white", // dark fill
47
+ )
48
+
49
+ const classesWhiteWhite = classArr(
50
+ classesTextFillWhite,
51
+ "dark:text-white", // dark text
52
+ "dark:fill-white", // dark fill
53
+ )
54
+
55
+ const baseClasses = classArr(
56
+ "size-6", // size
57
+ )
58
+
59
+ const badgeIconClasses = {
60
+ base: classesBlackWhite,
61
+ outline: classesBlackWhite,
62
+ contrast: classArr(classesTextFillWhite, "dark:text-black dark:fill-black"),
63
+ } as const satisfies Record<BadgeVariant, string>
64
+
65
+ export function badgeIconCva(variant: BadgeVariant, classes?: string) {
66
+ return classMerge(baseClasses, badgeIconClasses[variant], classes)
67
+ }
@@ -1,9 +1,10 @@
1
1
  ---
2
- import { buttonCva2, type ButtonSize, type ButtonVariant } from "~/button/buttonCva"
3
- import { buttonIconCva } from "~/button/buttonIconCva"
4
- import { classesButtonClickAnimation } from "~/button/classesButtonClickAnimation"
5
- import Icon1 from "~/icon/Icon1.astro"
6
- import { classMerge } from "~/utils/ui/classMerge"
2
+ import type { HTMLAttributes } from "astro/types"
3
+ import { buttonCva2, type ButtonSize, type ButtonVariant } from "~ui/button/buttonCva"
4
+ import { buttonIconCva } from "~ui/button/buttonIconCva"
5
+ import { classesButtonClickAnimation } from "~ui/button/classesButtonClickAnimation"
6
+ import Icon from "~ui/icon/Icon.astro"
7
+ import { classMerge } from "~ui/utils/classMerge"
7
8
 
8
9
  interface Props {
9
10
  id?: string
@@ -18,41 +19,30 @@ interface Props {
18
19
  iconRight?: string
19
20
  iconClass?: string
20
21
  class?: string
21
- onclick?: any
22
+ restProps?: HTMLAttributes<"button">
22
23
  }
23
- const props = Astro.props
24
+ const p = Astro.props
24
25
 
25
- const classes = buttonCva2(props.variant, props.size, classesButtonClickAnimation, props.class)
26
+ const classes = buttonCva2(p.variant, p.size, classesButtonClickAnimation, p.class)
26
27
  const hasChildren = Astro.slots.has("default")
27
- const hasContent = hasChildren || props.text
28
+ const hasContent = hasChildren || p.text
28
29
  ---
29
30
 
30
- <button id={props.id} title={props.title} class={classes} onclick={props.onclick}>
31
+ <button id={p.id} title={p.title} class={classes} {...p.restProps}>
32
+ {p.icon && <Icon path={p.icon} class={classMerge(hasContent && "mr-2", buttonIconCva(p.variant, p.iconClass))} />}
31
33
  {
32
- props.icon && (
33
- <Icon1
34
- path={props.icon}
35
- class={classMerge(hasContent && "mr-2", buttonIconCva(props.variant, props.iconClass))}
36
- />
37
- )
38
- }
39
- {
40
- props.text && (
41
- <span id={props.contentId} class={props.contentClass}>
42
- {props.text}
34
+ p.text && (
35
+ <span id={p.contentId} class={p.contentClass}>
36
+ {p.text}
43
37
  </span>
44
38
  )
45
39
  }
46
40
  {
47
41
  hasContent && (
48
- <span id={props.contentId} class={props.contentClass}>
42
+ <span id={p.contentId} class={p.contentClass}>
49
43
  <slot />
50
44
  </span>
51
45
  )
52
46
  }
53
- {
54
- props.iconRight && (
55
- <Icon1 path={props.iconRight} class={buttonIconCva(props.variant, hasContent && "ml-2", props.iconClass)} />
56
- )
57
- }
47
+ {p.iconRight && <Icon path={p.iconRight} class={buttonIconCva(p.variant, hasContent && "ml-2", p.iconClass)} />}
58
48
  </button>
@@ -1,5 +1,5 @@
1
- import { classArr } from "~/utils/ui/classArr"
2
- import { classMerge } from "~/utils/ui/classMerge"
1
+ import { classArr } from "~ui/utils/classArr"
2
+ import { classMerge } from "~ui/utils/classMerge"
3
3
  import { classesButtonClickAnimation } from "./classesButtonClickAnimation"
4
4
  import { classesButtonDisabled } from "./classesButtonDisabled"
5
5
 
@@ -94,19 +94,19 @@ const variantClasses = {
94
94
  // filled colors
95
95
  //
96
96
  filledYellow: classArr(
97
- "text-white dark:text-yellow-100 ", // text
97
+ "text-white", // text
98
98
  "bg-yellow-500 dark:bg-yellow-800 ", // bg
99
99
  "hover:bg-yellow-700 dark:hover:bg-yellow-600", // bg hover
100
100
  "focus:ring-yellow-400 dark:focus:ring-yellow-400", // focus
101
101
  ),
102
102
  filledAmber: classArr(
103
- "text-white dark:text-amber-100 ", // text
103
+ "text-white", // text
104
104
  "bg-amber-500 dark:bg-amber-800 ", // bg
105
105
  "hover:bg-amber-700 dark:hover:bg-amber-600", // bg hover
106
106
  "focus:ring-amber-400 dark:focus:ring-amber-400", // focus
107
107
  ),
108
108
  filledOrange: classArr(
109
- "text-white dark:text-orange-100 ", // text
109
+ "text-white", // text
110
110
  "bg-orange-500 dark:bg-orange-800 ", // bg
111
111
  "hover:bg-orange-700 dark:hover:bg-orange-600", // bg hover
112
112
  "focus:ring-orange-400 dark:focus:ring-orange-400", // focus
@@ -128,7 +128,7 @@ const variantClasses = {
128
128
  "focus:ring-sky-400 dark:focus:ring-sky-400", // focus
129
129
  ),
130
130
  filledIndigo: classArr(
131
- "text-white dark:text-indigo-100 ", // text
131
+ "text-white", // text
132
132
  "bg-indigo-500 dark:bg-indigo-800 ", // bg
133
133
  "hover:bg-indigo-700 dark:hover:bg-indigo-600", // bg hover
134
134
  "focus:ring-indigo-400 dark:focus:ring-indigo-400", // focus
@@ -1,5 +1,5 @@
1
- import { classArr } from "~/utils/ui/classArr"
2
- import { classMerge } from "~/utils/ui/classMerge"
1
+ import { classArr } from "~ui/utils/classArr"
2
+ import { classMerge } from "~ui/utils/classMerge"
3
3
  import { type ButtonVariant } from "./buttonCva"
4
4
 
5
5
  const classesTextFillBlack = "text-black fill-black"
@@ -1,4 +1,4 @@
1
- import { classArr } from "~/utils/ui/classArr"
1
+ import { classArr } from "~ui/utils/classArr"
2
2
 
3
3
  export const classesButtonClickAnimation = classArr(
4
4
  // "duration-300",
@@ -1,4 +1,4 @@
1
- import { classArr } from "~/utils/ui/classArr"
1
+ import { classArr } from "~ui/utils/classArr"
2
2
 
3
3
  /**
4
4
  * disable hover because popovers move with it
@@ -1,4 +1,4 @@
1
- import { classArr } from "~/utils/ui/classArr"
1
+ import { classArr } from "~ui/utils/classArr"
2
2
 
3
3
  /**
4
4
  * unused because it's a little to fancy
@@ -1,15 +1,16 @@
1
1
  ---
2
- import { classesCardWrapperP4 } from "~/card/classesCardWrapper"
3
- import { classArr } from "~/utils/ui/classArr"
4
- import { classMerge } from "~/utils/ui/classMerge"
2
+ import type { HTMLAttributes } from "astro/types"
3
+ import { classesCardWrapperP4 } from "~ui/card/classesCardWrapper"
4
+ import { classMerge } from "~ui/utils/classMerge"
5
5
 
6
6
  interface Props {
7
- id?:string
7
+ id?: string
8
8
  class?: string
9
+ restProps?: HTMLAttributes<"div">
9
10
  }
10
11
  const p = Astro.props
11
12
  ---
12
13
 
13
- <div id={p.id} class={classMerge(classesCardWrapperP4, p.class)}>
14
+ <div id={p.id} class={classMerge(classesCardWrapperP4, p.class)} {...p.restProps}>
14
15
  <slot />
15
16
  </div>
@@ -0,0 +1 @@
1
+ export const classesBorderWrapper = "border border-gray-500 rounded-xl"
@@ -1,16 +1,28 @@
1
- import { classArr } from "~/utils/ui/classArr"
1
+ import { classesShadowMdLg } from "~ui/card/classesShadow"
2
+ import { classArr } from "~ui/utils/classArr"
3
+
4
+ export const classesCardWrapperBorderDark = "dark:border dark:border-gray-500"
5
+ export const classesCardWrapperBg = "bg-white dark:bg-zinc-800"
2
6
 
3
7
  export const classesCardWrapper = classArr(
4
- "rounded-lg shadow-lg", // card shadows/padding
5
- "bg-white dark:bg-gray-900", // bg
8
+ "rounded-lg",
9
+ classesShadowMdLg, // card shadows/padding
10
+ classesCardWrapperBg, // bg
11
+ classesCardWrapperBorderDark, // border
6
12
  )
7
13
 
8
- export const classesCardWrapperP4 = classArr(classesCardWrapper, "p-4 lg:p-8")
9
- export const classesCardWrapperP8 = classArr(classesCardWrapper, "p-4 sm:p-8")
14
+ export const classesPadding4Lg8 = "p-4 lg:p-8"
15
+ export const classesPadding4sm8 = "p-4 sm:p-8"
16
+ export const classesPadding4sm8md12 = "p-4 sm:p-8 md:p-12"
17
+
18
+ export const classesCardWrapperP4 = classArr(classesCardWrapper, classesPadding4Lg8)
19
+ export const classesCardWrapperP8 = classArr(classesCardWrapper, classesPadding4sm8)
20
+
21
+ export const classesRoundedShadowXl = "rounded-xl shadow-xl"
10
22
 
11
23
  export const classesCardWrapperPage = classArr(
12
- "rounded-xl shadow-xl", // rounded border + shadow
13
- "p-4 sm:p-8 md:p-12", // padding
14
- // "sm:mx-auto", // center
15
- "bg-white dark:bg-gray-900", // bg
24
+ classesRoundedShadowXl, // rounded border + shadow
25
+ classesPadding4sm8md12, // padding
26
+ classesCardWrapperBg, // bg
27
+ classesCardWrapperBorderDark, // border
16
28
  )
@@ -0,0 +1,5 @@
1
+ export const classesShadowSmMd = "shadow-sm hover:shadow-md transition duration-500"
2
+
3
+ export const classesShadowMdLg = "shadow-md hover:shadow-lg transition duration-500"
4
+
5
+ export const classesShadowLgXl = "shadow-lg hover:shadow-xl transition duration-500"
@@ -1,8 +1,9 @@
1
1
  ---
2
- import Icon1 from "~/icon/Icon1.astro"
3
- import { classArr } from "~/utils/ui/classArr"
4
- import { classMerge } from "~/utils/ui/classMerge"
2
+ import Icon from "~ui/icon/Icon.astro"
3
+ import { classArr } from "~ui/utils/classArr"
4
+ import { classMerge } from "~ui/utils/classMerge"
5
5
  import { mdiChevronDown } from "@mdi/js"
6
+ import type { HTMLAttributes } from "astro/types"
6
7
 
7
8
  interface Props {
8
9
  icon?: string
@@ -10,12 +11,13 @@ interface Props {
10
11
  subtitle?: string
11
12
  class?: string
12
13
  summaryClass?: string
14
+ restProps?: HTMLAttributes<"details">
15
+ summaryProps?: HTMLAttributes<"summary">
13
16
  }
14
- const props = Astro.props
15
- const icon = props.icon
16
- const title = props.title
17
- const subtitle = props.subtitle
18
- const summaryClass = props.summaryClass
17
+ const p = Astro.props
18
+ const icon = p.icon
19
+ const title = p.title
20
+ const subtitle = p.subtitle
19
21
  const hasSummary = Astro.slots.has("summary")
20
22
  ---
21
23
 
@@ -26,29 +28,32 @@ const hasSummary = Astro.slots.has("summary")
26
28
  "rounded-lg border border-gray-200",
27
29
  "shadow-sm",
28
30
  "overflow-hidden",
29
- props.class,
31
+ p.class,
30
32
  )}
33
+ {...p.restProps}
31
34
  >
32
35
  <summary
33
36
  class={classArr(
34
37
  "flex flex-col sm:flex-row items-center justify-between gap-4",
35
- "p-6",
38
+ "p-4 sm:p-6",
36
39
  "cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors",
40
+ p.summaryClass,
37
41
  )}
42
+ {...p.summaryProps}
38
43
  >
39
44
  {
40
45
  !hasSummary && title && (
41
46
  <>
42
- {icon && <Icon1 path={icon} class="size-7 mt-1" />}
43
- <div class="flex-1">
47
+ {icon && <Icon path={icon} class="size-7 mt-1" />}
48
+ <span class="flex-1">
44
49
  <h3 class={"text-xl font-semibold"}>{title}</h3>
45
- {subtitle && <p class={"text-muted-foreground mt-1"}>{subtitle}</p>}
46
- </div>
50
+ {subtitle && <span class={"text-muted-foreground mt-1"}>{subtitle}</span>}
51
+ </span>
47
52
  </>
48
53
  )
49
54
  }
50
55
  <slot name="summary" />
51
- <Icon1
56
+ <Icon
52
57
  path={mdiChevronDown}
53
58
  class={classArr("size-7", "text-gray-400 dark:text-gray-600", "transition-transform group-open:rotate-180")}
54
59
  />
@@ -1,6 +1,6 @@
1
1
  ---
2
- import { classMerge } from "~/utils/ui/classMerge"
3
- import { isDevEnv } from "~/utils/ui/isDevEnv"
2
+ import { classMerge } from "~ui/utils/classMerge"
3
+ import { isDevEnv } from "~ui/utils/isDevEnv"
4
4
  ---
5
5
 
6
6
  {
@@ -1,6 +1,7 @@
1
1
  ---
2
+ import type { HTMLAttributes } from "astro/types"
2
3
  import { classesFieldset } from "./classesFieldset"
3
- import { classMerge } from "~/utils/ui/classMerge"
4
+ import { classMerge } from "~ui/utils/classMerge"
4
5
 
5
6
  interface Props {
6
7
  title: string
@@ -8,13 +9,15 @@ interface Props {
8
9
  subtitles?: string | string[]
9
10
  subtitleClass?: string
10
11
  class?: string
12
+ restProps?: HTMLAttributes<"fieldset">
13
+ legendProps?: HTMLAttributes<"legend">
11
14
  }
12
- const props = Astro.props
15
+ const p = Astro.props
13
16
  ---
14
17
 
15
- <fieldset class={classMerge(classesFieldset, props.class)}>
16
- <legend class={classMerge("px-1", props.titleClass)}>
17
- {props.title}
18
+ <fieldset class={classMerge(classesFieldset, p.class)} {...p.restProps}>
19
+ <legend class={classMerge("px-1", p.titleClass)} {...p.legendProps}>
20
+ {p.title}
18
21
  <!--{props.subtitles && <PopoverI title={props.title} points={props.subtitles} />}-->
19
22
  </legend>
20
23
  <slot />
@@ -1,19 +1,21 @@
1
1
  ---
2
- import { classesTextLink } from "~/link/classesTextLink"
3
- import { classArr } from "~/utils/ui/classArr"
2
+ import { classesTextLink } from "~ui/link/classesTextLink"
3
+ import { classArr } from "~ui/utils/classArr"
4
4
  import { type DemoListType } from "./DemoListType"
5
+ import { classMerge } from "~ui/utils/classMerge"
5
6
 
6
7
  interface Props {
7
8
  demos: DemoListType
9
+ urlPrefix?: string
8
10
  class?: string
9
11
  }
10
- const props = Astro.props
12
+ const p = Astro.props
11
13
 
12
14
  // Extract categories and their demo pages
13
- const categories = Object.entries(props.demos)
15
+ const categories = Object.entries(p.demos)
14
16
  ---
15
17
 
16
- <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
18
+ <div class={classMerge("grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 mt-4", p.class)}>
17
19
  {
18
20
  categories.map(([category, pages]) => (
19
21
  <section class="bg-white dark:bg-zinc-700 rounded-lg shadow-md p-4 border border-gray-200 dark:border-zinc-600">
@@ -21,7 +23,7 @@ const categories = Object.entries(props.demos)
21
23
  <ul class="list-disc pl-4 space-y-1">
22
24
  {pages.map((page) => (
23
25
  <li class={classArr(classesTextLink)}>
24
- <a href={`/demos/${category}/${page}`}>{page.replace(/_/g, " ").replaceAll("demo ", "")}</a>
26
+ <a href={`${p.urlPrefix ?? ""}/${category}/${page}`}>{page.replace(/_/g, " ").replaceAll("demo ", "")}</a>
25
27
  </li>
26
28
  ))}
27
29
  </ul>
@@ -1,6 +1,6 @@
1
1
  import { readdir, writeFile } from "node:fs/promises"
2
2
  import { join } from "node:path"
3
- import { runCmdAsync } from "~/utils/bun/runCmdAsync"
3
+ import { runCmdAsync } from "~utils/bun/runCmdAsync"
4
4
  import type { DemoListType } from "./DemoListType"
5
5
 
6
6
  export async function generateDemoList(demosPath: string, outputPath: string) {
@@ -20,7 +20,7 @@ export async function generateDemoList(demosPath: string, outputPath: string) {
20
20
  }
21
21
  sortDemoPageList(demoPageList)
22
22
 
23
- const outputContent = `import type { DemoListType } from "~/generate_demo_list/DemoListType"
23
+ const outputContent = `import type { DemoListType } from "~ui/generate_demo_list/DemoListType"
24
24
 
25
25
  export const demoList = ${JSON.stringify(demoPageList, null, 2)} satisfies DemoListType;
26
26
  `