@vitus-labs/rocketstories 0.54.0 → 0.57.0-alpha.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.
@@ -1,54 +1,89 @@
1
- import { isEmpty, config, pick, omit, compose, renderContent, merge, context as context$1, set, get, htmlTags } from '@vitus-labs/core';
2
- import React, { createContext, forwardRef, useMemo, useRef, useImperativeHandle, useContext as useContext$1, useState, useCallback, createElement, Fragment } from 'react';
1
+ import { isEmpty, pick, omit, compose, render, context as context$2, set, merge, config, get, htmlTags } from '@vitus-labs/core';
2
+ import React, { createContext, forwardRef, useMemo, useContext as useContext$1, useState, useCallback, useRef, useImperativeHandle, createElement, Fragment } from 'react';
3
3
  import hoistNonReactStatics from 'hoist-non-react-statics';
4
4
  import { Element, List } from '@vitus-labs/elements';
5
5
  import { styles } from '@vitus-labs/unistyle';
6
6
 
7
+ const PSEUDO_KEYS = ['hover', 'active', 'focus', 'pressed'];
8
+ const THEME_MODES = {
9
+ light: true,
10
+ dark: true,
11
+ };
12
+ const THEME_MODES_INVERSED = {
13
+ dark: 'light',
14
+ light: 'dark',
15
+ };
16
+ const CONFIG_KEYS = [
17
+ 'provider',
18
+ 'consumer',
19
+ 'DEBUG',
20
+ 'name',
21
+ 'component',
22
+ 'inversed',
23
+ 'passProps',
24
+ 'styled',
25
+ ];
26
+ const STYLING_KEYS = ['theme', 'attrs', 'styles'];
27
+ const STATIC_KEYS = [...STYLING_KEYS, 'compose'];
28
+ const ALL_RESERVED_KEYS = [
29
+ ...Object.keys(THEME_MODES),
30
+ ...CONFIG_KEYS,
31
+ ...STATIC_KEYS,
32
+ ];
33
+
34
+ const context$1 = createContext({});
35
+ const useLocalContext = (consumer) => {
36
+ const ctx = consumer ? useContext$1(context$1) : {};
37
+ const result = consumer ? consumer((callback) => callback(ctx)) : {};
38
+ return { pseudo: {}, ...result };
39
+ };
40
+ const LocalProvider = context$1.Provider;
41
+
7
42
  const handleEvent = (e) => {
8
43
  e.preventDefault();
9
44
  e.stopPropagation();
10
45
  };
