@yak/solid 0.0.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 +21 -0
- package/README.md +126 -0
- package/dist/context/baseContext.d.ts +7 -0
- package/dist/context/baseContext.js +8 -0
- package/dist/context/baseContext.js.map +1 -0
- package/dist/context/index.d.ts +29 -0
- package/dist/context/index.js +17 -0
- package/dist/context/index.js.map +1 -0
- package/dist/index.d.ts +352 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +473 -0
- package/dist/internal.js +382 -0
- package/dist/internal.js.map +1 -0
- package/dist/isolated-source-eval/index.d.ts +30 -0
- package/dist/isolated-source-eval/index.js +315 -0
- package/dist/isolated-source-eval/index.js.map +1 -0
- package/dist/isolated-source-eval/worker.js +59 -0
- package/dist/isolated-source-eval/worker.js.map +1 -0
- package/dist/loaders/vite-plugin.d.ts +116 -0
- package/dist/loaders/vite-plugin.js +862 -0
- package/dist/loaders/vite-plugin.js.map +1 -0
- package/loaders/vite-plugin.ts +29 -0
- package/package.json +108 -0
- package/runtime/__tests__/mergeClasses.test.ts +22 -0
- package/runtime/__tests__/reactivity.test.tsx +157 -0
- package/runtime/__tests__/styled.test.tsx +270 -0
- package/runtime/__tests__/testUtils.tsx +25 -0
- package/runtime/__tests__/tsconfig.json +9 -0
- package/runtime/__tests__/typeTest.tsx +62 -0
- package/runtime/atoms.ts +44 -0
- package/runtime/context/baseContext.ts +5 -0
- package/runtime/context/index.ts +37 -0
- package/runtime/cssLiteral.ts +215 -0
- package/runtime/cssProp.ts +26 -0
- package/runtime/globalStyle.ts +54 -0
- package/runtime/index.ts +39 -0
- package/runtime/internal.ts +41 -0
- package/runtime/internals/mergeClasses.ts +36 -0
- package/runtime/internals/mergeCssProp.ts +54 -0
- package/runtime/internals/unitPostFix.ts +34 -0
- package/runtime/keyframes.ts +30 -0
- package/runtime/mocks/cssLiteral.ts +74 -0
- package/runtime/mocks/globalStyle.ts +14 -0
- package/runtime/mocks/keyframes.ts +29 -0
- package/runtime/mocks/styled.ts +8 -0
- package/runtime/publicStyledApi.ts +177 -0
- package/runtime/styled.ts +393 -0
- package/runtime/styledDom.ts +139 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Digitec Galaxus AG
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# @yak/solid
|
|
2
|
+
|
|
3
|
+
SolidJS runtime for [yak](https://yak.js.org/): styled-components syntax, compiled to plain CSS at build time, with dynamic values driven by Solid's fine-grained reactivity.
|
|
4
|
+
|
|
5
|
+
> **Status: experimental.** `@yak/solid` targets Solid 2 (currently at RC) and tracks it closely. Expect breaking changes while Solid 2 stabilizes. Solid 1 is not supported. This includes SolidStart v2, which runs on Solid 1.
|
|
6
|
+
|
|
7
|
+
## How it works
|
|
8
|
+
|
|
9
|
+
Like `next-yak`, the yak SWC compiler extracts your CSS at build time. At runtime only a tiny layer remains that merges class names and feeds dynamic values through CSS custom properties:
|
|
10
|
+
|
|
11
|
+
- Static styles become plain CSS classes. A static `styled.div` never subscribes to the theme and adds a single reactive `class` binding.
|
|
12
|
+
- Dynamic interpolations (`${(props) => ...}`) become CSS variables set on the element's inline `style`. Updates flow through one memo per component: the element is never re-created, only its `class`/`style` bindings change, and only props actually used by the CSS re-run the memo.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @yak/solid
|
|
18
|
+
pnpm add -D vite-plugin-solid@next
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// vite.config.ts
|
|
23
|
+
import { defineConfig } from "vite";
|
|
24
|
+
import solid from "vite-plugin-solid";
|
|
25
|
+
import { yak } from "@yak/solid/vite";
|
|
26
|
+
|
|
27
|
+
export default defineConfig({
|
|
28
|
+
plugins: [yak(), solid()],
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { styled, css, keyframes } from "@yak/solid";
|
|
34
|
+
|
|
35
|
+
const Button = styled.button<{ $primary?: boolean }>`
|
|
36
|
+
color: #009688;
|
|
37
|
+
${(props) =>
|
|
38
|
+
props.$primary &&
|
|
39
|
+
css`
|
|
40
|
+
border-width: 2px;
|
|
41
|
+
`}
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
const Hand = styled.div<{ $angle: number }>`
|
|
45
|
+
transform: rotate(${(props) => props.$angle}deg);
|
|
46
|
+
`;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Interpolation functions re-run inside the component's style memo, so destructuring their parameter (`${({ $angle }) => ...}`) is also safe. These docs use the `props` style because it matches Solid's conventions.
|
|
50
|
+
|
|
51
|
+
The `css` prop works on all intrinsic elements (uses Solid's `class` attribute):
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
<p
|
|
55
|
+
css={css`
|
|
56
|
+
color: green;
|
|
57
|
+
`}
|
|
58
|
+
/>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Theming
|
|
62
|
+
|
|
63
|
+
Create a `yak.context.ts` next to your `vite.config.ts` (picked up automatically) and augment the `YakTheme` interface:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
export function getYakThemeContext() {
|
|
67
|
+
return { highContrast: false };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
declare module "@yak/solid" {
|
|
71
|
+
export interface YakTheme extends ReturnType<typeof getYakThemeContext> {}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`useTheme()` returns an accessor, like a signal getter. Call it where the value is used. That read subscribes the surrounding scope to theme changes:
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { styled, useTheme, YakThemeProvider } from "@yak/solid";
|
|
79
|
+
|
|
80
|
+
const Button = styled.button`
|
|
81
|
+
color: ${(props) => (props.theme().highContrast ? "#000" : "#555")};
|
|
82
|
+
`;
|
|
83
|
+
|
|
84
|
+
function Toolbar() {
|
|
85
|
+
const theme = useTheme();
|
|
86
|
+
return <span>{theme().highContrast ? "High contrast" : "Default"}</span>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// app root: the theme prop is reactive, signal reads inside it stay live
|
|
90
|
+
<YakThemeProvider theme={{ highContrast: highContrast() }}>
|
|
91
|
+
<App />
|
|
92
|
+
</YakThemeProvider>;
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The package also exports the context itself for native composition, e.g. overriding the theme for a subtree. In Solid 2 a context is its own provider and takes an accessor:
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
import { createMemo } from "solid-js";
|
|
99
|
+
import { YakThemeContext, useTheme } from "@yak/solid";
|
|
100
|
+
|
|
101
|
+
function InvertedSection(props) {
|
|
102
|
+
const parent = useTheme();
|
|
103
|
+
const inverted = createMemo(() => ({ ...parent(), highContrast: true }));
|
|
104
|
+
return <YakThemeContext value={inverted}>{props.children}</YakThemeContext>;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Differences to next-yak (React)
|
|
109
|
+
|
|
110
|
+
- `useTheme()` returns an accessor: read `theme().highContrast`, not `theme.highContrast`. The same applies to `props.theme()` in interpolations and `.attrs()`.
|
|
111
|
+
- `class` instead of `className` (Solid convention), also inside `.attrs({ ... })`.
|
|
112
|
+
- No jsx-runtime export: Solid compiles JSX natively. The css prop types activate by importing `@yak/solid`.
|
|
113
|
+
- Components run once. Solid's reactivity drives dynamic styles instead of re-renders.
|
|
114
|
+
- `foldStatic` is off by default (see [Static folding](#static-folding-opt-in) below).
|
|
115
|
+
|
|
116
|
+
## Static folding (opt-in)
|
|
117
|
+
|
|
118
|
+
`yak({ foldStatic: true })` additionally folds usages of fully static components into plain elements at build time, removing their wrapper components. It is off by default as we didn't test all the edge-cases and can't guarantee it works correctly everywhere.
|
|
119
|
+
|
|
120
|
+
## Requirements
|
|
121
|
+
|
|
122
|
+
- `solid-js` >= 2.0.0-rc.0 and `@solidjs/web` >= 2.0.0-rc.0
|
|
123
|
+
- `vite-plugin-solid` >= 3.0.0-next (the Solid 2 line, npm tag `next`)
|
|
124
|
+
- `yak-swc` with yak-package auto-detection (bundled as a dependency, version released together with this package or newer)
|
|
125
|
+
|
|
126
|
+
See the [`examples/vite-solid`](https://github.com/DigitecGalaxus/next-yak/tree/main/examples/vite-solid) app for a full setup.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseContext.js","names":[],"sources":["../../runtime/context/baseContext.ts"],"sourcesContent":["import type { YakTheme } from \"@yak/solid\";\n\nexport function getYakThemeContext() {\n return {} as YakTheme | undefined;\n}\n"],"mappings":";AAEA,SAAgB,qBAAqB;CACnC,OAAO,CAAC;AACV"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Accessor } from "solid-js";
|
|
2
|
+
import { JSX } from "@solidjs/web";
|
|
3
|
+
|
|
4
|
+
//#region runtime/context/index.d.ts
|
|
5
|
+
interface YakTheme {}
|
|
6
|
+
/**
|
|
7
|
+
* The yak theme context
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/DigitecGalaxus/next-yak/blob/main/packages/next-yak/runtime/context/README.md
|
|
10
|
+
*/
|
|
11
|
+
declare const YakThemeContext: import("solid-js").Context<Accessor<YakTheme>>;
|
|
12
|
+
/**
|
|
13
|
+
* Returns an accessor to the current yak theme
|
|
14
|
+
*/
|
|
15
|
+
declare const useTheme: () => Accessor<YakTheme>;
|
|
16
|
+
/**
|
|
17
|
+
* Yak theme context provider
|
|
18
|
+
*
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <YakThemeProvider theme={{ highContrast: highContrast() }}>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare const YakThemeProvider: (props: {
|
|
24
|
+
children?: JSX.Element;
|
|
25
|
+
theme?: YakTheme;
|
|
26
|
+
}) => JSX.Element;
|
|
27
|
+
//#endregion
|
|
28
|
+
export { YakTheme, YakThemeContext, YakThemeProvider, useTheme };
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createComponent, createContext, createMemo, useContext } from "solid-js";
|
|
2
|
+
|
|
3
|
+
//#region runtime/context/index.ts
|
|
4
|
+
const YakThemeContext = /* @__PURE__ */ createContext(() => ({}));
|
|
5
|
+
const useTheme = () => useContext(YakThemeContext);
|
|
6
|
+
const YakThemeProvider = (props) => {
|
|
7
|
+
return createComponent(YakThemeContext, {
|
|
8
|
+
value: createMemo(() => props.theme ?? {}),
|
|
9
|
+
get children() {
|
|
10
|
+
return props.children;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { YakThemeContext, YakThemeProvider, useTheme };
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../runtime/context/index.ts"],"sourcesContent":["import { createComponent, createContext, createMemo, useContext } from \"solid-js\";\nimport type { Accessor } from \"solid-js\";\nimport type { JSX } from \"@solidjs/web\";\n\nexport interface YakTheme {}\n\n/**\n * The yak theme context\n *\n * @see https://github.com/DigitecGalaxus/next-yak/blob/main/packages/next-yak/runtime/context/README.md\n */\nexport const YakThemeContext = /* @__PURE__ */ createContext<Accessor<YakTheme>>(() => ({}));\n\n/**\n * Returns an accessor to the current yak theme\n */\nexport const useTheme = (): Accessor<YakTheme> => useContext(YakThemeContext);\n\n/**\n * Yak theme context provider\n *\n * ```tsx\n * <YakThemeProvider theme={{ highContrast: highContrast() }}>\n * ```\n */\nexport const YakThemeProvider = (props: {\n children?: JSX.Element;\n theme?: YakTheme;\n}): JSX.Element => {\n const theme = createMemo<YakTheme>(() => props.theme ?? {});\n return createComponent(YakThemeContext, {\n value: theme,\n get children() {\n return props.children;\n },\n });\n};\n"],"mappings":";;;AAWA,MAAa,kBAAkC,qCAAyC,CAAC,EAAE;AAK3F,MAAa,iBAAqC,WAAW,eAAe;AAS5E,MAAa,oBAAoB,UAGd;CAEjB,OAAO,gBAAgB,iBAAiB;EACtC,OAFY,iBAA2B,MAAM,SAAS,CAAC,CAE5C;EACX,IAAI,WAAW;GACb,OAAO,MAAM;EACf;CACF,CAAC;AACH"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { Accessor } from "solid-js";
|
|
2
|
+
import { JSX } from "@solidjs/web";
|
|
3
|
+
|
|
4
|
+
//#region runtime/context/index.d.ts
|
|
5
|
+
interface YakTheme {}
|
|
6
|
+
/**
|
|
7
|
+
* The yak theme context
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/DigitecGalaxus/next-yak/blob/main/packages/next-yak/runtime/context/README.md
|
|
10
|
+
*/
|
|
11
|
+
declare const YakThemeContext: import("solid-js").Context<Accessor<YakTheme>>;
|
|
12
|
+
/**
|
|
13
|
+
* Returns an accessor to the current yak theme
|
|
14
|
+
*/
|
|
15
|
+
declare const useTheme: () => Accessor<YakTheme>;
|
|
16
|
+
/**
|
|
17
|
+
* Yak theme context provider
|
|
18
|
+
*
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <YakThemeProvider theme={{ highContrast: highContrast() }}>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare const YakThemeProvider: (props: {
|
|
24
|
+
children?: JSX.Element;
|
|
25
|
+
theme?: YakTheme;
|
|
26
|
+
}) => JSX.Element;
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region runtime/publicStyledApi.d.ts
|
|
29
|
+
/**
|
|
30
|
+
* Component signature accepted and produced by `styled`.
|
|
31
|
+
*
|
|
32
|
+
* Intentionally NOT Solid 2's `Component` type: that alias constrains props
|
|
33
|
+
* to `Record<string, any>` which does not compose with the `object`-based
|
|
34
|
+
* generics of the styled API (kept in sync with the React runtime).
|
|
35
|
+
*/
|
|
36
|
+
type AnyComponent<T> = (props: T) => JSX.Element;
|
|
37
|
+
/**
|
|
38
|
+
* Style object the runtime writes CSS custom properties into.
|
|
39
|
+
* Solid also allows string styles on elements; the runtime normalizes
|
|
40
|
+
* those to objects before processing (see `unwrapStyle` in styled.ts).
|
|
41
|
+
*/
|
|
42
|
+
type StyleObject = JSX.CSSProperties & Record<`--${string}`, string | number | undefined>;
|
|
43
|
+
/**
|
|
44
|
+
* Main styled interface that combines HTML tag mappings with the styled function.
|
|
45
|
+
* This is the primary entry point for creating styled components.
|
|
46
|
+
*/
|
|
47
|
+
interface Styled extends MappedHtmlTags, StyledFn {}
|
|
48
|
+
/**
|
|
49
|
+
* Function interface for creating styled components from any component or HTML tag.
|
|
50
|
+
* Supports Solid components, HTML tags, and custom web components.
|
|
51
|
+
*/
|
|
52
|
+
interface StyledFn {
|
|
53
|
+
<TProps extends object = JSX.ElementAttributes<Element>>(Component: HtmlTags | AnyComponent<TProps> | CustomWebComponentTag): LiteralWithAttrs<TProps>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* A yak component with a special symbol that allows component targeting
|
|
57
|
+
* and proper attrs function handling.
|
|
58
|
+
* @example styled.svg`${Button}:hover & { fill: red; }` or styled(Button)`color: red;`
|
|
59
|
+
*/
|
|
60
|
+
interface YakComponent<T> extends AnyComponent<T> {
|
|
61
|
+
[yakComponentSymbol]: [unknown, unknown, unknown, unknown];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Styled component with attrs method for adding default props.
|
|
65
|
+
* Extends StyledLiteral with the ability to specify default attributes.
|
|
66
|
+
*/
|
|
67
|
+
interface LiteralWithAttrs<T extends object> extends StyledLiteral<T> {
|
|
68
|
+
attrs: <TAttrsIn extends object = {}, TAttrsOut extends AttrsMerged<T, TAttrsIn> = AttrsMerged<T, TAttrsIn>>(attrs: Attrs<T, TAttrsIn, TAttrsOut>) => StyledLiteral<Substitute<T, TAttrsIn>>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Template literal function for defining CSS styles with interpolation support.
|
|
72
|
+
* Accepts CSS template strings and interpolated values with proper typing.
|
|
73
|
+
*/
|
|
74
|
+
interface StyledLiteral<T> {
|
|
75
|
+
<TCSSProps>(styles: TemplateStringsArray, ...values: Array<CSSInterpolation<T & NoInfer<TCSSProps> & {
|
|
76
|
+
theme: Accessor<YakTheme>;
|
|
77
|
+
}>>): YakComponent<TCSSProps & T>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Function variant of attrs that receives current props and returns additional props.
|
|
81
|
+
* Allows for dynamic prop generation based on component state.
|
|
82
|
+
*/
|
|
83
|
+
interface AttrsFunction<TBaseProps, TIn extends object = {}, TOut extends AttrsMerged<TBaseProps, TIn> = AttrsMerged<TBaseProps, TIn>> {
|
|
84
|
+
(p: Substitute<TBaseProps & {
|
|
85
|
+
theme: Accessor<YakTheme>;
|
|
86
|
+
}, TIn>): Partial<TOut>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Merges provided props with initial props, making specified props optional.
|
|
90
|
+
* Includes theme support for styled components.
|
|
91
|
+
*/
|
|
92
|
+
type AttrsMerged<TBaseProps, TIn extends object = {}> = Substitute<TBaseProps & {
|
|
93
|
+
theme?: Accessor<YakTheme>;
|
|
94
|
+
}, TIn>;
|
|
95
|
+
/**
|
|
96
|
+
* Maps all HTML tag names to their corresponding styled component types with attributes support.
|
|
97
|
+
* Provides typed access to all standard HTML elements through the styled interface.
|
|
98
|
+
*/
|
|
99
|
+
type MappedHtmlTags = { [Tag in HtmlTags]: LiteralWithAttrs<JSX.IntrinsicElements[Tag]> };
|
|
100
|
+
/**
|
|
101
|
+
* The attrs function allows adding additional props to a styled component.
|
|
102
|
+
* Props can be specified as an object or as a function that receives current props.
|
|
103
|
+
*/
|
|
104
|
+
type Attrs<TBaseProps, TIn extends object = {}, TOut extends AttrsMerged<TBaseProps, TIn> = AttrsMerged<TBaseProps, TIn>> = Partial<TOut> | AttrsFunction<TBaseProps, TIn, TOut>;
|
|
105
|
+
/**
|
|
106
|
+
* Utility type to merge two object types, with properties from B taking precedence.
|
|
107
|
+
* If a property exists in both A and B, the property from B is used.
|
|
108
|
+
*/
|
|
109
|
+
type Substitute<A extends object, B extends object> = FastOmit<A, keyof B> & B;
|
|
110
|
+
/**
|
|
111
|
+
* Union type of all valid HTML element tag names.
|
|
112
|
+
* Derived from Solid's JSX intrinsic elements.
|
|
113
|
+
*/
|
|
114
|
+
type HtmlTags = keyof JSX.IntrinsicElements;
|
|
115
|
+
/**
|
|
116
|
+
* Custom web component tag pattern that must contain at least one hyphen.
|
|
117
|
+
* Follows the web component naming convention.
|
|
118
|
+
*/
|
|
119
|
+
type CustomWebComponentTag = `${string}-${string}`;
|
|
120
|
+
/**
|
|
121
|
+
* Utility type to efficiently remove properties from an object type.
|
|
122
|
+
* More performant than the built-in Omit type for large object types.
|
|
123
|
+
*/
|
|
124
|
+
type FastOmit<T extends object, U extends string | number | symbol> = { [K in keyof T as K extends U ? never : K]: T[K] };
|
|
125
|
+
/**
|
|
126
|
+
* Set-like collector for class names.
|
|
127
|
+
*
|
|
128
|
+
* Implemented as a string builder in the runtime (a Set<string>
|
|
129
|
+
* split → Set → Array.from → join round-trip dominates render cost);
|
|
130
|
+
* a real Set<string> also satisfies this interface.
|
|
131
|
+
*/
|
|
132
|
+
type ClassCollector = {
|
|
133
|
+
add(name: string): void;
|
|
134
|
+
has(name: string): boolean;
|
|
135
|
+
delete(name: string): void;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Type of all functions that can be passed to manipulate styles
|
|
139
|
+
*
|
|
140
|
+
* `$dynamic` marks processors that execute user functions or write style
|
|
141
|
+
* values at render time; purely static processors (class names only) can
|
|
142
|
+
* skip theme lookup and style-object allocation.
|
|
143
|
+
*/
|
|
144
|
+
type RuntimeStyleProcessor<T> = ((props: T, classes: ClassCollector, style: StyleObject) => void) & {
|
|
145
|
+
$dynamic?: boolean;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Utility type to keep the generic API of a component while still being able to use it in a selector
|
|
149
|
+
*/
|
|
150
|
+
type GenericYakComponentOf<T, P = {}> = T & YakComponent<P> & {
|
|
151
|
+
<G = {}>(props: P & G): JSX.Element;
|
|
152
|
+
};
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region runtime/cssLiteral.d.ts
|
|
155
|
+
declare const yakComponentSymbol: unique symbol;
|
|
156
|
+
type ComponentStyles<TProps> = (props: TProps) => {
|
|
157
|
+
class: string;
|
|
158
|
+
style?: {
|
|
159
|
+
[key: string]: string;
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
type CSSInterpolation<TProps> = string | number | undefined | null | false | ComponentStyles<TProps> | {
|
|
163
|
+
[yakComponentSymbol]: any;
|
|
164
|
+
} | ((props: TProps) => CSSInterpolation<TProps>);
|
|
165
|
+
/**
|
|
166
|
+
* css() runtime factory of css``
|
|
167
|
+
*
|
|
168
|
+
* /!\ @yak/solid transpiles css`` and styled``
|
|
169
|
+
*
|
|
170
|
+
* This changes the typings of the css`` and styled`` functions.
|
|
171
|
+
* During development the user of @yak/solid wants to work with the
|
|
172
|
+
* typings BEFORE compilation.
|
|
173
|
+
*
|
|
174
|
+
* Therefore this is only an internal function only and it must be cast to any
|
|
175
|
+
* before exported to the user.
|
|
176
|
+
*
|
|
177
|
+
* The internal functioning of css`` is to return a single callback function that runs all functions
|
|
178
|
+
* (or creates new ones if needed) that are passed as arguments. These functions receive the props, classes, and style object as arguments
|
|
179
|
+
* and operate directly on the classes and style objects.
|
|
180
|
+
*/
|
|
181
|
+
declare function css$1<TProps>(styles: TemplateStringsArray, ...values: CSSInterpolation<NoInfer<TProps> & {
|
|
182
|
+
theme: Accessor<YakTheme>;
|
|
183
|
+
}>[]): ComponentStyles<TProps>;
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region runtime/cssProp.d.ts
|
|
186
|
+
declare module "@solidjs/web" {
|
|
187
|
+
namespace JSX {
|
|
188
|
+
interface ElementAttributes<T> {
|
|
189
|
+
css?: ComponentStyles<{}>;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//#endregion
|
|
194
|
+
//#region runtime/atoms.d.ts
|
|
195
|
+
/**
|
|
196
|
+
* Allows to use atomic CSS classes in a styled or css block
|
|
197
|
+
*
|
|
198
|
+
* @usage
|
|
199
|
+
*
|
|
200
|
+
* ```tsx
|
|
201
|
+
* import { styled, atoms } from "@yak/solid";
|
|
202
|
+
*
|
|
203
|
+
* const Button = styled.button<{ $primary?: boolean }>`
|
|
204
|
+
* ${atoms("text-teal-600", "text-base", "rounded-md")}
|
|
205
|
+
* ${props => props.$primary && atoms("shadow-md")}
|
|
206
|
+
* `;
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
declare const atoms: <T>(...atoms: (string | RuntimeStyleProcessor<T> | false)[]) => ComponentStyles<T>;
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region runtime/mocks/cssLiteral.d.ts
|
|
212
|
+
/**
|
|
213
|
+
* Allows to use CSS styles in a styled or css block
|
|
214
|
+
*
|
|
215
|
+
* e.g.
|
|
216
|
+
*
|
|
217
|
+
* ```tsx
|
|
218
|
+
* const Component = styled.div`
|
|
219
|
+
* color: black;
|
|
220
|
+
* ${({$active}) => $active && css`color: red;`}
|
|
221
|
+
* `;
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
declare const css: typeof css$1;
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region runtime/keyframes.d.ts
|
|
227
|
+
/**
|
|
228
|
+
* Allows to use CSS keyframe animations in a styled or css block
|
|
229
|
+
*
|
|
230
|
+
* @usage
|
|
231
|
+
*
|
|
232
|
+
* ```tsx
|
|
233
|
+
* import { styled, keyframes } from "@yak/solid";
|
|
234
|
+
*
|
|
235
|
+
* const rotate = keyframes`
|
|
236
|
+
* from {
|
|
237
|
+
* transform: rotate(0deg);
|
|
238
|
+
* }
|
|
239
|
+
* to {
|
|
240
|
+
* transform: rotate(360deg);
|
|
241
|
+
* }
|
|
242
|
+
* `;
|
|
243
|
+
*
|
|
244
|
+
* const Spinner = styled.div`
|
|
245
|
+
* animation: ${rotate} 1s linear infinite;
|
|
246
|
+
* `;
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
declare const keyframes$1: <T extends (string | number | bigint)[] = never>(styles: TemplateStringsArray, ..._dynamic: T) => string;
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region runtime/mocks/keyframes.d.ts
|
|
252
|
+
/**
|
|
253
|
+
* Allows to use CSS keyframe animations in a styled or css block
|
|
254
|
+
*
|
|
255
|
+
* @usage
|
|
256
|
+
*
|
|
257
|
+
* ```tsx
|
|
258
|
+
* import { styled, keyframes } from "@yak/solid";
|
|
259
|
+
*
|
|
260
|
+
* const rotate = keyframes`
|
|
261
|
+
* from {
|
|
262
|
+
* transform: rotate(0deg);
|
|
263
|
+
* }
|
|
264
|
+
* to {
|
|
265
|
+
* transform: rotate(360deg);
|
|
266
|
+
* }
|
|
267
|
+
* `;
|
|
268
|
+
*
|
|
269
|
+
* const Spinner = styled.div`
|
|
270
|
+
* animation: ${rotate} 1s linear infinite;
|
|
271
|
+
* `;
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
declare const keyframes: typeof keyframes$1;
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region runtime/styled.d.ts
|
|
277
|
+
/**
|
|
278
|
+
* The `styled` method works perfectly on all of your own or any third-party component,
|
|
279
|
+
* as long as they attach the passed `class` prop to a DOM element.
|
|
280
|
+
*
|
|
281
|
+
* @usage
|
|
282
|
+
*
|
|
283
|
+
* ```tsx
|
|
284
|
+
* const StyledLink = styled(Link)`
|
|
285
|
+
* color: #BF4F74;
|
|
286
|
+
* font-weight: bold;
|
|
287
|
+
* `;
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
declare const styled$1: Styled;
|
|
291
|
+
//#endregion
|
|
292
|
+
//#region runtime/mocks/styled.d.ts
|
|
293
|
+
declare const styled: typeof styled$1;
|
|
294
|
+
//#endregion
|
|
295
|
+
//#region runtime/globalStyle.d.ts
|
|
296
|
+
/**
|
|
297
|
+
* Values that may be interpolated into a `globalStyle` template.
|
|
298
|
+
*
|
|
299
|
+
* Only build-time values are allowed: constants, `keyframes` animation names,
|
|
300
|
+
* static `css` mixins and styled-component selectors. Runtime functions
|
|
301
|
+
* (`${(props) => ...}`) are intentionally excluded: a global rule has no element
|
|
302
|
+
* to attach a CSS variable to. Declare a CSS custom property instead and toggle
|
|
303
|
+
* it via an attribute/class on the root element.
|
|
304
|
+
*/
|
|
305
|
+
type GlobalStyleInterpolation = string | number | ComponentStyles<{}> | YakComponent<any>;
|
|
306
|
+
/**
|
|
307
|
+
* Declares global, unscoped styles that ride the same zero-runtime extraction
|
|
308
|
+
* pipeline as `styled` and `keyframes`.
|
|
309
|
+
*
|
|
310
|
+
* Global styles are **part of the stylesheet, not part of the render tree**.
|
|
311
|
+
* They apply exactly when the module declaring them is included in the bundle,
|
|
312
|
+
* typically by importing it from a layout or entry point. They cannot be
|
|
313
|
+
* conditionally mounted; express conditions in CSS (`@media`, `@supports`,
|
|
314
|
+
* `:root[data-theme]`, `:has()`) or through CSS custom properties.
|
|
315
|
+
*
|
|
316
|
+
* @usage
|
|
317
|
+
*
|
|
318
|
+
* ```tsx
|
|
319
|
+
* import { globalStyle, keyframes } from "@yak/solid";
|
|
320
|
+
*
|
|
321
|
+
* const fadeIn = keyframes`
|
|
322
|
+
* from { opacity: 0; }
|
|
323
|
+
* `;
|
|
324
|
+
*
|
|
325
|
+
* globalStyle`
|
|
326
|
+
* :root {
|
|
327
|
+
* --spacing: 4px;
|
|
328
|
+
* }
|
|
329
|
+
*
|
|
330
|
+
* body {
|
|
331
|
+
* margin: 0;
|
|
332
|
+
* }
|
|
333
|
+
*
|
|
334
|
+
* ::view-transition-new(root) {
|
|
335
|
+
* animation: ${fadeIn} 200ms ease;
|
|
336
|
+
* }
|
|
337
|
+
* `;
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
declare const globalStyle$1: (_styles: TemplateStringsArray, ..._values: Array<GlobalStyleInterpolation>) => void;
|
|
341
|
+
//#endregion
|
|
342
|
+
//#region runtime/mocks/globalStyle.d.ts
|
|
343
|
+
/**
|
|
344
|
+
* Test-friendly mock of `globalStyle`.
|
|
345
|
+
*
|
|
346
|
+
* `globalStyle` has no runtime behaviour: the SWC plugin extracts its CSS at
|
|
347
|
+
* build time and replaces the call with a no-op. The mock mirrors that: it does
|
|
348
|
+
* nothing so yak files can be imported in Jest/Vitest without the compiler.
|
|
349
|
+
*/
|
|
350
|
+
declare const globalStyle: typeof globalStyle$1;
|
|
351
|
+
//#endregion
|
|
352
|
+
export { type GenericYakComponentOf, type GlobalStyleInterpolation, type YakComponent, type YakTheme, YakThemeContext, YakThemeProvider, atoms, css, globalStyle, keyframes, styled, useTheme };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{YakThemeContext as e,YakThemeProvider as t,useTheme as n,useTheme as r}from"@yak/solid/context";import{createMemo as i,merge as a}from"solid-js";import{Dynamic as o,createComponent as s}from"@solidjs/web";const c=Symbol(`yak`);var l=class{value;constructor(e){this.value=e||``}add(e){this.value?this.has(e)||(this.value+=` `+e):this.value=e}has(e){return(` `+this.value+` `).includes(` `+e+` `)}delete(e){this.has(e)&&(this.value=this.value.split(` `).filter(t=>t!==e).join(` `))}};function u(...e){let t,n=[];for(let r of e)typeof r==`string`?t=r:typeof r==`function`?n.push(r):typeof r==`object`&&`style`in r&&n.push((e,t,n)=>{for(let t in r.style){let i=r.style[t];typeof i==`function`?n[t]=String(f(e,i)):n[t]=String(i)}});return n.length===0?Object.assign((e,n)=>{t&&n.add(t)},{$dynamic:!1}):Object.assign((e,r,i)=>{t&&r.add(t);for(let t=0;t<n.length;t++)d(e,n[t],r,i)},{$dynamic:!0})}const d=(e,t,n,r)=>{let i=t(e,n,r);for(;i;){if(typeof i==`function`){i=i(e,n,r);continue}else if(typeof i==`object`){let e=`class`in i?i.class:void 0;if(e&&n.add(e),`style`in i&&i.style)for(let e in i.style)r[e]=i.style[e]}break}},f=(e,t)=>{let n=t(e);if(typeof n==`function`)return f(e,n);if(typeof n!=`string`&&typeof n!=`number`&&!(n instanceof String)&&process.env.NODE_ENV===`development`)throw Error(`Dynamic CSS functions must return a string or number but returned ${JSON.stringify(n)}\n\nDynamic CSS function: ${t.toString()}\n`);return n},p=(...e)=>{let t=[],n=[];for(let r of e)typeof r==`string`?t.push(...r.split(` `)):typeof r==`function`&&n.push(r);return u(...t.length>0?[(e,n)=>{t.forEach(e=>n.add(e))},...n]:n)},m=(e,...t)=>{if(Array.isArray(e)&&`raw`in e){let n=e[0];for(let r=0;r<t.length;r++){let i=t[r];n+=i&&typeof i==`object`&&`__yak`in i?i.__yak:String(i),n+=e[r+1]}return{__yak:n}}let n=[];for(let e of t)typeof e==`function`&&n.push(e);return n.length===0?{class:``,style:void 0}:(e=>{for(let t=0;t<n.length;t++)h(e,n[t]);return{class:``,style:void 0}})};function h(e,t){let n=new Set,r={},i=t(e,n,r);for(;typeof i==`function`;)i=i(e,n,r);return i}const g=(e,...t)=>``,_=e=>e?typeof e==`string`?e:Array.isArray(e)?e.map(_).filter(Boolean).join(` `):typeof e==`object`?Object.keys(e).filter(t=>e[t]).join(` `):String(e):``,v=e=>s(o,e),y=e=>Object.assign(b(e),{attrs:t=>b(e,t)}),b=(e,t)=>{let n=typeof e==`function`&&e[c]!==void 0,[,o,d,f]=n?e[c]:[],p=n?f:e,m=E(t,o);return(e,...t)=>{let n=D(u(e,...t),d),o=typeof p==`string`,f=o?{component:p}:{},h=o?v:e=>s(p,e),g=!m&&!n.$dynamic?e=>h(C(a(e,f,{get class(){let t=new l(_(e.class));return n(e,t,void 0),t.value||void 0}}))):e=>{let t=r(),o=a({theme:t},e),s=m?i(()=>m(o)):void 0,c=s?a(o,s):o,u=i(()=>{let t=s?.(),r=new l(_(e.class)),i=_(t?.class);i&&r.add(i);let a=n.$dynamic||t?.style?{...x(e.style),...x(t?.style)}:x(e.style);return n(c,r,a),{class:r.value||void 0,style:a&&Object.keys(a).length>0?a:void 0}});return h(C(a(a(e,s??{},{get class(){return u().class},get style(){return u().style}}),f),()=>{let e=s?.();return!!e&&`theme`in e&&e.theme!==t}))};return Object.assign(g,{[c]:[g,m,n,p]})}},x=e=>{if(typeof e!=`string`)return e;let t={};for(let n of e.split(`;`)){let e=n.indexOf(`:`);if(e===-1)continue;let r=n.slice(0,e).trim(),i=n.slice(e+1).trim();r&&i&&(t[r]=i)}return t},S=(e,t)=>typeof e==`string`&&(e.startsWith(`$`)||e===`theme`&&!(t&&t())),C=(e,t)=>new Proxy(e,{get:(e,n)=>S(n,t)?void 0:Reflect.get(e,n),has:(e,n)=>!S(n,t)&&Reflect.has(e,n),ownKeys:e=>Reflect.ownKeys(e).filter(e=>!S(e,t)),getOwnPropertyDescriptor:(e,n)=>S(n,t)?void 0:Reflect.getOwnPropertyDescriptor(e,n)}),w=(e,t)=>{if(!(!e&&!t))return e?t?e+` `+t:e:t},T=(e,t)=>t?(e.class===t.class||!t.class)&&(e.style===t.style||!t.style)?{...e,...t}:{...e,...t,class:w(e.class,t.class),style:{...x(e.style),...x(t.style)}}:e,E=(e,t)=>{let n=e&&(typeof e==`function`?e:()=>e);return n&&t?e=>{let r=t(e);return T(r,n(T(e,r)))}:n||t},D=(e,t)=>e&&t?Object.assign((n,r,i)=>{t(n,r,i),e(n,r,i)},{$dynamic:e.$dynamic||t.$dynamic}):e||t,O=new Proxy(y,{get(e,t){return e(t)}}),k=(e,...t)=>{};export{e as YakThemeContext,t as YakThemeProvider,p as atoms,m as css,k as globalStyle,g as keyframes,O as styled,n as useTheme};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|