├── .github ├── dependabot.yml └── workflows │ └── testing.yml ├── .gitignore ├── .node-version ├── .prettierrc ├── LICENSE.md ├── README.md ├── bili.default.config.js ├── github-assets └── ogp.png ├── jest.config.js ├── package.json ├── packages ├── create-next-app │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── example │ │ ├── .gitignore │ │ ├── README.md │ │ ├── components │ │ │ ├── clock.tsx │ │ │ ├── counter.tsx │ │ │ ├── nav.tsx │ │ │ └── page.tsx │ │ ├── domains │ │ │ ├── index.ts │ │ │ ├── timer.spec.ts │ │ │ └── timer.ts │ │ ├── jest.config.js │ │ ├── lib │ │ │ ├── fleur.tsx │ │ │ └── useInterval.ts │ │ ├── package.json │ │ ├── pages │ │ │ ├── _app.tsx │ │ │ ├── index.tsx │ │ │ ├── ssg.tsx │ │ │ └── ssr.tsx │ │ └── tsconfig.json │ ├── package.json │ ├── src │ │ ├── declaration.d.ts │ │ ├── gitignore-default │ │ └── index.ts │ └── tsconfig.json ├── di │ ├── .gitignore │ ├── .npmignore │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── index.spec.ts │ │ └── index.ts │ ├── tsconfig.json │ └── tsconfig.test.json ├── example-todomvc │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── base.css │ │ ├── base.js │ │ └── index.css │ ├── src │ │ ├── app.tsx │ │ ├── client.tsx │ │ ├── components │ │ │ ├── App.tsx │ │ │ ├── Footer.tsx │ │ │ ├── Html.tsx │ │ │ └── TodoItem.tsx │ │ ├── domain │ │ │ ├── App │ │ │ │ ├── actions.ts │ │ │ │ ├── operations.ts │ │ │ │ └── store.ts │ │ │ ├── RouteStore.ts │ │ │ ├── Todo │ │ │ │ ├── actions.ts │ │ │ │ ├── api.ts │ │ │ │ ├── operations.ts │ │ │ │ ├── store.ts │ │ │ │ └── types.ts │ │ │ └── constants.ts │ │ ├── routes │ │ │ ├── Index.tsx │ │ │ └── Test.tsx │ │ ├── server.tsx │ │ └── utils │ │ │ ├── axios.ts │ │ │ └── utils.ts │ ├── tsconfig.json │ └── webpack.config.ts ├── fleur-benchmarks │ ├── .gitignore │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── fleur.spec.tsx │ │ ├── fluxible.spec.ts │ │ ├── react-redux.spec.tsx │ │ └── setup.ts │ └── tsconfig.json ├── fleur │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── bili.config.ts │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── Abort.ts │ │ ├── Action.spec.ts │ │ ├── Action.ts │ │ ├── AppContext.spec.ts │ │ ├── AppContext.ts │ │ ├── Dispatcher.ts │ │ ├── Fleur.spec.ts │ │ ├── Fleur.ts │ │ ├── MinimalOps.spec.ts │ │ ├── MinimalOps.ts │ │ ├── OperationContext.ts │ │ ├── Operations.ts │ │ ├── Store.spec.tsx │ │ ├── Store.ts │ │ ├── StoreContext.ts │ │ ├── index.ts │ │ ├── selector.spec.ts │ │ ├── selector.ts │ │ ├── selectorWithStore.spec.ts │ │ ├── selectorWithStore.ts │ │ ├── utils.ts │ │ ├── withReduxDevtools.spec.ts │ │ └── withReduxDevtools.ts │ ├── tsconfig.json │ └── tsconfig.test.json ├── next │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── react │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── bili.config.ts │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── ComponentReactContext.spec.tsx │ │ ├── ComponentReactContext.ts │ │ ├── WithRef.ts │ │ ├── connectToStores.spec.ts │ │ ├── connectToStores.ts │ │ ├── createElementWithContext.ts │ │ ├── declarations.d.ts │ │ ├── index.ts │ │ ├── ssr.spec.tsx │ │ ├── useFleurContext.ts │ │ ├── useStore.spec.ts │ │ ├── useStore.ts │ │ ├── utils │ │ │ ├── batchedUpdates.native.ts │ │ │ └── batchedUpdates.ts │ │ ├── withFleurContext.spec.tsx │ │ └── withFleurContext.ts │ ├── tsconfig.json │ └── tsconfig.test.json ├── route-store-dom │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── HistoryHandler.ts │ │ ├── Link.ts │ │ ├── RouteStore.spec.ts │ │ ├── RouteStore.ts │ │ ├── RouterContext.ts │ │ ├── actions.ts │ │ ├── client.spec.ts │ │ ├── createRouteStore.ts │ │ ├── index.spec.ts │ │ ├── index.ts │ │ ├── operations.ts │ │ ├── types.ts │ │ ├── useRoute.spec.ts │ │ ├── useRoute.ts │ │ ├── utils.ts │ │ ├── withRoute.spec.tsx │ │ └── withRoute.ts │ ├── tsconfig.json │ └── tsconfig.test.json └── testing │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ ├── MockContextBase.spec.ts │ ├── MockContextBase.ts │ ├── TestingFleurContext.ts │ ├── index.spec.tsx │ ├── index.ts │ ├── mockComponentContext.spec.tsx │ ├── mockComponentContext.ts │ ├── mockFleurContext.spec.ts │ ├── mockFleurContext.ts │ ├── mockOperationContext.spec.ts │ ├── mockOperationContext.ts │ ├── mockStore.spec.ts │ ├── mockStore.ts │ └── mockStoreContext.ts │ ├── tsconfig.json │ └── tsconfig.test.json ├── tslint.json └── yarn.lock /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 8 | allow: 9 | - dependency-type: direct 10 | ignore: 11 | - dependency-name: webpack 12 | versions: 13 | - 5.17.0 14 | - 5.19.0 15 | - 5.21.2 16 | - 5.23.0 17 | - 5.24.2 18 | - 5.24.3 19 | - 5.25.1 20 | - 5.27.1 21 | - 5.28.0 22 | - 5.30.0 23 | - 5.31.2 24 | - dependency-name: y18n 25 | versions: 26 | - 4.0.1 27 | - dependency-name: superjson 28 | versions: 29 | - 1.5.0 30 | - 1.5.2 31 | - 1.6.1 32 | - 1.6.2 33 | - 1.7.2 34 | - 1.7.3 35 | - dependency-name: husky 36 | versions: 37 | - 5.1.0 38 | - 5.1.2 39 | - 5.1.3 40 | - 5.2.0 41 | - dependency-name: "@types/react-dom" 42 | versions: 43 | - 17.0.1 44 | - 17.0.2 45 | - dependency-name: commander 46 | versions: 47 | - 7.1.0 48 | - dependency-name: webpack-cli 49 | versions: 50 | - 4.4.0 51 | - 4.5.0 52 | - dependency-name: react-dom 53 | versions: 54 | - 17.0.1 55 | - dependency-name: next 56 | versions: 57 | - 10.0.5 58 | - 10.0.6 59 | - 10.0.7 60 | - dependency-name: "@types/react" 61 | versions: 62 | - 17.0.1 63 | - 17.0.2 64 | - dependency-name: ts-loader 65 | versions: 66 | - 8.0.15 67 | -------------------------------------------------------------------------------- /.github/workflows/testing.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | testing: 7 | runs-on: ${{ matrix.os }} 8 | 9 | strategy: 10 | matrix: 11 | os: [ubuntu-latest] 12 | node-version: [12.x, 14.x, 16.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Setup Node.js for use with actions 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - name: Cache 21 | uses: actions/cache@v1.0.0 22 | with: 23 | path: ~/.cache/yarn 24 | key: ${{ matrix.os }}-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }} 25 | restore-keys: | 26 | ${{ matrix.os }}- 27 | - name: Install deps 28 | run: yarn install 29 | - name: Testing @fleur/fleur 30 | run: | 31 | cd packages/fleur 32 | yarn prepublishOnly 33 | yarn test --coverage --verbose 34 | - name: Testing @fleur/di 35 | run: | 36 | cd packages/di 37 | yarn prepublishOnly 38 | yarn test --coverage --verbose 39 | - name: Testing @fleur/react 40 | run: | 41 | cd packages/react 42 | yarn prepublishOnly 43 | yarn test --coverage --verbose 44 | - name: Testing @fleur/testing 45 | run: | 46 | cd packages/testing 47 | yarn prepublishOnly 48 | yarn test --coverage --verbose 49 | - name: Testing @fleur/create-next-app 50 | run: | 51 | cd packages/create-next-app 52 | yarn prepublishOnly 53 | node ./bin/index test-app 54 | cd test-app 55 | yarn install 56 | yarn run build 57 | - name: Testing @fleur/next 58 | run: | 59 | cd packages/next 60 | yarn prepublishOnly 61 | - name: Benchmarking 62 | run: | 63 | cd packages/fleur-benchmarks 64 | yarn test 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .DS_Store 3 | yarn-error.log 4 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 16.8.0 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "semi": false, 4 | "singleQuote": true 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 ragg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ogp](./github-assets/ogp.png) 2 | 3 | # 🌼 Fleur 🌼 [![travis](https://travis-ci.org/fleur-js/fleur.svg?branch=master)](https://travis-ci.org/fleur-js/fleur) 4 | 5 | An Fully-typed Flux framework inspired by Fluxible. 6 | Runs on Node / Web. 7 | 8 | (No dependence to React. See [this](https://www.npmjs.com/package/@fleur/react) if you want to use with React.) 9 | 10 | Social hashtag: #fleurjs 11 | 12 | ## Feature 13 | 14 | - Comfortable to write code 15 | - Fully typed. Friendly to type inference. 16 | - Next.js supported with [`create-fleur-next-app`](./packages/create-fleur-next-app) 17 | - **Completely** Server-side rendering support 18 | - Support React Hooks in `@fleur/react` 19 | 20 | ## Packages 21 | 22 | - [@fleur/fleur](./packages/fleur) - Basic flux-flow framework 23 | - [@fleur/react](./packages/react) - Fleur react connector 24 | - [@fleur/testing](./packages/testing) - Fleur Test helpers 25 | - [@fleur/create-next-app](./packages/create-next-app) - Create Next.js app with Fleur 26 | - [@fleur/next](./packages/next) - Next.js integration helpers 27 | - [@fleur/di](./packages/di) - Library independent DI function 28 | - [fleur-benchmarks](./packages/fleur-benchmarks) - Benchmarks. (Fleur vs Fluxible vs react-redux) 29 | - ~~[@fleur/route-store-dom](./packages/route-store-dom) - Fleur DOM router~~ 30 | - Use [`@fleur/froute`](https://github.com/fleur-js/froute) instead. 31 | 32 | ## Usage 33 | 34 | ### Recommended structure 35 | 36 | Fleur recommends [`Re-ducks`](https://github.com/alexnm/re-ducks) like directory structure. 37 | See file details on [`packages/fleur/README.md`](./packages/fleur/README.md) 38 | 39 | ``` 40 | app/ 41 | domains/ 42 | User/ 43 | actions.ts 44 | operations.ts 45 | store.ts 46 | selector.ts 47 | Article/ 48 | actions.ts 49 | operations.ts 50 | store.ts 51 | selector.ts 52 | # and any components structure you liked (Atomic, Smart / dumb, etc...) 53 | components/ 54 | containers/ 55 | ``` 56 | -------------------------------------------------------------------------------- /bili.default.config.js: -------------------------------------------------------------------------------- 1 | module.exports.defaultBiliConfig = { 2 | plugins: { 3 | terser: { 4 | mangle: { 5 | keep_classnames: true, 6 | }, 7 | compress: { 8 | arrows: true, 9 | arguments: true, 10 | ecma: 2015, 11 | }, 12 | output: { 13 | beautify: true, 14 | }, 15 | }, 16 | }, 17 | babel: { 18 | asyncToPromises: false, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /github-assets/ogp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanakla/fleur/ebc25bddd63d397b485467f494db14dd9b8e7bf5/github-assets/ogp.png -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @typedef {import('ts-jest/dist/types')} */ 2 | /** @type {import('@jest/types').Config.InitialOptions} */ 3 | module.exports = { 4 | rootDir: '.', 5 | preset: 'ts-jest', 6 | testRegex: 'src/.*\\.spec\\.tsx?$', 7 | moduleFileExtensions: ['ts', 'tsx', 'js'], 8 | globals: { 9 | 'ts-jest': { 10 | tsConfig: 'tsconfig.test.json', 11 | isolatedModules: true, 12 | }, 13 | }, 14 | testURL: 'http://localhost/', 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "wsrun --exclude-missing --serial -c prepublishOnly" 5 | }, 6 | "workspaces": [ 7 | "packages/*" 8 | ], 9 | "devDependencies": { 10 | "@types/jest": "26.0.20", 11 | "bili": "5.0.5", 12 | "cross-env": "7.0.3", 13 | "husky": "4.3.8", 14 | "lint-staged": "10.5.4", 15 | "npm-run-all": "^4.1.5", 16 | "prettier": "2.2.1", 17 | "ts-jest": "26.4.4", 18 | "tslint": "6.1.3", 19 | "tslint-config-prettier": "1.18.0", 20 | "typescript": "4.9.5", 21 | "wsrun": "5.2.4" 22 | }, 23 | "resolutions": { 24 | "@types/react": "^16.9.4" 25 | }, 26 | "husky": { 27 | "hooks": { 28 | "pre-commit": "lint-staged" 29 | } 30 | }, 31 | "lint-staged": { 32 | "*.{ts,tsx}": [ 33 | "tslint --fix", 34 | "prettier --write", 35 | "git add" 36 | ] 37 | }, 38 | "browserslist": [ 39 | "Chrome >= 71", 40 | "ios_saf >= 13", 41 | "safari >= 13" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /packages/create-next-app/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /bin 3 | /example/.next/ 4 | /example/next-env.d.ts 5 | /example/yarn.lock 6 | /test-build 7 | -------------------------------------------------------------------------------- /packages/create-next-app/.npmignore: -------------------------------------------------------------------------------- 1 | templates/.next 2 | templates/next-env.d.ts 3 | templates/yarn.lock 4 | -------------------------------------------------------------------------------- /packages/create-next-app/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @fleur/create-next-app Changelog 2 | 3 | ### 1.0.0 4 | 5 | Major release 6 | 7 | - Replace template by vercel/next.js#20695 8 | - Support `getServerSideProps` and `getStaticProps` 9 | - Support Automatic static render 10 | 11 | ### 0.7.0 12 | 13 | - Change package name to `@fleur/create-next-app` 14 | - Support Next.js 10 15 | - Follow @fleur/next update 16 | 17 | ### 0.6.0 18 | - dfc48c4 Fix deprecated type using 19 | 20 | ### 0.5.0 21 | - [#301](https://github.com/fleur-js/fleur/pull/301) Fix context creation each `getInitialProps` called. 22 | 23 | ### 0.4.1 24 | 25 | - [#238](https://github.com/fleur-js/fleur/pull/238) Update to use function custom `App` in create-fleur-next-app template 26 | 27 | ### 0.4.0 28 | 29 | - [#213](https://github.com/fleur-js/fleur/pull/213) Shrink `domains` example 30 | - [#213](https://github.com/fleur-js/fleur/pull/213) Using new `@fleur/next` API for serializing SSR state 31 | 32 | ### 0.3.0 33 | 34 | - [#160](https://github.com/fleur-js/fleur/pull/160) Bump up `@fleur/react` version to 3.0.0 and follow API changes 35 | 36 | ## 0.2.0 37 | 38 | - Update `@fleur/fleur-react` to `@fleur/react` 39 | 40 | ## 0.1.1 41 | 42 | - Initial release 43 | -------------------------------------------------------------------------------- /packages/create-next-app/README.md: -------------------------------------------------------------------------------- 1 | # 🌼 @fleur/create-next-app ▲ [![npm version](https://badge.fury.io/js/%40fleur%2Fcreate-next-app.svg)](https://www.npmjs.com/package/@fleur/create-next-app) 2 | 3 | Create Next.js application with [fleur](https://github.com/fleur-js/fleur) 4 | 5 | ## Quick start 6 | 7 | With yarn: `yarn create @fleur/next-app ` 8 | 9 | With npm: `npx @fleur/create-next-app --use-npm` 10 | -------------------------------------------------------------------------------- /packages/create-next-app/example/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # misc 7 | .DS_Store 8 | .env.local 9 | .env.development.local 10 | .env.test.local 11 | .env.production.local 12 | 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | 17 | # Next.js 18 | /.next 19 | /out 20 | -------------------------------------------------------------------------------- /packages/create-next-app/example/README.md: -------------------------------------------------------------------------------- 1 | # Fleur example 2 | 3 | This example shows how to integrate Fleur(@fleur/fleur) in Next.js. 4 | 5 | Fleur is an Flux framework inspired of Fluxible / Redux with modern React API. 6 | Cool type inferencibity, better testability, tuned perfomance and less re-rendering, to gives more productivity to you. 7 | 8 | See API Oveview in [Fleur's README](https://github.com/fleur-js/fleur/tree/main/packages/fleur). It's great. 9 | 10 | --- 11 | 12 | Fleur is similar to Redux. Applications are developed in four layers: Operation, Action, Store, and Component. 13 | 14 | Although each layer is separated, they work together stably through TypeScript's type inference. 15 | 16 | Since types are guaranteed by inference as much as possible, there is less code that needs to be written for type safety. The amount of typedef code required for Fleur would not be much different from the minimum amount of typedef code required for application safety. 17 | 18 | In this example, the global state of the application is managed by Fleur, and the code supports fetching data from the API via `getServerSideProps`, `getStaticProps`, and `getInitialProps` in Next.js. 19 | 20 | This example uses Fleur to manage the global state of the application, and displays a digital clock that is updated every second. 21 | 22 | The Operation is running with an async function. If you need to fetch data from the API, you can do so in the Operation, dispatch the action to the Store, and read it from the component via the `useStore` hooks. 23 | 24 | Fleur supports `getServerSideProps`, `getStaticProps`, and `getInitialProps` from Next.js, and also supports data fetching from these callbacks. 25 | 26 | ## Deploy your own 27 | 28 | Deploy the example using [Vercel](https://vercel.com): 29 | 30 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/fleur-js/fleur/tree/main/packages/create-next-app/example&project-name=with-fleur&repository-name=with-fleur) 31 | 32 | ## How to use 33 | 34 | Execute [`@fleur/create-next-app`](hhttps://github.com/fleur-js/fleur/tree/main/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: 35 | 36 | ```bash 37 | npx @fleur/create-next-app --use-npm 38 | # or 39 | yarn create @fleur/next-app 40 | ``` 41 | 42 | Deploy it to the cloud with [Vercel](https://vercel.com/import?filter=next.js) ([Documentation](https://nextjs.org/docs/deployment)). 43 | -------------------------------------------------------------------------------- /packages/create-next-app/example/components/clock.tsx: -------------------------------------------------------------------------------- 1 | import { useStore } from '@fleur/react' 2 | import { TimerStore } from '../domains/timer' 3 | 4 | const useClock = () => { 5 | return useStore((getStore) => ({ 6 | lastUpdate: getStore(TimerStore).state.lastUpdate, 7 | light: getStore(TimerStore).state.light, 8 | })) 9 | } 10 | 11 | const formatTime = (time: number) => { 12 | // cut off except hh:mm:ss 13 | return new Date(time).toJSON().slice(11, 19) 14 | } 15 | 16 | export const Clock = () => { 17 | const { lastUpdate, light } = useClock() 18 | return ( 19 |
20 | {formatTime(lastUpdate)} 21 | 34 |
35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /packages/create-next-app/example/components/counter.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useFleurContext, useStore } from '@fleur/react' 3 | import { TimerOps, TimerSelector } from '../domains/timer' 4 | 5 | const useCounter = () => { 6 | const { executeOperation } = useFleurContext() 7 | const count = useStore(TimerSelector.getCount) 8 | 9 | const increment = () => executeOperation(TimerOps.increment) 10 | const decrement = () => executeOperation(TimerOps.decrement) 11 | const reset = () => executeOperation(TimerOps.reset) 12 | 13 | return { count, increment, decrement, reset } 14 | } 15 | 16 | export const Counter = () => { 17 | const { count, increment, decrement, reset } = useCounter() 18 | 19 | return ( 20 |
21 |

22 | Count: {count} 23 |

24 | 25 | 26 | 27 |
28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /packages/create-next-app/example/components/nav.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | 3 | export const Nav = () => { 4 | return ( 5 | 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /packages/create-next-app/example/components/page.tsx: -------------------------------------------------------------------------------- 1 | import { useFleurContext } from '@fleur/react' 2 | import { TimerOps } from '../domains/timer' 3 | import { useInterval } from '../lib/useInterval' 4 | import { Clock } from './clock' 5 | import { Counter } from './counter' 6 | import { Nav } from './nav' 7 | 8 | export function Page() { 9 | const { executeOperation } = useFleurContext() 10 | 11 | // Tick the time every second 12 | useInterval(() => { 13 | executeOperation(TimerOps.tick, { light: true, lastUpdate: Date.now() }) 14 | }, 1000) 15 | 16 | return ( 17 | <> 18 |