creactive 0.0.55 → 0.0.56

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 (60) hide show
  1. package/build/index.js +1656 -2
  2. package/package.json +6 -4
  3. package/source/components/index.ts +2 -0
  4. package/source/components/text/constants/color.ts +26 -0
  5. package/source/components/text/constants/font.ts +32 -0
  6. package/source/components/text/constants/index.ts +5 -0
  7. package/source/components/text/constants/role.ts +12 -0
  8. package/source/components/text/constants/text.ts +22 -0
  9. package/source/components/text/constants/type.ts +27 -0
  10. package/source/components/text/index.ts +2 -0
  11. package/source/components/text/spec/children.spec.tsx +13 -0
  12. package/source/components/text/spec/color.spec.native.tsx +15 -0
  13. package/source/components/text/spec/color.spec.tsx +159 -0
  14. package/source/components/text/spec/color.spec.web.tsx +15 -0
  15. package/source/components/text/spec/font.spec.tsx +196 -0
  16. package/source/components/text/spec/position.spec.tsx +15 -0
  17. package/source/components/text/spec/text.spec.native.tsx +1043 -0
  18. package/source/components/text/spec/text.spec.tsx +39 -0
  19. package/source/components/text/spec/text.spec.web.tsx +1043 -0
  20. package/source/components/text/spec/type.spec.web.tsx +55 -0
  21. package/source/components/text/text.stories.tsx +46 -0
  22. package/source/components/text/text.tsx +262 -0
  23. package/source/components/text/text.types.ts +67 -0
  24. package/source/constants/index.ts +46 -0
  25. package/source/constants/theme/color.ts +27 -0
  26. package/source/constants/theme/font.ts +48 -0
  27. package/source/constants/theme/index.ts +50 -0
  28. package/source/constants/theme/text.ts +12 -0
  29. package/source/contexts/index.ts +15 -0
  30. package/source/contexts/media/components/index.ts +4 -0
  31. package/source/contexts/media/components/media/index.ts +2 -0
  32. package/source/contexts/media/components/media/media.tsx +37 -0
  33. package/source/contexts/media/components/media/media.types.ts +26 -0
  34. package/source/contexts/media/components/wrapper/index.ts +2 -0
  35. package/source/contexts/media/components/wrapper/wrapper.tsx +73 -0
  36. package/source/contexts/media/components/wrapper/wrapper.types.ts +3 -0
  37. package/source/contexts/media/constants/breakpoint.ts +18 -0
  38. package/source/contexts/media/constants/index.ts +6 -0
  39. package/source/contexts/media/hooks/index.ts +1 -0
  40. package/source/contexts/media/hooks/use-breakpoint.ts +18 -0
  41. package/source/contexts/media/index.ts +7 -0
  42. package/source/contexts/media/media.tsx +36 -0
  43. package/source/contexts/media/media.types.ts +38 -0
  44. package/source/contexts/theme/index.ts +8 -0
  45. package/source/contexts/theme/theme.tsx +280 -0
  46. package/source/contexts/theme/theme.types.ts +284 -0
  47. package/source/helpers/index.ts +3 -0
  48. package/source/helpers/storybook/constants/control.ts +25 -0
  49. package/source/helpers/storybook/constants/index.ts +1 -0
  50. package/source/helpers/storybook/control.spec.ts +140 -0
  51. package/source/helpers/storybook/control.ts +115 -0
  52. package/source/helpers/storybook/index.ts +1 -0
  53. package/source/helpers/style/index.ts +2 -0
  54. package/source/helpers/style/style.spec.web.ts +20 -0
  55. package/source/helpers/style/style.ts +14 -0
  56. package/source/helpers/style/style.types.ts +14 -0
  57. package/source/hooks/index.ts +1 -0
  58. package/source/hooks/use-theme-style-sheet.ts +135 -0
  59. package/source/index.ts +24 -0
  60. package/build/index.js.LICENSE.txt +0 -9