11
- const usePseudoState = (props) => {
46
+ const usePseudoState = ({ onBlur, onFocus, onMouseDown, onMouseEnter, onMouseLeave, onMouseUp, }) => {
12
47
  const [hover, setHover] = useState(false);
13
48
  const [focus, setFocus] = useState(false);
14
49
  const [pressed, setPressed] = useState(false);
15
- const onMouseEnter = useCallback((e) => {
50
+ const handleOnMouseEnter = useCallback((e) => {
16
51
  handleEvent(e);
17
52
  setHover(true);
18
- if (props.onMouseEnter)
19
- props.onMouseEnter(e);
20
- }, [props.onMouseEnter]);
21
- const onMouseLeave = useCallback((e) => {
53
+ if (onMouseEnter)
54
+ onMouseEnter(e);
55
+ }, [onMouseEnter]);
56
+ const handleOnMouseLeave = useCallback((e) => {
22
57
  handleEvent(e);
23
58
  setHover(false);
24
59
  setPressed(false);
25
- if (props.onMouseLeave)
26
- props.onMouseLeave(e);
27
- }, [props.onMouseLeave]);
28
- const onMouseDown = useCallback((e) => {
60
+ if (onMouseLeave)
61
+ onMouseLeave(e);
62
+ }, [onMouseLeave]);
63
+ const handleOnMouseDown = useCallback((e) => {
29
64
  handleEvent(e);
30
65
  setPressed(true);
31
- if (props.onMouseDown)
32
- props.onMouseDown(e);
33
- }, [props.onMouseDown]);
34
- const onMouseUp = useCallback((e) => {
66
+ if (onMouseDown)
67
+ onMouseDown(e);
68
+ }, [onMouseDown]);
69
+ const handleOnMouseUp = useCallback((e) => {
35
70
  handleEvent(e);
36
71
  setPressed(false);
37
- if (props.onMouseUp)
38
- props.onMouseUp(e);
39
- }, [props.onMouseUp]);
40
- const onFocus = useCallback((e) => {
72
+ if (onMouseUp)
73
+ onMouseUp(e);
74
+ }, [onMouseUp]);
75
+ const handleOnFocus = useCallback((e) => {
41
76
  handleEvent(e);
42
77
  setFocus(true);
43
- if (props.onFocus)
44
- props.onFocus(e);
45
- }, [props.onFocus]);
46
- const onBlur = useCallback((e) => {
78
+ if (onFocus)
79
+ onFocus(e);
80
+ }, [onFocus]);
81
+ const handleOnBlur = useCallback((e) => {
47
82
  handleEvent(e);
48
83
  setFocus(false);
49
- if (props.onBlur)
50
- props.onBlur(e);
51
- }, [props.onBlur]);
84
+ if (onBlur)
85
+ onBlur(e);
86
+ }, [onBlur]);
52
87
  return {
53
88
  state: {
54
89
  hover,
@@ -56,206 +91,69 @@ const usePseudoState = (props) => {
56
91
  pressed,
57
92
  },
58
93
  events: {
59
- onMouseEnter,
60
- onMouseLeave,
61
- onMouseDown,
62
- onMouseUp,
63
- onFocus,
64
- onBlur,
94
+ onMouseEnter: handleOnMouseEnter,
95
+ onMouseLeave: handleOnMouseLeave,
96
+ onMouseDown: handleOnMouseDown,
97
+ onMouseUp: handleOnMouseUp,
98
+ onFocus: handleOnFocus,
99
+ onBlur: handleOnBlur,
65
100
  },
66
101
  };
67
102
  };
68
103
 
69
- /* eslint-disable import/prefer-default-export */
70
- const chainOptions = (opts, defaultOpts = []) => {
71
- const result = [...defaultOpts];
72
- if (typeof opts === 'function')
73
- result.push(opts);
74
- else if (typeof opts === 'object')
75
- result.push(() => opts);
76
- return result;
77
- };
78
- const removeNullableValues = (obj) => Object.entries(obj)
79
- .filter(([, v]) => v != null && v !== false)
80
- .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});
81
-
82
- const isValidKey = (value) => value !== undefined && value !== null && value !== false;
83
- const isMultiKey = (value) => {
84
- if (typeof value === 'object')
85
- return [true, get(value, 'propName')];
86
- return [false, value];
87
- };
88
- const calculateDimensionsMap = ({ themes, useBooleans, }) => {
89
- const result = { keysMap: {}, keywords: {} };
90
- if (isEmpty(themes))
91
- return result;
92
- return Object.entries(themes).reduce((accumulator, [key, value]) => {
93
- const { keysMap, keywords } = accumulator;
94
- keywords[key] = true;
95
- Object.entries(value).forEach(([itemKey, itemValue]) => {
96
- if (!isValidKey(itemValue))
97
- return;
98
- if (useBooleans) {
99
- keywords[itemKey] = true;
100
- }
101
- set(keysMap, [key, itemKey], true);
102
- });
103
- return accumulator;
104
- }, result);
105
- };
106
- const getKeys = (obj) => Object.keys(obj);
107
- const getValues = (obj) => Object.values(obj);
108
- const getDimensionsValues = (obj) => getValues(obj).map((item) => {
109
- if (typeof item === 'object') {
110
- return item.propName;
111
- }
112
- return item;
113
- });
114
- const getMultipleDimensions = (obj) => getValues(obj).reduce((accumulator, value) => {
115
- if (typeof value === 'object') {
116
- // eslint-disable-next-line no-param-reassign
117
- if (value.multi === true)
118
- accumulator[value.propName] = true;
119
- }
120
- return accumulator;
121
- }, {});
122
-
123
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
124
- // --------------------------------------------------------
125
- // theme mode callback
126
- // --------------------------------------------------------
127
- const themeModeCb = (...params) => (mode) => {
128
- if (!mode || mode === 'light')
129
- return params[0];
130
- return params[1];
131
- };
132
- const calculateDimensionThemes = (theme, options, cb) => {
133
- const result = {};
134
- if (isEmpty(options.dimensions))
135
- return result;
136
- return Object.entries(options.dimensions).reduce((accumulator, [key, value]) => {
137
- const [, dimension] = isMultiKey(value);
138
- const helper = options[key];
139
- if (Array.isArray(helper) && helper.length > 0) {
140
- const finalDimensionThemes = calculateChainOptions$1(helper, [
141
- theme,
142
- cb,
143
- config.css,
144
- ]);
145
- // eslint-disable-next-line no-param-reassign
146
- accumulator[dimension] = removeNullableValues(finalDimensionThemes);
147
- }
148
- return accumulator;
149
- }, result);
150
- };
151
- const calculateChainOptions$1 = (options, args) => {
152
- const result = {};
153
- if (isEmpty(options))
154
- return result;
155
- return options.reduce((acc, item) => merge(acc, item(...args)), result);
156
- // using this does not allow overriding themes properly
157
- // return removeAllEmptyValues(helper)
158
- };
159
- const calculateTheme = ({ rocketstate, themes, baseTheme, }) => {
160
- // generate final theme which will be passed to styled component
161
- let finalTheme = { ...baseTheme };
162
- Object.entries(rocketstate).forEach(([key, value]) => {
163
- const keyTheme = themes[key];
164
- if (Array.isArray(value)) {
165
- value.forEach((item) => {
166
- finalTheme = merge({}, finalTheme, keyTheme[item]);
167
- });
168
- }
169
- else {
170
- finalTheme = merge({}, finalTheme, keyTheme[value]);
171
- }
172
- });
173
- return finalTheme;
174
- };
175
- const calculateThemeMode = (themes, variant) => {
176
- const callback = themeModeCb().toString();
177
- const isModeCallback = (value) => value.toString() === callback;
178
- const result = {};
179
- Object.entries(themes).forEach(([key, value]) => {
180
- if (typeof value === 'object' && value !== null) {
181
- result[key] = calculateThemeMode(value, variant);
182
- }
183
- else if (typeof value === 'function' && isModeCallback(value)) {
184
- result[key] = value(variant);
185
- }
186
- else {
187
- result[key] = value;
188
- }
189
- });
190
- return result;
191
- };
192
-
193
- const useTheme = ({ theme, options, cb }) => {
194
- const themes = calculateDimensionThemes(theme, options, cb);
195
- const { keysMap, keywords } = calculateDimensionsMap({
196
- themes,
197
- useBooleans: options.useBooleans,
198
- });
199
- // eslint-disable-next-line no-underscore-dangle
200
- const __ROCKETSTYLE__ = {
201
- dimensions: keysMap,
202
- reservedPropNames: keywords,
203
- baseTheme: calculateChainOptions$1(options.theme, [theme, cb, config.css]),
204
- themes,
205
- };
206
- return __ROCKETSTYLE__;
104
+ const useRocketstyleRef = ({ $rocketstyleRef, ref }) => {
105
+ const internalRef = useRef(null);
106
+ useImperativeHandle($rocketstyleRef, () => internalRef.current);
107
+ useImperativeHandle(ref, () => internalRef.current);
108
+ return internalRef;
207
109
  };
208
110
 
209
- const PSEUDO_KEYS = ['hover', 'active', 'focus', 'pressed'];
210
- const THEME_MODES = {
211
- light: true,
212
- dark: true,
213
- };
214
- const THEME_MODES_INVERSED = {
215
- dark: 'light',
216
- light: 'dark',
217
- };
218
- const CONFIG_KEYS = [
219
- 'provider',
220
- 'consumer',
221
- 'DEBUG',
222
- 'name',
223
- 'component',
224
- 'inversed',
225
- 'passProps',
226
- 'styled',
227
- ];
228
- const STYLING_KEYS = ['theme', 'attrs', 'styles'];
229
- const STATIC_KEYS = [...STYLING_KEYS, 'compose'];
230
- const ALL_RESERVED_KEYS = [
231
- ...Object.keys(THEME_MODES),
232
- ...CONFIG_KEYS,
233
- ...STATIC_KEYS,
234
- ];
235
-
236
- const useThemeOptions = ({ inversed }) => {
237
- const { theme, mode: ctxMode, isDark: ctxDark } = useContext$1(context$1);
111
+ const useThemeAttrs = ({ inversed }) => {
112
+ const { theme, mode: ctxMode = 'light', isDark: ctxDark, } = useContext$1(context$2) || {};
238
113
  const mode = inversed ? THEME_MODES_INVERSED[ctxMode] : ctxMode;
239
114
  const isDark = inversed ? !ctxDark : ctxDark;
240
115
  const isLight = !isDark;
241
116
  return { theme, mode, isDark, isLight };
242
117
  };
243
118
 
244
- const pickStyledProps = (props, keywords) => {
245
- const result = {};
246
- Object.entries(props).forEach(([key, value]) => {
247
- if (keywords[key])
248
- result[key] = value;
119
+ const RocketStyleProviderComponent = (WrappedComponent) => forwardRef(({ onMouseEnter, onMouseLeave, onMouseUp, onMouseDown, onFocus, onBlur, $rocketstate, ...props }, ref) => {
120
+ // pseudo hook to detect states hover / pressed / focus
121
+ const pseudo = usePseudoState({
122
+ onMouseEnter,
123
+ onMouseLeave,
124
+ onMouseUp,
125
+ onMouseDown,
126
+ onFocus,
127
+ onBlur,
249
128
  });
250
- return result;
251
- };
129
+ const updatedState = useMemo(() => ({
130
+ ...$rocketstate,
131
+ pseudo: { ...$rocketstate.pseudo, ...pseudo.state },
132
+ }), [$rocketstate, pseudo]);
133
+ return (React.createElement(LocalProvider, { value: updatedState },
134
+ React.createElement(WrappedComponent, { ...props, ...pseudo.events, ref: ref, "$rocketstate": updatedState })));
135
+ });
136
+
137
+ class ThemeManager {
138
+ baseTheme = new WeakMap();
139
+ dimensionsThemes = new WeakMap();
140
+ modeBaseTheme = { light: new WeakMap(), dark: new WeakMap() };
141
+ modeDimensionTheme = { light: new WeakMap(), dark: new WeakMap() };
142
+ }
143
+
144
+ /* eslint-disable no-param-reassign */
145
+ const pickStyledAttrs = (props, keywords) => Object.keys(props).reduce((acc, key) => {
146
+ if (keywords[key])
147
+ acc[key] = props[key];
148
+ return acc;
149
+ }, {});
252
150
  const calculateChainOptions = (options) => (args) => {
253
151
  const result = {};
254
152
  if (isEmpty(options))
255
153
  return result;
256
154
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
257
155
  // @ts-ignore
258
- return options.reduce((acc, item) => Object.assign(acc, item(...args)), result);
156
+ return options.reduce((acc, item) => Object.assign(acc, item(...args)), {});
259
157
  };
260
158
  const calculateStylingAttrs = ({ useBooleans, multiKeys }) => ({ props, dimensions }) => {
261
159
  const result = {};
@@ -316,14 +214,14 @@ const rocketStyleHOC = ({ inversed, attrs }) => {
316
214
  // --------------------------------------------------
317
215
  const _calculateChainOptions = calculateChainOptions(attrs);
318
216
  const Enhanced = (WrappedComponent) => forwardRef((props, ref) => {
319
- const { theme, mode, isDark, isLight } = useThemeOptions({
217
+ const { theme, mode, isDark, isLight } = useThemeAttrs({
320
218
  inversed,
321
219
  });
322
220
  const calculatedAttrs = _calculateChainOptions([
323
221
  props,
324
222
  theme,
325
223
  {
326
- renderContent,
224
+ render,
327
225
  mode,
328
226
  isDark,
329
227
  isLight,
@@ -334,61 +232,178 @@ const rocketStyleHOC = ({ inversed, attrs }) => {
334
232
  return Enhanced;
335
233
  };
336
234
 
337
- var localContext = createContext({});
338
-
339
- const RocketStyleProviderComponent = (WrappedComponent) => forwardRef(({ onMouseEnter, onMouseLeave, onMouseUp, onMouseDown, onFocus, onBlur, $rocketstate, ...props }, ref) => {
340
- // pseudo hook to detect states hover / pressed / focus
341
- const pseudo = usePseudoState({
342
- onMouseEnter,
343
- onMouseLeave,
344
- onMouseUp,
345
- onMouseDown,
346
- onFocus,
347
- onBlur,
235
+ const createStaticsChainingEnhancers = ({ context, dimensionKeys, func, options, }) => {
236
+ const keys = [...dimensionKeys, ...STATIC_KEYS];
237
+ keys.forEach((item) => {
238
+ // eslint-disable-next-line no-param-reassign
239
+ context[item] = (props) => func({ [item]: props }, options);
348
240
  });
349
- const updatedState = useMemo(() => ({
350
- ...$rocketstate,
351
- pseudo: { ...$rocketstate.pseudo, ...pseudo.state },
352
- }), [$rocketstate, pseudo]);
353
- return (React.createElement(localContext.Provider, { value: updatedState },
354
- React.createElement(WrappedComponent, { ...props, ...pseudo.events, ref: ref, "$rocketstate": updatedState })));
355
- });
356
-
357
- const calculateStyles = (styles, css) => {
358
- if (!styles)
359
- return [];
360
- return styles.map((item) => item(css));
241
+ };
242
+ const createStaticsEnhancers = ({ context, options, }) => {
243
+ if (!isEmpty(options)) {
244
+ Object.assign(context, options);
245
+ }
361
246
  };
362
247
 
363
- /* eslint-disable no-underscore-dangle */
364
- const orOptions = (keys, opts, defaultOpts) => keys.reduce((acc, item) => ({ ...acc, [item]: opts[item] || defaultOpts[item] }), {});
365
- const chainReservedOptions = (keys, opts, defaultOpts) => keys.reduce((acc, item) => ({
366
- ...acc,
367
- [item]: chainOptions(opts[item], defaultOpts[item]),
368
- }), {});
248
+ /* eslint-disable import/prefer-default-export */
249
+ const removeNullableValues = (obj) => Object.entries(obj)
250
+ .filter(([, v]) => v != null && v !== false)
251
+ .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});
369
252
  // --------------------------------------------------------
370
- // helpers for create statics chainin methods on component
253
+ // Remove All Empty Values
371
254
  // --------------------------------------------------------
372
- const createStaticsChainingEnhancers = ({ context, dimensionKeys, func, opts, }) => {
373
- dimensionKeys.forEach((item) => {
374
- // eslint-disable-next-line no-param-reassign
375
- context[item] = (props) => func({ [item]: props }, opts);
376
- });
255
+ // type RemoveAllEmptyValues = (obj: Record<string, any>) => Record<string, any>
256
+ // export const removeAllEmptyValues: RemoveAllEmptyValues = (obj) =>
257
+ // Object.entries(obj)
258
+ // .filter(([, v]) => v != null)
259
+ // .reduce(
260
+ // (acc, [k, v]) => ({
261
+ // ...acc,
262
+ // [k]: typeof v === 'object' ? removeAllEmptyValues(v) : v,
263
+ // }),
264
+ // {}
265
+ // )
266
+
267
+ const isValidKey = (value) => value !== undefined && value !== null && value !== false;
268
+ const isMultiKey = (value) => {
269
+ if (typeof value === 'object' && value !== null)
270
+ return [true, get(value, 'propName')];
271
+ return [false, value];
272
+ };
273
+ const getDimensionsMap = ({ themes, useBooleans }) => {
274
+ const result = {
275
+ keysMap: {},
276
+ keywords: {},
277
+ };
278
+ if (isEmpty(themes))
279
+ return result;
280
+ return Object.entries(themes).reduce((accumulator, [key, value]) => {
281
+ const { keysMap, keywords } = accumulator;
282
+ keywords[key] = true;
283
+ Object.entries(value).forEach(([itemKey, itemValue]) => {
284
+ if (!isValidKey(itemValue))
285
+ return;
286
+ if (useBooleans) {
287
+ keywords[itemKey] = true;
288
+ }
289
+ set(keysMap, [key, itemKey], true);
290
+ });
291
+ return accumulator;
292
+ }, result);
377
293
  };
294
+ const getKeys = (obj) => Object.keys(obj);
295
+ const getValues = (obj) => Object.values(obj);
296
+ const getDimensionsValues = (obj) => getValues(obj).map((item) => {
297
+ if (typeof item === 'object') {
298
+ return item.propName;
299
+ }
300
+ return item;
301
+ });
302
+ const getMultipleDimensions = (obj) => getValues(obj).reduce((accumulator, value) => {
303
+ if (typeof value === 'object') {
304
+ // eslint-disable-next-line no-param-reassign
305
+ if (value.multi === true)
306
+ accumulator[value.propName] = true;
307
+ }
308
+ return accumulator;
309
+ }, {});
310
+
311
+ /* eslint-disable no-param-reassign */
378
312
  // --------------------------------------------------------
379
- // helpers for create statics on component
313
+ // Theme Mode Callback
380
314
  // --------------------------------------------------------
381
- const createStaticsEnhancers = ({ context, opts }) => {
382
- if (!isEmpty(opts)) {
383
- Object.assign(context, opts);
315
+ const themeModeCallback = (light, dark) => (mode) => {
316
+ if (!mode || mode === 'light')
317
+ return light;
318
+ return dark;
319
+ };
320
+ themeModeCallback.isMode = true;
321
+ const isModeCallback = (value) => typeof value === 'function' && value.isMode;
322
+ const getThemeFromChain = (options, theme) => {
323
+ const result = {};
324
+ if (!options || isEmpty(options))
325
+ return result;
326
+ return options.reduce((acc, item) => merge(acc, item(theme, themeModeCallback, config.css)), result);
327
+ };
328
+ const getDimensionThemes = (theme, options) => {
329
+ const result = {};
330
+ if (isEmpty(options.dimensions))
331
+ return result;
332
+ return Object.entries(options.dimensions).reduce((acc, [key, value]) => {
333
+ const [, dimension] = isMultiKey(value);
334
+ const helper = options[key];
335
+ if (Array.isArray(helper) && helper.length > 0) {
336
+ const finalDimensionThemes = getThemeFromChain(helper, theme);
337
+ // eslint-disable-next-line no-param-reassign
338
+ acc[dimension] = removeNullableValues(finalDimensionThemes);
339
+ }
340
+ return acc;
341
+ }, result);
342
+ };
343
+ const getTheme$1 = ({ rocketstate, themes, baseTheme }) => {
344
+ // generate final theme which will be passed to styled component
345
+ let finalTheme = { ...baseTheme };
346
+ Object.entries(rocketstate).forEach(([key, value]) => {
347
+ const keyTheme = themes[key];
348
+ if (Array.isArray(value)) {
349
+ value.forEach((item) => {
350
+ finalTheme = merge({}, finalTheme, keyTheme[item]);
351
+ });
352
+ }
353
+ else {
354
+ finalTheme = merge({}, finalTheme, keyTheme[value]);
355
+ }
356
+ });
357
+ return finalTheme;
358
+ };
359
+ const getThemeByMode = (object, mode) => Object.keys(object).reduce((acc, key) => {
360
+ const value = object[key];
361
+ if (typeof value === 'object' && value !== null) {
362
+ acc[key] = getThemeByMode(value, mode);
363
+ }
364
+ else if (isModeCallback(value)) {
365
+ acc[key] = value(mode);
366
+ }
367
+ else {
368
+ acc[key] = value;
384
369
  }
370
+ return acc;
371
+ }, {});
372
+
373
+ const chainOptions = (opts, defaultOpts = []) => {
374
+ const result = [...defaultOpts];
375
+ if (typeof opts === 'function')
376
+ result.push(opts);
377
+ else if (typeof opts === 'object')
378
+ result.push(() => opts);
379
+ return result;
385
380
  };
386
- const cloneAndEnhance = (opts, defaultOpts) => styleComponent({
381
+ const chainOrOptions = (keys, opts, defaultOpts) => keys.reduce((acc, item) => ({ ...acc, [item]: opts[item] || defaultOpts[item] }), {});
382
+ const chainReservedKeyOptions = (keys, opts, defaultOpts) => keys.reduce((acc, item) => ({
383
+ ...acc,
384
+ [item]: chainOptions(opts[item], defaultOpts[item]),
385
+ }), {});
386
+
387
+ const calculateHocsFuncs = (options = {}) => Object.values(options)
388
+ .filter((item) => typeof item === 'function')
389
+ .reverse();
390
+
391
+ /* eslint-disable import/prefer-default-export */
392
+ const calculateStyles = (styles) => {
393
+ if (!styles)
394
+ return [];
395
+ return styles.map((item) => item(config.css));
396
+ };
397
+
398
+ /* eslint-disable @typescript-eslint/ban-ts-comment */
399
+ const cloneAndEnhance = (opts, defaultOpts) =>
400
+ // @ts-ignore
401
+ rocketComponent({
387
402
  ...defaultOpts,
388
403
  statics: { ...defaultOpts.statics, ...opts.statics },
389
404
  compose: { ...defaultOpts.compose, ...opts.compose },
390
- ...orOptions(CONFIG_KEYS, opts, defaultOpts),
391
- ...chainReservedOptions([...defaultOpts.dimensionKeys, ...STYLING_KEYS], opts, defaultOpts),
405
+ ...chainOrOptions(CONFIG_KEYS, opts, defaultOpts),
406
+ ...chainReservedKeyOptions([...defaultOpts.dimensionKeys, ...STYLING_KEYS], opts, defaultOpts),
392
407
  });
393
408
  // --------------------------------------------------------
394
409
  // styleComponent
@@ -397,7 +412,8 @@ const cloneAndEnhance = (opts, defaultOpts) => styleComponent({
397
412
  // assigned, so it can be even rendered as a valid component
398
413
  // or styles can be extended via its statics
399
414
  // --------------------------------------------------------
400
- const styleComponent = (options) => {
415
+ // @ts-ignore
416
+ const rocketComponent = (options) => {
401
417
  const { component, styles } = options;
402
418
  const { styled } = config;
403
419
  // const _calculateChainOptions = calculateChainOptions(options.attrs)
@@ -407,112 +423,149 @@ const styleComponent = (options) => {
407
423
  });
408
424
  const componentName = options.name || options.component.displayName || options.component.name;
409
425
  // create styled component with all options.styles if available
410
- const STYLED_COMPONENT = component.IS_ROCKETSTYLE || options.styled === false
426
+ const STYLED_COMPONENT = component.IS_ROCKETSTYLE || options.styled !== true
411
427
  ? component
412
428
  : styled(component) `
413
- ${calculateStyles(styles, config.css)};
429
+ ${calculateStyles(styles)};
414
430
  `;
415
431
  // --------------------------------------------------------
416
- // final component to be rendered
432
+ // COMPONENT - Final component to be rendered
417
433
  // --------------------------------------------------------
418
434
  const RenderComponent = options.provider
419
435
  ? RocketStyleProviderComponent(STYLED_COMPONENT)
420
436
  : STYLED_COMPONENT;
421
437
  // --------------------------------------------------------
422
- // hocs
438
+ // THEME - Cahed & Calculated theme(s)
423
439
  // --------------------------------------------------------
424
- const calculateHocsFuncs = Object.values(options.compose || {})
425
- .filter((item) => typeof item === 'function')
426
- .reverse();
427
- const hocsFuncs = [rocketStyleHOC(options), ...calculateHocsFuncs];
440
+ const ThemeManager$1 = new ThemeManager();
441
+ // --------------------------------------------------------
442
+ // COMPOSE - high-order components
443
+ // --------------------------------------------------------
444
+ const hocsFuncs = [
445
+ rocketStyleHOC(options),
446
+ ...calculateHocsFuncs(options.compose),
447
+ ];
428
448
  // --------------------------------------------------------
429
449
  // ENHANCED COMPONENT (returned component)
430
450
  // --------------------------------------------------------
431
451
  // .attrs() chaining option is calculated in HOC and passed as props already
432
- const EnhancedComponent = forwardRef(({ $rocketstyleRef, // it's forwarded from HOC which is always on top of hocs
452
+ const EnhancedComponent = forwardRef(({ $rocketstyleRef, // it's forwarded from HOC which is always on top of all hocs
433
453
  ...props }, ref) => {
434
454
  // --------------------------------------------------
435
455
  // handle refs
436
456
  // (1) one is passed from inner HOC - $rocketstyleRef
437
457
  // (2) second one is used to be used directly (e.g. inside hocs)
438
458
  // --------------------------------------------------
439
- const internalRef = useRef(null);
440
- if ($rocketstyleRef)
441
- useImperativeHandle($rocketstyleRef, () => internalRef.current, [
442
- $rocketstyleRef,
443
- ]);
444
- if (ref)
445
- useImperativeHandle(ref, () => internalRef.current, [ref]);
459
+ const internalRef = useRocketstyleRef({ $rocketstyleRef, ref });
446
460
  // --------------------------------------------------
447
461
  // hover - focus - pressed state passed via context from parent component
448
462
  // --------------------------------------------------
449
- const rocketstyleCtx = options.consumer ? useContext$1(localContext) : {};
463
+ const localCtx = useLocalContext(options.consumer);
450
464
  // --------------------------------------------------
451
465
  // general theme and theme mode dark / light passed in context
452
466
  // --------------------------------------------------
453
- const { theme, mode } = useThemeOptions(options);
467
+ const { theme, mode } = useThemeAttrs(options);
454
468
  // --------------------------------------------------
455
- // calculate themes for all possible styling dimensions
456
- // .theme(...) + defined dimensions like .states(...), .sizes(...)
469
+ // calculate themes for all defined styling dimensions
470
+ // .theme(...) + defined dimensions like .states(...), .sizes(...), etc.
457
471
  // --------------------------------------------------
458
- const __ROCKETSTYLE__ = useMemo(() => useTheme({
459
- theme,
460
- options,
461
- cb: themeModeCb,
462
- }),
463
- // recalculate this only when theme changes
472
+ // --------------------------------------------------
473
+ // BASE / DEFAULT THEME Object
474
+ // --------------------------------------------------
475
+ const baseTheme = useMemo(() => {
476
+ const helper = ThemeManager$1.baseTheme;
477
+ if (!helper.has(theme)) {
478
+ helper.set(theme, getThemeFromChain(options.theme, theme));
479
+ }
480
+ return helper.get(theme);
481
+ },
482
+ // recalculate this only when theme mode changes dark / light
483
+ [theme]);
484
+ // --------------------------------------------------
485
+ // DIMENSION(S) THEMES Object
486
+ // --------------------------------------------------
487
+ const themes = useMemo(() => {
488
+ const helper = ThemeManager$1.dimensionsThemes;
489
+ if (!helper.has(theme)) {
490
+ helper.set(theme, getDimensionThemes(theme, options));
491
+ }
492
+ return helper.get(theme);
493
+ },
494
+ // recalculate this only when theme object changes
464
495
  [theme]);
465
- const { reservedPropNames, themes: rocketThemes, dimensions, baseTheme: rocketBaseTheme, } = __ROCKETSTYLE__;
466
- const { baseTheme, themes } = useMemo(() => calculateThemeMode({ themes: rocketThemes, baseTheme: rocketBaseTheme }, mode),
496
+ // --------------------------------------------------
497
+ // BASE / DEFAULT MODE THEME Object
498
+ // --------------------------------------------------
499
+ const currentModeBaseTheme = useMemo(() => {
500
+ const helper = ThemeManager$1.modeBaseTheme[mode];
501
+ if (!helper.has(baseTheme)) {
502
+ helper.set(baseTheme, getThemeByMode(baseTheme, mode));
503
+ }
504
+ return helper.get(baseTheme);
505
+ },
506
+ // recalculate this only when theme mode changes dark / light
507
+ [mode, baseTheme]);
508
+ // --------------------------------------------------
509
+ // DIMENSION(S) MODE THEMES Object
510
+ // --------------------------------------------------
511
+ const currentModeThemes = useMemo(() => {
512
+ const helper = ThemeManager$1.modeDimensionTheme[mode];
513
+ if (!helper.has(themes)) {
514
+ helper.set(themes, getThemeByMode(themes, mode));
515
+ }
516
+ return helper.get(themes);
517
+ },
467
518
  // recalculate this only when theme mode changes dark / light
468
- [mode]);
519
+ [mode, themes]);
469
520
  // --------------------------------------------------
470
521
  // calculate reserved Keys defined in dimensions as styling keys
471
522
  // there is no need to calculate this each time - keys are based on
472
523
  // dimensions definitions
473
524
  // --------------------------------------------------
474
- const RESERVED_STYLING_PROPS_KEYS = useMemo(() => Object.keys(reservedPropNames), []);
525
+ const { keysMap: dimensions, keywords: reservedPropNames } = useMemo(() => getDimensionsMap({
526
+ themes,
527
+ useBooleans: options.useBooleans,
528
+ }), [themes]);
529
+ const RESERVED_STYLING_PROPS_KEYS = useMemo(() => Object.keys(reservedPropNames), [reservedPropNames]);
475
530
  // --------------------------------------------------
476
531
  // get final props which are (latest has the highest priority):
477
532
  // (1) merged styling from context,
478
533
  // (2) `attrs` chaining method, and from
479
534
  // (3) passing them directly to component
480
535
  // --------------------------------------------------
481
- const { pseudo = {}, ...mergeProps } = {
482
- ...(options.consumer
483
- ? options.consumer((callback) => callback(rocketstyleCtx))
484
- : {}),
536
+ const { pseudo, ...mergeProps } = {
537
+ ...localCtx,
485
538
  ...props,
486
539
  };
487
540
  // --------------------------------------------------
541
+ // pseudo rocket state
542
+ // calculate final component pseudo state including pseudo state
543
+ // from props and override by pseudo props from context
544
+ // --------------------------------------------------
545
+ const pseudoRocketstate = {
546
+ ...pseudo,
547
+ ...pick(props, PSEUDO_KEYS),
548
+ };
549
+ // --------------------------------------------------
488
550
  // rocketstate
489
551
  // calculate final component state including pseudo state
490
552
  // passed as $rocketstate prop
491
553
  // --------------------------------------------------
492
554
  const rocketstate = _calculateStylingAttrs({
493
- props: pickStyledProps(mergeProps, reservedPropNames),
555
+ props: pickStyledAttrs(mergeProps, reservedPropNames),
494
556
  dimensions,
495
557
  });
496
- // --------------------------------------------------
497
- // pseudo state
498
- // calculate final component pseudo state including pseudo state
499
- // from props and override by pseudo props from context
500
- // --------------------------------------------------
501
- const finalPseudo = {
502
- ...pick(props, PSEUDO_KEYS),
503
- ...pseudo,
504
- };
505
- const finalRocketstate = { ...rocketstate, pseudo: finalPseudo };
558
+ const finalRocketstate = { ...rocketstate, pseudo: pseudoRocketstate };
506
559
  // --------------------------------------------------
507
560
  // rocketstyle
508
561
  // calculated (based on styling props) final theme which will be passed
509
562
  // to our styled component
510
563
  // passed as $rocketstyle prop
511
564
  // --------------------------------------------------
512
- const rocketstyle = calculateTheme({
565
+ const rocketstyle = getTheme$1({
513
566
  rocketstate,
514
- themes,
515
- baseTheme,
567
+ themes: currentModeThemes,
568
+ baseTheme: currentModeBaseTheme,
516
569
  });
517
570
  // --------------------------------------------------
518
571
  // final props
@@ -550,9 +603,9 @@ const styleComponent = (options) => {
550
603
  // ------------------------------------------------------
551
604
  createStaticsChainingEnhancers({
552
605
  context: RocketComponent,
553
- dimensionKeys: [...options.dimensionKeys, ...STATIC_KEYS],
606
+ dimensionKeys: options.dimensionKeys,
554
607
  func: cloneAndEnhance,
555
- opts: options,
608
+ options,
556
609
  });
557
610
  // ------------------------------------------------------
558
611
  RocketComponent.IS_ROCKETSTYLE = true;
@@ -564,34 +617,37 @@ const styleComponent = (options) => {
564
617
  // ------------------------------------------------------
565
618
  createStaticsEnhancers({
566
619
  context: RocketComponent.is,
567
- opts: options.statics,
620
+ options: options.statics,
568
621
  });
622
+ // @ts-ignore
569
623
  RocketComponent.config = (opts = {}) => {
570
624
  const result = pick(opts, CONFIG_KEYS);
571
625
  return cloneAndEnhance(result, options);
572
626
  };
573
- RocketComponent.statics = (opts = {}) => cloneAndEnhance({ statics: opts }, options);
627
+ RocketComponent.statics = (opts) => cloneAndEnhance({ statics: opts }, options);
574
628
  RocketComponent.getStaticDimensions = (theme) => {
575
- const themes = useTheme({ theme, options, cb: themeModeCb });
629
+ const themes = getDimensionThemes(theme, options);
630
+ const { keysMap, keywords } = getDimensionsMap({
631
+ themes,
632
+ useBooleans: options.useBooleans,
633
+ });
576
634
  return {
577
- dimensions: themes.dimensions,
635
+ dimensions: keysMap,
636
+ keywords,
578
637
  useBooleans: options.useBooleans,
579
638
  multiKeys: options.multiKeys,
580
639
  };
581
640
  };
582
- RocketComponent.getDefaultAttrs = (props, theme, mode) => {
583
- const result = calculateChainOptions(options.attrs)([
584
- props,
585
- theme,
586
- {
587
- renderContent,
588
- mode,
589
- isDark: mode === 'light',
590
- isLight: mode === 'dark',
591
- },
592
- ]);
593
- return result;
594
- };
641
+ RocketComponent.getDefaultAttrs = (props, theme, mode) => calculateChainOptions(options.attrs)([
642
+ props,
643
+ theme,
644
+ {
645
+ render,
646
+ mode,
647
+ isDark: mode === 'light',
648
+ isLight: mode === 'dark',
649
+ },
650
+ ]);
595
651
  return RocketComponent;
596
652
  };
597
653
 
@@ -605,8 +661,8 @@ const DEFAULT_DIMENSIONS = {
605
661
  },
606
662
  };
607
663
 
608
- /* eslint-disable @typescript-eslint/ban-types */
609
- const rocketstyle$1 = () => ({ dimensions = DEFAULT_DIMENSIONS, useBooleans = true } = {}) => ({ name, component }) => {
664
+ // @ts-nocheck
665
+ const rocketstyle$1 = ({ dimensions = DEFAULT_DIMENSIONS, useBooleans = true } = {}) => ({ name, component }) => {
610
666
  // --------------------------------------------------------
611
667
  // handle ERRORS in development mode
612
668
  // --------------------------------------------------------
@@ -633,7 +689,7 @@ const rocketstyle$1 = () => ({ dimensions = DEFAULT_DIMENSIONS, useBooleans = tr
633
689
  throw Error(JSON.stringify(errors));
634
690
  }
635
691
  }
636
- return styleComponent({
692
+ return rocketComponent({
637
693
  name,
638
694
  component,
639
695
  useBooleans,
@@ -641,6 +697,7 @@ const rocketstyle$1 = () => ({ dimensions = DEFAULT_DIMENSIONS, useBooleans = tr
641
697
  dimensionKeys: getKeys(dimensions),
642
698
  dimensionValues: getDimensionsValues(dimensions),
643
699
  multiKeys: getMultipleDimensions(dimensions),
700
+ styled: true,
644
701
  });
645
702
  };
646
703
 
@@ -648,8 +705,7 @@ const isRocketComponent = (component) => {
648
705
  if (component &&
649
706
  typeof component === 'object' &&
650
707
  component !== null &&
651
- // eslint-disable-next-line dot-notation
652
- component['IS_ROCKETSTYLE'] === true) {
708
+ Object.prototype.hasOwnProperty.call(component, 'IS_ROCKETSTYLE')) {
653
709
  return true;
654
710
  }
655
711
  return false;
@@ -662,7 +718,7 @@ const Wrapper = config.styled.div `
662
718
  const component$2 = () => React.createElement(Wrapper, null, "Nothing here");
663
719
  component$2.displayName = '@vitus-labs/rocketstories/Empty';
664
720
 
665
- var element$1 = rocketstyle$1()()({
721
+ var element$1 = rocketstyle$1()({
666
722
  component: Element,
667
723
  name: 'element',
668
724
  })
@@ -1349,7 +1405,7 @@ const disableDimensionControls = (dimensions, dimensionName) => {
1349
1405
  const context = createContext({});
1350
1406
  const useContext = () => useContext$1(context);
1351
1407
  const ContextProvider = context.Provider;
1352
- const Provider = ({ children, ...props }) => (React.createElement(ContextProvider, { value: props }, children));
1408
+ const Provider = ({ children, ...props }) => React.createElement(ContextProvider, { value: props }, children);
1353
1409
 
1354
1410
  const component$1 = ({ title, ...props }) => {
1355
1411
  const { component } = useContext();
@@ -1652,7 +1708,7 @@ const createRocketStories = (options) => {
1652
1708
  };
1653
1709
  };
1654
1710
 
1655
- const init = ({ decorators = [], storyOptions = {} }) => (component) => rocketstories(component, { decorators, storyOptions });
1711
+ const init = ({ decorators = [], storyOptions = {}, ...rest }) => (component) => rocketstories(component, { decorators, storyOptions, ...rest });
1656
1712
  //@ts-ignore
1657
1713
  const rocketstories = (component, options = {}) => {
1658
1714
  const { decorators = [], storyOptions = {} } = options;