likvid-ui 0.1.0 → 2.0.0
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/components/LiquidButton/ButtonLoader.d.ts +1 -0
- package/dist/components/LiquidButton/ButtonLoader.js +5 -0
- package/dist/components/LiquidButton/LiquidButton.d.ts +37 -0
- package/dist/components/LiquidButton/LiquidButton.js +45 -0
- package/dist/components/LiquidButton/index.d.ts +2 -0
- package/dist/components/LiquidButton/index.js +2 -0
- package/dist/components/LiquidButton/liquidButton.module.css +128 -0
- package/dist/components/LiquidContainer/LiquidContainer.d.ts +45 -0
- package/dist/components/LiquidContainer/LiquidContainer.js +46 -0
- package/dist/components/LiquidContainer/index.d.ts +1 -0
- package/dist/components/LiquidContainer/index.js +1 -0
- package/dist/components/LiquidContainer/liquidContainer.module.css +44 -0
- package/dist/components/LiquidRadio/LiquidRadio.d.ts +16 -0
- package/dist/components/LiquidRadio/LiquidRadio.js +65 -0
- package/dist/components/LiquidRadio/index.d.ts +2 -0
- package/dist/components/LiquidRadio/index.js +1 -0
- package/dist/components/LiquidRadio/liquidRadio.module.css +155 -0
- package/dist/components/NavBarBase/NavBarBase.d.ts +14 -0
- package/dist/components/NavBarBase/NavBarBase.js +74 -0
- package/dist/components/NavBarBase/index.d.ts +2 -0
- package/dist/components/NavBarBase/index.js +1 -0
- package/dist/components/NavBarBase/navBarBase.helpers.d.ts +1 -0
- package/dist/components/NavBarBase/navBarBase.helpers.js +1 -0
- package/dist/components/NavBarBase/navBarBase.module.css +167 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +4 -1
- package/dist/utils/cx.d.ts +3 -0
- package/dist/utils/cx.js +1 -0
- package/package.json +24 -10
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ButtonLoader: import("react").MemoExoticComponent<() => import("react").JSX.Element>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import s from './liquidButton.module.css';
|
|
4
|
+
export const ButtonLoader = memo(() => (_jsx("span", { role: 'status', "aria-label": '\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430', className: s.loader })));
|
|
5
|
+
ButtonLoader.displayName = 'ButtonLoader';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type CSSProperties, type MouseEventHandler, type ReactNode, type Ref } from 'react';
|
|
2
|
+
type T_shape = 'pill' | 'widget';
|
|
3
|
+
type T_variant = 'glass' | 'accent' | 'accent-dark';
|
|
4
|
+
type T_tag = keyof JSX.IntrinsicElements;
|
|
5
|
+
interface I_commonProps {
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
title?: string | null;
|
|
8
|
+
callback?: () => void;
|
|
9
|
+
onClick?: MouseEventHandler<Element>;
|
|
10
|
+
isActive?: boolean;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
isLoading?: boolean;
|
|
13
|
+
className?: string;
|
|
14
|
+
width?: '100%' | 'max-content';
|
|
15
|
+
shape?: T_shape;
|
|
16
|
+
variant?: T_variant;
|
|
17
|
+
style?: CSSProperties;
|
|
18
|
+
}
|
|
19
|
+
type T_hrefProps<T_as extends T_tag> = T_as extends 'a' ? {
|
|
20
|
+
href: string;
|
|
21
|
+
} : {
|
|
22
|
+
href?: never;
|
|
23
|
+
};
|
|
24
|
+
type T_props<T_as extends T_tag = 'button'> = I_commonProps & T_hrefProps<T_as> & Omit<ComponentPropsWithoutRef<T_as>, keyof I_commonProps | 'as' | 'href' | 'ref'> & {
|
|
25
|
+
as?: T_as;
|
|
26
|
+
};
|
|
27
|
+
type T_polymorphic = <T_as extends T_tag = 'button'>(props: T_props<T_as> & {
|
|
28
|
+
ref?: Ref<HTMLElement>;
|
|
29
|
+
}) => ReactNode;
|
|
30
|
+
export declare const LiquidButton: T_polymorphic & {
|
|
31
|
+
a: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<I_commonProps & {
|
|
32
|
+
href: string;
|
|
33
|
+
} & Omit<Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref">, "ref" | "href" | "as" | keyof I_commonProps> & {
|
|
34
|
+
as?: "a" | undefined;
|
|
35
|
+
} & import("react").RefAttributes<HTMLElement>>>;
|
|
36
|
+
};
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createElement, forwardRef, memo } from 'react';
|
|
3
|
+
import { cx } from '../../utils/cx';
|
|
4
|
+
import { ButtonLoader } from './ButtonLoader';
|
|
5
|
+
import s from './liquidButton.module.css';
|
|
6
|
+
const SHAPE_CLASS = {
|
|
7
|
+
pill: s.shapePill,
|
|
8
|
+
widget: s.shapeWidget
|
|
9
|
+
};
|
|
10
|
+
const VARIANT_CLASS = {
|
|
11
|
+
glass: undefined,
|
|
12
|
+
accent: s.variantAccent,
|
|
13
|
+
'accent-dark': s.variantAccentDark
|
|
14
|
+
};
|
|
15
|
+
const BaseButton = memo(forwardRef(function LiquidButton(props, ref) {
|
|
16
|
+
const { as = 'button', children, className, callback, disabled = false, isActive = false, isLoading = false, shape = 'pill', style, title, variant = 'glass', width, onClick, ...rest } = props;
|
|
17
|
+
const isDisabled = disabled || isLoading;
|
|
18
|
+
const isLink = as === 'a';
|
|
19
|
+
const handlePress = (event) => {
|
|
20
|
+
if (isDisabled) {
|
|
21
|
+
if (isLink)
|
|
22
|
+
event.preventDefault();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
callback?.();
|
|
26
|
+
onClick?.(event);
|
|
27
|
+
};
|
|
28
|
+
return createElement(as, {
|
|
29
|
+
...rest,
|
|
30
|
+
ref,
|
|
31
|
+
disabled: as === 'button' ? isDisabled : undefined,
|
|
32
|
+
'aria-disabled': isDisabled && !isLink ? true : undefined,
|
|
33
|
+
onClick: handlePress,
|
|
34
|
+
style: width ? { ...style, width } : style,
|
|
35
|
+
className: cx(s.wrapper, SHAPE_CLASS[shape], VARIANT_CLASS[variant], isActive && s.wrapperActive, isDisabled && s.disabled, className)
|
|
36
|
+
}, isLoading ? (_jsx("span", { className: s.loading, children: _jsx(ButtonLoader, {}) })) : (title ? _jsx("p", { children: title }) : children));
|
|
37
|
+
}));
|
|
38
|
+
BaseButton.displayName = 'LiquidButton';
|
|
39
|
+
const LinkButton = memo(forwardRef(function LiquidButtonLink(props, ref) {
|
|
40
|
+
return _jsx(BaseButton, { ...props, as: 'a', ref: ref });
|
|
41
|
+
}));
|
|
42
|
+
LinkButton.displayName = 'LiquidButton.a';
|
|
43
|
+
export const LiquidButton = Object.assign(BaseButton, {
|
|
44
|
+
a: LinkButton
|
|
45
|
+
});
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
:where(.wrapper) {
|
|
2
|
+
--button-radius: var(--radius-pull);
|
|
3
|
+
|
|
4
|
+
position: relative;
|
|
5
|
+
width: max-content;
|
|
6
|
+
height: max-content;
|
|
7
|
+
border: none;
|
|
8
|
+
appearance: none;
|
|
9
|
+
font: inherit;
|
|
10
|
+
color: inherit;
|
|
11
|
+
text-decoration: none;
|
|
12
|
+
cursor: pointer;
|
|
13
|
+
background: linear-gradient(
|
|
14
|
+
to bottom right,
|
|
15
|
+
transparent 30%,
|
|
16
|
+
white
|
|
17
|
+
);
|
|
18
|
+
backdrop-filter: blur(2px);
|
|
19
|
+
box-shadow: 0 0 20px -2px #5d5c5c40;
|
|
20
|
+
padding: 0.875rem 1rem;
|
|
21
|
+
border-radius: var(--button-radius);
|
|
22
|
+
transition: 0.1s ease-in-out;
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
:where(.shapePill) {
|
|
29
|
+
--button-radius: var(--radius-pull);
|
|
30
|
+
corner-shape: initial !important;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:where(.shapeWidget) {
|
|
34
|
+
--button-radius: var(--radius-widget);
|
|
35
|
+
corner-shape: squircle !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:where(.shapeWidget)::before {
|
|
39
|
+
corner-shape: squircle;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:where(.wrapper):not(:disabled):not(.disabled):active {
|
|
43
|
+
transform: scale(1.1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:where(.wrapper):disabled,
|
|
47
|
+
:where(.wrapper).disabled {
|
|
48
|
+
opacity: 0.7;
|
|
49
|
+
cursor: not-allowed;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:where(.wrapper):disabled:active,
|
|
53
|
+
:where(.wrapper).disabled:active {
|
|
54
|
+
transform: none;
|
|
55
|
+
animation: liquidButtonShake 0.1s ease-in-out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@keyframes liquidButtonShake {
|
|
59
|
+
0%, 100% {
|
|
60
|
+
transform: translateX(0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
25% {
|
|
64
|
+
transform: translateX(-3px);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
50% {
|
|
68
|
+
transform: translateX(3px);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
75% {
|
|
72
|
+
transform: translateX(-2px);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
:where(.wrapper)::before {
|
|
77
|
+
content: '';
|
|
78
|
+
position: absolute;
|
|
79
|
+
inset: 0;
|
|
80
|
+
border-radius: var(--button-radius) !important;
|
|
81
|
+
box-shadow: inset 1px 1px 1px 0 white, inset -1px -1px 1px 0 white;
|
|
82
|
+
z-index: 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
:where(.variantAccent) {
|
|
86
|
+
background: var(--color-main);
|
|
87
|
+
color: white;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
:where(.variantAccentDark) {
|
|
91
|
+
background: var(--color-main-dark, var(--color-main));
|
|
92
|
+
color: white;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
:where(.wrapperActive) {
|
|
96
|
+
background: #000000a3;
|
|
97
|
+
color: white;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
:where(.wrapper) p {
|
|
101
|
+
margin: 0;
|
|
102
|
+
font-size: 0.875rem;
|
|
103
|
+
font-weight: 500;
|
|
104
|
+
transition: 0.1s ease-in-out;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
:where(.loading) {
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
justify-content: center;
|
|
111
|
+
height: 1.19em;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
:where(.loader) {
|
|
115
|
+
display: inline-block;
|
|
116
|
+
width: 1em;
|
|
117
|
+
height: 1em;
|
|
118
|
+
border: 2px solid rgba(128, 128, 128, 0.3);
|
|
119
|
+
border-top-color: currentColor;
|
|
120
|
+
border-radius: 50%;
|
|
121
|
+
animation: loaderSpin 0.8s linear infinite;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@keyframes loaderSpin {
|
|
125
|
+
to {
|
|
126
|
+
transform: rotate(360deg);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
type T_shape = 'widget' | 'pill';
|
|
3
|
+
interface I_shapeProps {
|
|
4
|
+
shape?: T_shape;
|
|
5
|
+
classNameShadow?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const LiquidContainer: {
|
|
8
|
+
div: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & I_shapeProps & {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
} & import("react").RefAttributes<HTMLDivElement>>>;
|
|
11
|
+
section: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & I_shapeProps & {
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
} & import("react").RefAttributes<HTMLElement>>>;
|
|
14
|
+
li: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & I_shapeProps & {
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
} & import("react").RefAttributes<HTMLLIElement>>>;
|
|
17
|
+
ul: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLUListElement>, HTMLUListElement>, "ref"> & I_shapeProps & {
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
} & import("react").RefAttributes<HTMLUListElement>>>;
|
|
20
|
+
ol: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").OlHTMLAttributes<HTMLOListElement>, HTMLOListElement>, "ref"> & I_shapeProps & {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
} & import("react").RefAttributes<HTMLOListElement>>>;
|
|
23
|
+
figure: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, "ref"> & I_shapeProps & {
|
|
24
|
+
children: ReactNode;
|
|
25
|
+
} & import("react").RefAttributes<HTMLElement>>>;
|
|
26
|
+
form: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>, "ref"> & I_shapeProps & {
|
|
27
|
+
children: ReactNode;
|
|
28
|
+
} & import("react").RefAttributes<HTMLFormElement>>>;
|
|
29
|
+
fieldset: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").FieldsetHTMLAttributes<HTMLFieldSetElement>, HTMLFieldSetElement>, "ref"> & I_shapeProps & {
|
|
30
|
+
children: ReactNode;
|
|
31
|
+
} & import("react").RefAttributes<HTMLFieldSetElement>>>;
|
|
32
|
+
label: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "ref"> & I_shapeProps & {
|
|
33
|
+
children: ReactNode;
|
|
34
|
+
} & import("react").RefAttributes<HTMLLabelElement>>>;
|
|
35
|
+
button: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & I_shapeProps & {
|
|
36
|
+
children: ReactNode;
|
|
37
|
+
} & import("react").RefAttributes<HTMLButtonElement>>>;
|
|
38
|
+
a: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref"> & I_shapeProps & {
|
|
39
|
+
children: ReactNode;
|
|
40
|
+
} & import("react").RefAttributes<HTMLAnchorElement>>>;
|
|
41
|
+
span: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & I_shapeProps & {
|
|
42
|
+
children: ReactNode;
|
|
43
|
+
} & import("react").RefAttributes<HTMLSpanElement>>>;
|
|
44
|
+
};
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createElement, forwardRef, memo } from 'react';
|
|
2
|
+
import { cx } from '../../utils/cx';
|
|
3
|
+
import s from './liquidContainer.module.css';
|
|
4
|
+
const VARIANTS = {
|
|
5
|
+
div: { defaultShape: 'widget' },
|
|
6
|
+
section: { defaultShape: 'widget' },
|
|
7
|
+
li: { defaultShape: 'widget' },
|
|
8
|
+
ul: { defaultShape: 'widget' },
|
|
9
|
+
ol: { defaultShape: 'widget' },
|
|
10
|
+
figure: { defaultShape: 'widget' },
|
|
11
|
+
form: { defaultShape: 'widget' },
|
|
12
|
+
fieldset: { defaultShape: 'widget' },
|
|
13
|
+
label: { defaultShape: 'pill' },
|
|
14
|
+
button: { defaultShape: 'pill', extraClass: s.wrapperButton, defaultProps: { type: 'button' } },
|
|
15
|
+
a: { defaultShape: 'pill' },
|
|
16
|
+
span: { defaultShape: 'pill' }
|
|
17
|
+
};
|
|
18
|
+
const SHAPE_CLASS = {
|
|
19
|
+
widget: undefined,
|
|
20
|
+
pill: s.wrapperPill
|
|
21
|
+
};
|
|
22
|
+
function createVariant(variant) {
|
|
23
|
+
const { defaultShape, extraClass, defaultProps } = VARIANTS[variant];
|
|
24
|
+
const Component = forwardRef(({ children, className, classNameShadow, shape = defaultShape, ...rest }, ref) => (createElement(variant, {
|
|
25
|
+
...defaultProps,
|
|
26
|
+
...rest,
|
|
27
|
+
ref,
|
|
28
|
+
className: cx(s.wrapper, SHAPE_CLASS[shape], extraClass, className)
|
|
29
|
+
}, createElement('div', { className: cx(s.shadow, classNameShadow), 'aria-hidden': true }), children)));
|
|
30
|
+
Component.displayName = `LiquidContainer.${variant}`;
|
|
31
|
+
return memo(Component);
|
|
32
|
+
}
|
|
33
|
+
export const LiquidContainer = {
|
|
34
|
+
div: createVariant('div'),
|
|
35
|
+
section: createVariant('section'),
|
|
36
|
+
li: createVariant('li'),
|
|
37
|
+
ul: createVariant('ul'),
|
|
38
|
+
ol: createVariant('ol'),
|
|
39
|
+
figure: createVariant('figure'),
|
|
40
|
+
form: createVariant('form'),
|
|
41
|
+
fieldset: createVariant('fieldset'),
|
|
42
|
+
label: createVariant('label'),
|
|
43
|
+
button: createVariant('button'),
|
|
44
|
+
a: createVariant('a'),
|
|
45
|
+
span: createVariant('span')
|
|
46
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LiquidContainer } from './LiquidContainer';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LiquidContainer } from './LiquidContainer';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
:where(.wrapper) {
|
|
2
|
+
position: relative;
|
|
3
|
+
backdrop-filter: blur(2px);
|
|
4
|
+
box-shadow: 0 0 40px -5px #5353531f;
|
|
5
|
+
border-radius: var(--radius-widget);
|
|
6
|
+
corner-shape: squircle !important;
|
|
7
|
+
transition: background 0.1s;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
:where(.wrapper) .shadow {
|
|
11
|
+
position: absolute;
|
|
12
|
+
inset: 0;
|
|
13
|
+
box-shadow: inset 1px 1px 1px 0 white, inset -1px -1px 1px 0 white;
|
|
14
|
+
z-index: -1;
|
|
15
|
+
border-radius: var(--radius-widget);
|
|
16
|
+
corner-shape: squircle !important;
|
|
17
|
+
background: linear-gradient(
|
|
18
|
+
to bottom right,
|
|
19
|
+
transparent 30%,
|
|
20
|
+
white
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:where(.wrapperPill) {
|
|
25
|
+
border-radius: var(--radius-pull);
|
|
26
|
+
corner-shape: initial !important;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:where(.wrapperPill) .shadow {
|
|
30
|
+
border-radius: var(--radius-pull);
|
|
31
|
+
corner-shape: initial !important;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
:where(.wrapperButton) {
|
|
35
|
+
border: none;
|
|
36
|
+
padding: 0;
|
|
37
|
+
margin: 0;
|
|
38
|
+
background: transparent;
|
|
39
|
+
font: inherit;
|
|
40
|
+
color: inherit;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
text-align: inherit;
|
|
43
|
+
appearance: none;
|
|
44
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import 'swiper/css';
|
|
3
|
+
export interface I_liquidRadioItem<T extends string = string> {
|
|
4
|
+
value: T;
|
|
5
|
+
label: string;
|
|
6
|
+
href: string;
|
|
7
|
+
}
|
|
8
|
+
interface I_liquidRadioProps<T extends string = string> {
|
|
9
|
+
items: readonly I_liquidRadioItem<T>[];
|
|
10
|
+
value: T;
|
|
11
|
+
onChange: (value: T) => void;
|
|
12
|
+
ariaLabel?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const LiquidRadio: <T extends string>(props: I_liquidRadioProps<T>) => ReactNode;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import Link from 'next/link';
|
|
5
|
+
import cn from 'classnames';
|
|
6
|
+
import classNames from 'classnames';
|
|
7
|
+
import { Swiper, SwiperSlide } from 'swiper/react';
|
|
8
|
+
import s from './liquidRadio.module.css';
|
|
9
|
+
import 'swiper/css';
|
|
10
|
+
export const LiquidRadio = memo(({ items, value, onChange, ariaLabel = 'Switch', className }) => {
|
|
11
|
+
const activeIndex = useMemo(() => Math.max(0, items.findIndex(item => item.value === value)), [items, value]);
|
|
12
|
+
const slidesCount = items.length * 2 - 1;
|
|
13
|
+
const slidesCountMap = Array.from({ length: slidesCount });
|
|
14
|
+
const slidesActive = items.length - 1;
|
|
15
|
+
const itemsLength = items.length;
|
|
16
|
+
const swiperRef = useRef(null);
|
|
17
|
+
const shadowRef = useRef(null);
|
|
18
|
+
const indexActiveRef = useRef(null);
|
|
19
|
+
const [isTouching, setIsTouching] = useState(false);
|
|
20
|
+
const handleChangeByActiveSlide = useCallback(() => {
|
|
21
|
+
const idx = indexActiveRef.current;
|
|
22
|
+
if (idx == null || idx < 0)
|
|
23
|
+
return;
|
|
24
|
+
const item = items[idx];
|
|
25
|
+
if (!item)
|
|
26
|
+
return;
|
|
27
|
+
onChange(item.value);
|
|
28
|
+
}, [items, onChange]);
|
|
29
|
+
const onNavigate = (clickIndex) => {
|
|
30
|
+
const activeSlideIndex = swiperRef.current?.activeIndex ?? 0;
|
|
31
|
+
const desiredSlideIndex = itemsLength - clickIndex + activeSlideIndex;
|
|
32
|
+
swiperRef.current?.slideTo(desiredSlideIndex, 300);
|
|
33
|
+
};
|
|
34
|
+
const handleTouchStart = () => {
|
|
35
|
+
setIsTouching(true);
|
|
36
|
+
};
|
|
37
|
+
const handleTouchEnd = () => {
|
|
38
|
+
setIsTouching(false);
|
|
39
|
+
handleChangeByActiveSlide();
|
|
40
|
+
};
|
|
41
|
+
const onProgress = useCallback((swiper, prog) => {
|
|
42
|
+
if (!shadowRef.current)
|
|
43
|
+
return;
|
|
44
|
+
const slidesLength = swiper.slides.length;
|
|
45
|
+
const perView = Number(swiper.params.slidesPerView) || 1;
|
|
46
|
+
const maxIndex = Math.max(0, slidesLength - perView);
|
|
47
|
+
const exactIndex = prog * maxIndex;
|
|
48
|
+
const hoverIndex = Math.round(exactIndex);
|
|
49
|
+
indexActiveRef.current = itemsLength - 1 - hoverIndex;
|
|
50
|
+
shadowRef.current.style.left = `${100 - prog * 100}%`;
|
|
51
|
+
}, [itemsLength]);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
const swiper = swiperRef.current;
|
|
54
|
+
if (!swiper)
|
|
55
|
+
return;
|
|
56
|
+
if (activeIndex < 0)
|
|
57
|
+
return;
|
|
58
|
+
const nextSlide = itemsLength - 1 - activeIndex;
|
|
59
|
+
swiper.slideTo(nextSlide, 200);
|
|
60
|
+
indexActiveRef.current = activeIndex;
|
|
61
|
+
}, [activeIndex, itemsLength]);
|
|
62
|
+
return (_jsxs("div", { "aria-label": ariaLabel, role: 'radiogroup', className: cn(s.wrapper, isTouching && s.wrapperPress, className), style: { gridTemplateColumns: `repeat(${itemsLength}, 1fr)` }, onPointerDown: handleTouchStart, onPointerUp: handleTouchEnd, onPointerCancel: handleTouchEnd, children: [_jsx("div", { className: cn(s.shadowWrapper, isTouching && s.shadowWrapperPress), children: _jsx("div", { className: s.shadow, ref: shadowRef }) }), _jsx(Swiper, { className: cn(s.swiper, isTouching && s.swiperPress), slidesPerView: itemsLength, onSwiper: sw => {
|
|
63
|
+
swiperRef.current = sw;
|
|
64
|
+
}, speed: 300, resistanceRatio: 0, initialSlide: itemsLength - 1 - Math.max(activeIndex, 0), onProgress: onProgress, children: slidesCountMap.map((_, index) => (_jsx(SwiperSlide, { className: s.slide, onPointerDown: () => onNavigate(index + 1), children: slidesActive === index ? (_jsx("div", { className: cn(s.activeSlide, isTouching && s.activeSlidePress) })) : null }, index))) }), items.map((item, index) => (_jsx(Link, { href: item.href, prefetch: true, role: 'radio', "aria-checked": !isTouching && index === activeIndex, className: classNames(s.item, { [s.itemActive]: !isTouching && index === activeIndex }), children: _jsx("p", { className: s.title, children: item.label }) }, item.value)))] }));
|
|
65
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { LiquidRadio } from './LiquidRadio';
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
.wrapper {
|
|
2
|
+
user-select: none;
|
|
3
|
+
-webkit-user-select: none;
|
|
4
|
+
-webkit-user-drag: none;
|
|
5
|
+
-webkit-touch-callout: none;
|
|
6
|
+
-webkit-tap-highlight-color: transparent;
|
|
7
|
+
|
|
8
|
+
position: relative;
|
|
9
|
+
display: grid;
|
|
10
|
+
border-radius: var(--radius-pull) !important;
|
|
11
|
+
z-index: 1;
|
|
12
|
+
|
|
13
|
+
background: rgba(250, 250, 250, 0.75);
|
|
14
|
+
|
|
15
|
+
box-shadow: 0 0 40px -5px #5353531f;
|
|
16
|
+
transition: transform 0.15s ease-out, background 0.1s;
|
|
17
|
+
padding: 0 3px;
|
|
18
|
+
|
|
19
|
+
backdrop-filter: blur(2px);
|
|
20
|
+
|
|
21
|
+
width: 100%;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.wrapper:before {
|
|
25
|
+
content: '';
|
|
26
|
+
position: absolute;
|
|
27
|
+
inset: 0;
|
|
28
|
+
border-radius: var(--radius-pull) !important;
|
|
29
|
+
box-shadow: inset 1.5px 1px 1px 0 white, inset -1.5px -1px 1px 0 white;
|
|
30
|
+
z-index: 0;
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.wrapperPress {
|
|
35
|
+
transform: scale(1.05);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.shadowWrapper {
|
|
39
|
+
position: absolute;
|
|
40
|
+
inset: 0;
|
|
41
|
+
border-radius: var(--radius-pull);
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
opacity: 0;
|
|
44
|
+
transition: 0.3s;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.shadowWrapperPress {
|
|
48
|
+
opacity: 1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.shadow {
|
|
52
|
+
position: absolute;
|
|
53
|
+
left: 50%;
|
|
54
|
+
top: 50%;
|
|
55
|
+
transform: translate(-50%, -50%);
|
|
56
|
+
background: rgba(250, 250, 250, 0.25);
|
|
57
|
+
box-shadow: 0 0 200px 150px rgba(250, 250, 250, 0.9);
|
|
58
|
+
width: 0;
|
|
59
|
+
height: 0;
|
|
60
|
+
opacity: 1;
|
|
61
|
+
border-radius: var(--radius-pull);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.item {
|
|
65
|
+
position: relative;
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
gap: 1px;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
padding: 0.75rem 0.75rem;
|
|
72
|
+
width: 100%;
|
|
73
|
+
pointer-events: none;
|
|
74
|
+
border: none;
|
|
75
|
+
background: transparent;
|
|
76
|
+
text-decoration: none;
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
cursor: default;
|
|
79
|
+
font: inherit;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.title {
|
|
83
|
+
position: relative;
|
|
84
|
+
margin: 0;
|
|
85
|
+
font-size: 0.875rem;
|
|
86
|
+
font-weight: 500;
|
|
87
|
+
transition: 0.2s, color 0s !important;
|
|
88
|
+
text-align: center;
|
|
89
|
+
width: 100%;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.swiper {
|
|
93
|
+
border-radius: var(--radius-pull);
|
|
94
|
+
position: absolute !important;
|
|
95
|
+
inset: 0 calc(-1 * var(--site-horizontal-padding-mobile));
|
|
96
|
+
padding:
|
|
97
|
+
0
|
|
98
|
+
calc(var(--site-horizontal-padding-mobile) + 3px)
|
|
99
|
+
!important;
|
|
100
|
+
|
|
101
|
+
z-index: 0 !important;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.swiperMirror {
|
|
105
|
+
pointer-events: none;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.swiperPress {
|
|
109
|
+
inset:
|
|
110
|
+
-10px
|
|
111
|
+
calc(-1 * var(--site-horizontal-padding-mobile))
|
|
112
|
+
-10px
|
|
113
|
+
calc(-1 * var(--site-horizontal-padding-mobile))
|
|
114
|
+
!important;
|
|
115
|
+
|
|
116
|
+
z-index: 1 !important;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.slide {
|
|
120
|
+
position: relative;
|
|
121
|
+
display: flex;
|
|
122
|
+
align-items: center;
|
|
123
|
+
justify-content: center;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.activeSlide {
|
|
127
|
+
position: absolute;
|
|
128
|
+
inset: 3px 0;
|
|
129
|
+
border-radius: var(--radius-pull);
|
|
130
|
+
transition: 0.15s;
|
|
131
|
+
background: #0000001a;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.activeSlidePress {
|
|
135
|
+
inset: 6px -7px;
|
|
136
|
+
box-shadow: 0 2px 3px #53535326;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.activeSlidePress {
|
|
140
|
+
background: transparent;
|
|
141
|
+
/*backdrop-filter: saturate(400%);*/
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.activeSlide:after {
|
|
145
|
+
content: '';
|
|
146
|
+
position: absolute;
|
|
147
|
+
inset: 0;
|
|
148
|
+
border-radius: var(--radius-pull);
|
|
149
|
+
opacity: 0.5;
|
|
150
|
+
transition: 0.1s;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.activeSlidePress:after {
|
|
154
|
+
box-shadow: inset 1px 1px 1px 0 white, inset -1px -1px 1px 0 white;
|
|
155
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import 'swiper/css';
|
|
3
|
+
export interface I_mobileNavTab {
|
|
4
|
+
title: string;
|
|
5
|
+
path: string;
|
|
6
|
+
icon: (color: string) => ReactNode;
|
|
7
|
+
isActive: (pathname: string) => boolean;
|
|
8
|
+
onPress?: () => void;
|
|
9
|
+
}
|
|
10
|
+
interface I_props {
|
|
11
|
+
tabs: I_mobileNavTab[];
|
|
12
|
+
}
|
|
13
|
+
export declare const NavBarBase: import("react").MemoExoticComponent<({ tabs }: I_props) => import("react").JSX.Element>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import Link from 'next/link';
|
|
5
|
+
import { usePathname, useRouter } from 'next/navigation';
|
|
6
|
+
import cn from 'classnames';
|
|
7
|
+
import classNames from 'classnames';
|
|
8
|
+
import { Swiper, SwiperSlide } from 'swiper/react';
|
|
9
|
+
import s from './navBarBase.module.css';
|
|
10
|
+
import 'swiper/css';
|
|
11
|
+
export const NavBarBase = memo(({ tabs }) => {
|
|
12
|
+
const router = useRouter();
|
|
13
|
+
const pathname = usePathname();
|
|
14
|
+
//
|
|
15
|
+
const activeTabIndex = useMemo(() => tabs.findIndex(tab => tab.isActive(pathname)), [tabs, pathname]);
|
|
16
|
+
const slidesCount = tabs.length * 2 - 1;
|
|
17
|
+
const slidesCountMap = Array.from({ length: slidesCount });
|
|
18
|
+
const slidesActive = tabs.length - 1;
|
|
19
|
+
const tabsLength = tabs.length;
|
|
20
|
+
const swiperRef = useRef(null);
|
|
21
|
+
const shadowRef = useRef(null);
|
|
22
|
+
const indexActiveRef = useRef(null);
|
|
23
|
+
//
|
|
24
|
+
const [isTouching, setIsTouching] = useState(false);
|
|
25
|
+
const handleNavigateByActiveSlide = useCallback(() => {
|
|
26
|
+
const swiper = swiperRef.current;
|
|
27
|
+
if (!swiper)
|
|
28
|
+
return;
|
|
29
|
+
const idx = indexActiveRef.current;
|
|
30
|
+
if (idx == null || idx < 0)
|
|
31
|
+
return;
|
|
32
|
+
const tab = tabs[idx];
|
|
33
|
+
if (!tab?.path)
|
|
34
|
+
return;
|
|
35
|
+
tab.onPress?.();
|
|
36
|
+
router.push(tab.path);
|
|
37
|
+
}, [tabs, router]);
|
|
38
|
+
const onNavigate = (clickIndex) => {
|
|
39
|
+
const activeIndex = swiperRef.current?.activeIndex ?? 0;
|
|
40
|
+
const desiredSlideIndex = tabsLength - clickIndex + activeIndex;
|
|
41
|
+
swiperRef.current?.slideTo(desiredSlideIndex, 300);
|
|
42
|
+
};
|
|
43
|
+
const handleNavTouchStart = () => {
|
|
44
|
+
setIsTouching(true);
|
|
45
|
+
};
|
|
46
|
+
const handleNavTouchEnd = () => {
|
|
47
|
+
setIsTouching(false);
|
|
48
|
+
handleNavigateByActiveSlide();
|
|
49
|
+
};
|
|
50
|
+
const onProgress = useCallback((swiper, prog) => {
|
|
51
|
+
if (!shadowRef.current)
|
|
52
|
+
return;
|
|
53
|
+
const slidesLength = swiper.slides.length;
|
|
54
|
+
const perView = Number(swiper.params.slidesPerView) || 1;
|
|
55
|
+
const maxIndex = Math.max(0, slidesLength - perView);
|
|
56
|
+
const exactIndex = prog * maxIndex;
|
|
57
|
+
const hoverIndex = Math.round(exactIndex);
|
|
58
|
+
indexActiveRef.current = tabsLength - 1 - hoverIndex;
|
|
59
|
+
shadowRef.current.style.left = `${100 - prog * 100}%`;
|
|
60
|
+
}, [tabsLength]);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
const swiper = swiperRef.current;
|
|
63
|
+
if (!swiper)
|
|
64
|
+
return;
|
|
65
|
+
if (activeTabIndex < 0)
|
|
66
|
+
return;
|
|
67
|
+
const nextSlide = tabsLength - 1 - activeTabIndex;
|
|
68
|
+
swiper.slideTo(nextSlide, 200);
|
|
69
|
+
indexActiveRef.current = activeTabIndex;
|
|
70
|
+
}, [activeTabIndex, tabsLength]);
|
|
71
|
+
return (_jsxs("nav", { "aria-label": 'Mobile Navigation', className: cn(s.wrapper, isTouching && s.wrapperPress), style: { gridTemplateColumns: `repeat(${tabsLength}, 1fr)` }, onPointerDown: handleNavTouchStart, onPointerUp: handleNavTouchEnd, onPointerCancel: handleNavTouchEnd, children: [_jsx("div", { className: cn(s.shadowWrapper, isTouching && s.shadowWrapperPress), children: _jsx("div", { className: s.shadow, ref: shadowRef }) }), _jsx(Swiper, { className: cn(s.swiper, isTouching && s.swiperPress), slidesPerView: tabsLength, onSwiper: sw => {
|
|
72
|
+
swiperRef.current = sw;
|
|
73
|
+
}, speed: 300, resistanceRatio: 0, initialSlide: tabsLength - 1 - Math.max(activeTabIndex, 0), onProgress: onProgress, children: slidesCountMap.map((_, index) => (_jsx(SwiperSlide, { className: s.slide, onPointerDown: () => onNavigate(index + 1), children: slidesActive === index ? (_jsx("div", { className: cn(s.activeSlide, isTouching && s.activeSlidePress) })) : null }, index))) }), tabs.map((item, index) => (_jsxs(Link, { className: classNames(s.item, { [s.itemActive]: !isTouching && index === activeTabIndex }), href: item.path, prefetch: true, onClick: () => item.onPress?.(), children: [_jsx("div", { style: { position: 'relative' }, children: _jsx("span", { className: s.itemIcon, children: item?.icon((index === activeTabIndex && !isTouching) ? 'var(--color-main)' : '#6d4c4c') }) }), _jsx("p", { className: s.title, children: item.title })] }, index)))] }));
|
|
74
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NavBarBase } from './NavBarBase';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { I_mobileNavTab } from './NavBarBase';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
.wrapper {
|
|
2
|
+
user-select: none;
|
|
3
|
+
-webkit-user-select: none;
|
|
4
|
+
-webkit-user-drag: none;
|
|
5
|
+
-webkit-touch-callout: none;
|
|
6
|
+
-webkit-tap-highlight-color: transparent;
|
|
7
|
+
|
|
8
|
+
position: relative;
|
|
9
|
+
display: grid;
|
|
10
|
+
border-radius: var(--radius-pull) !important;
|
|
11
|
+
z-index: 1;
|
|
12
|
+
width: calc(100% - (var(--site-horizontal-padding-mobile) * 2));
|
|
13
|
+
|
|
14
|
+
background: rgba(250, 250, 250, 0.75);
|
|
15
|
+
|
|
16
|
+
inset: 0 var(--site-horizontal-padding-mobile);
|
|
17
|
+
box-shadow: 0 0 40px -5px #5353531f;
|
|
18
|
+
transition: transform 0.15s ease-out, background 0.1s;
|
|
19
|
+
padding: 0 3px;
|
|
20
|
+
|
|
21
|
+
backdrop-filter: blur(2px);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.wrapper:before {
|
|
25
|
+
content: '';
|
|
26
|
+
position: absolute;
|
|
27
|
+
inset: 0;
|
|
28
|
+
border-radius: var(--radius-pull) !important;
|
|
29
|
+
box-shadow: inset 1.5px 1px 1px 0 white, inset -1.5px -1px 1px 0 white;
|
|
30
|
+
z-index: 0;
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.wrapperPress {
|
|
35
|
+
transform: scale(1.05);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.shadowWrapper {
|
|
39
|
+
position: absolute;
|
|
40
|
+
inset: 0;
|
|
41
|
+
border-radius: var(--radius-pull);
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
opacity: 0;
|
|
44
|
+
transition: 0.3s;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.shadowWrapperPress {
|
|
48
|
+
opacity: 1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.shadow {
|
|
52
|
+
position: absolute;
|
|
53
|
+
left: 50%;
|
|
54
|
+
top: 50%;
|
|
55
|
+
transform: translate(-50%, -50%);
|
|
56
|
+
background: rgba(250, 250, 250, 0.25);
|
|
57
|
+
box-shadow: 0 0 200px 150px rgba(250, 250, 250, 0.9);
|
|
58
|
+
width: 0;
|
|
59
|
+
height: 0;
|
|
60
|
+
opacity: 1;
|
|
61
|
+
border-radius: var(--radius-pull);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.item {
|
|
65
|
+
position: relative;
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
gap: 1px;
|
|
69
|
+
align-items: center;
|
|
70
|
+
padding: 0.5rem 0 0.6rem 0;
|
|
71
|
+
width: 100%;
|
|
72
|
+
pointer-events: none;
|
|
73
|
+
text-decoration: none;
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.itemIcon {
|
|
78
|
+
display: flex;
|
|
79
|
+
aspect-ratio: 1/1;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
height: 1.75rem;
|
|
82
|
+
transform-origin: center bottom;
|
|
83
|
+
will-change: transform;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.item p {
|
|
87
|
+
position: relative;
|
|
88
|
+
margin: 0;
|
|
89
|
+
font-size: 0.6rem;
|
|
90
|
+
font-weight: 500;
|
|
91
|
+
transition: 0.2s, color 0s !important;
|
|
92
|
+
white-space: nowrap;
|
|
93
|
+
text-overflow: ellipsis;
|
|
94
|
+
overflow: hidden;
|
|
95
|
+
text-align: center;
|
|
96
|
+
color: #6d4c4c;
|
|
97
|
+
width: 100%;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.itemActive p {
|
|
101
|
+
color: var(--color-main);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.swiper {
|
|
105
|
+
border-radius: var(--radius-pull);
|
|
106
|
+
position: absolute !important;
|
|
107
|
+
inset: 0 calc(-1 * var(--site-horizontal-padding-mobile));
|
|
108
|
+
padding:
|
|
109
|
+
0
|
|
110
|
+
calc(var(--site-horizontal-padding-mobile) + 3px)
|
|
111
|
+
!important;
|
|
112
|
+
|
|
113
|
+
z-index: 0 !important;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.swiperMirror {
|
|
117
|
+
pointer-events: none;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.swiperPress {
|
|
121
|
+
inset:
|
|
122
|
+
-10px
|
|
123
|
+
calc(-1 * var(--site-horizontal-padding-mobile))
|
|
124
|
+
-10px
|
|
125
|
+
calc(-1 * var(--site-horizontal-padding-mobile))
|
|
126
|
+
!important;
|
|
127
|
+
|
|
128
|
+
z-index: 1 !important;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.slide {
|
|
132
|
+
position: relative;
|
|
133
|
+
display: flex;
|
|
134
|
+
align-items: center;
|
|
135
|
+
justify-content: center;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.activeSlide {
|
|
139
|
+
position: absolute;
|
|
140
|
+
inset: 3px 0;
|
|
141
|
+
border-radius: var(--radius-pull);
|
|
142
|
+
transition: 0.15s;
|
|
143
|
+
background: #0000001a;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.activeSlidePress {
|
|
147
|
+
inset: 6px -7px;
|
|
148
|
+
box-shadow: 0 2px 3px #53535326;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.activeSlidePress {
|
|
152
|
+
background: transparent;
|
|
153
|
+
backdrop-filter: saturate(400%);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.activeSlide:after {
|
|
157
|
+
content: '';
|
|
158
|
+
position: absolute;
|
|
159
|
+
inset: 0;
|
|
160
|
+
border-radius: var(--radius-pull);
|
|
161
|
+
opacity: 0.5;
|
|
162
|
+
transition: 0.1s;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.activeSlidePress:after {
|
|
166
|
+
box-shadow: inset 1px 1px 1px 0 white, inset -1px -1px 1px 0 white;
|
|
167
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { LiquidContainer } from './components/LiquidContainer';
|
|
2
|
+
export { LiquidButton, ButtonLoader } from './components/LiquidButton';
|
|
3
|
+
export { NavBarBase } from './components/NavBarBase';
|
|
4
|
+
export type { I_mobileNavTab } from './components/NavBarBase';
|
|
5
|
+
export { LiquidRadio } from './components/LiquidRadio';
|
|
6
|
+
export type { I_liquidRadioItem } from './components/LiquidRadio';
|
package/dist/index.js
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { LiquidContainer } from './components/LiquidContainer';
|
|
2
|
+
export { LiquidButton, ButtonLoader } from './components/LiquidButton';
|
|
3
|
+
export { NavBarBase } from './components/NavBarBase';
|
|
4
|
+
export { LiquidRadio } from './components/LiquidRadio';
|
package/dist/utils/cx.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const cx = (...classes) => classes.filter(Boolean).join(' ');
|
package/package.json
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "likvid-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Likvid UI — glass-кит React-компонентов в стиле Apple Liquid Glass",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"build": "tsc -p tsconfig.build.json",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"pub": "
|
|
15
|
-
"pub:patch": "npm version patch --no-git-tag-version && yarn publish",
|
|
16
|
-
"pub:minor": "npm version minor --no-git-tag-version && yarn publish",
|
|
17
|
-
"pub:major": "npm version major --no-git-tag-version && yarn publish"
|
|
9
|
+
"build": "tsc -p tsconfig.build.json && node scripts/copy-css.mjs",
|
|
10
|
+
"prepack": "yarn build",
|
|
11
|
+
"pub": "npm publish",
|
|
12
|
+
"pub:patch": "npm version patch --no-git-tag-version && npm publish",
|
|
13
|
+
"pub:minor": "npm version minor --no-git-tag-version && npm publish",
|
|
14
|
+
"pub:major": "npm version major --no-git-tag-version && npm publish"
|
|
18
15
|
},
|
|
19
16
|
"exports": {
|
|
20
17
|
".": {
|
|
@@ -34,7 +31,24 @@
|
|
|
34
31
|
],
|
|
35
32
|
"license": "MIT",
|
|
36
33
|
"packageManager": "yarn@1.22.22",
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"next": ">=13",
|
|
36
|
+
"react": ">=18",
|
|
37
|
+
"react-dom": ">=18",
|
|
38
|
+
"swiper": ">=11"
|
|
39
|
+
},
|
|
40
|
+
"peerDependenciesMeta": {
|
|
41
|
+
"next": {
|
|
42
|
+
"optional": true
|
|
43
|
+
}
|
|
44
|
+
},
|
|
37
45
|
"devDependencies": {
|
|
46
|
+
"@types/react": "^18.3.12",
|
|
47
|
+
"@types/react-dom": "^18.3.1",
|
|
48
|
+
"swiper": "^11.2.10",
|
|
38
49
|
"typescript": "^5.6.3"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"classnames": "^2.5.1"
|
|
39
53
|
}
|
|
40
54
|
}
|