@vitus-labs/rocketstyle 2.0.0-beta.0 → 2.0.0-beta.1

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/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { config, context, render } from "@vitus-labs/core";
2
- import { ComponentType, FC, FocusEventHandler, ForwardRefExoticComponent, MouseEventHandler, ReactNode } from "react";
2
+ import { ComponentType, FC, FocusEventHandler, MouseEventHandler, ReactNode } from "react";
3
3
 
4
4
  //#region src/context/context.d.ts
5
5
  type Theme$1 = {
@@ -66,11 +66,9 @@ type PseudoProps = Partial<PseudoState & PseudoActions>;
66
66
  type TObj = Record<string, unknown>;
67
67
  type TFn = (...args: any) => any;
68
68
  type CallBackParam = TObj | TFn;
69
- type ElementType<T extends TObj | unknown = any> = (ComponentType<T> & Partial<{
69
+ type ElementType<T extends TObj | unknown = any> = ComponentType<T> & Partial<{
70
70
  [key: string]: any;
71
- }>) | (ForwardRefExoticComponent<T> & {
72
- [key: string]: any;
73
- });
71
+ }>;
74
72
  type ValueOf<T> = T[keyof T];
75
73
  type ArrayOfValues<T> = T[keyof T][];
76
74
  type ArrayOfKeys<T> = Array<keyof T>;
@@ -83,7 +81,7 @@ type ExtractNullableKeys<T> = { [P in keyof T as IsAny<T[P]> extends true ? P :
83
81
  type SpreadTwo<L, R> = Id<Pick<L, Exclude<keyof L, keyof R>> & R>;
84
82
  type Spread<A extends readonly [...any]> = A extends [infer L, ...infer R] ? SpreadTwo<L, Spread<R>> : unknown;
85
83
  type MergeTypes<A extends readonly [...any]> = ExtractNullableKeys<Spread<A>>;
86
- type ExtractProps<TComponentOrTProps> = TComponentOrTProps extends ComponentType<infer TProps> ? TProps : TComponentOrTProps extends ForwardRefExoticComponent<infer TProps> ? TProps : TComponentOrTProps;
84
+ type ExtractProps<TComponentOrTProps> = TComponentOrTProps extends ComponentType<infer TProps> ? TProps : TComponentOrTProps;
87
85
  //#endregion
88
86
  //#region src/types/styles.d.ts
89
87
  interface StylesDefault {}
@@ -219,10 +217,6 @@ type GenericHoc = (component: ElementType) => ElementType;
219
217
  type ComposeParam = Record<string, GenericHoc | null | undefined | false>;
220
218
  //#endregion
221
219
  //#region src/types/rocketstyle.d.ts
222
- interface ExoticComponent<P = {}> {
223
- (props: P): ReactNode;
224
- readonly $$typeof: symbol;
225
- }
226
220
  type RocketStyleComponent<OA extends TObj = {}, EA extends TObj = {}, T extends TObj = {}, CSS extends TObj = {}, S extends TObj = {}, HOC extends TObj = {}, D extends Dimensions = Dimensions, UB extends boolean = boolean, DKP extends TDKP = TDKP> = IRocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DKP> & { [I in keyof D]: <K extends DimensionValue = D[I], P extends DimensionCallbackParam<Theme<T>, Styles<CSS>> = DimensionCallbackParam<Theme<T>, Styles<CSS>>>(param: P) => P extends DimensionCallbackParam<Theme<T>, Styles<CSS>> ? RocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DimensionProps<K, D, P, DKP>> : RocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DKP> };
227
221
  /**
228
222
  * @param OA Origin component props params.
@@ -235,7 +229,10 @@ type RocketStyleComponent<OA extends TObj = {}, EA extends TObj = {}, T extends
235
229
  * @param DKP Dimensions key props.
236
230
  * @param DFP Calculated final component props
237
231
  */
238
- interface IRocketStyleComponent<OA extends TObj = {}, EA extends TObj = {}, T extends TObj = {}, CSS extends TObj = {}, S extends TObj = {}, HOC extends TObj = {}, D extends Dimensions = Dimensions, UB extends boolean = boolean, DKP extends TDKP = TDKP, DFP = MergeTypes<[OA, EA, DefaultProps, ExtractDimensionProps<D, DKP, UB>]>> extends ExoticComponent<DFP> {
232
+ interface IRocketStyleComponent<OA extends TObj = {}, EA extends TObj = {}, T extends TObj = {}, CSS extends TObj = {}, S extends TObj = {}, HOC extends TObj = {}, D extends Dimensions = Dimensions, UB extends boolean = boolean, DKP extends TDKP = TDKP, DFP = MergeTypes<[OA, EA, DefaultProps, ExtractDimensionProps<D, DKP, UB>]>> {
233
+ (props: DFP & {
234
+ ref?: any;
235
+ }): ReactNode;
239
236
  /**
240
237
  * A chaining method to define default component theme
241
238
  * @param param _object_
@@ -575,11 +572,11 @@ type Rocketstyle = <D extends Dimensions = DefaultDimensions, UB extends boolean
575
572
  name: string;
576
573
  component: C;
577
574
  }) => ReturnType<RocketComponent<C, {}, {}, D, UB>>;
578
- declare const rocketstyle: Rocketstyle;
575
+ declare const typedRocketstyle: Rocketstyle;
579
576
  //#endregion
580
577
  //#region src/isRocketComponent.d.ts
581
578
  type IsRocketComponent = <T>(component: T) => boolean;
582
579
  declare const isRocketComponent: IsRocketComponent;
583
580
  //#endregion
584
- export { type AttrsCb, type ComposeParam, type ConfigAttrs, type ConsumerCb, type ConsumerCtxCBValue, type ConsumerCtxCb, type DefaultProps, type DimensionCallbackParam, type DimensionProps, type DimensionValue, type Dimensions, type ElementType, type ExtractDimensionProps, type ExtractDimensions, type ExtractProps, type GenericHoc, type IRocketStyleComponent, type IsRocketComponent, type MergeTypes, Provider, type RocketComponentType, type RocketProviderState, type RocketStyleComponent, type RocketStyleInterpolationProps, type Rocketstyle, type StylesCb, type StylesDefault, type TDKP, type TObj, type TProvider, type ThemeCb, type ThemeDefault, type ThemeMode, type ThemeModeCallback, type ThemeModeKeys, context, rocketstyle as default, rocketstyle, isRocketComponent };
581
+ export { type AttrsCb, type ComposeParam, type ConfigAttrs, type ConsumerCb, type ConsumerCtxCBValue, type ConsumerCtxCb, type DefaultProps, type DimensionCallbackParam, type DimensionProps, type DimensionValue, type Dimensions, type ElementType, type ExtractDimensionProps, type ExtractDimensions, type ExtractProps, type GenericHoc, type IRocketStyleComponent, type IsRocketComponent, type MergeTypes, Provider, type RocketComponentType, type RocketProviderState, type RocketStyleComponent, type RocketStyleInterpolationProps, type Rocketstyle, type StylesCb, type StylesDefault, type TDKP, type TObj, type TProvider, type ThemeCb, type ThemeDefault, type ThemeMode, type ThemeModeCallback, type ThemeModeKeys, context, typedRocketstyle as default, typedRocketstyle as rocketstyle, isRocketComponent };
585
582
  //# sourceMappingURL=index2.d.ts.map
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Provider as Provider$1, compose, config, context, get, hoistNonReactStatics, isEmpty, merge, omit, pick, render, set, useStableValue } from "@vitus-labs/core";
2
- import { createContext, forwardRef, useCallback, useContext, useImperativeHandle, useMemo, useRef, useState } from "react";
2
+ import { createContext, useCallback, useContext, useImperativeHandle, useMemo, useRef, useState } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
 
5
5
  //#region src/constants/index.ts
@@ -244,32 +244,35 @@ const LocalProvider = context$1.Provider;
244
244
  * detecting pseudo-states (hover, focus, pressed) via mouse/focus events
245
245
  * and broadcasting them through local context to child rocketstyle components.
246
246
  */
247
- const RocketStyleProviderComponent = (WrappedComponent) => forwardRef(({ onMouseEnter, onMouseLeave, onMouseUp, onMouseDown, onFocus, onBlur, $rocketstate, ...props }, ref) => {
248
- const { state: pseudoState, events: pseudoEvents } = usePseudoState({
249
- onMouseEnter,
250
- onMouseLeave,
251
- onMouseUp,
252
- onMouseDown,
253
- onFocus,
254
- onBlur
255
- });
256
- const updatedState = useStableValue({
257
- ...$rocketstate,
258
- pseudo: {
259
- ...$rocketstate.pseudo,
260
- ...pseudoState
261
- }
262
- });
263
- return /* @__PURE__ */ jsx(LocalProvider, {
264
- value: updatedState,
265
- children: /* @__PURE__ */ jsx(WrappedComponent, {
266
- ...props,
267
- ...pseudoEvents,
268
- ref,
269
- $rocketstate: updatedState
270
- })
271
- });
272
- });
247
+ const RocketStyleProviderComponent = (WrappedComponent) => {
248
+ const HOC = ({ onMouseEnter, onMouseLeave, onMouseUp, onMouseDown, onFocus, onBlur, $rocketstate, ref, ...props }) => {
249
+ const { state: pseudoState, events: pseudoEvents } = usePseudoState({
250
+ onMouseEnter,
251
+ onMouseLeave,
252
+ onMouseUp,
253
+ onMouseDown,
254
+ onFocus,
255
+ onBlur
256
+ });
257
+ const updatedState = useStableValue({
258
+ ...$rocketstate,
259
+ pseudo: {
260
+ ...$rocketstate.pseudo,
261
+ ...pseudoState
262
+ }
263
+ });
264
+ return /* @__PURE__ */ jsx(LocalProvider, {
265
+ value: updatedState,
266
+ children: /* @__PURE__ */ jsx(WrappedComponent, {
267
+ ...props,
268
+ ...pseudoEvents,
269
+ ref,
270
+ $rocketstate: updatedState
271
+ })
272
+ });
273
+ };
274
+ return HOC;
275
+ };
273
276
 
274
277
  //#endregion
275
278
  //#region src/utils/attrs.ts
@@ -329,27 +332,30 @@ const calculateStylingAttrs = ({ useBooleans, multiKeys }) => ({ props, dimensio
329
332
  const rocketStyleHOC = ({ inversed, attrs, priorityAttrs }) => {
330
333
  const calculateAttrs = calculateChainOptions(attrs);
331
334
  const calculatePriorityAttrs = calculateChainOptions(priorityAttrs);
332
- const Enhanced = (WrappedComponent) => forwardRef((props, ref) => {
333
- const { theme, mode, isDark, isLight } = useThemeAttrs({ inversed });
334
- const callbackParams = [theme, {
335
- render,
336
- mode,
337
- isDark,
338
- isLight
339
- }];
340
- const filteredProps = removeUndefinedProps(props);
341
- const prioritizedAttrs = calculatePriorityAttrs([filteredProps, ...callbackParams]);
342
- const finalAttrs = calculateAttrs([{
343
- ...prioritizedAttrs,
344
- ...filteredProps
345
- }, ...callbackParams]);
346
- return /* @__PURE__ */ jsx(WrappedComponent, {
347
- $rocketstyleRef: ref,
348
- ...prioritizedAttrs,
349
- ...finalAttrs,
350
- ...filteredProps
351
- });
352
- });
335
+ const Enhanced = (WrappedComponent) => {
336
+ const HOC = ({ ref, ...props }) => {
337
+ const { theme, mode, isDark, isLight } = useThemeAttrs({ inversed });
338
+ const callbackParams = [theme, {
339
+ render,
340
+ mode,
341
+ isDark,
342
+ isLight
343
+ }];
344
+ const filteredProps = removeUndefinedProps(props);
345
+ const prioritizedAttrs = calculatePriorityAttrs([filteredProps, ...callbackParams]);
346
+ const finalAttrs = calculateAttrs([{
347
+ ...prioritizedAttrs,
348
+ ...filteredProps
349
+ }, ...callbackParams]);
350
+ return /* @__PURE__ */ jsx(WrappedComponent, {
351
+ $rocketstyleRef: ref,
352
+ ...prioritizedAttrs,
353
+ ...finalAttrs,
354
+ ...filteredProps
355
+ });
356
+ };
357
+ return HOC;
358
+ };
353
359
  return Enhanced;
354
360
  };
355
361
 
@@ -471,20 +477,21 @@ const getDimensionThemes = (theme, options) => {
471
477
  }, result);
472
478
  };
473
479
  const getTheme = ({ rocketstate, themes, baseTheme, transformKeys, appTheme }) => {
474
- let finalTheme = { ...baseTheme };
480
+ const finalTheme = { ...baseTheme };
475
481
  const deferredTransforms = [];
476
482
  Object.entries(rocketstate).forEach(([key, value]) => {
477
483
  const keyTheme = themes[key];
478
484
  const isTransform = transformKeys?.[key];
479
485
  const mergeValue = (item) => {
480
486
  const val = keyTheme[item];
487
+ if (val == null) return;
481
488
  if (isTransform && typeof val === "function") deferredTransforms.push(val);
482
- else finalTheme = merge({}, finalTheme, val);
489
+ else merge(finalTheme, val);
483
490
  };
484
491
  if (Array.isArray(value)) value.forEach(mergeValue);
485
492
  else mergeValue(value);
486
493
  });
487
- for (const transform of deferredTransforms) finalTheme = merge({}, finalTheme, transform(finalTheme, appTheme ?? {}, themeModeCallback, config.css));
494
+ for (const transform of deferredTransforms) merge(finalTheme, transform(finalTheme, appTheme ?? {}, themeModeCallback, config.css));
488
495
  return finalTheme;
489
496
  };
490
497
  const getThemeByMode = (object, mode) => Object.keys(object).reduce((acc, key) => {
@@ -497,6 +504,32 @@ const getThemeByMode = (object, mode) => Object.keys(object).reduce((acc, key) =
497
504
 
498
505
  //#endregion
499
506
  //#region src/rocketstyle.tsx
507
+ /**
508
+ * Core rocketstyle component factory. Creates a fully-featured React component
509
+ * that integrates theme management (with light/dark mode support), multi-tier
510
+ * WeakMap caching, dimension-based styling props, pseudo-state detection, and
511
+ * chainable static methods (`.attrs()`, `.theme()`, `.styles()`, `.config()`, etc.).
512
+ * @module rocketstyle
513
+ */
514
+ const arraysEqual = (a, b) => {
515
+ if (a.length !== b.length) return false;
516
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
517
+ return true;
518
+ };
519
+ const isShallowEqualRocketstate = (a, b) => {
520
+ if (a === b) return true;
521
+ if (!a || !b) return false;
522
+ const aKeys = Object.keys(a);
523
+ if (aKeys.length !== Object.keys(b).length) return false;
524
+ for (const k of aKeys) {
525
+ const av = a[k];
526
+ const bv = b[k];
527
+ if (av === bv) continue;
528
+ if (Array.isArray(av) && Array.isArray(bv) && arraysEqual(av, bv)) continue;
529
+ return false;
530
+ }
531
+ return true;
532
+ };
500
533
  /** Clones the current configuration and merges new options, returning a fresh rocketComponent. */
501
534
  const cloneAndEnhance = (defaultOpts, opts) => rocketComponent({
502
535
  ...defaultOpts,
@@ -520,7 +553,7 @@ const cloneAndEnhance = (defaultOpts, opts) => rocketComponent({
520
553
  * chainable static enhancers attached to the returned component.
521
554
  */
522
555
  const rocketComponent = (options) => {
523
- const { component, styles } = options;
556
+ const { component, styles, transformKeys } = options;
524
557
  const { styled } = config;
525
558
  const _calculateStylingAttrs = calculateStylingAttrs({
526
559
  multiKeys: options.multiKeys,
@@ -533,7 +566,7 @@ const rocketComponent = (options) => {
533
566
  const RenderComponent = options.provider ? RocketStyleProviderComponent(STYLED_COMPONENT) : STYLED_COMPONENT;
534
567
  const ThemeManager$1 = new ThemeManager();
535
568
  const hocsFuncs = [rocketStyleHOC(options), ...calculateHocsFuncs(options.compose)];
536
- const EnhancedComponent = forwardRef(({ $rocketstyleRef, ...props }, ref) => {
569
+ const EnhancedComponent = ({ $rocketstyleRef, ref, ...props }) => {
537
570
  const internalRef = useRocketstyleRef({
538
571
  $rocketstyleRef,
539
572
  ref
@@ -581,20 +614,17 @@ const rocketComponent = (options) => {
581
614
  ...rocketstate,
582
615
  pseudo: pseudoRocketstate
583
616
  };
584
- let rsKey = "";
585
- for (const k in rocketstate) {
586
- const v = rocketstate[k];
587
- rsKey += `${k}=`;
588
- rsKey += `${Array.isArray(v) ? v.join(",") : v}|`;
589
- }
617
+ const rocketstateRef = useRef(rocketstate);
618
+ if (!isShallowEqualRocketstate(rocketstateRef.current, rocketstate)) rocketstateRef.current = rocketstate;
619
+ const stableRocketstate = rocketstateRef.current;
590
620
  const rocketstyle = useMemo(() => getTheme({
591
- rocketstate,
621
+ rocketstate: stableRocketstate,
592
622
  themes: currentModeThemes,
593
623
  baseTheme: currentModeBaseTheme,
594
- transformKeys: options.transformKeys,
624
+ transformKeys,
595
625
  appTheme: theme
596
626
  }), [
597
- rsKey,
627
+ stableRocketstate,
598
628
  currentModeThemes,
599
629
  currentModeBaseTheme,
600
630
  theme
@@ -626,7 +656,7 @@ const rocketComponent = (options) => {
626
656
  }
627
657
  }
628
658
  return /* @__PURE__ */ jsx(RenderComponent, { ...finalProps });
629
- });
659
+ };
630
660
  const RocketComponent = compose(...hocsFuncs)(EnhancedComponent);
631
661
  RocketComponent.IS_ROCKETSTYLE = true;
632
662
  RocketComponent.displayName = componentName;
@@ -699,32 +729,44 @@ const validateInit = (name, component, dimensions) => {
699
729
  }
700
730
  if (!isEmpty(errors)) throw Error(JSON.stringify(errors));
701
731
  };
702
- const rocketstyle = ({ dimensions = DEFAULT_DIMENSIONS, useBooleans = true } = {}) => ({ name, component }) => {
703
- if (process.env.NODE_ENV !== "production") validateInit(name, component, dimensions);
704
- return rocketComponent({
705
- name,
706
- component,
707
- useBooleans,
708
- dimensions,
709
- dimensionKeys: getKeys(dimensions),
710
- dimensionValues: getDimensionsValues(dimensions),
711
- multiKeys: getMultipleDimensions(dimensions),
712
- transformKeys: getTransformDimensions(dimensions),
713
- styled: true
714
- });
732
+ /**
733
+ * Generic implementation. The `D | DefaultDimensions` runtime fallback is
734
+ * narrowed to `D` via a single cast — semantically correct because when no
735
+ * user dimensions are supplied, `D` *is* the default (its type-parameter
736
+ * default is `DefaultDimensions`). This single boundary cast replaces the
737
+ * file-wide `@ts-nocheck` previously used here.
738
+ */
739
+ const rocketstyle = (params) => {
740
+ const dimensions = params?.dimensions ?? DEFAULT_DIMENSIONS;
741
+ const useBooleans = params?.useBooleans ?? true;
742
+ return ({ name, component }) => {
743
+ if (process.env.NODE_ENV !== "production") validateInit(name, component, dimensions);
744
+ return rocketComponent({
745
+ name,
746
+ component,
747
+ useBooleans,
748
+ dimensions,
749
+ dimensionKeys: getKeys(dimensions),
750
+ dimensionValues: getDimensionsValues(dimensions),
751
+ multiKeys: getMultipleDimensions(dimensions),
752
+ transformKeys: getTransformDimensions(dimensions),
753
+ styled: true
754
+ });
755
+ };
715
756
  };
757
+ const typedRocketstyle = rocketstyle;
716
758
 
717
759
  //#endregion
718
760
  //#region src/isRocketComponent.tsx
719
761
  const isRocketComponent = (component) => {
720
- if (component && typeof component === "object" && component !== null && Object.hasOwn(component, "IS_ROCKETSTYLE")) return true;
762
+ if (component && (typeof component === "object" || typeof component === "function") && Object.hasOwn(component, "IS_ROCKETSTYLE")) return true;
721
763
  return false;
722
764
  };
723
765
 
724
766
  //#endregion
725
767
  //#region src/index.ts
726
- var src_default = rocketstyle;
768
+ var src_default = typedRocketstyle;
727
769
 
728
770
  //#endregion
729
- export { Provider, context, src_default as default, isRocketComponent, rocketstyle };
771
+ export { Provider, context, src_default as default, isRocketComponent, typedRocketstyle as rocketstyle };
730
772
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitus-labs/rocketstyle",
3
- "version": "2.0.0-beta.0",
3
+ "version": "2.0.0-beta.1",
4
4
  "license": "MIT",
5
5
  "author": "Vit Bokisch <vit@bokisch.cz>",
6
6
  "maintainers": [
@@ -65,16 +65,15 @@
65
65
  "version": "node ../../scripts/sync-peer-deps.mjs"
66
66
  },
67
67
  "peerDependencies": {
68
- "@vitus-labs/core": "2.0.0-alpha.27",
68
+ "@vitus-labs/core": "2.0.0-beta.1",
69
69
  "react": ">= 19"
70
70
  },
71
71
  "devDependencies": {
72
- "@vitus-labs/core": "2.0.0-beta.0",
73
- "@vitus-labs/elements": "2.0.0-beta.0",
74
- "@vitus-labs/tools-rolldown": "1.10.0",
75
- "@vitus-labs/tools-storybook": "1.10.0",
76
- "@vitus-labs/tools-typescript": "1.10.0",
77
- "@vitus-labs/unistyle": "2.0.0-beta.0"
78
- },
79
- "gitHead": "dd8b9f356086ecd8bfb69c87fcad1e8bfa9ab1f4"
72
+ "@vitus-labs/core": "workspace:*",
73
+ "@vitus-labs/elements": "workspace:*",
74
+ "@vitus-labs/tools-rolldown": "2.2.0",
75
+ "@vitus-labs/tools-storybook": "2.2.0",
76
+ "@vitus-labs/tools-typescript": "2.1.0",
77
+ "@vitus-labs/unistyle": "workspace:*"
78
+ }
80
79
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2023-present Vit Bokisch
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.