@wayke-se/components-react 3.5.3-beta.1 → 3.6.0-beta.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 (40) hide show
  1. package/dist-node/index.js +622 -127
  2. package/dist-node/index.js.map +1 -1
  3. package/dist-src/components/AccessoryCard/index.js +14 -0
  4. package/dist-src/components/AccessoryCard/wrapper.js +90 -0
  5. package/dist-src/components/DocumentList/wrapper.js +1 -1
  6. package/dist-src/components/Gallery/index.js +7 -4
  7. package/dist-src/components/Gallery/wrapper.js +1 -38
  8. package/dist-src/components/Icon/index.js +2 -0
  9. package/dist-src/components/Image/index.js +5 -0
  10. package/dist-src/components/Link/index.js +28 -0
  11. package/dist-src/components/NavButton/index.js +42 -0
  12. package/dist-src/components/OverflowGrid/index.js +56 -66
  13. package/dist-src/components/OverflowGrid/wrapper.js +144 -0
  14. package/dist-src/components/PriceBox/index.js +6 -0
  15. package/dist-src/components/PriceBox/wrapper.js +34 -0
  16. package/dist-src/layout/theme.js +8 -0
  17. package/dist-src/layouts/searchItem/Accessories/AccessoryModal.js +51 -0
  18. package/dist-src/layouts/searchItem/Accessories/index.js +32 -0
  19. package/dist-src/layouts/searchItem/Related.js +23 -25
  20. package/dist-src/layouts/searchItem/index.js +3 -1
  21. package/dist-src/queries/SEARCH_ITEM_BRANCH_QUERY.js +18 -0
  22. package/dist-src/queries/SEARCH_ITEM_QUERY.js +18 -0
  23. package/dist-types/@types/codegen/types.d.ts +17 -0
  24. package/dist-types/components/AccessoryCard/index.d.ts +16 -0
  25. package/dist-types/components/AccessoryCard/wrapper.d.ts +18 -0
  26. package/dist-types/components/Gallery/wrapper.d.ts +2 -6
  27. package/dist-types/components/Icon/index.d.ts +1 -0
  28. package/dist-types/components/Image/index.d.ts +1 -0
  29. package/dist-types/components/Link/index.d.ts +7 -0
  30. package/dist-types/components/NavButton/index.d.ts +3 -0
  31. package/dist-types/components/OverflowGrid/index.d.ts +12 -3
  32. package/dist-types/components/OverflowGrid/wrapper.d.ts +18 -0
  33. package/dist-types/components/PriceBox/index.d.ts +11 -0
  34. package/dist-types/components/PriceBox/wrapper.d.ts +10 -0
  35. package/dist-types/layout/theme.d.ts +8 -0
  36. package/dist-types/layouts/searchItem/Accessories/AccessoryModal.d.ts +8 -0
  37. package/dist-types/layouts/searchItem/Accessories/index.d.ts +7 -0
  38. package/dist-web/index.js +535 -122
  39. package/dist-web/index.js.map +1 -1
  40. package/package.json +1 -1
package/dist-web/index.js CHANGED
@@ -66,6 +66,14 @@ const theme = {
66
66
  Lg: '@media (min-width: 1200px)',
67
67
  LtLg: '@media (max-width: 1199px)',
68
68
  },
