@vitus-labs/core 1.4.2 → 1.4.3-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/lib/index.d.ts +82 -17
  2. package/lib/index.js +111 -27
  3. package/package.json +4 -4
package/lib/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { ThemeProvider, css, styled } from "styled-components";
2
1
  import * as React from "react";
3
2
  import { ComponentType, FC, ReactNode, cloneElement, createElement } from "react";
4
3
 
@@ -137,28 +136,94 @@ type HTMLTagAttrsByTag<T extends HTMLTags> = T extends HTMLTags ? HTMLElementAtt
137
136
  //#endregion
138
137
  //#region src/config.d.ts
139
138
  /**
140
- * Singleton configuration that bridges the UI system with styled-components.
141
- * All packages reference `config.css`, `config.styled`, etc. so the styling
142
- * engine can be swapped at runtime (e.g. for React Native) via `init()`.
139
+ * Describes the shape of a CSS-in-JS engine connector.
140
+ * Packages like `@vitus-labs/connector-styler`, `@vitus-labs/connector-emotion`,
141
+ * and `@vitus-labs/connector-styled-components` export this shape.
142
+ *
143
+ * Required properties (`css`, `styled`, `provider`) are consumed by config
144
+ * across all packages. Optional properties (`keyframes`, `createGlobalStyle`,
145
+ * `useTheme`) are exposed for direct use in application code.
143
146
  */
