🎉 Add the mail template project

This commit is contained in:
2025-11-09 03:19:35 +08:00
parent ce5f3434eb
commit f5b37e9419
15 changed files with 1245 additions and 1 deletions

View File

@@ -0,0 +1,55 @@
<script props>
// https://maizzle.com/docs/components/button
let align = {
left: 'text-left',
center: 'text-center',
right: 'text-right',
}[props.align] || ''
let styles = [
'display: inline-block;',
'text-decoration: none;',
'padding: 16px 24px;',
'font-size: 16px;',
'line-height: 1;',
'border-radius: 4px;',
]
let hasBgClass = () => props.class && props.class.split(' ').some(c => c.startsWith('bg-'))
if (props['bg-color'] && !hasBgClass()) {
styles.push(`background-color: ${props['bg-color']};`)
} else {
styles.push('background-color: #4338ca;')
}
if (props.color) {
styles.push(`color: ${props.color};`)
} else {
styles.push('color: #fffffe;')
}
module.exports = {
align,
href: props.href,
styles: styles.join(''),
msoPt: props['mso-pt'] || '16px',
msoPb: props['mso-pb'] || '31px',
}
</script>
<div class="{{ align }}">
<a
attributes
href="{{{ href }}}"
style="{{ styles }}"
>
<outlook trim>
<i class="mso-font-width-[150%]" style="mso-text-raise: {{ msoPb }};" hidden>&emsp;</i>
</outlook>
<span style="mso-text-raise: {{ msoPt }}" trim><yield /></span>
<outlook trim>
<i class="mso-font-width-[150%]" hidden>&emsp;&#8203;</i>
</outlook>
</a>
</div>

View File

@@ -0,0 +1,70 @@
<script props>
// https://maizzle.com/docs/components/divider
let styles = [
`height: ${props.height || '1px'};`,
`line-height: ${props.height || '1px'};`,
]
/**
* Color
*
* If a Tailwind background color class was passed, use it.
* Otherwise, the `color` prop will take precedence if
* as long as it was passed.
*/
let hasBgClass = () => props.class && props.class.split(' ').some(c => c.startsWith('bg-'))
if (props.color) {
styles.push(`background-color: ${props.color};`)
}
if (!props.color && !hasBgClass()) {
styles.push(`background-color: #cbd5e1;`)
}
/**
* Margins
*
* If any margin prop was passed, add `margin: 0` first.
* It's important that this comes first, so inlining
* does not use it to override existing margins.
*/
if (props.top || props.bottom || props.left || props.right || props['space-y'] || props['space-x']) {
styles.push('margin: 0;')
}
props['space-y'] = props['space-y'] === 0 ? '0px' : props['space-y'] || '24px'
if (props['space-y']) {
styles.push(`margin-top: ${props['space-y']}; margin-bottom: ${props['space-y']};`)
}
props['space-x'] = props['space-x'] === 0 ? '0px' : props['space-x']
if (props['space-x']) {
styles.push(`margin-left: ${props['space-x']}; margin-right: ${props['space-x']};`)
}
props.top = props.top === 0 ? '0px' : props.top
if (props.top) {
styles.push(`margin-top: ${props.top};`)
}
props.bottom = props.bottom === 0 ? '0px' : props.bottom
if (props.bottom) {
styles.push(`margin-bottom: ${props.bottom};`)
}
props.left = props.left === 0 ? '0px' : props.left
if (props.left) {
styles.push(`margin-left: ${props.left};`)
}
props.right = props.right === 0 ? '0px' : props.right
if (props.right) {
styles.push(`margin-right: ${props.right};`)
}
module.exports = {
styles: styles.join(''),
}
</script>
<div role="separator" style="{{ styles }}">&zwj;</div>

View File

@@ -0,0 +1,27 @@
<script props>
// https://maizzle.com/docs/components/spacer
let styles = []
if (props.height) {
styles.push(`line-height: ${props.height};`)
}
if (props['mso-height']) {
styles.push(`mso-line-height-alt: ${props['mso-height']};`)
}
module.exports = {
height: props.height,
styles: styles.join('')
}
</script>
<if condition="height">
<div
role="separator"
style="{{ styles }}"
>&zwj;</div>
</if>
<else>
<div role="separator">&zwj;</div>
</else>

View File

@@ -0,0 +1,25 @@
<script props>
// https://maizzle.com/docs/components/vml#v-fill
module.exports = {
width: props.width || '600px',
type: props.type || 'frame',
sizes: props.sizes,
origin: props.origin,
position: props.position,
aspect: props.aspect,
color: props.color,
inset: props.inset || '0,0,0,0',
stroke: props.stroke || 'f',
strokecolor: props.strokecolor,
fill: props.fill || 't',
fillcolor: props.fillcolor || 'none',
image: props.image || 'https://via.placeholder.com/600x400'
}
</script>
<!--[if mso]>
<v:rect fill="{{ fillcolor ? 't' : fill }}" stroke="{{ strokecolor ? 't' : stroke }}" style="width: {{ width }}" xmlns:v="urn:schemas-microsoft-com:vml"{{{ strokecolor ? ` strokecolor="${strokecolor}"` : '' }}}{{{ fillcolor ? ` fillcolor="${fillcolor}"` : '' }}}>
<v:fill type="{{ type }}" src="{{{ image }}}"{{{ sizes ? ` sizes="${sizes}"` : '' }}}{{{ aspect ? ` aspect="${aspect}"` : '' }}}{{{ origin ? ` origin="${origin}"` : '' }}}{{{ position ? ` position="${position}"` : '' }}}{{{ color ? ` color="${color}"` : '' }}} />
<v:textbox inset="{{ inset }}" style="mso-fit-shape-to-text: true"><div><![endif]-->
<yield />
<!--[if mso]></div></v:textbox></v:rect><![endif]-->