@adaptive-sm/astro-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.
- package/LICENSE +22 -0
- package/README.md +183 -0
- package/lib/button/Button.astro +58 -0
- package/lib/button/buttonCva.ts +196 -0
- package/lib/button/buttonIconCva.ts +52 -0
- package/lib/button/classesButtonClickAnimation.ts +8 -0
- package/lib/button/classesButtonClickAnimationPush.ts +6 -0
- package/lib/button/classesButtonClickAnimationSquish.ts +6 -0
- package/lib/button/classesButtonDisabled.ts +1 -0
- package/lib/card/CardWrapper.astro +15 -0
- package/lib/card/classesCardWrapper.ts +16 -0
- package/lib/details/Details.astro +57 -0
- package/lib/dev/TailwindIndicator.astro +28 -0
- package/lib/form/Fieldset.astro +21 -0
- package/lib/form/classesFieldset.ts +1 -0
- package/lib/generate_ai_rules/generate_agent_rules.bash +9 -0
- package/lib/generate_ai_rules/generate_agent_rules_1_lib.bash +33 -0
- package/lib/generate_ai_rules/generate_agent_rules_2_copy.bash +14 -0
- package/lib/generate_ai_rules/generate_agent_rules_3_combine.bash +31 -0
- package/lib/generate_demo_list/DemoList.astro +31 -0
- package/lib/generate_demo_list/DemoListType.ts +1 -0
- package/lib/generate_demo_list/generateDemoList.ts +55 -0
- package/lib/generate_image_list/generateImageList.ts +101 -0
- package/lib/grid/classesGridCols.ts +86 -0
- package/lib/icon/Icon1.astro +21 -0
- package/lib/img/ImageType.ts +6 -0
- package/lib/img/Img.astro +27 -0
- package/lib/img/TypedImg.astro +26 -0
- package/lib/img/classInvertDiagram.ts +1 -0
- package/lib/img/classesImgZoomInOnHover.ts +1 -0
- package/lib/layouts/MarkdownWrapper.astro +17 -0
- package/lib/layouts/MinimalLayout.astro +67 -0
- package/lib/layouts/parts/ThemeToggle.astro +137 -0
- package/lib/layouts/parts/astroElementId.ts +7 -0
- package/lib/layouts/parts/markdown.css +93 -0
- package/lib/link/LinkButton.astro +48 -0
- package/lib/link/LinkText.astro +23 -0
- package/lib/link/classesTextLink.ts +13 -0
- package/lib/list/BlackBulletPoint.astro +16 -0
- package/lib/list/BlackBulletPoints.astro +23 -0
- package/lib/list/CheckPoint.astro +20 -0
- package/lib/list/CheckPoints.astro +23 -0
- package/lib/list/NumberedList.astro +14 -0
- package/lib/list/Ps.astro +12 -0
- package/lib/list/TextOrLink.astro +19 -0
- package/lib/modal/Modal.astro +54 -0
- package/lib/modal/Modal.module.css +19 -0
- package/lib/modal/ModalButton.astro +41 -0
- package/lib/modal/modal.ts +137 -0
- package/lib/page/PageCentered.astro +14 -0
- package/lib/page/PageCenteredCard.astro +17 -0
- package/lib/page/classesBg.ts +27 -0
- package/lib/page/classesPageCentered.ts +6 -0
- package/lib/popover/Popover1.astro +45 -0
- package/lib/popover/setupPopoverListeners.ts +22 -0
- package/lib/select/Select.astro +45 -0
- package/lib/table/DesktopTableClassses.ts +6 -0
- package/lib/table/MobileTableClassses.ts +7 -0
- package/lib/table/Table.astro +41 -0
- package/lib/table/TableColumnDef.ts +10 -0
- package/lib/table/TableD.astro +55 -0
- package/lib/table/TableM.astro +22 -0
- package/lib/table/TableMEntry.astro +27 -0
- package/lib/table/sharedTableRowClasses.ts +1 -0
- package/lib/table/tableVisibilityClasses.ts +28 -0
- package/lib/text/classesTextGray.ts +1 -0
- package/lib/text/classesTextHeader.ts +1 -0
- package/lib/utils/bun/BunCmd.ts +7 -0
- package/lib/utils/bun/cryAndTryAgainLater.ts +6 -0
- package/lib/utils/bun/logBunCmd.ts +1 -0
- package/lib/utils/bun/runCmdAsync.ts +44 -0
- package/lib/utils/bun/runCmdLocally.ts +13 -0
- package/lib/utils/obj/objectKeys.ts +21 -0
- package/lib/utils/ran/generateId12.ts +7 -0
- package/lib/utils/ran/generateId3.ts +7 -0
- package/lib/utils/ran/generateId4.ts +7 -0
- package/lib/utils/ran/generateId5.ts +7 -0
- package/lib/utils/ran/generateId6.ts +7 -0
- package/lib/utils/ran/generateId7.ts +7 -0
- package/lib/utils/ran/generateReadableId.ts +35 -0
- package/lib/utils/ran/urlAlphabet32.ts +8 -0
- package/lib/utils/ui/classArr.ts +3 -0
- package/lib/utils/ui/classMerge.ts +10 -0
- package/lib/utils/ui/isDevEnv.ts +7 -0
- package/lib/utils/ui/tailwindBreakpoint.ts +83 -0
- package/package.json +56 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { mdiMoonWaxingCrescent, mdiWhiteBalanceSunny } from "@mdi/js"
|
|
3
|
+
import { buttonVariant, type ButtonVariant } from "~/button/buttonCva"
|
|
4
|
+
import Button from "~/button/Button.astro"
|
|
5
|
+
import Icon1 from "~/icon/Icon1.astro"
|
|
6
|
+
import { classArr } from "~/utils/ui/classArr"
|
|
7
|
+
import { astroElementId } from "~/layouts/parts/astroElementId"
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* have to use "is:inline" script to run/apply theme before page render -> white flash on page reload otherwise
|
|
11
|
+
* https://docs.astro.build/en/tutorial/6-islands/2/
|
|
12
|
+
* https://axellarsson.com/blog/astrojs-prevent-dark-mode-flicker/
|
|
13
|
+
* https://docs.astro.build/en/tutorials/add-view-transitions/#update-scripts
|
|
14
|
+
* https://github.com/Toxocious/toxocious.github.io/blob/main/src/components/theme_toggle/theme_toggle.astro
|
|
15
|
+
*/
|
|
16
|
+
interface Props {
|
|
17
|
+
class?: string
|
|
18
|
+
iconClass?: string
|
|
19
|
+
iconLightClass?: string
|
|
20
|
+
iconDarkClass?: string
|
|
21
|
+
variant?: ButtonVariant
|
|
22
|
+
title?: string
|
|
23
|
+
textLight?: string
|
|
24
|
+
textDark?: string
|
|
25
|
+
textClass?: string
|
|
26
|
+
textLightClass?: string
|
|
27
|
+
textDarkClass?: string
|
|
28
|
+
}
|
|
29
|
+
const p = Astro.props
|
|
30
|
+
const title = p.title ?? "Toggle theme"
|
|
31
|
+
const textLight = p.textLight ?? "Light"
|
|
32
|
+
const textDark = p.textLight ?? "Dark"
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
<Button
|
|
36
|
+
variant={p.variant ?? buttonVariant.ghost}
|
|
37
|
+
id={astroElementId.themeToggle}
|
|
38
|
+
transition:name={astroElementId.themeToggle}
|
|
39
|
+
title={title}
|
|
40
|
+
class={classArr(p.class)}
|
|
41
|
+
contentClass={classArr("flex flex-row gap-1")}
|
|
42
|
+
>
|
|
43
|
+
<Icon1 path={mdiWhiteBalanceSunny} class={classArr("size-6 dark:hidden mr-2", p.iconClass, p.iconLightClass)} />
|
|
44
|
+
<Icon1 path={mdiMoonWaxingCrescent} class={classArr("hidden size-6 dark:block mr-2", p.iconClass, p.iconDarkClass)} />
|
|
45
|
+
<p id="theme-toggle-text-light" class={classArr("dark:hidden", p.textClass, p.textLightClass)}>{textLight}</p>
|
|
46
|
+
<p id="theme-toggle-text-dark" class={classArr("hidden dark:block", p.textClass, p.textDarkClass)}>{textDark}</p>
|
|
47
|
+
</Button>
|
|
48
|
+
|
|
49
|
+
<script is:inline>
|
|
50
|
+
const log = false
|
|
51
|
+
|
|
52
|
+
if (log) console.log("theme-toggle script start")
|
|
53
|
+
function loadTheme() {
|
|
54
|
+
const stored = typeof localStorage !== "undefined" && localStorage.getItem("theme")
|
|
55
|
+
if (log) console.log("loadTheme", stored)
|
|
56
|
+
if (stored) {
|
|
57
|
+
return stored
|
|
58
|
+
}
|
|
59
|
+
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
60
|
+
return "dark"
|
|
61
|
+
}
|
|
62
|
+
return "light"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function applyThemeToWindow(theme) {
|
|
66
|
+
if (log) console.log("applyThemeToWindow", theme)
|
|
67
|
+
if (theme === "light") {
|
|
68
|
+
document.documentElement.classList.remove("dark")
|
|
69
|
+
// document.body.classList.remove("dark")
|
|
70
|
+
} else {
|
|
71
|
+
document.documentElement.classList.add("dark")
|
|
72
|
+
// document.body.classList.add("dark")
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let theme = loadTheme()
|
|
77
|
+
|
|
78
|
+
if (log) console.log("theme", theme)
|
|
79
|
+
|
|
80
|
+
//
|
|
81
|
+
// apply theme on page load
|
|
82
|
+
//
|
|
83
|
+
applyThemeToWindow(theme)
|
|
84
|
+
|
|
85
|
+
// window.localStorage.setItem('theme', theme)
|
|
86
|
+
|
|
87
|
+
const handleToggleClick = () => {
|
|
88
|
+
const element = document.documentElement
|
|
89
|
+
element.classList.toggle("dark")
|
|
90
|
+
const isDark = element.classList.contains("dark")
|
|
91
|
+
localStorage.setItem("theme", isDark ? "dark" : "light")
|
|
92
|
+
if (log) console.log("handleToggleClick", isDark ? "dark" : "light")
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
//
|
|
96
|
+
// apply theme on button click
|
|
97
|
+
//
|
|
98
|
+
const themeButton = document.getElementById("themeToggle")
|
|
99
|
+
if (themeButton) {
|
|
100
|
+
themeButton.addEventListener("click", handleToggleClick)
|
|
101
|
+
} else {
|
|
102
|
+
if (log) console.log("themeButton not found")
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//
|
|
106
|
+
// apply theme with keyboard shortcut
|
|
107
|
+
//
|
|
108
|
+
document.addEventListener("keydown", (event) => {
|
|
109
|
+
if (event.altKey && event.key === "s") {
|
|
110
|
+
event.preventDefault()
|
|
111
|
+
handleToggleClick()
|
|
112
|
+
} else if (event.altKey && event.key === "a") {
|
|
113
|
+
window.location.href = "/demos"
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
//
|
|
118
|
+
// apply theme after view transition
|
|
119
|
+
//
|
|
120
|
+
document.addEventListener("astro:after-swap", function () {
|
|
121
|
+
const stored = localStorage.getItem("theme")
|
|
122
|
+
if (log) console.log("astro swap", stored)
|
|
123
|
+
if (stored === "dark") document.documentElement.classList.toggle("dark", true)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
//
|
|
127
|
+
// apply theme across multiple tabs
|
|
128
|
+
//
|
|
129
|
+
const onStorage = (e) => {
|
|
130
|
+
if (log) console.log("onStorage event", e.key)
|
|
131
|
+
if (e.key !== "theme") return
|
|
132
|
+
const theme = e.newValue
|
|
133
|
+
if (theme) applyThemeToWindow(theme)
|
|
134
|
+
}
|
|
135
|
+
window.addEventListener("storage", onStorage)
|
|
136
|
+
if (log) console.log("theme-toggle script end")
|
|
137
|
+
</script>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/*
|
|
2
|
+
rem -> px
|
|
3
|
+
- 0.67rem -> 10.72px
|
|
4
|
+
- 0.5rem -> 8px
|
|
5
|
+
- 0.875rem -> 14px
|
|
6
|
+
- 1.25rem -> 20px
|
|
7
|
+
- 1.5rem -> 24px
|
|
8
|
+
- 2rem -> 32px
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
.markdown-body {
|
|
12
|
+
line-height: 1.5;
|
|
13
|
+
word-wrap: break-word;
|
|
14
|
+
font-size: 1.125rem;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.markdown-body h1,
|
|
18
|
+
.markdown-body h2,
|
|
19
|
+
.markdown-body h3,
|
|
20
|
+
.markdown-body h4,
|
|
21
|
+
.markdown-body h5,
|
|
22
|
+
.markdown-body h6 {
|
|
23
|
+
margin-top: 1.5rem;
|
|
24
|
+
margin-bottom: 1rem;
|
|
25
|
+
font-weight: var(--base-text-weight-semibold, 600);
|
|
26
|
+
line-height: 1.25;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.markdown-body h1 {
|
|
30
|
+
margin-top: 0.67rem;
|
|
31
|
+
margin-bottom: 0.67rem;
|
|
32
|
+
font-weight: var(--base-text-weight-semibold, 600);
|
|
33
|
+
font-size: 2rem;
|
|
34
|
+
border-bottom: 0.0625rem solid var(--color-border-muted);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.markdown-body h2 {
|
|
38
|
+
font-weight: var(--base-text-weight-semibold, 600);
|
|
39
|
+
font-size: 1.5rem;
|
|
40
|
+
border-bottom: 0.0625rem solid var(--color-border-muted);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.markdown-body h3 {
|
|
44
|
+
font-weight: var(--base-text-weight-semibold, 600);
|
|
45
|
+
font-size: 1.25rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.markdown-body h4 {
|
|
49
|
+
font-weight: var(--base-text-weight-semibold, 600);
|
|
50
|
+
font-size: 1rem;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.markdown-body h5 {
|
|
54
|
+
font-weight: var(--base-text-weight-semibold, 600);
|
|
55
|
+
font-size: 0.875rem;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.markdown-body h6 {
|
|
59
|
+
font-weight: var(--base-text-weight-semibold, 600);
|
|
60
|
+
font-size: 0.85rem;
|
|
61
|
+
color: var(--color-fg-muted);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.markdown-body p {
|
|
65
|
+
margin-top: 0.5rem;
|
|
66
|
+
margin-bottom: 0.5rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.markdown-body ul,
|
|
70
|
+
.markdown-body ol {
|
|
71
|
+
margin-top: 0;
|
|
72
|
+
margin-bottom: 0;
|
|
73
|
+
padding-left: 2rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
Add bullet points for list items
|
|
78
|
+
*/
|
|
79
|
+
.markdown-body ul {
|
|
80
|
+
list-style-type: disc;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.markdown-body ol {
|
|
84
|
+
list-style-type: decimal;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.markdown-body li {
|
|
88
|
+
display: list-item;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.markdown-body a {
|
|
92
|
+
color: hsl(var(--link));
|
|
93
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { buttonCva2, buttonVariant, 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
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
title?: string
|
|
9
|
+
href: string
|
|
10
|
+
variant?: ButtonVariant
|
|
11
|
+
size?: ButtonSize
|
|
12
|
+
icon?: string
|
|
13
|
+
iconRight?: string
|
|
14
|
+
iconClass?: string
|
|
15
|
+
newTab?: boolean
|
|
16
|
+
class?: string
|
|
17
|
+
id?: string
|
|
18
|
+
clickAnimation?: boolean
|
|
19
|
+
}
|
|
20
|
+
const props = Astro.props
|
|
21
|
+
const hasChildren = Astro.slots.has("default")
|
|
22
|
+
const classes = buttonCva2(
|
|
23
|
+
props.variant ?? buttonVariant.link,
|
|
24
|
+
props.size,
|
|
25
|
+
props.clickAnimation ?? classesButtonClickAnimation,
|
|
26
|
+
props.class,
|
|
27
|
+
)
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
<a href={props.href} class={classes} target={props.newTab ? "_blank" : undefined} id={props.id} title={props.title}>
|
|
31
|
+
{
|
|
32
|
+
props.icon && (
|
|
33
|
+
<Icon1
|
|
34
|
+
path={props.icon}
|
|
35
|
+
class={buttonIconCva(props.variant ?? "link", (props.title || hasChildren) && "mr-2", props.iconClass)}
|
|
36
|
+
/>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
<slot />
|
|
40
|
+
{
|
|
41
|
+
props.iconRight && (
|
|
42
|
+
<Icon1
|
|
43
|
+
path={props.iconRight}
|
|
44
|
+
class={buttonIconCva(props.variant ?? "link", (props.title || hasChildren) && "ml-2", props.iconClass)}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
</a>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { classMerge } from "~/utils/ui/classMerge"
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
title?: string
|
|
6
|
+
href: string
|
|
7
|
+
newTab?: boolean
|
|
8
|
+
class?: string
|
|
9
|
+
}
|
|
10
|
+
const props = Astro.props
|
|
11
|
+
const title = props.title
|
|
12
|
+
const href = props.href
|
|
13
|
+
const newTab = props.newTab
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<a
|
|
17
|
+
href={href}
|
|
18
|
+
class={classMerge("text-blue-500 no-underline hover:underline", props.class)}
|
|
19
|
+
target={newTab ? "_blank" : undefined}
|
|
20
|
+
title={title}
|
|
21
|
+
>
|
|
22
|
+
<slot/>
|
|
23
|
+
</a>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { classArr } from "../utils/ui/classArr"
|
|
2
|
+
|
|
3
|
+
export const classesTextLink = classArr(
|
|
4
|
+
"text-blue-600 hover:text-black", // light
|
|
5
|
+
"dark:text-orange-600 dark:hover:text-orange-400", // dark
|
|
6
|
+
"transition-colors", // animation
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
export const classesTextLinkGroupHover = classArr(
|
|
10
|
+
"group-hover:text-blue-600", // light
|
|
11
|
+
"dark:group-hover:text-orange-400", // dark
|
|
12
|
+
"transition-colors", // animation
|
|
13
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { classMerge } from "~/utils/ui/classMerge"
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
class?: string
|
|
6
|
+
}
|
|
7
|
+
const props = Astro.props
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<span
|
|
11
|
+
class={classMerge("text-xs text-blue-500 select-none mr-1 mt-1.5", props.class)}
|
|
12
|
+
aria-hidden={true}
|
|
13
|
+
style={{ fontSize: "0.5rem" }}
|
|
14
|
+
>
|
|
15
|
+
●</span
|
|
16
|
+
>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { mdiCircle } from "@mdi/js"
|
|
3
|
+
import { classMerge } from "~/utils/ui/classMerge"
|
|
4
|
+
import TextOrLink from "./TextOrLink.astro"
|
|
5
|
+
import Icon1 from "~/icon/Icon1.astro"
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
points: string[] | Readonly<string[]>
|
|
9
|
+
class?: string
|
|
10
|
+
classText?: string
|
|
11
|
+
classBullet?: string
|
|
12
|
+
}
|
|
13
|
+
const props = Astro.props
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
{
|
|
17
|
+
props.points.map((p) => (
|
|
18
|
+
<div class={classMerge("flex flex-row flex-nowrap", props.class)}>
|
|
19
|
+
<Icon1 path={mdiCircle} class={classMerge("w-1.5 h-1.5 mt-3 mx-1.5 shrink-0", props.classBullet)} />
|
|
20
|
+
<TextOrLink text={p} class={props.classText} />
|
|
21
|
+
</div>
|
|
22
|
+
))
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { mdiCheck } from "@mdi/js"
|
|
3
|
+
import { classMerge } from "~/utils/ui/classMerge"
|
|
4
|
+
import TextOrLink from "./TextOrLink.astro"
|
|
5
|
+
import Icon1 from "~/icon/Icon1.astro"
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
point: string
|
|
9
|
+
class?: string
|
|
10
|
+
classText?: string
|
|
11
|
+
classBullet?: string
|
|
12
|
+
}
|
|
13
|
+
const p = Astro.props
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<div class={classMerge("flex flex-row flex-nowrap", p.class)}>
|
|
17
|
+
<Icon1 path={mdiCheck} class={classMerge("fill-green-600 dark:fill-green-600 mr-1 flex-none", p.classBullet)} />
|
|
18
|
+
<TextOrLink text={p.point} class={p.classText} />
|
|
19
|
+
<slot />
|
|
20
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { mdiCheck } from "@mdi/js"
|
|
3
|
+
import { classMerge } from "~/utils/ui/classMerge"
|
|
4
|
+
import Icon1 from "~/icon/Icon1.astro"
|
|
5
|
+
import TextOrLink from "./TextOrLink.astro"
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
points: string[] | Readonly<string[]>
|
|
9
|
+
class?: string
|
|
10
|
+
classText?: string
|
|
11
|
+
classBullet?: string
|
|
12
|
+
}
|
|
13
|
+
const props = Astro.props
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
{
|
|
17
|
+
props.points.map((p) => (
|
|
18
|
+
<div class={classMerge("flex flex-row flex-nowrap", props.class)}>
|
|
19
|
+
<Icon1 path={mdiCheck} class={classMerge("fill-green-600 dark:fill-green-600 mr-1 flex-none", props.classBullet)} />
|
|
20
|
+
<TextOrLink text={p} class={props.classText} />
|
|
21
|
+
</div>
|
|
22
|
+
))
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { classMerge } from "~/utils/ui/classMerge"
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
points: string[] | Readonly<string[]>
|
|
6
|
+
classText?: string
|
|
7
|
+
class?: string
|
|
8
|
+
}
|
|
9
|
+
const props = Astro.props
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<ol class={classMerge("list-decimal", props.class)} style={{ paddingInlineStart: "18px" }}>
|
|
13
|
+
{props.points.map((l) => <li class={props.classText}>{l}</li>)}
|
|
14
|
+
</ol>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
import LinkText from "~/link/LinkText.astro"
|
|
3
|
+
import { classMerge } from "~/utils/ui/classMerge"
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
text: string
|
|
7
|
+
class?: string
|
|
8
|
+
}
|
|
9
|
+
const props = Astro.props
|
|
10
|
+
const text = props.text
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
text.startsWith("http") ? (
|
|
15
|
+
<LinkText href={text}>{text}</LinkText>
|
|
16
|
+
) : (
|
|
17
|
+
<p class={classMerge("leading-relaxed", props.class)}>{text}</p>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
import "./Modal.module.css"
|
|
3
|
+
import { classesTextHeader } from "~/text/classesTextHeader"
|
|
4
|
+
import { classMerge } from "~/utils/ui/classMerge"
|
|
5
|
+
import { buttonVariant } from "~/button/buttonCva"
|
|
6
|
+
import Button from "~/button/Button.astro"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* https://github.com/markteekman/accessible-astro-components/blob/main/Modal.astro
|
|
10
|
+
*/
|
|
11
|
+
interface Props {
|
|
12
|
+
triggerId: string
|
|
13
|
+
title: string
|
|
14
|
+
titleClass?: string
|
|
15
|
+
closeText?: string
|
|
16
|
+
class?: string
|
|
17
|
+
classContentArea?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const props = Astro.props
|
|
21
|
+
const triggerId = props.triggerId
|
|
22
|
+
const title = props.title
|
|
23
|
+
const titleClass = props.titleClass
|
|
24
|
+
const closeText = props.closeText ?? "Close"
|
|
25
|
+
const classContentArea = props.classContentArea
|
|
26
|
+
const closeId = `${triggerId}-close`
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
<dialog
|
|
30
|
+
class={classMerge(
|
|
31
|
+
"modal",
|
|
32
|
+
"fixed m-auto",
|
|
33
|
+
"max-w-5xl",
|
|
34
|
+
"bg-white dark:bg-gray-900 text-black dark:text-white", // bg
|
|
35
|
+
"border-1 border-black p-4 rounded-xl", // border
|
|
36
|
+
props.class,
|
|
37
|
+
)}
|
|
38
|
+
aria-labelledby={triggerId}
|
|
39
|
+
>
|
|
40
|
+
<div class={classMerge("w-full rounded-xl", classContentArea)}>
|
|
41
|
+
<div class="modal-content flex flex-col items-start gap-2 p-4">
|
|
42
|
+
<h2 tabindex="-1" class={classMerge(classesTextHeader, titleClass)}>
|
|
43
|
+
{title}
|
|
44
|
+
</h2>
|
|
45
|
+
<slot>Modal description</slot>
|
|
46
|
+
<Button id={closeId} variant={buttonVariant.outline} class="modal-close w-full">{closeText}</Button>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</dialog>
|
|
50
|
+
|
|
51
|
+
<script>
|
|
52
|
+
import { modal } from "./modal"
|
|
53
|
+
modal()
|
|
54
|
+
</script>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
dialog::backdrop {
|
|
2
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
3
|
+
filter: blur(6px);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/* Animation */
|
|
7
|
+
dialog[open],
|
|
8
|
+
dialog[open]::backdrop {
|
|
9
|
+
animation: fadein 0.2s ease-in-out;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@keyframes fadein {
|
|
13
|
+
from {
|
|
14
|
+
opacity: 0;
|
|
15
|
+
}
|
|
16
|
+
to {
|
|
17
|
+
opacity: 1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { generateId5 } from "~/utils/ran/generateId5"
|
|
3
|
+
import type { ButtonSize, ButtonVariant } from "~/button/buttonCva"
|
|
4
|
+
import Modal from "./Modal.astro"
|
|
5
|
+
import { classesTextGray } from "~/text/classesTextGray"
|
|
6
|
+
import { classArr } from "~/utils/ui/classArr"
|
|
7
|
+
import Button from "~/button/Button.astro"
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
button: {
|
|
11
|
+
title?: string
|
|
12
|
+
text?: string
|
|
13
|
+
variant: ButtonVariant
|
|
14
|
+
size?: ButtonSize
|
|
15
|
+
icon?: string
|
|
16
|
+
iconRight?: string
|
|
17
|
+
iconClass?: string
|
|
18
|
+
class?: string
|
|
19
|
+
}
|
|
20
|
+
id?: string
|
|
21
|
+
title?: string
|
|
22
|
+
class?: string
|
|
23
|
+
classContentArea?: string
|
|
24
|
+
}
|
|
25
|
+
const props = Astro.props
|
|
26
|
+
const id = props.id ?? `modal-id-${generateId5()}`
|
|
27
|
+
const button = props.button
|
|
28
|
+
const title = props.title ?? "Dialog Title"
|
|
29
|
+
const classContentArea = props.classContentArea
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
<Button id={id} {...button} />
|
|
33
|
+
<Modal
|
|
34
|
+
triggerId={id}
|
|
35
|
+
title={title}
|
|
36
|
+
titleClass={classArr(classesTextGray, "text-xl", "mb-2")}
|
|
37
|
+
class={props.class}
|
|
38
|
+
classContentArea={classContentArea}
|
|
39
|
+
>
|
|
40
|
+
<slot />
|
|
41
|
+
</Modal>
|