@teiler/svelte 0.0.29 → 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 ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023-present, NERDSLABS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md CHANGED
@@ -4,9 +4,16 @@
4
4
 
5
5
  **Teiler** is an open source library that simplifies the creation of stylish components for various frameworks.
6
6
 
7
- Currently in the **alpha phase**, the library is actively being developed and improved. It currently provides support solely for Svelte CSR (Client-Side Rendering).
7
+ Currently in the **alpha phase**, the library is actively being developed and improved. This package is the **Svelte 5** adapter and supports both CSR (Client-Side Rendering) and SSR (Server-Side Rendering).
8
8
 
9
- Join our community on our [Discord Server](https://discord.gg/J6Sv9sQ64t) to stay informed about the latest developments, exchange ideas, and connect with fellow developers. We are continuously working on expanding our support to include more frameworks, allowing developers to effortlessly create components across various environments.
9
+ Join our community on our [Discord Server](https://discord.gg/J6Sv9sQ64t) to stay informed about the latest developments, exchange ideas, and connect with fellow developers. We are continuously working on expanding our support to include more frameworks, allowing developers to effortlessly create components across various environments.
10
+
11
+ ## Requirements
12
+
13
+ - `svelte` `^5.16.0`
14
+ - A Svelte-aware bundler (Vite with `@sveltejs/vite-plugin-svelte`, SvelteKit, `rollup-plugin-svelte`, …)
15
+
16
+ The package ships uncompiled `.svelte` files through the `svelte` export condition, so your bundler compiles them for the right target (client or server) with the same Svelte version as your application.
10
17
 
11
18
  ### Example
12
19
 
@@ -33,6 +40,19 @@ const Button = component.button<{
33
40
  `
34
41
  ```
35
42
 
43
+ ```svelte
44
+ <Button _primary={primary} onclick={() => count++}>Clicked {count} times</Button>
45
+ ```
46
+
47
+ Props prefixed with `_` are used only for styles and are not forwarded to the DOM. Every other prop, including event handlers (`onclick`, `oninput`, …) and `class`, is forwarded to the rendered element.
48
+
49
+ ## Migrating from Svelte 4 (`@teiler/svelte` 0.0.x)
50
+
51
+ - Svelte 5 is required (`svelte` `^5.16.0`); Svelte 4 is no longer supported.
52
+ - Event handlers are props: `<Button onclick={handler}>` instead of `<Button on:click={handler}>`.
53
+ - If you provide the theme through context yourself, the `THEME` context holds a getter (`() => theme`) instead of a writable store. `ThemeProvider` usage is unchanged.
54
+ - UMD/CJS bundles are gone; the package is consumed as Svelte source by your bundler.
55
+
36
56
  ## Keyframes
37
57
 
38
58
  ```typescript
@@ -67,31 +87,88 @@ const Button = component.button<{}>`
67
87
  `
68
88
  ```
69
89
 
70
- ## Theme
90
+ ## Extending
71
91
 
72
- Example how to use themes.
92
+ Pass an existing component to `component` to add styles to it. The new component keeps the element of the extended one, unless you pick another element with `component.<tag>`:
73
93
 
74
94
  ```typescript
75
- // Main component inside application (`App.svelte`)
76
- <script context="module" lang="ts">
77
- export type CustomTheme = {
78
- fontColor: string,
79
- }
95
+ import { component } from '@teiler/svelte'
96
+
97
+ const Button = component.button`
98
+ display: inline-block;
99
+ border-radius: 4px;
100
+ `
101
+
102
+ // renders <button>
103
+ const PrimaryButton = component(Button)`
104
+ background: #CBCBCB;
105
+ `
106
+
107
+ // renders <a> with Button styles
108
+ const ButtonLink = component.a(Button)`
109
+ text-decoration: none;
110
+ `
111
+ ```
112
+
113
+ ## `as` prop
114
+
115
+ Use `as` to render a component as a different element or another component without creating a new styled component. Styles stay the same, `as` is not passed to the rendered element:
116
+
117
+ ```svelte
118
+ <script lang="ts">
119
+ import { Button } from './components'
120
+ import Link from './Link.svelte'
80
121
  </script>
122
+
123
+ <Button as="a" href="/docs">Docs</Button>
124
+ <Button as={Link} to="/home">Home</Button>
125
+ ```
126
+
127
+ When `as` is a component, it receives `class`, `children` and every other forwarded prop. Svelte has no attribute fallthrough, so the component has to apply `class` to its root element:
128
+
129
+ ```svelte
130
+ <!-- Link.svelte -->
81
131
  <script lang="ts">
132
+ import type { Snippet } from 'svelte'
133
+ import type { ClassValue } from 'svelte/elements'
134
+
135
+ const { to, class: className, children }: { to: string; class?: ClassValue; children?: Snippet } = $props()
136
+ </script>
137
+
138
+ <a href={to} class={className}>{@render children?.()}</a>
139
+ ```
140
+
141
+ Props are typed from `as`: `as="a"` accepts anchor attributes, `as={Link}` accepts the props of `Link` and requires its required props. Without `as`, the component accepts the attributes of its own element. `svelte-check` reports an unknown tag in `as` and attributes the target does not accept:
142
+
143
+ ```svelte
144
+ <Button as="a" href="/docs">Docs</Button> <!-- ok -->
145
+ <Button href="/docs">Docs</Button> <!-- error: href is not a button attribute -->
146
+ <Button as={Link}>Home</Button> <!-- error: to is required -->
147
+ ```
148
+
149
+ > [!NOTE]
150
+ > `mount()` and `render()` called from TypeScript cannot infer `as`, so there props are typed from the element of the styled component.
151
+
152
+ ## Theme
153
+
154
+ ```svelte
155
+ <!-- App.svelte -->
156
+ <script lang="ts">
157
+ import type { CustomTheme } from './theme'
158
+
82
159
  import { ThemeProvider } from '@teiler/svelte'
83
- import { Component } from './theme'
160
+ import { Component } from './components'
84
161
 
85
- export let theme: CustomTheme = {
86
- fontColor: 'red',
87
- }
162
+ let theme: CustomTheme = $state({ fontColor: 'red' })
88
163
  </script>
89
164
 
90
165
  <ThemeProvider {theme}>
91
166
  <Component>Some test text</Component>
92
167
  </ThemeProvider>
168
+ ```
93
169
 
94
- // Component with theme usage
170
+ ```typescript
171
+ // components.ts
95
172
  import { component } from '@teiler/svelte'
96
173
 
97
174
  const Component = component.div`
@@ -102,14 +179,77 @@ export { Component }
102
179
  ```
103
180
 
104
181
  To add typing for Typescript applications you need to add `extend` inside declaration file (`d.ts`)
182
+
105
183
  ```typescript
106
- import type { CustomTheme } from "./App.svelte";
184
+ import type { CustomTheme } from './theme'
107
185
 
108
186
  declare module '@teiler/core' {
109
187
  export interface DefaultTheme extends CustomTheme {}
110
188
  }
111
189
  ```
112
190
 
191
+ ## Server-Side Rendering
192
+
193
+ Styles are collected into a style sheet provided through the `STYLE_SHEET` context. Create one sheet per request, render, then put the extracted CSS into the document head.
194
+
195
+ ```typescript
196
+ import { createStyleSheet } from '@teiler/core'
197
+ import { render } from 'svelte/server'
198
+ import App from './App.svelte'
199
+
200
+ const sheet = createStyleSheet({})
201
+ const { body } = render(App, { context: new Map([['STYLE_SHEET', sheet]]) })
202
+ const { css, ids } = sheet.extract()
203
+
204
+ const styleTag = `<style data-teiler="${ids.join(' ')}">${css}</style>`
205
+ ```
206
+
207
+ Read `body` before calling `extract()`: styles are inserted while the component tree renders.
208
+
209
+ > [!WARNING]
210
+ > Always provide a style sheet through the `STYLE_SHEET` context on the server. Without it, every request shares one module-level style sheet, so styles accumulate across requests.
211
+
212
+ ## Hydration
213
+
214
+ On the client, pass the ids rendered by the server to `hydrate`, so styles that are already in the document are not inserted again. Provide the same style sheet to the app through context:
215
+
216
+ ```typescript
217
+ import { createStyleSheet } from '@teiler/core'
218
+ import { hydrate } from 'svelte'
219
+ import App from './App.svelte'
220
+
221
+ const sheet = createStyleSheet({})
222
+ const element = document.querySelector<HTMLStyleElement>('style[data-teiler]')
223
+
224
+ sheet.hydrate(element?.dataset.teiler?.split(' ') ?? [])
225
+
226
+ hydrate(App, { target: document.body, context: new Map([['STYLE_SHEET', sheet]]) })
227
+ ```
228
+
229
+ ## Content Security Policy
230
+
231
+ With a strict `style-src` policy, pass a `nonce` to the style sheet and provide it through the `STYLE_SHEET` context. Without an explicit `nonce` no attribute is set, and the default style sheet never has one.
232
+
233
+ On the server, `extract` returns the nonce, so it can be set on the rendered `<style>` tag:
234
+
235
+ ```typescript
236
+ const sheet = createStyleSheet({ nonce })
237
+ const { body } = render(App, { context: new Map([['STYLE_SHEET', sheet]]) })
238
+ const { css, ids } = sheet.extract()
239
+
240
+ const styleTag = `<style data-teiler="${ids.join(' ')}" nonce="${nonce}">${css}</style>`
241
+ ```
242
+
243
+ On the client, read the nonce from the server rendered tag before creating the style sheet:
244
+
245
+ ```typescript
246
+ const element = document.querySelector<HTMLStyleElement>('style[data-teiler]')
247
+ const sheet = createStyleSheet({ nonce: element?.nonce })
248
+ ```
249
+
250
+ > [!NOTE]
251
+ > Use the `nonce` property, not `getAttribute('nonce')`. Browsers hide the attribute when the policy is sent in a header, so `getAttribute` returns an empty string.
252
+
113
253
  ## Sew a Pattern
114
254
 
115
255
  This tool simplifies the creation of consistent and reusable visual styles for components across various web frameworks. It provides a pattern-based approach, where patterns serve as blueprints for defining the visual style of components.
@@ -140,3 +280,17 @@ const Button = sew(ButtonPattern, createComponent)
140
280
 
141
281
  export default Button
142
282
  ```
283
+
284
+ Patterns can be extended the same way as components. `pattern(ButtonPattern)` keeps the element of the extended pattern, `pattern.<tag>(ButtonPattern)` changes it:
285
+
286
+ ```typescript
287
+ import { pattern } from '@teiler/core'
288
+
289
+ const PrimaryButtonPattern = pattern(ButtonPattern)`
290
+ background: #CBCBCB;
291
+ `
292
+
293
+ const ButtonLinkPattern = pattern.a(ButtonPattern)`
294
+ text-decoration: none;
295
+ `
296
+ ```
@@ -0,0 +1,39 @@
1
+ <script lang="ts">
2
+ import type { DefaultTheme, HTMLElements, StyleDefinition } from '@teiler/core'
3
+ import type { Component, Snippet } from 'svelte'
4
+
5
+ import { clsx } from 'clsx'
6
+ import { insert } from '@teiler/core'
7
+ import { getStyleSheet } from './sheet.js'
8
+ import { getTheme } from './theme.js'
9
+
10
+ type Props = {
11
+ styleDefinition: StyleDefinition<HTMLElements, unknown>
12
+ as?: Exclude<HTMLElements, null> | Component<any>
13
+ class?: string
14
+ children?: Snippet
15
+ [key: string]: unknown
16
+ }
17
+
18
+ const { styleDefinition, as, class: className, children, ...props }: Props = $props()
19
+
20
+ const sheet = getStyleSheet()
21
+ const theme = getTheme()
22
+
23
+ const styleClassName = $derived(insert(sheet, styleDefinition, { ...props, theme: theme?.() ?? ({} as DefaultTheme) }))
24
+
25
+ const classes = $derived(clsx(styleClassName, styleDefinition.id, className))
26
+
27
+ const attributes = $derived(Object.fromEntries(Object.entries(props).filter(([key]) => key[0] !== '_')))
28
+ </script>
29
+
30
+ {#if styleClassName && styleDefinition.tag}
31
+ {@const Target = as ?? styleDefinition.tag}
32
+ {#if typeof Target === 'function'}
33
+ <Target class={classes} {...attributes} {children} />
34
+ {:else if children}
35
+ <svelte:element this={Target} class={classes} {...attributes}>{@render children()}</svelte:element>
36
+ {:else}
37
+ <svelte:element this={Target} class={classes} {...attributes} />
38
+ {/if}
39
+ {/if}
@@ -0,0 +1,12 @@
1
+ import type { HTMLElements, StyleDefinition } from '@teiler/core';
2
+ import type { Component, Snippet } from 'svelte';
3
+ type Props = {
4
+ styleDefinition: StyleDefinition<HTMLElements, unknown>;
5
+ as?: Exclude<HTMLElements, null> | Component<any>;
6
+ class?: string;
7
+ children?: Snippet;
8
+ [key: string]: unknown;
9
+ };
10
+ declare const Styled: Component<Props, {}, "">;
11
+ type Styled = ReturnType<typeof Styled>;
12
+ export default Styled;
@@ -0,0 +1,12 @@
1
+ <script lang="ts">
2
+ import type { DefaultTheme } from '@teiler/core'
3
+ import type { Snippet } from 'svelte'
4
+
5
+ import { setTheme } from './theme.js'
6
+
7
+ const { theme, children }: { theme: DefaultTheme; children?: Snippet } = $props()
8
+
9
+ setTheme(() => theme)
10
+ </script>
11
+
12
+ {@render children?.()}
@@ -0,0 +1,9 @@
1
+ import type { DefaultTheme } from '@teiler/core';
2
+ import type { Snippet } from 'svelte';
3
+ type $$ComponentProps = {
4
+ theme: DefaultTheme;
5
+ children?: Snippet;
6
+ };
7
+ declare const ThemeProvider: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type ThemeProvider = ReturnType<typeof ThemeProvider>;
9
+ export default ThemeProvider;
@@ -0,0 +1,36 @@
1
+ import type { HTMLElements, Properties, StyleDefinition, TeilerComponent } from '@teiler/core';
2
+ import type { ComponentConstructorOptions, ComponentInternals, Snippet, Component as SvelteComponent, SvelteComponent as SvelteComponentInstance } from 'svelte';
3
+ import type { ClassValue, SvelteHTMLElements } from 'svelte/elements';
4
+ import { keyframes } from '@teiler/core';
5
+ type Tag = Exclude<HTMLElements, null>;
6
+ type ElementProps<Target> = Target extends keyof SvelteHTMLElements ? SvelteHTMLElements[Target] : {};
7
+ type AsTarget = Tag | SvelteComponent<never>;
8
+ type TargetProps<As> = As extends SvelteComponent<infer Props> ? Omit<Props, 'class' | 'children'> & {
9
+ class?: ClassValue;
10
+ children?: Snippet;
11
+ } : ElementProps<As>;
12
+ type PolymorphicProps<Target extends HTMLElements, Props, As> = Props & {
13
+ as?: As;
14
+ } & ([As] extends [never] ? ElementProps<Target> : [AsTarget] extends [As] ? ElementProps<Target> : TargetProps<As>);
15
+ interface SvelteTeilerComponent<Target extends HTMLElements, Props extends object> extends TeilerComponent<Target, Props> {
16
+ <As extends AsTarget = never>(internals: ComponentInternals, props: PolymorphicProps<Target, Props, As>): {};
17
+ new <As extends AsTarget = never>(options: ComponentConstructorOptions<PolymorphicProps<Target, Props, As>>): SvelteComponentInstance<PolymorphicProps<Target, Props, As>>;
18
+ }
19
+ type SvelteGlobalComponent<Props extends object> = TeilerComponent<null, Props> & SvelteComponent<Props>;
20
+ declare const createComponent: <Target extends HTMLElements, Props extends object = {}>(styleDefinition: StyleDefinition<Target, Props>) => SvelteTeilerComponent<Target, Props>;
21
+ type InferProps<Component, Props> = Component extends TeilerComponent<HTMLElements, infer P> ? P & Props : Props;
22
+ type InferComponent<Component, Props extends object, Extended> = Component extends TeilerComponent<infer E, infer P extends object> ? SvelteTeilerComponent<Extended extends HTMLElements ? Extended : E, Props & P> : SvelteTeilerComponent<HTMLElements, Props>;
23
+ type Component<Target extends HTMLElements, Extended extends HTMLElements | undefined = Target> = {
24
+ <Props extends object = {}>(string: TemplateStringsArray, ...properties: Properties<Props>[]): SvelteTeilerComponent<Target, Props>;
25
+ <Component>(binded: Component): <Props extends object = {}>(string: TemplateStringsArray, ...properties: Properties<InferProps<Component, Props>>[]) => InferComponent<Component, Props, Extended>;
26
+ };
27
+ type Global = {
28
+ <Props extends object = {}>(string: TemplateStringsArray, ...properties: Properties<Props>[]): SvelteGlobalComponent<Props>;
29
+ };
30
+ type ComponentWithTags = Component<'div', undefined> & {
31
+ [K in Exclude<HTMLElements, null>]: Component<K>;
32
+ };
33
+ declare const svelteComponent: ComponentWithTags;
34
+ declare const svelteGlobal: Global;
35
+ export type { SvelteGlobalComponent, SvelteTeilerComponent };
36
+ export { svelteComponent as component, svelteGlobal as global, keyframes, createComponent };
@@ -0,0 +1,25 @@
1
+ import { component, global, keyframes, styled, tags } from '@teiler/core';
2
+ import Styled from './Styled.svelte';
3
+ const withStyleDefinition = (props, styleDefinition) => {
4
+ return new Proxy(props, {
5
+ get: (target, key) => (key === 'styleDefinition' ? styleDefinition : Reflect.get(target, key)),
6
+ has: (target, key) => key === 'styleDefinition' || Reflect.has(target, key),
7
+ });
8
+ };
9
+ const createComponent = (styleDefinition) => {
10
+ const wrapped = (internals, props) => Styled(internals, withStyleDefinition(props, styleDefinition));
11
+ return Object.assign(wrapped, { styleDefinition });
12
+ };
13
+ const construct = (tag, compiler) => {
14
+ return (stringOrBinded, ...properties) => {
15
+ return styled(tag, compiler, createComponent, stringOrBinded, ...properties);
16
+ };
17
+ };
18
+ const svelteComponent = construct(undefined, component);
19
+ tags.forEach((tag) => {
20
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
21
+ // @ts-expect-error
22
+ svelteComponent[tag] = construct(tag, component);
23
+ });
24
+ const svelteGlobal = construct(null, global);
25
+ export { svelteComponent as component, svelteGlobal as global, keyframes, createComponent };
@@ -1,2 +1,2 @@
1
- export { component, global, keyframes, createComponent } from './component'
2
- export { default as ThemeProvider } from './ThemeProvider.svelte'
1
+ export { component, global, keyframes, createComponent } from './component.js';
2
+ export { default as ThemeProvider } from './ThemeProvider.svelte';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { component, global, keyframes, createComponent } from './component.js';
2
+ export { default as ThemeProvider } from './ThemeProvider.svelte';
@@ -0,0 +1,4 @@
1
+ import { type Sheet } from '@teiler/core';
2
+ export declare let styleSheet: Sheet | null;
3
+ export declare const StyleSheet = "STYLE_SHEET";
4
+ export declare function getStyleSheet(): Sheet;
package/dist/sheet.js ADDED
@@ -0,0 +1,14 @@
1
+ import { createStyleSheet } from '@teiler/core';
2
+ import { getContext } from 'svelte';
3
+ export let styleSheet = null;
4
+ export const StyleSheet = 'STYLE_SHEET';
5
+ export function getStyleSheet() {
6
+ const fromContext = getContext(StyleSheet);
7
+ if (fromContext) {
8
+ return fromContext;
9
+ }
10
+ if (styleSheet === null) {
11
+ styleSheet = createStyleSheet({});
12
+ }
13
+ return styleSheet;
14
+ }
@@ -0,0 +1,5 @@
1
+ import type { DefaultTheme } from '@teiler/core';
2
+ export declare const Theme = "THEME";
3
+ export type ThemeGetter = () => DefaultTheme;
4
+ export declare function setTheme(theme: ThemeGetter): void;
5
+ export declare function getTheme(): ThemeGetter | undefined;
package/dist/theme.js ADDED
@@ -0,0 +1,8 @@
1
+ import { getContext, setContext } from 'svelte';
2
+ export const Theme = 'THEME';
3
+ export function setTheme(theme) {
4
+ setContext(Theme, theme);
5
+ }
6
+ export function getTheme() {
7
+ return getContext(Theme);
8
+ }
package/package.json CHANGED
@@ -1,63 +1,61 @@
1
1
  {
2
2
  "name": "@teiler/svelte",
3
- "version": "0.0.29",
3
+ "version": "0.1.0",
4
4
  "repository": {
5
- "url": "nerdslabs/teiler",
5
+ "type": "git",
6
+ "url": "git+https://github.com/nerdslabs/teiler.git",
6
7
  "directory": "packages/svelte"
7
8
  },
8
9
  "homepage": "https://github.com/nerdslabs/teiler/tree/master/packages/svelte#readme",
9
10
  "type": "module",
10
- "main": "dist/teiler-svelte.cjs.js",
11
- "module": "./dist/teiler-svelte.esm.js",
12
- "types": "./dist/teiler-svelte.d.ts",
11
+ "svelte": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
13
  "exports": {
14
14
  ".": {
15
- "import": "./dist/teiler-svelte.esm.js",
16
- "require": "./dist/teiler-svelte.cjs.ts",
17
- "types": "./dist/teiler-svelte.d.ts"
15
+ "types": "./dist/index.d.ts",
16
+ "svelte": "./dist/index.js",
17
+ "default": "./dist/index.js"
18
18
  }
19
19
  },
20
- "scripts": {
21
- "build": "rollup --config --bundleConfigAsCjs",
22
- "dev": "rollup --config --bundleConfigAsCjs --watch",
23
- "test": "node --experimental-vm-modules $(yarn bin jest)",
24
- "storybook": "storybook dev -p 6006 --no-open",
25
- "storybook-test": "test-storybook --url http://localhost:6006",
26
- "build-storybook": "storybook build"
27
- },
20
+ "files": [
21
+ "dist",
22
+ "!dist/**/*.test.*",
23
+ "!dist/**/*.fixture.*"
24
+ ],
28
25
  "dependencies": {
29
- "@teiler/core": "0.0.28",
30
- "svelte": "^4.2.20"
26
+ "@teiler/core": "0.1.0",
27
+ "clsx": "^2.1.1"
28
+ },
29
+ "peerDependencies": {
30
+ "svelte": "^5.16.0"
31
31
  },
32
32
  "devDependencies": {
33
- "@chromatic-com/storybook": "^3.2.7",
34
- "@rollup/plugin-commonjs": "^28.0.6",
35
- "@rollup/plugin-json": "^6.1.0",
36
- "@rollup/plugin-node-resolve": "^15.3.1",
37
- "@rollup/plugin-swc": "^0.4.0",
38
- "@storybook/addon-essentials": "^8.6.14",
39
- "@storybook/addon-interactions": "^8.6.14",
40
- "@storybook/addon-links": "^8.6.14",
41
- "@storybook/blocks": "^8.6.14",
42
- "@storybook/svelte": "^8.6.14",
43
- "@storybook/svelte-vite": "^8.6.14",
44
- "@storybook/test": "^8.6.14",
45
- "@storybook/test-runner": "0.19.1",
46
- "@sveltejs/vite-plugin-svelte": "^3.1.2",
47
- "@swc/core": "^1.13.2",
48
- "@swc/jest": "^0.2.39",
49
- "@testing-library/svelte": "^5.2.8",
50
- "jest": "^29.7.0",
51
- "jest-environment-jsdom": "^29.7.0",
52
- "jsdom": "^25.0.1",
53
- "rollup": "^4.45.1",
54
- "rollup-plugin-dts": "^6.2.1",
55
- "rollup-plugin-svelte": "^7.2.2",
56
- "rollup-plugin-terser": "^7.0.2",
57
- "storybook": "^8.6.14",
58
- "svelte-jester": "^5.0.0",
59
- "svelte-loader": "^3.2.4",
60
- "svelte-preprocess": "^5.1.4",
61
- "typescript": "^5.8.3"
33
+ "@chromatic-com/storybook": "^5.3.1",
34
+ "@storybook/addon-links": "^10.6.0",
35
+ "@storybook/addon-vitest": "^10.6.0",
36
+ "@storybook/svelte": "^10.6.0",
37
+ "@storybook/svelte-vite": "^10.6.0",
38
+ "@sveltejs/package": "^2.5.8",
39
+ "@sveltejs/vite-plugin-svelte": "^7.3.1",
40
+ "@testing-library/svelte": "^5.4.2",
41
+ "@vitest/browser-playwright": "^4.1.11",
42
+ "@vitest/coverage-v8": "^4.1.11",
43
+ "jsdom": "^30.1.1",
44
+ "playwright": "^1.63.0",
45
+ "storybook": "^10.6.0",
46
+ "svelte": "^5.57.1",
47
+ "svelte-check": "^4.7.6",
48
+ "typescript": "^6.0.3",
49
+ "vite": "^8.3.1",
50
+ "vitest": "^4.1.11"
51
+ },
52
+ "scripts": {
53
+ "build": "svelte-package -i src -o dist",
54
+ "dev": "svelte-package -i src -o dist --watch",
55
+ "test": "vitest run --project client --project server",
56
+ "typecheck": "node scripts/typecheck.js",
57
+ "storybook": "storybook dev -p 6006 --no-open",
58
+ "storybook-test": "vitest run --project storybook",
59
+ "build-storybook": "storybook build"
62
60
  }
63
- }
61
+ }