@transferwise/components 0.0.0-experimental-eaf43c2 → 0.0.0-experimental-6730b89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/avatarLayout/AvatarLayout.js.map +1 -1
- package/build/avatarLayout/AvatarLayout.mjs.map +1 -1
- package/build/avatarView/AvatarView.js +8 -4
- package/build/avatarView/AvatarView.js.map +1 -1
- package/build/avatarView/AvatarView.mjs +8 -4
- package/build/avatarView/AvatarView.mjs.map +1 -1
- package/build/avatarView/{NotificationDot.js → Dot.js} +14 -12
- package/build/avatarView/Dot.js.map +1 -0
- package/build/avatarView/{NotificationDot.mjs → Dot.mjs} +14 -12
- package/build/avatarView/Dot.mjs.map +1 -0
- package/build/i18n/en.json +0 -2
- package/build/i18n/en.json.js +0 -2
- package/build/i18n/en.json.js.map +1 -1
- package/build/i18n/en.json.mjs +0 -2
- package/build/i18n/en.json.mjs.map +1 -1
- package/build/index.js +0 -2
- package/build/index.js.map +1 -1
- package/build/index.mjs +0 -1
- package/build/index.mjs.map +1 -1
- package/build/main.css +17 -69
- package/build/styles/avatarView/AvatarView.css +17 -11
- package/build/styles/avatarView/Dot.css +26 -0
- package/build/styles/main.css +17 -69
- package/build/types/avatarLayout/AvatarLayout.d.ts +1 -1
- package/build/types/avatarLayout/AvatarLayout.d.ts.map +1 -1
- package/build/types/avatarView/AvatarView.d.ts +4 -1
- package/build/types/avatarView/AvatarView.d.ts.map +1 -1
- package/build/types/avatarView/Dot.d.ts +8 -0
- package/build/types/avatarView/Dot.d.ts.map +1 -0
- package/build/types/index.d.ts +0 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/test-utils/index.d.ts +0 -4
- package/build/types/test-utils/index.d.ts.map +1 -1
- package/package.json +2 -3
- package/src/avatarLayout/AvatarLayout.tsx +1 -1
- package/src/avatarView/AvatarView.css +17 -11
- package/src/avatarView/AvatarView.less +1 -1
- package/src/avatarView/AvatarView.story.tsx +37 -0
- package/src/avatarView/AvatarView.tsx +13 -6
- package/src/avatarView/Dot.css +26 -0
- package/src/avatarView/Dot.less +31 -0
- package/src/avatarView/Dot.tsx +42 -0
- package/src/i18n/en.json +0 -2
- package/src/index.ts +0 -2
- package/src/listItem/AvatarView/ListItemAvatarView.story.tsx +69 -2
- package/src/main.css +17 -69
- package/src/main.less +0 -1
- package/src/ssr.spec.tsx +0 -1
- package/build/avatarView/NotificationDot.js.map +0 -1
- package/build/avatarView/NotificationDot.mjs.map +0 -1
- package/build/moneyInputField/AmountInput.js +0 -284
- package/build/moneyInputField/AmountInput.js.map +0 -1
- package/build/moneyInputField/AmountInput.mjs +0 -282
- package/build/moneyInputField/AmountInput.mjs.map +0 -1
- package/build/moneyInputField/AnimatedNumber.js +0 -50
- package/build/moneyInputField/AnimatedNumber.js.map +0 -1
- package/build/moneyInputField/AnimatedNumber.mjs +0 -48
- package/build/moneyInputField/AnimatedNumber.mjs.map +0 -1
- package/build/moneyInputField/Chevron.js +0 -33
- package/build/moneyInputField/Chevron.js.map +0 -1
- package/build/moneyInputField/Chevron.mjs +0 -31
- package/build/moneyInputField/Chevron.mjs.map +0 -1
- package/build/moneyInputField/CurrencySelector.js +0 -160
- package/build/moneyInputField/CurrencySelector.js.map +0 -1
- package/build/moneyInputField/CurrencySelector.mjs +0 -157
- package/build/moneyInputField/CurrencySelector.mjs.map +0 -1
- package/build/moneyInputField/MoneyInputField.js +0 -113
- package/build/moneyInputField/MoneyInputField.js.map +0 -1
- package/build/moneyInputField/MoneyInputField.messages.js +0 -17
- package/build/moneyInputField/MoneyInputField.messages.js.map +0 -1
- package/build/moneyInputField/MoneyInputField.messages.mjs +0 -13
- package/build/moneyInputField/MoneyInputField.messages.mjs.map +0 -1
- package/build/moneyInputField/MoneyInputField.mjs +0 -109
- package/build/moneyInputField/MoneyInputField.mjs.map +0 -1
- package/build/moneyInputField/useFocus.js +0 -37
- package/build/moneyInputField/useFocus.js.map +0 -1
- package/build/moneyInputField/useFocus.mjs +0 -35
- package/build/moneyInputField/useFocus.mjs.map +0 -1
- package/build/moneyInputField/useInputStyle.js +0 -71
- package/build/moneyInputField/useInputStyle.js.map +0 -1
- package/build/moneyInputField/useInputStyle.mjs +0 -69
- package/build/moneyInputField/useInputStyle.mjs.map +0 -1
- package/build/moneyInputField/utils.js +0 -87
- package/build/moneyInputField/utils.js.map +0 -1
- package/build/moneyInputField/utils.mjs +0 -78
- package/build/moneyInputField/utils.mjs.map +0 -1
- package/build/styles/avatarView/NotificationDot.css +0 -20
- package/build/styles/moneyInputField/AmountInput.css +0 -32
- package/build/styles/moneyInputField/Chevron.css +0 -12
- package/build/styles/moneyInputField/CurrencySelector.css +0 -6
- package/build/styles/moneyInputField/MoneyInputField.css +0 -58
- package/build/types/avatarView/NotificationDot.d.ts +0 -8
- package/build/types/avatarView/NotificationDot.d.ts.map +0 -1
- package/build/types/moneyInputField/AmountInput.d.ts +0 -13
- package/build/types/moneyInputField/AmountInput.d.ts.map +0 -1
- package/build/types/moneyInputField/AnimatedNumber.d.ts +0 -9
- package/build/types/moneyInputField/AnimatedNumber.d.ts.map +0 -1
- package/build/types/moneyInputField/Chevron.d.ts +0 -6
- package/build/types/moneyInputField/Chevron.d.ts.map +0 -1
- package/build/types/moneyInputField/CurrencySelector.d.ts +0 -30
- package/build/types/moneyInputField/CurrencySelector.d.ts.map +0 -1
- package/build/types/moneyInputField/MoneyInputField.d.ts +0 -30
- package/build/types/moneyInputField/MoneyInputField.d.ts.map +0 -1
- package/build/types/moneyInputField/MoneyInputField.messages.d.ts +0 -12
- package/build/types/moneyInputField/MoneyInputField.messages.d.ts.map +0 -1
- package/build/types/moneyInputField/index.d.ts +0 -3
- package/build/types/moneyInputField/index.d.ts.map +0 -1
- package/build/types/moneyInputField/useFocus.d.ts +0 -7
- package/build/types/moneyInputField/useFocus.d.ts.map +0 -1
- package/build/types/moneyInputField/useInputStyle.d.ts +0 -10
- package/build/types/moneyInputField/useInputStyle.d.ts.map +0 -1
- package/build/types/moneyInputField/useSelectionRange.d.ts +0 -10
- package/build/types/moneyInputField/useSelectionRange.d.ts.map +0 -1
- package/build/types/moneyInputField/utils.d.ts +0 -22
- package/build/types/moneyInputField/utils.d.ts.map +0 -1
- package/src/avatarView/NotificationDot.css +0 -20
- package/src/avatarView/NotificationDot.less +0 -24
- package/src/avatarView/NotificationDot.tsx +0 -35
- package/src/moneyInputField/AmountInput.css +0 -32
- package/src/moneyInputField/AmountInput.less +0 -43
- package/src/moneyInputField/AmountInput.tsx +0 -355
- package/src/moneyInputField/AnimatedNumber.tsx +0 -40
- package/src/moneyInputField/Chevron.css +0 -12
- package/src/moneyInputField/Chevron.less +0 -13
- package/src/moneyInputField/Chevron.tsx +0 -35
- package/src/moneyInputField/CurrencySelector.css +0 -6
- package/src/moneyInputField/CurrencySelector.less +0 -7
- package/src/moneyInputField/CurrencySelector.tsx +0 -219
- package/src/moneyInputField/MoneyInputField.css +0 -58
- package/src/moneyInputField/MoneyInputField.less +0 -13
- package/src/moneyInputField/MoneyInputField.messages.ts +0 -13
- package/src/moneyInputField/MoneyInputField.story.tsx +0 -188
- package/src/moneyInputField/MoneyInputField.tsx +0 -123
- package/src/moneyInputField/index.ts +0 -2
- package/src/moneyInputField/useFocus.ts +0 -35
- package/src/moneyInputField/useInputStyle.ts +0 -85
- package/src/moneyInputField/useSelectionRange.ts +0 -23
- package/src/moneyInputField/utils.spec.ts +0 -114
- package/src/moneyInputField/utils.ts +0 -116
package/src/index.ts
CHANGED
|
@@ -62,7 +62,6 @@ export type {
|
|
|
62
62
|
CurrencyOptionItem,
|
|
63
63
|
MoneyInputProps,
|
|
64
64
|
} from './moneyInput';
|
|
65
|
-
export type { MoneyInputFieldProps } from './moneyInputField';
|
|
66
65
|
export type { NavigationOptionListProps } from './navigationOptionsList';
|
|
67
66
|
export type { NavigationOptionProps } from './navigationOption/NavigationOption';
|
|
68
67
|
export type { OverlayHeaderProps } from './overlayHeader';
|
|
@@ -189,7 +188,6 @@ export { default as Markdown } from './markdown';
|
|
|
189
188
|
export { default as Modal } from './modal';
|
|
190
189
|
export { default as Money } from './money';
|
|
191
190
|
export { default as MoneyInput } from './moneyInput';
|
|
192
|
-
export { default as MoneyInputField } from './moneyInputField';
|
|
193
191
|
export { default as NavigationOption } from './navigationOption';
|
|
194
192
|
export { default as NavigationOptionsList } from './navigationOptionsList';
|
|
195
193
|
export { default as Nudge } from './nudge';
|
|
@@ -62,6 +62,7 @@ export default {
|
|
|
62
62
|
selected: false,
|
|
63
63
|
badge: { type: 'action' },
|
|
64
64
|
notification: false,
|
|
65
|
+
dot: undefined,
|
|
65
66
|
profileName: undefined,
|
|
66
67
|
profileType: undefined,
|
|
67
68
|
imgSrc: undefined,
|
|
@@ -92,6 +93,11 @@ export default {
|
|
|
92
93
|
control: 'boolean',
|
|
93
94
|
description: 'Shows notification dot',
|
|
94
95
|
},
|
|
96
|
+
dot: {
|
|
97
|
+
control: 'select',
|
|
98
|
+
options: ['notification', 'online'],
|
|
99
|
+
description: 'Dot variant',
|
|
100
|
+
},
|
|
95
101
|
selected: {
|
|
96
102
|
control: 'boolean',
|
|
97
103
|
description: 'Toggles selected state',
|
|
@@ -263,6 +269,7 @@ export const Notification: Story = {
|
|
|
263
269
|
'profileType',
|
|
264
270
|
'size',
|
|
265
271
|
'notification',
|
|
272
|
+
'dot',
|
|
266
273
|
'selected',
|
|
267
274
|
]),
|
|
268
275
|
render: (args) => {
|
|
@@ -286,6 +293,52 @@ export const Notification: Story = {
|
|
|
286
293
|
},
|
|
287
294
|
};
|
|
288
295
|
|
|
296
|
+
/**
|
|
297
|
+
* Similarly, AvatarView also support an online dot, which also adjusts to the Avatar's size. <br />
|
|
298
|
+
* **NB:** You cannot use online and badge at the same time – badge will always take precedence over online.
|
|
299
|
+
*/
|
|
300
|
+
export const Online: Story = {
|
|
301
|
+
tags: ['early-access'],
|
|
302
|
+
parameters: {
|
|
303
|
+
docs: {
|
|
304
|
+
canvas: {
|
|
305
|
+
sourceState: 'hidden',
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
args: {
|
|
310
|
+
badge: undefined,
|
|
311
|
+
},
|
|
312
|
+
argTypes: hideControls([
|
|
313
|
+
'profileName',
|
|
314
|
+
'imgSrc',
|
|
315
|
+
'profileType',
|
|
316
|
+
'size',
|
|
317
|
+
'notification',
|
|
318
|
+
'dot',
|
|
319
|
+
'selected',
|
|
320
|
+
]),
|
|
321
|
+
render: (args) => {
|
|
322
|
+
return (
|
|
323
|
+
<List>
|
|
324
|
+
{SIZES.map((size) => (
|
|
325
|
+
<ListItem
|
|
326
|
+
key={size}
|
|
327
|
+
title={`Size ${size}`}
|
|
328
|
+
subtitle={lorem10}
|
|
329
|
+
media={
|
|
330
|
+
<ListItem.AvatarView {...args} size={size} dot="online">
|
|
331
|
+
<Taxi />
|
|
332
|
+
</ListItem.AvatarView>
|
|
333
|
+
}
|
|
334
|
+
control={CONTROLS.iconButton}
|
|
335
|
+
/>
|
|
336
|
+
))}
|
|
337
|
+
</List>
|
|
338
|
+
);
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
|
|
289
342
|
/**
|
|
290
343
|
* AvatarView supports different type of badges for additional context and information. <br />
|
|
291
344
|
* Refer to the [design documentation](https://wise.design/components/avatar#:~:text=support%20the%20information.-,With%20badge,-Badges%20contain%20additional) for details.
|
|
@@ -294,7 +347,14 @@ export const Badges: Story = {
|
|
|
294
347
|
args: {
|
|
295
348
|
imgSrc: '../avatar-square-dude.webp',
|
|
296
349
|
},
|
|
297
|
-
argTypes: hideControls([
|
|
350
|
+
argTypes: hideControls([
|
|
351
|
+
'profileName',
|
|
352
|
+
'imgSrc',
|
|
353
|
+
'profileType',
|
|
354
|
+
'notification',
|
|
355
|
+
'dot',
|
|
356
|
+
'selected',
|
|
357
|
+
]),
|
|
298
358
|
parameters: {
|
|
299
359
|
docs: {
|
|
300
360
|
canvas: {
|
|
@@ -323,7 +383,14 @@ export const Badges: Story = {
|
|
|
323
383
|
* AvatarView supports selected state for interactive contexts.
|
|
324
384
|
*/
|
|
325
385
|
export const Selected: Story = {
|
|
326
|
-
argTypes: hideControls([
|
|
386
|
+
argTypes: hideControls([
|
|
387
|
+
'profileName',
|
|
388
|
+
'imgSrc',
|
|
389
|
+
'profileType',
|
|
390
|
+
'notification',
|
|
391
|
+
'dot',
|
|
392
|
+
'selected',
|
|
393
|
+
]),
|
|
327
394
|
render: (args) => {
|
|
328
395
|
return (
|
|
329
396
|
<List>
|
package/src/main.css
CHANGED
|
@@ -586,26 +586,32 @@
|
|
|
586
586
|
.wds-inline-prompt.wds-inline-prompt--warning:has(a, button):active {
|
|
587
587
|
background-color: color-mix(in srgb, var(--color-sentiment-warning-secondary) 84%, var(--color-sentiment-warning-primary));
|
|
588
588
|
}
|
|
589
|
-
.np-
|
|
590
|
-
--np-
|
|
589
|
+
.np-dot {
|
|
590
|
+
--np-dot-size: 14px;
|
|
591
591
|
position: relative;
|
|
592
592
|
display: inline-block;
|
|
593
593
|
}
|
|
594
|
-
.np-
|
|
595
|
-
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-
|
|
596
|
-
mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-
|
|
597
|
-
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-
|
|
598
|
-
mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-
|
|
594
|
+
.np-dot-mask {
|
|
595
|
+
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
596
|
+
mask-image: radial-gradient(circle at bottom calc(100% - (var(--np-dot-size) / 2)) left calc(100% - (var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
597
|
+
-webkit-mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
598
|
+
mask-image: radial-gradient(circle at bottom calc(100% - calc(var(--np-dot-size) / 2)) left calc(100% - calc(var(--np-dot-size) / 2)), transparent 0, transparent calc(var(--np-dot-size) / 2 + var(--np-dot-offset)), black 0);
|
|
599
599
|
}
|
|
600
|
-
.np-
|
|
600
|
+
.np-dot-badge {
|
|
601
601
|
position: absolute;
|
|
602
|
-
width: var(--np-
|
|
603
|
-
height: var(--np-
|
|
604
|
-
background-color: var(--color-sentiment-negative);
|
|
602
|
+
width: var(--np-dot-size);
|
|
603
|
+
height: var(--np-dot-size);
|
|
605
604
|
border-radius: 9999px;
|
|
606
605
|
border-radius: var(--radius-full);
|
|
607
606
|
right: 0;
|
|
608
607
|
}
|
|
608
|
+
.np-dot-badge-notification {
|
|
609
|
+
background-color: var(--color-sentiment-negative);
|
|
610
|
+
}
|
|
611
|
+
.np-dot-badge-online {
|
|
612
|
+
background-color: #00a2dd;
|
|
613
|
+
background-color: var(--color-interactive-accent);
|
|
614
|
+
}
|
|
609
615
|
.np-avatar-view .np-avatar-view-content {
|
|
610
616
|
color: #37517e;
|
|
611
617
|
color: var(--color-content-primary);
|
|
@@ -4441,64 +4447,6 @@ button.np-link {
|
|
|
4441
4447
|
box-shadow: inset 0 0 0 1px #c9cbce !important;
|
|
4442
4448
|
box-shadow: inset 0 0 0 1px var(--color-interactive-secondary) !important;
|
|
4443
4449
|
}
|
|
4444
|
-
.wds-amount-input-container {
|
|
4445
|
-
width: 100%;
|
|
4446
|
-
}
|
|
4447
|
-
.wds-amount-input-input-container {
|
|
4448
|
-
display: flex;
|
|
4449
|
-
justify-content: right;
|
|
4450
|
-
width: 100%;
|
|
4451
|
-
transition: font-size 0.4s cubic-bezier(0.3, 0, 0.1, 1), height 0.4s cubic-bezier(0.3, 0, 0.1, 1), margin-top 0.4s cubic-bezier(0.3, 0, 0.1, 1), color 0.4s ease;
|
|
4452
|
-
color: var(--color-interactive-primary);
|
|
4453
|
-
overflow: hidden;
|
|
4454
|
-
margin-bottom: 0 !important;
|
|
4455
|
-
}
|
|
4456
|
-
@media (prefers-reduced-motion: reduce) {
|
|
4457
|
-
.wds-amount-input-input-container {
|
|
4458
|
-
transition: none;
|
|
4459
|
-
}
|
|
4460
|
-
}
|
|
4461
|
-
.wds-amount-input-input {
|
|
4462
|
-
border: none;
|
|
4463
|
-
outline: none;
|
|
4464
|
-
flex-grow: 1;
|
|
4465
|
-
text-align: right;
|
|
4466
|
-
background-color: transparent;
|
|
4467
|
-
}
|
|
4468
|
-
.wds-amount-input-input:focus-visible {
|
|
4469
|
-
outline: none;
|
|
4470
|
-
}
|
|
4471
|
-
.wds-amount-input-placeholder {
|
|
4472
|
-
flex-grow: 0;
|
|
4473
|
-
display: flex;
|
|
4474
|
-
align-items: center;
|
|
4475
|
-
}
|
|
4476
|
-
.wds-currency-selector:disabled {
|
|
4477
|
-
opacity: 1 !important;
|
|
4478
|
-
cursor: auto !important;
|
|
4479
|
-
cursor: initial !important;
|
|
4480
|
-
mix-blend-mode: initial !important;
|
|
4481
|
-
}
|
|
4482
|
-
.wds-chevron-container {
|
|
4483
|
-
width: 32px;
|
|
4484
|
-
width: var(--size-32);
|
|
4485
|
-
overflow: hidden;
|
|
4486
|
-
color: var(--color-interactive-primary);
|
|
4487
|
-
margin-left: 8px;
|
|
4488
|
-
margin-left: var(--size-8);
|
|
4489
|
-
transition: width 0.3s ease;
|
|
4490
|
-
}
|
|
4491
|
-
.wds-chevron-hidden {
|
|
4492
|
-
width: 0;
|
|
4493
|
-
}
|
|
4494
|
-
.wds-money-input-field-currency-selector {
|
|
4495
|
-
flex-shrink: 0;
|
|
4496
|
-
margin-right: 24px;
|
|
4497
|
-
margin-right: var(--size-24);
|
|
4498
|
-
}
|
|
4499
|
-
.wds-money-input-field-chevron {
|
|
4500
|
-
transform: translateY(-5%);
|
|
4501
|
-
}
|
|
4502
4450
|
.np-navigation-option {
|
|
4503
4451
|
-webkit-text-decoration: none;
|
|
4504
4452
|
text-decoration: none;
|
package/src/main.less
CHANGED
|
@@ -51,7 +51,6 @@
|
|
|
51
51
|
@import "./logo/Logo.less";
|
|
52
52
|
@import "./modal/Modal.less";
|
|
53
53
|
@import "./moneyInput/MoneyInput.less";
|
|
54
|
-
@import "./moneyInputField/MoneyInputField.less";
|
|
55
54
|
@import "./navigationOption/NavigationOption.less";
|
|
56
55
|
@import "./navigationOptionsList/NavigationOptionsList.less";
|
|
57
56
|
@import "./nudge/Nudge.less";
|
package/src/ssr.spec.tsx
CHANGED
|
@@ -92,7 +92,6 @@ describe('Server side rendering', () => {
|
|
|
92
92
|
// stick all possible properties we might need to render all components in here
|
|
93
93
|
const allProps: Record<string, unknown> = {
|
|
94
94
|
currencies: [],
|
|
95
|
-
currencySelector: { options: [] },
|
|
96
95
|
steps: [],
|
|
97
96
|
stepper: {
|
|
98
97
|
steps: [],
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NotificationDot.js","sources":["../../src/avatarView/NotificationDot.tsx"],"sourcesContent":["import { HTMLAttributes } from 'react';\nimport { Props as AvatarViewProps } from './AvatarView';\n\ntype Props = Pick<HTMLAttributes<HTMLDivElement>, 'children'> & {\n avatarSize?: AvatarViewProps['size'];\n};\n\n/**\n * Depending on avatar size, notifcation dot size and offset are different\n */\nconst MAP_STYLE_CONFIG = {\n 16: { size: 6, offset: 1 },\n 24: { size: 8, offset: 2 },\n 32: { size: 10, offset: 2 },\n 40: { size: 10, offset: 2 },\n 48: { size: 14, offset: 2 },\n 56: { size: 16, offset: 3 },\n 72: { size: 20, offset: 3 },\n};\n\nexport default function NotificationDot({ children, avatarSize = 48 }: Props) {\n return (\n <div\n className=\"np-notification-dot\"\n style={{\n // @ts-expect-error CSS custom props allowed\n '--np-notification-dot-size': `${MAP_STYLE_CONFIG[avatarSize].size}px`,\n '--np-notification-dot-offset': `${MAP_STYLE_CONFIG[avatarSize].offset}px`,\n }}\n >\n <div className=\"np-notification-dot-badge\" />\n <div className=\"np-notification-dot-mask\">{children}</div>\n </div>\n );\n}\n"],"names":["MAP_STYLE_CONFIG","size","offset","NotificationDot","children","avatarSize","_jsxs","className","style","_jsx"],"mappings":";;;;;;AAOA;;AAEG;AACH,MAAMA,gBAAgB,GAAG;AACvB,EAAA,EAAE,EAAE;AAAEC,IAAAA,IAAI,EAAE,CAAC;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC1B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,CAAC;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC1B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC3B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC3B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC3B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC3B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;AAAC;CAC1B;AAEa,SAAUC,eAAeA,CAAC;EAAEC,QAAQ;AAAEC,EAAAA,UAAU,GAAG;AAAE,CAAS,EAAA;AAC1E,EAAA,oBACEC,eAAA,CAAA,KAAA,EAAA;AACEC,IAAAA,SAAS,EAAC,qBAAqB;AAC/BC,IAAAA,KAAK,EAAE;AACL;MACA,4BAA4B,EAAE,GAAGR,gBAAgB,CAACK,UAAU,CAAC,CAACJ,IAAI,CAAA,EAAA,CAAI;AACtE,MAAA,8BAA8B,EAAE,CAAA,EAAGD,gBAAgB,CAACK,UAAU,CAAC,CAACH,MAAM,CAAA,EAAA;KACtE;AAAAE,IAAAA,QAAA,gBAEFK,cAAA,CAAA,KAAA,EAAA;AAAKF,MAAAA,SAAS,EAAC;KAA2B,CAC1C,eAAAE,cAAA,CAAA,KAAA,EAAA;AAAKF,MAAAA,SAAS,EAAC,0BAA0B;AAAAH,MAAAA,QAAA,EAAEA;AAAQ,KAAM,CAC3D;AAAA,GAAK,CAAC;AAEV;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NotificationDot.mjs","sources":["../../src/avatarView/NotificationDot.tsx"],"sourcesContent":["import { HTMLAttributes } from 'react';\nimport { Props as AvatarViewProps } from './AvatarView';\n\ntype Props = Pick<HTMLAttributes<HTMLDivElement>, 'children'> & {\n avatarSize?: AvatarViewProps['size'];\n};\n\n/**\n * Depending on avatar size, notifcation dot size and offset are different\n */\nconst MAP_STYLE_CONFIG = {\n 16: { size: 6, offset: 1 },\n 24: { size: 8, offset: 2 },\n 32: { size: 10, offset: 2 },\n 40: { size: 10, offset: 2 },\n 48: { size: 14, offset: 2 },\n 56: { size: 16, offset: 3 },\n 72: { size: 20, offset: 3 },\n};\n\nexport default function NotificationDot({ children, avatarSize = 48 }: Props) {\n return (\n <div\n className=\"np-notification-dot\"\n style={{\n // @ts-expect-error CSS custom props allowed\n '--np-notification-dot-size': `${MAP_STYLE_CONFIG[avatarSize].size}px`,\n '--np-notification-dot-offset': `${MAP_STYLE_CONFIG[avatarSize].offset}px`,\n }}\n >\n <div className=\"np-notification-dot-badge\" />\n <div className=\"np-notification-dot-mask\">{children}</div>\n </div>\n );\n}\n"],"names":["MAP_STYLE_CONFIG","size","offset","NotificationDot","children","avatarSize","_jsxs","className","style","_jsx"],"mappings":";;AAOA;;AAEG;AACH,MAAMA,gBAAgB,GAAG;AACvB,EAAA,EAAE,EAAE;AAAEC,IAAAA,IAAI,EAAE,CAAC;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC1B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,CAAC;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC1B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC3B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC3B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC3B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;GAAG;AAC3B,EAAA,EAAE,EAAE;AAAED,IAAAA,IAAI,EAAE,EAAE;AAAEC,IAAAA,MAAM,EAAE;AAAC;CAC1B;AAEa,SAAUC,eAAeA,CAAC;EAAEC,QAAQ;AAAEC,EAAAA,UAAU,GAAG;AAAE,CAAS,EAAA;AAC1E,EAAA,oBACEC,IAAA,CAAA,KAAA,EAAA;AACEC,IAAAA,SAAS,EAAC,qBAAqB;AAC/BC,IAAAA,KAAK,EAAE;AACL;MACA,4BAA4B,EAAE,GAAGR,gBAAgB,CAACK,UAAU,CAAC,CAACJ,IAAI,CAAA,EAAA,CAAI;AACtE,MAAA,8BAA8B,EAAE,CAAA,EAAGD,gBAAgB,CAACK,UAAU,CAAC,CAACH,MAAM,CAAA,EAAA;KACtE;AAAAE,IAAAA,QAAA,gBAEFK,GAAA,CAAA,KAAA,EAAA;AAAKF,MAAAA,SAAS,EAAC;KAA2B,CAC1C,eAAAE,GAAA,CAAA,KAAA,EAAA;AAAKF,MAAAA,SAAS,EAAC,0BAA0B;AAAAH,MAAAA,QAAA,EAAEA;AAAQ,KAAM,CAC3D;AAAA,GAAK,CAAC;AAEV;;;;"}
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var formatting = require('@transferwise/formatting');
|
|
4
|
-
var clsx = require('clsx');
|
|
5
|
-
var framerMotion = require('framer-motion');
|
|
6
|
-
var React = require('react');
|
|
7
|
-
var reactIntl = require('react-intl');
|
|
8
|
-
var AnimatedNumber = require('./AnimatedNumber.js');
|
|
9
|
-
var useFocus = require('./useFocus.js');
|
|
10
|
-
var useInputStyle = require('./useInputStyle.js');
|
|
11
|
-
var utils = require('./utils.js');
|
|
12
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
13
|
-
|
|
14
|
-
const AmountInput = ({
|
|
15
|
-
id,
|
|
16
|
-
describedById,
|
|
17
|
-
amount,
|
|
18
|
-
currency,
|
|
19
|
-
autoFocus,
|
|
20
|
-
onChange,
|
|
21
|
-
onFocusChange,
|
|
22
|
-
loading
|
|
23
|
-
}) => {
|
|
24
|
-
const intl = reactIntl.useIntl();
|
|
25
|
-
const {
|
|
26
|
-
focus,
|
|
27
|
-
setFocus,
|
|
28
|
-
visualFocus,
|
|
29
|
-
setVisualFocus
|
|
30
|
-
} = useFocus.useFocus();
|
|
31
|
-
const [value, setValue] = React.useState(amount ? utils.getFormattedString({
|
|
32
|
-
value: amount,
|
|
33
|
-
currency,
|
|
34
|
-
locale: intl.locale
|
|
35
|
-
}) : '');
|
|
36
|
-
const numericValue = React.useMemo(() => {
|
|
37
|
-
return utils.getUnformattedNumber({
|
|
38
|
-
value,
|
|
39
|
-
currency,
|
|
40
|
-
locale: intl.locale
|
|
41
|
-
});
|
|
42
|
-
}, [value, currency, intl.locale]);
|
|
43
|
-
const valueWithFullDecimals = React.useMemo(() => {
|
|
44
|
-
return utils.getFormattedString({
|
|
45
|
-
value: numericValue ?? 0,
|
|
46
|
-
currency,
|
|
47
|
-
locale: intl.locale,
|
|
48
|
-
alwaysShowDecimals: true
|
|
49
|
-
});
|
|
50
|
-
}, [numericValue, currency, intl.locale]);
|
|
51
|
-
const ref = React.useRef(null);
|
|
52
|
-
React.useEffect(() => {
|
|
53
|
-
if (autoFocus) {
|
|
54
|
-
ref.current?.focus();
|
|
55
|
-
}
|
|
56
|
-
}, []);
|
|
57
|
-
const placeholder = getPlaceholder(currency, intl.locale);
|
|
58
|
-
const groupSeparator = utils.getGroupSeparator(currency, intl.locale);
|
|
59
|
-
const decimalSeparator = utils.getDecimalSeparator(currency, intl.locale);
|
|
60
|
-
const maxDecimalCount = utils.getDecimalCount(currency, intl.locale);
|
|
61
|
-
const decimalPart = getDecimalPart(value, decimalSeparator);
|
|
62
|
-
const decimalMode = decimalSeparator && value.includes(decimalSeparator);
|
|
63
|
-
React.useEffect(() => {
|
|
64
|
-
if (!focus) {
|
|
65
|
-
setValue(amount ? utils.getFormattedString({
|
|
66
|
-
value: amount,
|
|
67
|
-
currency,
|
|
68
|
-
locale: intl.locale
|
|
69
|
-
}) : '');
|
|
70
|
-
}
|
|
71
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
72
|
-
}, [amount]);
|
|
73
|
-
React.useEffect(() => {
|
|
74
|
-
onFocusChange?.(visualFocus);
|
|
75
|
-
}, [visualFocus]);
|
|
76
|
-
const shouldReformatAfterUserInput = newValue => {
|
|
77
|
-
// don't reformat if formatting would wipe out user's input
|
|
78
|
-
if (reformatValue(newValue) === '') {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
const endsWithDecimalSeparator = decimalSeparator && newValue.endsWith(decimalSeparator);
|
|
82
|
-
const endsWithGroupSeparator = groupSeparator && newValue.endsWith(groupSeparator);
|
|
83
|
-
// if the user has entered a seperator to the end, formatting would delete it
|
|
84
|
-
if (endsWithDecimalSeparator || endsWithGroupSeparator) {
|
|
85
|
-
return false;
|
|
86
|
-
}
|
|
87
|
-
const containsDecimalSeparator = decimalSeparator && newValue.includes(decimalSeparator);
|
|
88
|
-
if (containsDecimalSeparator) {
|
|
89
|
-
const enteredDecimalsCount = utils.getEnteredDecimalsCount(newValue, decimalSeparator);
|
|
90
|
-
// don't reformat until user has entered all the allowed decimals
|
|
91
|
-
// for example, we don't want 1.1 to be reformatted to 1.10 immediately
|
|
92
|
-
if (enteredDecimalsCount < maxDecimalCount) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return true;
|
|
97
|
-
};
|
|
98
|
-
const reformatValue = newValue => {
|
|
99
|
-
const unformattedValue = utils.getUnformattedNumber({
|
|
100
|
-
value: newValue,
|
|
101
|
-
currency,
|
|
102
|
-
locale: intl.locale
|
|
103
|
-
});
|
|
104
|
-
const formattedValue = unformattedValue ? utils.getFormattedString({
|
|
105
|
-
value: unformattedValue,
|
|
106
|
-
currency,
|
|
107
|
-
locale: intl.locale
|
|
108
|
-
}) : '';
|
|
109
|
-
return formattedValue;
|
|
110
|
-
};
|
|
111
|
-
const handleChange = newValue => {
|
|
112
|
-
const oldCursorPosition = ref.current?.selectionStart ?? 0;
|
|
113
|
-
const newFormattedString = shouldReformatAfterUserInput(newValue) ? reformatValue(newValue) : newValue;
|
|
114
|
-
setValue(newFormattedString);
|
|
115
|
-
const newNumber = utils.getUnformattedNumber({
|
|
116
|
-
value: newFormattedString,
|
|
117
|
-
currency,
|
|
118
|
-
locale: intl.locale
|
|
119
|
-
});
|
|
120
|
-
if (newNumber !== numericValue) {
|
|
121
|
-
if (numericValue || newNumber) {
|
|
122
|
-
onChange(newNumber);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const newCursorPosition = oldCursorPosition + (newFormattedString.length - newValue.length);
|
|
126
|
-
requestAnimationFrame(() => {
|
|
127
|
-
ref?.current?.setSelectionRange(newCursorPosition, newCursorPosition);
|
|
128
|
-
});
|
|
129
|
-
};
|
|
130
|
-
const handlePaste = e => {
|
|
131
|
-
e.preventDefault();
|
|
132
|
-
const clipboardData = e.clipboardData?.getData('text/plain');
|
|
133
|
-
if (!clipboardData) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
// need to sanitise the pasted value otherwise other validation logic will ignore the input entirely
|
|
137
|
-
const sanitisedValue = reformatValue(clipboardData);
|
|
138
|
-
handleChange(sanitisedValue);
|
|
139
|
-
};
|
|
140
|
-
const handleBlur = () => {
|
|
141
|
-
setFocus(false);
|
|
142
|
-
setValue(reformatValue(value));
|
|
143
|
-
};
|
|
144
|
-
const handleBackspace = e => {
|
|
145
|
-
const input = e.target;
|
|
146
|
-
// using the updated selection range after the backspace key has been processed, instead of the current selection range in state
|
|
147
|
-
const {
|
|
148
|
-
value: currentValue,
|
|
149
|
-
selectionStart,
|
|
150
|
-
selectionEnd
|
|
151
|
-
} = input;
|
|
152
|
-
if (selectionStart === selectionEnd && selectionStart && selectionStart > 0) {
|
|
153
|
-
const charBeforeCursor = currentValue[selectionStart - 1];
|
|
154
|
-
// if the user deletes a thousands separator, remove the digit before it as well
|
|
155
|
-
if (charBeforeCursor === groupSeparator) {
|
|
156
|
-
e.preventDefault();
|
|
157
|
-
const beforeCursor = currentValue.slice(0, selectionStart - 2);
|
|
158
|
-
const afterCursor = currentValue.slice(selectionStart);
|
|
159
|
-
const newValue = `${beforeCursor}${afterCursor}`;
|
|
160
|
-
input.setSelectionRange(beforeCursor.length, beforeCursor.length);
|
|
161
|
-
handleChange(newValue);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
const handleKeyDown = e => {
|
|
166
|
-
setFocus(true);
|
|
167
|
-
if (!utils.isAllowedInputKey(e)) {
|
|
168
|
-
e.preventDefault();
|
|
169
|
-
}
|
|
170
|
-
if (e.key === 'Backspace') {
|
|
171
|
-
handleBackspace(e);
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
const isAllowedInput = e => {
|
|
175
|
-
const hasMultipleDecimalSeparators = decimalSeparator && e.target.value.split(decimalSeparator).length > 2;
|
|
176
|
-
if (hasMultipleDecimalSeparators) {
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
const newNumericValue = utils.getUnformattedNumber({
|
|
180
|
-
value: e.target.value,
|
|
181
|
-
currency,
|
|
182
|
-
locale: intl.locale
|
|
183
|
-
});
|
|
184
|
-
const maxLength = Number.MAX_SAFE_INTEGER.toString().length;
|
|
185
|
-
if (String(newNumericValue).length > maxLength) {
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
return true;
|
|
189
|
-
};
|
|
190
|
-
const addonContent = React.useMemo(() => {
|
|
191
|
-
// because we're using a separate "addon" element for the placeholder decimals, there is a possibility that the input itself will become scrollable
|
|
192
|
-
// and the decimals will appear on top of the input. Safest thing to do is to just hide the addon if there is not enough room
|
|
193
|
-
if (utils.isInputPossiblyOverflowing({
|
|
194
|
-
ref,
|
|
195
|
-
value
|
|
196
|
-
})) {
|
|
197
|
-
return null;
|
|
198
|
-
}
|
|
199
|
-
if (!decimalSeparator || !value) {
|
|
200
|
-
return null;
|
|
201
|
-
}
|
|
202
|
-
// if the user has typed a decimal separator, show the full decimal part as a placeholder
|
|
203
|
-
// this returns a string even if there is no content, typing should replace the placeholder immediately without animation
|
|
204
|
-
// otherwise there is an ugly animation when going from 1.23 to 1.2 due to AnimatePresence
|
|
205
|
-
if (focus && decimalMode) {
|
|
206
|
-
// reuse getDecimalPart
|
|
207
|
-
const fullDecimalPart = getDecimalPart(valueWithFullDecimals, decimalSeparator);
|
|
208
|
-
// show only the characters that are not already displayed by the input
|
|
209
|
-
return fullDecimalPart?.slice(decimalPart?.length);
|
|
210
|
-
}
|
|
211
|
-
// in unfocused state, always show the full decimal part unless the user has already entered decimals
|
|
212
|
-
if (!focus && !decimalMode) {
|
|
213
|
-
const [_, decimalPlaceholder] = placeholder.split(decimalSeparator);
|
|
214
|
-
return decimalSeparator + decimalPlaceholder;
|
|
215
|
-
}
|
|
216
|
-
return null;
|
|
217
|
-
}, [decimalMode, decimalPart?.length, decimalSeparator, focus, placeholder, value, valueWithFullDecimals]);
|
|
218
|
-
const style = useInputStyle.useInputStyle({
|
|
219
|
-
// whenever decimals are shown, we need to account for the full decimal part for the font size calculation
|
|
220
|
-
value: addonContent ? valueWithFullDecimals : value,
|
|
221
|
-
focus: visualFocus,
|
|
222
|
-
inputElement: ref.current,
|
|
223
|
-
loading
|
|
224
|
-
});
|
|
225
|
-
const getInputMask = () => {
|
|
226
|
-
return '';
|
|
227
|
-
};
|
|
228
|
-
return /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
229
|
-
className: "wds-amount-input-container",
|
|
230
|
-
children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
231
|
-
className: "wds-amount-input-input-container display-2",
|
|
232
|
-
style: style,
|
|
233
|
-
children: [/*#__PURE__*/jsxRuntime.jsx("input", {
|
|
234
|
-
ref: ref,
|
|
235
|
-
className: "wds-amount-input-input",
|
|
236
|
-
id: id,
|
|
237
|
-
autoComplete: "off",
|
|
238
|
-
inputMode: "decimal",
|
|
239
|
-
value: value,
|
|
240
|
-
type: "text",
|
|
241
|
-
placeholder: placeholder,
|
|
242
|
-
"aria-describedby": describedById
|
|
243
|
-
/* without this, the input tries to keep an aspect ratio and doesn't respect CSS width rules */,
|
|
244
|
-
size: 1,
|
|
245
|
-
onChange: e => {
|
|
246
|
-
if (isAllowedInput(e)) {
|
|
247
|
-
handleChange(e.target.value);
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
onBlurCapture: () => handleBlur(),
|
|
251
|
-
onPaste: e => handlePaste(e),
|
|
252
|
-
onFocus: () => {
|
|
253
|
-
setFocus(true);
|
|
254
|
-
},
|
|
255
|
-
onBlur: () => {
|
|
256
|
-
setTimeout(() => setVisualFocus(false), 30);
|
|
257
|
-
},
|
|
258
|
-
onKeyDown: e => handleKeyDown(e)
|
|
259
|
-
}), /*#__PURE__*/jsxRuntime.jsx(framerMotion.AnimatePresence, {
|
|
260
|
-
initial: false,
|
|
261
|
-
children: addonContent !== null && /*#__PURE__*/jsxRuntime.jsx(AnimatedNumber.AnimatedNumber, {
|
|
262
|
-
className: clsx.clsx('wds-amount-input-placeholder', visualFocus && 'wds-amount-input-placeholder-focus'),
|
|
263
|
-
onClick: () => ref.current?.focus(),
|
|
264
|
-
children: addonContent
|
|
265
|
-
})
|
|
266
|
-
})]
|
|
267
|
-
}), getInputMask()]
|
|
268
|
-
});
|
|
269
|
-
};
|
|
270
|
-
const getPlaceholder = (currency, locale) => {
|
|
271
|
-
return formatting.formatAmount(0, currency, locale, {
|
|
272
|
-
alwaysShowDecimals: true
|
|
273
|
-
});
|
|
274
|
-
};
|
|
275
|
-
const getDecimalPart = (value, decimalSeparator) => {
|
|
276
|
-
if (!value || !decimalSeparator) {
|
|
277
|
-
return undefined;
|
|
278
|
-
}
|
|
279
|
-
const [_, decimalPart] = value.split(decimalSeparator);
|
|
280
|
-
return decimalPart ?? undefined;
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
exports.AmountInput = AmountInput;
|
|
284
|
-
//# sourceMappingURL=AmountInput.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AmountInput.js","sources":["../../src/moneyInputField/AmountInput.tsx"],"sourcesContent":["import { formatAmount } from '@transferwise/formatting';\nimport { clsx } from 'clsx';\nimport { AnimatePresence } from 'framer-motion';\nimport { type ChangeEvent, type KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport { Props as MoneyInputFieldProps } from './MoneyInputField';\nimport { AnimatedNumber } from './AnimatedNumber';\nimport { useFocus } from './useFocus';\nimport { useInputStyle } from './useInputStyle';\nimport {\n getDecimalCount,\n getDecimalSeparator,\n getEnteredDecimalsCount,\n getFormattedString,\n getGroupSeparator,\n getUnformattedNumber,\n isAllowedInputKey,\n isInputPossiblyOverflowing,\n} from './utils';\n\ntype Props = {\n id: string;\n describedById?: string;\n amount?: number | null;\n currency: string;\n autoFocus?: boolean;\n onChange: (amount: number | null) => void;\n onFocusChange?: (focused: boolean) => void;\n} & Pick<MoneyInputFieldProps, 'loading'>;\n\nexport const AmountInput = ({\n id,\n describedById,\n amount,\n currency,\n autoFocus,\n onChange,\n onFocusChange,\n loading,\n}: Props) => {\n const intl = useIntl();\n const { focus, setFocus, visualFocus, setVisualFocus } = useFocus();\n\n const [value, setValue] = useState<string>(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n const numericValue = useMemo(() => {\n return getUnformattedNumber({\n value,\n currency,\n locale: intl.locale,\n });\n }, [value, currency, intl.locale]);\n\n const valueWithFullDecimals = useMemo(() => {\n return getFormattedString({\n value: numericValue ?? 0,\n currency,\n locale: intl.locale,\n alwaysShowDecimals: true,\n });\n }, [numericValue, currency, intl.locale]);\n\n const ref = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (autoFocus) {\n ref.current?.focus();\n }\n }, []);\n\n const placeholder = getPlaceholder(currency, intl.locale);\n const groupSeparator = getGroupSeparator(currency, intl.locale);\n const decimalSeparator = getDecimalSeparator(currency, intl.locale);\n const maxDecimalCount = getDecimalCount(currency, intl.locale);\n\n const decimalPart = getDecimalPart(value, decimalSeparator);\n const decimalMode = decimalSeparator && value.includes(decimalSeparator);\n\n useEffect(() => {\n if (!focus) {\n setValue(\n amount\n ? getFormattedString({\n value: amount,\n currency,\n locale: intl.locale,\n })\n : '',\n );\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [amount]);\n\n useEffect(() => {\n onFocusChange?.(visualFocus);\n }, [visualFocus]);\n\n const shouldReformatAfterUserInput = (newValue: string) => {\n // don't reformat if formatting would wipe out user's input\n if (reformatValue(newValue) === '') {\n return false;\n }\n\n const endsWithDecimalSeparator = decimalSeparator && newValue.endsWith(decimalSeparator);\n const endsWithGroupSeparator = groupSeparator && newValue.endsWith(groupSeparator);\n\n // if the user has entered a seperator to the end, formatting would delete it\n if (endsWithDecimalSeparator || endsWithGroupSeparator) {\n return false;\n }\n\n const containsDecimalSeparator = decimalSeparator && newValue.includes(decimalSeparator);\n\n if (containsDecimalSeparator) {\n const enteredDecimalsCount = getEnteredDecimalsCount(newValue, decimalSeparator);\n // don't reformat until user has entered all the allowed decimals\n // for example, we don't want 1.1 to be reformatted to 1.10 immediately\n if (enteredDecimalsCount < maxDecimalCount) {\n return false;\n }\n }\n\n return true;\n };\n\n const reformatValue = (newValue: string) => {\n const unformattedValue = getUnformattedNumber({\n value: newValue,\n currency,\n locale: intl.locale,\n });\n const formattedValue = unformattedValue\n ? getFormattedString({\n value: unformattedValue,\n currency,\n locale: intl.locale,\n })\n : '';\n return formattedValue;\n };\n\n const handleChange = (newValue: string) => {\n const oldCursorPosition = ref.current?.selectionStart ?? 0;\n\n const newFormattedString = shouldReformatAfterUserInput(newValue)\n ? reformatValue(newValue)\n : newValue;\n setValue(newFormattedString);\n\n const newNumber = getUnformattedNumber({\n value: newFormattedString,\n currency,\n locale: intl.locale,\n });\n\n if (newNumber !== numericValue) {\n if (numericValue || newNumber) {\n onChange(newNumber);\n }\n }\n\n const newCursorPosition = oldCursorPosition + (newFormattedString.length - newValue.length);\n requestAnimationFrame(() => {\n ref?.current?.setSelectionRange(newCursorPosition, newCursorPosition);\n });\n };\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n e.preventDefault();\n\n const clipboardData = e.clipboardData?.getData('text/plain');\n if (!clipboardData) {\n return;\n }\n\n // need to sanitise the pasted value otherwise other validation logic will ignore the input entirely\n const sanitisedValue = reformatValue(clipboardData);\n\n handleChange(sanitisedValue);\n };\n\n const handleBlur = () => {\n setFocus(false);\n setValue(reformatValue(value));\n };\n\n const handleBackspace = (e: KeyboardEvent<HTMLInputElement>) => {\n const input = e.target as HTMLInputElement;\n // using the updated selection range after the backspace key has been processed, instead of the current selection range in state\n const { value: currentValue, selectionStart, selectionEnd } = input;\n\n if (selectionStart === selectionEnd && selectionStart && selectionStart > 0) {\n const charBeforeCursor = currentValue[selectionStart - 1];\n\n // if the user deletes a thousands separator, remove the digit before it as well\n if (charBeforeCursor === groupSeparator) {\n e.preventDefault();\n const beforeCursor = currentValue.slice(0, selectionStart - 2);\n const afterCursor = currentValue.slice(selectionStart);\n const newValue = `${beforeCursor}${afterCursor}`;\n input.setSelectionRange(beforeCursor.length, beforeCursor.length);\n handleChange(newValue);\n }\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n setFocus(true);\n if (!isAllowedInputKey(e)) {\n e.preventDefault();\n }\n\n if (e.key === 'Backspace') {\n handleBackspace(e);\n }\n };\n\n const isAllowedInput = (e: ChangeEvent<HTMLInputElement>) => {\n const hasMultipleDecimalSeparators =\n decimalSeparator && e.target.value.split(decimalSeparator).length > 2;\n if (hasMultipleDecimalSeparators) {\n return false;\n }\n\n const newNumericValue = getUnformattedNumber({\n value: e.target.value,\n currency,\n locale: intl.locale,\n });\n const maxLength = Number.MAX_SAFE_INTEGER.toString().length;\n if (String(newNumericValue).length > maxLength) {\n return false;\n }\n\n return true;\n };\n\n const addonContent = useMemo((): string | null | undefined => {\n // because we're using a separate \"addon\" element for the placeholder decimals, there is a possibility that the input itself will become scrollable\n // and the decimals will appear on top of the input. Safest thing to do is to just hide the addon if there is not enough room\n if (isInputPossiblyOverflowing({ ref, value })) {\n return null;\n }\n if (!decimalSeparator || !value) {\n return null;\n }\n\n // if the user has typed a decimal separator, show the full decimal part as a placeholder\n // this returns a string even if there is no content, typing should replace the placeholder immediately without animation\n // otherwise there is an ugly animation when going from 1.23 to 1.2 due to AnimatePresence\n if (focus && decimalMode) {\n // reuse getDecimalPart\n const fullDecimalPart = getDecimalPart(valueWithFullDecimals, decimalSeparator);\n // show only the characters that are not already displayed by the input\n return fullDecimalPart?.slice(decimalPart?.length);\n }\n\n // in unfocused state, always show the full decimal part unless the user has already entered decimals\n if (!focus && !decimalMode) {\n const [_, decimalPlaceholder] = placeholder.split(decimalSeparator);\n return decimalSeparator + decimalPlaceholder;\n }\n\n return null;\n }, [\n decimalMode,\n decimalPart?.length,\n decimalSeparator,\n focus,\n placeholder,\n value,\n valueWithFullDecimals,\n ]);\n\n const style = useInputStyle({\n // whenever decimals are shown, we need to account for the full decimal part for the font size calculation\n value: addonContent ? valueWithFullDecimals : value,\n focus: visualFocus,\n inputElement: ref.current,\n loading,\n });\n\n const getInputMask = () => {\n return '';\n };\n\n return (\n <div className=\"wds-amount-input-container\">\n <div className=\"wds-amount-input-input-container display-2\" style={style}>\n <input\n ref={ref}\n className=\"wds-amount-input-input\"\n id={id}\n autoComplete=\"off\"\n inputMode=\"decimal\"\n value={value}\n type=\"text\"\n placeholder={placeholder}\n aria-describedby={describedById}\n /* without this, the input tries to keep an aspect ratio and doesn't respect CSS width rules */\n size={1}\n onChange={(e) => {\n if (isAllowedInput(e)) {\n handleChange(e.target.value);\n }\n }}\n onBlurCapture={() => handleBlur()}\n onPaste={(e) => handlePaste(e)}\n onFocus={() => {\n setFocus(true);\n }}\n onBlur={() => {\n setTimeout(() => setVisualFocus(false), 30);\n }}\n onKeyDown={(e) => handleKeyDown(e)}\n />\n <AnimatePresence initial={false}>\n {addonContent !== null && (\n <AnimatedNumber\n className={clsx(\n 'wds-amount-input-placeholder',\n visualFocus && 'wds-amount-input-placeholder-focus',\n )}\n onClick={() => ref.current?.focus()}\n >\n {addonContent}\n </AnimatedNumber>\n )}\n </AnimatePresence>\n </div>\n {getInputMask()}\n </div>\n );\n};\n\nconst getPlaceholder = (currency: string, locale: string) => {\n return formatAmount(0, currency, locale, { alwaysShowDecimals: true });\n};\n\nconst getDecimalPart = (value: string, decimalSeparator: string | null) => {\n if (!value || !decimalSeparator) {\n return undefined;\n }\n\n const [_, decimalPart] = value.split(decimalSeparator);\n return decimalPart ?? undefined;\n};\n"],"names":["AmountInput","id","describedById","amount","currency","autoFocus","onChange","onFocusChange","loading","intl","useIntl","focus","setFocus","visualFocus","setVisualFocus","useFocus","value","setValue","useState","getFormattedString","locale","numericValue","useMemo","getUnformattedNumber","valueWithFullDecimals","alwaysShowDecimals","ref","useRef","useEffect","current","placeholder","getPlaceholder","groupSeparator","getGroupSeparator","decimalSeparator","getDecimalSeparator","maxDecimalCount","getDecimalCount","decimalPart","getDecimalPart","decimalMode","includes","shouldReformatAfterUserInput","newValue","reformatValue","endsWithDecimalSeparator","endsWith","endsWithGroupSeparator","containsDecimalSeparator","enteredDecimalsCount","getEnteredDecimalsCount","unformattedValue","formattedValue","handleChange","oldCursorPosition","selectionStart","newFormattedString","newNumber","newCursorPosition","length","requestAnimationFrame","setSelectionRange","handlePaste","e","preventDefault","clipboardData","getData","sanitisedValue","handleBlur","handleBackspace","input","target","currentValue","selectionEnd","charBeforeCursor","beforeCursor","slice","afterCursor","handleKeyDown","isAllowedInputKey","key","isAllowedInput","hasMultipleDecimalSeparators","split","newNumericValue","maxLength","Number","MAX_SAFE_INTEGER","toString","String","addonContent","isInputPossiblyOverflowing","fullDecimalPart","_","decimalPlaceholder","style","useInputStyle","inputElement","getInputMask","_jsxs","className","children","_jsx","autoComplete","inputMode","type","size","onBlurCapture","onPaste","onFocus","onBlur","setTimeout","onKeyDown","AnimatePresence","initial","AnimatedNumber","clsx","onClick","formatAmount","undefined"],"mappings":";;;;;;;;;;;;;AA+BO,MAAMA,WAAW,GAAGA,CAAC;EAC1BC,EAAE;EACFC,aAAa;EACbC,MAAM;EACNC,QAAQ;EACRC,SAAS;EACTC,QAAQ;EACRC,aAAa;AACbC,EAAAA;AAAO,CACD,KAAI;AACV,EAAA,MAAMC,IAAI,GAAGC,iBAAO,EAAE;EACtB,MAAM;IAAEC,KAAK;IAAEC,QAAQ;IAAEC,WAAW;AAAEC,IAAAA;GAAgB,GAAGC,iBAAQ,EAAE;EAEnE,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,GAAGC,cAAQ,CAChCf,MAAM,GACFgB,wBAAkB,CAAC;AACjBH,IAAAA,KAAK,EAAEb,MAAM;IACbC,QAAQ;IACRgB,MAAM,EAAEX,IAAI,CAACW;GACd,CAAC,GACF,EAAE,CACP;AACD,EAAA,MAAMC,YAAY,GAAGC,aAAO,CAAC,MAAK;AAChC,IAAA,OAAOC,0BAAoB,CAAC;MAC1BP,KAAK;MACLZ,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;AACd,KAAA,CAAC;EACJ,CAAC,EAAE,CAACJ,KAAK,EAAEZ,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC,CAAC;AAElC,EAAA,MAAMI,qBAAqB,GAAGF,aAAO,CAAC,MAAK;AACzC,IAAA,OAAOH,wBAAkB,CAAC;MACxBH,KAAK,EAAEK,YAAY,IAAI,CAAC;MACxBjB,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW,MAAM;AACnBK,MAAAA,kBAAkB,EAAE;AACrB,KAAA,CAAC;EACJ,CAAC,EAAE,CAACJ,YAAY,EAAEjB,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC,CAAC;AAEzC,EAAA,MAAMM,GAAG,GAAGC,YAAM,CAAmB,IAAI,CAAC;AAE1CC,EAAAA,eAAS,CAAC,MAAK;AACb,IAAA,IAAIvB,SAAS,EAAE;AACbqB,MAAAA,GAAG,CAACG,OAAO,EAAElB,KAAK,EAAE;AACtB,IAAA;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMmB,WAAW,GAAGC,cAAc,CAAC3B,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC;EACzD,MAAMY,cAAc,GAAGC,uBAAiB,CAAC7B,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC;EAC/D,MAAMc,gBAAgB,GAAGC,yBAAmB,CAAC/B,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC;EACnE,MAAMgB,eAAe,GAAGC,qBAAe,CAACjC,QAAQ,EAAEK,IAAI,CAACW,MAAM,CAAC;AAE9D,EAAA,MAAMkB,WAAW,GAAGC,cAAc,CAACvB,KAAK,EAAEkB,gBAAgB,CAAC;EAC3D,MAAMM,WAAW,GAAGN,gBAAgB,IAAIlB,KAAK,CAACyB,QAAQ,CAACP,gBAAgB,CAAC;AAExEN,EAAAA,eAAS,CAAC,MAAK;IACb,IAAI,CAACjB,KAAK,EAAE;AACVM,MAAAA,QAAQ,CACNd,MAAM,GACFgB,wBAAkB,CAAC;AACjBH,QAAAA,KAAK,EAAEb,MAAM;QACbC,QAAQ;QACRgB,MAAM,EAAEX,IAAI,CAACW;OACd,CAAC,GACF,EAAE,CACP;AACH,IAAA;AACA;AACF,EAAA,CAAC,EAAE,CAACjB,MAAM,CAAC,CAAC;AAEZyB,EAAAA,eAAS,CAAC,MAAK;IACbrB,aAAa,GAAGM,WAAW,CAAC;AAC9B,EAAA,CAAC,EAAE,CAACA,WAAW,CAAC,CAAC;EAEjB,MAAM6B,4BAA4B,GAAIC,QAAgB,IAAI;AACxD;AACA,IAAA,IAAIC,aAAa,CAACD,QAAQ,CAAC,KAAK,EAAE,EAAE;AAClC,MAAA,OAAO,KAAK;AACd,IAAA;IAEA,MAAME,wBAAwB,GAAGX,gBAAgB,IAAIS,QAAQ,CAACG,QAAQ,CAACZ,gBAAgB,CAAC;IACxF,MAAMa,sBAAsB,GAAGf,cAAc,IAAIW,QAAQ,CAACG,QAAQ,CAACd,cAAc,CAAC;AAElF;IACA,IAAIa,wBAAwB,IAAIE,sBAAsB,EAAE;AACtD,MAAA,OAAO,KAAK;AACd,IAAA;IAEA,MAAMC,wBAAwB,GAAGd,gBAAgB,IAAIS,QAAQ,CAACF,QAAQ,CAACP,gBAAgB,CAAC;AAExF,IAAA,IAAIc,wBAAwB,EAAE;AAC5B,MAAA,MAAMC,oBAAoB,GAAGC,6BAAuB,CAACP,QAAQ,EAAET,gBAAgB,CAAC;AAChF;AACA;MACA,IAAIe,oBAAoB,GAAGb,eAAe,EAAE;AAC1C,QAAA,OAAO,KAAK;AACd,MAAA;AACF,IAAA;AAEA,IAAA,OAAO,IAAI;EACb,CAAC;EAED,MAAMQ,aAAa,GAAID,QAAgB,IAAI;IACzC,MAAMQ,gBAAgB,GAAG5B,0BAAoB,CAAC;AAC5CP,MAAAA,KAAK,EAAE2B,QAAQ;MACfvC,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;AACd,KAAA,CAAC;AACF,IAAA,MAAMgC,cAAc,GAAGD,gBAAgB,GACnChC,wBAAkB,CAAC;AACjBH,MAAAA,KAAK,EAAEmC,gBAAgB;MACvB/C,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;KACd,CAAC,GACF,EAAE;AACN,IAAA,OAAOgC,cAAc;EACvB,CAAC;EAED,MAAMC,YAAY,GAAIV,QAAgB,IAAI;IACxC,MAAMW,iBAAiB,GAAG5B,GAAG,CAACG,OAAO,EAAE0B,cAAc,IAAI,CAAC;AAE1D,IAAA,MAAMC,kBAAkB,GAAGd,4BAA4B,CAACC,QAAQ,CAAC,GAC7DC,aAAa,CAACD,QAAQ,CAAC,GACvBA,QAAQ;IACZ1B,QAAQ,CAACuC,kBAAkB,CAAC;IAE5B,MAAMC,SAAS,GAAGlC,0BAAoB,CAAC;AACrCP,MAAAA,KAAK,EAAEwC,kBAAkB;MACzBpD,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;AACd,KAAA,CAAC;IAEF,IAAIqC,SAAS,KAAKpC,YAAY,EAAE;MAC9B,IAAIA,YAAY,IAAIoC,SAAS,EAAE;QAC7BnD,QAAQ,CAACmD,SAAS,CAAC;AACrB,MAAA;AACF,IAAA;IAEA,MAAMC,iBAAiB,GAAGJ,iBAAiB,IAAIE,kBAAkB,CAACG,MAAM,GAAGhB,QAAQ,CAACgB,MAAM,CAAC;AAC3FC,IAAAA,qBAAqB,CAAC,MAAK;MACzBlC,GAAG,EAAEG,OAAO,EAAEgC,iBAAiB,CAACH,iBAAiB,EAAEA,iBAAiB,CAAC;AACvE,IAAA,CAAC,CAAC;EACJ,CAAC;EAED,MAAMI,WAAW,GAAIC,CAAyC,IAAI;IAChEA,CAAC,CAACC,cAAc,EAAE;IAElB,MAAMC,aAAa,GAAGF,CAAC,CAACE,aAAa,EAAEC,OAAO,CAAC,YAAY,CAAC;IAC5D,IAAI,CAACD,aAAa,EAAE;AAClB,MAAA;AACF,IAAA;AAEA;AACA,IAAA,MAAME,cAAc,GAAGvB,aAAa,CAACqB,aAAa,CAAC;IAEnDZ,YAAY,CAACc,cAAc,CAAC;EAC9B,CAAC;EAED,MAAMC,UAAU,GAAGA,MAAK;IACtBxD,QAAQ,CAAC,KAAK,CAAC;AACfK,IAAAA,QAAQ,CAAC2B,aAAa,CAAC5B,KAAK,CAAC,CAAC;EAChC,CAAC;EAED,MAAMqD,eAAe,GAAIN,CAAkC,IAAI;AAC7D,IAAA,MAAMO,KAAK,GAAGP,CAAC,CAACQ,MAA0B;AAC1C;IACA,MAAM;AAAEvD,MAAAA,KAAK,EAAEwD,YAAY;MAAEjB,cAAc;AAAEkB,MAAAA;AAAY,KAAE,GAAGH,KAAK;IAEnE,IAAIf,cAAc,KAAKkB,YAAY,IAAIlB,cAAc,IAAIA,cAAc,GAAG,CAAC,EAAE;AAC3E,MAAA,MAAMmB,gBAAgB,GAAGF,YAAY,CAACjB,cAAc,GAAG,CAAC,CAAC;AAEzD;MACA,IAAImB,gBAAgB,KAAK1C,cAAc,EAAE;QACvC+B,CAAC,CAACC,cAAc,EAAE;QAClB,MAAMW,YAAY,GAAGH,YAAY,CAACI,KAAK,CAAC,CAAC,EAAErB,cAAc,GAAG,CAAC,CAAC;AAC9D,QAAA,MAAMsB,WAAW,GAAGL,YAAY,CAACI,KAAK,CAACrB,cAAc,CAAC;AACtD,QAAA,MAAMZ,QAAQ,GAAG,CAAA,EAAGgC,YAAY,CAAA,EAAGE,WAAW,CAAA,CAAE;QAChDP,KAAK,CAACT,iBAAiB,CAACc,YAAY,CAAChB,MAAM,EAAEgB,YAAY,CAAChB,MAAM,CAAC;QACjEN,YAAY,CAACV,QAAQ,CAAC;AACxB,MAAA;AACF,IAAA;EACF,CAAC;EAED,MAAMmC,aAAa,GAAIf,CAAkC,IAAI;IAC3DnD,QAAQ,CAAC,IAAI,CAAC;AACd,IAAA,IAAI,CAACmE,uBAAiB,CAAChB,CAAC,CAAC,EAAE;MACzBA,CAAC,CAACC,cAAc,EAAE;AACpB,IAAA;AAEA,IAAA,IAAID,CAAC,CAACiB,GAAG,KAAK,WAAW,EAAE;MACzBX,eAAe,CAACN,CAAC,CAAC;AACpB,IAAA;EACF,CAAC;EAED,MAAMkB,cAAc,GAAIlB,CAAgC,IAAI;AAC1D,IAAA,MAAMmB,4BAA4B,GAChChD,gBAAgB,IAAI6B,CAAC,CAACQ,MAAM,CAACvD,KAAK,CAACmE,KAAK,CAACjD,gBAAgB,CAAC,CAACyB,MAAM,GAAG,CAAC;AACvE,IAAA,IAAIuB,4BAA4B,EAAE;AAChC,MAAA,OAAO,KAAK;AACd,IAAA;IAEA,MAAME,eAAe,GAAG7D,0BAAoB,CAAC;AAC3CP,MAAAA,KAAK,EAAE+C,CAAC,CAACQ,MAAM,CAACvD,KAAK;MACrBZ,QAAQ;MACRgB,MAAM,EAAEX,IAAI,CAACW;AACd,KAAA,CAAC;IACF,MAAMiE,SAAS,GAAGC,MAAM,CAACC,gBAAgB,CAACC,QAAQ,EAAE,CAAC7B,MAAM;IAC3D,IAAI8B,MAAM,CAACL,eAAe,CAAC,CAACzB,MAAM,GAAG0B,SAAS,EAAE;AAC9C,MAAA,OAAO,KAAK;AACd,IAAA;AAEA,IAAA,OAAO,IAAI;EACb,CAAC;AAED,EAAA,MAAMK,YAAY,GAAGpE,aAAO,CAAC,MAAgC;AAC3D;AACA;AACA,IAAA,IAAIqE,gCAA0B,CAAC;MAAEjE,GAAG;AAAEV,MAAAA;AAAK,KAAE,CAAC,EAAE;AAC9C,MAAA,OAAO,IAAI;AACb,IAAA;AACA,IAAA,IAAI,CAACkB,gBAAgB,IAAI,CAAClB,KAAK,EAAE;AAC/B,MAAA,OAAO,IAAI;AACb,IAAA;AAEA;AACA;AACA;IACA,IAAIL,KAAK,IAAI6B,WAAW,EAAE;AACxB;AACA,MAAA,MAAMoD,eAAe,GAAGrD,cAAc,CAACf,qBAAqB,EAAEU,gBAAgB,CAAC;AAC/E;AACA,MAAA,OAAO0D,eAAe,EAAEhB,KAAK,CAACtC,WAAW,EAAEqB,MAAM,CAAC;AACpD,IAAA;AAEA;AACA,IAAA,IAAI,CAAChD,KAAK,IAAI,CAAC6B,WAAW,EAAE;MAC1B,MAAM,CAACqD,CAAC,EAAEC,kBAAkB,CAAC,GAAGhE,WAAW,CAACqD,KAAK,CAACjD,gBAAgB,CAAC;MACnE,OAAOA,gBAAgB,GAAG4D,kBAAkB;AAC9C,IAAA;AAEA,IAAA,OAAO,IAAI;AACb,EAAA,CAAC,EAAE,CACDtD,WAAW,EACXF,WAAW,EAAEqB,MAAM,EACnBzB,gBAAgB,EAChBvB,KAAK,EACLmB,WAAW,EACXd,KAAK,EACLQ,qBAAqB,CACtB,CAAC;EAEF,MAAMuE,KAAK,GAAGC,2BAAa,CAAC;AAC1B;AACAhF,IAAAA,KAAK,EAAE0E,YAAY,GAAGlE,qBAAqB,GAAGR,KAAK;AACnDL,IAAAA,KAAK,EAAEE,WAAW;IAClBoF,YAAY,EAAEvE,GAAG,CAACG,OAAO;AACzBrB,IAAAA;AACD,GAAA,CAAC;EAEF,MAAM0F,YAAY,GAAGA,MAAK;AACxB,IAAA,OAAO,EAAE;EACX,CAAC;AAED,EAAA,oBACEC,eAAA,CAAA,KAAA,EAAA;AAAKC,IAAAA,SAAS,EAAC,4BAA4B;AAAAC,IAAAA,QAAA,gBACzCF,eAAA,CAAA,KAAA,EAAA;AAAKC,MAAAA,SAAS,EAAC,4CAA4C;AAACL,MAAAA,KAAK,EAAEA,KAAM;AAAAM,MAAAA,QAAA,gBACvEC,cAAA,CAAA,OAAA,EAAA;AACE5E,QAAAA,GAAG,EAAEA,GAAI;AACT0E,QAAAA,SAAS,EAAC,wBAAwB;AAClCnG,QAAAA,EAAE,EAAEA,EAAG;AACPsG,QAAAA,YAAY,EAAC,KAAK;AAClBC,QAAAA,SAAS,EAAC,SAAS;AACnBxF,QAAAA,KAAK,EAAEA,KAAM;AACbyF,QAAAA,IAAI,EAAC,MAAM;AACX3E,QAAAA,WAAW,EAAEA,WAAY;QACzB,kBAAA,EAAkB5B;AAClB;AACAwG,QAAAA,IAAI,EAAE,CAAE;QACRpG,QAAQ,EAAGyD,CAAC,IAAI;AACd,UAAA,IAAIkB,cAAc,CAAClB,CAAC,CAAC,EAAE;AACrBV,YAAAA,YAAY,CAACU,CAAC,CAACQ,MAAM,CAACvD,KAAK,CAAC;AAC9B,UAAA;QACF,CAAE;AACF2F,QAAAA,aAAa,EAAEA,MAAMvC,UAAU,EAAG;AAClCwC,QAAAA,OAAO,EAAG7C,CAAC,IAAKD,WAAW,CAACC,CAAC,CAAE;QAC/B8C,OAAO,EAAEA,MAAK;UACZjG,QAAQ,CAAC,IAAI,CAAC;QAChB,CAAE;QACFkG,MAAM,EAAEA,MAAK;UACXC,UAAU,CAAC,MAAMjG,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QAC7C,CAAE;AACFkG,QAAAA,SAAS,EAAGjD,CAAC,IAAKe,aAAa,CAACf,CAAC;AAAE,OAAA,CAErC,eAAAuC,cAAA,CAACW,4BAAe,EAAA;AAACC,QAAAA,OAAO,EAAE,KAAM;AAAAb,QAAAA,QAAA,EAC7BX,YAAY,KAAK,IAAI,iBACpBY,cAAA,CAACa,6BAAc,EAAA;UACbf,SAAS,EAAEgB,SAAI,CACb,8BAA8B,EAC9BvG,WAAW,IAAI,oCAAoC,CACnD;UACFwG,OAAO,EAAEA,MAAM3F,GAAG,CAACG,OAAO,EAAElB,KAAK,EAAG;AAAA0F,UAAAA,QAAA,EAEnCX;SACa;AACjB,OACc,CACnB;AAAA,KAAK,CACL,EAACQ,YAAY,EAAE;AAAA,GACZ,CAAC;AAEV;AAEA,MAAMnE,cAAc,GAAGA,CAAC3B,QAAgB,EAAEgB,MAAc,KAAI;AAC1D,EAAA,OAAOkG,uBAAY,CAAC,CAAC,EAAElH,QAAQ,EAAEgB,MAAM,EAAE;AAAEK,IAAAA,kBAAkB,EAAE;AAAI,GAAE,CAAC;AACxE,CAAC;AAED,MAAMc,cAAc,GAAGA,CAACvB,KAAa,EAAEkB,gBAA+B,KAAI;AACxE,EAAA,IAAI,CAAClB,KAAK,IAAI,CAACkB,gBAAgB,EAAE;AAC/B,IAAA,OAAOqF,SAAS;AAClB,EAAA;EAEA,MAAM,CAAC1B,CAAC,EAAEvD,WAAW,CAAC,GAAGtB,KAAK,CAACmE,KAAK,CAACjD,gBAAgB,CAAC;EACtD,OAAOI,WAAW,IAAIiF,SAAS;AACjC,CAAC;;;;"}
|