@hortiview/shared-components 2.11.2 → 2.12.1

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 (187) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +135 -3
  3. package/dist/{AlertBanner-C6wpAQMj.js → AlertBanner-Ci-F-6S9.js} +3 -3
  4. package/dist/{BigLoadingSpinner-CDbRVDNZ.js → BigLoadingSpinner-DGj9_Z5J.js} +1 -1
  5. package/dist/{GenericCard-Co9bGU19.js → GenericCard-CeqYrtLH.js} +3 -3
  6. package/dist/{ListAreaService-CGJm5I23.js → ListAreaService-Fsm3-gDM.js} +5 -5
  7. package/dist/{OfflineView-NUM9WE0F.js → OfflineView-CIwV08EQ.js} +3 -3
  8. package/dist/{_Map-BmafU0dj.js → _Map-D8db_GOu.js} +3 -3
  9. package/dist/{_commonjsHelpers-BkfeUUK-.js → _commonjsHelpers-B4e78b8K.js} +1 -1
  10. package/dist/{animationframe-EMBh6XeO.js → animationframe-BVKDmEXe.js} +2 -2
  11. package/dist/{component-neHBNHRu.js → component-Bz_dtX1r.js} +4 -4
  12. package/dist/{component-DsB0poTj.js → component-DEJuY56h.js} +5 -5
  13. package/dist/components/AlertBanner/AlertBanner.js +4 -4
  14. package/dist/components/AlertBanner/AlertBanner.test.js +3 -3
  15. package/dist/components/AlertBanner/LinkBanner.js +3 -3
  16. package/dist/components/AlertBanner/LinkBanner.test.js +2 -2
  17. package/dist/components/Allowed/Allowed.d.ts +21 -0
  18. package/dist/components/Allowed/Allowed.js +13 -0
  19. package/dist/components/Allowed/Allowed.test.d.ts +1 -0
  20. package/dist/components/Allowed/Allowed.test.js +49 -0
  21. package/dist/components/AllowedButton/AllowedButton.d.ts +51 -0
  22. package/dist/components/AllowedButton/AllowedButton.js +28 -0
  23. package/dist/components/AllowedButton/AllowedButton.test.d.ts +1 -0
  24. package/dist/components/AllowedButton/AllowedButton.test.js +126 -0
  25. package/dist/components/AllowedIconButton/AllowedIconButton.d.ts +43 -0
  26. package/dist/components/AllowedIconButton/AllowedIconButton.js +23 -0
  27. package/dist/components/AllowedIconButton/AllowedIconButton.test.d.ts +1 -0
  28. package/dist/components/AllowedIconButton/AllowedIconButton.test.js +121 -0
  29. package/dist/components/BaseView/BaseView.js +5 -5
  30. package/dist/components/BaseView/BaseView.test.js +2 -2
  31. package/dist/components/BasicHeading/BasicHeading.js +4 -4
  32. package/dist/components/BasicHeading/BasicHeading.test.js +3 -3
  33. package/dist/components/BlockView/BlockView.js +2 -2
  34. package/dist/components/BlockView/BlockView.test.js +2 -2
  35. package/dist/components/ChipCard/ChipCard.js +27 -27
  36. package/dist/components/ChipCard/ChipCard.test.js +2 -2
  37. package/dist/components/ContextMenu/ContextMenu.js +4 -4
  38. package/dist/components/ContextMenu/ContextMenu.test.js +2 -2
  39. package/dist/components/DeleteModal/DeleteModal.js +5 -5
  40. package/dist/components/DeleteModal/DeleteModal.test.js +2 -2
  41. package/dist/components/DetailContentWrapper/DetailContentWrapper.js +1 -1
  42. package/dist/components/Disclaimer/Disclaimer.js +3 -3
  43. package/dist/components/Disclaimer/Disclaimer.test.js +2 -2
  44. package/dist/components/EmptyView/EmptyView.js +3 -3
  45. package/dist/components/EmptyView/EmptyView.test.js +2 -2
  46. package/dist/components/Filter/Filter.js +18 -15
  47. package/dist/components/Filter/Filter.test.js +2 -2
  48. package/dist/components/FormComponents/FormCheckBox/FormCheckBox.js +1 -1
  49. package/dist/components/FormComponents/FormCheckBox/FormCheckBox.test.js +2 -2
  50. package/dist/components/FormComponents/FormDatePicker/FormDatePicker.js +6 -14
  51. package/dist/components/FormComponents/FormDatePicker/FormDatePicker.test.js +2 -2
  52. package/dist/components/FormComponents/FormNumber/CustomTextField.js +3 -3
  53. package/dist/components/FormComponents/FormNumber/FormNumber.js +1 -1
  54. package/dist/components/FormComponents/FormNumber/FormNumber.test.js +2 -2
  55. package/dist/components/FormComponents/FormRadio/FormRadio.js +1 -1
  56. package/dist/components/FormComponents/FormRadio/FormRadio.test.js +2 -2
  57. package/dist/components/FormComponents/FormSelect/FormSelect.js +3 -3
  58. package/dist/components/FormComponents/FormSelect/FormSelect.test.js +3 -3
  59. package/dist/components/FormComponents/FormSelect/SelectTooltipText.js +2 -2
  60. package/dist/components/FormComponents/FormSlider/FormSlider.js +13 -13
  61. package/dist/components/FormComponents/FormSlider/FormSlider.test.js +2 -2
  62. package/dist/components/FormComponents/FormText/FormText.js +2 -2
  63. package/dist/components/FormComponents/FormText/FormText.test.js +2 -2
  64. package/dist/components/FormComponents/FormToggle/FormToggle.js +4 -4
  65. package/dist/components/FormComponents/FormToggle/FormToggle.test.js +2 -2
  66. package/dist/components/FormattedNumberDisplay/FormattedNumberDisplay.js +1 -1
  67. package/dist/components/GenericTable/GenericTable.js +968 -965
  68. package/dist/components/GenericTable/GenericTable.test.js +2 -2
  69. package/dist/components/GenericTable/Mobile/GenericCard.js +4 -4
  70. package/dist/components/GenericTable/Mobile/GenericCard.test.js +3 -3
  71. package/dist/components/GenericTable/Mobile/GenericCardList.js +4 -4
  72. package/dist/components/GenericTable/Mobile/GenericCardList.test.js +2 -2
  73. package/dist/components/HashTabView/HashTabView.js +39 -39
  74. package/dist/components/HashTabView/HashTabView.test.js +2 -2
  75. package/dist/components/HeaderFilter/HeaderFilter.js +1 -1
  76. package/dist/components/HeaderFilter/HeaderFilter.test.js +2 -2
  77. package/dist/components/Iconify/Iconify.js +2 -2
  78. package/dist/components/Iconify/Iconify.test.js +2 -2
  79. package/dist/components/InfoCard/InfoCard.js +4 -4
  80. package/dist/components/InfoCard/InfoCard.test.js +2 -2
  81. package/dist/components/InfoGroup/InfoGroup.js +3 -3
  82. package/dist/components/InfoGroup/InfoGroup.test.js +2 -2
  83. package/dist/components/ListArea/ListArea.js +6 -6
  84. package/dist/components/ListArea/ListArea.test.js +5 -5
  85. package/dist/components/ListArea/ListAreaService.js +6 -6
  86. package/dist/components/LoadingSpinner/Big/BigLoadingSpinner.js +2 -2
  87. package/dist/components/LoadingSpinner/Big/BigLoadingSpinner.test.js +3 -3
  88. package/dist/components/LoadingSpinner/Default/LoadingSpinner.js +11 -11
  89. package/dist/components/LoadingSpinner/Default/LoadingSpinner.test.js +2 -2
  90. package/dist/components/Modal/Modal.js +18 -18
  91. package/dist/components/ModulePadding/ModulePadding.js +14 -11
  92. package/dist/components/ModulePadding/ModulePadding.test.js +2 -2
  93. package/dist/components/OfflineView/OfflineView.js +4 -4
  94. package/dist/components/OfflineView/OfflineView.test.js +3 -3
  95. package/dist/components/OnboardingBanner/OnboardingBanner.js +7 -7
  96. package/dist/components/OnboardingBanner/OnboardingBanner.test.js +2 -2
  97. package/dist/components/OverflowTooltip/OverflowTooltip.js +2 -2
  98. package/dist/components/OverflowTooltip/OverflowTooltip.test.js +4 -4
  99. package/dist/components/PermissionChecks/PermissionService.d.ts +35 -0
  100. package/dist/components/PermissionChecks/PermissionService.js +28 -0
  101. package/dist/components/PermissionChecks/PermissionService.test.d.ts +1 -0
  102. package/dist/components/PermissionChecks/PermissionService.test.js +83 -0
  103. package/dist/components/PermissionChecks/mockedPermissions.d.ts +24 -0
  104. package/dist/components/PermissionChecks/mockedPermissions.js +299 -0
  105. package/dist/components/SafeForm/SafeForm.test.js +3 -3
  106. package/dist/components/Scrollbar/scrollbar.test.js +2 -2
  107. package/dist/components/SearchBar/SearchBar.js +2 -2
  108. package/dist/components/SearchBar/SearchBar.test.js +2 -2
  109. package/dist/components/Select/Select.js +2 -2
  110. package/dist/components/Select/Select.test.js +2 -2
  111. package/dist/components/SharedComponentsPermissionProvider/PermissionContext.d.ts +17 -0
  112. package/dist/components/SharedComponentsPermissionProvider/PermissionContext.js +11 -0
  113. package/dist/components/SharedComponentsPermissionProvider/SharedComponentsPermissionProvider.d.ts +32 -0
  114. package/dist/components/SharedComponentsPermissionProvider/SharedComponentsPermissionProvider.js +17 -0
  115. package/dist/components/Stepper/Stepper.js +1 -1
  116. package/dist/components/Stepper/Stepper.test.js +2 -2
  117. package/dist/components/Stepper/components/StepperButton.js +1 -1
  118. package/dist/components/Stepper/components/StepperHeader.js +2 -2
  119. package/dist/components/Stepper/components/StepperIndicator.js +1 -1
  120. package/dist/components/VerticalDivider/VerticalDivider.test.js +2 -2
  121. package/dist/{correct-is-regexp-logic-BBlm4UpN.js → correct-is-regexp-logic-Y0ToWEjF.js} +1 -1
  122. package/dist/{defineProperty-K2c2Cqi7.js → defineProperty-BTsGZ3c1.js} +3 -3
  123. package/dist/{es.string.iterator-5IsLbO9h.js → es.string.iterator-UszlTFwY.js} +6 -6
  124. package/dist/{find-nTYsLuUo.js → find-CHg-_ooq.js} +4 -4
  125. package/dist/get-D8IXqiys.js +7 -0
  126. package/dist/{get-u1nFMLdT.js → get-DxjPG00Z.js} +3 -3
  127. package/dist/hooks/useBreakpoints.test.js +2 -2
  128. package/dist/hooks/useHelperText.js +1 -1
  129. package/dist/{identity-BIZAN_pL.js → identity-BVIVr9qu.js} +4 -4
  130. package/dist/{index-CkZYDkGd.js → index-BLPBqbdx.js} +17 -17
  131. package/dist/{index-_ck2BRrZ.js → index-BcGujPyk.js} +9 -9
  132. package/dist/index-CuHybtft.js +51 -0
  133. package/dist/{index.es-DiONypF4.js → index.es--C-VLspF.js} +16 -16
  134. package/dist/{index.es-DYViXXnI.js → index.es-B1h6DPYp.js} +2 -2
  135. package/dist/{index.es-CvHDFF6V.js → index.es-B74L_Dje.js} +29 -29
  136. package/dist/{index.es-B0QNuIUR.js → index.es-B8p8KCdj.js} +4 -4
  137. package/dist/{index.es-C19v_2Tu.js → index.es-BHvm4m-B.js} +37 -37
  138. package/dist/{index.es-DnEIFMjv.js → index.es-BPv5dCFQ.js} +14 -14
  139. package/dist/{index.es-CIsLNz4j.js → index.es-BanVdXEd.js} +2 -2
  140. package/dist/{index.es-CP6nYw6D.js → index.es-Bo-d_yTV.js} +2 -2
  141. package/dist/{index.es-DHSqxTgL.js → index.es-BoUnovl_.js} +11 -11
  142. package/dist/{index.es-HCdWwFg5.js → index.es-C7cC1Hdu.js} +53 -53
  143. package/dist/{index.es-DZBGtuyV.js → index.es-CWyjqoEE.js} +11 -11
  144. package/dist/{index.es-BZ3r3ilq.js → index.es-CeQB6igi.js} +6 -6
  145. package/dist/{index.es-Ci73HfOg.js → index.es-Cfv794DG.js} +1 -1
  146. package/dist/{index.es-CEPrAgSM.js → index.es-DGoBge9W.js} +4 -4
  147. package/dist/{index.es-Bw3LT0xk.js → index.es-DOnQ26kT.js} +3 -3
  148. package/dist/{index.es-B3-Acyxs.js → index.es-DUTChZks.js} +10 -10
  149. package/dist/{index.es-C_feFtLb.js → index.es-Da7ok-B-.js} +6 -6
  150. package/dist/{index.es-DCYlADaN.js → index.es-Dgxrk6xW.js} +2 -2
  151. package/dist/{index.es-nqOhHSs3.js → index.es-DmRhbgqK.js} +6 -6
  152. package/dist/{index.es-NEYPxnlS.js → index.es-SjZ_-d7U.js} +2 -2
  153. package/dist/{index.es-fV9oWpEf.js → index.es-nwjKmW7-.js} +58 -58
  154. package/dist/{index.es-C1SajYlm.js → index.es-oxil0uFe.js} +3 -3
  155. package/dist/{index.es-C1u7zUBz.js → index.es-t87yNd9Y.js} +10 -10
  156. package/dist/{isArray-DN9s620O.js → isArray-B457bpaW.js} +1 -1
  157. package/dist/isArray-BjSPDQ4v.js +7 -0
  158. package/dist/{isEmpty-CxD71Jv8.js → isEmpty-BnfHn4bl.js} +3 -3
  159. package/dist/{isString-BNaBRq3S.js → isString-DVA49FEo.js} +3 -3
  160. package/dist/{isTypedArray-Dw_IY7Zq.js → isTypedArray-DziahYkI.js} +10 -10
  161. package/dist/{keyboard-20bkocNM.js → keyboard-DiKJoabs.js} +3 -3
  162. package/dist/magic-string.es-uPKorP4O.js +663 -0
  163. package/dist/main.d.ts +8 -0
  164. package/dist/main.js +76 -60
  165. package/dist/{map-Bx7eZRyR.js → map-BprzXv4m.js} +5 -5
  166. package/dist/omit-CYY_mIYv.js +662 -0
  167. package/dist/{orderBy-BXxEvUw6.js → orderBy-DLBJlgdL.js} +7 -7
  168. package/dist/{parse-int-Cmh59J6W.js → parse-int-D-3oah_F.js} +2 -2
  169. package/dist/{react-number-format.es-BK1EpVXq.js → react-number-format.es-DzkMiF8j.js} +3 -3
  170. package/dist/{react-tooltip.min-DSY6KDqS.js → react-tooltip.min-CVsI--2Y.js} +102 -102
  171. package/dist/{react.esm-BbMrgZCM.js → react.esm-Bm0cAgpZ.js} +30 -30
  172. package/dist/services/UtilService.js +21 -18
  173. package/dist/services/services.test.js +1 -1
  174. package/dist/{slicedToArray-h0Nnkd_P.js → slicedToArray-ByMQIs5x.js} +6 -6
  175. package/dist/test-utils.d.ts +82 -0
  176. package/dist/test-utils.js +32 -0
  177. package/dist/{toString-CrgB_7Pe.js → toString-B7FIT8FE.js} +1 -1
  178. package/dist/types/Permission.d.ts +176 -0
  179. package/dist/types/Permission.js +4 -0
  180. package/dist/{uniqueId-NU3-C36A.js → uniqueId-BNVTeImh.js} +2 -2
  181. package/dist/vi.bdSIJ99Y-B308Q-4w.js +11963 -0
  182. package/package.json +9 -8
  183. package/dist/get-DuK51wnj.js +0 -7
  184. package/dist/isArray-Dub1wGJM.js +0 -7
  185. package/dist/magic-string.es-D4UQQyt0.js +0 -859
  186. package/dist/omit-uTAyrUTm.js +0 -645
  187. package/dist/vi.CjhMlMwf-CKxPQtd6.js +0 -12192