@@ -0,0 +1,284 @@
1
+ import type { FunctionComponent, PropsWithChildren } from 'react'
2
+
3
+ /**
4
+ * Theme RGB color type.
5
+ * Should be used to specify theme colors.
6
+ * Number instead of 0-255 union to avoid too complex union type.
7
+ */
8
+ export type ThemeColorRGB = `rgb(${number},${number},${number})`
9
+
10
+ /**
11
+ * Theme font weight type.
12
+ * Should be used to specify theme font weight.
13
+ */
14
+ export type ThemeFontWeight =
15
+ | 100
16
+ | 200
17
+ | 300
18
+ | 400
19
+ | 500
20
+ | 600
21
+ | 700
22
+ | 800
23
+ | 900
24
+
25
+ /**
26
+ * Theme context value interface.
27
+ * Contains all theme tokens you may need.
28
+ * This tokens are used inside components for styling.
29
+ * This tokens can be also accesed via theme context outside.
30
+ */
31
+ export interface ThemeContextValue {
32
+ /**
33
+ * Base foreground 100 color token.
34
+ * The least contrasting color in the foreground palette.
35
+ * Intended for nearly invisible elements.
36
+ */
37
+ colorForegroundBase100: ThemeColorRGB
38
+ /**
39
+ * Base foreground 200 color token.
40
+ * Still meant to be barely visible.
41
+ * Can help create a subtle sense of hierarchy.
42
+ */
43
+ colorForegroundBase200: ThemeColorRGB
44
+ /**
45
+ * Base foreground 300 color token.
46
+ * Suitable for slightly readable text or elements.
47
+ */
48
+ colorForegroundBase300: ThemeColorRGB
49
+ /**
50
+ * Base foreground 400 color token.
51
+ * A secondary color for secondary elements.
52
+ * If a secondary element has multiple levels, this is for the lower one.
53
+ */
54
+ colorForegroundBase400: ThemeColorRGB
55
+ /**
56
+ * Base foreground 500 color token.
57
+ * Also useful for secondary elements on low-contrast backgrounds.
58
+ */
59
+ colorForegroundBase500: ThemeColorRGB
60
+ /**
61
+ * Base foreground 600 color token.
62
+ * Ideal for secondary elements and less prominent text.
63
+ */
64
+ colorForegroundBase600: ThemeColorRGB
65
+ /**
66
+ * Base foreground 700 color token.
67
+ * Used for default elements on higher contrast backgrounds.
68
+ * Also suitable for slightly subdued elements.
69
+ */
70
+ colorForegroundBase700: ThemeColorRGB
71
+ /**
72
+ * Base foreground 800 color token.
73
+ * The default value for the text component.
74
+ * Ideal for high-contrast text and key elements.
75
+ */
76
+ colorForegroundBase800: ThemeColorRGB
77
+ /**
78
+ * Base foreground 900 color token.
79
+ * Similar to 800 but better suited for lower-contrast backgrounds.
80
+ */
81
+ colorForegroundBase900: ThemeColorRGB
82
+ /**
83
+ * Inverse foreground 100 color token.
84
+ * The least contrasting color in the inverse foreground palette.
85
+ * Intended for nearly invisible elements on inverse backgrounds.
86
+ */
87
+ colorForegroundInverse100: ThemeColorRGB
88
+ /**
89
+ * Inverse foreground 200 color token.
90
+ * Can help create a subtle sense of hierarchy on inverse backgrounds.
91
+ * Also almost invisible, but a bit more contrasting than 100.
92
+ */
93
+ colorForegroundInverse200: ThemeColorRGB
94
+ /**
95
+ * Inverse foreground 300 color token.
96
+ * Suitable for slightly readable text or elements on inverse backgrounds.
97
+ */
98
+ colorForegroundInverse300: ThemeColorRGB
99
+ /**
100
+ * Inverse foreground 400 color token.
101
+ * A secondary color for secondary elements on inverse backgrounds.
102
+ * If a secondary element has multiple levels, this is for the lower one.
103
+ */
104
+ colorForegroundInverse400: ThemeColorRGB
105
+ /**
106
+ * Inverse foreground 500 color token.
107
+ * Also useful for secondary elements on low-contrast inverse backgrounds.
108
+ */
109
+ colorForegroundInverse500: ThemeColorRGB
110
+ /**
111
+ * Inverse foreground 600 color token.
112
+ * Ideal for secondary elements on inverse backgrounds.
113
+ */
114
+ colorForegroundInverse600: ThemeColorRGB
115
+ /**
116
+ * Inverse foreground 700 color token.
117
+ * Used for default elements on higher contrast inverse backgrounds.
118
+ * Also suitable for slightly subdued elements.
119
+ */
120
+ colorForegroundInverse700: ThemeColorRGB
121
+ /**
122
+ * Inverse foreground 800 color token.
123
+ * Ideal for high-contrast text on inverse background.
124
+ */
125
+ colorForegroundInverse800: ThemeColorRGB
126
+ /**
127
+ * Inverse foreground 900 color token.
128
+ * Similar to 800 but can be a bit more contrasting.
129
+ * Suitable when you need even more contrast on inverse background.
130
+ */
131
+ colorForegroundInverse900: ThemeColorRGB
132
+ /**
133
+ * Base font family token.
134
+ * Supposed to be used by most components.
135
+ * If you don't known what font family to use - use this one.
136
+ */
137
+ fontFamilyBase: string
138
+ /**
139
+ * Base thin font weight token.
140
+ * Ideal for very delicate and decorative, large, elegant hero text.
141
+ */
142
+ fontWeightBaseThin: ThemeFontWeight
143
+ /**
144
+ * Base extra-light font weight token.
145
+ * Use for large, airy headings or subtle interface elements.
146
+ * Slightly more readable than extra-thin, but still decorative.
147
+ */
148
+ fontWeightBaseExtraLight: ThemeFontWeight
149
+ /**
150
+ * Base light font weight token.
151
+ * Suitable for subheadings, muted captions, and soft labels.
152
+ */
153
+ fontWeightBaseLight: ThemeFontWeight
154
+ /**
155
+ * Base regular font weight token.
156
+ * For the most common text elements in your interface.
157
+ * When unsure about font weight, this is the default option.
158
+ */
159
+ fontWeightBaseRegular: ThemeFontWeight
160
+ /**
161
+ * Base medium font weight token.
162
+ * Suitable for labels, buttons, and small subheadings.
163
+ * Slightly emphasized, providing better readability.
164
+ */
165
+ fontWeightBaseMedium: ThemeFontWeight
166
+ /**
167
+ * Base semi-bold font weight token.
168
+ * Provides stronger emphasis without being overwhelming.
169
+ * Ideal for section headers, emphasized text, and card titles.
170
+ */
171
+ fontWeightBaseSemibold: ThemeFontWeight
172
+ /**
173
+ * Base bold font weight token.
174
+ * For high emphasis on important elements.
175
+ * Use for main headings and strong call-to-action buttons.
176
+ */
177
+ fontWeightBaseBold: ThemeFontWeight
178
+ /**
179
+ * Extra-bold font weight token.
180
+ * Perfect for promo banners and large impactful headings.
181
+ */
182
+ fontWeightBaseExtraBold: ThemeFontWeight
183
+ /**
184
+ * Base black font weight token.
185
+ * Extreme emphasis for rare, dramatic cases.
186
+ * Great for headlines in posters and highly attention-grabbing elements.
187
+ */
188
+ fontWeightBaseBlack: ThemeFontWeight
189
+ /**
190
+ * Base 2 times extra-small font size token.
191
+ * Use this size for tiny text elements like captions.
192
+ * It represents the smallest readable text in your interface.
193
+ */
194
+ fontSizeBaseX2S: number
195
+ /**
196
+ * Base extra-small font size token.
197
+ * Suitable for subtitles or the smallest readable text, for example.
198
+ */
199
+ fontSizeBaseXS: number
200
+ /**
201
+ * Base small font size token.
202
+ * Can be used for smaller labels or captions among medium text.
203
+ * Also suitable for titles in smaller 2x small text.
204
+ */
205
+ fontSizeBaseSM: number
206
+ /**
207
+ * Base medium font size token.
208
+ * Intended for most text elements.
209
+ * If unsure about which font size to use, this is the default option.
210
+ */
211
+ fontSizeBaseMD: number
212
+ /**
213
+ * Base large font size token.
214
+ * Suitable for fourth-level page titles.
215
+ * Can also be used for larger labels or captions among medium text.
216
+ */
217
+ fontSizeBaseLG: number
218
+ /**
219
+ * Base extra-large font size token.
220
+ * Ideal for third-level page titles.
221
+ * Can also be used for larger labels or captions within medium text.
222
+ */
223
+ fontSizeBaseXL: number
224
+ /**
225
+ * Base 2 times extra-large font size token.
226
+ * Typically used for second-level page titles.
227
+ */
228
+ fontSizeBaseX2L: number
229
+ /**
230
+ * Base 3 times extra-large font size token.
231
+ * Designed for first-level page titles.
232
+ * Can also be used for labels or captions within huge text.
233
+ */
234
+ fontSizeBaseX3L: number
235
+ /**
236
+ * Base 4 times extra-large font size token.
237
+ * Ideal for huge text labels and captions.
238
+ */
239
+ fontSizeBaseX4L: number
240
+ /**
241
+ * Base 5 times extra-large font size token.
242
+ * Use this size for enormous text elements like hero titles.
243
+ * It should be the largest font size in your interface.
244
+ */
245
+ fontSizeBaseX5L: number
246
+ /**
247
+ * Base none line height token.
248
+ * Use for elements with no line height, like buttons, badges, and tags.
249
+ */
250
+ lineHeightBaseNone: number
251
+ /**
252
+ * Base tight line height token.
253
+ * For compact text elements with closely packed lines.
254
+ */
255
+ lineHeightBaseTight: number
256
+ /**
257
+ * Base snug line height token.
258
+ * Ideal for compact text that still needs some breathing room.
259
+ */
260
+ lineHeightBaseSnug: number
261
+ /**
262
+ * Base normal line height token.
263
+ * Standard line height for most text elements.
264
+ * Use for general content in your interface.
265
+ */
266
+ lineHeightBaseNormal: number
267
+ /**
268
+ * Base relaxed line height token.
269
+ * Provides more space between lines.
270
+ * Ideal for body text or large blocks of content.
271
+ */
272
+ lineHeightBaseRelaxed: number
273
+ /**
274
+ * Base loose line height token.
275
+ * Very spacious and airy, great for large headings.
276
+ * Suitable for text elements that need a lot of breathing room.
277
+ */
278
+ lineHeightBaseLoose: number
279
+ }
280
+ export type ThemeContextProviderProps = PropsWithChildren<
281
+ Partial<ThemeContextValue>
282
+ >
283
+ export type ThemeContextProviderComponent =
284
+ FunctionComponent<ThemeContextProviderProps>
@@ -0,0 +1,3 @@
1
+ export { StorybookControl } from '@/helpers/storybook'
2
+ export { renderStyle } from '@/helpers/style'
3
+ export type { RenderStyleHelper } from '@/helpers/style'
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Storybook control type enum for control helper.
3
+ * Should be used to build control instead of literal values.
4
+ * Feel free to extend this enum with new control types if required.
5
+ */
6
+ export const enum StorybookControlType {
7
+ SELECT = 'select',
8
+ TEXT = 'text',
9
+ NUMBER = 'number',
10
+ }
11
+
12
+ /**
13
+ * Storybook control undefined option.
14
+ * Optional enum controls are supposed to have undefined value option.
15
+ * This option is supposed to be mapped to undefined value in control mapping.
16
+ */
17
+ export const STORYBOOK_CONTROL_UNDEFINED_OPTION = '-'
18
+
19
+ /**
20
+ * Storybook control numeric enum flag.
21
+ * We pass this flag throug storybook inside control object.
22
+ * Allows to handle this flag later, inside decorator if we need.
23
+ */
24
+ export const STORYBOOK_CONTROL_NUMERIC_ENUM_FLAG =
25
+ 'isCreactiveStorybookNumericEnum'
@@ -0,0 +1 @@
1
+ export * from './control'
@@ -0,0 +1,140 @@
1
+ import type { StoryContext } from '@storybook/react'
2
+ import { StorybookControl, modifyContextNumericEnumControls } from './control'
3
+
4
+ describe('@/helpers/storybook/control', () => {
5
+ describe('from numeric enum con', () => {
6
+ it('creates control from numeric method', () => {
7
+ enum TestEnum {
8
+ A,
9
+ B,
10
+ C,
11
+ }
12
+ const testControl = StorybookControl.fromNumericEnum(
13
+ TestEnum as Record<keyof typeof TestEnum, TestEnum>
14
+ )
15
+ expect(testControl.control.isCreactiveStorybookNumericEnum).toEqual(true)
16
+ expect(testControl.control.type).toEqual('select')
17
+ expect(testControl.options).toEqual([TestEnum.A, TestEnum.B, TestEnum.C])
18
+ expect(testControl.defaultValue).toEqual(TestEnum.A)
19
+ expect(testControl.control.labels[TestEnum.A]).toEqual('A')
20
+ expect(testControl.control.labels[TestEnum.B]).toEqual('B')
21
+ expect(testControl.control.labels[TestEnum.C]).toEqual('C')
22
+ })
23
+
24
+ it('creates optional control from numeric enum ', () => {
25
+ enum TestEnum {
26
+ A,
27
+ B,
28
+ C,
29
+ }
30
+ const testControl = StorybookControl.fromNumericEnum(
31
+ TestEnum as Record<keyof typeof TestEnum, TestEnum>
32
+ )
33
+ expect(testControl.control.isCreactiveStorybookNumericEnum).toEqual(true)
34
+ expect(testControl.control.type).toEqual('select')
35
+ expect(testControl.options).toEqual([TestEnum.A, TestEnum.B, TestEnum.C])
36
+ expect(testControl.defaultValue).toEqual(TestEnum.A)
37
+ expect(testControl.control.labels[TestEnum.A]).toEqual('A')
38
+ expect(testControl.control.labels[TestEnum.B]).toEqual('B')
39
+ expect(testControl.control.labels[TestEnum.C]).toEqual('C')
40
+ expect(testControl.control.labels[undefined as number]).toEqual('-')
41
+ })
42
+ })
43
+
44
+ describe('for children control method', () => {
45
+ it('creates children control', () => {
46
+ const testControl = StorybookControl.forChildren()
47
+ expect(testControl.control.type).toEqual('text')
48
+ expect(testControl.defaultValue).toEqual(expect.any(String))
49
+ })
50
+ })
51
+
52
+ describe('modifying context numeric controls helper', () => {
53
+ it('modifies context with numeric enum controls', () => {
54
+ const testContext: Pick<StoryContext, 'argTypes' | 'args'> = {
55
+ argTypes: {
56
+ testField: {
57
+ control: {
58
+ isCreactiveStorybookNumericEnum: true,
59
+ type: 'select',
60
+ labels: {
61
+ 0: 'A',
62
+ 1: 'B',
63
+ 2: 'C',
64
+ },
65
+ },
66
+ defaultValue: 0,
67
+ options: [0, 1, 2],
68
+ name: 'testField',
69
+ },
70
+ },
71
+ args: {
72
+ testField: '0',
73
+ },
74
+ }
75
+ const modifiedContext = modifyContextNumericEnumControls(
76
+ testContext as StoryContext
77
+ )
78
+ expect(modifiedContext.args.testField).toEqual(0)
79
+ })
80
+
81
+ it('handles undefined control label when provided as value', () => {
82
+ // Storybook passes this label as a value for some reason when select it.
83
+ // This only happens, when some value was selected before.
84
+ // Our helper also handles this case inside (modifies value to undefined).
85
+ const testContext: Pick<StoryContext, 'argTypes' | 'args'> = {
86
+ argTypes: {
87
+ testField: {
88
+ control: {
89
+ isCreactiveStorybookNumericEnum: true,
90
+ type: 'select',
91
+ labels: {
92
+ undefined: '-',
93
+ 0: 'A',
94
+ 1: 'B',
95
+ 2: 'C',
96
+ },
97
+ },
98
+ defaultValue: undefined,
99
+ options: [undefined, 0, 1, 2],
100
+ name: 'testField',
101
+ },
102
+ },
103
+ args: {
104
+ testField: '-',
105
+ },
106
+ }
107
+ const modifiedContext = modifyContextNumericEnumControls(
108
+ testContext as StoryContext
109
+ )
110
+ expect(modifiedContext.args.testField).toEqual(undefined)
111
+ })
112
+
113
+ it('does nothing with controls without numeric enum flag', () => {
114
+ const testContext: Pick<StoryContext, 'argTypes' | 'args'> = {
115
+ argTypes: {
116
+ testField: {
117
+ control: {
118
+ type: 'select',
119
+ labels: {
120
+ 0: 'A',
121
+ 1: 'B',
122
+ 2: 'C',
123
+ },
124
+ },
125
+ defaultValue: 0,
126
+ options: [0, 1, 2],
127
+ name: 'testField',
128
+ },
129
+ },
130
+ args: {
131
+ testField: '0',
132
+ },
133
+ }
134
+ const modifiedContext = modifyContextNumericEnumControls(
135
+ testContext as StoryContext
136
+ )
137
+ expect(modifiedContext.args.testField).toEqual('0')
138
+ })
139
+ })
140
+ })
@@ -0,0 +1,115 @@
1
+ import { faker } from '@faker-js/faker'
2
+ import type { Decorator, StoryContext } from '@storybook/react'
3
+ import {
4
+ STORYBOOK_CONTROL_NUMERIC_ENUM_FLAG,
5
+ STORYBOOK_CONTROL_UNDEFINED_OPTION,
6
+ StorybookControlType,
7
+ } from './constants'
8
+
9
+ /**
10
+ * Modifies context arguments to handle numeric enum controls.
11
+ * Numeric enum values are passed as strings by storybook controls.
12
+ * Seems like this happens because of select control implementation.
13
+ * This method is exported for test here, but should not be exported ouside.
14
+ */
15
+ export const modifyContextNumericEnumControls = (context: StoryContext) => {
16
+ const args = {
17
+ ...context.args,
18
+ }
19
+ for (const key of Object.keys(context.argTypes)) {
20
+ if (typeof context.argTypes[key] === 'object') {
21
+ const control = context.argTypes[key].control as {
22
+ // The only flag, we are interested in..
23
+ [STORYBOOK_CONTROL_NUMERIC_ENUM_FLAG]?: boolean
24
+ // We don't care about everything else inside this type..
25
+ [key: string | number | symbol]: unknown
26
+ }
27
+ if (control[STORYBOOK_CONTROL_NUMERIC_ENUM_FLAG]) {
28
+ if (typeof args[key] === 'string') {
29
+ args[key] =
30
+ args[key] === STORYBOOK_CONTROL_UNDEFINED_OPTION
31
+ ? undefined
32
+ : Number(args[key])
33
+ }
34
+ }
35
+ }
36
+ }
37
+ return {
38
+ ...context,
39
+ args,
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Storybook control helpers.
45
+ * Collected into a single class for convenient import.
46
+ * Helps to build storybook control objects for components stories.
47
+ */
48
+ export const StorybookControl = new (class {
49
+ /**
50
+ * Builds a story object form provided numeric enum.
51
+ * Numeric enum will be mapped to storybook select control.
52
+ *
53
+ * @param target - target numeric enum for control
54
+ * @param isOptional - whether control is optional
55
+ */
56
+ public fromNumericEnum(target: Record<string, number>, isOptional = false) {
57
+ const options = Object.values(target).filter(
58
+ (value) => !isNaN(Number(value))
59
+ )
60
+ const keys = Object.keys(target).filter((value) => isNaN(Number(value)))
61
+ if (isOptional) options.unshift(undefined)
62
+ const labels: Record<number, string> = {}
63
+ for (const key of keys) labels[target[key]] = key
64
+ labels[undefined as number] = STORYBOOK_CONTROL_UNDEFINED_OPTION
65
+ return {
66
+ control: {
67
+ // Passing flag to handle numeric enum inside decorator.
68
+ [STORYBOOK_CONTROL_NUMERIC_ENUM_FLAG]: true,
69
+ type: StorybookControlType.SELECT,
70
+ labels,
71
+ },
72
+ options,
73
+ defaultValue: options[0],
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Builds a story object for numeric input control.
79
+ * Numeric input will be mapped to storybook number control.
80
+ *
81
+ * @param defaultValue - can be provided to set default value
82
+ */
83
+ public forNumber(defaultValue?: number) {
84
+ return {
85
+ control: {
86
+ type: StorybookControlType.NUMBER,
87
+ },
88
+ defaultValue,
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Returns default children control.
94
+ * Keeps storybook control factory logic together.
95
+ * Also allows to avoid faker import in every story file.
96
+ */
97
+ public forChildren() {
98
+ return {
99
+ control: {
100
+ type: StorybookControlType.TEXT,
101
+ },
102
+ defaultValue: faker.lorem.words(2),
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Returns decorator for storybook stories.
108
+ * This decorator should apply some context modifications.
109
+ */
110
+ public getDecorator(): Decorator {
111
+ return (Story, context) => {
112
+ return Story(modifyContextNumericEnumControls(context))
113
+ }
114
+ }
115
+ })()
@@ -0,0 +1 @@
1
+ export { StorybookControl } from './control'
@@ -0,0 +1,2 @@
1
+ export { renderStyle } from './style'
2
+ export type { RenderStyleHelper } from './style.types'
@@ -0,0 +1,20 @@
1
+ import { Fragment, isValidElement } from 'react'
2
+ import { renderStyle } from './style'
3
+
4
+ describe('@/helpers/style', () => {
5
+ describe('rendering style element helper', () => {
6
+ it('renders style element for react fragment', () => {
7
+ const element = renderStyle(Fragment)
8
+ expect(isValidElement(element)).toBe(true)
9
+ expect(element.type).toEqual('style')
10
+ const style = element.props.dangerouslySetInnerHTML.__html
11
+ expect(style).toContain('display:')
12
+ expect(style).toContain('inline')
13
+ expect(style).toContain('inline-flex')
14
+ expect(style).toContain('flex')
15
+ expect(style).toContain('pointer-events:')
16
+ expect(style).toContain('auto')
17
+ expect(style).toContain('none')
18
+ })
19
+ })
20
+ })
@@ -0,0 +1,14 @@
1
+ import { isValidElement } from 'react'
2
+ import { AppRegistry } from 'react-native'
3
+ import type { AppRegistry as WebAppRegistryType } from 'react-native-web'
4
+ import type { RenderStyleHelper } from './style.types'
5
+
6
+ export const renderStyle: RenderStyleHelper = (component, key = 'main') => {
7
+ // Converting types to be able to use web specific methods..
8
+ const WebAppRegistry = AppRegistry as unknown as WebAppRegistryType
9
+ WebAppRegistry.registerComponent(key, () => component)
10
+ // If someone use this function on native platform it will throw an error..
11
+ // Seems fine.. calling this function on native platform makes no sence..
12
+ const element = WebAppRegistry.getApplication(key, null).getStyleElement()
13
+ if (isValidElement(element)) return element
14
+ }
@@ -0,0 +1,14 @@
1
+ import type { ComponentType, JSX } from 'react'
2
+
3
+ /**
4
+ * Rendering style node (for web platform server side rendering) helper.
5
+ * Using this helper on native platform makes no sense and will throw an error!
6
+ * You are supposed to use it only for server side rendering.
7
+ *
8
+ * @see https://necolas.github.io/react-native-web/docs/rendering/
9
+ * @see https://docs.expo.dev/guides/using-nextjs/
10
+ */
11
+ export type RenderStyleHelper = (
12
+ component: ComponentType,
13
+ key?: string
14
+ ) => JSX.Element
@@ -0,0 +1 @@
1
+ export { useThemeStyleSheet } from '@/hooks/use-theme-style-sheet'