69
+ mask: {
70
+ gradient: {
71
+ toTop: 'linear-gradient(to top, #000, transparent)',
72
+ toBottom: 'linear-gradient(to bottom, #000, transparent)',
73
+ toLeft: 'linear-gradient(to left, #000, transparent)',
74
+ toRight: 'linear-gradient(to right, #000, transparent)',
75
+ },
76
+ },
69
77
  distances: {
70
78
  baseUnit: '8px',
71
79
  inputHeight: '48px',
@@ -650,6 +658,8 @@ const IconExclamationCircle = ({ block }) => (createElement(Icon$1, { viewBox: "
650
658
  createElement("path", { d: "M14.482 21.893c0-0.857 0.694-1.551 1.551-1.551s1.551 0.694 1.551 1.551c0 0.857-0.694 1.551-1.551 1.551s-1.551-0.694-1.551-1.551zM16.033 2.838c-7.271 0-13.187 5.916-13.187 13.187s5.916 13.187 13.187 13.187 13.187-5.916 13.187-13.187c0-7.271-5.916-13.187-13.187-13.187zM16.033 27.203c-6.163 0-11.178-5.015-11.178-11.178s5.015-11.178 11.178-11.178c6.164 0 11.178 5.015 11.178 11.178s-5.014 11.178-11.178 11.178zM16.033 8.308c-0.555 0-1.004 0.45-1.004 1.004v8.227c0 0.555 0.45 1.004 1.004 1.004s1.004-0.45 1.004-1.004v-8.227c0-0.555-0.45-1.004-1.004-1.004z" })));
651
659
  const IconExclamationTriangle = ({ block }) => (createElement(Icon$1, { viewBox: "0 0 32 32", block: block },
652
660
  createElement("path", { d: "M15.951 19.663c-0.457 0-0.828-0.37-0.828-0.828v-4.357c0-0.457 0.37-0.828 0.828-0.828s0.828 0.37 0.828 0.828v4.357c0 0.457-0.371 0.828-0.828 0.828zM15.952 22.906c-0.305 0-0.606-0.126-0.821-0.341s-0.338-0.514-0.338-0.818 0.122-0.606 0.338-0.821c0.431-0.43 1.209-0.43 1.639 0 0.215 0.215 0.341 0.516 0.341 0.821s-0.126 0.603-0.341 0.818c-0.215 0.215-0.513 0.341-0.818 0.341zM27.049 27.070h-22.196c-0.352 0-0.677-0.186-0.855-0.489s-0.184-0.677-0.014-0.985l11.098-20.105c0.175-0.317 0.508-0.513 0.87-0.513s0.695 0.197 0.87 0.513l11.098 20.105c0.17 0.308 0.165 0.683-0.014 0.985s-0.504 0.489-0.856 0.489zM6.536 25.083h18.83l-9.415-17.056-9.415 17.056z" })));
661
+ const IconImage = ({ block }) => (createElement(Icon$1, { viewBox: "0 0 16 16", block: block },
662
+ createElement("path", { d: "M14.4 1.6H1.6C.7 1.6 0 2.3 0 3.2v9.6c0 .9.7 1.6 1.6 1.6h12.8c.9 0 1.6-.7 1.6-1.6V3.2c0-.9-.7-1.6-1.6-1.6zm0 11.2H1.6V3.2h12.8v9.6zM3.2 6c0-.7.5-1.2 1.2-1.2s1.2.5 1.2 1.2-.5 1.2-1.2 1.2S3.2 6.7 3.2 6zm.2 4.5l6.2-4.4c.4-.3.9-.2 1.1.2v.1l2.4 4.2c.1.2 0 .4-.1.5-.1 0-.1.1-.2.1H3.7c-.2 0-.4-.2-.4-.4 0-.1 0-.3.1-.3z", fillRule: "evenodd", clipRule: "evenodd" })));
653
663
 
654
664
  const SortSelect = ({ value, options, onChange, unit }) => (React__default.createElement(Wrapper$4, null,
655
665
  React__default.createElement(Select, { value: value, onChange: onChange, title: "Sortering", "aria-label": "Sortering" }, options.map((option) => (React__default.createElement(Option, { key: option.value, value: option.value },
@@ -2940,47 +2950,10 @@ const ImageFull = styled.img `
2940
2950
  object-fit: cover;
2941
2951
  `;
2942
2952
  // Arrow Nav
2943
- const Arrow = styled(ButtonReset) `
2953
+ const Arrow = styled.div `
2944
2954
  position: absolute;
2945
2955
  top: 50%;
2946
2956
  transform: translateY(-50%);
2947
- display: flex;
2948
- align-items: center;
2949
- justify-content: center;
2950
- width: ${size(4)};
2951
- height: ${size(4)};
2952
- border-radius: 50%;
2953
- font-size: 1rem;
2954
- line-height: 1;
2955
- background-color: rgba(255, 255, 255, 0.4);
2956
- backdrop-filter: blur(5px);
2957
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
2958
- color: ${(props) => props.theme.color.textDark};
2959
- transform-origin: 50% 50%;
2960
- transition: transform 200ms ease;
2961
-
2962
- :before {
2963
- content: '';
2964
- position: absolute;
2965
- top: 0;
2966
- bottom: 0;
2967
- left: 0;
2968
- right: 0;
2969
- border-radius: 50%;
2970
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
2971
- opacity: 0;
2972
- transition: opacity 200ms ease;
2973
- }
2974
-
2975
- :hover {
2976
- :before {
2977
- opacity: 1;
2978
- }
2979
- }
2980
-
2981
- :active {
2982
- transform: translateY(-50%) scale(0.95);
2983
- }
2984
2957
 
2985
2958
  ${(props) => props.theme.breakpoint.LtSm} {
2986
2959
  display: none;
@@ -3083,6 +3056,46 @@ const EnableNavigationButton = styled.div `
3083
3056
  z-index: 1;
3084
3057
  `;
3085
3058
 
3059
+ const NavButton = styled(ButtonReset) `
3060
+ position: relative;
3061
+ display: flex;
3062
+ align-items: center;
3063
+ justify-content: center;
3064
+ width: ${size(4)};
3065
+ height: ${size(4)};
3066
+ border-radius: 50%;
3067
+ background-color: ${(props) => props.theme.color.bg};
3068
+ color: ${(props) => props.theme.color.textDark};
3069
+ font-size: 0.75rem;
3070
+ box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
3071
+ transition: transform 200ms ease;
3072
+
3073
+ &::before {
3074
+ content: '';
3075
+ position: absolute;
3076
+ top: 0;
3077
+ bottom: 0;
3078
+ left: 0;
3079
+ right: 0;
3080
+ border-radius: 50%;
3081
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
3082
+ opacity: 0;
3083
+ transition: opacity 200ms ease;
3084
+ }
3085
+
3086
+ &:enabled {
3087
+ &:hover {
3088
+ &::before {
3089
+ opacity: 1;
3090
+ }
3091
+ }
3092
+ }
3093
+
3094
+ &:active {
3095
+ transform: scale(0.95);
3096
+ }
3097
+ `;
3098
+
3086
3099
  const Wrapper$h = styled.div `
3087
3100
  position: fixed;
3088
3101
  top: 0;
@@ -4089,10 +4102,12 @@ const Gallery = ({ media, placeholderImage }) => {
4089
4102
  React__default.createElement(ButtonSecondary, { onClick: onEnableNavigation, title: "St\u00E4ng" },
4090
4103
  React__default.createElement(ButtonContent, null, "St\u00E4ng"))))),
4091
4104
  !navigationDisabled && mediaLength > 1 && (React__default.createElement(React__default.Fragment, null,
4092
- React__default.createElement(ArrowLeft, { onClick: prevImage, title: "F\u00F6reg\u00E5ende bild" },
4093
- React__default.createElement(IconChevronLeft, { block: true })),
4094
- React__default.createElement(ArrowRight, { onClick: nextImage, title: "N\u00E4sta bild" },
4095
- React__default.createElement(IconChevronRight, { block: true }))))),
4105
+ React__default.createElement(ArrowLeft, null,
4106
+ React__default.createElement(NavButton, { onClick: prevImage, title: "F\u00F6reg\u00E5ende bild" },
4107
+ React__default.createElement(IconChevronLeft, { block: true }))),
4108
+ React__default.createElement(ArrowRight, null,
4109
+ React__default.createElement(NavButton, { onClick: nextImage, title: "N\u00E4sta bild" },
4110
+ React__default.createElement(IconChevronRight, { block: true })))))),
4096
4111
  React__default.createElement(Alt, null,
4097
4112
  React__default.createElement(QuickNav, { ref: quickNavRef }, !!media?.length ? (media.map((m, i) => {
4098
4113
  const src = m.files[0].formats.filter(notEmpty).find((x) => x.format === '225x150')?.url ||
@@ -4218,6 +4233,24 @@ const SEARCH_ITEM_QUERY = gql `
4218
4233
  phonenumber
4219
4234
  avatar
4220
4235
  }
4236
+ accessories {
4237
+ articleNumber
4238
+ description
4239
+ excerpt
4240
+ id
4241
+ images
4242
+ logotype
4243
+ manufacturer
4244
+ model
4245
+ name
4246
+ price
4247
+ assemblyPrice
4248
+ productPage {
4249
+ title
4250
+ url
4251
+ }
4252
+ salePrice
4253
+ }
4221
4254
  manufacturer {
4222
4255
  description
4223
4256
  logotype
@@ -5895,69 +5928,200 @@ const SectionHeader = ({ children, onClick, actionTitle }) => (React__default.cr
5895
5928
  React__default.createElement(ButtonClear, { as: "a", href: "#", onClick: onClick },
5896
5929
  React__default.createElement(ButtonContent, null, actionTitle))))));
5897
5930
 
5898
- const OverflowGrid = styled.div `
5899
- ${(props) => props.theme.breakpoint.LtMd} {
5900
- ${Wrapper} & {
5901
- margin-left: ${size(-3)};
5902
- margin-right: ${size(-2)};
5903
- }
5931
+ const Wrapper$v = styled.div `
5932
+ --container-gutter: ${size(2)};
5933
+ --bg: ${(props) => props.theme.color.bg};
5934
+
5935
+ ${(props) => props.theme.breakpoint.Sm} {
5936
+ --container-gutter: ${size(3)};
5904
5937
  }
5905
5938
 
5939
+ position: relative;
5940
+
5941
+ ${({ $accentBg }) => $accentBg &&
5942
+ css `
5943
+ --bg: ${(props) => props.theme.color.accent};
5944
+ `}
5945
+ `;
5946
+ const Item$b = styled.li `
5947
+ flex: 1 0 auto;
5948
+ width: 100%;
5949
+ max-width: 100%;
5950
+ scroll-snap-align: start;
5951
+
5906
5952
  ${(props) => props.theme.breakpoint.LtSm} {
5907
- ${Wrapper} & {
5908
- margin-left: ${size(-2)};
5909
- margin-right: ${size(-1)};
5953
+ &:is(:only-child, #important) {
5954
+ width: 100%;
5955
+ max-width: 100%;
5910
5956
  }
5911
5957
  }
5912
5958
  `;
5913
- const OverflowGridList = styled.ul `
5959
+ const List$9 = styled.ul `
5914
5960
  display: flex;
5915
- align-items: flex-start;
5961
+ align-items: stretch;
5916
5962
  list-style: none;
5917
- padding: 0;
5918
- margin: ${size(-1)};
5963
+ padding: 0 var(--container-gutter);
5964
+ margin: 0;
5965
+ overflow: auto;
5966
+ scroll-snap-type: x mandatory;
5967
+ scroll-padding-left: var(--container-gutter);
5968
+ scrollbar-width: none;
5969
+ -ms-overflow-style: none;
5919
5970
 
5920
- ${(props) => props.theme.breakpoint.LtMd} {
5921
- ${Wrapper} & {
5922
- overflow: auto;
5923
- -webkit-overflow-scrolling: touch;
5924
- padding: 0 ${size(3)};
5971
+ &::-webkit-scrollbar {
5972
+ display: none;
5973
+ }
5925
5974
 
5926
- :after {
5927
- content: '';
5928
- flex: 0 0 auto;
5929
- height: 1px;
5930
- width: ${size(2)};
5975
+ ${({ $columns }) => $columns &&
5976
+ css `
5977
+ ${Item$b} {
5978
+ width: ${100 / $columns}%;
5979
+ max-width: ${100 / $columns}%;
5931
5980
  }
5932
- }
5933
- }
5981
+ `}
5934
5982
 
5935
- ${(props) => props.theme.breakpoint.LtSm} {
5936
- ${Wrapper} & {
5937
- padding: 0 ${size(2)};
5983
+ ${({ $columnsSm }) => $columnsSm &&
5984
+ css `
5985
+ ${(props) => props.theme.breakpoint.Sm} {
5986
+ ${Item$b} {
5987
+ width: ${100 / $columnsSm}%;
5988
+ max-width: ${100 / $columnsSm}%;
5989
+ }
5990
+ }
5991
+ `}
5938
5992
 
5939
- :after {
5940
- width: ${size(1)};
5993
+ ${({ $columnsMd }) => $columnsMd &&
5994
+ css `
5995
+ ${(props) => props.theme.breakpoint.Md} {
5996
+ ${Item$b} {
5997
+ width: ${100 / $columnsMd}%;
5998
+ max-width: ${100 / $columnsMd}%;
5999
+ }
5941
6000
  }
5942
- }
5943
- }
6001
+ `}
5944
6002
  `;
5945
- const OverflowGridItem = styled.li `
5946
- flex: 1 0 auto;
5947
- width: calc(100% - ${size(2)});
5948
- max-width: calc(100% - ${size(2)});
5949
- padding: ${size(1)};
6003
+ const ListWrapper = styled.div `
6004
+ position: relative;
6005
+ overflow: hidden;
6006
+ margin: 0 calc(var(--container-gutter) * -1);
5950
6007
 
5951
- ${(props) => props.theme.breakpoint.Sm} {
5952
- width: calc(50% - ${size(3)});
5953
- max-width: calc(50% - ${size(3)});
6008
+ ${(props) => props.theme.breakpoint.Md} {
6009
+ &::before,
6010
+ &::after {
6011
+ content: '';
6012
+ position: absolute;
6013
+ top: 0;
6014
+ bottom: 0;
6015
+ width: var(--container-gutter);
6016
+ background-color: var(--bg);
6017
+ z-index: 1;
6018
+ }
6019
+
6020
+ &::before {
6021
+ left: 0;
6022
+
6023
+ ${({ $spacing }) => $spacing
6024
+ ? css `
6025
+ mask-image: linear-gradient(to right, #000 ${size($spacing)}, transparent);
6026
+ `
6027
+ : css `
6028
+ mask-image: ${(props) => props.theme.mask.gradient.toRight};
6029
+ `}
6030
+ }
6031
+
6032
+ &::after {
6033
+ right: 0;
6034
+
6035
+ ${({ $spacing }) => $spacing
6036
+ ? css `
6037
+ mask-image: linear-gradient(to left, #000 ${size($spacing)}, transparent);
6038
+ `
6039
+ : css `
6040
+ mask-image: ${(props) => props.theme.mask.gradient.toLeft};
6041
+ `}
6042
+ }
5954
6043
  }
5955
6044
 
5956
- ${(props) => props.theme.breakpoint.Md} {
5957
- width: 33.333%;
5958
- max-width: 33.333%;
6045
+ ${({ $spacing }) => $spacing &&
6046
+ css `
6047
+ ${List$9} {
6048
+ margin: 0 -${size($spacing / 2)};
6049
+ }
6050
+
6051
+ ${Item$b} {
6052
+ padding: 0 ${size($spacing / 2)};
6053
+ }
6054
+ `}
6055
+ `;
6056
+ const NavBtn = styled.div `
6057
+ position: absolute;
6058
+ top: 50%;
6059
+ z-index: 2;
6060
+
6061
+ ${(props) => props.theme.breakpoint.LtSm} {
6062
+ display: none;
5959
6063
  }
5960
6064
  `;
6065
+ const PrevBtn = styled(NavBtn) `
6066
+ left: 0;
6067
+ transform: translate(-50%, -50%);
6068
+ `;
6069
+ const NextBtn = styled(NavBtn) `
6070
+ right: 0;
6071
+ transform: translate(50%, -50%);
6072
+ `;
6073
+
6074
+ const OverflowGrid = ({ items, itemKeyBase, spacing, columns, columnsSm, columnsMd, accentBg, }) => {
6075
+ const overflowElement = useRef(null);
6076
+ const onPrev = useCallback(() => {
6077
+ const itemWidth = overflowElement.current?.children[0].clientWidth || 0;
6078
+ const scrollLeft = overflowElement.current?.scrollLeft || 0;
6079
+ if (scrollLeft > 0) {
6080
+ overflowElement.current?.scroll({
6081
+ left: scrollLeft - itemWidth,
6082
+ behavior: 'smooth',
6083
+ });
6084
+ }
6085
+ }, []);
6086
+ const onNext = useCallback(() => {
6087
+ const itemWidth = overflowElement.current?.children[0].clientWidth || 0;
6088
+ const scrollWidth = overflowElement.current?.scrollWidth || 0;
6089
+ const scrollLeft = overflowElement.current?.scrollLeft || 0;
6090
+ const overflowElementWidth = overflowElement.current?.offsetWidth || 0;
6091
+ const overflowElementScrollWidth = scrollWidth - overflowElementWidth;
6092
+ if (overflowElementScrollWidth !== scrollLeft) {
6093
+ overflowElement.current?.scroll({
6094
+ left: scrollLeft + itemWidth,
6095
+ behavior: 'smooth',
6096
+ });
6097
+ }
6098
+ }, []);
6099
+ // Hide navigation buttons depending on scroll position
6100
+ const [hidePrevNav, setHidePrevNav] = useState(true);
6101
+ const [hideNextNav, setHideNextNav] = useState(true);
6102
+ const onScroll = () => {
6103
+ const scrollLeft = overflowElement.current?.scrollLeft || 0;
6104
+ const scrollWidth = overflowElement.current?.scrollWidth || 0;
6105
+ const overflowElementWidth = overflowElement.current?.offsetWidth || 0;
6106
+ const overflowElementScrollWidth = scrollWidth - overflowElementWidth;
6107
+ setHidePrevNav(scrollLeft == 0 ? true : false);
6108
+ setHideNextNav(overflowElementScrollWidth == scrollLeft ? true : false);
6109
+ };
6110
+ useEffect(() => {
6111
+ onScroll();
6112
+ overflowElement.current?.addEventListener('scroll', onScroll);
6113
+ return () => overflowElement.current?.removeEventListener('scroll', onScroll);
6114
+ }, []);
6115
+ return (React__default.createElement(Wrapper$v, { "$accentBg": accentBg },
6116
+ React__default.createElement(ListWrapper, { "$spacing": spacing },
6117
+ React__default.createElement(List$9, { ref: overflowElement, "$columns": columns, "$columnsSm": columnsSm, "$columnsMd": columnsMd }, items.map((item, i) => (React__default.createElement(Item$b, { key: itemKeyBase ? `${itemKeyBase}-${i}` : `overflow-grid-item-${i}` }, item))))),
6118
+ !hidePrevNav && (React__default.createElement(PrevBtn, null,
6119
+ React__default.createElement(NavButton, { onClick: onPrev, title: "Previous" },
6120
+ React__default.createElement(IconChevronLeft, null)))),
6121
+ !hideNextNav && (React__default.createElement(NextBtn, null,
6122
+ React__default.createElement(NavButton, { onClick: onNext, title: "Next" },
6123
+ React__default.createElement(IconChevronRight, null))))));
6124
+ };
5961
6125
 
5962
6126
  const RelatedSearchContext = createContext({
5963
6127
  moreLikeThisUrl: false,
@@ -6015,8 +6179,7 @@ const Related = ({ id, hashRoute, pathRoute, authorizedReseller, displayBranchNa
6015
6179
  React__default.createElement(SectionHeader, { onClick: () => { }, actionTitle: "Visa alla" },
6016
6180
  React__default.createElement(H2, { noMargin: true }, "Senast inkomna")))),
6017
6181
  React__default.createElement(Repeat, null,
6018
- React__default.createElement(OverflowGrid, null,
6019
- React__default.createElement(OverflowGridList, null, response?.documentList.documents.map((document) => {
6182
+ React__default.createElement(OverflowGrid, { accentBg: true, columns: 1.05, columnsSm: 2.1, columnsMd: 3, spacing: 2, items: response?.documentList.documents.map((document) => {
6020
6183
  const prefix = pathRoute ? `/${pathRoute}` : '/';
6021
6184
  const r = regexPathGuid();
6022
6185
  const pathRouteUrl = window.location.pathname === '/'
@@ -6024,28 +6187,27 @@ const Related = ({ id, hashRoute, pathRoute, authorizedReseller, displayBranchNa
6024
6187
  : r.test(`${pathRoute}${id}`)
6025
6188
  ? window.location.pathname.replace(r, document._id)
6026
6189
  : `${window.location.pathname}${prefix}${document._id}`;
6027
- return (React__default.createElement(OverflowGridItem, { key: document._id },
6028
- React__default.createElement(ProductCard, { id: document._id, onClick: onItemClicked, title: document.title, href: pathRoute ? pathRouteUrl : hashRoute ? `#${document._id}` : undefined, image: document.featuredImage?.files?.[0]?.url, description: document.shortDescription, branchName: displayBranchName ? document.branches?.[0]?.name : undefined, uspList: [
6029
- {
6030
- title: document.modelYear,
6031
- },
6032
- {
6033
- title: `${numberSeparator(document.mileage)} mil`,
6034
- },
6035
- {
6036
- title: document.gearboxType,
6037
- },
6038
- {
6039
- title: document.fuelType,
6040
- },
6041
- ], price: `${numberSeparator(document.price)} kr`, oldPrice: document.oldPrice !== undefined && document.price < document.oldPrice
6042
- ? `${numberSeparator(document.oldPrice)} kr`
6043
- : undefined, leasingPrice: document.leasingPrice !== undefined
6044
- ? `${numberSeparator(document.leasingPrice)} kr/mån`
6045
- : undefined, businessLeasingPrice: document.businessLeasingPrice !== undefined
6046
- ? `${numberSeparator(document.businessLeasingPrice)} kr/mån`
6047
- : undefined, pathRoute: pathRoute })));
6048
- })))))));
6190
+ return (React__default.createElement(ProductCard, { key: document._id, id: document._id, onClick: onItemClicked, title: document.title, href: pathRoute ? pathRouteUrl : hashRoute ? `#${document._id}` : undefined, image: document.featuredImage?.files?.[0]?.url, description: document.shortDescription, branchName: displayBranchName ? document.branches?.[0]?.name : undefined, uspList: [
6191
+ {
6192
+ title: document.modelYear,
6193
+ },
6194
+ {
6195
+ title: `${numberSeparator(document.mileage)} mil`,
6196
+ },
6197
+ {
6198
+ title: document.gearboxType,
6199
+ },
6200
+ {
6201
+ title: document.fuelType,
6202
+ },
6203
+ ], price: `${numberSeparator(document.price)} kr`, oldPrice: document.oldPrice !== undefined && document.price < document.oldPrice
6204
+ ? `${numberSeparator(document.oldPrice)} kr`
6205
+ : undefined, leasingPrice: document.leasingPrice !== undefined
6206
+ ? `${numberSeparator(document.leasingPrice)} kr/mån`
6207
+ : undefined, businessLeasingPrice: document.businessLeasingPrice !== undefined
6208
+ ? `${numberSeparator(document.businessLeasingPrice)} kr/mån`
6209
+ : undefined, pathRoute: pathRoute }));
6210
+ }) })))));
6049
6211
  };
