@uniformdev/csk-components 6.0.113-alpha.1 → 6.0.117-alpha.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 (95) hide show
  1. package/dist/{accordion-item-VWHOTJAC.mjs → accordion-item-QAVKQEB2.mjs} +1 -1
  2. package/dist/{accordion-item-NUEMADB2.mjs → accordion-item-Y4PSNOH4.mjs} +1 -1
  3. package/dist/{banner-2B4K5R4N.mjs → banner-EYII7V7X.mjs} +1 -1
  4. package/dist/carousel-RZ2DV6QX.mjs +1 -0
  5. package/dist/carousel-YELQRJVB.mjs +1 -0
  6. package/dist/chunk-2BMAPB63.mjs +1 -0
  7. package/dist/chunk-7GVG4HLE.mjs +1 -0
  8. package/dist/{chunk-LA36HQWS.mjs → chunk-B2O55EVA.mjs} +1 -1
  9. package/dist/chunk-EOV2LPGC.mjs +1 -0
  10. package/dist/chunk-EUVKAE6M.mjs +1 -0
  11. package/dist/chunk-FIN5US3Q.mjs +1 -0
  12. package/dist/chunk-M6FDQCD7.mjs +1 -0
  13. package/dist/{chunk-TDAANMNJ.mjs → chunk-PMMAALCQ.mjs} +1 -1
  14. package/dist/chunk-TCQTXNKT.mjs +1 -0
  15. package/dist/{chunk-3PDY7RJC.mjs → chunk-TFA6HYP4.mjs} +2 -2
  16. package/dist/{chunk-FPOIJMYT.mjs → chunk-VW2XC3SE.mjs} +1 -1
  17. package/dist/components/canvas/emptyPlaceholders.mjs +1 -1
  18. package/dist/components/canvas/index.d.mts +2 -18
  19. package/dist/components/canvas/index.mjs +2 -2
  20. package/dist/components/ui/index.d.mts +23 -10
  21. package/dist/components/ui/index.mjs +1 -1
  22. package/dist/content/components/canvas/Accordion/accordion.tsx +1 -3
  23. package/dist/content/components/canvas/Card/card.tsx +1 -3
  24. package/dist/content/components/canvas/Carousel/carousel.tsx +1 -3
  25. package/dist/content/components/canvas/Container/container.tsx +0 -4
  26. package/dist/content/components/canvas/Container/parameters.ts +0 -4
  27. package/dist/content/components/canvas/DemoHero/atoms.tsx +1 -1
  28. package/dist/content/components/canvas/DemoHero/columns-variant.tsx +1 -7
  29. package/dist/content/components/canvas/DemoHero/default-variant.tsx +1 -8
  30. package/dist/content/components/canvas/DemoHero/demo-hero.tsx +0 -4
  31. package/dist/content/components/canvas/DemoHero/fixed-hero.tsx +56 -66
  32. package/dist/content/components/canvas/DemoHero/index.tsx +1 -12
  33. package/dist/content/components/canvas/Flex/flex.tsx +0 -4
  34. package/dist/content/components/canvas/Grid/grid.tsx +1 -3
  35. package/dist/content/components/canvas/Image/image.tsx +2 -2
  36. package/dist/content/components/canvas/ImageGallery/image-gallery.tsx +1 -3
  37. package/dist/content/components/canvas/Modal/modal.tsx +12 -69
  38. package/dist/content/components/canvas/Review/default-variant.tsx +1 -3
  39. package/dist/content/components/canvas/Review/multi-column-variant.tsx +1 -3
  40. package/dist/content/components/canvas/Section/columns-variant.tsx +1 -7
  41. package/dist/content/components/canvas/Section/default-variant.tsx +1 -10
  42. package/dist/content/components/canvas/Section/section.tsx +0 -4
  43. package/dist/content/components/canvas/Table/table.tsx +1 -6
  44. package/dist/content/components/canvas/Tabs/tabs.tsx +1 -6
  45. package/dist/content/components/canvas/Testimonial/default-variant.tsx +2 -4
  46. package/dist/content/components/canvas/Testimonial/testimonial.tsx +0 -4
  47. package/dist/content/components/canvas/Testimonial/with-large-avatar-variant.tsx +2 -4
  48. package/dist/content/components/canvas/Testimonial/with-overlapping-image-variant.tsx +2 -4
  49. package/dist/content/components/canvas/Video/index.tsx +0 -2
  50. package/dist/content/components/canvas/Video/video.tsx +1 -2
  51. package/dist/content/components/ui/Accordion/accordion.tsx +23 -0
  52. package/dist/content/components/ui/Accordion/index.tsx +9 -0
  53. package/dist/content/components/ui/AccordionItem/accordion-item.tsx +41 -0
  54. package/dist/content/components/ui/AccordionItem/icon-arrow-down.tsx +20 -0
  55. package/dist/content/components/ui/AccordionItem/icon-arrow-up.tsx +20 -0
  56. package/dist/content/components/ui/AccordionItem/index.tsx +16 -0
  57. package/dist/content/components/ui/Carousel/carousel.tsx +2 -2
  58. package/dist/content/components/ui/Carousel/index.ts +1 -1
  59. package/dist/content/components/ui/Container/container.tsx +2 -7
  60. package/dist/content/components/ui/Container/index.ts +0 -6
  61. package/dist/content/components/ui/Flex/flex.tsx +19 -27
  62. package/dist/content/components/ui/Flex/index.ts +0 -2
  63. package/dist/content/components/ui/Footer/index.ts +1 -1
  64. package/dist/content/components/ui/Grid/grid.tsx +19 -25
  65. package/dist/content/components/ui/Grid/index.ts +1 -9
  66. package/dist/content/components/ui/Header/index.ts +1 -1
  67. package/dist/content/components/ui/InlineSVG/index.ts +13 -0
  68. package/dist/content/components/ui/InlineSVG/inline-svg.tsx +59 -0
  69. package/dist/content/components/ui/InlineSVG/utils.ts +77 -0
  70. package/dist/content/components/ui/Modal/index.tsx +22 -0
  71. package/dist/content/components/ui/Modal/modal.tsx +89 -0
  72. package/dist/content/components/{canvas → ui}/Modal/style-utils.ts +4 -4
  73. package/dist/image-gallery-AMU6FS7N.mjs +1 -0
  74. package/dist/{index-Bi9hBway.d.mts → index-D5cLtaIv.d.mts} +2 -6
  75. package/dist/index.mjs +1 -1
  76. package/dist/{mobile-GZUA7EI6.mjs → mobile-JGZBHQC2.mjs} +1 -1
  77. package/dist/modal-43IHAVWB.mjs +1 -0
  78. package/dist/modal-5FNTFSTN.mjs +1 -0
  79. package/dist/{navigation-flyout-EIN6DEX4.mjs → navigation-flyout-NAU6O2WG.mjs} +1 -1
  80. package/dist/tabs-J23TEEQ7.mjs +1 -0
  81. package/package.json +2 -2
  82. package/dist/carousel-BBEW5P4Y.mjs +0 -1
  83. package/dist/carousel-ERCHOWUS.mjs +0 -1
  84. package/dist/chunk-2SEOCBRK.mjs +0 -1
  85. package/dist/chunk-5VM2Y55L.mjs +0 -1
  86. package/dist/chunk-7GZZPOY4.mjs +0 -1
  87. package/dist/chunk-BJ3OD5EH.mjs +0 -1
  88. package/dist/chunk-JE7SVZ2M.mjs +0 -1
  89. package/dist/chunk-WNQCSSLG.mjs +0 -1
  90. package/dist/chunk-YUCUJWBO.mjs +0 -1
  91. package/dist/content/components/ui/Container/utils.ts +0 -18
  92. package/dist/image-gallery-F6JLG7XW.mjs +0 -1
  93. package/dist/modal-HKMQGV4B.mjs +0 -1
  94. package/dist/tabs-AQFKYC6M.mjs +0 -1
  95. /package/dist/content/components/{canvas → ui}/Modal/close-icon.tsx +0 -0