144
- interface Internal {
145
- css: typeof css;
146
- styled: typeof styled;
147
- provider: typeof ThemeProvider;
147
+ interface CSSEngineConnector {
148
+ /** Tagged template for composable CSS fragments. */
149
+ css: (strings: TemplateStringsArray, ...values: any[]) => any;
150
+ /** Component factory: `styled(tag)`\`...\`` → React component. */
151
+ styled: ((tag: any, options?: any) => (strings: TemplateStringsArray, ...values: any[]) => any) & Record<string, any>;
152
+ /** ThemeProvider component wrapping children with a theme context. */
153
+ provider: FC<{
154
+ theme: any;
155
+ children: ReactNode;
156
+ }>;
157
+ /** Tagged template for @keyframes animations. */
158
+ keyframes?: (strings: TemplateStringsArray, ...values: any[]) => any;
159
+ /** Factory for injecting global CSS. */
160
+ createGlobalStyle?: (strings: TemplateStringsArray, ...values: any[]) => any;
161
+ /** Hook to read the current theme from the engine's context. */
162
+ useTheme?: () => any;
163
+ }
164
+ interface PlatformConfig {
148
165
  component: ComponentType | HTMLTags;
149
166
  textComponent: ComponentType | HTMLTags;
150
167
  }
168
+ type InitConfig = Partial<CSSEngineConnector & PlatformConfig>;
169
+ /**
170
+ * Singleton configuration that bridges the UI system with the chosen
171
+ * CSS-in-JS engine. All packages reference `config.css`, `config.styled`,
172
+ * etc. — the engine is swapped via `init()` with a connector.
173
+ *
174
+ * The `css` and `styled` properties are **stable delegate functions** that
175
+ * can be safely destructured at module level (`const { styled, css } = config`).
176
+ * They internally read the latest engine reference set by `init()`.
177
+ *
178
+ * When destructured before `init()` is called:
179
+ * - `css` returns a thunk (function) that resolves at render time
180
+ * - `styled` returns a lazy component that creates the real component on first render
181
+ */
151
182
  declare class Configuration {
152
- css: Internal['css'];
153
- styled: Internal['styled'];
154
- ExternalProvider: Internal['provider'];
155
- component: Internal['component'];
156
- textComponent: Internal['textComponent'];
157
- constructor(props: Internal);
158
- init: (props: Partial<Internal>) => void;
183
+ _css: CSSEngineConnector['css'] | null;
184
+ _styled: CSSEngineConnector['styled'] | null;
185
+ _provider: CSSEngineConnector['provider'] | null;
186
+ _keyframes: CSSEngineConnector['keyframes'] | null;
187
+ _createGlobalStyle: CSSEngineConnector['createGlobalStyle'] | null;
188
+ _useTheme: CSSEngineConnector['useTheme'] | null;
189
+ component: ComponentType | HTMLTags;
190
+ textComponent: ComponentType | HTMLTags;
191
+ /**
192
+ * Stable CSS delegate. When the engine is available, delegates immediately.
193
+ * When not (module load time before init), returns a thunk that resolves
194
+ * at render time — all CSS-in-JS engines treat functions as interpolations.
195
+ */
196
+ css: (strings: TemplateStringsArray, ...values: any[]) => any;
197
+ /**
198
+ * Stable styled delegate (Proxy). Supports `styled(tag)` and `styled.div`.
199
+ * When the engine is not yet available, returns a lazy forwardRef component
200
+ * that creates the real styled component on first render.
201
+ */
202
+ styled: CSSEngineConnector['styled'];
203
+ /** The external ThemeProvider from the configured engine. */
204
+ get ExternalProvider(): CSSEngineConnector['provider'] | null;
205
+ /** Keyframes factory from the configured engine, or null. */
206
+ get keyframes(): CSSEngineConnector['keyframes'] | null;
207
+ /** Global style factory from the configured engine, or null. */
208
+ get createGlobalStyle(): CSSEngineConnector['createGlobalStyle'] | null;
209
+ /** Theme hook from the configured engine, or null. */
210
+ get useTheme(): CSSEngineConnector['useTheme'] | null;
211
+ constructor();
212
+ /**
213
+ * Initialize or swap the CSS-in-JS engine. Must be called before any
214
+ * component renders (typically at the app entry point).
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * import { init } from '@vitus-labs/core'
219
+ * import * as connector from '@vitus-labs/connector-styler'
220
+ * init(connector)
221
+ * ```
222
+ */
223
+ init: (props: InitConfig) => void;
159
224
  }
160
225
  declare const config: Configuration;
161
- declare const init: (props: Partial<Internal>) => void;
226
+ declare const init: (props: InitConfig) => void;
162
227
  //#endregion
163
228
  //#region src/types.d.ts
164
229
  interface Breakpoints {
@@ -247,5 +312,5 @@ declare const throttle: <T extends (...args: any[]) => any>(fn: T, wait?: number
247
312
  };
248
313
  declare const merge: <T extends Record<string, any>>(target: T, ...sources: Record<string, any>[]) => T;
249
314
  //#endregion
250
- export { type BreakpointKeys, type Breakpoints, type HTMLElementAttrs, type HTMLTagAttrsByTag, type HTMLTags, type HTMLTextTags, HTML_TAGS, HTML_TEXT_TAGS, type IsEmpty, Provider, type Render, compose, config, context, get, hoistNonReactStatics, init, isEmpty, isEqual, merge, omit, pick, render, set, throttle, useStableValue };
315
+ export { type BreakpointKeys, type Breakpoints, type CSSEngineConnector, type HTMLElementAttrs, type HTMLTagAttrsByTag, type HTMLTags, type HTMLTextTags, HTML_TAGS, HTML_TEXT_TAGS, type IsEmpty, Provider, type Render, compose, config, context, get, hoistNonReactStatics, init, isEmpty, isEqual, merge, omit, pick, render, set, throttle, useStableValue };
251
316
  //# sourceMappingURL=index2.d.ts.map
package/lib/index.js CHANGED
@@ -1,5 +1,4 @@
1
- import { ThemeProvider, css, styled } from "styled-components";
2
- import { cloneElement, createContext, createElement, isValidElement, useMemo, useRef } from "react";
1
+ import { cloneElement, createContext, createElement, forwardRef, isValidElement, useMemo, useRef } from "react";
3
2
  import { Fragment, jsx } from "react/jsx-runtime";
4
3
  import { isFragment, isMemo, isValidElementType } from "react-is";
5
4
 
@@ -15,34 +14,123 @@ const compose = (...fns) => (p) => fns.reduceRight((acc, cur) => cur(acc), p);
15
14
 
16
15
  //#endregion
17
16
  //#region src/config.ts
17
+ const notConfigured = (_name) => {
18
+ throw new Error("[@vitus-labs/core] CSS engine not configured. Call init() with a connector before rendering.\n\n import { init } from '@vitus-labs/core'\n import * as connector from '@vitus-labs/connector-styler'\n init(connector)\n");
19
+ };
20
+ const createStyledDelegate = (self) => {
21
+ const createLazy = (tag, options, strings, values) => {
22
+ let Real = null;
23
+ const Lazy = forwardRef((props, ref) => {
24
+ if (!Real) {
25
+ const engine = self._styled;
26
+ if (!engine) return notConfigured("styled");
27
+ Real = options ? engine(tag, options)(strings, ...values) : engine(tag)(strings, ...values);
28
+ }
29
+ return createElement(Real, {
30
+ ...props,
31
+ ref
32
+ });
33
+ });
34
+ Lazy.displayName = `styled(${typeof tag === "string" ? tag : tag.displayName || tag.name || "Component"})`;
35
+ return Lazy;
36
+ };
37
+ const factory = (tag, options) => {
38
+ return (strings, ...values) => {
39
+ if (self._styled) return options ? self._styled(tag, options)(strings, ...values) : self._styled(tag)(strings, ...values);
40
+ return createLazy(tag, options, strings, values);
41
+ };
42
+ };
43
+ return new Proxy(factory, { get(_target, prop) {
44
+ if (prop === "prototype" || prop === "$$typeof") return void 0;
45
+ return (strings, ...values) => {
46
+ if (self._styled) return self._styled[prop](strings, ...values);
47
+ return createLazy(prop, void 0, strings, values);
48
+ };
49
+ } });
50
+ };
51
+ /**
52
+ * Singleton configuration that bridges the UI system with the chosen
53
+ * CSS-in-JS engine. All packages reference `config.css`, `config.styled`,
54
+ * etc. — the engine is swapped via `init()` with a connector.
55
+ *
56
+ * The `css` and `styled` properties are **stable delegate functions** that
57
+ * can be safely destructured at module level (`const { styled, css } = config`).
58
+ * They internally read the latest engine reference set by `init()`.
59
+ *
60
+ * When destructured before `init()` is called:
61
+ * - `css` returns a thunk (function) that resolves at render time
62
+ * - `styled` returns a lazy component that creates the real component on first render
63
+ */
18
64
  var Configuration = class {
19
- css;
20
- styled;
21
- ExternalProvider;
65
+ _css = null;
66
+ _styled = null;
67
+ _provider = null;
68
+ _keyframes = null;
69
+ _createGlobalStyle = null;
70
+ _useTheme = null;
22
71
  component = "div";
23
72
  textComponent = "span";
24
- constructor(props) {
25
- this.css = props.css;
26
- this.styled = props.styled;
27
- this.ExternalProvider = props.provider;
28
- this.component = props.component;
29
- this.textComponent = props.textComponent;
73
+ /**
74
+ * Stable CSS delegate. When the engine is available, delegates immediately.
75
+ * When not (module load time before init), returns a thunk that resolves
76
+ * at render time — all CSS-in-JS engines treat functions as interpolations.
77
+ */
78
+ css = (strings, ...values) => {
79
+ if (this._css) return this._css(strings, ...values);
80
+ return () => {
81
+ const engine = this._css;
82
+ if (!engine) return notConfigured("css");
83
+ return engine(strings, ...values);
84
+ };
85
+ };
86
+ /**
87
+ * Stable styled delegate (Proxy). Supports `styled(tag)` and `styled.div`.
88
+ * When the engine is not yet available, returns a lazy forwardRef component
89
+ * that creates the real styled component on first render.
90
+ */
91
+ styled;
92
+ /** The external ThemeProvider from the configured engine. */
93
+ get ExternalProvider() {
94
+ return this._provider;
95
+ }
96
+ /** Keyframes factory from the configured engine, or null. */
97
+ get keyframes() {
98
+ return this._keyframes ?? null;
99
+ }
100
+ /** Global style factory from the configured engine, or null. */
101
+ get createGlobalStyle() {
102
+ return this._createGlobalStyle ?? null;
103
+ }
104
+ /** Theme hook from the configured engine, or null. */
105
+ get useTheme() {
106
+ return this._useTheme ?? null;
107
+ }
108
+ constructor() {
109
+ this.styled = createStyledDelegate(this);
30
110
  }
111
+ /**
112
+ * Initialize or swap the CSS-in-JS engine. Must be called before any
113
+ * component renders (typically at the app entry point).
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * import { init } from '@vitus-labs/core'
118
+ * import * as connector from '@vitus-labs/connector-styler'
119
+ * init(connector)
120
+ * ```
121
+ */
31
122
  init = (props) => {
32
- if (props.css) this.css = props.css;
33
- if (props.styled) this.styled = props.styled;
34
- if (props.provider) this.ExternalProvider = props.provider;
123
+ if (props.css) this._css = props.css;
124
+ if (props.styled) this._styled = props.styled;
125
+ if (props.provider) this._provider = props.provider;
126
+ if (props.keyframes) this._keyframes = props.keyframes;
127
+ if (props.createGlobalStyle) this._createGlobalStyle = props.createGlobalStyle;
128
+ if (props.useTheme) this._useTheme = props.useTheme;
35
129
  if (props.component) this.component = props.component;
36
130
  if (props.textComponent) this.textComponent = props.textComponent;
37
131
  };
38
132
  };
39
- const config = new Configuration({
40
- css,
41
- styled,
42
- provider: ThemeProvider,
43
- component: "div",
44
- textComponent: "span"
45
- });
133
+ const config = new Configuration();
46
134
  const { init } = config;
47
135
 
48
136
  //#endregion
@@ -351,12 +439,8 @@ const HTML_TEXT_TAGS = [
351
439
  const render = (content, attachProps) => {
352
440
  if (!content) return null;
353
441
  const render = (child) => attachProps ? createElement(child, attachProps) : createElement(child);
354
- if ([
355
- "number",
356
- "boolean",
357
- "bigint",
358
- "string"
359
- ].includes(typeof content)) return content;
442
+ const t = typeof content;
443
+ if (t === "string" || t === "number" || t === "boolean" || t === "bigint") return content;
360
444
  if (Array.isArray(content) || isFragment(content)) return content;
361
445
  if (isValidElementType(content)) return render(content);
362
446
  if (isValidElement(content)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitus-labs/core",
3
- "version": "1.4.2",
3
+ "version": "1.4.3-alpha.3+16703b4",
4
4
  "license": "MIT",
5
5
  "author": "Vit Bokisch <vit@bokisch.cz>",
6
6
  "maintainers": [
@@ -9,6 +9,7 @@
9
9
  "type": "module",
10
10
  "sideEffects": false,
11
11
  "exports": {
12
+ "source": "./src/index.ts",
12
13
  "import": "./lib/index.js",
13
14
  "types": "./lib/index.d.ts"
14
15
  },
@@ -51,8 +52,7 @@
51
52
  "typecheck": "tsc --noEmit"
52
53
  },
53
54
  "peerDependencies": {
54
- "react": ">= 19",
55
- "styled-components": ">= 6"
55
+ "react": ">= 19"
56
56
  },
57
57
  "dependencies": {
58
58
  "react-is": "^19.2.3"
@@ -61,5 +61,5 @@
61
61
  "@vitus-labs/tools-rolldown": "^1.6.0",
62
62
  "@vitus-labs/tools-typescript": "^1.6.0"
63
63
  },
64
- "gitHead": "f12f43c61149964ff4f3f4b80cb6f92da2825915"
64
+ "gitHead": "16703b4c8dc0525bd504c531aeb082bf593579cc"
65
65
  }