diff --git a/components/state-management/state-management-react/README.md b/components/state-management/state-management-react/README.md new file mode 100644 index 0000000..95f302e --- /dev/null +++ b/components/state-management/state-management-react/README.md @@ -0,0 +1,108 @@ +# State Management Core + +This package provides a simple interface for working with multiple reactive framworks. + +It assumes a view/view model architecture for your app. The view is responsible for what +the user sees, and the view model is responsible for the stateful logic that makes the view +operational. + +This package establishes a convention for writing a view model in vanilla JavaScript and +your view in React, Svelte, or some other reactive framework. + +This package exists for view models that are exposed as libraries. Since your view model +is not tied to a specific framework, developers can write their own views using their +framework of choice. + +## Fields + +A field represents a single piece of reactive data. Its usage is best explained with an example. + +Suppose your app has a search bar. Every time the user changes the search text, the app +should perform a search. + +Here's how you would define the search text field: + +```js +const searchText = new Field("", (newSearchText) => { + // This callback runs whenever the user changes the search text. + searchFor(newSearchText); +}); + +// Get current value of the field +let text = searchText.value; + +// Update the field and perform the search. +// This is how the UI should update the field. +searchText.requestUpdate("hello world"); + +// Update the field without performing the search. +// Your program can use this method internally to update the field without side effects. +searchText.value = "abc"; +``` + +## View Models + +In the context of this package, a view model is an object with fields. +To define a view model, write a function like the following: + +```js +function usePersonViewModel() { + // The view model can have fields... + const name = new Field(); + const age = new Field(); + + // ...and actions + function haveBirthday() { + age.value++; + } + + return { name, age, haveBirthday }; +} +``` + +## Usage in UI framework + +Framework-specific adapters make view models accessible to your UI. For example, +if you framework is Svelte, use the `state-management-svelte` package: + +```svelte + + +

Hello, {person.name}!

