From 1b22a043925e7b9daf3022008f61a4ae62634803 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 11:21:46 +1100 Subject: [PATCH 01/17] feat: enhance npm publishing workflow for dev branch with conditional package name and access level --- .gitea/workflows/publishToNpm.yaml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/publishToNpm.yaml b/.gitea/workflows/publishToNpm.yaml index 58646b0..3232df6 100644 --- a/.gitea/workflows/publishToNpm.yaml +++ b/.gitea/workflows/publishToNpm.yaml @@ -4,6 +4,7 @@ on: push: branches: - main + - dev jobs: publish: @@ -22,7 +23,24 @@ jobs: - name: Install dependencies run: npm install + - name: Determine package name + id: package_name + run: | + if [ "${{ gitea.ref }}" == "refs/heads/main" ]; then + echo "PACKAGE_NAME=datenel-react" >> $GITEA_ENV + echo "ACCESS_LEVEL=public" >> $GITEA_ENV + elif [ "${{ gitea.ref }}" == "refs/heads/dev" ]; then + echo "PACKAGE_NAME=@astrian/datenel-react-dev" >> $GITEA_ENV + echo "ACCESS_LEVEL=restricted" >> $GITEA_ENV + fi + + - name: Update package.json for dev releases + if: GITEA.ref == 'refs/heads/dev' + run: | + jq --arg name "@astrian/datenel-react-dev" '.name=$name' package.json > temp.json && mv temp.json package.json + jq --arg version "0.0.0-dev.$(date +%s)" '.version=$version' package.json > temp.json && mv temp.json package.json + - name: Publish to npm - run: npm publish + run: npm publish --access $ACCESS_LEVEL env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} -- 2.45.1 From c55f5d0bfdf8da7f5d588d7475b626af1747fe1f Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 11:23:18 +1100 Subject: [PATCH 02/17] fix: remove access level settings from npm publishing workflow --- .gitea/workflows/publishToNpm.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitea/workflows/publishToNpm.yaml b/.gitea/workflows/publishToNpm.yaml index 3232df6..7b6aedf 100644 --- a/.gitea/workflows/publishToNpm.yaml +++ b/.gitea/workflows/publishToNpm.yaml @@ -28,10 +28,8 @@ jobs: run: | if [ "${{ gitea.ref }}" == "refs/heads/main" ]; then echo "PACKAGE_NAME=datenel-react" >> $GITEA_ENV - echo "ACCESS_LEVEL=public" >> $GITEA_ENV elif [ "${{ gitea.ref }}" == "refs/heads/dev" ]; then echo "PACKAGE_NAME=@astrian/datenel-react-dev" >> $GITEA_ENV - echo "ACCESS_LEVEL=restricted" >> $GITEA_ENV fi - name: Update package.json for dev releases -- 2.45.1 From 0eb95f05ae5a17600d5cdd33e6f419b175ef099e Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 11:25:28 +1100 Subject: [PATCH 03/17] feat: update npm publishing workflow to set access level based on branch --- .gitea/workflows/publishToNpm.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitea/workflows/publishToNpm.yaml b/.gitea/workflows/publishToNpm.yaml index 7b6aedf..3232df6 100644 --- a/.gitea/workflows/publishToNpm.yaml +++ b/.gitea/workflows/publishToNpm.yaml @@ -28,8 +28,10 @@ jobs: run: | if [ "${{ gitea.ref }}" == "refs/heads/main" ]; then echo "PACKAGE_NAME=datenel-react" >> $GITEA_ENV + echo "ACCESS_LEVEL=public" >> $GITEA_ENV elif [ "${{ gitea.ref }}" == "refs/heads/dev" ]; then echo "PACKAGE_NAME=@astrian/datenel-react-dev" >> $GITEA_ENV + echo "ACCESS_LEVEL=restricted" >> $GITEA_ENV fi - name: Update package.json for dev releases -- 2.45.1 From ee0e9d430cfc7927f6e21507f6dcd52f07f8dca2 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 11:42:18 +1100 Subject: [PATCH 04/17] docs: add contribution and development instructions to README --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index aa8b936..6419ef9 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,15 @@ export default () => { More features are on the roadmap. +## Contribution & Development + +```zsh +npm i # or `yarn` +npm run dev # or `yarn dev` +``` + +Then the package will launch a testing React hot-reload server in `localhost:1926`. The server file available in `playground` folder, feel free to modify content inside it. + ## License MIT \ No newline at end of file -- 2.45.1 From d0d0aa6cf5bf10ad6c4d99a789681ef5def7b8d7 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 11:43:29 +1100 Subject: [PATCH 05/17] docs: improve clarity in README regarding the testing React hot-reload server --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6419ef9..c9a099d 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ npm i # or `yarn` npm run dev # or `yarn dev` ``` -Then the package will launch a testing React hot-reload server in `localhost:1926`. The server file available in `playground` folder, feel free to modify content inside it. +Then the package will launch a testing React hot-reload server on `localhost:1926`. The server file is available in the `playground` folder, feel free to modify the content inside it. ## License -- 2.45.1 From 9c95a543630fb07d9c5074aef6eea559574e2562 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 13:12:53 +1100 Subject: [PATCH 06/17] feat: enable type entry insertion in dts plugin for Vite configuration --- vite.config.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vite.config.ts b/vite.config.ts index db4dafb..c487547 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -19,7 +19,9 @@ export default defineConfig(({mode}) => ({ }, }, }, - plugins: [react(), dts()], + plugins: [react(), dts({ + insertTypesEntry: true + })], resolve: { alias: { "@": path.resolve(__dirname, "./src"), -- 2.45.1 From 622e3a82008ce6a8b06ade0314d0441b51b0f68a Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 13:18:11 +1100 Subject: [PATCH 07/17] fix: rename export from WeekPicker to SingleDatePicker in index.ts --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 4a2a50c..bef03e4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ import './style.scss' -export {default as WeekPicker} from './components/SingleDatePicker.tsx' \ No newline at end of file +export {default as SingleDatePicker} from './components/SingleDatePicker.tsx' \ No newline at end of file -- 2.45.1 From d2c9e4aeeb26ec1c09d59b8f0762b45206a01f7b Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 13:18:27 +1100 Subject: [PATCH 08/17] fix: update import from WeekPicker to SingleDatePicker in app.tsx --- playground/app.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/playground/app.tsx b/playground/app.tsx index c26d28d..c69e610 100644 --- a/playground/app.tsx +++ b/playground/app.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { WeekPicker } from "../src/index.ts" +import { SingleDatePicker } from "../src/index.ts" import './app.scss' export default () => { @@ -11,7 +11,7 @@ export default () => { return (
- Date: Thu, 20 Feb 2025 13:46:44 +1100 Subject: [PATCH 09/17] feat: update TypeScript configuration and enhance SingleDatePicker component with improved typing --- package.json | 10 ++++++---- src/components/SingleDatePicker.tsx | 10 ++++++---- tsconfig.app.json | 12 ++++++++---- tsconfig.json | 9 ++++++--- tsconfig.node.json | 7 +++++-- vite.config.ts | 3 ++- 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 6f9cda4..c6432d5 100644 --- a/package.json +++ b/package.json @@ -22,13 +22,13 @@ "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-react-refresh": "^0.4.18", "globals": "^15.14.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", "sass-embedded": "^1.85.0", "typescript": "~5.7.2", "typescript-eslint": "^8.22.0", "vite": "^6.1.0", - "vite-plugin-dts": "^4.5.0", - "react": "^19.0.0", - "react-dom": "^19.0.0" + "vite-plugin-dts": "^4.5.0" }, "exports": { "import": "./dist/datenel.es.js", @@ -38,5 +38,7 @@ "main": "dist/index.cjs.js", "module": "dist/datenel.es.js", "types": "dist/index.d.ts", - "files": ["dist"] + "files": [ + "dist" + ] } diff --git a/src/components/SingleDatePicker.tsx b/src/components/SingleDatePicker.tsx index 8c83d8c..d4096ae 100644 --- a/src/components/SingleDatePicker.tsx +++ b/src/components/SingleDatePicker.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import { getCalendarDates, getL10Weekday, generateUniqueId, applyColor } from '../utils' -interface Props { +export interface SingleDatePickerProps { /** * Control the selected * date programmatically, including situations like provide a default value or control the selected @@ -78,9 +78,9 @@ interface Props { * * @component * - * @param {Props} props + * @param {SingleDatePickerProps} props */ -export default ({ value, onSelect, localization, onClose, mainColor = '#000000', accentColor = '#000000', reversedColor = '#ffffff', hoverColor = '#00000017', borderColor = '#e0e0e0' }: Props) => { +const SingleDatePicker: React.FC = ({ value, onSelect, localization, onClose, mainColor = '#000000', accentColor = '#000000', reversedColor = '#ffffff', hoverColor = '#00000017', borderColor = '#e0e0e0' }: SingleDatePickerProps) => { const [currentMonth, setCurrentMonth] = useState(new Date().getMonth()) const [currentYear, setCurrentYear] = useState(new Date().getFullYear()) const [selectedDate, setSelectedDate] = useState(new Date()) @@ -224,4 +224,6 @@ export default ({ value, onSelect, localization, onClose, mainColor = '#000000', { !!onClose && }
) -} \ No newline at end of file +} + +export default SingleDatePicker \ No newline at end of file diff --git a/tsconfig.app.json b/tsconfig.app.json index 358ca9b..1da4adf 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -10,9 +10,10 @@ /* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, + "emitDeclarationOnly": true, + "declaration": true, "isolatedModules": true, "moduleDetection": "force", - "noEmit": true, "jsx": "react-jsx", /* Linting */ @@ -20,7 +21,10 @@ "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true + "noUncheckedSideEffectImports": true, + + "composite": true, + "outDir": "./dist" // 指定输出目录 }, - "include": ["src"] -} + "include": ["src", "tsconfig.app.json", "tsconfig.node.json"] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index dfc4658..2456ef6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,9 @@ "baseUrl": ".", "paths": { "@/*": ["src/*"] - } - } -} + }, + "declaration": true, + "outDir": "./dist" + }, + "include": ["src/**/*", "tsconfig.app.json", "tsconfig.node.json"] +} \ No newline at end of file diff --git a/tsconfig.node.json b/tsconfig.node.json index db0becc..0ee34bb 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -9,16 +9,19 @@ /* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, + "emitDeclarationOnly": true, + "declaration": true, "isolatedModules": true, "moduleDetection": "force", - "noEmit": true, /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true + "noUncheckedSideEffectImports": true, + + "composite": true }, "include": ["vite.config.ts"] } diff --git a/vite.config.ts b/vite.config.ts index c487547..36217fc 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -20,7 +20,8 @@ export default defineConfig(({mode}) => ({ }, }, plugins: [react(), dts({ - insertTypesEntry: true + insertTypesEntry: true, + logLevel: "info" })], resolve: { alias: { -- 2.45.1 From 952b053e9c65bd7635407a63631ec031e8d4e028 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 14:07:01 +1100 Subject: [PATCH 10/17] fix: update TypeScript definition path in package.json and configure dts plugin with tsconfig path --- package.json | 2 +- vite.config.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c6432d5..62d9cd4 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ }, "main": "dist/index.cjs.js", "module": "dist/datenel.es.js", - "types": "dist/index.d.ts", + "types": "dist/src/index.d.ts", "files": [ "dist" ] diff --git a/vite.config.ts b/vite.config.ts index 36217fc..85f0cdc 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -20,8 +20,7 @@ export default defineConfig(({mode}) => ({ }, }, plugins: [react(), dts({ - insertTypesEntry: true, - logLevel: "info" + tsconfigPath: "./tsconfig.app.json" })], resolve: { alias: { -- 2.45.1 From c0b833be6f993f1e98048f97bbef7e6a1c056246 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 14:46:29 +1100 Subject: [PATCH 11/17] fix: update import path for SingleDatePicker and adjust Vite configuration for output filenames --- src/index.ts | 2 +- vite.config.ts | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index bef03e4..75a3e89 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,3 @@ import './style.scss' -export {default as SingleDatePicker} from './components/SingleDatePicker.tsx' \ No newline at end of file +export {default as SingleDatePicker} from './components/SingleDatePicker' \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 85f0cdc..c38d9a7 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,20 +8,30 @@ export default defineConfig(({mode}) => ({ lib: { entry: "src/index.ts", name: "datenel-react", - fileName: format => `datenel.${format}.js`, + fileName: format => `index.${format}.js`, }, rollupOptions: { external: ["react"], output: { globals: { react: "React", + "react-dom": "ReactDOM", }, + assetFileNames: assetInfo => { + if (assetInfo.names[0].endsWith(".css")) { + return "index.css"; + } + return `assets/${assetInfo.names[0]}`; + } }, }, }, - plugins: [react(), dts({ - tsconfigPath: "./tsconfig.app.json" - })], + plugins: [ + react(), + dts({ + tsconfigPath: "./tsconfig.app.json" + }), + ], resolve: { alias: { "@": path.resolve(__dirname, "./src"), -- 2.45.1 From 6fdcd80710761036775bc1b539f23892a65b5696 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 14:52:48 +1100 Subject: [PATCH 12/17] feat: add vite-plugin-css-injected-by-js for improved CSS handling and update app import path --- package-lock.json | 11 +++++++++++ package.json | 1 + playground/app.tsx | 2 +- vite.config.ts | 3 +++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 1918eb0..59f5adf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "typescript": "~5.7.2", "typescript-eslint": "^8.22.0", "vite": "^6.1.0", + "vite-plugin-css-injected-by-js": "^3.5.2", "vite-plugin-dts": "^4.5.0" }, "peerDependencies": { @@ -4523,6 +4524,16 @@ } } }, + "node_modules/vite-plugin-css-injected-by-js": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.2.tgz", + "integrity": "sha512-2MpU/Y+SCZyWUB6ua3HbJCrgnF0KACAsmzOQt1UvRVJCGF6S8xdA3ZUhWcWdM9ivG4I5az8PnQmwwrkC2CAQrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "vite": ">2.0.0-0" + } + }, "node_modules/vite-plugin-dts": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-4.5.0.tgz", diff --git a/package.json b/package.json index 62d9cd4..4daa8bb 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "typescript": "~5.7.2", "typescript-eslint": "^8.22.0", "vite": "^6.1.0", + "vite-plugin-css-injected-by-js": "^3.5.2", "vite-plugin-dts": "^4.5.0" }, "exports": { diff --git a/playground/app.tsx b/playground/app.tsx index c69e610..565a61b 100644 --- a/playground/app.tsx +++ b/playground/app.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { SingleDatePicker } from "../src/index.ts" +import { SingleDatePicker } from "../dist/index.es" import './app.scss' export default () => { diff --git a/vite.config.ts b/vite.config.ts index c38d9a7..e510078 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import dts from 'vite-plugin-dts' import path from "path" +import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js" export default defineConfig(({mode}) => ({ build: { @@ -11,6 +12,7 @@ export default defineConfig(({mode}) => ({ fileName: format => `index.${format}.js`, }, rollupOptions: { + preserveEntrySignatures: "strict", external: ["react"], output: { globals: { @@ -31,6 +33,7 @@ export default defineConfig(({mode}) => ({ dts({ tsconfigPath: "./tsconfig.app.json" }), + cssInjectedByJsPlugin() ], resolve: { alias: { -- 2.45.1 From 9f8c6c915615a6a19eee61f37832046a354b4611 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 14:56:35 +1100 Subject: [PATCH 13/17] fix: update main and module entry points in package.json for UMD and ES module formats --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4daa8bb..9ab6784 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "require": "./dist/index.cjs.js", "default": "./dist/datenel.es.js" }, - "main": "dist/index.cjs.js", - "module": "dist/datenel.es.js", + "main": "dist/index.umd.js", + "module": "dist/index.es.js", "types": "dist/src/index.d.ts", "files": [ "dist" -- 2.45.1 From dcdf8ccdbef86ae2fe5fa1f62e2f729410281f67 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 14:56:48 +1100 Subject: [PATCH 14/17] fix: update export paths in package.json for consistency in module formats --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9ab6784..46b1027 100644 --- a/package.json +++ b/package.json @@ -32,9 +32,9 @@ "vite-plugin-dts": "^4.5.0" }, "exports": { - "import": "./dist/datenel.es.js", + "import": "./dist/index.es.js", "require": "./dist/index.cjs.js", - "default": "./dist/datenel.es.js" + "default": "./dist/index.es.js" }, "main": "dist/index.umd.js", "module": "dist/index.es.js", -- 2.45.1 From 70bb0b14afa203c4c16a595ff82a2d173c6b08ab Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 15:06:02 +1100 Subject: [PATCH 15/17] fix: update package.json to correct main entry point and improve type definitions --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 46b1027..5408d45 100644 --- a/package.json +++ b/package.json @@ -32,13 +32,14 @@ "vite-plugin-dts": "^4.5.0" }, "exports": { + "types": "./dist/index.d.ts", "import": "./dist/index.es.js", "require": "./dist/index.cjs.js", "default": "./dist/index.es.js" }, - "main": "dist/index.umd.js", + "main": "dist/index.cjs.js", "module": "dist/index.es.js", - "types": "dist/src/index.d.ts", + "types": "dist/index.d.ts", "files": [ "dist" ] -- 2.45.1 From 2c48ddbdb2b498eca8181d114d8bd84b43fc0910 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 15:19:24 +1100 Subject: [PATCH 16/17] fix: update types path in package.json to point to the correct location --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5408d45..0e7efb6 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "vite-plugin-dts": "^4.5.0" }, "exports": { - "types": "./dist/index.d.ts", + "types": "./dist/src/index.d.ts", "import": "./dist/index.es.js", "require": "./dist/index.cjs.js", "default": "./dist/index.es.js" -- 2.45.1 From 397103b63631b1cc95211b5fe783906db9d55949 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Thu, 20 Feb 2025 15:27:14 +1100 Subject: [PATCH 17/17] fix: update example in README to use SingleDatePicker instead of WeekPicker --- README.md | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index c9a099d..5130c7e 100644 --- a/README.md +++ b/README.md @@ -30,28 +30,27 @@ Here is an example of how to use Datenel in your React application: ```tsx import React from 'react' -import { WeekPicker } from 'datenel-react' -import './app.scss' +import { SingleDatePicker } from 'datenel-react' export default () => { - function onSelect(value) { - alert(`You selected ${value.year}-${value-month}-${value.day}`) - } + function onSelect(value) { + alert(`You selected ${value.year}-${value-month}-${value.day}`) + } - return ( -
-
- -
-
- ) + return ( +
+
+ +
+
+ ) } ``` -- 2.45.1