6050
6212
 
6051
6213
  const PackageOptions = ({ packageOptions }) => {
@@ -6088,7 +6250,7 @@ const getBg = (severity) => {
6088
6250
  }
6089
6251
  return bg;
6090
6252
  };
6091
- const Wrapper$v = styled.div.attrs(() => ({
6253
+ const Wrapper$w = styled.div.attrs(() => ({
6092
6254
  className: 'wayke__theme wayke__font--bold',
6093
6255
  })) `
6094
6256
  display: inline-block;
@@ -6100,7 +6262,7 @@ const Wrapper$v = styled.div.attrs(() => ({
6100
6262
  line-height: 1.2;
6101
6263
  `;
6102
6264
 
6103
- const Badge = ({ label, severity }) => React__default.createElement(Wrapper$v, { severity: severity }, label);
6265
+ const Badge = ({ label, severity }) => React__default.createElement(Wrapper$w, { severity: severity }, label);
6104
6266
 
6105
6267
  const KeyOrder = [
6106
6268
  'monday',
@@ -6208,7 +6370,7 @@ const SettingsContext = createContext({});
6208
6370
 
6209
6371
  const useSettings = () => useContext(SettingsContext);
6210
6372
 
6211
- const Wrapper$w = styled.a `
6373
+ const Wrapper$x = styled.a `
6212
6374
  display: block;
6213
6375
  `;
6214
6376
  const Image$3 = styled.img `
@@ -6247,7 +6409,7 @@ const StaticMap = ({ position }) => {
6247
6409
  }
6248
6410
  const { latitude, longitude } = position;
6249
6411
  if (visible && googleMapsApiKey) {
6250
- return (React__default.createElement(Wrapper$w, { href: `http://maps.google.com/maps?q=${latitude},${longitude}`, title: "Visa p\u00E5 Google Maps", target: "_blank", rel: "nofollow noopener noreferrer" },
6412
+ return (React__default.createElement(Wrapper$x, { href: `http://maps.google.com/maps?q=${latitude},${longitude}`, title: "Visa p\u00E5 Google Maps", target: "_blank", rel: "nofollow noopener noreferrer" },
6251
6413
  React__default.createElement(Image$3, { src: `https://maps.googleapis.com/maps/api/staticmap?center=${latitude},${longitude}&zoom=10&size=640x280&maptype=roadmap&markers=${googleMapsMarker ? `icon:${encodeURIComponent(googleMapsMarker)}` : ''}%7C${latitude},${longitude}&key=${googleMapsApiKey}`, alt: "Karta" })));
6252
6414
  }
6253
6415
  return (React__default.createElement(Placeholder, { href: `http://maps.google.com/maps?q=${latitude},${longitude}`, target: "_blank", rel: "noopener noreferrer nofollow", onClick: onShowMap },
@@ -6314,6 +6476,24 @@ const SEARCH_ITEM_BRANCH_QUERY = gql `
6314
6476
  phonenumber
6315
6477
  avatar
6316
6478
  }
6479
+ accessories {
6480
+ articleNumber
6481
+ description
6482
+ excerpt
6483
+ id
6484
+ images
6485
+ logotype
6486
+ manufacturer
6487
+ model
6488
+ name
6489
+ price
6490
+ assemblyPrice
6491
+ productPage {
6492
+ title
6493
+ url
6494
+ }
6495
+ salePrice
6496
+ }
6317
6497
  branch {
6318
6498
  connections {
6319
6499
  id
@@ -7084,7 +7264,7 @@ const MetadataItem = ({ name, hint, value, unit }) => {
7084
7264
  React__default.createElement(Content$2, { dangerouslySetInnerHTML: { __html: hint } })))));
7085
7265
  };
7086
7266
 
7087
- const Wrapper$x = styled.div `
7267
+ const Wrapper$y = styled.div `
7088
7268
  overflow: hidden;
7089
7269
  margin-top: ${size(-1)};
7090
7270
  margin-left: ${size(-1)};
@@ -7095,7 +7275,7 @@ const Wrapper$x = styled.div `
7095
7275
  margin-right: ${size(-2)};
7096
7276
  }
7097
7277
  `;
7098
- const List$9 = styled.ul `
7278
+ const List$a = styled.ul `
7099
7279
  list-style: none;
7100
7280
  padding: 0;
7101
7281
  margin: 0;
@@ -7109,7 +7289,7 @@ const List$9 = styled.ul `
7109
7289
  padding-right: ${size(1)};
7110
7290
  }
7111
7291
  `;
7112
- const Item$b = styled.li `
7292
+ const Item$c = styled.li `
7113
7293
  display: inline-block;
7114
7294
  vertical-align: bottom;
7115
7295
  font-size: 1rem;
@@ -7150,8 +7330,8 @@ const Action$8 = styled(ButtonReset).attrs(() => ({
7150
7330
  `}
7151
7331
  `;
7152
7332
 
7153
- const Tabs = ({ tabs, active, onClick }) => (createElement(Wrapper$x, null,
7154
- createElement(List$9, null, tabs.map((tab) => (createElement(Item$b, { key: tab.name },
7333
+ const Tabs = ({ tabs, active, onClick }) => (createElement(Wrapper$y, null,
7334
+ createElement(List$a, null, tabs.map((tab) => (createElement(Item$c, { key: tab.name },
7155
7335
  createElement(Action$8, { title: tab.displayName, onClick: onClick ? () => onClick(tab.name) : undefined, active: tab.name === active ? 'true' : undefined }, tab.displayName)))))));
7156
7336
 
7157
7337
  const MetadataSubCategory = ({ name, properties }) => (React__default.createElement(Repeat, null,
@@ -7208,7 +7388,7 @@ const PdfListItem = styled.li.attrs(() => ({
7208
7388
  flex: 0 0 100%;
7209
7389
  }
7210
7390
  `;
7211
- const List$a = styled.ul `
7391
+ const List$b = styled.ul `
7212
7392
  list-style: none;
7213
7393
  padding: 0;
7214
7394
  display: flex;
@@ -7236,7 +7416,7 @@ const PdfSubtitle = styled.div `
7236
7416
  color: ${(props) => props.theme.color.textDarkLighten};
7237
7417
  `;
7238
7418
  const PdfColumn = styled.div `
7239
- flex 0 0 auto;
7419
+ flex: 0 0 auto;
7240
7420
  &:first-child {
7241
7421
  flex: 1 1 auto;
7242
7422
  }
@@ -7271,7 +7451,7 @@ const PdfDownloadItem = ({ document }) => {
7271
7451
  React__default.createElement(PdfColumn, null,
7272
7452
  React__default.createElement(PdfLink, { href: document.url, rel: "noopener noreferrer nofollow", target: "_blank" }, "\u00D6ppna")))));
7273
7453
  };
7274
- const DocumentList = ({ documents }) => (React__default.createElement(List$a, null, documents.map((document, i) => (React__default.createElement(PdfDownloadItem, { key: `${document.url}-${i}`, document: document })))));
7454
+ const DocumentList = ({ documents }) => (React__default.createElement(List$b, null, documents.map((document, i) => (React__default.createElement(PdfDownloadItem, { key: `${document.url}-${i}`, document: document })))));
7275
7455
 
7276
7456
  const Translation = {
7277
7457
  'tyre-label': 'Energideklaration för däck',
@@ -7312,6 +7492,238 @@ const Documents = ({ documents }) => {
7312
7492
  React__default.createElement(DocumentList, { documents: group.documents }))))));
7313
7493
  };
7314
7494
 
7495
+ const Wrapper$z = styled.div `
7496
+ display: flex;
7497
+ flex-direction: column;
7498
+ gap: ${size(2)};
7499
+ height: 100%;
7500
+ `;
7501
+ const imageBaseStyling = css `
7502
+ flex-shrink: 0;
7503
+ aspect-ratio: 16 / 9;
7504
+ border-radius: 3px;
7505
+ `;
7506
+ const Image$4 = styled.img `
7507
+ ${imageBaseStyling};
7508
+ display: block;
7509
+ width: 100%;
7510
+ object-fit: cover;
7511
+ `;
7512
+ const ImageaPlaceholder = styled.div `
7513
+ ${imageBaseStyling};
7514
+ display: flex;
7515
+ align-items: center;
7516
+ justify-content: center;
7517
+ color: ${(props) => props.theme.color.textDarkLighten};
7518
+ font-size: 2rem;
7519
+ background-color: ${(props) => props.theme.color.accent};
7520
+ `;
7521
+ const Body$5 = styled.div `
7522
+ flex: 1 1 auto;
7523
+ display: flex;
7524
+ align-items: flex-start;
7525
+ flex-direction: column;
7526
+ gap: ${size(1)};
7527
+ `;
7528
+ const Heading$7 = styled.div `
7529
+ display: flex;
7530
+ align-items: center;
7531
+ justify-content: space-between;
7532
+ gap: ${size(2)};
7533
+ `;
7534
+ const Title$2 = styled.div.attrs(() => ({
7535
+ className: 'wayke__theme wayke__font--bold',
7536
+ })) `
7537
+ font-size: 1.125rem;
7538
+ `;
7539
+ const Branding = styled.img `
7540
+ display: block;
7541
+ `;
7542
+ const Price$2 = styled.div.attrs(() => ({
7543
+ className: 'wayke__theme wayke__font--bold',
7544
+ })) ``;
7545
+ const Preamble = styled.div `
7546
+ --preamble-max-height: ${size(6)};
7547
+ --preamble-gradient-height: calc(var(--preamble-max-height) / 2);
7548
+
7549
+ position: relative;
7550
+ max-height: var(--preamble-max-height);
7551
+ overflow: hidden;
7552
+ display: -webkit-box;
7553
+ -webkit-box-orient: vertical;
7554
+ -webkit-line-clamp: 2;
7555
+ white-space: pre-wrap;
7556
+
7557
+ &::before {
7558
+ content: '';
7559
+ position: absolute;
7560
+ top: var(--preamble-max-height);
7561
+ left: 0;
7562
+ width: 100%;
7563
+ height: var(--preamble-gradient-height);
7564
+ transform: translateY(-100%); // Only visible if Preamble reaches max height
7565
+ color: ${(props) => props.theme.color.bg};
7566
+ mask-image: ${(props) => props.theme.mask.gradient.toTop};
7567
+ pointer-events: none;
7568
+ }
7569
+ `;
7570
+ const ReadMoreBtn = styled(ButtonReset).attrs(() => ({
7571
+ className: 'wayke__theme wayke__font--bold wayke__color--primary-text',
7572
+ })) `
7573
+ margin-top: auto;
7574
+ display: block;
7575
+ color: ${(props) => props.theme.color.link};
7576
+ font-size: 0.875rem;
7577
+
7578
+ &:hover {
7579
+ text-decoration: underline;
7580
+ }
7581
+ `;
7582
+
7583
+ const AccessoryCard = ({ title, image, branding, price, preamble, readMoreCta, }) => (React__default.createElement(Wrapper$z, null,
7584
+ image ? (React__default.createElement(Image$4, { src: image.src, srcSet: image.srcSet, alt: image.alt })) : (React__default.createElement(ImageaPlaceholder, null,
7585
+ React__default.createElement(IconImage, null))),
7586
+ React__default.createElement(Body$5, null,
7587
+ React__default.createElement(Heading$7, null,
7588
+ React__default.createElement(Title$2, null, title),
7589
+ branding && React__default.createElement(Branding, { src: branding.src, srcSet: branding.srcSet, alt: branding.alt })),
7590
+ price && React__default.createElement(Price$2, null, price),
7591
+ preamble && React__default.createElement(Preamble, null, preamble),
7592
+ readMoreCta && React__default.createElement(ReadMoreBtn, { onClick: readMoreCta }, "L\u00E4s mer"))));
7593
+
7594
+ const Image$5 = styled.img `
7595
+ display: block;
7596
+ width: 100%;
7597
+ `;
7598
+
7599
+ const Link$1 = styled.a.attrs(() => ({
7600
+ className: 'wayke__theme wayke__color--primary-text',
7601
+ })) `
7602
+ text-decoration: none;
7603
+ cursor: pointer;
7604
+ text-decoration: underline;
7605
+
7606
+ :not(:hover) {
7607
+ color: ${(props) => props.theme.color.textDark};
7608
+ }
7609
+
7610
+ &:hover {
7611
+ text-decoration: underline;
7612
+ }
7613
+
7614
+ ${({ $hoverGhost }) => $hoverGhost &&
7615
+ css `
7616
+ &:before {
7617
+ content: '';
7618
+ position: absolute;
7619
+ top: 0;
7620
+ left: 0;
7621
+ width: 100%;
7622
+ height: 100%;
7623
+ }
7624
+ `}
7625
+ `;
7626
+
7627
+ const Wrapper$A = styled.ul `
7628
+ --price-box-gutter: ${size(2)};
7629
+
7630
+ list-style: none;
7631
+ padding: var(--price-box-gutter);
7632
+ margin: 0;
7633
+ border: 1px solid ${(props) => props.theme.color.border};
7634
+ `;
7635
+ const Row = styled.li `
7636
+ display: flex;
7637
+ align-items: center;
7638
+ justify-content: space-between;
7639
+ gap: var(--price-box-gutter);
7640
+
7641
+ & + & {
7642
+ margin-top: calc(var(--price-box-gutter) / 4);
7643
+ }
7644
+
7645
+ ${({ $oldPrice }) => $oldPrice &&
7646
+ css `
7647
+ --price-text-decoration: line-through;
7648
+
7649
+ color: ${(props) => props.theme.color.textDarkLighten};
7650
+ font-size: 0.875rem;
7651
+ `}
7652
+ `;
7653
+ const Label$a = styled.div ``;
7654
+ const Price$3 = styled.div.attrs(() => ({
7655
+ className: 'wayke__theme wayke__font--bold',
7656
+ })) `
7657
+ text-decoration: var(--price-text-decoration);
7658
+ `;
7659
+
7660
+ const PriceBox = ({ prices }) => (React__default.createElement(Wrapper$A, null, prices?.map((item, i) => (React__default.createElement(Row, { key: `${item.label}-${i}`, "$oldPrice": item.oldPrice },
7661
+ React__default.createElement(Label$a, null, item.label),
7662
+ React__default.createElement(Price$3, null, item.price))))));
7663
+
7664
+ const AccesoryModal = ({ accessory, onClose }) => {
7665
+ const priceList = [
7666
+ {
7667
+ label: 'Kontantpris',
7668
+ price: `${numberSeparator(accessory.price)} kr`,
7669
+ oldPrice: false,
7670
+ },
7671
+ ];
7672
+ if (accessory.salePrice) {
7673
+ priceList.push({
7674
+ label: 'Tidigare pris',
7675
+ price: `${numberSeparator(accessory.salePrice)} kr`,
7676
+ oldPrice: true,
7677
+ });
7678
+ }
7679
+ if (accessory.assemblyPrice) {
7680
+ priceList.push({
7681
+ label: 'Monteringskostnad',
7682
+ price: `${numberSeparator(accessory.assemblyPrice)} kr`,
7683
+ oldPrice: false,
7684
+ });
7685
+ }
7686
+ return (React__default.createElement(Modal, { title: accessory.name, onClose: onClose },
7687
+ accessory.images?.[0] && (React__default.createElement(Repeat, null,
7688
+ React__default.createElement(Image$5, { src: `${accessory.images[0]}?w=632`, alt: `${accessory.name}` }))),
7689
+ accessory.logotype && (React__default.createElement(Repeat, null,
7690
+ React__default.createElement(LogoBox, { logo: `${accessory.logotype}?w=160`, logo2x: `${accessory.logotype}?w=320`, alt: accessory.manufacturer || 'Logotyp', wide: true }))),
7691
+ React__default.createElement(Repeat, null,
7692
+ React__default.createElement(PriceBox, { prices: priceList })),
7693
+ React__default.createElement(Repeat, null,
7694
+ React__default.createElement(Content$2, { dangerouslySetInnerHTML: { __html: marked(accessory.description) } })),
7695
+ accessory.articleNumber && (React__default.createElement(Repeat, null,
7696
+ React__default.createElement(UtilityTextBold, { as: "div" }, "Art. nr."),
7697
+ React__default.createElement("div", null, accessory.articleNumber))),
7698
+ accessory.productPage && accessory.productPage.url && (React__default.createElement(Repeat, null,
7699
+ React__default.createElement(Link$1, { href: accessory.productPage.url, title: `Mer information om ${accessory.name}`, target: "_blank", rel: "noopener noreferrer nofollow" },
7700
+ accessory.productPage.title || 'Läs mer',
7701
+ " (\u00F6ppnas i ny flik)")))));
7702
+ };
7703
+
7704
+ const AccessoriesSection = ({ accessories }) => {
7705
+ const [modal, setModal] = useState();
7706
+ const onOpenModal = (accessory) => setModal(accessory);
7707
+ const onCloseModal = () => setModal(undefined);
7708
+ if (!accessories?.length)
7709
+ return null;
7710
+ return (React__default.createElement(React__default.Fragment, null,
7711
+ modal && React__default.createElement(AccesoryModal, { accessory: modal, onClose: onCloseModal }),
7712
+ React__default.createElement(ProductPageMainSection, null,
7713
+ React__default.createElement(Repeat, null,
7714
+ React__default.createElement(H2, { noMargin: true }, "Tillbeh\u00F6r")),
7715
+ React__default.createElement(Repeat, null,
7716
+ React__default.createElement(Content$2, null,
7717
+ React__default.createElement("p", null, "Tillbeh\u00F6r som passar till detta fordon."))),
7718
+ React__default.createElement(Repeat, null,
7719
+ React__default.createElement(OverflowGrid, { columns: 1.05, columnsSm: 2.1, columnsMd: 2, spacing: 2, items: accessories.map((accessory) => (React__default.createElement(AccessoryCard, { key: accessory.id, title: accessory.name, image: accessory.images?.[0]
7720
+ ? {
7721
+ src: `${accessory.images?.[0]}?w=539&h=303`,
7722
+ alt: accessory.name,
7723
+ }
7724
+ : undefined, price: `${numberSeparator(accessory.price)} kr`, preamble: accessory.excerpt, readMoreCta: () => onOpenModal(accessory) }))) })))));
7725
+ };
7726
+
7315
7727
  const WaykeSearchItem = ({ id, hashRoute, pathRoute, disableResetScrollOnInit, placeholderImage, modifyDocumentTitleItem, displayBranchName, onClickSearchItem, }) => {
7316
7728
  const { ecomSettings } = useSettings();
7317
7729
  const ecomContext = useRef();
@@ -7365,7 +7777,7 @@ const WaykeSearchItem = ({ id, hashRoute, pathRoute, disableResetScrollOnInit, p
7365
7777
  const { vehicle } = result;
7366
7778
  const contact = centralStorageVehicle?.contact;
7367
7779
  const branch = centralStorageVehicle?.branch;
7368
- const { title, shortDescription, media, description, price, discount, financialOptions, manufacturer, ecommerce, packageOptions, publishedAt, documents, availableFrom, flags, } = vehicle;
7780
+ const { title, accessories, shortDescription, media, description, price, discount, financialOptions, manufacturer, ecommerce, packageOptions, publishedAt, documents, availableFrom, flags, } = vehicle;
7369
7781
  const insuranceOptions = centralStorageVehicle?.insuranceOptions
7370
7782
  ? centralStorageVehicle.insuranceOptions
7371
7783
  : vehicle.insuranceOptions;
@@ -7448,6 +7860,7 @@ const WaykeSearchItem = ({ id, hashRoute, pathRoute, disableResetScrollOnInit, p
7448
7860
  React__default.createElement(Branch, { branch: branch, displayBranchName: displayBranchName, loading: loadingCentralStorageVehicle }),
7449
7861
  ecommerce && ecommerce.enabled && (React__default.createElement(Repeat, null,
7450
7862
  React__default.createElement(ButtonPrimary, { disabled: !!ecommerce.reserved, title: "K\u00F6p bilen online", onClick: () => ecomContext.current?.start() }, "K\u00F6p bilen online")))),
7863
+ React__default.createElement(AccessoriesSection, { accessories: accessories }),
7451
7864
  React__default.createElement(PackageOptions, { packageOptions: packageOptions }),
7452
7865
  React__default.createElement(ManufacturerPackageOption, { packageOption: manufacturer?.packageOption }))))),
7453
7866
  React__default.createElement(Related, { id: id, hashRoute: hashRoute, pathRoute: pathRoute, authorizedReseller: !!branch?.flags?.authorizedReseller, displayBranchName: displayBranchName, onClickSearchItem: onClickSearchItem })),