@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.
- package/dist/{accordion-item-VWHOTJAC.mjs → accordion-item-QAVKQEB2.mjs} +1 -1
- package/dist/{accordion-item-NUEMADB2.mjs → accordion-item-Y4PSNOH4.mjs} +1 -1
- package/dist/{banner-2B4K5R4N.mjs → banner-EYII7V7X.mjs} +1 -1
- package/dist/carousel-RZ2DV6QX.mjs +1 -0
- package/dist/carousel-YELQRJVB.mjs +1 -0
- package/dist/chunk-2BMAPB63.mjs +1 -0
- package/dist/chunk-7GVG4HLE.mjs +1 -0
- package/dist/{chunk-LA36HQWS.mjs → chunk-B2O55EVA.mjs} +1 -1
- package/dist/chunk-EOV2LPGC.mjs +1 -0
- package/dist/chunk-EUVKAE6M.mjs +1 -0
- package/dist/chunk-FIN5US3Q.mjs +1 -0
- package/dist/chunk-M6FDQCD7.mjs +1 -0
- package/dist/{chunk-TDAANMNJ.mjs → chunk-PMMAALCQ.mjs} +1 -1
- package/dist/chunk-TCQTXNKT.mjs +1 -0
- package/dist/{chunk-3PDY7RJC.mjs → chunk-TFA6HYP4.mjs} +2 -2
- package/dist/{chunk-FPOIJMYT.mjs → chunk-VW2XC3SE.mjs} +1 -1
- package/dist/components/canvas/emptyPlaceholders.mjs +1 -1
- package/dist/components/canvas/index.d.mts +2 -18
- package/dist/components/canvas/index.mjs +2 -2
- package/dist/components/ui/index.d.mts +23 -10
- package/dist/components/ui/index.mjs +1 -1
- package/dist/content/components/canvas/Accordion/accordion.tsx +1 -3
- package/dist/content/components/canvas/Card/card.tsx +1 -3
- package/dist/content/components/canvas/Carousel/carousel.tsx +1 -3
- package/dist/content/components/canvas/Container/container.tsx +0 -4
- package/dist/content/components/canvas/Container/parameters.ts +0 -4
- package/dist/content/components/canvas/DemoHero/atoms.tsx +1 -1
- package/dist/content/components/canvas/DemoHero/columns-variant.tsx +1 -7
- package/dist/content/components/canvas/DemoHero/default-variant.tsx +1 -8
- package/dist/content/components/canvas/DemoHero/demo-hero.tsx +0 -4
- package/dist/content/components/canvas/DemoHero/fixed-hero.tsx +56 -66
- package/dist/content/components/canvas/DemoHero/index.tsx +1 -12
- package/dist/content/components/canvas/Flex/flex.tsx +0 -4
- package/dist/content/components/canvas/Grid/grid.tsx +1 -3
- package/dist/content/components/canvas/Image/image.tsx +2 -2
- package/dist/content/components/canvas/ImageGallery/image-gallery.tsx +1 -3
- package/dist/content/components/canvas/Modal/modal.tsx +12 -69
- package/dist/content/components/canvas/Review/default-variant.tsx +1 -3
- package/dist/content/components/canvas/Review/multi-column-variant.tsx +1 -3
- package/dist/content/components/canvas/Section/columns-variant.tsx +1 -7
- package/dist/content/components/canvas/Section/default-variant.tsx +1 -10
- package/dist/content/components/canvas/Section/section.tsx +0 -4
- package/dist/content/components/canvas/Table/table.tsx +1 -6
- package/dist/content/components/canvas/Tabs/tabs.tsx +1 -6
- package/dist/content/components/canvas/Testimonial/default-variant.tsx +2 -4
- package/dist/content/components/canvas/Testimonial/testimonial.tsx +0 -4
- package/dist/content/components/canvas/Testimonial/with-large-avatar-variant.tsx +2 -4
- package/dist/content/components/canvas/Testimonial/with-overlapping-image-variant.tsx +2 -4
- package/dist/content/components/canvas/Video/index.tsx +0 -2
- package/dist/content/components/canvas/Video/video.tsx +1 -2
- package/dist/content/components/ui/Accordion/accordion.tsx +23 -0
- package/dist/content/components/ui/Accordion/index.tsx +9 -0
- package/dist/content/components/ui/AccordionItem/accordion-item.tsx +41 -0
- package/dist/content/components/ui/AccordionItem/icon-arrow-down.tsx +20 -0
- package/dist/content/components/ui/AccordionItem/icon-arrow-up.tsx +20 -0
- package/dist/content/components/ui/AccordionItem/index.tsx +16 -0
- package/dist/content/components/ui/Carousel/carousel.tsx +2 -2
- package/dist/content/components/ui/Carousel/index.ts +1 -1
- package/dist/content/components/ui/Container/container.tsx +2 -7
- package/dist/content/components/ui/Container/index.ts +0 -6
- package/dist/content/components/ui/Flex/flex.tsx +19 -27
- package/dist/content/components/ui/Flex/index.ts +0 -2
- package/dist/content/components/ui/Footer/index.ts +1 -1
- package/dist/content/components/ui/Grid/grid.tsx +19 -25
- package/dist/content/components/ui/Grid/index.ts +1 -9
- package/dist/content/components/ui/Header/index.ts +1 -1
- package/dist/content/components/ui/InlineSVG/index.ts +13 -0
- package/dist/content/components/ui/InlineSVG/inline-svg.tsx +59 -0
- package/dist/content/components/ui/InlineSVG/utils.ts +77 -0
- package/dist/content/components/ui/Modal/index.tsx +22 -0
- package/dist/content/components/ui/Modal/modal.tsx +89 -0
- package/dist/content/components/{canvas → ui}/Modal/style-utils.ts +4 -4
- package/dist/image-gallery-AMU6FS7N.mjs +1 -0
- package/dist/{index-Bi9hBway.d.mts → index-D5cLtaIv.d.mts} +2 -6
- package/dist/index.mjs +1 -1
- package/dist/{mobile-GZUA7EI6.mjs → mobile-JGZBHQC2.mjs} +1 -1
- package/dist/modal-43IHAVWB.mjs +1 -0
- package/dist/modal-5FNTFSTN.mjs +1 -0
- package/dist/{navigation-flyout-EIN6DEX4.mjs → navigation-flyout-NAU6O2WG.mjs} +1 -1
- package/dist/tabs-J23TEEQ7.mjs +1 -0
- package/package.json +2 -2
- package/dist/carousel-BBEW5P4Y.mjs +0 -1
- package/dist/carousel-ERCHOWUS.mjs +0 -1
- package/dist/chunk-2SEOCBRK.mjs +0 -1
- package/dist/chunk-5VM2Y55L.mjs +0 -1
- package/dist/chunk-7GZZPOY4.mjs +0 -1
- package/dist/chunk-BJ3OD5EH.mjs +0 -1
- package/dist/chunk-JE7SVZ2M.mjs +0 -1
- package/dist/chunk-WNQCSSLG.mjs +0 -1
- package/dist/chunk-YUCUJWBO.mjs +0 -1
- package/dist/content/components/ui/Container/utils.ts +0 -18
- package/dist/image-gallery-F6JLG7XW.mjs +0 -1
- package/dist/modal-HKMQGV4B.mjs +0 -1
- package/dist/tabs-AQFKYC6M.mjs +0 -1
- /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' | '
|
|
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,
|
|
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' | '
|
|
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,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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' | '
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
+
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ContainerProps as BaseContainerProps } from '@/components/ui/Container';
|
|
2
2
|
|
|
3
|
-
export type FooterProps = Omit<BaseContainerProps, '
|
|
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
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
'
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
| '
|
|
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' | '
|
|
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));
|