diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 00000000..e5b6d8d6 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 00000000..ab848d1a --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "restricted", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..47c926b3 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,13 @@ +# These are supported funding model platforms + +github: [mayank1513] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: [https://pages.razorpay.com/mayank1513] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..9b77ea71 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,40 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "" +labels: "" +assignees: "" +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + +- OS: [e.g. iOS] +- Browser [e.g. chrome, safari] +- Version [e.g. 22] + +**Smartphone (please complete the following information):** + +- Device: [e.g. iPhone6] +- OS: [e.g. iOS8.1] +- Browser [e.g. stock browser, safari] +- Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..2bc5d5f7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "" +labels: "" +assignees: "" +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..e1e8acdd --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,45 @@ +name: Update dependencies and Docs + +on: + push: + branches: [main] + schedule: + - cron: "0 */8 * * *" +jobs: + generate-docs: + if: github.event.repository.owner.login == 'react18-tools' + runs-on: ubuntu-latest + permissions: + packages: write + contents: write + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/setup-node@v3 + with: + registry-url: https://registry.npmjs.org + node-version: 20 + - run: npm i -g pnpm && pnpm i + name: Install dependencies + - name: Test + run: npm test + - run: git status && git clean -f -d && git status + name: clean up working directory + - run: npx @turbo/codemod update . && pnpm update --latest -w + name: Update dependencies + - run: pnpm build + name: Build all apps to make sure it is not broken due to dependency upgrades + - name: Run unit tests + run: pnpm test + - name: Generate/update docs + run: pnpm doc + - name: Setup Git + run: | + git config --global user.name "mayank1513" + git config --global user.email "mayank.srmu@gmail.com" + git fetch + git checkout main + - name: Save upgraded packages back to repo + run: git add . && git commit -m "upgrade deps && docs" && git push origin main diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..ee8fa649 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,57 @@ +name: Publish to NPM + +# publish only when package json has changed - assuming version upgrade +on: + push: + branches: [main] + paths: "lib/fork-me/package.json" + +jobs: + publish: + # Don't run just after creating repo from template + # Also avoid running after merging set-up PR + if: github.run_number > 2 && github.event.repository.owner.login == 'react18-tools' + runs-on: ubuntu-latest + permissions: + packages: write + contents: write + id-token: write + + defaults: + run: + working-directory: ./lib/fork-me + + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/setup-node@v3 + with: + node-version: 20 + registry-url: https://registry.npmjs.org + - run: npm i -g pnpm && pnpm i + name: Install dependencies + # fail and not publish if any of the unit tests are failing + - name: Test + run: pnpm test + - name: Create release and publish to NPM + run: pnpm build && pnpm publish-package + # continue on error to publish scoped package name <- by default repo is setup for a non-scoped + scoped package name + continue-on-error: true + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} + OWNER: ${{ github.event.repository.owner.login }} + REPO: ${{ github.event.repository.name }} + + - name: Publish Scoped package to NPM + # continue on error - expecing npm to trow error if scoping is done twice + continue-on-error: true + id: publish_scoped + run: cd dist && node ../scope.js && npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} + OWNER: ${{ github.event.repository.owner.login }} + REPO: ${{ github.event.repository.name }} diff --git a/.github/workflows/setup.yml b/.github/workflows/setup.yml new file mode 100644 index 00000000..4ad1c8f9 --- /dev/null +++ b/.github/workflows/setup.yml @@ -0,0 +1,29 @@ +name: setup repo + +on: + create: + +jobs: + setup: + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + - name: Setup Git and create PR + run: | + git config --global user.name "Mayank Chaudhari" + git config --global user.email "mayank.srmu@gmail.com" + git fetch + git checkout main + - name: Set up repo + run: chmod +x ./setup.sh && (sudo bash ./setup.sh ${{ github.event.repository.owner.login }} ${{ github.event.repository.name }} || ./setup.sh ${{ github.event.repository.owner.login }} ${{ github.event.repository.name }}) + - name: Push changes back to repo + run: | + git add . + git commit -m 'Rebrand πŸ’– Mayank Kumar Chaudhari [skip ci]' + git push origin main diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..4e6efb80 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,35 @@ +name: test + +on: + push: + pull_request: + schedule: + - cron: "5 */8 * * *" +jobs: + test: + if: github.run_number != 1 + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 20 + - run: npm i -g pnpm && pnpm i + name: Install dependencies + - name: Run unit tests + run: pnpm test + - name: Upload coverage reports to Codecov + continue-on-error: true + uses: codecov/codecov-action@v3 + with: + directory: ./lib/fork-me + token: ${{ secrets.CODECOV_TOKEN }} + flags: fork-me + - uses: paambaati/codeclimate-action@v5.0.0 + continue-on-error: true + env: + CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} + with: + coverageLocations: ./lib/fork-me/coverage/*.xml:clover diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..3e6eed46 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +node_modules +.pnp +.pnp.js + +# testing +coverage + +# next.js +.next/ +out/ +build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# turbo +.turbo + +# vercel +.vercel + +# lock files +*lock* diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..ded82e2f --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +auto-install-peers = true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..7841d3f3 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +*lock.* + +# ignore hbs files as prettier removes all spaces and makes it ugly +*hbs diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..25fc6e9d --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "singleQuote": false, + "printWidth": 100, + "tabWidth": 2, + "arrowParens": "avoid", + "jsxBracketSameLine": true, + "bracketSameLine": true, + "useTabs": true +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..6315e5c1 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["esbenp.prettier-vscode", "mayank1513.trello-kanban-task-board"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..3f05f7e7 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,31 @@ +{ + // Formatting using Prettier by default for all languages + "editor.defaultFormatter": "esbenp.prettier-vscode", + // Formatting using Prettier for JavaScript, overrides VSCode default. + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + + // Ensure enough terminal history is preserved when running tests. + "terminal.integrated.scrollback": 10000, + + // Configure todo-tree to exclude node_modules, dist, and compiled. + "todo-tree.filtering.excludeGlobs": ["**/node_modules", "**/dist", "**/compiled"], + // Match TODO-APP in addition to other TODOs. + "todo-tree.general.tags": ["BUG", "HACK", "FIXME", "TODO", "XXX", "[ ]", "[x]", "TODO-APP"], + + // Disable TypeScript surveys. + "typescript.surveys.enabled": false, + + "grammarly.selectors": [ + { + "language": "markdown", + "scheme": "file" + } + ], + "editor.tabSize": 2, + "editor.wordWrap": "on", + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "editor.formatOnSaveMode": "file" +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..3b68e0fa --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,53 @@ +## Code of Conduct + +### Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +### Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others’ private information, such as a physical or email address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +### Enforcement Responsibilities + +Project maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. + +### Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project team responsible for enforcement at [coc@example.com](mailto:coc@example.com). All complaints will be reviewed and investigated promptly and fairly. + +All project maintainers are obligated to respect the privacy and security of the reporter of any incident. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, +available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct/][version] + +[homepage]: http://contributor-covenant.org +[version]: https://www.contributor-covenant.org/version/2/1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..78ecd9da --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Mayank + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..cfbd40bc --- /dev/null +++ b/README.md @@ -0,0 +1,168 @@ +# Turborepo template + +[![test](https://github.com/react18-tools/turborepo-template/actions/workflows/test.yml/badge.svg)](https://github.com/react18-tools/turborepo-template/actions/workflows/test.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/aa896ec14c570f3bb274/maintainability)](https://codeclimate.com/github/react18-tools/turborepo-template/maintainability) [![codecov](https://codecov.io/gh/react18-tools/turborepo-template/graph/badge.svg)](https://codecov.io/gh/react18-tools/turborepo-template) [![Version](https://img.shields.io/npm/v/@mayank1513/fork-me.svg?colorB=green)](https://www.npmjs.com/package/@mayank1513/fork-me) [![Downloads](https://img.jsdelivr.com/img.shields.io/npm/dt/@mayank1513/fork-me.svg)](https://www.npmjs.com/package/@mayank1513/fork-me) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/@mayank1513/fork-me) [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/from-referrer/) + +## Features + +This template offers following pre-configured features. Additionally, your repo will automatically be rebranded with help of workflow and post install scripts. + +βœ… Monorepo powered by turbo repo to build, test and deploy your library + +βœ… Next.js, Vite and Remix examples to demonstrate how your library can be used (Feel free to remove Remix as it is still unstable when it comes to monorepo setup and importing from folders) + +βœ… Examples pre-configured to use Light/Dark theme according to user preference + +βœ… The examples provided are ready to be deployed to Vercel + +βœ… Typedoc setup to automatically create documentation for your library based on tsdoc comments + +βœ… Code of Conduct and contributing files that you can always update + +βœ… Prettier and linter configured as per the modern best practices (Feel free to add your flavour) + +βœ… Recommended VSCode extensions - Prettier and [Kanban board](https://github.com/mayank1513/vscode-extension-trello-kanban-board) to auto-format your code and manage your project priorities right within your IDE + +βœ… Powerful code generators - try yarn turbo gen + +βœ… Test setup with Vitest - A modern and fast testing framework supporting Jest like APIs + +βœ… Workflows to automate running tests on every pull-request or code push events + +βœ… Workflow to automatically publish and create a GitHub release when you update your librari's `package.json` file. + +βœ… Workflow to automatically rebrand entire template based on the name of the repo you create from this template. (As soon as you create a repo from this template, setup workflow is triggered which renames @mayank1513/fork-me to your repo name and does lots of other fixes to set you up and running.) + +βœ… With all these features, this readme file contains a quick checklist for you to configure Codecov and other badges, setup your docs website on GitHub pages, etc. See [Checklist](https://github.com/react18-tools/turborepo-template/#checklist). + +#### Create a library that is + +βœ… Fully Treeshakable (import from @mayank1513/fork-me/client/component) + +βœ… Full TypeScript Support + +βœ… Unleash the full power of React18 Server components + +βœ… Works with all build systems/tools/frameworks for React18 + +βœ… Doccumented with [Typedoc](https://react18-tools.github.io/turborepo-template) ([Docs](https://react18-tools.github.io/turborepo-template)) + +## Introduction + +This template is based on the official starter Turborepo but with additional features tailored for creating and publishing JavaScript/TypeScript and specifically React18 libraries. + +## Getting started: + +Click on the `"Use this template"` button to customize it for your next JavaScript/TypeScript/React/Vue/Next.js library or project. + +## What's Different? + +Compared to the default scaffold from create-turbo, this template offers: + +- Unit tests with `vitest` +- Build setup with `tsup` and `esbuild-react18-useclient` Supports React Server components out of the box +- **Automatic file generation** + - just run `yarn turbo gen` and follow the prompts to auto generate your new component with test file and dependency linking + - follow best practices automatically +- GitHub actions/workflows to auto publish your package when version changes +- GitHub action/workflow + preinstall scripts to automatically rebrand your repo on creation + +## Step by Step Instructions and Checklist + +- [ ] Star [this repo](https://github.com/react18-tools/turborepo-template/) so that you and others can find it more easily for your next projects. It also helps me understand that people are using this repo so that I can maintain the repo and the documentation well. +- [ ] Clone this repo +- [ ] Install and setup Node.js and IDE (I prefer VSCode) +- [ ] Install the recommended VSCode extensions - [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode), [Trello Kanban](https://marketplace.visualstudio.com/items?itemName=mayank1513.trello-kanban-task-board) +- [ ] Install dependencies using `pnpm` + - [ ] If you don't have `pnpm` installed, run `npm i -g pnpm` to install `pnpm` -> run `pnpm setup` to set up `pnpm` for global installations + - [ ] Run `pnpm i` to install dependencies and `preinstall` script will automatically touch up workflows and create a commit + - [ ] Run `pnpm i -g turbo` to install `turbo` globally (Sometime due to `TypeScript` and `Plop` version conflicts code generation requires global `turbo`). + - [ ] Run `turbo gen react-component`, and follow prompts to generate server or client components for your library + - [ ] Use `snake-case` for your component name - it will be automatically converted to `PascalCase` + - [ ] Your component and test files will be created in `**/src/client/` or `**/src/server/` directory depending on whether you choose `client` or `server` component +- [ ] Set up `CodeCov` + - [ ] Visit codecov and setup your repo + - [ ] Create repository secrets for `CODECOV_TOKEN` +- [ ] Set up `CodeClimate` + - [ ] Visit CodeClimate and setup your repo + - [ ] Create repository secrets for `CC_TEST_REPORTER_ID` + - [ ] add `*.test.*` to ignore patterns on the website + - [ ] update code climate badge +- [ ] Add `NPM_AUTH_TOKEN` to repository secrets to automate publishing package + - [ ] login to your `npm` account and create automation token + - [ ] Create a new repository secrets `NPM_AUTH_TOKEN` +- [ ] Update description in `packages/@mayank1513/fork-me/package.json` +- [ ] Update Repo Stats by visiting and setting up [repobeats](https://repobeats.axiom.co/) +- [ ] Create your library and update examples +- [ ] Update README +- [ ] Setup GitHub pages to deploy docs + - [ ] Go to [repo settings](https://github.com/react18-tools/turborepo-template/settings/pages) -> pages (On left panel); Select deploy from a branch; Then Select `main` and `/docs` +- [ ] Push your changes/Create PR and see your library being automatically tested and published +- [ ] Optionally deploy your example(s) to Vercel. +- [ ] You are most welcome to star this template, contribute, and/or sponsor the `terbo-repo-template` project or my other open-source work + +## What's inside? + +### Utilities + +This Turborepo template includes pre-configured tools: + +- [TypeScript](https://www.typescriptlang.org/) for static type checking +- [ESLint](https://eslint.org/) for code linting +- [Prettier](https://prettier.io) for code formatting +- Plop based code generator for scaffolding new components +- Automatically rebrand this template to match your repo name + +### Apps and Packages + +This Turborepo includes the following packages/examples/lib: + +- `nextjs`: a [Next.js](https://nextjs.org/) app +- `vite`: a [Vite.js](https://vitest.dev) app +- `fork-me`: a React component library shared by both `Next.js` and `Vite` examples +- `eslint-config-custom`: ESLint configurations (includes `eslint-config-next` and `eslint-config-prettier`) +- `tsconfig`: `tsconfig.json`s used throughout the monorepo + +Each package/example is 100% [TypeScript](https://www.typescriptlang.org/). + +### Build + +To build all apps and packages, run the following command: + +``` +cd my-turborepo +pnpm build +``` + +### Develop + +To develop all apps and packages, run the following command: + +``` +cd my-turborepo +pnpm dev +``` + +## Useful Links + +Learn more about the power of Turborepo: + +- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) +- [Caching](https://turbo.build/repo/docs/core-concepts/caching) +- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) +- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) +- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) +- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) + +### 🀩 Don't forger to start [this repo](https://github.com/mayank1513/turborepo-template)! + +Want hands-on course for getting started with Turborepo? Check out [React and Next.js with TypeScript](https://mayank-chaudhari.vercel.app/courses/react-and-next-js-with-typescript) and [The Game of Chess with Next.js, React and TypeScrypt](https://www.udemy.com/course/game-of-chess-with-nextjs-react-and-typescrypt/?referralCode=851A28F10B254A8523FE) + +![Repo Stats](https://repobeats.axiom.co/api/embed/2ef1a24385037998386148afe5a98ded6006f410.svg "Repobeats analytics image") + +## License + +Licensed as MIT open source. + +
+ +

with πŸ’– by Mayank Kumar Chaudhari

