@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,434 @@
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 { cloneElement, ComponentChildren, RefObject, VNode } from 'preact';
11
+ import {
12
+ StateUpdater,
13
+ useContext,
14
+ useState,
15
+ useRef,
16
+ useEffect,
17
+ useMemo,
18
+ useCallback,
19
+ } from 'preact/hooks';
20
+ import { IntlContext, Lang } from '@adobe-commerce/elsie/i18n';
21
+ import { HTMLAttributes } from 'preact/compat';
22
+ import { SlotQueueContext } from './render';
23
+
24
+ import '@adobe-commerce/elsie/components/UIProvider/debugger.css';
25
+
26
+ type MutateElement = (elem: HTMLElement) => void;
27
+
28
+ interface State {
29
+ get: (key: string) => void;
30
+ set: (key: string, value: any) => void;
31
+ }
32
+
33
+ interface SlotElement {
34
+ appendChild: MutateElement;
35
+ prependChild: MutateElement;
36
+ appendSibling: MutateElement;
37
+ prependSibling: MutateElement;
38
+ }
39
+
40
+ interface PrivateContext<T> {
41
+ _setProps: (s: StateUpdater<{}>) => void;
42
+ _registerMethod: (
43
+ cb: (next: T & DefaultSlotContext<T>, state: State) => void
44
+ ) => void;
45
+ _htmlElementToVNode: (element: HTMLElement) => VNode;
46
+ }
47
+
48
+ interface DefaultSlotContext<T> extends PrivateContext<T> {
49
+ dictionary: Lang;
50
+ getSlotElement: (key: string) => SlotElement;
51
+ replaceWith: MutateElement;
52
+ appendChild: MutateElement;
53
+ prependChild: MutateElement;
54
+ appendSibling: MutateElement;
55
+ prependSibling: MutateElement;
56
+ onRender: (cb: (next: T & DefaultSlotContext<T>) => void) => void;
57
+ onChange: (cb: (next: T & DefaultSlotContext<T>) => void) => void;
58
+ }
59
+
60
+ type Context<T> = T & ThisType<DefaultSlotContext<T>>; // NOSONAR
61
+
62
+ export type SlotProps<T = any> = (
63
+ ctx: T & DefaultSlotContext<T>,
64
+ element: HTMLDivElement | null
65
+ ) => Promise<void> | void;
66
+
67
+ export type SlotMethod<P = any> = (
68
+ callback: (next: unknown, state: State) => P
69
+ ) => void;
70
+
71
+ // Slot Hook
72
+ export function useSlot<K, V extends HTMLDivElement>(
73
+ name: string,
74
+ // @ts-ignore
75
+ context: Context<K> = {},
76
+ callback?: SlotProps<K>,
77
+ children?: ComponentChildren,
78
+ render?: Function
79
+ ): [RefObject<V>, Record<string, any>] {
80
+ const slotsQueue = useContext(SlotQueueContext);
81
+
82
+ // HTML Element
83
+ const elementRef = useRef<V>(null);
84
+
85
+ const status = useRef<'pending' | 'ready' | 'loading'>('pending');
86
+
87
+ // Methods
88
+ const methodsRef = useRef<any>([]);
89
+
90
+ // Children VNodes
91
+ const [props, _setProps] = useState<Record<string, any>>({
92
+ children: [children],
93
+ });
94
+
95
+ // Attributes
96
+ const [_state, setState] = useState<any>({});
97
+
98
+ const state = useMemo(
99
+ () => ({
100
+ get: (key: string) => _state[key],
101
+ set: (key: string, value: any) => {
102
+ setState({ ...state, [key]: value });
103
+ },
104
+ }),
105
+ [_state]
106
+ );
107
+
108
+ /** Internationalization */
109
+ // @ts-ignore
110
+ const { intl }: any = useContext(IntlContext);
111
+
112
+ // @ts-ignore
113
+ context.dictionary = intl.dictionary;
114
+
115
+ /** Privates */
116
+ // @ts-ignore
117
+ context._setProps = (next: State<any>) => {
118
+ _setProps((prev) => {
119
+ // next props
120
+ const _next = typeof next === 'function' ? next(prev) : next;
121
+
122
+ // On render method...
123
+ if (render) {
124
+ const renderNode = cloneElement(render(prev), { key: 'render' });
125
+
126
+ // find index of existing render node
127
+ const index = prev.children.findIndex((n: any) => n?.key === 'render');
128
+
129
+ // replace existing render node
130
+ prev.children[index] = renderNode;
131
+ }
132
+
133
+ return _next;
134
+ });
135
+ };
136
+
137
+ const _registerMethod = useCallback((cb: Function) => {
138
+ if (typeof cb === 'function') {
139
+ methodsRef.current.push(cb);
140
+ } else {
141
+ console.warn('Skipped: Invalid _registerMethod', cb);
142
+ }
143
+ }, []);
144
+
145
+ // @ts-ignore
146
+ context._registerMethod = _registerMethod;
147
+
148
+ const _htmlElementToVNode = useCallback((elem: HTMLElement) => {
149
+ return (
150
+ <div
151
+ data-slot-html-element={elem.tagName.toLowerCase()}
152
+ ref={(refElem) => {
153
+ refElem?.appendChild(elem);
154
+ }}
155
+ />
156
+ );
157
+ }, []);
158
+
159
+ // @ts-ignore
160
+ context._htmlElementToVNode = _htmlElementToVNode;
161
+
162
+ /** Prebuilt Methods */
163
+ // @ts-ignore
164
+ context.getSlotElement = useCallback(
165
+ (key: string) => {
166
+ const element = elementRef.current?.querySelector(
167
+ `[data-slot-key="${key}"]`
168
+ );
169
+
170
+ log(
171
+ `🟦 "${name}" Slot getSlotElement: ${key}`,
172
+ elementRef.current?.cloneNode(true),
173
+ element?.cloneNode(true)
174
+ );
175
+
176
+ if (!element) return;
177
+
178
+ return {
179
+ appendChild: (elem: HTMLElement) => {
180
+ element.appendChild(elem);
181
+ },
182
+
183
+ prependChild: (elem: HTMLElement) => {
184
+ element.insertBefore(elem, element.firstChild);
185
+ },
186
+
187
+ appendSibling: (elem: HTMLElement) => {
188
+ const parent = element.parentNode;
189
+ parent?.insertBefore(elem, element.nextSibling);
190
+ },
191
+
192
+ prependSibling: (elem: HTMLElement) => {
193
+ const parent = element.parentNode;
194
+ parent?.insertBefore(elem, element);
195
+ },
196
+ };
197
+ },
198
+ [name]
199
+ );
200
+
201
+ // @ts-ignore
202
+ context.onRender = useCallback((cb: Function) => {
203
+ methodsRef.current.push(cb);
204
+ }, []);
205
+
206
+ /**
207
+ * @deprecated Use `onRender` instead.
208
+ */
209
+ // @ts-ignore
210
+ context.onChange = context.onRender;
211
+
212
+ // @ts-ignore
213
+ context.replaceWith = useCallback(
214
+ (elem: HTMLElement) => {
215
+ // @ts-ignore
216
+ _registerMethod((next) => {
217
+ // @ts-ignore
218
+ const children = _htmlElementToVNode(elem);
219
+
220
+ next._setProps({ children: [children] });
221
+ });
222
+ },
223
+ [_htmlElementToVNode, _registerMethod]
224
+ );
225
+
226
+ // @ts-ignore
227
+ context.appendChild = useCallback(
228
+ (elem: HTMLElement) => {
229
+ // @ts-ignore
230
+ _registerMethod((next) => {
231
+ // @ts-ignore
232
+ const vnode = _htmlElementToVNode(elem);
233
+
234
+ next._setProps((prev: any) => {
235
+ return {
236
+ ...prev,
237
+ children: [...prev.children, vnode],
238
+ };
239
+ });
240
+ });
241
+ },
242
+ [_htmlElementToVNode, _registerMethod]
243
+ );
244
+
245
+ // @ts-ignore
246
+ context.prependChild = useCallback(
247
+ (elem: HTMLElement) => {
248
+ // @ts-ignore
249
+ _registerMethod((next) => {
250
+ // @ts-ignore
251
+ const vnode = _htmlElementToVNode(elem);
252
+
253
+ next._setProps((prev: any) => {
254
+ return {
255
+ ...prev,
256
+ children: [vnode, ...prev.children],
257
+ };
258
+ });
259
+ });
260
+ },
261
+ [_htmlElementToVNode, _registerMethod]
262
+ );
263
+
264
+ // @ts-ignore
265
+ context.appendSibling = useCallback(
266
+ (elem: HTMLElement) => {
267
+ // @ts-ignore
268
+ _registerMethod(() => {
269
+ const parent = elementRef.current?.parentNode;
270
+
271
+ parent?.insertBefore(elem, elementRef.current?.nextSibling ?? null);
272
+ });
273
+ },
274
+ [_registerMethod]
275
+ );
276
+
277
+ // @ts-ignore
278
+ context.prependSibling = useCallback(
279
+ (elem: HTMLElement) => {
280
+ // @ts-ignore
281
+ _registerMethod(() => {
282
+ const parent = elementRef.current?.parentNode;
283
+
284
+ parent?.insertBefore(elem, elementRef.current);
285
+ });
286
+ },
287
+ [_registerMethod]
288
+ );
289
+
290
+ const handleLifeCycleRender = useCallback(async () => {
291
+ if (status.current === 'loading') return;
292
+
293
+ status.current = 'loading';
294
+
295
+ log(`🟨 "${name}" Slot Rendered`);
296
+
297
+ // Reset
298
+ const renderNode = render
299
+ ? cloneElement(render(props), { key: 'render' })
300
+ : null;
301
+ _setProps({ children: [renderNode ?? children] });
302
+
303
+ // Run all registered methods
304
+ methodsRef.current.forEach((method: any) => {
305
+ method(context, state);
306
+ });
307
+
308
+ status.current = 'ready';
309
+ }, [children, context, name, props, render, state]);
310
+
311
+ // Initialization
312
+ const handleLifeCycleInit = useCallback(async () => {
313
+ if (!callback) return;
314
+
315
+ try {
316
+ status.current = 'loading';
317
+
318
+ log(`🟩 "${name}" Slot Initialized`);
319
+ await callback(context as K & DefaultSlotContext<K>, elementRef.current);
320
+ } catch (error) {
321
+ console.error(`Error in "${callback.name}" Slot callback`, error);
322
+ } finally {
323
+ status.current = 'ready';
324
+
325
+ // first render
326
+ await handleLifeCycleRender();
327
+ }
328
+ }, [callback, context, handleLifeCycleRender, name]);
329
+
330
+ // Initialization
331
+ useEffect(() => {
332
+ handleLifeCycleInit().finally(() => {
333
+ if (slotsQueue) {
334
+ slotsQueue.value.delete(name);
335
+ slotsQueue.value = new Set(slotsQueue.value);
336
+ }
337
+ });
338
+
339
+ // eslint-disable-next-line react-hooks/exhaustive-deps
340
+ }, []);
341
+
342
+ // Update
343
+ useEffect(() => {
344
+ handleLifeCycleRender();
345
+
346
+ // eslint-disable-next-line react-hooks/exhaustive-deps
347
+ }, [JSON.stringify(context), JSON.stringify(_state)]);
348
+
349
+ return [elementRef, props];
350
+ }
351
+
352
+ // Slot Component
353
+ interface SlotPropsComponent<T>
354
+ extends Omit<HTMLAttributes<HTMLDivElement>, 'slot'> {
355
+ name: string;
356
+ slot?: SlotProps<T>;
357
+ context?: Context<T>;
358
+ render?: (props: Record<string, any>) => VNode | VNode[];
359
+ }
360
+
361
+ export function Slot<T>({
362
+ name,
363
+ context,
364
+ slot,
365
+ children,
366
+ render,
367
+ ...props
368
+ }: Readonly<SlotPropsComponent<T>>) {
369
+ const slotsQueue = useContext(SlotQueueContext);
370
+
371
+ const [elementRef, slotProps] = useSlot<T, HTMLDivElement>(
372
+ name,
373
+ context,
374
+ slot,
375
+ children,
376
+ render
377
+ );
378
+
379
+ useMemo(() => {
380
+ if (!name) {
381
+ return console.warn('Slot "name" is required');
382
+ }
383
+
384
+ // add slot to queue
385
+ if (slotsQueue) {
386
+ slotsQueue.value.add(name);
387
+ slotsQueue.value = new Set(slotsQueue.value);
388
+ }
389
+ }, [name, slotsQueue]);
390
+
391
+ return (
392
+ <div {...props} ref={elementRef} data-slot={name}>
393
+ {slotProps.children}
394
+ </div>
395
+ );
396
+ }
397
+
398
+ // Debugger
399
+
400
+ // @ts-ignore
401
+ window.DROPINS = window.DROPINS || {};
402
+
403
+ // @ts-ignore
404
+ window.DROPINS.showSlots = async (state) => {
405
+ // cache state in session storage
406
+ window.sessionStorage.setItem(
407
+ 'dropin-debugger--show-slots',
408
+ state.toString()
409
+ );
410
+
411
+ document.body.classList.toggle('dropin-debugger--show-slots', state);
412
+ };
413
+
414
+ let log: (...attrs: any) => void = () => {};
415
+
416
+ // @ts-ignore
417
+ window.DROPINS.logSlots = async (state) => {
418
+ // cache state in session storage
419
+ window.sessionStorage.setItem('dropin-debugger--log-slots', state.toString());
420
+
421
+ log = state ? (...attrs) => console.log(...attrs) : () => {};
422
+ };
423
+
424
+ /** Persistent Settings */
425
+
426
+ // @ts-ignore
427
+ window.DROPINS.showSlots(
428
+ window.sessionStorage.getItem('dropin-debugger--show-slots') === 'true'
429
+ );
430
+
431
+ // @ts-ignore
432
+ window.DROPINS.logSlots(
433
+ window.sessionStorage.getItem('dropin-debugger--log-slots') === 'true'
434
+ );
@@ -0,0 +1,47 @@
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 {
11
+ render as originalRender,
12
+ RenderOptions,
13
+ RenderResult,
14
+ } from '@testing-library/preact';
15
+ import fs from 'fs';
16
+ import path from 'path';
17
+
18
+ import { UIProvider } from '@adobe-commerce/elsie/components';
19
+
20
+ export * from '@testing-library/preact';
21
+
22
+ const directoryPath = path.relative(process.cwd(), 'src/i18n/'); // path to the JSON files (relative to this file
23
+
24
+ const files = fs.readdirSync(directoryPath); // get a list of all files in the directory
25
+
26
+ const jsonFiles = files.filter((file) => path.extname(file) === '.json'); // filter out only the JSON files
27
+
28
+ const langDefinitions = jsonFiles.reduce((acc, file) => {
29
+ const filePath = path.join(directoryPath, file); // get the full path to the file
30
+ const rawData = fs.readFileSync(filePath); // read the file synchronously
31
+ const parsedData = JSON.parse(rawData as any); // parse the JSON data and return it
32
+ return { ...acc, [file.replace('.json', '')]: parsedData };
33
+ }, {});
34
+
35
+ export const render = (
36
+ ui: any,
37
+ options?: Omit<RenderOptions, 'queries'>
38
+ ): RenderResult => {
39
+ return originalRender(
40
+ <UIProvider lang={'en_US'} langDefinitions={langDefinitions}>
41
+ <div className="dropin-design">
42
+ {ui}
43
+ </div>
44
+ </UIProvider>,
45
+ options
46
+ );
47
+ };
@@ -0,0 +1,16 @@
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
+
12
+ export type Container<T, D = { [key: string]: any }> = FunctionComponent<
13
+ T & { initialData?: D }
14
+ > & {
15
+ getInitialData?: (props: T) => Promise<D>;
16
+ };
@@ -0,0 +1,42 @@
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 { VNode, ComponentChildren } from 'preact';
11
+ import { classes } from '.';
12
+
13
+ export type VComponentProps = {
14
+ node: VNode | VNode[];
15
+ children?: ComponentChildren;
16
+ [key: string]: any; // allow other unspecified props to be passed without any TS warning
17
+ };
18
+
19
+ export function VComponent({ node, ...props }: VComponentProps) {
20
+ if (!node) return null;
21
+
22
+ if (Array.isArray(node)) {
23
+ return (
24
+ <>
25
+ {node.map((n, key) => (
26
+ <VComponent
27
+ key={key}
28
+ node={n}
29
+ className={props.className}
30
+ {...props}
31
+ />
32
+ ))}
33
+ </>
34
+ );
35
+ }
36
+
37
+ // @ts-ignore
38
+ props.className = classes([node.props.className, props.className]);
39
+
40
+ // @ts-ignore
41
+ return <node.type ref={node.ref} key={node.key} {...node.props} {...props} />;
42
+ }
Binary file
Binary file
@@ -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 { default as Card } from './Card.png';
11
+ export { default as Image } from './example.jpg';
Binary file
@@ -0,0 +1,14 @@
1
+ <svg version="1.2" baseProfile="tiny-ps" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 488 432" width="488" height="432">
2
+ <title>Adobe_Corporate_logo-svg</title>
3
+ <style>
4
+ tspan { white-space:pre }
5
+ .shp0 { fill: #fa0c00 }
6
+ </style>
7
+ <g id="Layer">
8
+ <path id="Layer" class="shp0" d="M180.43 0L0 0L0 431.15L180.43 0Z" />
9
+ <path id="Layer" class="shp0" d="M307.37 0L487.57 0L487.57 431.15L307.37 0Z" />
10
+ <path id="Layer" class="shp0" d="M243.9 158.91L358.74 431.15L283.4 431.15L249.07 344.47L165.03 344.47L243.9 158.91Z" />
11
+ </g>
12
+ <g id="Layer">
13
+ </g>
14
+ </svg>
@@ -0,0 +1,21 @@
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
+ const path = require('path');
11
+
12
+ const { name } = require('./.elsie');
13
+
14
+ module.exports = {
15
+ stories: [
16
+ {
17
+ directory: path.resolve(__dirname, './src'),
18
+ titlePrefix: name,
19
+ },
20
+ ],
21
+ };
@@ -0,0 +1,28 @@
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
+ // Mock Browser API's which are not supported by JSDOM, e.g. ServiceWorker, LocalStorage
11
+ import { TextDecoder, TextEncoder } from 'util';
12
+ import { BroadcastChannel } from 'worker_threads';
13
+
14
+ Object.defineProperty(window, 'BroadcastChannel', {
15
+ value: BroadcastChannel,
16
+ writable: true,
17
+ });
18
+
19
+ // mock values which are used by the gql builder function (which for some reason is not provided)
20
+ Object.defineProperty(window, 'TextDecoder', {
21
+ value: TextDecoder,
22
+ writable: true,
23
+ });
24
+
25
+ Object.defineProperty(window, 'TextEncoder', {
26
+ value: TextEncoder,
27
+ writable: true,
28
+ });
@@ -0,0 +1,12 @@
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
+ // This fixed an error related to the CSS and loading gif breaking my Jest test
11
+ // See https://facebook.github.io/jest/docs/en/webpack.html#handling-static-assets
12
+ export default 'test-file-stub';
File without changes
@@ -0,0 +1,18 @@
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
+ declare module '*.svg' {
11
+ import { SVGProps, FunctionComponent } from 'preact/compat';
12
+
13
+ const ReactComponent: FunctionComponent<
14
+ SVGProps<SVGSVGElement> & { title?: string }
15
+ >;
16
+
17
+ export default ReactComponent;
18
+ }