tgui-core 1.0.2 → 1.0.4

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 (158) hide show
  1. package/{src/components → components}/AnimatedNumber.tsx +185 -185
  2. package/{src/components → components}/BlockQuote.tsx +15 -15
  3. package/{src/components → components}/BodyZoneSelector.tsx +149 -149
  4. package/{src/components → components}/Box.tsx +255 -255
  5. package/{src/components → components}/Button.tsx +415 -415
  6. package/{src/components → components}/ByondUi.jsx +121 -121
  7. package/{src/components → components}/Chart.tsx +160 -160
  8. package/{src/components → components}/ColorBox.tsx +30 -30
  9. package/{src/components → components}/Dimmer.tsx +19 -19
  10. package/{src/components → components}/Divider.tsx +26 -26
  11. package/{src/components → components}/DmIcon.tsx +72 -72
  12. package/{src/components → components}/DraggableControl.jsx +282 -282
  13. package/{src/components → components}/Dropdown.tsx +246 -246
  14. package/{src/components → components}/Flex.tsx +105 -105
  15. package/{src/components → components}/Icon.tsx +91 -91
  16. package/{src/components → components}/Input.tsx +181 -181
  17. package/{src/components → components}/KeyListener.tsx +40 -40
  18. package/{src/components → components}/Knob.tsx +185 -185
  19. package/{src/components → components}/LabeledList.tsx +130 -130
  20. package/{src/components → components}/MenuBar.tsx +233 -238
  21. package/{src/components → components}/Modal.tsx +25 -25
  22. package/{src/components → components}/NoticeBox.tsx +48 -48
  23. package/{src/components → components}/NumberInput.tsx +328 -328
  24. package/{src/components → components}/ProgressBar.tsx +79 -79
  25. package/{src/components → components}/RestrictedInput.jsx +301 -301
  26. package/{src/components → components}/RoundGauge.tsx +189 -189
  27. package/{src/components → components}/Section.tsx +125 -125
  28. package/{src/components → components}/Slider.tsx +173 -173
  29. package/{src/components → components}/Stack.tsx +101 -101
  30. package/{src/components → components}/Table.tsx +90 -90
  31. package/{src/components → components}/Tabs.tsx +90 -90
  32. package/{src/components → components}/TextArea.tsx +198 -198
  33. package/{src/components → components}/TimeDisplay.jsx +64 -64
  34. package/components/index.ts +51 -0
  35. package/{src/debug/KitchenSink.jsx → debug/KitchenSink.tsx} +56 -56
  36. package/{src/debug/actions.js → debug/actions.ts} +11 -11
  37. package/{src/debug/hooks.js → debug/hooks.ts} +10 -10
  38. package/{src/debug/middleware.js → debug/middleware.ts} +67 -86
  39. package/{src/debug/reducer.js → debug/reducer.ts} +27 -22
  40. package/{src/debug/selectors.js → debug/selectors.ts} +7 -7
  41. package/{src/layouts → layouts}/Layout.tsx +75 -75
  42. package/{src/layouts → layouts}/NtosWindow.tsx +162 -162
  43. package/{src/layouts → layouts}/Pane.tsx +56 -56
  44. package/{src/layouts → layouts}/Window.tsx +227 -227
  45. package/layouts/index.ts +10 -0
  46. package/package.json +3 -2
  47. package/src/assets.ts +43 -43
  48. package/src/backend.ts +368 -369
  49. package/src/drag.ts +280 -280
  50. package/src/events.ts +237 -237
  51. package/src/hotkeys.ts +212 -212
  52. package/src/renderer.ts +50 -50
  53. package/stories/Blink.stories.tsx +20 -0
  54. package/stories/BlockQuote.stories.tsx +23 -0
  55. package/stories/Box.stories.tsx +27 -0
  56. package/stories/Button.stories.tsx +68 -0
  57. package/stories/ByondUi.stories.tsx +45 -0
  58. package/stories/Collapsible.stories.tsx +23 -0
  59. package/stories/Flex.stories.tsx +68 -0
  60. package/stories/Input.stories.tsx +124 -0
  61. package/stories/LabeledList.stories.tsx +73 -0
  62. package/stories/Popper.stories.tsx +58 -0
  63. package/stories/ProgressBar.stories.tsx +58 -0
  64. package/stories/Stack.stories.tsx +55 -0
  65. package/stories/Storage.stories.tsx +46 -0
  66. package/stories/Themes.stories.tsx +30 -0
  67. package/stories/Tooltip.stories.tsx +48 -0
  68. package/stories/common.tsx +19 -0
  69. package/tsconfig.json +0 -21
  70. package/src/components/Grid.tsx +0 -44
  71. /package/{src/common → common}/collections.ts +0 -0
  72. /package/{src/common → common}/color.ts +0 -0
  73. /package/{src/common → common}/events.ts +0 -0
  74. /package/{src/common → common}/exhaustive.ts +0 -0
  75. /package/{src/common → common}/fp.ts +0 -0
  76. /package/{src/common → common}/keycodes.ts +0 -0
  77. /package/{src/common → common}/keys.ts +0 -0
  78. /package/{src/common → common}/math.ts +0 -0
  79. /package/{src/common → common}/perf.ts +0 -0
  80. /package/{src/common → common}/random.ts +0 -0
  81. /package/{src/common → common}/react.ts +0 -0
  82. /package/{src/common → common}/redux.ts +0 -0
  83. /package/{src/common → common}/storage.js +0 -0
  84. /package/{src/common → common}/string.ts +0 -0
  85. /package/{src/common → common}/timer.ts +0 -0
  86. /package/{src/common → common}/type-utils.ts +0 -0
  87. /package/{src/common → common}/types.ts +0 -0
  88. /package/{src/common → common}/uuid.ts +0 -0
  89. /package/{src/common → common}/vector.ts +0 -0
  90. /package/{src/components → components}/Autofocus.tsx +0 -0
  91. /package/{src/components → components}/Blink.jsx +0 -0
  92. /package/{src/components → components}/Collapsible.tsx +0 -0
  93. /package/{src/components → components}/Dialog.tsx +0 -0
  94. /package/{src/components → components}/FakeTerminal.jsx +0 -0
  95. /package/{src/components → components}/FitText.tsx +0 -0
  96. /package/{src/components → components}/Image.tsx +0 -0
  97. /package/{src/components → components}/InfinitePlane.jsx +0 -0
  98. /package/{src/components → components}/LabeledControls.tsx +0 -0
  99. /package/{src/components → components}/Popper.tsx +0 -0
  100. /package/{src/components → components}/StyleableSection.tsx +0 -0
  101. /package/{src/components → components}/Tooltip.tsx +0 -0
  102. /package/{src/components → components}/TrackOutsideClicks.tsx +0 -0
  103. /package/{src/components → components}/VirtualList.tsx +0 -0
  104. /package/{src/debug → debug}/index.ts +0 -0
  105. /package/{src/styles → styles}/base.scss +0 -0
  106. /package/{src/styles → styles}/colors.scss +0 -0
  107. /package/{src/styles → styles}/components/BlockQuote.scss +0 -0
  108. /package/{src/styles → styles}/components/Button.scss +0 -0
  109. /package/{src/styles → styles}/components/ColorBox.scss +0 -0
  110. /package/{src/styles → styles}/components/Dialog.scss +0 -0
  111. /package/{src/styles → styles}/components/Dimmer.scss +0 -0
  112. /package/{src/styles → styles}/components/Divider.scss +0 -0
  113. /package/{src/styles → styles}/components/Dropdown.scss +0 -0
  114. /package/{src/styles → styles}/components/Flex.scss +0 -0
  115. /package/{src/styles → styles}/components/Icon.scss +0 -0
  116. /package/{src/styles → styles}/components/Input.scss +0 -0
  117. /package/{src/styles → styles}/components/Knob.scss +0 -0
  118. /package/{src/styles → styles}/components/LabeledList.scss +0 -0
  119. /package/{src/styles → styles}/components/MenuBar.scss +0 -0
  120. /package/{src/styles → styles}/components/Modal.scss +0 -0
  121. /package/{src/styles → styles}/components/NoticeBox.scss +0 -0
  122. /package/{src/styles → styles}/components/NumberInput.scss +0 -0
  123. /package/{src/styles → styles}/components/ProgressBar.scss +0 -0
  124. /package/{src/styles → styles}/components/RoundGauge.scss +0 -0
  125. /package/{src/styles → styles}/components/Section.scss +0 -0
  126. /package/{src/styles → styles}/components/Slider.scss +0 -0
  127. /package/{src/styles → styles}/components/Stack.scss +0 -0
  128. /package/{src/styles → styles}/components/Table.scss +0 -0
  129. /package/{src/styles → styles}/components/Tabs.scss +0 -0
  130. /package/{src/styles → styles}/components/TextArea.scss +0 -0
  131. /package/{src/styles → styles}/components/Tooltip.scss +0 -0
  132. /package/{src/styles → styles}/functions.scss +0 -0
  133. /package/{src/styles → styles}/layouts/Layout.scss +0 -0
  134. /package/{src/styles → styles}/layouts/NtosHeader.scss +0 -0
  135. /package/{src/styles → styles}/layouts/NtosWindow.scss +0 -0
  136. /package/{src/styles → styles}/layouts/TitleBar.scss +0 -0
  137. /package/{src/styles → styles}/layouts/Window.scss +0 -0
  138. /package/{src/styles → styles}/main.scss +0 -0
  139. /package/{src/styles → styles}/reset.scss +0 -0
  140. /package/{src/styles → styles}/themes/abductor.scss +0 -0
  141. /package/{src/styles → styles}/themes/admin.scss +0 -0
  142. /package/{src/styles → styles}/themes/cardtable.scss +0 -0
  143. /package/{src/styles → styles}/themes/hackerman.scss +0 -0
  144. /package/{src/styles → styles}/themes/malfunction.scss +0 -0
  145. /package/{src/styles → styles}/themes/neutral.scss +0 -0
  146. /package/{src/styles → styles}/themes/ntOS95.scss +0 -0
  147. /package/{src/styles → styles}/themes/ntos.scss +0 -0
  148. /package/{src/styles → styles}/themes/ntos_cat.scss +0 -0
  149. /package/{src/styles → styles}/themes/ntos_darkmode.scss +0 -0
  150. /package/{src/styles → styles}/themes/ntos_lightmode.scss +0 -0
  151. /package/{src/styles → styles}/themes/ntos_spooky.scss +0 -0
  152. /package/{src/styles → styles}/themes/ntos_synth.scss +0 -0
  153. /package/{src/styles → styles}/themes/ntos_terminal.scss +0 -0
  154. /package/{src/styles → styles}/themes/paper.scss +0 -0
  155. /package/{src/styles → styles}/themes/retro.scss +0 -0
  156. /package/{src/styles → styles}/themes/spookyconsole.scss +0 -0
  157. /package/{src/styles → styles}/themes/syndicate.scss +0 -0
  158. /package/{src/styles → styles}/themes/wizard.scss +0 -0