+``` + +For more details, see documentation for `state-management-svelte` or the adapter for your +framework of choice. + +Behind the scenes, the adapter does something like this to keep the view model in sync with the UI: + +```js +const person = usePersonViewModel(); + +// Replace `defineReactiveState` with your framework's mechanism +const reactiveName = defineReactiveSate(); + +/** + * Establish a two-way binding between `reactiveName` and `person.name`: + */ + +// Update the UI in response to the field +person.name.updateUI = (value) => { + reactiveName = value; // Or however you update reactiveName in your framework +}; + +// Update the field in response to the UI. +// Replace `watch()` with whatever your framework uses to subscribe to a variable. +watch(reactiveName, (value) => person.name.requestUpdate(value)); + +/** + * Now your UI can use `reactiveName` to interact with the name field. + */ +``` diff --git a/components/state-management/state-management-react/index.ts b/components/state-management/state-management-react/index.ts new file mode 100644 index 0000000..2925eb0 --- /dev/null +++ b/components/state-management/state-management-react/index.ts @@ -0,0 +1 @@ +export * from "./src/use-field"; diff --git a/components/state-management/state-management-react/package.json b/components/state-management/state-management-react/package.json new file mode 100644 index 0000000..3270565 --- /dev/null +++ b/components/state-management/state-management-react/package.json @@ -0,0 +1,28 @@ +{ + "name": "@ethnolib/state-management-react", + "description": "An adapter to use @ethnolib/state-management-core with React", + "author": "SIL Global", + "license": "MIT", + "version": "0.1.0", + "main": "./index.js", + "types": "./index.d.ts", + "scripts": { + "build": "nx vite:build", + "typecheck": "tsc", + "test": "nx vite:test --config vitest.config.ts", + "testonce": "nx vite:test --config vitest.config.ts --run", + "lint": "eslint ." + }, + "devDependencies": { + "@nx/vite": "^19.1.2", + "@types/react": "^17", + "@types/react-dom": "^17", + "@types/node": "^20.16.11", + "@vitejs/plugin-react-swc": "^3.8.0", + "tsx": "^4.19.2", + "typescript": "^5.2.2" + }, + "volta": { + "extends": "../../../package.json" + } +} diff --git a/components/state-management/state-management-react/src/use-field.ts b/components/state-management/state-management-react/src/use-field.ts new file mode 100644 index 0000000..2abbd59 --- /dev/null +++ b/components/state-management/state-management-react/src/use-field.ts @@ -0,0 +1,15 @@ +import { useState } from "react"; +import { Field } from "@ethnolib/state-management-core"; + +export function useField(field: Field): [T, (value: T) => void] { + const [fieldValue, _setFieldValue] = useState(field.value); + + function setFieldValue(value: T) { + field.requestUpdate(value); + _setFieldValue(value); + } + + field.updateUI = (value) => _setFieldValue(value); + + return [fieldValue, setFieldValue]; +} diff --git a/components/state-management/state-management-react/tsconfig.json b/components/state-management/state-management-react/tsconfig.json new file mode 100644 index 0000000..b2ec30c --- /dev/null +++ b/components/state-management/state-management-react/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true + }, + "ts-node": { + "moduleTypes": { + "*": "esm" + } + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ], + "extends": "../../../tsconfig.base.json" +} diff --git a/components/state-management/state-management-react/tsconfig.lib.json b/components/state-management/state-management-react/tsconfig.lib.json new file mode 100644 index 0000000..6c0f0ad --- /dev/null +++ b/components/state-management/state-management-react/tsconfig.lib.json @@ -0,0 +1,28 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": ["node", "vite/client"], + "composite": true, + "declaration": true, + "declarationMap": true + }, + "exclude": [ + "langtagProcessing.ts", + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": [ + "./**/*.js", + "./**/*.jsx", + "./**/*.ts", + "./**/*.tsx", + "../index.ts" + ] +} diff --git a/components/state-management/state-management-react/vite.config.ts b/components/state-management/state-management-react/vite.config.ts new file mode 100644 index 0000000..e6bd7dd --- /dev/null +++ b/components/state-management/state-management-react/vite.config.ts @@ -0,0 +1,36 @@ +/// +import { defineConfig } from "vite"; +import dts from "vite-plugin-dts"; +import * as path from "path"; +import { nxViteTsPaths } from "@nx/vite/plugins/nx-tsconfig-paths.plugin"; + +export default defineConfig({ + root: __dirname, + cacheDir: + "../../../node_modules/.vite/components/state-management/state-management-core", + + plugins: [ + nxViteTsPaths(), + dts({ + entryRoot: ".", + tsconfigPath: path.join(__dirname, "tsconfig.lib.json"), + }), + ], + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + outDir: "./dist", + emptyOutDir: true, + reportCompressedSize: true, + commonjsOptions: { + transformMixedEsModules: true, + }, + lib: { + entry: "./index.ts", + name: "@ethnolib/find-language", + fileName: "index", + formats: ["es", "cjs"], + }, + }, +}); diff --git a/components/state-management/state-management-react/vitest.config.ts b/components/state-management/state-management-react/vitest.config.ts new file mode 100644 index 0000000..803a872 --- /dev/null +++ b/components/state-management/state-management-react/vitest.config.ts @@ -0,0 +1,10 @@ +/// +import { defineConfig } from "vite"; + +export default defineConfig({ + test: { + expect: { + requireAssertions: true, + }, + }, +}); diff --git a/package-lock.json b/package-lock.json index 4e1f6cc..10a0eb0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -622,6 +622,7 @@ "components/language-chooser/svelte/language-chooser-svelte": { "name": "@ethnolib/language-chooser-svelte", "version": "0.0.1", + "extraneous": true, "devDependencies": { "@nx/vite": "^20.4.6", "@sveltejs/vite-plugin-svelte": "^6.1.4", @@ -641,10 +642,32 @@ "node": ">=18.18" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/@sveltejs/vite-plugin-svelte": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.0.tgz", - "integrity": "sha512-nJsV36+o7rZUDlrnSduMNl11+RoDE1cKqOI0yUEBCcqFoAZOk47TwD3dPKS2WmRutke9StXnzsPBslY7prDM9w==", + "components/language-chooser/svelte/language-chooser-svelte-daisyui": { + "name": "@ethnolib/language-chooser-svelte-daisyui", + "version": "0.0.1", + "devDependencies": { + "@nx/vite": "^20.4.6", + "@sveltejs/vite-plugin-svelte": "^6.1.4", + "@tailwindcss/postcss": "^4.1.13", + "@tailwindcss/typography": "^0.5.16", + "@tsconfig/svelte": "^5.0.0", + "autoprefixer": "^10.4.21", + "daisyui": "^5.1.12", + "eslint-plugin-svelte": "^2.44.0", + "postcss": "^8.5.6", + "svelte": "^5.38.6", + "svelte-check": "^4.0.5", + "svelte-preprocess": "^6.0.0", + "tailwindcss": "^3.4.17" + }, + "engines": { + "node": ">=18.18" + } + }, + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/@sveltejs/vite-plugin-svelte": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.1.tgz", + "integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==", "dev": true, "license": "MIT", "dependencies": { @@ -662,7 +685,7 @@ "vite": "^6.3.0 || ^7.0.0" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/@sveltejs/vite-plugin-svelte-inspector": { + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/@sveltejs/vite-plugin-svelte-inspector": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.1.tgz", "integrity": "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==", @@ -680,14 +703,14 @@ "vite": "^6.3.0 || ^7.0.0" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/arg": { + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", "dev": true, "license": "MIT" }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/chokidar": { + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", @@ -712,7 +735,7 @@ "fsevents": "~2.3.2" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/fast-glob": { + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", @@ -729,7 +752,7 @@ "node": ">=8.6.0" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/lilconfig": { + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/lilconfig": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", @@ -742,10 +765,10 @@ "url": "https://github.com/sponsors/antonk52" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", "dev": true, "funding": [ { @@ -759,26 +782,33 @@ ], "license": "MIT", "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" + "lilconfig": "^3.1.1" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { + "jiti": ">=1.21.0", "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { + "jiti": { + "optional": true + }, "postcss": { "optional": true }, - "ts-node": { + "tsx": { + "optional": true + }, + "yaml": { "optional": true } } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/readdirp": { + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", @@ -791,7 +821,7 @@ "node": ">=8.10.0" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/readdirp/node_modules/picomatch": { + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/readdirp/node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", @@ -804,10 +834,10 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/tailwindcss": { - "version": "3.4.17", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", - "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/tailwindcss": { + "version": "3.4.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz", + "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", "dev": true, "license": "MIT", "dependencies": { @@ -819,7 +849,7 @@ "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.21.6", + "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", @@ -828,7 +858,7 @@ "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", @@ -842,7 +872,7 @@ "node": ">=14.0.0" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/tailwindcss/node_modules/glob-parent": { + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/tailwindcss/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", @@ -855,10 +885,10 @@ "node": ">=10.13.0" } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/vite": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", - "integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==", + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/vite": { + "version": "7.1.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.12.tgz", + "integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==", "dev": true, "license": "MIT", "peer": true, @@ -931,12 +961,14 @@ } } }, - "components/language-chooser/svelte/language-chooser-svelte/node_modules/yaml": { + "components/language-chooser/svelte/language-chooser-svelte-daisyui/node_modules/yaml": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", "dev": true, "license": "ISC", + "optional": true, + "peer": true, "bin": { "yaml": "bin.mjs" }, @@ -1124,6 +1156,178 @@ "dev": true, "license": "MIT" }, + "components/state-management/state-management-react": { + "name": "@ethnolib/state-management-react", + "version": "0.1.0", + "license": "MIT", + "devDependencies": { + "@nx/vite": "^19.1.2", + "@types/node": "^20.16.11", + "@types/react": "^17", + "@types/react-dom": "^17", + "@vitejs/plugin-react-swc": "^3.8.0", + "tsx": "^4.19.2", + "typescript": "^5.2.2" + } + }, + "components/state-management/state-management-react/node_modules/@nx/devkit": { + "version": "19.8.14", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.8.14.tgz", + "integrity": "sha512-A8dCGttbuqgg9P56VTb0ElD2vM5nc5g0aLnX5PSXo4SkFXwd8DV5GgwJKWB1GO9hYyEtbj4gKek0KxnCtdav4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nrwl/devkit": "19.8.14", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 19 <= 21" + } + }, + "components/state-management/state-management-react/node_modules/@nx/js": { + "version": "19.8.14", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.8.14.tgz", + "integrity": "sha512-Nk0eEB2F/ZbBkH2iT+cgLWIittY8n5eOrA/uBBG2XMdencJZ9E2HNA/UzSGPZmD4EYVk0R1vm83k5+IMS1VAZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.8.14", + "@nx/devkit": "19.8.14", + "@nx/workspace": "19.8.14", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "enquirer": "~2.3.6", + "fast-glob": "3.2.7", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "components/state-management/state-management-react/node_modules/@nx/vite": { + "version": "19.8.14", + "resolved": "https://registry.npmjs.org/@nx/vite/-/vite-19.8.14.tgz", + "integrity": "sha512-vCmY+zXlCaBTfMP6qPmhmH19qlAANr93omyp6CK9HSRIncGDqHEKmUYMsEiZYiVepNecwhcNdckz9y0rGaZNVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nrwl/vite": "19.8.14", + "@nx/devkit": "19.8.14", + "@nx/js": "19.8.14", + "@phenomnomnominal/tsquery": "~5.0.1", + "@swc/helpers": "~0.5.0", + "enquirer": "~2.3.6", + "minimatch": "9.0.3", + "tsconfig-paths": "^4.1.2" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vitest": "^1.3.1 || ^2.0.0" + } + }, + "components/state-management/state-management-react/node_modules/@types/node": { + "version": "20.19.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.23.tgz", + "integrity": "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "components/state-management/state-management-react/node_modules/babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + } + }, + "components/state-management/state-management-react/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "components/state-management/state-management-react/node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "components/state-management/state-management-react/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, "components/state-management/state-management-svelte": { "name": "@ethnolib/state-management-svelte", "version": "0.1.0", @@ -4068,14 +4272,18 @@ "resolved": "components/language-chooser/react/language-chooser-react-mui", "link": true }, - "node_modules/@ethnolib/language-chooser-svelte": { - "resolved": "components/language-chooser/svelte/language-chooser-svelte", + "node_modules/@ethnolib/language-chooser-svelte-daisyui": { + "resolved": "components/language-chooser/svelte/language-chooser-svelte-daisyui", "link": true }, "node_modules/@ethnolib/state-management-core": { "resolved": "components/state-management/state-management-core", "link": true }, + "node_modules/@ethnolib/state-management-react": { + "resolved": "components/state-management/state-management-react", + "link": true + }, "node_modules/@ethnolib/state-management-svelte": { "resolved": "components/state-management/state-management-svelte", "link": true @@ -6219,6 +6427,157 @@ "node": ">=8" } }, + "node_modules/@nrwl/vite": { + "version": "19.8.14", + "resolved": "https://registry.npmjs.org/@nrwl/vite/-/vite-19.8.14.tgz", + "integrity": "sha512-9aKWDuXy1W/A//Z+CeQTlcBK2MDjdUuDnickXqg+NyZL7y5uDUJqLm+B4QI+6jwtZR+F5TiTM4l95azoUnAKuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/vite": "19.8.14" + } + }, + "node_modules/@nrwl/vite/node_modules/@nx/devkit": { + "version": "19.8.14", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.8.14.tgz", + "integrity": "sha512-A8dCGttbuqgg9P56VTb0ElD2vM5nc5g0aLnX5PSXo4SkFXwd8DV5GgwJKWB1GO9hYyEtbj4gKek0KxnCtdav4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nrwl/devkit": "19.8.14", + "ejs": "^3.1.7", + "enquirer": "~2.3.6", + "ignore": "^5.0.4", + "minimatch": "9.0.3", + "semver": "^7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + }, + "peerDependencies": { + "nx": ">= 19 <= 21" + } + }, + "node_modules/@nrwl/vite/node_modules/@nx/js": { + "version": "19.8.14", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.8.14.tgz", + "integrity": "sha512-Nk0eEB2F/ZbBkH2iT+cgLWIittY8n5eOrA/uBBG2XMdencJZ9E2HNA/UzSGPZmD4EYVk0R1vm83k5+IMS1VAZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "19.8.14", + "@nx/devkit": "19.8.14", + "@nx/workspace": "19.8.14", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "enquirer": "~2.3.6", + "fast-glob": "3.2.7", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "jsonc-parser": "3.2.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, + "node_modules/@nrwl/vite/node_modules/@nx/vite": { + "version": "19.8.14", + "resolved": "https://registry.npmjs.org/@nx/vite/-/vite-19.8.14.tgz", + "integrity": "sha512-vCmY+zXlCaBTfMP6qPmhmH19qlAANr93omyp6CK9HSRIncGDqHEKmUYMsEiZYiVepNecwhcNdckz9y0rGaZNVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nrwl/vite": "19.8.14", + "@nx/devkit": "19.8.14", + "@nx/js": "19.8.14", + "@phenomnomnominal/tsquery": "~5.0.1", + "@swc/helpers": "~0.5.0", + "enquirer": "~2.3.6", + "minimatch": "9.0.3", + "tsconfig-paths": "^4.1.2" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vitest": "^1.3.1 || ^2.0.0" + } + }, + "node_modules/@nrwl/vite/node_modules/babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + } + }, + "node_modules/@nrwl/vite/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nrwl/vite/node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@nrwl/workspace": { "version": "19.8.14", "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.8.14.tgz",