diff --git a/contributing.md b/contributing.md new file mode 100644 index 00000000..fccc2111 --- /dev/null +++ b/contributing.md @@ -0,0 +1,92 @@ +# Contributing to fork-me + +## What's inside? + +### Utilities + +This Turborepo has some additional tools already setup for you: + +- [TypeScript](https://www.typescriptlang.org/) for static type checking +- [ESLint](https://eslint.org/) for code linting +- [Prettier](https://prettier.io) for code formatting + +### Apps and Packages + +This Turborepo includes the following packages/examples: + +- `nextjs`: a [Next.js](https://nextjs.org/) app +- `vite`: a [Vite.js](https://vitest.dev) app +- `eslint-config-custom`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) +- `tsconfig`: `tsconfig.json`s used throughout the monorepo + +To increase the visibility we have moved core library to lib + +- `fork-me`: a React component library shared by both `nextjs` and `vite` examples lives in `./lib/fork-me` + +Each package/example is 100% [TypeScript](https://www.typescriptlang.org/). + +## Automatic file generation + +- just run `yarn turbo gen` and follow the propts to auto generate your new component with test file and dependency linking +- follow best practices automatically + +### Build + +To build all apps and packages, run the following command: + +```bash +cd my-turborepo +pnpm build +``` + +### Develop + +To develop all apps and packages, run the following command: + +```bash +cd my-turborepo +pnpm dev +``` + +### Run unit tests + +To run unit tests, run the following command: + +```bash +cd my-turborepo +pnpm test +``` + +### Linting and formating + +Before creating PR make sure lint is passing and also run formatter to properly format the code. + +```bash +cd my-turborepo +pnpm lint +``` + +and + +```bash +pnpm format +``` + +## Useful Links + +Learn more about Turborepo and Next.js: + +- [React and Next.js with TypeScript](https://www.udemy.com/course/react-and-next-js-with-typescript/?referralCode=7202184A1E57C3DCA8B2) - an interactive Next.js course. +- [The Game of Chess with Next.js, React and TypeScrypt](https://www.udemy.com/course/game-of-chess-with-nextjs-react-and-typescrypt/?referralCode=851A28F10B254A8523FE) +- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) +- [Caching](https://turbo.build/repo/docs/core-concepts/caching) +- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) +- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) +- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) +- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) + +> A quick tip: Delete all stale branches `git branch --merged main | grep -v '^[ *]*main$' | xargs git branch -d` + +
+ +

with πŸ’– by Mayank Kumar Chaudhari

diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 00000000..e2ac6616 --- /dev/null +++ b/docs/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css new file mode 100644 index 00000000..0b4990d0 --- /dev/null +++ b/docs/assets/highlight.css @@ -0,0 +1,64 @@ +:root { + --light-hl-0: #795E26; + --dark-hl-0: #DCDCAA; + --light-hl-1: #000000; + --dark-hl-1: #D4D4D4; + --light-hl-2: #A31515; + --dark-hl-2: #CE9178; + --light-hl-3: #008000; + --dark-hl-3: #6A9955; + --light-hl-4: #001080; + --dark-hl-4: #9CDCFE; + --light-hl-5: #AF00DB; + --dark-hl-5: #C586C0; + --light-code-background: #FFFFFF; + --dark-code-background: #1E1E1E; +} + +@media (prefers-color-scheme: light) { :root { + --hl-0: var(--light-hl-0); + --hl-1: var(--light-hl-1); + --hl-2: var(--light-hl-2); + --hl-3: var(--light-hl-3); + --hl-4: var(--light-hl-4); + --hl-5: var(--light-hl-5); + --code-background: var(--light-code-background); +} } + +@media (prefers-color-scheme: dark) { :root { + --hl-0: var(--dark-hl-0); + --hl-1: var(--dark-hl-1); + --hl-2: var(--dark-hl-2); + --hl-3: var(--dark-hl-3); + --hl-4: var(--dark-hl-4); + --hl-5: var(--dark-hl-5); + --code-background: var(--dark-code-background); +} } + +:root[data-theme='light'] { + --hl-0: var(--light-hl-0); + --hl-1: var(--light-hl-1); + --hl-2: var(--light-hl-2); + --hl-3: var(--light-hl-3); + --hl-4: var(--light-hl-4); + --hl-5: var(--light-hl-5); + --code-background: var(--light-code-background); +} + +:root[data-theme='dark'] { + --hl-0: var(--dark-hl-0); + --hl-1: var(--dark-hl-1); + --hl-2: var(--dark-hl-2); + --hl-3: var(--dark-hl-3); + --hl-4: var(--dark-hl-4); + --hl-5: var(--dark-hl-5); + --code-background: var(--dark-code-background); +} + +.hl-0 { color: var(--hl-0); } +.hl-1 { color: var(--hl-1); } +.hl-2 { color: var(--hl-2); } +.hl-3 { color: var(--hl-3); } +.hl-4 { color: var(--hl-4); } +.hl-5 { color: var(--hl-5); } +pre, code { background: var(--code-background); } diff --git a/docs/assets/main.js b/docs/assets/main.js new file mode 100644 index 00000000..3092fea0 --- /dev/null +++ b/docs/assets/main.js @@ -0,0 +1,59 @@ +"use strict"; +"use strict";(()=>{var Ie=Object.create;var ne=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var _e=Object.getPrototypeOf,Re=Object.prototype.hasOwnProperty;var Me=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Fe=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Oe(e))!Re.call(t,i)&&i!==n&&ne(t,i,{get:()=>e[i],enumerable:!(r=Pe(e,i))||r.enumerable});return t};var De=(t,e,n)=>(n=t!=null?Ie(_e(t)):{},Fe(e||!t||!t.__esModule?ne(n,"default",{value:t,enumerable:!0}):n,t));var ae=Me((se,oe)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,u],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?d+=2:a==l&&(n+=r[u+1]*i[d+1],u+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),v=s.str.charAt(1),f;v in s.node.edges?f=s.node.edges[v]:(f=new t.TokenSet,s.node.edges[v]=f),s.str.length==1&&(f.final=!0),i.push({node:f,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof se=="object"?oe.exports=n():e.lunr=n()}(this,function(){return t})})()});var re=[];function G(t,e){re.push({selector:e,constructor:t})}var U=class{constructor(){this.alwaysVisibleMember=null;this.createComponents(document.body),this.ensureActivePageVisible(),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible())}createComponents(e){re.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r}}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(n&&n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let r=document.createElement("p");r.classList.add("warning"),r.textContent="This member is normally hidden due to your filter settings.",n.prepend(r)}}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent="Copied!",e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent="Copy"},100)},1e3)})})}};var ie=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var de=De(ae());async function le(t,e){if(!window.searchData)return;let n=await fetch(window.searchData),r=new Blob([await n.arrayBuffer()]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();t.data=i,t.index=de.Index.load(i.index),e.classList.remove("loading"),e.classList.add("ready")}function he(){let t=document.getElementById("tsd-search");if(!t)return;let e={base:t.dataset.base+"/"},n=document.getElementById("tsd-search-script");t.classList.add("loading"),n&&(n.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),n.addEventListener("load",()=>{le(e,t)}),le(e,t));let r=document.querySelector("#tsd-search input"),i=document.querySelector("#tsd-search .results");if(!r||!i)throw new Error("The input field or the result list wrapper was not found");let s=!1;i.addEventListener("mousedown",()=>s=!0),i.addEventListener("mouseup",()=>{s=!1,t.classList.remove("has-focus")}),r.addEventListener("focus",()=>t.classList.add("has-focus")),r.addEventListener("blur",()=>{s||(s=!1,t.classList.remove("has-focus"))}),Ae(t,i,r,e)}function Ae(t,e,n,r){n.addEventListener("input",ie(()=>{Ne(t,e,n,r)},200));let i=!1;n.addEventListener("keydown",s=>{i=!0,s.key=="Enter"?Ve(e,n):s.key=="Escape"?n.blur():s.key=="ArrowUp"?ue(e,-1):s.key==="ArrowDown"?ue(e,1):i=!1}),n.addEventListener("keypress",s=>{i&&s.preventDefault()}),document.body.addEventListener("keydown",s=>{s.altKey||s.ctrlKey||s.metaKey||!n.matches(":focus")&&s.key==="/"&&(n.focus(),s.preventDefault())})}function Ne(t,e,n,r){if(!r.index||!r.data)return;e.textContent="";let i=n.value.trim(),s;if(i){let o=i.split(" ").map(a=>a.length?`*${a}*`:"").join(" ");s=r.index.search(o)}else s=[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o`,d=ce(l.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(d+=` (score: ${s[o].score.toFixed(2)})`),l.parent&&(d=` + ${ce(l.parent,i)}.${d}`);let v=document.createElement("li");v.classList.value=l.classes??"";let f=document.createElement("a");f.href=r.base+l.url,f.innerHTML=u+d,v.append(f),e.appendChild(v)}}function ue(t,e){let n=t.querySelector(".current");if(!n)n=t.querySelector(e==1?"li:first-child":"li:last-child"),n&&n.classList.add("current");else{let r=n;if(e===1)do r=r.nextElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);else do r=r.previousElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);r&&(n.classList.remove("current"),r.classList.add("current"))}}function Ve(t,e){let n=t.querySelector(".current");if(n||(n=t.querySelector("li:first-child")),n){let r=n.querySelector("a");r&&(window.location.href=r.href),e.blur()}}function ce(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(K(t.substring(s,o)),`${K(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(K(t.substring(s))),i.join("")}var He={"&":"&","<":"<",">":">","'":"'",'"':"""};function K(t){return t.replace(/[&<>"'"]/g,e=>He[e])}var C=class{constructor(e){this.el=e.el,this.app=e.app}};var F="mousedown",pe="mousemove",H="mouseup",J={x:0,y:0},fe=!1,ee=!1,Be=!1,D=!1,me=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(me?"is-mobile":"not-mobile");me&&"ontouchstart"in document.documentElement&&(Be=!0,F="touchstart",pe="touchmove",H="touchend");document.addEventListener(F,t=>{ee=!0,D=!1;let e=F=="touchstart"?t.targetTouches[0]:t;J.y=e.pageY||0,J.x=e.pageX||0});document.addEventListener(pe,t=>{if(ee&&!D){let e=F=="touchstart"?t.targetTouches[0]:t,n=J.x-(e.pageX||0),r=J.y-(e.pageY||0);D=Math.sqrt(n*n+r*r)>10}});document.addEventListener(H,()=>{ee=!1});document.addEventListener("click",t=>{fe&&(t.preventDefault(),t.stopImmediatePropagation(),fe=!1)});var X=class extends C{constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener(H,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(F,n=>this.onDocumentPointerDown(n)),document.addEventListener(H,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){D||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!D&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var te;try{te=localStorage}catch{te={getItem(){return null},setItem(){}}}var Q=te;var ve=document.head.appendChild(document.createElement("style"));ve.dataset.for="filters";var Y=class extends C{constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),ve.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } +`,this.updateIndexHeadingVisibility()}fromLocalStorage(){let e=Q.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){Q.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),this.updateIndexHeadingVisibility()}updateIndexHeadingVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}};var Z=class extends C{constructor(e){super(e),this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.dataset.key??this.summary.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`;let n=Q.getItem(this.key);this.el.open=n?n==="true":this.el.open,this.el.addEventListener("toggle",()=>this.update());let r=this.summary.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)}),this.update()}update(){this.icon.style.transform=`rotate(${this.el.open?0:-90}deg)`,Q.setItem(this.key,this.el.open.toString())}};function ge(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,ye(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),ye(t.value)})}function ye(t){document.documentElement.dataset.theme=t}var Le;function be(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",xe),xe())}async function xe(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let n=await(await fetch(window.navigationData)).arrayBuffer(),r=new Blob([n]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();Le=t.dataset.base+"/",t.innerHTML="";for(let s of i)we(s,t,[]);window.app.createComponents(t),window.app.ensureActivePageVisible()}function we(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-index-accordion`:"tsd-index-accordion",s.dataset.key=i.join("$");let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.innerHTML='',Ee(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let l=a.appendChild(document.createElement("ul"));l.className="tsd-nested-navigation";for(let u of t.children)we(u,l,i)}else Ee(t,r,t.class)}function Ee(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));r.href=Le+t.path,n&&(r.className=n),location.href===r.href&&r.classList.add("current"),t.kind&&(r.innerHTML=``),r.appendChild(document.createElement("span")).textContent=t.text}else e.appendChild(document.createElement("span")).textContent=t.text}G(X,"a[data-toggle]");G(Z,".tsd-index-accordion");G(Y,".tsd-filter-item input[type=checkbox]");var Se=document.getElementById("tsd-theme");Se&&ge(Se);var je=new U;Object.defineProperty(window,"app",{value:je});he();be();})(); +/*! Bundled license information: + +lunr/lunr.js: + (** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 + * Copyright (C) 2020 Oliver Nightingale + * @license MIT + *) + (*! + * lunr.utils + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Set + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.tokenizer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Pipeline + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Vector + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.stemmer + * Copyright (C) 2020 Oliver Nightingale + * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt + *) + (*! + * lunr.stopWordFilter + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.trimmer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.TokenSet + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Index + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Builder + * Copyright (C) 2020 Oliver Nightingale + *) +*/ diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js new file mode 100644 index 00000000..9e4a8838 --- /dev/null +++ b/docs/assets/navigation.js @@ -0,0 +1 @@ +window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA42PwQqDMBBE/2XPaYVSesgH9NZTjyISkhWDSSzrWgrFfy8hKrYq9DSH2Xk7k7+B8cUgQTuLgbOOFR08TgoCHoprkOBb0zvssnRXRr/0OOmxZu9AQGODAXkSoGvrDGEAmc8v7qzotkBWfdBs27ALTYFv9uU8FIOYmQa1U6QiZt11Yf4UXBA6pCdSVrXUxOGjrmHprox+7DjqX8OvLTXbw3egKbAxvPgAWspRvLEBAAA=" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js new file mode 100644 index 00000000..81294ee6 --- /dev/null +++ b/docs/assets/search.js @@ -0,0 +1 @@ +window.searchData = "data:application/octet-stream;base64,H4sIAAAAAAAAA42Sy26DMBBF/+Wup4RXSOMPqNRFV5W6sVCEYKKi8IgMSSsh/r0yjxoSSLsyie+5M3M9DVT5VUHIBqe0SCBcQhHlDIE4S7moN1UdqaecxxOEi8ogkJfJJeNq08sO+vqQ83han3WegRBnUVVxBQG0NNYI/N8i73Wk3ozp8VLEdVoWq7a9fsGdcI4UF/V646a+mTHhOItUpEveDTa5eziNcatYXVltjqU66cLDeWfcyw76Wo82nP9N7KVUp8XEVmx7/ePEVhpvQ0JaJPwN0eDKqtIxCbiWZ+1BOKacJXp3+tYIcZnn2jAc7j44rkulFb1kY4OkTY5tPe9dcsYPlwLrebcPQ5KjRafs/ug4ByQ9cgJr7/szmTOTuSDpL8ncmcwDyaEmbccmguFjxnkzzgfJ3ZK938m6sK6sak5e+9CknO4iqMFhiNMen7OBDdG0rQlP/9Lms9U0pG9Id4XUz6ffw0A7A/kr0Bxwb/ojeKtcty5TODDwA+o2EufvSCZrOiW3f9fTxeYTegZylqCQcE7PnKUFQ8iwbX8AMFKCFSoFAAA="; \ No newline at end of file diff --git a/docs/assets/style.css b/docs/assets/style.css new file mode 100644 index 00000000..98a43779 --- /dev/null +++ b/docs/assets/style.css @@ -0,0 +1,1414 @@ +:root { + /* Light */ + --light-color-background: #f2f4f8; + --light-color-background-secondary: #eff0f1; + --light-color-warning-text: #222; + --light-color-background-warning: #e6e600; + --light-color-icon-background: var(--light-color-background); + --light-color-accent: #c5c7c9; + --light-color-active-menu-item: var(--light-color-accent); + --light-color-text: #222; + --light-color-text-aside: #6e6e6e; + --light-color-link: #1f70c2; + + --light-color-ts-keyword: #056bd6; + --light-color-ts-project: #b111c9; + --light-color-ts-module: var(--light-color-ts-project); + --light-color-ts-namespace: var(--light-color-ts-project); + --light-color-ts-enum: #7e6f15; + --light-color-ts-enum-member: var(--light-color-ts-enum); + --light-color-ts-variable: #4760ec; + --light-color-ts-function: #572be7; + --light-color-ts-class: #1f70c2; + --light-color-ts-interface: #108024; + --light-color-ts-constructor: var(--light-color-ts-class); + --light-color-ts-property: var(--light-color-ts-variable); + --light-color-ts-method: var(--light-color-ts-function); + --light-color-ts-call-signature: var(--light-color-ts-method); + --light-color-ts-index-signature: var(--light-color-ts-property); + --light-color-ts-constructor-signature: var(--light-color-ts-constructor); + --light-color-ts-parameter: var(--light-color-ts-variable); + /* type literal not included as links will never be generated to it */ + --light-color-ts-type-parameter: #a55c0e; + --light-color-ts-accessor: var(--light-color-ts-property); + --light-color-ts-get-signature: var(--light-color-ts-accessor); + --light-color-ts-set-signature: var(--light-color-ts-accessor); + --light-color-ts-type-alias: #d51270; + /* reference not included as links will be colored with the kind that it points to */ + + --light-external-icon: url("data:image/svg+xml;utf8,"); + --light-color-scheme: light; + + /* Dark */ + --dark-color-background: #2b2e33; + --dark-color-background-secondary: #1e2024; + --dark-color-background-warning: #bebe00; + --dark-color-warning-text: #222; + --dark-color-icon-background: var(--dark-color-background-secondary); + --dark-color-accent: #9096a2; + --dark-color-active-menu-item: #5d5d6a; + --dark-color-text: #f5f5f5; + --dark-color-text-aside: #dddddd; + --dark-color-link: #00aff4; + + --dark-color-ts-keyword: #3399ff; + --dark-color-ts-project: #e358ff; + --dark-color-ts-module: var(--dark-color-ts-project); + --dark-color-ts-namespace: var(--dark-color-ts-project); + --dark-color-ts-enum: #f4d93e; + --dark-color-ts-enum-member: var(--dark-color-ts-enum); + --dark-color-ts-variable: #798dff; + --dark-color-ts-function: #a280ff; + --dark-color-ts-class: #8ac4ff; + --dark-color-ts-interface: #6cff87; + --dark-color-ts-constructor: var(--dark-color-ts-class); + --dark-color-ts-property: var(--dark-color-ts-variable); + --dark-color-ts-method: var(--dark-color-ts-function); + --dark-color-ts-call-signature: var(--dark-color-ts-method); + --dark-color-ts-index-signature: var(--dark-color-ts-property); + --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor); + --dark-color-ts-parameter: var(--dark-color-ts-variable); + /* type literal not included as links will never be generated to it */ + --dark-color-ts-type-parameter: #e07d13; + --dark-color-ts-accessor: var(--dark-color-ts-property); + --dark-color-ts-get-signature: var(--dark-color-ts-accessor); + --dark-color-ts-set-signature: var(--dark-color-ts-accessor); + --dark-color-ts-type-alias: #ff6492; + /* reference not included as links will be colored with the kind that it points to */ + + --dark-external-icon: url("data:image/svg+xml;utf8,"); + --dark-color-scheme: dark; +} + +@media (prefers-color-scheme: light) { + :root { + --color-background: var(--light-color-background); + --color-background-secondary: var(--light-color-background-secondary); + --color-background-warning: var(--light-color-background-warning); + --color-warning-text: var(--light-color-warning-text); + --color-icon-background: var(--light-color-icon-background); + --color-accent: var(--light-color-accent); + --color-active-menu-item: var(--light-color-active-menu-item); + --color-text: var(--light-color-text); + --color-text-aside: var(--light-color-text-aside); + --color-link: var(--light-color-link); + + --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-module: var(--light-color-ts-module); + --color-ts-namespace: var(--light-color-ts-namespace); + --color-ts-enum: var(--light-color-ts-enum); + --color-ts-enum-member: var(--light-color-ts-enum-member); + --color-ts-variable: var(--light-color-ts-variable); + --color-ts-function: var(--light-color-ts-function); + --color-ts-class: var(--light-color-ts-class); + --color-ts-interface: var(--light-color-ts-interface); + --color-ts-constructor: var(--light-color-ts-constructor); + --color-ts-property: var(--light-color-ts-property); + --color-ts-method: var(--light-color-ts-method); + --color-ts-call-signature: var(--light-color-ts-call-signature); + --color-ts-index-signature: var(--light-color-ts-index-signature); + --color-ts-constructor-signature: var( + --light-color-ts-constructor-signature + ); + --color-ts-parameter: var(--light-color-ts-parameter); + --color-ts-type-parameter: var(--light-color-ts-type-parameter); + --color-ts-accessor: var(--light-color-ts-accessor); + --color-ts-get-signature: var(--light-color-ts-get-signature); + --color-ts-set-signature: var(--light-color-ts-set-signature); + --color-ts-type-alias: var(--light-color-ts-type-alias); + + --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); + } +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--dark-color-background); + --color-background-secondary: var(--dark-color-background-secondary); + --color-background-warning: var(--dark-color-background-warning); + --color-warning-text: var(--dark-color-warning-text); + --color-icon-background: var(--dark-color-icon-background); + --color-accent: var(--dark-color-accent); + --color-active-menu-item: var(--dark-color-active-menu-item); + --color-text: var(--dark-color-text); + --color-text-aside: var(--dark-color-text-aside); + --color-link: var(--dark-color-link); + + --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-module: var(--dark-color-ts-module); + --color-ts-namespace: var(--dark-color-ts-namespace); + --color-ts-enum: var(--dark-color-ts-enum); + --color-ts-enum-member: var(--dark-color-ts-enum-member); + --color-ts-variable: var(--dark-color-ts-variable); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-class: var(--dark-color-ts-class); + --color-ts-interface: var(--dark-color-ts-interface); + --color-ts-constructor: var(--dark-color-ts-constructor); + --color-ts-property: var(--dark-color-ts-property); + --color-ts-method: var(--dark-color-ts-method); + --color-ts-call-signature: var(--dark-color-ts-call-signature); + --color-ts-index-signature: var(--dark-color-ts-index-signature); + --color-ts-constructor-signature: var( + --dark-color-ts-constructor-signature + ); + --color-ts-parameter: var(--dark-color-ts-parameter); + --color-ts-type-parameter: var(--dark-color-ts-type-parameter); + --color-ts-accessor: var(--dark-color-ts-accessor); + --color-ts-get-signature: var(--dark-color-ts-get-signature); + --color-ts-set-signature: var(--dark-color-ts-set-signature); + --color-ts-type-alias: var(--dark-color-ts-type-alias); + + --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); + } +} + +html { + color-scheme: var(--color-scheme); +} + +body { + margin: 0; +} + +:root[data-theme="light"] { + --color-background: var(--light-color-background); + --color-background-secondary: var(--light-color-background-secondary); + --color-background-warning: var(--light-color-background-warning); + --color-warning-text: var(--light-color-warning-text); + --color-icon-background: var(--light-color-icon-background); + --color-accent: var(--light-color-accent); + --color-active-menu-item: var(--light-color-active-menu-item); + --color-text: var(--light-color-text); + --color-text-aside: var(--light-color-text-aside); + --color-link: var(--light-color-link); + + --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-module: var(--light-color-ts-module); + --color-ts-namespace: var(--light-color-ts-namespace); + --color-ts-enum: var(--light-color-ts-enum); + --color-ts-enum-member: var(--light-color-ts-enum-member); + --color-ts-variable: var(--light-color-ts-variable); + --color-ts-function: var(--light-color-ts-function); + --color-ts-class: var(--light-color-ts-class); + --color-ts-interface: var(--light-color-ts-interface); + --color-ts-constructor: var(--light-color-ts-constructor); + --color-ts-property: var(--light-color-ts-property); + --color-ts-method: var(--light-color-ts-method); + --color-ts-call-signature: var(--light-color-ts-call-signature); + --color-ts-index-signature: var(--light-color-ts-index-signature); + --color-ts-constructor-signature: var( + --light-color-ts-constructor-signature + ); + --color-ts-parameter: var(--light-color-ts-parameter); + --color-ts-type-parameter: var(--light-color-ts-type-parameter); + --color-ts-accessor: var(--light-color-ts-accessor); + --color-ts-get-signature: var(--light-color-ts-get-signature); + --color-ts-set-signature: var(--light-color-ts-set-signature); + --color-ts-type-alias: var(--light-color-ts-type-alias); + + --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); +} + +:root[data-theme="dark"] { + --color-background: var(--dark-color-background); + --color-background-secondary: var(--dark-color-background-secondary); + --color-background-warning: var(--dark-color-background-warning); + --color-warning-text: var(--dark-color-warning-text); + --color-icon-background: var(--dark-color-icon-background); + --color-accent: var(--dark-color-accent); + --color-active-menu-item: var(--dark-color-active-menu-item); + --color-text: var(--dark-color-text); + --color-text-aside: var(--dark-color-text-aside); + --color-link: var(--dark-color-link); + + --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-module: var(--dark-color-ts-module); + --color-ts-namespace: var(--dark-color-ts-namespace); + --color-ts-enum: var(--dark-color-ts-enum); + --color-ts-enum-member: var(--dark-color-ts-enum-member); + --color-ts-variable: var(--dark-color-ts-variable); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-class: var(--dark-color-ts-class); + --color-ts-interface: var(--dark-color-ts-interface); + --color-ts-constructor: var(--dark-color-ts-constructor); + --color-ts-property: var(--dark-color-ts-property); + --color-ts-method: var(--dark-color-ts-method); + --color-ts-call-signature: var(--dark-color-ts-call-signature); + --color-ts-index-signature: var(--dark-color-ts-index-signature); + --color-ts-constructor-signature: var( + --dark-color-ts-constructor-signature + ); + --color-ts-parameter: var(--dark-color-ts-parameter); + --color-ts-type-parameter: var(--dark-color-ts-type-parameter); + --color-ts-accessor: var(--dark-color-ts-accessor); + --color-ts-get-signature: var(--dark-color-ts-get-signature); + --color-ts-set-signature: var(--dark-color-ts-set-signature); + --color-ts-type-alias: var(--dark-color-ts-type-alias); + + --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); +} + +.always-visible, +.always-visible .tsd-signatures { + display: inherit !important; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + line-height: 1.2; +} + +h1 > a:not(.link), +h2 > a:not(.link), +h3 > a:not(.link), +h4 > a:not(.link), +h5 > a:not(.link), +h6 > a:not(.link) { + text-decoration: none; + color: var(--color-text); +} + +h1 { + font-size: 1.875rem; + margin: 0.67rem 0; +} + +h2 { + font-size: 1.5rem; + margin: 0.83rem 0; +} + +h3 { + font-size: 1.25rem; + margin: 1rem 0; +} + +h4 { + font-size: 1.05rem; + margin: 1.33rem 0; +} + +h5 { + font-size: 1rem; + margin: 1.5rem 0; +} + +h6 { + font-size: 0.875rem; + margin: 2.33rem 0; +} + +.uppercase { + text-transform: uppercase; +} + +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +.container { + max-width: 1700px; + padding: 0 2rem; +} + +/* Footer */ +.tsd-generator { + border-top: 1px solid var(--color-accent); + padding-top: 1rem; + padding-bottom: 1rem; + max-height: 3.5rem; +} + +.tsd-generator > p { + margin-top: 0; + margin-bottom: 0; + padding: 0 1rem; +} + +.container-main { + margin: 0 auto; + /* toolbar, footer, margin */ + min-height: calc(100vh - 41px - 56px - 4rem); +} + +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@keyframes fade-out { + from { + opacity: 1; + visibility: visible; + } + to { + opacity: 0; + } +} +@keyframes fade-in-delayed { + 0% { + opacity: 0; + } + 33% { + opacity: 0; + } + 100% { + opacity: 1; + } +} +@keyframes fade-out-delayed { + 0% { + opacity: 1; + visibility: visible; + } + 66% { + opacity: 0; + } + 100% { + opacity: 0; + } +} +@keyframes pop-in-from-right { + from { + transform: translate(100%, 0); + } + to { + transform: translate(0, 0); + } +} +@keyframes pop-out-to-right { + from { + transform: translate(0, 0); + visibility: visible; + } + to { + transform: translate(100%, 0); + } +} +body { + background: var(--color-background); + font-family: "Segoe UI", sans-serif; + font-size: 16px; + color: var(--color-text); +} + +a { + color: var(--color-link); + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +a.external[target="_blank"] { + background-image: var(--external-icon); + background-position: top 3px right; + background-repeat: no-repeat; + padding-right: 13px; +} + +code, +pre { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + padding: 0.2em; + margin: 0; + font-size: 0.875rem; + border-radius: 0.8em; +} + +pre { + position: relative; + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; + padding: 10px; + border: 1px solid var(--color-accent); +} +pre code { + padding: 0; + font-size: 100%; +} +pre > button { + position: absolute; + top: 10px; + right: 10px; + opacity: 0; + transition: opacity 0.1s; + box-sizing: border-box; +} +pre:hover > button, +pre > button.visible { + opacity: 1; +} + +blockquote { + margin: 1em 0; + padding-left: 1em; + border-left: 4px solid gray; +} + +.tsd-typography { + line-height: 1.333em; +} +.tsd-typography ul { + list-style: square; + padding: 0 0 0 20px; + margin: 0; +} +.tsd-typography .tsd-index-panel h3, +.tsd-index-panel .tsd-typography h3, +.tsd-typography h4, +.tsd-typography h5, +.tsd-typography h6 { + font-size: 1em; +} +.tsd-typography h5, +.tsd-typography h6 { + font-weight: normal; +} +.tsd-typography p, +.tsd-typography ul, +.tsd-typography ol { + margin: 1em 0; +} +.tsd-typography table { + border-collapse: collapse; + border: none; +} +.tsd-typography td, +.tsd-typography th { + padding: 6px 13px; + border: 1px solid var(--color-accent); +} +.tsd-typography thead, +.tsd-typography tr:nth-child(even) { + background-color: var(--color-background-secondary); +} + +.tsd-breadcrumb { + margin: 0; + padding: 0; + color: var(--color-text-aside); +} +.tsd-breadcrumb a { + color: var(--color-text-aside); + text-decoration: none; +} +.tsd-breadcrumb a:hover { + text-decoration: underline; +} +.tsd-breadcrumb li { + display: inline; +} +.tsd-breadcrumb li:after { + content: " / "; +} + +.tsd-comment-tags { + display: flex; + flex-direction: column; +} +dl.tsd-comment-tag-group { + display: flex; + align-items: center; + overflow: hidden; + margin: 0.5em 0; +} +dl.tsd-comment-tag-group dt { + display: flex; + margin-right: 0.5em; + font-size: 0.875em; + font-weight: normal; +} +dl.tsd-comment-tag-group dd { + margin: 0; +} +code.tsd-tag { + padding: 0.25em 0.4em; + border: 0.1em solid var(--color-accent); + margin-right: 0.25em; + font-size: 70%; +} +h1 code.tsd-tag:first-of-type { + margin-left: 0.25em; +} + +dl.tsd-comment-tag-group dd:before, +dl.tsd-comment-tag-group dd:after { + content: " "; +} +dl.tsd-comment-tag-group dd pre, +dl.tsd-comment-tag-group dd:after { + clear: both; +} +dl.tsd-comment-tag-group p { + margin: 0; +} + +.tsd-panel.tsd-comment .lead { + font-size: 1.1em; + line-height: 1.333em; + margin-bottom: 2em; +} +.tsd-panel.tsd-comment .lead:last-child { + margin-bottom: 0; +} + +.tsd-filter-visibility h4 { + font-size: 1rem; + padding-top: 0.75rem; + padding-bottom: 0.5rem; + margin: 0; +} +.tsd-filter-item:not(:last-child) { + margin-bottom: 0.5rem; +} +.tsd-filter-input { + display: flex; + width: fit-content; + width: -moz-fit-content; + align-items: center; + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + cursor: pointer; +} +.tsd-filter-input input[type="checkbox"] { + cursor: pointer; + position: absolute; + width: 1.5em; + height: 1.5em; + opacity: 0; +} +.tsd-filter-input input[type="checkbox"]:disabled { + pointer-events: none; +} +.tsd-filter-input svg { + cursor: pointer; + width: 1.5em; + height: 1.5em; + margin-right: 0.5em; + border-radius: 0.33em; + /* Leaving this at full opacity breaks event listeners on Firefox. + Don't remove unless you know what you're doing. */ + opacity: 0.99; +} +.tsd-filter-input input[type="checkbox"]:focus + svg { + transform: scale(0.95); +} +.tsd-filter-input input[type="checkbox"]:focus:not(:focus-visible) + svg { + transform: scale(1); +} +.tsd-checkbox-background { + fill: var(--color-accent); +} +input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { + stroke: var(--color-text); +} +.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { + fill: var(--color-background); + stroke: var(--color-accent); + stroke-width: 0.25rem; +} +.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { + stroke: var(--color-accent); +} + +.tsd-theme-toggle { + padding-top: 0.75rem; +} +.tsd-theme-toggle > h4 { + display: inline; + vertical-align: middle; + margin-right: 0.75rem; +} + +.tsd-hierarchy { + list-style: square; + margin: 0; +} +.tsd-hierarchy .target { + font-weight: bold; +} + +.tsd-full-hierarchy:not(:last-child) { + margin-bottom: 1em; + padding-bottom: 1em; + border-bottom: 1px solid var(--color-accent); +} +.tsd-full-hierarchy, +.tsd-full-hierarchy ul { + list-style: none; + margin: 0; + padding: 0; +} +.tsd-full-hierarchy ul { + padding-left: 1.5rem; +} +.tsd-full-hierarchy a { + padding: 0.25rem 0 !important; + font-size: 1rem; + display: inline-flex; + align-items: center; + color: var(--color-text); +} + +.tsd-panel-group.tsd-index-group { + margin-bottom: 0; +} +.tsd-index-panel .tsd-index-list { + list-style: none; + line-height: 1.333em; + margin: 0; + padding: 0.25rem 0 0 0; + overflow: hidden; + display: grid; + grid-template-columns: repeat(3, 1fr); + column-gap: 1rem; + grid-template-rows: auto; +} +@media (max-width: 1024px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(2, 1fr); + } +} +@media (max-width: 768px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(1, 1fr); + } +} +.tsd-index-panel .tsd-index-list li { + -webkit-page-break-inside: avoid; + -moz-page-break-inside: avoid; + -ms-page-break-inside: avoid; + -o-page-break-inside: avoid; + page-break-inside: avoid; +} + +.tsd-flag { + display: inline-block; + padding: 0.25em 0.4em; + border-radius: 4px; + color: var(--color-comment-tag-text); + background-color: var(--color-comment-tag); + text-indent: 0; + font-size: 75%; + line-height: 1; + font-weight: normal; +} + +.tsd-anchor { + position: relative; + top: -100px; +} + +.tsd-member { + position: relative; +} +.tsd-member .tsd-anchor + h3 { + display: flex; + align-items: center; + margin-top: 0; + margin-bottom: 0; + border-bottom: none; +} + +.tsd-navigation.settings { + margin: 1rem 0; +} +.tsd-navigation > a, +.tsd-navigation .tsd-accordion-summary { + width: calc(100% - 0.25rem); + display: flex; + align-items: center; +} +.tsd-navigation a, +.tsd-navigation summary > span, +.tsd-page-navigation a { + display: flex; + width: calc(100% - 0.25rem); + align-items: center; + padding: 0.25rem; + color: var(--color-text); + text-decoration: none; + box-sizing: border-box; +} +.tsd-navigation a.current, +.tsd-page-navigation a.current { + background: var(--color-active-menu-item); +} +.tsd-navigation a:hover, +.tsd-page-navigation a:hover { + text-decoration: underline; +} +.tsd-navigation ul, +.tsd-page-navigation ul { + margin-top: 0; + margin-bottom: 0; + padding: 0; + list-style: none; +} +.tsd-navigation li, +.tsd-page-navigation li { + padding: 0; + max-width: 100%; +} +.tsd-nested-navigation { + margin-left: 3rem; +} +.tsd-nested-navigation > li > details { + margin-left: -1.5rem; +} +.tsd-small-nested-navigation { + margin-left: 1.5rem; +} +.tsd-small-nested-navigation > li > details { + margin-left: -1.5rem; +} + +.tsd-page-navigation ul { + padding-left: 1.75rem; +} + +#tsd-sidebar-links a { + margin-top: 0; + margin-bottom: 0.5rem; + line-height: 1.25rem; +} +#tsd-sidebar-links a:last-of-type { + margin-bottom: 0; +} + +a.tsd-index-link { + padding: 0.25rem 0 !important; + font-size: 1rem; + line-height: 1.25rem; + display: inline-flex; + align-items: center; + color: var(--color-text); +} +.tsd-accordion-summary { + list-style-type: none; /* hide marker on non-safari */ + outline: none; /* broken on safari, so just hide it */ +} +.tsd-accordion-summary::-webkit-details-marker { + display: none; /* hide marker on safari */ +} +.tsd-accordion-summary, +.tsd-accordion-summary a { + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + + cursor: pointer; +} +.tsd-accordion-summary a { + width: calc(100% - 1.5rem); +} +.tsd-accordion-summary > * { + margin-top: 0; + margin-bottom: 0; + padding-top: 0; + padding-bottom: 0; +} +.tsd-index-accordion .tsd-accordion-summary > svg { + margin-left: 0.25rem; +} +.tsd-index-content > :not(:first-child) { + margin-top: 0.75rem; +} +.tsd-index-heading { + margin-top: 1.5rem; + margin-bottom: 0.75rem; +} + +.tsd-kind-icon { + margin-right: 0.5rem; + width: 1.25rem; + height: 1.25rem; + min-width: 1.25rem; + min-height: 1.25rem; +} +.tsd-kind-icon path { + transform-origin: center; + transform: scale(1.1); +} +.tsd-signature > .tsd-kind-icon { + margin-right: 0.8rem; +} + +.tsd-panel { + margin-bottom: 2.5rem; +} +.tsd-panel.tsd-member { + margin-bottom: 4rem; +} +.tsd-panel:empty { + display: none; +} +.tsd-panel > h1, +.tsd-panel > h2, +.tsd-panel > h3 { + margin: 1.5rem -1.5rem 0.75rem -1.5rem; + padding: 0 1.5rem 0.75rem 1.5rem; +} +.tsd-panel > h1.tsd-before-signature, +.tsd-panel > h2.tsd-before-signature, +.tsd-panel > h3.tsd-before-signature { + margin-bottom: 0; + border-bottom: none; +} + +.tsd-panel-group { + margin: 4rem 0; +} +.tsd-panel-group.tsd-index-group { + margin: 2rem 0; +} +.tsd-panel-group.tsd-index-group details { + margin: 2rem 0; +} + +#tsd-search { + transition: background-color 0.2s; +} +#tsd-search .title { + position: relative; + z-index: 2; +} +#tsd-search .field { + position: absolute; + left: 0; + top: 0; + right: 2.5rem; + height: 100%; +} +#tsd-search .field input { + box-sizing: border-box; + position: relative; + top: -50px; + z-index: 1; + width: 100%; + padding: 0 10px; + opacity: 0; + outline: 0; + border: 0; + background: transparent; + color: var(--color-text); +} +#tsd-search .field label { + position: absolute; + overflow: hidden; + right: -40px; +} +#tsd-search .field input, +#tsd-search .title, +#tsd-toolbar-links a { + transition: opacity 0.2s; +} +#tsd-search .results { + position: absolute; + visibility: hidden; + top: 40px; + width: 100%; + margin: 0; + padding: 0; + list-style: none; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); +} +#tsd-search .results li { + background-color: var(--color-background); + line-height: initial; + padding: 4px; +} +#tsd-search .results li:nth-child(even) { + background-color: var(--color-background-secondary); +} +#tsd-search .results li.state { + display: none; +} +#tsd-search .results li.current:not(.no-results), +#tsd-search .results li:hover:not(.no-results) { + background-color: var(--color-accent); +} +#tsd-search .results a { + display: flex; + align-items: center; + padding: 0.25rem; + box-sizing: border-box; +} +#tsd-search .results a:before { + top: 10px; +} +#tsd-search .results span.parent { + color: var(--color-text-aside); + font-weight: normal; +} +#tsd-search.has-focus { + background-color: var(--color-accent); +} +#tsd-search.has-focus .field input { + top: 0; + opacity: 1; +} +#tsd-search.has-focus .title, +#tsd-search.has-focus #tsd-toolbar-links a { + z-index: 0; + opacity: 0; +} +#tsd-search.has-focus .results { + visibility: visible; +} +#tsd-search.loading .results li.state.loading { + display: block; +} +#tsd-search.failure .results li.state.failure { + display: block; +} + +#tsd-toolbar-links { + position: absolute; + top: 0; + right: 2rem; + height: 100%; + display: flex; + align-items: center; + justify-content: flex-end; +} +#tsd-toolbar-links a { + margin-left: 1.5rem; +} +#tsd-toolbar-links a:hover { + text-decoration: underline; +} + +.tsd-signature { + margin: 0 0 1rem 0; + padding: 1rem 0.5rem; + border: 1px solid var(--color-accent); + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-size: 14px; + overflow-x: auto; +} + +.tsd-signature-keyword { + color: var(--color-ts-keyword); + font-weight: normal; +} + +.tsd-signature-symbol { + color: var(--color-text-aside); + font-weight: normal; +} + +.tsd-signature-type { + font-style: italic; + font-weight: normal; +} + +.tsd-signatures { + padding: 0; + margin: 0 0 1em 0; + list-style-type: none; +} +.tsd-signatures .tsd-signature { + margin: 0; + border-color: var(--color-accent); + border-width: 1px 0; + transition: background-color 0.1s; +} +.tsd-description .tsd-signatures .tsd-signature { + border-width: 1px; +} + +ul.tsd-parameter-list, +ul.tsd-type-parameter-list { + list-style: square; + margin: 0; + padding-left: 20px; +} +ul.tsd-parameter-list > li.tsd-parameter-signature, +ul.tsd-type-parameter-list > li.tsd-parameter-signature { + list-style: none; + margin-left: -20px; +} +ul.tsd-parameter-list h5, +ul.tsd-type-parameter-list h5 { + font-size: 16px; + margin: 1em 0 0.5em 0; +} +.tsd-sources { + margin-top: 1rem; + font-size: 0.875em; +} +.tsd-sources a { + color: var(--color-text-aside); + text-decoration: underline; +} +.tsd-sources ul { + list-style: none; + padding: 0; +} + +.tsd-page-toolbar { + position: sticky; + z-index: 1; + top: 0; + left: 0; + width: 100%; + color: var(--color-text); + background: var(--color-background-secondary); + border-bottom: 1px var(--color-accent) solid; + transition: transform 0.3s ease-in-out; +} +.tsd-page-toolbar a { + color: var(--color-text); + text-decoration: none; +} +.tsd-page-toolbar a.title { + font-weight: bold; +} +.tsd-page-toolbar a.title:hover { + text-decoration: underline; +} +.tsd-page-toolbar .tsd-toolbar-contents { + display: flex; + justify-content: space-between; + height: 2.5rem; + margin: 0 auto; +} +.tsd-page-toolbar .table-cell { + position: relative; + white-space: nowrap; + line-height: 40px; +} +.tsd-page-toolbar .table-cell:first-child { + width: 100%; +} +.tsd-page-toolbar .tsd-toolbar-icon { + box-sizing: border-box; + line-height: 0; + padding: 12px 0; +} + +.tsd-widget { + display: inline-block; + overflow: hidden; + opacity: 0.8; + height: 40px; + transition: + opacity 0.1s, + background-color 0.2s; + vertical-align: bottom; + cursor: pointer; +} +.tsd-widget:hover { + opacity: 0.9; +} +.tsd-widget.active { + opacity: 1; + background-color: var(--color-accent); +} +.tsd-widget.no-caption { + width: 40px; +} +.tsd-widget.no-caption:before { + margin: 0; +} + +.tsd-widget.options, +.tsd-widget.menu { + display: none; +} +input[type="checkbox"] + .tsd-widget:before { + background-position: -120px 0; +} +input[type="checkbox"]:checked + .tsd-widget:before { + background-position: -160px 0; +} + +img { + max-width: 100%; +} + +.tsd-anchor-icon { + display: inline-flex; + align-items: center; + margin-left: 0.5rem; + vertical-align: middle; + color: var(--color-text); +} + +.tsd-anchor-icon svg { + width: 1em; + height: 1em; + visibility: hidden; +} + +.tsd-anchor-link:hover > .tsd-anchor-icon svg { + visibility: visible; +} + +.deprecated { + text-decoration: line-through !important; +} + +.warning { + padding: 1rem; + color: var(--color-warning-text); + background: var(--color-background-warning); +} + +.tsd-kind-project { + color: var(--color-ts-project); +} +.tsd-kind-module { + color: var(--color-ts-module); +} +.tsd-kind-namespace { + color: var(--color-ts-namespace); +} +.tsd-kind-enum { + color: var(--color-ts-enum); +} +.tsd-kind-enum-member { + color: var(--color-ts-enum-member); +} +.tsd-kind-variable { + color: var(--color-ts-variable); +} +.tsd-kind-function { + color: var(--color-ts-function); +} +.tsd-kind-class { + color: var(--color-ts-class); +} +.tsd-kind-interface { + color: var(--color-ts-interface); +} +.tsd-kind-constructor { + color: var(--color-ts-constructor); +} +.tsd-kind-property { + color: var(--color-ts-property); +} +.tsd-kind-method { + color: var(--color-ts-method); +} +.tsd-kind-call-signature { + color: var(--color-ts-call-signature); +} +.tsd-kind-index-signature { + color: var(--color-ts-index-signature); +} +.tsd-kind-constructor-signature { + color: var(--color-ts-constructor-signature); +} +.tsd-kind-parameter { + color: var(--color-ts-parameter); +} +.tsd-kind-type-literal { + color: var(--color-ts-type-literal); +} +.tsd-kind-type-parameter { + color: var(--color-ts-type-parameter); +} +.tsd-kind-accessor { + color: var(--color-ts-accessor); +} +.tsd-kind-get-signature { + color: var(--color-ts-get-signature); +} +.tsd-kind-set-signature { + color: var(--color-ts-set-signature); +} +.tsd-kind-type-alias { + color: var(--color-ts-type-alias); +} + +/* if we have a kind icon, don't color the text by kind */ +.tsd-kind-icon ~ span { + color: var(--color-text); +} + +* { + scrollbar-width: thin; + scrollbar-color: var(--color-accent) var(--color-icon-background); +} + +*::-webkit-scrollbar { + width: 0.75rem; +} + +*::-webkit-scrollbar-track { + background: var(--color-icon-background); +} + +*::-webkit-scrollbar-thumb { + background-color: var(--color-accent); + border-radius: 999rem; + border: 0.25rem solid var(--color-icon-background); +} + +/* mobile */ +@media (max-width: 769px) { + .tsd-widget.options, + .tsd-widget.menu { + display: inline-block; + } + + .container-main { + display: flex; + } + html .col-content { + float: none; + max-width: 100%; + width: 100%; + } + html .col-sidebar { + position: fixed !important; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + z-index: 1024; + top: 0 !important; + bottom: 0 !important; + left: auto !important; + right: 0 !important; + padding: 1.5rem 1.5rem 0 0; + width: 75vw; + visibility: hidden; + background-color: var(--color-background); + transform: translate(100%, 0); + } + html .col-sidebar > *:last-child { + padding-bottom: 20px; + } + html .overlay { + content: ""; + display: block; + position: fixed; + z-index: 1023; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.75); + visibility: hidden; + } + + .to-has-menu .overlay { + animation: fade-in 0.4s; + } + + .to-has-menu .col-sidebar { + animation: pop-in-from-right 0.4s; + } + + .from-has-menu .overlay { + animation: fade-out 0.4s; + } + + .from-has-menu .col-sidebar { + animation: pop-out-to-right 0.4s; + } + + .has-menu body { + overflow: hidden; + } + .has-menu .overlay { + visibility: visible; + } + .has-menu .col-sidebar { + visibility: visible; + transform: translate(0, 0); + display: flex; + flex-direction: column; + gap: 1.5rem; + max-height: 100vh; + padding: 1rem 2rem; + } + .has-menu .tsd-navigation { + max-height: 100%; + } +} + +/* one sidebar */ +@media (min-width: 770px) { + .container-main { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + grid-template-areas: "sidebar content"; + margin: 2rem auto; + } + + .col-sidebar { + grid-area: sidebar; + } + .col-content { + grid-area: content; + padding: 0 1rem; + } +} +@media (min-width: 770px) and (max-width: 1399px) { + .col-sidebar { + max-height: calc(100vh - 2rem - 42px); + overflow: auto; + position: sticky; + top: 42px; + padding-top: 1rem; + } + .site-menu { + margin-top: 1rem; + } +} + +/* two sidebars */ +@media (min-width: 1200px) { + .container-main { + grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 20rem); + grid-template-areas: "sidebar content toc"; + } + + .col-sidebar { + display: contents; + } + + .page-menu { + grid-area: toc; + padding-left: 1rem; + } + .site-menu { + grid-area: sidebar; + } + + .site-menu { + margin-top: 1rem 0; + } + + .page-menu, + .site-menu { + max-height: calc(100vh - 2rem - 42px); + overflow: auto; + position: sticky; + top: 42px; + } +} diff --git a/docs/functions/client_star_me_star_me.StarMe.html b/docs/functions/client_star_me_star_me.StarMe.html new file mode 100644 index 00000000..c0ea3daa --- /dev/null +++ b/docs/functions/client_star_me_star_me.StarMe.html @@ -0,0 +1,2 @@ +StarMe | Code Documentation

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/functions/server_fork_me_fork_me.ForkMe.html b/docs/functions/server_fork_me_fork_me.ForkMe.html new file mode 100644 index 00000000..1b6a9053 --- /dev/null +++ b/docs/functions/server_fork_me_fork_me.ForkMe.html @@ -0,0 +1,4 @@ +ForkMe | Code Documentation

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000..97853abe --- /dev/null +++ b/docs/index.html @@ -0,0 +1,14 @@ +Code Documentation

Code Documentation

Fork Me React.js component

A simple fork me component for React.js projects!

+

Install

$ pnpm add @mayank1513/fork-me
# or
$ npm install @mayank1513/fork-me
# or
$ yarn add @mayank1513/fork-me +
+

Add on your page

<ForkMe gitHubUrl="https://github.com/mayank1513/turborepo-template" />
// and
<StarMe gitHubUrl="https://github.com/mayank1513/turborepo-template" /> +
+

You need to import styles for ForkMe component

+
import "@mayank1513/fork-me/server/index.css";
+
+

Optional parameters

    text?: string; // replace the Fork me on GitHub text
width?: string | number; // if you need to adjust the width of the ribbon (length)
height?: string | number; // to adjust height of the ribbon
bgColor?: string; // background color
textColor?: string; // text color +
+
+

This package also serves as an example to demonstrate how to build and publish React.js library compatible with React Server Components

+
+

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/modules/client_star_me_star_me.html b/docs/modules/client_star_me_star_me.html new file mode 100644 index 00000000..734ef207 --- /dev/null +++ b/docs/modules/client_star_me_star_me.html @@ -0,0 +1,2 @@ +client/star-me/star-me | Code Documentation

Module client/star-me/star-me

Index

Functions

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/modules/declaration.html b/docs/modules/declaration.html new file mode 100644 index 00000000..2ef434be --- /dev/null +++ b/docs/modules/declaration.html @@ -0,0 +1 @@ +declaration | Code Documentation

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/modules/server_fork_me_fork_me.html b/docs/modules/server_fork_me_fork_me.html new file mode 100644 index 00000000..6e968947 --- /dev/null +++ b/docs/modules/server_fork_me_fork_me.html @@ -0,0 +1,2 @@ +server/fork-me/fork-me | Code Documentation

Module server/fork-me/fork-me

Index

Functions

Generated using TypeDoc

\ No newline at end of file diff --git a/examples/nextjs/.eslintrc.js b/examples/nextjs/.eslintrc.js new file mode 100644 index 00000000..1d9773ea --- /dev/null +++ b/examples/nextjs/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ["custom/next"], +}; diff --git a/examples/nextjs/.gitignore b/examples/nextjs/.gitignore new file mode 100644 index 00000000..1437c53f --- /dev/null +++ b/examples/nextjs/.gitignore @@ -0,0 +1,34 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel diff --git a/examples/nextjs/CHANGELOG.md b/examples/nextjs/CHANGELOG.md new file mode 100644 index 00000000..ee5f1991 --- /dev/null +++ b/examples/nextjs/CHANGELOG.md @@ -0,0 +1,39 @@ +# nextjs-example + +## 1.0.5 + +### Patch Changes + +- Updated dependencies + - @mayank1513/fork-me@2.0.1 + - shared-ui@1.0.1 + +## 1.0.4 + +### Patch Changes + +- Support Next.js 14 +- Updated dependencies + - @mayank1513/fork-me@2.0.0 + +## 1.0.3 + +### Patch Changes + +- Updated dependencies + - @mayank1513/fork-me@1.1.2 + +## 1.0.2 + +### Patch Changes + +- Fix CSS modules +- Updated dependencies + - @mayank1513/fork-me@1.1.1 + +## 1.0.1 + +### Patch Changes + +- Updated dependencies + - @mayank1513/fork-me@1.1.0 diff --git a/examples/nextjs/README.md b/examples/nextjs/README.md new file mode 100644 index 00000000..1626d340 --- /dev/null +++ b/examples/nextjs/README.md @@ -0,0 +1,28 @@ +## Getting Started + +First, run the development server: + +```bash +yarn dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, as `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello). + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - Learn about Next.js features and API. +- [Learn Next.js](https://www.udemy.com/course/react-and-next-js-with-typescript/?referralCode=7202184A1E57C3DCA8B2) - an interactive Next.js course. + +You can check out [the Turbo Template GitHub repository](https://github.com/mayank1513/turborepo-template/) - your feedback and contributions are welcome! + +### 🀩 Don't forget to start this repo! + +
+ +

