@faststore/components 3.98.0-dev.1 → 3.98.0-dev.8

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 (198) hide show
  1. package/dist/cjs/atoms/Link/Link.d.ts +1 -1
  2. package/dist/cjs/atoms/Link/Link.d.ts.map +1 -1
  3. package/dist/cjs/atoms/Link/Link.js.map +1 -1
  4. package/dist/cjs/atoms/List/List.d.ts.map +1 -1
  5. package/dist/cjs/atoms/List/List.js.map +1 -1
  6. package/dist/cjs/hooks/index.d.ts +7 -3
  7. package/dist/cjs/hooks/index.d.ts.map +1 -1
  8. package/dist/cjs/hooks/index.js +12 -6
  9. package/dist/cjs/hooks/index.js.map +1 -1
  10. package/dist/cjs/hooks/useCSVParser.d.ts +43 -0
  11. package/dist/cjs/hooks/useCSVParser.d.ts.map +1 -0
  12. package/dist/cjs/hooks/useCSVParser.js +264 -0
  13. package/dist/cjs/hooks/useCSVParser.js.map +1 -0
  14. package/dist/cjs/hooks/useFileUpload.d.ts +26 -0
  15. package/dist/cjs/hooks/useFileUpload.d.ts.map +1 -0
  16. package/dist/cjs/hooks/useFileUpload.js +68 -0
  17. package/dist/cjs/hooks/useFileUpload.js.map +1 -0
  18. package/dist/cjs/index.d.ts +58 -50
  19. package/dist/cjs/index.d.ts.map +1 -1
  20. package/dist/cjs/index.js +47 -32
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/molecules/Accordion/AccordionItem.d.ts.map +1 -1
  23. package/dist/cjs/molecules/Accordion/AccordionItem.js.map +1 -1
  24. package/dist/cjs/molecules/Dropzone/Dropzone.d.ts +87 -0
  25. package/dist/cjs/molecules/Dropzone/Dropzone.d.ts.map +1 -0
  26. package/dist/cjs/molecules/Dropzone/Dropzone.js +85 -0
  27. package/dist/cjs/molecules/Dropzone/Dropzone.js.map +1 -0
  28. package/dist/cjs/molecules/Dropzone/index.d.ts +3 -0
  29. package/dist/cjs/molecules/Dropzone/index.d.ts.map +1 -0
  30. package/dist/cjs/molecules/Dropzone/index.js +9 -0
  31. package/dist/cjs/molecules/Dropzone/index.js.map +1 -0
  32. package/dist/cjs/molecules/FileUploadCard/FileUploadCard.d.ts +113 -0
  33. package/dist/cjs/molecules/FileUploadCard/FileUploadCard.d.ts.map +1 -0
  34. package/dist/cjs/molecules/FileUploadCard/FileUploadCard.js +169 -0
  35. package/dist/cjs/molecules/FileUploadCard/FileUploadCard.js.map +1 -0
  36. package/dist/cjs/molecules/FileUploadCard/index.d.ts +3 -0
  37. package/dist/cjs/molecules/FileUploadCard/index.d.ts.map +1 -0
  38. package/dist/cjs/molecules/FileUploadCard/index.js +9 -0
  39. package/dist/cjs/molecules/FileUploadCard/index.js.map +1 -0
  40. package/dist/cjs/molecules/FileUploadStatus/FileUploadStatus.d.ts +93 -0
  41. package/dist/cjs/molecules/FileUploadStatus/FileUploadStatus.d.ts.map +1 -0
  42. package/dist/cjs/molecules/FileUploadStatus/FileUploadStatus.js +77 -0
  43. package/dist/cjs/molecules/FileUploadStatus/FileUploadStatus.js.map +1 -0
  44. package/dist/cjs/molecules/FileUploadStatus/index.d.ts +3 -0
  45. package/dist/cjs/molecules/FileUploadStatus/index.d.ts.map +1 -0
  46. package/dist/cjs/molecules/FileUploadStatus/index.js +11 -0
  47. package/dist/cjs/molecules/FileUploadStatus/index.js.map +1 -0
  48. package/dist/cjs/molecules/SearchInputField/SearchInputField.d.ts +23 -1
  49. package/dist/cjs/molecules/SearchInputField/SearchInputField.d.ts.map +1 -1
  50. package/dist/cjs/molecules/SearchInputField/SearchInputField.js +9 -4
  51. package/dist/cjs/molecules/SearchInputField/SearchInputField.js.map +1 -1
  52. package/dist/cjs/molecules/SearchProducts/SearchProductItem.d.ts +1 -1
  53. package/dist/cjs/molecules/SearchProducts/SearchProductItem.d.ts.map +1 -1
  54. package/dist/cjs/molecules/SearchProducts/SearchProductItem.js +2 -2
  55. package/dist/cjs/molecules/SearchProducts/SearchProductItem.js.map +1 -1
  56. package/dist/cjs/molecules/SearchProvider/SearchProvider.d.ts +5 -1
  57. package/dist/cjs/molecules/SearchProvider/SearchProvider.d.ts.map +1 -1
  58. package/dist/cjs/molecules/SearchProvider/SearchProvider.js +2 -2
  59. package/dist/cjs/molecules/SearchProvider/SearchProvider.js.map +1 -1
  60. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawer.d.ts +24 -0
  61. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawer.d.ts.map +1 -0
  62. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawer.js +14 -0
  63. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawer.js.map +1 -0
  64. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerFooter.d.ts +16 -0
  65. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerFooter.d.ts.map +1 -0
  66. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerFooter.js +37 -0
  67. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerFooter.js.map +1 -0
  68. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerHeader.d.ts +9 -0
  69. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerHeader.d.ts.map +1 -0
  70. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerHeader.js +24 -0
  71. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerHeader.js.map +1 -0
  72. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerProducts.d.ts +35 -0
  73. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerProducts.d.ts.map +1 -0
  74. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerProducts.js +91 -0
  75. package/dist/cjs/organisms/QuickOrderDrawer/QuickOrderDrawerProducts.js.map +1 -0
  76. package/dist/cjs/organisms/QuickOrderDrawer/index.d.ts +11 -0
  77. package/dist/cjs/organisms/QuickOrderDrawer/index.d.ts.map +1 -0
  78. package/dist/cjs/organisms/QuickOrderDrawer/index.js +18 -0
  79. package/dist/cjs/organisms/QuickOrderDrawer/index.js.map +1 -0
  80. package/dist/cjs/organisms/QuickOrderDrawer/provider/QuickOrderDrawerProvider.d.ts +61 -0
  81. package/dist/cjs/organisms/QuickOrderDrawer/provider/QuickOrderDrawerProvider.d.ts.map +1 -0
  82. package/dist/cjs/organisms/QuickOrderDrawer/provider/QuickOrderDrawerProvider.js +86 -0
  83. package/dist/cjs/organisms/QuickOrderDrawer/provider/QuickOrderDrawerProvider.js.map +1 -0
  84. package/dist/cjs/organisms/SearchInput/SearchInput.d.ts +8 -0
  85. package/dist/cjs/organisms/SearchInput/SearchInput.d.ts.map +1 -1
  86. package/dist/cjs/organisms/SearchInput/SearchInput.js +2 -2
  87. package/dist/cjs/organisms/SearchInput/SearchInput.js.map +1 -1
  88. package/dist/esm/atoms/Link/Link.d.ts +1 -1
  89. package/dist/esm/atoms/Link/Link.d.ts.map +1 -1
  90. package/dist/esm/atoms/Link/Link.js.map +1 -1
  91. package/dist/esm/atoms/List/List.d.ts.map +1 -1
  92. package/dist/esm/atoms/List/List.js.map +1 -1
  93. package/dist/esm/hooks/index.d.ts +7 -3
  94. package/dist/esm/hooks/index.d.ts.map +1 -1
  95. package/dist/esm/hooks/index.js +6 -3
  96. package/dist/esm/hooks/index.js.map +1 -1
  97. package/dist/esm/hooks/useCSVParser.d.ts +43 -0
  98. package/dist/esm/hooks/useCSVParser.d.ts.map +1 -0
  99. package/dist/esm/hooks/useCSVParser.js +259 -0
  100. package/dist/esm/hooks/useCSVParser.js.map +1 -0
  101. package/dist/esm/hooks/useFileUpload.d.ts +26 -0
  102. package/dist/esm/hooks/useFileUpload.d.ts.map +1 -0
  103. package/dist/esm/hooks/useFileUpload.js +64 -0
  104. package/dist/esm/hooks/useFileUpload.js.map +1 -0
  105. package/dist/esm/index.d.ts +58 -50
  106. package/dist/esm/index.d.ts.map +1 -1
  107. package/dist/esm/index.js +24 -20
  108. package/dist/esm/index.js.map +1 -1
  109. package/dist/esm/molecules/Accordion/AccordionItem.d.ts.map +1 -1
  110. package/dist/esm/molecules/Accordion/AccordionItem.js.map +1 -1
  111. package/dist/esm/molecules/Dropzone/Dropzone.d.ts +87 -0
  112. package/dist/esm/molecules/Dropzone/Dropzone.d.ts.map +1 -0
  113. package/dist/esm/molecules/Dropzone/Dropzone.js +82 -0
  114. package/dist/esm/molecules/Dropzone/Dropzone.js.map +1 -0
  115. package/dist/esm/molecules/Dropzone/index.d.ts +3 -0
  116. package/dist/esm/molecules/Dropzone/index.d.ts.map +1 -0
  117. package/dist/esm/molecules/Dropzone/index.js +2 -0
  118. package/dist/esm/molecules/Dropzone/index.js.map +1 -0
  119. package/dist/esm/molecules/FileUploadCard/FileUploadCard.d.ts +113 -0
  120. package/dist/esm/molecules/FileUploadCard/FileUploadCard.d.ts.map +1 -0
  121. package/dist/esm/molecules/FileUploadCard/FileUploadCard.js +166 -0
  122. package/dist/esm/molecules/FileUploadCard/FileUploadCard.js.map +1 -0
  123. package/dist/esm/molecules/FileUploadCard/index.d.ts +3 -0
  124. package/dist/esm/molecules/FileUploadCard/index.d.ts.map +1 -0
  125. package/dist/esm/molecules/FileUploadCard/index.js +2 -0
  126. package/dist/esm/molecules/FileUploadCard/index.js.map +1 -0
  127. package/dist/esm/molecules/FileUploadStatus/FileUploadStatus.d.ts +93 -0
  128. package/dist/esm/molecules/FileUploadStatus/FileUploadStatus.d.ts.map +1 -0
  129. package/dist/esm/molecules/FileUploadStatus/FileUploadStatus.js +73 -0
  130. package/dist/esm/molecules/FileUploadStatus/FileUploadStatus.js.map +1 -0
  131. package/dist/esm/molecules/FileUploadStatus/index.d.ts +3 -0
  132. package/dist/esm/molecules/FileUploadStatus/index.d.ts.map +1 -0
  133. package/dist/esm/molecules/FileUploadStatus/index.js +2 -0
  134. package/dist/esm/molecules/FileUploadStatus/index.js.map +1 -0
  135. package/dist/esm/molecules/SearchInputField/SearchInputField.d.ts +23 -1
  136. package/dist/esm/molecules/SearchInputField/SearchInputField.d.ts.map +1 -1
  137. package/dist/esm/molecules/SearchInputField/SearchInputField.js +9 -4
  138. package/dist/esm/molecules/SearchInputField/SearchInputField.js.map +1 -1
  139. package/dist/esm/molecules/SearchProducts/SearchProductItem.d.ts +1 -1
  140. package/dist/esm/molecules/SearchProducts/SearchProductItem.d.ts.map +1 -1
  141. package/dist/esm/molecules/SearchProducts/SearchProductItem.js +2 -2
  142. package/dist/esm/molecules/SearchProducts/SearchProductItem.js.map +1 -1
  143. package/dist/esm/molecules/SearchProvider/SearchProvider.d.ts +5 -1
  144. package/dist/esm/molecules/SearchProvider/SearchProvider.d.ts.map +1 -1
  145. package/dist/esm/molecules/SearchProvider/SearchProvider.js +2 -2
  146. package/dist/esm/molecules/SearchProvider/SearchProvider.js.map +1 -1
  147. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawer.d.ts +24 -0
  148. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawer.d.ts.map +1 -0
  149. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawer.js +11 -0
  150. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawer.js.map +1 -0
  151. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerFooter.d.ts +16 -0
  152. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerFooter.d.ts.map +1 -0
  153. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerFooter.js +34 -0
  154. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerFooter.js.map +1 -0
  155. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerHeader.d.ts +9 -0
  156. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerHeader.d.ts.map +1 -0
  157. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerHeader.js +21 -0
  158. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerHeader.js.map +1 -0
  159. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerProducts.d.ts +35 -0
  160. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerProducts.d.ts.map +1 -0
  161. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerProducts.js +88 -0
  162. package/dist/esm/organisms/QuickOrderDrawer/QuickOrderDrawerProducts.js.map +1 -0
  163. package/dist/esm/organisms/QuickOrderDrawer/index.d.ts +11 -0
  164. package/dist/esm/organisms/QuickOrderDrawer/index.d.ts.map +1 -0
  165. package/dist/esm/organisms/QuickOrderDrawer/index.js +6 -0
  166. package/dist/esm/organisms/QuickOrderDrawer/index.js.map +1 -0
  167. package/dist/esm/organisms/QuickOrderDrawer/provider/QuickOrderDrawerProvider.d.ts +61 -0
  168. package/dist/esm/organisms/QuickOrderDrawer/provider/QuickOrderDrawerProvider.d.ts.map +1 -0
  169. package/dist/esm/organisms/QuickOrderDrawer/provider/QuickOrderDrawerProvider.js +80 -0
  170. package/dist/esm/organisms/QuickOrderDrawer/provider/QuickOrderDrawerProvider.js.map +1 -0
  171. package/dist/esm/organisms/SearchInput/SearchInput.d.ts +8 -0
  172. package/dist/esm/organisms/SearchInput/SearchInput.d.ts.map +1 -1
  173. package/dist/esm/organisms/SearchInput/SearchInput.js +2 -2
  174. package/dist/esm/organisms/SearchInput/SearchInput.js.map +1 -1
  175. package/package.json +5 -2
  176. package/src/atoms/Link/Link.tsx +4 -1
  177. package/src/atoms/List/List.tsx +18 -16
  178. package/src/hooks/index.ts +11 -3
  179. package/src/hooks/useCSVParser.ts +367 -0
  180. package/src/hooks/useFileUpload.ts +88 -0
  181. package/src/index.ts +97 -66
  182. package/src/molecules/Accordion/AccordionItem.tsx +4 -3
  183. package/src/molecules/Dropzone/Dropzone.tsx +248 -0
  184. package/src/molecules/Dropzone/index.ts +2 -0
  185. package/src/molecules/FileUploadCard/FileUploadCard.tsx +406 -0
  186. package/src/molecules/FileUploadCard/index.tsx +2 -0
  187. package/src/molecules/FileUploadStatus/FileUploadStatus.tsx +258 -0
  188. package/src/molecules/FileUploadStatus/index.tsx +6 -0
  189. package/src/molecules/SearchInputField/SearchInputField.tsx +72 -23
  190. package/src/molecules/SearchProducts/SearchProductItem.tsx +8 -3
  191. package/src/molecules/SearchProvider/SearchProvider.tsx +6 -1
  192. package/src/organisms/QuickOrderDrawer/QuickOrderDrawer.tsx +58 -0
  193. package/src/organisms/QuickOrderDrawer/QuickOrderDrawerFooter.tsx +72 -0
  194. package/src/organisms/QuickOrderDrawer/QuickOrderDrawerHeader.tsx +43 -0
  195. package/src/organisms/QuickOrderDrawer/QuickOrderDrawerProducts.tsx +323 -0
  196. package/src/organisms/QuickOrderDrawer/index.ts +19 -0
  197. package/src/organisms/QuickOrderDrawer/provider/QuickOrderDrawerProvider.tsx +205 -0
  198. package/src/organisms/SearchInput/SearchInput.tsx +6 -0
