@licklist/design 0.78.5-dev.41 → 0.78.5-dev.45
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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/v2/components/Alert/Alert.js +87 -0
- package/dist/v2/components/Alert/Alert.scss.js +6 -0
- package/dist/v2/components/Button/Button.d.ts +8 -4
- package/dist/v2/components/Button/Button.d.ts.map +1 -1
- package/dist/v2/components/Button/Button.js +121 -0
- package/dist/v2/components/Button/Button.scss.js +6 -0
- package/dist/v2/components/Button/index.d.ts +2 -2
- package/dist/v2/components/Button/index.d.ts.map +1 -1
- package/dist/v2/components/Checkbox/Checkbox.d.ts +9 -0
- package/dist/v2/components/Checkbox/Checkbox.d.ts.map +1 -0
- package/dist/v2/components/Checkbox/Checkbox.js +231 -0
- package/dist/v2/components/Checkbox/Checkbox.scss.js +6 -0
- package/dist/v2/components/Checkbox/index.d.ts +3 -0
- package/dist/v2/components/Checkbox/index.d.ts.map +1 -0
- package/dist/v2/components/FormField/FormField.d.ts +10 -0
- package/dist/v2/components/FormField/FormField.d.ts.map +1 -0
- package/dist/v2/components/FormField/FormField.js +98 -0
- package/dist/v2/components/FormField/FormField.scss.js +6 -0
- package/dist/v2/components/FormField/index.d.ts +3 -0
- package/dist/v2/components/FormField/index.d.ts.map +1 -0
- package/dist/v2/components/NPSScore/NPSScore.js +546 -0
- package/dist/v2/components/NPSScore/NPSScore.scss.js +6 -0
- package/dist/v2/components/NewInput/NewInput.d.ts +20 -0
- package/dist/v2/components/NewInput/NewInput.d.ts.map +1 -0
- package/dist/v2/components/NewInput/NewInput.js +134 -0
- package/dist/v2/components/NewInput/index.d.ts +2 -0
- package/dist/v2/components/NewInput/index.d.ts.map +1 -0
- package/dist/v2/components/NewPageHeader/NewPageHeader.d.ts +10 -0
- package/dist/v2/components/NewPageHeader/NewPageHeader.d.ts.map +1 -0
- package/dist/v2/components/NewPageHeader/NewPageHeader.js +36 -0
- package/dist/v2/components/NewPageHeader/NewPageHeader.scss.js +6 -0
- package/dist/v2/components/NewPageHeader/index.d.ts +2 -0
- package/dist/v2/components/NewPageHeader/index.d.ts.map +1 -0
- package/dist/v2/components/SectionHeader/SectionHeader.d.ts +8 -0
- package/dist/v2/components/SectionHeader/SectionHeader.d.ts.map +1 -0
- package/dist/v2/components/SectionHeader/SectionHeader.js +13 -0
- package/dist/v2/components/SectionHeader/SectionHeader.scss.js +6 -0
- package/dist/v2/components/SectionHeader/index.d.ts +3 -0
- package/dist/v2/components/SectionHeader/index.d.ts.map +1 -0
- package/dist/v2/components/Select/Select.scss.js +1 -1
- package/dist/v2/components/WYSIWYGEditor/Icons.d.ts +14 -0
- package/dist/v2/components/WYSIWYGEditor/Icons.d.ts.map +1 -0
- package/dist/v2/components/WYSIWYGEditor/Icons.js +192 -0
- package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.d.ts +13 -0
- package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.d.ts.map +1 -0
- package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.js +219 -0
- package/dist/v2/components/WYSIWYGEditor/WYSIWYGEditor.scss.js +6 -0
- package/dist/v2/components/WYSIWYGEditor/index.d.ts +3 -0
- package/dist/v2/components/WYSIWYGEditor/index.d.ts.map +1 -0
- package/dist/v2/components/index.d.ts +22 -0
- package/dist/v2/components/index.d.ts.map +1 -0
- package/dist/v2/styles/components/Button.scss +51 -53
- package/dist/v2/styles/form/Layout.scss +15 -0
- package/dist/v2/styles/form/NewInput.scss +76 -53
- package/dist/v2/styles/form/NewInput.scss.js +6 -0
- package/dist/v2/styles/index.scss +1 -0
- package/dist/v2/styles/tokens/_colors.scss +6 -6
- package/dist/v2/styles/tokens/_typography.scss +2 -2
- package/package.json +3 -3
- package/src/index.ts +1 -0
- package/src/v2/components/Alert/Alert.scss +3 -3
- package/src/v2/components/Button/Button.tsx +34 -12
- package/src/v2/components/Button/index.ts +2 -2
- package/src/v2/components/Checkbox/Checkbox.scss +205 -0
- package/src/v2/components/Checkbox/Checkbox.stories.tsx +316 -0
- package/src/v2/components/Checkbox/Checkbox.tsx +106 -0
- package/src/v2/components/Checkbox/index.ts +3 -0
- package/src/v2/components/FormField/FormField.scss +87 -0
- package/src/v2/components/FormField/FormField.stories.tsx +71 -0
- package/src/v2/components/FormField/FormField.tsx +37 -0
- package/src/v2/components/FormField/index.ts +3 -0
- package/src/v2/components/NewInput/NewInput.stories.tsx +433 -0
- package/src/v2/components/NewInput/NewInput.tsx +96 -0
- package/src/v2/components/NewInput/index.ts +1 -0
- package/src/v2/components/NewPageHeader/NewPageHeader.scss +47 -0
- package/src/v2/components/NewPageHeader/NewPageHeader.stories.tsx +44 -0
- package/src/v2/components/NewPageHeader/NewPageHeader.tsx +35 -0
- package/src/v2/components/NewPageHeader/index.ts +1 -0
- package/src/v2/components/SectionHeader/SectionHeader.scss +11 -0
- package/src/v2/components/SectionHeader/SectionHeader.tsx +15 -0
- package/src/v2/components/SectionHeader/index.ts +2 -0
- package/src/v2/components/Select/Select.scss +5 -5
- package/src/v2/components/WYSIWYGEditor/Icons.tsx +81 -0
- package/src/v2/components/WYSIWYGEditor/WYSIWYGEditor.scss +318 -0
- package/src/v2/components/WYSIWYGEditor/WYSIWYGEditor.stories.tsx +252 -0
- package/src/v2/components/WYSIWYGEditor/WYSIWYGEditor.tsx +237 -0
- package/src/v2/components/WYSIWYGEditor/index.ts +3 -0
- package/src/v2/components/index.ts +37 -0
- package/src/v2/styles/components/Button.scss +51 -53
- package/src/v2/styles/form/Layout.scss +15 -0
- package/src/v2/styles/form/NewInput.scss +76 -53
- package/src/v2/styles/index.scss +1 -0
- package/src/v2/styles/tokens/_colors.scss +6 -6
- package/src/v2/styles/tokens/_typography.scss +2 -2
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
|
|
70
70
|
&--error {
|
|
71
71
|
background-color: var(--surface-status-error);
|
|
72
|
-
border-color: var(--
|
|
72
|
+
border-color: var(--borders-status-border-error);
|
|
73
73
|
|
|
74
74
|
&:hover:not(:disabled) {
|
|
75
75
|
background-color: var(--errors-lighter);
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
&:focus {
|
|
80
|
-
border-color: var(--
|
|
80
|
+
border-color: var(--borders-status-border-error);
|
|
81
81
|
background-color: var(--surface-status-error);
|
|
82
82
|
}
|
|
83
83
|
}
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
height: 6px;
|
|
142
142
|
stroke: var(--label-secondary);
|
|
143
143
|
transition: all 0.2s ease-in-out;
|
|
144
|
-
|
|
144
|
+
|
|
145
145
|
.select:focus + & {
|
|
146
146
|
transform: translateY(-50%) rotate(180deg);
|
|
147
147
|
}
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
opacity: 0.8;
|
|
165
165
|
transform: scale(0.98);
|
|
166
166
|
border-color: var(--cyan-700);
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
&:focus {
|
|
169
169
|
transform: scale(0.98) translateY(-1px);
|
|
170
170
|
}
|
|
@@ -185,4 +185,4 @@
|
|
|
185
185
|
|
|
186
186
|
.select--filter-active {
|
|
187
187
|
animation: filterPulse 0.6s ease-out;
|
|
188
|
-
}
|
|
188
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
|
|
2
|
+
export const BoldIcon = () => (
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 24 24" fill="none">
|
|
4
|
+
<path d="M9 11.25H12.375C13.4105 11.25 14.25 10.4105 14.25 9.375C14.25 8.33947 13.4105 7.5 12.375 7.5H9V11.25ZM16.5 14.625C16.5 16.489 14.989 18 13.125 18H7.5V6H12.375C14.239 6 15.75 7.51104 15.75 9.375C15.75 10.2782 15.3952 11.0986 14.8173 11.7043C15.8234 12.2885 16.5 13.3777 16.5 14.625ZM9 12.75V16.5H13.125C14.1605 16.5 15 15.6605 15 14.625C15 13.5895 14.1605 12.75 13.125 12.75H9Z" fill="#626A90"/>
|
|
5
|
+
</svg>
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
export const ItalicIcon = () => (
|
|
9
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
10
|
+
<path d="M14.25 18H8.25V16.5H10.445L12.0319 7.5H9.75V6H15.75V7.5H13.555L11.9681 16.5H14.25V18Z" fill="#626A90"/>
|
|
11
|
+
</svg>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export const UnderlineIcon = () => (
|
|
15
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
16
|
+
<path d="M9 5.25V12C9 13.6568 10.3431 15 12 15C13.6568 15 15 13.6568 15 12V5.25H16.5V12C16.5 14.4853 14.4853 16.5 12 16.5C9.51472 16.5 7.5 14.4853 7.5 12V5.25H9ZM6 18H18V19.5H6V18Z" fill="#626A90"/>
|
|
17
|
+
</svg>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const StrikeThroughIcon = () => (
|
|
21
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
22
|
+
<path d="M15.8653 13.5C16.0384 13.8871 16.125 14.317 16.125 14.7897C16.125 15.7969 15.7322 16.5837 14.9465 17.1503C14.1607 17.7167 13.0751 18 11.6896 18C10.4601 18 9.24251 17.7139 8.03694 17.1416V15.4507C9.17653 16.1087 10.3431 16.4377 11.5367 16.4377C13.45 16.4377 14.4096 15.8884 14.4156 14.7897C14.4156 14.3204 14.2537 13.9198 13.9298 13.588C13.9004 13.5579 13.8704 13.5286 13.8398 13.5H5.25V12H18.75V13.5H15.8653ZM12.807 11.25H8.72181C8.59245 11.1325 8.47212 11.0019 8.36082 10.8584C8.03694 10.4406 7.875 9.93419 7.875 9.33905C7.875 8.41202 8.22437 7.62375 8.92312 6.97425C9.62187 6.32474 10.703 6 12.1664 6C13.2701 6 14.3257 6.24606 15.3333 6.7382V8.35193C14.4336 7.83691 13.447 7.5794 12.3734 7.5794C10.514 7.5794 9.58438 8.16595 9.58438 9.33905C9.58438 9.65379 9.74782 9.92847 10.0747 10.1631C10.4016 10.3977 10.8049 10.5851 11.2847 10.7253C11.7499 10.8612 12.2573 11.0361 12.807 11.25Z" fill="#626A90"/>
|
|
23
|
+
</svg>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export const Heading1Icon = () => (
|
|
27
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="12" viewBox="0 0 15 12" fill="none">
|
|
28
|
+
<path d="M3.3125 4.63086H6.87891V0H10.1914V12H6.87891V7.28418H3.3125V12H0V0H3.3125V4.63086ZM14.54 12H12.9717V7.96191H11.5654V6.85254H12.1152C12.9535 6.85254 13.2871 6.54609 13.2871 5.59961H14.54V12Z" fill="#626A90"/>
|
|
29
|
+
</svg>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export const Heading2Icon = () => (
|
|
33
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="12" viewBox="0 0 17 12" fill="none">
|
|
34
|
+
<path d="M3.3125 4.63086H6.87891V0H10.1914V12H6.87891V7.28418H3.3125V12H0V0H3.3125V4.63086ZM14.3154 5.45605C15.8385 5.4562 16.7217 6.24039 16.7217 7.41211C16.7216 8.41248 16.2352 8.84564 15.0635 9.47656C14.0813 9.99919 13.6486 10.4133 13.6123 10.7197H16.7217V12H11.7549C11.7549 10.2603 12.3864 9.36835 13.9639 8.53906C14.8381 8.0794 15.1172 7.86234 15.1172 7.42969C15.1171 7.02416 14.8377 6.73535 14.333 6.73535C13.7651 6.73536 13.4225 7.10543 13.3594 7.77246L11.7549 7.68262C11.8631 6.27643 12.783 5.45605 14.3154 5.45605Z" fill="#626A90"/>
|
|
35
|
+
</svg>
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export const ParagraphIcon = () => (
|
|
39
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
40
|
+
<path d="M12 7.5V18.75H10.5V15C8.01472 15 6 12.9853 6 10.5C6 8.01472 8.01472 6 10.5 6H18V7.5H15.75V18.75H14.25V7.5H12ZM10.5 7.5C8.84314 7.5 7.5 8.84314 7.5 10.5C7.5 12.1568 8.84314 13.5 10.5 13.5V7.5Z" fill="#626A90"/>
|
|
41
|
+
</svg>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export const BulletListIcon = () => (
|
|
45
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
46
|
+
<path d="M9 6H18.75V7.5H9V6ZM6.375 7.875C5.75368 7.875 5.25 7.37132 5.25 6.75C5.25 6.12868 5.75368 5.625 6.375 5.625C6.99632 5.625 7.5 6.12868 7.5 6.75C7.5 7.37132 6.99632 7.875 6.375 7.875ZM6.375 13.125C5.75368 13.125 5.25 12.6213 5.25 12C5.25 11.3787 5.75368 10.875 6.375 10.875C6.99632 10.875 7.5 11.3787 7.5 12C7.5 12.6213 6.99632 13.125 6.375 13.125ZM6.375 18.3C5.75368 18.3 5.25 17.7963 5.25 17.175C5.25 16.5537 5.75368 16.05 6.375 16.05C6.99632 16.05 7.5 16.5537 7.5 17.175C7.5 17.7963 6.99632 18.3 6.375 18.3ZM9 11.25H18.75V12.75H9V11.25ZM9 16.5H18.75V18H9V16.5Z" fill="#626A90"/>
|
|
47
|
+
</svg>
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
export const NumberedListIcon = () => (
|
|
51
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
52
|
+
<path d="M7.31268 5.625H6.538L5.4375 5.91988V7.08436L6.18752 6.88337L6.18763 9.375H5.25V10.5H8.25V9.375H7.31268V5.625ZM10.5 6H18.75V7.5H10.5V6ZM10.5 11.25H18.75V12.75H10.5V11.25ZM10.5 16.5H18.75V18H10.5V16.5ZM5.15625 14.7188C5.15625 13.8385 5.86979 13.125 6.75 13.125C7.63021 13.125 8.34375 13.8385 8.34375 14.7188C8.34375 15.0829 8.22137 15.419 8.0156 15.6875L8.01203 15.6922L6.9869 16.875H8.25V18H5.25009L5.24969 17.1589L7.10378 15.0262C7.17548 14.9439 7.21875 14.8366 7.21875 14.7188C7.21875 14.4599 7.00889 14.25 6.75 14.25C6.50533 14.25 6.3043 14.4376 6.2831 14.6766L6.27382 14.9062H5.15625V14.7188Z" fill="#626A90"/>
|
|
53
|
+
</svg>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
export const QuoteAltIcon = () => (
|
|
57
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
58
|
+
<path d="M6.43756 15.9909C5.66487 15.1706 5.25 14.25 5.25 12.7578C5.25 10.1332 7.09238 7.78029 9.77294 6.61743L10.4425 7.65064C7.94103 9.00409 7.45214 10.7595 7.25673 11.8665C7.65947 11.6583 8.18669 11.585 8.70353 11.6329C10.0568 11.7584 11.1234 12.8693 11.1234 14.25C11.1234 15.6998 9.94812 16.875 8.49837 16.875C7.69357 16.875 6.92397 16.5072 6.43756 15.9909ZM13.9375 15.9909C13.1649 15.1706 12.75 14.25 12.75 12.7578C12.75 10.1332 14.5924 7.78029 17.2729 6.61743L17.9425 7.65064C15.441 9.00409 14.9522 10.7595 14.7567 11.8665C15.1594 11.6583 15.6867 11.585 16.2035 11.6329C17.5568 11.7584 18.6234 12.8693 18.6234 14.25C18.6234 15.6998 17.4481 16.875 15.9984 16.875C15.1936 16.875 14.424 16.5072 13.9375 15.9909Z" fill="#626A90"/>
|
|
59
|
+
</svg>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
export const DividerIcon = () => (
|
|
63
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
64
|
+
<rect x="5.25" y="11.25" width="13.5" height="1.5" fill="#626A90"/>
|
|
65
|
+
<circle cx="21.75" cy="12" r="0.75" fill="#626A90" fill-opacity="0.5"/>
|
|
66
|
+
<circle cx="2.25" cy="12" r="0.75" fill="#626A90" fill-opacity="0.5"/>
|
|
67
|
+
</svg>
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
export const UndoIcon = () => (
|
|
71
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
72
|
+
<path d="M14.25 16.5H15.375C16.4105 16.5 17.25 15.6605 17.25 14.625C17.25 13.5895 16.4105 12.75 15.375 12.75H5.25V11.25H15.375C17.239 11.25 18.75 12.761 18.75 14.625C18.75 16.489 17.239 18 15.375 18H14.25V19.5L11.25 17.25L14.25 15V16.5ZM5.25 6H18.75V7.5H5.25V6ZM9.75 16.5V18H5.25V16.5H9.75Z" fill="#626A90"/>
|
|
73
|
+
</svg>
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
export const RedoIcon = () => (
|
|
77
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
78
|
+
<path d="M6.06131 6.69136C7.57508 5.61718 9.42169 5.01103 11.2847 5.00012C13.6826 4.98606 15.9892 5.92634 17.705 7.61633C19.4208 9.30632 20.4039 11.6033 20.4411 14.0084C20.4784 16.4135 19.5668 18.7239 17.9042 20.4371C16.2415 22.1504 13.9686 23.123 11.5794 23.1437C9.19013 23.1643 6.87707 22.2312 5.14341 20.5472L6.18225 19.4716C7.62779 20.8757 9.55655 21.6538 11.5488 21.6366C13.5411 21.6193 15.4363 20.8083 16.8227 19.3798C18.2091 17.9513 18.9692 16.0248 18.9381 14.0194C18.9071 12.014 18.0873 10.0987 16.6567 8.68961C15.2261 7.28052 13.3028 6.49646 11.3033 6.50818C9.75051 6.51728 8.21142 7.02243 6.94998 7.91782L10.25 11.25H5.25V6.25L6.06131 6.69136Z" fill="#626A90"/>
|
|
79
|
+
</svg>
|
|
80
|
+
);
|
|
81
|
+
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
@import '../../styles/index.scss';
|
|
2
|
+
|
|
3
|
+
.wysiwyg-editor {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
align-items: stretch;
|
|
7
|
+
align-self: stretch;
|
|
8
|
+
gap: var(--spacing-reg);
|
|
9
|
+
width: 100%;
|
|
10
|
+
|
|
11
|
+
&__label {
|
|
12
|
+
font-family: var(--font-family-sans, 'Geist', sans-serif);
|
|
13
|
+
color: var(--label-primary);
|
|
14
|
+
font-size: 15px;
|
|
15
|
+
font-style: normal;
|
|
16
|
+
font-weight: 600;
|
|
17
|
+
line-height: 20px;
|
|
18
|
+
margin: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&__required {
|
|
22
|
+
color: var(--label-status-error, #ef4444);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
&__wrapper {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
border: 2px solid var(--border-primary, #e8e9ef);
|
|
29
|
+
border-radius: var(--radius-md, 4px);
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
background-color: var(--surface-secondary, #f8f8fa);
|
|
32
|
+
transition: border-color 0.2s ease;
|
|
33
|
+
|
|
34
|
+
&:focus-within {
|
|
35
|
+
border-color: var(--border-selected, #6200EE);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&--error {
|
|
39
|
+
border-color: var(--borders-status-border-error, #ef4444);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&__toolbar {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-wrap: wrap;
|
|
46
|
+
padding: 0 4px;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: 0;
|
|
49
|
+
align-self: stretch;
|
|
50
|
+
border-radius: 2px 2px 0 0;
|
|
51
|
+
background: var(--surface-tertiary);
|
|
52
|
+
border-bottom: 2px solid var(--border-primary);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&__toolbar-btn {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
width: 40px;
|
|
60
|
+
height: 40px;
|
|
61
|
+
border: none;
|
|
62
|
+
background: transparent;
|
|
63
|
+
border-radius: 4px;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
color: var(--label-secondary);
|
|
66
|
+
transition: all 0.2s ease;
|
|
67
|
+
|
|
68
|
+
svg {
|
|
69
|
+
width: 24px;
|
|
70
|
+
height: 24px;
|
|
71
|
+
flex-shrink: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
&[title="Heading 1"] svg,
|
|
75
|
+
&[title="Heading 2"] svg {
|
|
76
|
+
transform: scale(0.8);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
&:hover {
|
|
80
|
+
background-color: var(--surface-secondary);
|
|
81
|
+
color: var(--label-primary);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
&--active {
|
|
85
|
+
background-color: var(--surface-action-soft, #efeffe);
|
|
86
|
+
color: var(--label-action, #5d5bf4);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
&__toolbar-divider {
|
|
91
|
+
width: 1px;
|
|
92
|
+
height: 18px;
|
|
93
|
+
background-color: var(--border-primary, #e8e9ef);
|
|
94
|
+
margin: 0 8px;
|
|
95
|
+
display: block;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
&__content {
|
|
99
|
+
min-height: 200px;
|
|
100
|
+
padding: 12px;
|
|
101
|
+
outline: none;
|
|
102
|
+
font-family: var(--font-family-sans, 'Geist', sans-serif);
|
|
103
|
+
font-size: var(--text-regular-size, 15px);
|
|
104
|
+
line-height: var(--text-regular-line, 20px);
|
|
105
|
+
color: var(--label-primary, #121e52);
|
|
106
|
+
background-color: var(--surface-secondary, #f8f8fa);
|
|
107
|
+
overflow-y: auto;
|
|
108
|
+
text-align: left;
|
|
109
|
+
|
|
110
|
+
@media (max-width: 768px) {
|
|
111
|
+
font-size: 16px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
&--disabled {
|
|
115
|
+
background-color: var(--surface-status-disabled, #f8f8fa);
|
|
116
|
+
cursor: not-allowed;
|
|
117
|
+
opacity: 0.6;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
&:empty:before {
|
|
121
|
+
content: attr(data-placeholder);
|
|
122
|
+
color: var(--label-secondary, #626a90);
|
|
123
|
+
pointer-events: none;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Styles for content elements
|
|
127
|
+
h1, h2, p, ul, ol, blockquote, hr {
|
|
128
|
+
font-family: var(--font-family-sans, 'Geist', sans-serif);
|
|
129
|
+
font-size: var(--text-regular-size, 15px);
|
|
130
|
+
line-height: var(--text-regular-line, 20px);
|
|
131
|
+
color: var(--label-primary, #121e52);
|
|
132
|
+
overflow-y: auto;
|
|
133
|
+
text-align: left;
|
|
134
|
+
|
|
135
|
+
@media (max-width: 768px) {
|
|
136
|
+
font-size: 16px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
&:first-child {
|
|
140
|
+
margin-top: 0;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
h1 {
|
|
145
|
+
font-size: 22px;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
h2 {
|
|
149
|
+
font-size: 20px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
h3 {
|
|
153
|
+
font-size: 18px;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
h4 {
|
|
157
|
+
font-size: 16px;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
h5 {
|
|
161
|
+
font-size: 14px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
h6 {
|
|
165
|
+
font-size: 13px;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
p {
|
|
169
|
+
margin: 8px 0;
|
|
170
|
+
font-family: var(--font-family-sans, 'Geist', sans-serif);
|
|
171
|
+
font-size: var(--text-regular-size, 15px);
|
|
172
|
+
line-height: var(--text-regular-line, 20px);
|
|
173
|
+
color: var(--label-primary, #121e52);
|
|
174
|
+
|
|
175
|
+
&:first-child {
|
|
176
|
+
margin-top: 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
&:last-child {
|
|
180
|
+
margin-bottom: 0;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
ul, ol {
|
|
185
|
+
margin: 8px 0;
|
|
186
|
+
padding-left: 24px;
|
|
187
|
+
font-family: var(--font-family-sans, 'Geist', sans-serif);
|
|
188
|
+
font-size: var(--text-regular-size, 15px);
|
|
189
|
+
line-height: var(--text-regular-line, 20px);
|
|
190
|
+
color: var(--label-primary, #121e52);
|
|
191
|
+
|
|
192
|
+
&:first-child {
|
|
193
|
+
margin-top: 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
&:last-child {
|
|
197
|
+
margin-bottom: 0;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
li {
|
|
202
|
+
margin: 4px 0;
|
|
203
|
+
font-family: var(--font-family-sans, 'Geist', sans-serif);
|
|
204
|
+
font-size: var(--text-regular-size, 15px);
|
|
205
|
+
line-height: var(--text-regular-line, 20px);
|
|
206
|
+
color: var(--label-primary, #121e52);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
blockquote {
|
|
210
|
+
margin: 12px 0;
|
|
211
|
+
padding: 8px 16px;
|
|
212
|
+
border-left: 4px solid var(--border-selected, #121e52);
|
|
213
|
+
background-color: var(--surface-tertiary, #efefef);
|
|
214
|
+
font-family: var(--font-family-sans, 'Geist', sans-serif);
|
|
215
|
+
font-size: var(--text-regular-size, 15px);
|
|
216
|
+
line-height: var(--text-regular-line, 20px);
|
|
217
|
+
color: var(--label-secondary, #626a90);
|
|
218
|
+
font-style: italic;
|
|
219
|
+
|
|
220
|
+
&:first-child {
|
|
221
|
+
margin-top: 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
&:last-child {
|
|
225
|
+
margin-bottom: 0;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
hr {
|
|
230
|
+
display: block;
|
|
231
|
+
margin: 16px 0;
|
|
232
|
+
border: none;
|
|
233
|
+
border-top: 2px solid var(--border-primary, #e8e9ef);
|
|
234
|
+
height: 0;
|
|
235
|
+
box-sizing: content-box;
|
|
236
|
+
opacity: 1;
|
|
237
|
+
visibility: visible;
|
|
238
|
+
|
|
239
|
+
&:first-child {
|
|
240
|
+
margin-top: 0;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
&:last-child {
|
|
244
|
+
margin-bottom: 0;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
strong, b {
|
|
249
|
+
font-weight: 600;
|
|
250
|
+
color: var(--label-primary, #121e52);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
em, i {
|
|
254
|
+
font-style: italic;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
u {
|
|
258
|
+
text-decoration: underline;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
s, strike {
|
|
262
|
+
text-decoration: line-through;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
code {
|
|
266
|
+
font-family: 'Monaco', 'Courier New', monospace;
|
|
267
|
+
font-size: 12px;
|
|
268
|
+
background-color: var(--surface-tertiary, #efefef);
|
|
269
|
+
padding: 2px 4px;
|
|
270
|
+
border-radius: 3px;
|
|
271
|
+
color: var(--label-primary, #121e52);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
pre {
|
|
275
|
+
margin: 12px 0;
|
|
276
|
+
padding: 12px;
|
|
277
|
+
background-color: var(--surface-tertiary, #efefef);
|
|
278
|
+
border-radius: var(--radius-sm, 4px);
|
|
279
|
+
overflow-x: auto;
|
|
280
|
+
|
|
281
|
+
code {
|
|
282
|
+
background-color: transparent;
|
|
283
|
+
padding: 0;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
a {
|
|
288
|
+
color: var(--label-action, #5d5bf4);
|
|
289
|
+
text-decoration: underline;
|
|
290
|
+
cursor: pointer;
|
|
291
|
+
|
|
292
|
+
&:hover {
|
|
293
|
+
color: var(--label-action-hover, #4a48d1);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
&__placeholder {
|
|
299
|
+
color: var(--label-secondary, #626a90);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
&__help-text {
|
|
303
|
+
font-family: var(--font-family-sans, 'Geist', sans-serif);
|
|
304
|
+
font-size: var(--text-regular-size, 15px);
|
|
305
|
+
font-style: normal;
|
|
306
|
+
font-weight: 400;
|
|
307
|
+
line-height: var(--text-regular-line, 20px);
|
|
308
|
+
margin-top: -5px;
|
|
309
|
+
color: var(--label-secondary);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
&__error-text {
|
|
313
|
+
font-size: var(--text-xs-size, 11px);
|
|
314
|
+
color: var(--label-status-error, #ef4444);
|
|
315
|
+
margin-top: 2px;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { WYSIWYGEditor } from './WYSIWYGEditor'
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof WYSIWYGEditor> = {
|
|
6
|
+
title: 'V2/Components/WYSIWYGEditor',
|
|
7
|
+
component: WYSIWYGEditor,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'padded',
|
|
10
|
+
},
|
|
11
|
+
tags: ['autodocs'],
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default meta
|
|
15
|
+
type Story = StoryObj<typeof WYSIWYGEditor>
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {
|
|
18
|
+
args: {
|
|
19
|
+
label: 'Waiver Text',
|
|
20
|
+
placeholder: 'Enter waiver text here...',
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const WithHelpText: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
label: 'Waiver Text',
|
|
27
|
+
helpText: 'Enter the legal text for your waiver. You can use the toolbar to format the text.',
|
|
28
|
+
placeholder: 'Enter waiver text here...',
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const WithError: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
label: 'Waiver Text',
|
|
35
|
+
error: 'This field is required',
|
|
36
|
+
placeholder: 'Enter waiver text here...',
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const WithInitialValue: Story = {
|
|
41
|
+
args: {
|
|
42
|
+
label: 'Waiver Text',
|
|
43
|
+
value: '<p><strong>Waiver Agreement</strong></p><p>By signing this document, you agree to the following terms and conditions...</p><ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>',
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const Disabled: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
label: 'Waiver Text',
|
|
50
|
+
disabled: true,
|
|
51
|
+
value: '<p>This editor is disabled and cannot be edited.</p>',
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Controlled editor with state management
|
|
56
|
+
export const Controlled: Story = {
|
|
57
|
+
render: () => {
|
|
58
|
+
const [value, setValue] = useState('<p>Start typing here...</p>')
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
|
|
62
|
+
<WYSIWYGEditor
|
|
63
|
+
label="Controlled Editor"
|
|
64
|
+
helpText="The content below updates as you type"
|
|
65
|
+
value={value}
|
|
66
|
+
onChange={setValue}
|
|
67
|
+
/>
|
|
68
|
+
<div style={{ padding: '16px', background: '#f8f9fa', borderRadius: '8px' }}>
|
|
69
|
+
<strong>Current HTML Value:</strong>
|
|
70
|
+
<pre style={{
|
|
71
|
+
marginTop: '8px',
|
|
72
|
+
padding: '12px',
|
|
73
|
+
background: 'white',
|
|
74
|
+
borderRadius: '4px',
|
|
75
|
+
fontSize: '12px',
|
|
76
|
+
overflow: 'auto'
|
|
77
|
+
}}>
|
|
78
|
+
{value}
|
|
79
|
+
</pre>
|
|
80
|
+
<div style={{ marginTop: '12px' }}>
|
|
81
|
+
<strong>Character Count:</strong> {value.length}
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
<button
|
|
85
|
+
onClick={() => setValue('<p>Content has been reset!</p>')}
|
|
86
|
+
style={{
|
|
87
|
+
padding: '8px 16px',
|
|
88
|
+
background: '#269B36',
|
|
89
|
+
color: 'white',
|
|
90
|
+
border: 'none',
|
|
91
|
+
borderRadius: '4px',
|
|
92
|
+
cursor: 'pointer',
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
Reset Content
|
|
96
|
+
</button>
|
|
97
|
+
</div>
|
|
98
|
+
)
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Real-world waiver form example
|
|
103
|
+
export const WaiverFormExample: Story = {
|
|
104
|
+
render: () => {
|
|
105
|
+
const [waiverText, setWaiverText] = useState(`<p><strong>WAIVER AND RELEASE OF LIABILITY</strong></p>
|
|
106
|
+
<p>In consideration of being allowed to participate in any way in the activities and events of [Company Name], the undersigned:</p>
|
|
107
|
+
<ol>
|
|
108
|
+
<li>Agrees that prior to participating, they will inspect the facilities and equipment to be used, and if they believe anything is unsafe, they will immediately advise their supervisor of such condition(s) and refuse to participate.</li>
|
|
109
|
+
<li>Acknowledges and fully understands that each participant will be engaging in activities that involve risk of serious injury, including permanent disability and death, and severe social and economic losses which might result not only from their own actions, inactions or negligence but the action, inaction or negligence of others, the rules of play, or the condition of the premises or of any equipment used.</li>
|
|
110
|
+
<li>Assumes all risks and accepts responsibility for the damages following such injury, permanent disability or death, even if caused, in whole or in part, by the action, inaction or negligence of the releasees named below.</li>
|
|
111
|
+
</ol>
|
|
112
|
+
<p><strong>I HAVE READ THIS RELEASE OF LIABILITY AND ASSUMPTION OF RISK AGREEMENT, FULLY UNDERSTAND ITS TERMS, UNDERSTAND THAT I HAVE GIVEN UP SUBSTANTIAL RIGHTS BY SIGNING IT, AND SIGN IT FREELY AND VOLUNTARILY WITHOUT ANY INDUCEMENT.</strong></p>`)
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '20px', maxWidth: '800px' }}>
|
|
116
|
+
<h3>Waiver Template Form</h3>
|
|
117
|
+
|
|
118
|
+
<div>
|
|
119
|
+
<label style={{ display: 'block', marginBottom: '8px', fontWeight: 500 }}>
|
|
120
|
+
Template Name
|
|
121
|
+
</label>
|
|
122
|
+
<input
|
|
123
|
+
type="text"
|
|
124
|
+
defaultValue="General Liability Waiver"
|
|
125
|
+
style={{
|
|
126
|
+
width: '100%',
|
|
127
|
+
padding: '8px 12px',
|
|
128
|
+
border: '1px solid #ddd',
|
|
129
|
+
borderRadius: '4px',
|
|
130
|
+
}}
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<WYSIWYGEditor
|
|
135
|
+
label="Waiver Text"
|
|
136
|
+
helpText="Enter the legal text for your waiver. Use the toolbar to format as needed."
|
|
137
|
+
value={waiverText}
|
|
138
|
+
onChange={setWaiverText}
|
|
139
|
+
/>
|
|
140
|
+
|
|
141
|
+
<div style={{
|
|
142
|
+
padding: '16px',
|
|
143
|
+
background: '#f8f9fa',
|
|
144
|
+
borderRadius: '8px',
|
|
145
|
+
fontSize: '14px'
|
|
146
|
+
}}>
|
|
147
|
+
<strong>Preview:</strong>
|
|
148
|
+
<div
|
|
149
|
+
style={{
|
|
150
|
+
marginTop: '12px',
|
|
151
|
+
padding: '16px',
|
|
152
|
+
background: 'white',
|
|
153
|
+
borderRadius: '4px',
|
|
154
|
+
border: '1px solid #e0e0e0'
|
|
155
|
+
}}
|
|
156
|
+
dangerouslySetInnerHTML={{ __html: waiverText }}
|
|
157
|
+
/>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<div style={{ display: 'flex', gap: '12px' }}>
|
|
161
|
+
<button
|
|
162
|
+
style={{
|
|
163
|
+
padding: '10px 20px',
|
|
164
|
+
background: '#269B36',
|
|
165
|
+
color: 'white',
|
|
166
|
+
border: 'none',
|
|
167
|
+
borderRadius: '4px',
|
|
168
|
+
cursor: 'pointer',
|
|
169
|
+
fontWeight: 500,
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
Save Waiver Template
|
|
173
|
+
</button>
|
|
174
|
+
<button
|
|
175
|
+
style={{
|
|
176
|
+
padding: '10px 20px',
|
|
177
|
+
background: '#6c757d',
|
|
178
|
+
color: 'white',
|
|
179
|
+
border: 'none',
|
|
180
|
+
borderRadius: '4px',
|
|
181
|
+
cursor: 'pointer',
|
|
182
|
+
}}
|
|
183
|
+
>
|
|
184
|
+
Cancel
|
|
185
|
+
</button>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
)
|
|
189
|
+
},
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Demonstrates all formatting options
|
|
193
|
+
export const FormattingShowcase: Story = {
|
|
194
|
+
args: {
|
|
195
|
+
label: 'Formatting Options',
|
|
196
|
+
helpText: 'Try using the toolbar buttons to format your text',
|
|
197
|
+
value: `<h1>Heading 1</h1>
|
|
198
|
+
<h2>Heading 2</h2>
|
|
199
|
+
<p>This is <strong>bold text</strong>, <em>italic text</em>, <u>underlined text</u>, and <del>strikethrough text</del>.</p>
|
|
200
|
+
<blockquote>This is a blockquote</blockquote>
|
|
201
|
+
<p>Unordered list:</p>
|
|
202
|
+
<ul>
|
|
203
|
+
<li>First item</li>
|
|
204
|
+
<li>Second item</li>
|
|
205
|
+
<li>Third item</li>
|
|
206
|
+
</ul>
|
|
207
|
+
<p>Ordered list:</p>
|
|
208
|
+
<ol>
|
|
209
|
+
<li>First item</li>
|
|
210
|
+
<li>Second item</li>
|
|
211
|
+
<li>Third item</li>
|
|
212
|
+
</ol>
|
|
213
|
+
<hr>
|
|
214
|
+
<p>Normal text after a divider</p>`,
|
|
215
|
+
},
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Maximum length validation example
|
|
219
|
+
export const WithMaxLength: Story = {
|
|
220
|
+
render: () => {
|
|
221
|
+
const MAX_LENGTH = 25500
|
|
222
|
+
const [value, setValue] = useState('<p>Start typing...</p>')
|
|
223
|
+
const remaining = MAX_LENGTH - value.length
|
|
224
|
+
const isOverLimit = remaining < 0
|
|
225
|
+
|
|
226
|
+
return (
|
|
227
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
|
228
|
+
<WYSIWYGEditor
|
|
229
|
+
label="Waiver Text"
|
|
230
|
+
helpText={`Maximum 25,500 characters`}
|
|
231
|
+
error={isOverLimit ? `Exceeds maximum length by ${Math.abs(remaining)} characters` : undefined}
|
|
232
|
+
value={value}
|
|
233
|
+
onChange={setValue}
|
|
234
|
+
/>
|
|
235
|
+
<div style={{
|
|
236
|
+
padding: '12px',
|
|
237
|
+
background: isOverLimit ? '#fee' : '#f8f9fa',
|
|
238
|
+
borderRadius: '4px',
|
|
239
|
+
fontSize: '14px'
|
|
240
|
+
}}>
|
|
241
|
+
<strong>Characters:</strong> {value.length.toLocaleString()} / {MAX_LENGTH.toLocaleString()}
|
|
242
|
+
<div style={{ marginTop: '4px', color: isOverLimit ? '#dc3545' : '#28a745' }}>
|
|
243
|
+
{isOverLimit
|
|
244
|
+
? `❌ ${Math.abs(remaining).toLocaleString()} over limit`
|
|
245
|
+
: `✓ ${remaining.toLocaleString()} remaining`
|
|
246
|
+
}
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
)
|
|
251
|
+
},
|
|
252
|
+
}
|