@adobe-commerce/elsie 1.0.0-alpha04071347

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 (340) hide show
  1. package/.elsie.js +21 -0
  2. package/.eslintrc.js +18 -0
  3. package/README.md +52 -0
  4. package/__mocks__/svg.js +11 -0
  5. package/bin/builders/build/index.js +20 -0
  6. package/bin/builders/generate/api/index.js +65 -0
  7. package/bin/builders/generate/api/templates/function.js +9 -0
  8. package/bin/builders/generate/api/templates/index.js +7 -0
  9. package/bin/builders/generate/api/templates/story.js +23 -0
  10. package/bin/builders/generate/api/templates/unit-test.js +15 -0
  11. package/bin/builders/generate/component/index.js +87 -0
  12. package/bin/builders/generate/component/templates/Component.js +43 -0
  13. package/bin/builders/generate/component/templates/css.js +24 -0
  14. package/bin/builders/generate/component/templates/index.js +8 -0
  15. package/bin/builders/generate/component/templates/stories.js +46 -0
  16. package/bin/builders/generate/component/templates/unit-test.js +19 -0
  17. package/bin/builders/generate/config/index.js +54 -0
  18. package/bin/builders/generate/config/templates/elsie.js +29 -0
  19. package/bin/builders/generate/container/index.js +65 -0
  20. package/bin/builders/generate/container/templates/Component.js +18 -0
  21. package/bin/builders/generate/container/templates/index.js +8 -0
  22. package/bin/builders/generate/container/templates/stories.js +34 -0
  23. package/bin/builders/generate/container/templates/unit-test.js +19 -0
  24. package/bin/builders/generate/index.js +283 -0
  25. package/bin/builders/gql/createOrClearDirectory.js +33 -0
  26. package/bin/builders/gql/getSchemaRef.js +25 -0
  27. package/bin/builders/gql/index.js +71 -0
  28. package/bin/builders/lint/index.js +5 -0
  29. package/bin/builders/serve/index.js +44 -0
  30. package/bin/builders/storybook/index.js +5 -0
  31. package/bin/builders/test/index.js +5 -0
  32. package/bin/index.js +26 -0
  33. package/bin/lib/cli.js +8 -0
  34. package/bin/lib/config.js +12 -0
  35. package/bin/lib/log-message.js +11 -0
  36. package/bin/lib/string.js +26 -0
  37. package/bin/lib/validate-typeof.js +28 -0
  38. package/bin/lib/write-file.js +30 -0
  39. package/bin/lib/write-parent-index.js +45 -0
  40. package/config/eslint.js +113 -0
  41. package/config/jest.js +90 -0
  42. package/config/prettier.js +16 -0
  43. package/config/setEnvVars.js +14 -0
  44. package/config/storybook/addon.js +130 -0
  45. package/config/storybook/components/FileTree/FileTree.jsx +192 -0
  46. package/config/storybook/components/FileTree/index.js +10 -0
  47. package/config/storybook/components/Flex/Flex.jsx +21 -0
  48. package/config/storybook/components/Flex/Flex.module.css +29 -0
  49. package/config/storybook/components/Flex/index.js +10 -0
  50. package/config/storybook/components/OptionsTable/OptionsTable.jsx +88 -0
  51. package/config/storybook/components/OptionsTable/OptionsTable.module.css +104 -0
  52. package/config/storybook/components/OptionsTable/index.js +10 -0
  53. package/config/storybook/components/Panel/Panel.module.css +56 -0
  54. package/config/storybook/components/Panel/Panel.tsx +46 -0
  55. package/config/storybook/components/Panel/index.ts +10 -0
  56. package/config/storybook/components/Screenshot/Screenshot.jsx +23 -0
  57. package/config/storybook/components/Screenshot/Screenshot.module.css +28 -0
  58. package/config/storybook/components/Screenshot/index.js +10 -0
  59. package/config/storybook/components/Steps/Steps.jsx +21 -0
  60. package/config/storybook/components/Steps/Steps.module.css +43 -0
  61. package/config/storybook/components/Steps/index.js +10 -0
  62. package/config/storybook/components/StoryWrapper/StoryWrapper.jsx +18 -0
  63. package/config/storybook/components/StoryWrapper/StoryWrapper.module.css +22 -0
  64. package/config/storybook/components/StoryWrapper/index.js +10 -0
  65. package/config/storybook/components/Summary/Summary.jsx +19 -0
  66. package/config/storybook/components/Summary/Summary.module.css +20 -0
  67. package/config/storybook/components/Summary/index.js +10 -0
  68. package/config/storybook/components/Variants/Variants.js +57 -0
  69. package/config/storybook/components/Variants/docs.css +48 -0
  70. package/config/storybook/components/Variants/index.js +10 -0
  71. package/config/storybook/components/video/index.jsx +28 -0
  72. package/config/storybook/manager.js +23 -0
  73. package/config/storybook/preview.jsx +88 -0
  74. package/config/storybook/theming/fonts.css +68 -0
  75. package/config/storybook/theming/logo.svg +19 -0
  76. package/config/storybook/theming/manager.css +63 -0
  77. package/config/storybook/theming/preview.css +93 -0
  78. package/config/storybook/theming/theme.js +61 -0
  79. package/config/tsconfig-base.json +16 -0
  80. package/config/tsconfig-preact.json +15 -0
  81. package/config/vite.mjs +306 -0
  82. package/package.json +113 -0
  83. package/post-release.sh +5 -0
  84. package/src/components/Accordion/Accordion.css +88 -0
  85. package/src/components/Accordion/Accordion.stories.tsx +582 -0
  86. package/src/components/Accordion/Accordion.tsx +177 -0
  87. package/src/components/Accordion/index.ts +11 -0
  88. package/src/components/ActionButton/ActionButton.css +100 -0
  89. package/src/components/ActionButton/ActionButton.stories.tsx +169 -0
  90. package/src/components/ActionButton/ActionButton.tsx +53 -0
  91. package/src/components/ActionButton/index.ts +10 -0
  92. package/src/components/ActionButtonGroup/ActionButtonGroup.css +77 -0
  93. package/src/components/ActionButtonGroup/ActionButtonGroup.stories.tsx +97 -0
  94. package/src/components/ActionButtonGroup/ActionButtonGroup.tsx +91 -0
  95. package/src/components/ActionButtonGroup/index.ts +10 -0
  96. package/src/components/AlertBanner/AlertBanner.css +144 -0
  97. package/src/components/AlertBanner/AlertBanner.stories.tsx +165 -0
  98. package/src/components/AlertBanner/AlertBanner.tsx +90 -0
  99. package/src/components/AlertBanner/index.ts +11 -0
  100. package/src/components/Breadcrumbs/Breadcrumbs.css +60 -0
  101. package/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +195 -0
  102. package/src/components/Breadcrumbs/Breadcrumbs.tsx +71 -0
  103. package/src/components/Breadcrumbs/index.ts +11 -0
  104. package/src/components/Button/Button.css +213 -0
  105. package/src/components/Button/Button.mdx +133 -0
  106. package/src/components/Button/Button.stories.tsx +398 -0
  107. package/src/components/Button/Button.tsx +121 -0
  108. package/src/components/Button/index.ts +11 -0
  109. package/src/components/Card/Card.css +34 -0
  110. package/src/components/Card/Card.stories.tsx +76 -0
  111. package/src/components/Card/Card.tsx +34 -0
  112. package/src/components/Card/index.ts +10 -0
  113. package/src/components/CartItem/CartItem.css +509 -0
  114. package/src/components/CartItem/CartItem.stories.tsx +628 -0
  115. package/src/components/CartItem/CartItem.tsx +467 -0
  116. package/src/components/CartItem/CartItemSkeleton.tsx +38 -0
  117. package/src/components/CartItem/index.ts +12 -0
  118. package/src/components/CartList/CartList.css +35 -0
  119. package/src/components/CartList/CartList.stories.tsx +111 -0
  120. package/src/components/CartList/CartList.tsx +40 -0
  121. package/src/components/CartList/index.ts +11 -0
  122. package/src/components/Checkbox/Checkbox.css +255 -0
  123. package/src/components/Checkbox/Checkbox.stories.tsx +290 -0
  124. package/src/components/Checkbox/Checkbox.tsx +138 -0
  125. package/src/components/Checkbox/index.ts +10 -0
  126. package/src/components/ColorSwatch/ColorSwatch.css +132 -0
  127. package/src/components/ColorSwatch/ColorSwatch.stories.tsx +274 -0
  128. package/src/components/ColorSwatch/ColorSwatch.tsx +127 -0
  129. package/src/components/ColorSwatch/index.ts +11 -0
  130. package/src/components/ContentGrid/ContentGrid.css +54 -0
  131. package/src/components/ContentGrid/ContentGrid.stories.tsx +137 -0
  132. package/src/components/ContentGrid/ContentGrid.tsx +57 -0
  133. package/src/components/ContentGrid/index.ts +11 -0
  134. package/src/components/Divider/Divider.css +22 -0
  135. package/src/components/Divider/Divider.stories.tsx +62 -0
  136. package/src/components/Divider/Divider.tsx +33 -0
  137. package/src/components/Divider/index.ts +11 -0
  138. package/src/components/Field/Field.css +83 -0
  139. package/src/components/Field/Field.stories.tsx +238 -0
  140. package/src/components/Field/Field.tsx +84 -0
  141. package/src/components/Field/index.ts +10 -0
  142. package/src/components/Header/Header.css +56 -0
  143. package/src/components/Header/Header.stories.tsx +180 -0
  144. package/src/components/Header/Header.tsx +81 -0
  145. package/src/components/Header/index.ts +11 -0
  146. package/src/components/Icon/Icon.css +26 -0
  147. package/src/components/Icon/Icon.stories.helpers.jsx +21 -0
  148. package/src/components/Icon/Icon.stories.tsx +98 -0
  149. package/src/components/Icon/Icon.tsx +112 -0
  150. package/src/components/Icon/index.ts +10 -0
  151. package/src/components/IllustratedMessage/IllustratedMessage.css +61 -0
  152. package/src/components/IllustratedMessage/IllustratedMessage.stories.tsx +126 -0
  153. package/src/components/IllustratedMessage/IllustratedMessage.tsx +78 -0
  154. package/src/components/IllustratedMessage/index.ts +11 -0
  155. package/src/components/Image/Image.css +52 -0
  156. package/src/components/Image/Image.stories.tsx +89 -0
  157. package/src/components/Image/Image.tsx +66 -0
  158. package/src/components/Image/index.ts +10 -0
  159. package/src/components/ImageSwatch/ImageSwatch.css +154 -0
  160. package/src/components/ImageSwatch/ImageSwatch.stories.tsx +310 -0
  161. package/src/components/ImageSwatch/ImageSwatch.tsx +123 -0
  162. package/src/components/ImageSwatch/index.ts +11 -0
  163. package/src/components/InLineAlert/InLineAlert.css +116 -0
  164. package/src/components/InLineAlert/InLineAlert.stories.tsx +326 -0
  165. package/src/components/InLineAlert/InLineAlert.tsx +128 -0
  166. package/src/components/InLineAlert/index.ts +11 -0
  167. package/src/components/Incrementer/Incrementer.css +165 -0
  168. package/src/components/Incrementer/Incrementer.stories.tsx +172 -0
  169. package/src/components/Incrementer/Incrementer.tsx +192 -0
  170. package/src/components/Incrementer/index.ts +10 -0
  171. package/src/components/Input/Input.css +304 -0
  172. package/src/components/Input/Input.stories.tsx +155 -0
  173. package/src/components/Input/Input.tsx +166 -0
  174. package/src/components/Input/index.ts +11 -0
  175. package/src/components/InputDate/InputDate.css +56 -0
  176. package/src/components/InputDate/InputDate.stories.tsx +117 -0
  177. package/src/components/InputDate/InputDate.tsx +120 -0
  178. package/src/components/InputDate/index.ts +11 -0
  179. package/src/components/InputPassword/InputPassword.css +31 -0
  180. package/src/components/InputPassword/InputPassword.stories.tsx +148 -0
  181. package/src/components/InputPassword/InputPassword.tsx +135 -0
  182. package/src/components/InputPassword/PasswordStatusIndicator/PasswordStatusIndicator.css +31 -0
  183. package/src/components/InputPassword/PasswordStatusIndicator/PasswordStatusIndicator.tsx +96 -0
  184. package/src/components/InputPassword/PasswordStatusIndicator/index.ts +11 -0
  185. package/src/components/InputPassword/index.ts +11 -0
  186. package/src/components/Modal/Modal.css +125 -0
  187. package/src/components/Modal/Modal.stories.tsx +250 -0
  188. package/src/components/Modal/Modal.tsx +157 -0
  189. package/src/components/Modal/index.ts +10 -0
  190. package/src/components/Pagination/Pagination.css +95 -0
  191. package/src/components/Pagination/Pagination.stories.tsx +117 -0
  192. package/src/components/Pagination/Pagination.tsx +149 -0
  193. package/src/components/Pagination/index.ts +11 -0
  194. package/src/components/Picker/Picker.css +220 -0
  195. package/src/components/Picker/Picker.stories.tsx +318 -0
  196. package/src/components/Picker/Picker.tsx +203 -0
  197. package/src/components/Picker/index.ts +10 -0
  198. package/src/components/Price/Price.css +57 -0
  199. package/src/components/Price/Price.stories.tsx +110 -0
  200. package/src/components/Price/Price.tsx +75 -0
  201. package/src/components/Price/index.ts +10 -0
  202. package/src/components/PriceRange/PriceRange.css +66 -0
  203. package/src/components/PriceRange/PriceRange.stories.tsx +240 -0
  204. package/src/components/PriceRange/PriceRange.tsx +248 -0
  205. package/src/components/PriceRange/index.ts +11 -0
  206. package/src/components/ProgressSpinner/ProgressSpinner.css +91 -0
  207. package/src/components/ProgressSpinner/ProgressSpinner.stories.tsx +300 -0
  208. package/src/components/ProgressSpinner/ProgressSpinner.tsx +86 -0
  209. package/src/components/ProgressSpinner/index.ts +11 -0
  210. package/src/components/RadioButton/RadioButton.css +134 -0
  211. package/src/components/RadioButton/RadioButton.stories.tsx +126 -0
  212. package/src/components/RadioButton/RadioButton.tsx +86 -0
  213. package/src/components/RadioButton/index.ts +11 -0
  214. package/src/components/Skeleton/Skeleton.css +145 -0
  215. package/src/components/Skeleton/Skeleton.stories.tsx +265 -0
  216. package/src/components/Skeleton/Skeleton.tsx +133 -0
  217. package/src/components/Skeleton/index.ts +10 -0
  218. package/src/components/Tag/Tag.css +26 -0
  219. package/src/components/Tag/Tag.stories.tsx +103 -0
  220. package/src/components/Tag/Tag.tsx +38 -0
  221. package/src/components/Tag/index.ts +11 -0
  222. package/src/components/TextArea/TextArea.css +140 -0
  223. package/src/components/TextArea/TextArea.stories.tsx +130 -0
  224. package/src/components/TextArea/TextArea.tsx +89 -0
  225. package/src/components/TextArea/index.ts +11 -0
  226. package/src/components/TextSwatch/TextSwatch.css +152 -0
  227. package/src/components/TextSwatch/TextSwatch.stories.tsx +277 -0
  228. package/src/components/TextSwatch/TextSwatch.tsx +131 -0
  229. package/src/components/TextSwatch/index.ts +11 -0
  230. package/src/components/ToggleButton/ToggleButton.css +95 -0
  231. package/src/components/ToggleButton/ToggleButton.stories.tsx +190 -0
  232. package/src/components/ToggleButton/ToggleButton.tsx +75 -0
  233. package/src/components/ToggleButton/index.ts +11 -0
  234. package/src/components/UIProvider/UIProvider.css +140 -0
  235. package/src/components/UIProvider/UIProvider.tsx +61 -0
  236. package/src/components/UIProvider/debugger.css +47 -0
  237. package/src/components/UIProvider/index.ts +10 -0
  238. package/src/components/UIProvider/normalize.css +26 -0
  239. package/src/components/index.ts +49 -0
  240. package/src/docs/API/event-bus.mdx +52 -0
  241. package/src/docs/API/graphql.mdx +214 -0
  242. package/src/docs/API/initializer.mdx +119 -0
  243. package/src/docs/API/render.mdx +125 -0
  244. package/src/docs/Design/colors.mdx +202 -0
  245. package/src/docs/Design/designBlocks.jsx +87 -0
  246. package/src/docs/Design/getTokenData.ts +28 -0
  247. package/src/docs/Design/grid.mdx +365 -0
  248. package/src/docs/Design/overview.mdx +69 -0
  249. package/src/docs/Design/shapes.mdx +100 -0
  250. package/src/docs/Design/spacing.mdx +22 -0
  251. package/src/docs/Design/typography.mdx +126 -0
  252. package/src/docs/Utilities/classList.mdx +52 -0
  253. package/src/docs/Utilities/debounce.mdx +49 -0
  254. package/src/docs/Utilities/deepmerge.mdx +12 -0
  255. package/src/docs/Utilities/getFormErrors.mdx +41 -0
  256. package/src/docs/Utilities/getFormValues.mdx +38 -0
  257. package/src/docs/assets/Banner.png +0 -0
  258. package/src/docs/assets/Colors.png +0 -0
  259. package/src/docs/assets/DropinBanner.png +0 -0
  260. package/src/docs/assets/ShapeStyles.png +0 -0
  261. package/src/docs/assets/Spacing.png +0 -0
  262. package/src/docs/assets/Typography.png +0 -0
  263. package/src/docs/cli-usage.mdx +181 -0
  264. package/src/docs/components/overview.mdx +124 -0
  265. package/src/docs/quick-start.mdx +245 -0
  266. package/src/docs/slots.mdx +211 -0
  267. package/src/docs/welcome.mdx +52 -0
  268. package/src/i18n/en_US.json +146 -0
  269. package/src/i18n/index.ts +26 -0
  270. package/src/icons/Add.svg +9 -0
  271. package/src/icons/AddressBook.svg +3 -0
  272. package/src/icons/Bulk.svg +24 -0
  273. package/src/icons/Burger.svg +5 -0
  274. package/src/icons/Card.svg +7 -0
  275. package/src/icons/Cart.svg +11 -0
  276. package/src/icons/Check.svg +8 -0
  277. package/src/icons/CheckWithCircle.svg +4 -0
  278. package/src/icons/ChevronDown.svg +3 -0
  279. package/src/icons/ChevronRight.svg +8 -0
  280. package/src/icons/ChevronUp.svg +3 -0
  281. package/src/icons/Close.svg +4 -0
  282. package/src/icons/Coupon.svg +3 -0
  283. package/src/icons/Date.svg +4 -0
  284. package/src/icons/Delivery.svg +11 -0
  285. package/src/icons/EmptyBox.svg +3 -0
  286. package/src/icons/Eye.svg +3 -0
  287. package/src/icons/EyeClose.svg +3 -0
  288. package/src/icons/Gift.svg +3 -0
  289. package/src/icons/GiftCard.svg +3 -0
  290. package/src/icons/Heart.svg +3 -0
  291. package/src/icons/HeartFilled.svg +3 -0
  292. package/src/icons/InfoFilled.svg +3 -0
  293. package/src/icons/Locker.svg +11 -0
  294. package/src/icons/Minus.svg +3 -0
  295. package/src/icons/Order.svg +6 -0
  296. package/src/icons/OrderError.svg +15 -0
  297. package/src/icons/OrderSuccess.svg +15 -0
  298. package/src/icons/PaymentError.svg +16 -0
  299. package/src/icons/Placeholder.svg +3 -0
  300. package/src/icons/PlaceholderFilled.svg +4 -0
  301. package/src/icons/Search.svg +9 -0
  302. package/src/icons/SearchFilled.svg +10 -0
  303. package/src/icons/Sort.svg +12 -0
  304. package/src/icons/Star.svg +8 -0
  305. package/src/icons/Trash.svg +7 -0
  306. package/src/icons/User.svg +5 -0
  307. package/src/icons/View.svg +14 -0
  308. package/src/icons/Wallet.svg +6 -0
  309. package/src/icons/Warning.svg +12 -0
  310. package/src/icons/WarningFilled.svg +3 -0
  311. package/src/icons/WarningWithCircle.svg +4 -0
  312. package/src/icons/index.ts +42 -0
  313. package/src/lib/classes.ts +34 -0
  314. package/src/lib/config.ts +24 -0
  315. package/src/lib/debounce.ts +16 -0
  316. package/src/lib/deepmerge.ts +45 -0
  317. package/src/lib/deviceUtils.ts +16 -0
  318. package/src/lib/form-values.ts +31 -0
  319. package/src/lib/i18n.ts +18 -0
  320. package/src/lib/image-params-keymap.ts +36 -0
  321. package/src/lib/index.ts +24 -0
  322. package/src/lib/initializer.ts +134 -0
  323. package/src/lib/is-number.ts +12 -0
  324. package/src/lib/render.tsx +138 -0
  325. package/src/lib/resolve-image.ts +101 -0
  326. package/src/lib/signals.ts +11 -0
  327. package/src/lib/slot.tsx +434 -0
  328. package/src/lib/tests.tsx +47 -0
  329. package/src/lib/types.ts +16 -0
  330. package/src/lib/vcomponent.tsx +42 -0
  331. package/static/assets/images/Card.png +0 -0
  332. package/static/assets/images/example.jpg +0 -0
  333. package/static/assets/images/index.ts +11 -0
  334. package/static/dropin.png +0 -0
  335. package/static/favicon.svg +14 -0
  336. package/storybook-stories.js +21 -0
  337. package/tests/__mocks__/browserMocks.ts +28 -0
  338. package/tests/__mocks__/fileMocks.ts +12 -0
  339. package/tests/__mocks__/styleMock.ts +0 -0
  340. package/types/icons.d.ts +18 -0