@@ -0,0 +1,323 @@
1
+ import React, { type FunctionComponent } from 'react'
2
+ import Icon from '../../atoms/Icon'
3
+ import IconButton from '../../molecules/IconButton'
4
+ import QuantitySelector from '../../molecules/QuantitySelector'
5
+ import {
6
+ Table,
7
+ TableBody,
8
+ TableCell,
9
+ TableHead,
10
+ TableRow,
11
+ } from '../../molecules/Table'
12
+
13
+ import Badge from '../../atoms/Badge'
14
+ import type { PriceFormatter } from '../../atoms/Price'
15
+ import Price from '../../atoms/Price'
16
+ import Skeleton from '../../atoms/Skeleton'
17
+ import { useUI } from '../../hooks'
18
+ import Alert from '../../molecules/Alert'
19
+ import Tooltip from '../../molecules/Tooltip'
20
+ import {
21
+ useQuickOrderDrawer,
22
+ type VariationProductColumn,
23
+ } from './provider/QuickOrderDrawerProvider'
24
+
25
+ type ImageComponentType = FunctionComponent<{
26
+ src: string
27
+ alt: string
28
+ width?: number
29
+ height?: number
30
+ loading?: 'eager' | 'lazy'
31
+ }>
32
+
33
+ // TODO: Replace with faststore Image component in final implementation
34
+ // This is a temporary reference component for storybook preview
35
+ const DefaultImageComponent: ImageComponentType = ({
36
+ src,
37
+ alt,
38
+ width,
39
+ height,
40
+ ...otherProps
41
+ }) => <img src={src} alt={alt} width={width} height={height} {...otherProps} />
42
+
43
+ export type QuickOrderDrawerProductsProps = {
44
+ columns: VariationProductColumn
45
+ formatter?: PriceFormatter
46
+ ImageComponent?: ImageComponentType
47
+ /**
48
+ * Messages for CMS configuration
49
+ */
50
+ messages?: {
51
+ alertAriaLabel?: string
52
+ tableAriaLabel?: string
53
+ quantityUpdatedTooltip?: string
54
+ quantityUpdatedAriaLabel?: string
55
+ outOfStockLabel?: string
56
+ availableLabel?: string
57
+ selectQuantityAriaLabel?: string
58
+ removeProductAriaLabel?: string
59
+ invalidQuantityTitle?: string
60
+ invalidQuantityMessage?: (
61
+ min: number,
62
+ max: number,
63
+ quantity: number
64
+ ) => string
65
+ emptyStateTitle?: string
66
+ emptyStateMessage?: string
67
+ }
68
+ }
69
+
70
+ const QuickOrderDrawerProducts = ({
71
+ columns,
72
+ formatter,
73
+ ImageComponent = DefaultImageComponent,
74
+ messages,
75
+ }: QuickOrderDrawerProductsProps) => {
76
+ const { pushToast } = useUI()
77
+ const {
78
+ products,
79
+ onChangeQuantityItem,
80
+ onDelete,
81
+ isLoading,
82
+ alertMessage,
83
+ setAlertMessage,
84
+ formatter: contextFormatter,
85
+ } = useQuickOrderDrawer()
86
+ const priceFormatter = formatter || contextFormatter
87
+
88
+ const showSkeleton = isLoading
89
+ return (
90
+ <div data-fs-quick-order-drawer-content>
91
+ <>
92
+ {!isLoading && alertMessage && (
93
+ <Alert
94
+ icon={<Icon name="AlertFilled" weight="bold" />}
95
+ dismissible
96
+ onClick={() => setAlertMessage('')}
97
+ aria-label={messages?.alertAriaLabel}
98
+ >
99
+ {alertMessage}
100
+ </Alert>
101
+ )}
102
+ <Table
103
+ data-fs-quick-order-drawer-table
104
+ variant="bordered"
105
+ aria-label={messages?.tableAriaLabel}
106
+ >
107
+ <TableHead>
108
+ <TableRow>
109
+ <TableCell
110
+ data-fs-quick-order-drawer-product-header
111
+ align="left"
112
+ variant="header"
113
+ scope="col"
114
+ >
115
+ {columns.name}
116
+ </TableCell>
117
+
118
+ <TableCell align="left" variant="header" scope="col">
119
+ {columns.availability.label}
120
+ </TableCell>
121
+
122
+ <TableCell align="center" variant="header" scope="col">
123
+ {columns.price}
124
+ </TableCell>
125
+
126
+ <TableCell align="left" variant="header" scope="col">
127
+ {columns.quantity}
128
+ </TableCell>
129
+ <TableCell align="right" variant="header" scope="col"></TableCell>
130
+ </TableRow>
131
+ </TableHead>
132
+
133
+ <TableBody>
134
+ {showSkeleton ? (
135
+ <>
136
+ {Array.from({ length: 5 }).map((_, index) => {
137
+ return (
138
+ <TableRow key={`table-row-skeleton-${index}`}>
139
+ {Array.from({
140
+ length: 5,
141
+ }).map((_, cellIndex) => {
142
+ return (
143
+ <TableCell key={`table-cell-skeleton-${cellIndex}`}>
144
+ <Skeleton size={{ width: '96%', height: '30px' }} />
145
+ </TableCell>
146
+ )
147
+ })}
148
+ </TableRow>
149
+ )
150
+ })}
151
+ </>
152
+ ) : products.length > 0 ? (
153
+ <>
154
+ {products.map((variantProduct) => (
155
+ <TableRow
156
+ key={`${variantProduct.name}-${variantProduct.id}`}
157
+ data-fs-quick-order-table-row={variantProduct.availability}
158
+ >
159
+ <TableCell data-fs-quick-order-cell="product" align="left">
160
+ <div data-fs-quick-order-table-cell-img-container>
161
+ <ImageComponent
162
+ height={48}
163
+ src={variantProduct.image.url}
164
+ alt={
165
+ variantProduct.image.alternateName ||
166
+ variantProduct.name
167
+ }
168
+ />
169
+ </div>
170
+
171
+ <div data-fs-quick-order-table-cell-name-container>
172
+ <div data-fs-quick-order-text={'primary'}>
173
+ {variantProduct.name}
174
+ </div>
175
+ <span data-fs-quick-order-text={'secondary'}>
176
+ {variantProduct.id}
177
+ </span>
178
+ </div>
179
+ {variantProduct.availability === 'available' &&
180
+ variantProduct.quantityUpdated && (
181
+ <Tooltip
182
+ content={messages?.quantityUpdatedTooltip}
183
+ placement="left-center"
184
+ >
185
+ <IconButton
186
+ aria-label={messages?.quantityUpdatedAriaLabel}
187
+ icon={<Icon name="CircleWarning" weight="bold" />}
188
+ />
189
+ </Tooltip>
190
+ )}
191
+ </TableCell>
192
+
193
+ <TableCell align="left">
194
+ {columns.availability.stockDisplaySettings ===
195
+ 'showAvailability' && (
196
+ <Badge
197
+ variant={
198
+ variantProduct.availability === 'outOfStock'
199
+ ? 'warning'
200
+ : 'success'
201
+ }
202
+ >
203
+ {variantProduct.availability === 'outOfStock'
204
+ ? messages?.outOfStockLabel
205
+ : messages?.availableLabel}
206
+ </Badge>
207
+ )}
208
+
209
+ {columns.availability.stockDisplaySettings ===
210
+ 'showStockQuantity' && variantProduct.inventory}
211
+ </TableCell>
212
+
213
+ <TableCell data-fs-quick-order-cell="price" align="right">
214
+ <Price
215
+ value={variantProduct.price}
216
+ variant="spot"
217
+ formatter={priceFormatter}
218
+ data-fs-quick-order-table-price={
219
+ variantProduct.availability
220
+ }
221
+ />
222
+ </TableCell>
223
+
224
+ <TableCell
225
+ align="right"
226
+ data-fs-quick-order-cell="quantity-selector"
227
+ >
228
+ <div data-fs-quick-order-table-action>
229
+ <QuantitySelector
230
+ min={0}
231
+ max={variantProduct.inventory}
232
+ disabled={
233
+ !variantProduct.inventory ||
234
+ variantProduct.availability === 'outOfStock'
235
+ }
236
+ initial={variantProduct.selectedCount}
237
+ onChange={(value) =>
238
+ onChangeQuantityItem(variantProduct.id, value)
239
+ }
240
+ aria-label={messages?.selectQuantityAriaLabel?.replace(
241
+ '{productName}',
242
+ variantProduct.name
243
+ )}
244
+ onValidateBlur={(
245
+ min: number,
246
+ maxValue: number,
247
+ quantity: number
248
+ ) => {
249
+ const title = messages?.invalidQuantityTitle
250
+ const message = messages?.invalidQuantityMessage
251
+ ? messages.invalidQuantityMessage(
252
+ min,
253
+ maxValue,
254
+ quantity
255
+ )
256
+ : ''
257
+
258
+ pushToast({
259
+ title,
260
+ message,
261
+ status: 'INFO',
262
+ icon: (
263
+ <Icon
264
+ name="CircleWavyWarning"
265
+ width={30}
266
+ height={30}
267
+ />
268
+ ),
269
+ })
270
+ }}
271
+ />
272
+ </div>
273
+ </TableCell>
274
+ <TableCell align="right" data-fs-quick-order-delete-cell>
275
+ <IconButton
276
+ onClick={() => onDelete(variantProduct.id)}
277
+ icon={<Icon name="Thrash" color="#1F1F1F" />}
278
+ aria-label={messages?.removeProductAriaLabel?.replace(
279
+ '{productName}',
280
+ variantProduct.name
281
+ )}
282
+ />
283
+ </TableCell>
284
+ </TableRow>
285
+ ))}
286
+ </>
287
+ ) : (
288
+ <TableRow>
289
+ <TableCell
290
+ align="center"
291
+ data-fs-quick-order-empty-state
292
+ {...({
293
+ colSpan: 5,
294
+ } as React.HTMLAttributes<HTMLTableCellElement>)}
295
+ >
296
+ <div data-fs-quick-order-empty-state-container>
297
+ <Icon
298
+ name="MagnifyingGlass"
299
+ width={48}
300
+ height={48}
301
+ weight="thin"
302
+ data-fs-quick-order-empty-state-icon
303
+ />
304
+ <div data-fs-quick-order-empty-state-content>
305
+ <p data-fs-quick-order-empty-state-title>
306
+ {messages?.emptyStateTitle}
307
+ </p>
308
+ <p data-fs-quick-order-empty-state-message>
309
+ {messages?.emptyStateMessage}
310
+ </p>
311
+ </div>
312
+ </div>
313
+ </TableCell>
314
+ </TableRow>
315
+ )}
316
+ </TableBody>
317
+ </Table>
318
+ </>
319
+ </div>
320
+ )
321
+ }
322
+
323
+ export default QuickOrderDrawerProducts
@@ -0,0 +1,19 @@
1
+ export { default as QuickOrderDrawer, default } from './QuickOrderDrawer'
2
+ export type { QuickOrderDrawerProps } from './QuickOrderDrawer'
3
+
4
+ export { default as QuickOrderDrawerHeader } from './QuickOrderDrawerHeader'
5
+ export type { QuickOrderDrawerHeaderProps } from './QuickOrderDrawerHeader'
6
+
7
+ export { default as QuickOrderDrawerProducts } from './QuickOrderDrawerProducts'
8
+ export type { QuickOrderDrawerProductsProps } from './QuickOrderDrawerProducts'
9
+
10
+ export { default as QuickOrderDrawerFooter } from './QuickOrderDrawerFooter'
11
+ export type { QuickOrderDrawerFooterProps } from './QuickOrderDrawerFooter'
12
+
13
+ export { useQuickOrderDrawer } from './provider/QuickOrderDrawerProvider'
14
+ export type {
15
+ AlertMessages,
16
+ Product,
17
+ QuickOrderDrawerProviderProps,
18
+ VariationProductColumn,
19
+ } from './provider/QuickOrderDrawerProvider'
@@ -0,0 +1,205 @@
1
+ import React, {
2
+ createContext,
3
+ useCallback,
4
+ useContext,
5
+ useEffect,
6
+ useMemo,
7
+ useState,
8
+ type ReactNode,
9
+ } from 'react'
10
+ import type { PriceFormatter } from '../../../atoms/Price'
11
+
12
+ export interface Product {
13
+ id: string
14
+ name: string
15
+ price: number
16
+ quantityUpdated: boolean
17
+ image: {
18
+ url: string
19
+ alternateName: string
20
+ }
21
+ inventory: number
22
+ availability: 'available' | 'outOfStock'
23
+ selectedCount: number
24
+ }
25
+
26
+ export interface VariationProductColumn {
27
+ name: string
28
+ availability: {
29
+ label: string
30
+ stockDisplaySettings: 'showStockQuantity' | 'showAvailability'
31
+ }
32
+ price: string
33
+ quantity: string
34
+ }
35
+
36
+ interface QuickOrderDrawerContextValue {
37
+ products: Product[]
38
+ totalPrice: number
39
+ itemsCount: number
40
+ alertMessage: string
41
+ isLoading: boolean
42
+ setAlertMessage: (message: string) => void
43
+ onChangeQuantityItem: (id: string, value: number) => void
44
+ onDelete: (id: string) => void
45
+ onAddToCart: () => void
46
+ formatter?: PriceFormatter
47
+ }
48
+
49
+ const QuickOrderDrawerContext = createContext<
50
+ QuickOrderDrawerContextValue | undefined
51
+ >(undefined)
52
+
53
+ export interface AlertMessages {
54
+ notFoundAndOutOfStock?: string
55
+ notFound?: string
56
+ outOfStock?: string
57
+ }
58
+
59
+ export interface QuickOrderDrawerProviderProps {
60
+ children: ReactNode
61
+ initialProducts?: Product[]
62
+ isLoading?: boolean
63
+ totalRequestedSkus?: number
64
+ onAddToCart?: (
65
+ products: Product[],
66
+ totalPrice: number,
67
+ itemsCount: number
68
+ ) => void
69
+ formatter?: PriceFormatter
70
+ /**
71
+ * Initial alert message for CMS configuration
72
+ */
73
+ initialAlertMessage?: string
74
+ /**
75
+ * Alert messages from CMS for different scenarios.
76
+ */
77
+ alertMessages?: AlertMessages
78
+ }
79
+
80
+ export const QuickOrderDrawerProvider = ({
81
+ children,
82
+ initialProducts = [],
83
+ isLoading = false,
84
+ totalRequestedSkus,
85
+ onAddToCart: onAddToCartCallback,
86
+ formatter,
87
+ initialAlertMessage,
88
+ alertMessages,
89
+ }: QuickOrderDrawerProviderProps) => {
90
+ const [products, setProducts] = useState<Product[]>(initialProducts || [])
91
+
92
+ const getAlertMessage = (prods: Product[], totalRequestedSkus?: number) => {
93
+ if (prods.length === 0) {
94
+ return ''
95
+ }
96
+
97
+ const hasOutOfStock = prods.some((p) => p.availability === 'outOfStock')
98
+ const hasNotFound =
99
+ totalRequestedSkus !== undefined &&
100
+ totalRequestedSkus > 0 &&
101
+ prods.length < totalRequestedSkus
102
+
103
+ if (hasNotFound && hasOutOfStock) {
104
+ return alertMessages?.notFoundAndOutOfStock ?? ''
105
+ }
106
+ if (hasNotFound) {
107
+ return alertMessages?.notFound ?? ''
108
+ }
109
+ if (hasOutOfStock) {
110
+ return alertMessages?.outOfStock ?? ''
111
+ }
112
+ return ''
113
+ }
114
+
115
+ const [alertMessage, setAlertMessage] = useState<string>(
116
+ initialAlertMessage ?? ''
117
+ )
118
+
119
+ useEffect(() => {
120
+ const newProducts = initialProducts || []
121
+
122
+ setProducts(newProducts)
123
+ }, [initialProducts])
124
+
125
+ useEffect(() => {
126
+ if (!isLoading) {
127
+ setAlertMessage(getAlertMessage(products, totalRequestedSkus))
128
+ } else if (isLoading) {
129
+ setAlertMessage('')
130
+ }
131
+ }, [products, isLoading, totalRequestedSkus])
132
+
133
+ const { totalPrice, itemsCount } = useMemo(() => {
134
+ const filteredProducts = products.filter(
135
+ (product) =>
136
+ product.selectedCount > 0 && product.availability === 'available'
137
+ )
138
+
139
+ return filteredProducts.reduce<{ totalPrice: number; itemsCount: number }>(
140
+ (prev, curr) => ({
141
+ totalPrice: prev.totalPrice + curr.price * curr.selectedCount,
142
+ itemsCount: prev.itemsCount + curr.selectedCount,
143
+ }),
144
+ { totalPrice: 0, itemsCount: 0 }
145
+ )
146
+ }, [products])
147
+
148
+ const onChangeQuantityItem = useCallback((id: string, value: number) => {
149
+ setProducts((oldProducts) =>
150
+ oldProducts.map((product) => {
151
+ if (product.id !== id) {
152
+ return product
153
+ }
154
+
155
+ return { ...product, selectedCount: value }
156
+ })
157
+ )
158
+ }, [])
159
+
160
+ const onDelete = useCallback((id: string) => {
161
+ setProducts((oldProducts) =>
162
+ oldProducts.filter((product) => product.id !== id)
163
+ )
164
+ }, [])
165
+
166
+ const onAddToCart = useCallback(() => {
167
+ const productsToAdd = products.filter(
168
+ (product) =>
169
+ product.selectedCount > 0 && product.availability === 'available'
170
+ )
171
+
172
+ onAddToCartCallback?.(productsToAdd, totalPrice, itemsCount)
173
+ }, [products, totalPrice, itemsCount, onAddToCartCallback])
174
+
175
+ const value: QuickOrderDrawerContextValue = {
176
+ products,
177
+ totalPrice,
178
+ itemsCount,
179
+ alertMessage,
180
+ isLoading,
181
+ setAlertMessage,
182
+ onChangeQuantityItem,
183
+ onDelete,
184
+ onAddToCart,
185
+ formatter,
186
+ }
187
+
188
+ return (
189
+ <QuickOrderDrawerContext.Provider value={value}>
190
+ {children}
191
+ </QuickOrderDrawerContext.Provider>
192
+ )
193
+ }
194
+
195
+ export const useQuickOrderDrawer = (): QuickOrderDrawerContextValue => {
196
+ const context = useContext(QuickOrderDrawerContext)
197
+
198
+ if (context === undefined) {
199
+ throw new Error(
200
+ 'useQuickOrderDrawer should be used within a QuickOrderDrawerProvider'
201
+ )
202
+ }
203
+
204
+ return context
205
+ }
@@ -14,6 +14,10 @@ export type SearchInputProps = {
14
14
  * The current status of the Search Dropdown.
15
15
  */
16
16
  visibleDropdown: boolean
17
+ /**
18
+ * Search result searchId.
19
+ */
20
+ searchId?: string
17
21
  } & HTMLAttributes<HTMLDivElement> &
18
22
  SearchProviderContextValue
19
23
 
@@ -28,6 +32,7 @@ const SearchInput = forwardRef<HTMLDivElement, SearchInputProps>(
28
32
  term,
29
33
  terms,
30
34
  onSearchSelection,
35
+ searchId,
31
36
  ...otherProps
32
37
  },
33
38
  ref
@@ -46,6 +51,7 @@ const SearchInput = forwardRef<HTMLDivElement, SearchInputProps>(
46
51
  term={term}
47
52
  products={products}
48
53
  terms={terms}
54
+ searchId={searchId}
49
55
  >
50
56
  {children}
51
57
  </SearchProvider>