@alex.radulescu/styled-static 0.2.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/dist/hash.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Murmurhash2 implementation for generating short, deterministic hashes.
3
+ * Used to create unique class names from CSS content.
4
+ *
5
+ * Based on https://github.com/garycourt/murmurhash-js
6
+ * This is a well-known, fast, non-cryptographic hash function.
7
+ */
8
+ export declare function hash(str?: string): string;
9
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,IAAI,CAAC,GAAG,SAAK,GAAG,MAAM,CA0CrC"}
package/dist/hash.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Murmurhash2 implementation for generating short, deterministic hashes.
3
+ * Used to create unique class names from CSS content.
4
+ *
5
+ * Based on https://github.com/garycourt/murmurhash-js
6
+ * This is a well-known, fast, non-cryptographic hash function.
7
+ */
8
+ export function hash(str = "") {
9
+ let l = str.length;
10
+ let h = l ^ l;
11
+ let i = 0;
12
+ let k;
13
+ while (l >= 4) {
14
+ k =
15
+ (str.charCodeAt(i) & 0xff) |
16
+ ((str.charCodeAt(++i) & 0xff) << 8) |
17
+ ((str.charCodeAt(++i) & 0xff) << 16) |
18
+ ((str.charCodeAt(++i) & 0xff) << 24);
19
+ k =
20
+ (k & 0xffff) * 0x5bd1e995 + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16);
21
+ k ^= k >>> 24;
22
+ k =
23
+ (k & 0xffff) * 0x5bd1e995 + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16);
24
+ h =
25
+ ((h & 0xffff) * 0x5bd1e995 +
26
+ ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^
27
+ k;
28
+ l -= 4;
29
+ ++i;
30
+ }
31
+ // Handle remaining bytes (1-3) without switch fallthrough
32
+ if (l >= 3)
33
+ h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
34
+ if (l >= 2)
35
+ h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
36
+ if (l >= 1) {
37
+ h ^= str.charCodeAt(i) & 0xff;
38
+ h =
39
+ (h & 0xffff) * 0x5bd1e995 + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16);
40
+ }
41
+ h ^= h >>> 13;
42
+ h = (h & 0xffff) * 0x5bd1e995 + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16);
43
+ h ^= h >>> 15;
44
+ return (h >>> 0).toString(36);
45
+ }
46
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,IAAI,CAAC,GAAG,GAAG,EAAE;IAC3B,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC;IACnB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACd,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,IAAI,CAAS,CAAC;IAEd,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACd,CAAC;YACC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;gBAC1B,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;gBACnC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBACpC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAEvC,CAAC;YACC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3E,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACd,CAAC;YACC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAE3E,CAAC;YACC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,UAAU;gBACxB,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC/C,CAAC,CAAC;QAEJ,CAAC,IAAI,CAAC,CAAC;QACP,EAAE,CAAC,CAAC;IACN,CAAC;IAED,0DAA0D;IAC1D,IAAI,CAAC,IAAI,CAAC;QAAE,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACtD,IAAI,CAAC,IAAI,CAAC;QAAE,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACX,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAC9B,CAAC;YACC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACd,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7E,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAEd,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * styled-static
3
+ *
4
+ * Zero-runtime styled components for React 19+ with Vite.
5
+ * CSS is extracted to static files at build time.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { styled, css, createGlobalStyle } from 'styled-static';
10
+ *
11
+ * // Style HTML elements
12
+ * const Button = styled.button`
13
+ * padding: 0.5rem 1rem;
14
+ * background: blue;
15
+ * color: white;
16
+ *
17
+ * &:hover {
18
+ * background: darkblue;
19
+ * }
20
+ * `;
21
+ *
22
+ * // Extend existing styled components
23
+ * const PrimaryButton = styled(Button)`
24
+ * font-weight: bold;
25
+ * `;
26
+ *
27
+ * // Get a class name for mixing
28
+ * const activeClass = css`
29
+ * outline: 2px solid blue;
30
+ * `;
31
+ *
32
+ * // Global styles
33
+ * const GlobalStyle = createGlobalStyle`
34
+ * * { box-sizing: border-box; }
35
+ * body { margin: 0; }
36
+ * `;
37
+ *
38
+ * // Usage
39
+ * <GlobalStyle />
40
+ * <Button>Click me</Button>
41
+ * <Button as="a" href="/link">Link button</Button>
42
+ * <PrimaryButton className={activeClass}>Active</PrimaryButton>
43
+ * ```
44
+ */
45
+ export type { StyledComponent, StyledFunction, HTMLTag, PropsOf } from './types';
46
+ /**
47
+ * Create styled React components with zero runtime overhead.
48
+ * CSS is extracted to static files at build time.
49
+ *
50
+ * @example
51
+ * // Style HTML elements
52
+ * const Button = styled.button`
53
+ * padding: 0.5rem 1rem;
54
+ * background: blue;
55
+ * `;
56
+ *
57
+ * // Extend existing styled components
58
+ * const PrimaryButton = styled(Button)`
59
+ * font-weight: bold;
60
+ * `;
61
+ *
62
+ * // Use with `as` prop for polymorphism
63
+ * <Button as="a" href="/link">Click</Button>
64
+ *
65
+ * // Use transient props (won't reach DOM)
66
+ * <Button $primary={true}>Click</Button>
67
+ */
68
+ export declare const styled: import("./types").StyledFunction;
69
+ /**
70
+ * Get a scoped class name for CSS.
71
+ * Useful for conditional classes or mixing with styled components.
72
+ *
73
+ * @example
74
+ * const activeClass = css`
75
+ * background: blue;
76
+ * color: white;
77
+ * `;
78
+ *
79
+ * const highlightClass = css`
80
+ * box-shadow: 0 0 10px yellow;
81
+ * `;
82
+ *
83
+ * <div className={isActive ? activeClass : ''} />
84
+ * <Button className={`${activeClass} ${highlightClass}`}>Mixed</Button>
85
+ */
86
+ export declare function css(_strings: TemplateStringsArray, ..._interpolations: never[]): string;
87
+ /**
88
+ * Create global (unscoped) styles.
89
+ * Returns a component that should be rendered once at the root of your app.
90
+ * The component renders nothing - CSS is extracted at build time.
91
+ *
92
+ * @example
93
+ * const GlobalStyle = createGlobalStyle`
94
+ * * {
95
+ * box-sizing: border-box;
96
+ * }
97
+ *
98
+ * body {
99
+ * margin: 0;
100
+ * font-family: system-ui, sans-serif;
101
+ * }
102
+ *
103
+ * :root {
104
+ * --color-primary: #3b82f6;
105
+ * --color-text: #1a1a1a;
106
+ * }
107
+ * `;
108
+ *
109
+ * // In your app entry point
110
+ * createRoot(document.getElementById('root')!).render(
111
+ * <StrictMode>
112
+ * <GlobalStyle />
113
+ * <App />
114
+ * </StrictMode>
115
+ * );
116
+ */
117
+ export declare function createGlobalStyle(_strings: TemplateStringsArray, ..._interpolations: never[]): () => null;
118
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAcjF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,MAAM,EAGb,OAAO,SAAS,EAAE,cAAc,CAAC;AAEvC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,GAAG,CACjB,QAAQ,EAAE,oBAAoB,EAC9B,GAAG,eAAe,EAAE,KAAK,EAAE,GAC1B,MAAM,CAER;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,oBAAoB,EAC9B,GAAG,eAAe,EAAE,KAAK,EAAE,GAC1B,MAAM,IAAI,CAEZ"}
package/dist/index.js ADDED
@@ -0,0 +1,133 @@
1
+ /**
2
+ * styled-static
3
+ *
4
+ * Zero-runtime styled components for React 19+ with Vite.
5
+ * CSS is extracted to static files at build time.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import { styled, css, createGlobalStyle } from 'styled-static';
10
+ *
11
+ * // Style HTML elements
12
+ * const Button = styled.button`
13
+ * padding: 0.5rem 1rem;
14
+ * background: blue;
15
+ * color: white;
16
+ *
17
+ * &:hover {
18
+ * background: darkblue;
19
+ * }
20
+ * `;
21
+ *
22
+ * // Extend existing styled components
23
+ * const PrimaryButton = styled(Button)`
24
+ * font-weight: bold;
25
+ * `;
26
+ *
27
+ * // Get a class name for mixing
28
+ * const activeClass = css`
29
+ * outline: 2px solid blue;
30
+ * `;
31
+ *
32
+ * // Global styles
33
+ * const GlobalStyle = createGlobalStyle`
34
+ * * { box-sizing: border-box; }
35
+ * body { margin: 0; }
36
+ * `;
37
+ *
38
+ * // Usage
39
+ * <GlobalStyle />
40
+ * <Button>Click me</Button>
41
+ * <Button as="a" href="/link">Link button</Button>
42
+ * <PrimaryButton className={activeClass}>Active</PrimaryButton>
43
+ * ```
44
+ */
45
+ function throwConfigError(name) {
46
+ throw new Error(`${name} was not transformed at build time. ` +
47
+ `Ensure the styled-static plugin is configured in vite.config.ts:\n\n` +
48
+ ` import { styledStatic } from 'styled-static/vite';\n` +
49
+ ` import react from '@vitejs/plugin-react';\n\n` +
50
+ ` export default defineConfig({\n` +
51
+ ` plugins: [styledStatic(), react()],\n` +
52
+ ` });`);
53
+ }
54
+ /**
55
+ * Create styled React components with zero runtime overhead.
56
+ * CSS is extracted to static files at build time.
57
+ *
58
+ * @example
59
+ * // Style HTML elements
60
+ * const Button = styled.button`
61
+ * padding: 0.5rem 1rem;
62
+ * background: blue;
63
+ * `;
64
+ *
65
+ * // Extend existing styled components
66
+ * const PrimaryButton = styled(Button)`
67
+ * font-weight: bold;
68
+ * `;
69
+ *
70
+ * // Use with `as` prop for polymorphism
71
+ * <Button as="a" href="/link">Click</Button>
72
+ *
73
+ * // Use transient props (won't reach DOM)
74
+ * <Button $primary={true}>Click</Button>
75
+ */
76
+ export const styled = new Proxy({}, {
77
+ get: () => () => throwConfigError('styled'),
78
+ apply: () => throwConfigError('styled'),
79
+ });
80
+ /**
81
+ * Get a scoped class name for CSS.
82
+ * Useful for conditional classes or mixing with styled components.
83
+ *
84
+ * @example
85
+ * const activeClass = css`
86
+ * background: blue;
87
+ * color: white;
88
+ * `;
89
+ *
90
+ * const highlightClass = css`
91
+ * box-shadow: 0 0 10px yellow;
92
+ * `;
93
+ *
94
+ * <div className={isActive ? activeClass : ''} />
95
+ * <Button className={`${activeClass} ${highlightClass}`}>Mixed</Button>
96
+ */
97
+ export function css(_strings, ..._interpolations) {
98
+ throwConfigError('css');
99
+ }
100
+ /**
101
+ * Create global (unscoped) styles.
102
+ * Returns a component that should be rendered once at the root of your app.
103
+ * The component renders nothing - CSS is extracted at build time.
104
+ *
105
+ * @example
106
+ * const GlobalStyle = createGlobalStyle`
107
+ * * {
108
+ * box-sizing: border-box;
109
+ * }
110
+ *
111
+ * body {
112
+ * margin: 0;
113
+ * font-family: system-ui, sans-serif;
114
+ * }
115
+ *
116
+ * :root {
117
+ * --color-primary: #3b82f6;
118
+ * --color-text: #1a1a1a;
119
+ * }
120
+ * `;
121
+ *
122
+ * // In your app entry point
123
+ * createRoot(document.getElementById('root')!).render(
124
+ * <StrictMode>
125
+ * <GlobalStyle />
126
+ * <App />
127
+ * </StrictMode>
128
+ * );
129
+ */
130
+ export function createGlobalStyle(_strings, ..._interpolations) {
131
+ throwConfigError('createGlobalStyle');
132
+ }
133
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAIH,SAAS,gBAAgB,CAAC,IAAY;IACpC,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,sCAAsC;QAC3C,sEAAsE;QACtE,wDAAwD;QACxD,iDAAiD;QACjD,mCAAmC;QACnC,2CAA2C;QAC3C,OAAO,CACV,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,EAAW,EAAE;IAC3C,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC;IAC3C,KAAK,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC;CACxC,CAAqC,CAAC;AAEvC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,GAAG,CACjB,QAA8B,EAC9B,GAAG,eAAwB;IAE3B,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAA8B,EAC9B,GAAG,eAAwB;IAE3B,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * styled-static runtime
3
+ *
4
+ * This is the minimal runtime required for styled-static (~300 bytes minified).
5
+ * It provides:
6
+ *
7
+ * - `as` prop polymorphism: render as different HTML element
8
+ * - Transient props filtering: $-prefixed props don't reach the DOM
9
+ * - className merging: styled classes + user classes in correct order
10
+ * - displayName: for React DevTools (dev mode only)
11
+ *
12
+ * React 19's automatic ref forwarding handles refs without explicit forwardRef.
13
+ */
14
+ import { type ComponentType, type JSX } from 'react';
15
+ type HTMLTag = keyof JSX.IntrinsicElements;
16
+ /**
17
+ * Creates a styled component from an HTML tag.
18
+ *
19
+ * Supports the `as` prop for polymorphic rendering:
20
+ * @example
21
+ * const Button = __styled('button', 'ss-abc123');
22
+ * <Button as="a" href="/link">Link</Button> // Renders as <a>
23
+ *
24
+ * @param tag - Default HTML tag to render
25
+ * @param className - Generated class name from CSS
26
+ * @param displayName - Component name for DevTools (dev mode only)
27
+ */
28
+ export declare function __styled<T extends HTMLTag>(tag: T, className: string, displayName?: string): ComponentType<any>;
29
+ /**
30
+ * Creates a styled component by extending an existing component.
31
+ *
32
+ * The new className is merged with the base component's className,
33
+ * maintaining proper CSS cascade order:
34
+ * - Base component's styles apply first
35
+ * - Extension styles apply second (can override base)
36
+ * - User's className applies last (can override both)
37
+ *
38
+ * @example
39
+ * const Button = __styled('button', 'ss-base');
40
+ * const Primary = __styledExtend(Button, 'ss-primary');
41
+ * // <Primary /> renders with class="ss-base ss-primary"
42
+ * // <Primary className="custom" /> renders with class="ss-base ss-primary custom"
43
+ *
44
+ * @param Base - Component to extend
45
+ * @param className - Additional class name for this extension
46
+ * @param displayName - Component name for DevTools (dev mode only)
47
+ */
48
+ export declare function __styledExtend<P extends {
49
+ className?: string;
50
+ }>(Base: ComponentType<P>, className: string, displayName?: string): ComponentType<any>;
51
+ /**
52
+ * GlobalStyle component - renders nothing.
53
+ * The CSS is extracted to a static file at build time.
54
+ * This component exists only to provide a familiar API.
55
+ */
56
+ export declare const __GlobalStyle: ComponentType<Record<string, never>>;
57
+ export {};
58
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAiB,KAAK,aAAa,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAEpE,KAAK,OAAO,GAAG,MAAM,GAAG,CAAC,iBAAiB,CAAC;AAyB3C;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,EACxC,GAAG,EAAE,CAAC,EACN,SAAS,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,GACnB,aAAa,CAAC,GAAG,CAAC,CAepB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7D,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,EACtB,SAAS,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,GACnB,aAAa,CAAC,GAAG,CAAC,CAkBpB;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAc,CAAC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * styled-static runtime
3
+ *
4
+ * This is the minimal runtime required for styled-static (~300 bytes minified).
5
+ * It provides:
6
+ *
7
+ * - `as` prop polymorphism: render as different HTML element
8
+ * - Transient props filtering: $-prefixed props don't reach the DOM
9
+ * - className merging: styled classes + user classes in correct order
10
+ * - displayName: for React DevTools (dev mode only)
11
+ *
12
+ * React 19's automatic ref forwarding handles refs without explicit forwardRef.
13
+ */
14
+ import { createElement } from 'react';
15
+ /**
16
+ * Filters out transient props (those starting with $).
17
+ * This prevents React warnings about invalid DOM attributes.
18
+ */
19
+ function filterTransientProps(props) {
20
+ const filtered = {};
21
+ for (const key in props) {
22
+ if (key[0] !== '$') {
23
+ filtered[key] = props[key];
24
+ }
25
+ }
26
+ return filtered;
27
+ }
28
+ /**
29
+ * Merges class names in the correct order for CSS cascade.
30
+ * Order: styled class(es) first, user className last
31
+ * This allows user classes to override styled classes when needed.
32
+ */
33
+ function mergeClassNames(styledClass, userClass) {
34
+ return userClass ? `${styledClass} ${userClass}` : styledClass;
35
+ }
36
+ /**
37
+ * Creates a styled component from an HTML tag.
38
+ *
39
+ * Supports the `as` prop for polymorphic rendering:
40
+ * @example
41
+ * const Button = __styled('button', 'ss-abc123');
42
+ * <Button as="a" href="/link">Link</Button> // Renders as <a>
43
+ *
44
+ * @param tag - Default HTML tag to render
45
+ * @param className - Generated class name from CSS
46
+ * @param displayName - Component name for DevTools (dev mode only)
47
+ */
48
+ export function __styled(tag, className, displayName) {
49
+ const Component = (props) => {
50
+ const { as: As = tag, className: userClass, ...rest } = props;
51
+ const domProps = filterTransientProps(rest);
52
+ domProps.className = mergeClassNames(className, userClass);
53
+ return createElement(As, domProps);
54
+ };
55
+ if (displayName) {
56
+ Component.displayName = displayName;
57
+ }
58
+ return Component;
59
+ }
60
+ /**
61
+ * Creates a styled component by extending an existing component.
62
+ *
63
+ * The new className is merged with the base component's className,
64
+ * maintaining proper CSS cascade order:
65
+ * - Base component's styles apply first
66
+ * - Extension styles apply second (can override base)
67
+ * - User's className applies last (can override both)
68
+ *
69
+ * @example
70
+ * const Button = __styled('button', 'ss-base');
71
+ * const Primary = __styledExtend(Button, 'ss-primary');
72
+ * // <Primary /> renders with class="ss-base ss-primary"
73
+ * // <Primary className="custom" /> renders with class="ss-base ss-primary custom"
74
+ *
75
+ * @param Base - Component to extend
76
+ * @param className - Additional class name for this extension
77
+ * @param displayName - Component name for DevTools (dev mode only)
78
+ */
79
+ export function __styledExtend(Base, className, displayName) {
80
+ const Component = (props) => {
81
+ const { className: userClass, ...rest } = props;
82
+ const cleanProps = filterTransientProps(rest);
83
+ // Extension class comes after base class (base handles its own class)
84
+ // User class comes last for maximum override capability
85
+ cleanProps.className = mergeClassNames(className, userClass);
86
+ return createElement(Base, cleanProps);
87
+ };
88
+ if (displayName) {
89
+ Component.displayName = displayName;
90
+ }
91
+ return Component;
92
+ }
93
+ /**
94
+ * GlobalStyle component - renders nothing.
95
+ * The CSS is extracted to a static file at build time.
96
+ * This component exists only to provide a familiar API.
97
+ */
98
+ export const __GlobalStyle = () => null;
99
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,aAAa,EAAgC,MAAM,OAAO,CAAC;AAIpE;;;GAGG;AACH,SAAS,oBAAoB,CAAC,KAA8B;IAC1D,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAC7C,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACnB,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,WAAmB,EAAE,SAAkB;IAC9D,OAAO,SAAS,CAAC,CAAC,CAAC,GAAG,WAAW,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ,CACtB,GAAM,EACN,SAAiB,EACjB,WAAoB;IAEpB,MAAM,SAAS,GAAG,CAAC,KAAU,EAAE,EAAE;QAC/B,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QAE9D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAC5C,QAAQ,CAAC,SAAS,GAAG,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAE3D,OAAO,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC,CAAC;IAEF,IAAI,WAAW,EAAE,CAAC;QAChB,SAAS,CAAC,WAAW,GAAG,WAAW,CAAC;IACtC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAsB,EACtB,SAAiB,EACjB,WAAoB;IAEpB,MAAM,SAAS,GAAG,CAAC,KAAU,EAAE,EAAE;QAC/B,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QAEhD,MAAM,UAAU,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAE9C,sEAAsE;QACtE,wDAAwD;QACxD,UAAU,CAAC,SAAS,GAAG,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAE7D,OAAO,aAAa,CAAC,IAAI,EAAE,UAAe,CAAC,CAAC;IAC9C,CAAC,CAAC;IAEF,IAAI,WAAW,EAAE,CAAC;QAChB,SAAS,CAAC,WAAW,GAAG,WAAW,CAAC;IACtC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAyC,GAAG,EAAE,CAAC,IAAI,CAAC"}
@@ -0,0 +1,57 @@
1
+ import type { ComponentType, JSX } from "react";
2
+ /** All valid HTML tag names */
3
+ export type HTMLTag = keyof JSX.IntrinsicElements;
4
+ /** Extract props from an HTML tag or component */
5
+ export type PropsOf<T> = T extends HTMLTag ? JSX.IntrinsicElements[T] : T extends ComponentType<infer P> ? P : never;
6
+ /**
7
+ * Transient props - prefixed with $ to prevent forwarding to DOM.
8
+ * These props are filtered out before rendering, useful for conditional styling logic.
9
+ *
10
+ * @example
11
+ * <Button $primary={true} $size="large" />
12
+ * // $primary and $size won't appear in the DOM
13
+ */
14
+ export type TransientProps = {
15
+ [K in `$${string}`]?: unknown;
16
+ };
17
+ /**
18
+ * The `as` prop enables polymorphic rendering.
19
+ * Allows a styled component to render as a different HTML element.
20
+ *
21
+ * @example
22
+ * const Button = styled.button`...`;
23
+ * <Button as="a" href="/link">Link styled as button</Button>
24
+ */
25
+ export type AsProp = {
26
+ as?: HTMLTag;
27
+ };
28
+ /**
29
+ * A styled React component with full type inference.
30
+ *
31
+ * For HTML elements: includes original element props + transient props + as prop
32
+ * For components: includes component props + transient props (no as prop)
33
+ */
34
+ export type StyledComponent<T extends HTMLTag | ComponentType<any>> = T extends HTMLTag ? ComponentType<PropsOf<T> & TransientProps & AsProp> : T extends ComponentType<infer P> ? ComponentType<P & TransientProps> : never;
35
+ /**
36
+ * The main styled function type.
37
+ * Supports both `styled.element` and `styled(Component)` syntax.
38
+ */
39
+ export type StyledFunction = {
40
+ /**
41
+ * Style an HTML element.
42
+ * @example
43
+ * const Button = styled.button`padding: 1rem;`;
44
+ */
45
+ <T extends HTMLTag>(tag: T): (strings: TemplateStringsArray, ...interpolations: never[]) => StyledComponent<T>;
46
+ /**
47
+ * Extend an existing styled component or any component with className prop.
48
+ * @example
49
+ * const PrimaryButton = styled(Button)`background: blue;`;
50
+ */
51
+ <P extends {
52
+ className?: string;
53
+ }>(component: ComponentType<P>): (strings: TemplateStringsArray, ...interpolations: never[]) => StyledComponent<ComponentType<P>>;
54
+ } & {
55
+ [K in HTMLTag]: (strings: TemplateStringsArray, ...interpolations: never[]) => StyledComponent<K>;
56
+ };
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEhD,+BAA+B;AAC/B,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,iBAAiB,CAAC;AAElD,kDAAkD;AAClD,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GACtC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,GACxB,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAChC,CAAC,GACD,KAAK,CAAC;AAEV;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG;KAAG,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC,EAAE,OAAO;CAAE,CAAC;AAE/D;;;;;;;GAOG;AACH,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,CAAC,EAAE,OAAO,CAAC;CACd,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,IAChE,CAAC,SAAS,OAAO,GACb,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,GAAG,MAAM,CAAC,GACnD,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAChC,aAAa,CAAC,CAAC,GAAG,cAAc,CAAC,GACjC,KAAK,CAAC;AAEZ;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;OAIG;IACH,CAAC,CAAC,SAAS,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAC3B,OAAO,EAAE,oBAAoB,EAC7B,GAAG,cAAc,EAAE,KAAK,EAAE,KACvB,eAAe,CAAC,CAAC,CAAC,CAAC;IAExB;;;;OAIG;IACH,CAAC,CAAC,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,CAC/D,OAAO,EAAE,oBAAoB,EAC7B,GAAG,cAAc,EAAE,KAAK,EAAE,KACvB,eAAe,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;CACxC,GAAG;KAQD,CAAC,IAAI,OAAO,GAAG,CACd,OAAO,EAAE,oBAAoB,EAC7B,GAAG,cAAc,EAAE,KAAK,EAAE,KACvB,eAAe,CAAC,CAAC,CAAC;CACxB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/dist/vite.d.ts ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * styled-static Vite Plugin
3
+ *
4
+ * Transforms styled-static syntax into optimized React components with
5
+ * static CSS extraction.
6
+ *
7
+ * ## Why AST over Regex?
8
+ *
9
+ * We use Vite's built-in parser (via Rollup's acorn) instead of regex because:
10
+ *
11
+ * 1. **Robustness**: Regex breaks on edge cases like CSS containing backticks,
12
+ * strings that look like styled calls, or complex nesting.
13
+ *
14
+ * Example that would break regex:
15
+ * ```tsx
16
+ * const x = styled.div`content: "styled.button\`test\`";`;
17
+ * const comment = "// styled.div`fake`"; // This isn't actually a styled call
18
+ * ```
19
+ *
20
+ * 2. **No extra dependencies**: Vite provides `this.parse()` for free via Rollup.
21
+ * We don't need acorn or acorn-walk as separate dependencies.
22
+ *
23
+ * 3. **Accuracy**: AST gives us exact node positions for surgical code replacement
24
+ * with proper source maps. Regex can't reliably handle nested backticks or
25
+ * escaped characters.
26
+ *
27
+ * 4. **Maintainability**: Adding new syntax patterns is straightforward with AST
28
+ * visitors vs. increasingly complex regex patterns that become unmaintainable.
29
+ *
30
+ * ## Transformation Pipeline
31
+ *
32
+ * 1. Parse source with Vite's parser
33
+ * 2. Find all styled/css/createGlobalStyle tagged template literals
34
+ * 3. For each:
35
+ * - Extract CSS content
36
+ * - Hash it to generate unique class name
37
+ * - Process CSS (nesting, autoprefixer)
38
+ * - Create virtual CSS module
39
+ * - Replace original code with runtime call + import
40
+ * 4. Return transformed code with source map
41
+ *
42
+ * ## className Order (CSS Cascade)
43
+ *
44
+ * When components are extended, classes are ordered for proper cascade:
45
+ * - Base styles first
46
+ * - Extension styles second (override base)
47
+ * - User className last (override all)
48
+ *
49
+ * Example:
50
+ * ```tsx
51
+ * const Button = styled.button`padding: 1rem;`; // .ss-abc
52
+ * const Primary = styled(Button)`background: blue;`; // .ss-def
53
+ * <Primary className="custom" />
54
+ * // Renders: class="ss-abc ss-def custom"
55
+ * // CSS cascade: padding → background → custom overrides
56
+ * ```
57
+ */
58
+ import type { Plugin } from "vite";
59
+ /** Plugin configuration options */
60
+ export interface StyledStaticOptions {
61
+ /**
62
+ * Prefix for generated class names.
63
+ * @default 'ss'
64
+ */
65
+ classPrefix?: string;
66
+ /**
67
+ * Browsers to target for autoprefixer.
68
+ * Set to false to disable autoprefixer.
69
+ * @default ['last 2 Chrome versions', 'last 2 Firefox versions', 'last 2 Safari versions', 'last 2 Edge versions']
70
+ */
71
+ autoprefixer?: string[] | false;
72
+ }
73
+ /**
74
+ * Vite plugin for styled-static.
75
+ *
76
+ * @example
77
+ * import { defineConfig } from 'vite';
78
+ * import react from '@vitejs/plugin-react';
79
+ * import { styledStatic } from 'styled-static/vite';
80
+ *
81
+ * export default defineConfig({
82
+ * plugins: [styledStatic(), react()],
83
+ * });
84
+ */
85
+ export declare function styledStatic(options?: StyledStaticOptions): Plugin;
86
+ export default styledStatic;
87
+ //# sourceMappingURL=vite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,MAAM,CAAC;AAuBnD,mCAAmC;AACnC,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;CACjC;AAyBD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,CA8KtE;AAsOD,eAAe,YAAY,CAAC"}