@saasquatch/mint-components 1.5.5-1 → 1.5.5-2

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 (172) hide show
  1. package/dist/cjs/{ShadowViewAddon-1716c9f5.js → ShadowViewAddon-1bbdf477.js} +2 -2
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/mint-components.cjs.js +1 -1
  4. package/dist/cjs/sqm-big-stat_35.cjs.entry.js +126 -161
  5. package/dist/cjs/sqm-empty_5.cjs.entry.js +2 -2
  6. package/dist/cjs/sqm-hero.cjs.entry.js +7 -15
  7. package/dist/cjs/sqm-leaderboard-rank.cjs.entry.js +15 -8
  8. package/dist/cjs/sqm-password-field.cjs.entry.js +2 -5
  9. package/dist/cjs/sqm-portal-email-verification.cjs.entry.js +4 -4
  10. package/dist/cjs/sqm-portal-forgot-password.cjs.entry.js +4 -4
  11. package/dist/cjs/sqm-portal-logout.cjs.entry.js +1 -1
  12. package/dist/cjs/sqm-portal-profile.cjs.entry.js +8 -18
  13. package/dist/cjs/sqm-portal-protected-route.cjs.entry.js +1 -1
  14. package/dist/cjs/sqm-portal-reset-password.cjs.entry.js +10 -12
  15. package/dist/cjs/sqm-portal-verify-email.cjs.entry.js +2 -2
  16. package/dist/cjs/sqm-referral-table_11.cjs.entry.js +8 -21
  17. package/dist/cjs/sqm-rewards-table_9.cjs.entry.js +4 -8
  18. package/dist/cjs/sqm-stencilbook.cjs.entry.js +300 -98
  19. package/dist/collection/components/sqm-asset-card/sqm-asset-card.js +2 -2
  20. package/dist/collection/components/sqm-big-stat/sqm-big-stat.js +7 -13
  21. package/dist/collection/components/sqm-checkbox-field/sqm-checkbox-field.js +10 -11
  22. package/dist/collection/components/sqm-divided-layout/sqm-divided-layout.js +4 -4
  23. package/dist/collection/components/sqm-dropdown-field/sqm-dropdown-field.js +5 -5
  24. package/dist/collection/components/sqm-edit-profile/sqm-edit-profile.js +9 -9
  25. package/dist/collection/components/sqm-empty/EmptyState.stories.js +1 -0
  26. package/dist/collection/components/sqm-empty/sqm-empty.js +0 -1
  27. package/dist/collection/components/sqm-form-message/sqm-form-message.js +3 -3
  28. package/dist/collection/components/sqm-hero/sqm-hero.js +15 -23
  29. package/dist/collection/components/sqm-hero-image/sqm-hero-image.js +3 -7
  30. package/dist/collection/components/sqm-hook-story-container/sqm-hook-story-container.js +0 -3
  31. package/dist/collection/components/sqm-leaderboard/Leaderboard.stories.js +147 -27
  32. package/dist/collection/components/sqm-leaderboard/UseLeaderboard.stories.js +56 -0
  33. package/dist/collection/components/sqm-leaderboard/sqm-leaderboard-view.js +2 -2
  34. package/dist/collection/components/sqm-leaderboard/sqm-leaderboard.js +70 -20
  35. package/dist/collection/components/sqm-leaderboard/useLeaderboard.js +42 -19
  36. package/dist/collection/components/sqm-leaderboard-rank/LeaderboardRank.stories.js +18 -0
  37. package/dist/collection/components/sqm-leaderboard-rank/sqm-leaderboard-rank.js +28 -8
  38. package/dist/collection/components/sqm-leaderboard-rank/useLeaderboardRank.js +15 -8
  39. package/dist/collection/components/sqm-name-fields/sqm-name-fields.js +4 -4
  40. package/dist/collection/components/sqm-navigation-menu/sqm-navigation-menu.js +3 -3
  41. package/dist/collection/components/sqm-navigation-sidebar/sqm-navigation-sidebar.js +1 -1
  42. package/dist/collection/components/sqm-navigation-sidebar-item/sqm-navigation-sidebar-item.js +1 -1
  43. package/dist/collection/components/sqm-password-field/sqm-password-field.js +6 -9
  44. package/dist/collection/components/sqm-popup-container/sqm-popup-container.js +11 -11
  45. package/dist/collection/components/sqm-portal-change-password/sqm-portal-change-password.js +22 -34
  46. package/dist/collection/components/sqm-portal-container/sqm-portal-container.js +4 -4
  47. package/dist/collection/components/sqm-portal-email-verification/sqm-portal-email-verification.js +8 -8
  48. package/dist/collection/components/sqm-portal-forgot-password/sqm-portal-forgot-password.js +8 -8
  49. package/dist/collection/components/sqm-portal-login/sqm-portal-login.js +26 -42
  50. package/dist/collection/components/sqm-portal-logout/sqm-portal-logout.js +2 -2
  51. package/dist/collection/components/sqm-portal-profile/sqm-portal-profile.js +21 -31
  52. package/dist/collection/components/sqm-portal-protected-route/sqm-portal-protected-route.js +2 -2
  53. package/dist/collection/components/sqm-portal-register/sqm-portal-register.js +28 -36
  54. package/dist/collection/components/sqm-portal-reset-password/sqm-portal-reset-password.js +21 -23
  55. package/dist/collection/components/sqm-portal-verify-email/sqm-portal-verify-email.js +4 -4
  56. package/dist/collection/components/sqm-referral-card/sqm-referral-card.js +0 -1
  57. package/dist/collection/components/sqm-referral-iframe/sqm-referral-iframe.js +9 -11
  58. package/dist/collection/components/sqm-referral-table/columns/sqm-referral-table-user-column.js +6 -10
  59. package/dist/collection/components/sqm-referral-table/sqm-referral-table.js +14 -23
  60. package/dist/collection/components/sqm-reward-exchange-list/sqm-reward-exchange-list.js +15 -22
  61. package/dist/collection/components/sqm-rewards-table/columns/sqm-rewards-table-reward-column.js +2 -2
  62. package/dist/collection/components/sqm-rewards-table/columns/sqm-rewards-table-source-column.js +8 -12
  63. package/dist/collection/components/sqm-route/sqm-route.js +1 -1
  64. package/dist/collection/components/sqm-share-button/sqm-share-button.js +15 -18
  65. package/dist/collection/components/sqm-share-code/sqm-share-code.js +7 -6
  66. package/dist/collection/components/sqm-share-link/sqm-share-link.js +7 -6
  67. package/dist/collection/components/sqm-stat-container/sqm-stat-container.js +2 -2
  68. package/dist/collection/components/sqm-task-card/sqm-task-card.js +8 -96
  69. package/dist/collection/components/sqm-text-span/sqm-text-span.js +1 -1
  70. package/dist/collection/components/sqm-timeline/sqm-timeline-entry.js +0 -1
  71. package/dist/collection/components/sqm-titled-section/sqm-titled-section.js +4 -4
  72. package/dist/collection/components/sqm-user-name/sqm-user-name.js +5 -6
  73. package/dist/esm/{ShadowViewAddon-16edf1a4.js → ShadowViewAddon-e2996624.js} +2 -2
  74. package/dist/esm/loader.js +1 -1
  75. package/dist/esm/mint-components.js +1 -1
  76. package/dist/esm/sqm-big-stat_35.entry.js +127 -162
  77. package/dist/esm/sqm-empty_5.entry.js +2 -2
  78. package/dist/esm/sqm-hero.entry.js +7 -15
  79. package/dist/esm/sqm-leaderboard-rank.entry.js +15 -8
  80. package/dist/esm/sqm-password-field.entry.js +2 -5
  81. package/dist/esm/sqm-portal-email-verification.entry.js +4 -4
  82. package/dist/esm/sqm-portal-forgot-password.entry.js +4 -4
  83. package/dist/esm/sqm-portal-logout.entry.js +1 -1
  84. package/dist/esm/sqm-portal-profile.entry.js +8 -18
  85. package/dist/esm/sqm-portal-protected-route.entry.js +1 -1
  86. package/dist/esm/sqm-portal-reset-password.entry.js +10 -12
  87. package/dist/esm/sqm-portal-verify-email.entry.js +2 -2
  88. package/dist/esm/sqm-referral-table_11.entry.js +8 -21
  89. package/dist/esm/sqm-rewards-table_9.entry.js +4 -8
  90. package/dist/esm/sqm-stencilbook.entry.js +300 -98
  91. package/dist/esm-es5/ShadowViewAddon-e2996624.js +1 -0
  92. package/dist/esm-es5/loader.js +1 -1
  93. package/dist/esm-es5/mint-components.js +1 -1
  94. package/dist/esm-es5/sqm-big-stat_35.entry.js +1 -1
  95. package/dist/esm-es5/sqm-leaderboard-rank.entry.js +1 -1
  96. package/dist/esm-es5/sqm-stencilbook.entry.js +1 -1
  97. package/dist/mint-components/mint-components.esm.js +1 -1
  98. package/dist/mint-components/p-232672a2.entry.js +13 -0
  99. package/dist/mint-components/{p-294c486f.js → p-3facf714.js} +1 -1
  100. package/dist/mint-components/p-64cc1a70.system.entry.js +1 -0
  101. package/dist/mint-components/p-87ffb558.entry.js +9 -0
  102. package/dist/mint-components/p-91acec3d.entry.js +159 -0
  103. package/dist/mint-components/p-94096609.system.js +1 -1
  104. package/dist/mint-components/p-951e7817.system.entry.js +1 -0
  105. package/dist/mint-components/p-ba99d04e.system.entry.js +1 -0
  106. package/dist/mint-components/p-d3cc0d60.system.js +1 -0
  107. package/dist/types/components/sqm-asset-card/sqm-asset-card.d.ts +2 -2
  108. package/dist/types/components/sqm-big-stat/sqm-big-stat.d.ts +4 -12
  109. package/dist/types/components/sqm-checkbox-field/sqm-checkbox-field.d.ts +5 -6
  110. package/dist/types/components/sqm-divided-layout/sqm-divided-layout.d.ts +2 -2
  111. package/dist/types/components/sqm-dropdown-field/sqm-dropdown-field.d.ts +3 -3
  112. package/dist/types/components/sqm-edit-profile/sqm-edit-profile.d.ts +7 -10
  113. package/dist/types/components/sqm-empty/sqm-empty.d.ts +0 -1
  114. package/dist/types/components/sqm-form-message/sqm-form-message.d.ts +2 -8
  115. package/dist/types/components/sqm-hero/sqm-hero.d.ts +8 -20
  116. package/dist/types/components/sqm-hero-image/sqm-hero-image.d.ts +1 -5
  117. package/dist/types/components/sqm-hook-story-container/sqm-hook-story-container.d.ts +0 -3
  118. package/dist/types/components/sqm-leaderboard/Leaderboard.stories.d.ts +2 -1
  119. package/dist/types/components/sqm-leaderboard/UseLeaderboard.stories.d.ts +18 -0
  120. package/dist/types/components/sqm-leaderboard/sqm-leaderboard-view.d.ts +2 -2
  121. package/dist/types/components/sqm-leaderboard/sqm-leaderboard.d.ts +25 -9
  122. package/dist/types/components/sqm-leaderboard/useLeaderboard.d.ts +4 -2
  123. package/dist/types/components/sqm-leaderboard-rank/LeaderboardRank.stories.d.ts +5 -0
  124. package/dist/types/components/sqm-leaderboard-rank/sqm-leaderboard-rank.d.ts +14 -7
  125. package/dist/types/components/sqm-leaderboard-rank/useLeaderboardRank.d.ts +2 -1
  126. package/dist/types/components/sqm-name-fields/sqm-name-fields.d.ts +2 -2
  127. package/dist/types/components/sqm-navigation-menu/sqm-navigation-menu.d.ts +2 -4
  128. package/dist/types/components/sqm-navigation-sidebar/sqm-navigation-sidebar.d.ts +1 -1
  129. package/dist/types/components/sqm-navigation-sidebar-item/sqm-navigation-sidebar-item.d.ts +1 -1
  130. package/dist/types/components/sqm-password-field/sqm-password-field.d.ts +2 -5
  131. package/dist/types/components/sqm-popup-container/sqm-popup-container.d.ts +6 -21
  132. package/dist/types/components/sqm-portal-change-password/sqm-portal-change-password.d.ts +8 -20
  133. package/dist/types/components/sqm-portal-container/sqm-portal-container.d.ts +3 -5
  134. package/dist/types/components/sqm-portal-email-verification/sqm-portal-email-verification.d.ts +4 -4
  135. package/dist/types/components/sqm-portal-forgot-password/sqm-portal-forgot-password.d.ts +4 -4
  136. package/dist/types/components/sqm-portal-login/sqm-portal-login.d.ts +9 -25
  137. package/dist/types/components/sqm-portal-logout/sqm-portal-logout.d.ts +1 -1
  138. package/dist/types/components/sqm-portal-profile/sqm-portal-profile.d.ts +8 -18
  139. package/dist/types/components/sqm-portal-protected-route/sqm-portal-protected-route.d.ts +1 -1
  140. package/dist/types/components/sqm-portal-register/sqm-portal-register.d.ts +12 -20
  141. package/dist/types/components/sqm-portal-reset-password/sqm-portal-reset-password.d.ts +10 -12
  142. package/dist/types/components/sqm-portal-verify-email/sqm-portal-verify-email.d.ts +2 -2
  143. package/dist/types/components/sqm-referral-card/sqm-referral-card.d.ts +0 -1
  144. package/dist/types/components/sqm-referral-iframe/sqm-referral-iframe.d.ts +4 -7
  145. package/dist/types/components/sqm-referral-table/columns/sqm-referral-table-user-column.d.ts +2 -6
  146. package/dist/types/components/sqm-referral-table/sqm-referral-table.d.ts +6 -15
  147. package/dist/types/components/sqm-reward-exchange-list/sqm-reward-exchange-list.d.ts +9 -16
  148. package/dist/types/components/sqm-rewards-table/columns/sqm-rewards-table-reward-column.d.ts +1 -1
  149. package/dist/types/components/sqm-rewards-table/columns/sqm-rewards-table-source-column.d.ts +3 -7
  150. package/dist/types/components/sqm-route/sqm-route.d.ts +1 -1
  151. package/dist/types/components/sqm-share-button/sqm-share-button.d.ts +9 -17
  152. package/dist/types/components/sqm-share-code/sqm-share-code.d.ts +2 -2
  153. package/dist/types/components/sqm-share-link/sqm-share-link.d.ts +2 -2
  154. package/dist/types/components/sqm-stat-container/sqm-stat-container.d.ts +1 -1
  155. package/dist/types/components/sqm-task-card/sqm-task-card.d.ts +8 -35
  156. package/dist/types/components/sqm-text-span/sqm-text-span.d.ts +1 -1
  157. package/dist/types/components/sqm-timeline/sqm-timeline-entry.d.ts +0 -1
  158. package/dist/types/components/sqm-titled-section/sqm-titled-section.d.ts +2 -2
  159. package/dist/types/components/sqm-user-name/sqm-user-name.d.ts +2 -3
  160. package/dist/types/components.d.ts +372 -494
  161. package/grapesjs/grapesjs.js +1 -1
  162. package/package.json +3 -8
  163. package/dist/esm-es5/ShadowViewAddon-16edf1a4.js +0 -1
  164. package/dist/mint-components/p-075154b7.entry.js +0 -13
  165. package/dist/mint-components/p-20305fa4.system.entry.js +0 -1
  166. package/dist/mint-components/p-4ccb3b36.system.entry.js +0 -1
  167. package/dist/mint-components/p-62cc7fae.entry.js +0 -9
  168. package/dist/mint-components/p-6ce2e2eb.system.entry.js +0 -1
  169. package/dist/mint-components/p-acc840a5.system.js +0 -1
  170. package/dist/mint-components/p-dbf1beab.entry.js +0 -150
  171. package/docs/docs.docx +0 -0
  172. package/docs/raisins.json +0 -1
