better-svelte-email 0.0.1

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 (38) hide show
  1. package/README.md +422 -0
  2. package/dist/components/Body.svelte +9 -0
  3. package/dist/components/Body.svelte.d.ts +13 -0
  4. package/dist/components/Button.svelte +54 -0
  5. package/dist/components/Button.svelte.d.ts +21 -0
  6. package/dist/components/Container.svelte +28 -0
  7. package/dist/components/Container.svelte.d.ts +13 -0
  8. package/dist/components/Head.svelte +13 -0
  9. package/dist/components/Head.svelte.d.ts +6 -0
  10. package/dist/components/Html.svelte +19 -0
  11. package/dist/components/Html.svelte.d.ts +10 -0
  12. package/dist/components/Section.svelte +21 -0
  13. package/dist/components/Section.svelte.d.ts +13 -0
  14. package/dist/components/Text.svelte +17 -0
  15. package/dist/components/Text.svelte.d.ts +15 -0
  16. package/dist/components/__tests__/test-email.svelte +13 -0
  17. package/dist/components/__tests__/test-email.svelte.d.ts +26 -0
  18. package/dist/components/index.d.ts +7 -0
  19. package/dist/components/index.js +9 -0
  20. package/dist/emails/demo-email.svelte +108 -0
  21. package/dist/emails/demo-email.svelte.d.ts +13 -0
  22. package/dist/emails/test-email.svelte +15 -0
  23. package/dist/emails/test-email.svelte.d.ts +26 -0
  24. package/dist/index.d.ts +8 -0
  25. package/dist/index.js +10 -0
  26. package/dist/preprocessor/head-injector.d.ts +9 -0
  27. package/dist/preprocessor/head-injector.js +57 -0
  28. package/dist/preprocessor/index.d.ts +25 -0
  29. package/dist/preprocessor/index.js +196 -0
  30. package/dist/preprocessor/parser.d.ts +14 -0
  31. package/dist/preprocessor/parser.js +249 -0
  32. package/dist/preprocessor/transformer.d.ts +18 -0
  33. package/dist/preprocessor/transformer.js +158 -0
  34. package/dist/preprocessor/types.d.ts +104 -0
  35. package/dist/preprocessor/types.js +1 -0
  36. package/dist/utils/index.d.ts +12 -0
  37. package/dist/utils/index.js +24 -0
  38. package/package.json +97 -0