package/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## [2.12.1](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.12.0...v2.12.1) (2026-02-03)
2
+
3
+ ### Code Refactoring
4
+
5
+ * update HVMainPermissions ([84cf791](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/84cf791abc08176505ae51d176a178a4e6a95c83))
6
+
7
+ ## [2.12.0](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.11.2...v2.12.0) (2026-02-02)
8
+
9
+ ### Features
10
+
11
+ * add a permission context and provider to be able to access permissions inside of shared components ([7462a97](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/7462a970c02a715eb8edb526d5afc4c50f829de3))
12
+ * add loadingspinner to AllowedButton ([a999ba5](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/a999ba53f1ae6806ec6a39b1443dc419fc0c2587))
13
+ * add permission types and enum from main repo ([f3da7fb](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/f3da7fb003158daf2e0901fe37cb90af5982af1d))
14
+ * add permissionService ([fabef22](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/fabef220f5f85773bc4044b069c8241b42987fad))
15
+ * add storybooks for newly introduced components ([7d79ea3](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/7d79ea3286f3775fe5ee30a432de7abf777c8995))
16
+ * addnew permission components to readMe + export new components from main ([1fbe431](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/1fbe4316e5e424b9c2bbcfc27e3ae03e427b1e31))
17
+ * introduce button components that are permission-gated ([c811d31](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/c811d3198bb72f32007db3a37c8eb822b341f1f9))
18
+ * introduce get permissionFromModulePermissionToken ([523ff1b](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/commit/523ff1b8d9c08af701a0318efb0e260cbf436431))
19
+
1
20
  ## [2.11.2](https://dev.azure.com/sdundc/HV%20Platform/_git/HortiView-Frontend-Shared/compare/v2.11.1...v2.11.2) (2026-01-27)
