xenopomp-essentials 0.3.1 → 0.3.3

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 (143) hide show
  1. package/.config/.lintstagedrc.json +3 -0
  2. package/.config/build.config.ts +41 -0
  3. package/.config/testing-exclusions/index.ts +2 -0
  4. package/.config/testing-exclusions/istanbul-exclusions.ts +1 -0
  5. package/.config/testing-exclusions/vitest-exclusions.ts +8 -0
  6. package/.config/ts/tsconfig.lint.json +10 -0
  7. package/.config/vitest.config.ts +18 -0
  8. package/.gitattributes +25 -0
  9. package/.github/workflows/ci.yml +54 -0
  10. package/.github/workflows/npm-publish.yml +27 -0
  11. package/.husky/pre-commit +1 -0
  12. package/.idea/codeStyles/Project.xml +59 -0
  13. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  14. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  15. package/.idea/modules.xml +8 -0
  16. package/.idea/prettier.xml +7 -0
  17. package/.idea/runConfigurations/_template__of_Vitest.xml +9 -0
  18. package/.idea/runConfigurations/build.xml +13 -0
  19. package/.idea/runConfigurations/coverage.xml +12 -0
  20. package/.idea/runConfigurations/lint.xml +13 -0
  21. package/.idea/runConfigurations/lint_code.xml +13 -0
  22. package/.idea/vcs.xml +6 -0
  23. package/.idea/xenopomp-essentials-js.iml +14 -0
  24. package/.prettierrc +20 -0
  25. package/.yarnrc +2 -0
  26. package/README.md +0 -0
  27. package/__tests__/assets/assertions/expect-deep-equal.ts +14 -0
  28. package/__tests__/assets/assertions/expect-to-render.ts +26 -0
  29. package/__tests__/assets/assertions/index.ts +3 -0
  30. package/__tests__/assets/assertions/not-throwing.ts +6 -0
  31. package/__tests__/assets/index.ts +1 -0
  32. package/__tests__/data/index.ts +1 -0
  33. package/__tests__/data/parseVersion.data.ts +52 -0
  34. package/__tests__/unit/cli/path-builder.test.ts +39 -0
  35. package/__tests__/unit/components/hoc/jsx-dot-notation/component.test-source.tsx +24 -0
  36. package/__tests__/unit/components/hoc/jsx-dot-notation/hoc.test.tsx +11 -0
  37. package/__tests__/unit/components/metrika.test.tsx +14 -0
  38. package/__tests__/unit/components/react-scan.test.tsx +10 -0
  39. package/__tests__/unit/eslint/config.test.tsx +41 -0
  40. package/__tests__/unit/utils/capitalize.test.ts +17 -0
  41. package/__tests__/unit/utils/minmax.test.ts +21 -0
  42. package/__tests__/unit/utils/parseVersion.test.ts +22 -0
  43. package/__tests__/unit/utils/pipe.test.ts +23 -0
  44. package/__tests__/unit/utils/transliterate.test.ts +17 -0
  45. package/_templates/generator/help/index.ejs.t +5 -0
  46. package/_templates/generator/new/hello.ejs.t +18 -0
  47. package/_templates/generator/with-prompt/hello.ejs.t +18 -0
  48. package/_templates/generator/with-prompt/prompt.ejs.t +14 -0
  49. package/_templates/init/repo/new-repo.ejs.t +4 -0
  50. package/_templates/type/new/module.ejs.t +7 -0
  51. package/_templates/type/new/type.ejs.t +7 -0
  52. package/_templates/util/new/func.ejs.t +7 -0
  53. package/_templates/util/new/module.ejs.t +7 -0
  54. package/_templates/util/new/test.ejs.t +13 -0
  55. package/eslint.config.ts +17 -0
  56. package/package.json +4 -3
  57. package/src/cli-tools/changeFile.ts +1 -0
  58. package/src/cli-tools/index.ts +2 -0
  59. package/src/cli-tools/pathBuilder.ts +89 -0
  60. package/src/eslint/config.ts +145 -0
  61. package/src/eslint/configs/all.ts +74 -0
  62. package/src/eslint/configs/deprecation.ts +33 -0
  63. package/src/eslint/configs/index.ts +7 -0
  64. package/src/eslint/configs/markdown.ts +30 -0
  65. package/src/eslint/configs/next.ts +40 -0
  66. package/src/eslint/configs/old.ts +67 -0
  67. package/src/eslint/configs/prettier.ts +6 -0
  68. package/src/eslint/configs/react.ts +18 -0
  69. package/src/eslint/index.ts +7 -0
  70. package/src/eslint/prefixes/author.ts +2 -0
  71. package/src/eslint/prefixes/index.ts +1 -0
  72. package/src/eslint/types/configs.ts +4 -0
  73. package/src/eslint/types/custom-config.ts +4 -0
  74. package/src/eslint/types/index.ts +2 -0
  75. package/src/index.ts +3 -0
  76. package/src/next/Metrika/Metrika.props.ts +11 -0
  77. package/src/next/Metrika/Metrika.tsx +56 -0
  78. package/src/next/ReactScan/ReactScan.tsx +33 -0
  79. package/src/next/index.ts +2 -0
  80. package/src/react/hoc/index.ts +1 -0
  81. package/src/react/hoc/jsxDotNotation.tsx +38 -0
  82. package/src/react/index.ts +1 -0
  83. package/src/repo-eslint-rules/deep-type-naming.rule.ts +49 -0
  84. package/src/repo-eslint-rules/index.ts +9 -0
  85. package/src/schemas/import-meta.schema.ts +12 -0
  86. package/src/schemas/index.ts +1 -0
  87. package/src/types/aliases/AnyObject.ts +5 -0
  88. package/src/types/aliases/EmptyObject.ts +8 -0
  89. package/src/types/aliases/Fn.ts +12 -0
  90. package/src/types/aliases/index.ts +3 -0
  91. package/src/types/index.ts +4 -0
  92. package/src/types/next/NextParams.ts +26 -0
  93. package/src/types/next/index.ts +1 -0
  94. package/src/types/react/AnyFc.ts +6 -0
  95. package/src/types/react/AsyncFC.ts +16 -0
  96. package/src/types/react/DataAttributes.ts +21 -0
  97. package/src/types/react/FCProps.ts +19 -0
  98. package/src/types/react/FunctionalChildren.ts +13 -0
  99. package/src/types/react/SetState.ts +11 -0
  100. package/src/types/react/VariableFC.ts +48 -0
  101. package/src/types/react/VariableProps.ts +9 -0
  102. package/src/types/react/index.ts +8 -0
  103. package/src/types/utilities/ArrayType.ts +12 -0
  104. package/src/types/utilities/AsyncReturnType.ts +14 -0
  105. package/src/types/utilities/DeepInject.ts +22 -0
  106. package/src/types/utilities/Defined.ts +5 -0
  107. package/src/types/utilities/Jsonish.ts +11 -0
  108. package/src/types/utilities/LenientAutocomplete.ts +24 -0
  109. package/src/types/utilities/MatchType.ts +26 -0
  110. package/src/types/utilities/MergeTypes.ts +12 -0
  111. package/src/types/utilities/Modify.ts +10 -0
  112. package/src/types/utilities/Nullable.ts +5 -0
  113. package/src/types/utilities/OneOf.ts +42 -0
  114. package/src/types/utilities/Prettify.ts +15 -0
  115. package/src/types/utilities/RecordKey.ts +9 -0
  116. package/src/types/utilities/RecordValue.ts +9 -0
  117. package/src/types/utilities/ReplaceReturnType.ts +10 -0
  118. package/src/types/utilities/SelectivePartial.ts +17 -0
  119. package/src/types/utilities/StrictOmit.ts +19 -0
  120. package/src/types/utilities/Synchronous.ts +18 -0
  121. package/src/types/utilities/Undefinable.ts +5 -0
  122. package/src/types/utilities/WeakOmit.ts +17 -0
  123. package/src/types/utilities/Writeable.ts +18 -0
  124. package/src/types/utilities/index.ts +24 -0
  125. package/src/utils/capitalize.ts +15 -0
  126. package/src/utils/index.ts +7 -0
  127. package/src/utils/minmax.ts +35 -0
  128. package/src/utils/parseVersion.ts +42 -0
  129. package/src/utils/pipe.ts +29 -0
  130. package/src/utils/transliterate.ts +8 -0
  131. package/tsconfig.json +43 -0
  132. package/cli-tools/index.d.mts +0 -60
  133. package/cli-tools/index.d.ts +0 -60
  134. package/cli-tools/index.mjs +0 -1
  135. package/eslint/index.d.mts +0 -39
  136. package/eslint/index.d.ts +0 -39
  137. package/eslint/index.mjs +0 -3
  138. package/index.d.mts +0 -611
  139. package/index.d.ts +0 -611
  140. package/index.mjs +0 -1
  141. package/next/index.d.mts +0 -67
  142. package/next/index.d.ts +0 -67
  143. package/next/index.mjs +0 -11