with πŸ’– by Mayank Kumar Chaudhari

diff --git a/examples/nextjs/app/favicon.ico b/examples/nextjs/app/favicon.ico new file mode 100644 index 00000000..71e4bd71 Binary files /dev/null and b/examples/nextjs/app/favicon.ico differ diff --git a/examples/nextjs/app/layout.tsx b/examples/nextjs/app/layout.tsx new file mode 100644 index 00000000..25f15f47 --- /dev/null +++ b/examples/nextjs/app/layout.tsx @@ -0,0 +1,16 @@ +import { NextJsSSGThemeSwitcher } from "nextjs-themes/server/nextjs"; +import { Inter } from "next/font/google"; +import { SharedRootLayout } from "shared-ui"; + +const inter = Inter({ subsets: ["latin"] }); + +export default function RootLayout({ children }: { children: React.ReactNode }): JSX.Element { + return ( + + + + {children} + + + ); +} diff --git a/examples/nextjs/app/page.tsx b/examples/nextjs/app/page.tsx new file mode 100644 index 00000000..c4377b2f --- /dev/null +++ b/examples/nextjs/app/page.tsx @@ -0,0 +1,3 @@ +export default function Home(): JSX.Element { + return

Next.js Example

; +} diff --git a/examples/nextjs/cache/config.json b/examples/nextjs/cache/config.json new file mode 100644 index 00000000..cb01ad90 --- /dev/null +++ b/examples/nextjs/cache/config.json @@ -0,0 +1,6 @@ +{ + "telemetry": { + "notifiedAt": "1701772138754", + "enabled": false + } +} \ No newline at end of file diff --git a/examples/nextjs/next-env.d.ts b/examples/nextjs/next-env.d.ts new file mode 100644 index 00000000..4f11a03d --- /dev/null +++ b/examples/nextjs/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/nextjs/next.config.js b/examples/nextjs/next.config.js new file mode 100644 index 00000000..b4b8f818 --- /dev/null +++ b/examples/nextjs/next.config.js @@ -0,0 +1,4 @@ +module.exports = { + reactStrictMode: true, + transpilePackages: [""], +}; diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json new file mode 100644 index 00000000..6ee3b06d --- /dev/null +++ b/examples/nextjs/package.json @@ -0,0 +1,29 @@ +{ + "name": "nextjs-example", + "version": "1.0.5", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "postinstall": "next telemetry disable" + }, + "dependencies": { + "@mayank1513/fork-me": "workspace:*", + "next": "^14.1.0", + "nextjs-themes": "^2.1.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "shared-ui": "workspace:*" + }, + "devDependencies": { + "@next/eslint-plugin-next": "^14.1.0", + "@types/node": "^20.11.19", + "@types/react": "^18.2.56", + "@types/react-dom": "^18.2.19", + "eslint-config-custom": "workspace:*", + "tsconfig": "workspace:*", + "typescript": "^5.3.3" + } +} diff --git a/examples/nextjs/tsconfig.json b/examples/nextjs/tsconfig.json new file mode 100644 index 00000000..644ee04f --- /dev/null +++ b/examples/nextjs/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "tsconfig/nextjs.json", + "compilerOptions": { + "plugins": [{ "name": "next" }] + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/examples/remix/.eslintrc.cjs b/examples/remix/.eslintrc.cjs new file mode 100644 index 00000000..2061cd22 --- /dev/null +++ b/examples/remix/.eslintrc.cjs @@ -0,0 +1,4 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], +}; diff --git a/examples/remix/.gitignore b/examples/remix/.gitignore new file mode 100644 index 00000000..1998c294 --- /dev/null +++ b/examples/remix/.gitignore @@ -0,0 +1 @@ +.cache \ No newline at end of file diff --git a/examples/remix/CHANGELOG.md b/examples/remix/CHANGELOG.md new file mode 100644 index 00000000..7643b1a9 --- /dev/null +++ b/examples/remix/CHANGELOG.md @@ -0,0 +1,9 @@ +# remix-example + +## null + +### Patch Changes + +- Updated dependencies + - @mayank1513/fork-me@2.0.1 + - shared-ui@1.0.1 diff --git a/examples/remix/app/root.tsx b/examples/remix/app/root.tsx new file mode 100644 index 00000000..4ebdb015 --- /dev/null +++ b/examples/remix/app/root.tsx @@ -0,0 +1,29 @@ +import { cssBundleHref } from "@remix-run/css-bundle"; +import type { LinksFunction } from "@remix-run/node"; +import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react"; +import { SharedRootLayout } from "shared-ui"; + +export const links: LinksFunction = () => [ + ...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []), +]; + +export default function App() { + return ( + + + + + + + + + + + + + + + + + ); +} diff --git a/examples/remix/app/routes/_index.tsx b/examples/remix/app/routes/_index.tsx new file mode 100644 index 00000000..7e84feff --- /dev/null +++ b/examples/remix/app/routes/_index.tsx @@ -0,0 +1,3 @@ +export default function Home() { + return

Remix Example

; +} diff --git a/examples/remix/package.json b/examples/remix/package.json new file mode 100644 index 00000000..0b813c4f --- /dev/null +++ b/examples/remix/package.json @@ -0,0 +1,50 @@ +{ + "name": "remix-example", + "version": "0.0.0", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "build": "remix build", + "dev": "remix dev --manual", + "start": "remix-serve ./build/index.js", + "typecheck": "tsc" + }, + "dependencies": { + "@mayank1513/fork-me": "workspace:*", + "@remix-run/css-bundle": "^2.6.0", + "@remix-run/node": "^2.6.0", + "@remix-run/react": "^2.6.0", + "@remix-run/serve": "^2.6.0", + "isbot": "5.1.0", + "nextjs-themes": "^2.1.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "shared-ui": "workspace:*" + }, + "devDependencies": { + "@remix-run/dev": "^2.6.0", + "@remix-run/eslint-config": "^2.6.0", + "@types/react": "^18.2.56", + "@types/react-dom": "^18.2.19", + "eslint": "^8.56.0", + "typescript": "^5.3.3" + }, + "engines": { + "node": ">=18.0.0" + }, + "pnpm": { + "packageExtensions": { + "@remix-run/dev": { + "peerDependencies": { + "react-dom": "18.2.0" + } + }, + "@remix-run/serve": { + "peerDependencies": { + "react-dom": "18.2.0" + } + } + } + } +} diff --git a/examples/remix/remix.config.js b/examples/remix/remix.config.js new file mode 100644 index 00000000..2afd6649 --- /dev/null +++ b/examples/remix/remix.config.js @@ -0,0 +1,9 @@ +/** @type {import('@remix-run/dev').AppConfig} */ +export default { + ignoredRouteFiles: ["**/.*"], + serverDependenciesToBundle: ["@mayank1513/fork-me", "shared-ui"], + // appDirectory: "app", + // assetsBuildDirectory: "public/build", + // publicPath: "/build/", + // serverBuildPath: "build/index.js", +}; diff --git a/examples/remix/remix.env.d.ts b/examples/remix/remix.env.d.ts new file mode 100644 index 00000000..dcf8c45e --- /dev/null +++ b/examples/remix/remix.env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/examples/remix/tsconfig.json b/examples/remix/tsconfig.json new file mode 100644 index 00000000..28cce918 --- /dev/null +++ b/examples/remix/tsconfig.json @@ -0,0 +1,22 @@ +{ + "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"], + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "target": "ES2022", + "strict": true, + "allowJs": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "~/*": ["./app/*"] + }, + + // Remix takes care of building everything in `remix build`. + "noEmit": true + } +} diff --git a/examples/vite/.eslintrc.cjs b/examples/vite/.eslintrc.cjs new file mode 100644 index 00000000..f63fe7dc --- /dev/null +++ b/examples/vite/.eslintrc.cjs @@ -0,0 +1,15 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react-hooks/recommended", + ], + ignorePatterns: ["dist", ".eslintrc.cjs"], + parser: "@typescript-eslint/parser", + plugins: ["react-refresh"], + rules: { + "react-refresh/only-export-components": ["warn", { allowConstantExport: true }], + }, +}; diff --git a/examples/vite/.gitignore b/examples/vite/.gitignore new file mode 100644 index 00000000..5a079d55 --- /dev/null +++ b/examples/vite/.gitignore @@ -0,0 +1,37 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel + +# vite +dist diff --git a/examples/vite/CHANGELOG.md b/examples/vite/CHANGELOG.md new file mode 100644 index 00000000..26d35458 --- /dev/null +++ b/examples/vite/CHANGELOG.md @@ -0,0 +1,38 @@ +# vite-example + +## 0.0.5 + +### Patch Changes + +- Updated dependencies + - @mayank1513/fork-me@2.0.1 + - shared-ui@1.0.1 + +## 0.0.4 + +### Patch Changes + +- Support Next.js 14 +- Updated dependencies + - @mayank1513/fork-me@2.0.0 + +## 0.0.3 + +### Patch Changes + +- Updated dependencies + - @mayank1513/fork-me@1.1.2 + +## 0.0.2 + +### Patch Changes + +- Updated dependencies + - @mayank1513/fork-me@1.1.1 + +## 0.0.1 + +### Patch Changes + +- Updated dependencies + - @mayank1513/fork-me@1.1.0 diff --git a/examples/vite/README.md b/examples/vite/README.md new file mode 100644 index 00000000..603a1359 --- /dev/null +++ b/examples/vite/README.md @@ -0,0 +1,25 @@ +## Getting Started + +First, run the development server: + +```bash +yarn dev +``` + +Open [http://localhost:3001](http://localhost:3001) with your browser to see the result. +Edit `src/App.tsx` and save to test HMR + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - Learn about Next.js features and API. +- [Learn Next.js](https://www.udemy.com/course/react-and-next-js-with-typescript/?referralCode=7202184A1E57C3DCA8B2) - an interactive Next.js course. + +You can check out [the Turbo Template GitHub repository](https://github.com/mayank1513/turborepo-template/) - your feedback and contributions are welcome! + +### 🀩 Don't forget to start this repo! + +
+ +

with πŸ’– by Mayank Kumar Chaudhari

diff --git a/examples/vite/index.html b/examples/vite/index.html new file mode 100644 index 00000000..e4b78eae --- /dev/null +++ b/examples/vite/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/examples/vite/package.json b/examples/vite/package.json new file mode 100644 index 00000000..f891df64 --- /dev/null +++ b/examples/vite/package.json @@ -0,0 +1,31 @@ +{ + "name": "vite-example", + "private": true, + "version": "0.0.5", + "type": "module", + "scripts": { + "dev": "vite --port 3001", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@mayank1513/fork-me": "workspace:*", + "nextjs-themes": "^2.1.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "shared-ui": "workspace:*" + }, + "devDependencies": { + "@types/react": "^18.2.56", + "@types/react-dom": "^18.2.19", + "@typescript-eslint/eslint-plugin": "^7.0.1", + "@typescript-eslint/parser": "^7.0.1", + "@vitejs/plugin-react-swc": "^3.6.0", + "eslint": "^8.56.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "typescript": "^5.3.3", + "vite": "^5.1.3" + } +} diff --git a/examples/vite/public/vite.svg b/examples/vite/public/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/examples/vite/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/vite/src/App.tsx b/examples/vite/src/App.tsx new file mode 100644 index 00000000..21bf2947 --- /dev/null +++ b/examples/vite/src/App.tsx @@ -0,0 +1,5 @@ +function App() { + return

Vite + React + TS Example

; +} + +export default App; diff --git a/examples/vite/src/main.tsx b/examples/vite/src/main.tsx new file mode 100644 index 00000000..1f270783 --- /dev/null +++ b/examples/vite/src/main.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App.tsx"; +import { SharedRootLayout } from "shared-ui"; + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + + + , +); diff --git a/examples/vite/src/vite-env.d.ts b/examples/vite/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/examples/vite/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/vite/tsconfig.json b/examples/vite/tsconfig.json new file mode 100644 index 00000000..483d7b4d --- /dev/null +++ b/examples/vite/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/examples/vite/tsconfig.node.json b/examples/vite/tsconfig.node.json new file mode 100644 index 00000000..42872c59 --- /dev/null +++ b/examples/vite/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/examples/vite/vite.config.ts b/examples/vite/vite.config.ts new file mode 100644 index 00000000..41114b5e --- /dev/null +++ b/examples/vite/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react-swc"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); diff --git a/lib/fork-me/.eslintrc.js b/lib/fork-me/.eslintrc.js new file mode 100644 index 00000000..05ac2b2b --- /dev/null +++ b/lib/fork-me/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ["custom/react-internal"], +}; diff --git a/lib/fork-me/.gitignore b/lib/fork-me/.gitignore new file mode 100644 index 00000000..06435e20 --- /dev/null +++ b/lib/fork-me/.gitignore @@ -0,0 +1,2 @@ +# tsup build +dist diff --git a/lib/fork-me/CHANGELOG.md b/lib/fork-me/CHANGELOG.md new file mode 100644 index 00000000..f294e17e --- /dev/null +++ b/lib/fork-me/CHANGELOG.md @@ -0,0 +1,31 @@ +# @mayank1513/fork-me + +## 2.0.1 + +### Patch Changes + +- Add provenance + +## 2.0.0 + +### Major Changes + +- Support Next.js 14 + +## 1.1.2 + +### Patch Changes + +- Add z-index to make sure ribbon is not covered + +## 1.1.1 + +### Patch Changes + +- Fix CSS modules + +## 1.1.0 + +### Minor Changes + +- Added new prop shadowColor - drop shadow on hover defaults to bgColor diff --git a/lib/fork-me/README.md b/lib/fork-me/README.md new file mode 100644 index 00000000..1d007344 --- /dev/null +++ b/lib/fork-me/README.md @@ -0,0 +1,39 @@ +# Fork Me React.js component + +A simple fork me component for React.js projects! + +## Install + +```bash +$ pnpm add @mayank1513/fork-me +# or +$ npm install @mayank1513/fork-me +# or +$ yarn add @mayank1513/fork-me +``` + +## Add on your page + +```ts + +// and + +``` + +You need to import styles for ForkMe component + +```ts +import "@mayank1513/fork-me/server/index.css"; +``` + +## Optional parameters + +```ts + text?: string; // replace the Fork me on GitHub text + width?: string | number; // if you need to adjust the width of the ribbon (length) + height?: string | number; // to adjust height of the ribbon + bgColor?: string; // background color + textColor?: string; // text color +``` + +> This package also serves as an example to demonstrate how to build and publish `React.js` library compatible with React Server Components diff --git a/lib/fork-me/index.ts b/lib/fork-me/index.ts new file mode 100644 index 00000000..c3238670 --- /dev/null +++ b/lib/fork-me/index.ts @@ -0,0 +1,4 @@ +"use client"; + +/** to make sure import statements remain same for monorepo setup and install via npm */ +export * from "./src/client"; diff --git a/lib/fork-me/package.json b/lib/fork-me/package.json new file mode 100644 index 00000000..81cd6daa --- /dev/null +++ b/lib/fork-me/package.json @@ -0,0 +1,75 @@ +{ + "name": "@mayank1513/fork-me", + "author": "Mayank Kumar Chaudhari ", + "private": false, + "version": "2.0.1", + "description": "An intuitive React.js fork me ribbon component for promoting open source project forks.", + "main": "./index.ts", + "types": "./index.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/react18-tools/turborepo-template.git" + }, + "bugs": { + "url": "https://github.com/react18-tools/turborepo-template/issues" + }, + "homepage": "https://github.com/react18-tools/turborepo-template/tree/main/lib/fork-me#readme", + "sideEffects": false, + "license": "MIT", + "scripts": { + "test": "vitest run --coverage", + "build": "tsup src && tsc -p tsconfig-build.json && node touchup.js", + "doc": "typedoc", + "publish-package": "cd dist && npm publish --provenance --access public", + "lint": "eslint ." + }, + "devDependencies": { + "@testing-library/react": "^14.2.1", + "@turbo/gen": "^1.12.4", + "@types/node": "^20.11.19", + "@types/react": "^18.2.56", + "@types/react-dom": "^18.2.19", + "@vitejs/plugin-react": "^4.2.1", + "@vitest/coverage-v8": "^1.3.0", + "esbuild-plugin-css-module": "^0.0.1", + "esbuild-plugin-react18": "^0.0.7", + "eslint-config-custom": "workspace:*", + "jsdom": "^24.0.0", + "octokit": "^3.1.2", + "react": "^18.2.0", + "tsconfig": "workspace:*", + "tsup": "^8.0.2", + "typedoc": "^0.25.8", + "typescript": "^5.3.3", + "vite-tsconfig-paths": "^4.3.1", + "vitest": "^1.3.0" + }, + "peerDependencies": { + "@types/react": "16.8 - 18", + "next": "10 - 14", + "react": "16.8 - 18" + }, + "peerDependenciesMeta": { + "next": { + "optional": true + } + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/mayank1513" + }, + "keywords": [ + "fork-me", + "GitHub", + "nextjs", + "nextjs13", + "react", + "react18", + "react-server-components", + "react-client-components", + "typescript", + "javascript", + "mayank1513", + "turborepo-trmplate" + ] +} \ No newline at end of file diff --git a/lib/fork-me/scope.js b/lib/fork-me/scope.js new file mode 100644 index 00000000..43598f88 --- /dev/null +++ b/lib/fork-me/scope.js @@ -0,0 +1,23 @@ +/* eslint-disable -- no need - external file */ +"use strict"; + +const fs = require("node:fs"); +const path = require("node:path"); + +const owner = process.env.OWNER; +const packageJson = require(path.resolve(process.cwd(), "package.json")); +const ref = packageJson.name; +if (!ref.startsWith(`@${owner}`)) { + packageJson.name = `@${owner}/${packageJson.name}`; + fs.writeFileSync( + path.resolve(process.cwd(), "package.json"), + JSON.stringify(packageJson, null, 2), + ); + const readMePath = path.resolve(process.cwd(), "README.md"); + let readMe = fs.readFileSync(readMePath, { encoding: "utf8" }); + const tmp = "!--|--!"; + readMe = readMe.replace(new RegExp(`$${owner}/${ref}`, "g"), tmp); + readMe = readMe.replace(new RegExp(ref, "g"), packageJson.name); + readMe = readMe.replace(new RegExp(tmp, "g"), `$${owner}/${ref}`); + fs.writeFileSync(readMePath, readMe); +} diff --git a/lib/fork-me/server.ts b/lib/fork-me/server.ts new file mode 100644 index 00000000..dcc241ce --- /dev/null +++ b/lib/fork-me/server.ts @@ -0,0 +1,3 @@ +/** to make sure import statements remain same for monorepo setup and install via npm */ + +export * from "./src/server"; diff --git a/lib/fork-me/src/client/index.ts b/lib/fork-me/src/client/index.ts new file mode 100644 index 00000000..25220c81 --- /dev/null +++ b/lib/fork-me/src/client/index.ts @@ -0,0 +1,9 @@ +"use client"; +/** + * need to export server components and client components from separate files as + * directive on top of the file from which component is imported takes effect. + * i.e., server component re-exported from file with "use client" will behave as client component + * */ + +// client component exports +export * from "./star-me"; diff --git a/lib/fork-me/src/client/star-me/index.ts b/lib/fork-me/src/client/star-me/index.ts new file mode 100644 index 00000000..371f7a8b --- /dev/null +++ b/lib/fork-me/src/client/star-me/index.ts @@ -0,0 +1,3 @@ +"use client"; + +export * from "./star-me"; diff --git a/lib/fork-me/src/client/star-me/star-me.test.tsx b/lib/fork-me/src/client/star-me/star-me.test.tsx new file mode 100644 index 00000000..40e0c330 --- /dev/null +++ b/lib/fork-me/src/client/star-me/star-me.test.tsx @@ -0,0 +1,35 @@ +import { cleanup, fireEvent, render, screen } from "@testing-library/react"; +import { afterEach, describe, test, vi } from "vitest"; +import { StarMe } from "./star-me"; + +describe("star-me", () => { + afterEach(cleanup); + + test("smoke", ({ expect }) => { + render(); + expect(screen.getByTestId("star-me-h1").textContent).toBe("Star Me"); + }); + + test("test custom children", ({ expect }) => { + const text = "Star this repo"; + render({text}); + expect(screen.getByTestId("star-me-h1").textContent).toBe(text); + }); + + test("test custom props", ({ expect }) => { + const className = "my-star-class"; + render( + , + ); + expect(screen.getByTestId("star-me-h1").className).toBe(className); + }); + + test("test popup", ({ expect }) => { + render( + ""} />, + ); + const spy = vi.spyOn(window, "open"); + fireEvent.click(screen.getByTestId("star-me-h1")); + expect(spy).toHaveBeenCalled(); + }); +}); diff --git a/lib/fork-me/src/client/star-me/star-me.tsx b/lib/fork-me/src/client/star-me/star-me.tsx new file mode 100644 index 00000000..b0481678 --- /dev/null +++ b/lib/fork-me/src/client/star-me/star-me.tsx @@ -0,0 +1,22 @@ +import * as React from "react"; + +interface StarMeProps extends React.HTMLAttributes { + gitHubUrl: string; +} + +/** + * # StarMe + * Star repo in a popup window + * + */ +export function StarMe({ gitHubUrl, onClick, children, ...props }: StarMeProps) { + const starMe = (e: React.MouseEvent) => { + window.open(gitHubUrl, "_blank", "height: 400,width:1200,left:150,top:150"); + onClick?.(e); + }; + return ( + + ); +} diff --git a/lib/fork-me/src/declaration.d.ts b/lib/fork-me/src/declaration.d.ts new file mode 100644 index 00000000..1eabbb42 --- /dev/null +++ b/lib/fork-me/src/declaration.d.ts @@ -0,0 +1 @@ +declare module "*.module.css"; diff --git a/lib/fork-me/src/index.ts b/lib/fork-me/src/index.ts new file mode 100644 index 00000000..013d21b0 --- /dev/null +++ b/lib/fork-me/src/index.ts @@ -0,0 +1,3 @@ +"use client"; +// client component exports +export * from "./client"; diff --git a/lib/fork-me/src/server/fork-me/fork-me.module.css b/lib/fork-me/src/server/fork-me/fork-me.module.css new file mode 100644 index 00000000..4069fddb --- /dev/null +++ b/lib/fork-me/src/server/fork-me/fork-me.module.css @@ -0,0 +1,24 @@ +.fork { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + width: var(--w); + height: var(--h); + transform: rotate(45deg); + top: calc(0.354 * var(--w) - var(--h)); + right: calc(-0.14 * var(--w) - 0.5 * var(--h)); + color: var(--tc); + text-decoration: none; + background-color: var(--bc); + border: 1px dashed gray; + text-shadow: + 0px 1px 0px rgba(255, 255, 255, 0.3), + 0px -1px 0px rgba(0, 0, 0, 0.7); + text-decoration: none; + z-index: 10000; +} +.fork:hover { + filter: drop-shadow(0 0 5px var(--sc)); +} diff --git a/lib/fork-me/src/server/fork-me/fork-me.test.tsx b/lib/fork-me/src/server/fork-me/fork-me.test.tsx new file mode 100644 index 00000000..95e74dbf --- /dev/null +++ b/lib/fork-me/src/server/fork-me/fork-me.test.tsx @@ -0,0 +1,31 @@ +import { cleanup, render } from "@testing-library/react"; +import { afterEach, describe, test } from "vitest"; +import { ForkMe } from "./fork-me"; + +describe.concurrent("fork-me", () => { + afterEach(cleanup); + + test("Smoke test", ({ expect }) => { + const component = render( + , + ); + expect(component.container.textContent).toBe("Fork Me on GitHub"); + }); + + test("Custom text", ({ expect }) => { + const text = "Star me on GitHub"; + const component = render( + , + ); + expect(component.container.textContent).toBe(text); + }); +}); diff --git a/lib/fork-me/src/server/fork-me/fork-me.tsx b/lib/fork-me/src/server/fork-me/fork-me.tsx new file mode 100644 index 00000000..d5b463e7 --- /dev/null +++ b/lib/fork-me/src/server/fork-me/fork-me.tsx @@ -0,0 +1,74 @@ +import * as React from "react"; +import cssClasses from "./fork-me.module.css"; + +interface ForkMeProps { + gitHubUrl: string; + text?: string; + width?: string | number; + height?: string | number; + bgColor?: string; + shadowColor?: string; + textColor?: string; + noAutoFork?: boolean; +} + +/** + * # ForkMe + * Fork me ribbon + * + * @param props - ForkMeProps + * @returns React.ReactElement + */ +export function ForkMe({ + gitHubUrl, + text, + width, + height, + bgColor, + shadowColor, + textColor, + noAutoFork, +}: ForkMeProps) { + const w = (Number.isNaN(Number(width)) ? width : `${width}px`) || "15em"; + const h = (Number.isNaN(Number(height)) ? height : `${height}px`) || "35px"; + const bgC = bgColor || "#aaa"; + const tC = textColor || "#555"; + const style = { + "--w": w, + "--h": h, + "--tc": tC, + "--bc": bgC, + "--sc": bgC || shadowColor, + position: "fixed" as const, + display: "flex", + alignItems: "center", + justifyContent: "center", + fontWeight: 700, + width: w, + height: h, + transform: "rotate(45deg)", + top: "calc(0.354 * var(--w) - var(--h))", + right: "calc(-0.14 * var(--w) - 0.5 * var(--h))", + color: tC, + backgroundColor: bgC, + textShadow: "0px 1px 0px rgba(255, 255, 255, 0.3), 0px -1px 0px rgba(0, 0, 0, 0.7)", + border: "1px dashed gray", + outline: `4px solid ${bgC}`, // to satisfy typescript + textDecoration: "none", + zIndex: 1000, + }; + + let url = gitHubUrl; + if (!noAutoFork) url = url.endsWith("fork") ? url : `${url}/fork`; + + return ( + + {text || "Fork Me on GitHub"} + + ); +} diff --git a/lib/fork-me/src/server/fork-me/index.ts b/lib/fork-me/src/server/fork-me/index.ts new file mode 100644 index 00000000..ab5ebd1f --- /dev/null +++ b/lib/fork-me/src/server/fork-me/index.ts @@ -0,0 +1 @@ +export * from "./fork-me"; diff --git a/lib/fork-me/src/server/index.ts b/lib/fork-me/src/server/index.ts new file mode 100644 index 00000000..cc34b95f --- /dev/null +++ b/lib/fork-me/src/server/index.ts @@ -0,0 +1,8 @@ +/** + * need to export server components and client components from separate files as + * directive on top of the file from which component is imported takes effect. + * i.e., server component re-exported from file with "use client" will behave as client component + * */ + +// server component exports +export * from "./fork-me"; diff --git a/lib/fork-me/touchup.js b/lib/fork-me/touchup.js new file mode 100644 index 00000000..db383ce2 --- /dev/null +++ b/lib/fork-me/touchup.js @@ -0,0 +1,62 @@ +/* eslint-disable -- no need - external file */ +"use strict"; + +const fs = require("fs"); +const path = require("path"); +const packageJson = require(path.resolve(__dirname, "package.json")); +if (process.env.TOKEN) { + const { Octokit } = require("octokit"); + // Octokit.js + // https://github.com/octokit/core.js#readme + const octokit = new Octokit({ + auth: process.env.TOKEN, + }); + + const octoOptions = { + owner: process.env.OWNER, + repo: process.env.REPO, + headers: { + "X-GitHub-Api-Version": "2022-11-28", + }, + }; + const tag_name = `v${packageJson.version}`; + const name = `Release ${tag_name}`; + /** Create a release */ + octokit.request("POST /repos/{owner}/{repo}/releases", { + ...octoOptions, + tag_name, + target_commitish: "main", + name, + draft: false, + prerelease: false, + generate_release_notes: true, + headers: { + "X-GitHub-Api-Version": "2022-11-28", + }, + }); +} +delete packageJson.devDependencies; +delete packageJson.scripts; + +packageJson.main = "index.js"; +packageJson.types = "index.d.ts"; + +fs.writeFileSync( + path.resolve(__dirname, "dist", "package.json"), + JSON.stringify(packageJson, null, 2), +); + +fs.copyFileSync(path.resolve(__dirname, "README.md"), path.resolve(__dirname, "dist", "README.md")); + +const dirs = [path.resolve(__dirname, "dist")]; + +while (dirs.length) { + const dir = dirs.shift(); + fs.readdirSync(dir).forEach(f => { + const f1 = path.resolve(dir, f); + if (f.includes(".test.")) fs.unlink(f1, () => {}); + else if (fs.lstatSync(f1).isDirectory()) { + dirs.push(f1); + } + }); +} diff --git a/lib/fork-me/tsconfig-build.json b/lib/fork-me/tsconfig-build.json new file mode 100644 index 00000000..3785799b --- /dev/null +++ b/lib/fork-me/tsconfig-build.json @@ -0,0 +1,10 @@ +{ + "extends": "tsconfig/react-library.json", + "compilerOptions": { + "outDir": "dist", + "emitDeclarationOnly": true, + "sourceMap": false + }, + "include": ["src"], + "exclude": ["dist", "build", "node_modules", "**/*.test.*", "**/*.spec.*"] +} diff --git a/lib/fork-me/tsconfig.doc.json b/lib/fork-me/tsconfig.doc.json new file mode 100644 index 00000000..70249fd8 --- /dev/null +++ b/lib/fork-me/tsconfig.doc.json @@ -0,0 +1,5 @@ +{ + "extends": "tsconfig/react-library.json", + "include": ["src"], + "exclude": ["**/*.test.tsx", "**/index.ts"] +} diff --git a/lib/fork-me/tsconfig.json b/lib/fork-me/tsconfig.json new file mode 100644 index 00000000..fd5dc9fa --- /dev/null +++ b/lib/fork-me/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "tsconfig/react-library.json", + "include": ["."], + "exclude": ["dist", "build", "node_modules"] +} diff --git a/lib/fork-me/tsup.config.ts b/lib/fork-me/tsup.config.ts new file mode 100644 index 00000000..cdf68965 --- /dev/null +++ b/lib/fork-me/tsup.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from "tsup"; +import react18Plugin from "esbuild-plugin-react18"; +import cssModulePlugin from "esbuild-plugin-css-module"; + +export default defineConfig(options => ({ + format: ["cjs", "esm"], + target: "es2019", + sourcemap: false, + clean: true, + bundle: true, + minify: !options.watch, + esbuildPlugins: [react18Plugin(), cssModulePlugin()], + legacyOutput: true, +})); diff --git a/lib/fork-me/turbo/generators/config.ts b/lib/fork-me/turbo/generators/config.ts new file mode 100644 index 00000000..3281d6b6 --- /dev/null +++ b/lib/fork-me/turbo/generators/config.ts @@ -0,0 +1,119 @@ +import fs from "node:fs"; +import path from "node:path"; +import type { PlopTypes } from "@turbo/gen"; + +export default function generator(plop: PlopTypes.NodePlopAPI): void { + // A simple generator to add a new React component to the internal UI library + plop.setGenerator("react-component", { + description: "Adds a new react component", + prompts: [ + { + type: "input", + name: "name", + message: "What is the name of the component?", + }, + { + type: "confirm", + name: "isClient", + message: 'Is this a client component? (Should we add "use client" directive?)', + }, + { + type: "input", + name: "description", + message: "Describe your component. (This will be added as js-doc comment.)", + }, + ], + actions: data => (data ? getActions(data as InquirerDataType) : []), + }); +} + +interface InquirerDataType { + isClient: boolean; + name: string; +} + +function getActions(data: InquirerDataType) { + const { nestedRouteActions, root } = getNestedRouteActions(data); + return nestedRouteActions.concat([ + { + type: "add", + path: `${root}{{kebabCase name}}/index.ts`, + template: `${ + data.isClient ? '"use client";\n\n' : "" + }export * from "./{{kebabCase name}}";\n`, + }, + { + type: "add", + path: `${root}{{kebabCase name}}/{{kebabCase name}}.tsx`, + templateFile: "templates/component.hbs", + }, + { + type: "add", + path: `${root}{{kebabCase name}}/{{kebabCase name}}.test.tsx`, + templateFile: "templates/component.test.hbs", + }, + { + type: "append", + path: `${root}index.ts`, + pattern: /(? component exports)/g, + template: 'export * from "./{{kebabCase name}}";', + }, + ]); +} + +function getNestedRouteActions(data: InquirerDataType) { + const { isClient, name } = data; + const root = isClient ? "src/client/" : "src/server/"; + const nestedRouteActions: PlopTypes.ActionType[] = []; + + /** Return early if no nested routes */ + if (!name.includes("/")) return { nestedRouteActions, root }; + + const lastSlashInd = name.lastIndexOf("/") || name.lastIndexOf("\\"); + /** following is required to make sure appropreate name is used while creating components */ + data.name = name.slice(lastSlashInd + 1); + + const directories = name.slice(0, lastSlashInd).split(/\/|\\/); + const rootSegments = [...root.split(/\/|\\/)]; + + for (let i = 1; i <= directories.length; i++) + updateIndexFilesIfNeeded(nestedRouteActions, rootSegments, directories.slice(0, i), isClient); + + return { nestedRouteActions, root: `${root + directories.join("/")}/` }; +} + +function updateIndexFilesIfNeeded( + nestedRouteActions: PlopTypes.ActionType[], + rootSegments: string[], + currentDirSegments: string[], + isClient: boolean, +) { + const indexFilePath = path.resolve( + process.cwd(), + "..", + "..", + ...rootSegments, + ...currentDirSegments, + "index.ts", + ); + const root = rootSegments.join("/"); + if (!fs.existsSync(indexFilePath)) { + const content = `${isClient ? '"use client";\n' : ""}// ${currentDirSegments.join( + "/", + )} component exports\n`; + nestedRouteActions.push({ + type: "add", + path: `${root + currentDirSegments.join("/")}/index.ts`, + template: content, + }); + const length = currentDirSegments.length; + nestedRouteActions.push({ + type: "append", + pattern: /(? component exports)/g, + path: `${ + root + (length === 1 ? "" : `${currentDirSegments.slice(0, length - 1).join("/")}/`) + }index.ts`, + template: `export * from "./${currentDirSegments[length - 1]}"`, + }); + } +} diff --git a/lib/fork-me/turbo/generators/templates/component.hbs b/lib/fork-me/turbo/generators/templates/component.hbs new file mode 100644 index 00000000..7005671e --- /dev/null +++ b/lib/fork-me/turbo/generators/templates/component.hbs @@ -0,0 +1,18 @@ +import * as React from "react"; + +interface {{ pascalCase name }}Props { + children?: React.ReactNode; +} + +/** + * # {{ pascalCase name }} + * {{ description }} + */ +export function {{ pascalCase name }}({ children }: {{ pascalCase name }}Props) { + return ( +
+

{{ name }}

+ {children} +
+ ); +} diff --git a/lib/fork-me/turbo/generators/templates/component.test.hbs b/lib/fork-me/turbo/generators/templates/component.test.hbs new file mode 100644 index 00000000..f08ba2b0 --- /dev/null +++ b/lib/fork-me/turbo/generators/templates/component.test.hbs @@ -0,0 +1,12 @@ +import { cleanup, render, screen } from "@testing-library/react"; +import { afterEach, describe, test } from "vitest"; +import { {{ pascalCase name }} } from "./{{ kebabCase name }}"; + +describe.concurrent("{{ kebabCase name }}", () => { + afterEach(cleanup); + + test("check if h1 heading exists", ({ expect }) => { + render(<{{ pascalCase name }} />); + expect(screen.getByTestId("{{ kebabCase name }}-h1").textContent).toBe("{{ name }}"); + }); +}); diff --git a/lib/fork-me/typedoc.config.js b/lib/fork-me/typedoc.config.js new file mode 100644 index 00000000..dec526f7 --- /dev/null +++ b/lib/fork-me/typedoc.config.js @@ -0,0 +1,9 @@ +/** @type {import('typedoc').TypeDocOptions} */ +module.exports = { + name: "Code Documentation", + entryPoints: ["./src"], + entryPointStrategy: "Expand", + tsconfig: "./tsconfig.doc.json", + out: "../../docs", + commentStyle: "all", +}; diff --git a/lib/fork-me/vitest.config.ts b/lib/fork-me/vitest.config.ts new file mode 100644 index 00000000..c264278a --- /dev/null +++ b/lib/fork-me/vitest.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from "vitest/config"; +import react from "@vitejs/plugin-react"; +import tsconfigPaths from "vite-tsconfig-paths"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react(), tsconfigPaths()], + test: { + environment: "jsdom", + globals: true, + setupFiles: [], + coverage: { + include: ["src/**"], + exclude: ["src/**/index.ts", "src/**/declaration.d.ts"], + reporter: ["text", "json", "clover", "html"], + }, + }, +}); diff --git a/package.json b/package.json new file mode 100644 index 00000000..fdc1ed96 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "private": true, + "scripts": { + "build": "turbo run build", + "dev": "turbo run dev", + "test": "turbo run test", + "doc": "turbo run doc", + "lint": "turbo run lint", + "format": "prettier --write \"**/*.{ts,tsx,js,jsx,md,css,scss}\"", + "preinstall": "echo setup" + }, + "devDependencies": { + "@changesets/cli": "^2.27.1", + "eslint": "^8.56.0", + "prettier": "^3.2.5", + "tsconfig": "workspace:*", + "turbo": "^1.12.4" + }, + "packageManager": "pnpm@8.6.10", + "name": "turborepo-template" +} diff --git a/packages/eslint-config-custom/CHANGELOG.md b/packages/eslint-config-custom/CHANGELOG.md new file mode 100644 index 00000000..08f8a0f2 --- /dev/null +++ b/packages/eslint-config-custom/CHANGELOG.md @@ -0,0 +1,7 @@ +# eslint-config-custom + +## 0.0.1 + +### Patch Changes + +- Support Next.js 14 diff --git a/packages/eslint-config-custom/README.md b/packages/eslint-config-custom/README.md new file mode 100644 index 00000000..8b42d901 --- /dev/null +++ b/packages/eslint-config-custom/README.md @@ -0,0 +1,3 @@ +# `@turbo/eslint-config` + +Collection of internal eslint configurations. diff --git a/packages/eslint-config-custom/library.js b/packages/eslint-config-custom/library.js new file mode 100644 index 00000000..db32ca2c --- /dev/null +++ b/packages/eslint-config-custom/library.js @@ -0,0 +1,33 @@ +const { resolve } = require("node:path"); + +const project = resolve(process.cwd(), "tsconfig.json"); + +/* + * This is a custom ESLint configuration for use with + * typescript packages. + * + * This config extends the Vercel Engineering Style Guide. + * For more information, see https://github.com/vercel/style-guide + * + */ + +module.exports = { + extends: ["@vercel/style-guide/eslint/node", "@vercel/style-guide/eslint/typescript"].map( + require.resolve, + ), + parserOptions: { + project, + }, + globals: { + React: true, + JSX: true, + }, + settings: { + "import/resolver": { + typescript: { + project, + }, + }, + }, + ignorePatterns: ["node_modules/", "dist/"], +}; diff --git a/packages/eslint-config-custom/next.js b/packages/eslint-config-custom/next.js new file mode 100644 index 00000000..3cee3392 --- /dev/null +++ b/packages/eslint-config-custom/next.js @@ -0,0 +1,43 @@ +const { resolve } = require("node:path"); + +const project = resolve(process.cwd(), "tsconfig.json"); + +/* + * This is a custom ESLint configuration for use with + * Next.js apps. + * + * This config extends the Vercel Engineering Style Guide. + * For more information, see https://github.com/vercel/style-guide + * + */ + +module.exports = { + extends: [ + "@vercel/style-guide/eslint/node", + "@vercel/style-guide/eslint/typescript", + "@vercel/style-guide/eslint/browser", + "@vercel/style-guide/eslint/react", + "@vercel/style-guide/eslint/next", + "eslint-config-turbo", + ].map(require.resolve), + parserOptions: { + project, + }, + globals: { + React: true, + JSX: true, + }, + settings: { + "import/resolver": { + typescript: { + project, + }, + }, + }, + ignorePatterns: ["node_modules/", "dist/"], + // add rules configurations here + rules: { + "import/no-default-export": "off", + "unicorn/filename-case": "off", + }, +}; diff --git a/packages/eslint-config-custom/package.json b/packages/eslint-config-custom/package.json new file mode 100644 index 00000000..cf89b0cb --- /dev/null +++ b/packages/eslint-config-custom/package.json @@ -0,0 +1,10 @@ +{ + "name": "eslint-config-custom", + "license": "MIT", + "version": "0.0.1", + "private": true, + "devDependencies": { + "@vercel/style-guide": "^5.2.0", + "eslint-config-turbo": "^1.12.4" + } +} diff --git a/packages/eslint-config-custom/react-internal.js b/packages/eslint-config-custom/react-internal.js new file mode 100644 index 00000000..d944fe95 --- /dev/null +++ b/packages/eslint-config-custom/react-internal.js @@ -0,0 +1,40 @@ +const { resolve } = require("node:path"); + +const project = resolve(process.cwd(), "tsconfig.json"); + +/* + * This is a custom ESLint configuration for use with + * internal (bundled by their consumer) libraries + * that utilize React. + * + * This config extends the Vercel Engineering Style Guide. + * For more information, see https://github.com/vercel/style-guide + * + */ + +module.exports = { + extends: [ + "@vercel/style-guide/eslint/browser", + "@vercel/style-guide/eslint/typescript", + "@vercel/style-guide/eslint/react", + ].map(require.resolve), + parserOptions: { + project, + }, + globals: { + JSX: true, + }, + settings: { + "import/resolver": { + typescript: { + project, + }, + }, + }, + ignorePatterns: ["node_modules/", "dist/", ".eslintrc.js"], + // add rules configurations here + rules: { + "import/no-default-export": "off", + "@typescript-eslint/explicit-function-return-type": "off", + }, +}; diff --git a/packages/shared-ui/.eslintrc.js b/packages/shared-ui/.eslintrc.js new file mode 100644 index 00000000..05ac2b2b --- /dev/null +++ b/packages/shared-ui/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ["custom/react-internal"], +}; diff --git a/packages/shared-ui/index.ts b/packages/shared-ui/index.ts new file mode 100644 index 00000000..3bd16e17 --- /dev/null +++ b/packages/shared-ui/index.ts @@ -0,0 +1 @@ +export * from "./src"; diff --git a/packages/shared-ui/package.json b/packages/shared-ui/package.json new file mode 100644 index 00000000..b15f9c1b --- /dev/null +++ b/packages/shared-ui/package.json @@ -0,0 +1,27 @@ +{ + "name": "shared-ui", + "author": "Mayank Kumar Chaudhari ", + "private": true, + "version": "1.0.1", + "description": "Shared UI Package", + "main": "./index.ts", + "types": "./index.ts", + "scripts": { + "lint": "eslint ." + }, + "devDependencies": { + "@mayank1513/fork-me": "workspace:*", + "@types/node": "^20.11.19", + "@types/react": "^18.2.56", + "@types/react-dom": "^18.2.19", + "eslint-config-custom": "workspace:*", + "next": "^14.1.0", + "nextjs-themes": "^2.1.1", + "react": "^18.2.0", + "tsconfig": "workspace:*", + "typescript": "5.3.3" + }, + "dependencies": { + "eslint": "^8.56.0" + } +} diff --git a/packages/shared-ui/src/cards/cards.module.css b/packages/shared-ui/src/cards/cards.module.css new file mode 100644 index 00000000..050430d1 --- /dev/null +++ b/packages/shared-ui/src/cards/cards.module.css @@ -0,0 +1,75 @@ +.cards { + display: flex; + justify-content: space-evenly; + flex-wrap: wrap; + gap: 25px; + width: var(--max-width); + max-width: 95vw; +} + +.card { + all: unset; + display: flex; + flex-direction: column; + padding: 1rem 1.2rem; + border-radius: var(--border-radius); + background: rgba(var(--card-rgb), 0); + border: 1px solid rgba(var(--card-border-rgb), 0.1); + cursor: pointer; + transition: + background 200ms, + border 200ms; +} + +.card span { + display: inline-block; + transition: transform 200ms; +} + +.card h2 { + font-weight: 600; + margin-top: 0; + text-align: start; +} + +.card p { + margin: 0; + opacity: 0.6; + font-size: 0.9rem; + line-height: 1.5; + width: 34ch; + text-align: start; +} + +.card nav { + display: flex; + gap: 15px; + padding-top: 10px; +} + +.card nav select { + flex-grow: 1; +} + +/* Enable hover only on non-touch devices */ +@media (hover: hover) and (pointer: fine) { + .card:hover { + background: rgba(var(--card-rgb), 0.1); + border: 1px solid rgba(var(--card-border-rgb), 0.15); + } + + .card:hover span { + transform: translateX(4px); + } +} + +/* Mobile and Tablet */ +@media (max-width: 1023px) { + .card { + padding: 1rem 2.5rem; + } + + .card h2 { + margin-bottom: 0.5rem; + } +} diff --git a/packages/shared-ui/src/cards/docs-card.tsx b/packages/shared-ui/src/cards/docs-card.tsx new file mode 100644 index 00000000..21e1a3f8 --- /dev/null +++ b/packages/shared-ui/src/cards/docs-card.tsx @@ -0,0 +1,16 @@ +import styles from "./cards.module.css"; + +export function DocsCard() { + return ( + +

