mirror of
https://github.com/tabler/tabler.git
synced 2026-08-29 13:21:29 +04:00
`Render Modal as real markup` (#2742) reformatted ~140 files back to tabs/semicolons, breaking the Prettier config added by the Astro quality gates (#2749). Re-run prettier --write to restore it, and fix the type errors it had been masking: HTMLElement casts and `this` typing in ChangePasswordModalContent/ConfirmDeleteModalContent scripts, plain-JS syntax in the inline-injected progress.astro script, narrowed prop unions in Button/Check/Spinner, nullable icon svg casts in Icons/Rating, and a duplicate firstLetters/invalid `placeholder` attribute in Select.astro. Also fix shared/vitest.config.mts's stale `astro/lib/**/*.test.ts` include glob left over from the shared source restructure, which made `pnpm test` report zero test files.
99 lines
4.0 KiB
Plaintext
99 lines
4.0 KiB
Plaintext
---
|
|
// Masonry auto-inits from the data-masonry attribute (page-lib, no init script,
|
|
// like cards-masonry.astro); fslightbox is a pure page-lib (no init script).
|
|
import DefaultLayout from '@shared/layouts/DefaultLayout.astro'
|
|
import CardStamp from '@ui/CardStamp.astro'
|
|
import Prose from '@ui/Prose.astro'
|
|
import CaptureScript from '@shared/components/CaptureScript.astro'
|
|
import { site } from '@shared/lib/site'
|
|
import emails from '@data/emails.json'
|
|
|
|
const emailEntries = Object.entries(emails)
|
|
---
|
|
|
|
<DefaultLayout pageHeader="Email templates" pageMenu="addons.emails" pageLibs={['masonry', 'fslightbox']}>
|
|
<div class="row row-cards">
|
|
<div class="col-12">
|
|
<div class="card card-md">
|
|
<CardStamp size="lg" icon="mail" color="primary" />
|
|
<div class="card-body">
|
|
<div class="row align-items-center">
|
|
<div class="col-10">
|
|
<h3 class="h1">Tabler Emails</h3>
|
|
<Prose class="text-secondary fs-3">
|
|
{emailEntries.length} eye-catching, customizable and responsive email templates to improve your email communication. No coding skills needed.
|
|
</Prose>
|
|
<div class="mt-3">
|
|
<a href={site.emails.buy_link} class="btn btn-primary" target="_blank">Buy all emails for {site.emails.price}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<div class="row row-cards" data-masonry={'{"percentPosition": true }'}>
|
|
{
|
|
emailEntries.map(([key, email]) => (
|
|
<div class="col-4">
|
|
<a href={`./static/emails/${key}.jpg`} data-bs-toggle="modal" data-bs-target="#email-modal" data-bs-title={email.descriptionShort} data-bs-description={email.descriptionLong} data-bs-image={`./static/emails/${key}.jpg`}>
|
|
<img src={`./static/emails/${key}.jpg`} class="img-fluid rounded" alt={email.descriptionShort} width={email.width} height={email.height} />
|
|
</a>
|
|
</div>
|
|
))
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal fade" id="email-modal" aria-hidden="true" aria-labelledby="email-modal-label" tabindex="-1">
|
|
<div class="modal-dialog modal-xl modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
<div class="modal-body p-0">
|
|
<div class="row g-0">
|
|
<div class="col-6">
|
|
<div class="p-6 bg-surface-secondary rounded-start">
|
|
<img src="" class="img-fluid rounded-start" data-email-image />
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<div class="p-7">
|
|
<Prose>
|
|
<h3 data-email-title></h3>
|
|
<p data-email-description></p>
|
|
</Prose>
|
|
|
|
<div class="mt-6">
|
|
<a href={site.emails.buy_link} class="btn btn-primary w-100" target="_blank">Buy {site.emails.count} emails for {site.emails.price}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<CaptureScript>
|
|
<!-- BEGIN EMAIL MODAL SCRIPT -->
|
|
<script is:inline>
|
|
const emailModal = document.getElementById('email-modal')
|
|
if (emailModal) {
|
|
emailModal.addEventListener('show.bs.modal', function (e) {
|
|
const button = e.relatedTarget
|
|
if (!(button instanceof HTMLElement)) return
|
|
|
|
const image = button.getAttribute('data-bs-image'),
|
|
title = button.getAttribute('data-bs-title'),
|
|
description = button.getAttribute('data-bs-description')
|
|
|
|
emailModal.querySelector('[data-email-title]').textContent = title
|
|
emailModal.querySelector('[data-email-description]').textContent = description
|
|
emailModal.querySelector('[data-email-image]').src = image
|
|
})
|
|
}
|
|
</script>
|
|
<!-- END EMAIL MODAL SCRIPT -->
|
|
</CaptureScript>
|
|
</DefaultLayout>
|