@niibase/uniwind 1.5.1 → 1.6.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/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ ## What's Changed in 1.6.0
2
+
3
+
4
+
5
+ ### 🚀 Features
6
+
7
+ * export ThemeName and make themes public in Uniwind class (#460) by @Brentlok
8
+
9
+ ### 🐛 Bug Fixes
10
+
11
+ * parsing multiple transforms tokens in single class (#451) by @Brentlok
12
+
13
+ ### 🏠 Chores
14
+
15
+ * validate each entry in serialization instead of whole object (#456) by @Brentlok
16
+
17
+ ### 📦 Other
18
+
19
+ * Merge branch 'orig' by @divineniiquaye
20
+
21
+
22
+ **Full Changelog**: https://github.com/divineniiquaye/uniwind/compare/v1.5.1...v1.6.0
23
+
24
+
1
25
  ## What's Changed in 1.5.1
2
26
 
3
27
 
@@ -13,7 +13,7 @@ const SYSTEM_THEME = "system";
13
13
  const RN_VERSION = _reactNative.Platform.constants?.reactNativeVersion?.minor ?? 0;
14
14
  const UNSPECIFIED_THEME = RN_VERSION >= 82 ? "unspecified" : void 0;
15
15
  class UniwindConfigBuilder {
16
- themes = ["light", "dark"];
16
+ _themes = ["light", "dark"];
17
17
  #hasAdaptiveThemes = true;
18
18
  #currentTheme = this.colorScheme;
19
19
  constructor() {
@@ -27,6 +27,9 @@ class UniwindConfigBuilder {
27
27
  }
28
28
  });
29
29
  }
30
+ get themes() {
31
+ return this._themes;
32
+ }
30
33
  get hasAdaptiveThemes() {
31
34
  return this.#hasAdaptiveThemes;
32
35
  }
@@ -61,7 +64,7 @@ class UniwindConfigBuilder {
61
64
  }
62
65
  return;
63
66
  }
64
- if (!this.themes.includes(theme)) {
67
+ if (!this._themes.includes(theme)) {
65
68
  throw new Error(`Uniwind: You're trying to setTheme to '${theme}', but it was not registered.`);
66
69
  }
67
70
  this.#hasAdaptiveThemes = false;
@@ -89,7 +92,7 @@ class UniwindConfigBuilder {
89
92
  insets;
90
93
  }
91
94
  __reinit(_, themes) {
92
- this.themes = themes;
95
+ this._themes = themes;
93
96
  }
94
97
  onThemeChange() {}
95
98
  }
@@ -94,6 +94,15 @@ const serializeJSObject = (obj, serializer) => {
94
94
  const serializedObject = common.pipe(obj)(
95
95
  Object.entries,
96
96
  (entries) => entries.map(([key, value]) => serializer(key, serialize(value))),
97
+ (serializedValues) => serializedValues.filter((serializedValue) => {
98
+ try {
99
+ new Function(`function validateJS() { const obj = ({ ${serializedValue} }) }`);
100
+ return true;
101
+ } catch {
102
+ stringifyThemes.Logger.error(`Failed to serialize ${serializedValue} as a valid JS object entry. Skipping.`);
103
+ return false;
104
+ }
105
+ }),
97
106
  (entries) => entries.join(","),
98
107
  (result) => {
99
108
  if (result === "") {
@@ -102,12 +111,6 @@ const serializeJSObject = (obj, serializer) => {
102
111
  return `${result},`;
103
112
  }
104
113
  );
105
- try {
106
- new Function(`function validateJS() { const obj = ({ ${serializedObject} }) }`);
107
- } catch {
108
- stringifyThemes.Logger.error("Failed to serialize javascript object");
109
- return "";
110
- }
111
114
  return serializedObject;
112
115
  };
113
116
 
@@ -842,6 +845,12 @@ class CSS {
842
845
  if (declarationValue.length === 1) {
843
846
  return this.processValue(declarationValue[0]);
844
847
  }
848
+ if (this.isTransformArray(declarationValue)) {
849
+ return declarationValue.flatMap((value) => {
850
+ const result = this.processValue(value);
851
+ return Array.isArray(result) ? result : [result];
852
+ });
853
+ }
845
854
  return this.addComaBetweenTokens(declarationValue).reduce((acc, value, index, array) => {
846
855
  if (typeof value === "object") {
847
856
  const nextValue = array.at(index + 1);
@@ -949,6 +958,31 @@ class CSS {
949
958
  this.logUnsupported(`Unsupported value - ${JSON.stringify(declarationValue)}`);
950
959
  return void 0;
951
960
  }
961
+ // eslint-disable-next-line @typescript-eslint/member-ordering
962
+ static TRANSFORM_TYPES = /* @__PURE__ */ new Set([
963
+ "translate",
964
+ "translateX",
965
+ "translateY",
966
+ "translateZ",
967
+ "rotate",
968
+ "rotateX",
969
+ "rotateY",
970
+ "rotateZ",
971
+ "scale",
972
+ "scaleX",
973
+ "scaleY",
974
+ "scaleZ",
975
+ "skew",
976
+ "skewX",
977
+ "skewY",
978
+ "matrix",
979
+ "perspective"
980
+ ]);
981
+ isTransformArray(values) {
982
+ return values.every(
983
+ (value) => typeof value === "object" && value !== null && "type" in value && CSS.TRANSFORM_TYPES.has(value.type)
984
+ );
985
+ }
952
986
  isOverflow(value) {
953
987
  return typeof value === "object" && "x" in value && ["hidden", "visible"].includes(value.x);
954
988
  }
@@ -87,6 +87,15 @@ const serializeJSObject = (obj, serializer) => {
87
87
  const serializedObject = pipe(obj)(
88
88
  Object.entries,
89
89
  (entries) => entries.map(([key, value]) => serializer(key, serialize(value))),
90
+ (serializedValues) => serializedValues.filter((serializedValue) => {
91
+ try {
92
+ new Function(`function validateJS() { const obj = ({ ${serializedValue} }) }`);
93
+ return true;
94
+ } catch {
95
+ Logger.error(`Failed to serialize ${serializedValue} as a valid JS object entry. Skipping.`);
96
+ return false;
97
+ }
98
+ }),
90
99
  (entries) => entries.join(","),
91
100
  (result) => {
92
101
  if (result === "") {
@@ -95,12 +104,6 @@ const serializeJSObject = (obj, serializer) => {
95
104
  return `${result},`;
96
105
  }
97
106
  );
98
- try {
99
- new Function(`function validateJS() { const obj = ({ ${serializedObject} }) }`);
100
- } catch {
101
- Logger.error("Failed to serialize javascript object");
102
- return "";
103
- }
104
107
  return serializedObject;
105
108
  };
106
109
 
@@ -835,6 +838,12 @@ class CSS {
835
838
  if (declarationValue.length === 1) {
836
839
  return this.processValue(declarationValue[0]);
837
840
  }
841
+ if (this.isTransformArray(declarationValue)) {
842
+ return declarationValue.flatMap((value) => {
843
+ const result = this.processValue(value);
844
+ return Array.isArray(result) ? result : [result];
845
+ });
846
+ }
838
847
  return this.addComaBetweenTokens(declarationValue).reduce((acc, value, index, array) => {
839
848
  if (typeof value === "object") {
840
849
  const nextValue = array.at(index + 1);
@@ -942,6 +951,31 @@ class CSS {
942
951
  this.logUnsupported(`Unsupported value - ${JSON.stringify(declarationValue)}`);
943
952
  return void 0;
944
953
  }
954
+ // eslint-disable-next-line @typescript-eslint/member-ordering
955
+ static TRANSFORM_TYPES = /* @__PURE__ */ new Set([
956
+ "translate",
957
+ "translateX",
958
+ "translateY",
959
+ "translateZ",
960
+ "rotate",
961
+ "rotateX",
962
+ "rotateY",
963
+ "rotateZ",
964
+ "scale",
965
+ "scaleX",
966
+ "scaleY",
967
+ "scaleZ",
968
+ "skew",
969
+ "skewX",
970
+ "skewY",
971
+ "matrix",
972
+ "perspective"
973
+ ]);
974
+ isTransformArray(values) {
975
+ return values.every(
976
+ (value) => typeof value === "object" && value !== null && "type" in value && CSS.TRANSFORM_TYPES.has(value.type)
977
+ );
978
+ }
945
979
  isOverflow(value) {
946
980
  return typeof value === "object" && "x" in value && ["hidden", "visible"].includes(value.x);
947
981
  }
@@ -5,8 +5,9 @@ import { CSSVariables, GenerateStyleSheetsCallback, ThemeName } from '../types';
5
5
  declare const SYSTEM_THEME: "system";
6
6
  export declare class UniwindConfigBuilder {
7
7
  #private;
8
- protected themes: string[];
8
+ protected _themes: string[];
9
9
  constructor();
10
+ get themes(): Array<ThemeName>;
10
11
  get hasAdaptiveThemes(): boolean;
11
12
  get currentTheme(): ThemeName;
12
13
  private get colorScheme();
@@ -7,7 +7,7 @@ const SYSTEM_THEME = "system";
7
7
  const RN_VERSION = Platform.constants?.reactNativeVersion?.minor ?? 0;
8
8
  const UNSPECIFIED_THEME = RN_VERSION >= 82 ? "unspecified" : void 0;
9
9
  export class UniwindConfigBuilder {
10
- themes = ["light", "dark"];
10
+ _themes = ["light", "dark"];
11
11
  #hasAdaptiveThemes = true;
12
12
  #currentTheme = this.colorScheme;
13
13
  constructor() {
@@ -21,6 +21,9 @@ export class UniwindConfigBuilder {
21
21
  }
22
22
  });
23
23
  }
24
+ get themes() {
25
+ return this._themes;
26
+ }
24
27
  get hasAdaptiveThemes() {
25
28
  return this.#hasAdaptiveThemes;
26
29
  }
@@ -52,7 +55,7 @@ export class UniwindConfigBuilder {
52
55
  }
53
56
  return;
54
57
  }
55
- if (!this.themes.includes(theme)) {
58
+ if (!this._themes.includes(theme)) {
56
59
  throw new Error(`Uniwind: You're trying to setTheme to '${theme}', but it was not registered.`);
57
60
  }
58
61
  this.#hasAdaptiveThemes = false;
@@ -81,7 +84,7 @@ export class UniwindConfigBuilder {
81
84
  insets;
82
85
  }
83
86
  __reinit(_, themes) {
84
- this.themes = themes;
87
+ this._themes = themes;
85
88
  }
86
89
  onThemeChange() {
87
90
  }
@@ -1,5 +1,6 @@
1
1
  export * from './components/ScopedTheme';
2
2
  export { Uniwind } from './core';
3
+ export type { ThemeName } from './core/types';
3
4
  export { withUniwind } from './hoc';
4
5
  export type { ApplyUniwind, ApplyUniwindOptions } from './hoc/types';
5
6
  export { useCSSVariable, useResolveClassNames, useUniwind } from './hooks';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@niibase/uniwind",
4
- "version": "1.5.1",
4
+ "version": "1.6.0",
5
5
  "description": "A fork of Uniwind with Reanimated 4 support",
6
6
  "homepage": "https://uniwind.dev",
7
7
  "author": "Unistack",
@@ -121,7 +121,7 @@
121
121
  "ts-jest": "29.4.6",
122
122
  "typescript": "catalog:",
123
123
  "unbuild": "3.6.1",
124
- "vite": "7.3.1",
124
+ "vite": "catalog:",
125
125
  "esbuild": "0.27.3"
126
126
  }
127
127
  }
@@ -4,7 +4,7 @@ import { StyleDependency } from '../../types'
4
4
  import './metro-injected'
5
5
 
6
6
  type UniwindWithThemes = {
7
- themes: typeof Uniwind['themes']
7
+ themes: typeof Uniwind['_themes']
8
8
  }
9
9
 
10
10
  const addClassNameToRoot = () => {
@@ -13,7 +13,7 @@ const RN_VERSION = Platform.constants?.reactNativeVersion?.minor ?? 0
13
13
  const UNSPECIFIED_THEME = RN_VERSION >= 82 ? 'unspecified' : undefined
14
14
 
15
15
  export class UniwindConfigBuilder {
16
- protected themes = ['light', 'dark']
16
+ protected _themes = ['light', 'dark']
17
17
  #hasAdaptiveThemes = true
18
18
  #currentTheme = this.colorScheme as ThemeName
19
19
 
@@ -33,6 +33,10 @@ export class UniwindConfigBuilder {
33
33
  })
34
34
  }
35
35
 
36
+ get themes() {
37
+ return this._themes as Array<ThemeName>
38
+ }
39
+
36
40
  get hasAdaptiveThemes() {
37
41
  return this.#hasAdaptiveThemes
38
42
  }
@@ -77,7 +81,7 @@ export class UniwindConfigBuilder {
77
81
  return
78
82
  }
79
83
 
80
- if (!this.themes.includes(theme)) {
84
+ if (!this._themes.includes(theme)) {
81
85
  throw new Error(`Uniwind: You're trying to setTheme to '${theme}', but it was not registered.`)
82
86
  }
83
87
 
@@ -116,7 +120,7 @@ export class UniwindConfigBuilder {
116
120
  }
117
121
 
118
122
  protected __reinit(_: GenerateStyleSheetsCallback, themes: Array<string>) {
119
- this.themes = themes
123
+ this._themes = themes
120
124
  }
121
125
 
122
126
  protected onThemeChange() {
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './components/ScopedTheme'
2
2
  export { Uniwind } from './core'
3
+ export type { ThemeName } from './core/types'
3
4
  export { withUniwind } from './hoc'
4
5
  export type { ApplyUniwind, ApplyUniwindOptions } from './hoc/types'
5
6
  export { useCSSVariable, useResolveClassNames, useUniwind } from './hooks'
@@ -434,6 +434,14 @@ export class CSS {
434
434
  return this.processValue(declarationValue[0]!)
435
435
  }
436
436
 
437
+ if (this.isTransformArray(declarationValue)) {
438
+ return declarationValue.flatMap(value => {
439
+ const result = this.processValue(value)
440
+
441
+ return Array.isArray(result) ? result : [result]
442
+ })
443
+ }
444
+
437
445
  return this.addComaBetweenTokens(declarationValue).reduce<string | number>((acc, value, index, array) => {
438
446
  if (typeof value === 'object') {
439
447
  const nextValue = array.at(index + 1)
@@ -580,6 +588,33 @@ export class CSS {
580
588
  return undefined
581
589
  }
582
590
 
591
+ // eslint-disable-next-line @typescript-eslint/member-ordering
592
+ private static readonly TRANSFORM_TYPES = new Set([
593
+ 'translate',
594
+ 'translateX',
595
+ 'translateY',
596
+ 'translateZ',
597
+ 'rotate',
598
+ 'rotateX',
599
+ 'rotateY',
600
+ 'rotateZ',
601
+ 'scale',
602
+ 'scaleX',
603
+ 'scaleY',
604
+ 'scaleZ',
605
+ 'skew',
606
+ 'skewX',
607
+ 'skewY',
608
+ 'matrix',
609
+ 'perspective',
610
+ ])
611
+
612
+ private isTransformArray(values: Array<any>) {
613
+ return values.every(
614
+ value => typeof value === 'object' && value !== null && 'type' in value && CSS.TRANSFORM_TYPES.has(value.type),
615
+ )
616
+ }
617
+
583
618
  private isOverflow(value: any): value is { x: OverflowKeyword; y: OverflowKeyword } {
584
619
  return typeof value === 'object' && 'x' in value && ['hidden', 'visible'].includes(value.x)
585
620
  }
@@ -100,6 +100,19 @@ export const serializeJSObject = (obj: Record<string, any>, serializer: (key: st
100
100
  const serializedObject = pipe(obj)(
101
101
  Object.entries,
102
102
  entries => entries.map(([key, value]) => serializer(key, serialize(value))),
103
+ serializedValues =>
104
+ serializedValues.filter(serializedValue => {
105
+ try {
106
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func
107
+ new Function(`function validateJS() { const obj = ({ ${serializedValue} }) }`)
108
+
109
+ return true
110
+ } catch {
111
+ Logger.error(`Failed to serialize ${serializedValue} as a valid JS object entry. Skipping.`)
112
+
113
+ return false
114
+ }
115
+ }),
103
116
  entries => entries.join(','),
104
117
  result => {
105
118
  if (result === '') {
@@ -110,13 +123,5 @@ export const serializeJSObject = (obj: Record<string, any>, serializer: (key: st
110
123
  },
111
124
  )
112
125
 
113
- try {
114
- // eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func
115
- new Function(`function validateJS() { const obj = ({ ${serializedObject} }) }`)
116
- } catch {
117
- Logger.error('Failed to serialize javascript object')
118
- return ''
119
- }
120
-
121
126
  return serializedObject
122
127
  }