@goncharovv/layout 0.0.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/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # React + TypeScript + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9
+
10
+ ## Expanding the ESLint configuration
11
+
12
+ If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
13
+
14
+ ```js
15
+ export default defineConfig([
16
+ globalIgnores(['dist']),
17
+ {
18
+ files: ['**/*.{ts,tsx}'],
19
+ extends: [
20
+ // Other configs...
21
+
22
+ // Remove tseslint.configs.recommended and replace with this
23
+ tseslint.configs.recommendedTypeChecked,
24
+ // Alternatively, use this for stricter rules
25
+ tseslint.configs.strictTypeChecked,
26
+ // Optionally, add this for stylistic rules
27
+ tseslint.configs.stylisticTypeChecked,
28
+
29
+ // Other configs...
30
+ ],
31
+ languageOptions: {
32
+ parserOptions: {
33
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
34
+ tsconfigRootDir: import.meta.dirname,
35
+ },
36
+ // other options...
37
+ },
38
+ },
39
+ ])
40
+ ```
41
+
42
+ You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
43
+
44
+ ```js
45
+ // eslint.config.js
46
+ import reactX from 'eslint-plugin-react-x'
47
+ import reactDom from 'eslint-plugin-react-dom'
48
+
49
+ export default defineConfig([
50
+ globalIgnores(['dist']),
51
+ {
52
+ files: ['**/*.{ts,tsx}'],
53
+ extends: [
54
+ // Other configs...
55
+ // Enable lint rules for React
56
+ reactX.configs['recommended-typescript'],
57
+ // Enable lint rules for React DOM
58
+ reactDom.configs.recommended,
59
+ ],
60
+ languageOptions: {
61
+ parserOptions: {
62
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
63
+ tsconfigRootDir: import.meta.dirname,
64
+ },
65
+ // other options...
66
+ },
67
+ },
68
+ ])
69
+ ```
@@ -0,0 +1,7 @@
1
+ import { BaseStackProps } from './factory';
2
+ export interface HStackProps extends BaseStackProps {
3
+ reverse?: boolean;
4
+ }
5
+ export declare const HStack: <TElementType extends import("react").ElementType = "div">(props: {
6
+ as?: TElementType | undefined;
7
+ } & Omit<HStackProps, "as"> & Omit<import("react").PropsWithoutRef<import("react").ComponentProps<TElementType>>, "style" | "alignItems" | "align" | "justifyContent" | "justify" | "wrap" | "gap" | "centered" | "className" | "children" | "spacing" | "reverse">) => import("react").ReactNode;
@@ -0,0 +1,14 @@
1
+ import cn from 'classnames';
2
+ import { createStack } from './factory';
3
+ import styles from './Stack.module.css';
4
+ export const HStack = createStack('HStack', {
5
+ overrideProps: (props) => {
6
+ const { reverse, className, ...rest } = props;
7
+ return {
8
+ ...rest,
9
+ className: cn(styles.horizontal, {
10
+ [styles.reversed]: reverse,
11
+ }, className),
12
+ };
13
+ },
14
+ });
@@ -0,0 +1,11 @@
1
+ import { CSSProperties } from 'react';
2
+ import { BaseStackProps } from './factory';
3
+ export type StackDirection = 'vertical' | 'horizontal';
4
+ export interface StackProps extends BaseStackProps {
5
+ vertical?: boolean;
6
+ horizontal?: boolean;
7
+ direction?: CSSProperties['flexDirection'];
8
+ }
9
+ export declare const Stack: <TElementType extends import("react").ElementType = "div">(props: {
10
+ as?: TElementType | undefined;
11
+ } & Omit<StackProps, "as"> & Omit<import("react").PropsWithoutRef<import("react").ComponentProps<TElementType>>, "style" | "alignItems" | "align" | "justifyContent" | "justify" | "wrap" | "gap" | "centered" | "className" | "children" | "spacing" | "horizontal" | "vertical" | "direction">) => import("react").ReactNode;
@@ -0,0 +1,18 @@
1
+ import cn from 'classnames';
2
+ import { createStack } from './factory';
3
+ import styles from './Stack.module.css';
4
+ export const Stack = createStack('Stack', {
5
+ overrideProps: (props) => {
6
+ const { direction, horizontal, vertical, className, ...rest } = props;
7
+ return {
8
+ ...rest,
9
+ className: cn({
10
+ [styles.vertical]: vertical,
11
+ [styles.horizontal]: horizontal,
12
+ }, className),
13
+ styles: {
14
+ flexDirection: direction,
15
+ },
16
+ };
17
+ },
18
+ });
@@ -0,0 +1,7 @@
1
+ import { BaseStackProps } from './factory';
2
+ export interface VStackProps extends BaseStackProps {
3
+ reverse?: boolean;
4
+ }
5
+ export declare const VStack: <TElementType extends import("react").ElementType = "div">(props: {
6
+ as?: TElementType | undefined;
7
+ } & Omit<VStackProps, "as"> & Omit<import("react").PropsWithoutRef<import("react").ComponentProps<TElementType>>, "style" | "alignItems" | "align" | "justifyContent" | "justify" | "wrap" | "gap" | "centered" | "className" | "children" | "spacing" | "reverse">) => import("react").ReactNode;
@@ -0,0 +1,14 @@
1
+ import cn from 'classnames';
2
+ import { createStack } from './factory';
3
+ import styles from './Stack.module.css';
4
+ export const VStack = createStack('VStack', {
5
+ overrideProps: (props) => {
6
+ const { reverse, className, ...rest } = props;
7
+ return {
8
+ ...rest,
9
+ className: cn(styles.vertical, {
10
+ [styles.reversed]: reverse,
11
+ }, className),
12
+ };
13
+ },
14
+ });
@@ -0,0 +1,46 @@
1
+ import React, { CSSProperties, ElementType, PropsWithChildren, ReactNode } from 'react';
2
+ import { PropsWithSpacing } from '../../shared/spacings';
3
+ import { Prettify } from '../../shared/types';
4
+ export interface BaseStackProps<TElementType extends ElementType = 'div'> extends PropsWithChildren, PropsWithSpacing {
5
+ as?: TElementType;
6
+ alignItems?: CSSProperties['alignItems'];
7
+ /**
8
+ * shortcut for `alignItems`
9
+ */
10
+ align?: CSSProperties['alignItems'];
11
+ justifyContent?: CSSProperties['justifyContent'];
12
+ /**
13
+ * shortcut for `justifyContent`
14
+ */
15
+ justify?: CSSProperties['justifyContent'];
16
+ /**
17
+ * `flex-wrap` property
18
+ *
19
+ * If value equals `true`, add css property `flex-wrap: wrap`;
20
+ */
21
+ wrap?: true | CSSProperties['flexWrap'];
22
+ /**
23
+ * Custom gap. This is uncommon prop. Consider using `spacing` instead.
24
+ */
25
+ gap?: number;
26
+ /**
27
+ * Alias for:
28
+ * ```css
29
+ * justify-content: center;
30
+ * align-items: center;
31
+ * ```
32
+ */
33
+ centered?: boolean;
34
+ style?: CSSProperties;
35
+ className?: string;
36
+ }
37
+ /**
38
+ * `_TPropsHint` is used only to show in IDE list of own Stack props
39
+ */
40
+ type StackPropsBuilder<TElementType extends ElementType, TProps, _TPropsHint = Prettify<TProps>> = {
41
+ as?: TElementType;
42
+ } & Omit<TProps, 'as'> & Omit<React.ComponentPropsWithoutRef<TElementType>, keyof Omit<TProps, 'as'>>;
43
+ export declare function createStack<TProps extends BaseStackProps>(name: string, options: {
44
+ overrideProps?: (props: TProps) => BaseStackProps;
45
+ }): <TElementType extends ElementType = "div">(props: StackPropsBuilder<TElementType, TProps>) => ReactNode;
46
+ export {};
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import cn from 'classnames';
3
+ import { getSpacingStyles } from '../../shared/spacings';
4
+ import styles from './Stack.module.css';
5
+ export function createStack(name, options) {
6
+ const Component = function GenericStack(_props) {
7
+ const props = options.overrideProps ? options.overrideProps(_props) : _props;
8
+ // WARNING: Avoid proxying *component props* to real DOM
9
+ const { as: Element = 'div', align, alignItems, centered, gap, justify, justifyContent, spacing, style, wrap, className, children, ...rest } = props;
10
+ return (_jsx(Element, { ...rest, className: cn(styles.stack, {
11
+ [styles.centered]: centered,
12
+ }, className), style: {
13
+ gap: spacing ? getSpacingStyles(spacing).gap : gap,
14
+ flexWrap: wrap === true ? 'wrap' : wrap,
15
+ alignItems: centered ? undefined : (alignItems ?? align),
16
+ justifyContent: centered ? undefined : (justifyContent ?? justify),
17
+ ...style,
18
+ }, children: children }));
19
+ };
20
+ Component.displayName = name;
21
+ /**
22
+ * Typing for better DX
23
+ */
24
+ return Component;
25
+ }
@@ -0,0 +1,3 @@
1
+ export * from './HStack';
2
+ export * from './Stack';
3
+ export * from './VStack';
@@ -0,0 +1,3 @@
1
+ export * from './HStack';
2
+ export * from './Stack';
3
+ export * from './VStack';
@@ -0,0 +1 @@
1
+ export * from './Stacks';
@@ -0,0 +1 @@
1
+ export * from './Stacks';
@@ -0,0 +1 @@
1
+ export * from './components';
@@ -0,0 +1 @@
1
+ export * from './components';
@@ -0,0 +1,42 @@
1
+ import { CSSProperties } from 'react';
2
+ export declare const spacings: {
3
+ none: number;
4
+ 'small-xs': number;
5
+ 'small-s': number;
6
+ 'small-m': number;
7
+ 'small-l': number;
8
+ 'medium-xs': number;
9
+ 'medium-s': number;
10
+ 'medium-m': number;
11
+ 'medium-l': number;
12
+ 'large-xxs': number;
13
+ 'large-xs': number;
14
+ 'large-s': number;
15
+ 'large-m': number;
16
+ 'large-l': number;
17
+ };
18
+ export type Spacing = keyof typeof spacings;
19
+ export interface PropsWithSpacing {
20
+ /**
21
+ * - none: 0px
22
+ * - small:
23
+ * - 'small-xs': 2px
24
+ * - 'small-s': 4px
25
+ * - 'small-m': 6px
26
+ * - 'small-l': 8px
27
+ * - medium:
28
+ * - 'medium-xs': 12px
29
+ * - 'medium-s': 16px
30
+ * - 'medium-m': 20px
31
+ * - 'medium-l': 24px
32
+ * - large:
33
+ * - 'large-xxs': 32px
34
+ * - 'large-xs': 40px
35
+ * - 'large-s': 48px
36
+ * - 'large-m': 64px
37
+ * - 'large-l': 80px
38
+ */
39
+ spacing?: Spacing;
40
+ }
41
+ export declare function getSpacing(spacing: Spacing | undefined): number | undefined;
42
+ export declare function getSpacingStyles(spacing: Spacing | undefined): CSSProperties;
@@ -0,0 +1,30 @@
1
+ //
2
+ // MUST keep in sync with the `spacings.css`
3
+ //
4
+ export const spacings = {
5
+ 'none': 0,
6
+ 'small-xs': 2,
7
+ 'small-s': 4,
8
+ 'small-m': 6,
9
+ 'small-l': 8,
10
+ 'medium-xs': 12,
11
+ 'medium-s': 16,
12
+ 'medium-m': 20,
13
+ 'medium-l': 24,
14
+ 'large-xxs': 32,
15
+ 'large-xs': 40,
16
+ 'large-s': 48,
17
+ 'large-m': 64,
18
+ 'large-l': 80,
19
+ };
20
+ export function getSpacing(spacing) {
21
+ if (!spacing) {
22
+ return undefined;
23
+ }
24
+ return spacings[spacing];
25
+ }
26
+ export function getSpacingStyles(spacing) {
27
+ return {
28
+ gap: `var(--spacing-${spacing})`,
29
+ };
30
+ }
@@ -0,0 +1 @@
1
+ export * from './config';
@@ -0,0 +1 @@
1
+ export * from './config';
@@ -0,0 +1,3 @@
1
+ export declare type Prettify<T> = {
2
+ [K in keyof T]: T[K];
3
+ } & {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ .stack {
2
+ display: flex;
3
+ }
4
+
5
+ .vertical {
6
+ flex-direction: column;
7
+ }
8
+ .vertical.reversed {
9
+ flex-direction: column-reverse;;
10
+ }
11
+
12
+ .horizontal {
13
+ flex-direction: row;
14
+ }
15
+ .horizontal.reversed {
16
+ flex-direction: row-reverse;
17
+ }
18
+
19
+ .centered {
20
+ align-items: center;
21
+ justify-content: center;
22
+ }
@@ -0,0 +1 @@
1
+ @import './spacings.css';
@@ -0,0 +1,20 @@
1
+ /*
2
+ * MUST keep in sync with the `shared/spacings/config.ts`
3
+ */
4
+
5
+ :root {
6
+ --spacing-small-xxs: 0px;
7
+ --spacing-small-xs: 2px;
8
+ --spacing-small-s: 4px;
9
+ --spacing-small-m: 6px;
10
+ --spacing-small-l: 8px;
11
+ --spacing-medium-xs: 12px;
12
+ --spacing-medium-s: 16px;
13
+ --spacing-medium-m: 20px;
14
+ --spacing-medium-l: 24px;
15
+ --spacing-large-xxs: 32px;
16
+ --spacing-large-xs: 40px;
17
+ --spacing-large-s: 48px;
18
+ --spacing-large-m: 64px;
19
+ --spacing-large-l: 80px;
20
+ }
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@goncharovv/layout",
3
+ "private": false,
4
+ "version": "0.0.1",
5
+ "type": "module",
6
+ "main": "dist/esm/index.js",
7
+ "types": "dist/esm/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "dev": "vite",
13
+ "build": "gulp",
14
+ "lint": "eslint .",
15
+ "preview": "vite preview"
16
+ },
17
+ "dependencies": {
18
+ "classnames": "2.5.1"
19
+ },
20
+ "peerDependencies": {
21
+ "react": "^19",
22
+ "react-dom": "^19"
23
+ },
24
+ "devDependencies": {
25
+ "@goncharovv/eslint-config": "1.0.6",
26
+ "@gravity-ui/gulp-utils": "1.0.3",
27
+ "@types/react": "^19.1.13",
28
+ "@types/react-dom": "^19.1.9",
29
+ "@vitejs/plugin-react": "^5.0.2",
30
+ "eslint": "^9.35.0",
31
+ "globals": "16.4.0",
32
+ "gulp": "5.0.1",
33
+ "rimraf": "6.0.1",
34
+ "typescript": "~5.8.3",
35
+ "vite": "^7.1.6"
36
+ }
37
+ }