@ultraviolet/plus 0.4.10 → 0.5.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.
Files changed (24) hide show
  1. package/dist/index.d.ts +261 -1
  2. package/dist/src/components/ContentCard/index.js +1 -1
  3. package/dist/src/components/ContentCardGroup/Card.js +41 -11
  4. package/dist/src/components/EstimateCost/Components/CustomUnitInput.js +48 -0
  5. package/dist/src/components/EstimateCost/Components/Item.js +327 -0
  6. package/dist/src/components/EstimateCost/Components/LineThrough.js +15 -0
  7. package/dist/src/components/EstimateCost/Components/NumberInput.js +41 -0
  8. package/dist/src/components/EstimateCost/Components/Region.js +50 -0
  9. package/dist/src/components/EstimateCost/Components/Regular.js +44 -0
  10. package/dist/src/components/EstimateCost/Components/Strong.js +37 -0
  11. package/dist/src/components/EstimateCost/Components/Unit.js +61 -0
  12. package/dist/src/components/EstimateCost/Components/UnitInput.js +122 -0
  13. package/dist/src/components/EstimateCost/Components/Zone.js +50 -0
  14. package/dist/src/components/EstimateCost/EstimateCost.js +126 -0
  15. package/dist/src/components/EstimateCost/EstimateCostContent.js +299 -0
  16. package/dist/src/components/EstimateCost/EstimateCostProvider.js +39 -0
  17. package/dist/src/components/EstimateCost/OverlayComponent.js +139 -0
  18. package/dist/src/components/EstimateCost/OverlayContext.js +19 -0
  19. package/dist/src/components/EstimateCost/componentStyle.js +196 -0
  20. package/dist/src/components/EstimateCost/constants.js +31 -0
  21. package/dist/src/components/EstimateCost/helper.js +23 -0
  22. package/dist/src/components/EstimateCost/locales/en.js +23 -0
  23. package/dist/src/index.js +1 -0
  24. package/package.json +9 -2