+ Docs -> +

+

Explore the official docs.

+
+ ); +} diff --git a/packages/shared-ui/src/cards/examples-card.tsx b/packages/shared-ui/src/cards/examples-card.tsx new file mode 100644 index 00000000..f4114cac --- /dev/null +++ b/packages/shared-ui/src/cards/examples-card.tsx @@ -0,0 +1,16 @@ +import styles from "./cards.module.css"; + +export function ExamplesCard() { + return ( + +

+ More Examples -> +

+

Explore more examples on official GitHub Repo.

+
+ ); +} diff --git a/packages/shared-ui/src/cards/index.tsx b/packages/shared-ui/src/cards/index.tsx new file mode 100644 index 00000000..67bf5cf1 --- /dev/null +++ b/packages/shared-ui/src/cards/index.tsx @@ -0,0 +1,14 @@ +import { ExamplesCard } from "./examples-card"; +import styles from "./cards.module.css"; +import { StarMeCard } from "./star-me-card"; +import { DocsCard } from "./docs-card"; + +export function Cards() { + return ( +
+ + + +
+ ); +} diff --git a/packages/shared-ui/src/cards/star-me-card.tsx b/packages/shared-ui/src/cards/star-me-card.tsx new file mode 100644 index 00000000..da5266cd --- /dev/null +++ b/packages/shared-ui/src/cards/star-me-card.tsx @@ -0,0 +1,13 @@ +import { StarMe } from "@mayank1513/fork-me"; +import styles from "./cards.module.css"; + +export function StarMeCard() { + return ( + +

+ Star this repo -> +

+

Star this repo for your new library!

+
+ ); +} diff --git a/packages/shared-ui/src/common/logo.tsx b/packages/shared-ui/src/common/logo.tsx new file mode 100644 index 00000000..5a7e340b --- /dev/null +++ b/packages/shared-ui/src/common/logo.tsx @@ -0,0 +1,5 @@ +import type { HTMLProps } from "react"; + +export function Logo(props: HTMLProps) { + return turborepo-template; +} diff --git a/packages/shared-ui/src/common/select.tsx b/packages/shared-ui/src/common/select.tsx new file mode 100644 index 00000000..bbacd8fb --- /dev/null +++ b/packages/shared-ui/src/common/select.tsx @@ -0,0 +1,25 @@ +import type { HTMLProps, ReactNode } from "react"; + +export interface SelectOptionsProps { + value: string; + children: ReactNode; +} + +interface SelectProps extends HTMLProps { + options: string[] | SelectOptionsProps[]; +} + +export function Select({ options, ...props }: SelectProps) { + const renderOptions = options.map(option => + typeof option === "string" ? { value: option, children: option } : option, + ); + return ( + + ); +} diff --git a/packages/shared-ui/src/declaration.d.ts b/packages/shared-ui/src/declaration.d.ts new file mode 100644 index 00000000..a1421d73 --- /dev/null +++ b/packages/shared-ui/src/declaration.d.ts @@ -0,0 +1,4 @@ +declare module "*.module.css" { + const classNames: Record; + export = classNames; +} diff --git a/packages/shared-ui/src/globals.css b/packages/shared-ui/src/globals.css new file mode 100644 index 00000000..a88be8e2 --- /dev/null +++ b/packages/shared-ui/src/globals.css @@ -0,0 +1,115 @@ +* { + box-sizing: border-box; +} + +:root { + --max-width: 1100px; + --border-radius: 12px; + --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", + "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", + "Courier New", monospace; + --bg-color: #fff; + --text-color: #000; + + --primary-glow: conic-gradient( + from 180deg at 50% 50%, + #16abff33 0deg, + #0885ff33 55deg, + #54d6ff33 120deg, + #0071ff33 160deg, + transparent 360deg + ); + --secondary-glow: radial-gradient(rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); + + --callout-rgb: 238, 240, 241; + --callout-border-rgb: 172, 175, 176; + --card-rgb: 180, 185, 188; + --card-border-rgb: 131, 134, 135; + --tile-border: conic-gradient( + #00000080, + #00000040, + #00000030, + #00000020, + #00000010, + #00000010, + #00000080 + ); +} + +/* dark themes */ +.dark, +.dark ~ * { + --bg-color: #000; + --text-color: #fff; +} + +.dark, +.dark ~ * { + --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); + --secondary-glow: linear-gradient( + to bottom right, + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0.3) + ); + + --callout-rgb: 20, 20, 20; + --callout-border-rgb: 108, 108, 108; + --card-rgb: 100, 100, 100; + --card-border-rgb: 200, 200, 200; + --tile-border: conic-gradient( + #ffffff80, + #ffffff40, + #ffffff30, + #ffffff20, + #ffffff10, + #ffffff10, + #ffffff80 + ); +} + +/* light themes */ + +.light, +.light ~ * { + --bg-color: #fff; + --text-color: #000; +} + +html { + padding: 0; + margin: 0; +} + +body, +#root { + padding: 0; + margin: 0; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +main, +footer { + background: var(--bg-color); + color: var(--text-color); +} + +main { + flex-grow: 1; +} + +footer { + text-align: center; + padding: 10px; +} + +a { + color: inherit; + text-decoration: none; +} + +.grow { + flex-grow: 1; +} diff --git a/packages/shared-ui/src/index.ts b/packages/shared-ui/src/index.ts new file mode 100644 index 00000000..1c2c847f --- /dev/null +++ b/packages/shared-ui/src/index.ts @@ -0,0 +1 @@ +export * from "./root-layout"; diff --git a/packages/shared-ui/src/root-layout.module.css b/packages/shared-ui/src/root-layout.module.css new file mode 100644 index 00000000..d2eb0df6 --- /dev/null +++ b/packages/shared-ui/src/root-layout.module.css @@ -0,0 +1,153 @@ +.main { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + padding: 3rem 0; + min-height: calc(100vh - 55px); +} + +.description { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: nowrap !important; + font-size: 0.85rem; + max-width: var(--max-width); + width: 100%; + z-index: 2; + font-family: var(--font-mono); + padding: 10px; + padding-right: 100px; + position: sticky; + top: 0; + backdrop-filter: blur(3px); +} + +.description a { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; +} + +.description p { + position: relative; + margin: 0; + padding: 1rem; + background-color: rgba(var(--callout-rgb), 0.5); + border: 1px solid rgba(var(--callout-border-rgb), 0.3); + border-radius: var(--border-radius); +} + +.code { + font-weight: 700; + font-family: var(--font-mono); +} + +.center { + display: flex; + justify-content: center; + align-items: center; + position: relative; + flex-wrap: wrap; + padding: 3rem; + gap: 20px 50px; +} + +.center > div { + position: relative; +} + +.center::before { + background: var(--secondary-glow); + border-radius: 50%; + width: 480px; + height: 360px; + margin-left: -400px; + pointer-events: none; +} + +.center::after { + background: var(--primary-glow); + width: 240px; + height: 180px; + z-index: -1; +} + +.center::before, +.center::after { + content: ""; + left: 50%; + position: absolute; + filter: blur(45px); + transform: translateZ(0); +} + +.logo { + position: relative; + display: flex; + justify-content: center; + align-items: center; + margin-left: 16px; + transform: translateZ(0); + border-radius: var(--border-radius); + overflow: hidden; + box-shadow: 0px 2px 8px -1px #0000001a; + padding: 2px; +} +.logo p { + background: var(--bg-color); +} +.logo::before, +.logo::after { + content: " "; + position: absolute; + z-index: -1; +} + +/* Conic Gradient Animation */ +.logo::before { + animation: 3s rotate infinite linear; + width: 800%; + height: 800%; + background: var(--tile-border); +} + +/* Inner Square */ +.logo::after { + inset: 0; + padding: 1px; + border-radius: var(--border-radius); + background: linear-gradient( + to bottom right, + rgba(var(--tile-start-rgb), 1), + rgba(var(--tile-end-rgb), 1) + ); + background-clip: content-box; +} + +.by { + display: flex; + gap: 20px; +} + +/* Mobile and Tablet */ +@media (max-width: 800px) { + .center { + padding: 4rem; + } + .description { + padding: 30px; + padding-right: 100px; + } +} + +@keyframes rotate { + from { + transform: rotate(360deg); + } + to { + transform: rotate(0deg); + } +} diff --git a/packages/shared-ui/src/root-layout.tsx b/packages/shared-ui/src/root-layout.tsx new file mode 100644 index 00000000..d3e4c4aa --- /dev/null +++ b/packages/shared-ui/src/root-layout.tsx @@ -0,0 +1,32 @@ +import "./globals.css"; +import "nextjs-themes/styles.css"; +import { ThemeSwitcher } from "nextjs-themes"; +import { ForkMe } from "@mayank1513/fork-me/server"; // todo: import directory not supported in remix +import type { HTMLProps } from "react"; +import styles from "./root-layout.module.css"; +import { Cards } from "./cards"; +import { Description } from "./root/description"; +import { Hero } from "./root/hero"; +import { Footer } from "./root/footer"; + +export type SharedRootLayoutProps = HTMLProps; + +export function SharedRootLayout({ children, className = "", ...props }: SharedRootLayoutProps) { + return ( + <> + +
+ + {children} + + +
+