@@ -27,7 +27,7 @@ const sqmPortalContainerView = require('./sqm-portal-container-view-840db620.js'
27
27
  const sqmPortalProfileView = require('./sqm-portal-profile-view-64e85659.js');
28
28
  const sqmPortalResetPasswordView = require('./sqm-portal-reset-password-view-f8dc0b79.js');
29
29
  const sqmPortalVerifyEmailView = require('./sqm-portal-verify-email-view-cc59877c.js');
30
- const ShadowViewAddon = require('./ShadowViewAddon-1716c9f5.js');
30
+ const ShadowViewAddon = require('./ShadowViewAddon-1bbdf477.js');
31
31
  const sqmPortalSectionView = require('./sqm-portal-section-view-854a3e9c.js');
32
32
 
33
33
  /**
@@ -1601,6 +1601,7 @@ const SlottedIntoComponent = () => {
1601
1601
  rankType: "rowNumber",
1602
1602
  leaderboard: [],
1603
1603
  showUser: true,
1604
+ rowNumber: 10,
1604
1605
  userRank: {
1605
1606
  firstName: "Kutay",
1606
1607
  lastInitial: "C",
@@ -1771,7 +1772,7 @@ const BigStat = /*#__PURE__*/Object.freeze({
1771
1772
  MultipleStats: MultipleStats
1772
1773
  });
1773
1774
 
1774
- const scenario$4 = "@owner:noah\n@author:noah\nFeature: Leaderboard\n\n\tThe leaderboard displays the top referrers along with their scores\n\n\t@motivating\n\tScenario Outline: The leaderboard can be for referrals started or converted\n\t\tGiven a leaderboard is configured with \"leaderboard-type\" <value>\n\t\tAnd a user with started referrals\n\t\tAnd a user with converted referrals\n\t\tWhen they view the leaderboard\n\t\tThen then only <referralType> referrals are counted in the leaderboard\n\t\tExamples:\n\t\t\t| value | referralType |\n\t\t\t| topStartedReferrers | started |\n\t\t\t| topConvertedReferrers | converted |\n\t\t\t| | started |\n\n\t@motivating\n\tScenario: If there are any users with referrals the leaderboard is shown\n\t\tGiven there is aleast one user\n\t\tThen the leaderboard displays up to 10 top referrers\n\t\tAnd leaderboard is ordered by the referrers score in descending ordered\n\n\t@motivating\n\tScenario: The leaderboard can filter referrals within an time interval\n\t\tGiven a leaderboard is configured with \"interval\" \"2021-11-02T07:00:00.000Z/2021-11-07T07:00:00.000Z\"\n\t\tAnd a user with referrals\n\t\tWhen they view the leaderboard\n\t\tThen only referrals from within \"2021-11-02T07:00:00.000Z/2021-11-07T07:00:00.000Z\" are counted in the leaderboard\n\n\t@motivating\n\tScenario Outline: Rank Type can be configured\n\t\tGiven a leaderboard is configured with \"rank-type\" <value>\n\t\tAnd a user\n\t\tWhen they view the leaderboard\n\t\tThen their leaderboard rank is their <rank>\n\t\tExamples:\n\t\t\t| value | rank |\n\t\t\t| rowNumber | row number |\n\t\t\t| denseRank | dense rank |\n\t\t\t| rank | rank |\n\n\t@minutiae\n\t@ui\n\tScenario: An empty state is displayed if no users\n\t\tGiven a user\n\t\tBut no users have made any referrals\n\t\tWhen they view the leaderboard\n\t\tThen an empty state is dislayed\n\t\tAnd they see an image of a leaderboard\n\t\tAnd below they see \"View your rank in the leaderboard\"\n\t\tAnd below they see \"Be the first to refer a friend and reach the top of the leaderboard\"\n\t\tAnd the text is center aligned\n\n\t@minutiae\n\t@ui\n\tScenario: A custom empty state can be provided\n\t\tGiven a user\n\t\tBut no users have made any referrals\n\t\tWhen they view the leaderboard\n\t\tThen the contents of the \"empty\" slot are displayed\n\n\t@minutiae\n\t@ui\n\tScenario: Leaderboard headings can be customized\n\t\tGiven a leaderboard\n\t\tAnd it has the following props\n\t\t\t| prop | value |\n\t\t\t| rankheading | Place |\n\t\t\t| usersheading | Customer |\n\t\t\t| statsheading | Referral Count |\n\t\t\t| show-rank | true |\n\t\tAnd a user\n\t\tWhen they view the leaderboard\n\t\tThen they see the following columns with headings\n\t\t\t| column | heading |\n\t\t\t| rank | Place |\n\t\t\t| user | Customer |\n\t\t\t| stat | Referral Count |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Rank can be hidden or shown\n\t\tGiven a leaderboard\n\t\tAnd it has prop \"show-rank\" with <propValue>\n\t\tAnd a user\n\t\tWhen they view the leaderboard\n\t\tThen they <maySee> the rank column\n\t\tExamples:\n\t\t\t| propValue | maySee |\n\t\t\t| true | see |\n\t\t\t| false | don't see |\n\t\t\t| | don't see |\n\n\t@motivating\n\t@ui\n\tScenario: Users in the top 10 referrers see their leaderboard row highlighted\n\t\tGiven a user\n\t\tAnd they are in the top 10 referrers\n\t\tWhen they view the leaderboard\n\t\tThen they see the row with their name highlighted with brand colour\n\n\t@motivating\n\t@ui\n\tScenario Outline: Users not in the top 10 referrers can see their progress at the bottom of the leaderboard\n\t\tGiven a user\n\t\tAnd they <mayHmayHaveReferralave>\n\t\tAnd they are not in the top 10 referrers\n\t\tAnd the leaderboard has prop \"show-user\" with <value>\n\t\tWhen they view the leaderboard\n\t\tThen they <maySee> \"...\" under the top 10 referrers\n\t\tAnd under \"...\" they <maySee> a row highlighted with brand colour\n\t\tAnd they <maySee> their name\n\t\tAnd they <maySee> their referral count\n\t\tAnd they <maySeeRank>\n\t\tExamples:\n\t\t\t| mayHaveReferral | value | maySee | maySeeRank |\n\t\t\t| have referrals | true | see | see their rank |\n\t\t\t| don't have referrals | true | see | don't see their rank |\n\t\t\t| | false | don't see | don't see their rank |\n\t\t\t| have referrals | | see | see their rank |\n\n\t@minutiae\n\tScenario: Users without names are displayed as an \"Anonymous User\"\n\t\tGiven a user\n\t\tAnd they do not have a first name\n\t\tAnd they do not have a last initial\n\t\tWhen they view the leaderboard\n\t\tThen they see the user displayed as \"Anonymous User\"\n\n\t@minutiae\n\tScenario Outline: If a user only has a first or last name, then only that is displayed\n\t\tGiven a user\n\t\tAnd they only have a <name>\n\t\tWhen they view the leaderboard\n\t\tThen they only see their <name>\n\t\tExamples:\n\t\t\t| name |\n\t\t\t| firstName |\n\t\t\t| lastName |";
1775
+ const scenario$4 = "@owner:noah\n@author:noah\nFeature: Leaderboard\n\n\tThe leaderboard supports three main cases\n\t- Top Started Referrers\n\t- Top Converted Referrers\n\t- Top Point Earners\n\tTo display these different types of leaderboards it uses the backends pre-canned options.\n\tThe backend supports filtering on programId and interval, programId is sourced from program context.\n\n\tBackground: A user exists\n\t\tGiven a user\n\t\tAnd they are viewing the leaderboard\n\n\t@motivating\n\tScenario Outline: Two types of referrals leaderboards can be displayed\n\t\tGiven a leaderboard has prop \"leaderboard-type\" with <value>\n\t\tAnd there are started referrals on the tenant\n\t\tAnd there are started converted on the tenant\n\t\tWhen the user views the leaderboard\n\t\tThen they see the referral <referralType> leaderboard\n\t\tExamples:\n\t\t\t| value | referralType |\n\t\t\t| topStartedReferrers | started |\n\t\t\t| topConvertedReferrers | converted |\n\n\t@motivating\n\tScenario: The top point earners leaderboard can be displayed\n\t\tGiven a leaderboard has prop \"leaderboard-type\" with value \"topPointEarners\"\n\t\tAnd there are users with points\n\t\tWhen the user views the leaderboard\n\t\tThen they see the top point earners leaderboard\n\t\tAnd text values are displayed for point counts\n\n\t@minutia\n\tScenario Outline: Reward pretty value is used on the top point earners leaderboard\n\t\tGiven top point earners leaderboard\n\t\tAnd the \"POINT\" reward unit has a pretty value for the following locales\n\t\t\t| locale |\n\t\t\t| en |\n\t\t\t| fr |\n\t\t\t| tr |\n\t\tWhen the user views the leaderboard\n\t\tAnd they have <locale>\n\t\tThen they see the translated pretty value in the stat value column\n\n\t@motivating\n\tScenario Outline: Program Context is used by default to filter leaderboard results\n\t\tGiven a <leaderboardType> leaderboard loaded with program context for \"my-program\"\n\t\tWhen the user views the leaderboard\n\t\tThen they only see <results> from \"my-program\"\n\t\tExamples:\n\t\t\t| leaderboardType | results |\n\t\t\t| topStartedReferrers | started referrals |\n\t\t\t| topConvertedReferrers | converted referrals |\n\t\t\t| topPointEarners | points earned |\n\n\t@motivating\n\tScenario Outline: Program Id context can be overwritten with a prop\n\t\tGiven a <leaderboardType> leaderboard has prop \"program-Id\" with value \"my-test-program\"\n\t\tWhen the user views the leaderboard\n\t\tThen they only see <results> from \"my-test-program\"\n\t\tExamples:\n\t\t\t| leaderboardType | results |\n\t\t\t| topStartedReferrers | started referrals |\n\t\t\t| topConvertedReferrers | converted referrals |\n\t\t\t| topPointEarners | points earned |\n\n\t@motivating\n\tScenario Outline: Global leaderboards can be displayed by clearing program context\n\t\t#This is important for clients with use cases like StaffTracks global points leaderboard\n\t\t#This can also be done with a program section in a similar manner\n\t\tGiven a <leaderboardType> leaderboard has prop \"program-Id\" with value \"\"\n\t\tWhen the user views the leaderboard\n\t\tThen they see global <results>\n\t\tExamples:\n\t\t\t| leaderboardType | results |\n\t\t\t| topStartedReferrers | started referrals |\n\t\t\t| topConvertedReferrers | converted referrals |\n\t\t\t| topPointEarners | points earned |\n\n\t@motivating\n\tScenario: Leaderboard results are shown in descending order\n\t\tGiven there are leaderboard results\n\t\tWhen the user views the leaderboard\n\t\tThen they see up to the 10 top leaderboard results\n\t\tAnd leaderboard is in descending order\n\n\t@motivating\n\tScenario Outline: Leaderboard results can be filtered with a time interval\n\t\tGiven a <leaderboardType> leaderboard\n\t\tAnd it has prop \"interval\" with value \"2021-11-02T07:00:00.000Z/2021-11-07T07:00:00.000Z\"\n\t\tWhen the user views the leaderboard\n\t\tThen they only see <results> from within \"2021-11-02T07:00:00.000Z/2021-11-07T07:00:00.000Z\"\n\t\tExamples:\n\t\t\t| leaderboardType | results |\n\t\t\t| topStartedReferrers | started referrals |\n\t\t\t| topConvertedReferrers | converted referrals |\n\t\t\t| topPointEarners | points earned |\n\n\t@motivating\n\tScenario Outline: Leaderboard rank type can be configured\n\t\tGiven a leaderboard has prop \"rank-type\" with <value>\n\t\tWhen the user views the leaderboard\n\t\tThen their leaderboard rank is their <rank>\n\t\tExamples:\n\t\t\t| value | rank |\n\t\t\t| rowNumber | row number |\n\t\t\t| denseRank | dense rank |\n\t\t\t| rank | rank |\n\n\t@minutia\n\tScenario Outline: The max number of leaderboard rows displayed can be configured but defaults to 10\n\t\tGiven a leaderboard has prop \"max-rows\" with <value>\n\t\tAnd the leaderboard has <resultCount>\n\t\tWhen the user views the leaderboard\n\t\tThen they see <number> rows\n\t\tExamples:\n\t\t\t| value | resultCount | number |\n\t\t\t| | 10 | 10 |\n\t\t\t| 5 | 10 | 5 |\n\t\t\t| 3 | 1 | 1 |\n\t\t\t| 25 | 15 | 15 |\n\n\t@minutiae\n\t@ui\n\tScenario: Leaderboards with no results show an empty state\n\t\tGiven a leaderboard has no results\n\t\tWhen the user views the leaderboard\n\t\tThen an empty state is dislayed\n\t\tAnd they see an image of a leaderboard\n\t\tAnd below they see \"View your rank in the leaderboard\"\n\t\tAnd below they see \"Be the first to refer a friend and reach the top of the leaderboard\"\n\t\tAnd the text is center aligned\n\n\t@minutiae\n\t@ui\n\tScenario: A custom empty state can be provided\n\t\tGiven a leaderboard has no results\n\t\tWhen the user views the leaderboard\n\t\tThen the contents of the \"empty\" slot are displayed\n\n\t@minutiae\n\t@ui\n\tScenario: Leaderboard headings can be customized\n\t\tGiven a leaderboard\n\t\tAnd it has the following props\n\t\t\t| prop | value |\n\t\t\t| rankheading | Place |\n\t\t\t| usersheading | Customer |\n\t\t\t| statsheading | Referral Count |\n\t\t\t| show-rank | true |\n\t\tWhen the user views the leaderboard\n\t\tThen they see the following columns with headings\n\t\t\t| column | heading |\n\t\t\t| rank | Place |\n\t\t\t| user | Customer |\n\t\t\t| stat | Referral Count |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Leaderboard rank can be hidden or shown\n\t\tGiven a leaderboard\n\t\tAnd it has prop \"show-rank\" with <propValue>\n\t\tWhen the user views the leaderboard\n\t\tThen they <maySee> the rank column\n\t\tExamples:\n\t\t\t| propValue | maySee |\n\t\t\t| true | see |\n\t\t\t| false | don't see |\n\t\t\t| | don't see |\n\n\t@motivating\n\t@ui\n\tScenario: Users in the top 10 of the leaderboard results see their leaderboard row highlighted\n\t\tGiven a user in the top 10 of the leaderboard results\n\t\tWhen they view the leaderboard\n\t\tThen they see the row with their name highlighted with brand colour\n\n\t@motivating\n\t@ui\n\tScenario Outline: Users not in the top 10 leaderboard results can see their progress at the bottom of the leaderboard\n\t\tGiven a user <mayHave> completed actions counted by the leaderboard\n\t\tAnd they are not in the top 10 leaderboard results\n\t\tAnd the leaderboard has prop \"show-user\" with <value>\n\t\tWhen they view the leaderboard\n\t\tThen they <maySee> \"...\" under the top 10 leaderboard results\n\t\tAnd under \"...\" they <maySee> a row highlighted with brand colour\n\t\tAnd they <maySee> their name\n\t\tAnd they <maySee> their leaderboard value\n\t\tAnd they <maySeeRank>\n\t\tExamples:\n\t\t\t| mayHave | value | maySee | maySeeRank |\n\t\t\t| has | true | see | see their rank |\n\t\t\t| hasn't | true | see | don't see their rank |\n\t\t\t| N/A | false | don't see | don't see their rank |\n\t\t\t| hasn't | | see | don't see their rank |\n\n\t@minutiae\n\tScenario: Users without names are displayed as an \"Anonymous User\"\n\t\tGiven a user\n\t\tAnd they do not have a first name\n\t\tAnd they do not have a last initial\n\t\tWhen they view the leaderboard\n\t\tThen they see the user displayed as \"Anonymous User\"\n\n\t@minutiae\n\tScenario Outline: If a user only has a first or last name, then only that is displayed\n\t\tGiven a user\n\t\tAnd they only have a <name>\n\t\tWhen they view the leaderboard\n\t\tThen they only see their <name>\n\t\tExamples:\n\t\t\t| name |\n\t\t\t| firstName |\n\t\t\t| lastName |";
1775
1776
 
1776
1777
  const Leaderboard_stories = {
1777
1778
  title: "Components/Leaderboard",
@@ -1781,72 +1782,144 @@ const Leaderboard_stories = {
1781
1782
  };
1782
1783
  const users = [
1783
1784
  {
1784
- firstName: "Viktor",
1785
- lastInitial: "V",
1786
- value: 82,
1785
+ firstName: "",
1786
+ lastInitial: "",
1787
+ textValue: "82",
1788
+ rank: 1,
1789
+ rowNumber: 1,
1790
+ },
1791
+ {
1792
+ firstName: "MF",
1793
+ lastInitial: "D",
1794
+ textValue: "73",
1795
+ rank: 2,
1796
+ rowNumber: 2,
1797
+ },
1798
+ {
1799
+ firstName: "Freddie",
1800
+ lastInitial: "G",
1801
+ textValue: "64",
1802
+ rank: 3,
1803
+ rowNumber: 3,
1804
+ },
1805
+ {
1806
+ firstName: "Benny",
1807
+ lastInitial: "B",
1808
+ textValue: "55",
1809
+ rank: 4,
1810
+ rowNumber: 4,
1811
+ },
1812
+ {
1813
+ firstName: "Mos",
1814
+ lastInitial: "D",
1815
+ textValue: "46",
1816
+ rank: 5,
1817
+ rowNumber: 5,
1818
+ },
1819
+ {
1820
+ firstName: "Joe",
1821
+ lastInitial: "S",
1822
+ textValue: "42",
1823
+ rank: 6,
1824
+ rowNumber: 6,
1825
+ },
1826
+ {
1827
+ firstName: "Zach",
1828
+ lastInitial: "H",
1829
+ textValue: "41",
1830
+ rank: 7,
1831
+ rowNumber: 7,
1832
+ },
1833
+ {
1834
+ firstName: "Sarah",
1835
+ lastInitial: "S",
1836
+ textValue: "39",
1837
+ rank: 8,
1838
+ rowNumber: 8,
1839
+ },
1840
+ {
1841
+ firstName: "James",
1842
+ lastInitial: "",
1843
+ textValue: "33",
1844
+ rank: 9,
1845
+ rowNumber: 9,
1846
+ },
1847
+ {
1848
+ firstName: "",
1849
+ lastInitial: "J",
1850
+ textValue: "29",
1851
+ rank: 10,
1852
+ rowNumber: 10,
1853
+ },
1854
+ ];
1855
+ const pointsUsers = [
1856
+ {
1857
+ firstName: "",
1858
+ lastInitial: "",
1859
+ textValue: "82 Points",
1787
1860
  rank: 1,
1788
1861
  rowNumber: 1,
1789
1862
  },
1790
1863
  {
1791
1864
  firstName: "MF",
1792
1865
  lastInitial: "D",
1793
- value: 73,
1866
+ textValue: "73 Points",
1794
1867
  rank: 2,
1795
1868
  rowNumber: 2,
1796
1869
  },
1797
1870
  {
1798
1871
  firstName: "Freddie",
1799
1872
  lastInitial: "G",
1800
- value: 64,
1873
+ textValue: "64 Points",
1801
1874
  rank: 3,
1802
1875
  rowNumber: 3,
1803
1876
  },
1804
1877
  {
1805
1878
  firstName: "Benny",
1806
1879
  lastInitial: "B",
1807
- value: 55,
1880
+ textValue: "55 Points",
1808
1881
  rank: 4,
1809
1882
  rowNumber: 4,
1810
1883
  },
1811
1884
  {
1812
1885
  firstName: "Mos",
1813
1886
  lastInitial: "D",
1814
- value: 46,
1887
+ textValue: "46 Points",
1815
1888
  rank: 5,
1816
1889
  rowNumber: 5,
1817
1890
  },
1818
1891
  {
1819
1892
  firstName: "Joe",
1820
1893
  lastInitial: "S",
1821
- value: 42,
1894
+ textValue: "42 Points",
1822
1895
  rank: 6,
1823
1896
  rowNumber: 6,
1824
1897
  },
1825
1898
  {
1826
1899
  firstName: "Zach",
1827
1900
  lastInitial: "H",
1828
- value: 41,
1901
+ textValue: "41 Points",
1829
1902
  rank: 7,
1830
1903
  rowNumber: 7,
1831
1904
  },
1832
1905
  {
1833
1906
  firstName: "Sarah",
1834
1907
  lastInitial: "S",
1835
- value: 39,
1908
+ textValue: "39 Points",
1836
1909
  rank: 8,
1837
1910
  rowNumber: 8,
1838
1911
  },
1839
1912
  {
1840
1913
  firstName: "James",
1841
1914
  lastInitial: "",
1842
- value: 33,
1915
+ textValue: "33 Points",
1843
1916
  rank: 9,
1844
1917
  rowNumber: 9,
1845
1918
  },
1846
1919
  {
1847
1920
  firstName: "",
1848
1921
  lastInitial: "J",
1849
- value: 29,
1922
+ textValue: "29 Points",
1850
1923
  rank: 10,
1851
1924
  rowNumber: 10,
1852
1925
  },
@@ -1855,7 +1928,7 @@ const defaultStyles$1 = {
1855
1928
  usersheading: "User",
1856
1929
  statsheading: "Referrals",
1857
1930
  rankheading: "Rank",
1858
- anonymousUser: "Anonymous User"
1931
+ anonymousUser: "Anonymous User",
1859
1932
  };
1860
1933
  const defaultElements$1 = {
1861
1934
  empty: (index.h("sqm-empty", { "empty-state-image": "https://res.cloudinary.com/saasquatch/image/upload/v1644360953/squatch-assets/empty_leaderboard2.png", "empty-state-header": "View your rank in the leaderboard", "empty-state-text": "Be the first to refer a friend and reach the top of the leaderboard" })),
@@ -1878,10 +1951,11 @@ const Empty$1 = () => {
1878
1951
  data: {
1879
1952
  rankType: "rowNumber",
1880
1953
  leaderboard: [],
1954
+ rowNumber: 10,
1881
1955
  viewerRank: {
1882
1956
  firstName: "Kutay",
1883
1957
  lastInitial: "C",
1884
- value: 8,
1958
+ textValue: "8",
1885
1959
  rowNumber: 11,
1886
1960
  rank: 23,
1887
1961
  },
@@ -1903,6 +1977,7 @@ const Loading = () => {
1903
1977
  },
1904
1978
  data: {
1905
1979
  rankType: "rowNumber",
1980
+ rowNumber: 10,
1906
1981
  leaderboard: [],
1907
1982
  },
1908
1983
  elements: {
@@ -1922,11 +1997,12 @@ const One = () => {
1922
1997
  },
1923
1998
  data: {
1924
1999
  rankType: "rowNumber",
2000
+ rowNumber: 1,
1925
2001
  leaderboard: [
1926
2002
  {
1927
2003
  firstName: "Viktor",
1928
2004
  lastInitial: "V",
1929
- value: 82,
2005
+ textValue: "82",
1930
2006
  rank: 1,
1931
2007
  rowNumber: 1,
1932
2008
  },
@@ -1934,7 +2010,7 @@ const One = () => {
1934
2010
  viewerRank: {
1935
2011
  firstName: "Viktor",
1936
2012
  lastInitial: "V",
1937
- value: 82,
2013
+ textValue: "82",
1938
2014
  rank: 1,
1939
2015
  rowNumber: 1,
1940
2016
  },
@@ -1956,33 +2032,40 @@ const Five = () => {
1956
2032
  },
1957
2033
  data: {
1958
2034
  rankType: "rowNumber",
2035
+ rowNumber: 5,
1959
2036
  leaderboard: [
1960
2037
  {
1961
2038
  firstName: "Viktor",
1962
2039
  lastInitial: "V",
1963
- value: 82,
2040
+ textValue: "82",
1964
2041
  rank: 1,
1965
2042
  rowNumber: 1,
1966
2043
  },
1967
- { firstName: "MF", lastInitial: "D", value: 73, rank: 2, rowNumber: 2 },
2044
+ {
2045
+ firstName: "MF",
2046
+ lastInitial: "D",
2047
+ textValue: "73",
2048
+ rank: 2,
2049
+ rowNumber: 2,
2050
+ },
1968
2051
  {
1969
2052
  firstName: "Freddie",
1970
2053
  lastInitial: "G",
1971
- value: 64,
2054
+ textValue: "64",
1972
2055
  rank: 3,
1973
2056
  rowNumber: 3,
1974
2057
  },
1975
2058
  {
1976
2059
  firstName: "Benny",
1977
2060
  lastInitial: "B",
1978
- value: 55,
2061
+ textValue: "55",
1979
2062
  rank: 4,
1980
2063
  rowNumber: 4,
1981
2064
  },
1982
2065
  {
1983
2066
  firstName: "Mos",
1984
2067
  lastInitial: "D",
1985
- value: 46,
2068
+ textValue: "46",
1986
2069
  rank: 5,
1987
2070
  rowNumber: 5,
1988
2071
  },
@@ -1990,7 +2073,7 @@ const Five = () => {
1990
2073
  viewerRank: {
1991
2074
  firstName: "Viktor",
1992
2075
  lastInitial: "V",
1993
- value: 82,
2076
+ textValue: "82",
1994
2077
  rank: 1,
1995
2078
  rowNumber: 1,
1996
2079
  },
@@ -2001,12 +2084,13 @@ const Five = () => {
2001
2084
  };
2002
2085
  return index.h(ShadowViewAddon.LeaderboardView, Object.assign({}, props));
2003
2086
  };
2004
- const Ten = () => {
2087
+ const ReferralLeaderboard = () => {
2005
2088
  const props = {
2006
2089
  states: {
2007
2090
  loading: false,
2008
2091
  hasLeaders: true,
2009
2092
  styles: {
2093
+ ...defaultStyles$1,
2010
2094
  rankheading: "Rank",
2011
2095
  usersheading: "User",
2012
2096
  statsheading: "Referrals",
@@ -2016,10 +2100,42 @@ const Ten = () => {
2016
2100
  data: {
2017
2101
  rankType: "rowNumber",
2018
2102
  leaderboard: users,
2103
+ rowNumber: 10,
2019
2104
  viewerRank: {
2020
2105
  firstName: "Viktor",
2021
2106
  lastInitial: "V",
2022
- value: 82,
2107
+ textValue: "82",
2108
+ rank: 1,
2109
+ rowNumber: 1,
2110
+ },
2111
+ },
2112
+ elements: {
2113
+ ...defaultElements$1,
2114
+ },
2115
+ };
2116
+ return index.h(ShadowViewAddon.LeaderboardView, Object.assign({}, props));
2117
+ };
2118
+ const PointsLeaderboard = () => {
2119
+ const props = {
2120
+ states: {
2121
+ loading: false,
2122
+ hasLeaders: true,
2123
+ styles: {
2124
+ ...defaultStyles$1,
2125
+ rankheading: "Rank",
2126
+ usersheading: "User",
2127
+ statsheading: "Points",
2128
+ showRank: false,
2129
+ },
2130
+ },
2131
+ data: {
2132
+ rankType: "rowNumber",
2133
+ leaderboard: pointsUsers,
2134
+ rowNumber: 10,
2135
+ viewerRank: {
2136
+ firstName: "Viktor",
2137
+ lastInitial: "V",
2138
+ textValue: "82 Points",
2023
2139
  rank: 1,
2024
2140
  rowNumber: 1,
2025
2141
  },
@@ -2043,10 +2159,11 @@ const TenWithRank = () => {
2043
2159
  data: {
2044
2160
  rankType: "rowNumber",
2045
2161
  leaderboard: users,
2162
+ rowNumber: 10,
2046
2163
  viewerRank: {
2047
2164
  firstName: "Viktor",
2048
2165
  lastInitial: "V",
2049
- value: 82,
2166
+ textValue: "82",
2050
2167
  rank: 1,
2051
2168
  rowNumber: 1,
2052
2169
  },
@@ -2070,10 +2187,11 @@ const ViewerOutside = () => {
2070
2187
  data: {
2071
2188
  rankType: "rowNumber",
2072
2189
  leaderboard: users,
2190
+ rowNumber: 10,
2073
2191
  viewerRank: {
2074
2192
  firstName: "Kutay",
2075
2193
  lastInitial: "C",
2076
- value: 8,
2194
+ textValue: "8",
2077
2195
  rowNumber: 11,
2078
2196
  rank: 23,
2079
2197
  },
@@ -2097,6 +2215,7 @@ const ViewerAnonymous = () => {
2097
2215
  data: {
2098
2216
  rankType: "rowNumber",
2099
2217
  leaderboard: users,
2218
+ rowNumber: 10,
2100
2219
  viewerRank: null,
2101
2220
  },
2102
2221
  elements: {
@@ -2110,6 +2229,7 @@ const HideViewer = () => {
2110
2229
  states: {
2111
2230
  loading: false,
2112
2231
  hasLeaders: true,
2232
+ rowNumber: 10,
2113
2233
  styles: {
2114
2234
  ...defaultStyles$1,
2115
2235
  showRank: true,
@@ -2119,10 +2239,11 @@ const HideViewer = () => {
2119
2239
  data: {
2120
2240
  rankType: "rowNumber",
2121
2241
  leaderboard: users,
2242
+ rowNumber: 10,
2122
2243
  viewerRank: {
2123
2244
  firstName: "Viktor",
2124
2245
  lastInitial: "V",
2125
- value: 82,
2246
+ textValue: "82",
2126
2247
  rowNumber: 1,
2127
2248
  rank: 1,
2128
2249
  },
@@ -2141,7 +2262,8 @@ const Leaderboard = /*#__PURE__*/Object.freeze({
2141
2262
  Loading: Loading,
2142
2263
  One: One,
2143
2264
  Five: Five,
2144
- Ten: Ten,
2265
+ ReferralLeaderboard: ReferralLeaderboard,
2266
+ PointsLeaderboard: PointsLeaderboard,
2145
2267
  TenWithRank: TenWithRank,
2146
2268
  ViewerOutside: ViewerOutside,
2147
2269
  ViewerAnonymous: ViewerAnonymous,
@@ -2317,8 +2439,13 @@ const Router = /*#__PURE__*/Object.freeze({
2317
2439
  RouterPlayground: RouterPlayground
2318
2440
  });
2319
2441
 
2442
+ const scenario$5 = "@owner:noah\n@author:noah\nFeature: Leaderboard Rank\n\n The leaderboard rank components displays the current users rank on the leaderboard.\n\n @minutiae\n Scenario: Users without a rank are shown a generic message\n Given a user has no rank\n Then the component displays a generic message\n And the message is the string from the prop \"unrankedText\"\n\n @motivating\n Scenario: Users with a rank are shown a message containing their rank\n Given a user has a valid rank\n And the prop \"rankText\" is an ICU message\n Then the ICU message is parsed to include the user's rank\n And the parsed message is displayed to the users\n\n @motivating\n Scenario Outline: Ranks from any of the three standard leaderboards can be displayed\n Given a leaderboard rank component with <leaderboardType>\n And a user has a valid rank\n When they view the leaderboard rank component\n Then they see their rank for <leaderboardType>\n Examples:\n | leaderboardType |\n | topStartedReferrers |\n | topConvertedReferrers |\n | topPointEarners |\n\n @motivating\n Scenario Outline: Leaderboard rank can be filtered with a time interval\n Given a leaderboard rank component with <leaderboardType>\n And it has prop \"interval\" with value \"2021-11-02T07:00:00.000Z/2021-11-07T07:00:00.000Z\"\n When they view the leaderboard rank component\n Then they see their rank for <results> from within \"2021-11-02T07:00:00.000Z/2021-11-07T07:00:00.000Z\"\n Examples:\n | leaderboardType | results |\n | topStartedReferrers | started referrals |\n | topConvertedReferrers | converted referrals |\n | topPointEarners | points earned |\n\n @motivating\n Scenario Outline: Program Context is used by default to filter leaderboard rank\n Given a <leaderboardType> leaderboard rank component loaded with program context for \"my-program\"\n When they view the leaderboard rank component\n Then they see their rank for <leaderboardType> from \"my-program\"\n Examples:\n | leaderboardType |\n | topStartedReferrers |\n | topConvertedReferrers |\n | topPointEarners |\n\n @motivating\n Scenario Outline: Program Id context can be overwritten with a prop\n Given a <leaderboardType> leaderboard rank component has prop \"program-Id\" with value \"my-test-program\"\n When they view the leaderboard rank component\n Then they see their rank for <leaderboardType> from \"my-test-program\"\n Examples:\n | leaderboardType | results |\n | topStartedReferrers | started referrals |\n | topConvertedReferrers | converted referrals |\n | topPointEarners | points earned |\n\n @motivating\n Scenario Outline: Global leaderboards ranks can be displayed by clearing program context\n #This can also be done with a program section in a similar manner\n Given a <leaderboardType> leaderboard rank component has prop \"program-Id\" with value \"\"\n When they view the leaderboard rank component\n Then they see global <results> rank\n Examples:\n | leaderboardType | results |\n | topStartedReferrers | started referrals |\n | topConvertedReferrers | converted referrals |\n | topPointEarners | points earned |\n\n @motivating\n Scenario: Rank calculation is controlled by the \"rankType\" prop\n Given the current user is User C\n And User C has <points>\n And User A has <points>\n And User B has <points>\n And the value of the \"rankType\" prop is <rankType>\n Then the rank of the current user is <rank>\n Examples:\n | user | points | rankType | rank |\n | User A | 5 | rowNumber | 3 |\n | User B | 10 | rowNumber | 1 |\n | User C | 10 | rowNumber | 2 |\n\n | user | points | rankType | rank |\n | User A | 10 | rank | 1 |\n | User B | 10 | rank | 1 |\n | User C | 5 | rank | 3 |\n\n | user | points | rankType | rank |\n | User A | 10 | denseRank | 1 |\n | User B | 10 | denseRank | 1 |\n | User C | 5 | denseRank | 2 |";
2443
+
2320
2444
  const LeaderboardRank_stories = {
2321
2445
  title: "Components/Leaderboard Rank",
2446
+ parameters: {
2447
+ scenario: scenario$5,
2448
+ },
2322
2449
  };
2323
2450
  const First = () => {
2324
2451
  const props = { data: { rank: "1st" } };
@@ -2327,11 +2454,27 @@ const First = () => {
2327
2454
  index.h(sqmLeaderboardRankView.LeaderboardRankView, Object.assign({}, props)),
2328
2455
  " on the leaderboard"));
2329
2456
  };
2457
+ const Second = () => {
2458
+ const props = { data: { rank: "2nd" } };
2459
+ return (index.h("p", null,
2460
+ "Your rank is ",
2461
+ index.h(sqmLeaderboardRankView.LeaderboardRankView, Object.assign({}, props)),
2462
+ " on the leaderboard"));
2463
+ };
2464
+ const Unranked = () => {
2465
+ const props = { data: { rank: "unranked" } };
2466
+ return (index.h("p", null,
2467
+ "You are currently ",
2468
+ index.h(sqmLeaderboardRankView.LeaderboardRankView, Object.assign({}, props)),
2469
+ ", refer a friend!"));
2470
+ };
2330
2471
 
2331
2472
  const LeaderboardRank = /*#__PURE__*/Object.freeze({
2332
2473
  __proto__: null,
2333
2474
  'default': LeaderboardRank_stories,
2334
- First: First
2475
+ First: First,
2476
+ Second: Second,
2477
+ Unranked: Unranked
2335
2478
  });
2336
2479
 
2337
2480
  function setupGraphQL() {
@@ -2941,6 +3084,62 @@ const TopStartedReferrers = createHookStory(() => {
2941
3084
  }),
2942
3085
  ];
2943
3086
  });
3087
+ const topPointEarners = createHookStory(() => {
3088
+ setupGraphQL$5();
3089
+ return [
3090
+ View$1({
3091
+ leaderboardType: "topPointEarners",
3092
+ statsheading: "Points",
3093
+ usersheading: "Top Earners",
3094
+ }),
3095
+ View$1({
3096
+ leaderboardType: "topPointEarners",
3097
+ rankType: "rank",
3098
+ statsheading: "Points",
3099
+ usersheading: "Top Earners",
3100
+ }),
3101
+ View$1({
3102
+ leaderboardType: "topPointEarners",
3103
+ rankType: "denseRank",
3104
+ statsheading: "Points",
3105
+ usersheading: "Top Earners",
3106
+ }),
3107
+ ];
3108
+ });
3109
+ const globalLeaderboards = createHookStory(() => {
3110
+ setupGraphQL$5();
3111
+ return [
3112
+ View$1({
3113
+ leaderboardType: "topPointEarners",
3114
+ rankType: "rank",
3115
+ statsheading: "Points",
3116
+ usersheading: "Top Earners",
3117
+ programId: "",
3118
+ }),
3119
+ View$1({
3120
+ leaderboardType: "topStartedReferrers",
3121
+ rankType: "rank",
3122
+ statsheading: "Referrals",
3123
+ programId: "",
3124
+ }),
3125
+ View$1({
3126
+ leaderboardType: "topConvertedReferrers",
3127
+ rankType: "rank",
3128
+ statsheading: "Referrals",
3129
+ programId: "",
3130
+ }),
3131
+ ];
3132
+ });
3133
+ const FiveResults = createHookStory(() => {
3134
+ setupGraphQL$5();
3135
+ return [
3136
+ View$1({
3137
+ leaderboardType: "topStartedReferrers",
3138
+ maxRows: 5,
3139
+ statsheading: "Referrals",
3140
+ }),
3141
+ ];
3142
+ });
2944
3143
  const EmptyLeaderboard = createHookStory(() => {
2945
3144
  setupOtherGraphQL();
2946
3145
  return [
@@ -2993,6 +3192,9 @@ const UseLeaderboard = /*#__PURE__*/Object.freeze({
2993
3192
  'default': UseLeaderboard_stories,
2994
3193
  TopConvertedReferrers: TopConvertedReferrers,
2995
3194
  TopStartedReferrers: TopStartedReferrers,
3195
+ topPointEarners: topPointEarners,
3196
+ globalLeaderboards: globalLeaderboards,
3197
+ FiveResults: FiveResults,
2996
3198
  EmptyLeaderboard: EmptyLeaderboard,
2997
3199
  DemoHook: DemoHook,
2998
3200
  DemoHookEmpty: DemoHookEmpty
@@ -3964,12 +4166,12 @@ const PortalRegister = /*#__PURE__*/Object.freeze({
3964
4166
  TermsAndConditions: TermsAndConditions
3965
4167
  });
3966
4168
 
3967
- const scenario$5 = "@author:derek\n@owner:ian\nFeature: Forgot Password\n\n @motivating\n Scenario: Users can request to reset their password\n Given a user enters their email address\n And that email address is linked to a previously created account\n When they click \"Reset Password\"\n Then the button enters a loading state\n When the password reset email is sent\n Then a confirmation banner is shown stating a password reset email was sent\n\n @motivating\n Scenario: Users are notified if sending their password reset email fails\n Given a user enters their email address\n And that email address is linked to a previously created account\n When they click \"Reset Password\"\n Then the button enters a loading state\n When the password reset email fails to send\n Then the user does not receive a password reset email\n And an error banner is shown stating that they should try again\n\n @motivating\n @landmine\n Scenario: If the input email is not associated to an account a success banner is shown but an email is not be sent\n Given the user entered an email address that is not associated to an accoun\n When they click \"Reset Password\"\n Then the button enters a loading state\n But no email is sent\n And a success banner is shown stating a password reset email was sent if the given email was associated to an account\n\n @motivating\n Scenario: Users can resend password reset email\n Given a user had previously requested to reset their password\n When they enter their email address\n And that email address is linked to a previously created account\n And they click \"Reset Password\"\n Then the user receives a second password reset email\n And a success banner is shown stating that their email was sent\n\n @motivating\n Scenario Outline: The email link can be configured to redirect users to a specific base path but defaults to \"/resetPassword\"\n Given a user viewing the password reset component\n And the component <mayHave> \"redirect-path\" with <value>\n When they request a password reset email\n And they click the link in the email\n Then they are redirected to <redirectPath>\n Examples:\n | mayHave | value | redirectPath |\n | doesn't have | N/A | /resetPassword |\n | has | /resetMyPassword | /resetMyPassword |\n\n @minutae\n Scenario Outline: Navigation back to the login page can be customized but defaults to \"/login\"\n Given a user viewing the password reset component\n And the component <mayHave> \"login-path\" with <value>\n Then they see a \"Sign In\" text button\n When they click \"Sign In\"\n Then they are redirected to <redirectPath>\n Examples:\n | mayHave | value | redirectPath |\n | doesn't have | N/A | /login |\n | has | /signin | /signin |";
4169
+ const scenario$6 = "@author:derek\n@owner:ian\nFeature: Forgot Password\n\n @motivating\n Scenario: Users can request to reset their password\n Given a user enters their email address\n And that email address is linked to a previously created account\n When they click \"Reset Password\"\n Then the button enters a loading state\n When the password reset email is sent\n Then a confirmation banner is shown stating a password reset email was sent\n\n @motivating\n Scenario: Users are notified if sending their password reset email fails\n Given a user enters their email address\n And that email address is linked to a previously created account\n When they click \"Reset Password\"\n Then the button enters a loading state\n When the password reset email fails to send\n Then the user does not receive a password reset email\n And an error banner is shown stating that they should try again\n\n @motivating\n @landmine\n Scenario: If the input email is not associated to an account a success banner is shown but an email is not be sent\n Given the user entered an email address that is not associated to an accoun\n When they click \"Reset Password\"\n Then the button enters a loading state\n But no email is sent\n And a success banner is shown stating a password reset email was sent if the given email was associated to an account\n\n @motivating\n Scenario: Users can resend password reset email\n Given a user had previously requested to reset their password\n When they enter their email address\n And that email address is linked to a previously created account\n And they click \"Reset Password\"\n Then the user receives a second password reset email\n And a success banner is shown stating that their email was sent\n\n @motivating\n Scenario Outline: The email link can be configured to redirect users to a specific base path but defaults to \"/resetPassword\"\n Given a user viewing the password reset component\n And the component <mayHave> \"redirect-path\" with <value>\n When they request a password reset email\n And they click the link in the email\n Then they are redirected to <redirectPath>\n Examples:\n | mayHave | value | redirectPath |\n | doesn't have | N/A | /resetPassword |\n | has | /resetMyPassword | /resetMyPassword |\n\n @minutae\n Scenario Outline: Navigation back to the login page can be customized but defaults to \"/login\"\n Given a user viewing the password reset component\n And the component <mayHave> \"login-path\" with <value>\n Then they see a \"Sign In\" text button\n When they click \"Sign In\"\n Then they are redirected to <redirectPath>\n Examples:\n | mayHave | value | redirectPath |\n | doesn't have | N/A | /login |\n | has | /signin | /signin |";
3968
4170
 
3969
4171
  const PortalForgotPassword_stories = {
3970
4172
  title: "Components/Portal Forgot Password",
3971
4173
  parameters: {
3972
- scenario: scenario$5,
4174
+ scenario: scenario$6,
3973
4175
  },
3974
4176
  };
3975
4177
  const defaultProps$4 = {
@@ -4046,12 +4248,12 @@ const PortalForgotPassword = /*#__PURE__*/Object.freeze({
4046
4248
  ForgotPasswordSuccess: ForgotPasswordSuccess
4047
4249
  });
4048
4250
 
4049
- const scenario$6 = "@author:derek\n@owner:ian\nFeature: Email Verification\n\n @minutae\n Scenario: User's redirected from registration can re-send their verification email\n Given a user has registered\n And they have been sent a verification email\n When they are redirected to the email verification page\n Then a message is displayed\n And it reflects that a email has been sent to their email\n But they can still re-send the email\n When they click to \"Resend-Email\"\n Then they receive a verification email\n\n @motivating\n Scenario: Users are notified if sending the email verification message fails\n Given a user viewing the email verification component\n And they have an email stored in session data from registration\n When they click to \"Resend-Email\"\n Then the button enters a loading state\n When an error occurs trying to send the verification email\n Then the user does not receive a verification email\n And an error banner is shown stating that they should try again\n\n @motivating\n Scenario: Users are notified if sending the email verification message succeeds\n Given a user viewing the email verification component\n And they have an email stored in session data from registration\n When they click to \"Resend-Email\"\n Then the button enters a loading state\n When the email verification message sends\n Then the user receives a verification email\n And a success banner is shown stating that their email was resent\n\n @motivating\n Scenario Outline: The email link can be configured to redirect users to a specific base path but defaults to \"/verifyEmail\"\n Given a user viewing the email verification component\n And they have an email stored in session data from registration\n And the component <mayHave> \"redirect-path\" with <value>\n When they resend their verification email\n And they click the link in the email\n Then they are redirected to <redirectPath>\n Examples:\n | mayHave | value | redirectPath |\n | doesn't have | N/A | /verifyEmail |\n | has | /verifyMyEmail | /verifyMyEmail |";
4251
+ const scenario$7 = "@author:derek\n@owner:ian\nFeature: Email Verification\n\n @minutae\n Scenario: User's redirected from registration can re-send their verification email\n Given a user has registered\n And they have been sent a verification email\n When they are redirected to the email verification page\n Then a message is displayed\n And it reflects that a email has been sent to their email\n But they can still re-send the email\n When they click to \"Resend-Email\"\n Then they receive a verification email\n\n @motivating\n Scenario: Users are notified if sending the email verification message fails\n Given a user viewing the email verification component\n And they have an email stored in session data from registration\n When they click to \"Resend-Email\"\n Then the button enters a loading state\n When an error occurs trying to send the verification email\n Then the user does not receive a verification email\n And an error banner is shown stating that they should try again\n\n @motivating\n Scenario: Users are notified if sending the email verification message succeeds\n Given a user viewing the email verification component\n And they have an email stored in session data from registration\n When they click to \"Resend-Email\"\n Then the button enters a loading state\n When the email verification message sends\n Then the user receives a verification email\n And a success banner is shown stating that their email was resent\n\n @motivating\n Scenario Outline: The email link can be configured to redirect users to a specific base path but defaults to \"/verifyEmail\"\n Given a user viewing the email verification component\n And they have an email stored in session data from registration\n And the component <mayHave> \"redirect-path\" with <value>\n When they resend their verification email\n And they click the link in the email\n Then they are redirected to <redirectPath>\n Examples:\n | mayHave | value | redirectPath |\n | doesn't have | N/A | /verifyEmail |\n | has | /verifyMyEmail | /verifyMyEmail |";
4050
4252
 
4051
4253
  const PortalEmailVerification_stories = {
4052
4254
  title: "Components/Portal Email Verification",
4053
4255
  parameters: {
4054
- scenario: scenario$6,
4256
+ scenario: scenario$7,
4055
4257
  },
4056
4258
  };
4057
4259
  const defaultProps$5 = {
@@ -4132,12 +4334,12 @@ const PortalEmailVerification = /*#__PURE__*/Object.freeze({
4132
4334
  EmailVerificationSuccess: EmailVerificationSuccess
4133
4335
  });
4134
4336
 
4135
- const scenario$7 = "@author:derek\n@owner:ian\nFeature: Reset Password\n\n Background: A user in on the password reset page\n Given a user who has been redirected to the password reset page\n\n @motivating\n Scenario: Users can reset their password\n Given a user has a valid oob code as a url query parameter\n When they enter their password twice\n And they click \"Update\"\n Then their password is updated\n And a banner with a success message is displayed\n And they can log in with their new password\n\n @motivating\n Scenario Outline: Users cannot reset their password with an invalid or missing oob code\n Given a user has a <oobCode> as a url query parameter\n And the component <mayHave> \"failed-page\" with <value>\n Then they see an error message saying that their password reset code is invalid/expired\n When they click \"Continue\"\n Then they are redirected to <redirectPath>\n Examples:\n | oobCode | mayHave | value | redirectPath |\n | invalid oob code | doesn't have | N/A | / |\n | non existant oob code | doesn't have | N/A | / |\n | invalid oob code | has | /login | /login |\n | non existant oob code | has | /login | /login |\n\n @motivating\n Scenario: Users must enter the same password twice to successfully reset their password\n Given a user has been redirected to the password reset page\n And they have a valid oob code as a url query parameter\n When they enter two different passwords into the password reset form\n And they click \"Update\"\n Then their password is not be reset\n And an error banner stating the input passwords must match appears\n And their password is not be reset\n When they enter the same password twice\n And they click \"Update\"\n Then a banner appears with a success message\n And they can log in with their new password\n\n @motivating\n Scenario: Users are redirected to \"/\" by default\n Given the component does not have prop \"nextPage\"\n And the users url does not contain a \"nextPage\" query parameter\n And a user has entered their password twice\n When they click \"Update\"\n Then their password is updated\n And they are redirected to \"/\"\n\n @motivating\n Scenario: Custom redirection can be configured\n Given the component has prop \"nextPage\" with value \"/activity\"\n And the users url does not contain a \"nextPage\" query parameter\n And a user has entered their password twice\n When they click \"Update\"\n Then their password is updated\n And they are redirected to \"/activity\"\n\n @motivating\n Scenario Outline: Users are redirected to the value of the nextPage url parameter as if it were a relative path\n Given the component is loaded at <currentUrl>\n When they click \"Update\"\n Then their password is updated\n And they are redirected to <url>\n Examples:\n | currentUrl | url |\n | https://www.example.com?nextPage=./activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=/activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=www.google.com | https://www.example.com/www.google.com |\n | https://www.example.com?nextPage=//foo.com | https://www.example.com/ |\n | https://www.example.com?nextPage=https://malicious.example.com | https://www.example.com/ |\n | http://www.example.com/nest/page?oob=123&other&nextPage=activity#heading-1 | http://www.example.com/activity |\n | https://www.example.com?nextPage=activity?foo=bar | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar#hash | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar%23hash | https://www.example.com/activity?foo=bar#hash |\n | https://www.example.com:1337?nextPage=activity | https://www.example.com:1337/activity |\n | http://1.1.1.1:1111?nextPage=activity | http://1.1.1.1:1111/activity |\n\n @landmine\n Scenario Outline: Username and password are not persisted on redirects\n Given the component is loaded at <currentUrl>\n When they click \"Update\"\n Then their password is updated\n And they are redirected to <url>\n Examples:\n | currentUrl | url |\n | https://user:pass@www.example.com:444?nextPage=activity | https://www.example.com:444/activity |";
4337
+ const scenario$8 = "@author:derek\n@owner:ian\nFeature: Reset Password\n\n Background: A user in on the password reset page\n Given a user who has been redirected to the password reset page\n\n @motivating\n Scenario: Users can reset their password\n Given a user has a valid oob code as a url query parameter\n When they enter their password twice\n And they click \"Update\"\n Then their password is updated\n And a banner with a success message is displayed\n And they can log in with their new password\n\n @motivating\n Scenario Outline: Users cannot reset their password with an invalid or missing oob code\n Given a user has a <oobCode> as a url query parameter\n And the component <mayHave> \"failed-page\" with <value>\n Then they see an error message saying that their password reset code is invalid/expired\n When they click \"Continue\"\n Then they are redirected to <redirectPath>\n Examples:\n | oobCode | mayHave | value | redirectPath |\n | invalid oob code | doesn't have | N/A | / |\n | non existant oob code | doesn't have | N/A | / |\n | invalid oob code | has | /login | /login |\n | non existant oob code | has | /login | /login |\n\n @motivating\n Scenario: Users must enter the same password twice to successfully reset their password\n Given a user has been redirected to the password reset page\n And they have a valid oob code as a url query parameter\n When they enter two different passwords into the password reset form\n And they click \"Update\"\n Then their password is not be reset\n And an error banner stating the input passwords must match appears\n And their password is not be reset\n When they enter the same password twice\n And they click \"Update\"\n Then a banner appears with a success message\n And they can log in with their new password\n\n @motivating\n Scenario: Users are redirected to \"/\" by default\n Given the component does not have prop \"nextPage\"\n And the users url does not contain a \"nextPage\" query parameter\n And a user has entered their password twice\n When they click \"Update\"\n Then their password is updated\n And they are redirected to \"/\"\n\n @motivating\n Scenario: Custom redirection can be configured\n Given the component has prop \"nextPage\" with value \"/activity\"\n And the users url does not contain a \"nextPage\" query parameter\n And a user has entered their password twice\n When they click \"Update\"\n Then their password is updated\n And they are redirected to \"/activity\"\n\n @motivating\n Scenario Outline: Users are redirected to the value of the nextPage url parameter as if it were a relative path\n Given the component is loaded at <currentUrl>\n When they click \"Update\"\n Then their password is updated\n And they are redirected to <url>\n Examples:\n | currentUrl | url |\n | https://www.example.com?nextPage=./activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=/activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=www.google.com | https://www.example.com/www.google.com |\n | https://www.example.com?nextPage=//foo.com | https://www.example.com/ |\n | https://www.example.com?nextPage=https://malicious.example.com | https://www.example.com/ |\n | http://www.example.com/nest/page?oob=123&other&nextPage=activity#heading-1 | http://www.example.com/activity |\n | https://www.example.com?nextPage=activity?foo=bar | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar#hash | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar%23hash | https://www.example.com/activity?foo=bar#hash |\n | https://www.example.com:1337?nextPage=activity | https://www.example.com:1337/activity |\n | http://1.1.1.1:1111?nextPage=activity | http://1.1.1.1:1111/activity |\n\n @landmine\n Scenario Outline: Username and password are not persisted on redirects\n Given the component is loaded at <currentUrl>\n When they click \"Update\"\n Then their password is updated\n And they are redirected to <url>\n Examples:\n | currentUrl | url |\n | https://user:pass@www.example.com:444?nextPage=activity | https://www.example.com:444/activity |";
4136
4338
 
4137
4339
  const PortalResetPassword_stories = {
4138
4340
  title: "Components/Portal Reset Password",
4139
4341
  parameters: {
4140
- scenario: scenario$7,
4342
+ scenario: scenario$8,
4141
4343
  },
4142
4344
  };
4143
4345
  const defaultProps$6 = {
@@ -4296,12 +4498,12 @@ const PortalResetPassword = /*#__PURE__*/Object.freeze({
4296
4498
  CodeValidating: CodeValidating
4297
4499
  });
4298
4500
 
4299
- const scenario$8 = "@author:derek\n@owner:ian\nFeature: Verify Email\n\n Background: A user is on the email verification page\n Given a user who has been redirected to the email verification page\n\n @motivating\n Scenario: Verifying your email takes you to the portal login page\n Given a user has a valid oob code as a url query parameter\n When they click \"Verify Email\"\n Then the button enters a loading state\n When their email is validated\n Then a button that says \"Continue\" appears\n When they click \"Continue\"\n Then they are redirected to login\n\n @motivating\n Scenario: Users are automatically redirected if they dont click \"Continue\"\n Given a user has a valid oob code as a url query parameter\n When they click \"Verify Email\"\n Then the button enters a loading state\n When their email is validated\n Then a button that says \"Continue\" appears\n When they wait 5 seconds\n Then they are redirected to login\n\n @motivating\n Scenario: Users are notified if verifying their email has failed\n Given a user has a valid oob code as a url query parameter\n When they click \"Verify Email\"\n Then the button enters a loading state\n When their email fails to be validated\n Then an banner is shown stating that an error occured\n\n @motivating\n Scenario Outline: Users cannot verify their email with an invalid or missing oob code\n Given a user has a <oobCode> as a url query parameter\n And the component <mayHave> \"failed-page\" with <value>\n Then they see an error message saying that their verification code is invalid/expired\n When they click \"Continue\"\n Then they are redirected to <redirectPath>\n Examples:\n | oobCode | mayHave | value | redirectPath |\n | invalid oob code | doesn't have | N/A | / |\n | non existant oob code | doesn't have | N/A | / |\n | invalid oob code | has | /login | /login |\n | non existant oob code | has | /login | /login |\n\n @motivating\n Scenario: Users are redirected to \"/\" by default\n Given the component does not have prop \"nextPage\"\n And the users url does not contain a \"nextPage\" query parameter\n And a user has verified their email\n When they click \"Continue\"\n Then they are redirected to \"/\"\n\n @motivating\n Scenario: Custom redirection can be configured\n Given the component has prop \"nextPage\" with value \"/activity\"\n And the users url does not contain a \"nextPage\" query parameter\n And a user has verified their email\n When they click \"Continue\"\n Then they are redirected to \"/activity\"\n\n @motivating\n Scenario Outline: Users are redirected to the value of the nextPage url parameter if it exists\n Given the component <mayHave> prop \"nextPage\" with <nextPageValue>\n And the users url contains a \"nextPage\" query paramater with <nextPageParamValue>\n And the user has verified their email\n When they click \"Continue\"\n Then they are redirected to <nextPageParamValue>\n Examples:\n | mayHave | nextPageValue | nextPageParamValue |\n | has | /dashboard | /activity |\n | does not have | N/A | /activity |\n\n @motivating\n Scenario Outline: Users are redirected to the value of the nextPage url parameter as if it were a relative path\n Given the component is loaded at <currentUrl>\n And the user has verified their email\n When they click \"Continue\"\n And they are redirected to <url>\n Examples:\n | currentUrl | url |\n | https://www.example.com?nextPage=./activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=/activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=www.google.com | https://www.example.com/www.google.com |\n | https://www.example.com?nextPage=//foo.com | https://www.example.com/ |\n | https://www.example.com?nextPage=https://malicious.example.com | https://www.example.com/ |\n | http://www.example.com/nest/page?oob=123&other&nextPage=activity#heading-1 | http://www.example.com/activity |\n | https://www.example.com?nextPage=activity?foo=bar | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar#hash | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar%23hash | https://www.example.com/activity?foo=bar#hash |\n | https://www.example.com:1337?nextPage=activity | https://www.example.com:1337/activity |\n | http://1.1.1.1:1111?nextPage=activity | http://1.1.1.1:1111/activity |\n\n @landmine\n Scenario Outline: Username and password are not persisted on redirects\n Given the component is loaded at <currentUrl>\n And the user has verified their email\n When they click \"Continue\"\n And they are redirected to <url>\n Examples:\n | currentUrl | url |\n | https://user:pass@www.example.com:444?nextPage=activity | https://www.example.com:444/activity |";
4501
+ const scenario$9 = "@author:derek\n@owner:ian\nFeature: Verify Email\n\n Background: A user is on the email verification page\n Given a user who has been redirected to the email verification page\n\n @motivating\n Scenario: Verifying your email takes you to the portal login page\n Given a user has a valid oob code as a url query parameter\n When they click \"Verify Email\"\n Then the button enters a loading state\n When their email is validated\n Then a button that says \"Continue\" appears\n When they click \"Continue\"\n Then they are redirected to login\n\n @motivating\n Scenario: Users are automatically redirected if they dont click \"Continue\"\n Given a user has a valid oob code as a url query parameter\n When they click \"Verify Email\"\n Then the button enters a loading state\n When their email is validated\n Then a button that says \"Continue\" appears\n When they wait 5 seconds\n Then they are redirected to login\n\n @motivating\n Scenario: Users are notified if verifying their email has failed\n Given a user has a valid oob code as a url query parameter\n When they click \"Verify Email\"\n Then the button enters a loading state\n When their email fails to be validated\n Then an banner is shown stating that an error occured\n\n @motivating\n Scenario Outline: Users cannot verify their email with an invalid or missing oob code\n Given a user has a <oobCode> as a url query parameter\n And the component <mayHave> \"failed-page\" with <value>\n Then they see an error message saying that their verification code is invalid/expired\n When they click \"Continue\"\n Then they are redirected to <redirectPath>\n Examples:\n | oobCode | mayHave | value | redirectPath |\n | invalid oob code | doesn't have | N/A | / |\n | non existant oob code | doesn't have | N/A | / |\n | invalid oob code | has | /login | /login |\n | non existant oob code | has | /login | /login |\n\n @motivating\n Scenario: Users are redirected to \"/\" by default\n Given the component does not have prop \"nextPage\"\n And the users url does not contain a \"nextPage\" query parameter\n And a user has verified their email\n When they click \"Continue\"\n Then they are redirected to \"/\"\n\n @motivating\n Scenario: Custom redirection can be configured\n Given the component has prop \"nextPage\" with value \"/activity\"\n And the users url does not contain a \"nextPage\" query parameter\n And a user has verified their email\n When they click \"Continue\"\n Then they are redirected to \"/activity\"\n\n @motivating\n Scenario Outline: Users are redirected to the value of the nextPage url parameter if it exists\n Given the component <mayHave> prop \"nextPage\" with <nextPageValue>\n And the users url contains a \"nextPage\" query paramater with <nextPageParamValue>\n And the user has verified their email\n When they click \"Continue\"\n Then they are redirected to <nextPageParamValue>\n Examples:\n | mayHave | nextPageValue | nextPageParamValue |\n | has | /dashboard | /activity |\n | does not have | N/A | /activity |\n\n @motivating\n Scenario Outline: Users are redirected to the value of the nextPage url parameter as if it were a relative path\n Given the component is loaded at <currentUrl>\n And the user has verified their email\n When they click \"Continue\"\n And they are redirected to <url>\n Examples:\n | currentUrl | url |\n | https://www.example.com?nextPage=./activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=/activity | https://www.example.com/activity |\n | https://www.example.com?nextPage=www.google.com | https://www.example.com/www.google.com |\n | https://www.example.com?nextPage=//foo.com | https://www.example.com/ |\n | https://www.example.com?nextPage=https://malicious.example.com | https://www.example.com/ |\n | http://www.example.com/nest/page?oob=123&other&nextPage=activity#heading-1 | http://www.example.com/activity |\n | https://www.example.com?nextPage=activity?foo=bar | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar#hash | https://www.example.com/activity?foo=bar |\n | https://www.example.com?nextPage=%2Factivity%3Ffoo%3Dbar%23hash | https://www.example.com/activity?foo=bar#hash |\n | https://www.example.com:1337?nextPage=activity | https://www.example.com:1337/activity |\n | http://1.1.1.1:1111?nextPage=activity | http://1.1.1.1:1111/activity |\n\n @landmine\n Scenario Outline: Username and password are not persisted on redirects\n Given the component is loaded at <currentUrl>\n And the user has verified their email\n When they click \"Continue\"\n And they are redirected to <url>\n Examples:\n | currentUrl | url |\n | https://user:pass@www.example.com:444?nextPage=activity | https://www.example.com:444/activity |";
4300
4502
 
4301
4503
  const PortalVerifyEmail_stories = {
4302
4504
  title: "Components/Portal Verify Email",
4303
4505
  parameters: {
4304
- scenario: scenario$8,
4506
+ scenario: scenario$9,
4305
4507
  },
4306
4508
  };
4307
4509
  const errorProps$5 = {
@@ -4468,12 +4670,12 @@ const DividedLayout = /*#__PURE__*/Object.freeze({
4468
4670
  ColumnCustomDivider: ColumnCustomDivider
4469
4671
  });
4470
4672
 
4471
- const scenario$9 = "Feature: Change Password\n\n @motivating\n Scenario: Users can change their password\n Given a user has registered for the portal\n And they have a password\n When they navigate to the edit profile page\n And click \"Change your password...\"\n Then a popup will appear\n When they enter their new password\n And confirm it\n And click \"Change Password\"\n Then they will see a success banner stating that the change was successful\n When they logout\n And try to login\n Then they will not be able to login with their old password\n But they will be able to login with their new password\n\n @motivating\n Scenario: Users must confirm their password change\n Given a user has registered for the portal\n When they navigate to the edit profile page\n And click \"Change your password...\"\n Then a popup will appear\n When they enter their new password\n But they enter a different password to confirm\n And click \"Change Password\"\n Then they will see an error banner stating that the passwords didnt match\n When they logout\n And try to login\n Then they will be able to login with their existing password\n\n @motivating\n Scenario: Users must enter a new password and confirm it to change their password\n Given a user has registered for the portal\n When they navigate to the edit profile page\n And click \"Change your password...\"\n Then a popup will appear\n When they click \"Change password\"\n Then a validation error will appear for the new password field\n And their password will not be changed\n When they enter a new password\n And they click \"Change password\"\n Then a validation error will appear for the confirm new password field\n And their password will not be changed\n\n @motivating\n Scenario: An error banner will be displayed if the password change fails\n Given a user has registered for the portal\n When they navigate to the edit profile page\n And click \"Change your password...\"\n When they enter their new password\n And confirm it\n And click \"Change Password\"\n But the change fails\n Then they will see an error banner stating that the change failed\n When they logout\n And try to login\n Then they will be able to login with their existing password";
4673
+ const scenario$a = "Feature: Change Password\n\n @motivating\n Scenario: Users can change their password\n Given a user has registered for the portal\n And they have a password\n When they navigate to the edit profile page\n And click \"Change your password...\"\n Then a popup will appear\n When they enter their new password\n And confirm it\n And click \"Change Password\"\n Then they will see a success banner stating that the change was successful\n When they logout\n And try to login\n Then they will not be able to login with their old password\n But they will be able to login with their new password\n\n @motivating\n Scenario: Users must confirm their password change\n Given a user has registered for the portal\n When they navigate to the edit profile page\n And click \"Change your password...\"\n Then a popup will appear\n When they enter their new password\n But they enter a different password to confirm\n And click \"Change Password\"\n Then they will see an error banner stating that the passwords didnt match\n When they logout\n And try to login\n Then they will be able to login with their existing password\n\n @motivating\n Scenario: Users must enter a new password and confirm it to change their password\n Given a user has registered for the portal\n When they navigate to the edit profile page\n And click \"Change your password...\"\n Then a popup will appear\n When they click \"Change password\"\n Then a validation error will appear for the new password field\n And their password will not be changed\n When they enter a new password\n And they click \"Change password\"\n Then a validation error will appear for the confirm new password field\n And their password will not be changed\n\n @motivating\n Scenario: An error banner will be displayed if the password change fails\n Given a user has registered for the portal\n When they navigate to the edit profile page\n And click \"Change your password...\"\n When they enter their new password\n And confirm it\n And click \"Change Password\"\n But the change fails\n Then they will see an error banner stating that the change failed\n When they logout\n And try to login\n Then they will be able to login with their existing password";
4472
4674
 
4473
4675
  const ChangePassword_stories = {
4474
4676
  title: "Components/Change Password",
4475
4677
  parameters: {
4476
- scenario: scenario$9,
4678
+ scenario: scenario$a,
4477
4679
  },
4478
4680
  };
4479
4681
  const defaultProps$7 = {
@@ -4873,11 +5075,11 @@ const status = "@author:noah\n@owner:noah\nFeature: Referral Table Status Column
4873
5075
 
4874
5076
  const user = "@author:noah\n@owner:noah\nFeature: Referral Table User Column\n\n Shows the user of each referral\n\n Background:\n Given the user column is included in the referral table\n\n @motivating\n @ui\n Scenario: The title of the date column is configurable\n Given the \"column-title\" prop is set to \"My column title\"\n Then the date column is shown with \"My column title\"\n\n @motivating\n Scenario: The first and last name of the other user in the referral is displayed for each referral\n Given at least one referral exists\n Then for each referral where the other user's name is available their first and last name is displayed\n\n @motivating\n Scenario: Deleted users are displayed with a fallback name\n Given a referral exists where the other user was deleted\n Then in place of the name the text from the prop \"deleted-user\" is used\n\n @motivating\n Scenario: Anonymous users are displayed with a fallback name\n Given a referral exists where the other user was anonymous\n Then in place of the name the text from the prop \"anonymous-user\" is used";
4875
5077
 
4876
- const scenario$a = column + date + reward + status + user;
5078
+ const scenario$b = column + date + reward + status + user;
4877
5079
  const ReferralTableRewardsCell_stories = {
4878
5080
  title: "Components/Referral Table Rewards Cell",
4879
5081
  parameters: {
4880
- scenario: scenario$a,
5082
+ scenario: scenario$b,
4881
5083
  },
4882
5084
  };
4883
5085
  const baseReward = {
@@ -5121,12 +5323,12 @@ const ReferralTableRewardsCell = /*#__PURE__*/Object.freeze({
5121
5323
  tenRewardsCell: tenRewardsCell
5122
5324
  });
5123
5325
 
5124
- const scenario$b = "@owner:sam\n@author:sam\nFeature: Referral Table\n\n The Referral table component shows users a list of their referrals. The referral table it's self can be customized\n with a collection of columns.\n\n @motivating\n @ui\n Scenario: The empty state is shown if there are no referrals\n Given a user with no referrals\n When they view the referral table\n Then no referrals are displayed\n And they see an image with a user icon\n And \"View your referral details\" in bold\n And \"Track the status of your referrals and rewards earned by referring friends\" below the bolded text\n And the pagination buttons are disabled\n\n @motivating\n @ui\n Scenario: The empty state image and text are customizable\n Given the referral table has 'sqm-empty' as a child with the following props\n | prop | value |\n | empty-state-imgage | https://res.cloudinary.com/saasquatch/image/upload/v1634255445/squatch-assets/Copy_of_saasquatch-logo-tree-large-horizontal.png |\n | empty-state-header | View your referral history |\n | empty-state-text | See your previous referrals and what you earned! |\n And a user with no referrals\n When they view the referral table\n Then they see no referrals\n And they see the SaaSquatch logo\n And \"View your referral history\" in bold\n And \"See your previous referrals and what you earned!\" below the bolded text\n\n @minutae\n @ui\n Scenario: A custom empty state can be provided\n Given a user with no referrals\n And a custom empty state has been supplied in the \"empty\" slot\n When they view the referral table\n Then they see the custom empty state\n\n @motivating\n @ui\n Scenario: The loading state is shown while referrals are loading\n Given the table is loading\n Then the loading state is shown in the table\n And a custom loading state can be supplied in the \"loading\" slot\n And the pagination buttons are disabled\n\n @motivating\n @ui\n Scenario Outline: The table becomes paginated when the number of referrals exceeds the per page limit\n Given the user has <number of referrals>\n And the table is configured to show <page limit> referrals per page\n Then the table will have <number of pages> page(s)\n And pagination buttons will allow users to navigate between pages\n And the pagination button to go to the next page is disabled on the last page of referrals\n And the pagination button to go to the previous page is disabled on the first page of referrals\n Examples:\n | number of referrals | page limit | number of pages |\n | 0 | 4 | 1 |\n | 1 | 4 | 1 |\n | 3 | 4 | 1 |\n | 5 | 4 | 2 |\n | 42 | 4 | 11 |\n\n @motivating\n @ui\n Scenario: The table converts to a card view on tablet and mobile window sizes\n Given a user with referrals\n When they view the table\n And their window size is smaller than \"799px\"\n Then referrals are displayed as cards\n And they are in two columns\n When their window size is smaller than \"599px\"\n Then the referrals are displayed as cards in a singular column\n\n @motivating\n @ui\n Scenario: Table and Mobile beakpoints can be configured\n Given the referral table has been configured with the following props\n | prop | value |\n | smBreakpoint | 599 |\n | mdBreakpoint | 799 |\n And a user with referrals\n When they view the table\n And their window size is smaller than \"799px\"\n Then referrals are displayed as cards\n And they are in two columns\n When their window size is smaller than \"599px\"\n Then the referrals are displayed as cards in a singular column\n\n @motivating\n @ui\n Scenario Outline: By default the first column heading is hidden in mobile, but others can be hidden\n Given a referral table with 4 columns\n And prop \"hidden-columns\" with <hideColumnValue>\n And a user with referrals\n When they view the referral table\n And their window size is below the tablet breakpoint\n Then referral cards are displayed\n And the titles of <columnsArehidden> within the card\n Examples:\n | hideColumnValue | columnsArehidden |\n | | the first column |\n | 0,1,2 | the first, second and third columns |\n | 3 | the fourth column |\n\n @motivating\n Scenario: The use who referred the current user can be shown in the table\n Given the table is configured with <showReferrer> set to true\n And the current user was referrered by <referrer>\n Then the first table row on the first page of the table is for <referrer>\n\n @motivating\n Scenario: Only referrals which occured in the program specific by program-id are shown\n Given the table is configured with \"program-id\"\n Then only referrals from the program with \"program-id\" are shown\n\n @motivating\n Scenario: Classic program shows only classic referrals\n Given the \"program-id\" of the table is set to \"classic\"\n Then only classic referrals are shown in the table\n\n @minutae\n @ui\n Scenario: Column heading can be hidden\n Given the table is configured with \"show-labels\" set to false\n Then the table is displayed without column headings";
5326
+ const scenario$c = "@owner:sam\n@author:sam\nFeature: Referral Table\n\n The Referral table component shows users a list of their referrals. The referral table it's self can be customized\n with a collection of columns.\n\n @motivating\n @ui\n Scenario: The empty state is shown if there are no referrals\n Given a user with no referrals\n When they view the referral table\n Then no referrals are displayed\n And they see an image with a user icon\n And \"View your referral details\" in bold\n And \"Track the status of your referrals and rewards earned by referring friends\" below the bolded text\n And the pagination buttons are disabled\n\n @motivating\n @ui\n Scenario: The empty state image and text are customizable\n Given the referral table has 'sqm-empty' as a child with the following props\n | prop | value |\n | empty-state-imgage | https://res.cloudinary.com/saasquatch/image/upload/v1634255445/squatch-assets/Copy_of_saasquatch-logo-tree-large-horizontal.png |\n | empty-state-header | View your referral history |\n | empty-state-text | See your previous referrals and what you earned! |\n And a user with no referrals\n When they view the referral table\n Then they see no referrals\n And they see the SaaSquatch logo\n And \"View your referral history\" in bold\n And \"See your previous referrals and what you earned!\" below the bolded text\n\n @minutae\n @ui\n Scenario: A custom empty state can be provided\n Given a user with no referrals\n And a custom empty state has been supplied in the \"empty\" slot\n When they view the referral table\n Then they see the custom empty state\n\n @motivating\n @ui\n Scenario: The loading state is shown while referrals are loading\n Given the table is loading\n Then the loading state is shown in the table\n And a custom loading state can be supplied in the \"loading\" slot\n And the pagination buttons are disabled\n\n @motivating\n @ui\n Scenario Outline: The table becomes paginated when the number of referrals exceeds the per page limit\n Given the user has <number of referrals>\n And the table is configured to show <page limit> referrals per page\n Then the table will have <number of pages> page(s)\n And pagination buttons will allow users to navigate between pages\n And the pagination button to go to the next page is disabled on the last page of referrals\n And the pagination button to go to the previous page is disabled on the first page of referrals\n Examples:\n | number of referrals | page limit | number of pages |\n | 0 | 4 | 1 |\n | 1 | 4 | 1 |\n | 3 | 4 | 1 |\n | 5 | 4 | 2 |\n | 42 | 4 | 11 |\n\n @motivating\n @ui\n Scenario: The table converts to a card view on tablet and mobile window sizes\n Given a user with referrals\n When they view the table\n And their window size is smaller than \"799px\"\n Then referrals are displayed as cards\n And they are in two columns\n When their window size is smaller than \"599px\"\n Then the referrals are displayed as cards in a singular column\n\n @motivating\n @ui\n Scenario: Table and Mobile beakpoints can be configured\n Given the referral table has been configured with the following props\n | prop | value |\n | smBreakpoint | 599 |\n | mdBreakpoint | 799 |\n And a user with referrals\n When they view the table\n And their window size is smaller than \"799px\"\n Then referrals are displayed as cards\n And they are in two columns\n When their window size is smaller than \"599px\"\n Then the referrals are displayed as cards in a singular column\n\n @motivating\n @ui\n Scenario Outline: By default the first column heading is hidden in mobile, but others can be hidden\n Given a referral table with 4 columns\n And prop \"hidden-columns\" with <hideColumnValue>\n And a user with referrals\n When they view the referral table\n And their window size is below the tablet breakpoint\n Then referral cards are displayed\n And the titles of <columnsArehidden> within the card\n Examples:\n | hideColumnValue | columnsArehidden |\n | | the first column |\n | 0,1,2 | the first, second and third columns |\n | 3 | the fourth column |\n\n @motivating\n Scenario: The use who referred the current user can be shown in the table\n Given the table is configured with <showReferrer> set to true\n And the current user was referrered by <referrer>\n Then the first table row on the first page of the table is for <referrer>\n\n @motivating\n Scenario: Only referrals which occured in the program specific by program-id are shown\n Given the table is configured with \"program-id\"\n Then only referrals from the program with \"program-id\" are shown\n\n @motivating\n Scenario: Classic program shows only classic referrals\n Given the \"program-id\" of the table is set to \"classic\"\n Then only classic referrals are shown in the table\n\n @minutae\n @ui\n Scenario: Column heading can be hidden\n Given the table is configured with \"show-labels\" set to false\n Then the table is displayed without column headings";
5125
5327
 
5126
5328
  const ReferralTable_stories = {
5127
5329
  title: "Components/Referral Table",
5128
5330
  parameters: {
5129
- scenario: scenario$b,
5331
+ scenario: scenario$c,
5130
5332
  },
5131
5333
  };
5132
5334
  const loadingElement = (index.h("div", { slot: "loading", style: { display: "contents" } },
@@ -5676,11 +5878,11 @@ const ReferralTable = /*#__PURE__*/Object.freeze({
5676
5878
  ColumnsMobileHidden: ColumnsMobileHidden
5677
5879
  });
5678
5880
 
5679
- const scenario$c = column + date + reward + status + user;
5881
+ const scenario$d = column + date + reward + status + user;
5680
5882
  const ReferralTableCell_stories = {
5681
5883
  title: "Components/Referral Table Cell",
5682
5884
  parameters: {
5683
- scenario: scenario$c,
5885
+ scenario: scenario$d,
5684
5886
  },
5685
5887
  };
5686
5888
  const TableCell = () => {
@@ -5920,11 +6122,11 @@ const ResizerStylesheet = `
5920
6122
  `;
5921
6123
  const Resizer = (_, children) => (index.h("div", { class: "resizer" }, children));
5922
6124
 
5923
- const scenario$d = scenarioTaskCard + scenarioProgressBar;
6125
+ const scenario$e = scenarioTaskCard + scenarioProgressBar;
5924
6126
  const TaskCard_stories = {
5925
6127
  title: "Components/Task Card/",
5926
6128
  parameters: {
5927
- scenario: scenario$d,
6129
+ scenario: scenario$e,
5928
6130
  },
5929
6131
  };
5930
6132
  const storyFrame = {
@@ -9375,17 +9577,17 @@ var marked = stencilHooks_module.createCommonjsModule(function (module, exports)
9375
9577
  })));
9376
9578
  });
9377
9579
 
9378
- const LoginReadme = "# sqm-portal-login\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| --------------------- | ----------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |\n| `demoData` | -- | | `{ states?: { error: string; loading: boolean; forgotPasswordPath: string; registerPath: string; }; content?: { forgotPasswordButton?: any; secondaryButton?: any; emailLabel?: string; passwordLabel?: string; submitLabel?: string; pageLabel?: string; }; }` | `undefined` |\n| `emailLabel` | `email-label` | Label for email field | `string` | `\"Email\"` |\n| `forgotPasswordLabel` | `forgot-password-label` | Label for forgotten password button | `string` | `\"Forgot Password?\"` |\n| `forgotPasswordPath` | `forgot-password-path` | Forgot password redirect path | `string` | `\"/forgotPassword\"` |\n| `nextPage` | `next-page` | Page navigated to after sign-in | `string` | `\"/\"` |\n| `pageLabel` | `page-label` | | `string` | `\"Sign in to your account\"` |\n| `passwordLabel` | `password-label` | Label for password field | `string` | `\"Password\"` |\n| `registerLabel` | `register-label` | Label for register button | `string` | `\"Register\"` |\n| `registerPath` | `register-path` | Register redirect path | `string` | `\"/register\"` |\n| `submitLabel` | `submit-label` | Label for submit button | `string` | `\"Sign In\"` |\n\n\n## Dependencies\n\n### Used by\n\n - [sqm-stencilbook](../sqm-stencilbook)\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-login --> sqm-form-message\n sqm-stencilbook --> sqm-portal-login\n style sqm-portal-login fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9580
+ const LoginReadme = "# sqm-portal-login\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| --------------------- | ----------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |\n| `demoData` | -- | | `{ states?: { error: string; loading: boolean; forgotPasswordPath: string; registerPath: string; }; content?: { forgotPasswordButton?: any; secondaryButton?: any; emailLabel?: string; passwordLabel?: string; submitLabel?: string; pageLabel?: string; }; }` | `undefined` |\n| `emailLabel` | `email-label` | | `string` | `\"Email\"` |\n| `forgotPasswordLabel` | `forgot-password-label` | | `string` | `\"Forgot Password?\"` |\n| `forgotPasswordPath` | `forgot-password-path` | | `string` | `\"/forgotPassword\"` |\n| `nextPage` | `next-page` | | `string` | `\"/\"` |\n| `pageLabel` | `page-label` | | `string` | `\"Sign in to your account\"` |\n| `passwordLabel` | `password-label` | | `string` | `\"Password\"` |\n| `registerLabel` | `register-label` | | `string` | `\"Register\"` |\n| `registerPath` | `register-path` | | `string` | `\"/register\"` |\n| `submitLabel` | `submit-label` | | `string` | `\"Sign In\"` |\n\n\n## Dependencies\n\n### Used by\n\n - [sqm-stencilbook](../sqm-stencilbook)\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-login --> sqm-form-message\n sqm-stencilbook --> sqm-portal-login\n style sqm-portal-login fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9379
9581
 
9380
- const ReferralIframeReadme = "# sqm-referral-iframe\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| -------------- | --------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ----------- |\n| `demoData` | -- | | `{ states?: { content: { iframeSrc: string; iframeHeight: string; iframeWidth: string; }; }; data?: { shareCode: string; }; }` | `undefined` |\n| `iframeHeight` | `iframe-height` | Height of the iframe container | `string` | `\"100%\"` |\n| `iframeSrc` | `iframe-src` | URL of iframe to display | `string` | `undefined` |\n| `iframeWidth` | `iframe-width` | Width of the iframe container | `string` | `\"100%\"` |\n\n\n## Dependencies\n\n### Used by\n\n - [sqm-stencilbook](../sqm-stencilbook)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-stencilbook --> sqm-referral-iframe\n style sqm-referral-iframe fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9582
+ const ReferralIframeReadme = "# sqm-referral-iframe\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| -------------- | --------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------- |\n| `demoData` | -- | | `{ states?: { content: { iframeSrc: string; iframeHeight: string; iframeWidth: string; }; }; data?: { shareCode: string; }; }` | `undefined` |\n| `iframeHeight` | `iframe-height` | | `string` | `\"100%\"` |\n| `iframeSrc` | `iframe-src` | | `string` | `undefined` |\n| `iframeWidth` | `iframe-width` | | `string` | `\"100%\"` |\n\n\n## Dependencies\n\n### Used by\n\n - [sqm-stencilbook](../sqm-stencilbook)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-stencilbook --> sqm-referral-iframe\n style sqm-referral-iframe fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9381
9583
 
9382
9584
  const ForgotPasswordReadme = "# sqm-portal-forgot-password\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| -------------- | --------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |\n| `demoData` | -- | | `{ states?: { error: string; loading: boolean; success: boolean; loginPath: string; }; content?: { secondaryButton: any; messageSlot: any; emailLabel?: string; submitLabel?: string; }; }` | `undefined` |\n| `emailLabel` | `email-label` | | `string` | `\"Email\"` |\n| `loginPath` | `login-path` | | `string` | `\"/login\"` |\n| `redirectPath` | `redirect-path` | The page that users are redirected to from the password reset email. | `string` | `\"/resetPassword\"` |\n| `submitLabel` | `submit-label` | | `string` | `\"Request Password Reset\"` |\n\n\n## Dependencies\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-forgot-password --> sqm-form-message\n style sqm-portal-forgot-password fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9383
9585
 
9384
- const RegisterReadme = "# sqm-portal-register\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| -------------------------- | ---------------------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |\n| `confirmPassword` | `confirm-password` | Show or hide the confirm password input | `boolean` | `false` |\n| `confirmPasswordLabel` | `confirm-password-label` | | `string` | `\"Confirm Password\"` |\n| `demoData` | -- | | `{ states?: { error: string; loading: boolean; confirmPassword: boolean; hideInputs: boolean; validationState?: FormState; enablePasswordValidation?: boolean; loginPath: string; }; refs?: { formRef: any; }; content?: { formData?: VNode; terms?: VNode; passwordField?: VNode; secondaryButton?: VNode; emailLabel?: string; passwordLabel?: string; submitLabel?: string; pageLabel?: string; confirmPasswordLabel: string; }; }` | `undefined` |\n| `emailLabel` | `email-label` | | `string` | `\"Email\"` |\n| `enablePasswordValidation` | `enable-password-validation` | | `boolean` | `true` |\n| `hideInputs` | `hide-inputs` | Hide default input fields to use custom fields | `boolean` | `false` |\n| `loginLabel` | `login-label` | | `string` | `\"Sign in\"` |\n| `loginPath` | `login-path` | Login button redirection path | `string` | `\"/login\"` |\n| `nextPage` | `next-page` | Page navigated to after registration | `string` | `\"/\"` |\n| `pageLabel` | `page-label` | | `string` | `\"Register\"` |\n| `passwordLabel` | `password-label` | | `string` | `\"Password\"` |\n| `redirectPath` | `redirect-path` | The page that users are redirected to from the verification email. | `string` | `\"/verifyEmail\"` |\n| `submitLabel` | `submit-label` | | `string` | `\"Register\"` |\n\n\n## Dependencies\n\n### Used by\n\n - [sqm-stencilbook](../sqm-stencilbook)\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n- [sqm-password-field](../sqm-password-field)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-register --> sqm-form-message\n sqm-portal-register --> sqm-password-field\n sqm-stencilbook --> sqm-portal-register\n style sqm-portal-register fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9586
+ const RegisterReadme = "# sqm-portal-register\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| -------------------------- | ---------------------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |\n| `confirmPassword` | `confirm-password` | | `boolean` | `false` |\n| `confirmPasswordLabel` | `confirm-password-label` | | `string` | `\"Confirm Password\"` |\n| `demoData` | -- | | `{ states?: { error: string; loading: boolean; confirmPassword: boolean; hideInputs: boolean; validationState?: FormState; enablePasswordValidation?: boolean; loginPath: string; }; refs?: { formRef: any; }; content?: { formData?: VNode; terms?: VNode; passwordField?: VNode; secondaryButton?: VNode; emailLabel?: string; passwordLabel?: string; submitLabel?: string; pageLabel?: string; confirmPasswordLabel: string; }; }` | `undefined` |\n| `emailLabel` | `email-label` | | `string` | `\"Email\"` |\n| `enablePasswordValidation` | `enable-password-validation` | | `boolean` | `true` |\n| `hideInputs` | `hide-inputs` | | `boolean` | `false` |\n| `loginLabel` | `login-label` | | `string` | `\"Sign in\"` |\n| `loginPath` | `login-path` | | `string` | `\"/login\"` |\n| `nextPage` | `next-page` | | `string` | `\"/\"` |\n| `pageLabel` | `page-label` | | `string` | `\"Register\"` |\n| `passwordLabel` | `password-label` | | `string` | `\"Password\"` |\n| `redirectPath` | `redirect-path` | The page that users are redirected to from the verification email. | `string` | `\"/verifyEmail\"` |\n| `submitLabel` | `submit-label` | | `string` | `\"Register\"` |\n\n\n## Dependencies\n\n### Used by\n\n - [sqm-stencilbook](../sqm-stencilbook)\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n- [sqm-password-field](../sqm-password-field)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-register --> sqm-form-message\n sqm-portal-register --> sqm-password-field\n sqm-stencilbook --> sqm-portal-register\n style sqm-portal-register fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9385
9587
 
9386
- const EditProfileReadme = "# sqm-portal-profile\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| ------------------------ | --------------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |\n| `countrytext` | `countrytext` | Country input field label | `string` | `\"Country\"` |\n| `demoData` | -- | | `{ states?: { success: boolean; loading: boolean; submitDisabled: boolean; showCountry: boolean; formState: { country: string; firstName: string; lastName: string; errors: any; error: string; }; user: { id: string; accountId: string; firstName: string; lastName: string; email: string; countryCode: string; }; text: { firstnametext: string; lastnametext: string; emailtext: string; countrytext: string; editProfileHeader: string; editProfileSubHeader: string; submitChangeButtonText: string; }; }; }` | `undefined` |\n| `editProfileHeader` | `edit-profile-header` | | `string` | `\"Edit your profile\"` |\n| `editProfileSubHeader` | `edit-profile-sub-header` | | `string` | `\"Personal Information\"` |\n| `emailtext` | `emailtext` | Email input field label | `string` | `\"Email\"` |\n| `firstnametext` | `firstnametext` | First name input field label | `string` | `\"First Name\"` |\n| `lastnametext` | `lastnametext` | Last name input field label | `string` | `\"Last Name\"` |\n| `showCountry` | `show-country` | Show or hide the country field | `boolean` | `true` |\n| `submitChangeButtonText` | `submit-change-button-text` | | `string` | `\"Submit Changes\"` |\n\n\n## Dependencies\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-profile --> sqm-form-message\n style sqm-portal-profile fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9588
+ const EditProfileReadme = "# sqm-portal-profile\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| ------------------------ | --------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |\n| `countrytext` | `countrytext` | | `string` | `\"Country\"` |\n| `demoData` | -- | | `{ states?: { success: boolean; loading: boolean; submitDisabled: boolean; showCountry: boolean; formState: { country: string; firstName: string; lastName: string; errors: any; error: string; }; user: { id: string; accountId: string; firstName: string; lastName: string; email: string; countryCode: string; }; text: { firstnametext: string; lastnametext: string; emailtext: string; countrytext: string; editProfileHeader: string; editProfileSubHeader: string; submitChangeButtonText: string; }; }; }` | `undefined` |\n| `editProfileHeader` | `edit-profile-header` | | `string` | `\"Edit your profile\"` |\n| `editProfileSubHeader` | `edit-profile-sub-header` | | `string` | `\"Personal Information\"` |\n| `emailtext` | `emailtext` | | `string` | `\"Email\"` |\n| `firstnametext` | `firstnametext` | | `string` | `\"First Name\"` |\n| `lastnametext` | `lastnametext` | | `string` | `\"Last Name\"` |\n| `showCountry` | `show-country` | | `boolean` | `true` |\n| `submitChangeButtonText` | `submit-change-button-text` | | `string` | `\"Submit Changes\"` |\n\n\n## Dependencies\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-profile --> sqm-form-message\n style sqm-portal-profile fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9387
9589
 
9388
- const ResetPasswordReadme = "# sqm-portal-reset-password\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| --------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |\n| `confirmPassword` | `confirm-password` | Show or hide confirm password field | `boolean` | `false` |\n| `confirmPasswordFieldLabel` | `confirm-password-field-label` | | `string` | `\"Confirm Password\"` |\n| `continueButtonText` | `continue-button-text` | Button text displayed after a successful password reset | `string` | `\"Continue\"` |\n| `demoData` | -- | | `{ states?: { error: string; loading: boolean; reset: boolean; confirmPassword: boolean; oobCodeValidating: boolean; oobCodeValid: boolean; passwordDemoData?: PasswordFieldViewDemoProps; content: { passwordResetHeader: string; resetPasswordHeader: string; continueButtonText: string; resetPasswordButtonText: string; confirmPasswordFieldLabel: string; passwordFieldLabel: string; }; }; }` | `undefined` |\n| `failedPage` | `failed-page` | The page that users are redirected to if the reset fails due to outdated password reset attempt. | `string` | `\"/\"` |\n| `nextPage` | `next-page` | The page that users are redirected to when the password reset succeeds. | `string` | `\"/\"` |\n| `passwordFieldLabel` | `password-field-label` | | `string` | `\"New Password\"` |\n| `passwordResetHeader` | `password-reset-header` | Displayed after a successful password reset | `string` | `\"Password reset\"` |\n| `resetPasswordButtonText` | `reset-password-button-text` | | `string` | `\"Reset Password\"` |\n| `resetPasswordHeader` | `reset-password-header` | | `string` | `\"Reset your password\"` |\n\n\n## Dependencies\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n- [sqm-password-field](../sqm-password-field)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-reset-password --> sqm-form-message\n sqm-portal-reset-password --> sqm-password-field\n style sqm-portal-reset-password fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9590
+ const ResetPasswordReadme = "# sqm-portal-reset-password\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| --------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |\n| `confirmPassword` | `confirm-password` | | `boolean` | `false` |\n| `confirmPasswordFieldLabel` | `confirm-password-field-label` | | `string` | `\"Confirm Password\"` |\n| `continueButtonText` | `continue-button-text` | Displayed after a successful password reset | `string` | `\"Continue\"` |\n| `demoData` | -- | | `{ states?: { error: string; loading: boolean; reset: boolean; confirmPassword: boolean; oobCodeValidating: boolean; oobCodeValid: boolean; passwordDemoData?: PasswordFieldViewDemoProps; content: { passwordResetHeader: string; resetPasswordHeader: string; continueButtonText: string; resetPasswordButtonText: string; confirmPasswordFieldLabel: string; passwordFieldLabel: string; }; }; }` | `undefined` |\n| `failedPage` | `failed-page` | The page that users are redirected to if the reset fails due to outdated password reset attempt. | `string` | `\"/\"` |\n| `nextPage` | `next-page` | The page that users are redirected to when the password reset succeeds. | `string` | `\"/\"` |\n| `passwordFieldLabel` | `password-field-label` | | `string` | `\"New Password\"` |\n| `passwordResetHeader` | `password-reset-header` | Displayed after a successful password reset | `string` | `\"Password reset\"` |\n| `resetPasswordButtonText` | `reset-password-button-text` | | `string` | `\"Reset Password\"` |\n| `resetPasswordHeader` | `reset-password-header` | | `string` | `\"Reset your password\"` |\n\n\n## Dependencies\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n- [sqm-password-field](../sqm-password-field)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-reset-password --> sqm-form-message\n sqm-portal-reset-password --> sqm-password-field\n style sqm-portal-reset-password fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9389
9591
 
9390
9592
  const EmailVerificationReadme = "# sqm-portal-email-verification\n\n\n\n<!-- Auto Generated Below -->\n\n\n## Properties\n\n| Property | Attribute | Description | Type | Default |\n| ------------------------- | --------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |\n| `demoData` | -- | | `{ states?: { error: string; loading: boolean; success: boolean; }; content?: { email: string; verifyMessage: string; emailVerificationHeader: string; resendEmailButtonText: string; }; }` | `undefined` |\n| `emailVerificationHeader` | `email-verification-header` | | `string` | `\"Verify your email\"` |\n| `redirectPath` | `redirect-path` | The page that users are redirected to from the verification email. | `string` | `\"/verifyEmail\"` |\n| `resendEmailButtonText` | `resend-email-button-text` | | `string` | `\"Re-send Email\"` |\n| `verifyMessage` | `verify-message` | | `string` | `\"A verification email was sent to {email}. Please verify your email to continue to the portal.\"` |\n\n\n## Dependencies\n\n### Depends on\n\n- [sqm-form-message](../sqm-form-message)\n\n### Graph\n```mermaid\ngraph TD;\n sqm-portal-email-verification --> sqm-form-message\n style sqm-portal-email-verification fill:#f9f,stroke:#333,stroke-width:4px\n```\n\n----------------------------------------------\n\n*Built with [StencilJS](https://stenciljs.com/)*\n";
9391
9593
 
@@ -9598,12 +9800,12 @@ const PoweredByImg = /*#__PURE__*/Object.freeze({
9598
9800
  CustomWidthAndHeight: CustomWidthAndHeight
9599
9801
  });
9600
9802
 
9601
- const scenario$e = "Feature: Portal Footer\n\n Background: A user is viewing the portal\n Given a hosted portal\n And a user is viewing the portal\n And the portal has a footer\n\n Scenario Outline: FAQ and T&C links/text are configurable and open in a new page when clicked\n Given the footer has prop \"terms-link\" with value \"https://example.com/terms\"\n And prop \"terms-text\" with value \"Terms and Conditions\"\n And prop \"faq-link\" with value \"https://example.com/FAQ\"\n And prop \"faq-text\" with value \"Visit FAQ\"\n When a user clicks on the \"Visit FAQ\" link\n Then they will be redirected to \"https://example.com/FAQ\" in a new page\n When they go back to the portal\n And click on the \"Terms and Conditions\" link\n Then they will be redirected to \"https://example.com/terms\" in a new page\n\n Scenario Outline: FAQ/T&C Links are not shown if a link is not provided\n Given the footer does not have <linkProp>\n But it <mayHave> <textProp> with <value>\n Then the <link> will not be shown in the footer\n Examples:\n | linkProp | mayHave | textProp | value | link |\n | terms-link | has | termsText | Terms and Conditions | T&C Link |\n | faq-link | has | faqText | Visit FAQ | FAQ Link |\n | terms-link | doesn't have | | | T&C Link |\n | faq-link | doesn't have | | | FAQ Link |\n\n Scenario Outline: The support email and text is configurable but has a default\n Given the footer <mayHave> <emailPropWithValue>\n And the footer <mayAlsoHave> <textPropWithValue>\n Then the footer's support email text is <renderedEmailText>\n And the email address will be a mailto link with <mailtoEmail>\n When the user clicks on the email address mailto Link\n Then the users preferred email client will open with a draft email to <mailtoEmail>\n Examples:\n | mayHave | emailPropWithValue | mayAlsoHave | textPropWithValue | mailtoEmail | renderedEmailText |\n | has | support@saasquatch.com | has | For support please contact {email} | support@saasquatch.com | For support please contact support@saasquatch.com |\n | doesn't have | N/A | doesn't have | N/A | support@example.com | For program support, contact support@example.com |\n\n Scenario Outline: Powered by SaaSquatch is shown by default\n Given the footer <mayHaveProp> \"show-powered-by\" with <value>\n Then the powered by SaaSquatch image <mayBeShown>\n Examples:\n | mayHaveProp | value | mayBeShown |\n | has prop | true | is shown |\n | has prop | false | isn't shown |\n | has prop | test | is shown |\n | has prop | | is shown |\n | doesn't have prop | | is shown |\n\n Scenario: Powered By Saasquatch links out to \"https://saasquatch.com\"\n Given the footer has the powered by SaaSquatch image\n When a user clicks on it\n Then they will be redirected to \"https://saasquatch.com\" in a new page";
9803
+ const scenario$f = "Feature: Portal Footer\n\n Background: A user is viewing the portal\n Given a hosted portal\n And a user is viewing the portal\n And the portal has a footer\n\n Scenario Outline: FAQ and T&C links/text are configurable and open in a new page when clicked\n Given the footer has prop \"terms-link\" with value \"https://example.com/terms\"\n And prop \"terms-text\" with value \"Terms and Conditions\"\n And prop \"faq-link\" with value \"https://example.com/FAQ\"\n And prop \"faq-text\" with value \"Visit FAQ\"\n When a user clicks on the \"Visit FAQ\" link\n Then they will be redirected to \"https://example.com/FAQ\" in a new page\n When they go back to the portal\n And click on the \"Terms and Conditions\" link\n Then they will be redirected to \"https://example.com/terms\" in a new page\n\n Scenario Outline: FAQ/T&C Links are not shown if a link is not provided\n Given the footer does not have <linkProp>\n But it <mayHave> <textProp> with <value>\n Then the <link> will not be shown in the footer\n Examples:\n | linkProp | mayHave | textProp | value | link |\n | terms-link | has | termsText | Terms and Conditions | T&C Link |\n | faq-link | has | faqText | Visit FAQ | FAQ Link |\n | terms-link | doesn't have | | | T&C Link |\n | faq-link | doesn't have | | | FAQ Link |\n\n Scenario Outline: The support email and text is configurable but has a default\n Given the footer <mayHave> <emailPropWithValue>\n And the footer <mayAlsoHave> <textPropWithValue>\n Then the footer's support email text is <renderedEmailText>\n And the email address will be a mailto link with <mailtoEmail>\n When the user clicks on the email address mailto Link\n Then the users preferred email client will open with a draft email to <mailtoEmail>\n Examples:\n | mayHave | emailPropWithValue | mayAlsoHave | textPropWithValue | mailtoEmail | renderedEmailText |\n | has | support@saasquatch.com | has | For support please contact {email} | support@saasquatch.com | For support please contact support@saasquatch.com |\n | doesn't have | N/A | doesn't have | N/A | support@example.com | For program support, contact support@example.com |\n\n Scenario Outline: Powered by SaaSquatch is shown by default\n Given the footer <mayHaveProp> \"show-powered-by\" with <value>\n Then the powered by SaaSquatch image <mayBeShown>\n Examples:\n | mayHaveProp | value | mayBeShown |\n | has prop | true | is shown |\n | has prop | false | isn't shown |\n | has prop | test | is shown |\n | has prop | | is shown |\n | doesn't have prop | | is shown |\n\n Scenario: Powered By Saasquatch links out to \"https://saasquatch.com\"\n Given the footer has the powered by SaaSquatch image\n When a user clicks on it\n Then they will be redirected to \"https://saasquatch.com\" in a new page";
9602
9804
 
9603
9805
  const PortalFooter_stories = {
9604
9806
  title: "Components/Portal Footer",
9605
9807
  parameters: {
9606
- scenario: scenario$e,
9808
+ scenario: scenario$f,
9607
9809
  },
9608
9810
  };
9609
9811
  const defaultProps$9 = {
@@ -9632,12 +9834,12 @@ const PortalFooter = /*#__PURE__*/Object.freeze({
9632
9834
  FooterNoPoweredBy: FooterNoPoweredBy
9633
9835
  });
9634
9836
 
9635
- const scenario$f = "Feature: Hero Unit\n\n Background: A portal with a hero unit exists\n Given a hosted portal\n And the portal has hero unit on the login page\n And a user is viewing the login page\n\n Scenario: The hero unit defaults to a single column layout\n Given a hero unit does not have a \"columns\" prop\n But the following html is wrapped by the hero unit\n \"\"\"\n <sqm-portal-login></sqm-portal-login>\n <div slot=\"secondary-column\">\n <h1 style=\"text-align:center\">Get Referring!</h1>\n <p style=\"text-align:center\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do\n eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim\n ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in\n reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla\n pariatur.\n </p>\n </div>\n \"\"\"\n Then only a single column will be displayed\n And within it will be the login component\n\n Scenario Outline: The hero unit supports single or dual column layouts\n Given a hero unit with prop \"columns\" having <columnValue>\n And it wraps <html>\n Then the hero unit displays <columnValue> columns\n Examples:\n | columnValue | html |\n | 1 | <h1>Column 1!</h1> |\n | 2 | <h1>Column 1!</h1><div slot=\"secondary-column\"><h1 style=\"text-align:center\">Column 2!</h1></div> |\n\n Scenario: HTML to be displayed in the second column comes from the \"secondary-column\" slot\n Given a hero unit with \"columns\" \"2\"\n And the following html\n \"\"\"\n <h1>Column 1!</h1>\n <div>\n <h1 style=\"text-align:center\">Column 2!</h1>\n </div>\n \"\"\"\n When the hero unit is rendered\n Then only one column is displayed with content\n And column 1 will contain the \"Column 1!\" text\n And column 1 will contain the \"Column 2!\" text\n When the div for column two is updated to have 'slot=\"secondary-column\"'\n Then the two columns are displayed with content\n And column 1 will contain the \"Column 1!\" text\n And column 2 will contain the \"Column 2!\" text\n\n Scenario Outline: A background for the hero unit can be set as an image or colour\n Given a hero unit with <backgroundPropValue>\n Then the background will be <background>\n Examples:\n | background | background |\n | https://images.unsplash.com/photo-1599676821464-3555954838d | image of misty mountains |\n | LightSlateGrey | light slate grey |\n | #00FF00 | green |\n | rgb(128,0,128) | purple |\n\n Scenario Outline: Wrap Direction can be configured for mobile experiences\n Given a hero unit with the following HTML\n \"\"\"\n <h1>Column 1!</h1>\n <div slot=\"secondary-column\">\n <h1 style=\"text-align:center\">Column 2!</h1>\n </div>\n \"\"\"\n And prop \"wrap-direction\" has <value>\n When the window width is less than 600px\n Then the two columns will stack\n And <column> will be on top\n Examples:\n | value | column |\n | wrap | 1 |\n | wrap-reverse | 2 |\n | | 1 |";
9837
+ const scenario$g = "Feature: Hero Unit\n\n Background: A portal with a hero unit exists\n Given a hosted portal\n And the portal has hero unit on the login page\n And a user is viewing the login page\n\n Scenario: The hero unit defaults to a single column layout\n Given a hero unit does not have a \"columns\" prop\n But the following html is wrapped by the hero unit\n \"\"\"\n <sqm-portal-login></sqm-portal-login>\n <div slot=\"secondary-column\">\n <h1 style=\"text-align:center\">Get Referring!</h1>\n <p style=\"text-align:center\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do\n eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim\n ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat. Duis aute irure dolor in\n reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla\n pariatur.\n </p>\n </div>\n \"\"\"\n Then only a single column will be displayed\n And within it will be the login component\n\n Scenario Outline: The hero unit supports single or dual column layouts\n Given a hero unit with prop \"columns\" having <columnValue>\n And it wraps <html>\n Then the hero unit displays <columnValue> columns\n Examples:\n | columnValue | html |\n | 1 | <h1>Column 1!</h1> |\n | 2 | <h1>Column 1!</h1><div slot=\"secondary-column\"><h1 style=\"text-align:center\">Column 2!</h1></div> |\n\n Scenario: HTML to be displayed in the second column comes from the \"secondary-column\" slot\n Given a hero unit with \"columns\" \"2\"\n And the following html\n \"\"\"\n <h1>Column 1!</h1>\n <div>\n <h1 style=\"text-align:center\">Column 2!</h1>\n </div>\n \"\"\"\n When the hero unit is rendered\n Then only one column is displayed with content\n And column 1 will contain the \"Column 1!\" text\n And column 1 will contain the \"Column 2!\" text\n When the div for column two is updated to have 'slot=\"secondary-column\"'\n Then the two columns are displayed with content\n And column 1 will contain the \"Column 1!\" text\n And column 2 will contain the \"Column 2!\" text\n\n Scenario Outline: A background for the hero unit can be set as an image or colour\n Given a hero unit with <backgroundPropValue>\n Then the background will be <background>\n Examples:\n | background | background |\n | https://images.unsplash.com/photo-1599676821464-3555954838d | image of misty mountains |\n | LightSlateGrey | light slate grey |\n | #00FF00 | green |\n | rgb(128,0,128) | purple |\n\n Scenario Outline: Wrap Direction can be configured for mobile experiences\n Given a hero unit with the following HTML\n \"\"\"\n <h1>Column 1!</h1>\n <div slot=\"secondary-column\">\n <h1 style=\"text-align:center\">Column 2!</h1>\n </div>\n \"\"\"\n And prop \"wrap-direction\" has <value>\n When the window width is less than 600px\n Then the two columns will stack\n And <column> will be on top\n Examples:\n | value | column |\n | wrap | 1 |\n | wrap-reverse | 2 |\n | | 1 |";
9636
9838
 
9637
9839
  const Hero_stories = {
9638
9840
  title: "Components/Hero Layout",
9639
9841
  parameters: {
9640
- scenario: scenario$f,
9842
+ scenario: scenario$g,
9641
9843
  },
9642
9844
  };
9643
9845
  const LoginOneColumn = () => {
@@ -9814,12 +10016,12 @@ const Hero = /*#__PURE__*/Object.freeze({
9814
10016
  TwoColumnLoginWithImgElement: TwoColumnLoginWithImgElement
9815
10017
  });
9816
10018
 
9817
- const scenario$g = "@owner:sam\n@author:sam\n\nFeature: Referral Iframe\n\n Used to provide an external form for submitting referral leads using the current user's referral code\n\n Background: A user is logged in\n Given there is a logged in user\n\n @motivating\n Scenario: Referral code is passed to the iframe as a query parameter\n Given the \"iframe-src\" is \"https://example.com\"\n And the user has navigated to \"/refer\"\n And the user's referral code is \"BOBBYREFER\"\n When the iframe content is loaded\n Then the iframe url will be \"https://example.com?rsCode=BOBBYREFER\"\n\n @ui\n Scenario Outline: The height and width of the iFrame can be controlled via props\n Given the \"iframe-src\" is \"https://example.com\"\n And the iframe content is 1000x1000\n And the \"iframe-height\" is set to <heightValue>\n And the \"iframe-width\" is set to <widthValue>\n Then the content of the iframe will be displayed with scrollbars\n And the dimension of the iFrame displayed will be 500x500\n When the \"iframe-height\" is set to <heightValue>\n And the \"iframe-width\" is set to <widthValue>\n Then the full content of the iframe will be displayed on the page\n And the dimension of the iFrame displayed will be 1000x1000\n Examples:\n | heightValue | widthValue |\n | 500px | 500px |\n | 50% | 50% |\n\n @minutae\n Scenario Outline: The iFrame will fail fast if a iFrame source isn't provided\n Given \"iframe-src\" <mayBeAnAttribute>\n And it <mayHaveValue>\n When a user views the referral iFrame component\n Then an alert with an error message is displayed in place of the iFrame\n And it has a details section\n When \"More details\" is clicked\n Then the following information will be displayed\n | component being used |\n | missing attribute(s) |\n\n Examples:\n | mayBeAnAttribute | mayHaveValue |\n | is not an attribute | N/A |\n | is an attribute | \"\" |\n | is an attribute | |";
10019
+ const scenario$h = "@owner:sam\n@author:sam\n\nFeature: Referral Iframe\n\n Used to provide an external form for submitting referral leads using the current user's referral code\n\n Background: A user is logged in\n Given there is a logged in user\n\n @motivating\n Scenario: Referral code is passed to the iframe as a query parameter\n Given the \"iframe-src\" is \"https://example.com\"\n And the user has navigated to \"/refer\"\n And the user's referral code is \"BOBBYREFER\"\n When the iframe content is loaded\n Then the iframe url will be \"https://example.com?rsCode=BOBBYREFER\"\n\n @ui\n Scenario Outline: The height and width of the iFrame can be controlled via props\n Given the \"iframe-src\" is \"https://example.com\"\n And the iframe content is 1000x1000\n And the \"iframe-height\" is set to <heightValue>\n And the \"iframe-width\" is set to <widthValue>\n Then the content of the iframe will be displayed with scrollbars\n And the dimension of the iFrame displayed will be 500x500\n When the \"iframe-height\" is set to <heightValue>\n And the \"iframe-width\" is set to <widthValue>\n Then the full content of the iframe will be displayed on the page\n And the dimension of the iFrame displayed will be 1000x1000\n Examples:\n | heightValue | widthValue |\n | 500px | 500px |\n | 50% | 50% |\n\n @minutae\n Scenario Outline: The iFrame will fail fast if a iFrame source isn't provided\n Given \"iframe-src\" <mayBeAnAttribute>\n And it <mayHaveValue>\n When a user views the referral iFrame component\n Then an alert with an error message is displayed in place of the iFrame\n And it has a details section\n When \"More details\" is clicked\n Then the following information will be displayed\n | component being used |\n | missing attribute(s) |\n\n Examples:\n | mayBeAnAttribute | mayHaveValue |\n | is not an attribute | N/A |\n | is an attribute | \"\" |\n | is an attribute | |";
9818
10020
 
9819
10021
  const ReferralIframe_stories = {
9820
10022
  title: "Components/Referral Iframe",
9821
10023
  parameters: {
9822
- scenario: scenario$g,
10024
+ scenario: scenario$h,
9823
10025
  },
9824
10026
  };
9825
10027
  const props = {
@@ -9850,12 +10052,12 @@ const ReferralIframe$1 = /*#__PURE__*/Object.freeze({
9850
10052
  ReferralIframeError: ReferralIframeError
9851
10053
  });
9852
10054
 
9853
- const scenario$h = "@owner:sam\n@author:sam\n\nFeature: Name Fields\n\n Fields to be used to fill the first and last name of a user during registration\n\n Background:\n Given the current page is \"/register\"\n\n @motivating\n Scenario: Both first name and last name are required\n Given the email field has valid input\n And the password field has valid input\n And first name field is empty\n And last name field is empty\n When register is clicked\n Then the name fields will be highlighted in red\n And the error messages will say \"Cannot be empty\"\n\n @motivating\n Scenario: First and last name are upserted with the SaaSquatch user\n Given all fields have been filled with data\n | firstName | lastName | email | password |\n | Bob | Testerson | bob@example.com | SecurePassword1 |\n When register is clicked\n Then the email verification page will be loaded\n And the user will be upserted\n And the SaaSquatch user will contain data\n | firstName | lastName | email |\n | Bob | Testerson | bob@example.com |\n\n";
10055
+ const scenario$i = "@owner:sam\n@author:sam\n\nFeature: Name Fields\n\n Fields to be used to fill the first and last name of a user during registration\n\n Background:\n Given the current page is \"/register\"\n\n @motivating\n Scenario: Both first name and last name are required\n Given the email field has valid input\n And the password field has valid input\n And first name field is empty\n And last name field is empty\n When register is clicked\n Then the name fields will be highlighted in red\n And the error messages will say \"Cannot be empty\"\n\n @motivating\n Scenario: First and last name are upserted with the SaaSquatch user\n Given all fields have been filled with data\n | firstName | lastName | email | password |\n | Bob | Testerson | bob@example.com | SecurePassword1 |\n When register is clicked\n Then the email verification page will be loaded\n And the user will be upserted\n And the SaaSquatch user will contain data\n | firstName | lastName | email |\n | Bob | Testerson | bob@example.com |\n\n";
9854
10056
 
9855
10057
  const NameFields_stories = {
9856
10058
  title: "Components/Name Fields",
9857
10059
  parameters: {
9858
- scenario: scenario$h,
10060
+ scenario: scenario$i,
9859
10061
  },
9860
10062
  };
9861
10063
  const props$1 = {
@@ -9893,12 +10095,12 @@ const NameFields$1 = /*#__PURE__*/Object.freeze({
9893
10095
  NameFieldsWithErrors: NameFieldsWithErrors
9894
10096
  });
9895
10097
 
9896
- const scenario$i = "@owner:sam\n@author:sam\nFeature: Checkbox Field\n\n Field to be used to be used as a checkbox during registration. A motivating use case is to use this component as a terms\n and conditions field, to sastisfy legal requirements that a customer might have for their end users.\n\n Background: A user is on the portal registration page\n Given a user is viewing the \"/register\"\n And \"/register\" contains the registration form\n And the registration form has the following fields\n | fields |\n | first name |\n | last name |\n | email |\n | password |\n | checkbox |\n\n @motivating\n Scenario: Checkbox is required by default\n Given the user is filling out the registration form\n And the name fields have valid input\n And the email field has valid input\n And the password field has valid input\n And the checkbox is not checked\n When they try to register\n Then the checkbox is highlighted in red\n And the error message says \"Must be checked\"\n\n @landmine\n Scenario: Checkboxes with the same \"checkbox-name\" are not submitted in the form data\n Given the register form has the following html\n \"\"\"\n <sqm-portal-register>\n <sqm-name-fields slot=\"formData\"></sqm-name-fields>\n <sqm-checkbox-field\n slot=\"formData\"\n checkbox-label=\"I am not a robot\"\n error-message=\"Cannot be a robot\"\n checkbox-name=\"isHuman\"\n ></sqm-checkbox-field>\n <div slot=\"terms\">\n <sqm-checkbox-field checkbox-name=\"isHuman\"></sqm-checkbox-field>\n </div>\n </sqm-portal-register>\n \"\"\"\n And the checkboxes are checked\n When the user tries to register\n Then the form is submitted\n But no field with key \"isHuman\" is included in the form data\n\n @motivating\n Scenario: Multiple checkboxes need different \"checkbox-name\" values\n Given the register form has the following html\n \"\"\"\n <sqm-portal-register>\n <sqm-name-fields slot=\"formData\"></sqm-name-fields>\n <sqm-checkbox-field\n slot=\"formData\"\n checkbox-label=\"I am not a robot\"\n error-message=\"Cannot be a robot\"\n checkbox-name=\"isHuman\"\n ></sqm-checkbox-field>\n <div slot=\"terms\">\n <sqm-checkbox-field checkbox-name=\"myCheckbox\"></sqm-checkbox-field>\n </div>\n </sqm-portal-register>\n \"\"\"\n And the checkboxes are not checked\n When the user tries to register\n Then both checkboxes are bordered in red\n And the checkboxes have different error messages\n When the user checks the boxes\n And tries to register\n Then the form is submitted\n And the following fields are included in the form data\n | feilds |\n | isHuman |\n | myCheckbox |\n\n @motivating\n Scenario: Checkboxes can be optional\n Given the register form has the following html\n \"\"\"\n <sqm-portal-register>\n <sqm-name-fields slot=\"formData\"></sqm-name-fields>\n <sqm-checkbox-field\n slot=\"formData\"\n checkbox-label=\"I am not a robot\"\n checkbox-optional=\"true\"\n checkbox-name=\"isHuman\"\n />\n </sqm-portal-register>\n \"\"\"\n And the checkbox is not checked\n When the user tries to register\n Then there is no error for the checkbox\n\n @minutae\n Scenario Outline: Validation error message is configurable\n The error message string is evaluated as an ICU string, but currently is provided no context\n Given the checkbox is required\n And the checkbox has prop \"error-message\" with <propValue>\n When the user tries to register\n But they havent checked the checkbox\n Then they see <errorMessage> below\n Examples:\n | propValue | errorMessage |\n | | Must be checked |\n | My Custom Message | My Custom Message |\n\n @motivating\n Scenario Outline: Checkbox text and link are configurable\n Given the checkbox has the following prop values\n | prop | value |\n | checkbox-label | <labelText> |\n | checkbox-label-link | <labelLink> |\n | checkbox-label-link-text | <labelLinkText> |\n When the user views the checkbox\n Then they see <text>\n And when they click <labelLinkText> they are redirected to <labelLink>\n #First example below is the defaults set by the controller\n Examples:\n | labelText | labelLinkText | labelLink | text |\n | By signing up you agree to the {labelLink} | Terms and Conditions | https://example.com | By signing up you agree to the Terms and Conditions |\n | Read our {labelLink} before registration | Terms of Service | https://example.com/terms | Read our Terms of Service before registration |\n | By registering you agree to our terms and conditions | N/A | N/A | By registering you agree to our terms and conditions |\n\n @motivating\n Scenario: The form field name attribute is configurable\n Given the checkbox has prop \"checkbox-name\" with value \"myCheckBox\"\n When the user checks the box\n And they register\n Then the boolean value of the checkbox is submitted under \"myCheckBox\" field\n\n @minutae\n Scenario Outline: The checkbox field component fails fast if a checkbox name isn't provided\n Given the checkbox <mayHave> prop \"checkbox-name\"\n And it <mayHavePropValue>\n When a user views the checkbox\n Then an alert with an error message is displayed in place of the checkbox\n And it has a details section\n When \"More details\" is clicked\n Then the following information is displayed\n | information |\n | component being used |\n | missing attribute(s) |\n Examples:\n | mayBeAnAttribute | mayHavePropValue |\n | doesn't have | N/A |\n | has | \"\" |\n | has | |";
10098
+ const scenario$j = "@owner:sam\n@author:sam\nFeature: Checkbox Field\n\n Field to be used to be used as a checkbox during registration. A motivating use case is to use this component as a terms\n and conditions field, to sastisfy legal requirements that a customer might have for their end users.\n\n Background: A user is on the portal registration page\n Given a user is viewing the \"/register\"\n And \"/register\" contains the registration form\n And the registration form has the following fields\n | fields |\n | first name |\n | last name |\n | email |\n | password |\n | checkbox |\n\n @motivating\n Scenario: Checkbox is required by default\n Given the user is filling out the registration form\n And the name fields have valid input\n And the email field has valid input\n And the password field has valid input\n And the checkbox is not checked\n When they try to register\n Then the checkbox is highlighted in red\n And the error message says \"Must be checked\"\n\n @landmine\n Scenario: Checkboxes with the same \"checkbox-name\" are not submitted in the form data\n Given the register form has the following html\n \"\"\"\n <sqm-portal-register>\n <sqm-name-fields slot=\"formData\"></sqm-name-fields>\n <sqm-checkbox-field\n slot=\"formData\"\n checkbox-label=\"I am not a robot\"\n error-message=\"Cannot be a robot\"\n checkbox-name=\"isHuman\"\n ></sqm-checkbox-field>\n <div slot=\"terms\">\n <sqm-checkbox-field checkbox-name=\"isHuman\"></sqm-checkbox-field>\n </div>\n </sqm-portal-register>\n \"\"\"\n And the checkboxes are checked\n When the user tries to register\n Then the form is submitted\n But no field with key \"isHuman\" is included in the form data\n\n @motivating\n Scenario: Multiple checkboxes need different \"checkbox-name\" values\n Given the register form has the following html\n \"\"\"\n <sqm-portal-register>\n <sqm-name-fields slot=\"formData\"></sqm-name-fields>\n <sqm-checkbox-field\n slot=\"formData\"\n checkbox-label=\"I am not a robot\"\n error-message=\"Cannot be a robot\"\n checkbox-name=\"isHuman\"\n ></sqm-checkbox-field>\n <div slot=\"terms\">\n <sqm-checkbox-field checkbox-name=\"myCheckbox\"></sqm-checkbox-field>\n </div>\n </sqm-portal-register>\n \"\"\"\n And the checkboxes are not checked\n When the user tries to register\n Then both checkboxes are bordered in red\n And the checkboxes have different error messages\n When the user checks the boxes\n And tries to register\n Then the form is submitted\n And the following fields are included in the form data\n | feilds |\n | isHuman |\n | myCheckbox |\n\n @motivating\n Scenario: Checkboxes can be optional\n Given the register form has the following html\n \"\"\"\n <sqm-portal-register>\n <sqm-name-fields slot=\"formData\"></sqm-name-fields>\n <sqm-checkbox-field\n slot=\"formData\"\n checkbox-label=\"I am not a robot\"\n checkbox-optional=\"true\"\n checkbox-name=\"isHuman\"\n />\n </sqm-portal-register>\n \"\"\"\n And the checkbox is not checked\n When the user tries to register\n Then there is no error for the checkbox\n\n @minutae\n Scenario Outline: Validation error message is configurable\n The error message string is evaluated as an ICU string, but currently is provided no context\n Given the checkbox is required\n And the checkbox has prop \"error-message\" with <propValue>\n When the user tries to register\n But they havent checked the checkbox\n Then they see <errorMessage> below\n Examples:\n | propValue | errorMessage |\n | | Must be checked |\n | My Custom Message | My Custom Message |\n\n @motivating\n Scenario Outline: Checkbox text and link are configurable\n Given the checkbox has the following prop values\n | prop | value |\n | checkbox-label | <labelText> |\n | checkbox-label-link | <labelLink> |\n | checkbox-label-link-text | <labelLinkText> |\n When the user views the checkbox\n Then they see <text>\n And when they click <labelLinkText> they are redirected to <labelLink>\n #First example below is the defaults set by the controller\n Examples:\n | labelText | labelLinkText | labelLink | text |\n | By signing up you agree to the {labelLink} | Terms and Conditions | https://example.com | By signing up you agree to the Terms and Conditions |\n | Read our {labelLink} before registration | Terms of Service | https://example.com/terms | Read our Terms of Service before registration |\n | By registering you agree to our terms and conditions | N/A | N/A | By registering you agree to our terms and conditions |\n\n @motivating\n Scenario: The form field name attribute is configurable\n Given the checkbox has prop \"checkbox-name\" with value \"myCheckBox\"\n When the user checks the box\n And they register\n Then the boolean value of the checkbox is submitted under \"myCheckBox\" field\n\n @minutae\n Scenario Outline: The checkbox field component fails fast if a checkbox name isn't provided\n Given the checkbox <mayHave> prop \"checkbox-name\"\n And it <mayHavePropValue>\n When a user views the checkbox\n Then an alert with an error message is displayed in place of the checkbox\n And it has a details section\n When \"More details\" is clicked\n Then the following information is displayed\n | information |\n | component being used |\n | missing attribute(s) |\n Examples:\n | mayBeAnAttribute | mayHavePropValue |\n | doesn't have | N/A |\n | has | \"\" |\n | has | |";
9897
10099
 
9898
10100
  const CheckboxField_stories = {
9899
10101
  title: "Components/Checkbox Field",
9900
10102
  parameters: {
9901
- scenario: scenario$i,
10103
+ scenario: scenario$j,
9902
10104
  },
9903
10105
  };
9904
10106
  const defaultProps$a = {
@@ -9998,7 +10200,7 @@ const CheckboxField = /*#__PURE__*/Object.freeze({
9998
10200
  const UseCheckboxField_stories = {
9999
10201
  title: "Hooks / useCheckboxField",
10000
10202
  parameters: {
10001
- scenario: scenario$i,
10203
+ scenario: scenario$j,
10002
10204
  },
10003
10205
  };
10004
10206
  function setupGraphQL$9() {
@@ -10173,12 +10375,12 @@ const UseDropdownField = /*#__PURE__*/Object.freeze({
10173
10375
  MissingName: MissingName$1
10174
10376
  });
10175
10377
 
10176
- const scenario$j = "@author:derek\n@owner:derek\nFeature: Form Input Field\n\n This component is used as a custom registration field during registration. The field can be text,\n a date or phone number. A motivating use case is to ask for a users company name, this value would then be mapped\n through the Managed Identity Service and upserted on the user after registration.\n\n Background: A user exists and is viewing the hosted portal registration\n Given a user is viewing \"/register\"\n And \"/register\" contains the registration form\n And the registration form has a custom input field\n\n @motivating\n Scenario Outline: Input fields are required by default but can be optional\n Given the input has prop \"field-optional\" with <value>\n And the input is empty\n When the user tries to register\n Then the input <mayBe> highlighted in red\n And an error message <mayAppear> in red below\n And form submission <mayBe> blocked\n Examples:\n | value | mayBe | mayAppear |\n | false | is | appears |\n | | is | appears |\n | true | isn't | doesn't appear |\n\n @motivating\n Scenario: Input field labels are configurable\n Given the input has prop \"field-label\" with value \"My Custom Input\"\n When the user views the registration form\n Then they see the input field\n And it has label \"My Custom Input\" above the input\n\n @minutae\n Scenario Outline: The validation error message is configurable\n The error message string is evaluated as an ICU string, but currently is provided no context\n Given the input is required\n And it has prop \"error-message\" with <value>\n When the user tries to register\n But they haven't filled in the input\n Then they see <errorMessage> below\n Examples:\n | value | errorMessage |\n | | Cannot be empty |\n | My Custom Message | My Custom Message |\n\n @motivating\n Scenario: Form data attribute name is configurable\n Given the input has prop \"field-name\" with value \"myCustomField\"\n When the user types \"testing testing\" into the input\n And they register\n Then \"testing testing\" is submitted under \"myCustomField\" in the form data\n\n @motivating\n Scenario Outline: The input field is a text input by default\n Given the input <mayHave> prop \"field-type\" with <value>\n When the user views the input field\n Then it is a text input\n Examples:\n | mayHave | value |\n | has | text |\n | doesn't have | |\n\n @motivating\n Scenario: Date type inputs are supported\n Given the input has prop \"field-type\" \"date\"\n When the user views the input field\n Then they see \"mm/dd/yyyy\" as a placeholder\n And they see a calendar icon on the right\n When they start typing a date\n Then it maintains the \"mm/dd/yyyy\" format\n When they click the calendar icon\n Then a dropdown appears\n And they see a calendar\n When they select a date\n Then it is applied to the input\n\n @landmine\n Scenario: The clear text button in the date picker does not clear the date\n Due to an incompatibility between our shoelace version and the browser, the clear funtionality is not supported currently\n Given the input has prop \"field-type\" \"date\"\n And the user has entered a date\n When they click the calendar icon\n And click the 'clear' text button\n Then their selected date is not cleared\n\n @motivating\n Scenario: Phone number type inputs are supported\n Given the input has prop \"field-type\" with value \"tel\"\n When the user starts typing a phone number in the input\n Then it is formatted into the following form \"(XXX) XXX-XXXX\"\n When they pre-fix their phone number with a \"1\"\n Then it is formatted into the following form \"1 (XXX) XXX-XXXX\"\n\n @landmine\n Scenario: Telephone formatting is removed after 10 numbers\n Given a user using a phone number input field\n And they entered their 10 character phone number\n And it was not prefixed with a 1\n When they add another character\n Then the formatting is removed\n\n @landmine\n Scenario Outline: Input values are always recorded as strings in the form data\n Given the input has prop \"field-type\" with <value>\n And it has a \"field-name\"\n When the user inputs <formInput>\n And they register\n Then <formData> is recorded in the form data as a string\n Examples:\n | value | formInput | formData |\n | text | Hello there | Hello there |\n | date | 05/07/2021 | 2021-05-07 |\n | tel | (250) 234-9877 | (250) 234-9877 |\n\n @minutae\n Scenario Outline: The input field component fails fast if a field name isn't provided\n Given the input <mayHave> prop \"field-name\"\n And it <mayHavePropValue>\n When a user views the input\n Then an alert with an error message is displayed in place of the input\n And it has a details section\n When \"More details\" is clicked\n Then the following information is displayed\n | information |\n | component being used |\n | missing attribute(s) |\n Examples:\n | mayBeAnAttribute | mayHavePropValue |\n | doesn't have | N/A |\n | has | \"\" |\n | has | |";
10378
+ const scenario$k = "@author:derek\n@owner:derek\nFeature: Form Input Field\n\n This component is used as a custom registration field during registration. The field can be text,\n a date or phone number. A motivating use case is to ask for a users company name, this value would then be mapped\n through the Managed Identity Service and upserted on the user after registration.\n\n Background: A user exists and is viewing the hosted portal registration\n Given a user is viewing \"/register\"\n And \"/register\" contains the registration form\n And the registration form has a custom input field\n\n @motivating\n Scenario Outline: Input fields are required by default but can be optional\n Given the input has prop \"field-optional\" with <value>\n And the input is empty\n When the user tries to register\n Then the input <mayBe> highlighted in red\n And an error message <mayAppear> in red below\n And form submission <mayBe> blocked\n Examples:\n | value | mayBe | mayAppear |\n | false | is | appears |\n | | is | appears |\n | true | isn't | doesn't appear |\n\n @motivating\n Scenario: Input field labels are configurable\n Given the input has prop \"field-label\" with value \"My Custom Input\"\n When the user views the registration form\n Then they see the input field\n And it has label \"My Custom Input\" above the input\n\n @minutae\n Scenario Outline: The validation error message is configurable\n The error message string is evaluated as an ICU string, but currently is provided no context\n Given the input is required\n And it has prop \"error-message\" with <value>\n When the user tries to register\n But they haven't filled in the input\n Then they see <errorMessage> below\n Examples:\n | value | errorMessage |\n | | Cannot be empty |\n | My Custom Message | My Custom Message |\n\n @motivating\n Scenario: Form data attribute name is configurable\n Given the input has prop \"field-name\" with value \"myCustomField\"\n When the user types \"testing testing\" into the input\n And they register\n Then \"testing testing\" is submitted under \"myCustomField\" in the form data\n\n @motivating\n Scenario Outline: The input field is a text input by default\n Given the input <mayHave> prop \"field-type\" with <value>\n When the user views the input field\n Then it is a text input\n Examples:\n | mayHave | value |\n | has | text |\n | doesn't have | |\n\n @motivating\n Scenario: Date type inputs are supported\n Given the input has prop \"field-type\" \"date\"\n When the user views the input field\n Then they see \"mm/dd/yyyy\" as a placeholder\n And they see a calendar icon on the right\n When they start typing a date\n Then it maintains the \"mm/dd/yyyy\" format\n When they click the calendar icon\n Then a dropdown appears\n And they see a calendar\n When they select a date\n Then it is applied to the input\n\n @landmine\n Scenario: The clear text button in the date picker does not clear the date\n Due to an incompatibility between our shoelace version and the browser, the clear funtionality is not supported currently\n Given the input has prop \"field-type\" \"date\"\n And the user has entered a date\n When they click the calendar icon\n And click the 'clear' text button\n Then their selected date is not cleared\n\n @motivating\n Scenario: Phone number type inputs are supported\n Given the input has prop \"field-type\" with value \"tel\"\n When the user starts typing a phone number in the input\n Then it is formatted into the following form \"(XXX) XXX-XXXX\"\n When they pre-fix their phone number with a \"1\"\n Then it is formatted into the following form \"1 (XXX) XXX-XXXX\"\n\n @landmine\n Scenario: Telephone formatting is removed after 10 numbers\n Given a user using a phone number input field\n And they entered their 10 character phone number\n And it was not prefixed with a 1\n When they add another character\n Then the formatting is removed\n\n @landmine\n Scenario Outline: Input values are always recorded as strings in the form data\n Given the input has prop \"field-type\" with <value>\n And it has a \"field-name\"\n When the user inputs <formInput>\n And they register\n Then <formData> is recorded in the form data as a string\n Examples:\n | value | formInput | formData |\n | text | Hello there | Hello there |\n | date | 05/07/2021 | 2021-05-07 |\n | tel | (250) 234-9877 | (250) 234-9877 |\n\n @minutae\n Scenario Outline: The input field component fails fast if a field name isn't provided\n Given the input <mayHave> prop \"field-name\"\n And it <mayHavePropValue>\n When a user views the input\n Then an alert with an error message is displayed in place of the input\n And it has a details section\n When \"More details\" is clicked\n Then the following information is displayed\n | information |\n | component being used |\n | missing attribute(s) |\n Examples:\n | mayBeAnAttribute | mayHavePropValue |\n | doesn't have | N/A |\n | has | \"\" |\n | has | |";
10177
10379
 
10178
10380
  const InputField_stories = {
10179
10381
  title: "Components/Input Field",
10180
10382
  parameters: {
10181
- scenario: scenario$j,
10383
+ scenario: scenario$k,
10182
10384
  },
10183
10385
  };
10184
10386
  const defaultProps$c = {
@@ -10269,7 +10471,7 @@ const InputField = /*#__PURE__*/Object.freeze({
10269
10471
  const UseInputField_stories = {
10270
10472
  title: "Hooks / useInputField",
10271
10473
  parameters: {
10272
- scenario: scenario$j,
10474
+ scenario: scenario$k,
10273
10475
  },
10274
10476
  };
10275
10477
  function setupGraphQL$b() {
@@ -10351,12 +10553,12 @@ const UseInputField = /*#__PURE__*/Object.freeze({
10351
10553
  MissingName: MissingName$2
10352
10554
  });
10353
10555
 
10354
- const scenario$k = "@author:derek\n@owner:derek\nFeature: Reward Exchange List\n\n The Reward Exchange List gives end users the power to exchange their rewards for other rewards.\n It populates a list from the reward exchange rules set up on a given tenant.\n\n Background:\n Given a tenant with reward exchange rules\n\n @motivating\n @ui\n Scenario: The empty state is shown if there are no visible exchanges\n Given a user with no visible exchanges\n When they view the reward exchange\n Then no exchange options are displayed\n And they see an image of a present\n And \"Redeem Rewards\" in bold\n And \"Use your points to redeem rewards once they become available\" below the bolded text\n And the pagination buttons are disabled\n\n @minutae\n @ui\n Scenario: A custom empty state can be provided\n Given a user with no visible exchanges\n And a custom empty state has been supplied in the \"empty\" slot\n When they view the reward exchange\n Then they see the custom empty state\n\n @motivating\n @ui\n Scenario: A Loading Skeleton is displayed when the reward exchange rules are loading\n Given a user\n When they load the reward exchange list\n Then they see a loading Skeleton\n And it has 8 skeleton cards\n When the reward exchange rules have loaded\n Then the skeleton is replaced with reward exchange options\n\n @motivating\n Scenario: An error banner appears when the reward exchange list fails to load\n Given a user trying to view the reward exchange list\n But it fails to load\n Then an error banner is displayed\n And it displays \"Unable to load reward exchange list. Please try again\"\n\n @motivating\n @ui\n Scenario: The exchange progress bar progresses through the exchange process\n Given a user who is eligible for the tenants reward exchange rules\n When they view the reward exchange list\n Then the process bar displays the following elements\n | elements |\n | Step 1 `Rewards` title in black |\n | Step 1 circle with green outline, white fill and number 1 in green |\n | Step 2 `Select` title in grey |\n | Step 2 circle with grey fill and number 2 in white |\n | Step 3 `Confirm` title in grey |\n | Step 3 circle with grey fill and number 3 in white |\n | lines between all steps are greyed out |\n When they continue to the selection page\n Then the progress bar displays the following elements\n | elements |\n | Step 1 `Rewards` title in black |\n | Step 1 circle with white checkmark and green fill |\n | Step 2 `Select` title in black |\n | Step 2 circle with green outline, white fill and number 2 in green |\n | Step 3 `Confirm` title in grey |\n | Step 3 circle with grey fill and number 3 in white |\n | Green line between step 1 and 2 |\n | Grey line between step 2 and 3 |\n When they continue to the confirmation page\n Then the progress bar displays the following elements\n | elements |\n | Step 1 `Rewards` title in black |\n | Step 1 circle with white checkmark and green fill |\n | Step 2 `Select` title in black |\n | Step 2 circle with white checkmark and green fill |\n | Step 3 `Confirm` title in black |\n | Step 3 circle with green outline, white fill and number 3 in green |\n | Green line between all steps |\n When they continue to the redemption page\n Then the progress bar displays the following elements\n | elements |\n | Step 1 `Rewards` title in black |\n | Step 1 circle with white checkmark and green fill |\n | Step 2 `Select` title in black |\n | Step 2 circle with white checkmark and green fill |\n | Step 3 `Confirm` title in black |\n | Step 3 circle with white checkmark and green fill |\n | Green line between all steps |\n\n @motivating\n Scenario: Users must choose a reward exchange option to continue to the selection page\n Given a user who is eligible for the tenants reward exchange rules\n When they view the reward exchange list\n Then the 'Continue' button is disabled\n When they select a reward exchange card\n Then the card is outlined in brand colour with a brand colour cirlcular check box icon in the top right\n And the continue button is no longer disabled\n When they click \"Continue\"\n Then they are brought to the selection page\n\n @motivating\n @ui\n Scenario: Reward exchange rule names and images are used in the reward exchange cards\n Given a tenant reward exchange rule\n And it has name \"My Visa Exchange Rule\"\n And it has an image\n When a user views the reward exchange list\n Then they see a exchange card with title \"My Visa Exchange Rule\"\n And the exchange image on the left hand side of the card\n\n @motivating\n Scenario Outline: Reward exchange source values are displayed on reward exchange cards\n Given a <type> reward exchange rule\n When a user views the reward exchange list\n Then they see <text> under the name on the exchange option cards\n And the pretty values are localized to a user locale\n Examples:\n | type | text |\n | FIXED_GLOBAL_REWARD | the exchange source pretty value |\n | STEPPED_FIXED_GLOBAL_REWARD | the exchange source min pretty value to the source max pretty value |\n | VARIABLE_GLOBAL_REWARD | the exchange source min pretty value to the source max pretty value |\n | VARIABLE_CREDIT_REWARD | the exchange source min pretty value to the source max pretty value |\n\n @motivating\n Scenario Outline: Reward exchange cards can display customized error messages\n Given a reward exchange rule\n And it has <availabilityPredicate>\n And the reward exchange list has prop \"not-available-error\" with <value>\n When the user views the reward exchange list\n Then the card for the reward exchange rule is disabled\n And <message> is displayed\n Examples:\n | availabilityPredicate | value | message |\n | 'champion' in user.segments ? \"NOT_CHAMPION\" : true | {unavailableReasonCode, select, NOT_CHAMPION {Sorry must be a champion!} other {unavailableReasonCode} } | Sorry must be a champion! |\n | user.customFields.purchaseCount < 10 ? \"MORE_PURCHASE\" : true | {unavailableReasonCode, select, MORE_PURCHASE {Complete 10 purchases to unlock} other {unavailableReasonCode} } | Complete 10 purchases to unlock |\n\n @motivating\n Scenario: Exchange options are disabled if they put a user over the W9 limit\n Given a user who is approaching their W9 limit\n And a reward exchange rule\n And its destination reward has a US taxable value that would put the user over their limit\n When they view the reward exchange list\n Then the reward exchange card is disabled\n And a \"US Tax Limit\" error message is displayed on to the right of a exclamation triangle icon\n And the text is orange\n And the icon is orange\n\n @motivating\n Scenario Outline: Exchange options are disabled if a users lacks enough credit to redeem\n Given a <type> reward exchange rule\n But the user lacks enough credit to exchange for it\n When they view the reward exchange list\n Then the reward exchange card is disabled\n And a <text> error message is displayed on to the right of a exclamation triangle icon\n And the text is orange\n And the icon is orange\n Examples:\n | type | text |\n | FIXED_GLOBAL_REWARD | {prettySourceValue} required |\n | STEPPED_FIXED_GLOBAL_REWARD | {prettySourceMinValue} required |\n | VARIABLE_GLOBAL_REWARD | {prettySourceMinValue} required |\n | VARIABLE_CREDIT_REWARD | {prettySourceMinValue} required |\n\n @motivating\n Scenario: Users can go back to the Rewards page from the Select page\n Given a user viewing the Select page\n Then they see a \"Cancel\" text button\n And a \"Continue to confirmation\" brand colour button in the bottom right corner\n When they click \"Cancel\"\n Then they return to the Rewards page\n\n @motivating\n Scenario: Users can go back to the Select Page from the Confirm page\n Given a user viewing the Confirm page\n Then they see a \"Back\" text button\n And a \"Redeem\" brand colour button in the bottom right corner\n When they click \"Back\"\n Then they return to the Select Page\n\n @motivating\n Scenario: Reward rules with visibility predicates that evaluates to false are not shown\n Given a tenant reward exchange rule with visibility predicates that evaluates to false\n When a user views the reward exchange list\n Then they do not see the card for that reward exchange rule\n\n @motivating\n Scenario Outline: Users can choose their reward option for variable rewards on the Select page\n Given a <type> exchange rule\n And it has the following fields\n | fields |\n | name |\n | description |\n | image |\n When a user views the reward exchange list\n And they progress to the Select page for this exchange\n Then they see the exchange rule image on the left hand side\n And on the right hand side they see the following in this order from top to bottom\n | elements |\n | exchange name |\n | exchange description |\n | select list with all exchange options using pretty values, destination reward above source reward |\n Examples:\n | type |\n | STEPPED_FIXED_GLOBAL_REWARD |\n | VARIABLE_GLOBAL_REWARD |\n | VARIABLE_CREDIT_REWARD |\n\n @motivating\n Scenario: Users who selected a fixed exchange rule see exchange information on the Select page\n Given a \"FIXED_GLOBAL_REWARD\" exchange rule\n And it has the following fields\n | fields |\n | name |\n | description |\n | image |\n When a user views the reward exchange list\n And they progress to the Select page for this exchange\n Then they see the exchange rule image on the left hand side\n And on the right hand side they see the following in this order from top to bottom\n | elements |\n | exchange name |\n | exchange source pretty value displayed in brand colour |\n | exchange description |\n\n @motivating\n Scenario Outline: Users selection variable rewards can only select rewards they are eligible to exchange for\n Given a <type> exchange rule\n When a user views the reward exchange list\n And they progress to the Select page for this exchange\n Then they see a drop down with all the reward exchange selections\n When they click on the drop down\n But they are not eligible for all of the exchanges options <dueToReason>\n Then the ineligble options are disabled\n And under the source value is <text>\n Examples:\n | type | dueToReason | text |\n | STEPPED_FIXED_GLOBAL_REWARD | due to insufficent source value | {prettySourceValue} required |\n | VARIABLE_GLOBAL_REWARD | due to insufficent source value | {prettySourceValue} required |\n | VARIABLE_CREDIT_REWARD | due to insufficent source value | {prettySourceValue} required |\n | STEPPED_FIXED_GLOBAL_REWARD | W9 | US Tax Limit |\n | VARIABLE_GLOBAL_REWARD | W9 | US Tax Limit |\n | VARIABLE_CREDIT_REWARD | W9 | US Tax Limit |\n\n @motivating\n Scenario Outline: The Confirm page allows users to view their exchange before committing\n Given a <type> exchange rule\n When a user views the reward exchange list\n And they select the exchange\n And they progress to Confirm page\n Then they see a row with title \"Reward\"\n And it contains the exchange name\n And it contains the exchange image\n And they <maySee> a row with title \"Reward Amount\"\n And it <mayContain> <amountTitle>\n And they see a row with title \"Cost to Redeem\"\n And it contains the source reward pretty value in bolded text\n Examples:\n | type | maySee | mayContain | amountTitle |\n | FIXED_GLOBAL_REWARD | don't | doesn't contain | N/A |\n | VARIABLE_GLOBAL_REWARD | see | contains | the pretty destination value |\n | STEPPED_FIXED_GLOBAL_REWARD | see | contains | the pretty destination value |\n | VARIABLE_CREDIT_REWARD | see | contains | the pretty destination value |\n\n @motivating\n Scenario: An error banner is displayed if an error occurs during redemeption\n Given a user has selected a reward to exchange\n And is on the confirmation page\n When they click \"Redeem\"\n But an error occurs\n Then an error banner appears\n And it contains details about the error\n And the reward exchange is not completed\n\n @motivating\n Scenario: Confetti is displayed when a reward exchange succeeds\n Given a user has selected a reward to exchange\n And they are on the confirmation page\n When they click \"Redeem\"\n And the exchange is successful\n Then they see confetti centered on the success page\n And they see text describing what they exchanged for their new reward\n And they see a \"Done\" brand colour button\n When they click \"Done\"\n Then they see the Rewards page\n\n @motivating\n Scenario: Fuel tank codes are shown when a reward exchange succeeds\n Given a user has selected to exchange for a fuel tank reward\n When they complete the reward exchange\n And are on the success page\n Then they see a textbox with their fuel tank code\n And a clipboard icon\n When they click the clipboard icon\n Then their fuel tank code is copied to their clipboard\n\n @motivating\n Scenario Outline: Users can exchange for any type of reward\n Given a <type> reward exchange rule for a <reward>\n And a user who has enough source credit to exchange for the reward\n When they go through the exchange flow\n And exchange for their reward\n Then their credit is exchanged for the <reward>\n Examples:\n | type | reward |\n | FIXED_GLOBAL_REWARD | gift card |\n | FIXED_GLOBAL_REWARD | fuel tank code |\n | FIXED_GLOBAL_REWARD | discount |\n | FIXED_GLOBAL_REWARD | credit reward |\n | STEPPED_FIXED_GLOBAL_REWARD | gift card |\n | STEPPED_FIXED_GLOBAL_REWARD | discount |\n | STEPPED_FIXED_GLOBAL_REWARD | credit reward |\n | VARIABLE_GLOBAL_REWARD | gift card |\n | VARIABLE_GLOBAL_REWARD | discount |\n | VARIABLE_GLOBAL_REWARD | credit reward |\n | VARIABLE_CREDIT_REWARD | credit reward |";
10556
+ const scenario$l = "@author:derek\n@owner:derek\nFeature: Reward Exchange List\n\n The Reward Exchange List gives end users the power to exchange their rewards for other rewards.\n It populates a list from the reward exchange rules set up on a given tenant.\n\n Background:\n Given a tenant with reward exchange rules\n\n @motivating\n @ui\n Scenario: The empty state is shown if there are no visible exchanges\n Given a user with no visible exchanges\n When they view the reward exchange\n Then no exchange options are displayed\n And they see an image of a present\n And \"Redeem Rewards\" in bold\n And \"Use your points to redeem rewards once they become available\" below the bolded text\n And the pagination buttons are disabled\n\n @minutae\n @ui\n Scenario: A custom empty state can be provided\n Given a user with no visible exchanges\n And a custom empty state has been supplied in the \"empty\" slot\n When they view the reward exchange\n Then they see the custom empty state\n\n @motivating\n @ui\n Scenario: A Loading Skeleton is displayed when the reward exchange rules are loading\n Given a user\n When they load the reward exchange list\n Then they see a loading Skeleton\n And it has 8 skeleton cards\n When the reward exchange rules have loaded\n Then the skeleton is replaced with reward exchange options\n\n @motivating\n Scenario: An error banner appears when the reward exchange list fails to load\n Given a user trying to view the reward exchange list\n But it fails to load\n Then an error banner is displayed\n And it displays \"Unable to load reward exchange list. Please try again\"\n\n @motivating\n @ui\n Scenario: The exchange progress bar progresses through the exchange process\n Given a user who is eligible for the tenants reward exchange rules\n When they view the reward exchange list\n Then the process bar displays the following elements\n | elements |\n | Step 1 `Rewards` title in black |\n | Step 1 circle with green outline, white fill and number 1 in green |\n | Step 2 `Select` title in grey |\n | Step 2 circle with grey fill and number 2 in white |\n | Step 3 `Confirm` title in grey |\n | Step 3 circle with grey fill and number 3 in white |\n | lines between all steps are greyed out |\n When they continue to the selection page\n Then the progress bar displays the following elements\n | elements |\n | Step 1 `Rewards` title in black |\n | Step 1 circle with white checkmark and green fill |\n | Step 2 `Select` title in black |\n | Step 2 circle with green outline, white fill and number 2 in green |\n | Step 3 `Confirm` title in grey |\n | Step 3 circle with grey fill and number 3 in white |\n | Green line between step 1 and 2 |\n | Grey line between step 2 and 3 |\n When they continue to the confirmation page\n Then the progress bar displays the following elements\n | elements |\n | Step 1 `Rewards` title in black |\n | Step 1 circle with white checkmark and green fill |\n | Step 2 `Select` title in black |\n | Step 2 circle with white checkmark and green fill |\n | Step 3 `Confirm` title in black |\n | Step 3 circle with green outline, white fill and number 3 in green |\n | Green line between all steps |\n When they continue to the redemption page\n Then the progress bar displays the following elements\n | elements |\n | Step 1 `Rewards` title in black |\n | Step 1 circle with white checkmark and green fill |\n | Step 2 `Select` title in black |\n | Step 2 circle with white checkmark and green fill |\n | Step 3 `Confirm` title in black |\n | Step 3 circle with white checkmark and green fill |\n | Green line between all steps |\n\n @motivating\n Scenario: Users must choose a reward exchange option to continue to the selection page\n Given a user who is eligible for the tenants reward exchange rules\n When they view the reward exchange list\n Then the 'Continue' button is disabled\n When they select a reward exchange card\n Then the card is outlined in brand colour with a brand colour cirlcular check box icon in the top right\n And the continue button is no longer disabled\n When they click \"Continue\"\n Then they are brought to the selection page\n\n @motivating\n @ui\n Scenario: Reward exchange rule names and images are used in the reward exchange cards\n Given a tenant reward exchange rule\n And it has name \"My Visa Exchange Rule\"\n And it has an image\n When a user views the reward exchange list\n Then they see a exchange card with title \"My Visa Exchange Rule\"\n And the exchange image on the left hand side of the card\n\n @motivating\n Scenario Outline: Reward exchange source values are displayed on reward exchange cards\n Given a <type> reward exchange rule\n When a user views the reward exchange list\n Then they see <text> under the name on the exchange option cards\n And the pretty values are localized to a user locale\n Examples:\n | type | text |\n | FIXED_GLOBAL_REWARD | the exchange source pretty value |\n | STEPPED_FIXED_GLOBAL_REWARD | the exchange source min pretty value to the source max pretty value |\n | VARIABLE_GLOBAL_REWARD | the exchange source min pretty value to the source max pretty value |\n | VARIABLE_CREDIT_REWARD | the exchange source min pretty value to the source max pretty value |\n\n @motivating\n Scenario Outline: Reward exchange cards can display customized error messages\n Given a reward exchange rule\n And it has <availabilityPredicate>\n And the reward exchange list has prop \"not-available-error\" with <value>\n When the user views the reward exchange list\n Then the card for the reward exchange rule is disabled\n And <message> is displayed\n Examples:\n | availabilityPredicate | value | message |\n | 'champion' in user.segments ? \"NOT_CHAMPION\" : true | {unavailableReasonCode, select, NOT_CHAMPION {Sorry must be a champion!} other {unavailableReasonCode} } | Sorry must be a champion! |\n | user.customFields.purchaseCount < 10 ? \"MORE_PURCHASE\" : true | {unavailableReasonCode, select, MORE_PURCHASE {Complete 10 purchases to unlock} other {unavailableReasonCode} } | Complete 10 purchases to unlock |\n\n @motivating\n Scenario: Exchange options are disabled if they put a user over the W9 limit\n Given a user who is approaching their W9 limit\n And a reward exchange rule\n And its destination reward has a US taxable value that would put the user over their limit\n When they view the reward exchange list\n Then the reward exchange card is disabled\n And a \"US Tax Limit\" error message is displayed on to the right of a exclamation triangle icon\n And the text is orange\n And the icon is orange\n\n @motivating\n Scenario Outline: Exchange options are disabled if a users lacks enough credit to redeem\n Given a <type> reward exchange rule\n But the user lacks enough credit to exchange for it\n When they view the reward exchange list\n Then the reward exchange card is disabled\n And a <text> error message is displayed on to the right of a exclamation triangle icon\n And the text is orange\n And the icon is orange\n Examples:\n | type | text |\n | FIXED_GLOBAL_REWARD | {prettySourceValue} required |\n | STEPPED_FIXED_GLOBAL_REWARD | {prettySourceMinValue} required |\n | VARIABLE_GLOBAL_REWARD | {prettySourceMinValue} required |\n | VARIABLE_CREDIT_REWARD | {prettySourceMinValue} required |\n\n @motivating\n Scenario: Users can go back to the Rewards page from the Select page\n Given a user viewing the Select page\n Then they see a \"Cancel\" text button\n And a \"Continue to confirmation\" brand colour button in the bottom right corner\n When they click \"Cancel\"\n Then they return to the Rewards page\n\n @motivating\n Scenario: Users can go back to the Select Page from the Confirm page\n Given a user viewing the Confirm page\n Then they see a \"Back\" text button\n And a \"Redeem\" brand colour button in the bottom right corner\n When they click \"Back\"\n Then they return to the Select Page\n\n @motivating\n Scenario: Reward rules with visibility predicates that evaluates to false are not shown\n Given a tenant reward exchange rule with visibility predicates that evaluates to false\n When a user views the reward exchange list\n Then they do not see the card for that reward exchange rule\n\n @motivating\n Scenario Outline: Users can choose their reward option for variable rewards on the Select page\n Given a <type> exchange rule\n And it has the following fields\n | fields |\n | name |\n | description |\n | image |\n When a user views the reward exchange list\n And they progress to the Select page for this exchange\n Then they see the exchange rule image on the left hand side\n And on the right hand side they see the following in this order from top to bottom\n | elements |\n | exchange name |\n | exchange description |\n | select list with all exchange options using pretty values, destination reward above source reward |\n Examples:\n | type |\n | STEPPED_FIXED_GLOBAL_REWARD |\n | VARIABLE_GLOBAL_REWARD |\n | VARIABLE_CREDIT_REWARD |\n\n @motivating\n Scenario: Users who selected a fixed exchange rule see exchange information on the Select page\n Given a \"FIXED_GLOBAL_REWARD\" exchange rule\n And it has the following fields\n | fields |\n | name |\n | description |\n | image |\n When a user views the reward exchange list\n And they progress to the Select page for this exchange\n Then they see the exchange rule image on the left hand side\n And on the right hand side they see the following in this order from top to bottom\n | elements |\n | exchange name |\n | exchange source pretty value displayed in brand colour |\n | exchange description |\n\n @motivating\n Scenario Outline: Users selection variable rewards can only select rewards they are eligible to exchange for\n Given a <type> exchange rule\n When a user views the reward exchange list\n And they progress to the Select page for this exchange\n Then they see a drop down with all the reward exchange selections\n When they click on the drop down\n But they are not eligible for all of the exchanges options <dueToReason>\n Then the ineligble options are disabled\n And under the source value is <text>\n Examples:\n | type | dueToReason | text |\n | STEPPED_FIXED_GLOBAL_REWARD | due to insufficent source value | {prettySourceValue} required |\n | VARIABLE_GLOBAL_REWARD | due to insufficent source value | {prettySourceValue} required |\n | VARIABLE_CREDIT_REWARD | due to insufficent source value | {prettySourceValue} required |\n | STEPPED_FIXED_GLOBAL_REWARD | W9 | US Tax Limit |\n | VARIABLE_GLOBAL_REWARD | W9 | US Tax Limit |\n | VARIABLE_CREDIT_REWARD | W9 | US Tax Limit |\n\n @motivating\n Scenario Outline: The Confirm page allows users to view their exchange before committing\n Given a <type> exchange rule\n When a user views the reward exchange list\n And they select the exchange\n And they progress to Confirm page\n Then they see a row with title \"Reward\"\n And it contains the exchange name\n And it contains the exchange image\n And they <maySee> a row with title \"Reward Amount\"\n And it <mayContain> <amountTitle>\n And they see a row with title \"Cost to Redeem\"\n And it contains the source reward pretty value in bolded text\n Examples:\n | type | maySee | mayContain | amountTitle |\n | FIXED_GLOBAL_REWARD | don't | doesn't contain | N/A |\n | VARIABLE_GLOBAL_REWARD | see | contains | the pretty destination value |\n | STEPPED_FIXED_GLOBAL_REWARD | see | contains | the pretty destination value |\n | VARIABLE_CREDIT_REWARD | see | contains | the pretty destination value |\n\n @motivating\n Scenario: An error banner is displayed if an error occurs during redemeption\n Given a user has selected a reward to exchange\n And is on the confirmation page\n When they click \"Redeem\"\n But an error occurs\n Then an error banner appears\n And it contains details about the error\n And the reward exchange is not completed\n\n @motivating\n Scenario: Confetti is displayed when a reward exchange succeeds\n Given a user has selected a reward to exchange\n And they are on the confirmation page\n When they click \"Redeem\"\n And the exchange is successful\n Then they see confetti centered on the success page\n And they see text describing what they exchanged for their new reward\n And they see a \"Done\" brand colour button\n When they click \"Done\"\n Then they see the Rewards page\n\n @motivating\n Scenario: Fuel tank codes are shown when a reward exchange succeeds\n Given a user has selected to exchange for a fuel tank reward\n When they complete the reward exchange\n And are on the success page\n Then they see a textbox with their fuel tank code\n And a clipboard icon\n When they click the clipboard icon\n Then their fuel tank code is copied to their clipboard\n\n @motivating\n Scenario Outline: Users can exchange for any type of reward\n Given a <type> reward exchange rule for a <reward>\n And a user who has enough source credit to exchange for the reward\n When they go through the exchange flow\n And exchange for their reward\n Then their credit is exchanged for the <reward>\n Examples:\n | type | reward |\n | FIXED_GLOBAL_REWARD | gift card |\n | FIXED_GLOBAL_REWARD | fuel tank code |\n | FIXED_GLOBAL_REWARD | discount |\n | FIXED_GLOBAL_REWARD | credit reward |\n | STEPPED_FIXED_GLOBAL_REWARD | gift card |\n | STEPPED_FIXED_GLOBAL_REWARD | discount |\n | STEPPED_FIXED_GLOBAL_REWARD | credit reward |\n | VARIABLE_GLOBAL_REWARD | gift card |\n | VARIABLE_GLOBAL_REWARD | discount |\n | VARIABLE_GLOBAL_REWARD | credit reward |\n | VARIABLE_CREDIT_REWARD | credit reward |";
10355
10557
 
10356
10558
  const RewardExchangeList_stories = {
10357
10559
  title: "Components/Reward Exchange List",
10358
10560
  parameters: {
10359
- scenario: scenario$k,
10561
+ scenario: scenario$l,
10360
10562
  },
10361
10563
  };
10362
10564
  const StoryBase = (props) => () => {
@@ -10404,12 +10606,12 @@ const RewardExchangeList = /*#__PURE__*/Object.freeze({
10404
10606
  Empty: Empty$2
10405
10607
  });
10406
10608
 
10407
- const scenario$l = "@author:derek\n@owner:derek\nFeature: Program Explainer\n\n @motivating\n @ui\n Scenario Outline: The program explainer wraps program explainer steps and aligns them\n Given a program explainer component\n And it has <number> program explainer steps as components\n When a user views the program explainer\n Then they see <number> steps aligned horizontally\n And they have equal height/width\n And equal padding in between\n When they are viewed on a screen smaller than 500px\n Then the steps stack vertically with equal padding in between\n And they have equal width\n But height may vary\n Examples:\n | number |\n | 2 |\n | 3 |\n | 4 |\n\n @motivating\n @ui\n Scenario: The program explainer displays a section header\n Given a program explainer step with props\n | prop | value |\n | header | My Header |\n And it has program explainer steps as children\n When a user views the program explainer\n Then they see \"My Header\" centered above the explainer steps\n\n @motivating\n @ui\n Scenario: Colours are customizable\n Given a program explainer with props\n | prop | value |\n | text-color | purple |\n | background-color | grey |\n When a user views the program explainer\n Then the header is purple\n And the background between steos is grey\n";
10609
+ const scenario$m = "@author:derek\n@owner:derek\nFeature: Program Explainer\n\n @motivating\n @ui\n Scenario Outline: The program explainer wraps program explainer steps and aligns them\n Given a program explainer component\n And it has <number> program explainer steps as components\n When a user views the program explainer\n Then they see <number> steps aligned horizontally\n And they have equal height/width\n And equal padding in between\n When they are viewed on a screen smaller than 500px\n Then the steps stack vertically with equal padding in between\n And they have equal width\n But height may vary\n Examples:\n | number |\n | 2 |\n | 3 |\n | 4 |\n\n @motivating\n @ui\n Scenario: The program explainer displays a section header\n Given a program explainer step with props\n | prop | value |\n | header | My Header |\n And it has program explainer steps as children\n When a user views the program explainer\n Then they see \"My Header\" centered above the explainer steps\n\n @motivating\n @ui\n Scenario: Colours are customizable\n Given a program explainer with props\n | prop | value |\n | text-color | purple |\n | background-color | grey |\n When a user views the program explainer\n Then the header is purple\n And the background between steos is grey\n";
10408
10610
 
10409
10611
  const ProgramExplainer_stories = {
10410
10612
  title: "Components/Program Explainer",
10411
10613
  parameters: {
10412
- scenario: scenario$l,
10614
+ scenario: scenario$m,
10413
10615
  },
10414
10616
  };
10415
10617
  const OneStep = () => {
@@ -10465,12 +10667,12 @@ const ProgramExplainer = /*#__PURE__*/Object.freeze({
10465
10667
  ProgramExplainerGeneric: ProgramExplainerGeneric
10466
10668
  });
10467
10669
 
10468
- const scenario$m = "@author:derek\n@owner:derek\nFeature: Program Explainer Step\n\n @motivating\n @ui\n Scenario: The program explainer step displays a icon, header and description\n Given a program explainer step with props\n | prop | value |\n | header | My Header |\n | description | My program explainer description |\n | icon | person-plus-fill |\n When a user views the explainer step\n Then they see an person icon with a + in the top left hand corner\n And the icon is weight 300 brand colour\n And below they see \"My Header\" in large bold font\n And below they see \"My program explainer description\" in medium font\n And the step background colour is weight 50 brand colour\n\n @motivating\n @ui\n Scenario: The program explainer can display an image in place of an icon\n Given a program explainer\n And it has an \"image-url\" prop with a value of a valid url to an image\n When a user views the explainer step\n Then the image is displayed in place of an incon in the top left hand corner\n\n @motivating\n @ui\n Scenario: Colours are customizable\n Given a program explainer step with props\n | prop | value |\n | text-color | purple |\n | background-color | grey |\n When a user views the explainer step\n Then they see the step background is grey\n And the header text is purple\n And the description text is purple\n";
10670
+ const scenario$n = "@author:derek\n@owner:derek\nFeature: Program Explainer Step\n\n @motivating\n @ui\n Scenario: The program explainer step displays a icon, header and description\n Given a program explainer step with props\n | prop | value |\n | header | My Header |\n | description | My program explainer description |\n | icon | person-plus-fill |\n When a user views the explainer step\n Then they see an person icon with a + in the top left hand corner\n And the icon is weight 300 brand colour\n And below they see \"My Header\" in large bold font\n And below they see \"My program explainer description\" in medium font\n And the step background colour is weight 50 brand colour\n\n @motivating\n @ui\n Scenario: The program explainer can display an image in place of an icon\n Given a program explainer\n And it has an \"image-url\" prop with a value of a valid url to an image\n When a user views the explainer step\n Then the image is displayed in place of an incon in the top left hand corner\n\n @motivating\n @ui\n Scenario: Colours are customizable\n Given a program explainer step with props\n | prop | value |\n | text-color | purple |\n | background-color | grey |\n When a user views the explainer step\n Then they see the step background is grey\n And the header text is purple\n And the description text is purple\n";
10469
10671
 
10470
10672
  const ProgramExplainerStep_stories = {
10471
10673
  title: "Components/Program Explainer Step",
10472
10674
  parameters: {
10473
- scenario: scenario$m,
10675
+ scenario: scenario$n,
10474
10676
  },
10475
10677
  };
10476
10678
  const ProgramExplainerStep = () => {
@@ -10487,12 +10689,12 @@ const ProgramExplainerStep$1 = /*#__PURE__*/Object.freeze({
10487
10689
  ProgramExplainerStepCustom: ProgramExplainerStepCustom
10488
10690
  });
10489
10691
 
10490
- const scenario$n = "@author:derek\n@owner:logan\nFeature: Brand Configuration\n\n\t@motivating\n\tScenario: The brand components creates a colour pallet from a brand colour and applies it to children\n\t\tGiven a brand component with \"brand-color\" \"#4225c4\"\n\t\tAnd it is wrapping several mint components\n\t\tWhen a user views the children components\n\t\tThen the following css variables are set\n\t\t\t| variable | value |\n\t\t\t| --sl-color-primary-50 | hsla(251, 68%, 95%, 1) |\n\t\t\t| --sl-color-primary-100 | hsla(251, 68%, 86%, 1) |\n\t\t\t| --sl-color-primary-200 | hsla(251, 68%, 76%, 1) |\n\t\t\t| --sl-color-primary-300 | hsla(251, 68%, 66%, 1) |\n\t\t\t| --sl-color-primary-400 | hsla(251, 68%, 56%, 1) |\n\t\t\t| --sl-color-primary-500 | hsla(251, 68%, 46%, 1) |\n\t\t\t| --sl-color-primary-600 | hsla(251, 68%, 39%, 1) |\n\t\t\t| --sl-color-primary-700 | hsla(251, 68%, 32%, 1) |\n\t\t\t| --sl-color-primary-800 | hsla(251, 68%, 25%, 1) |\n\t\t\t| --sl-color-primary-900 | hsla(251, 68%, 18%, 1) |\n\t\t\t| --sl-color-primary-950 | hsla(251, 68%, 15%, 1) |\n\t\t\t| --sl-focus-ring-color-primary | var(--sl-color-primary-100) |\n\t\t\t| --sl-input-border-color-focus | var(--sl-color-primary-500) |\n\t\t\t| --sl-color-primary-hue | var(--sl-color-primary-500) |\n\t\tAnd they are applied to the children components\n\t\tBut they are not applied to any components outside of the brand component\n\t\tAnd they are not applied to any vanilla components\n\n\t@minutae\n\tScenario Outline: The brand colour can be hex, HSL or rgb\n\t\tGiven a brand component with \"brand-color\" <colour>\n\t\tAnd it is wrapping several mint components\n\t\tWhen a user views the children components\n\t\tThen the colour is used to create a brand palete\n\t\tAnd it is applied to the children components\n\t\tExamples:\n\t\t\t| colour |\n\t\t\t| #4225c4 |\n\t\t\t| rgb(66, 37, 196) |\n\t\t\t| hsl(251, 68%, 46%) |\n\t\t\t| hsla(251, 68%, 46%, 1) |\n\n\t@motivating\n\tScenario: The brand component can apply a brand font to children components\n\t\tGiven a brand component with \"brand-font\" \"Nunito Sans\"\n\t\tAnd it is wrapping several mint components\n\t\tWhen a user views the children components\n\t\tThen the following css variables are set\n\t\t\t| variable | value |\n\t\t\t| --sl-font-sans | \"Nunito Sans\", arial |\n\t\t\t| --sl-input-font-family | \"Nunito Sans\", arial |\n\t\t\t| --sl-tooltip-font-family | \"Nunito Sans\", arial |\n\t\t\t| font-family | \"Nunito Sans\", arial |\n\t\tAnd they are applied to the children components\n\t\tAnd the children component's text is \"Nunito Sans\"";
10692
+ const scenario$o = "@author:derek\n@owner:logan\nFeature: Brand Configuration\n\n\t@motivating\n\tScenario: The brand components creates a colour pallet from a brand colour and applies it to children\n\t\tGiven a brand component with \"brand-color\" \"#4225c4\"\n\t\tAnd it is wrapping several mint components\n\t\tWhen a user views the children components\n\t\tThen the following css variables are set\n\t\t\t| variable | value |\n\t\t\t| --sl-color-primary-50 | hsla(251, 68%, 95%, 1) |\n\t\t\t| --sl-color-primary-100 | hsla(251, 68%, 86%, 1) |\n\t\t\t| --sl-color-primary-200 | hsla(251, 68%, 76%, 1) |\n\t\t\t| --sl-color-primary-300 | hsla(251, 68%, 66%, 1) |\n\t\t\t| --sl-color-primary-400 | hsla(251, 68%, 56%, 1) |\n\t\t\t| --sl-color-primary-500 | hsla(251, 68%, 46%, 1) |\n\t\t\t| --sl-color-primary-600 | hsla(251, 68%, 39%, 1) |\n\t\t\t| --sl-color-primary-700 | hsla(251, 68%, 32%, 1) |\n\t\t\t| --sl-color-primary-800 | hsla(251, 68%, 25%, 1) |\n\t\t\t| --sl-color-primary-900 | hsla(251, 68%, 18%, 1) |\n\t\t\t| --sl-color-primary-950 | hsla(251, 68%, 15%, 1) |\n\t\t\t| --sl-focus-ring-color-primary | var(--sl-color-primary-100) |\n\t\t\t| --sl-input-border-color-focus | var(--sl-color-primary-500) |\n\t\t\t| --sl-color-primary-hue | var(--sl-color-primary-500) |\n\t\tAnd they are applied to the children components\n\t\tBut they are not applied to any components outside of the brand component\n\t\tAnd they are not applied to any vanilla components\n\n\t@minutae\n\tScenario Outline: The brand colour can be hex, HSL or rgb\n\t\tGiven a brand component with \"brand-color\" <colour>\n\t\tAnd it is wrapping several mint components\n\t\tWhen a user views the children components\n\t\tThen the colour is used to create a brand palete\n\t\tAnd it is applied to the children components\n\t\tExamples:\n\t\t\t| colour |\n\t\t\t| #4225c4 |\n\t\t\t| rgb(66, 37, 196) |\n\t\t\t| hsl(251, 68%, 46%) |\n\t\t\t| hsla(251, 68%, 46%, 1) |\n\n\t@motivating\n\tScenario: The brand component can apply a brand font to children components\n\t\tGiven a brand component with \"brand-font\" \"Nunito Sans\"\n\t\tAnd it is wrapping several mint components\n\t\tWhen a user views the children components\n\t\tThen the following css variables are set\n\t\t\t| variable | value |\n\t\t\t| --sl-font-sans | \"Nunito Sans\", arial |\n\t\t\t| --sl-input-font-family | \"Nunito Sans\", arial |\n\t\t\t| --sl-tooltip-font-family | \"Nunito Sans\", arial |\n\t\t\t| font-family | \"Nunito Sans\", arial |\n\t\tAnd they are applied to the children components\n\t\tAnd the children component's text is \"Nunito Sans\"";
10491
10693
 
10492
10694
  const SqmBrand_stories = {
10493
10695
  title: "Components/Brand",
10494
10696
  parameters: {
10495
- scenario: scenario$n,
10697
+ scenario: scenario$o,
10496
10698
  },
10497
10699
  };
10498
10700
  const SampleComponents = () => (index.h("div", { style: { padding: "10px", border: "5px solid #EEE" } },
@@ -10593,12 +10795,12 @@ const BrandStories = /*#__PURE__*/Object.freeze({
10593
10795
  Fonts: Fonts
10594
10796
  });
10595
10797
 
10596
- const scenario$o = "@author:kutay\n@owner:kutay\nFeature: Card Feed\n\n\tThe Card Feed component displays Task Card components in a grid layout.\n\n\tBackground: A user on the portal is viewing the widget\n\t\tGiven a user viewing the Card Feed component\n\n\t@motivating\n\tScenario: The Card Feed component displays Task Cards given as children slots\n\t\tGiven a Card Feed component\n\t\tAnd it is wrapping a number of task cards as children\n\t\tWhen the user views the Card Feed\n\t\tThen the task cards are displayed in a masonry layout\n\t\tWhen the card feed with grows or shrinks in width\n\t\tThen the number of columns adjust to the given width\n\n\t@motivating\n\t@ui\n\tScenario Outline: The Card Feed component can have a maximum width\n\t\tGiven a Card Feed component\n\t\tAnd it is wrapping a number of task cards as children\n\t\tAnd has prop \"width\" has a provided <value>\n\t\tThen the task cards are displayed in a masonry layout\n\t\tWhen the card feed with grows or shrinks in width\n\t\tThen the number of columns adjust to the given width\n\t\tAnd the task cards do not exceed <width>\n\t\tExamples:\n\t\t\t| value | width |\n\t\t\t| | 347px |\n\t\t\t| 200 | 200px |\n\t\t\t| 400 | 400px |\n\n\t@motivating\n\t@ui\n\tScenario Outline: The Card Feed component gap between task cards can be customized\n\t\tGiven a Card Feed component\n\t\tAnd it is wrapping a number of task cards as children\n\t\tAnd has prop \"gap\" has a provided <value>\n\t\tThen the task cards are displayed in a masonry layout\n\t\tAnd the gap between the columns is the <gap>\n\t\tExamples:\n\t\t\t| value | gap |\n\t\t\t| | 24px |\n\t\t\t| 20 | 20px |\n\t\t\t| 50 | 50px |";
10798
+ const scenario$p = "@author:kutay\n@owner:kutay\nFeature: Card Feed\n\n\tThe Card Feed component displays Task Card components in a grid layout.\n\n\tBackground: A user on the portal is viewing the widget\n\t\tGiven a user viewing the Card Feed component\n\n\t@motivating\n\tScenario: The Card Feed component displays Task Cards given as children slots\n\t\tGiven a Card Feed component\n\t\tAnd it is wrapping a number of task cards as children\n\t\tWhen the user views the Card Feed\n\t\tThen the task cards are displayed in a masonry layout\n\t\tWhen the card feed with grows or shrinks in width\n\t\tThen the number of columns adjust to the given width\n\n\t@motivating\n\t@ui\n\tScenario Outline: The Card Feed component can have a maximum width\n\t\tGiven a Card Feed component\n\t\tAnd it is wrapping a number of task cards as children\n\t\tAnd has prop \"width\" has a provided <value>\n\t\tThen the task cards are displayed in a masonry layout\n\t\tWhen the card feed with grows or shrinks in width\n\t\tThen the number of columns adjust to the given width\n\t\tAnd the task cards do not exceed <width>\n\t\tExamples:\n\t\t\t| value | width |\n\t\t\t| | 347px |\n\t\t\t| 200 | 200px |\n\t\t\t| 400 | 400px |\n\n\t@motivating\n\t@ui\n\tScenario Outline: The Card Feed component gap between task cards can be customized\n\t\tGiven a Card Feed component\n\t\tAnd it is wrapping a number of task cards as children\n\t\tAnd has prop \"gap\" has a provided <value>\n\t\tThen the task cards are displayed in a masonry layout\n\t\tAnd the gap between the columns is the <gap>\n\t\tExamples:\n\t\t\t| value | gap |\n\t\t\t| | 24px |\n\t\t\t| 20 | 20px |\n\t\t\t| 50 | 50px |";
10597
10799
 
10598
10800
  const CardFeed_stories = {
10599
10801
  title: "Components/Card Feed",
10600
10802
  parameters: {
10601
- scenario: scenario$o,
10803
+ scenario: scenario$p,
10602
10804
  },
10603
10805
  };
10604
10806
  const oneAction$1 = {
@@ -10835,12 +11037,12 @@ const CardFeed = /*#__PURE__*/Object.freeze({
10835
11037
  CardFeedGeneric: CardFeedGeneric
10836
11038
  });
10837
11039
 
10838
- const scenario$p = "@author:kutay\n@owner:noah\nFeature: Portal Container\n\n\t@motivating\n\t@ui\n\tScenario: Horizontal content overflows, but does not stretch\n\t\tGiven there are two element in the container\n\t\tAnd the first is small\n\t\tAnd the second would stretch the container wider than it's parent\n\t\tThen the second one is clipped\n\t\tAnd the first one doesn't stretch\n\n\t@landmine\n\t@ui\n\tScenario: `max-width` is required for displaying as a row\n\t\tGiven I have `direction` to \"row\"\n\t\tAnd I have not set a `max-width`\n\t\tThen it displays as a column\n\n\t@motivating\n\t@ui\n\tScenario Outline: Content padding can be customized\n\t\tGiven prop \"padding\" has <value>\n\t\tThen <padding> is applied to content\n\n\t\tExamples:\n\t\t\t| value | padding |\n\t\t\t| none | no padding |\n\t\t\t| xxx-small | xxx-small |\n\t\t\t| xx-small | xx-small |\n\t\t\t| x-small | x-small |\n\t\t\t| small | small |\n\t\t\t| medium | medium |\n\t\t\t| large | large |\n\t\t\t| x-large | x-large |\n\t\t\t| xx-large | xx-large |\n\t\t\t| xxx-large | xxx-large |\n\t\t\t| xxxx-large | xxxx-large |\n\t\t\t| N/A | no padding |\n\n\n\t@motivating\n\t@ui\n\tScenario Outline: Gap between content elements can be customized\n\t\tGiven prop \"gap\" has <value>\n\t\tThen <gap> is applied to elements between content\n\n\t\tExamples:\n\t\t\t| value | gap |\n\t\t\t| none | no padding |\n\t\t\t| xxx-small | xxx-small |\n\t\t\t| xx-small | xx-small |\n\t\t\t| x-small | x-small |\n\t\t\t| small | small |\n\t\t\t| medium | medium |\n\t\t\t| large | large |\n\t\t\t| x-large | x-large |\n\t\t\t| xx-large | xx-large |\n\t\t\t| xxx-large | xxx-large |\n\t\t\t| xxxx-large | xxxx-large |\n\t\t\t| N/A | no padding |\n\n\t@minutae\n\t@ui\n\tScenario: Content can be center aligned in horizontal view\n\t\tGiven I have supplied the prop \"center\"\n\t\tThen the content is center aligned\n\n\t@minutae\n\t@ui\n\tScenario: Content in the last row can span full width with display in horizontal view\n\t\tGiven I have `display` to \"flex\"\n\t\tThen the content is full width on the last row\n\n\t@motivating\n\t@ui\n\tScenario Outline: Content can be aligned along the x-axis \n\t\tGiven prop \"justify-content\" has <value>\n\t\tThen content within the container is aligned <alignment>\n\n\t\tExamples:\n\t\t\t| value | alignment |\n\t\t\t| none | no alignment |\n\t\t\t| start | to the start |\n\t\t\t| center | to the center |\n\t\t\t| end | to the end |\n\t\t\t| space-between | with space between |\n\t\t\t| space-around | with space around |\n\t\t\t| space-evenly | with space evenly |";
11040
+ const scenario$q = "@author:kutay\n@owner:noah\nFeature: Portal Container\n\n\t@motivating\n\t@ui\n\tScenario: Horizontal content overflows, but does not stretch\n\t\tGiven there are two element in the container\n\t\tAnd the first is small\n\t\tAnd the second would stretch the container wider than it's parent\n\t\tThen the second one is clipped\n\t\tAnd the first one doesn't stretch\n\n\t@landmine\n\t@ui\n\tScenario: `max-width` is required for displaying as a row\n\t\tGiven I have `direction` to \"row\"\n\t\tAnd I have not set a `max-width`\n\t\tThen it displays as a column\n\n\t@motivating\n\t@ui\n\tScenario Outline: Content padding can be customized\n\t\tGiven prop \"padding\" has <value>\n\t\tThen <padding> is applied to content\n\n\t\tExamples:\n\t\t\t| value | padding |\n\t\t\t| none | no padding |\n\t\t\t| xxx-small | xxx-small |\n\t\t\t| xx-small | xx-small |\n\t\t\t| x-small | x-small |\n\t\t\t| small | small |\n\t\t\t| medium | medium |\n\t\t\t| large | large |\n\t\t\t| x-large | x-large |\n\t\t\t| xx-large | xx-large |\n\t\t\t| xxx-large | xxx-large |\n\t\t\t| xxxx-large | xxxx-large |\n\t\t\t| N/A | no padding |\n\n\n\t@motivating\n\t@ui\n\tScenario Outline: Gap between content elements can be customized\n\t\tGiven prop \"gap\" has <value>\n\t\tThen <gap> is applied to elements between content\n\n\t\tExamples:\n\t\t\t| value | gap |\n\t\t\t| none | no padding |\n\t\t\t| xxx-small | xxx-small |\n\t\t\t| xx-small | xx-small |\n\t\t\t| x-small | x-small |\n\t\t\t| small | small |\n\t\t\t| medium | medium |\n\t\t\t| large | large |\n\t\t\t| x-large | x-large |\n\t\t\t| xx-large | xx-large |\n\t\t\t| xxx-large | xxx-large |\n\t\t\t| xxxx-large | xxxx-large |\n\t\t\t| N/A | no padding |\n\n\t@minutae\n\t@ui\n\tScenario: Content can be center aligned in horizontal view\n\t\tGiven I have supplied the prop \"center\"\n\t\tThen the content is center aligned\n\n\t@minutae\n\t@ui\n\tScenario: Content in the last row can span full width with display in horizontal view\n\t\tGiven I have `display` to \"flex\"\n\t\tThen the content is full width on the last row\n\n\t@motivating\n\t@ui\n\tScenario Outline: Content can be aligned along the x-axis \n\t\tGiven prop \"justify-content\" has <value>\n\t\tThen content within the container is aligned <alignment>\n\n\t\tExamples:\n\t\t\t| value | alignment |\n\t\t\t| none | no alignment |\n\t\t\t| start | to the start |\n\t\t\t| center | to the center |\n\t\t\t| end | to the end |\n\t\t\t| space-between | with space between |\n\t\t\t| space-around | with space around |\n\t\t\t| space-evenly | with space evenly |";
10839
11041
 
10840
11042
  const PortalContainer_stories = {
10841
11043
  title: "Components/Portal Container",
10842
11044
  parameters: {
10843
- scenario: scenario$p,
11045
+ scenario: scenario$q,
10844
11046
  },
10845
11047
  };
10846
11048
  const TooWideColumn = () => (index.h("div", { style: { width: "200px", border: "1px dashed grey" } },
@@ -10982,11 +11184,11 @@ const scenario3 = "@author:derek\n@owner:derek\nFeature: Reward Table Status Col
10982
11184
 
10983
11185
  const scenario4 = "@author:derek\n@owner:derek\nFeature: Reward Table Source Column\n\n Shows the source of each reward\n\n @motivating\n @ui\n Scenario Outline: The title of the source column is configurable\n Given the \"column-title\" prop is set to <value>\n Then the source column is shown with <columnTitle>\n Examples:\n | value | columnTitle |\n | Source | |\n | My column title | My column title |\n\n @motivating\n @ui\n Scenario: The source column displays manual if the reward is caused by a manual action\n Given a user with a \"MANUAL\" reward\n When they view the rewards table\n Then the source of their reward is displayed as \"Manual\"\n\n @motivating\n @ui\n Scenario: The source column displays the program name if the reward is caused automatically by a program\n Given a user with a \"AUTOMATED\" program reward\n And the program has name \"Loyalty Program\"\n When they view the rewards table\n Then the source of their reward is displayed as \"Loyalty Program\"\n\n @motivating\n @ui\n Scenario Outline: The source column displays customizable reward exchange text with amount if the reward is caused by reward exchange\n Given the \"reward-exchange-text\" prop is <propValue>\n And a user with a \"MANUAL\" reward\n But it was created by a reward exchange\n Then they view the rewards table\n Then the source displays <exchangeText>\n And under it displays the following\n | prettyRedeemedCredit → prettyValue |\n Examples:\n | propValue | exchangeText |\n | | Reward Exchange |\n | Exchanged | Exchanged |\n\n @motivating\n @ui\n Scenario Outline: The source column displays customizable referral information if the reward is from a referral\n Given the \"reward-source-text\" prop is <propValue>\n And a user with a referral reward\n And that reward has <rewardSource>\n When they view the rewards table\n Then then source displays <referralText>\n And under it displays the full name of the <referralUser>\n Examples:\n | propValue | rewardSource | referralText | referralUser |\n | | REFERRED | Referred by | referrer user |\n | | FRIEND_SIGNUP | Referral to | referred user |\n | {rewardSource, select, FRIEND_SIGNUP {You Referred} REFERRED {Referred you} other {}} | REFERRED | Referred you | referrer user |\n | {rewardSource, select, FRIEND_SIGNUP {You Referred} REFERRED {Referred you} other {}} | FRIEND_SIGNUP | You Referred | referred user |\n\n @motivating\n @ui\n Scenario Outline: The source column displays the existing name for a referral if either the first name or last name does not exist\n Given a user with a referral reward\n And referral user exists\n And referral user has <name>\n But referral user has no <otherName>\n When they view the rewards table\n Then referral user's name is displayed as <name>\n Examples:\n | name | otherName |\n | first.name | last.name |\n | last.name | first.name |\n\n @motivating\n @ui\n Scenario Outline: The source column displays referral as \"Anonymous User\" if the referral user has no names\n Given a user with a referral reward\n And that reward has <rewardSource>\n And the <referralUser> has no first name\n And the <referralUser> has no last name\n When they view the rewards table\n Then then source displays <sourceText>\n And under it displays \"Anonymous User\"\n Examples:\n | rewardSource | referralUser | sourceText |\n | FRIEND_SIGNUP | referrer | Referral to |\n | REFERRED | referred user | Referred by |\n\n @motivating\n @ui\n Scenario Outline: The source column displays referral as \"Deleted User\" if the referral user is deleted in the system\n Given a user with a referral reward\n And that reward has <rewardSource>\n But <referral> user was deleted\n When they view the rewards table\n Then the source displays <sourceText>\n And under it displays \"Deleted User\"\n Examples:\n | rewardSource | referral | sourceText |\n | \"FRIEND_SIGNUP\" | referrer | Referral to |\n | \"REFERRED\" | referred | Referred by |\n\n @minutae\n @ui\n Scenario Outline: Name fallbacks for referral users without names are customizable\n Given <prop> with <value>\n And a user with a referral reward\n But the referral user <hadAction>\n When they view the rewards table\n Then the source displays <value> as the referral user\n Examples:\n | prop | value | hadAction |\n | deleted-user | Former Customer | was deleted |\n | anonymous-user | Nameless User | had first and last name deleted |\n\n @motivating\n Scenario Outline: Source text can be customized\n Given the \"reward-source-text\" prop is \"{rewardSource, select, MANUAL {Support} AUTOMATED {Loyalty Program} other {}}\"\n And a user with a <rewardSource> reward\n When they view the rewards table\n Then the source is <sourceText>\n Examples:\n | rewardSource | sourceText |\n | MANUAL | Support |\n | AUTOMATED | Loyalty Program |";
10984
11186
 
10985
- const scenario$q = scenario1 + scenario2 + scenario3 + scenario4;
11187
+ const scenario$r = scenario1 + scenario2 + scenario3 + scenario4;
10986
11188
  const RewardsTableCell_stories = {
10987
11189
  title: "Components/Rewards Table Cell",
10988
11190
  parameters: {
10989
- scenario: scenario$q,
11191
+ scenario: scenario$r,
10990
11192
  },
10991
11193
  };
10992
11194
  const rewardsData$1 = {
@@ -11284,12 +11486,12 @@ const RewardsTableCell = /*#__PURE__*/Object.freeze({
11284
11486
  EmptyCell: EmptyCell$2
11285
11487
  });
11286
11488
 
11287
- const scenario$r = "@owner:sam\n@author:sam\nFeature: Rewards Table\n\n Shows a list of rewards as a table\n\n @motivating\n @ui\n Scenario: The empty state is shown if there are no rewards\n Given a user with rewards\n When they view the reward table\n Then no rewards are displayed\n And they see an image with a user icon\n And \"View your rewards\" in bold\n And \"See all the rewards you have earned from referring friends and completing tasks\" below the bolded text\n And the pagination buttons are disabled\n\n @minutae\n @ui\n Scenario: A custom empty state can be provided\n Given a user with no rewards\n And a custom empty state has been supplied in the \"empty\" slot\n When they view the reward table\n Then they see the custom empty state\n\n @minutae\n @ui\n Scenario: The loading state is shown while rewards are loading\n Given the table is loading\n Then the loading state is shown in the table\n And a custom loading state can be supplied in the \"loading\" slot\n And the pagination buttons are disabled\n\n @motivating\n @ui\n Scenario Outline: The table becomes paginated when the number of rewards exceeds the per page limit\n Given the user has <number of rewards>\n And the table is configured to show <page limit> rewards per page\n Then the table will have <number of pages> page(s)\n And pagination buttons will allow users to navigate between pages\n And the pagination button to go to the next page is disabled on the last page of rewards\n And the pagination button to go to the previous page is disabled on the first page of rewards\n Examples:\n | number of rewards | page limit | number of pages |\n | 0 | 4 | 1 |\n | 1 | 4 | 1 |\n | 3 | 4 | 1 |\n | 5 | 4 | 2 |\n | 42 | 4 | 11 |\n\n @motivating\n @ui\n Scenario: The table converts to a card view on tablet and mobile window sizes\n Given a user with rewards\n When they view the table\n And their window size is smaller than \"799px\"\n Then rewards are displayed as cards\n And they are in two columns\n When their window size is smaller than \"599px\"\n Then the rewards are displayed as cards in a singular column\n\n @motivating\n @ui\n Scenario: Table and Mobile beakpoints can be configured\n Given the reward table has been configured with the following props\n | prop | value |\n | smBreakpoint | 599 |\n | mdBreakpoint | 799 |\n And a user with rewards\n When they view the table\n And their window size is smaller than \"799px\"\n Then rewards are displayed as cards\n And they are in two columns\n When their window size is smaller than \"599px\"\n Then the rewards are displayed as cards in a singular column\n\n @motivating\n @ui\n Scenario Outline: By default the first column heading is hidden in mobile\n Given a reward table with 4 columns\n And prop \"hidden-columns\" with <hideColumnValue>\n And a user with rewards\n When they view the reward table\n And their window size is below the tablet breakpoint\n Then reward cards are displayed\n And the titles of <columnsArehidden> within the card\n Examples:\n | hideColumnValue | columnsArehidden |\n | | the first column |\n | 0,1,2 | the first, second and third columns |\n | 3 | the fourth column |\n\n @motivating\n Scenario: Only rewards which occured in the program specific by \"program-id\" are shown\n Given the table is configured with \"program-id\"\n Then only rewards from the program with \"program-id\" are shown\n\n @landmine\n Scenario: When a `classic` program Id is set then any reward without a programId is shown\n There is no easy way for the backend to filter for \"classic\" programs,\n thus we are filtering for rewards without programId's.\n\n Given the \"program-id\" of the table is set to \"classic\"\n Then rewards from classic programs are shown\n And manual rewards are shown\n\n @minutae\n @ui\n Scenario: Column heading can be hidden\n Given the table is configured with \"show-labels\" set to false\n Then the table is displayed without column headings";
11489
+ const scenario$s = "@owner:sam\n@author:sam\nFeature: Rewards Table\n\n Shows a list of rewards as a table\n\n @motivating\n @ui\n Scenario: The empty state is shown if there are no rewards\n Given a user with rewards\n When they view the reward table\n Then no rewards are displayed\n And they see an image with a user icon\n And \"View your rewards\" in bold\n And \"See all the rewards you have earned from referring friends and completing tasks\" below the bolded text\n And the pagination buttons are disabled\n\n @minutae\n @ui\n Scenario: A custom empty state can be provided\n Given a user with no rewards\n And a custom empty state has been supplied in the \"empty\" slot\n When they view the reward table\n Then they see the custom empty state\n\n @minutae\n @ui\n Scenario: The loading state is shown while rewards are loading\n Given the table is loading\n Then the loading state is shown in the table\n And a custom loading state can be supplied in the \"loading\" slot\n And the pagination buttons are disabled\n\n @motivating\n @ui\n Scenario Outline: The table becomes paginated when the number of rewards exceeds the per page limit\n Given the user has <number of rewards>\n And the table is configured to show <page limit> rewards per page\n Then the table will have <number of pages> page(s)\n And pagination buttons will allow users to navigate between pages\n And the pagination button to go to the next page is disabled on the last page of rewards\n And the pagination button to go to the previous page is disabled on the first page of rewards\n Examples:\n | number of rewards | page limit | number of pages |\n | 0 | 4 | 1 |\n | 1 | 4 | 1 |\n | 3 | 4 | 1 |\n | 5 | 4 | 2 |\n | 42 | 4 | 11 |\n\n @motivating\n @ui\n Scenario: The table converts to a card view on tablet and mobile window sizes\n Given a user with rewards\n When they view the table\n And their window size is smaller than \"799px\"\n Then rewards are displayed as cards\n And they are in two columns\n When their window size is smaller than \"599px\"\n Then the rewards are displayed as cards in a singular column\n\n @motivating\n @ui\n Scenario: Table and Mobile beakpoints can be configured\n Given the reward table has been configured with the following props\n | prop | value |\n | smBreakpoint | 599 |\n | mdBreakpoint | 799 |\n And a user with rewards\n When they view the table\n And their window size is smaller than \"799px\"\n Then rewards are displayed as cards\n And they are in two columns\n When their window size is smaller than \"599px\"\n Then the rewards are displayed as cards in a singular column\n\n @motivating\n @ui\n Scenario Outline: By default the first column heading is hidden in mobile\n Given a reward table with 4 columns\n And prop \"hidden-columns\" with <hideColumnValue>\n And a user with rewards\n When they view the reward table\n And their window size is below the tablet breakpoint\n Then reward cards are displayed\n And the titles of <columnsArehidden> within the card\n Examples:\n | hideColumnValue | columnsArehidden |\n | | the first column |\n | 0,1,2 | the first, second and third columns |\n | 3 | the fourth column |\n\n @motivating\n Scenario: Only rewards which occured in the program specific by \"program-id\" are shown\n Given the table is configured with \"program-id\"\n Then only rewards from the program with \"program-id\" are shown\n\n @landmine\n Scenario: When a `classic` program Id is set then any reward without a programId is shown\n There is no easy way for the backend to filter for \"classic\" programs,\n thus we are filtering for rewards without programId's.\n\n Given the \"program-id\" of the table is set to \"classic\"\n Then rewards from classic programs are shown\n And manual rewards are shown\n\n @minutae\n @ui\n Scenario: Column heading can be hidden\n Given the table is configured with \"show-labels\" set to false\n Then the table is displayed without column headings";
11288
11490
 
11289
11491
  const RewardsTable_stories = {
11290
11492
  title: "Components/Rewards Table",
11291
11493
  parameters: {
11292
- scenario: scenario$r,
11494
+ scenario: scenario$s,
11293
11495
  },
11294
11496
  };
11295
11497
  const loadingElement$1 = (index.h("div", { slot: "loading", style: { display: "contents" } },
@@ -11533,12 +11735,12 @@ const UseReferralTable = /*#__PURE__*/Object.freeze({
11533
11735
  ReferralTableFr: ReferralTableFr
11534
11736
  });
11535
11737
 
11536
- const scenario$s = "@author:kutay\n@owner:kutay\nFeature: Hero Image\n\n\tThe Hero Image component displays media images with a header, description and button using an overlay or a double column layout to offer an attrative widget page.\n\n\tBackground: A user on the portal is viewing the widget\n\t\tGiven a user viewing the Hero Image component\n\n\t@motivating\n\t@ui\n\tScenario: Overlay image displays header, description, and button with brand color\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000278/squatch-assets/bTwu1Um.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"overlay\" |\n\t\tThen they see their image\n\t\tAnd the image has no padding\n\t\tAnd it has a brand colour overlay\n\t\tAnd \"Klip Rewards\" is displayed over top of the image in xxx-large font\n\t\tAnd below \"Refer friends or complete tasks while using Klip to earn rewards\" is displayed over top of the image in x-large font\n\t\tAnd below they see a brand coloured button with text \"Start earning\"\n\t\tAnd the text section has xxx-large padding\n\t\tWhen the component is scaled down to 599px\n\t\tThen the image is scaled to fit content\n\n\t@motivating\n\t@ui\n\tScenario Outline: Overlay image crop can be aligned left, center or right\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000278/squatch-assets/bTwu1Um.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"overlay\" |\n\t\t\t| image-pos | <value> |\n\t\tThen the image with overlay is displayed\n\t\tWhen the component is scaled down to 599px\n\t\tThen the image is <alignment> to fit content\n\t\tExamples:\n\t\t\t| value | alignment |\n\t\t\t| left | left aligned |\n\t\t\t| center | centered |\n\t\t\t| right | right aligned |\n\t\t\t| N/A | centered |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Overlay padding is configurable\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000278/squatch-assets/bTwu1Um.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"overlay\" |\n\t\t\t| padding-text | <value> |\n\t\tThen the image with overlay is displayed\n\t\tAnd <padding> is applied around header, description and button\n\t\tExamples:\n\t\t\t| value | padding |\n\t\t\t| none | no padding |\n\t\t\t| xxx-small | xxx-small |\n\t\t\t| xx-small | xx-small |\n\t\t\t| x-small | x-small |\n\t\t\t| small | small |\n\t\t\t| medium | medium |\n\t\t\t| large | large |\n\t\t\t| x-large | x-large |\n\t\t\t| xx-large | xx-large |\n\t\t\t| xxx-large | xxx-large |\n\t\t\t| xxxx-large | xxxx-large |\n\t\t\t| N/A | no padding |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Overlay color and background is configurable\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000278/squatch-assets/bTwu1Um.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"overlay\" |\n\t\t\t| text-color | <textColor> |\n\t\t\t| overlay-color | <overlayColor> |\n\t\t\t| overlay-opacity | <overlayOpacity> |\n\t\tThen the image with overlay is displayed\n\t\tAnd the overlay is <overlayColor>\n\t\tAnd the overlay has <overlayOpacity>\n\t\tAnd the text is <textColor>\n\t\tExamples:\n\t\t\t| textColor | overlayColor | overlayOpacity |\n\t\t\t| #fffc4b | #ff7f7f | 0.9 |\n\t\t\t| #1d0314 | #4baa1a | 0 |\n\t\t\t| #211a27 | #aa481a | 1 |\n\n\t@motivating\n\t@ui\n\tScenario: Two-column layout displays an image on one side and on the other side a header, description, and button\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000275/squatch-assets/yr6ER3R.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\tThen the image is displayed on the left\n\t\tAnd the following elements are displayed on the right\n\t\t\t| elements |\n\t\t\t| header |\n\t\t\t| description |\n\t\t\t| button |\n\t\tWhen the component is scaled down to 599px\n\t\tThen the two-column layout switches to a row layout\n\t\tAnd the image is displayed on top\n\t\tAnd the content is displayed below\n\n\t@motivating\n\t@ui\n\tScenario Outline: Image position is configurable for desktop and mobile\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000275/squatch-assets/yr6ER3R.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\t\t| image-pos | <imagePos> |\n\t\t\t| image-mobile-pos | <imageMobilePos> |\n\t\tThen the image is displayed on the <imagePos>\n\t\tWhen the component is scaled down to 599px\n\t\tThen two-column layout switches to a row layout\n\t\tAnd image is displayed on the <imageMobilePos>\n\t\tExamples:\n\t\t\t| imagePos | imageMobilePos |\n\t\t\t| left | top |\n\t\t\t| right | bottom |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Padding is configurable for the image and text of two column layouts\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000275/squatch-assets/yr6ER3R.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\t\t| padding-text | <paddingText> |\n\t\t\t| padding-image | <paddingImage> |\n\t\tThen the two column layout is displayed\n\t\tAnd the image has padding <paddingImage>\n\t\tAnd the text has padding <paddingText>\n\t\tExamples:\n\t\t\t| paddingText | paddingImage |\n\t\t\t| xxx-small | xxx-small |\n\t\t\t| xx-small | xx-small |\n\t\t\t| x-small | x-small |\n\t\t\t| small | small |\n\t\t\t| medium | medium |\n\t\t\t| large | large |\n\t\t\t| x-large | x-large |\n\t\t\t| xx-large | xx-large |\n\t\t\t| xxx-large | xxx-large |\n\t\t\t| xxxx-large | xxxx-large |\n\t\t\t| none | none |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Two-column layout image division percentage is configurable\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000248/squatch-assets/MVgOJn7.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\t\t| image-percentage | <percent> |\n\t\tThen the two column layout is displayed\n\t\tAnd the image takes up <percent> of the two-column layout\n\t\tAnd the text elements take up the remainder of the space\n\t\tExamples:\n\t\t\t| percent |\n\t\t\t| 25% |\n\t\t\t| 42% |\n\t\t\t| 66% |\n\n\t@motivating\n\t@ui\n\tScenario: Two-column layout text and background color is configurable\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000275/squatch-assets/yr6ER3R.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\t\t| text-color | <textColor> |\n\t\t\t| background-color | <backgroundColor> |\n\t\tThen the two column layout is displayed\n\t\tAnd the text has color <textColor>\n\t\tAnd the background has color <backgroundColor>\n\t\tExamples:\n\t\t\t| textColor | backgroundColor |\n\t\t\t| #fffc4b | #ff7f7f |\n\t\t\t| #1d0314 | #4baa1a |\n\t\t\t| #211a27 | #aa481a |";
11738
+ const scenario$t = "@author:kutay\n@owner:kutay\nFeature: Hero Image\n\n\tThe Hero Image component displays media images with a header, description and button using an overlay or a double column layout to offer an attrative widget page.\n\n\tBackground: A user on the portal is viewing the widget\n\t\tGiven a user viewing the Hero Image component\n\n\t@motivating\n\t@ui\n\tScenario: Overlay image displays header, description, and button with brand color\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000278/squatch-assets/bTwu1Um.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"overlay\" |\n\t\tThen they see their image\n\t\tAnd the image has no padding\n\t\tAnd it has a brand colour overlay\n\t\tAnd \"Klip Rewards\" is displayed over top of the image in xxx-large font\n\t\tAnd below \"Refer friends or complete tasks while using Klip to earn rewards\" is displayed over top of the image in x-large font\n\t\tAnd below they see a brand coloured button with text \"Start earning\"\n\t\tAnd the text section has xxx-large padding\n\t\tWhen the component is scaled down to 599px\n\t\tThen the image is scaled to fit content\n\n\t@motivating\n\t@ui\n\tScenario Outline: Overlay image crop can be aligned left, center or right\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000278/squatch-assets/bTwu1Um.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"overlay\" |\n\t\t\t| image-pos | <value> |\n\t\tThen the image with overlay is displayed\n\t\tWhen the component is scaled down to 599px\n\t\tThen the image is <alignment> to fit content\n\t\tExamples:\n\t\t\t| value | alignment |\n\t\t\t| left | left aligned |\n\t\t\t| center | centered |\n\t\t\t| right | right aligned |\n\t\t\t| N/A | centered |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Overlay padding is configurable\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000278/squatch-assets/bTwu1Um.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"overlay\" |\n\t\t\t| padding-text | <value> |\n\t\tThen the image with overlay is displayed\n\t\tAnd <padding> is applied around header, description and button\n\t\tExamples:\n\t\t\t| value | padding |\n\t\t\t| none | no padding |\n\t\t\t| xxx-small | xxx-small |\n\t\t\t| xx-small | xx-small |\n\t\t\t| x-small | x-small |\n\t\t\t| small | small |\n\t\t\t| medium | medium |\n\t\t\t| large | large |\n\t\t\t| x-large | x-large |\n\t\t\t| xx-large | xx-large |\n\t\t\t| xxx-large | xxx-large |\n\t\t\t| xxxx-large | xxxx-large |\n\t\t\t| N/A | no padding |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Overlay color and background is configurable\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000278/squatch-assets/bTwu1Um.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"overlay\" |\n\t\t\t| text-color | <textColor> |\n\t\t\t| overlay-color | <overlayColor> |\n\t\t\t| overlay-opacity | <overlayOpacity> |\n\t\tThen the image with overlay is displayed\n\t\tAnd the overlay is <overlayColor>\n\t\tAnd the overlay has <overlayOpacity>\n\t\tAnd the text is <textColor>\n\t\tExamples:\n\t\t\t| textColor | overlayColor | overlayOpacity |\n\t\t\t| #fffc4b | #ff7f7f | 0.9 |\n\t\t\t| #1d0314 | #4baa1a | 0 |\n\t\t\t| #211a27 | #aa481a | 1 |\n\n\t@motivating\n\t@ui\n\tScenario: Two-column layout displays an image on one side and on the other side a header, description, and button\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000275/squatch-assets/yr6ER3R.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\tThen the image is displayed on the left\n\t\tAnd the following elements are displayed on the right\n\t\t\t| elements |\n\t\t\t| header |\n\t\t\t| description |\n\t\t\t| button |\n\t\tWhen the component is scaled down to 599px\n\t\tThen the two-column layout switches to a row layout\n\t\tAnd the image is displayed on top\n\t\tAnd the content is displayed below\n\n\t@motivating\n\t@ui\n\tScenario Outline: Image position is configurable for desktop and mobile\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000275/squatch-assets/yr6ER3R.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\t\t| image-pos | <imagePos> |\n\t\t\t| image-mobile-pos | <imageMobilePos> |\n\t\tThen the image is displayed on the <imagePos>\n\t\tWhen the component is scaled down to 599px\n\t\tThen two-column layout switches to a row layout\n\t\tAnd image is displayed on the <imageMobilePos>\n\t\tExamples:\n\t\t\t| imagePos | imageMobilePos |\n\t\t\t| left | top |\n\t\t\t| right | bottom |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Padding is configurable for the image and text of two column layouts\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000275/squatch-assets/yr6ER3R.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\t\t| padding-text | <paddingText> |\n\t\t\t| padding-image | <paddingImage> |\n\t\tThen the two column layout is displayed\n\t\tAnd the image has padding <paddingImage>\n\t\tAnd the text has padding <paddingText>\n\t\tExamples:\n\t\t\t| paddingText | paddingImage |\n\t\t\t| xxx-small | xxx-small |\n\t\t\t| xx-small | xx-small |\n\t\t\t| x-small | x-small |\n\t\t\t| small | small |\n\t\t\t| medium | medium |\n\t\t\t| large | large |\n\t\t\t| x-large | x-large |\n\t\t\t| xx-large | xx-large |\n\t\t\t| xxx-large | xxx-large |\n\t\t\t| xxxx-large | xxxx-large |\n\t\t\t| none | none |\n\n\t@motivating\n\t@ui\n\tScenario Outline: Two-column layout image division percentage is configurable\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000248/squatch-assets/MVgOJn7.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\t\t| image-percentage | <percent> |\n\t\tThen the two column layout is displayed\n\t\tAnd the image takes up <percent> of the two-column layout\n\t\tAnd the text elements take up the remainder of the space\n\t\tExamples:\n\t\t\t| percent |\n\t\t\t| 25% |\n\t\t\t| 42% |\n\t\t\t| 66% |\n\n\t@motivating\n\t@ui\n\tScenario: Two-column layout text and background color is configurable\n\t\tGiven a Hero Image component configured with the following props\n\t\t\t| prop | value |\n\t\t\t| image-url | \"https://res.cloudinary.com/saasquatch/image/upload/v1644000275/squatch-assets/yr6ER3R.png\" |\n\t\t\t| header | \"Klip Rewards\" |\n\t\t\t| description | \"Refer friends or complete tasks while using Klip to earn rewards\" |\n\t\t\t| button-text | \"Start earning\" |\n\t\t\t| layout | \"columns\" |\n\t\t\t| text-color | <textColor> |\n\t\t\t| background-color | <backgroundColor> |\n\t\tThen the two column layout is displayed\n\t\tAnd the text has color <textColor>\n\t\tAnd the background has color <backgroundColor>\n\t\tExamples:\n\t\t\t| textColor | backgroundColor |\n\t\t\t| #fffc4b | #ff7f7f |\n\t\t\t| #1d0314 | #4baa1a |\n\t\t\t| #211a27 | #aa481a |";
11537
11739
 
11538
11740
  const HeroImage_stories = {
11539
11741
  title: "Components/Hero Image",
11540
11742
  parameters: {
11541
- scenario: scenario$s,
11743
+ scenario: scenario$t,
11542
11744
  },
11543
11745
  };
11544
11746
  const OverlayHeader = () => {
@@ -11611,12 +11813,12 @@ const HeroImage = /*#__PURE__*/Object.freeze({
11611
11813
  ColumnsCustomColors: ColumnsCustomColors
11612
11814
  });
11613
11815
 
11614
- const scenario$t = "@author:kutay\n@owner:kutay\nFeature: Referral Card\n\n\tThe Referral Card component takes in two slots and displays them side by side.\n\n\tBackground: A user on the portal is viewing the widget\n\t\tGiven a user viewing the Referral Card component\n\n\t@motivating\n\t@ui\n\tScenario: Referral Card component displays provided content in left and right slots side by side\n\t\tGiven a Referral Card component\n\t\tAnd a slot with the name \"left\"\n\t\tAnd a slot with the name \"right\"\n\t\tWhen the user views the referral card\n\t\tThen the slot contents are displayed the card with equal width\n\t\tWhen the component is scaled down to 499px\n\t\tThen the column layout switches to row layout\n\t\tAnd the \"left\" slot content is displayed above the \"right\" slot content\n\n\t@motivating\n\t@ui\n\tScenario Outline: Referral Card component content can be vertically aligned start, center, end\n\t\tGiven a Referral Card component\n\t\tAnd a slot with the name \"left\"\n\t\tAnd a slot with the name \"right\"\n\t\tAnd the prop \"vertical-alignment\" has <value>\n\t\tThen slots contents are displayed inside the card\n\t\tAnd slots are vertically aligned to <alignment> of the card\n\t\tExamples:\n\t\t\t| value | alignment |\n\t\t\t| start | the top |\n\t\t\t| center | the center |\n\t\t\t| end | the bottom |\n\t\t\t| N/A | the top |\n\n";
11816
+ const scenario$u = "@author:kutay\n@owner:kutay\nFeature: Referral Card\n\n\tThe Referral Card component takes in two slots and displays them side by side.\n\n\tBackground: A user on the portal is viewing the widget\n\t\tGiven a user viewing the Referral Card component\n\n\t@motivating\n\t@ui\n\tScenario: Referral Card component displays provided content in left and right slots side by side\n\t\tGiven a Referral Card component\n\t\tAnd a slot with the name \"left\"\n\t\tAnd a slot with the name \"right\"\n\t\tWhen the user views the referral card\n\t\tThen the slot contents are displayed the card with equal width\n\t\tWhen the component is scaled down to 499px\n\t\tThen the column layout switches to row layout\n\t\tAnd the \"left\" slot content is displayed above the \"right\" slot content\n\n\t@motivating\n\t@ui\n\tScenario Outline: Referral Card component content can be vertically aligned start, center, end\n\t\tGiven a Referral Card component\n\t\tAnd a slot with the name \"left\"\n\t\tAnd a slot with the name \"right\"\n\t\tAnd the prop \"vertical-alignment\" has <value>\n\t\tThen slots contents are displayed inside the card\n\t\tAnd slots are vertically aligned to <alignment> of the card\n\t\tExamples:\n\t\t\t| value | alignment |\n\t\t\t| start | the top |\n\t\t\t| center | the center |\n\t\t\t| end | the bottom |\n\t\t\t| N/A | the top |\n\n";
11615
11817
 
11616
11818
  const ReferralCard_stories = {
11617
11819
  title: "Components/Referral Card",
11618
11820
  parameters: {
11619
- scenario: scenario$t,
11821
+ scenario: scenario$u,
11620
11822
  },
11621
11823
  };
11622
11824
  const media = (slot) => {
@@ -11707,11 +11909,11 @@ const scenarioTimeline = "@author:derek\n@owner:kutay\nFeature: Timeline\n\n
11707
11909
 
11708
11910
  const scenarioTimelineEntry = "@author:derek\n@owner:kutay\nFeature: Timeline Entry\n\n @motivating\n @ui\n Scenario: Timeline entries have an icon, a reward and an entry desciption\n Given an timeline entry with the following props\n | prop | value |\n | unit | Visa Giftcard |\n | reward | 50$ |\n | desc | Earn a 50$ Visa Giftcard for each referral you make |\n When a user views the entry\n Then they see a gift icon\n And see \"$50 VISA GIFTCARRD\" to the right\n And \"$50\" is bolded with x-large font size\n And below they see \"Earn a 50$ Visa Giftcard for each referral you make\"\n\n @motivating\n @ui\n Scenario Outline: Icon can either be a gift or a brand colour cirle\n Given a timeline entry with \"icon\" <iconPropValue>\n When a user views the entry\n Then they see an <icon>\n Examples:\n | iconPropValue 1 | icon |\n | gift | gift |\n | circle | brand colour circle |\n | | gift |\n\n @motivating\n @ui\n Scenario: A timeline entry can display a line to connect it to another entry\n Given a timeline entry with \"line\" \"true\"\n When a user views the entry\n Then they see the entry\n But it has a brand colour line connecting it to the next timeline entry\n";
11709
11911
 
11710
- const scenario$u = scenarioTimeline + scenarioTimelineEntry;
11912
+ const scenario$v = scenarioTimeline + scenarioTimelineEntry;
11711
11913
  const Timeline_stories = {
11712
11914
  title: "Components/Timeline",
11713
11915
  parameters: {
11714
- scenario: scenario$u,
11916
+ scenario: scenario$v,
11715
11917
  },
11716
11918
  };
11717
11919
  const TimelineWith1Reward = () => {
@@ -11784,12 +11986,12 @@ const Timeline = /*#__PURE__*/Object.freeze({
11784
11986
  TimelineWith4Rewards: TimelineWith4Rewards
11785
11987
  });
11786
11988
 
11787
- const scenario$v = "@author:kutay\n@owner:kutay\nFeature: Image\n\n\tBackground: A user on the portal is viewing the widget\n\t\tGiven a user viewing the image component\n\n\t@motivating\n\t@ui\n\tScenario: Image is displayed from URL\n\t\tGiven an Image component\n\t\tAnd prop \"image-url\" is provided with a valid image url\n\t\tThen the image is displayed\n\t\tAnd it is centered\n\n\t@motivating\n\t@ui\n\tScenario Outline: Images can be aligned left, center or right\n\t\tGiven an Image component\n\t\tAnd prop \"image-url\" is provided with a valid image url\n\t\tAnd prop \"align\" has <value>\n\t\tThen the image is displayed\n\t\tAnd it is aligned to the <value>\n\t\tExamples:\n\t\t\t| value |\n\t\t\t| left |\n\t\t\t| center |\n\t\t\t| right |\n\n\t@motivating\n\t@ui\n\tScenario: Image background can be assigned a color\n\t\tGiven an Image component\n\t\tAnd prop \"image-url\" is provided with a valid image url\n\t\tAnd prop \"background-color\" is provided a color\n\t\tThen the image is displayed\n\t\tAnd the background is the provided color\n\n\t@motivating\n\t@ui\n\tScenario: Image minimum height can be constrained\n\t\tGiven an Image component\n\t\tAnd prop \"image-url\" is provided\n\t\tAnd prop \"min-height\" is given a minimum value\n\t\tThen the image is displayed\n\t\tAnd the container size changes\n\t\tThen the image does not shrink below its minimum height";
11989
+ const scenario$w = "@author:kutay\n@owner:kutay\nFeature: Image\n\n\tBackground: A user on the portal is viewing the widget\n\t\tGiven a user viewing the image component\n\n\t@motivating\n\t@ui\n\tScenario: Image is displayed from URL\n\t\tGiven an Image component\n\t\tAnd prop \"image-url\" is provided with a valid image url\n\t\tThen the image is displayed\n\t\tAnd it is centered\n\n\t@motivating\n\t@ui\n\tScenario Outline: Images can be aligned left, center or right\n\t\tGiven an Image component\n\t\tAnd prop \"image-url\" is provided with a valid image url\n\t\tAnd prop \"align\" has <value>\n\t\tThen the image is displayed\n\t\tAnd it is aligned to the <value>\n\t\tExamples:\n\t\t\t| value |\n\t\t\t| left |\n\t\t\t| center |\n\t\t\t| right |\n\n\t@motivating\n\t@ui\n\tScenario: Image background can be assigned a color\n\t\tGiven an Image component\n\t\tAnd prop \"image-url\" is provided with a valid image url\n\t\tAnd prop \"background-color\" is provided a color\n\t\tThen the image is displayed\n\t\tAnd the background is the provided color\n\n\t@motivating\n\t@ui\n\tScenario: Image minimum height can be constrained\n\t\tGiven an Image component\n\t\tAnd prop \"image-url\" is provided\n\t\tAnd prop \"min-height\" is given a minimum value\n\t\tThen the image is displayed\n\t\tAnd the container size changes\n\t\tThen the image does not shrink below its minimum height";
11788
11990
 
11789
11991
  const Image_stories = {
11790
11992
  title: "Components/Image",
11791
11993
  parameters: {
11792
- scenario: scenario$v,
11994
+ scenario: scenario$w,
11793
11995
  },
11794
11996
  };
11795
11997
  const Image = () => {
@@ -11822,12 +12024,12 @@ const Image$1 = /*#__PURE__*/Object.freeze({
11822
12024
  MinimumHeight: MinimumHeight
11823
12025
  });
11824
12026
 
11825
- const scenario$w = "@author:derek\n@owner:noah\nFeature: Titled Section\n\n Background: The titled section has a label and content\n Given a titled section\n And it has a label\n And it has content in the content slot\n\n @motivating\n @ui\n Scenario: Text alignment defaults to left align but can be configured\n Given the titled section has \"text-align\" <textAlignPropValue>\n When a user views the titled section\n Then the text in the label is <aligned>\n And the text in the content is <aligned>\n Examples:\n | textAlignPropValue | aligned |\n | center | center |\n | left | left |\n | right | right |\n | | left |\n\n @minutae\n @ui\n Scenario: Label margin is configurable\n Given the titled section has \"label-margin\" <marginPropValue>\n When a user views the titled section\n Then <marginPropValue> margin is between the label and content\n Examples:\n | marginPropValue | margin |\n | none | no |\n | xxx-small | xxx-small |\n | xx-small | xx-small |\n | x-small | x-small |\n | small | small |\n | medium | medium |\n | large | large |\n | x-large | x-large |\n | xx-large | xx-large |\n | xxx-large | xxx-large |\n | xxxx-large | xxxx-large |\n | | no |\n\n @minutae\n @ui\n Scenario Outline: Titled section padding is configurable\n Given the titled section has \"padding\" <paddingPropValue>\n When a user views the titled section\n Then <paddingPropValue> padding is applied around the titled section\n Examples:\n | paddingPropValue | padding |\n | none | no |\n | xxx-small | xxx-small |\n | xx-small | xx-small |\n | x-small | x-small |\n | small | small |\n | medium | medium |\n | large | large |\n | x-large | x-large |\n | xx-large | xx-large |\n | xxx-large | xxx-large |\n | xxxx-large | xxxx-large |\n | | no |";
12027
+ const scenario$x = "@author:derek\n@owner:noah\nFeature: Titled Section\n\n Background: The titled section has a label and content\n Given a titled section\n And it has a label\n And it has content in the content slot\n\n @motivating\n @ui\n Scenario: Text alignment defaults to left align but can be configured\n Given the titled section has \"text-align\" <textAlignPropValue>\n When a user views the titled section\n Then the text in the label is <aligned>\n And the text in the content is <aligned>\n Examples:\n | textAlignPropValue | aligned |\n | center | center |\n | left | left |\n | right | right |\n | | left |\n\n @minutae\n @ui\n Scenario: Label margin is configurable\n Given the titled section has \"label-margin\" <marginPropValue>\n When a user views the titled section\n Then <marginPropValue> margin is between the label and content\n Examples:\n | marginPropValue | margin |\n | none | no |\n | xxx-small | xxx-small |\n | xx-small | xx-small |\n | x-small | x-small |\n | small | small |\n | medium | medium |\n | large | large |\n | x-large | x-large |\n | xx-large | xx-large |\n | xxx-large | xxx-large |\n | xxxx-large | xxxx-large |\n | | no |\n\n @minutae\n @ui\n Scenario Outline: Titled section padding is configurable\n Given the titled section has \"padding\" <paddingPropValue>\n When a user views the titled section\n Then <paddingPropValue> padding is applied around the titled section\n Examples:\n | paddingPropValue | padding |\n | none | no |\n | xxx-small | xxx-small |\n | xx-small | xx-small |\n | x-small | x-small |\n | small | small |\n | medium | medium |\n | large | large |\n | x-large | x-large |\n | xx-large | xx-large |\n | xxx-large | xxx-large |\n | xxxx-large | xxxx-large |\n | | no |";
11826
12028
 
11827
12029
  const TitledSection_stories = {
11828
12030
  title: "Components/Titled Section",
11829
12031
  parameters: {
11830
- scenario: scenario$w,
12032
+ scenario: scenario$x,
11831
12033
  },
11832
12034
  };
11833
12035
  const AlignLeft = () => {
@@ -12223,12 +12425,12 @@ const Scroll = /*#__PURE__*/Object.freeze({
12223
12425
  ShoelaceProps: ShoelaceProps
12224
12426
  });
12225
12427
 
12226
- const scenario$x = "@author:Zach\n@owner:Zach\nFeature: Tabs\n\n The Tabs takes in the Tab component as children and maps through to display their header and content.\n\n Background: A user on the portal is viewing the widget\n Given a user viewing the Tabs component\n\n @motivating\n Scenario: Content inside the active tab is shown\n Given the header is set to <tabHeader>\n And the content inside is <tabContent>\n And the user has clicked <tabHeader>\n Then the <tabContent> is shown\n Examples:\n | tabHeader | tabContent |\n | Settings | This is the settings tab |\n | General | This is the general tab |\n | History | This is the history tab |\n\n @motivating\n @ui\n Scenario: The placement of the tabs is configurable\n Given The placement prop has been passed a valid <placement>\n Then tabs are placed on the <placementResult>\n Examples:\n | placement | placementResult |\n | | top of the content |\n | left | left hand side of the content |\n | right | right hand side of the content |\n | bottom | bottom of the content |\n\n\n @minutae\n @ui\n Scenario Outline: Tabs are setup to use the brand color\n Given the brand color is set to darkblue\n Then the text inside the active tab is darkblue\n And the underline of the active tab is darkblue\n\n @ui\n Scenario: Tabs are responsive\n Given the user is on a mobile device\n When there are more tabs than the horizontal space allows for\n Then clickable arrows appear on the left and right of the tabs\n And the tabs are scrollable\n\n @landmine\n Scenario: Program section cannot be used inside of tabs\n Given a tabs component\n And tab containing a program section with program-id \"test123\"\n And the program section wraps a component using program context\n When the tabs component is rendered\n Then the \"sq:program-id\" event listener for the program section is removed\n And the component does not use program-id \"test123\" to source its data\n And falls back to the global program id";
12428
+ const scenario$y = "@author:Zach\n@owner:Zach\nFeature: Tabs\n\n The Tabs takes in the Tab component as children and maps through to display their header and content.\n\n Background: A user on the portal is viewing the widget\n Given a user viewing the Tabs component\n\n @motivating\n Scenario: Content inside the active tab is shown\n Given the header is set to <tabHeader>\n And the content inside is <tabContent>\n And the user has clicked <tabHeader>\n Then the <tabContent> is shown\n Examples:\n | tabHeader | tabContent |\n | Settings | This is the settings tab |\n | General | This is the general tab |\n | History | This is the history tab |\n\n @motivating\n @ui\n Scenario: The placement of the tabs is configurable\n Given The placement prop has been passed a valid <placement>\n Then tabs are placed on the <placementResult>\n Examples:\n | placement | placementResult |\n | | top of the content |\n | left | left hand side of the content |\n | right | right hand side of the content |\n | bottom | bottom of the content |\n\n\n @minutae\n @ui\n Scenario Outline: Tabs are setup to use the brand color\n Given the brand color is set to darkblue\n Then the text inside the active tab is darkblue\n And the underline of the active tab is darkblue\n\n @ui\n Scenario: Tabs are responsive\n Given the user is on a mobile device\n When there are more tabs than the horizontal space allows for\n Then clickable arrows appear on the left and right of the tabs\n And the tabs are scrollable\n\n @landmine\n Scenario: Program section cannot be used inside of tabs\n Given a tabs component\n And tab containing a program section with program-id \"test123\"\n And the program section wraps a component using program context\n When the tabs component is rendered\n Then the \"sq:program-id\" event listener for the program section is removed\n And the component does not use program-id \"test123\" to source its data\n And falls back to the global program id";
12227
12429
 
12228
12430
  const Tabs_stories = {
12229
12431
  title: "Components/Tabs",
12230
12432
  parameters: {
12231
- scenario: scenario$x,
12433
+ scenario: scenario$y,
12232
12434
  },
12233
12435
  };
12234
12436
  const SimpleTabs = () => (index.h("div", { style: { maxWidth: "700px", margin: "auto" }, innerHTML: `
@@ -12727,12 +12929,12 @@ const Tabs = /*#__PURE__*/Object.freeze({
12727
12929
  RightTabs: RightTabs
12728
12930
  });
12729
12931
 
12730
- const scenario$y = "@author:johan\n@owner:johan\nFeature: Share Code\n\n The share code component is a box that allows users to see and copy their referral code for a given program\n \n Background: Environment\n Given there is a valid program ID in the environment\n And there is a valid user ID and account ID in the environment\n\n @motivating\n Scenario: A Users referral code can be copied to their clipboard\n Given tooltiptext is \"hello tooltip\"\n When the component renders\n Then there is a textbox with the user's share link\n When the clipboard icon is clicked\n Then the link is copied to clipboard\n And a tooltip will appear for ~1 second\n\n @minutae\n Scenario: Tooltip lifespan defaults to 2000\n Given the tooltip's lifespan is set to 2000\n And there is tooltip text\n When the component renders\n And the clipboard icon is clicked\n Then a tooltip will appear for ~2 seconds\n\n @minutae\n Scenario: Demo\n Given isDemo() returns true\n Then the share link is \"https://www.example.com/sharelink/abc\"\n And the component won't be interactive\n And the tooltip is hidden\n\n @minutae\n Scenario: Program ID can be sourced from prop\n Given the programId prop is set to \"program-a\"\n And window.widgetIdent.programId is set to \"program-b\"\n When the component renders\n Then the share link is for \"program-a\"\n\n @minutae\n Scenario: Program ID can be sourced from window\n Given the programId prop is unset\n And window.widgetIdent.programId is set to \"program-b\"\n When the component renders\n Then the share link is for \"program-b\"\n\n @minutae\n Scenario: An analytic event is fired when a user copies their code\n Given a user viewing the share code component\n And the component is rendered for \"program-a\"\n When they click to copy their code\n Then an \"USER_REFERRAL_PROGRAM_ENGAGEMENT_EVENT\" analytic event is fired\n And it is for \"program-a\"\n And it has share medium \"DIRECT\"\n";
12932
+ const scenario$z = "@author:johan\n@owner:johan\nFeature: Share Code\n\n The share code component is a box that allows users to see and copy their referral code for a given program\n \n Background: Environment\n Given there is a valid program ID in the environment\n And there is a valid user ID and account ID in the environment\n\n @motivating\n Scenario: A Users referral code can be copied to their clipboard\n Given tooltiptext is \"hello tooltip\"\n When the component renders\n Then there is a textbox with the user's share link\n When the clipboard icon is clicked\n Then the link is copied to clipboard\n And a tooltip will appear for ~1 second\n\n @minutae\n Scenario: Tooltip lifespan defaults to 2000\n Given the tooltip's lifespan is set to 2000\n And there is tooltip text\n When the component renders\n And the clipboard icon is clicked\n Then a tooltip will appear for ~2 seconds\n\n @minutae\n Scenario: Demo\n Given isDemo() returns true\n Then the share link is \"https://www.example.com/sharelink/abc\"\n And the component won't be interactive\n And the tooltip is hidden\n\n @minutae\n Scenario: Program ID can be sourced from prop\n Given the programId prop is set to \"program-a\"\n And window.widgetIdent.programId is set to \"program-b\"\n When the component renders\n Then the share link is for \"program-a\"\n\n @minutae\n Scenario: Program ID can be sourced from window\n Given the programId prop is unset\n And window.widgetIdent.programId is set to \"program-b\"\n When the component renders\n Then the share link is for \"program-b\"\n\n @minutae\n Scenario: An analytic event is fired when a user copies their code\n Given a user viewing the share code component\n And the component is rendered for \"program-a\"\n When they click to copy their code\n Then an \"USER_REFERRAL_PROGRAM_ENGAGEMENT_EVENT\" analytic event is fired\n And it is for \"program-a\"\n And it has share medium \"DIRECT\"\n";
12731
12933
 
12732
12934
  const ShareCode_stories = {
12733
12935
  title: "Components/Share Code",
12734
12936
  parameters: {
12735
- scenario: scenario$y,
12937
+ scenario: scenario$z,
12736
12938
  },
12737
12939
  };
12738
12940
  const ShareCode = () => {