@@ -0,0 +1,30 @@
1
+ import { GLOB_MARKDOWN_CODE } from '@antfu/eslint-config';
2
+ import type { TypedFlatConfigItem } from '@antfu/eslint-config';
3
+
4
+ import { AUTHOR_NAME_LOWER } from '../prefixes';
5
+
6
+ export async function markdown(): Promise<TypedFlatConfigItem[]> {
7
+ return [
8
+ {
9
+ name: `${AUTHOR_NAME_LOWER}:markdown`,
10
+ files: [GLOB_MARKDOWN_CODE],
11
+ rules: {
12
+ 'import/no-unresolved': 'off',
13
+ 'unused-imports/no-unused-imports': 'off',
14
+ 'unused-imports/no-unused-vars': 'off',
15
+ 'no-alert': 'off',
16
+ 'no-console': 'off',
17
+ 'no-restricted-imports': 'off',
18
+ 'no-undef': 'off',
19
+ 'no-unused-expressions': 'off',
20
+ 'no-unused-vars': 'off',
21
+ 'antfu/no-cjs-exports': 'off',
22
+ 'antfu/no-ts-export-equal': 'off',
23
+ 'ts/no-redeclare': 'off',
24
+ 'ts/no-unused-vars': 'off',
25
+ 'ts/no-var-requires': 'off',
26
+ 'ts/consistent-type-imports': 'off',
27
+ },
28
+ },
29
+ ];
30
+ }
@@ -0,0 +1,40 @@
1
+ import type { TypedFlatConfigItem } from '@antfu/eslint-config';
2
+ import { interopDefault } from '@antfu/eslint-config';
3
+
4
+ import { AUTHOR_NAME_LOWER } from '../prefixes';
5
+
6
+ export async function next(): Promise<TypedFlatConfigItem[]> {
7
+ // @ts-expect-error un typed
8
+ const next = await interopDefault(import('@next/eslint-plugin-next'));
9
+
10
+ return [
11
+ {
12
+ name: `${AUTHOR_NAME_LOWER}:next`,
13
+ plugins: { '@next/next': next },
14
+ rules: {
15
+ '@next/next/google-font-display': 'warn',
16
+ '@next/next/google-font-preconnect': 'warn',
17
+ '@next/next/next-script-for-ga': 'warn',
18
+ '@next/next/no-async-client-component': 'warn',
19
+ '@next/next/no-before-interactive-script-outside-document': 'warn',
20
+ '@next/next/no-css-tags': 'warn',
21
+ '@next/next/no-head-element': 'warn',
22
+ '@next/next/no-html-link-for-pages': 'warn',
23
+ '@next/next/no-img-element': 'warn',
24
+ '@next/next/no-page-custom-font': 'warn',
25
+ '@next/next/no-styled-jsx-in-document': 'warn',
26
+ '@next/next/no-sync-scripts': 'warn',
27
+ '@next/next/no-title-in-document-head': 'warn',
28
+ '@next/next/no-typos': 'warn',
29
+ '@next/next/no-unwanted-polyfillio': 'warn',
30
+ // errors
31
+ '@next/next/inline-script-id': 'error',
32
+ '@next/next/no-assign-module-variable': 'error',
33
+ '@next/next/no-document-import-in-page': 'error',
34
+ '@next/next/no-duplicate-head': 'error',
35
+ '@next/next/no-head-import-in-document': 'error',
36
+ '@next/next/no-script-component-in-head': 'error',
37
+ },
38
+ },
39
+ ];
40
+ }
@@ -0,0 +1,67 @@
1
+ import type { TypedFlatConfigItem } from '@antfu/eslint-config';
2
+ import globals from 'globals';
3
+
4
+ import { AUTHOR_NAME_LOWER } from '../prefixes';
5
+
6
+ export async function old(): Promise<TypedFlatConfigItem[]> {
7
+ return [
8
+ {
9
+ name: `${AUTHOR_NAME_LOWER}:old_config`,
10
+ languageOptions: {
11
+ globals: {
12
+ ...globals.browser,
13
+ ...globals.jquery,
14
+ ...globals.node,
15
+
16
+ // Rewrite globals anyway
17
+ document: 'readonly',
18
+ navigator: 'readonly',
19
+ window: 'readonly',
20
+ },
21
+ },
22
+
23
+ // Ignore patterns
24
+ ignores: [
25
+ '**/.next/*',
26
+ '**/node_modules/*',
27
+ '**/.github/*',
28
+ 'cypress',
29
+ '**/__tests__/e2e/*',
30
+ '*.json',
31
+ '**/*.d.ts',
32
+ '.eslintrc.js',
33
+ 'eslint.config.js',
34
+ '.prettierrc',
35
+ '.stylelintrc.js',
36
+ 'tsconfig.json',
37
+ 'package.json',
38
+ '*.md',
39
+ '*.config.ts',
40
+ '*.config.js',
41
+ '*.md',
42
+ ],
43
+ },
44
+ {
45
+ name: `${AUTHOR_NAME_LOWER}:rules_breakup_1`,
46
+ rules: { '@next/next/no-duplicate-head': 'off' },
47
+ },
48
+ {
49
+ name: `${AUTHOR_NAME_LOWER}:rules_breakup_2`,
50
+ rules: {
51
+ 'style/operator-linebreak': 'off',
52
+ 'test/consistent-test-it': 'off',
53
+ 'test/prefer-lowercase-title': 'off',
54
+ 'style/jsx-quotes': 'off',
55
+ 'style/multiline-ternary': 'off',
56
+ 'style/indent': 'off',
57
+ },
58
+ ignores: ['cypress'],
59
+ },
60
+ {
61
+ name: `${AUTHOR_NAME_LOWER}:prettier`,
62
+ rules: {
63
+ 'antfu/if-newline': 'off',
64
+ },
65
+ },
66
+ ];
67
+ }
@@ -0,0 +1,6 @@
1
+ import type { TypedFlatConfigItem } from '@antfu/eslint-config';
2
+ import recommended from 'eslint-plugin-prettier/recommended';
3
+
4
+ export async function prettier(): Promise<TypedFlatConfigItem[]> {
5
+ return [recommended];
6
+ }
@@ -0,0 +1,18 @@
1
+ import type { TypedFlatConfigItem } from '@antfu/eslint-config';
2
+ import { GLOB_JSX, GLOB_TSX } from '@antfu/eslint-config';
3
+
4
+ import { AUTHOR_NAME_LOWER } from '../prefixes';
5
+
6
+ export async function react(): Promise<TypedFlatConfigItem[]> {
7
+ return [
8
+ {
9
+ files: [GLOB_JSX, GLOB_TSX],
10
+ name: `${AUTHOR_NAME_LOWER}:react`,
11
+ rules: {
12
+ 'react-refresh/only-export-components': 'off',
13
+ 'react/no-clone-element': 'off',
14
+ 'react/no-missing-component-display-name': 'off',
15
+ },
16
+ },
17
+ ];
18
+ }
@@ -0,0 +1,7 @@
1
+ import type { Options } from './config';
2
+ import xenopomp from './config';
3
+
4
+ export type { Options };
5
+ export * from './types';
6
+
7
+ export default xenopomp;
@@ -0,0 +1,2 @@
1
+ export const AUTHOR_NAME = 'XenoPOMP';
2
+ export const AUTHOR_NAME_LOWER = AUTHOR_NAME.toLowerCase();
@@ -0,0 +1 @@
1
+ export * from './author';
@@ -0,0 +1,4 @@
1
+ import type { antfu } from '@antfu/eslint-config';
2
+
3
+ export type UserConfigItem = Parameters<typeof antfu>[1];
4
+ export type Configs = ReturnType<typeof antfu>;
@@ -0,0 +1,4 @@
1
+ export interface CustomConfig {
2
+ all?: boolean;
3
+ next?: boolean;
4
+ }
@@ -0,0 +1,2 @@
1
+ export * from './custom-config';
2
+ export * from './configs';
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './utils';
3
+ export * from './react';
@@ -0,0 +1,11 @@
1
+ export interface MetrikaProps {
2
+ /**
3
+ * ID of your Yandex.Metrika`s counter.
4
+ * Locate at dashboard.
5
+ */
6
+ id: number;
7
+
8
+ clickMap?: boolean;
9
+ trackLinks?: boolean;
10
+ accurateTrackBounce?: boolean;
11
+ }
@@ -0,0 +1,56 @@
1
+ import Script from 'next/script';
2
+ import type { FC } from 'react';
3
+
4
+ import type { MetrikaProps } from './Metrika.props';
5
+
6
+ /**
7
+ * This component allows you to use Yandex.Metrika
8
+ * in your Next.js projects.
9
+ *
10
+ * @since 0.0.1
11
+ *
12
+ * @example
13
+ * import { Metrika } from 'xenopomp-essentials/next';
14
+ *
15
+ * export default function RootLayout({
16
+ * children,
17
+ * }: {
18
+ * children: React.ReactNode
19
+ * }) {
20
+ * return (
21
+ * <html lang="en">
22
+ * <head>
23
+ * <Metrika id={123456789} />
24
+ * </head>
25
+ * <body>{children}</body>
26
+ * </html>
27
+ * )
28
+ * }
29
+ *
30
+ * @see https://metrika.yandex.ru
31
+ */
32
+ export const Metrika: FC<MetrikaProps> = ({
33
+ id,
34
+ clickMap = true,
35
+ trackLinks = true,
36
+ accurateTrackBounce = true,
37
+ }) => {
38
+ return (
39
+ <Script
40
+ id='metrika-counter'
41
+ strategy='afterInteractive'
42
+ >
43
+ {` (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
44
+ m[i].l=1*new Date();
45
+ for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
46
+ k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
47
+ (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
48
+
49
+ ym(${id}, "init", {
50
+ clickmap:${clickMap},
51
+ trackLinks:${trackLinks},
52
+ accurateTrackBounce:${accurateTrackBounce}
53
+ });`}
54
+ </Script>
55
+ );
56
+ };
@@ -0,0 +1,33 @@
1
+ import type { FC } from 'react';
2
+
3
+ /**
4
+ * Adds react-scan to your Next.js application.
5
+ * @constructor
6
+ * @since 0.0.1
7
+ *
8
+ * @example
9
+ * import { ReactScan } from 'xenopomp-essentials/next';
10
+ *
11
+ * export default function RootLayout({
12
+ * children,
13
+ * }: {
14
+ * children: React.ReactNode
15
+ * }) {
16
+ * return (
17
+ * <html lang="en">
18
+ * <head>
19
+ * <ReactScan />
20
+ * </head>
21
+ * <body>{children}</body>
22
+ * </html>
23
+ * )
24
+ *}
25
+ */
26
+ export const ReactScan: FC<unknown> = () => {
27
+ return (
28
+ <script
29
+ src='https://unpkg.com/react-scan/dist/auto.global.js'
30
+ async
31
+ />
32
+ );
33
+ };
@@ -0,0 +1,2 @@
1
+ export * from './ReactScan/ReactScan';
2
+ export * from './Metrika/Metrika';
@@ -0,0 +1 @@
1
+ export * from './jsxDotNotation';
@@ -0,0 +1,38 @@
1
+ import type { FC } from 'react';
2
+
3
+ import type { EmptyObject } from '@/types';
4
+
5
+ /**
6
+ * Creates properly type object with jsxDotNotation.
7
+ *
8
+ * @param comp
9
+ * @param rest
10
+ *
11
+ * @example
12
+ * const FlexComp: FC<PropsWithChildren> = ({ children }) => <div>{children}</div>;
13
+ * const FlexRow: FC<PropsWithChildren & { short?: boolean }> = ({ children }) => (
14
+ * <div>{children}</div>
15
+ * );
16
+ * const FlexCol: FC<PropsWithChildren> = ({ children }) => <div>{children}</div>;
17
+ *
18
+ * const Flex = jsxDotNotation(FlexComp, {
19
+ * Row: FlexRow,
20
+ * Col: FlexCol,
21
+ * });
22
+ *
23
+ * const Am = () => {
24
+ * return (
25
+ * <Flex>
26
+ * <Flex.Row short>
27
+ * <Flex.Col></Flex.Col>
28
+ * </Flex.Row>
29
+ * </Flex>
30
+ * );
31
+ * };
32
+ */
33
+ export function jsxDotNotation<
34
+ Props = EmptyObject,
35
+ Rest extends Record<string, FC<any>> = EmptyObject,
36
+ >(comp: FC<Props>, rest: Rest) {
37
+ return Object.assign(comp, rest);
38
+ }
@@ -0,0 +1 @@
1
+ export * from './hoc';
@@ -0,0 +1,49 @@
1
+ import type { TSESTree } from '@typescript-eslint/utils';
2
+ import { ESLintUtils } from '@typescript-eslint/utils';
3
+
4
+ const createRule = ESLintUtils.RuleCreator(
5
+ () => 'https://github.com/XenoPOMP/xenopomp-essentials-js',
6
+ );
7
+
8
+ export const deepTypeNamingRule = createRule({
9
+ name: 'deep-types-naming',
10
+ defaultOptions: [],
11
+ meta: {
12
+ type: 'suggestion',
13
+ docs: {
14
+ description: 'Naming convention for deep types.',
15
+ },
16
+ messages: {
17
+ invalidName: 'Deep type name have to follow "TypeDeep" convention.',
18
+ },
19
+ schema: [],
20
+ },
21
+ create(context) {
22
+ function doesNotFollowConvention(name: string): boolean {
23
+ // Word Deep not detected. Stop visitor execution.
24
+ if (!/Deep/.test(name)) {
25
+ return false;
26
+ }
27
+
28
+ // Word "Deep" is presented inside type declaration name.
29
+ // Checking for convention.
30
+ return !/^\w+Deep/.test(name);
31
+ }
32
+
33
+ return {
34
+ 'TSInterfaceDeclaration, TSTypeAliasDeclaration': function (
35
+ node: TSESTree.TSInterfaceDeclaration | TSESTree.TSTypeAliasDeclaration,
36
+ ) {
37
+ const { id } = node;
38
+
39
+ if (doesNotFollowConvention(id.name)) {
40
+ // Report that problem is detected.
41
+ context.report({
42
+ messageId: 'invalidName',
43
+ node: node.id,
44
+ });
45
+ }
46
+ },
47
+ };
48
+ },
49
+ });
@@ -0,0 +1,9 @@
1
+ import { deepTypeNamingRule } from './deep-type-naming.rule';
2
+
3
+ const plugin = {
4
+ rules: {
5
+ 'deep-type-naming': deepTypeNamingRule,
6
+ },
7
+ };
8
+
9
+ export default plugin;
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+
3
+ const importMetaSchema = z.object({
4
+ dirname: z.string().optional(),
5
+ });
6
+
7
+ /**
8
+ * Validates import.meta object.
9
+ *
10
+ * @since 0.0.1
11
+ */
12
+ export const importMeta = importMetaSchema.parse(import.meta);
@@ -0,0 +1 @@
1
+ export * from './import-meta.schema';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Matches any object but not arrays, class instances etc.
3
+ * @since 0.0.1
4
+ */
5
+ export type AnyObject = Record<PropertyKey, unknown>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This type stands for empty object type.
3
+ *
4
+ * @since 0.0.1
5
+ * @example
6
+ * const message: EmptyObject = { type: string; }; // Will cause error.
7
+ */
8
+ export type EmptyObject = Record<PropertyKey, never>;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Simple alias for creating function types. You can use it for type guards
3
+ * as representation of any function, also you can create cleaner type declarations
4
+ * for functions.
5
+ *
6
+ * @since 0.0.1
7
+ * @example
8
+ * type MyFn = Fn<[a: string, b: string], string>;
9
+ */
10
+ export type Fn<Args extends any[] = any[], Res = unknown> = (
11
+ ...args: Args
12
+ ) => Res;
@@ -0,0 +1,3 @@
1
+ export * from './AnyObject';
2
+ export * from './EmptyObject';
3
+ export * from './Fn';
@@ -0,0 +1,4 @@
1
+ export * from './aliases';
2
+ export * from './next';
3
+ export * from './react';
4
+ export * from './utilities';
@@ -0,0 +1,26 @@
1
+ type ParamObj<P extends string> = Record<P, string>;
2
+
3
+ /**
4
+ * Represents Next.js routing params.
5
+ * @since 0.0.1
6
+ */
7
+ export interface NextParams<P extends string> {
8
+ params: ParamObj<P>;
9
+ }
10
+
11
+ /**
12
+ * Represents Next.js routing search params.
13
+ * @since 0.0.1
14
+ */
15
+ export interface NextSearchParams<P extends string> {
16
+ searchParams: ParamObj<P>;
17
+ }
18
+
19
+ /**
20
+ * This type describes Next error page params.
21
+ * @since 0.0.1
22
+ */
23
+ export interface NextErrorParams<E extends Error = any> {
24
+ error: E;
25
+ reset: () => void;
26
+ }
@@ -0,0 +1 @@
1
+ export * from './NextParams';
@@ -0,0 +1,6 @@
1
+ import type { FC } from 'react';
2
+
3
+ /**
4
+ * Matches any proper React component.
5
+ */
6
+ export type AnyFC = FC<unknown>;
@@ -0,0 +1,16 @@
1
+ import type { FC, ReactNode } from 'react';
2
+
3
+ import type { ReplaceReturnType } from '@/types';
4
+
5
+ /**
6
+ * Same as **FC** (or FunctionalComponent), but it returns Promise.
7
+ *
8
+ * @since 0.0.1
9
+ * @example
10
+ * const Header: AsyncFC<HeaderProps> = async ({}) => {
11
+ * // Do async stuff here...
12
+ *
13
+ * return <div></div>;
14
+ * };
15
+ */
16
+ export type AsyncFC<T = unknown> = ReplaceReturnType<FC<T>, Promise<ReactNode>>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Type that represents data-{attr} keys.
3
+ */
4
+ type Attribute = `data-${string}`;
5
+
6
+ /**
7
+ * Matches any proper data-{attr} keys.
8
+ */
9
+ type DataAttributeShape = Record<Attribute, any>;
10
+
11
+ /**
12
+ * Represents React`s data-{attr} properties for components.
13
+ *
14
+ * @example
15
+ * type AdditionalAttributes = DataAttributes<{ 'data-disabled': boolean }>;
16
+ *
17
+ * const attrs: AdditionalAttributes = {
18
+ * 'data-disabled': false, // this attr is required
19
+ * };
20
+ */
21
+ export type DataAttributes<Shape extends DataAttributeShape> = Shape;
@@ -0,0 +1,19 @@
1
+ import type { FC } from 'react';
2
+
3
+ /**
4
+ * @deprecated use {@link FCProps} instead.
5
+ */
6
+ export type FcProps<Comp> = FCProps<Comp>;
7
+
8
+ /**
9
+ * Extracts type of props from FC type.
10
+ *
11
+ * @since 0.0.1
12
+ * @example
13
+ * type Props = FcProps<FC<{ align?: boolean }>>;
14
+ * // ^? { align?: boolean }
15
+ *
16
+ * type VariableProps = FcProps<VariableFC<'button', { notAlign?: boolean }>>;
17
+ * // ^? {notAlign?: boolean} & Omit<ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement>, undefined>
18
+ */
19
+ export type FCProps<Comp> = Comp extends FC<infer Props> ? Props : never;
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ /**
4
+ * This type allows you to make children that can be function.
5
+ *
6
+ * @since 0.0.1
7
+ * @example
8
+ * type Child = FunctionalChildren<[options: string]>;
9
+ * // ReactNode | ((options: string) => ReactNode)
10
+ */
11
+ export type FunctionalChildren<Args extends any[]> =
12
+ | ReactNode
13
+ | ((...args: Args) => ReactNode);
@@ -0,0 +1,11 @@
1
+ import type { Dispatch, SetStateAction } from 'react';
2
+
3
+ /**
4
+ * Type of set state function from useState.
5
+ *
6
+ * @since 0.0.1
7
+ * @example
8
+ * // typeof setState => SetState<string>
9
+ * const [state, setState] = useState<string>('example');
10
+ */
11
+ export type SetState<TType> = Dispatch<SetStateAction<TType>>;
@@ -0,0 +1,48 @@
1
+ import type { ComponentProps, ElementType, FC } from 'react';
2
+
3
+ import type { AsyncFC, WeakOmit } from '@/types';
4
+
5
+ /**
6
+ * This type wraps ComponentProps<A> to your FC.
7
+ *
8
+ * - __A__ - element type
9
+ * - __P__ - wrapping props
10
+ * - __Ex__ - excluded component props (for example, if you do not want to include 'children' prop in component)
11
+ *
12
+ * @since 0.0.1
13
+ *
14
+ * @example
15
+ * type VariableComponentPropsWithChildren = ComponentProps<VariableFC<'div'>>;
16
+ * type VariableComponentPropsWithoutChildren = ComponentProps<VariableFC<'div', {}, 'children'>>;
17
+ *
18
+ * @example
19
+ * // With children
20
+ * const VariableComponent: VariableFC<'section', { variant?: 'default' }> = ({ variant, ...props }) => {
21
+ * return <section {...props}></section>
22
+ * }
23
+ *
24
+ * @example
25
+ * // Without children
26
+ * const VariableComponent: VariableFC<'section', { variant?: 'default' }, 'children'> = ({ variant, ...props }) => {
27
+ * return (
28
+ * <section {...props}>
29
+ * <div>Insert your own children</div>
30
+ * </section>
31
+ * );
32
+ * }
33
+ */
34
+ export type VariableFC<
35
+ A extends ElementType,
36
+ P = unknown,
37
+ Ex extends keyof ComponentProps<A> | undefined = undefined,
38
+ > = FC<P & WeakOmit<ComponentProps<A>, Ex>>;
39
+
40
+ /**
41
+ * Works similar to {@link VariableFC}, but return type is Promise<ReactNode>;
42
+ * @since 0.0.1
43
+ */
44
+ export type AsyncVariableFC<
45
+ A extends ElementType,
46
+ P = unknown,
47
+ Ex extends keyof ComponentProps<A> | undefined = undefined,
48
+ > = AsyncFC<P & WeakOmit<ComponentProps<A>, Ex>>;
@@ -0,0 +1,9 @@
1
+ import type { ComponentProps, ElementType } from 'react';
2
+
3
+ import type { FCProps, VariableFC } from '@/types';
4
+
5
+ export type VariableProps<
6
+ A extends ElementType,
7
+ P = unknown,
8
+ Ex extends keyof ComponentProps<A> | undefined = undefined,
9
+ > = FCProps<VariableFC<A, P, Ex>>;