@kirill.konshin/next 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/.ctirc ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "addNewline": true,
3
+ "fileExcludePatterns": [
4
+ "*.stories.*",
5
+ "*.test.*",
6
+ "*.fixture.*"
7
+ ],
8
+ "verbose": false,
9
+ "withoutBackupFile": true,
10
+ "withoutComment": true
11
+ }
@@ -0,0 +1,16 @@
1
+ vite v7.0.6 building SSR bundle for production...
2
+ create succeeded: /home/runner/work/utils/utils/packages/next/src
3
+ transforming...
4
+ ✓ 6 modules transformed.
5
+ rendering chunks...
6
+
7
+ [vite:dts] Start generate declaration files...
8
+ dist/noSSR.js 0.33 kB │ map: 1.38 kB
9
+ dist/index.js 0.34 kB │ map: 0.10 kB
10
+ dist/useIsInner.js 0.37 kB │ map: 0.61 kB
11
+ dist/measure.js 0.38 kB │ map: 1.04 kB
12
+ dist/appLink.js 0.77 kB │ map: 1.58 kB
13
+ [vite:dts] Declaration files built in 1575ms.
14
+
15
+ ✓ built in 2.28s
16
+ Updated package.json with exports
@@ -0,0 +1,8 @@
1
+ import { ComponentProps, FC } from 'react';
2
+ import { default as Link, LinkProps } from 'next/link';
3
+ export declare const AppLink: FC<{
4
+ children: any;
5
+ exact?: boolean;
6
+ activeClassName?: any;
7
+ } & LinkProps & ComponentProps<typeof Link>>;
8
+ //# sourceMappingURL=appLink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appLink.d.ts","sourceRoot":"","sources":["../src/appLink.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,IAAI,EAAE,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAI5C,eAAO,MAAM,OAAO,EAAE,EAAE,CACpB;IACI,QAAQ,EAAE,GAAG,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,eAAe,CAAC,EAAE,GAAG,CAAC;CACzB,GAAG,SAAS,GACT,cAAc,CAAC,OAAO,IAAI,CAAC,CAyBlC,CAAC"}
@@ -0,0 +1,34 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { usePathname } from "next/navigation";
4
+ import Link from "next/link";
5
+ import clsx from "clsx";
6
+ const AppLink = function AppLink2({
7
+ href,
8
+ children,
9
+ className = "",
10
+ activeClassName = "",
11
+ prefetch = false,
12
+ // set explicit default
13
+ exact = false,
14
+ ...props
15
+ }) {
16
+ const pathname = usePathname();
17
+ const hrefPath = typeof href === "string" ? href : href.pathname || "/";
18
+ return /* @__PURE__ */ jsx(
19
+ Link,
20
+ {
21
+ ...props,
22
+ href,
23
+ className: clsx(className, {
24
+ [activeClassName]: !exact && pathname.startsWith(hrefPath) || exact && pathname === hrefPath
25
+ }),
26
+ prefetch,
27
+ children
28
+ }
29
+ );
30
+ };
31
+ export {
32
+ AppLink
33
+ };
34
+ //# sourceMappingURL=appLink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appLink.js","sources":["../src/appLink.tsx"],"sourcesContent":["'use client';\n\nimport React, { ComponentProps, FC } from 'react';\nimport { usePathname } from 'next/navigation';\nimport Link, { LinkProps } from 'next/link';\nimport clsx from 'clsx';\n\n//TODO Test this\nexport const AppLink: FC<\n {\n children: any;\n exact?: boolean;\n activeClassName?: any;\n } & LinkProps &\n ComponentProps<typeof Link>\n> = function AppLink({\n href,\n children,\n className = '',\n activeClassName = '',\n prefetch = false, // set explicit default\n exact = false,\n ...props\n}) {\n const pathname = usePathname();\n const hrefPath = typeof href === 'string' ? href : href.pathname || '/';\n\n return (\n <Link\n {...props}\n href={href}\n className={clsx(className, {\n [activeClassName]: (!exact && pathname.startsWith(hrefPath)) || (exact && pathname === hrefPath),\n })}\n prefetch={prefetch}\n >\n {children}\n </Link>\n );\n};\n"],"names":["AppLink"],"mappings":";;;;;AAQO,MAAM,UAOT,SAASA,SAAQ;AAAA,EACjB;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,WAAW;AAAA;AAAA,EACX,QAAQ;AAAA,EACR,GAAG;AACP,GAAG;AACC,QAAM,WAAW,YAAA;AACjB,QAAM,WAAW,OAAO,SAAS,WAAW,OAAO,KAAK,YAAY;AAEpE,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MACJ;AAAA,MACA,WAAW,KAAK,WAAW;AAAA,QACvB,CAAC,eAAe,GAAI,CAAC,SAAS,SAAS,WAAW,QAAQ,KAAO,SAAS,aAAa;AAAA,MAAA,CAC1F;AAAA,MACD;AAAA,MAEC;AAAA,IAAA;AAAA,EAAA;AAGb;"}
@@ -0,0 +1,6 @@
1
+ export * from './appLink';
2
+ export * from './measure';
3
+ export * from './noSSR';
4
+ export * from './redirect';
5
+ export * from './useIsInner';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ import { AppLink } from "./appLink.js";
2
+ import { isProd, measurer } from "./measure.js";
3
+ import { NoSSR } from "./noSSR.js";
4
+ import "next/navigation";
5
+ import "react";
6
+ import { useIsIndex, useIsInner } from "./useIsInner.js";
7
+ export {
8
+ AppLink,
9
+ NoSSR,
10
+ isProd,
11
+ measurer,
12
+ useIsIndex,
13
+ useIsInner
14
+ };
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,15 @@
1
+ export declare const isProd: boolean;
2
+ export declare const measurer: {
3
+ measure: (what: string, step: string, supplemental?: string, ...args: any[]) => {
4
+ done: (result?: string, ...args2: any[]) => void;
5
+ fail: (result?: string, ...args2: any[]) => void;
6
+ log: (...args2: any[]) => void;
7
+ };
8
+ important: (str: any) => any;
9
+ subject: (str: any) => any;
10
+ arg: (str: any) => any;
11
+ sup: (str: any) => any;
12
+ ok: (str: any) => any;
13
+ err: (str: any) => any;
14
+ };
15
+ //# sourceMappingURL=measure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../src/measure.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM,EAAE,OACsF,CAAC;AAE5G,eAAO,MAAM,QAAQ,EAAE;IACnB,OAAO,EAAE,CACL,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,MAAM,EACrB,GAAG,IAAI,EAAE,GAAG,EAAE,KACb;QACD,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;QACjD,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;QACjD,GAAG,EAAE,CAAC,GAAG,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;KAClC,CAAC;IACF,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC;IAC7B,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC;IAC3B,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC;IACvB,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC;IACvB,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC;IACtB,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC;CACW,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { createMeasurer } from "@kirill.konshin/core";
2
+ import { PHASE_PRODUCTION_BUILD, PHASE_PRODUCTION_SERVER } from "next/constants";
3
+ const isProd = process.env.NEXT_PHASE === PHASE_PRODUCTION_BUILD || process.env.NEXT_PHASE === PHASE_PRODUCTION_SERVER;
4
+ const measurer = createMeasurer({ colors: isProd });
5
+ export {
6
+ isProd,
7
+ measurer
8
+ };
9
+ //# sourceMappingURL=measure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure.js","sources":["../src/measure.ts"],"sourcesContent":["import { createMeasurer } from '@kirill.konshin/core';\nimport { PHASE_PRODUCTION_BUILD, PHASE_PRODUCTION_SERVER } from 'next/constants';\n\nexport const isProd: boolean =\n process.env.NEXT_PHASE === PHASE_PRODUCTION_BUILD || process.env.NEXT_PHASE === PHASE_PRODUCTION_SERVER;\n\nexport const measurer: {\n measure: (\n what: string,\n step: string,\n supplemental?: string,\n ...args: any[]\n ) => {\n done: (result?: string, ...args2: any[]) => void;\n fail: (result?: string, ...args2: any[]) => void;\n log: (...args2: any[]) => void;\n };\n important: (str: any) => any;\n subject: (str: any) => any;\n arg: (str: any) => any;\n sup: (str: any) => any;\n ok: (str: any) => any;\n err: (str: any) => any;\n} = createMeasurer({ colors: isProd });\n"],"names":[],"mappings":";;AAGO,MAAM,SACT,QAAQ,IAAI,eAAe,0BAA0B,QAAQ,IAAI,eAAe;AAE7E,MAAM,WAiBT,eAAe,EAAE,QAAQ,QAAQ;"}
@@ -0,0 +1,29 @@
1
+ import { FC, JSX } from 'react';
2
+ /**
3
+ * Prefer using Next.js `dynamic()` import with `ssr: false` because this will also remove import from server bundle.
4
+ *
5
+ * ```tsx
6
+ * 'use client';
7
+ *
8
+ * import React from 'react';
9
+ * import dynamic from 'next/dynamic';
10
+ *
11
+ * const PageClient = dynamic(() => import('./pageClient'), { ssr: false });
12
+ *
13
+ * export default function Page() {
14
+ * return (
15
+ * <PageClient />
16
+ * );
17
+ * }
18
+ * ```
19
+ *
20
+ * In other cases this component can be used to just prevent server rendering.
21
+ *
22
+ * @see https://github.com/kadirahq/react-no-ssr/blob/master/src/index.js
23
+ * @see https://nextjs.org/docs/messages/react-hydration-error#solution-1-using-useeffect-to-run-on-the-client-only
24
+ */
25
+ export declare const NoSSR: FC<{
26
+ children: any;
27
+ onSSR?: JSX.Element;
28
+ }>;
29
+ //# sourceMappingURL=noSSR.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noSSR.d.ts","sourceRoot":"","sources":["../src/noSSR.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAE,EAAE,EAAE,GAAG,EAA6B,MAAM,OAAO,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC;IAAE,QAAQ,EAAE,GAAG,CAAC;IAAC,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;CAAE,CAQ5D,CAAC"}
package/dist/noSSR.js ADDED
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { useState, useLayoutEffect } from "react";
3
+ const NoSSR = function NoSSR2({ children, onSSR = null }) {
4
+ const [canRender, setCanRender] = useState(false);
5
+ useLayoutEffect(() => {
6
+ setCanRender(true);
7
+ }, []);
8
+ return canRender ? children : onSSR;
9
+ };
10
+ export {
11
+ NoSSR
12
+ };
13
+ //# sourceMappingURL=noSSR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noSSR.js","sources":["../src/noSSR.tsx"],"sourcesContent":["'use client';\n\nimport React, { FC, JSX, useLayoutEffect, useState } from 'react';\n\n/**\n * Prefer using Next.js `dynamic()` import with `ssr: false` because this will also remove import from server bundle.\n *\n * ```tsx\n * 'use client';\n *\n * import React from 'react';\n * import dynamic from 'next/dynamic';\n *\n * const PageClient = dynamic(() => import('./pageClient'), { ssr: false });\n *\n * export default function Page() {\n * return (\n * <PageClient />\n * );\n * }\n * ```\n *\n * In other cases this component can be used to just prevent server rendering.\n *\n * @see https://github.com/kadirahq/react-no-ssr/blob/master/src/index.js\n * @see https://nextjs.org/docs/messages/react-hydration-error#solution-1-using-useeffect-to-run-on-the-client-only\n */\nexport const NoSSR: FC<{ children: any; onSSR?: JSX.Element }> = function NoSSR({ children, onSSR = null }): any {\n const [canRender, setCanRender] = useState(false);\n\n useLayoutEffect(() => {\n setCanRender(true);\n }, []);\n\n return canRender ? children : onSSR;\n};\n"],"names":["NoSSR"],"mappings":";;AA2BO,MAAM,QAAoD,SAASA,OAAM,EAAE,UAAU,QAAQ,QAAa;AAC7G,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,kBAAgB,MAAM;AAClB,iBAAa,IAAI;AAAA,EACrB,GAAG,CAAA,CAAE;AAEL,SAAO,YAAY,WAAW;AAClC;"}
@@ -0,0 +1,6 @@
1
+ import { LinkProps } from 'next/link';
2
+ export default function Redirect({ to, replace }: {
3
+ to: LinkProps['href'];
4
+ replace?: LinkProps['replace'];
5
+ }): null;
6
+ //# sourceMappingURL=redirect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../src/redirect.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;IAAE,EAAE,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;CAAE,QAM1G"}
@@ -0,0 +1,3 @@
1
+ export declare const useIsInner: () => boolean;
2
+ export declare const useIsIndex: () => boolean;
3
+ //# sourceMappingURL=useIsInner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIsInner.d.ts","sourceRoot":"","sources":["../src/useIsInner.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,QAAO,OAG7B,CAAC;AAEF,eAAO,MAAM,UAAU,QAAO,OAG7B,CAAC"}
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { useSelectedLayoutSegments } from "next/navigation";
3
+ const useIsInner = () => {
4
+ const pathname = useSelectedLayoutSegments();
5
+ return pathname.length > 0;
6
+ };
7
+ const useIsIndex = () => {
8
+ const pathname = useSelectedLayoutSegments();
9
+ return pathname.length === 0;
10
+ };
11
+ export {
12
+ useIsIndex,
13
+ useIsInner
14
+ };
15
+ //# sourceMappingURL=useIsInner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIsInner.js","sources":["../src/useIsInner.ts"],"sourcesContent":["'use client';\n\nimport { useSelectedLayoutSegments } from 'next/navigation';\n\nexport const useIsInner = (): boolean => {\n const pathname = useSelectedLayoutSegments();\n return pathname.length > 0;\n};\n\nexport const useIsIndex = (): boolean => {\n const pathname = useSelectedLayoutSegments();\n return pathname.length === 0;\n};\n"],"names":[],"mappings":";;AAIO,MAAM,aAAa,MAAe;AACrC,QAAM,WAAW,0BAAA;AACjB,SAAO,SAAS,SAAS;AAC7B;AAEO,MAAM,aAAa,MAAe;AACrC,QAAM,WAAW,0BAAA;AACjB,SAAO,SAAS,WAAW;AAC/B;"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@kirill.konshin/next",
3
+ "description": "Utilities",
4
+ "version": "0.0.1",
5
+ "type": "module",
6
+ "scripts": {
7
+ "----- BUILD -----": "",
8
+ "clean": "rm -rf dist .tscache tsconfig.tsbuildinfo",
9
+ "build": "vite build",
10
+ "build:index": "cti create ./src",
11
+ "build:check-types": "attw --pack .",
12
+ "start": "yarn build --watch",
13
+ "wait": "wait-on ./dist/index.js",
14
+ "----- TEST -----": "",
15
+ "test:disabled": "vitest run --coverage",
16
+ "test:watch": "vitest watch --coverage",
17
+ "----- STORYBOOK -----": "",
18
+ "storybook:start": "storybook dev -p 6006",
19
+ "storybook:build": "storybook build"
20
+ },
21
+ "dependencies": {
22
+ "@kirill.konshin/core": "*",
23
+ "clsx": "^2.1.1",
24
+ "colors": "^1.4.0",
25
+ "file-saver": "^2.0.5",
26
+ "many-keys-map": "^3.0.3",
27
+ "psd": "^3.4.0",
28
+ "sharp": "^0.34.3"
29
+ },
30
+ "devDependencies": {
31
+ "@kirill.konshin/utils-private": "*",
32
+ "next": "^15.4.5",
33
+ "react": "^19.1.1"
34
+ },
35
+ "peerDependencies": {
36
+ "next": "^15",
37
+ "react": "^19"
38
+ },
39
+ "peerDependenciesMeta": {
40
+ "next": {
41
+ "optional": true
42
+ },
43
+ "react": {
44
+ "optional": true
45
+ }
46
+ },
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "author": "Kirill Konshin <kirill@konshin.org> (https://konshin.org)",
51
+ "license": "MIT",
52
+ "exports": {
53
+ ".": {
54
+ "import": {
55
+ "import": "./dist/index.js",
56
+ "types": "./dist/index.d.ts"
57
+ }
58
+ }
59
+ },
60
+ "main": "./dist/index.js",
61
+ "module": "./dist/index.js",
62
+ "types": "./dist/index.d.ts"
63
+ }
@@ -0,0 +1,40 @@
1
+ 'use client';
2
+
3
+ import React, { ComponentProps, FC } from 'react';
4
+ import { usePathname } from 'next/navigation';
5
+ import Link, { LinkProps } from 'next/link';
6
+ import clsx from 'clsx';
7
+
8
+ //TODO Test this
9
+ export const AppLink: FC<
10
+ {
11
+ children: any;
12
+ exact?: boolean;
13
+ activeClassName?: any;
14
+ } & LinkProps &
15
+ ComponentProps<typeof Link>
16
+ > = function AppLink({
17
+ href,
18
+ children,
19
+ className = '',
20
+ activeClassName = '',
21
+ prefetch = false, // set explicit default
22
+ exact = false,
23
+ ...props
24
+ }) {
25
+ const pathname = usePathname();
26
+ const hrefPath = typeof href === 'string' ? href : href.pathname || '/';
27
+
28
+ return (
29
+ <Link
30
+ {...props}
31
+ href={href}
32
+ className={clsx(className, {
33
+ [activeClassName]: (!exact && pathname.startsWith(hrefPath)) || (exact && pathname === hrefPath),
34
+ })}
35
+ prefetch={prefetch}
36
+ >
37
+ {children}
38
+ </Link>
39
+ );
40
+ };
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from './appLink';
2
+ export * from './measure';
3
+ export * from './noSSR';
4
+ export * from './redirect';
5
+ export * from './useIsInner';
package/src/measure.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { createMeasurer } from '@kirill.konshin/core';
2
+ import { PHASE_PRODUCTION_BUILD, PHASE_PRODUCTION_SERVER } from 'next/constants';
3
+
4
+ export const isProd: boolean =
5
+ process.env.NEXT_PHASE === PHASE_PRODUCTION_BUILD || process.env.NEXT_PHASE === PHASE_PRODUCTION_SERVER;
6
+
7
+ export const measurer: {
8
+ measure: (
9
+ what: string,
10
+ step: string,
11
+ supplemental?: string,
12
+ ...args: any[]
13
+ ) => {
14
+ done: (result?: string, ...args2: any[]) => void;
15
+ fail: (result?: string, ...args2: any[]) => void;
16
+ log: (...args2: any[]) => void;
17
+ };
18
+ important: (str: any) => any;
19
+ subject: (str: any) => any;
20
+ arg: (str: any) => any;
21
+ sup: (str: any) => any;
22
+ ok: (str: any) => any;
23
+ err: (str: any) => any;
24
+ } = createMeasurer({ colors: isProd });
package/src/noSSR.tsx ADDED
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+
3
+ import React, { FC, JSX, useLayoutEffect, useState } from 'react';
4
+
5
+ /**
6
+ * Prefer using Next.js `dynamic()` import with `ssr: false` because this will also remove import from server bundle.
7
+ *
8
+ * ```tsx
9
+ * 'use client';
10
+ *
11
+ * import React from 'react';
12
+ * import dynamic from 'next/dynamic';
13
+ *
14
+ * const PageClient = dynamic(() => import('./pageClient'), { ssr: false });
15
+ *
16
+ * export default function Page() {
17
+ * return (
18
+ * <PageClient />
19
+ * );
20
+ * }
21
+ * ```
22
+ *
23
+ * In other cases this component can be used to just prevent server rendering.
24
+ *
25
+ * @see https://github.com/kadirahq/react-no-ssr/blob/master/src/index.js
26
+ * @see https://nextjs.org/docs/messages/react-hydration-error#solution-1-using-useeffect-to-run-on-the-client-only
27
+ */
28
+ export const NoSSR: FC<{ children: any; onSSR?: JSX.Element }> = function NoSSR({ children, onSSR = null }): any {
29
+ const [canRender, setCanRender] = useState(false);
30
+
31
+ useLayoutEffect(() => {
32
+ setCanRender(true);
33
+ }, []);
34
+
35
+ return canRender ? children : onSSR;
36
+ };
@@ -0,0 +1,13 @@
1
+ 'use client';
2
+
3
+ import { useRouter } from 'next/navigation';
4
+ import { useEffect } from 'react';
5
+ import type { LinkProps } from 'next/link';
6
+
7
+ export default function Redirect({ to, replace }: { to: LinkProps['href']; replace?: LinkProps['replace'] }) {
8
+ const router = useRouter();
9
+ useEffect(() => {
10
+ router[replace ? 'replace' : 'push'](to.toString()); //TODO Test this
11
+ }, [replace, router, to]);
12
+ return null;
13
+ }
@@ -0,0 +1,13 @@
1
+ 'use client';
2
+
3
+ import { useSelectedLayoutSegments } from 'next/navigation';
4
+
5
+ export const useIsInner = (): boolean => {
6
+ const pathname = useSelectedLayoutSegments();
7
+ return pathname.length > 0;
8
+ };
9
+
10
+ export const useIsIndex = (): boolean => {
11
+ const pathname = useSelectedLayoutSegments();
12
+ return pathname.length === 0;
13
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../utils-private/tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist",
6
+ "declarationDir": "dist"
7
+ },
8
+ "include": ["src"],
9
+ "exclude": []
10
+ }
package/turbo.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://turbo.build/schema.json",
3
+ "extends": ["//"],
4
+ "tasks": {
5
+ "build": {
6
+ "dependsOn": ["^build"],
7
+ "outputs": ["src/**/*/index.ts", "package.json", "dist/**/*"]
8
+ }
9
+ }
10
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,2 @@
1
+ import config from '../utils-private/vite.config';
2
+ export default config;