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",