mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 14:42:17 +00:00
tsconfig, core
This commit is contained in:
@@ -6,5 +6,5 @@
|
||||
"linked": [],
|
||||
"access": "public",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": ["@zitadel/docs"]
|
||||
"ignore": ["@zitadel/login"]
|
||||
}
|
||||
|
||||
72
.github/workflows/release.yml
vendored
72
.github/workflows/release.yml
vendored
@@ -1,44 +1,44 @@
|
||||
name: Release
|
||||
# name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
# on:
|
||||
# push:
|
||||
# branches:
|
||||
# - main
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
# concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v2
|
||||
# jobs:
|
||||
# release:
|
||||
# name: Release
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Checkout Repo
|
||||
# uses: actions/checkout@v2
|
||||
|
||||
- name: Setup pnpm 7
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
# - name: Setup pnpm 7
|
||||
# uses: pnpm/action-setup@v2
|
||||
# with:
|
||||
# version: 7
|
||||
|
||||
- name: Setup Node.js 16.x
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.x
|
||||
# - name: Setup Node.js 16.x
|
||||
# uses: actions/setup-node@v2
|
||||
# with:
|
||||
# node-version: 16.x
|
||||
|
||||
- name: Install Dependencies
|
||||
run: pnpm i
|
||||
# - name: Install Dependencies
|
||||
# run: pnpm i
|
||||
|
||||
- name: Create Release Pull Request or Publish to npm
|
||||
id: changesets
|
||||
uses: changesets/action@v1
|
||||
with:
|
||||
# This expects you to have a script called release which does a build for your packages and calls changeset publish
|
||||
publish: pnpm release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
# - name: Create Release Pull Request or Publish to npm
|
||||
# id: changesets
|
||||
# uses: changesets/action@v1
|
||||
# with:
|
||||
# # This expects you to have a script called release which does a build for your packages and calls changeset publish
|
||||
# publish: pnpm release
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Send a Slack notification if a publish happens
|
||||
if: steps.changesets.outputs.published == 'true'
|
||||
# You can do something when a publish happens.
|
||||
run: my-slack-bot send-notification --message "A new version of ${GITHUB_REPOSITORY} was published!"
|
||||
# - name: Send a Slack notification if a publish happens
|
||||
# if: steps.changesets.outputs.published == 'true'
|
||||
# # You can do something when a publish happens.
|
||||
# run: my-slack-bot send-notification --message "A new version of ${GITHUB_REPOSITORY} was published!"
|
||||
|
||||
34
README.md
34
README.md
@@ -1,6 +1,6 @@
|
||||
# ZITADEL typescript with Changesets
|
||||
# ZITADEL typescript with Turborepo and Changesets
|
||||
|
||||
This is an monorepo containing all typescript/javascript packages and applications for ZITADEL powered by Turborepo. Versioning and package publishing is handled by [Changesets](https://github.com/changesets/changesets) and fully automated with GitHub Actions.
|
||||
This is an monorepo containing all typescript/javascript packages and applications for ZITADEL. Versioning and package publishing is handled by [Changesets](https://github.com/changesets/changesets) and fully automated with GitHub Actions.
|
||||
|
||||
## What's inside?
|
||||
|
||||
@@ -9,8 +9,10 @@ This Turborepo includes the following:
|
||||
### Apps and Packages
|
||||
|
||||
- `login`: The new login UI powered by Next.js
|
||||
- `@zitadel/core`: core node SDK
|
||||
- `@zitadel/react-utils`: shared React utilities
|
||||
- `@zitadel/core`: core components for establishing client connection, grpc stub
|
||||
- `@zitadel/react`: shared React utilities and components
|
||||
<!-- - `@zitadel/client`: shared public client utilities -->
|
||||
- `@zitadel/next`: shared Next.js utilities
|
||||
- `@zitadel/tsconfig`: shared `tsconfig.json`s used throughout the monorepo
|
||||
- `eslint-config-zitadel`: ESLint preset
|
||||
|
||||
@@ -18,7 +20,7 @@ Each package and app is 100% [TypeScript](https://www.typescriptlang.org/).
|
||||
|
||||
### Utilities
|
||||
|
||||
This repo has some additional tools already setup for you:
|
||||
This repo has some additional tools:
|
||||
|
||||
- [TypeScript](https://www.typescriptlang.org/) for static type checking
|
||||
- [ESLint](https://eslint.org/) for code linting
|
||||
@@ -26,19 +28,19 @@ This repo has some additional tools already setup for you:
|
||||
|
||||
### Useful commands
|
||||
|
||||
- `yarn build` - Build all packages and the docs site
|
||||
- `yarn dev` - Develop all packages and the docs site
|
||||
- `yarn lint` - Lint all packages
|
||||
- `yarn changeset` - Generate a changeset
|
||||
- `yarn clean` - Clean up all `node_modules` and `dist` folders (runs each package's clean script)
|
||||
- `pnpm build` - Build all packages and the docs site
|
||||
- `pnpm dev` - Develop all packages and the docs site
|
||||
- `pnpm lint` - Lint all packages
|
||||
- `pnpm changeset` - Generate a changeset
|
||||
- `pnpm clean` - Clean up all `node_modules` and `dist` folders (runs each package's clean script)
|
||||
|
||||
## Versioning and Publishing packages
|
||||
|
||||
Package publishing has been configured using [Changesets](https://github.com/changesets/changesets). Please review their [documentation](https://github.com/changesets/changesets#documentation) to familiarize yourself with the workflow.
|
||||
Package publishing has been configured using [Changesets](https://github.com/changesets/changesets). Here is their [documentation](https://github.com/changesets/changesets#documentation) for more information about the workflow.
|
||||
|
||||
This example comes with automated npm releases setup in a [GitHub Action](https://github.com/changesets/action). To get this working, you will need to create an `NPM_TOKEN` and `GITHUB_TOKEN` in your repository settings. You should also install the [Changesets bot](https://github.com/apps/changeset-bot) on your GitHub repository as well.
|
||||
The [GitHub Action](https://github.com/changesets/action) needs an `NPM_TOKEN` and `GITHUB_TOKEN` in the repository settings. The [Changesets bot](https://github.com/apps/changeset-bot) should also be installed on the GitHub repository.
|
||||
|
||||
For more information about this automation, refer to the official [changesets documentation](https://github.com/changesets/changesets/blob/main/docs/automating-changesets.md)
|
||||
Read the [changesets documentation](https://github.com/changesets/changesets/blob/main/docs/automating-changesets.md) for more information about this automation
|
||||
|
||||
### npm
|
||||
|
||||
@@ -55,3 +57,9 @@ To publish packages to a private npm organization scope, **remove** the followin
|
||||
### GitHub Package Registry
|
||||
|
||||
See [Working with the npm registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#publishing-a-package-using-publishconfig-in-the-packagejson-file)
|
||||
|
||||
### TODOs
|
||||
|
||||
- Buf setup to get grpc stub in the core package
|
||||
- Decide whether a seperate client package is required to expose public client convenience methods only or generate a grpc-web output there
|
||||
- Fix #/\* path in login application
|
||||
|
||||
5
apps/docs/next-env.d.ts
vendored
5
apps/docs/next-env.d.ts
vendored
@@ -1,5 +0,0 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
reactStrictMode: true,
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"name": "@zitadel/docs",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"start": "next start ",
|
||||
"dev": "next dev -p 3002",
|
||||
"lint": "next lint",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@zitadel/core": "workspace:*",
|
||||
"@zitadel/utils": "workspace:*",
|
||||
"next": "latest",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"@types/node": "^17.0.12",
|
||||
"@types/react": "^18.0.22",
|
||||
"@types/react-dom": "^18.0.7",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"typescript": "^4.5.4"
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { Button } from "@zitadel/core";
|
||||
import { useIsomorphicLayoutEffect } from "@zitadel/utils";
|
||||
|
||||
export default function Docs() {
|
||||
useIsomorphicLayoutEffect(() => {
|
||||
console.log("zitadel docs page");
|
||||
}, []);
|
||||
return (
|
||||
<div>
|
||||
<h1>zitadel Documentation</h1>
|
||||
<Button>Click me</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"exclude": ["node_modules"],
|
||||
"extends": "@zitadel/tsconfig/nextjs.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
"incremental": true
|
||||
},
|
||||
"include": ["src", "next-env.d.ts"]
|
||||
}
|
||||
4
apps/login/.vscode/settings.json
vendored
Normal file
4
apps/login/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"typescript.tsdk": "../../node_modules/.pnpm/typescript@4.8.4/node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
}
|
||||
@@ -6,11 +6,10 @@
|
||||
"dev": "next dev",
|
||||
"lint": "next lint",
|
||||
"lint-staged": "lint-staged",
|
||||
"prettier": "prettier --write --ignore-unknown .",
|
||||
"prettier:check": "prettier --check --ignore-unknown .",
|
||||
"start": "next start",
|
||||
"test": "yarn prettier:check &nexarn lint",
|
||||
"generate": "buf generate external/zitadel/proto"
|
||||
"generate": "buf generate external/zitadel/proto",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"git": {
|
||||
"pre-commit": "lint-staged"
|
||||
@@ -18,13 +17,10 @@
|
||||
"lint-staged": {
|
||||
"*": "prettier --write --ignore-unknown"
|
||||
},
|
||||
"prettier": {
|
||||
"arrowParens": "always",
|
||||
"semi": true,
|
||||
"trailingComma": "all",
|
||||
"singleQuote": true
|
||||
},
|
||||
"dependencies": {
|
||||
"@zitadel/core": "workspace:*",
|
||||
"@zitadel/react": "workspace:*",
|
||||
"@zitadel/next": "workspace:*",
|
||||
"@heroicons/react": "2.0.13",
|
||||
"@next/font": "13.0.5",
|
||||
"@tailwindcss/forms": "0.5.3",
|
||||
@@ -37,10 +33,11 @@
|
||||
"react-dom": "18.2.0",
|
||||
"react-hook-form": "7.39.5",
|
||||
"styled-components": "6.0.0-beta.2",
|
||||
"tinycolor2": "1.4.2",
|
||||
"use-count-up": "3.0.1"
|
||||
"tinycolor2": "1.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"@bufbuild/buf": "^1.14.0",
|
||||
"@types/ms": "0.7.31",
|
||||
"@types/node": "18.11.9",
|
||||
@@ -50,13 +47,10 @@
|
||||
"@vercel/git-hooks": "1.0.0",
|
||||
"autoprefixer": "10.4.13",
|
||||
"del-cli": "5.0.0",
|
||||
"eslint": "8.27.0",
|
||||
"eslint-config-next": "13.0.3",
|
||||
"grpc-tools": "1.11.3",
|
||||
"lint-staged": "13.0.3",
|
||||
"make-dir-cli": "3.0.0",
|
||||
"postcss": "8.4.21",
|
||||
"prettier": "2.7.1",
|
||||
"prettier-plugin-tailwindcss": "0.1.13",
|
||||
"tailwindcss": "3.2.4",
|
||||
"ts-proto": "^1.139.0",
|
||||
|
||||
@@ -1,29 +1,11 @@
|
||||
{
|
||||
"extends": "@zitadel/tsconfig/nextjs.json",
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"#/*": ["./*"]
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
]
|
||||
"plugins": [{ "name": "next" }]
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules", "external"]
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { useCountUp } from 'use-count-up';
|
||||
|
||||
const CountUp = ({
|
||||
start,
|
||||
end,
|
||||
duration = 1,
|
||||
}: {
|
||||
start: number;
|
||||
end: number;
|
||||
duration?: number;
|
||||
}) => {
|
||||
const { value } = useCountUp({
|
||||
isCounting: true,
|
||||
end,
|
||||
start,
|
||||
duration,
|
||||
decimalPlaces: 1,
|
||||
});
|
||||
|
||||
return <span>{value}</span>;
|
||||
};
|
||||
|
||||
export default CountUp;
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"name": "Monorepo with Changesets",
|
||||
"description": "Simple Next.js monorepo preconfigured to publish packages via Changesets"
|
||||
"name": "ZITADEL typescript Monorepo with Changesets",
|
||||
"description": "ZITADEL typescript monorepo preconfigured to publish packages via Changesets"
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
"dist/**"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsup src/index.tsx --format esm,cjs --dts --external react",
|
||||
"dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react",
|
||||
"build": "tsup src/index.ts --format esm,cjs --dts",
|
||||
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
|
||||
"lint": "eslint \"src/**/*.ts*\"",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
||||
},
|
||||
@@ -19,9 +19,6 @@
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"@types/react": "^17.0.13",
|
||||
"@types/react-dom": "^17.0.8",
|
||||
"react": "^17.0.2",
|
||||
"tsup": "^5.10.1",
|
||||
"typescript": "^4.5.3"
|
||||
},
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import * as React from "react";
|
||||
|
||||
export interface ButtonProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function Button(props: ButtonProps) {
|
||||
return <button>{props.children}</button>;
|
||||
}
|
||||
|
||||
Button.displayName = "Button";
|
||||
19
packages/zitadel-core/src/core.ts
Normal file
19
packages/zitadel-core/src/core.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Return a slugified copy of a string.
|
||||
*
|
||||
* @param {CoreProps} str The ZITADEL client configuration
|
||||
* @return {Core} The client implementation.
|
||||
*/
|
||||
|
||||
export interface ZitadelCoreProps {
|
||||
clientId: string;
|
||||
}
|
||||
|
||||
export interface ZitadelApp {
|
||||
config: ZitadelCoreProps;
|
||||
}
|
||||
|
||||
export function initializeApp(config: ZitadelCoreProps): ZitadelApp {
|
||||
const app = { config };
|
||||
return app;
|
||||
}
|
||||
1
packages/zitadel-core/src/index.ts
Normal file
1
packages/zitadel-core/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { initializeApp } from "./core";
|
||||
31
packages/zitadel-next/package.json
Normal file
31
packages/zitadel-next/package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@zitadel/next",
|
||||
"version": "0.0.0",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"dist/**"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsup src/index.tsx --format esm,cjs --dts --external react",
|
||||
"dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react",
|
||||
"lint": "eslint \"src/**/*.ts*\"",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"tsup": "^5.10.1",
|
||||
"typescript": "^4.5.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^13"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
1
packages/zitadel-next/src/index.tsx
Normal file
1
packages/zitadel-next/src/index.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export { toSlug } from "./toSlug";
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@zitadel/utils",
|
||||
"name": "@zitadel/react",
|
||||
"version": "0.0.0",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
@@ -17,10 +17,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"@types/react": "^17.0.13",
|
||||
"@types/react-dom": "^17.0.8",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"@types/react": "^17.0.13",
|
||||
"@types/react-dom": "^17.0.8",
|
||||
"react": "^17.0.2",
|
||||
"tsup": "^5.10.1",
|
||||
"typescript": "^4.5.3"
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as React from "react";
|
||||
export { Button, type ButtonProps } from "./Button";
|
||||
export {
|
||||
SignInWithGoogle,
|
||||
type SignInWithGoogleProps,
|
||||
5
packages/zitadel-react/tsconfig.json
Normal file
5
packages/zitadel-react/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "@zitadel/tsconfig/react-library.json",
|
||||
"include": ["."],
|
||||
"exclude": ["dist", "build", "node_modules"]
|
||||
}
|
||||
@@ -3,17 +3,26 @@
|
||||
"display": "Next.js",
|
||||
"extends": "./base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"declaration": false,
|
||||
"declarationMap": false,
|
||||
"incremental": true,
|
||||
"jsx": "preserve",
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"module": "esnext",
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"rootDir": "src",
|
||||
"target": "es5"
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"baseUrl": ".",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
]
|
||||
},
|
||||
"include": ["src", "next-env.d.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export { toSlug } from "./toSlug";
|
||||
export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
|
||||
export { usePrevious } from "./usePrevious";
|
||||
@@ -1,13 +0,0 @@
|
||||
import * as React from "react";
|
||||
|
||||
/**
|
||||
* On the server, React emits a warning when calling `useLayoutEffect`.
|
||||
* This is because neither `useLayoutEffect` nor `useEffect` run on the server.
|
||||
* We use this safe version which suppresses the warning by replacing it with a noop on the server.
|
||||
*
|
||||
* See: https://reactjs.org/docs/hooks-reference.html#uselayouteffect
|
||||
*/
|
||||
const useIsomorphicLayoutEffect =
|
||||
typeof window !== "undefined" ? React.useLayoutEffect : () => {};
|
||||
|
||||
export { useIsomorphicLayoutEffect };
|
||||
@@ -1,17 +0,0 @@
|
||||
import * as React from "react";
|
||||
|
||||
function usePrevious<T>(value: T) {
|
||||
// The ref object is a generic container whose current property is mutable ...
|
||||
// ... and can hold any value, similar to an instance property on a class
|
||||
const ref = React.useRef<T>(value);
|
||||
|
||||
// Store current value in ref
|
||||
React.useEffect(() => {
|
||||
ref.current = value;
|
||||
}, [value]); // Only re-run if value changes
|
||||
|
||||
// Return previous value (happens before update in useEffect above)
|
||||
return ref.current;
|
||||
}
|
||||
|
||||
export { usePrevious };
|
||||
651
pnpm-lock.yaml
generated
651
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user