This is a port of a project (https://notedok.com/) I started back in 2013, so some code is pretty old and just moved as is. The part related to UI rendering, logic and event handling is completely reworked to align with my own proposed experimental guidelines.
src\model.tscontains the boxes, i.e. types for each of the note states. All the types are treated as immutablesrc\noteLifecycle.tscontains the arrows, i.e. all the valid state transitions. All the functions here are puresrc\events.tscontains the full list of events that are generated by components/commands. All the types are treated as immutablesrc\commands.tscontains all the commands that can be issued. All the types are treated as immutablesrc\reducer.tshandles all the events by delegating actual execution tosrc\business.ts. All the functions here are puresrc\business.tsis the one fully covered by unit-tests (src\business.tests.ts). All the interesting things are happening there- Side effects (such as generating random unique note titles) are only allowed in commands (meaning: actual implementations of commands, for example,
src\commands\storage.ts) - All the components are [almost] pure and don't manage their own state, except the
src\components\SearchPanel.tsx, where the state is managed locally, as an on-going experiment - There is also some impurity due integration with a legacy autocomplete library (no time to tackle it now). Some components force focus upon first render etc.
- Most of the components, however, treated as pure and are wrapped in
memo - The state is managed using custom-made
src\hooks\useReducer.tshook. The reason to use custom hook is that I like the Elm model where reducer spits out new state and command, and the existinguseReduceronly returns the new state. I don't like thunks and stuff like that - The app state lives in
src\AppStatefulContainer.tsx, the uppermost component
Development
npm run dev
Prod build:
npm run build
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
- Configure the top-level
parserOptionsproperty like this:
export default tseslint.config({
languageOptions: {
// other options...
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: import.meta.dirname,
},
},
});- Replace
tseslint.configs.recommendedtotseslint.configs.recommendedTypeCheckedortseslint.configs.strictTypeChecked - Optionally add
...tseslint.configs.stylisticTypeChecked - Install eslint-plugin-react and update the config:
// eslint.config.js
import react from "eslint-plugin-react";
export default tseslint.config({
// Set the react version
settings: { react: { version: "18.3" } },
plugins: {
// Add the react plugin
react,
},
rules: {
// other rules...
// Enable its recommended rules
...react.configs.recommended.rules,
...react.configs["jsx-runtime"].rules,
},
});