@@ -0,0 +1,327 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { css } from '@emotion/react';
3
+ import { Text, Tooltip, Stack, Icon, zoomIn, Badge } from '@ultraviolet/ui';
4
+ import { useMemo, useState, useEffect, useCallback, useId, Children, isValidElement, cloneElement } from 'react';
5
+ import flattenChildren from 'react-flatten-children';
6
+ import { useEstimateCost } from '../EstimateCostProvider.js';
7
+ import { useOverlay } from '../OverlayContext.js';
8
+ import { Cell, StyledDiv, PriceCell, OverlayRow, StyledLeftSide } from '../componentStyle.js';
9
+ import { multiplier, maximumFractionDigitsLong, maximumFractionDigits, MAX_CELL_WIDTH } from '../constants.js';
10
+ import { calculatePrice } from '../helper.js';
11
+ import { jsxs, jsx, Fragment } from '@emotion/react/jsx-runtime';
12
+
13
+ function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
14
+ const TIME_RELATED_UNIT = ['seconds', 'minutes', 'hours', 'days', 'months'];
15
+ const StyledResourceName = /*#__PURE__*/_styled('div', {
16
+ shouldForwardProp: prop => !['isOverlay', 'animated'].includes(prop),
17
+ target: "e1kzy2rr7"
18
+ })("text-align:", _ref => {
19
+ let {
20
+ isOverlay
21
+ } = _ref;
22
+ return isOverlay ? 'initial' : 'right';
23
+ }, ";", _ref2 => {
24
+ let {
25
+ isOverlay,
26
+ animated
27
+ } = _ref2;
28
+ return isOverlay ? /*#__PURE__*/css("height:48px;display:flex;flex-direction:column;-webkit-box-pack:center;justify-content:center;animation:", animated ? /*#__PURE__*/css("800ms ", zoomIn, ";") : '', ";") : null;
29
+ }, ";");
30
+ const StyledBadge = /*#__PURE__*/_styled(Badge, {
31
+ target: "e1kzy2rr6"
32
+ })("margin-left:", _ref3 => {
33
+ let {
34
+ theme
35
+ } = _ref3;
36
+ return theme.space['1'];
37
+ }, ";align-self:center;");
38
+ const StyledText = /*#__PURE__*/_styled(Text, {
39
+ target: "e1kzy2rr5"
40
+ })("margin-left:", _ref4 => {
41
+ let {
42
+ theme
43
+ } = _ref4;
44
+ return theme.space['1'];
45
+ }, ";");
46
+ const MaxWidthText = /*#__PURE__*/_styled(Text, {
47
+ target: "e1kzy2rr4"
48
+ })(process.env.NODE_ENV === "production" ? {
49
+ name: "88bww",
50
+ styles: "max-width:75%"
51
+ } : {
52
+ name: "88bww",
53
+ styles: "max-width:75%",
54
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
55
+ });
56
+ const TextAlignRight = /*#__PURE__*/_styled(Text, {
57
+ target: "e1kzy2rr3"
58
+ })(process.env.NODE_ENV === "production" ? {
59
+ name: "2qga7i",
60
+ styles: "text-align:right"
61
+ } : {
62
+ name: "2qga7i",
63
+ styles: "text-align:right",
64
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
65
+ });
66
+ const StyledTooltip = /*#__PURE__*/_styled(Tooltip, {
67
+ target: "e1kzy2rr2"
68
+ })(process.env.NODE_ENV === "production" ? {
69
+ name: "uaxjgr",
70
+ styles: "vertical-align:text-top"
71
+ } : {
72
+ name: "uaxjgr",
73
+ styles: "vertical-align:text-top",
74
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
75
+ });
76
+ const StyledPriceCell = /*#__PURE__*/_styled(Cell, {
77
+ target: "e1kzy2rr1"
78
+ })(_ref5 => {
79
+ let {
80
+ theme
81
+ } = _ref5;
82
+ return PriceCell(theme);
83
+ }, ";");
84
+ const StyleNoPriceItem = /*#__PURE__*/_styled(Text, {
85
+ target: "e1kzy2rr0"
86
+ })(process.env.NODE_ENV === "production" ? {
87
+ name: "2qga7i",
88
+ styles: "text-align:right"
89
+ } : {
90
+ name: "2qga7i",
91
+ styles: "text-align:right",
92
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
93
+ });
94
+ const Item = _ref6 => {
95
+ let {
96
+ discount = 0,
97
+ priceText,
98
+ discountText,
99
+ label,
100
+ tooltipInfo,
101
+ // Shows an icon with tooltip that contains this text
102
+ subLabel = '',
103
+ // Usually used for showing amount that is free
104
+ price: basePrice = 0,
105
+ // Hourly price for one unit
106
+ monthlyPrice = 0,
107
+ // Price per month
108
+ unit: baseUnit,
109
+ // Can be GB, MB, Node, Queries, etc.
110
+ amount: currentAmount = 1,
111
+ // Current number of items
112
+ onAmountChange,
113
+ amountFree = 0,
114
+ // Amount that is free - offered by company
115
+ maxAmount = 0,
116
+ // Max amount - used for kubernetes for example
117
+ longFractionDigits = false,
118
+ // In case price is really long 0.0000076 - up 7 fraction digits
119
+ noIteration = false,
120
+ // if item is not based on time (ex: download, upload, transfer)
121
+ noIterationText,
122
+ noBorder,
123
+ // remove the border bottom of the item
124
+ noPrice,
125
+ // remove the price on right side of the table
126
+ isDefined = true,
127
+ children = null,
128
+ isFirstElement = false,
129
+ isLastElement = false,
130
+ isPrimaryBackground = false,
131
+ productsCallback,
132
+ iteration: receivedIteration,
133
+ // Object from parent that contains time period (hours, days, months)
134
+ shouldBeHidden = false,
135
+ // Hide element from overlay if screen width is small
136
+ hideFromOverlay = false,
137
+ // Hide element from overlay in any case
138
+ textNotDefined,
139
+ // Text to display in case of not defined value
140
+ animated = false,
141
+ // if true, zoomIn animation is triggered
142
+ tabulation,
143
+ // Increase left padding of the item
144
+ labelTextVariant,
145
+ // To change left cell typography variant
146
+ labelTextProminence,
147
+ // To change left cell typography prominence
148
+ notice // To display a gray text below the label
149
+ } = _ref6;
150
+ const {
151
+ locales,
152
+ formatNumber
153
+ } = useEstimateCost();
154
+ let iteration;
155
+ if (noIteration) {
156
+ iteration = {
157
+ ...(receivedIteration ?? {
158
+ value: 0
159
+ }),
160
+ unit: 'hours'
161
+ };
162
+ } else {
163
+ iteration = receivedIteration;
164
+ }
165
+ const price = useMemo(() => {
166
+ if (monthlyPrice > 0 && basePrice === 0) {
167
+ return monthlyPrice / multiplier.months;
168
+ }
169
+ return basePrice;
170
+ }, [basePrice, monthlyPrice]);
171
+ const unit = useMemo(() => {
172
+ if (!baseUnit) {
173
+ return locales['estimate.cost.units.gb.label'];
174
+ }
175
+ return baseUnit;
176
+ }, [baseUnit, locales]);
177
+ const {
178
+ isOverlay
179
+ } = useOverlay();
180
+ const Row = isOverlay ? OverlayRow : 'tr';
181
+ const Cell$1 = isOverlay ? Cell.withComponent('div', {
182
+ target: "e1kzy2rr8"
183
+ }) : Cell;
184
+ const LeftSide = isOverlay ? 'div' : StyledLeftSide;
185
+ const [amount, setAmount] = useState(currentAmount);
186
+ const [isVariant, setIsVariant] = useState(false);
187
+ useEffect(() => setAmount(currentAmount), [setAmount, currentAmount]);
188
+ useEffect(() => onAmountChange?.(amount), [onAmountChange, amount]);
189
+ const itemCallback = useCallback((localAmount, localIsVariant) => {
190
+ setAmount(localAmount);
191
+ setIsVariant(localIsVariant);
192
+ }, [setAmount, setIsVariant]);
193
+ const id = useId();
194
+
195
+ // We remove Item from object list when Iem component unmount to avoid duplicates
196
+ useEffect(() => () => productsCallback?.remove({
197
+ id
198
+ }), [id, productsCallback]);
199
+ useEffect(() => {
200
+ if (!isOverlay) {
201
+ productsCallback?.add({
202
+ id,
203
+ amount,
204
+ price,
205
+ amountFree,
206
+ isVariant,
207
+ maxAmount,
208
+ noIteration,
209
+ longFractionDigits,
210
+ discount
211
+ });
212
+ }
213
+ }, [price, discount, amount, id, productsCallback, maxAmount, noIteration, isVariant, amountFree, isOverlay, longFractionDigits]);
214
+ const computedItemPrice = useMemo(() => calculatePrice({
215
+ price,
216
+ amount,
217
+ amountFree,
218
+ timeUnit: noIteration ? 'hours' : iteration?.unit ?? 'hours',
219
+ timeAmount: noIteration ? 1 : iteration?.value ?? 1,
220
+ discount
221
+ }), [price, amount, amountFree, iteration, noIteration, discount]);
222
+ const computedMaxItemPrice = useMemo(() => calculatePrice({
223
+ price,
224
+ amount: maxAmount,
225
+ amountFree,
226
+ timeUnit: noIteration ? 'hours' : iteration?.unit ?? 'hours',
227
+ timeAmount: noIteration ? 1 : iteration?.value ?? 1,
228
+ discount
229
+ }), [price, maxAmount, amountFree, iteration, noIteration, discount]);
230
+ const formatMaximumFractionDigits = useMemo(() => {
231
+ if (!iteration?.unit) {
232
+ return undefined;
233
+ }
234
+ return longFractionDigits ? maximumFractionDigitsLong[iteration?.unit] : maximumFractionDigits[iteration?.unit];
235
+ }, [iteration?.unit, longFractionDigits]);
236
+ return jsxs(Row, {
237
+ isFirstElement: isFirstElement,
238
+ shouldBeHidden: shouldBeHidden,
239
+ hideFromOverlay: hideFromOverlay,
240
+ children: [jsx(Cell$1, {
241
+ width: !isOverlay ? MAX_CELL_WIDTH : 'inherit',
242
+ hasBorder: !isLastElement && !noBorder,
243
+ tabulation: tabulation,
244
+ children: jsxs(LeftSide, {
245
+ children: [jsxs(Stack, {
246
+ children: [jsxs(Stack, {
247
+ direction: "row",
248
+ children: [jsx(Text, {
249
+ as: "p",
250
+ variant: labelTextVariant ?? 'body',
251
+ prominence: labelTextProminence ?? 'default',
252
+ children: label
253
+ }), tooltipInfo ? jsx(StyledDiv, {
254
+ children: jsx(StyledTooltip, {
255
+ text: tooltipInfo,
256
+ children: jsx(Icon, {
257
+ name: "help-circle-outline",
258
+ size: 20
259
+ })
260
+ })
261
+ }) : null, subLabel && !isOverlay ? jsx(StyledText, {
262
+ as: "p",
263
+ variant: "body",
264
+ color: "primary",
265
+ italic: true,
266
+ children: subLabel
267
+ }) : null, discount > 0 && discountText ? jsx(StyledBadge, {
268
+ prominence: "strong",
269
+ size: "small",
270
+ sentiment: "warning",
271
+ children: discountText
272
+ }) : null]
273
+ }), notice ? jsx(MaxWidthText, {
274
+ as: "p",
275
+ variant: "caption",
276
+ prominence: "weak",
277
+ children: notice
278
+ }) : null]
279
+ }), jsx(StyledResourceName, {
280
+ isOverlay: isOverlay,
281
+ animated: animated,
282
+ children: isDefined ? Children.map(flattenChildren(children), child => /*#__PURE__*/isValidElement(child) ? /*#__PURE__*/cloneElement(child, {
283
+ itemCallback,
284
+ amount,
285
+ maxAmount,
286
+ unit
287
+ }) : null) : textNotDefined || locales['estimate.cost.notDefined']
288
+ })]
289
+ })
290
+ }), !isOverlay ? jsx(StyledPriceCell, {
291
+ hasBorder: !isLastElement && !noBorder,
292
+ primary: isPrimaryBackground,
293
+ children: !noPrice ? jsxs(Fragment, {
294
+ children: [jsxs(StyleNoPriceItem, {
295
+ as: "p",
296
+ variant: noIterationText ? 'headingSmall' : 'bodyStrong',
297
+ prominence: computedItemPrice === 0 && computedMaxItemPrice === 0 ? 'weak' : 'default',
298
+ color: computedItemPrice === 0 && computedMaxItemPrice === 0 ? 'neutral' : 'primary',
299
+ children: [priceText, !priceText ? formatNumber(computedItemPrice, {
300
+ maximumFractionDigits: formatMaximumFractionDigits
301
+ }) : null, noIterationText ? jsxs(Text, {
302
+ sentiment: "primary",
303
+ as: "span",
304
+ variant: "bodySmall",
305
+ children: ["/", noIterationText]
306
+ }) : null, !priceText && computedMaxItemPrice > 0 ? ` - ${formatNumber(computedMaxItemPrice, {
307
+ maximumFractionDigits: formatMaximumFractionDigits
308
+ })}` : null]
309
+ }), amount - amountFree > 1 && computedItemPrice > 0 || maxAmount > 0 && computedMaxItemPrice > 0 ? jsxs(TextAlignRight, {
310
+ as: "p",
311
+ variant: "body",
312
+ children: [formatNumber(calculatePrice({
313
+ price,
314
+ amount: 1,
315
+ timeUnit: 'hours',
316
+ timeAmount: 1,
317
+ discount
318
+ }), {
319
+ maximumFractionDigits: longFractionDigits ? maximumFractionDigitsLong.hours : maximumFractionDigits.hours
320
+ }), TIME_RELATED_UNIT.includes(unit) ? locales[`estimate.cost.units.${unit}.label`].toLowerCase() : `/${unit}`, !noIteration ? `/${locales['estimate.cost.units.hours.label'].toLowerCase()}` : null]
321
+ }) : null]
322
+ }) : null
323
+ }) : null]
324
+ });
325
+ };
326
+
327
+ export { Item };
@@ -0,0 +1,15 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { css } from '@emotion/react';
3
+
4
+ const LineThrough = /*#__PURE__*/_styled('span', {
5
+ shouldForwardProp: prop => !['isActive'].includes(prop),
6
+ target: "e1d1k6i0"
7
+ })(_ref => {
8
+ let {
9
+ isActive,
10
+ theme
11
+ } = _ref;
12
+ return isActive ? /*#__PURE__*/css("text-decoration-line:line-through;text-decoration-color:", theme.colors.warning.border, ";") : null;
13
+ }, ";");
14
+
15
+ export { LineThrough };
@@ -0,0 +1,41 @@
1
+ import { NumberInput as NumberInput$1 } from '@ultraviolet/ui';
2
+ import { useEffect } from 'react';
3
+ import { useOverlay } from '../OverlayContext.js';
4
+ import { ItemResourceName } from '../componentStyle.js';
5
+ import { Regular } from './Regular.js';
6
+ import { jsx } from '@emotion/react/jsx-runtime';
7
+
8
+ const NumberInput = _ref => {
9
+ let {
10
+ amount,
11
+ minValue = 0,
12
+ maxValue = 100,
13
+ getAmountValue,
14
+ itemCallback
15
+ } = _ref;
16
+ const {
17
+ isOverlay
18
+ } = useOverlay();
19
+ useEffect(() => {
20
+ getAmountValue?.(amount);
21
+ }, [getAmountValue, amount]);
22
+ return isOverlay ? jsx(ItemResourceName, {
23
+ animated: false,
24
+ children: jsx(Regular, {
25
+ children: amount
26
+ })
27
+ }) : jsx(NumberInput$1, {
28
+ minValue: minValue,
29
+ maxValue: maxValue,
30
+ size: "small",
31
+ onChange: value => {
32
+ if (typeof value === 'number' && itemCallback) {
33
+ itemCallback(value, true);
34
+ getAmountValue?.(value);
35
+ }
36
+ },
37
+ value: amount
38
+ });
39
+ };
40
+
41
+ export { NumberInput };
@@ -0,0 +1,50 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { useEstimateCost } from '../EstimateCostProvider.js';
3
+ import { Item } from './Item.js';
4
+ import { Strong } from './Strong.js';
5
+ import { jsx, jsxs } from '@emotion/react/jsx-runtime';
6
+
7
+ const StyledImage = /*#__PURE__*/_styled("img", {
8
+ target: "exu7lwu0"
9
+ })("width:15px;margin-right:", _ref => {
10
+ let {
11
+ theme
12
+ } = _ref;
13
+ return theme.space['1'];
14
+ }, ";");
15
+ const Region = _ref2 => {
16
+ let {
17
+ label,
18
+ image,
19
+ shouldBeHidden = false,
20
+ priceText,
21
+ animated = false,
22
+ isFirstElement,
23
+ isLastElement,
24
+ productsCallback,
25
+ iteration,
26
+ discount
27
+ } = _ref2;
28
+ const {
29
+ locales
30
+ } = useEstimateCost();
31
+ return jsx(Item, {
32
+ label: locales['estimate.cost.region.label'],
33
+ shouldBeHidden: shouldBeHidden,
34
+ priceText: priceText,
35
+ animated: animated,
36
+ isFirstElement: isFirstElement,
37
+ isLastElement: isLastElement,
38
+ productsCallback: productsCallback,
39
+ iteration: iteration,
40
+ discount: discount,
41
+ children: jsxs(Strong, {
42
+ children: [jsx(StyledImage, {
43
+ alt: label,
44
+ src: image
45
+ }), label]
46
+ })
47
+ });
48
+ };
49
+
50
+ export { Region };
@@ -0,0 +1,44 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { css } from '@emotion/react';
3
+ import { useOverlay } from '../OverlayContext.js';
4
+ import { jsx } from '@emotion/react/jsx-runtime';
5
+
6
+ const StyledRegular = /*#__PURE__*/_styled('div', {
7
+ shouldForwardProp: prop => !['variant', 'isOverlay'].includes(prop),
8
+ target: "e1l9k4qo0"
9
+ })("display:", _ref => {
10
+ let {
11
+ isOverlay
12
+ } = _ref;
13
+ return isOverlay ? 'flex' : 'inline-flex';
14
+ }, ";max-width:500px;align-items:center;font-size:16px;color:", _ref2 => {
15
+ let {
16
+ theme
17
+ } = _ref2;
18
+ return theme.colors.neutral.textStrong;
19
+ }, ";margin-right:4px;", _ref3 => {
20
+ let {
21
+ theme,
22
+ variant
23
+ } = _ref3;
24
+ return variant === 'small' && /*#__PURE__*/css("display:block;font-size:14px;line-height:8px;color:", theme.colors.neutral.text, ";");
25
+ }, ";");
26
+ const Regular = _ref4 => {
27
+ let {
28
+ variant = 'normal',
29
+ isDisabledOnOverlay = false,
30
+ children = null,
31
+ className
32
+ } = _ref4;
33
+ const {
34
+ isOverlay
35
+ } = useOverlay();
36
+ return !isDisabledOnOverlay || !isOverlay ? jsx(StyledRegular, {
37
+ className: className,
38
+ variant: variant,
39
+ isOverlay: isOverlay,
40
+ children: children
41
+ }) : null;
42
+ };
43
+
44
+ export { Regular };
@@ -0,0 +1,37 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { Regular } from './Regular.js';
3
+ import { jsx } from '@emotion/react/jsx-runtime';
4
+
5
+ const StyledStrong = /*#__PURE__*/_styled(Regular, {
6
+ shouldForwardProp: prop => !['variant'].includes(prop),
7
+ target: "e1bhvxf60"
8
+ })("display:inline-flex;align-items:center;font-size:", _ref => {
9
+ let {
10
+ variant
11
+ } = _ref;
12
+ return variant === 'big' ? 24 : 16;
13
+ }, "px;", _ref2 => {
14
+ let {
15
+ variant
16
+ } = _ref2;
17
+ return variant === 'capitalized' ? `text-transform: capitalize;` : '';
18
+ }, " color:", _ref3 => {
19
+ let {
20
+ theme
21
+ } = _ref3;
22
+ return theme.colors.neutral.textStrong;
23
+ }, ";font-weight:500;margin-right:4px;");
24
+ const Strong = _ref4 => {
25
+ let {
26
+ variant = 'normal',
27
+ children = null,
28
+ isDisabledOnOverlay = false
29
+ } = _ref4;
30
+ return jsx(StyledStrong, {
31
+ variant: variant,
32
+ isDisabledOnOverlay: isDisabledOnOverlay,
33
+ children: children
34
+ });
35
+ };
36
+
37
+ export { Strong, StyledStrong };
@@ -0,0 +1,61 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { TextInput } from '@ultraviolet/ui';
3
+ import { useState, useEffect } from 'react';
4
+ import { useOverlay } from '../OverlayContext.js';
5
+ import { ItemResourceName } from '../componentStyle.js';
6
+ import { Regular } from './Regular.js';
7
+ import { jsx } from '@emotion/react/jsx-runtime';
8
+
9
+ function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
10
+ const StyledTextInput = /*#__PURE__*/_styled(TextInput, {
11
+ target: "e1pr25uw0"
12
+ })(process.env.NODE_ENV === "production" ? {
13
+ name: "l1y63n",
14
+ styles: "input[type='number']::-webkit-inner-spin-button,input[type='number']::-webkit-outer-spin-button{-webkit-appearance:none;margin:0;}input[type='number']{-moz-appearance:textfield;}"
15
+ } : {
16
+ name: "l1y63n",
17
+ styles: "input[type='number']::-webkit-inner-spin-button,input[type='number']::-webkit-outer-spin-button{-webkit-appearance:none;margin:0;}input[type='number']{-moz-appearance:textfield;}",
18
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
19
+ });
20
+ const Unit = _ref => {
21
+ let {
22
+ amount,
23
+ itemCallback,
24
+ getAmountValue,
25
+ unit
26
+ } = _ref;
27
+ const {
28
+ isOverlay
29
+ } = useOverlay();
30
+ const [capacity, setCapacity] = useState(amount === 0 ? undefined : amount);
31
+ useEffect(() => {
32
+ itemCallback?.(capacity, true);
33
+ getAmountValue?.(capacity);
34
+ }, [getAmountValue, itemCallback, capacity]);
35
+ return isOverlay ? jsx(ItemResourceName, {
36
+ animated: false,
37
+ children: jsx(Regular, {
38
+ children: capacity
39
+ })
40
+ }) :
41
+ // 120px is arbitrary, just to avoid full width input (ugly) nor too small input.
42
+ jsx("div", {
43
+ style: {
44
+ width: '120px'
45
+ },
46
+ children: jsx(StyledTextInput, {
47
+ type: "number",
48
+ size: "small",
49
+ unit: unit,
50
+ placeholder: "00",
51
+ name: "capacity",
52
+ value: capacity?.toString(),
53
+ onChange: capacityText => {
54
+ setCapacity(Number(capacityText) < 0 ? 0 : Number(capacityText));
55
+ getAmountValue?.(capacity);
56
+ }
57
+ })
58
+ });
59
+ };
60
+
61
+ export { Unit };
@@ -0,0 +1,122 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { Stack, TextInput, SelectInput } from '@ultraviolet/ui';
3
+ import { jsxs, jsx } from '@emotion/react/jsx-runtime';
4
+
5
+ const sizesHeight = {
6
+ large: 48,
7
+ medium: 40,
8
+ small: 32
9
+ };
10
+ const CustomTextInput = /*#__PURE__*/_styled(TextInput, {
11
+ target: "epio27v1"
12
+ })("input{border-radius:", _ref => {
13
+ let {
14
+ theme
15
+ } = _ref;
16
+ return theme.radii.default;
17
+ }, " 0 0 ", _ref2 => {
18
+ let {
19
+ theme
20
+ } = _ref2;
21
+ return theme.radii.default;
22
+ }, ";min-width:60px;border-right:0;&:hover,&:focus{text-decoration:none;border-right-width:1px;border-right-style:solid;border-color:", _ref3 => {
23
+ let {
24
+ theme
25
+ } = _ref3;
26
+ return theme.colors.primary.borderWeak;
27
+ }, ";}}input[type='number']::-webkit-inner-spin-button,input[type='number']::-webkit-outer-spin-button{-webkit-appearance:none;margin:0;}input[type='number']{-moz-appearance:textfield;}");
28
+ const CustomSelectInput = /*#__PURE__*/_styled(SelectInput, {
29
+ target: "epio27v0"
30
+ })(_ref4 => {
31
+ let {
32
+ width
33
+ } = _ref4;
34
+ return width && `width: ${width}px;`;
35
+ }, " ", _ref5 => {
36
+ let {
37
+ height
38
+ } = _ref5;
39
+ return height && `height: ${height}px;`;
40
+ }, " &:hover,&:focus{text-decoration:none;border-color:", _ref6 => {
41
+ let {
42
+ theme
43
+ } = _ref6;
44
+ return theme.colors.primary.borderWeak;
45
+ }, ";box-shadow:none;}");
46
+ const customSelectStyle = height => () => ({
47
+ control: {
48
+ borderBottomLeftRadius: 0,
49
+ borderTopLeftRadius: 0,
50
+ boxShadow: 'none',
51
+ height,
52
+ minHeight: height
53
+ },
54
+ singleValue: {
55
+ marginTop: 0
56
+ }
57
+ });
58
+ const UnitInput = _ref7 => {
59
+ let {
60
+ name = '',
61
+ maxValue = 99999,
62
+ minValue = 1,
63
+ size = 'medium',
64
+ placeholder = '0',
65
+ onChange,
66
+ onChangeUnitValue,
67
+ value,
68
+ unitValue,
69
+ textBoxWidth = 100,
70
+ selectInputWidth = 200,
71
+ disabled = false,
72
+ options,
73
+ className,
74
+ notice,
75
+ label,
76
+ required,
77
+ valueError,
78
+ unitError,
79
+ type = 'number',
80
+ 'data-testid': dataTestId
81
+ } = _ref7;
82
+ return jsxs(Stack, {
83
+ direction: "row",
84
+ "data-testid": dataTestId,
85
+ children: [jsx(CustomTextInput, {
86
+ height: sizesHeight[size],
87
+ width: textBoxWidth,
88
+ type: type,
89
+ name: `${name}-value`,
90
+ max: maxValue,
91
+ min: minValue,
92
+ required: required,
93
+ value: value,
94
+ placeholder: placeholder,
95
+ onChange: input => {
96
+ const numericValue = input ? parseInt(input, 10) : minValue;
97
+ onChange(numericValue);
98
+ },
99
+ className: className,
100
+ disabled: disabled,
101
+ notice: notice,
102
+ label: label,
103
+ error: valueError
104
+ }), jsx(CustomSelectInput, {
105
+ width: selectInputWidth,
106
+ noTopLabel: true,
107
+ height: sizesHeight[size],
108
+ id: `${name}-unit`,
109
+ name: `${name}-unit`,
110
+ onChange: newValue => {
111
+ onChangeUnitValue(newValue.value);
112
+ },
113
+ error: unitError,
114
+ value: options.find(option => option.value === unitValue) || options[0],
115
+ options: options,
116
+ customStyle: customSelectStyle(sizesHeight[size]),
117
+ disabled: disabled || options.length === 1
118
+ })]
119
+ });
120
+ };
121
+
122
+ export { UnitInput, sizesHeight };