2
21
 
3
22
  ### Bug Fixes
package/README.md CHANGED
@@ -54,6 +54,7 @@ Additionally the library provides form components using [react-hook-form](https:
54
54
  1. [OfflineView](#offlineview)
55
55
  1. [OnboardingBanner](#onboardingbanner)
56
56
  1. [OverflowTooltip](#overflowtooltip)
57
+ 1. [Permissions](#permissions)
57
58
  1. [SafeForm](#safeform)
58
59
  1. [ScrollBar](#scrollbar)
59
60
  1. [SearchBar](#searchbar)
@@ -932,6 +933,137 @@ const longText =
932
933
  </OverflowTooltip>;
933
934
  ```
934
935
 
936
+ ### Permissions
937
+
938
+ This shared library provides different hooks and component that can be used to check wether a user is allowed to proceed with an action, view a component or not.
939
+
940
+ In order for this component to correctly determine whether a user has the appropriate permissions, a basic setup must be implemented. The following section explains how:
941
+
942
+ #### Setup
943
+
944
+ #### 1. Wrap your app with the SharedComponentsPermissionProvider
945
+
946
+ In your main application file (e.g., `App.tsx` or `main.tsx`), wrap your app with the `PermissionProvider`:
947
+
948
+ ```tsx
949
+ import { SharedComponentsPermissionProvider } from '@hortiview/shared-components';
950
+
951
+ function App() {
952
+ // Get these values from your store or state management
953
+ // In this example `Zustand` stores are used
954
+ const userPermissions = useClaimsIdentityStore(state => state.userPermissions);
955
+ const activeOrganizationId = useActiveOrganizationStore(state => state.activeOrganization?.id);
956
+
957
+ return (
958
+ <SharedComponentsPermissionProvider
959
+ userPermissions={userPermissions}
960
+ activeOrganizationId={activeOrganizationId}
961
+ >
962
+ <YourAppComponents />
963
+ </SharedComponentsPermissionProvider>
964
+ );
965
+ }
966
+ ```
967
+
968
+ #### 2.1 Use the Allowed component anywhere in your app
969
+
970
+ Once the provider is set up, you can use `<Allowed />` anywhere in your component tree without passing props. The wrapped component is conditionally rendered depending on the user permissions:
971
+
972
+ ```tsx
973
+ import { Allowed } from '@hortiview/shared-components';
974
+
975
+ function MyComponent() {
976
+ return (
977
+ <Allowed neededPermissions={["organization-read", "organization-edit"]} entityId={organizationId}>
978
+ <OrganizationSettings />
979
+ <Allowed/>
980
+ );
981
+ }
982
+ ```
983
+
984
+ #### 2.2 Use the useIsAllowed-hook anywhere in your app
985
+
986
+ The `useIsAllowed`-hook works similar to the `<Allowed />` component. Instead of being used as a wrapper it returns a boolean. That value can be used to conditionally render components or control application logic based on user permissions.
987
+
988
+ ```tsx
989
+ import { useIsAllowed } from '@hortiview/shared-components';
990
+
991
+ function MyComponent() {
992
+ const isAllowed = useIsAllowed();
993
+
994
+ // Check if user has permission to edit members for the current organization
995
+ const canEditMembers = isAllowed(['member-edit', 'member-create'], orgId);
996
+
997
+ return <MembersList isDisabled={!canEditMembers} />;
998
+ }
999
+ ```
1000
+
1001
+ #### 2.3 Use the AllowedButton or AllowedIconButton anywhere in your app
1002
+
1003
+ Once the provider is set up, you can use `AllowedButton` and `AllowedIconButton` anywhere in your component tree without passing props. Both buttons expect a permissions array and call the `useIsAllowed` under the hood.
1004
+
1005
+ > **Note:** Both components will automatically hide (return `null`) if the user doesn't have the required permissions. The button will only render when the user is authorized.
1006
+
1007
+ **AllowedButton Example:**
1008
+
1009
+ ```jsx
1010
+ import { AllowedButton, Permission } from '@hortiview/shared-components';
1011
+
1012
+ function FarmActions({ farmId }) {
1013
+ return (
1014
+ <div>
1015
+ <AllowedButton
1016
+ data-testid='edit-season-button'
1017
+ label='Edit Season'
1018
+ permissions={['season-edit']}
1019
+ entityId={organizationId}
1020
+ buttonVariant='filled'
1021
+ onClick={() => handleEditSeason(seasonId)}
1022
+ />
1023
+
1024
+ <AllowedButton
1025
+ data-testid='delete-season-button'
1026
+ label='Delete Season'
1027
+ permissions={['season-delete']}
1028
+ entityId={organizationId}
1029
+ buttonVariant='danger'
1030
+ onClick={() => handleDeleteSeason(seasonId)}
1031
+ />
1032
+ </div>
1033
+ );
1034
+ }
1035
+ ```
1036
+
1037
+ **AllowedIconButton Example:**
1038
+
1039
+ ```jsx
1040
+ import { AllowedIconButton, Permission } from '@hortiview/shared-components';
1041
+
1042
+ function BlockActions({ blockId, farmId }) {
1043
+ return (
1044
+ <div>
1045
+ <AllowedIconButton
1046
+ data-testid='edit-block-icon'
1047
+ icon='edit'
1048
+ permissions={['block-edit', 'block-create']}
1049
+ entityId={farmId}
1050
+ iconButtonVariant='filled-primary'
1051
+ onClick={() => handleEditBlock(blockId)}
1052
+ />
1053
+
1054
+ <AllowedIconButton
1055
+ data-testid='delete-block-icon'
1056
+ icon='delete'
1057
+ permissions={['block-delete']}
1058
+ entityId={farmId}
1059
+ iconButtonVariant='filled-danger'
1060
+ onClick={() => handleDeleteBlock(blockId)}
1061
+ />
1062
+ </div>
1063
+ );
1064
+ }
1065
+ ```
1066
+
935
1067
  ### SafeForm
936
1068
 
937
1069
  A wrapper around a form that prevents accidental submission when pressing Enter in input fields.
@@ -1018,10 +1150,10 @@ import { Select } from '@hortiview/shared-components';
1018
1150
  ### Stepper
1019
1151
 
1020
1152
  Provides a simple stepper component, which contains the step indicators, a title text and buttons to navigate forwards and backwards.
1021
- The component is available in two types:
1153
+ The component is available in two types:
1022
1154
 
1023
- * 'default' (steps as dots and a centered step title below them)
1024
- * 'description' (n/n numerical progress, description/title right of it)
1155
+ - 'default' (steps as dots and a centered step title below them)
1156
+ - 'description' (n/n numerical progress, description/title right of it)
1025
1157
 
1026
1158
  **Be aware that you need to control the Stepper flow by your own, like:**
1027
1159
 
@@ -1,7 +1,7 @@
1
1
  import { jsx as n, Fragment as i, jsxs as t } from "react/jsx-runtime";
2
- import { G as l } from "./index.es-C1SajYlm.js";
3
- import { I as _ } from "./index.es-DCYlADaN.js";
4
- import { T as m } from "./index.es-NEYPxnlS.js";
2
+ import { G as l } from "./index.es-oxil0uFe.js";
3
+ import { I as _ } from "./index.es-Dgxrk6xW.js";
4
+ import { T as m } from "./index.es-SjZ_-d7U.js";
5
5
  import './assets/AlertBanner.css';const d = "_messageContainer_2hnjr_1", g = "_info_2hnjr_9", h = "_danger_2hnjr_14", f = "_success_2hnjr_19", p = "_warning_2hnjr_24", u = "_closeIcon_2hnjr_29", j = "_linkBanner_2hnjr_34", s = {
6
6
  messageContainer: d,
7
7
  info: g,
@@ -1,5 +1,5 @@
1
1
  import { jsx as i, jsxs as n } from "react/jsx-runtime";
2
- import { T as r } from "./index.es-NEYPxnlS.js";
2
+ import { T as r } from "./index.es-SjZ_-d7U.js";
3
3
  import { Iconify as d } from "./components/Iconify/Iconify.js";
4
4
  import './assets/BigLoadingSpinner.css';const e = "_loadingBigOverlay_7dxo1_1", s = "_bigLoadSpinnerCard_7dxo1_12", g = "_bigLoadSpinnerCardText_7dxo1_27", t = "_logo_7dxo1_33", o = {
5
5
  loadingBigOverlay: e,
@@ -1,7 +1,7 @@
1
1
  import { jsx as r, jsxs as d, Fragment as C } from "react/jsx-runtime";
2
- import { C as h, a as m, b as T, c as g, d as v } from "./index.es-DnEIFMjv.js";
3
- import { G as b, a as x, b as c } from "./index.es-BZ3r3ilq.js";
4
- import { d as f } from "./index.es-NEYPxnlS.js";
2
+ import { C as h, a as m, b as T, c as g, d as v } from "./index.es-BPv5dCFQ.js";
3
+ import { G as b, a as x, b as c } from "./index.es-CeQB6igi.js";
4
+ import { d as f } from "./index.es-SjZ_-d7U.js";
5
5
  import { useMemo as w } from "react";
6
6
  import { OverflowTooltip as l } from "./components/OverflowTooltip/OverflowTooltip.js";
7
7
  import './assets/GenericCard.css';const u = "_cardTitle_ny9m0_1", B = "_cardBody_ny9m0_5", N = "_cardContent_ny9m0_10", $ = "_row_ny9m0_14", G = "_font_ny9m0_18", k = "_fontHeader_ny9m0_23", H = "_title_ny9m0_27", S = "_emptyContainer_ny9m0_33", A = "_empty_ny9m0_33", n = {
@@ -1,9 +1,9 @@
1
1
  import { jsx as a, jsxs as B } from "react/jsx-runtime";
2
- import { G } from "./index.es-C1SajYlm.js";
3
- import { I as S } from "./index.es-DCYlADaN.js";
4
- import { P as O } from "./index.es-CIsLNz4j.js";
5
- import { c as k, d as $, T as j } from "./index.es-NEYPxnlS.js";
6
- import { c as H } from "./index-_ck2BRrZ.js";
2
+ import { G } from "./index.es-oxil0uFe.js";
3
+ import { I as S } from "./index.es-Dgxrk6xW.js";
4
+ import { P as O } from "./index.es-BanVdXEd.js";
5
+ import { c as k, d as $, T as j } from "./index.es-SjZ_-d7U.js";
6
+ import { c as H } from "./index-BcGujPyk.js";
7
7
  import { Iconify as M } from "./components/Iconify/Iconify.js";
8
8
  import { AvailableCustomIcons as P } from "./enums/AvailableCustomIcons.js";
9
9
  import './assets/ListAreaService.css';const R = "_fullWidth_1abq6_1", W = "_mainElevation_1abq6_6", L = "_searchbar_1abq6_13", w = "_roundedBottom_1abq6_21", A = "_primaryText_1abq6_26", z = "_list_1abq6_30", D = "_listItem_1abq6_41", F = "_isSelected_1abq6_65", J = "_noGroupHeaderMargin_1abq6_74", K = "_indentGroupedElement_1abq6_78", Q = "_isNotSelected_1abq6_82", U = "_iconColor_1abq6_92", V = "_overlineTitle_1abq6_96", X = "_noOverlineTitle_1abq6_101", Y = "_truncate_1abq6_105", Z = "_truncateOverlineText_1abq6_116", ee = "_hasNoRoundedEdges_1abq6_121", t = {
@@ -1,8 +1,8 @@
1
1
  import { jsxs as r, jsx as e } from "react/jsx-runtime";
2
- import { G as o } from "./index.es-C1SajYlm.js";
2
+ import { G as o } from "./index.es-oxil0uFe.js";
3
3
  import { Iconify as _ } from "./components/Iconify/Iconify.js";
4
- import { b as m, d as y, T as h } from "./index.es-NEYPxnlS.js";
5
- import { B as A } from "./index.es-B0QNuIUR.js";
4
+ import { b as m, d as y, T as h } from "./index.es-SjZ_-d7U.js";
5
+ import { B as A } from "./index.es-B8p8KCdj.js";
6
6
  import './assets/OfflineView.css';const T = "_gapAndTextAlign_10nts_1", v = "_container_10nts_6", x = "_bgWhite_10nts_12", G = "_bgGrey_10nts_17", W = "_subtitle_10nts_22", t = {
7
7
  gapAndTextAlign: T,
8
8
  container: v,
@@ -1,4 +1,4 @@
1
- import { a as D, d as M } from "./isArray-DN9s620O.js";
1
+ import { a as D, d as M } from "./isArray-B457bpaW.js";
2
2
  var v, h;
3
3
  function T() {
4
4
  if (h) return v;
@@ -33,10 +33,10 @@ var g, I;
33
33
  function m() {
34
34
  if (I) return g;
35
35
  I = 1;
36
- var e = V(), r = function() {
36
+ var e = V(), r = (function() {
37
37
  var a = /[^.]+$/.exec(e && e.keys && e.keys.IE_PROTO || "");
38
38
  return a ? "Symbol(src)_1." + a : "";
39
- }();
39
+ })();
40
40
  function t(a) {
41
41
  return !!r && r in a;
42
42
  }
@@ -3,7 +3,7 @@ function f(e) {
3
3
  return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
4
4
  }
5
5
  function l(e) {
6
- if (e.__esModule) return e;
6
+ if (Object.prototype.hasOwnProperty.call(e, "__esModule")) return e;
7
7
  var r = e.default;
8
8
  if (typeof r == "function") {
9
9
  var t = function o() {
@@ -22,7 +22,7 @@
22
22
  */
23
23
  var o = (
24
24
  /** @class */
25
- function() {
25
+ (function() {
26
26
  function a() {
27
27
  this.rafIDs = /* @__PURE__ */ new Map();
28
28
  }
@@ -47,7 +47,7 @@ var o = (
47
47
  t.push(e);
48
48
  }), t;
49
49
  }, a;
50
- }()
50
+ })()
51
51
  );
52
52
  export {
53
53
  o as A
@@ -23,7 +23,7 @@ import { _ as r, a as u } from "./tslib.es6-BDCynO9F.js";
23
23
  */
24
24
  var a = (
25
25
  /** @class */
26
- function() {
26
+ (function() {
27
27
  function t(e) {
28
28
  e === void 0 && (e = {}), this.adapter = e;
29
29
  }
@@ -54,7 +54,7 @@ var a = (
54
54
  }), t.prototype.init = function() {
55
55
  }, t.prototype.destroy = function() {
56
56
  }, t;
57
- }()
57
+ })()
58
58
  );
59
59
  /**
60
60
  * @license
@@ -80,7 +80,7 @@ var a = (
80
80
  */
81
81
  var f = (
82
82
  /** @class */
83
- function() {
83
+ (function() {
84
84
  function t(e, o) {
85
85
  for (var n = [], i = 2; i < arguments.length; i++)
86
86
  n[i - 2] = arguments[i];
@@ -106,7 +106,7 @@ var f = (
106
106
  detail: o
107
107
  }) : (i = document.createEvent("CustomEvent"), i.initCustomEvent(e, n, !1, o)), this.root.dispatchEvent(i);
108
108
  }, t;
109
- }()
109
+ })()
110
110
  );
111
111
  export {
112
112
  a as M,
@@ -1,5 +1,5 @@
1
1
  import { b as E, c as v } from "./tslib.es6-BDCynO9F.js";
2
- import { M as S, a as I } from "./component-neHBNHRu.js";
2
+ import { M as S, a as I } from "./component-Bz_dtX1r.js";
3
3
  /**
4
4
  * @license
5
5
  * Copyright 2018 Google Inc.
@@ -199,7 +199,7 @@ var y = [
199
199
  "contextmenu"
200
200
  ], f = [], O = (
201
201
  /** @class */
202
- function(n) {
202
+ (function(n) {
203
203
  E(i, n);
204
204
  function i(t) {
205
205
  var e = n.call(this, v(v({}, i.defaultAdapter), t)) || this;
@@ -448,7 +448,7 @@ var y = [
448
448
  top: Math.round(this.frame_.height / 2 - this.initialSize_ / 2)
449
449
  }, this.adapter.updateCssVariable(a, this.unboundedCoords_.left + "px"), this.adapter.updateCssVariable(r, this.unboundedCoords_.top + "px"));
450
450
  }, i;
451
- }(S)
451
+ })(S)
452
452
  );
453
453
  /**
454
454
  * @license
@@ -474,7 +474,7 @@ var y = [
474
474
  */
475
475
  var U = (
476
476
  /** @class */
477
- function(n) {
477
+ (function(n) {
478
478
  E(i, n);
479
479
  function i() {
480
480
  var t = n !== null && n.apply(this, arguments) || this;
@@ -558,7 +558,7 @@ var U = (
558
558
  }, i.prototype.setUnbounded_ = function() {
559
559
  this.foundation.setUnbounded(!!this.unbounded_);
560
560
  }, i;
561
- }(I)
561
+ })(I)
562
562
  );
563
563
  export {
564
564
  U as M,
@@ -1,8 +1,8 @@
1
1
  import "react/jsx-runtime";
2
- import "../../index.es-C1SajYlm.js";
3
- import "../../index.es-DCYlADaN.js";
4
- import "../../index.es-NEYPxnlS.js";
5
- import { A as e } from "../../AlertBanner-C6wpAQMj.js";
2
+ import "../../index.es-oxil0uFe.js";
3
+ import "../../index.es-Dgxrk6xW.js";
4
+ import "../../index.es-SjZ_-d7U.js";
5
+ import { A as e } from "../../AlertBanner-Ci-F-6S9.js";
6
6
  export {
7
7
  e as AlertBanner
8
8
  };
@@ -1,8 +1,8 @@
1
1
  import { jsx as e, Fragment as m } from "react/jsx-runtime";
2
- import { a as t, s } from "../../react.esm-BbMrgZCM.js";
2
+ import { a as t, s } from "../../react.esm-Bm0cAgpZ.js";
3
3
  import { a as o } from "../../useBreakpoints-MzTZ0tCT.js";
4
- import { A as n } from "../../AlertBanner-C6wpAQMj.js";
5
- import { d as p, b as c, a as l, t as r, g as a } from "../../vi.CjhMlMwf-CKxPQtd6.js";
4
+ import { A as n } from "../../AlertBanner-Ci-F-6S9.js";
5
+ import { d as p, b as c, a as l, t as r, g as a } from "../../vi.bdSIJ99Y-B308Q-4w.js";
6
6
  p("AlertBanner Test", () => {
7
7
  c(() => {
8
8
  l.spyOn(o, "useBreakpoints").mockReturnValue({
@@ -1,8 +1,8 @@
1
1
  import { jsx as r, jsxs as a } from "react/jsx-runtime";
2
- import { G as l } from "../../index.es-C1SajYlm.js";
3
- import { T as s } from "../../index.es-NEYPxnlS.js";
2
+ import { G as l } from "../../index.es-oxil0uFe.js";
3
+ import { T as s } from "../../index.es-SjZ_-d7U.js";
4
4
  import { Iconify as p } from "../Iconify/Iconify.js";
5
- import { A as m, s as c } from "../../AlertBanner-C6wpAQMj.js";
5
+ import { A as m, s as c } from "../../AlertBanner-Ci-F-6S9.js";
6
6
  const g = ({
7
7
  text: n,
8
8
  color: o = "info",
@@ -1,8 +1,8 @@
1
1
  import { jsx as s } from "react/jsx-runtime";
2
- import { a as r, s as e } from "../../react.esm-BbMrgZCM.js";
2
+ import { a as r, s as e } from "../../react.esm-Bm0cAgpZ.js";
3
3
  import { a as o } from "../../useBreakpoints-MzTZ0tCT.js";
4
4
  import { LinkBanner as a } from "./LinkBanner.js";
5
- import { d as n, b as i, a as m, t as p, g as t } from "../../vi.CjhMlMwf-CKxPQtd6.js";
5
+ import { d as n, b as i, a as m, t as p, g as t } from "../../vi.bdSIJ99Y-B308Q-4w.js";
6
6
  n("LinkBanner Test", () => {
7
7
  i(() => {
8
8
  m.spyOn(o, "useBreakpoints").mockReturnValue({
@@ -0,0 +1,21 @@
1
+ import { PropsWithChildren } from 'react';
2
+ import { HVPermissions } from '../../types/Permission';
3
+
4
+ type AllowedProps = {
5
+ neededPermissions: HVPermissions[];
6
+ entityId: string | undefined;
7
+ disclaimer?: boolean;
8
+ disclaimerText?: string;
9
+ };
10
+ /**
11
+ * A component wrapper which takes permissions and an entity id (as a fallback the activeOrganization id is used) the permission is for.
12
+ * Returns the children if the user has the permission for the entity, nothing otherwise (or an optional disclaimer)
13
+ * @param children - the children to return if allowed to see it
14
+ * @param entityId - the entity id, the permission is for (FarmOrganizationId, VendorOrganizationId or FarmId)
15
+ * @param neededPermissions - the permissions needed to see the children
16
+ * @param disclaimer - if true a disclaimer is shown, otherwise not. (default: false)
17
+ * @param disclaimerText - the text to show in the disclaimer (default: 'You are not allowed to see the content of this section.')
18
+ * @returns
19
+ */
20
+ export declare const Allowed: ({ children, neededPermissions, entityId, disclaimer, disclaimerText, }: PropsWithChildren<AllowedProps>) => string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<import('react').ReactNode> | null | undefined;
21
+ export {};
@@ -0,0 +1,13 @@
1
+ import { jsx as s } from "react/jsx-runtime";
2
+ import { Disclaimer as i } from "../Disclaimer/Disclaimer.js";
3
+ import { useIsAllowed as n } from "../PermissionChecks/PermissionService.js";
4
+ const d = ({
5
+ children: o,
6
+ neededPermissions: e,
7
+ entityId: t,
8
+ disclaimer: r = !1,
9
+ disclaimerText: l = "You are not allowed to see the content of this section."
10
+ }) => n()(e, t) ? o : r ? /* @__PURE__ */ s(i, { text: l }) : null;
11
+ export {
12
+ d as Allowed
13
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,49 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ import { s as n } from "../../react.esm-Bm0cAgpZ.js";
3
+ import { renderWithPermissions as s } from "../../test-utils.js";
4
+ import { HVMainPermissions as o } from "../../types/Permission.js";
5
+ import { Allowed as i } from "./Allowed.js";
6
+ import { d as l, t as d, g as t } from "../../vi.bdSIJ99Y-B308Q-4w.js";
7
+ l("Test Allowed", () => {
8
+ d("should return the children if allowed to see them", () => {
9
+ const r = /* @__PURE__ */ e("div", { children: "Allowed to see children" });
10
+ s(
11
+ /* @__PURE__ */ e(i, { neededPermissions: [o.CurrentUserRead], entityId: "General", children: r }),
12
+ {
13
+ userPermissions: {
14
+ General: [o.CurrentUserRead]
15
+ }
16
+ }
17
+ ), t(n.getByText("Allowed to see children")).toBeInTheDocument();
18
+ }), d("should return empty wrapper when not allowed to see children", () => {
19
+ const r = /* @__PURE__ */ e("div", { children: "Allowed to see children" });
20
+ s(
21
+ /* @__PURE__ */ e(i, { neededPermissions: [o.CurrentUserRead], entityId: "General", children: r }),
22
+ {
23
+ userPermissions: {
24
+ General: []
25
+ }
26
+ }
27
+ ), t(n.queryByText("Allowed to see children")).not.toBeInTheDocument();
28
+ }), d("should return disclaimer when defined & not allowed to see children", () => {
29
+ const r = /* @__PURE__ */ e("div", { children: "Allowed to see children" });
30
+ s(
31
+ /* @__PURE__ */ e(
32
+ i,
33
+ {
34
+ disclaimer: !0,
35
+ neededPermissions: [o.CurrentUserRead],
36
+ entityId: "General",
37
+ children: r
38
+ }
39
+ ),
40
+ {
41
+ userPermissions: {
42
+ General: []
43
+ }
44
+ }
45
+ ), t(n.queryByText("Allowed to see children")).not.toBeInTheDocument(), t(
46
+ n.getByText("You are not allowed to see the content of this section.")
47
+ ).toBeInTheDocument();
48
+ });
49
+ });
@@ -0,0 +1,51 @@
1
+ import { ButtonProps } from '@element-public/react-button';
2
+ import { HVPermissions } from '../../types/Permission';
3
+
4
+ export type AllowedButtonProps = Omit<ButtonProps, 'buttonSize' | 'variant' | 'type' | 'label'> & {
5
+ /**
6
+ * This applies the html button type (button, submit, reset) or the anchor media type when used with the href property.
7
+ * Default: 'button'
8
+ */
9
+ buttonType?: 'button' | 'submit' | 'reset' | string;
10
+ /**
11
+ * Applies the selected style to the button.
12
+ * Default: 'filled'
13
+ */
14
+ variant?: 'filled' | 'outlined' | 'danger' | 'text' | 'success';
15
+ /**
16
+ * data-testid used for testing.
17
+ */
18
+ 'data-testid': string;
19
+ /**
20
+ * The entity id, the permission is for (FarmOrganizationId, VendorOrganizationId or FarmLocationId).
21
+ */
22
+ entityId?: string;
23
+ /**
24
+ * Id used for linking the button to a form.
25
+ */
26
+ formId?: string;
27
+ /**
28
+ * If true, the button shows a loading spinner instead of the label.
29
+ * While true, the button is disabled.
30
+ */
31
+ isLoading?: boolean;
32
+ /**
33
+ * Can be a string or JSX.Element for setting a loading spinner or custom component.
34
+ */
35
+ label: string | JSX.Element;
36
+ /**
37
+ * The permissions needed to enable the button. If the array is empty, the button is always enabled.
38
+ */
39
+ permissions: HVPermissions[];
40
+ /**
41
+ * Changes the the size of the button.
42
+ * Default: 'medium'
43
+ */
44
+ size?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
45
+ };
46
+ /**
47
+ * A permission-gated button component that only renders when the user has the required permissions.
48
+ * @param {AllowedButtonProps} props - Component properties
49
+ * @returns {JSX.Element | null} The button component or null if permissions are not met
50
+ */
51
+ export declare const AllowedButton: ({ buttonType, variant, "data-testid": testId, label, size, isLoading, ...props }: AllowedButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,28 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ import { B as r } from "../../index.es-B8p8KCdj.js";
3
+ import { Allowed as s } from "../Allowed/Allowed.js";
4
+ import { LoadingSpinner as a } from "../LoadingSpinner/Default/LoadingSpinner.js";
5
+ const c = ({
6
+ buttonType: d = "button",
7
+ variant: n = "filled",
8
+ "data-testid": o,
9
+ label: m,
10
+ size: l = "medium",
11
+ isLoading: i = !1,
12
+ ...t
13
+ }) => /* @__PURE__ */ e(s, { neededPermissions: t.permissions, entityId: t.entityId, children: /* @__PURE__ */ e(
14
+ r,
15
+ {
16
+ buttonSize: l,
17
+ "data-testid": `allowed-button-${o}`,
18
+ disabled: t.disabled || i,
19
+ form: t.formId,
20
+ type: d,
21
+ variant: n,
22
+ ...t,
23
+ children: i ? /* @__PURE__ */ e(a, { size: "sm", spinnerOnly: !0 }) : m
24
+ }
25
+ ) });
26
+ export {
27
+ c as AllowedButton
28
+ };