@@ -4,7 +4,7 @@ import { TestimonialProps } from '.';
4
4
 
5
5
  type WithLargeAvatarVariantProps = Pick<
6
6
  TestimonialProps,
7
- 'backgroundColor' | 'spacing' | 'border' | 'fluidContent' | 'fullHeight' | 'fitHeight' | 'height'
7
+ 'backgroundColor' | 'spacing' | 'border' | 'fluidContent' | 'height'
8
8
  > & {
9
9
  testimonialPrimaryImage: React.ReactNode;
10
10
  testimonialContent: React.ReactNode;
@@ -21,11 +21,9 @@ export const WithLargeAvatarVariant: FC<WithLargeAvatarVariantProps> = ({
21
21
  spacing,
22
22
  border,
23
23
  fluidContent,
24
- fullHeight,
25
- fitHeight,
26
24
  height,
27
25
  }) => (
28
- <Container {...{ backgroundColor, spacing, border, fluidContent, fullHeight, fitHeight, height }}>
26
+ <Container {...{ backgroundColor, spacing, border, fluidContent, height }}>
29
27
  <div className="mx-auto flex items-center gap-x-10 md:max-w-[80%]">
30
28
  <div className="hidden aspect-square w-full max-w-xs shrink-0 overflow-hidden rounded-xl lg:block">
31
29
  {testimonialPrimaryImage}
@@ -4,7 +4,7 @@ import { TestimonialProps } from '.';
4
4
 
5
5
  type WithLargeAvatarVariantProps = Pick<
6
6
  TestimonialProps,
7
- 'backgroundColor' | 'spacing' | 'border' | 'fluidContent' | 'fullHeight' | 'fitHeight' | 'height'
7
+ 'backgroundColor' | 'spacing' | 'border' | 'fluidContent' | 'height'
8
8
  > & {
9
9
  testimonialPrimaryImage: React.ReactNode;
10
10
  testimonialContent: React.ReactNode;
@@ -21,11 +21,9 @@ export const WithOverlappingImageVariant: FC<WithLargeAvatarVariantProps> = ({
21
21
  spacing,
22
22
  border,
23
23
  fluidContent,
24
- fullHeight,
25
- fitHeight,
26
24
  height,
27
25
  }) => (
28
- <Container {...{ backgroundColor, spacing, border, fluidContent, fullHeight, fitHeight, height }}>
26
+ <Container {...{ backgroundColor, spacing, border, fluidContent, height }}>
29
27
  <Container className="pb-10 lg:pb-0">
30
28
  <div className="mx-auto flex max-w-2xl flex-col items-center gap-10 lg:max-w-none lg:flex-row">
31
29
  <div className="-mt-7 aspect-[2/1] w-full shrink-0 overflow-hidden rounded-xl lg:-my-7 lg:aspect-[1/1.4] lg:max-w-xs">
@@ -1,11 +1,9 @@
1
1
  import { AssetParamValue } from '@uniformdev/assets';
2
- import { LinkParamValue } from '@uniformdev/canvas';
3
2
  import { ComponentProps } from '@uniformdev/canvas-next-rsc/component';
4
3
  import { ViewPort } from '@/types/cskTypes';
5
4
 
6
5
  export type VideoParameters = {
7
6
  video?: AssetParamValue;
8
- url?: LinkParamValue; // Deprecated. Please use video parameter instead of url
9
7
  placeholderImage?: AssetParamValue;
10
8
  autoPlay?: boolean;
11
9
  lazyLoad?: boolean;
@@ -8,7 +8,6 @@ import { VideoPlaceholder } from './placeholder';
8
8
 
9
9
  export const Video: FC<VideoProps> = ({
10
10
  video,
11
- url, // Deprecated. Please use video parameter instead of url
12
11
  placeholderImage,
13
12
  autoPlay,
14
13
  lazyLoad,
@@ -24,7 +23,7 @@ export const Video: FC<VideoProps> = ({
24
23
  const [resolvedVideo] = resolveAsset(video);
25
24
  const [resolvedImage] = resolveAsset(placeholderImage);
26
25
 
27
- const resolvedVideoUrl = resolvedVideo?.url || (url?.type === 'url' ? url.path : undefined);
26
+ const resolvedVideoUrl = resolvedVideo?.url;
28
27
 
29
28
  if (!resolvedVideoUrl) {
30
29
  return <VideoPlaceholder component={component} context={context} />;
@@ -0,0 +1,23 @@
1
+ import { FC } from 'react';
2
+ import Container from '@/components/ui/Container';
3
+ import { cn } from '@/utils/styling';
4
+ import { AccordionProps } from '.';
5
+
6
+ export const Accordion: FC<AccordionProps> = ({
7
+ accordionContent,
8
+ accordionItems,
9
+ backgroundColor,
10
+ spacing,
11
+ border,
12
+ fluidContent,
13
+ height,
14
+ className,
15
+ }) => (
16
+ <Container
17
+ className={cn('flex flex-col gap-8', className)}
18
+ {...{ backgroundColor, spacing, border, fluidContent, height }}
19
+ >
20
+ {accordionContent && <div className="flex flex-col gap-4 text-start">{accordionContent}</div>}
21
+ {accordionItems}
22
+ </Container>
23
+ );
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from 'react';
2
+ import { ContainerProps } from '@/components/ui/Container';
3
+
4
+ export type AccordionProps = ContainerProps & {
5
+ accordionContent?: ReactNode;
6
+ accordionItems: ReactNode;
7
+ };
8
+
9
+ export { Accordion as default } from './accordion';
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+
3
+ import { FC, useCallback, useState } from 'react';
4
+ import Container from '@/components/ui/Container';
5
+ import { cn } from '@/utils/styling';
6
+ import { AccordionItemProps } from '.';
7
+ import { IconArrowDown } from './icon-arrow-down';
8
+ import { IconArrowUp } from './icon-arrow-up';
9
+
10
+ export const AccordionItem: FC<AccordionItemProps> = ({
11
+ text,
12
+ backgroundColor,
13
+ spacing,
14
+ className,
15
+ accordionItemContent,
16
+ }) => {
17
+ const [isOpened, setOpened] = useState(false);
18
+ const toggleOpenAccordion = useCallback(() => setOpened(isOpened => !isOpened), []);
19
+
20
+ return (
21
+ <Container {...{ fluidContent: true }}>
22
+ <Container {...{ backgroundColor, spacing, fluidContent: true, className }}>
23
+ <button
24
+ onClick={toggleOpenAccordion}
25
+ className="flex w-full cursor-pointer flex-row items-center justify-between text-start"
26
+ >
27
+ {text}
28
+ <div
29
+ className={cn({
30
+ [`text-${backgroundColor} invert`]: !!backgroundColor,
31
+ 'text-black dark:text-white': !backgroundColor,
32
+ })}
33
+ >
34
+ {isOpened ? <IconArrowDown /> : <IconArrowUp />}
35
+ </div>
36
+ </button>
37
+ </Container>
38
+ {isOpened && accordionItemContent}
39
+ </Container>
40
+ );
41
+ };
@@ -0,0 +1,20 @@
1
+ import { FC, SVGProps } from 'react';
2
+
3
+ export const IconArrowDown: FC<SVGProps<SVGSVGElement>> = ({ className, ...restProps }) => (
4
+ <svg
5
+ className={className}
6
+ width="15"
7
+ height="9"
8
+ viewBox="0 0 15 9"
9
+ fill="currentColor"
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ {...restProps}
12
+ >
13
+ <path
14
+ fillRule="evenodd"
15
+ clipRule="evenodd"
16
+ d="M7.50013 0L0 7.13651L1.95843 9L7.5 3.7271L13.0416 9L15 7.13651L7.50013 0Z"
17
+ fill="currentColor"
18
+ />
19
+ </svg>
20
+ );
@@ -0,0 +1,20 @@
1
+ import { FC, SVGProps } from 'react';
2
+
3
+ export const IconArrowUp: FC<SVGProps<SVGSVGElement>> = ({ className, ...restProps }) => (
4
+ <svg
5
+ className={className}
6
+ width="15"
7
+ height="9"
8
+ viewBox="0 0 15 9"
9
+ fill="currentColor"
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ {...restProps}
12
+ >
13
+ <path
14
+ fillRule="evenodd"
15
+ clipRule="evenodd"
16
+ d="M7.49987 9L15 1.86349L13.0416 0L7.5 5.2729L1.95843 0L0 1.86349L7.49987 9Z"
17
+ fill="currentColor"
18
+ />
19
+ </svg>
20
+ );
@@ -0,0 +1,16 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import dynamic from 'next/dynamic';
3
+ import { ContainerProps } from '@/components/ui/Container';
4
+
5
+ export type AccordionItemParameters = Pick<ContainerProps, 'backgroundColor' | 'spacing' | 'border'> & {
6
+ text: ReactElement;
7
+ accordionItemContent: ReactNode;
8
+ };
9
+
10
+ export type AccordionItemAdditionalProps = {
11
+ className?: string;
12
+ };
13
+
14
+ export type AccordionItemProps = AccordionItemParameters & AccordionItemAdditionalProps;
15
+
16
+ export default dynamic(() => import('./accordion-item').then(mod => mod.AccordionItem));
@@ -11,7 +11,7 @@ export const Carousel: FC<CarouselProps> = ({
11
11
  spacing,
12
12
  border,
13
13
  fluidContent,
14
- fullHeight,
14
+ height,
15
15
  itemsPerPage = '1',
16
16
  children,
17
17
  gapX,
@@ -116,7 +116,7 @@ export const Carousel: FC<CarouselProps> = ({
116
116
  });
117
117
 
118
118
  return (
119
- <BaseContainer {...{ backgroundColor, spacing, border, fluidContent, fullHeight }}>
119
+ <BaseContainer {...{ backgroundColor, spacing, border, fluidContent, height }}>
120
120
  <div
121
121
  className={cn('relative', {
122
122
  [resolveViewPort(gapX, '-mx-{value}')]: gapX,
@@ -4,7 +4,7 @@ import { ContainerProps as BaseContainerProps } from '@/components/ui/Container'
4
4
 
5
5
  export type CarouselProps = Pick<
6
6
  BaseContainerProps,
7
- 'title' | 'backgroundColor' | 'spacing' | 'border' | 'fluidContent' | 'fullHeight'
7
+ 'title' | 'backgroundColor' | 'spacing' | 'border' | 'fluidContent' | 'height'
8
8
  > & {
9
9
  countOfItems?: number;
10
10
  children: (options: { className?: string; style?: React.CSSProperties }) => ReactElement;
@@ -1,7 +1,6 @@
1
1
  import { FC } from 'react';
2
2
  import { cn, formatSpaceParameterValue, resolveViewPort } from '@/utils/styling';
3
3
  import { ContainerProps } from '.';
4
- import { getHeightValue } from './utils';
5
4
 
6
5
  export const Container: FC<ContainerProps> = ({
7
6
  className,
@@ -12,8 +11,6 @@ export const Container: FC<ContainerProps> = ({
12
11
  spacing,
13
12
  border = '',
14
13
  fluidContent = false,
15
- fullHeight = false,
16
- fitHeight = false,
17
14
  height,
18
15
  maxWidth,
19
16
  ...rest
@@ -23,8 +20,6 @@ export const Container: FC<ContainerProps> = ({
23
20
  { marginTop, marginBottom, marginRight, marginLeft, paddingTop, paddingBottom, paddingRight, paddingLeft },
24
21
  ] = formatSpaceParameterValue(spacing);
25
22
 
26
- const heightValue = getHeightValue({ height, fullHeight, fitHeight });
27
-
28
23
  return (
29
24
  <div
30
25
  className={cn(
@@ -34,7 +29,7 @@ export const Container: FC<ContainerProps> = ({
34
29
  'mx-auto w-full': !fluidContent,
35
30
  'max-w-7xl max-w-container-width': !maxWidth && !fluidContent,
36
31
  [`max-w-${maxWidth}`]: !!maxWidth && !fluidContent,
37
- [resolveViewPort(heightValue, 'h-{value}')]: heightValue,
32
+ [resolveViewPort(height, 'h-{value}')]: height,
38
33
  },
39
34
  wrapperClassName
40
35
  )}
@@ -52,7 +47,7 @@ export const Container: FC<ContainerProps> = ({
52
47
  [resolveViewPort(paddingRight, 'pr-{value}')]: paddingRight,
53
48
  [resolveViewPort(paddingLeft, 'pl-{value}')]: paddingLeft,
54
49
  [resolveViewPort(border, '{value}')]: border,
55
- [resolveViewPort(heightValue, 'h-{value}')]: heightValue,
50
+ [resolveViewPort(height, 'h-{value}')]: height,
56
51
  },
57
52
  className
58
53
  )}
@@ -6,15 +6,9 @@ export type ContainerProps = HTMLAttributes<HTMLDivElement> & {
6
6
  spacing?: SpaceType | ViewPort<SpaceType>;
7
7
  border?: string | ViewPort<string>;
8
8
  fluidContent?: boolean;
9
- /** @deprecated Use height prop instead */
10
- fullHeight?: boolean;
11
- /** @deprecated Use height prop instead */
12
- fitHeight?: boolean;
13
9
  height?: string | ViewPort<string>;
14
10
  wrapperClassName?: string;
15
11
  maxWidth?: string;
16
12
  };
17
13
 
18
- export { getHeightValue } from './utils';
19
-
20
14
  export { Container as default } from './container';
@@ -1,5 +1,5 @@
1
1
  import { FC } from 'react';
2
- import BaseContainer, { getHeightValue } from '@/components/ui/Container';
2
+ import BaseContainer from '@/components/ui/Container';
3
3
  import { cn, resolveViewPort } from '@/utils/styling';
4
4
  import { FlexProps } from '.';
5
5
 
@@ -14,32 +14,24 @@ export const Flex: FC<FlexProps> = ({
14
14
  spacing,
15
15
  border,
16
16
  fluidContent,
17
- fullHeight,
18
- fitHeight,
19
17
  height,
20
18
  children,
21
- }) => {
22
- const heightValue = getHeightValue({ height, fullHeight, fitHeight });
23
-
24
- return (
25
- <BaseContainer
26
- {...{ backgroundColor, spacing, border, fluidContent, fullHeight, fitHeight, height, wrapperClassName }}
19
+ }) => (
20
+ <BaseContainer {...{ backgroundColor, spacing, border, fluidContent, height, wrapperClassName }}>
21
+ <div
22
+ className={cn(
23
+ 'flex',
24
+ {
25
+ [resolveViewPort(direction, 'flex-{value}')]: direction,
26
+ [resolveViewPort(justifyContent, 'justify-{value}')]: justifyContent,
27
+ [resolveViewPort(gap, 'gap-{value}')]: gap,
28
+ [resolveViewPort(alignItems, 'items-{value}')]: alignItems,
29
+ [resolveViewPort(height, 'h-{value}')]: height,
30
+ },
31
+ className
32
+ )}
27
33
  >
28
- <div
29
- className={cn(
30
- 'flex',
31
- {
32
- [resolveViewPort(direction, 'flex-{value}')]: direction,
33
- [resolveViewPort(justifyContent, 'justify-{value}')]: justifyContent,
34
- [resolveViewPort(gap, 'gap-{value}')]: gap,
35
- [resolveViewPort(alignItems, 'items-{value}')]: alignItems,
36
- [resolveViewPort(heightValue, 'h-{value}')]: heightValue,
37
- },
38
- className
39
- )}
40
- >
41
- {children}
42
- </div>
43
- </BaseContainer>
44
- );
45
- };
34
+ {children}
35
+ </div>
36
+ </BaseContainer>
37
+ );
@@ -14,8 +14,6 @@ export type FlexProps = Pick<
14
14
  | 'spacing'
15
15
  | 'border'
16
16
  | 'fluidContent'
17
- | 'fullHeight'
18
- | 'fitHeight'
19
17
  | 'height'
20
18
  | 'children'
21
19
  > & {
@@ -1,6 +1,6 @@
1
1
  import { ContainerProps as BaseContainerProps } from '@/components/ui/Container';
2
2
 
3
- export type FooterProps = Omit<BaseContainerProps, 'fullHeight' | 'content'> & {
3
+ export type FooterProps = Omit<BaseContainerProps, 'height' | 'content'> & {
4
4
  logo?: React.ReactNode;
5
5
  copyright?: React.ReactNode;
6
6
  content?: React.ReactNode;
@@ -1,5 +1,5 @@
1
1
  import { FC } from 'react';
2
- import BaseContainer, { getHeightValue } from '@/components/ui/Container';
2
+ import BaseContainer from '@/components/ui/Container';
3
3
  import { cn, resolveViewPort } from '@/utils/styling';
4
4
  import { GridProps } from '.';
5
5
 
@@ -12,29 +12,23 @@ export const Grid: FC<GridProps> = ({
12
12
  spacing,
13
13
  border,
14
14
  fluidContent,
15
- fullHeight,
16
- fitHeight,
17
15
  height,
18
16
  children,
19
- }) => {
20
- const heightValue = getHeightValue({ height, fullHeight, fitHeight });
21
-
22
- return (
23
- <BaseContainer {...{ backgroundColor, spacing, border, fluidContent, fullHeight, fitHeight, height }}>
24
- <div
25
- className={cn(
26
- 'grid',
27
- {
28
- [resolveViewPort(columnsCount, 'grid-cols-{value}')]: columnsCount,
29
- [resolveViewPort(gapX, 'gap-x-{value}')]: gapX,
30
- [resolveViewPort(gapY, 'gap-y-{value}')]: gapY,
31
- [resolveViewPort(heightValue, 'h-{value}')]: heightValue,
32
- },
33
- className
34
- )}
35
- >
36
- {children}
37
- </div>
38
- </BaseContainer>
39
- );
40
- };
17
+ }) => (
18
+ <BaseContainer {...{ backgroundColor, spacing, border, fluidContent, height }}>
19
+ <div
20
+ className={cn(
21
+ 'grid',
22
+ {
23
+ [resolveViewPort(columnsCount, 'grid-cols-{value}')]: columnsCount,
24
+ [resolveViewPort(gapX, 'gap-x-{value}')]: gapX,
25
+ [resolveViewPort(gapY, 'gap-y-{value}')]: gapY,
26
+ [resolveViewPort(height, 'h-{value}')]: height,
27
+ },
28
+ className
29
+ )}
30
+ >
31
+ {children}
32
+ </div>
33
+ </BaseContainer>
34
+ );
@@ -3,15 +3,7 @@ import { ViewPort } from '@/types/cskTypes';
3
3
 
4
4
  export type GridProps = Pick<
5
5
  BaseContainerProps,
6
- | 'title'
7
- | 'backgroundColor'
8
- | 'spacing'
9
- | 'border'
10
- | 'fluidContent'
11
- | 'fullHeight'
12
- | 'fitHeight'
13
- | 'children'
14
- | 'height'
6
+ 'title' | 'backgroundColor' | 'spacing' | 'border' | 'fluidContent' | 'children' | 'height'
15
7
  > & {
16
8
  columnsCount?: string | ViewPort<string>;
17
9
  gapY?: string | ViewPort<string>;
@@ -2,7 +2,7 @@ import { PropsWithChildren, ReactNode } from 'react';
2
2
  import { ContainerProps as BaseContainerProps } from '@/components/ui/Container';
3
3
 
4
4
  export type HeaderProps = PropsWithChildren &
5
- Omit<BaseContainerProps, 'fluidContent' | 'fullHeight'> & {
5
+ Omit<BaseContainerProps, 'fluidContent' | 'height'> & {
6
6
  leftSection?: ReactNode;
7
7
  rightSection?: ReactNode;
8
8
  color?: string;
@@ -0,0 +1,13 @@
1
+ export type InlineSVGProps = {
2
+ src: string;
3
+ className?: string;
4
+ fill?: boolean;
5
+ width?: number;
6
+ height?: number;
7
+ sanitize?: boolean;
8
+ fallback?: React.ReactNode;
9
+ useCurrentColor?: boolean;
10
+ alt?: string;
11
+ };
12
+
13
+ export { InlineSVG as default } from './inline-svg';
@@ -0,0 +1,59 @@
1
+ import { FC, SVGProps } from 'react';
2
+ import { cn } from '@/utils/styling';
3
+ import { InlineSVGProps } from '.';
4
+ import { fetchSvg, sanitizeSvg, applyCurrentColor, getSvgAttributes, getSvgInnerContent } from './utils';
5
+
6
+ export const InlineSVG: FC<InlineSVGProps> = async ({
7
+ src,
8
+ className = '',
9
+ width,
10
+ height,
11
+ fill,
12
+ sanitize = true,
13
+ useCurrentColor = true,
14
+ fallback,
15
+ alt,
16
+ }) => {
17
+ if (!src) return fallback ?? null;
18
+
19
+ const transformSvg = (svg: string): string => {
20
+ const transformers: Array<(input: string) => string> = [];
21
+
22
+ if (sanitize) transformers.push(sanitizeSvg);
23
+ if (useCurrentColor) transformers.push(applyCurrentColor);
24
+
25
+ return transformers.reduce((result, fn) => fn(result), svg);
26
+ };
27
+
28
+ try {
29
+ const raw = await fetchSvg(src);
30
+ const cleaned = transformSvg(raw);
31
+ const attrs = getSvgAttributes(cleaned);
32
+ const content = getSvgInnerContent(cleaned);
33
+
34
+ const svgProps: SVGProps<SVGSVGElement> = {
35
+ ...attrs,
36
+ role: 'img',
37
+ 'aria-label': alt,
38
+ width: fill ? '100%' : width,
39
+ height: fill ? '100%' : height,
40
+ className: cn(attrs.className, className, {
41
+ 'absolute inset-0': fill,
42
+ }),
43
+ };
44
+
45
+ return (
46
+ <div className="relative size-full">
47
+ <svg {...svgProps} dangerouslySetInnerHTML={{ __html: content }} />
48
+ </div>
49
+ );
50
+ } catch {
51
+ return (
52
+ fallback ?? (
53
+ <div className={cn(className)} style={{ width, height }}>
54
+ <div className="rounded border border-red-200 bg-red-50 p-2 text-sm text-red-500">Failed to load SVG</div>
55
+ </div>
56
+ )
57
+ );
58
+ }
59
+ };
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Sanitizes SVG by removing potentially dangerous or unwanted content.
3
+ */
4
+ export const sanitizeSvg = (svg: string): string =>
5
+ svg
6
+ .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
7
+ .replace(/\son\w+="[^"]*"/gi, '')
8
+ .replace(/\son\w+='[^']*'/gi, '')
9
+ .replace(/javascript:/gi, '');
10
+
11
+ /**
12
+ * Replaces color attributes (fill, stroke, color) with `currentColor`
13
+ * except for 'none' and 'transparent'.
14
+ */
15
+ export const applyCurrentColor = (svg: string): string =>
16
+ svg
17
+ .replace(/fill=(['"])(?!none|transparent)[^'"]*\1/gi, 'fill="currentColor"')
18
+ .replace(/stroke=(['"])(?!none|transparent)[^'"]*\1/gi, 'stroke="currentColor"')
19
+ .replace(/color=(['"])[^'"]*\1/gi, 'color="currentColor"');
20
+
21
+ /**
22
+ * Extracts attributes from the <svg> tag as key-value pairs.
23
+ */
24
+ export const getSvgAttributes = (svg: string): Record<string, string> => {
25
+ const match = svg.match(/<svg\s+([^>]*)>/i);
26
+ if (!match || !match[1]) return {};
27
+
28
+ const attrString = match[1];
29
+ const attributes: Record<string, string> = {};
30
+
31
+ const attrRegex = /(\w[\w-]*)=["']([^"']*)["']/g;
32
+ let result: RegExpExecArray | null;
33
+
34
+ while ((result = attrRegex.exec(attrString))) {
35
+ const [, key, value] = result;
36
+ if (key && value) {
37
+ attributes[key] = value;
38
+ }
39
+ }
40
+
41
+ return attributes;
42
+ };
43
+
44
+ /**
45
+ * Extracts inner content from an SVG string (everything inside <svg>...</svg>).
46
+ */
47
+ export const getSvgInnerContent = (svg: string): string => {
48
+ const match = svg.match(/<svg[^>]*>([\s\S]*?)<\/svg>/i);
49
+ return match?.[1] ?? '';
50
+ };
51
+
52
+ /**
53
+ * Fetches raw SVG content from a remote URL.
54
+ */
55
+ export const fetchSvg = async (url: string): Promise<string> => {
56
+ try {
57
+ const response = await fetch(url, {
58
+ headers: {
59
+ Accept: 'image/svg+xml, text/plain, */*',
60
+ },
61
+ });
62
+
63
+ if (!response.ok) {
64
+ throw new Error(`Failed to fetch SVG: ${response.status} ${response.statusText}`);
65
+ }
66
+
67
+ const content = await response.text();
68
+ if (!content.trim().includes('<svg')) {
69
+ throw new Error('Response is not valid SVG');
70
+ }
71
+
72
+ return content;
73
+ } catch (err) {
74
+ console.error('Error fetching SVG:', err);
75
+ throw err;
76
+ }
77
+ };
@@ -0,0 +1,22 @@
1
+ import { ReactNode } from 'react';
2
+ import dynamic from 'next/dynamic';
3
+
4
+ export const MaxWidthMap = {
5
+ small: 'max-w-xl',
6
+ medium: 'max-w-2xl',
7
+ large: 'max-w-4xl',
8
+ };
9
+
10
+ export type ModalProps = {
11
+ maxWidth?: 'small' | 'medium' | 'large';
12
+ className?: string;
13
+ backgroundColor?: string;
14
+ closeIconColor?: string;
15
+ disableCloseModalOnClickOutside?: boolean;
16
+ trigger: ReactNode;
17
+ content: ReactNode;
18
+ actions?: ReactNode;
19
+ onChangeModalState?: (state: boolean) => void;
20
+ };
21
+
22
+ export default dynamic(() => import('./modal').then(mod => mod.Modal));