@@ -1,255 +1,255 @@
1
- /**
2
- * @file
3
- * @copyright 2020 Aleksej Komarov
4
- * @license MIT
5
- */
6
-
7
- import { BooleanLike, classes } from '../common/react';
8
- import {
9
- createElement,
10
- KeyboardEventHandler,
11
- MouseEventHandler,
12
- ReactNode,
13
- UIEventHandler,
14
- } from 'react';
15
-
16
- import { CSS_COLORS } from '../constants';
17
-
18
- type BooleanProps = Partial<Record<keyof typeof booleanStyleMap, boolean>>;
19
- type StringProps = Partial<
20
- Record<keyof typeof stringStyleMap, string | BooleanLike>
21
- >;
22
-
23
- export type EventHandlers = Partial<{
24
- onClick: MouseEventHandler<HTMLDivElement>;
25
- onContextMenu: MouseEventHandler<HTMLDivElement>;
26
- onDoubleClick: MouseEventHandler<HTMLDivElement>;
27
- onKeyDown: KeyboardEventHandler<HTMLDivElement>;
28
- onKeyUp: KeyboardEventHandler<HTMLDivElement>;
29
- onMouseDown: MouseEventHandler<HTMLDivElement>;
30
- onMouseMove: MouseEventHandler<HTMLDivElement>;
31
- onMouseOver: MouseEventHandler<HTMLDivElement>;
32
- onMouseUp: MouseEventHandler<HTMLDivElement>;
33
- onScroll: UIEventHandler<HTMLDivElement>;
34
- }>;
35
-
36
- export type BoxProps = Partial<{
37
- as: string;
38
- children: ReactNode;
39
- className: string | BooleanLike;
40
- style: Partial<CSSStyleDeclaration>;
41
- }> &
42
- BooleanProps &
43
- StringProps &
44
- EventHandlers;
45
-
46
- // Don't you dare put this elsewhere
47
- type DangerDoNotUse = {
48
- dangerouslySetInnerHTML?: {
49
- __html: any;
50
- };
51
- };
52
-
53
- /**
54
- * Coverts our rem-like spacing unit into a CSS unit.
55
- */
56
- export const unit = (value: unknown) => {
57
- if (typeof value === 'string') {
58
- // Transparently convert pixels into rem units
59
- if (value.endsWith('px')) {
60
- return parseFloat(value) / 12 + 'rem';
61
- }
62
- return value;
63
- }
64
- if (typeof value === 'number') {
65
- return value + 'rem';
66
- }
67
- };
68
-
69
- /**
70
- * Same as `unit`, but half the size for integers numbers.
71
- */
72
- export const halfUnit = (value: unknown) => {
73
- if (typeof value === 'string') {
74
- return unit(value);
75
- }
76
- if (typeof value === 'number') {
77
- return unit(value * 0.5);
78
- }
79
- };
80
-
81
- const isColorCode = (str: unknown) => !isColorClass(str);
82
-
83
- const isColorClass = (str: unknown): boolean => {
84
- return typeof str === 'string' && CSS_COLORS.includes(str as any);
85
- };
86
-
87
- const mapRawPropTo = (attrName) => (style, value) => {
88
- if (typeof value === 'number' || typeof value === 'string') {
89
- style[attrName] = value;
90
- }
91
- };
92
-
93
- const mapUnitPropTo = (attrName, unit) => (style, value) => {
94
- if (typeof value === 'number' || typeof value === 'string') {
95
- style[attrName] = unit(value);
96
- }
97
- };
98
-
99
- const mapBooleanPropTo = (attrName, attrValue) => (style, value) => {
100
- if (value) {
101
- style[attrName] = attrValue;
102
- }
103
- };
104
-
105
- const mapDirectionalUnitPropTo = (attrName, unit, dirs) => (style, value) => {
106
- if (typeof value === 'number' || typeof value === 'string') {
107
- for (let i = 0; i < dirs.length; i++) {
108
- style[attrName + '-' + dirs[i]] = unit(value);
109
- }
110
- }
111
- };
112
-
113
- const mapColorPropTo = (attrName) => (style, value) => {
114
- if (isColorCode(value)) {
115
- style[attrName] = value;
116
- }
117
- };
118
-
119
- // String / number props
120
- const stringStyleMap = {
121
- align: mapRawPropTo('textAlign'),
122
- bottom: mapUnitPropTo('bottom', unit),
123
- fontFamily: mapRawPropTo('fontFamily'),
124
- fontSize: mapUnitPropTo('fontSize', unit),
125
- fontWeight: mapRawPropTo('fontWeight'),
126
- height: mapUnitPropTo('height', unit),
127
- left: mapUnitPropTo('left', unit),
128
- maxHeight: mapUnitPropTo('maxHeight', unit),
129
- maxWidth: mapUnitPropTo('maxWidth', unit),
130
- minHeight: mapUnitPropTo('minHeight', unit),
131
- minWidth: mapUnitPropTo('minWidth', unit),
132
- opacity: mapRawPropTo('opacity'),
133
- overflow: mapRawPropTo('overflow'),
134
- overflowX: mapRawPropTo('overflowX'),
135
- overflowY: mapRawPropTo('overflowY'),
136
- position: mapRawPropTo('position'),
137
- right: mapUnitPropTo('right', unit),
138
- textAlign: mapRawPropTo('textAlign'),
139
- top: mapUnitPropTo('top', unit),
140
- verticalAlign: mapRawPropTo('verticalAlign'),
141
- width: mapUnitPropTo('width', unit),
142
-
143
- lineHeight: (style, value) => {
144
- if (typeof value === 'number') {
145
- style['lineHeight'] = value;
146
- } else if (typeof value === 'string') {
147
- style['lineHeight'] = unit(value);
148
- }
149
- },
150
- // Margin
151
- m: mapDirectionalUnitPropTo('margin', halfUnit, [
152
- 'Top',
153
- 'Bottom',
154
- 'Left',
155
- 'Right',
156
- ]),
157
- mb: mapUnitPropTo('marginBottom', halfUnit),
158
- ml: mapUnitPropTo('marginLeft', halfUnit),
159
- mr: mapUnitPropTo('marginRight', halfUnit),
160
- mt: mapUnitPropTo('marginTop', halfUnit),
161
- mx: mapDirectionalUnitPropTo('margin', halfUnit, ['Left', 'Right']),
162
- my: mapDirectionalUnitPropTo('margin', halfUnit, ['Top', 'Bottom']),
163
- // Padding
164
- p: mapDirectionalUnitPropTo('padding', halfUnit, [
165
- 'Top',
166
- 'Bottom',
167
- 'Left',
168
- 'Right',
169
- ]),
170
- pb: mapUnitPropTo('paddingBottom', halfUnit),
171
- pl: mapUnitPropTo('paddingLeft', halfUnit),
172
- pr: mapUnitPropTo('paddingRight', halfUnit),
173
- pt: mapUnitPropTo('paddingTop', halfUnit),
174
- px: mapDirectionalUnitPropTo('padding', halfUnit, ['Left', 'Right']),
175
- py: mapDirectionalUnitPropTo('padding', halfUnit, ['Top', 'Bottom']),
176
- // Color props
177
- color: mapColorPropTo('color'),
178
- textColor: mapColorPropTo('color'),
179
- backgroundColor: mapColorPropTo('backgroundColor'),
180
- } as const;
181
-
182
- // Boolean props
183
- const booleanStyleMap = {
184
- bold: mapBooleanPropTo('fontWeight', 'bold'),
185
- fillPositionedParent: (style, value) => {
186
- if (value) {
187
- style['position'] = 'absolute';
188
- style['top'] = 0;
189
- style['bottom'] = 0;
190
- style['left'] = 0;
191
- style['right'] = 0;
192
- }
193
- },
194
- inline: mapBooleanPropTo('display', 'inline-block'),
195
- italic: mapBooleanPropTo('fontStyle', 'italic'),
196
- nowrap: mapBooleanPropTo('whiteSpace', 'nowrap'),
197
- preserveWhitespace: mapBooleanPropTo('whiteSpace', 'pre-wrap'),
198
- } as const;
199
-
200
- export const computeBoxProps = (props) => {
201
- const computedProps: Record<string, any> = {};
202
- const computedStyles: Record<string, string | number> = {};
203
-
204
- // Compute props
205
- for (let propName of Object.keys(props)) {
206
- if (propName === 'style') {
207
- continue;
208
- }
209
-
210
- const propValue = props[propName];
211
-
212
- const mapPropToStyle =
213
- stringStyleMap[propName] || booleanStyleMap[propName];
214
-
215
- if (mapPropToStyle) {
216
- mapPropToStyle(computedStyles, propValue);
217
- } else {
218
- computedProps[propName] = propValue;
219
- }
220
- }
221
-
222
- // Merge computed styles and any directly provided styles
223
- computedProps.style = { ...computedStyles, ...props.style };
224
-
225
- return computedProps;
226
- };
227
-
228
- export const computeBoxClassName = (props: BoxProps) => {
229
- const color = props.textColor || props.color;
230
- const backgroundColor = props.backgroundColor;
231
- return classes([
232
- isColorClass(color) && 'color-' + color,
233
- isColorClass(backgroundColor) && 'color-bg-' + backgroundColor,
234
- ]);
235
- };
236
-
237
- export const Box = (props: BoxProps & DangerDoNotUse) => {
238
- const { as = 'div', className, children, ...rest } = props;
239
-
240
- // Compute class name and styles
241
- const computedClassName = className
242
- ? `${className} ${computeBoxClassName(rest)}`
243
- : computeBoxClassName(rest);
244
- const computedProps = computeBoxProps(rest);
245
-
246
- // Render the component
247
- return createElement(
248
- typeof as === 'string' ? as : 'div',
249
- {
250
- ...computedProps,
251
- className: computedClassName,
252
- },
253
- children
254
- );
255
- };
1
+ /**
2
+ * @file
3
+ * @copyright 2020 Aleksej Komarov
4
+ * @license MIT
5
+ */
6
+
7
+ import { BooleanLike, classes } from '../common/react';
8
+ import {
9
+ createElement,
10
+ KeyboardEventHandler,
11
+ MouseEventHandler,
12
+ ReactNode,
13
+ UIEventHandler,
14
+ } from 'react';
15
+
16
+ import { CSS_COLORS } from '../src/constants';
17
+
18
+ type BooleanProps = Partial<Record<keyof typeof booleanStyleMap, boolean>>;
19
+ type StringProps = Partial<
20
+ Record<keyof typeof stringStyleMap, string | BooleanLike>
21
+ >;
22
+
23
+ export type EventHandlers = Partial<{
24
+ onClick: MouseEventHandler<HTMLDivElement>;
25
+ onContextMenu: MouseEventHandler<HTMLDivElement>;
26
+ onDoubleClick: MouseEventHandler<HTMLDivElement>;
27
+ onKeyDown: KeyboardEventHandler<HTMLDivElement>;
28
+ onKeyUp: KeyboardEventHandler<HTMLDivElement>;
29
+ onMouseDown: MouseEventHandler<HTMLDivElement>;
30
+ onMouseMove: MouseEventHandler<HTMLDivElement>;
31
+ onMouseOver: MouseEventHandler<HTMLDivElement>;
32
+ onMouseUp: MouseEventHandler<HTMLDivElement>;
33
+ onScroll: UIEventHandler<HTMLDivElement>;
34
+ }>;
35
+
36
+ export type BoxProps = Partial<{
37
+ as: string;
38
+ children: ReactNode;
39
+ className: string | BooleanLike;
40
+ style: Partial<CSSStyleDeclaration>;
41
+ }> &
42
+ BooleanProps &
43
+ StringProps &
44
+ EventHandlers;
45
+
46
+ // Don't you dare put this elsewhere
47
+ type DangerDoNotUse = {
48
+ dangerouslySetInnerHTML?: {
49
+ __html: any;
50
+ };
51
+ };
52
+
53
+ /**
54
+ * Coverts our rem-like spacing unit into a CSS unit.
55
+ */
56
+ export const unit = (value: unknown) => {
57
+ if (typeof value === 'string') {
58
+ // Transparently convert pixels into rem units
59
+ if (value.endsWith('px')) {
60
+ return parseFloat(value) / 12 + 'rem';
61
+ }
62
+ return value;
63
+ }
64
+ if (typeof value === 'number') {
65
+ return value + 'rem';
66
+ }
67
+ };
68
+
69
+ /**
70
+ * Same as `unit`, but half the size for integers numbers.
71
+ */
72
+ export const halfUnit = (value: unknown) => {
73
+ if (typeof value === 'string') {
74
+ return unit(value);
75
+ }
76
+ if (typeof value === 'number') {
77
+ return unit(value * 0.5);
78
+ }
79
+ };
80
+
81
+ const isColorCode = (str: unknown) => !isColorClass(str);
82
+
83
+ const isColorClass = (str: unknown): boolean => {
84
+ return typeof str === 'string' && CSS_COLORS.includes(str as any);
85
+ };
86
+
87
+ const mapRawPropTo = (attrName) => (style, value) => {
88
+ if (typeof value === 'number' || typeof value === 'string') {
89
+ style[attrName] = value;
90
+ }
91
+ };
92
+
93
+ const mapUnitPropTo = (attrName, unit) => (style, value) => {
94
+ if (typeof value === 'number' || typeof value === 'string') {
95
+ style[attrName] = unit(value);
96
+ }
97
+ };
98
+
99
+ const mapBooleanPropTo = (attrName, attrValue) => (style, value) => {
100
+ if (value) {
101
+ style[attrName] = attrValue;
102
+ }
103
+ };
104
+
105
+ const mapDirectionalUnitPropTo = (attrName, unit, dirs) => (style, value) => {
106
+ if (typeof value === 'number' || typeof value === 'string') {
107
+ for (let i = 0; i < dirs.length; i++) {
108
+ style[attrName + '-' + dirs[i]] = unit(value);
109
+ }
110
+ }
111
+ };
112
+
113
+ const mapColorPropTo = (attrName) => (style, value) => {
114
+ if (isColorCode(value)) {
115
+ style[attrName] = value;
116
+ }
117
+ };
118
+
119
+ // String / number props
120
+ const stringStyleMap = {
121
+ align: mapRawPropTo('textAlign'),
122
+ bottom: mapUnitPropTo('bottom', unit),
123
+ fontFamily: mapRawPropTo('fontFamily'),
124
+ fontSize: mapUnitPropTo('fontSize', unit),
125
+ fontWeight: mapRawPropTo('fontWeight'),
126
+ height: mapUnitPropTo('height', unit),
127
+ left: mapUnitPropTo('left', unit),
128
+ maxHeight: mapUnitPropTo('maxHeight', unit),
129
+ maxWidth: mapUnitPropTo('maxWidth', unit),
130
+ minHeight: mapUnitPropTo('minHeight', unit),
131
+ minWidth: mapUnitPropTo('minWidth', unit),
132
+ opacity: mapRawPropTo('opacity'),
133
+ overflow: mapRawPropTo('overflow'),
134
+ overflowX: mapRawPropTo('overflowX'),
135
+ overflowY: mapRawPropTo('overflowY'),
136
+ position: mapRawPropTo('position'),
137
+ right: mapUnitPropTo('right', unit),
138
+ textAlign: mapRawPropTo('textAlign'),
139
+ top: mapUnitPropTo('top', unit),
140
+ verticalAlign: mapRawPropTo('verticalAlign'),
141
+ width: mapUnitPropTo('width', unit),
142
+
143
+ lineHeight: (style, value) => {
144
+ if (typeof value === 'number') {
145
+ style['lineHeight'] = value;
146
+ } else if (typeof value === 'string') {
147
+ style['lineHeight'] = unit(value);
148
+ }
149
+ },
150
+ // Margin
151
+ m: mapDirectionalUnitPropTo('margin', halfUnit, [
152
+ 'Top',
153
+ 'Bottom',
154
+ 'Left',
155
+ 'Right',
156
+ ]),
157
+ mb: mapUnitPropTo('marginBottom', halfUnit),
158
+ ml: mapUnitPropTo('marginLeft', halfUnit),
159
+ mr: mapUnitPropTo('marginRight', halfUnit),
160
+ mt: mapUnitPropTo('marginTop', halfUnit),
161
+ mx: mapDirectionalUnitPropTo('margin', halfUnit, ['Left', 'Right']),
162
+ my: mapDirectionalUnitPropTo('margin', halfUnit, ['Top', 'Bottom']),
163
+ // Padding
164
+ p: mapDirectionalUnitPropTo('padding', halfUnit, [
165
+ 'Top',
166
+ 'Bottom',
167
+ 'Left',
168
+ 'Right',
169
+ ]),
170
+ pb: mapUnitPropTo('paddingBottom', halfUnit),
171
+ pl: mapUnitPropTo('paddingLeft', halfUnit),
172
+ pr: mapUnitPropTo('paddingRight', halfUnit),
173
+ pt: mapUnitPropTo('paddingTop', halfUnit),
174
+ px: mapDirectionalUnitPropTo('padding', halfUnit, ['Left', 'Right']),
175
+ py: mapDirectionalUnitPropTo('padding', halfUnit, ['Top', 'Bottom']),
176
+ // Color props
177
+ color: mapColorPropTo('color'),
178
+ textColor: mapColorPropTo('color'),
179
+ backgroundColor: mapColorPropTo('backgroundColor'),
180
+ } as const;
181
+
182
+ // Boolean props
183
+ const booleanStyleMap = {
184
+ bold: mapBooleanPropTo('fontWeight', 'bold'),
185
+ fillPositionedParent: (style, value) => {
186
+ if (value) {
187
+ style['position'] = 'absolute';
188
+ style['top'] = 0;
189
+ style['bottom'] = 0;
190
+ style['left'] = 0;
191
+ style['right'] = 0;
192
+ }
193
+ },
194
+ inline: mapBooleanPropTo('display', 'inline-block'),
195
+ italic: mapBooleanPropTo('fontStyle', 'italic'),
196
+ nowrap: mapBooleanPropTo('whiteSpace', 'nowrap'),
197
+ preserveWhitespace: mapBooleanPropTo('whiteSpace', 'pre-wrap'),
198
+ } as const;
199
+
200
+ export const computeBoxProps = (props) => {
201
+ const computedProps: Record<string, any> = {};
202
+ const computedStyles: Record<string, string | number> = {};
203
+
204
+ // Compute props
205
+ for (let propName of Object.keys(props)) {
206
+ if (propName === 'style') {
207
+ continue;
208
+ }
209
+
210
+ const propValue = props[propName];
211
+
212
+ const mapPropToStyle =
213
+ stringStyleMap[propName] || booleanStyleMap[propName];
214
+
215
+ if (mapPropToStyle) {
216
+ mapPropToStyle(computedStyles, propValue);
217
+ } else {
218
+ computedProps[propName] = propValue;
219
+ }
220
+ }
221
+
222
+ // Merge computed styles and any directly provided styles
223
+ computedProps.style = { ...computedStyles, ...props.style };
224
+
225
+ return computedProps;
226
+ };
227
+
228
+ export const computeBoxClassName = (props: BoxProps) => {
229
+ const color = props.textColor || props.color;
230
+ const backgroundColor = props.backgroundColor;
231
+ return classes([
232
+ isColorClass(color) && 'color-' + color,
233
+ isColorClass(backgroundColor) && 'color-bg-' + backgroundColor,
234
+ ]);
235
+ };
236
+
237
+ export const Box = (props: BoxProps & DangerDoNotUse) => {
238
+ const { as = 'div', className, children, ...rest } = props;
239
+
240
+ // Compute class name and styles
241
+ const computedClassName = className
242
+ ? `${className} ${computeBoxClassName(rest)}`
243
+ : computeBoxClassName(rest);
244
+ const computedProps = computeBoxProps(rest);
245
+
246
+ // Render the component
247
+ return createElement(
248
+ typeof as === 'string' ? as : 'div',
249
+ {
250
+ ...computedProps,
251
+ className: computedClassName,
252
+ },
253
+ children
254
+ );
255
+ };