package/README.md ADDED
@@ -0,0 +1,422 @@
1
+ # better-svelte-email
2
+
3
+ [![CI](https://github.com/YOUR_USERNAME/better-svelte-email/actions/workflows/ci.yml/badge.svg)](https://github.com/YOUR_USERNAME/better-svelte-email/actions/workflows/ci.yml)
4
+ [![Tests](https://github.com/YOUR_USERNAME/better-svelte-email/actions/workflows/release.yml/badge.svg)](https://github.com/YOUR_USERNAME/better-svelte-email/actions/workflows/release.yml)
5
+
6
+ A Svelte 5 preprocessor that transforms Tailwind CSS classes in email components to inline styles with responsive media query support.
7
+
8
+ ## Features
9
+
10
+ ✨ **Stable & Future-Proof** - Uses Svelte 5's public preprocessor API
11
+ 🎨 **Tailwind CSS Support** - Transforms Tailwind classes to inline styles for email clients
12
+ 📱 **Responsive Emails** - Preserves responsive classes (`sm:`, `md:`, `lg:`) as media queries
13
+ ⚡ **Build-Time Transformation** - Zero runtime overhead
14
+ 🔍 **TypeScript First** - Fully typed with comprehensive type definitions
15
+ ✅ **Well Tested** - Extensive test coverage with unit and integration tests
16
+
17
+ ## Why?
18
+
19
+ Email clients don't support modern CSS in `<style>` tags, requiring inline styles. But writing inline styles is tedious and hard to maintain. This preprocessor lets you write Tailwind CSS classes and automatically transforms them to inline styles at build time.
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install better-svelte-email
25
+ # or
26
+ bun add better-svelte-email
27
+ # or
28
+ pnpm add better-svelte-email
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ### 1. Configure the Preprocessor
34
+
35
+ Add the preprocessor to your `svelte.config.js`:
36
+
37
+ ```javascript
38
+ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
39
+ import { betterSvelteEmailPreprocessor } from 'better-svelte-email';
40
+
41
+ /** @type {import('@sveltejs/kit').Config} */
42
+ const config = {
43
+ preprocess: [
44
+ vitePreprocess(),
45
+ betterSvelteEmailPreprocessor({
46
+ pathToEmailFolder: '/src/lib/emails',
47
+ debug: false
48
+ })
49
+ ],
50
+ kit: {
51
+ adapter: adapter()
52
+ }
53
+ };
54
+
55
+ export default config;
56
+ ```
57
+
58
+ ### 2. Create Email Components
59
+
60
+ Create your email templates in `src/lib/emails/`:
61
+
62
+ ```svelte
63
+ <!-- src/lib/emails/welcome.svelte -->
64
+ <script>
65
+ let { name = 'User' } = $props();
66
+ </script>
67
+
68
+ <Html>
69
+ <Head />
70
+ <Body class="bg-gray-100">
71
+ <Container class="mx-auto p-8">
72
+ <Text class="mb-4 text-2xl font-bold">
73
+ Welcome, {name}!
74
+ </Text>
75
+
76
+ <Button
77
+ href="https://example.com"
78
+ class="rounded bg-blue-600 px-6 py-3 text-white sm:bg-green-600"
79
+ >
80
+ Get Started
81
+ </Button>
82
+ </Container>
83
+ </Body>
84
+ </Html>
85
+ ```
86
+
87
+ ### 3. Render and Send
88
+
89
+ ```typescript
90
+ // src/routes/api/send-email/+server.ts
91
+ import { render } from 'svelte/server';
92
+ import WelcomeEmail from '$lib/emails/welcome.svelte';
93
+
94
+ export async function POST({ request }) {
95
+ const { name, email } = await request.json();
96
+
97
+ // Render email (preprocessor already ran at build time!)
98
+ // In Svelte 5, pass props directly to render
99
+ const result = render(WelcomeEmail, { props: { name } });
100
+
101
+ // Send email using your preferred service (Resend, SendGrid, etc.)
102
+ // await resend.emails.send({
103
+ // from: 'noreply@example.com',
104
+ // to: email,
105
+ // subject: 'Welcome!',
106
+ // html: result.body
107
+ // });
108
+
109
+ return new Response('Sent');
110
+ }
111
+ ```
112
+
113
+ ## How It Works
114
+
115
+ The preprocessor transforms your Tailwind classes in three steps:
116
+
117
+ ### 1. Non-Responsive Classes → Inline Styles
118
+
119
+ ```svelte
120
+ <!-- Input -->
121
+ <Button class="bg-blue-500 p-4 text-white">Click</Button>
122
+
123
+ <!-- Output -->
124
+ <Button
125
+ styleString="background-color: rgb(59, 130, 246); color: rgb(255, 255, 255); padding: 16px;"
126
+ >
127
+ Click
128
+ </Button>
129
+ ```
130
+
131
+ ### 2. Responsive Classes → Media Queries
132
+
133
+ ```svelte
134
+ <!-- Input -->
135
+ <Button class="bg-blue-500 sm:bg-red-500">Click</Button>
136
+
137
+ <!-- Output -->
138
+ <Button class="sm_bg-red-500" styleString="background-color: rgb(59, 130, 246);">Click</Button>
139
+
140
+ <!-- Injected into <Head> -->
141
+ <style>
142
+ @media (max-width: 475px) {
143
+ .sm_bg-red-500 {
144
+ background-color: rgb(239, 68, 68) !important;
145
+ }
146
+ }
147
+ </style>
148
+ ```
149
+
150
+ ### 3. Mixed Classes → Both
151
+
152
+ ```svelte
153
+ <!-- Input -->
154
+ <Button class="rounded bg-blue-500 p-4 sm:bg-red-500 md:p-6">Click</Button>
155
+
156
+ <!-- Output -->
157
+ <Button
158
+ class="sm_bg-red-500 md_p-6"
159
+ styleString="border-radius: 4px; background-color: rgb(59, 130, 246); padding: 16px;"
160
+ >
161
+ Click
162
+ </Button>
163
+ ```
164
+
165
+ ## Configuration
166
+
167
+ ### Options
168
+
169
+ ```typescript
170
+ interface PreprocessorOptions {
171
+ /**
172
+ * Path to folder containing email components
173
+ * @default '/src/lib/emails'
174
+ */
175
+ pathToEmailFolder?: string;
176
+
177
+ /**
178
+ * Custom Tailwind configuration
179
+ * @default undefined
180
+ */
181
+ tailwindConfig?: TailwindConfig;
182
+
183
+ /**
184
+ * Enable debug logging
185
+ * @default false
186
+ */
187
+ debug?: boolean;
188
+ }
189
+ ```
190
+
191
+ ### Custom Tailwind Config
192
+
193
+ ```javascript
194
+ betterSvelteEmailPreprocessor({
195
+ pathToEmailFolder: '/src/lib/emails',
196
+ tailwindConfig: {
197
+ theme: {
198
+ extend: {
199
+ colors: {
200
+ brand: '#FF3E00'
201
+ }
202
+ }
203
+ }
204
+ }
205
+ });
206
+ ```
207
+
208
+ ## Supported Features
209
+
210
+ ### ✅ Supported
211
+
212
+ - ✅ Static Tailwind classes
213
+ - ✅ All standard Tailwind utilities (colors, spacing, typography, etc.)
214
+ - ✅ Responsive breakpoints (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`)
215
+ - ✅ HTML elements and Svelte components
216
+ - ✅ Nested components
217
+ - ✅ Conditional blocks (`{#if}`)
218
+ - ✅ Each blocks (`{#each}`)
219
+ - ✅ Custom Tailwind configurations
220
+
221
+ ### ❌ Not Supported (Yet)
222
+
223
+ - ❌ Dynamic class expressions (`class={someVar}`)
224
+ - ❌ Arbitrary values in responsive classes (`sm:[color:red]`)
225
+ - ❌ Container queries
226
+
227
+ ## API Reference
228
+
229
+ ### Main Export
230
+
231
+ ```typescript
232
+ import { betterSvelteEmailPreprocessor } from 'better-svelte-email';
233
+ ```
234
+
235
+ ### Advanced Exports
236
+
237
+ For advanced use cases, you can use individual functions:
238
+
239
+ ```typescript
240
+ import {
241
+ parseClassAttributes,
242
+ transformTailwindClasses,
243
+ generateMediaQueries,
244
+ injectMediaQueries
245
+ } from 'better-svelte-email';
246
+ ```
247
+
248
+ ## Testing
249
+
250
+ The library includes comprehensive tests:
251
+
252
+ ```bash
253
+ # Run all tests
254
+ npm test
255
+
256
+ # Run tests in watch mode
257
+ npm run test:watch
258
+
259
+ # Run tests with UI
260
+ npm run test:ui
261
+
262
+ # Run tests with coverage
263
+ npm run test:coverage
264
+ ```
265
+
266
+ ## Examples
267
+
268
+ ### Simple Button
269
+
270
+ ```svelte
271
+ <Button class="rounded bg-blue-500 px-4 py-2 text-white">Click Me</Button>
272
+ ```
273
+
274
+ ### Responsive Layout
275
+
276
+ ```svelte
277
+ <Container class="mx-auto w-full max-w-2xl p-4 sm:p-6 md:p-8">
278
+ <Text class="text-lg sm:text-xl md:text-2xl">Responsive Text</Text>
279
+ </Container>
280
+ ```
281
+
282
+ ### Complex Email
283
+
284
+ ```svelte
285
+ <Html>
286
+ <Head />
287
+ <Body class="bg-gray-100 font-sans">
288
+ <Container class="mx-auto my-8 max-w-2xl rounded-lg bg-white shadow-lg">
289
+ <Section class="p-8">
290
+ <Text class="mb-4 text-3xl font-bold text-gray-900">Welcome to Our Service</Text>
291
+
292
+ <Text class="mb-6 text-gray-600">
293
+ Thank you for signing up. We're excited to have you on board!
294
+ </Text>
295
+
296
+ <Button
297
+ href="https://example.com/verify"
298
+ class="rounded-lg bg-blue-600 px-8 py-4 font-semibold text-white sm:bg-green-600"
299
+ >
300
+ Verify Your Email
301
+ </Button>
302
+ </Section>
303
+ </Container>
304
+ </Body>
305
+ </Html>
306
+ ```
307
+
308
+ ## Troubleshooting
309
+
310
+ ### Classes not being transformed
311
+
312
+ 1. Make sure your file is in the configured `pathToEmailFolder`
313
+ 2. Check that your classes are static strings, not dynamic expressions
314
+ 3. Enable debug mode to see warnings: `{ debug: true }`
315
+
316
+ ### Media queries not working
317
+
318
+ 1. Ensure you have a `<Head />` component in your email
319
+ 2. Check that you're using standard breakpoints (`sm:`, `md:`, etc.)
320
+ 3. Verify the media queries are being injected (view the rendered HTML)
321
+
322
+ ### Type errors
323
+
324
+ Make sure you have the latest version of Svelte 5:
325
+
326
+ ```bash
327
+ npm install svelte@^5.0.0
328
+ ```
329
+
330
+ ## Contributing
331
+
332
+ Contributions are welcome! Please feel free to submit a Pull Request.
333
+
334
+ ## License
335
+
336
+ MIT
337
+
338
+ ## Author
339
+
340
+ Anatole
341
+
342
+ ## Svelte 5 Syntax
343
+
344
+ This library requires **Svelte 5** and uses modern Svelte 5 syntax. Key differences from Svelte 4:
345
+
346
+ ### Props Declaration
347
+
348
+ ```svelte
349
+ <!-- Svelte 5 (Correct) -->
350
+ <script>
351
+ let { name = 'User', email } = $props();
352
+ </script>
353
+
354
+ <!-- Svelte 4 (Old - Don't use) -->
355
+ <script>
356
+ export let name = 'User';
357
+ export let email;
358
+ </script>
359
+ ```
360
+
361
+ ### Server Rendering
362
+
363
+ ```typescript
364
+ // Svelte 5
365
+ import { render } from 'svelte/server';
366
+ const result = render(Component, { props: { name } });
367
+ const html = result.body;
368
+ ```
369
+
370
+ For a complete guide on Svelte 5 syntax, see [SVELTE5_MIGRATION.md](./SVELTE5_MIGRATION.md).
371
+
372
+ ## Development
373
+
374
+ ### Running Tests
375
+
376
+ ```bash
377
+ bun test
378
+ ```
379
+
380
+ All tests must pass before pushing to main. The CI/CD pipeline will automatically run tests on every push and pull request.
381
+
382
+ ### Building
383
+
384
+ ```bash
385
+ bun run build
386
+ ```
387
+
388
+ ### Contributing
389
+
390
+ 1. Fork the repository
391
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
392
+ 3. Make your changes
393
+ 4. Run tests (`bun test`)
394
+ 5. Commit your changes using [conventional commits](https://www.conventionalcommits.org/):
395
+ - `feat:` - New features
396
+ - `fix:` - Bug fixes
397
+ - `docs:` - Documentation changes
398
+ - `test:` - Test additions/changes
399
+ - `chore:` - Maintenance tasks
400
+ 6. Push to your branch (`git push origin feature/amazing-feature`)
401
+ 7. Open a Pull Request
402
+
403
+ ### Releases
404
+
405
+ Releases are automated via GitHub Actions. When you bump the version in `package.json` and push to `main`, a new release will be automatically created with a generated changelog.
406
+
407
+ See [RELEASE.md](./RELEASE.md) for detailed release process documentation.
408
+
409
+ ## Acknowledgments
410
+
411
+ - Built on top of [Svelte 5](https://svelte.dev/)
412
+ - Uses [tw-to-css](https://github.com/dvkndn/tw-to-css) for Tailwind to CSS conversion
413
+ - Uses [magic-string](https://github.com/rich-harris/magic-string) for efficient source transformations
414
+
415
+ ## Related Projects
416
+
417
+ - [react-email](https://react.email/) - React version for email templates
418
+ - [svelte-email](https://github.com/carstenlebek/svelte-email) - Original Svelte email library
419
+
420
+ ## Support
421
+
422
+ If you find this project useful, please consider giving it a ⭐️ on GitHub!
@@ -0,0 +1,9 @@
1
+ <script>
2
+ import { styleToString } from '../utils/index.js';
3
+
4
+ let { styleString = '', children, ...restProps } = $props();
5
+ </script>
6
+
7
+ <body {...restProps} style={styleString}>
8
+ {@render children?.()}
9
+ </body>
@@ -0,0 +1,13 @@
1
+ export default Body;
2
+ type Body = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const Body: import("svelte").Component<{
7
+ styleString?: string;
8
+ children: any;
9
+ } & Record<string, any>, {}, "">;
10
+ type $$ComponentProps = {
11
+ styleString?: string;
12
+ children: any;
13
+ } & Record<string, any>;
@@ -0,0 +1,54 @@
1
+ <script>
2
+ import { styleToString, pxToPt } from '../utils/index.js';
3
+
4
+ let {
5
+ href = '#',
6
+ target = '_blank',
7
+ styleString = '',
8
+ pX = 0,
9
+ pY = 0,
10
+ children,
11
+ ...restProps
12
+ } = $props();
13
+
14
+ const y = pY * 2;
15
+ const textRaise = pxToPt(y.toString());
16
+
17
+ // Button link styles
18
+ const buttonStyle = styleToString({
19
+ lineHeight: '100%',
20
+ textDecoration: 'none',
21
+ display: 'inline-block',
22
+ maxWidth: '100%',
23
+ padding: pY || pX ? `${pY}px ${pX}px` : undefined
24
+ });
25
+
26
+ // Button text styles with MSO support
27
+ const buttonTextStyle = styleToString({
28
+ maxWidth: '100%',
29
+ display: 'inline-block',
30
+ lineHeight: '120%',
31
+ textDecoration: 'none',
32
+ textTransform: 'none',
33
+ msoPaddingAlt: '0px',
34
+ msoTextRaise: pY ? pxToPt(pY.toString()) : undefined
35
+ });
36
+
37
+ const finalStyle = buttonStyle + (styleString ? ';' + styleString : '');
38
+ </script>
39
+
40
+ <a {...restProps} {href} {target} style={finalStyle}>
41
+ {#if pX}
42
+ <span>
43
+ {@html `<!--[if mso]><i style="letter-spacing: ${pX}px;mso-font-width:-100%;mso-text-raise:${textRaise}" hidden>&nbsp;</i><![endif]-->`}
44
+ </span>
45
+ {/if}
46
+ <span style={buttonTextStyle}>
47
+ {@render children?.()}
48
+ </span>
49
+ {#if pX}
50
+ <span>
51
+ {@html `<!--[if mso]><i style="letter-spacing: ${pX}px;mso-font-width:-100%" hidden>&nbsp;</i><![endif]-->`}
52
+ </span>
53
+ {/if}
54
+ </a>
@@ -0,0 +1,21 @@
1
+ export default Button;
2
+ type Button = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const Button: import("svelte").Component<{
7
+ href?: string;
8
+ target?: string;
9
+ styleString?: string;
10
+ pX?: number;
11
+ pY?: number;
12
+ children: any;
13
+ } & Record<string, any>, {}, "">;
14
+ type $$ComponentProps = {
15
+ href?: string;
16
+ target?: string;
17
+ styleString?: string;
18
+ pX?: number;
19
+ pY?: number;
20
+ children: any;
21
+ } & Record<string, any>;
@@ -0,0 +1,28 @@
1
+ <script>
2
+ import { styleToString } from '../utils/index.js';
3
+
4
+ let { styleString = '', children, ...restProps } = $props();
5
+
6
+ // Default max-width for email containers (600px = 37.5em)
7
+ const baseStyle = styleToString({ maxWidth: '37.5em' });
8
+ const finalStyle = baseStyle + (styleString ? ';' + styleString : '');
9
+ </script>
10
+
11
+ <table
12
+ align="center"
13
+ width="100%"
14
+ role="presentation"
15
+ cellspacing="0"
16
+ cellpadding="0"
17
+ border="0"
18
+ {...restProps}
19
+ style={finalStyle}
20
+ >
21
+ <tbody>
22
+ <tr style="width: 100%;">
23
+ <td>
24
+ {@render children?.()}
25
+ </td>
26
+ </tr>
27
+ </tbody>
28
+ </table>
@@ -0,0 +1,13 @@
1
+ export default Container;
2
+ type Container = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const Container: import("svelte").Component<{
7
+ styleString?: string;
8
+ children: any;
9
+ } & Record<string, any>, {}, "">;
10
+ type $$ComponentProps = {
11
+ styleString?: string;
12
+ children: any;
13
+ } & Record<string, any>;
@@ -0,0 +1,13 @@
1
+ <script lang="ts">
2
+ let { children }: { children?: any } = $props();
3
+ </script>
4
+
5
+ <head>
6
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <meta name="x-apple-disable-message-reformatting" />
9
+ <!--[if !mso]><!-->
10
+ <meta http-equiv="x-ua-compatible" content="IE=edge" />
11
+ <!--<![endif]-->
12
+ {@render children?.()}
13
+ </head>
@@ -0,0 +1,6 @@
1
+ type $$ComponentProps = {
2
+ children?: any;
3
+ };
4
+ declare const Head: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type Head = ReturnType<typeof Head>;
6
+ export default Head;
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ lang?: string;
4
+ dir?: 'ltr' | 'rtl' | 'auto' | null | undefined;
5
+ styleString?: string;
6
+ children?: any;
7
+ [key: string]: any;
8
+ }
9
+
10
+ let { lang = 'en', dir = 'ltr', styleString = '', children, ...restProps }: Props = $props();
11
+
12
+ const doctype =
13
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
14
+ </script>
15
+
16
+ {@html doctype}
17
+ <html {...restProps} id="__svelte-email" {lang} {dir} style={styleString}>
18
+ {@render children?.()}
19
+ </html>
@@ -0,0 +1,10 @@
1
+ interface Props {
2
+ lang?: string;
3
+ dir?: 'ltr' | 'rtl' | 'auto' | null | undefined;
4
+ styleString?: string;
5
+ children?: any;
6
+ [key: string]: any;
7
+ }
8
+ declare const Html: import("svelte").Component<Props, {}, "">;
9
+ type Html = ReturnType<typeof Html>;
10
+ export default Html;
@@ -0,0 +1,21 @@
1
+ <script>
2
+ let { styleString = '', children, ...restProps } = $props();
3
+ </script>
4
+
5
+ <table
6
+ width="100%"
7
+ role="presentation"
8
+ cellspacing="0"
9
+ cellpadding="0"
10
+ border="0"
11
+ {...restProps}
12
+ style={styleString}
13
+ >
14
+ <tbody>
15
+ <tr>
16
+ <td>
17
+ {@render children?.()}
18
+ </td>
19
+ </tr>
20
+ </tbody>
21
+ </table>
@@ -0,0 +1,13 @@
1
+ export default Section;
2
+ type Section = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const Section: import("svelte").Component<{
7
+ styleString?: string;
8
+ children: any;
9
+ } & Record<string, any>, {}, "">;
10
+ type $$ComponentProps = {
11
+ styleString?: string;
12
+ children: any;
13
+ } & Record<string, any>;
@@ -0,0 +1,17 @@
1
+ <script>
2
+ import { styleToString } from '../utils/index.js';
3
+
4
+ let { as = 'p', styleString = '', children, ...restProps } = $props();
5
+
6
+ // Default email-safe text styles
7
+ const baseStyle = styleToString({
8
+ fontSize: '14px',
9
+ lineHeight: '24px',
10
+ margin: '16px 0'
11
+ });
12
+ const finalStyle = baseStyle + (styleString ? ';' + styleString : '');
13
+ </script>
14
+
15
+ <svelte:element this={as} {...restProps} style={finalStyle}>
16
+ {@render children?.()}
17
+ </svelte:element>
@@ -0,0 +1,15 @@
1
+ export default Text;
2
+ type Text = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const Text: import("svelte").Component<{
7
+ as?: string;
8
+ styleString?: string;
9
+ children: any;
10
+ } & Record<string, any>, {}, "">;
11
+ type $$ComponentProps = {
12
+ as?: string;
13
+ styleString?: string;
14
+ children: any;
15
+ } & Record<string, any>;