@@ -0,0 +1,138 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ import { FunctionComponent, VNode } from 'preact';
11
+ import { ChangeEvent, HTMLAttributes, useRef, useState } from 'preact/compat';
12
+ import { classes } from '@adobe-commerce/elsie/lib';
13
+ import { Check } from '@adobe-commerce/elsie/icons';
14
+ import { Icon } from '@adobe-commerce/elsie/components/Icon';
15
+ import '@adobe-commerce/elsie/components/Checkbox/Checkbox.css';
16
+ import { useEffect } from 'preact/hooks';
17
+
18
+ export interface CheckboxProps
19
+ extends Omit<HTMLAttributes<HTMLInputElement>, 'size' | 'label'> {
20
+ name: string;
21
+ size?: 'medium' | 'large';
22
+ disabled?: boolean;
23
+ error?: boolean;
24
+ label?: string | VNode | VNode[];
25
+ description?: string | VNode | VNode[];
26
+ }
27
+
28
+ export const Checkbox: FunctionComponent<CheckboxProps> = ({
29
+ name,
30
+ value,
31
+ size = 'medium',
32
+ disabled = false,
33
+ error = false,
34
+ label = '',
35
+ description = '',
36
+ className,
37
+ checked,
38
+ ...props
39
+ }) => {
40
+ const [isChecked, setIsChecked] = useState(
41
+ checked === undefined ? false : checked
42
+ );
43
+ const ref = useRef<HTMLInputElement>(null);
44
+
45
+ const handleCheckboxChange = (e: ChangeEvent<HTMLInputElement>) => {
46
+ props.onChange?.(e);
47
+ setIsChecked(e.currentTarget.checked);
48
+ };
49
+
50
+ const handleOnKeyDown = (e: KeyboardEvent) => {
51
+ if (e.key === ' ') {
52
+ e.preventDefault();
53
+ ref?.current?.click();
54
+ }
55
+ };
56
+
57
+ useEffect(() => {
58
+ if (typeof checked === 'boolean') {
59
+ setIsChecked(checked);
60
+ }
61
+ }, [checked]);
62
+
63
+ return (
64
+ <label
65
+ className={classes([
66
+ 'dropin-checkbox',
67
+ ['dropin-checkbox--disabled', disabled],
68
+ ])}
69
+ >
70
+ <input
71
+ ref={ref}
72
+ name={name}
73
+ value={value}
74
+ type="checkbox"
75
+ disabled={disabled}
76
+ className={classes([
77
+ 'dropin-checkbox__checkbox',
78
+ ['dropin-checkbox__checkbox--error', error],
79
+ className,
80
+ ])}
81
+ {...props}
82
+ onChange={handleCheckboxChange}
83
+ checked={isChecked}
84
+ />
85
+
86
+ <div className="dropin-checkbox__checkbox-icon">
87
+ {/*Zero-width space character, used to align checkbox properly*/}
88
+ {'\u200B'}
89
+ <span
90
+ aria-checked={isChecked ? 'true' : 'false'}
91
+ aria-labelledby={`${name}-label`}
92
+ aria-describedby={description ? `${name}-description` : undefined}
93
+ className={classes([
94
+ 'dropin-checkbox__box',
95
+ ['dropin-checkbox__box--error', error],
96
+ ['dropin-checkbox__box--disabled', disabled],
97
+ ])}
98
+ role="checkbox"
99
+ tabIndex={disabled ? -1 : 0}
100
+ onKeyDown={handleOnKeyDown}
101
+ >
102
+ <Icon
103
+ className={classes(['dropin-checkbox__checkmark'])}
104
+ source={Check}
105
+ size="16"
106
+ stroke="3"
107
+ />
108
+ </span>
109
+ </div>
110
+
111
+ <div
112
+ id={`${name}-label`}
113
+ className={classes([
114
+ 'dropin-checkbox__label',
115
+ `dropin-checkbox__label--${size}`,
116
+ ['dropin-checkbox__label--disabled', disabled],
117
+ ])}
118
+ >
119
+ {label}
120
+ </div>
121
+
122
+ <div />
123
+ {description && (
124
+ <div
125
+ id={`${name}-description`}
126
+ role={'note'}
127
+ className={classes([
128
+ 'dropin-checkbox__description',
129
+ `dropin-checkbox__description--${size}`,
130
+ ['dropin-checkbox__description--disabled', disabled],
131
+ ])}
132
+ >
133
+ {description}
134
+ </div>
135
+ )}
136
+ </label>
137
+ );
138
+ };
@@ -0,0 +1,10 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ export * from '@adobe-commerce/elsie/components/Checkbox/Checkbox';
@@ -0,0 +1,132 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ /* https://cssguidelin.es/#bem-like-naming */
11
+
12
+ /* Hide the default radio/checkbox button */
13
+ .dropin-color-swatch__container input[type='radio'],
14
+ .dropin-color-swatch__container input[type='checkbox'] {
15
+ opacity: 0;
16
+ position: absolute;
17
+ width: 0;
18
+ height: 0;
19
+ }
20
+
21
+ .dropin-color-swatch__container .dropin-color-swatch__span {
22
+ border-radius: 50%;
23
+ display: inline-block;
24
+ --bg-color: var(--color-neutral-300);
25
+ box-shadow: 0 0 0 var(--shape-border-width-1) var(--color-neutral-400);
26
+ position: relative;
27
+ cursor: pointer;
28
+ background-color: var(--bg-color);
29
+ }
30
+
31
+ .dropin-color-swatch__container--medium .dropin-color-swatch__span {
32
+ height: 32px;
33
+ width: 32px;
34
+ }
35
+
36
+ .dropin-color-swatch__container--large .dropin-color-swatch__span {
37
+ height: 40px;
38
+ width: 40px;
39
+ }
40
+
41
+ .dropin-color-swatch__container
42
+ input[type='radio']:not(:checked):active
43
+ ~ .dropin-color-swatch__span,
44
+ .dropin-color-swatch__container
45
+ input[type='checkbox']:not(:checked):active
46
+ ~ .dropin-color-swatch__span {
47
+ box-shadow: 0 0 0 var(--shape-border-width-1) var(--color-neutral-500);
48
+ outline: none;
49
+ }
50
+
51
+ .dropin-color-swatch__container
52
+ input[type='radio']:checked
53
+ ~ .dropin-color-swatch__span,
54
+ .dropin-color-swatch__container
55
+ input[type='checkbox']:checked
56
+ ~ .dropin-color-swatch__span,
57
+ .dropin-color-swatch--selected {
58
+ box-shadow: 0 0 0 var(--shape-border-width-3) var(--color-neutral-50),
59
+ 0 0 0 3px var(--color-neutral-800);
60
+ }
61
+
62
+ .dropin-color-swatch__container
63
+ input[type='radio']:checked:active
64
+ ~ .dropin-color-swatch__span,
65
+ .dropin-color-swatch__container
66
+ input[type='checkbox']:checked:active
67
+ ~ .dropin-color-swatch__span {
68
+ box-shadow: 0 0 0 var(--shape-border-width-3) var(--color-neutral-50),
69
+ 0 0 0 var(--shape-border-width-4) var(--color-neutral-900);
70
+ }
71
+
72
+ .dropin-color-swatch__container
73
+ input[type='radio']:focus-visible
74
+ + .dropin-color-swatch__span,
75
+ .dropin-color-swatch__container
76
+ input[type='checkbox']:focus-visible
77
+ + .dropin-color-swatch__span {
78
+ box-shadow: 0 0 0 var(--shape-border-width-3) var(--color-neutral-900),
79
+ 0 0 0 6px var(--color-neutral-400);
80
+ }
81
+
82
+ .dropin-color-swatch__container
83
+ input[type='radio']:disabled
84
+ ~ .dropin-color-swatch__span,
85
+ .dropin-color-swatch__container
86
+ input[type='checkbox']:disabled
87
+ ~ .dropin-color-swatch__span,
88
+ .dropin-color-swatch--disabled,
89
+ .dropin-color-swatch__container
90
+ input[type='radio']:disabled:active
91
+ ~ .dropin-color-swatch__span,
92
+ .dropin-color-swatch__container
93
+ input[type='checkbox']:disabled:active
94
+ ~ .dropin-color-swatch__span {
95
+ box-shadow: 0 0 0 var(--shape-border-width-4) var(--color-neutral-500);
96
+ opacity: 0.24; /* Hard coded value */
97
+ pointer-events: none;
98
+ }
99
+
100
+ .dropin-color-swatch__span--out-of-stock {
101
+ box-shadow: 0 0 0 var(--shape-border-width-1) var(--color-neutral-700);
102
+ background: linear-gradient(
103
+ to top left,
104
+ rgba(0, 0, 0, 0) 0%,
105
+ rgba(0, 0, 0, 0) calc(50% - 0.8px),
106
+ var(--color-neutral-700) 50%,
107
+ rgba(0, 0, 0, 0) calc(50% + 0.8px),
108
+ rgba(0, 0, 0, 0) 100%
109
+ ),
110
+ var(--bg-color);
111
+ }
112
+
113
+ .dropin-color-swatch__container
114
+ input[type='radio']:not(:disabled)
115
+ ~ .dropin-color-swatch__span,
116
+ .dropin-color-swatch__container
117
+ input[type='checkbox']:not(:disabled)
118
+ ~ .dropin-color-swatch__span {
119
+ cursor: pointer;
120
+ }
121
+
122
+ /* Medium (portrait tablets and large phones, 768px and up) */
123
+ /* @media only screen and (min-width: 768px) { } */
124
+
125
+ /* Large (landscape tablets, 1024px and up) */
126
+ /* @media only screen and (min-width: 1024px) { } */
127
+
128
+ /* XLarge (laptops/desktops, 1366px and up) */
129
+ /* @media only screen and (min-width: 1366px) { } */
130
+
131
+ /* XXlarge (large laptops and desktops, 1920px and up) */
132
+ /* @media only screen and (min-width: 1920px) { } */
@@ -0,0 +1,274 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ // https://storybook.js.org/docs/7.0/preact/writing-stories/introduction
11
+ import type { Meta, StoryObj } from '@storybook/preact';
12
+ import { action } from '@storybook/addon-actions';
13
+ import { expect, within } from '@storybook/test';
14
+ import {
15
+ ColorSwatch,
16
+ ColorSwatchProps,
17
+ } from '@adobe-commerce/elsie/components/ColorSwatch';
18
+
19
+ /**
20
+ * Use Color Swatches to display fills — such as colors, gradients, and textures — that can be applied to an object.
21
+ */
22
+ const meta: Meta<ColorSwatchProps> = {
23
+ title: 'Components/ColorSwatch',
24
+ component: ColorSwatch,
25
+ argTypes: {
26
+ name: {
27
+ description: 'Field name (used for mapping the value in a form)',
28
+ type: {
29
+ required: false,
30
+ name: 'string',
31
+ },
32
+ },
33
+ label: {
34
+ description: 'Field label',
35
+ type: {
36
+ required: true,
37
+ name: 'string',
38
+ },
39
+ },
40
+ groupAriaLabel: {
41
+ description: 'Label name for the swatch group',
42
+ type: {
43
+ required: true,
44
+ name: 'string',
45
+ },
46
+ },
47
+ id: {
48
+ description: 'Field id',
49
+ type: {
50
+ required: false,
51
+ name: 'string',
52
+ },
53
+ },
54
+ size: {
55
+ description: 'Size of the color swatch',
56
+ type: {
57
+ required: false,
58
+ name: 'string',
59
+ },
60
+ defaultValue: { summary: 'medium' },
61
+ options: ['medium', 'large'],
62
+ control: { type: 'radio' },
63
+ },
64
+ color: {
65
+ description: 'Color of the swatch',
66
+ type: {
67
+ required: false,
68
+ name: 'string',
69
+ },
70
+ },
71
+ value: {
72
+ description: 'Field value',
73
+ type: {
74
+ required: false,
75
+ name: 'string',
76
+ },
77
+ },
78
+ disabled: {
79
+ description: 'Whether or not the color swatch is disabled',
80
+ type: {
81
+ required: false,
82
+ name: 'boolean',
83
+ },
84
+ },
85
+ selected: {
86
+ description: 'Whether or not the color swatch is active',
87
+ type: {
88
+ required: false,
89
+ name: 'boolean',
90
+ },
91
+ },
92
+ multi: {
93
+ description: 'Whether or not the color swatch allows multiple selection',
94
+ type: {
95
+ required: false,
96
+ name: 'boolean',
97
+ },
98
+ },
99
+ onUpdateError: {
100
+ description: 'Function to handle errors',
101
+ type: {
102
+ required: false,
103
+ name: 'function',
104
+ },
105
+ },
106
+ outOfStock: {
107
+ description: 'Whether or not the color swatch is out of stock',
108
+ type: {
109
+ required: false,
110
+ name: 'boolean',
111
+ },
112
+ },
113
+ onValue: {
114
+ description: 'Function to handle value changes',
115
+ type: {
116
+ required: false,
117
+ name: 'function',
118
+ },
119
+ },
120
+ },
121
+ };
122
+
123
+ export default meta;
124
+
125
+ type Story = StoryObj<ColorSwatchProps>;
126
+
127
+ /**
128
+ * ```ts
129
+ * import { ColorSwatch } from '@adobe-commerce/elsie/components/ColorSwatch';
130
+ * ```
131
+ */
132
+
133
+ export const DefaultColorSwatch: Story = {
134
+ args: {
135
+ name: 'colorSwatchField',
136
+ id: 'graySwatch',
137
+ label: 'gray',
138
+ groupAriaLabel: 'Color Swatch',
139
+ value: 'gray',
140
+ size: 'medium',
141
+ color: '#E8E8E8',
142
+ selected: false,
143
+ disabled: false,
144
+ outOfStock: false,
145
+ onValue: action('onValue'),
146
+ },
147
+ play: async ({ canvasElement }) => {
148
+ const canvas = within(canvasElement);
149
+ const textSwatch = await canvas.findByRole('radio');
150
+ const spanElement = document.querySelector(
151
+ '.dropin-color-swatch__span'
152
+ ) as HTMLElement;
153
+ expect(spanElement).toBeVisible();
154
+ await expect(textSwatch).not.toBeChecked();
155
+ },
156
+ };
157
+
158
+ export const SelectedColorSwatch: Story = {
159
+ args: {
160
+ name: 'colorSwatchField',
161
+ id: 'graySwatch',
162
+ value: 'gray',
163
+ label: 'gray',
164
+ groupAriaLabel: 'Color Swatch',
165
+ size: 'medium',
166
+ color: '#E8E8E8',
167
+ selected: true,
168
+ disabled: false,
169
+ outOfStock: false,
170
+ onValue: action('onValue'),
171
+ },
172
+ play: async ({ canvasElement }) => {
173
+ const canvas = within(canvasElement);
174
+ const textSwatch = await canvas.findByRole('radio');
175
+ const spanElement = document.querySelector(
176
+ '.dropin-color-swatch__span'
177
+ ) as HTMLElement;
178
+ expect(spanElement).toBeVisible();
179
+ await expect(textSwatch).toBeChecked();
180
+ await expect(
181
+ canvas.getByLabelText('Color Swatch: gray swatch selected')
182
+ ).toBeChecked();
183
+ },
184
+ };
185
+
186
+ export const DisabledColorSwatch: Story = {
187
+ args: {
188
+ name: 'colorSwatchField',
189
+ id: 'graySwatch',
190
+ value: 'gray',
191
+ label: 'gray',
192
+ groupAriaLabel: 'Color Swatch',
193
+ size: 'medium',
194
+ color: '#E8E8E8',
195
+ selected: false,
196
+ disabled: true,
197
+ outOfStock: false,
198
+ onValue: action('onValue'),
199
+ },
200
+ play: async ({ canvasElement }) => {
201
+ const canvas = within(canvasElement);
202
+ await expect(await canvas.findByRole('radio')).toBeDisabled();
203
+ },
204
+ };
205
+
206
+ export const OutOfStockColorSwatch: Story = {
207
+ args: {
208
+ name: 'colorSwatchField',
209
+ id: 'graySwatch',
210
+ label: 'gray',
211
+ groupAriaLabel: 'Color Swatch',
212
+ value: 'gray',
213
+ size: 'medium',
214
+ color: '#E8E8E8',
215
+ selected: false,
216
+ disabled: false,
217
+ outOfStock: true,
218
+ onValue: action('onValue'),
219
+ },
220
+ };
221
+
222
+ export const SelectedOutOfStockColorSwatch: Story = {
223
+ args: {
224
+ name: 'colorSwatch_Field',
225
+ id: 'graySwatch',
226
+ value: 'gray',
227
+ label: 'gray',
228
+ groupAriaLabel: 'Color Swatch',
229
+ size: 'medium',
230
+ color: '#E8E8E8',
231
+ selected: true,
232
+ disabled: false,
233
+ outOfStock: true,
234
+ onValue: action('onValue'),
235
+ },
236
+ };
237
+
238
+ export const MultiColorSwatch: Story = {
239
+ args: {
240
+ name: 'colorSwatchField',
241
+ id: 'graySwatch',
242
+ value: 'gray',
243
+ size: 'medium',
244
+ color: '#E8E8E8',
245
+ selected: false,
246
+ disabled: false,
247
+ outOfStock: false,
248
+ multi: true,
249
+ onValue: action('onValue'),
250
+ 'aria-label': 'Grey Color Swatch',
251
+ },
252
+ render: (args) => (
253
+ <div style="display: flex; flex-wrap:wrap; gap: 25px">
254
+ <ColorSwatch
255
+ {...args}
256
+ id={'colorSwatch1'}
257
+ value={'green'}
258
+ color={'green'}
259
+ />
260
+ <ColorSwatch
261
+ {...args}
262
+ id={'colorSwatch2'}
263
+ value={'blue'}
264
+ color={'blue'}
265
+ />
266
+ <ColorSwatch
267
+ {...args}
268
+ id={'colorSwatch3'}
269
+ value={'yellow'}
270
+ color={'yellow'}
271
+ />
272
+ </div>
273
+ ),
274
+ };
@@ -0,0 +1,127 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ import { FunctionComponent } from 'preact';
11
+ import { HTMLAttributes, useCallback } from 'preact/compat';
12
+ import { classes } from '@adobe-commerce/elsie/lib';
13
+ import '@adobe-commerce/elsie/components/ColorSwatch/ColorSwatch.css';
14
+ import { useText } from '@adobe-commerce/elsie/i18n';
15
+
16
+ export interface ColorSwatchProps
17
+ extends Omit<HTMLAttributes<HTMLInputElement>, 'label' | 'size'> {
18
+ name?: string;
19
+ label?: string;
20
+ groupAriaLabel?: string;
21
+ id?: string;
22
+ size?: 'medium' | 'large';
23
+ color?: string;
24
+ value?: string;
25
+ disabled?: boolean;
26
+ selected?: boolean;
27
+ outOfStock?: boolean;
28
+ multi?: boolean;
29
+ onValue?: (value: any) => void;
30
+ onUpdateError?: (error: Error) => void;
31
+ }
32
+
33
+ export const ColorSwatch: FunctionComponent<ColorSwatchProps> = ({
34
+ className,
35
+ name,
36
+ value,
37
+ id,
38
+ label,
39
+ groupAriaLabel,
40
+ size = 'medium',
41
+ color,
42
+ disabled = false,
43
+ selected = false,
44
+ outOfStock = false,
45
+ multi = false,
46
+ onValue,
47
+ onUpdateError,
48
+ ...props
49
+ }) => {
50
+ // i18n
51
+ const outOfStockLabel = useText('Dropin.Swatches.outOfStock.label').label;
52
+ const selectedLabel = useText('Dropin.Swatches.selected.label').label;
53
+ const swatchLabel = useText('Dropin.Swatches.swatch.label').label;
54
+
55
+ const onValueHandler = useCallback(
56
+ async (newValue: any) => {
57
+ if (onValue) {
58
+ try {
59
+ await onValue(newValue);
60
+ } catch (e) {
61
+ if (onUpdateError) {
62
+ onUpdateError(e as Error);
63
+ }
64
+ }
65
+ }
66
+ },
67
+ [onValue, onUpdateError]
68
+ );
69
+
70
+ const handleOnValue = (e: Event) => {
71
+ const input = e.target as HTMLInputElement;
72
+
73
+ onValueHandler(input.value);
74
+ };
75
+
76
+ const isValidColor = (color: string) => {
77
+ const colorStyle = new Option().style;
78
+ colorStyle.color = color;
79
+ return colorStyle.color !== ''; // Returns true if the browser accepts this as a valid color
80
+ };
81
+
82
+ const defaultColor = 'var(--color-gray-300);';
83
+
84
+ const validColor = color && isValidColor(color) ? color : defaultColor;
85
+
86
+ const handleAriaLabel = () => {
87
+ if (outOfStock) return `${groupAriaLabel}: ${label} ${outOfStockLabel}`;
88
+ if (selected) return `${groupAriaLabel}: ${label} ${selectedLabel}`;
89
+ return `${groupAriaLabel}: ${label} ${swatchLabel}`;
90
+ };
91
+
92
+ return (
93
+ <label
94
+ className={classes([
95
+ 'dropin-color-swatch__container',
96
+ `dropin-color-swatch__container--${size}`,
97
+ className,
98
+ ])}
99
+ >
100
+ <input
101
+ type={multi ? 'checkbox' : 'radio'}
102
+ name={name}
103
+ id={id}
104
+ value={value}
105
+ aria-label={handleAriaLabel()}
106
+ checked={selected}
107
+ disabled={disabled}
108
+ onChange={handleOnValue}
109
+ {...props}
110
+ className={classes([
111
+ 'dropin-color-swatch',
112
+ ['dropin-color-swatch--selected', selected],
113
+ ['dropin-color-swatch--disabled', disabled],
114
+ className,
115
+ ])}
116
+ />
117
+ <span
118
+ style={{ '--bg-color': validColor }}
119
+ className={classes([
120
+ 'dropin-color-swatch__span',
121
+ ['dropin-color-swatch__span--out-of-stock', outOfStock],
122
+ className,
123
+ ])}
124
+ />
125
+ </label>
126
+ );
127
+ };
@@ -0,0 +1,11 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ export * from '@adobe-commerce/elsie/components/ColorSwatch/ColorSwatch';
11
+ export { ColorSwatch as default } from '@adobe-commerce/elsie/components/ColorSwatch/ColorSwatch';