From 81017120f7ea037ea1b08e88fc6ce7ff6600a732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Droz=CC=87dz=CC=87yn=CC=81ski?= Date: Tue, 14 Nov 2023 22:16:47 +0100 Subject: [PATCH] feat: add a Themes support --- README.md | 43 ++++++++++++++++++++ packages/core/src/constructor.test.ts | 10 ++--- packages/core/src/constructor.ts | 14 +++++-- packages/core/src/css.ts | 3 +- packages/core/src/index.ts | 2 +- packages/core/src/pattern.test.ts | 2 +- packages/svelte/src/Styled.svelte | 6 ++- packages/svelte/src/ThemeProvider.svelte | 14 +++++++ packages/svelte/stories/Theme.stories.svelte | 29 +++++++++++++ packages/svelte/stories/Theme.svelte | 17 ++++++++ packages/svelte/stories/stories.d.ts | 5 +++ packages/svelte/stories/theme.ts | 7 ++++ packages/svelte/tsconfig.json | 3 +- 13 files changed, 141 insertions(+), 14 deletions(-) create mode 100644 packages/svelte/src/ThemeProvider.svelte create mode 100644 packages/svelte/stories/Theme.stories.svelte create mode 100644 packages/svelte/stories/Theme.svelte create mode 100644 packages/svelte/stories/stories.d.ts create mode 100644 packages/svelte/stories/theme.ts diff --git a/README.md b/README.md index 2bcf0df..6020539 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,49 @@ const Button = component.button<{}>` ` ``` +## Theme + +Example how to use themes. + +```typescript +// Main component inside application (`App.svelte`) + + + + + Some test text + + +// Component with theme usage +import component from '@teiler/svelte' + +const Component = component.div` + color: ${({ theme }) => theme.fontColor}; +` + +export { Component } +``` + +To add typing for Typescript applications you need to add `extend` inside declaration file (`d.ts`) +```typescript +import type { CustomTheme } from "./App.svelte"; + +declare module '@teiler/core' { + export interface DefaultTheme extends CustomTheme {} +} +``` + ## Sew a Pattern 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. diff --git a/packages/core/src/constructor.test.ts b/packages/core/src/constructor.test.ts index b75cd3d..d73dbcd 100644 --- a/packages/core/src/constructor.test.ts +++ b/packages/core/src/constructor.test.ts @@ -49,18 +49,18 @@ describe('component', () => { const styleSheet = createStyleSheet({}) const test = jest.fn(component) - test(styleSheet, [[['color: red;'], []]], []) + test(styleSheet, [[['color: red;'], []]], {}) expect(test).toHaveReturnedWith(['teiler-wq229y']) }) test('should create style from styles with props', () => { const styleSheet = createStyleSheet({}) - const test = jest.fn(component) + const test = jest.fn(component<{ color: string }>) - test(styleSheet, [[['color: ', ';'], [({ color }) => color]]], [{ color: 'red' }]) + test(styleSheet, [[['color: ', ';'], [({ color }) => color]]], { color: 'blue' }) - expect(test).toHaveReturnedWith(['teiler-10upe3l']) + expect(test).toHaveReturnedWith(['teiler-1r77qux']) }) }) @@ -77,7 +77,7 @@ describe('global', () => { test('should create style from styles with props', () => { const styleSheet = createStyleSheet({}) - const test = jest.fn(global) + const test = jest.fn(global<{ color: string }>) test(styleSheet, [[['body { color: ', '; }'], [({ color }) => color]]], { color: 'blue' }) diff --git a/packages/core/src/constructor.ts b/packages/core/src/constructor.ts index 7bfab68..515c83e 100644 --- a/packages/core/src/constructor.ts +++ b/packages/core/src/constructor.ts @@ -3,7 +3,13 @@ import type { Sheet } from './sheet' import { compile, transpile } from './css' import hash from './hash' -type Expression = (props: Props) => string | boolean +type DefaultTheme = {[key: string]: string | boolean} + +type Arguments = { + theme?: DefaultTheme +} & Props + +type Expression = (props: Arguments) => string | boolean type StyleDefinition = { id: string name: string @@ -60,7 +66,7 @@ function insert(sheet: Sheet, definitions: StyleDefinition[]): string[] { }, []) } -function component(sheet: Sheet, styles: Array>, props: Props): string[] { +function component(sheet: Sheet, styles: Array>, props: Arguments): string[] { const {css, definitions} = compile(styles, props) const id = hash(css) @@ -74,7 +80,7 @@ function component(sheet: Sheet, styles: Array>, props: Prop return insert(sheet, [...definitions, definition]) } -function global(sheet: Sheet, styles: Array>, props: Props): void { +function global(sheet: Sheet, styles: Array>, props: Arguments): void { const {css, definitions} = compile(styles, props) const id = hash(css) @@ -98,5 +104,5 @@ function keyframes(strings: ReadonlyArray, ...properties: Raw[]): StyleD return { id, name, css: `@keyframes ${name} { ${css} }`, type: 'keyframes' } } -export type { Compile, Properties, Sheet, Style, StyleDefinition, TeilerComponent, Target } +export type { Arguments, Compile, DefaultTheme, Properties, Sheet, Style, StyleDefinition, TeilerComponent, Target } export { keyframes, component, global, styled } diff --git a/packages/core/src/css.ts b/packages/core/src/css.ts index f695e83..cf200f4 100644 --- a/packages/core/src/css.ts +++ b/packages/core/src/css.ts @@ -1,3 +1,4 @@ +import type { Arguments } from './constructor' import type { Style, StyleDefinition } from '.' import { middleware, prefixer, rulesheet, serialize, stringify, compile as stylisCompile } from 'stylis' @@ -9,7 +10,7 @@ type CompileResult = { definitions: StyleDefinition[] } -function compile(styles: Array>, props: Props): CompileResult { +function compile(styles: Array>, props: Arguments): CompileResult { return styles.reduce((result, [strings, properties]) => { const compiled = strings .reduce((acc, strings, index) => { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 76faa17..15d114b 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,4 +1,4 @@ -export type { Compile, Properties, Sheet, Style, StyleDefinition, TeilerComponent, Target } from './constructor' +export type { Compile, DefaultTheme, Properties, Sheet, Style, StyleDefinition, TeilerComponent, Target } from './constructor' export { default as createStyleSheet } from './sheet' export { pattern, sew } from './pattern' diff --git a/packages/core/src/pattern.test.ts b/packages/core/src/pattern.test.ts index c4e80fe..6fc0d03 100644 --- a/packages/core/src/pattern.test.ts +++ b/packages/core/src/pattern.test.ts @@ -35,7 +35,7 @@ describe('pattern', () => { }) test('should create a pattern with params', () => { - const button = pattern.button`background: ${({ color }) => color};` + const button = pattern.button<{color: string}>`background: ${({ color }) => color};` expect(button).toMatchObject({ styles: [[['background: ', ';'], [expect.any(Function)]]], tag: 'button', diff --git a/packages/svelte/src/Styled.svelte b/packages/svelte/src/Styled.svelte index 9a0da57..fde7320 100644 --- a/packages/svelte/src/Styled.svelte +++ b/packages/svelte/src/Styled.svelte @@ -1,6 +1,8 @@ + + + + diff --git a/packages/svelte/stories/Theme.stories.svelte b/packages/svelte/stories/Theme.stories.svelte new file mode 100644 index 0000000..601eeef --- /dev/null +++ b/packages/svelte/stories/Theme.stories.svelte @@ -0,0 +1,29 @@ + + + + + + + + + \ No newline at end of file diff --git a/packages/svelte/stories/Theme.svelte b/packages/svelte/stories/Theme.svelte new file mode 100644 index 0000000..4315bf9 --- /dev/null +++ b/packages/svelte/stories/Theme.svelte @@ -0,0 +1,17 @@ + + + + + Some test text + diff --git a/packages/svelte/stories/stories.d.ts b/packages/svelte/stories/stories.d.ts new file mode 100644 index 0000000..1a13249 --- /dev/null +++ b/packages/svelte/stories/stories.d.ts @@ -0,0 +1,5 @@ +import type { CustomTheme } from "./Theme.svelte"; + +declare module '@teiler/core' { + export interface DefaultTheme extends CustomTheme {} +} diff --git a/packages/svelte/stories/theme.ts b/packages/svelte/stories/theme.ts new file mode 100644 index 0000000..ef58960 --- /dev/null +++ b/packages/svelte/stories/theme.ts @@ -0,0 +1,7 @@ +import component from '@teiler/svelte' + +const Component = component.div` + color: ${({ theme }) => theme.fontColor}; +` + +export { Component } diff --git a/packages/svelte/tsconfig.json b/packages/svelte/tsconfig.json index 0014988..bf08c5f 100644 --- a/packages/svelte/tsconfig.json +++ b/packages/svelte/tsconfig.json @@ -1,6 +1,7 @@ { "include": [ - "src/**/*" + "src/**/*", + "stories/stories.d.ts" ], "exclude": [ "node_modules"