diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 62ae188133..b25e8f5c33 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -67,6 +67,7 @@ module.exports = { 'warn', { alias: { + '@/app': './apps/www/src/app', '@/plate': './apps/www/src/lib/plate', '@/components': './apps/www/src/components', '@/hooks': './apps/www/src/hooks', diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index 5051f484a3..fc7a852f23 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -8,13 +8,13 @@ assignees: '' --- -**Description** +## Description -**Steps to Reproduce** +## Steps to Reproduce @@ -25,7 +25,7 @@ assignees: '' 3. Scroll down to '....' 4. See the error --> -**Sandbox** +## Sandbox @@ -35,18 +35,18 @@ Share a link to a CodeSandbox where the error can be reproduced. You can start f [base sandbox here](https://codesandbox.io/s/rxo5rl?file=%2FApp.tsx) or refer to the examples too. --> -**Expected Behavior** +## Expected Behavior -**Environment** +## Environment - slate: - slate-react: - browser: chrome -**Bounty** +## Bounty Click [here](https://console.algora.io/org/Udecode/bounties/new) to add a bounty via Algora. diff --git a/.github/workflows/sync-templates.yml b/.github/workflows/sync-templates.yml index e05a71fad8..7b2c59b71d 100644 --- a/.github/workflows/sync-templates.yml +++ b/.github/workflows/sync-templates.yml @@ -10,12 +10,18 @@ on: - 'templates/**' jobs: - build-playground: - name: build-playground + build: + name: build runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + template: + - plate-template + - plate-playground-template defaults: run: - working-directory: templates/plate-playground-template + working-directory: templates/${{ matrix.template }} steps: - name: Checkout Repo uses: actions/checkout@v3 @@ -52,13 +58,18 @@ jobs: - name: Install dependencies run: pnpm install - # Lint, typecheck, build - name: Build run: pnpm build sync: - needs: build-playground + needs: build runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + template: + - plate-template + - plate-playground-template if: ${{ success() }} steps: - name: Checkout Repo @@ -68,5 +79,5 @@ jobs: - name: Sync Templates env: API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} - run: ./scripts/sync-templates.sh "templates/plate-playground-template" + run: ./scripts/sync-templates.sh "templates/${{ matrix.template }}" shell: bash \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 449f17febf..3d53e9f8ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,115 +4,135 @@ Thank you for your interest in helping to improve **`plate`**! As a community-le This document will provide guidance to help streamline the process and make efficient use of everyone's valuable time. -## **Issues** +## About this repository -No software is without bugs. If you encounter a problem, please follow these steps: - -- Look through our **[issue list](https://github.com/udecode/plate/issues?utf8=%E2%9C%93&q=)** to see if the issue already exists. - - If you find an existing issue that matches yours, please give it a "thumbs-up reaction". This helps us prioritize which issues to address first! -- If you can't find a match, feel free to create a new issue. - -### **Reproductions** +This repository is a monorepo. -The best way to help us understand and fix your issue is to provide a minimal reproduction of the problem. You can do this using **[our CodeSandbox](https://codesandbox.io/s/github/udecode/plate-playground)**. +- We use [yarn](https://yarnpkg.com/en/docs/install) and [`workspaces`](https://yarnpkg.com/features/workspaces) for development. +- We use [Rollup](https://rollupjs.org/) as our build system. +- We use [changesets](https://github.com/changesets/changesets) for managing releases. -### Development Guide +## Structure -### **Initial Setup** +This repository is structured as follows: -### Yarn +``` +apps +└── www + ├── content + └── src + └── app + ├── components + └── registry + └── default + ├── example + └── plate-ui +packages +└── core +``` -This repo uses yarn workspaces. You'll need to install **`yarn`** as your package manager. Check out the **[installation guide](https://yarnpkg.com/en/docs/install)** for help. +| Path | Description | +|---------------------------|------------------------------------------| +| `apps/www/content` | The content for the website. | +| `apps/www/src/app` | The Next.js application for the website. | +| `apps/www/src/components` | The React components for the website. | +| `apps/www/src/registry` | The registry for the components. | +| `packages/core` | The `@udecode/plate-core` package. | -### Clone +## Development -Clone the repo by running the following command: +### Start by cloning the repository: ```bash -git clone https://github.com/udecode/plate.git +git clone git@github.com:udecode/plate.git ``` -### Install & Build - -Navigate to the project's root directory and run the following commands: +### Install ```bash -cd plate yarn install -yarn build ``` -### **Development** - -To start the NextJS app on your local machine, use: +### Build ```bash -yarn dev +yarn build ``` -If you'd like to monitor a specific package for changes, run: +### Run a workspace -```bash -yarn workspace build:watch -``` +You can use the `turbo --filter=[WORKSPACE]` command to start the development process for a workspace. -### How to: Create a Component +#### Examples -- Create your component in `apps/www/src/registry/default/plate-ui` -- Add your component to `apps/www/src/registry/registry.ts` -- Run `yarn build:registry` +1. To run the `platejs.org` website: -To try installing your component locally: +``` +turbo --filter=www dev +``` -- `cd templates/plate-playground` -- `yarn g:plate-ui add ` +2. To build the `@udecode/plate-core` package: -### **How to: Docs** +``` +turbo --filter=@udecode/plate-core build +``` -Adding a new value? Here's the process: +## Documentation -- Create the value in **`/apps/www/src/lib/plate/demo/values`** -- Add your value to **`/apps/www/src/config/setting-values.ts`** -- Add your value to **`/apps/www/src/lib/plate/demo/values/usePlaygroundValue.ts`** +The documentation for this project is located in the `www` workspace. After running `yarn build`, you can run the documentation locally by running the following command: -Creating a new plugin? +```bash +yarn dev +``` -- Add your plugin to **`/apps/www/src/config/setting-plugins.ts`** -- Add your plugin to **`/apps/www/src/registry/default/example/playground-demo.tsx`** +Documentation is written using [MDX](https://mdxjs.com). You can find the documentation files in the `apps/www/content/docs` directory. -Creating a new document? +**Re-run the following commands on each package update:** -- Create a new mdx file in **`/apps/www/content/docs`** -- Add the new document to **`/apps/www/src/config/docs.ts`** +```bash +turbo --filter=[PACKAGE] build +yarn dev +``` -### How to: Create a Plate Package +## Components -Use the command below and follow the prompts to create a new package: +We use a registry system for developing components. You can find the source code for the components under `apps/www/src/registry`. The components are organized by styles. ```bash -yarn gen:package +apps +└── www + └── registry + ├── default + │ ├── example + │ └── plate-ui ``` -After creating your package, install and build it: +When adding or modifying components, please ensure that: -```bash -yarn install -yarn build -``` +1. You update the documentation. +2. You run `yarn build:registry` to update the registry. + +## CLI + +The `@udecode/plate-ui` package is a CLI for adding components to your project. You can find the documentation for the CLI [here](https://platejs.org/docs/components/cli). + +Any changes to the CLI should be made in the `packages/plate-ui` directory. If you can, it would be great if you could add tests for your changes. ### Run Linter -We use ESLint as our code linter (for all code, including TypeScript). To run the linter, use the following command: +We use [ESLint](https://eslint.org/) as our code linter. To run the linter, use the following command: ```bash yarn lint -# or +# autofix with: yarn lint:fix ``` +## Testing + ### Run Unit Tests -To list all test suites and options for running tests, use: +Tests are written using [Jest](https://jestjs.io/). You can run all the tests from the root of the repository. ```bash yarn test @@ -120,6 +140,8 @@ yarn test There are various modes available for running tests, including **`--watch`**, **`--coverage`**, and **`--runInBand`**. These can be selected from the command line interface or passed to **`yarn test`** as specific parameters. +Please ensure that the tests are passing when submitting a pull request. If you're adding new features, please include tests. + ### Run Playwright Tests We use Playwright for our end-to-end (e2e) tests in headless browsers. The React app for these tests is located in **`/apps/e2e-examples`**. @@ -136,15 +158,7 @@ To run all tests: yarn playwright ``` -For further details, refer to the specific sections in the original document. - -### Updating Tests - -Before submitting any contributions in a PR, please add or update meaningful tests. If your PR has failing tests, it will be considered as “Work in Progress” and won't be merged until all tests pass. - -For further details on how to add tests, refer to the specific sections in the original document. - -## Rel**ease Guide** +## Release Guide For those wanting a release, follow this sequence: @@ -152,32 +166,31 @@ For those wanting a release, follow this sequence: - Run **`yarn brl`** to synchronize the exports and automatically update the index files. - Make sure lint, test, and build pass. - Open a PR against **`main`** and **[add a changeset](https://github.com/atlassian/changesets/blob/main/docs/adding-a-changeset.md)**. -- To create a **[snapshot release](https://github.com/atlassian/changesets/blob/main/docs/snapshot-releases.md)**, maintainers can comment a GitHub issue starting with **`/release:next`**. - Merge the PR, which will trigger the bot to create a PR release. - Review the final changesets. - Merge the PR release, and the bot will release the updated packages on npm. -## **Pull Requests (PRs)** +## Requests for new features -We welcome all contributions and there are many ways you can help. Before you submit a new PR, please run **`yarn prerelease`**. Do not submit a PR if tests are failing. If you need help, the best way is to **[join Plate's Discord and ask in the #contributing channel](https://discord.gg/mAZRuBzGM3)**. +If you have a request for a new feature, please open a discussion on GitHub. We'll be happy to help you out. -You miss time/knowledge but still want to contribute? Just open a PR or a gist on Discord and we'll try to help. +## Issues -### **Reviewing PRs** - -**As a PR submitter**, you should reference the issue if there is one, include a short description of what you contributed, and provide instructions for manual testing if it is a code change. If your PR is reviewed as only needing trivial changes and you have commit access, then you can merge the PR after making those changes. +No software is without bugs. If you encounter a problem, please follow these steps: -**As a PR reviewer**, read through the changes and comment on any potential problems. Also, follow the testing instructions and manually test the changes. If the instructions are missing, unclear, or overly complex, request better instructions from the submitter. Unless the PR is a draft, if you approve the review and there are no other required discussions or changes, you should also go ahead and merge the PR. +- Look through our **[issue list](https://github.com/udecode/plate/issues?utf8=%E2%9C%93&q=)** to see if the issue already exists. + - If you find an existing issue that matches yours, please give it a "thumbs-up reaction". This helps us prioritize which issues to address first! +- If you can't find a match, feel free to create a new issue. -## **Issue Triage** +### Reproductions -Helping with issue triaging is a great way to contribute: +The best way to help us understand and fix your issue is to provide a minimal reproduction of the problem. You can do this using **[our CodeSandbox](https://codesandbox.io/s/github/udecode/plate-playground)**. -### **Responding to questions** +### Responding to questions The **[Q&A](https://github.com/udecode/plate/discussions/categories/q-a)** is a great place to help. If you can answer a question, it will benefit the asker and others who have a similar question. If an issue needs reproduction, you may be able to guide the reporter toward one, or even reproduce it yourself using **[this technique](https://github.com/udecode/plate/blob/main/CONTRIBUTING.md#reproductions)**. -### **Triaging issues** +### Triaging issues Once you've helped out on a few issues, you can help label issues and respond to reporters. We use a label scheme to categorize issues: @@ -189,9 +202,67 @@ All issues should have a **`type`** label. **`dependencies`** is for keeping pac If an issue is a **`bug`**, and it doesn't have a clear reproduction that you have personally confirmed, label it **`needs reproduction`** and ask the author to try and create a reproduction, or have a go yourself. -### **Closing issues** +### Closing issues - Duplicate issues should be closed with a link to the original. - Unreproducible issues should be closed if it's not possible to reproduce them. If the reporter drops offline, it is reasonable to wait 2 weeks before closing. - **`bug`**s should be closed when the issue is fixed and released. - **`feature`**s, **`maintenance`**s, should be closed when released or if the feature is deemed not appropriate. + +## Pull Requests (PRs) + +We welcome all contributions and there are many ways you can help. Before you submit a new PR, please run **build**, **lint** and **test**. Do not submit a PR if tests are failing. If you need help, the best way is to **[join Plate's Discord and ask in the #contributing channel](https://discord.gg/mAZRuBzGM3)**. + +You miss time/knowledge but still want to contribute? Just open a PR or a gist on Discord and we'll try to help. + +### Reviewing PRs + +**As a PR submitter**, you should reference the issue if there is one, include a short description of what you contributed, and provide instructions for manual testing if it is a code change. If your PR is reviewed as only needing trivial changes and you have commit access, then you can merge the PR after making those changes. + +**As a PR reviewer**, read through the changes and comment on any potential problems. Also, follow the testing instructions and manually test the changes. If the instructions are missing, unclear, or overly complex, request better instructions from the submitter. Unless the PR is a draft, if you approve the review and there are no other required discussions or changes, you should also go ahead and merge the PR. + +## Guides + +### How to: Create a Component + +- Create your component in `apps/www/src/registry/default/plate-ui` +- Add your component to `apps/www/src/registry/registry.ts` +- Run `yarn build:registry` + +To try installing your component locally: + +- `cd templates/plate-playground` +- `yarn g:plate-ui add ` + +### **How to: Docs** + +Adding a new value? Here's the process: + +- Create the value in **`/apps/www/src/lib/plate/demo/values`** +- Add your value to **`/apps/www/src/config/setting-values.ts`** +- Add your value to **`/apps/www/src/lib/plate/demo/values/usePlaygroundValue.ts`** + +Creating a new plugin? + +- Add your plugin to **`/apps/www/src/config/setting-plugins.ts`** +- Add your plugin to **`/apps/www/src/registry/default/example/playground-demo.tsx`** + +Creating a new document? + +- Create a new mdx file in **`/apps/www/content/docs`** +- Add the new document to **`/apps/www/src/config/docs.ts`** + +### How to: Create a Plate Package + +Use the command below and follow the prompts to create a new package: + +```bash +yarn gen:package +``` + +After creating your package, install and build it: + +```bash +yarn install +yarn build +``` \ No newline at end of file diff --git a/README.md b/README.md index a87ccaa926..39f81de7fb 100644 --- a/README.md +++ b/README.md @@ -31,20 +31,23 @@ Plate [//]: # '3. **Primitives**: Besides the headless plugins, we also provide primitive hooks and components built on top of [Radix UI](https://www.radix-ui.com/). These are **unstyled** and accessible parts for making great design systems.' [//]: # '4. **Components**: We know a good-looking start is important. So, we give you components created with Plate CLI and [shadcn/ui](https://ui.shadcn.com/). Use these as a starting point to create your own component library.' -## Documentation +## Templates -You can learn more about Plate by checking out our [documentation](https://platejs.org/docs). +You can choose one of the following templates to get started: -## Running locally +| Option | NextJS | Tailwind | Plate | Plugins | +| --------------------------------------------------------------------------------- | ------ | -------- | ----- | ------- | +| [Plate playground template](https://github.com/udecode/plate-playground-template) | ✅ | ✅ | ✅ | ✅ | +| [Plate minimal template](https://github.com/udecode/plate-template) | ✅ | ✅ | ✅ | | +| [NextJS template](https://platejs.org/docs/components/installation/next) | ✅ | ✅ | | | -To get started, check out our [contributing guide](CONTRIBUTING.md). +## Documentation -## Contributing +You can learn more about Plate by checking out our [documentation](https://platejs.org/docs). -### Ideas and discussions +## Contributing -[Discussions](https://github.com/udecode/plate/discussions) is the best -place for bringing opinions and contributions. Your feedback and contributions are welcome and will help us ensure that we are heading in the right direction with the project. +To get started, check out our [contributing guide](CONTRIBUTING.md). ### Contributors diff --git a/apps/e2e-examples/src/TableApp.tsx b/apps/e2e-examples/src/TableApp.tsx index 1886132a99..394c966c9a 100644 --- a/apps/e2e-examples/src/TableApp.tsx +++ b/apps/e2e-examples/src/TableApp.tsx @@ -1,5 +1,10 @@ import { createPlateUI } from '@/plate/create-plate-ui'; -import { createPlugins, createTablePlugin, Plate } from '@udecode/plate'; +import { + createPlugins, + createTablePlugin, + Plate, + PlateContent, +} from '@udecode/plate'; import { useVariant } from './useVariant'; @@ -80,10 +85,8 @@ export function TableApp() { ]; return ( - + + + ); } diff --git a/apps/www/content/docs/accessing-editor.mdx b/apps/www/content/docs/accessing-editor.mdx index 65ed433fea..bdf1112aa5 100644 --- a/apps/www/content/docs/accessing-editor.mdx +++ b/apps/www/content/docs/accessing-editor.mdx @@ -57,11 +57,11 @@ const createMyPlugin = createPluginFactory({ ## From a Child of Plate -Use the **`usePlateEditorRef`** or **`usePlateEditorState`** hooks. +Use the **`useEditorRef`** or **`useEditorState`** hooks. -Internally, **`usePlateEditorState`** is a wrapper for **`usePlateEditorRef`**. The only difference is that **`usePlateEditorState`** causes React to re-render whenever the **`editor`** state changes, whereas **`usePlateEditorRef`** does not cause a re-render. Since **`editor`** is mutable and is updated by reference, **`usePlateEditorRef`** will be sufficient (and more efficient) in most situations. +Internally, **`useEditorState`** is a wrapper for **`useEditorRef`**. The only difference is that **`useEditorState`** causes React to re-render whenever the **`editor`** state changes, whereas **`useEditorRef`** does not cause a re-render. Since **`editor`** is mutable and is updated by reference, **`useEditorRef`** will be sufficient (and more efficient) in most situations. -You can call these hooks from any React component that is rendered as a descendant of the **`Plate`** (or **`PlateProvider`**) component, including [Plugin Components](/docs/plugin-components). +You can call these hooks from any React component that is rendered as a descendant of the **`Plate`** component, including [Plugin Components](/docs/plugin-components). ```tsx showLineNumbers {6} const ParagraphElement = ({ @@ -69,17 +69,15 @@ const ParagraphElement = ({ children, ...props }: PlateElementProps) => { - const editor = usePlateEditorRef(); - + const editor = useEditorRef(); + const handleClick = useCallback(() => { - console.log('You clicked on a paragraph, and the editor is ', editor); + console.info('You clicked on a paragraph, and the editor is ', editor); }, [editor]); - + return ( -

- {children} -

+

{children}

); }; @@ -89,55 +87,59 @@ One common pattern is to add an effect component as a child of **`Plate`** that ```tsx showLineNumbers {2,17} const CustomEffect = () => { - const editor = usePlateEditorRef(); - + const editor = useEditorRef(); + useEffect(() => { const interval = setInterval(() => { - console.log('The editor is ', editor); + console.info('The editor is ', editor); }, 1000); - + return () => clearInterval(interval); }, [editor]); - + return null; }; export default () => ( + + ); ``` - **If **`editor`** is modified by reference, why include it in dependency lists?**
- Good question! Even though **`editor`** is usually modified by reference, there are some situations in which it's replaced with a fresh instance, such as when the editor is reset. + **If **`editor`** is modified by reference, why include it in dependency + lists?** +
+ Good question! Even though **`editor`** is usually modified by reference, + there are some situations in which it's replaced with a fresh instance, such + as when the editor is reset.
## From a Sibling of Plate -Wrap **`Plate`** and the sibling in **`PlateProvider`**, and then use **`usePlateEditorRef`** or **`usePlateEditorState`** from within the sibling. - -Note that certain **`Plate`** props, such as **`plugins`** and **`initialValue`**, must be lifted up to the **`PlateProvider`**. See [From an Ancestor](#from-an-ancestor) if this is impractical or impossible for you to achieve. +Wrap **`PlateContent`** and the sibling in **`Plate`**, and then use **`useEditorRef`** or **`useEditorState`** from within the sibling. ```tsx showLineNumbers {2,8,11} const Toolbar = () => { - const editor = usePlateEditorState(); + const editor = useEditorState(); // Do something with editor // ... }; -export default () => ( - +const Editor = () => ( + - - + +
); ``` ## From an Ancestor -If you need to access the **`editor`** instance from an ancestor of **`Plate`**, wrapping the relevant components in a **`PlateProvider`** is the preferred solution. If this is not an option, you can instead use the **`editorRef`** prop to pass a reference to the **`editor`** instance up the React component tree to where it is needed. +If you need to access the **`editor`** instance from an ancestor of **`PlateContent`**, wrapping the relevant components in a **`Plate`** is the preferred solution. If this is not an option, you can instead use the **`editorRef`** prop to pass a reference to the **`editor`** instance up the React component tree to where it is needed. The **`editorRef`** prop can be used with **`useRef`**, **`useState`**, or a custom ref callback. Regardless of which you use, you'll need to handle the case where **`editor`** is null. This happens when the editor hasn't had a chance to render yet or has unmounted. @@ -146,70 +148,71 @@ The **`editorRef`** prop can be used with **`useRef`**, **`useState`**, or a cus ```tsx showLineNumbers {2,21} const App = () => { const editorRef = useRef(null); - + const handleSomeEvent = useCallback(() => { // editor has type PlateEditor | null const editor = editorRef.current; - + if (editor) { // Do something with editor } }, []); - + // Pass editorRef and handleSomeEvent down to where they're needed // ... }; -const MyEditor = ({ +const Editor = ({ editorRef, }: { editorRef: MutableRefObject; -}) => ; +}) => ( + + + +); ``` ### With State If you want your ancestor component to re-render when the editor content changes, you may want to use **`useState`** to store your **`editor`** instance. Since the **`editorRef`** callback is only called once when the editor first mounts, you'll also need to manually trigger a re-render by updating a counter whenever the **`onChange`** handler of **`Plate`** is called. -Using **`editorRef`** with **`useState`** without a counter is equivalent to using **`usePlateEditorRef`** instead of **`usePlateEditorState`** (the difference is discussed above). Most of the time, if you don't need the ancestor component to re-render on every change, you should be using **`useRef`** instead. +Using **`editorRef`** with **`useState`** without a counter is equivalent to using **`useEditorRef`** instead of **`useEditorState`** (the difference is discussed above). Most of the time, if you don't need the ancestor component to re-render on every change, you should be using **`useRef`** instead. ```tsx showLineNumbers {2-3,34-35} const App = () => { const [editor, setEditor] = useState(null); const [, handleUpdateEditor] = useReducer((x) => x + 1, 0); - + // Pass editor, setEditor and handleUpdateEditor down to where they're needed // ... }; -const EditorPreview = ({ - editor, -}: { - editor: PlateEditor | null; -}) => { +const EditorPreview = ({ editor }: { editor: PlateEditor | null }) => { // html has type string | null const html = useMemo( - () => editor && serializeHtml(editor, { - nodes: editor.children, - }), + () => + editor && + serializeHtml(editor, { + nodes: editor.children, + }), [editor, editor?.children] ); - + if (!html) return null; return
; }; -const MyEditor = ({ +const Editor = ({ setEditor, handleUpdateEditor, }: { setEditor: (editor: PlateEditor | null) => void; handleUpdateEditor: () => void; }) => ( - + + + ); ``` @@ -227,7 +230,7 @@ const plugins = createPlugins([ // ... ]); -export default ({ initialHtml }: { initialHtml: string }) => { +const Editor = ({ initialHtml }: { initialHtml: string }) => { /** * Changing the initialValue after render is not supported, so initialHtml * is not included in the useMemo deps. @@ -238,13 +241,11 @@ export default ({ initialHtml }: { initialHtml: string }) => { element: initialHtml, }); }, []); - + return ( - + + + ); }; ``` - diff --git a/apps/www/content/docs/api/core.mdx b/apps/www/content/docs/api/core.mdx index f59b75e106..802c66b0ac 100644 --- a/apps/www/content/docs/api/core.mdx +++ b/apps/www/content/docs/api/core.mdx @@ -315,7 +315,7 @@ Hook to get the element from a node component. The plugin key. -- **Default:** `SCOPE_ELEMENT`. +- **Default:** the closest element key. @@ -327,12 +327,17 @@ The value of the element as a TElement. ### useEditorRef -Get the Slate editor reference. +Get the Slate editor reference without re-rendering. - Does not re-render on editor change. -- Does not support nested editors. - Should be used inside `Plate`. +- Note the reference does not change when the editor changes. + + + The ID of the plate editor. Useful only when nesting editors. Default is using the closest editor id. + + A `PlateEditor` object, which is the Slate editor. @@ -341,81 +346,71 @@ A `PlateEditor` object, which is the Slate editor. ### useEditorState -Get the Slate editor reference. +Get the Slate editor reference with re-rendering. - Re-renders on editor change. -- Does not support nested editors. +- Supports nested editors. - Should be used inside `Plate`. +- Note the reference does not change when the editor changes. + + + The ID of the plate editor. Default is using the closest editor id. + + A `PlateEditor` object, which is the Slate editor. -### usePlateEditorRef +### useEditorReadOnly -Get an editor reference which is never updated. - -- Does not re-render on editor change. -- Supports nested editors. -- Should be used inside `Plate` or `PlateProvider`. +Get the editor's `readOnly` state. - The ID of the plate editor. Useful only when nesting editors. + The ID of the plate editor. -A `PlateEditor` object, which is the Slate editor. +The `readOnly` state of the editor. -### usePlateEditorState - -Get the Slate editor reference. Re-renders on editor change. +### useEditorSelection -- Re-renders on editor change. -- Supports nested editors. -- Should be used inside `Plate` or `PlateProvider`. +Get the editor's selection. Memoized so it does not re-render if the range is the same. The ID of the plate editor. - - -A `PlateEditor` object, which is the Slate editor. - - +The current selection in the editor. -### usePlateReadOnly +### useEditorVersion -Get the editor's `readOnly` state. +Get the version of the editor value. That version is incremented on each editor change. The ID of the plate editor. - - -The `readOnly` state of the editor. - - +The current version of the editor value. -### usePlateSelection +### useSelectionVersion -Get the editor's selection which is updated on each editor change. +Get the version of the editor selection. That version is incremented on each selection change (the range being different). The ID of the plate editor. -The current selection in the editor. +The current version of the editor selection. ## Core plugins @@ -447,6 +442,10 @@ Creates a plugin that merges and registers all the inline types and void types f Creates a plugin that overrides the default `insertData` function in the editor, which is called when data is being pasted or dragged into the editor. +### createLengthPlugin + +Creates a plugin that enforces a maximum length for the editor. + ### createNodeFactoryPlugin Creates a plugin that overrides the default `blockFactory` and `childrenFactory` functions in the editor. These functions are used to generate the default blocks and children for the editor. diff --git a/apps/www/content/docs/api/core/plate.mdx b/apps/www/content/docs/api/core/plate.mdx index f961433d62..5cf08313bb 100644 --- a/apps/www/content/docs/api/core/plate.mdx +++ b/apps/www/content/docs/api/core/plate.mdx @@ -3,27 +3,27 @@ title: Plate description: API reference for Plate component. --- -`Plate` is the core component rendering the editor. It takes care of computing and passing `Slate` and `Editable` props from the `plugins`. +`Plate` is the root component loading the editor state into a store provider. -`PlateProvider` is the component loading the Plate store. Any component rendered below has access to the Plate store. If `Plate` does not find any parent `PlateProvider`, it will take care of creating one (provider-less mode). +`PlateContent` is the component that renders the editor. ## Plate Props - + A unique ID to store the editor state by ID. This is mandatory when nesting **`Plate`** instances but optional otherwise. -- **Default:** `'main'`. +- **Default:** `'plate'`. -The last component rendered inside **`Slate`**, after **`Editable`**. Use **`firstChildren`** to render the first children. +Children components have access to the plate store. -See [decorate](#decorate). +See [decorations](https://docs.slatejs.org/concepts/09-rendering#decorations). @@ -38,189 +38,153 @@ Can be **`true`** to disable all core plugins, an object to selectively disable + - + + +A controlled **`editor`**. + +- **Default:** **`createPlateEditor({ id, plugins, disableCorePlugins })`** + + + + +An uncontrolled **`editor`** ref. + +- **Default:** **`createPlateEditor({ id, plugins, disableCorePlugins })`** + + + + +Initial editor value. -Props for the **`Editable`** component. Extends `TextareaHTMLAttributes`. See [Editable](https://docs.slatejs.org/libraries/slate-react/editable) docs. +- **Default:** **`editor.childrenFactory()`** + + + + +Specifies the maximum number of characters allowed in the editor. - + + + +If **`true`**, normalizes the initial **`editor`** value upon creation. This is useful for applying normalization rules on existing content. + +- **Default:** **`false`** + + + + +Controlled callback called when the editor state changes. - + + +Plate plugins. See [Plugin](/docs/plugin) guide. + + + + +Alias to **`initialValue`**. Stored in the store on each change (**`Editable.onChange`**). To update **`value`** with history support, use **[Slate transforms](https://docs.slatejs.org/concepts/04-transforms)**. To reset **`value`**, use `resetEditor`. + +- **Default:** **`editor.childrenFactory()`** + + + + +## PlateContent Props + +Props for the [Editable](https://docs.slatejs.org/libraries/slate-react/editable) component. Extends `TextareaHTMLAttributes`. + + + + +Custom **`Editable`** node. + +- **Default:** **``** + + + - - - - - - - - - - - - + - - - - - - - -Ref to the **`Editable`** component. [Not yet supported by Slate React](https://github.com/ianstormtaylor/slate/issues/4082). - - - - -A controlled **`editor`**. - -- **Default:** **`createPlateEditor({ id, plugins, disableCorePlugins })`** - - - - -The first children rendered inside **`Slate`**, before **`Editable`**. Use **`children`** instead if you need resolved Slate DOM on the first render. - - - - -Initial editor value. - -- **Default:** **`editor.childrenFactory()`** - - - - -If **`true`**, normalizes the initial **`editor`** value upon creation. This is useful for applying normalization rules on existing content. - -- **Default:** **`false`** - - - - -Controlled callback called when the editor state changes. - - - - -Plate plugins. See [Plugin](/docs/plugin) guide. - - - - -Custom **`Editable`** node. - -- **Default:** **``** - - - - -See [renderElement](#renderelement). - - - - -See [renderLeaf](#renderleaf). - - - - -Alias to **`initialValue`**. Stored in the store on each change (**`Editable.onChange`**). To update **`value`** with history support, use **[Slate transforms](https://docs.slatejs.org/concepts/04-transforms)**. To reset **`value`**, use `useResetPlateEditor`, which will also reset the editor. - -- **Default:** **`editor.childrenFactory()`** - - - - -## PlateProvider Props - -A react component that provides the context for the Plate editor. - -Same props than [PlateProps](#plate-props) excluding: - -- `editableProps` -- `editableRef` -- `firstChildren` -- `renderEditable` - -If used, only the listed props should be set on `Plate`. + ## How Plate Works **`Plate`** computes the **`Slate`** props: **`key`**, **`editor`**, **`onChange`**. -In addition to **`editableProps`**, **`Plate`** computes **`Editable`** props if **`editor`** is defined: +**`Plate`** also computes **`Editable`** props if **`editor`** is defined: ### decorate -This prop integrates **`decorate`** plugins. If a **`decorate`** prop is defined, it will be added. Similarly, if **`editableProps.decorate`** is defined, it will be included as well. +This prop integrates **`decorate`** plugins. If a **`decorate`** prop is defined, it will be added. ### renderElement @@ -230,7 +194,7 @@ When a plugin's **`isElement`** is **`true`** and its **`type`** matches **`prop - **`component`** is used to render the element itself. - **`inject.aboveComponent`** and **`inject.belowComponent`** can inject components above and below **`component`**, respectively. -If no suitable plugin is found for a node type, **`editableProps.renderElement`** is used (if defined). In the absence of this prop, **`DefaultElement`** (a plain **`div`**) is used. +If no suitable plugin is found for a node type, **`renderElement`** prop is used (if defined). In the absence of this prop, **`DefaultElement`** (a plain **`div`**) is used. ### renderLeaf @@ -239,7 +203,7 @@ If a plugin's **`isLeaf`** is **`true`** and its **`type`** matches **`props.lea - **`inject.props`** are used to inject rendering props. - **`component`** is used to render the leaf. -If no plugin is found for a node type, **`editableProps.renderLeaf`** is used (if defined). If this is also not defined, **`DefaultLeaf`** (a plain **`span`**) is used. +If no plugin is found for a node type, **`renderLeaf`** prop is used (if defined). If this is also not defined, **`DefaultLeaf`** (a plain **`span`**) is used. ### Handlers diff --git a/apps/www/content/docs/api/core/store.mdx b/apps/www/content/docs/api/core/store.mdx index 5c7b33b928..94181cb543 100644 --- a/apps/www/content/docs/api/core/store.mdx +++ b/apps/www/content/docs/api/core/store.mdx @@ -7,7 +7,7 @@ description: API reference for Plate store. **Note**: To use the store hooks in a component, it needs to be rendered - inside `PlateProvider` or `Plate`. + inside `Plate`. ## Plate Store @@ -19,7 +19,7 @@ The PlateStoreState object stores the state of the Plate editor. It contains inf -A unique ID used as a provider scope. Use it if you have multiple `PlateProvider` in the same React tree. +A unique ID used as a provider scope. Use it if you have multiple `Plate` in the same React tree. - **Default:** `PLATE_SCOPE` @@ -34,6 +34,12 @@ Slate editor reference. + + +Whether the `PlateContent` is mounted. + + + Whether the editor is read-only. @@ -60,21 +66,21 @@ Value of the `editor`. - + -A random key updated on each `editor` change. +Version incremented on each `editor` change. - + -A random key updated on each `editor.selection` change. +Version incremented on each `editor.selection` change. - + -A random key updated when calling `redecorate`. This is a dependency of the `decorate` function. +Version incremented when calling `redecorate`. This is a dependency of the `decorate` function. diff --git a/apps/www/content/docs/block-selection.mdx b/apps/www/content/docs/block-selection.mdx index ba44179de0..468bdc4b26 100644 --- a/apps/www/content/docs/block-selection.mdx +++ b/apps/www/content/docs/block-selection.mdx @@ -37,13 +37,10 @@ const plugins = [ ### Styling -You can style the selection area by using the `slate-selection-area` class: +You can style the selection area by adding this class to `body`, selecting `slate-selection-area`. -```css -.slate-selection-area { - background: #4f90f22d; - border: 1px solid #4f90f2; -} +```js +'[&_.slate-selection-area]:border [&_.slate-selection-area]:border-primary [&_.slate-selection-area]:bg-primary/20' ``` ## API diff --git a/apps/www/content/docs/components/align-dropdown-menu.mdx b/apps/www/content/docs/components/align-dropdown-menu.mdx index 7f4fc75023..c675d94354 100644 --- a/apps/www/content/docs/components/align-dropdown-menu.mdx +++ b/apps/www/content/docs/components/align-dropdown-menu.mdx @@ -11,8 +11,6 @@ docs: title: Toolbar --- - - ## Installation @@ -66,4 +64,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/blockquote-element.mdx b/apps/www/content/docs/components/blockquote-element.mdx index 73349eb67d..573150da8b 100644 --- a/apps/www/content/docs/components/blockquote-element.mdx +++ b/apps/www/content/docs/components/blockquote-element.mdx @@ -7,8 +7,6 @@ docs: title: Block Quote --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/caption.mdx b/apps/www/content/docs/components/caption.mdx index 0532968538..d04d439b29 100644 --- a/apps/www/content/docs/components/caption.mdx +++ b/apps/www/content/docs/components/caption.mdx @@ -7,8 +7,6 @@ docs: title: Caption --- - - ## Installation @@ -61,5 +59,7 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/changelog.mdx b/apps/www/content/docs/components/changelog.mdx index 57ebfa77a1..550c240b08 100644 --- a/apps/www/content/docs/components/changelog.mdx +++ b/apps/www/content/docs/components/changelog.mdx @@ -10,6 +10,31 @@ Use the [CLI](https://platejs.org/docs/components/cli) to install the latest ver ## September 2023 #4 +### 18 Sept #4.4 + +- `editor`: New component 🎉 See [Editor](https://platejs.org/docs/components/editor) +- `fixed-toolbar-buttons`, `floating-toolbar-buttons`, `mode-dropdown-menu`: + - plate 24: rename `usePlateReadOnly` to `useEditorReadOnly` +- `code-block-element`: changes in `code-block-element.css` + +### 15 Sept #4.3 + +- `table-element` + - fix: typing in a table should keep the floating toolbar opened +- `floating-toolbar`: + - fix: import +- `comment-leaf`, `link-element` + - feat: use primary color +- block selection: + - add this class to `body`: `'[&_.slate-selected]:!bg-primary/20 [&_.slate-selection-area]:border [&_.slate-selection-area]:border-primary [&_.slate-selection-area]:bg-primary/10'` + +### 12 Sept #4.2 + +- `button`: add `whitespace-nowrap` +- `popover`: hidden when printing +- `caption`: hidden placeholder when printing +- `highlight-leaf`: highlight color is now based on the primary color + ### 2 Sept #4.1 - `link-floating-toolbar` diff --git a/apps/www/content/docs/components/cli.mdx b/apps/www/content/docs/components/cli.mdx index 8d82640ada..6b5807a1f6 100644 --- a/apps/www/content/docs/components/cli.mdx +++ b/apps/www/content/docs/components/cli.mdx @@ -71,6 +71,10 @@ Which components would you like to add? › Space to select. Return to submit. ◯ combobox ``` + + Pick the components you want in our interactive builder to generate the bulk add command to run. + + ### Options ```txt diff --git a/apps/www/content/docs/components/cloud.mdx b/apps/www/content/docs/components/cloud.mdx index 7fa2c19734..1bf736158c 100644 --- a/apps/www/content/docs/components/cloud.mdx +++ b/apps/www/content/docs/components/cloud.mdx @@ -7,8 +7,6 @@ docs: title: Cloud --- - - ## Installation @@ -63,6 +61,8 @@ Update the import paths to match your project setup. ## Examples + + ### Plugins ```tsx @@ -97,12 +97,12 @@ const plugins = createMyPlugins( ```tsx export default function CloudDemo() { return ( - plugins={plugins} initialValue={cloudValue}> + plugins={plugins} initialValue={cloudValue}> - editableProps={editableProps} /> - + + ); } ``` diff --git a/apps/www/content/docs/components/code-block-element.mdx b/apps/www/content/docs/components/code-block-element.mdx index ede22ef284..63ca5db9f6 100644 --- a/apps/www/content/docs/components/code-block-element.mdx +++ b/apps/www/content/docs/components/code-block-element.mdx @@ -9,8 +9,6 @@ docs: title: Command --- - - ## Installation @@ -63,4 +61,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/code-leaf.mdx b/apps/www/content/docs/components/code-leaf.mdx index b21cb789f3..98dd1d7e38 100644 --- a/apps/www/content/docs/components/code-leaf.mdx +++ b/apps/www/content/docs/components/code-leaf.mdx @@ -7,8 +7,6 @@ docs: title: Basic Marks --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/code-line-element.mdx b/apps/www/content/docs/components/code-line-element.mdx index 762c027e21..37379ff681 100644 --- a/apps/www/content/docs/components/code-line-element.mdx +++ b/apps/www/content/docs/components/code-line-element.mdx @@ -7,8 +7,6 @@ docs: title: Code Block --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/code-syntax-leaf.mdx b/apps/www/content/docs/components/code-syntax-leaf.mdx index 4ce4c23f87..a71504deba 100644 --- a/apps/www/content/docs/components/code-syntax-leaf.mdx +++ b/apps/www/content/docs/components/code-syntax-leaf.mdx @@ -7,8 +7,6 @@ docs: title: Code Block --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/color-dropdown-menu.mdx b/apps/www/content/docs/components/color-dropdown-menu.mdx index 89f935fe7a..258855e6aa 100644 --- a/apps/www/content/docs/components/color-dropdown-menu.mdx +++ b/apps/www/content/docs/components/color-dropdown-menu.mdx @@ -17,8 +17,6 @@ docs: title: Tooltip --- - - ## Installation @@ -78,4 +76,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/combobox.mdx b/apps/www/content/docs/components/combobox.mdx index 78df665eef..b9033d28f6 100644 --- a/apps/www/content/docs/components/combobox.mdx +++ b/apps/www/content/docs/components/combobox.mdx @@ -7,8 +7,6 @@ docs: title: Combobox --- - - ## Installation @@ -63,5 +61,7 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/comment-leaf.mdx b/apps/www/content/docs/components/comment-leaf.mdx index 0da3b6d90b..499d29ae73 100644 --- a/apps/www/content/docs/components/comment-leaf.mdx +++ b/apps/www/content/docs/components/comment-leaf.mdx @@ -7,8 +7,6 @@ docs: title: Comments --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/comment-toolbar-button.mdx b/apps/www/content/docs/components/comment-toolbar-button.mdx index f5bd0e6703..79d803c148 100644 --- a/apps/www/content/docs/components/comment-toolbar-button.mdx +++ b/apps/www/content/docs/components/comment-toolbar-button.mdx @@ -9,8 +9,6 @@ docs: title: Toolbar --- - - ## Installation @@ -62,5 +60,7 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/comments-popover.mdx b/apps/www/content/docs/components/comments-popover.mdx index 9200dc6ec3..5d5f724ed0 100644 --- a/apps/www/content/docs/components/comments-popover.mdx +++ b/apps/www/content/docs/components/comments-popover.mdx @@ -11,8 +11,6 @@ docs: title: Avatar --- - - ## Installation @@ -76,5 +74,7 @@ Update the import paths to match your project setup. ## Examples - + + + diff --git a/apps/www/content/docs/components/components-json.mdx b/apps/www/content/docs/components/components-json.mdx new file mode 100644 index 0000000000..a3b0807cbf --- /dev/null +++ b/apps/www/content/docs/components/components-json.mdx @@ -0,0 +1,149 @@ +--- +title: components.json +description: Configuration for your project. +--- + +The `components.json` file holds configuration for your project. + +We use it to understand how your project is set up and how to generate components customized for your project. + + + Note: The `components.json` file is optional and **only required if you're + using the CLI** to add components to your project. If you're using the copy + and paste method, you don't need this file. + + +You can create a `components.json` file in your project by running the following command: + +```bash +npx @udecode/plate-ui@latest init +``` + +See the CLI section for more information. + +## $schema + +You can see the JSON Schema for `components.json` [here](https://platejs.org/schema.json). + +```json title="components.json" +{ + "$schema": "https://platejs.org/schema.json" +} +``` + +## style + +The style for your components. **This cannot be changed after initialization.** + +```json title="components.json" +{ + "style": "default" +} +``` + +## tailwind + +Configuration to help the CLI understand how Tailwind CSS is set up in your project. + +See the installation section for how to set up Tailwind CSS. + +### tailwind.config + +Path to where your `tailwind.config.js` file is located. + +```json title="components.json" +{ + "tailwind": { + "config": "tailwind.config.js" | "tailwind.config.ts" + } +} +``` + +### tailwind.css + +Path to the CSS file that imports Tailwind CSS into your project. + +```json title="components.json" +{ + "tailwind": { + "css": "src/styles/globals.css" + } +} +``` + +### tailwind.baseColor + +This is used to generate the default color palette for your components. **This cannot be changed after initialization.** + +```json title="components.json" +{ + "tailwind": { + "baseColor": "slate" | "gray" | "neutral" | "stone" | "zinc" + } +} +``` + +### tailwind.cssVariables + +You can choose between using CSS variables or Tailwind CSS utility classes for theming. + +To use utility classes for theming set `tailwind.cssVariables` to `false`. For CSS variables, set `tailwind.cssVariables` to `true`. + +```json title="components.json" +{ + "tailwind": { + "cssVariables": `true` | `false` + } +} +``` + +For more information, see the theming docs. + +**This cannot be changed after initialization.** To switch between CSS variables and utility classes, you'll have to delete and re-install your components. + +## rsc + +Whether or not to enable support for React Server Components. + +The CLI automatically adds a `use client` directive to client components when set to `true`. + +```json title="components.json" +{ + "rsc": `true` | `false` +} +``` + +## aliases + +The CLI uses these values and the `paths` config from your `tsconfig.json` file to place generated components in the correct location. + +Path aliases have to be set up in your `tsconfig.json` file. + + + **Important:** If you're using the `src` directory, make sure it is included + under `paths` in your `tsconfig.json` file. + + +### aliases.utils + +Import alias for your utility functions. + +```json title="components.json" +{ + "aliases": { + "utils": "@/lib/utils" + } +} +``` + +### aliases.components + +Import alias for your components. + +```json title="components.json" +{ + "aliases": { + "components": "@/components" + } +} +``` \ No newline at end of file diff --git a/apps/www/content/docs/components/cursor-overlay.mdx b/apps/www/content/docs/components/cursor-overlay.mdx index a9d299c0e7..05e2a2b054 100644 --- a/apps/www/content/docs/components/cursor-overlay.mdx +++ b/apps/www/content/docs/components/cursor-overlay.mdx @@ -4,8 +4,6 @@ description: Overlay a cursor indicator for collaborative editing or real-time i component: true --- - - ## Installation @@ -58,7 +56,9 @@ Update the import paths to match your project setup. ## Examples - + + + ## API diff --git a/apps/www/content/docs/components/dark-mode/index.mdx b/apps/www/content/docs/components/dark-mode/index.mdx new file mode 100644 index 0000000000..4f4e19a4fe --- /dev/null +++ b/apps/www/content/docs/components/dark-mode/index.mdx @@ -0,0 +1,33 @@ +--- +title: Dark Mode +description: Adding dark mode to your site. +--- + +
+ + + Next.js + + +

Next.js

+
+ + + Vite + + +

Vite

+
+
diff --git a/apps/www/content/docs/components/dark-mode.mdx b/apps/www/content/docs/components/dark-mode/next.mdx similarity index 86% rename from apps/www/content/docs/components/dark-mode.mdx rename to apps/www/content/docs/components/dark-mode/next.mdx index 805a1246d0..49bdb1eb31 100644 --- a/apps/www/content/docs/components/dark-mode.mdx +++ b/apps/www/content/docs/components/dark-mode/next.mdx @@ -1,12 +1,20 @@ --- -title: Dark Mode -description: Adding dark mode to your site. +title: Next.js +description: Adding dark mode to your next app. --- -## Next.js +## Dark mode +### Install next-themes + +Start by installing `next-themes`: + +```bash +npm install next-themes +``` + ### Create a theme provider ```tsx title="components/theme-provider.tsx" diff --git a/apps/www/content/docs/components/dark-mode/vite.mdx b/apps/www/content/docs/components/dark-mode/vite.mdx new file mode 100644 index 0000000000..982125c618 --- /dev/null +++ b/apps/www/content/docs/components/dark-mode/vite.mdx @@ -0,0 +1,150 @@ +--- +title: Vite +description: Adding dark mode to your vite app. +--- + +## Dark mode + + + +### Create a theme provider + +```tsx title="components/theme-provider.tsx" +import { createContext, useContext, useEffect, useState } from "react" + +type Theme = "dark" | "light" | "system" + +type ThemeProviderProps = { + children: React.ReactNode + defaultTheme?: Theme + storageKey?: string +} + +type ThemeProviderState = { + theme: Theme + setTheme: (theme: Theme) => void +} + +const initialState: ThemeProviderState = { + theme: "system", + setTheme: () => null, +} + +const ThemeProviderContext = createContext(initialState) + +export function ThemeProvider({ + children, + defaultTheme = "system", + storageKey = "vite-ui-theme", + ...props +}: ThemeProviderProps) { + const [theme, setTheme] = useState( + () => (localStorage.getItem(storageKey) as Theme) || defaultTheme + ) + + useEffect(() => { + const root = window.document.documentElement + + root.classList.remove("light", "dark") + + if (theme === "system") { + const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") + .matches + ? "dark" + : "light" + + root.classList.add(systemTheme) + return + } + + root.classList.add(theme) + }, [theme]) + + const value = { + theme, + setTheme: (theme: Theme) => { + localStorage.setItem(storageKey, theme) + setTheme(theme) + }, + } + + return ( + + {children} + + ) +} + +export const useTheme = () => { + const context = useContext(ThemeProviderContext) + + if (context === undefined) + throw new Error("useTheme must be used within a ThemeProvider") + + return context +} +``` + +### Wrap your root layout + +Add the `ThemeProvider` to your root layout. + +```tsx {1,5-7} title="App.tsx" +import { ThemeProvider } from "@/components/theme-provider" + +function App() { + return ( + + {children} + + ) +} + +export default App +``` + +### Add a mode toggle + +Place a mode toggle on your site to toggle between light and dark mode. + +```tsx title="components/mode-toggle.tsx" +import { Moon, Sun } from "lucide-react" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { useTheme } from "@/components/theme-provider" + +export function ModeToggle() { + const { setTheme } = useTheme() + + return ( + + + + + + setTheme("light")}> + Light + + setTheme("dark")}> + Dark + + setTheme("system")}> + System + + + + ) +} +``` + + \ No newline at end of file diff --git a/apps/www/content/docs/components/draggable.mdx b/apps/www/content/docs/components/draggable.mdx index e08b730de2..346263a9a9 100644 --- a/apps/www/content/docs/components/draggable.mdx +++ b/apps/www/content/docs/components/draggable.mdx @@ -9,8 +9,6 @@ docs: title: Tooltip --- - - ## Installation @@ -63,6 +61,8 @@ Update the import paths to match your project setup. ## Examples + + ```tsx import { createPlugins } from '@udecode/plate-common'; import { createDndPlugin } from '@udecode/plate-dnd'; @@ -93,7 +93,9 @@ import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; - + + + ; ``` diff --git a/apps/www/content/docs/components/editor.mdx b/apps/www/content/docs/components/editor.mdx new file mode 100644 index 0000000000..58ecd7bc3e --- /dev/null +++ b/apps/www/content/docs/components/editor.mdx @@ -0,0 +1,75 @@ +--- +title: Editor +description: From Textarea to WYSIWYG editor. +component: true +docs: + - route: /docs/api/core/plate + title: Plate +--- + +## Installation + + + + + CLI + Manual + + + + +```bash +npx @udecode/plate-ui@latest add editor +``` + + + + + + + + + +Copy and paste the following code into your project. + + + + + + + +Update the import paths to match your project setup. + + + + + + + + + +## Examples + +### Default + + + +### Disabled + + + +### Ghost + + + +### With Label + + + +### With Text + + + +### With Button + + diff --git a/apps/www/content/docs/components/emoji-combobox.mdx b/apps/www/content/docs/components/emoji-combobox.mdx index c7c18302fe..a46401ee53 100644 --- a/apps/www/content/docs/components/emoji-combobox.mdx +++ b/apps/www/content/docs/components/emoji-combobox.mdx @@ -9,8 +9,6 @@ docs: title: Emoji --- - - ## Installation @@ -61,4 +59,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/emoji-dropdown-menu.mdx b/apps/www/content/docs/components/emoji-dropdown-menu.mdx index bb88070968..7766252e87 100644 --- a/apps/www/content/docs/components/emoji-dropdown-menu.mdx +++ b/apps/www/content/docs/components/emoji-dropdown-menu.mdx @@ -9,8 +9,6 @@ docs: title: Emoji --- - - ## Installation @@ -73,4 +71,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/emoji-toolbar-dropdown.mdx b/apps/www/content/docs/components/emoji-toolbar-dropdown.mdx index b377bd117f..2386b6ae03 100644 --- a/apps/www/content/docs/components/emoji-toolbar-dropdown.mdx +++ b/apps/www/content/docs/components/emoji-toolbar-dropdown.mdx @@ -4,8 +4,6 @@ description: Display an emoji selection menu within a toolbar interface. component: true --- - - ## Installation @@ -58,4 +56,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/excalidraw-element.mdx b/apps/www/content/docs/components/excalidraw-element.mdx index cdef35c435..1e58412f56 100644 --- a/apps/www/content/docs/components/excalidraw-element.mdx +++ b/apps/www/content/docs/components/excalidraw-element.mdx @@ -7,8 +7,6 @@ docs: title: Excalidraw --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/fixed-toolbar-buttons.mdx b/apps/www/content/docs/components/fixed-toolbar-buttons.mdx index b92c2e4501..c4d5fbf533 100644 --- a/apps/www/content/docs/components/fixed-toolbar-buttons.mdx +++ b/apps/www/content/docs/components/fixed-toolbar-buttons.mdx @@ -17,8 +17,6 @@ docs: title: Turn Into Dropdown Menu --- - - ## Installation @@ -74,4 +72,6 @@ Update the import paths to match your project setup. ## Examples - + + + diff --git a/apps/www/content/docs/components/fixed-toolbar.mdx b/apps/www/content/docs/components/fixed-toolbar.mdx index e904df537b..1a0fcd2138 100644 --- a/apps/www/content/docs/components/fixed-toolbar.mdx +++ b/apps/www/content/docs/components/fixed-toolbar.mdx @@ -7,8 +7,6 @@ docs: title: Toolbar --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples - + + + diff --git a/apps/www/content/docs/components/floating-toolbar-buttons.mdx b/apps/www/content/docs/components/floating-toolbar-buttons.mdx index d4f2861ee2..df793294db 100644 --- a/apps/www/content/docs/components/floating-toolbar-buttons.mdx +++ b/apps/www/content/docs/components/floating-toolbar-buttons.mdx @@ -13,8 +13,6 @@ docs: title: Turn Into Dropdown Menu --- - - ## Installation @@ -68,4 +66,6 @@ Update the import paths to match your project setup. ## Examples - + + + diff --git a/apps/www/content/docs/components/floating-toolbar.mdx b/apps/www/content/docs/components/floating-toolbar.mdx index 9fede62960..abbd75ab0d 100644 --- a/apps/www/content/docs/components/floating-toolbar.mdx +++ b/apps/www/content/docs/components/floating-toolbar.mdx @@ -7,8 +7,6 @@ docs: title: Toolbar --- - - ## Installation @@ -63,4 +61,6 @@ Update the import paths to match your project setup. ## Examples - + + + diff --git a/apps/www/content/docs/components/heading-element.mdx b/apps/www/content/docs/components/heading-element.mdx index 3465721cbf..8f9da3d56c 100644 --- a/apps/www/content/docs/components/heading-element.mdx +++ b/apps/www/content/docs/components/heading-element.mdx @@ -7,8 +7,6 @@ docs: title: Basic Elements --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/highlight-leaf.mdx b/apps/www/content/docs/components/highlight-leaf.mdx index 2b5aa9cc21..e4c8ca6e9d 100644 --- a/apps/www/content/docs/components/highlight-leaf.mdx +++ b/apps/www/content/docs/components/highlight-leaf.mdx @@ -7,8 +7,6 @@ docs: title: Highlight --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/hr-element.mdx b/apps/www/content/docs/components/hr-element.mdx index c9c01430e2..c7b3674efb 100644 --- a/apps/www/content/docs/components/hr-element.mdx +++ b/apps/www/content/docs/components/hr-element.mdx @@ -7,8 +7,6 @@ docs: title: Horizontal Rule --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/image-element.mdx b/apps/www/content/docs/components/image-element.mdx index 90515efca5..0232a45a8c 100644 --- a/apps/www/content/docs/components/image-element.mdx +++ b/apps/www/content/docs/components/image-element.mdx @@ -13,8 +13,6 @@ docs: title: Resizable --- - - ## Installation @@ -68,4 +66,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/indent-list-toolbar-button.mdx b/apps/www/content/docs/components/indent-list-toolbar-button.mdx index 7510caf7ac..8a5f64c157 100644 --- a/apps/www/content/docs/components/indent-list-toolbar-button.mdx +++ b/apps/www/content/docs/components/indent-list-toolbar-button.mdx @@ -9,8 +9,6 @@ docs: title: Toolbar --- - - ## Installation @@ -83,6 +81,6 @@ Update the import paths to match your project setup. ## Examples -## Examples + diff --git a/apps/www/content/docs/components/indent-toolbar-button.mdx b/apps/www/content/docs/components/indent-toolbar-button.mdx index ba14fad3d9..c7b75ccc03 100644 --- a/apps/www/content/docs/components/indent-toolbar-button.mdx +++ b/apps/www/content/docs/components/indent-toolbar-button.mdx @@ -9,8 +9,6 @@ docs: title: Toolbar --- - - ## Installation @@ -62,4 +60,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/insert-dropdown-menu.mdx b/apps/www/content/docs/components/insert-dropdown-menu.mdx index 086a8f7ae9..da77dffdb6 100644 --- a/apps/www/content/docs/components/insert-dropdown-menu.mdx +++ b/apps/www/content/docs/components/insert-dropdown-menu.mdx @@ -15,8 +15,6 @@ docs: title: Toolbar --- - - ## Installation @@ -71,4 +69,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/installation/next.mdx b/apps/www/content/docs/components/installation/next.mdx index d2964f30ec..d9216718bf 100644 --- a/apps/www/content/docs/components/installation/next.mdx +++ b/apps/www/content/docs/components/installation/next.mdx @@ -94,7 +94,7 @@ npx @udecode/plate-ui@latest add button The command above will add the `Button` component to your project. You can then import it like this: ```tsx {1,6} showLineNumbers -import { Button } from '@/components/plate-ui'; +import { Button } from '@/components/plate-ui/button'; export default function Home() { return ( diff --git a/apps/www/content/docs/components/installation/remix.mdx b/apps/www/content/docs/components/installation/remix.mdx index 660d0be750..affda511ee 100644 --- a/apps/www/content/docs/components/installation/remix.mdx +++ b/apps/www/content/docs/components/installation/remix.mdx @@ -110,7 +110,7 @@ npx @udecode/plate-ui@latest add button The command above will add the `Button` component to your project. You can then import it like this: ```tsx {1,6} showLineNumbers -import { Button } from '@/components/ui'; +import { Button } from '@/components/ui/button'; export default function Home() { return ( diff --git a/apps/www/content/docs/components/installation/vite.mdx b/apps/www/content/docs/components/installation/vite.mdx index 624593b0be..916b2e0a0f 100644 --- a/apps/www/content/docs/components/installation/vite.mdx +++ b/apps/www/content/docs/components/installation/vite.mdx @@ -100,7 +100,7 @@ npx @udecode/plate-ui@latest add button The command above will add the `Button` component to your project. You can then import it like this: ```tsx {1,6} showLineNumbers -import { Button } from '@/components/ui'; +import { Button } from '@/components/ui/button'; export default function Home() { return ( diff --git a/apps/www/content/docs/components/kbd-leaf.mdx b/apps/www/content/docs/components/kbd-leaf.mdx index 6d90b50006..3d0ba9e427 100644 --- a/apps/www/content/docs/components/kbd-leaf.mdx +++ b/apps/www/content/docs/components/kbd-leaf.mdx @@ -4,8 +4,6 @@ description: Component for keyboard input. component: true --- - - ## Installation @@ -58,4 +56,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/line-height-dropdown-menu.mdx b/apps/www/content/docs/components/line-height-dropdown-menu.mdx index 0219dfac03..4be47e7a50 100644 --- a/apps/www/content/docs/components/line-height-dropdown-menu.mdx +++ b/apps/www/content/docs/components/line-height-dropdown-menu.mdx @@ -11,8 +11,6 @@ docs: title: Dropdown Menu --- - - ## Installation @@ -65,4 +63,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/link-element.mdx b/apps/www/content/docs/components/link-element.mdx index 74faf5a615..399017dbce 100644 --- a/apps/www/content/docs/components/link-element.mdx +++ b/apps/www/content/docs/components/link-element.mdx @@ -7,8 +7,6 @@ docs: title: Link --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/link-floating-toolbar.mdx b/apps/www/content/docs/components/link-floating-toolbar.mdx index 64099bfcec..a3eb8d9b54 100644 --- a/apps/www/content/docs/components/link-floating-toolbar.mdx +++ b/apps/www/content/docs/components/link-floating-toolbar.mdx @@ -15,8 +15,6 @@ docs: title: Separator --- - - ## Installation @@ -71,4 +69,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/link-toolbar-button.mdx b/apps/www/content/docs/components/link-toolbar-button.mdx index e13d050acd..7aa33dd59d 100644 --- a/apps/www/content/docs/components/link-toolbar-button.mdx +++ b/apps/www/content/docs/components/link-toolbar-button.mdx @@ -9,8 +9,6 @@ docs: title: Toolbar --- - - ## Installation @@ -62,5 +60,7 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/list-element.mdx b/apps/www/content/docs/components/list-element.mdx index 04167349ab..7137f83833 100644 --- a/apps/www/content/docs/components/list-element.mdx +++ b/apps/www/content/docs/components/list-element.mdx @@ -7,8 +7,6 @@ docs: title: List --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/list-toolbar-button.mdx b/apps/www/content/docs/components/list-toolbar-button.mdx index 33f8cb61fb..2678604aaf 100644 --- a/apps/www/content/docs/components/list-toolbar-button.mdx +++ b/apps/www/content/docs/components/list-toolbar-button.mdx @@ -9,8 +9,6 @@ docs: title: Toolbar --- - - ## Installation @@ -59,3 +57,7 @@ Update the import paths to match your project setup. + +## Examples + + diff --git a/apps/www/content/docs/components/mark-toolbar-button.mdx b/apps/www/content/docs/components/mark-toolbar-button.mdx index da87dceecb..93332dd03e 100644 --- a/apps/www/content/docs/components/mark-toolbar-button.mdx +++ b/apps/www/content/docs/components/mark-toolbar-button.mdx @@ -9,8 +9,6 @@ docs: title: Toolbar --- - - ## Installation @@ -62,5 +60,7 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/media-embed-element.mdx b/apps/www/content/docs/components/media-embed-element.mdx index d0e1b9ceb9..cf7e408795 100644 --- a/apps/www/content/docs/components/media-embed-element.mdx +++ b/apps/www/content/docs/components/media-embed-element.mdx @@ -13,8 +13,6 @@ docs: title: Resizable --- - - ## Installation @@ -67,4 +65,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/media-popover.mdx b/apps/www/content/docs/components/media-popover.mdx index 334ffaa230..35562a35d2 100644 --- a/apps/www/content/docs/components/media-popover.mdx +++ b/apps/www/content/docs/components/media-popover.mdx @@ -15,8 +15,6 @@ docs: title: Separator --- - - ## Installation @@ -71,5 +69,7 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/media-toolbar-button.mdx b/apps/www/content/docs/components/media-toolbar-button.mdx index 7389e43571..a8b36be0d5 100644 --- a/apps/www/content/docs/components/media-toolbar-button.mdx +++ b/apps/www/content/docs/components/media-toolbar-button.mdx @@ -9,8 +9,6 @@ docs: title: Toolbar --- - - ## Installation @@ -62,4 +60,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/mention-combobox.mdx b/apps/www/content/docs/components/mention-combobox.mdx index 50065e1db0..1687d201d4 100644 --- a/apps/www/content/docs/components/mention-combobox.mdx +++ b/apps/www/content/docs/components/mention-combobox.mdx @@ -9,8 +9,6 @@ docs: title: Mention --- - - ## Installation @@ -62,4 +60,6 @@ Update the import paths to match your project setup. ## Examples - + + + diff --git a/apps/www/content/docs/components/mention-element.mdx b/apps/www/content/docs/components/mention-element.mdx index 7721b029f2..a299795bee 100644 --- a/apps/www/content/docs/components/mention-element.mdx +++ b/apps/www/content/docs/components/mention-element.mdx @@ -7,8 +7,6 @@ docs: title: Mention --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/mention-input-element.mdx b/apps/www/content/docs/components/mention-input-element.mdx index f67b2d003d..f97f05e807 100644 --- a/apps/www/content/docs/components/mention-input-element.mdx +++ b/apps/www/content/docs/components/mention-input-element.mdx @@ -7,8 +7,6 @@ docs: title: Mention --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/mode-dropdown-menu.mdx b/apps/www/content/docs/components/mode-dropdown-menu.mdx index b1dc98e790..4cc76fa1ae 100644 --- a/apps/www/content/docs/components/mode-dropdown-menu.mdx +++ b/apps/www/content/docs/components/mode-dropdown-menu.mdx @@ -9,8 +9,6 @@ docs: title: Toolbar --- - - ## Installation @@ -66,4 +64,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/more-dropdown-menu.mdx b/apps/www/content/docs/components/more-dropdown-menu.mdx index 6049633b76..2fa8af9d7e 100644 --- a/apps/www/content/docs/components/more-dropdown-menu.mdx +++ b/apps/www/content/docs/components/more-dropdown-menu.mdx @@ -11,8 +11,6 @@ docs: title: Toolbar --- - - ## Installation @@ -69,5 +67,7 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/outdent-toolbar-button.mdx b/apps/www/content/docs/components/outdent-toolbar-button.mdx index 6b824431fa..d9443509e8 100644 --- a/apps/www/content/docs/components/outdent-toolbar-button.mdx +++ b/apps/www/content/docs/components/outdent-toolbar-button.mdx @@ -9,8 +9,6 @@ docs: title: Toolbar --- - - ## Installation @@ -62,4 +60,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/paragraph-element.mdx b/apps/www/content/docs/components/paragraph-element.mdx index 8bc47de9bb..eb10fac0c3 100644 --- a/apps/www/content/docs/components/paragraph-element.mdx +++ b/apps/www/content/docs/components/paragraph-element.mdx @@ -7,8 +7,6 @@ docs: title: Basic Elements --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/placeholder.mdx b/apps/www/content/docs/components/placeholder.mdx index c26f702708..7b9920508b 100644 --- a/apps/www/content/docs/components/placeholder.mdx +++ b/apps/www/content/docs/components/placeholder.mdx @@ -9,8 +9,6 @@ docs: title: Paragraph --- - - ## Installation @@ -62,4 +60,6 @@ Update the import paths to match your project setup. ## Examples - + + + diff --git a/apps/www/content/docs/components/resizable.mdx b/apps/www/content/docs/components/resizable.mdx index c0da80458f..03d9224665 100644 --- a/apps/www/content/docs/components/resizable.mdx +++ b/apps/www/content/docs/components/resizable.mdx @@ -4,8 +4,6 @@ description: Resize nodes using handles. component: true --- - - ## Installation @@ -58,5 +56,7 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/search-highlight-leaf.mdx b/apps/www/content/docs/components/search-highlight-leaf.mdx index f85e001f7c..473ee6c2ae 100644 --- a/apps/www/content/docs/components/search-highlight-leaf.mdx +++ b/apps/www/content/docs/components/search-highlight-leaf.mdx @@ -7,8 +7,6 @@ docs: title: Highlight --- - - ## Installation @@ -60,3 +58,7 @@ Update the import paths to match your project setup. + +## Examples + + diff --git a/apps/www/content/docs/components/table-cell-element.mdx b/apps/www/content/docs/components/table-cell-element.mdx index cd28382f3f..b3bdc4d7ea 100644 --- a/apps/www/content/docs/components/table-cell-element.mdx +++ b/apps/www/content/docs/components/table-cell-element.mdx @@ -7,8 +7,6 @@ docs: title: Table --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/table-dropdown-menu.mdx b/apps/www/content/docs/components/table-dropdown-menu.mdx index 63d300fb9c..6d1a42ad47 100644 --- a/apps/www/content/docs/components/table-dropdown-menu.mdx +++ b/apps/www/content/docs/components/table-dropdown-menu.mdx @@ -11,8 +11,6 @@ docs: title: Toolbar --- - - ## Installation @@ -65,4 +63,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/table-element.mdx b/apps/www/content/docs/components/table-element.mdx index 6b39d4149e..766eed0463 100644 --- a/apps/www/content/docs/components/table-element.mdx +++ b/apps/www/content/docs/components/table-element.mdx @@ -7,8 +7,6 @@ docs: title: Table --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/table-row-element.mdx b/apps/www/content/docs/components/table-row-element.mdx index 16534d874b..9a65f2a208 100644 --- a/apps/www/content/docs/components/table-row-element.mdx +++ b/apps/www/content/docs/components/table-row-element.mdx @@ -7,8 +7,6 @@ docs: title: Table --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/theming.mdx b/apps/www/content/docs/components/theming.mdx index 16a0faa285..6b8443b243 100644 --- a/apps/www/content/docs/components/theming.mdx +++ b/apps/www/content/docs/components/theming.mdx @@ -8,7 +8,7 @@ You can choose between using CSS variables or Tailwind CSS utility classes for t ## Utility classes ```tsx /bg-zinc-950/ /text-zinc-50/ /dark:bg-white/ /dark:text-zinc-950/ -
+
``` To use utility classes for theming set `tailwind.cssVariables` to `false` in your `components.json` file. diff --git a/apps/www/content/docs/components/todo-list-element.mdx b/apps/www/content/docs/components/todo-list-element.mdx index 208d917fc8..75cb91aa0f 100644 --- a/apps/www/content/docs/components/todo-list-element.mdx +++ b/apps/www/content/docs/components/todo-list-element.mdx @@ -7,8 +7,6 @@ docs: title: List --- - - ## Installation @@ -59,4 +57,6 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/components/turn-into-dropdown-menu.mdx b/apps/www/content/docs/components/turn-into-dropdown-menu.mdx index 842adca460..89cba9b922 100644 --- a/apps/www/content/docs/components/turn-into-dropdown-menu.mdx +++ b/apps/www/content/docs/components/turn-into-dropdown-menu.mdx @@ -15,8 +15,6 @@ docs: title: Toolbar --- - - ## Installation @@ -71,5 +69,7 @@ Update the import paths to match your project setup. ## Examples + + diff --git a/apps/www/content/docs/getting-started.mdx b/apps/www/content/docs/getting-started.mdx index 6da8346c66..2d3b9c6e31 100644 --- a/apps/www/content/docs/getting-started.mdx +++ b/apps/www/content/docs/getting-started.mdx @@ -3,11 +3,23 @@ title: Getting Started description: A quick tutorial to get you up and running with Plate. --- + + Use our interactive builder to generate _personalized_ installation steps. + + ### Create project -Using Plate components? Check out the [installation guide](/docs/components/installation). +You can choose one of the following templates to get started: + +| Option | NextJS | Tailwind | Plate | Plugins | +| ------------------------------------------------------------------------------------------------------------------ | ------ | -------- | ----- | ------- | +| Plate playground template | ✅ | ✅ | ✅ | ✅ | +| Plate minimal template | ✅ | ✅ | ✅ | | +| NextJS template | ✅ | ✅ | | | + +For an existing project, jump to the next step. ### Add dependencies @@ -25,26 +37,44 @@ npm install @udecode/plate slate slate-react slate-history slate-hyperscript rea ### Basic Editor -Let's start with a minimal editor setup leveraging **`Plate`** and **`editableProps`**. +Let's start with a minimal editor setup. -```tsx showLineNumbers {1,3-5,9} +```tsx showLineNumbers {1,5-7} import { Plate } from '@udecode/plate-common'; -const editableProps = { - placeholder: 'Type...', -}; - export default function BasicEditor() { - return ; + return ( + + + + ); } ``` -Simple and straightforward. Try it out: +`Plate` manages the editor state and `PlateContent` renders the editor content. +### Styling + +Let's give our editor some styles: [Editor](/docs/components/editor) is a styled version of `PlateContent`. + +```tsx showLineNumbers {1,5-7} +import { Plate } from '@udecode/plate-common'; + +export default function BasicEditor() { + return ( + + + + ); +} +``` + + + - **Note**: The following examples are using these global styles: + **Note**: `Editor` is just an example of a styled editor using Tailwind. You can create your own styled version of `PlateContent`. @@ -52,7 +82,7 @@ Simple and straightforward. Try it out: Let's specify the initial content of the editor: a single paragraph. -```tsx showLineNumbers {3-12,18} +```tsx showLineNumbers {3-12,16-18} // ... const initialValue = [ @@ -67,13 +97,17 @@ const initialValue = [ ]; export default function BasicEditor() { - return ; + return ( + + + + ); } ``` - **Note**: Plate uses the **`type`** property to enable plugins to render nodes by - type. + **Note**: Plate uses the **`type`** property to enable plugins to render nodes + by type. @@ -82,18 +116,19 @@ export default function BasicEditor() { At this stage, it's crucial to monitor editor modifications in order to store the values appropriately. The **`onChange`** prop will serve this purpose. -```tsx showLineNumbers {8-10} +```tsx showLineNumbers {7-9} // ... export default function BasicEditor() { return ( { // save newValue... }} - /> + > + + ); } ``` @@ -102,6 +137,10 @@ export default function BasicEditor() { ### Plugins + +Use our interactive builder to pick your plugins. + + Let's use the basic plugins for a rich-text editor. @@ -109,22 +148,22 @@ Let's use the basic plugins for a rich-text editor. The debug value indicates everything works as expected. However, we haven't provided any components for rendering, hence it's utilizing the default (unstyled) ones. The default element component is a **`div`** and the default leaf component is a **`span`**. - **Note**: You don't need to add core plugins such as **`react`** and **`history`** as - **`Plate`** already does it. + **Note**: You don't need to add core plugins such as **`react`** and + **`history`** as **`Plate`** already does it. ### Components - **Note**: Plate plugins are packaged unstyled, implying that you have complete - control over markup and styling, hence you can integrate your own design - system or [Plate UI](/docs/components). +**Note**: Plate plugins are packaged unstyled, implying that you have complete +control over markup and styling, hence you can integrate your own design +system or [Plate UI](/docs/components). If using the latter, use our interactive builder to pick your components. To simultaneously plug-in all the components, **`createPlugins`** can be used: - use the first parameter for the **`plugins`** -- use the second parameter for the **`components`**. In the following example, we'll call **`createPlateUI()`**, which returns all Plate components by plugin key. +- use the second parameter for the **`components`**. In the following example, we have created **`createPlateUI`**, which returns all Plate components by plugin key. ```tsx showLineNumbers {16-31, 36} // ... @@ -136,7 +175,7 @@ import { createUnderlinePlugin, } from '@udecode/plate-basic-marks'; import { createBlockquotePlugin } from '@udecode/plate-block-quote'; -import { Plate, createPlugins } from '@udecode/plate-common'; +import { createPlugins, Plate } from '@udecode/plate-common'; import { createHeadingPlugin } from '@udecode/plate-heading'; import { createParagraphPlugin } from '@udecode/plate-paragraph'; @@ -164,7 +203,9 @@ export default function BasicEditor() { + > + + ); } ``` @@ -173,4 +214,8 @@ export default function BasicEditor() { +### That's it! + +You can now play around with the Playground and start building your own editor. + diff --git a/apps/www/content/docs/img.png b/apps/www/content/docs/img.png new file mode 100644 index 0000000000..6320223885 Binary files /dev/null and b/apps/www/content/docs/img.png differ diff --git a/apps/www/content/docs/media.mdx b/apps/www/content/docs/media.mdx index 62b2538f5b..e100286e24 100644 --- a/apps/www/content/docs/media.mdx +++ b/apps/www/content/docs/media.mdx @@ -46,7 +46,9 @@ import { createSelectOnBackspacePlugin } from '@udecode/plate-select'; const plugins = [ // ...otherPlugins, - createCaptionPlugin({ options: [ELEMENT_IMAGE, ELEMENT_MEDIA_EMBED] }), + createCaptionPlugin({ + options: { pluginKeys: [ELEMENT_IMAGE, ELEMENT_MEDIA_EMBED] }, + }), createImagePlugin(), createMediaEmbedPlugin(), createSelectOnBackspacePlugin({ diff --git a/apps/www/content/docs/plugin.mdx b/apps/www/content/docs/plugin.mdx index 297f8d0e9f..f227ed8438 100644 --- a/apps/www/content/docs/plugin.mdx +++ b/apps/www/content/docs/plugin.mdx @@ -31,7 +31,11 @@ const plugins = createPlugins([ ]); export default () => { - return ; + return ( + + + + ); }; ``` @@ -53,9 +57,7 @@ const createParagraphPlugin = createPluginFactory({ Each element should have an associated component, which you can provide either as an option **`component: ParagraphElement`** to **`createPluginFactory`**, or in the **`components`** option of **`createPlugins`** (recommended). ```ts showLineNumbers {4} -const plugins = createPlugins([ - createParagraphPlugin(), -], { +const plugins = createPlugins([createParagraphPlugin()], { components: { [ELEMENT_PARAGRAPH]: ParagraphElement, }, @@ -160,7 +162,7 @@ Rather than render an element or a mark, you may want to customize the behavior ### Event Handlers -The recommended way to respond to user-generated events from inside a plugin is with the **`handlers`** plugin option. A handler should be a function that takes an **`editor`** object and returns another function that takes an event object. +The recommended way to respond to user-generated events from inside a plugin is with the **`handlers`** plugin option. A handler should be a function that takes an **`editor`** object and returns another function that takes an event object. The **`onChange`** handler, which is called when the editor value changes, is an exception to this rule; the inner function of an **`onChange`** handler should accept a **`Value`** object instead of an event. @@ -169,10 +171,10 @@ const createExamplePlugin = createPluginFactory({ key: KEY_EXAMPLE, handlers: { onChange: (editor) => (value) => { - console.log(editor, value); + console.info(editor, value); }, onKeyDown: (editor) => (event) => { - console.log(`You pressed ${event.key}`); + console.info(`You pressed ${event.key}`); }, }, }); @@ -215,15 +217,17 @@ A paragraph node affected by the above plugin would look like this: ### With Overrides (Advanced) -Occasionally, you'll need to override the built-in editor methods provided by Slate to work around bugs or add complex functionality. To do this, you can use the **`withOverrides`** plugin option to directly mutate properties of the **`editor`** object after its creation. +Occasionally, you'll need to override the built-in editor methods provided by Slate to work around bugs or add complex functionality. To do this, you can use the **`withOverrides`** plugin option to directly mutate properties of the **`editor`** object after its creation. -One common application of this technique is to create custom [normalizers](https://docs.slatejs.org/concepts/11-normalizing). +One common application of this technique is to create custom [normalizers](https://docs.slatejs.org/concepts/11-normalizing). ```ts showLineNumbers {20} const withCustomNormalizer = < V extends Value = Value, - E extends PlateEditor = PlateEditor ->(editor: E) => { + E extends PlateEditor = PlateEditor, +>( + editor: E +) => { const { normalizeNode } = editor; editor.normalizeNode = ([node, path]: TNodeEntry) => { @@ -261,7 +265,7 @@ const createDemoPlugin = createPluginFactory({ handlers: { onKeyDown: (editor) => (event) => { const { username } = getPluginOptions(editor, KEY_DEMO); - console.log(`${username} pressed ${event.key}`) + console.info(`${username} pressed ${event.key}`); }, }, then: (_editor, { options }) => ({ @@ -279,13 +283,21 @@ const createDemoPlugin = createPluginFactory({ }); const MyEditor = ({ username }: { username: string }) => { - const plugins = useMemo(() => createPlugins([ - createDemoPlugin({ - options: { username }, - }), - ]), [username]); - - return ; + const plugins = useMemo( + () => + createPlugins([ + createDemoPlugin({ + options: { username }, + }), + ]), + [username] + ); + + return ( + + + + ); }; export default () => ; diff --git a/apps/www/package.json b/apps/www/package.json index 5ec66177b1..5e2d662052 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -9,6 +9,7 @@ "build:contentlayer": "contentlayer build", "build:registry": "ts-node --esm --project ./scripts/tsconfig.scripts.json ./scripts/build-registry.ts", "dev": "concurrently \"contentlayer dev\" \"NODE_OPTIONS=--max-old-space-size=16192 next dev\"", + "dev:quick": "NODE_OPTIONS=--max-old-space-size=16192 next dev", "start": "next start", "lint": "npx eslint . --ext .js,.jsx,.ts,.tsx", "lint:fix": "yarn lint --fix", @@ -112,10 +113,11 @@ "framer-motion": "10.12.20", "jotai": "^2.2.2", "lodash.template": "^4.5.0", - "lucide-react": "0.260.0", - "next": "13.4.9", + "lucide-react": "^0.277.0", + "next": "13.4.19", "next-contentlayer": "0.3.4", "next-themes": "^0.2.1", + "next-usequerystate": "1.8.0-beta.13", "prism-react-renderer": "^1.3.5", "react": "^18.2.0", "react-dnd": "patch:react-dnd@npm%3A15.1.2#~/.yarn/patches/react-dnd-npm-15.1.2-0351d81431.patch", @@ -123,6 +125,7 @@ "react-dom": "^18.2.0", "react-lite-youtube-embed": "^2.3.52", "react-modal-sheet": "2.0.0", + "react-syntax-highlighter": "^15.5.0", "react-tweet": "^3.1.0", "react-wrap-balancer": "^1.0.0", "sass": "^1.63.6", @@ -144,7 +147,9 @@ "devDependencies": { "@types/lodash.template": "^4.5.1", "@types/react-color": "^3.0.6", + "@types/react-syntax-highlighter": "^15.5.7", "autoprefixer": "^10.4.14", + "concurrently": "^8.2.0", "mdast-util-toc": "^6.1.1", "postcss": "^8.4.25", "rehype": "^12.0.1", @@ -159,7 +164,8 @@ "tailwindcss": "^3.3.2", "tailwindcss-animate": "^1.0.6", "ts-node": "^10.9.1", - "typescript": "5.1.6" + "typescript": "5.1.6", + "vaul": "^0.6.0" }, "browserslist": { "production": [ diff --git a/apps/www/public/registry/colors/gray.json b/apps/www/public/registry/colors/gray.json index be08990361..6de69e6d03 100644 --- a/apps/www/public/registry/colors/gray.json +++ b/apps/www/public/registry/colors/gray.json @@ -3,90 +3,90 @@ "light": { "background": "white", "foreground": "gray-950", - "muted": "gray-100", - "muted-foreground": "gray-500", - "popover": "white", - "popover-foreground": "gray-950", - "border": "gray-200", - "input": "gray-200", "card": "white", "card-foreground": "gray-950", + "popover": "white", + "popover-foreground": "gray-950", "primary": "gray-900", "primary-foreground": "gray-50", "secondary": "gray-100", "secondary-foreground": "gray-900", + "muted": "gray-100", + "muted-foreground": "gray-500", "accent": "gray-100", "accent-foreground": "gray-900", "destructive": "red-500", "destructive-foreground": "gray-50", - "ring": "gray-400" + "border": "gray-200", + "input": "gray-200", + "ring": "gray-950" }, "dark": { "background": "gray-950", "foreground": "gray-50", - "muted": "gray-800", - "muted-foreground": "gray-400", - "popover": "gray-950", - "popover-foreground": "gray-50", - "border": "gray-800", - "input": "gray-800", "card": "gray-950", "card-foreground": "gray-50", + "popover": "gray-950", + "popover-foreground": "gray-50", "primary": "gray-50", "primary-foreground": "gray-900", "secondary": "gray-800", "secondary-foreground": "gray-50", + "muted": "gray-800", + "muted-foreground": "gray-400", "accent": "gray-800", "accent-foreground": "gray-50", "destructive": "red-900", - "destructive-foreground": "red-50", - "ring": "gray-800" + "destructive-foreground": "gray-50", + "border": "gray-800", + "input": "gray-800", + "ring": "gray-300" } }, "cssVars": { "light": { "background": "0 0% 100%", "foreground": "224 71.4% 4.1%", - "muted": "220 14.3% 95.9%", - "muted-foreground": "220 8.9% 46.1%", - "popover": "0 0% 100%", - "popover-foreground": "224 71.4% 4.1%", - "border": "220 13% 91%", - "input": "220 13% 91%", "card": "0 0% 100%", "card-foreground": "224 71.4% 4.1%", + "popover": "0 0% 100%", + "popover-foreground": "224 71.4% 4.1%", "primary": "220.9 39.3% 11%", "primary-foreground": "210 20% 98%", "secondary": "220 14.3% 95.9%", "secondary-foreground": "220.9 39.3% 11%", + "muted": "220 14.3% 95.9%", + "muted-foreground": "220 8.9% 46.1%", "accent": "220 14.3% 95.9%", "accent-foreground": "220.9 39.3% 11%", "destructive": "0 84.2% 60.2%", "destructive-foreground": "210 20% 98%", - "ring": "217.9 10.6% 64.9%" + "border": "220 13% 91%", + "input": "220 13% 91%", + "ring": "224 71.4% 4.1%" }, "dark": { "background": "224 71.4% 4.1%", "foreground": "210 20% 98%", - "muted": "215 27.9% 16.9%", - "muted-foreground": "217.9 10.6% 64.9%", - "popover": "224 71.4% 4.1%", - "popover-foreground": "210 20% 98%", - "border": "215 27.9% 16.9%", - "input": "215 27.9% 16.9%", "card": "224 71.4% 4.1%", "card-foreground": "210 20% 98%", + "popover": "224 71.4% 4.1%", + "popover-foreground": "210 20% 98%", "primary": "210 20% 98%", "primary-foreground": "220.9 39.3% 11%", "secondary": "215 27.9% 16.9%", "secondary-foreground": "210 20% 98%", + "muted": "215 27.9% 16.9%", + "muted-foreground": "217.9 10.6% 64.9%", "accent": "215 27.9% 16.9%", "accent-foreground": "210 20% 98%", "destructive": "0 62.8% 30.6%", - "destructive-foreground": "0 85.7% 97.3%", - "ring": "215 27.9% 16.9%" + "destructive-foreground": "210 20% 98%", + "border": "215 27.9% 16.9%", + "input": "215 27.9% 16.9%", + "ring": "216 12.2% 83.9%" } }, "inlineColorsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n", - "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 224 71.4% 4.1%;\n \n --muted: 220 14.3% 95.9%;\n --muted-foreground: 220 8.9% 46.1%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 224 71.4% 4.1%;\n \n --card: 0 0% 100%;\n --card-foreground: 224 71.4% 4.1%;\n \n --border: 220 13% 91%;\n --input: 220 13% 91%;\n \n --primary: 220.9 39.3% 11%;\n --primary-foreground: 210 20% 98%;\n \n --secondary: 220 14.3% 95.9%;\n --secondary-foreground: 220.9 39.3% 11%;\n \n --accent: 220 14.3% 95.9%;\n --accent-foreground: 220.9 39.3% 11%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 20% 98%;\n \n --ring: 217.9 10.6% 64.9%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 224 71.4% 4.1%;\n --foreground: 210 20% 98%;\n \n --muted: 215 27.9% 16.9%;\n --muted-foreground: 217.9 10.6% 64.9%;\n \n --popover: 224 71.4% 4.1%;\n --popover-foreground: 210 20% 98%;\n \n --card: 224 71.4% 4.1%;\n --card-foreground: 210 20% 98%;\n \n --border: 215 27.9% 16.9%;\n --input: 215 27.9% 16.9%;\n \n --primary: 210 20% 98%;\n --primary-foreground: 220.9 39.3% 11%;\n \n --secondary: 215 27.9% 16.9%;\n --secondary-foreground: 210 20% 98%;\n \n --accent: 215 27.9% 16.9%;\n --accent-foreground: 210 20% 98%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 85.7% 97.3%;\n \n --ring: 215 27.9% 16.9%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" + "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 224 71.4% 4.1%;\n\n --card: 0 0% 100%;\n --card-foreground: 224 71.4% 4.1%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 224 71.4% 4.1%;\n \n --primary: 220.9 39.3% 11%;\n --primary-foreground: 210 20% 98%;\n \n --secondary: 220 14.3% 95.9%;\n --secondary-foreground: 220.9 39.3% 11%;\n \n --muted: 220 14.3% 95.9%;\n --muted-foreground: 220 8.9% 46.1%;\n \n --accent: 220 14.3% 95.9%;\n --accent-foreground: 220.9 39.3% 11%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 20% 98%;\n\n --border: 220 13% 91%;\n --input: 220 13% 91%;\n --ring: 224 71.4% 4.1%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 224 71.4% 4.1%;\n --foreground: 210 20% 98%;\n \n --card: 224 71.4% 4.1%;\n --card-foreground: 210 20% 98%;\n \n --popover: 224 71.4% 4.1%;\n --popover-foreground: 210 20% 98%;\n \n --primary: 210 20% 98%;\n --primary-foreground: 220.9 39.3% 11%;\n \n --secondary: 215 27.9% 16.9%;\n --secondary-foreground: 210 20% 98%;\n \n --muted: 215 27.9% 16.9%;\n --muted-foreground: 217.9 10.6% 64.9%;\n \n --accent: 215 27.9% 16.9%;\n --accent-foreground: 210 20% 98%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 210 20% 98%;\n \n --border: 215 27.9% 16.9%;\n --input: 215 27.9% 16.9%;\n --ring: 216 12.2% 83.9%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" } \ No newline at end of file diff --git a/apps/www/public/registry/colors/index.json b/apps/www/public/registry/colors/index.json index e92b283369..c25158efb1 100644 --- a/apps/www/public/registry/colors/index.json +++ b/apps/www/public/registry/colors/index.json @@ -45,9 +45,9 @@ "scale": 300, "hex": "#cbd5e1", "rgb": "rgb(203,213,225)", - "hsl": "hsl(212.7,26.8%,83.9)", + "hsl": "hsl(212.7,26.8%,83.9%)", "rgbChannel": "203 213 225", - "hslChannel": "hsl(212.7,26.8%,83.9)" + "hslChannel": "212.7 26.8% 83.9%" }, { "scale": 400, diff --git a/apps/www/public/registry/colors/neutral.json b/apps/www/public/registry/colors/neutral.json index c2488562ac..2f29127b36 100644 --- a/apps/www/public/registry/colors/neutral.json +++ b/apps/www/public/registry/colors/neutral.json @@ -3,90 +3,90 @@ "light": { "background": "white", "foreground": "neutral-950", - "muted": "neutral-100", - "muted-foreground": "neutral-500", - "popover": "white", - "popover-foreground": "neutral-950", - "border": "neutral-200", - "input": "neutral-200", "card": "white", "card-foreground": "neutral-950", + "popover": "white", + "popover-foreground": "neutral-950", "primary": "neutral-900", "primary-foreground": "neutral-50", "secondary": "neutral-100", "secondary-foreground": "neutral-900", + "muted": "neutral-100", + "muted-foreground": "neutral-500", "accent": "neutral-100", "accent-foreground": "neutral-900", "destructive": "red-500", "destructive-foreground": "neutral-50", - "ring": "neutral-400" + "border": "neutral-200", + "input": "neutral-200", + "ring": "neutral-950" }, "dark": { "background": "neutral-950", "foreground": "neutral-50", - "muted": "neutral-800", - "muted-foreground": "neutral-400", - "popover": "neutral-950", - "popover-foreground": "neutral-50", - "border": "neutral-800", - "input": "neutral-800", "card": "neutral-950", "card-foreground": "neutral-50", + "popover": "neutral-950", + "popover-foreground": "neutral-50", "primary": "neutral-50", "primary-foreground": "neutral-900", "secondary": "neutral-800", "secondary-foreground": "neutral-50", + "muted": "neutral-800", + "muted-foreground": "neutral-400", "accent": "neutral-800", "accent-foreground": "neutral-50", "destructive": "red-900", - "destructive-foreground": "red-50", - "ring": "neutral-800" + "destructive-foreground": "neutral-50", + "border": "neutral-800", + "input": "neutral-800", + "ring": "neutral-300" } }, "cssVars": { "light": { "background": "0 0% 100%", "foreground": "0 0% 3.9%", - "muted": "0 0% 96.1%", - "muted-foreground": "0 0% 45.1%", - "popover": "0 0% 100%", - "popover-foreground": "0 0% 3.9%", - "border": "0 0% 89.8%", - "input": "0 0% 89.8%", "card": "0 0% 100%", "card-foreground": "0 0% 3.9%", + "popover": "0 0% 100%", + "popover-foreground": "0 0% 3.9%", "primary": "0 0% 9%", "primary-foreground": "0 0% 98%", "secondary": "0 0% 96.1%", "secondary-foreground": "0 0% 9%", + "muted": "0 0% 96.1%", + "muted-foreground": "0 0% 45.1%", "accent": "0 0% 96.1%", "accent-foreground": "0 0% 9%", "destructive": "0 84.2% 60.2%", "destructive-foreground": "0 0% 98%", - "ring": "0 0% 63.9%" + "border": "0 0% 89.8%", + "input": "0 0% 89.8%", + "ring": "0 0% 3.9%" }, "dark": { "background": "0 0% 3.9%", "foreground": "0 0% 98%", - "muted": "0 0% 14.9%", - "muted-foreground": "0 0% 63.9%", - "popover": "0 0% 3.9%", - "popover-foreground": "0 0% 98%", - "border": "0 0% 14.9%", - "input": "0 0% 14.9%", "card": "0 0% 3.9%", "card-foreground": "0 0% 98%", + "popover": "0 0% 3.9%", + "popover-foreground": "0 0% 98%", "primary": "0 0% 98%", "primary-foreground": "0 0% 9%", "secondary": "0 0% 14.9%", "secondary-foreground": "0 0% 98%", + "muted": "0 0% 14.9%", + "muted-foreground": "0 0% 63.9%", "accent": "0 0% 14.9%", "accent-foreground": "0 0% 98%", "destructive": "0 62.8% 30.6%", - "destructive-foreground": "0 85.7% 97.3%", - "ring": "0 0% 14.9%" + "destructive-foreground": "0 0% 98%", + "border": "0 0% 14.9%", + "input": "0 0% 14.9%", + "ring": "0 0% 83.1%" } }, "inlineColorsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n", - "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 0 0% 3.9%;\n \n --muted: 0 0% 96.1%;\n --muted-foreground: 0 0% 45.1%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 0 0% 3.9%;\n \n --card: 0 0% 100%;\n --card-foreground: 0 0% 3.9%;\n \n --border: 0 0% 89.8%;\n --input: 0 0% 89.8%;\n \n --primary: 0 0% 9%;\n --primary-foreground: 0 0% 98%;\n \n --secondary: 0 0% 96.1%;\n --secondary-foreground: 0 0% 9%;\n \n --accent: 0 0% 96.1%;\n --accent-foreground: 0 0% 9%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 0 0% 98%;\n \n --ring: 0 0% 63.9%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 0 0% 3.9%;\n --foreground: 0 0% 98%;\n \n --muted: 0 0% 14.9%;\n --muted-foreground: 0 0% 63.9%;\n \n --popover: 0 0% 3.9%;\n --popover-foreground: 0 0% 98%;\n \n --card: 0 0% 3.9%;\n --card-foreground: 0 0% 98%;\n \n --border: 0 0% 14.9%;\n --input: 0 0% 14.9%;\n \n --primary: 0 0% 98%;\n --primary-foreground: 0 0% 9%;\n \n --secondary: 0 0% 14.9%;\n --secondary-foreground: 0 0% 98%;\n \n --accent: 0 0% 14.9%;\n --accent-foreground: 0 0% 98%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 85.7% 97.3%;\n \n --ring: 0 0% 14.9%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" + "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 0 0% 3.9%;\n\n --card: 0 0% 100%;\n --card-foreground: 0 0% 3.9%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 0 0% 3.9%;\n \n --primary: 0 0% 9%;\n --primary-foreground: 0 0% 98%;\n \n --secondary: 0 0% 96.1%;\n --secondary-foreground: 0 0% 9%;\n \n --muted: 0 0% 96.1%;\n --muted-foreground: 0 0% 45.1%;\n \n --accent: 0 0% 96.1%;\n --accent-foreground: 0 0% 9%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 0 0% 98%;\n\n --border: 0 0% 89.8%;\n --input: 0 0% 89.8%;\n --ring: 0 0% 3.9%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 0 0% 3.9%;\n --foreground: 0 0% 98%;\n \n --card: 0 0% 3.9%;\n --card-foreground: 0 0% 98%;\n \n --popover: 0 0% 3.9%;\n --popover-foreground: 0 0% 98%;\n \n --primary: 0 0% 98%;\n --primary-foreground: 0 0% 9%;\n \n --secondary: 0 0% 14.9%;\n --secondary-foreground: 0 0% 98%;\n \n --muted: 0 0% 14.9%;\n --muted-foreground: 0 0% 63.9%;\n \n --accent: 0 0% 14.9%;\n --accent-foreground: 0 0% 98%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 0% 98%;\n \n --border: 0 0% 14.9%;\n --input: 0 0% 14.9%;\n --ring: 0 0% 83.1%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" } \ No newline at end of file diff --git a/apps/www/public/registry/colors/slate.json b/apps/www/public/registry/colors/slate.json index 46469cb783..6d80bc7857 100644 --- a/apps/www/public/registry/colors/slate.json +++ b/apps/www/public/registry/colors/slate.json @@ -3,90 +3,90 @@ "light": { "background": "white", "foreground": "slate-950", - "muted": "slate-100", - "muted-foreground": "slate-500", - "popover": "white", - "popover-foreground": "slate-950", - "border": "slate-200", - "input": "slate-200", "card": "white", "card-foreground": "slate-950", + "popover": "white", + "popover-foreground": "slate-950", "primary": "slate-900", "primary-foreground": "slate-50", "secondary": "slate-100", "secondary-foreground": "slate-900", + "muted": "slate-100", + "muted-foreground": "slate-500", "accent": "slate-100", "accent-foreground": "slate-900", "destructive": "red-500", "destructive-foreground": "slate-50", - "ring": "slate-400" + "border": "slate-200", + "input": "slate-200", + "ring": "slate-950" }, "dark": { "background": "slate-950", "foreground": "slate-50", - "muted": "slate-800", - "muted-foreground": "slate-400", - "popover": "slate-950", - "popover-foreground": "slate-50", - "border": "slate-800", - "input": "slate-800", "card": "slate-950", "card-foreground": "slate-50", + "popover": "slate-950", + "popover-foreground": "slate-50", "primary": "slate-50", "primary-foreground": "slate-900", "secondary": "slate-800", "secondary-foreground": "slate-50", + "muted": "slate-800", + "muted-foreground": "slate-400", "accent": "slate-800", "accent-foreground": "slate-50", "destructive": "red-900", - "destructive-foreground": "red-50", - "ring": "slate-800" + "destructive-foreground": "slate-50", + "border": "slate-800", + "input": "slate-800", + "ring": "slate-300" } }, "cssVars": { "light": { "background": "0 0% 100%", "foreground": "222.2 84% 4.9%", - "muted": "210 40% 96.1%", - "muted-foreground": "215.4 16.3% 46.9%", - "popover": "0 0% 100%", - "popover-foreground": "222.2 84% 4.9%", - "border": "214.3 31.8% 91.4%", - "input": "214.3 31.8% 91.4%", "card": "0 0% 100%", "card-foreground": "222.2 84% 4.9%", + "popover": "0 0% 100%", + "popover-foreground": "222.2 84% 4.9%", "primary": "222.2 47.4% 11.2%", "primary-foreground": "210 40% 98%", "secondary": "210 40% 96.1%", "secondary-foreground": "222.2 47.4% 11.2%", + "muted": "210 40% 96.1%", + "muted-foreground": "215.4 16.3% 46.9%", "accent": "210 40% 96.1%", "accent-foreground": "222.2 47.4% 11.2%", "destructive": "0 84.2% 60.2%", "destructive-foreground": "210 40% 98%", - "ring": "215 20.2% 65.1%" + "border": "214.3 31.8% 91.4%", + "input": "214.3 31.8% 91.4%", + "ring": "222.2 84% 4.9%" }, "dark": { "background": "222.2 84% 4.9%", "foreground": "210 40% 98%", - "muted": "217.2 32.6% 17.5%", - "muted-foreground": "215 20.2% 65.1%", - "popover": "222.2 84% 4.9%", - "popover-foreground": "210 40% 98%", - "border": "217.2 32.6% 17.5%", - "input": "217.2 32.6% 17.5%", "card": "222.2 84% 4.9%", "card-foreground": "210 40% 98%", + "popover": "222.2 84% 4.9%", + "popover-foreground": "210 40% 98%", "primary": "210 40% 98%", "primary-foreground": "222.2 47.4% 11.2%", "secondary": "217.2 32.6% 17.5%", "secondary-foreground": "210 40% 98%", + "muted": "217.2 32.6% 17.5%", + "muted-foreground": "215 20.2% 65.1%", "accent": "217.2 32.6% 17.5%", "accent-foreground": "210 40% 98%", "destructive": "0 62.8% 30.6%", - "destructive-foreground": "0 85.7% 97.3%", - "ring": "217.2 32.6% 17.5%" + "destructive-foreground": "210 40% 98%", + "border": "217.2 32.6% 17.5%", + "input": "217.2 32.6% 17.5%", + "ring": "212.7 26.8% 83.9%" } }, "inlineColorsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n", - "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 222.2 84% 4.9%;\n \n --muted: 210 40% 96.1%;\n --muted-foreground: 215.4 16.3% 46.9%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 222.2 84% 4.9%;\n \n --card: 0 0% 100%;\n --card-foreground: 222.2 84% 4.9%;\n \n --border: 214.3 31.8% 91.4%;\n --input: 214.3 31.8% 91.4%;\n \n --primary: 222.2 47.4% 11.2%;\n --primary-foreground: 210 40% 98%;\n \n --secondary: 210 40% 96.1%;\n --secondary-foreground: 222.2 47.4% 11.2%;\n \n --accent: 210 40% 96.1%;\n --accent-foreground: 222.2 47.4% 11.2%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 40% 98%;\n \n --ring: 215 20.2% 65.1%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 222.2 84% 4.9%;\n --foreground: 210 40% 98%;\n \n --muted: 217.2 32.6% 17.5%;\n --muted-foreground: 215 20.2% 65.1%;\n \n --popover: 222.2 84% 4.9%;\n --popover-foreground: 210 40% 98%;\n \n --card: 222.2 84% 4.9%;\n --card-foreground: 210 40% 98%;\n \n --border: 217.2 32.6% 17.5%;\n --input: 217.2 32.6% 17.5%;\n \n --primary: 210 40% 98%;\n --primary-foreground: 222.2 47.4% 11.2%;\n \n --secondary: 217.2 32.6% 17.5%;\n --secondary-foreground: 210 40% 98%;\n \n --accent: 217.2 32.6% 17.5%;\n --accent-foreground: 210 40% 98%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 85.7% 97.3%;\n \n --ring: 217.2 32.6% 17.5%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" + "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 222.2 84% 4.9%;\n\n --card: 0 0% 100%;\n --card-foreground: 222.2 84% 4.9%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 222.2 84% 4.9%;\n \n --primary: 222.2 47.4% 11.2%;\n --primary-foreground: 210 40% 98%;\n \n --secondary: 210 40% 96.1%;\n --secondary-foreground: 222.2 47.4% 11.2%;\n \n --muted: 210 40% 96.1%;\n --muted-foreground: 215.4 16.3% 46.9%;\n \n --accent: 210 40% 96.1%;\n --accent-foreground: 222.2 47.4% 11.2%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 40% 98%;\n\n --border: 214.3 31.8% 91.4%;\n --input: 214.3 31.8% 91.4%;\n --ring: 222.2 84% 4.9%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 222.2 84% 4.9%;\n --foreground: 210 40% 98%;\n \n --card: 222.2 84% 4.9%;\n --card-foreground: 210 40% 98%;\n \n --popover: 222.2 84% 4.9%;\n --popover-foreground: 210 40% 98%;\n \n --primary: 210 40% 98%;\n --primary-foreground: 222.2 47.4% 11.2%;\n \n --secondary: 217.2 32.6% 17.5%;\n --secondary-foreground: 210 40% 98%;\n \n --muted: 217.2 32.6% 17.5%;\n --muted-foreground: 215 20.2% 65.1%;\n \n --accent: 217.2 32.6% 17.5%;\n --accent-foreground: 210 40% 98%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 210 40% 98%;\n \n --border: 217.2 32.6% 17.5%;\n --input: 217.2 32.6% 17.5%;\n --ring: 212.7 26.8% 83.9%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" } \ No newline at end of file diff --git a/apps/www/public/registry/colors/stone.json b/apps/www/public/registry/colors/stone.json index 05e92bb5cc..e06a13460d 100644 --- a/apps/www/public/registry/colors/stone.json +++ b/apps/www/public/registry/colors/stone.json @@ -3,90 +3,90 @@ "light": { "background": "white", "foreground": "stone-950", - "muted": "stone-100", - "muted-foreground": "stone-500", - "popover": "white", - "popover-foreground": "stone-950", - "border": "stone-200", - "input": "stone-200", "card": "white", "card-foreground": "stone-950", + "popover": "white", + "popover-foreground": "stone-950", "primary": "stone-900", "primary-foreground": "stone-50", "secondary": "stone-100", "secondary-foreground": "stone-900", + "muted": "stone-100", + "muted-foreground": "stone-500", "accent": "stone-100", "accent-foreground": "stone-900", "destructive": "red-500", "destructive-foreground": "stone-50", - "ring": "stone-400" + "border": "stone-200", + "input": "stone-200", + "ring": "stone-950" }, "dark": { "background": "stone-950", "foreground": "stone-50", - "muted": "stone-800", - "muted-foreground": "stone-400", - "popover": "stone-950", - "popover-foreground": "stone-50", - "border": "stone-800", - "input": "stone-800", "card": "stone-950", "card-foreground": "stone-50", + "popover": "stone-950", + "popover-foreground": "stone-50", "primary": "stone-50", "primary-foreground": "stone-900", "secondary": "stone-800", "secondary-foreground": "stone-50", + "muted": "stone-800", + "muted-foreground": "stone-400", "accent": "stone-800", "accent-foreground": "stone-50", "destructive": "red-900", - "destructive-foreground": "red-50", - "ring": "stone-800" + "destructive-foreground": "stone-50", + "border": "stone-800", + "input": "stone-800", + "ring": "stone-300" } }, "cssVars": { "light": { "background": "0 0% 100%", "foreground": "20 14.3% 4.1%", - "muted": "60 4.8% 95.9%", - "muted-foreground": "25 5.3% 44.7%", - "popover": "0 0% 100%", - "popover-foreground": "20 14.3% 4.1%", - "border": "20 5.9% 90%", - "input": "20 5.9% 90%", "card": "0 0% 100%", "card-foreground": "20 14.3% 4.1%", + "popover": "0 0% 100%", + "popover-foreground": "20 14.3% 4.1%", "primary": "24 9.8% 10%", "primary-foreground": "60 9.1% 97.8%", "secondary": "60 4.8% 95.9%", "secondary-foreground": "24 9.8% 10%", + "muted": "60 4.8% 95.9%", + "muted-foreground": "25 5.3% 44.7%", "accent": "60 4.8% 95.9%", "accent-foreground": "24 9.8% 10%", "destructive": "0 84.2% 60.2%", "destructive-foreground": "60 9.1% 97.8%", - "ring": "24 5.4% 63.9%" + "border": "20 5.9% 90%", + "input": "20 5.9% 90%", + "ring": "20 14.3% 4.1%" }, "dark": { "background": "20 14.3% 4.1%", "foreground": "60 9.1% 97.8%", - "muted": "12 6.5% 15.1%", - "muted-foreground": "24 5.4% 63.9%", - "popover": "20 14.3% 4.1%", - "popover-foreground": "60 9.1% 97.8%", - "border": "12 6.5% 15.1%", - "input": "12 6.5% 15.1%", "card": "20 14.3% 4.1%", "card-foreground": "60 9.1% 97.8%", + "popover": "20 14.3% 4.1%", + "popover-foreground": "60 9.1% 97.8%", "primary": "60 9.1% 97.8%", "primary-foreground": "24 9.8% 10%", "secondary": "12 6.5% 15.1%", "secondary-foreground": "60 9.1% 97.8%", + "muted": "12 6.5% 15.1%", + "muted-foreground": "24 5.4% 63.9%", "accent": "12 6.5% 15.1%", "accent-foreground": "60 9.1% 97.8%", "destructive": "0 62.8% 30.6%", - "destructive-foreground": "0 85.7% 97.3%", - "ring": "12 6.5% 15.1%" + "destructive-foreground": "60 9.1% 97.8%", + "border": "12 6.5% 15.1%", + "input": "12 6.5% 15.1%", + "ring": "24 5.7% 82.9%" } }, "inlineColorsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n", - "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 20 14.3% 4.1%;\n \n --muted: 60 4.8% 95.9%;\n --muted-foreground: 25 5.3% 44.7%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 20 14.3% 4.1%;\n \n --card: 0 0% 100%;\n --card-foreground: 20 14.3% 4.1%;\n \n --border: 20 5.9% 90%;\n --input: 20 5.9% 90%;\n \n --primary: 24 9.8% 10%;\n --primary-foreground: 60 9.1% 97.8%;\n \n --secondary: 60 4.8% 95.9%;\n --secondary-foreground: 24 9.8% 10%;\n \n --accent: 60 4.8% 95.9%;\n --accent-foreground: 24 9.8% 10%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 60 9.1% 97.8%;\n \n --ring: 24 5.4% 63.9%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 20 14.3% 4.1%;\n --foreground: 60 9.1% 97.8%;\n \n --muted: 12 6.5% 15.1%;\n --muted-foreground: 24 5.4% 63.9%;\n \n --popover: 20 14.3% 4.1%;\n --popover-foreground: 60 9.1% 97.8%;\n \n --card: 20 14.3% 4.1%;\n --card-foreground: 60 9.1% 97.8%;\n \n --border: 12 6.5% 15.1%;\n --input: 12 6.5% 15.1%;\n \n --primary: 60 9.1% 97.8%;\n --primary-foreground: 24 9.8% 10%;\n \n --secondary: 12 6.5% 15.1%;\n --secondary-foreground: 60 9.1% 97.8%;\n \n --accent: 12 6.5% 15.1%;\n --accent-foreground: 60 9.1% 97.8%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 85.7% 97.3%;\n \n --ring: 12 6.5% 15.1%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" + "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 20 14.3% 4.1%;\n\n --card: 0 0% 100%;\n --card-foreground: 20 14.3% 4.1%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 20 14.3% 4.1%;\n \n --primary: 24 9.8% 10%;\n --primary-foreground: 60 9.1% 97.8%;\n \n --secondary: 60 4.8% 95.9%;\n --secondary-foreground: 24 9.8% 10%;\n \n --muted: 60 4.8% 95.9%;\n --muted-foreground: 25 5.3% 44.7%;\n \n --accent: 60 4.8% 95.9%;\n --accent-foreground: 24 9.8% 10%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 60 9.1% 97.8%;\n\n --border: 20 5.9% 90%;\n --input: 20 5.9% 90%;\n --ring: 20 14.3% 4.1%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 20 14.3% 4.1%;\n --foreground: 60 9.1% 97.8%;\n \n --card: 20 14.3% 4.1%;\n --card-foreground: 60 9.1% 97.8%;\n \n --popover: 20 14.3% 4.1%;\n --popover-foreground: 60 9.1% 97.8%;\n \n --primary: 60 9.1% 97.8%;\n --primary-foreground: 24 9.8% 10%;\n \n --secondary: 12 6.5% 15.1%;\n --secondary-foreground: 60 9.1% 97.8%;\n \n --muted: 12 6.5% 15.1%;\n --muted-foreground: 24 5.4% 63.9%;\n \n --accent: 12 6.5% 15.1%;\n --accent-foreground: 60 9.1% 97.8%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 60 9.1% 97.8%;\n \n --border: 12 6.5% 15.1%;\n --input: 12 6.5% 15.1%;\n --ring: 24 5.7% 82.9%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" } \ No newline at end of file diff --git a/apps/www/public/registry/colors/zinc.json b/apps/www/public/registry/colors/zinc.json index c26bf0e86f..b13b9e6c59 100644 --- a/apps/www/public/registry/colors/zinc.json +++ b/apps/www/public/registry/colors/zinc.json @@ -3,90 +3,90 @@ "light": { "background": "white", "foreground": "zinc-950", - "muted": "zinc-100", - "muted-foreground": "zinc-500", - "popover": "white", - "popover-foreground": "zinc-950", - "border": "zinc-200", - "input": "zinc-200", "card": "white", "card-foreground": "zinc-950", + "popover": "white", + "popover-foreground": "zinc-950", "primary": "zinc-900", "primary-foreground": "zinc-50", "secondary": "zinc-100", "secondary-foreground": "zinc-900", + "muted": "zinc-100", + "muted-foreground": "zinc-500", "accent": "zinc-100", "accent-foreground": "zinc-900", "destructive": "red-500", "destructive-foreground": "zinc-50", - "ring": "zinc-400" + "border": "zinc-200", + "input": "zinc-200", + "ring": "zinc-950" }, "dark": { "background": "zinc-950", "foreground": "zinc-50", - "muted": "zinc-800", - "muted-foreground": "zinc-400", - "popover": "zinc-950", - "popover-foreground": "zinc-50", - "border": "zinc-800", - "input": "zinc-800", "card": "zinc-950", "card-foreground": "zinc-50", + "popover": "zinc-950", + "popover-foreground": "zinc-50", "primary": "zinc-50", "primary-foreground": "zinc-900", "secondary": "zinc-800", "secondary-foreground": "zinc-50", + "muted": "zinc-800", + "muted-foreground": "zinc-400", "accent": "zinc-800", "accent-foreground": "zinc-50", "destructive": "red-900", - "destructive-foreground": "red-50", - "ring": "zinc-800" + "destructive-foreground": "zinc-50", + "border": "zinc-800", + "input": "zinc-800", + "ring": "zinc-300" } }, "cssVars": { "light": { "background": "0 0% 100%", "foreground": "240 10% 3.9%", - "muted": "240 4.8% 95.9%", - "muted-foreground": "240 3.8% 46.1%", - "popover": "0 0% 100%", - "popover-foreground": "240 10% 3.9%", - "border": "240 5.9% 90%", - "input": "240 5.9% 90%", "card": "0 0% 100%", "card-foreground": "240 10% 3.9%", + "popover": "0 0% 100%", + "popover-foreground": "240 10% 3.9%", "primary": "240 5.9% 10%", "primary-foreground": "0 0% 98%", "secondary": "240 4.8% 95.9%", "secondary-foreground": "240 5.9% 10%", + "muted": "240 4.8% 95.9%", + "muted-foreground": "240 3.8% 46.1%", "accent": "240 4.8% 95.9%", "accent-foreground": "240 5.9% 10%", "destructive": "0 84.2% 60.2%", "destructive-foreground": "0 0% 98%", - "ring": "240 5% 64.9%" + "border": "240 5.9% 90%", + "input": "240 5.9% 90%", + "ring": "240 10% 3.9%" }, "dark": { "background": "240 10% 3.9%", "foreground": "0 0% 98%", - "muted": "240 3.7% 15.9%", - "muted-foreground": "240 5% 64.9%", - "popover": "240 10% 3.9%", - "popover-foreground": "0 0% 98%", - "border": "240 3.7% 15.9%", - "input": "240 3.7% 15.9%", "card": "240 10% 3.9%", "card-foreground": "0 0% 98%", + "popover": "240 10% 3.9%", + "popover-foreground": "0 0% 98%", "primary": "0 0% 98%", "primary-foreground": "240 5.9% 10%", "secondary": "240 3.7% 15.9%", "secondary-foreground": "0 0% 98%", + "muted": "240 3.7% 15.9%", + "muted-foreground": "240 5% 64.9%", "accent": "240 3.7% 15.9%", "accent-foreground": "0 0% 98%", "destructive": "0 62.8% 30.6%", - "destructive-foreground": "0 85.7% 97.3%", - "ring": "240 3.7% 15.9%" + "destructive-foreground": "0 0% 98%", + "border": "240 3.7% 15.9%", + "input": "240 3.7% 15.9%", + "ring": "240 4.9% 83.9%" } }, "inlineColorsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n", - "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 240 10% 3.9%;\n \n --muted: 240 4.8% 95.9%;\n --muted-foreground: 240 3.8% 46.1%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 240 10% 3.9%;\n \n --card: 0 0% 100%;\n --card-foreground: 240 10% 3.9%;\n \n --border: 240 5.9% 90%;\n --input: 240 5.9% 90%;\n \n --primary: 240 5.9% 10%;\n --primary-foreground: 0 0% 98%;\n \n --secondary: 240 4.8% 95.9%;\n --secondary-foreground: 240 5.9% 10%;\n \n --accent: 240 4.8% 95.9%;\n --accent-foreground: 240 5.9% 10%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 0 0% 98%;\n \n --ring: 240 5% 64.9%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 240 10% 3.9%;\n --foreground: 0 0% 98%;\n \n --muted: 240 3.7% 15.9%;\n --muted-foreground: 240 5% 64.9%;\n \n --popover: 240 10% 3.9%;\n --popover-foreground: 0 0% 98%;\n \n --card: 240 10% 3.9%;\n --card-foreground: 0 0% 98%;\n \n --border: 240 3.7% 15.9%;\n --input: 240 3.7% 15.9%;\n \n --primary: 0 0% 98%;\n --primary-foreground: 240 5.9% 10%;\n \n --secondary: 240 3.7% 15.9%;\n --secondary-foreground: 0 0% 98%;\n \n --accent: 240 3.7% 15.9%;\n --accent-foreground: 0 0% 98%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 85.7% 97.3%;\n \n --ring: 240 3.7% 15.9%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" + "cssVarsTemplate": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n \n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 240 10% 3.9%;\n\n --card: 0 0% 100%;\n --card-foreground: 240 10% 3.9%;\n \n --popover: 0 0% 100%;\n --popover-foreground: 240 10% 3.9%;\n \n --primary: 240 5.9% 10%;\n --primary-foreground: 0 0% 98%;\n \n --secondary: 240 4.8% 95.9%;\n --secondary-foreground: 240 5.9% 10%;\n \n --muted: 240 4.8% 95.9%;\n --muted-foreground: 240 3.8% 46.1%;\n \n --accent: 240 4.8% 95.9%;\n --accent-foreground: 240 5.9% 10%;\n \n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 0 0% 98%;\n\n --border: 240 5.9% 90%;\n --input: 240 5.9% 90%;\n --ring: 240 10% 3.9%;\n \n --radius: 0.5rem;\n }\n \n .dark {\n --background: 240 10% 3.9%;\n --foreground: 0 0% 98%;\n \n --card: 240 10% 3.9%;\n --card-foreground: 0 0% 98%;\n \n --popover: 240 10% 3.9%;\n --popover-foreground: 0 0% 98%;\n \n --primary: 0 0% 98%;\n --primary-foreground: 240 5.9% 10%;\n \n --secondary: 240 3.7% 15.9%;\n --secondary-foreground: 0 0% 98%;\n \n --muted: 240 3.7% 15.9%;\n --muted-foreground: 240 5% 64.9%;\n \n --accent: 240 3.7% 15.9%;\n --accent-foreground: 0 0% 98%;\n \n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 0% 98%;\n \n --border: 240 3.7% 15.9%;\n --input: 240 3.7% 15.9%;\n --ring: 240 4.9% 83.9%;\n }\n}\n \n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}" } \ No newline at end of file diff --git a/apps/www/public/registry/index.json b/apps/www/public/registry/index.json index 73bbcdf8c0..b07a5b08b5 100644 --- a/apps/www/public/registry/index.json +++ b/apps/www/public/registry/index.json @@ -1,4 +1,13 @@ [ + { + "name": "editor", + "dependencies": [], + "registryDependencies": [], + "files": [ + "plate-ui/editor.tsx" + ], + "type": "components:plate-ui" + }, { "name": "cloud", "dependencies": [ @@ -776,7 +785,9 @@ "dependencies": [ "@udecode/plate-table" ], - "registryDependencies": [], + "registryDependencies": [ + "dropdown-menu" + ], "files": [ "plate-ui/table-element.tsx" ], @@ -798,7 +809,9 @@ "dependencies": [ "@udecode/plate-list" ], - "registryDependencies": [], + "registryDependencies": [ + "checkbox" + ], "files": [ "plate-ui/todo-list-element.tsx" ], diff --git a/apps/www/public/registry/styles/default/button.json b/apps/www/public/registry/styles/default/button.json index 0a78d3fd51..9f79b86106 100644 --- a/apps/www/public/registry/styles/default/button.json +++ b/apps/www/public/registry/styles/default/button.json @@ -7,7 +7,7 @@ "files": [ { "name": "button.tsx", - "content": "import * as React from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive:\n 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline:\n 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n xs: 'h-8 rounded-md px-3',\n sm: 'h-9 rounded-md px-3',\n sms: 'h-9 w-9 rounded-md px-0',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n },\n isMenu: {\n true: 'h-auto w-full cursor-pointer justify-start',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes,\n VariantProps {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef(\n ({ className, isMenu, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n \n );\n }\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n" + "content": "import * as React from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive:\n 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline:\n 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n inlineLink: 'text-base text-primary underline underline-offset-4',\n },\n size: {\n default: 'h-10 px-4 py-2',\n xs: 'h-8 rounded-md px-3',\n sm: 'h-9 rounded-md px-3',\n sms: 'h-9 w-9 rounded-md px-0',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n none: '',\n },\n isMenu: {\n true: 'h-auto w-full cursor-pointer justify-start',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes,\n VariantProps {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef(\n ({ className, isMenu, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n \n );\n }\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/caption.json b/apps/www/public/registry/styles/default/caption.json index 4306780dce..7d8891c944 100644 --- a/apps/www/public/registry/styles/default/caption.json +++ b/apps/www/public/registry/styles/default/caption.json @@ -7,7 +7,7 @@ "files": [ { "name": "caption.tsx", - "content": "import React, { ComponentProps } from 'react';\nimport {\n Caption as CaptionPrimitive,\n CaptionTextarea as CaptionTextareaPrimitive,\n} from '@udecode/plate-caption';\nimport { cva, VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst captionVariants = cva('max-w-full', {\n variants: {\n align: {\n left: 'mr-auto',\n center: 'mx-auto',\n right: 'ml-auto',\n },\n },\n defaultVariants: {\n align: 'center',\n },\n});\n\nconst Caption = React.forwardRef<\n React.ElementRef,\n ComponentProps & VariantProps\n>(({ className, align, ...props }, ref) => (\n \n));\nCaption.displayName = 'Caption';\n\nconst CaptionTextarea = React.forwardRef<\n React.ElementRef,\n ComponentProps\n>(({ className, ...props }, ref) => (\n \n));\nCaptionTextarea.displayName = 'CaptionTextarea';\n\nexport { Caption, CaptionTextarea };\n" + "content": "import React, { ComponentProps } from 'react';\nimport {\n Caption as CaptionPrimitive,\n CaptionTextarea as CaptionTextareaPrimitive,\n} from '@udecode/plate-caption';\nimport { cva, VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst captionVariants = cva('max-w-full', {\n variants: {\n align: {\n left: 'mr-auto',\n center: 'mx-auto',\n right: 'ml-auto',\n },\n },\n defaultVariants: {\n align: 'center',\n },\n});\n\nconst Caption = React.forwardRef<\n React.ElementRef,\n ComponentProps & VariantProps\n>(({ className, align, ...props }, ref) => (\n \n));\nCaption.displayName = 'Caption';\n\nconst CaptionTextarea = React.forwardRef<\n React.ElementRef,\n ComponentProps\n>(({ className, ...props }, ref) => (\n \n));\nCaptionTextarea.displayName = 'CaptionTextarea';\n\nexport { Caption, CaptionTextarea };\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/checkbox.json b/apps/www/public/registry/styles/default/checkbox.json index c9c4158437..24c92e8515 100644 --- a/apps/www/public/registry/styles/default/checkbox.json +++ b/apps/www/public/registry/styles/default/checkbox.json @@ -7,7 +7,7 @@ "files": [ { "name": "checkbox.tsx", - "content": "'use client';\n\nimport * as React from 'react';\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox';\n\nimport { cn } from '@/lib/utils';\nimport { Icons } from '@/components/icons';\n\nconst Checkbox = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n \n \n \n \n));\nCheckbox.displayName = CheckboxPrimitive.Root.displayName;\n\nexport { Checkbox };\n" + "content": "'use client';\n\nimport * as React from 'react';\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox';\n\nimport { cn } from '@/lib/utils';\nimport { Icons } from '@/components/icons';\n\nconst Checkbox = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n \n \n \n \n));\nCheckbox.displayName = CheckboxPrimitive.Root.displayName;\n\nexport { Checkbox };\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/cloud.json b/apps/www/public/registry/styles/default/cloud.json index 2abee7f988..0dcaf2cb36 100644 --- a/apps/www/public/registry/styles/default/cloud.json +++ b/apps/www/public/registry/styles/default/cloud.json @@ -19,15 +19,15 @@ }, { "name": "cloud-resize-controls.tsx", - "content": "'use client';\n\nimport React, {\n Dispatch,\n SetStateAction,\n useCallback,\n useRef,\n useState,\n} from 'react';\nimport { resizeInWidth } from '@portive/client';\nimport {\n PlateCloudEditor,\n PlateCloudImageEditor,\n TCloudImageElement,\n} from '@udecode/plate-cloud';\nimport {\n findNodePath,\n setNodes,\n usePlateEditorRef,\n} from '@udecode/plate-common';\n\ntype ImageSize = { width: number; height: number };\n\ntype SetImageSize = Dispatch>;\n\n/**\n * The resize label that shows the width/height of the image\n */\nfunction ResizeLabel({ size }: { size: { width: number; height: number } }) {\n const isBelow = size.width < 100 || size.height < 100;\n const bottom = isBelow ? -24 : 4;\n return (\n \n {size.width} × {size.height}\n
\n );\n}\n\n/**\n * The little divets on the resize handle bar.\n */\nconst barStyle = {\n position: 'absolute',\n top: 8,\n width: 1,\n height: 16,\n background: 'rgba(255,255,255,0.75)',\n} as const;\n\n/**\n * The handle used to drag resize an image\n */\nfunction ResizeHandles({\n onMouseDown,\n}: {\n onMouseDown: React.MouseEventHandler;\n}) {\n return (\n <>\n {/* Invisible Handle */}\n \n {/* Visible Handle */}\n \n
\n
\n
\n
\n
\n \n );\n}\n\nexport function ResizeControls({\n element,\n size,\n setSize,\n}: {\n element: TCloudImageElement;\n size: ImageSize;\n setSize: SetImageSize;\n}) {\n const editor = usePlateEditorRef() as PlateCloudEditor &\n PlateCloudImageEditor;\n const [isResizing, setIsResizing] = useState(false);\n\n const { minResizeWidth, maxResizeWidth } = editor.cloudImage;\n\n const currentSizeRef = useRef<{ width: number; height: number }>();\n\n const onMouseDown = useCallback(\n (mouseDownEvent: React.MouseEvent) => {\n setIsResizing(true);\n const startX = mouseDownEvent.clientX;\n const startWidth = size.width;\n const minWidth = minResizeWidth;\n const maxWidth = Math.min(element.maxWidth, maxResizeWidth);\n /**\n * Handle resize dragging through an event handler on mouseMove on the\n * document.\n */\n function onDocumentMouseMove(mouseMoveEvent: MouseEvent) {\n mouseMoveEvent.preventDefault();\n mouseMoveEvent.stopPropagation();\n /**\n * Calculate the proposed width based on drag position\n */\n const proposedWidth = startWidth + mouseMoveEvent.clientX - startX;\n\n /**\n * Constrain the proposed with between min, max and original width\n */\n const nextWidth = Math.min(maxWidth, Math.max(minWidth, proposedWidth));\n\n const currentSize = resizeInWidth(\n { width: element.maxWidth, height: element.maxHeight },\n nextWidth\n );\n\n currentSizeRef.current = currentSize;\n setSize(currentSize);\n }\n\n const originalCursor = document.body.style.cursor;\n\n /**\n * When the user releases the mouse, remove all the event handlers\n */\n function onDocumentMouseUp() {\n setIsResizing(false);\n document.removeEventListener('mousemove', onDocumentMouseMove);\n document.removeEventListener('mouseup', onDocumentMouseUp);\n document.body.style.cursor = originalCursor;\n\n const at = findNodePath(editor, element);\n\n if (!currentSizeRef.current) return;\n\n setNodes(editor, currentSizeRef.current, { at });\n }\n\n /**\n * Attach document event listeners\n */\n document.addEventListener('mousemove', onDocumentMouseMove);\n document.addEventListener('mouseup', onDocumentMouseUp);\n\n /**\n * While dragging, we want the cursor to be `ew-resize` (left-right arrow)\n * even if the cursor happens to not be exactly on the handle at the moment\n * due to a delay in the cursor moving to a location and the image resizing\n * to it.\n *\n * Also, image has max width/height and the cursor can fall outside of it.\n */\n document.body.style.cursor = 'ew-resize';\n },\n [size.width, minResizeWidth, element, maxResizeWidth, setSize, editor]\n );\n\n if (element.width < minResizeWidth) return null;\n\n return (\n <>\n {isResizing ? : null}\n \n \n );\n}\n" + "content": "'use client';\n\nimport React, {\n Dispatch,\n SetStateAction,\n useCallback,\n useRef,\n useState,\n} from 'react';\nimport { resizeInWidth } from '@portive/client';\nimport {\n PlateCloudEditor,\n PlateCloudImageEditor,\n TCloudImageElement,\n} from '@udecode/plate-cloud';\nimport { findNodePath, setNodes, useEditorRef } from '@udecode/plate-common';\n\ntype ImageSize = { width: number; height: number };\n\ntype SetImageSize = Dispatch>;\n\n/**\n * The resize label that shows the width/height of the image\n */\nfunction ResizeLabel({ size }: { size: { width: number; height: number } }) {\n const isBelow = size.width < 100 || size.height < 100;\n const bottom = isBelow ? -24 : 4;\n return (\n \n {size.width} × {size.height}\n
\n );\n}\n\n/**\n * The little divets on the resize handle bar.\n */\nconst barStyle = {\n position: 'absolute',\n top: 8,\n width: 1,\n height: 16,\n background: 'rgba(255,255,255,0.75)',\n} as const;\n\n/**\n * The handle used to drag resize an image\n */\nfunction ResizeHandles({\n onMouseDown,\n}: {\n onMouseDown: React.MouseEventHandler;\n}) {\n return (\n <>\n {/* Invisible Handle */}\n \n {/* Visible Handle */}\n \n
\n
\n
\n
\n
\n \n );\n}\n\nexport function ResizeControls({\n element,\n size,\n setSize,\n}: {\n element: TCloudImageElement;\n size: ImageSize;\n setSize: SetImageSize;\n}) {\n const editor = useEditorRef() as PlateCloudEditor & PlateCloudImageEditor;\n const [isResizing, setIsResizing] = useState(false);\n\n const { minResizeWidth, maxResizeWidth } = editor.cloudImage;\n\n const currentSizeRef = useRef<{ width: number; height: number }>();\n\n const onMouseDown = useCallback(\n (mouseDownEvent: React.MouseEvent) => {\n setIsResizing(true);\n const startX = mouseDownEvent.clientX;\n const startWidth = size.width;\n const minWidth = minResizeWidth;\n const maxWidth = Math.min(element.maxWidth, maxResizeWidth);\n /**\n * Handle resize dragging through an event handler on mouseMove on the\n * document.\n */\n function onDocumentMouseMove(mouseMoveEvent: MouseEvent) {\n mouseMoveEvent.preventDefault();\n mouseMoveEvent.stopPropagation();\n /**\n * Calculate the proposed width based on drag position\n */\n const proposedWidth = startWidth + mouseMoveEvent.clientX - startX;\n\n /**\n * Constrain the proposed with between min, max and original width\n */\n const nextWidth = Math.min(maxWidth, Math.max(minWidth, proposedWidth));\n\n const currentSize = resizeInWidth(\n { width: element.maxWidth, height: element.maxHeight },\n nextWidth\n );\n\n currentSizeRef.current = currentSize;\n setSize(currentSize);\n }\n\n const originalCursor = document.body.style.cursor;\n\n /**\n * When the user releases the mouse, remove all the event handlers\n */\n function onDocumentMouseUp() {\n setIsResizing(false);\n document.removeEventListener('mousemove', onDocumentMouseMove);\n document.removeEventListener('mouseup', onDocumentMouseUp);\n document.body.style.cursor = originalCursor;\n\n const at = findNodePath(editor, element);\n\n if (!currentSizeRef.current) return;\n\n setNodes(editor, currentSizeRef.current, { at });\n }\n\n /**\n * Attach document event listeners\n */\n document.addEventListener('mousemove', onDocumentMouseMove);\n document.addEventListener('mouseup', onDocumentMouseUp);\n\n /**\n * While dragging, we want the cursor to be `ew-resize` (left-right arrow)\n * even if the cursor happens to not be exactly on the handle at the moment\n * due to a delay in the cursor moving to a location and the image resizing\n * to it.\n *\n * Also, image has max width/height and the cursor can fall outside of it.\n */\n document.body.style.cursor = 'ew-resize';\n },\n [size.width, minResizeWidth, element, maxResizeWidth, setSize, editor]\n );\n\n if (element.width < minResizeWidth) return null;\n\n return (\n <>\n {isResizing ? : null}\n \n \n );\n}\n" }, { "name": "cloud-status-bar.tsx", - "content": "'use client';\n\nimport React, { HTMLAttributes, useEffect, useRef, useState } from 'react';\nimport { Upload, UploadProgress } from '@udecode/plate-cloud';\n\nimport { cn } from '@/lib/utils';\n\nexport function ProgressBar({\n upload,\n className,\n ...props\n}: {\n upload: UploadProgress;\n} & HTMLAttributes) {\n const [width, setWidth] = useState(null);\n const ref = useRef(null);\n\n useEffect(() => {\n if (ref.current) setWidth(ref.current.offsetWidth);\n }, []);\n\n /**\n * This formula looks a little funny because we want the `0` value of the\n * progress bar to have a width that is still the height of the progress bar.\n *\n * This is for a few reasons:\n *\n * 1. We want the zero point to start with the progress bar being a circle\n * 2. If we want rounded edges, if the width is shorter than the height,\n * we get an oval instead of a circle\n * 3. The halfway point looks visually wrong because of the circle progress\n * bar when it is technically at the halfway point.\n */\n const progressWidth =\n width == null\n ? 0\n : (upload.sentBytes / upload.totalBytes) * (width - 16) + 16;\n\n return (\n \n \n
\n );\n}\n\nexport function FailBar({\n className,\n ...props\n}: HTMLAttributes) {\n return (\n \n );\n}\n\nexport function StatusBar(props: { upload: Upload; children?: JSX.Element }) {\n const { upload, children } = props;\n switch (upload.status) {\n case 'progress': {\n return ;\n }\n case 'error': {\n return Upload Failed;\n }\n case 'not-found': {\n return Uploading...;\n }\n case 'success': {\n return children || null;\n }\n default: {\n throw new Error(`Should be unreachable`);\n }\n }\n}\n" + "content": "'use client';\n\nimport React, { HTMLAttributes, useEffect, useRef, useState } from 'react';\nimport { Upload, UploadProgress } from '@udecode/plate-cloud';\n\nimport { cn } from '@/lib/utils';\n\nexport function ProgressBar({\n upload,\n className,\n ...props\n}: {\n upload: UploadProgress;\n} & HTMLAttributes) {\n const [width, setWidth] = useState(null);\n const ref = useRef(null);\n\n useEffect(() => {\n if (ref.current) setWidth(ref.current.offsetWidth);\n }, []);\n\n /**\n * This formula looks a little funny because we want the `0` value of the\n * progress bar to have a width that is still the height of the progress bar.\n *\n * This is for a few reasons:\n *\n * 1. We want the zero point to start with the progress bar being a circle\n * 2. If we want rounded edges, if the width is shorter than the height,\n * we get an oval instead of a circle\n * 3. The halfway point looks visually wrong because of the circle progress\n * bar when it is technically at the halfway point.\n */\n const progressWidth =\n width == null\n ? 0\n : (upload.sentBytes / upload.totalBytes) * (width - 16) + 16;\n\n return (\n \n \n
\n );\n}\n\nexport function FailBar({\n className,\n ...props\n}: HTMLAttributes) {\n return (\n \n );\n}\n\nexport function StatusBar(props: {\n upload: Upload;\n children?: React.ReactNode;\n}) {\n const { upload, children } = props;\n switch (upload.status) {\n case 'progress': {\n return ;\n }\n case 'error': {\n return Upload Failed;\n }\n case 'not-found': {\n return Uploading...;\n }\n case 'success': {\n return children || null;\n }\n default: {\n throw new Error(`Should be unreachable`);\n }\n }\n}\n" }, { "name": "cloud-toolbar-buttons.tsx", - "content": "'use client';\n\nimport React from 'react';\nimport { PlateCloudEditor } from '@udecode/plate-cloud';\nimport { usePlateEditorRef } from '@udecode/plate-common';\n\nconst buttonStyle: React.CSSProperties = {\n marginRight: 4,\n background: '#f0f0f0',\n border: 'none',\n padding: 8,\n cursor: 'pointer',\n};\n\nexport function CloudToolbarButtons() {\n const editor = usePlateEditorRef() as PlateCloudEditor;\n const getSaveValue = () => {\n console.info('editor.children', editor.children);\n console.info('editor.cloud.getSaveValue()', editor.cloud.getSaveValue());\n };\n\n const finishUploads = async () => {\n const start = Date.now();\n // eslint-disable-next-line no-console\n console.info('start finishUploads');\n await editor.cloud.finishUploads();\n const end = Date.now();\n // NOTE: We don't use backtick with curly brace replacement because it\n // doesn't work with gen:code script at time of writing.\n // eslint-disable-next-line no-console\n console.info(`end finishUploads in ms:`, end - start);\n };\n\n return (\n <>\n \n \n \n Note: After clicking a button, output will be shown in console.\n \n \n );\n}\n" + "content": "'use client';\n\nimport React from 'react';\nimport { PlateCloudEditor } from '@udecode/plate-cloud';\nimport { useEditorRef, Value } from '@udecode/plate-common';\n\nconst buttonStyle: React.CSSProperties = {\n marginRight: 4,\n background: '#f0f0f0',\n border: 'none',\n padding: 8,\n cursor: 'pointer',\n};\n\nexport function CloudToolbarButtons() {\n const editor = useEditorRef();\n const getSaveValue = () => {\n console.info('editor.children', editor.children);\n console.info('editor.cloud.getSaveValue()', editor.cloud.getSaveValue());\n };\n\n const finishUploads = async () => {\n const start = Date.now();\n // eslint-disable-next-line no-console\n console.info('start finishUploads');\n await editor.cloud.finishUploads();\n const end = Date.now();\n // NOTE: We don't use backtick with curly brace replacement because it\n // doesn't work with gen:code script at time of writing.\n // eslint-disable-next-line no-console\n console.info(`end finishUploads in ms:`, end - start);\n };\n\n return (\n <>\n \n \n \n Note: After clicking a button, output will be shown in console.\n \n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/code-block-element.json b/apps/www/public/registry/styles/default/code-block-element.json index b0b0e1b680..a32f355518 100644 --- a/apps/www/public/registry/styles/default/code-block-element.json +++ b/apps/www/public/registry/styles/default/code-block-element.json @@ -13,7 +13,7 @@ }, { "name": "code-block-element.css", - "content": "/**\n * One Light theme for prism.js\n * Based on Atom's One Light theme: https://github.com/atom/atom/tree/master/packages/one-light-syntax\n */\n\n/**\n * One Light colours (accurate as of commit eb064bf on 19 Feb 2021)\n * From colors.less\n * --mono-1: hsl(230, 8%, 24%);\n * --mono-2: hsl(230, 6%, 44%);\n * --mono-3: hsl(230, 4%, 64%)\n * --hue-1: hsl(198, 99%, 37%);\n * --hue-2: hsl(221, 87%, 60%);\n * --hue-3: hsl(301, 63%, 40%);\n * --hue-4: hsl(119, 34%, 47%);\n * --hue-5: hsl(5, 74%, 59%);\n * --hue-5-2: hsl(344, 84%, 43%);\n * --hue-6: hsl(35, 99%, 36%);\n * --hue-6-2: hsl(35, 99%, 40%);\n * --syntax-fg: hsl(230, 8%, 24%);\n * --syntax-bg: hsl(230, 1%, 98%);\n * --syntax-gutter: hsl(230, 1%, 62%);\n * --syntax-guide: hsla(230, 8%, 24%, 0.2);\n * --syntax-accent: hsl(230, 100%, 66%);\n * From syntax-variables.less\n * --syntax-selection-color: hsl(230, 1%, 90%);\n * --syntax-gutter-background-color-selected: hsl(230, 1%, 90%);\n * --syntax-cursor-line: hsla(230, 8%, 24%, 0.05);\n */\n\ncode[class*='language-'],\npre[class*='language-'] {\n background: hsl(230, 1%, 98%);\n color: hsl(230, 8%, 24%);\n font-family: 'Fira Code', 'Fira Mono', Menlo, Consolas, 'DejaVu Sans Mono',\n monospace;\n direction: ltr;\n text-align: left;\n white-space: pre;\n word-spacing: normal;\n word-break: normal;\n line-height: 1.5;\n -moz-tab-size: 2;\n -o-tab-size: 2;\n tab-size: 2;\n -webkit-hyphens: none;\n -moz-hyphens: none;\n -ms-hyphens: none;\n hyphens: none;\n}\n\n/* Selection */\ncode[class*='language-']::-moz-selection,\ncode[class*='language-'] *::-moz-selection,\npre[class*='language-'] *::-moz-selection {\n background: hsl(230, 1%, 90%);\n color: inherit;\n}\n\ncode[class*='language-']::selection,\ncode[class*='language-'] *::selection,\npre[class*='language-'] *::selection {\n background: hsl(230, 1%, 90%);\n color: inherit;\n}\n\n/* Code blocks */\npre[class*='language-'] {\n padding: 1em;\n margin: 0.5em 0;\n overflow: auto;\n border-radius: 0.3em;\n}\n\n/* Inline code */\n:not(pre) > code[class*='language-'] {\n padding: 0.2em 0.3em;\n border-radius: 0.3em;\n white-space: normal;\n}\n\n.token.comment,\n.token.prolog,\n.token.cdata {\n color: hsl(230, 4%, 64%);\n}\n\n.token.doctype,\n.token.punctuation,\n.token.entity {\n color: hsl(230, 8%, 24%);\n}\n\n.token.attr-name,\n.token.class-name,\n.token.boolean,\n.token.constant,\n.token.number,\n.token.atrule {\n color: hsl(35, 99%, 36%);\n}\n\n.token.keyword {\n color: hsl(301, 63%, 40%);\n}\n\n.token.property,\n.token.tag,\n.token.symbol,\n.token.deleted,\n.token.important {\n color: hsl(5, 74%, 59%);\n}\n\n.token.selector,\n.token.string,\n.token.char,\n.token.builtin,\n.token.inserted,\n.token.regex,\n.token.attr-value,\n.token.attr-value > .token.punctuation {\n color: hsl(119, 34%, 47%);\n}\n\n.token.variable,\n.token.operator,\n.token.function {\n color: hsl(221, 87%, 60%);\n}\n\n.token.url {\n color: hsl(198, 99%, 37%);\n}\n\n/* HTML overrides */\n.token.attr-value > .token.punctuation.attr-equals,\n.token.special-attr > .token.attr-value > .token.value.css {\n color: hsl(230, 8%, 24%);\n}\n\n/* CSS overrides */\n.language-css .token.selector {\n color: hsl(5, 74%, 59%);\n}\n\n.language-css .token.property {\n color: hsl(230, 8%, 24%);\n}\n\n.language-css .token.function,\n.language-css .token.url > .token.function {\n color: hsl(198, 99%, 37%);\n}\n\n.language-css .token.url > .token.string.url {\n color: hsl(119, 34%, 47%);\n}\n\n.language-css .token.important,\n.language-css .token.atrule .token.rule {\n color: hsl(301, 63%, 40%);\n}\n\n/* JS overrides */\n.language-javascript .token.operator {\n color: hsl(301, 63%, 40%);\n}\n\n.language-javascript\n .token.template-string\n > .token.interpolation\n > .token.interpolation-punctuation.punctuation {\n color: hsl(344, 84%, 43%);\n}\n\n/* JSON overrides */\n.language-json .token.operator {\n color: hsl(230, 8%, 24%);\n}\n\n.language-json .token.null.keyword {\n color: hsl(35, 99%, 36%);\n}\n\n/* MD overrides */\n.language-markdown .token.url,\n.language-markdown .token.url > .token.operator,\n.language-markdown .token.url-reference.url > .token.string {\n color: hsl(230, 8%, 24%);\n}\n\n.language-markdown .token.url > .token.content {\n color: hsl(221, 87%, 60%);\n}\n\n.language-markdown .token.url > .token.url,\n.language-markdown .token.url-reference.url {\n color: hsl(198, 99%, 37%);\n}\n\n.language-markdown .token.blockquote.punctuation,\n.language-markdown .token.hr.punctuation {\n color: hsl(230, 4%, 64%);\n font-style: italic;\n}\n\n.language-markdown .token.code-snippet {\n color: hsl(119, 34%, 47%);\n}\n\n.language-markdown .token.bold .token.content {\n color: hsl(35, 99%, 36%);\n}\n\n.language-markdown .token.italic .token.content {\n color: hsl(301, 63%, 40%);\n}\n\n.language-markdown .token.strike .token.content,\n.language-markdown .token.strike .token.punctuation,\n.language-markdown .token.list.punctuation,\n.language-markdown .token.title.important > .token.punctuation {\n color: hsl(5, 74%, 59%);\n}\n\n/* General */\n.token.bold {\n font-weight: bold;\n}\n\n.token.comment,\n.token.italic {\n font-style: italic;\n}\n\n.token.entity {\n cursor: help;\n}\n\n.token.namespace {\n opacity: 0.8;\n}\n\n/* Plugin overrides */\n/* Selectors should have higher specificity than those in the plugins' default stylesheets */\n\n/* Show Invisibles plugin overrides */\n.token.token.tab:not(:empty):before,\n.token.token.cr:before,\n.token.token.lf:before,\n.token.token.space:before {\n color: hsla(230, 8%, 24%, 0.2);\n}\n\n/* Toolbar plugin overrides */\n/* Space out all buttons and move them away from the right edge of the code block */\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item {\n margin-right: 0.4em;\n}\n\n/* Styling the buttons */\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > button,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > a,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > span {\n background: hsl(230, 1%, 90%);\n color: hsl(230, 6%, 44%);\n padding: 0.1em 0.4em;\n border-radius: 0.3em;\n}\n\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus {\n background: hsl(230, 1%, 78%); /* custom: darken(--syntax-bg, 20%) */\n color: hsl(230, 8%, 24%);\n}\n\n/* Line Highlight plugin overrides */\n/* The highlighted line itself */\n.line-highlight.line-highlight {\n background: hsla(230, 8%, 24%, 0.05);\n}\n\n/* Default line numbers in Line Highlight plugin */\n.line-highlight.line-highlight:before,\n.line-highlight.line-highlight[data-end]:after {\n background: hsl(230, 1%, 90%);\n color: hsl(230, 8%, 24%);\n padding: 0.1em 0.6em;\n border-radius: 0.3em;\n box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); /* same as Toolbar plugin default */\n}\n\n/* Hovering over a linkable line number (in the gutter area) */\n/* Requires Line Numbers plugin as well */\npre[id].linkable-line-numbers.linkable-line-numbers\n span.line-numbers-rows\n > span:hover:before {\n background-color: hsla(230, 8%, 24%, 0.05);\n}\n\n/* Line Numbers and Command Line plugins overrides */\n/* Line separating gutter from coding area */\n.line-numbers.line-numbers .line-numbers-rows,\n.command-line .command-line-prompt {\n border-right-color: hsla(230, 8%, 24%, 0.2);\n}\n\n/* Stuff in the gutter */\n.line-numbers .line-numbers-rows > span:before,\n.command-line .command-line-prompt > span:before {\n color: hsl(230, 1%, 62%);\n}\n\n/* Match Braces plugin overrides */\n/* Note: Outline colour is inherited from the braces */\n.rainbow-braces .token.token.punctuation.brace-level-1,\n.rainbow-braces .token.token.punctuation.brace-level-5,\n.rainbow-braces .token.token.punctuation.brace-level-9 {\n color: hsl(5, 74%, 59%);\n}\n\n.rainbow-braces .token.token.punctuation.brace-level-2,\n.rainbow-braces .token.token.punctuation.brace-level-6,\n.rainbow-braces .token.token.punctuation.brace-level-10 {\n color: hsl(119, 34%, 47%);\n}\n\n.rainbow-braces .token.token.punctuation.brace-level-3,\n.rainbow-braces .token.token.punctuation.brace-level-7,\n.rainbow-braces .token.token.punctuation.brace-level-11 {\n color: hsl(221, 87%, 60%);\n}\n\n.rainbow-braces .token.token.punctuation.brace-level-4,\n.rainbow-braces .token.token.punctuation.brace-level-8,\n.rainbow-braces .token.token.punctuation.brace-level-12 {\n color: hsl(301, 63%, 40%);\n}\n\n/* Diff Highlight plugin overrides */\n/* Taken from https://github.com/atom/github/blob/master/styles/variables.less */\npre.diff-highlight > code .token.token.deleted:not(.prefix),\npre > code.diff-highlight .token.token.deleted:not(.prefix) {\n background-color: hsla(353, 100%, 66%, 0.15);\n}\n\npre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection,\npre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection,\npre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection,\npre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection {\n background-color: hsla(353, 95%, 66%, 0.25);\n}\n\npre.diff-highlight > code .token.token.deleted:not(.prefix)::selection,\npre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection,\npre > code.diff-highlight .token.token.deleted:not(.prefix)::selection,\npre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection {\n background-color: hsla(353, 95%, 66%, 0.25);\n}\n\npre.diff-highlight > code .token.token.inserted:not(.prefix),\npre > code.diff-highlight .token.token.inserted:not(.prefix) {\n background-color: hsla(137, 100%, 55%, 0.15);\n}\n\npre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection,\npre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection,\npre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection,\npre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection {\n background-color: hsla(135, 73%, 55%, 0.25);\n}\n\npre.diff-highlight > code .token.token.inserted:not(.prefix)::selection,\npre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection,\npre > code.diff-highlight .token.token.inserted:not(.prefix)::selection,\npre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection {\n background-color: hsla(135, 73%, 55%, 0.25);\n}\n\n/* Previewers plugin overrides */\n/* Based on https://github.com/atom-community/atom-ide-datatip/blob/master/styles/atom-ide-datatips.less and https://github.com/atom/atom/blob/master/packages/one-light-ui */\n/* Border around popup */\n.prism-previewer.prism-previewer:before,\n.prism-previewer-gradient.prism-previewer-gradient div {\n border-color: hsl(0, 0, 95%);\n}\n\n/* Angle and time should remain as circles and are hence not included */\n.prism-previewer-color.prism-previewer-color:before,\n.prism-previewer-gradient.prism-previewer-gradient div,\n.prism-previewer-easing.prism-previewer-easing:before {\n border-radius: 0.3em;\n}\n\n/* Triangles pointing to the code */\n.prism-previewer.prism-previewer:after {\n border-top-color: hsl(0, 0, 95%);\n}\n\n.prism-previewer-flipped.prism-previewer-flipped.after {\n border-bottom-color: hsl(0, 0, 95%);\n}\n\n/* Background colour within the popup */\n.prism-previewer-angle.prism-previewer-angle:before,\n.prism-previewer-time.prism-previewer-time:before,\n.prism-previewer-easing.prism-previewer-easing {\n background: hsl(0, 0%, 100%);\n}\n\n/* For angle, this is the positive area (eg. 90deg will display one quadrant in this colour) */\n/* For time, this is the alternate colour */\n.prism-previewer-angle.prism-previewer-angle circle,\n.prism-previewer-time.prism-previewer-time circle {\n stroke: hsl(230, 8%, 24%);\n stroke-opacity: 1;\n}\n\n/* Stroke colours of the handle, direction point, and vector itself */\n.prism-previewer-easing.prism-previewer-easing circle,\n.prism-previewer-easing.prism-previewer-easing path,\n.prism-previewer-easing.prism-previewer-easing line {\n stroke: hsl(230, 8%, 24%);\n}\n\n/* Fill colour of the handle */\n.prism-previewer-easing.prism-previewer-easing circle {\n fill: transparent;\n}\n" + "content": "/**\n * One Light theme for prism.js\n * Based on Atom's One Light theme: https://github.com/atom/atom/tree/master/packages/one-light-syntax\n */\n\n/**\n * One Light colours (accurate as of commit eb064bf on 19 Feb 2021)\n * From colors.less\n * --mono-1: hsl(230, 8%, 24%);\n * --mono-2: hsl(230, 6%, 44%);\n * --mono-3: hsl(230, 4%, 64%)\n * --hue-1: hsl(198, 99%, 37%);\n * --hue-2: hsl(221, 87%, 60%);\n * --hue-3: hsl(301, 63%, 40%);\n * --hue-4: hsl(119, 34%, 47%);\n * --hue-5: hsl(5, 74%, 59%);\n * --hue-5-2: hsl(344, 84%, 43%);\n * --hue-6: hsl(35, 99%, 36%);\n * --hue-6-2: hsl(35, 99%, 40%);\n * --syntax-fg: hsl(230, 8%, 24%);\n * --syntax-bg: hsl(230, 1%, 98%);\n * --syntax-gutter: hsl(230, 1%, 62%);\n * --syntax-guide: hsla(230, 8%, 24%, 0.2);\n * --syntax-accent: hsl(230, 100%, 66%);\n * From syntax-variables.less\n * --syntax-selection-color: hsl(230, 1%, 90%);\n * --syntax-gutter-background-color-selected: hsl(230, 1%, 90%);\n * --syntax-cursor-line: hsla(230, 8%, 24%, 0.05);\n */\n\n.slate-code_block code[class*='language-'],\n.slate-code_block pre[class*='language-'] {\n background: hsl(230, 1%, 98%);\n color: hsl(230, 8%, 24%);\n font-family: 'Fira Code', 'Fira Mono', Menlo, Consolas, 'DejaVu Sans Mono',\n monospace;\n direction: ltr;\n text-align: left;\n white-space: pre;\n word-spacing: normal;\n word-break: normal;\n line-height: 1.5;\n -moz-tab-size: 2;\n -o-tab-size: 2;\n tab-size: 2;\n -webkit-hyphens: none;\n -moz-hyphens: none;\n -ms-hyphens: none;\n hyphens: none;\n}\n\n/* Selection */\n.slate-code_block code[class*='language-']::-moz-selection,\n.slate-code_block code[class*='language-'] *::-moz-selection,\n.slate-code_block pre[class*='language-'] *::-moz-selection {\n background: hsl(230, 1%, 90%);\n color: inherit;\n}\n\n.slate-code_block code[class*='language-']::selection,\n.slate-code_block code[class*='language-'] *::selection,\n.slate-code_block pre[class*='language-'] *::selection {\n background: hsl(230, 1%, 90%);\n color: inherit;\n}\n\n/* Code blocks */\n.slate-code_block pre[class*='language-'] {\n padding: 1em;\n margin: 0.5em 0;\n overflow: auto;\n border-radius: 0.3em;\n}\n\n/* Inline code */\n.slate-code_block :not(pre) > code[class*='language-'] {\n padding: 0.2em 0.3em;\n border-radius: 0.3em;\n white-space: normal;\n}\n\n.token.comment,\n.token.prolog,\n.token.cdata {\n color: hsl(230, 4%, 64%);\n}\n\n.token.doctype,\n.token.punctuation,\n.token.entity {\n color: hsl(230, 8%, 24%);\n}\n\n.token.attr-name,\n.token.class-name,\n.token.boolean,\n.token.constant,\n.token.number,\n.token.atrule {\n color: hsl(35, 99%, 36%);\n}\n\n.token.keyword {\n color: hsl(301, 63%, 40%);\n}\n\n.token.property,\n.token.tag,\n.token.symbol,\n.token.deleted,\n.token.important {\n color: hsl(5, 74%, 59%);\n}\n\n.token.selector,\n.token.string,\n.token.char,\n.token.builtin,\n.token.inserted,\n.token.regex,\n.token.attr-value,\n.token.attr-value > .token.punctuation {\n color: hsl(119, 34%, 47%);\n}\n\n.token.variable,\n.token.operator,\n.token.function {\n color: hsl(221, 87%, 60%);\n}\n\n.token.url {\n color: hsl(198, 99%, 37%);\n}\n\n/* HTML overrides */\n.token.attr-value > .token.punctuation.attr-equals,\n.token.special-attr > .token.attr-value > .token.value.css {\n color: hsl(230, 8%, 24%);\n}\n\n/* CSS overrides */\n.language-css .token.selector {\n color: hsl(5, 74%, 59%);\n}\n\n.language-css .token.property {\n color: hsl(230, 8%, 24%);\n}\n\n.language-css .token.function,\n.language-css .token.url > .token.function {\n color: hsl(198, 99%, 37%);\n}\n\n.language-css .token.url > .token.string.url {\n color: hsl(119, 34%, 47%);\n}\n\n.language-css .token.important,\n.language-css .token.atrule .token.rule {\n color: hsl(301, 63%, 40%);\n}\n\n/* JS overrides */\n.language-javascript .token.operator {\n color: hsl(301, 63%, 40%);\n}\n\n.language-javascript\n .token.template-string\n > .token.interpolation\n > .token.interpolation-punctuation.punctuation {\n color: hsl(344, 84%, 43%);\n}\n\n/* JSON overrides */\n.language-json .token.operator {\n color: hsl(230, 8%, 24%);\n}\n\n.language-json .token.null.keyword {\n color: hsl(35, 99%, 36%);\n}\n\n/* MD overrides */\n.language-markdown .token.url,\n.language-markdown .token.url > .token.operator,\n.language-markdown .token.url-reference.url > .token.string {\n color: hsl(230, 8%, 24%);\n}\n\n.language-markdown .token.url > .token.content {\n color: hsl(221, 87%, 60%);\n}\n\n.language-markdown .token.url > .token.url,\n.language-markdown .token.url-reference.url {\n color: hsl(198, 99%, 37%);\n}\n\n.language-markdown .token.blockquote.punctuation,\n.language-markdown .token.hr.punctuation {\n color: hsl(230, 4%, 64%);\n font-style: italic;\n}\n\n.language-markdown .token.code-snippet {\n color: hsl(119, 34%, 47%);\n}\n\n.language-markdown .token.bold .token.content {\n color: hsl(35, 99%, 36%);\n}\n\n.language-markdown .token.italic .token.content {\n color: hsl(301, 63%, 40%);\n}\n\n.language-markdown .token.strike .token.content,\n.language-markdown .token.strike .token.punctuation,\n.language-markdown .token.list.punctuation,\n.language-markdown .token.title.important > .token.punctuation {\n color: hsl(5, 74%, 59%);\n}\n\n/* General */\n.token.bold {\n font-weight: bold;\n}\n\n.token.comment,\n.token.italic {\n font-style: italic;\n}\n\n.token.entity {\n cursor: help;\n}\n\n.token.namespace {\n opacity: 0.8;\n}\n\n/* Plugin overrides */\n/* Selectors should have higher specificity than those in the plugins' default stylesheets */\n\n/* Show Invisibles plugin overrides */\n.token.token.tab:not(:empty):before,\n.token.token.cr:before,\n.token.token.lf:before,\n.token.token.space:before {\n color: hsla(230, 8%, 24%, 0.2);\n}\n\n/* Toolbar plugin overrides */\n/* Space out all buttons and move them away from the right edge of the code block */\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item {\n margin-right: 0.4em;\n}\n\n/* Styling the buttons */\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > button,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > a,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > span {\n background: hsl(230, 1%, 90%);\n color: hsl(230, 6%, 44%);\n padding: 0.1em 0.4em;\n border-radius: 0.3em;\n}\n\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover,\ndiv.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus {\n background: hsl(230, 1%, 78%); /* custom: darken(--syntax-bg, 20%) */\n color: hsl(230, 8%, 24%);\n}\n\n/* Line Highlight plugin overrides */\n/* The highlighted line itself */\n.line-highlight.line-highlight {\n background: hsla(230, 8%, 24%, 0.05);\n}\n\n/* Default line numbers in Line Highlight plugin */\n.line-highlight.line-highlight:before,\n.line-highlight.line-highlight[data-end]:after {\n background: hsl(230, 1%, 90%);\n color: hsl(230, 8%, 24%);\n padding: 0.1em 0.6em;\n border-radius: 0.3em;\n box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); /* same as Toolbar plugin default */\n}\n\n/* Hovering over a linkable line number (in the gutter area) */\n/* Requires Line Numbers plugin as well */\npre[id].linkable-line-numbers.linkable-line-numbers\n span.line-numbers-rows\n > span:hover:before {\n background-color: hsla(230, 8%, 24%, 0.05);\n}\n\n/* Line Numbers and Command Line plugins overrides */\n/* Line separating gutter from coding area */\n.line-numbers.line-numbers .line-numbers-rows,\n.command-line .command-line-prompt {\n border-right-color: hsla(230, 8%, 24%, 0.2);\n}\n\n/* Stuff in the gutter */\n.line-numbers .line-numbers-rows > span:before,\n.command-line .command-line-prompt > span:before {\n color: hsl(230, 1%, 62%);\n}\n\n/* Match Braces plugin overrides */\n/* Note: Outline colour is inherited from the braces */\n.rainbow-braces .token.token.punctuation.brace-level-1,\n.rainbow-braces .token.token.punctuation.brace-level-5,\n.rainbow-braces .token.token.punctuation.brace-level-9 {\n color: hsl(5, 74%, 59%);\n}\n\n.rainbow-braces .token.token.punctuation.brace-level-2,\n.rainbow-braces .token.token.punctuation.brace-level-6,\n.rainbow-braces .token.token.punctuation.brace-level-10 {\n color: hsl(119, 34%, 47%);\n}\n\n.rainbow-braces .token.token.punctuation.brace-level-3,\n.rainbow-braces .token.token.punctuation.brace-level-7,\n.rainbow-braces .token.token.punctuation.brace-level-11 {\n color: hsl(221, 87%, 60%);\n}\n\n.rainbow-braces .token.token.punctuation.brace-level-4,\n.rainbow-braces .token.token.punctuation.brace-level-8,\n.rainbow-braces .token.token.punctuation.brace-level-12 {\n color: hsl(301, 63%, 40%);\n}\n\n/* Diff Highlight plugin overrides */\n/* Taken from https://github.com/atom/github/blob/master/styles/variables.less */\npre.diff-highlight > code .token.token.deleted:not(.prefix),\npre > code.diff-highlight .token.token.deleted:not(.prefix) {\n background-color: hsla(353, 100%, 66%, 0.15);\n}\n\npre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection,\npre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection,\npre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection,\npre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection {\n background-color: hsla(353, 95%, 66%, 0.25);\n}\n\npre.diff-highlight > code .token.token.deleted:not(.prefix)::selection,\npre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection,\npre > code.diff-highlight .token.token.deleted:not(.prefix)::selection,\npre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection {\n background-color: hsla(353, 95%, 66%, 0.25);\n}\n\npre.diff-highlight > code .token.token.inserted:not(.prefix),\npre > code.diff-highlight .token.token.inserted:not(.prefix) {\n background-color: hsla(137, 100%, 55%, 0.15);\n}\n\npre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection,\npre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection,\npre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection,\npre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection {\n background-color: hsla(135, 73%, 55%, 0.25);\n}\n\npre.diff-highlight > code .token.token.inserted:not(.prefix)::selection,\npre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection,\npre > code.diff-highlight .token.token.inserted:not(.prefix)::selection,\npre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection {\n background-color: hsla(135, 73%, 55%, 0.25);\n}\n\n/* Previewers plugin overrides */\n/* Based on https://github.com/atom-community/atom-ide-datatip/blob/master/styles/atom-ide-datatips.less and https://github.com/atom/atom/blob/master/packages/one-light-ui */\n/* Border around popup */\n.prism-previewer.prism-previewer:before,\n.prism-previewer-gradient.prism-previewer-gradient div {\n border-color: hsl(0, 0, 95%);\n}\n\n/* Angle and time should remain as circles and are hence not included */\n.prism-previewer-color.prism-previewer-color:before,\n.prism-previewer-gradient.prism-previewer-gradient div,\n.prism-previewer-easing.prism-previewer-easing:before {\n border-radius: 0.3em;\n}\n\n/* Triangles pointing to the code */\n.prism-previewer.prism-previewer:after {\n border-top-color: hsl(0, 0, 95%);\n}\n\n.prism-previewer-flipped.prism-previewer-flipped.after {\n border-bottom-color: hsl(0, 0, 95%);\n}\n\n/* Background colour within the popup */\n.prism-previewer-angle.prism-previewer-angle:before,\n.prism-previewer-time.prism-previewer-time:before,\n.prism-previewer-easing.prism-previewer-easing {\n background: hsl(0, 0%, 100%);\n}\n\n/* For angle, this is the positive area (eg. 90deg will display one quadrant in this colour) */\n/* For time, this is the alternate colour */\n.prism-previewer-angle.prism-previewer-angle circle,\n.prism-previewer-time.prism-previewer-time circle {\n stroke: hsl(230, 8%, 24%);\n stroke-opacity: 1;\n}\n\n/* Stroke colours of the handle, direction point, and vector itself */\n.prism-previewer-easing.prism-previewer-easing circle,\n.prism-previewer-easing.prism-previewer-easing path,\n.prism-previewer-easing.prism-previewer-easing line {\n stroke: hsl(230, 8%, 24%);\n}\n\n/* Fill colour of the handle */\n.prism-previewer-easing.prism-previewer-easing circle {\n fill: transparent;\n}\n" }, { "name": "code-block-combobox.tsx", diff --git a/apps/www/public/registry/styles/default/combobox.json b/apps/www/public/registry/styles/default/combobox.json index f9d8c4f5ca..66fe0f9c87 100644 --- a/apps/www/public/registry/styles/default/combobox.json +++ b/apps/www/public/registry/styles/default/combobox.json @@ -9,7 +9,7 @@ "files": [ { "name": "combobox.tsx", - "content": "'use client';\n\nimport React, { useEffect } from 'react';\nimport * as Popover from '@radix-ui/react-popover';\nimport {\n comboboxActions,\n ComboboxContentItemProps,\n ComboboxContentProps,\n ComboboxProps,\n Data,\n NoData,\n TComboboxItem,\n useActiveComboboxStore,\n useComboboxContent,\n useComboboxContentState,\n useComboboxControls,\n useComboboxItem,\n useComboboxSelectors,\n} from '@udecode/plate-combobox';\nimport {\n useEventEditorSelectors,\n usePlateEditorState,\n} from '@udecode/plate-common';\nimport { createVirtualRef } from '@udecode/plate-floating';\n\nimport { cn } from '@/lib/utils';\n\nexport function ComboboxItem({\n combobox,\n index,\n item,\n onRenderItem,\n}: ComboboxContentItemProps) {\n const { props } = useComboboxItem({ item, index, combobox, onRenderItem });\n\n return (\n \n );\n}\n\nexport function ComboboxContent(\n props: ComboboxContentProps\n) {\n const {\n component: Component,\n items,\n portalElement,\n combobox,\n onRenderItem,\n } = props;\n\n const editor = usePlateEditorState();\n\n const filteredItems =\n useComboboxSelectors.filteredItems() as TComboboxItem[];\n const activeComboboxStore = useActiveComboboxStore()!;\n\n const state = useComboboxContentState({ items, combobox });\n const { menuProps, targetRange } = useComboboxContent(state);\n\n return (\n \n \n\n \n event.preventDefault()}\n >\n {Component ? Component({ store: activeComboboxStore }) : null}\n\n {filteredItems.map((item, index) => (\n \n ))}\n \n \n \n );\n}\n\n/**\n * Register the combobox id, trigger, onSelectItem\n * Renders the combobox if active.\n */\nexport function Combobox({\n id,\n trigger,\n searchPattern,\n onSelectItem,\n controlled,\n maxSuggestions,\n filter,\n sort,\n disabled: _disabled,\n ...props\n}: ComboboxProps) {\n const storeItems = useComboboxSelectors.items();\n const disabled =\n _disabled ?? (storeItems.length === 0 && !props.items?.length);\n\n const focusedEditorId = useEventEditorSelectors.focus?.();\n const combobox = useComboboxControls();\n const activeId = useComboboxSelectors.activeId();\n const editor = usePlateEditorState();\n\n useEffect(() => {\n comboboxActions.setComboboxById({\n id,\n trigger,\n searchPattern,\n controlled,\n onSelectItem,\n maxSuggestions,\n filter,\n sort,\n });\n }, [\n id,\n trigger,\n searchPattern,\n controlled,\n onSelectItem,\n maxSuggestions,\n filter,\n sort,\n ]);\n\n if (\n !combobox ||\n !editor.selection ||\n focusedEditorId !== editor.id ||\n activeId !== id ||\n disabled\n ) {\n return null;\n }\n\n return ;\n}\n" + "content": "'use client';\n\nimport React, { useEffect } from 'react';\nimport * as Popover from '@radix-ui/react-popover';\nimport {\n comboboxActions,\n ComboboxContentItemProps,\n ComboboxContentProps,\n ComboboxProps,\n Data,\n NoData,\n TComboboxItem,\n useActiveComboboxStore,\n useComboboxContent,\n useComboboxContentState,\n useComboboxControls,\n useComboboxItem,\n useComboboxSelectors,\n} from '@udecode/plate-combobox';\nimport { useEditorState, useEventEditorSelectors } from '@udecode/plate-common';\nimport { createVirtualRef } from '@udecode/plate-floating';\n\nimport { cn } from '@/lib/utils';\n\nexport function ComboboxItem({\n combobox,\n index,\n item,\n onRenderItem,\n}: ComboboxContentItemProps) {\n const { props } = useComboboxItem({ item, index, combobox, onRenderItem });\n\n return (\n \n );\n}\n\nexport function ComboboxContent(\n props: ComboboxContentProps\n) {\n const {\n component: Component,\n items,\n portalElement,\n combobox,\n onRenderItem,\n } = props;\n\n const editor = useEditorState();\n\n const filteredItems =\n useComboboxSelectors.filteredItems() as TComboboxItem[];\n const activeComboboxStore = useActiveComboboxStore()!;\n\n const state = useComboboxContentState({ items, combobox });\n const { menuProps, targetRange } = useComboboxContent(state);\n\n return (\n \n \n\n \n event.preventDefault()}\n >\n {Component ? Component({ store: activeComboboxStore }) : null}\n\n {filteredItems.map((item, index) => (\n \n ))}\n \n \n \n );\n}\n\n/**\n * Register the combobox id, trigger, onSelectItem\n * Renders the combobox if active.\n */\nexport function Combobox({\n id,\n trigger,\n searchPattern,\n onSelectItem,\n controlled,\n maxSuggestions,\n filter,\n sort,\n disabled: _disabled,\n ...props\n}: ComboboxProps) {\n const storeItems = useComboboxSelectors.items();\n const disabled =\n _disabled ?? (storeItems.length === 0 && !props.items?.length);\n\n const focusedEditorId = useEventEditorSelectors.focus?.();\n const combobox = useComboboxControls();\n const activeId = useComboboxSelectors.activeId();\n const editor = useEditorState();\n\n useEffect(() => {\n comboboxActions.setComboboxById({\n id,\n trigger,\n searchPattern,\n controlled,\n onSelectItem,\n maxSuggestions,\n filter,\n sort,\n });\n }, [\n id,\n trigger,\n searchPattern,\n controlled,\n onSelectItem,\n maxSuggestions,\n filter,\n sort,\n ]);\n\n if (\n !combobox ||\n !editor.selection ||\n focusedEditorId !== editor.id ||\n activeId !== id ||\n disabled\n ) {\n return null;\n }\n\n return ;\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/comment-leaf.json b/apps/www/public/registry/styles/default/comment-leaf.json index 6f02099174..b39184e1ba 100644 --- a/apps/www/public/registry/styles/default/comment-leaf.json +++ b/apps/www/public/registry/styles/default/comment-leaf.json @@ -7,7 +7,7 @@ "files": [ { "name": "comment-leaf.tsx", - "content": "'use client';\n\nimport React from 'react';\nimport {\n TCommentText,\n useCommentLeaf,\n useCommentLeafState,\n} from '@udecode/plate-comments';\nimport { PlateLeaf, PlateLeafProps, Value } from '@udecode/plate-common';\n\nexport function CommentLeaf({\n className,\n ...props\n}: PlateLeafProps) {\n const { children, nodeProps, leaf } = props;\n\n const state = useCommentLeafState({ leaf });\n const { props: rootProps } = useCommentLeaf(state);\n\n // hide resolved comments\n if (!state.commentCount) return <>{children};\n\n let aboveChildren = <>{children};\n\n const backgroundColor = state.isActive\n ? 'rgb(255, 212, 0)'\n : 'rgba(255, 212, 0, 0.14)';\n\n if (!state.isActive) {\n for (let i = 1; i < state.commentCount; i++) {\n aboveChildren = (\n \n {aboveChildren}\n \n );\n }\n }\n\n return (\n \n {aboveChildren}\n \n );\n}\n" + "content": "'use client';\n\nimport React from 'react';\nimport {\n TCommentText,\n useCommentLeaf,\n useCommentLeafState,\n} from '@udecode/plate-comments';\nimport { PlateLeaf, PlateLeafProps, Value } from '@udecode/plate-common';\n\nimport { cn } from '@/lib/utils';\n\nexport function CommentLeaf({\n className,\n ...props\n}: PlateLeafProps) {\n const { children, nodeProps, leaf } = props;\n\n const state = useCommentLeafState({ leaf });\n const { props: rootProps } = useCommentLeaf(state);\n\n // hide resolved comments\n if (!state.commentCount) return <>{children};\n\n let aboveChildren = <>{children};\n\n if (!state.isActive) {\n for (let i = 1; i < state.commentCount; i++) {\n aboveChildren = {aboveChildren};\n }\n }\n\n return (\n \n {aboveChildren}\n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/editor.json b/apps/www/public/registry/styles/default/editor.json new file mode 100644 index 0000000000..6b0409a576 --- /dev/null +++ b/apps/www/public/registry/styles/default/editor.json @@ -0,0 +1,12 @@ +{ + "name": "editor", + "dependencies": [], + "registryDependencies": [], + "files": [ + { + "name": "editor.tsx", + "content": "import React from 'react';\nimport { PlateContent } from '@udecode/plate-common';\nimport { cva } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nimport type { PlateContentProps } from '@udecode/plate-common';\nimport type { VariantProps } from 'class-variance-authority';\n\nconst editorVariants = cva(\n cn(\n 'relative overflow-x-auto whitespace-pre-wrap break-words',\n 'min-h-[80px] w-full rounded-md bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none',\n '[&_[data-slate-placeholder]]:text-muted-foreground [&_[data-slate-placeholder]]:!opacity-100',\n '[&_[data-slate-placeholder]]:top-[auto_!important]',\n '[&_strong]:font-bold'\n ),\n {\n variants: {\n variant: {\n outline: 'border border-input',\n ghost: '',\n },\n focused: {\n true: 'ring-2 ring-ring ring-offset-2',\n },\n disabled: {\n true: 'cursor-not-allowed opacity-50',\n },\n focusRing: {\n true: 'focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n false: '',\n },\n size: {\n sm: 'text-sm',\n md: 'text-base',\n },\n },\n defaultVariants: {\n variant: 'outline',\n focusRing: true,\n size: 'sm',\n },\n }\n);\n\nexport type EditorProps = PlateContentProps &\n VariantProps;\n\nconst Editor = React.forwardRef(\n (\n {\n className,\n disabled,\n focused,\n focusRing,\n readOnly,\n size,\n variant,\n ...props\n },\n ref\n ) => {\n return (\n
\n \n
\n );\n }\n);\nEditor.displayName = 'Editor';\n\nexport { Editor };\n" + } + ], + "type": "components:plate-ui" +} \ No newline at end of file diff --git a/apps/www/public/registry/styles/default/emoji-combobox.json b/apps/www/public/registry/styles/default/emoji-combobox.json index 09b2a4e29e..7c848cd6cd 100644 --- a/apps/www/public/registry/styles/default/emoji-combobox.json +++ b/apps/www/public/registry/styles/default/emoji-combobox.json @@ -7,7 +7,7 @@ "files": [ { "name": "emoji-combobox.tsx", - "content": "import React from 'react';\nimport { ComboboxItemProps } from '@udecode/plate-combobox';\nimport {\n EmojiItemData,\n KEY_EMOJI,\n TEmojiCombobox,\n useEmojiComboboxState,\n} from '@udecode/plate-emoji';\n\nimport { Combobox } from './combobox';\n\nexport function EmojiComboboxItem({\n item,\n}: ComboboxItemProps): JSX.Element {\n const {\n data: { id, emoji },\n } = item;\n\n return (\n
\n {emoji} :{id}:\n
\n );\n}\n\nexport function EmojiCombobox({\n pluginKey = KEY_EMOJI,\n id = pluginKey,\n ...props\n}: TEmojiCombobox) {\n const { trigger, onSelectItem } = useEmojiComboboxState({ pluginKey });\n\n return (\n \n );\n}\n" + "content": "import React from 'react';\nimport { ComboboxItemProps } from '@udecode/plate-combobox';\nimport {\n EmojiItemData,\n KEY_EMOJI,\n TEmojiCombobox,\n useEmojiComboboxState,\n} from '@udecode/plate-emoji';\n\nimport { Combobox } from './combobox';\n\nexport function EmojiComboboxItem({ item }: ComboboxItemProps) {\n const {\n data: { id, emoji },\n } = item;\n\n return (\n
\n {emoji} :{id}:\n
\n );\n}\n\nexport function EmojiCombobox({\n pluginKey = KEY_EMOJI,\n id = pluginKey,\n ...props\n}: TEmojiCombobox) {\n const { trigger, onSelectItem } = useEmojiComboboxState({ pluginKey });\n\n return (\n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/emoji-dropdown-menu.json b/apps/www/public/registry/styles/default/emoji-dropdown-menu.json index 8b761e78ff..8eb64526ce 100644 --- a/apps/www/public/registry/styles/default/emoji-dropdown-menu.json +++ b/apps/www/public/registry/styles/default/emoji-dropdown-menu.json @@ -17,7 +17,7 @@ }, { "name": "emoji-icons.tsx", - "content": "import React from 'react';\nimport { EmojiCategoryList } from '@udecode/plate-emoji';\n\nexport const emojiCategoryIcons: Record<\n EmojiCategoryList,\n { outline: JSX.Element; solid: JSX.Element }\n> = {\n activity: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n custom: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n flags: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n foods: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n frequent: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n nature: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n objects: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n people: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n places: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n symbols: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n};\n\nexport const emojiSearchIcons = {\n loupe: (\n \n \n \n ),\n\n delete: (\n \n \n \n ),\n};\n" + "content": "import React from 'react';\nimport { EmojiCategoryList } from '@udecode/plate-emoji';\n\nexport const emojiCategoryIcons: Record<\n EmojiCategoryList,\n { outline: React.ReactElement; solid: React.ReactElement }\n> = {\n activity: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n custom: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n flags: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n foods: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n frequent: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n nature: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n objects: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n people: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n places: {\n outline: (\n \n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n\n symbols: {\n outline: (\n \n \n \n ),\n solid: (\n \n \n \n ),\n },\n};\n\nexport const emojiSearchIcons = {\n loupe: (\n \n \n \n ),\n\n delete: (\n \n \n \n ),\n};\n" }, { "name": "emoji-picker.tsx", diff --git a/apps/www/public/registry/styles/default/fixed-toolbar-buttons.json b/apps/www/public/registry/styles/default/fixed-toolbar-buttons.json index dbbf89274e..2cd9635aa8 100644 --- a/apps/www/public/registry/styles/default/fixed-toolbar-buttons.json +++ b/apps/www/public/registry/styles/default/fixed-toolbar-buttons.json @@ -13,7 +13,7 @@ "files": [ { "name": "fixed-toolbar-buttons.tsx", - "content": "import React from 'react';\nimport {\n MARK_BOLD,\n MARK_CODE,\n MARK_ITALIC,\n MARK_STRIKETHROUGH,\n MARK_UNDERLINE,\n} from '@udecode/plate-basic-marks';\nimport { usePlateReadOnly } from '@udecode/plate-common';\n\nimport { Icons } from '@/components/icons';\n\nimport { InsertDropdownMenu } from './insert-dropdown-menu';\nimport { MarkToolbarButton } from './mark-toolbar-button';\nimport { ModeDropdownMenu } from './mode-dropdown-menu';\nimport { ToolbarGroup } from './toolbar';\nimport { TurnIntoDropdownMenu } from './turn-into-dropdown-menu';\n\nexport function FixedToolbarButtons() {\n const readOnly = usePlateReadOnly();\n\n return (\n
\n \n {!readOnly && (\n <>\n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n )}\n\n
\n\n \n \n \n
\n
\n );\n}\n" + "content": "import React from 'react';\nimport {\n MARK_BOLD,\n MARK_CODE,\n MARK_ITALIC,\n MARK_STRIKETHROUGH,\n MARK_UNDERLINE,\n} from '@udecode/plate-basic-marks';\nimport { useEditorReadOnly } from '@udecode/plate-common';\n\nimport { Icons } from '@/components/icons';\n\nimport { InsertDropdownMenu } from './insert-dropdown-menu';\nimport { MarkToolbarButton } from './mark-toolbar-button';\nimport { ModeDropdownMenu } from './mode-dropdown-menu';\nimport { ToolbarGroup } from './toolbar';\nimport { TurnIntoDropdownMenu } from './turn-into-dropdown-menu';\n\nexport function FixedToolbarButtons() {\n const readOnly = useEditorReadOnly();\n\n return (\n
\n \n {!readOnly && (\n <>\n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n )}\n\n
\n\n \n \n \n
\n
\n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/floating-toolbar-buttons.json b/apps/www/public/registry/styles/default/floating-toolbar-buttons.json index 636ee90bd1..b7b8ad653f 100644 --- a/apps/www/public/registry/styles/default/floating-toolbar-buttons.json +++ b/apps/www/public/registry/styles/default/floating-toolbar-buttons.json @@ -11,7 +11,7 @@ "files": [ { "name": "floating-toolbar-buttons.tsx", - "content": "import React from 'react';\nimport {\n MARK_BOLD,\n MARK_CODE,\n MARK_ITALIC,\n MARK_STRIKETHROUGH,\n MARK_UNDERLINE,\n} from '@udecode/plate-basic-marks';\nimport { usePlateReadOnly } from '@udecode/plate-common';\n\nimport { Icons } from '@/components/icons';\n\nimport { MarkToolbarButton } from './mark-toolbar-button';\nimport { MoreDropdownMenu } from './more-dropdown-menu';\nimport { TurnIntoDropdownMenu } from './turn-into-dropdown-menu';\n\nexport function FloatingToolbarButtons() {\n const readOnly = usePlateReadOnly();\n\n return (\n <>\n {!readOnly && (\n <>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n )}\n\n \n \n );\n}\n" + "content": "import React from 'react';\nimport {\n MARK_BOLD,\n MARK_CODE,\n MARK_ITALIC,\n MARK_STRIKETHROUGH,\n MARK_UNDERLINE,\n} from '@udecode/plate-basic-marks';\nimport { useEditorReadOnly } from '@udecode/plate-common';\n\nimport { Icons } from '@/components/icons';\n\nimport { MarkToolbarButton } from './mark-toolbar-button';\nimport { MoreDropdownMenu } from './more-dropdown-menu';\nimport { TurnIntoDropdownMenu } from './turn-into-dropdown-menu';\n\nexport function FloatingToolbarButtons() {\n const readOnly = useEditorReadOnly();\n\n return (\n <>\n {!readOnly && (\n <>\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n )}\n\n \n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/floating-toolbar.json b/apps/www/public/registry/styles/default/floating-toolbar.json index 03c228ba24..601c13530a 100644 --- a/apps/www/public/registry/styles/default/floating-toolbar.json +++ b/apps/www/public/registry/styles/default/floating-toolbar.json @@ -9,7 +9,7 @@ "files": [ { "name": "floating-toolbar.tsx", - "content": "import React from 'react';\nimport { flip, offset } from '@floating-ui/react';\nimport { PortalBody, useComposedRef } from '@udecode/plate-common';\nimport {\n useFloatingToolbar,\n useFloatingToolbarState,\n} from '@udecode/plate-floating';\nimport { FloatingToolbarState } from '@udecode/plate-floating/dist';\n\nimport { cn } from '@/lib/utils';\n\nimport { Toolbar, ToolbarProps } from './toolbar';\n\nexport interface FloatingToolbarProps extends ToolbarProps {\n state?: FloatingToolbarState;\n}\n\nconst FloatingToolbar = React.forwardRef<\n React.ElementRef,\n FloatingToolbarProps\n>(({ state, children, ...props }, componentRef) => {\n const floatingToolbarState = useFloatingToolbarState({\n ...state,\n floatingOptions: {\n placement: 'top',\n middleware: [\n offset(12),\n flip({\n padding: 12,\n fallbackPlacements: [\n 'top-start',\n 'top-end',\n 'bottom-start',\n 'bottom-end',\n ],\n }),\n ],\n ...state?.floatingOptions,\n },\n });\n\n const {\n ref: floatingRef,\n props: rootProps,\n hidden,\n } = useFloatingToolbar(floatingToolbarState);\n\n const ref = useComposedRef(componentRef, floatingRef);\n\n if (hidden) return null;\n\n return (\n \n \n {children}\n \n \n );\n});\nFloatingToolbar.displayName = 'FloatingToolbar';\n\nexport { FloatingToolbar };\n" + "content": "'use client';\n\nimport React from 'react';\nimport { PortalBody, useComposedRef } from '@udecode/plate-common';\nimport {\n flip,\n FloatingToolbarState,\n offset,\n useFloatingToolbar,\n useFloatingToolbarState,\n} from '@udecode/plate-floating';\n\nimport { cn } from '@/lib/utils';\n\nimport { Toolbar, ToolbarProps } from './toolbar';\n\nexport interface FloatingToolbarProps extends ToolbarProps {\n state?: FloatingToolbarState;\n}\n\nconst FloatingToolbar = React.forwardRef<\n React.ElementRef,\n FloatingToolbarProps\n>(({ state, children, ...props }, componentRef) => {\n const floatingToolbarState = useFloatingToolbarState({\n ...state,\n floatingOptions: {\n placement: 'top',\n middleware: [\n offset(12),\n flip({\n padding: 12,\n fallbackPlacements: [\n 'top-start',\n 'top-end',\n 'bottom-start',\n 'bottom-end',\n ],\n }),\n ],\n ...state?.floatingOptions,\n },\n });\n\n const {\n ref: floatingRef,\n props: rootProps,\n hidden,\n } = useFloatingToolbar(floatingToolbarState);\n\n const ref = useComposedRef(componentRef, floatingRef);\n\n if (hidden) return null;\n\n return (\n \n \n {children}\n \n \n );\n});\nFloatingToolbar.displayName = 'FloatingToolbar';\n\nexport { FloatingToolbar };\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/highlight-leaf.json b/apps/www/public/registry/styles/default/highlight-leaf.json index 643b1fbd97..a17015d91e 100644 --- a/apps/www/public/registry/styles/default/highlight-leaf.json +++ b/apps/www/public/registry/styles/default/highlight-leaf.json @@ -7,7 +7,7 @@ "files": [ { "name": "highlight-leaf.tsx", - "content": "import React from 'react';\nimport { PlateLeaf, PlateLeafProps } from '@udecode/plate-common';\n\nimport { cn } from '@/lib/utils';\n\nexport function HighlightLeaf({\n className,\n children,\n ...props\n}: PlateLeafProps) {\n return (\n \n {children}\n \n );\n}\n" + "content": "import React from 'react';\nimport { PlateLeaf, PlateLeafProps } from '@udecode/plate-common';\n\nimport { cn } from '@/lib/utils';\n\nexport function HighlightLeaf({\n className,\n children,\n ...props\n}: PlateLeafProps) {\n return (\n \n {children}\n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/insert-dropdown-menu.json b/apps/www/public/registry/styles/default/insert-dropdown-menu.json index d540f96330..7c78b9cdac 100644 --- a/apps/www/public/registry/styles/default/insert-dropdown-menu.json +++ b/apps/www/public/registry/styles/default/insert-dropdown-menu.json @@ -12,7 +12,7 @@ "files": [ { "name": "insert-dropdown-menu.tsx", - "content": "'use client';\n\nimport React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport { ELEMENT_BLOCKQUOTE } from '@udecode/plate-block-quote';\nimport {\n focusEditor,\n insertEmptyElement,\n usePlateEditorState,\n} from '@udecode/plate-common';\nimport { ELEMENT_H1, ELEMENT_H2, ELEMENT_H3 } from '@udecode/plate-heading';\nimport { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nconst items = [\n {\n label: 'Basic blocks',\n items: [\n {\n value: ELEMENT_PARAGRAPH,\n label: 'Paragraph',\n description: 'Paragraph',\n icon: Icons.paragraph,\n },\n {\n value: ELEMENT_H1,\n label: 'Heading 1',\n description: 'Heading 1',\n icon: Icons.h1,\n },\n {\n value: ELEMENT_H2,\n label: 'Heading 2',\n description: 'Heading 2',\n icon: Icons.h2,\n },\n {\n value: ELEMENT_H3,\n label: 'Heading 3',\n description: 'Heading 3',\n icon: Icons.h3,\n },\n {\n value: ELEMENT_BLOCKQUOTE,\n label: 'Quote',\n description: 'Quote (⌘+⇧+.)',\n icon: Icons.blockquote,\n },\n // {\n // value: ELEMENT_TABLE,\n // label: 'Table',\n // description: 'Table',\n // icon: Icons.table,\n // },\n // {\n // value: 'ul',\n // label: 'Bulleted list',\n // description: 'Bulleted list',\n // icon: Icons.ul,\n // },\n // {\n // value: 'ol',\n // label: 'Numbered list',\n // description: 'Numbered list',\n // icon: Icons.ol,\n // },\n // {\n // value: ELEMENT_HR,\n // label: 'Divider',\n // description: 'Divider (---)',\n // icon: Icons.hr,\n // },\n ],\n },\n // {\n // label: 'Media',\n // items: [\n // {\n // value: ELEMENT_CODE_BLOCK,\n // label: 'Code',\n // description: 'Code (```)',\n // icon: Icons.codeblock,\n // },\n // {\n // value: ELEMENT_IMAGE,\n // label: 'Image',\n // description: 'Image',\n // icon: Icons.image,\n // },\n // {\n // value: ELEMENT_MEDIA_EMBED,\n // label: 'Embed',\n // description: 'Embed',\n // icon: Icons.embed,\n // },\n // {\n // value: ELEMENT_EXCALIDRAW,\n // label: 'Excalidraw',\n // description: 'Excalidraw',\n // icon: Icons.excalidraw,\n // },\n // ],\n // },\n // {\n // label: 'Inline',\n // items: [\n // {\n // value: ELEMENT_LINK,\n // label: 'Link',\n // description: 'Link',\n // icon: Icons.link,\n // },\n // ],\n // },\n];\n\nexport function InsertDropdownMenu(props: DropdownMenuProps) {\n const editor = usePlateEditorState();\n const openState = useOpenState();\n\n return (\n \n \n \n \n \n \n\n \n {items.map(({ items: nestedItems, label }, index) => (\n \n {index !== 0 && }\n\n {label}\n {nestedItems.map(\n ({ value: type, label: itemLabel, icon: Icon }) => (\n {\n switch (type) {\n // case ELEMENT_CODE_BLOCK: {\n // insertEmptyCodeBlock(editor);\n //\n // break;\n // }\n // case ELEMENT_IMAGE: {\n // await insertMedia(editor, { type: ELEMENT_IMAGE });\n //\n // break;\n // }\n // case ELEMENT_MEDIA_EMBED: {\n // await insertMedia(editor, {\n // type: ELEMENT_MEDIA_EMBED,\n // });\n //\n // break;\n // }\n // case 'ul':\n // case 'ol': {\n // insertEmptyElement(editor, ELEMENT_PARAGRAPH, {\n // select: true,\n // nextBlock: true,\n // });\n //\n // if (settingsStore.get.checkedId(KEY_LIST_STYLE_TYPE)) {\n // toggleIndentList(editor, {\n // listStyleType: type === 'ul' ? 'disc' : 'decimal',\n // });\n // } else if (settingsStore.get.checkedId('list')) {\n // toggleList(editor, { type });\n // }\n //\n // break;\n // }\n // case ELEMENT_TABLE: {\n // insertTable(editor);\n //\n // break;\n // }\n // case ELEMENT_LINK: {\n // triggerFloatingLink(editor, { focused: true });\n //\n // break;\n // }\n default: {\n insertEmptyElement(editor, type, {\n select: true,\n nextBlock: true,\n });\n }\n }\n\n focusEditor(editor);\n }}\n >\n \n {itemLabel}\n \n )\n )}\n \n ))}\n \n \n );\n}\n" + "content": "'use client';\n\nimport React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport { ELEMENT_BLOCKQUOTE } from '@udecode/plate-block-quote';\nimport {\n focusEditor,\n insertEmptyElement,\n useEditorState,\n} from '@udecode/plate-common';\nimport { ELEMENT_H1, ELEMENT_H2, ELEMENT_H3 } from '@udecode/plate-heading';\nimport { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nconst items = [\n {\n label: 'Basic blocks',\n items: [\n {\n value: ELEMENT_PARAGRAPH,\n label: 'Paragraph',\n description: 'Paragraph',\n icon: Icons.paragraph,\n },\n {\n value: ELEMENT_H1,\n label: 'Heading 1',\n description: 'Heading 1',\n icon: Icons.h1,\n },\n {\n value: ELEMENT_H2,\n label: 'Heading 2',\n description: 'Heading 2',\n icon: Icons.h2,\n },\n {\n value: ELEMENT_H3,\n label: 'Heading 3',\n description: 'Heading 3',\n icon: Icons.h3,\n },\n {\n value: ELEMENT_BLOCKQUOTE,\n label: 'Quote',\n description: 'Quote (⌘+⇧+.)',\n icon: Icons.blockquote,\n },\n // {\n // value: ELEMENT_TABLE,\n // label: 'Table',\n // description: 'Table',\n // icon: Icons.table,\n // },\n // {\n // value: 'ul',\n // label: 'Bulleted list',\n // description: 'Bulleted list',\n // icon: Icons.ul,\n // },\n // {\n // value: 'ol',\n // label: 'Numbered list',\n // description: 'Numbered list',\n // icon: Icons.ol,\n // },\n // {\n // value: ELEMENT_HR,\n // label: 'Divider',\n // description: 'Divider (---)',\n // icon: Icons.hr,\n // },\n ],\n },\n // {\n // label: 'Media',\n // items: [\n // {\n // value: ELEMENT_CODE_BLOCK,\n // label: 'Code',\n // description: 'Code (```)',\n // icon: Icons.codeblock,\n // },\n // {\n // value: ELEMENT_IMAGE,\n // label: 'Image',\n // description: 'Image',\n // icon: Icons.image,\n // },\n // {\n // value: ELEMENT_MEDIA_EMBED,\n // label: 'Embed',\n // description: 'Embed',\n // icon: Icons.embed,\n // },\n // {\n // value: ELEMENT_EXCALIDRAW,\n // label: 'Excalidraw',\n // description: 'Excalidraw',\n // icon: Icons.excalidraw,\n // },\n // ],\n // },\n // {\n // label: 'Inline',\n // items: [\n // {\n // value: ELEMENT_LINK,\n // label: 'Link',\n // description: 'Link',\n // icon: Icons.link,\n // },\n // ],\n // },\n];\n\nexport function InsertDropdownMenu(props: DropdownMenuProps) {\n const editor = useEditorState();\n const openState = useOpenState();\n\n return (\n \n \n \n \n \n \n\n \n {items.map(({ items: nestedItems, label }, index) => (\n \n {index !== 0 && }\n\n {label}\n {nestedItems.map(\n ({ value: type, label: itemLabel, icon: Icon }) => (\n {\n switch (type) {\n // case ELEMENT_CODE_BLOCK: {\n // insertEmptyCodeBlock(editor);\n //\n // break;\n // }\n // case ELEMENT_IMAGE: {\n // await insertMedia(editor, { type: ELEMENT_IMAGE });\n //\n // break;\n // }\n // case ELEMENT_MEDIA_EMBED: {\n // await insertMedia(editor, {\n // type: ELEMENT_MEDIA_EMBED,\n // });\n //\n // break;\n // }\n // case 'ul':\n // case 'ol': {\n // insertEmptyElement(editor, ELEMENT_PARAGRAPH, {\n // select: true,\n // nextBlock: true,\n // });\n //\n // if (settingsStore.get.checkedId(KEY_LIST_STYLE_TYPE)) {\n // toggleIndentList(editor, {\n // listStyleType: type === 'ul' ? 'disc' : 'decimal',\n // });\n // } else if (settingsStore.get.checkedId('list')) {\n // toggleList(editor, { type });\n // }\n //\n // break;\n // }\n // case ELEMENT_TABLE: {\n // insertTable(editor);\n //\n // break;\n // }\n // case ELEMENT_LINK: {\n // triggerFloatingLink(editor, { focused: true });\n //\n // break;\n // }\n default: {\n insertEmptyElement(editor, type, {\n select: true,\n nextBlock: true,\n });\n }\n }\n\n focusEditor(editor);\n }}\n >\n \n {itemLabel}\n \n )\n )}\n \n ))}\n \n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/link-element.json b/apps/www/public/registry/styles/default/link-element.json index 1c21907eb8..b9ee37fd80 100644 --- a/apps/www/public/registry/styles/default/link-element.json +++ b/apps/www/public/registry/styles/default/link-element.json @@ -7,7 +7,7 @@ "files": [ { "name": "link-element.tsx", - "content": "import React from 'react';\nimport { PlateElement, PlateElementProps, Value } from '@udecode/plate-common';\nimport { TLinkElement, useLink } from '@udecode/plate-link';\n\nimport { cn } from '@/lib/utils';\n\nconst LinkElement = React.forwardRef<\n React.ElementRef,\n PlateElementProps\n>(({ className, children, ...props }, ref) => {\n const { props: linkProps } = useLink({ element: props.element });\n\n return (\n \n {children}\n \n );\n});\nLinkElement.displayName = 'LinkElement';\n\nexport { LinkElement };\n" + "content": "import React from 'react';\nimport { PlateElement, PlateElementProps, Value } from '@udecode/plate-common';\nimport { TLinkElement, useLink } from '@udecode/plate-link';\n\nimport { cn } from '@/lib/utils';\n\nconst LinkElement = React.forwardRef<\n React.ElementRef,\n PlateElementProps\n>(({ className, children, ...props }, ref) => {\n const { props: linkProps } = useLink({ element: props.element });\n\n return (\n \n {children}\n \n );\n});\nLinkElement.displayName = 'LinkElement';\n\nexport { LinkElement };\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/link-floating-toolbar.json b/apps/www/public/registry/styles/default/link-floating-toolbar.json index 748a96ee0e..a140212ac0 100644 --- a/apps/www/public/registry/styles/default/link-floating-toolbar.json +++ b/apps/www/public/registry/styles/default/link-floating-toolbar.json @@ -12,7 +12,7 @@ "files": [ { "name": "link-floating-toolbar.tsx", - "content": "import React from 'react';\nimport {\n flip,\n offset,\n UseVirtualFloatingOptions,\n} from '@udecode/plate-floating';\nimport {\n FloatingLinkUrlInput,\n LinkFloatingToolbarState,\n LinkOpenButton,\n useFloatingLinkEdit,\n useFloatingLinkEditState,\n useFloatingLinkInsert,\n useFloatingLinkInsertState,\n} from '@udecode/plate-link';\n\nimport { cn } from '@/lib/utils';\nimport { Icons } from '@/components/icons';\n\nimport { buttonVariants } from './button';\nimport { inputVariants } from './input';\nimport { popoverVariants } from './popover';\nimport { Separator } from './separator';\n\nconst floatingOptions: UseVirtualFloatingOptions = {\n placement: 'bottom-start',\n middleware: [\n offset(12),\n flip({\n padding: 12,\n fallbackPlacements: ['bottom-end', 'top-start', 'top-end'],\n }),\n ],\n};\n\nexport interface LinkFloatingToolbarProps {\n state?: LinkFloatingToolbarState;\n}\n\nexport function LinkFloatingToolbar({ state }: LinkFloatingToolbarProps) {\n const insertState = useFloatingLinkInsertState({\n ...state,\n floatingOptions: {\n ...floatingOptions,\n ...state?.floatingOptions,\n },\n });\n const {\n props: insertProps,\n ref: insertRef,\n hidden,\n textInputProps,\n } = useFloatingLinkInsert(insertState);\n\n const editState = useFloatingLinkEditState({\n ...state,\n floatingOptions: {\n ...floatingOptions,\n ...state?.floatingOptions,\n },\n });\n const {\n props: editProps,\n ref: editRef,\n editButtonProps,\n unlinkButtonProps,\n } = useFloatingLinkEdit(editState);\n\n if (hidden) return null;\n\n const input = (\n
\n
\n
\n \n
\n\n \n
\n\n \n\n
\n
\n \n
\n \n
\n
\n );\n\n const editContent = editState.isEditing ? (\n input\n ) : (\n
\n \n Edit link\n \n\n \n\n \n \n \n\n \n\n \n \n \n
\n );\n\n return (\n <>\n \n {input}\n
\n\n \n {editContent}\n \n \n );\n}\n" + "content": "'use client';\n\nimport React from 'react';\nimport {\n flip,\n offset,\n UseVirtualFloatingOptions,\n} from '@udecode/plate-floating';\nimport {\n FloatingLinkUrlInput,\n LinkFloatingToolbarState,\n LinkOpenButton,\n useFloatingLinkEdit,\n useFloatingLinkEditState,\n useFloatingLinkInsert,\n useFloatingLinkInsertState,\n} from '@udecode/plate-link';\n\nimport { cn } from '@/lib/utils';\nimport { Icons } from '@/components/icons';\n\nimport { buttonVariants } from './button';\nimport { inputVariants } from './input';\nimport { popoverVariants } from './popover';\nimport { Separator } from './separator';\n\nconst floatingOptions: UseVirtualFloatingOptions = {\n placement: 'bottom-start',\n middleware: [\n offset(12),\n flip({\n padding: 12,\n fallbackPlacements: ['bottom-end', 'top-start', 'top-end'],\n }),\n ],\n};\n\nexport interface LinkFloatingToolbarProps {\n state?: LinkFloatingToolbarState;\n}\n\nexport function LinkFloatingToolbar({ state }: LinkFloatingToolbarProps) {\n const insertState = useFloatingLinkInsertState({\n ...state,\n floatingOptions: {\n ...floatingOptions,\n ...state?.floatingOptions,\n },\n });\n const {\n props: insertProps,\n ref: insertRef,\n hidden,\n textInputProps,\n } = useFloatingLinkInsert(insertState);\n\n const editState = useFloatingLinkEditState({\n ...state,\n floatingOptions: {\n ...floatingOptions,\n ...state?.floatingOptions,\n },\n });\n const {\n props: editProps,\n ref: editRef,\n editButtonProps,\n unlinkButtonProps,\n } = useFloatingLinkEdit(editState);\n\n if (hidden) return null;\n\n const input = (\n
\n
\n
\n \n
\n\n \n
\n\n \n\n
\n
\n \n
\n \n
\n
\n );\n\n const editContent = editState.isEditing ? (\n input\n ) : (\n
\n \n Edit link\n \n\n \n\n \n \n \n\n \n\n \n \n \n
\n );\n\n return (\n <>\n \n {input}\n \n\n \n {editContent}\n \n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/media-popover.json b/apps/www/public/registry/styles/default/media-popover.json index 4558855ba9..f44b36a19c 100644 --- a/apps/www/public/registry/styles/default/media-popover.json +++ b/apps/www/public/registry/styles/default/media-popover.json @@ -12,7 +12,7 @@ "files": [ { "name": "media-popover.tsx", - "content": "import React, { useEffect } from 'react';\nimport {\n isCollapsed,\n useElement,\n usePlateEditorState,\n useRemoveNodeButton,\n} from '@udecode/plate-common';\nimport {\n floatingMediaActions,\n FloatingMedia as FloatingMediaPrimitive,\n useFloatingMediaSelectors,\n} from '@udecode/plate-media';\nimport { useReadOnly, useSelected } from 'slate-react';\n\nimport { Icons } from '@/components/icons';\n\nimport { Button, buttonVariants } from './button';\nimport { inputVariants } from './input';\nimport { Popover, PopoverAnchor, PopoverContent } from './popover';\nimport { Separator } from './separator';\n\nexport interface MediaPopoverProps {\n pluginKey?: string;\n children: React.ReactNode;\n}\n\nexport function MediaPopover({ pluginKey, children }: MediaPopoverProps) {\n const readOnly = useReadOnly();\n const selected = useSelected();\n const editor = usePlateEditorState();\n\n const isOpen = !readOnly && selected && isCollapsed(editor.selection);\n const isEditing = useFloatingMediaSelectors().isEditing();\n\n useEffect(() => {\n if (!isOpen && isEditing) {\n floatingMediaActions.isEditing(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n const element = useElement();\n const { props: buttonProps } = useRemoveNodeButton({ element });\n\n if (readOnly) return <>{children};\n\n return (\n \n {children}\n\n e.preventDefault()}\n >\n {isEditing ? (\n
\n
\n
\n \n
\n\n \n
\n
\n ) : (\n
\n \n Edit link\n \n\n \n\n \n
\n )}\n \n
\n );\n}\n" + "content": "import React, { useEffect } from 'react';\nimport {\n isCollapsed,\n useEditorState,\n useElement,\n useRemoveNodeButton,\n} from '@udecode/plate-common';\nimport {\n floatingMediaActions,\n FloatingMedia as FloatingMediaPrimitive,\n useFloatingMediaSelectors,\n} from '@udecode/plate-media';\nimport { useReadOnly, useSelected } from 'slate-react';\n\nimport { Icons } from '@/components/icons';\n\nimport { Button, buttonVariants } from './button';\nimport { inputVariants } from './input';\nimport { Popover, PopoverAnchor, PopoverContent } from './popover';\nimport { Separator } from './separator';\n\nexport interface MediaPopoverProps {\n pluginKey?: string;\n children: React.ReactNode;\n}\n\nexport function MediaPopover({ pluginKey, children }: MediaPopoverProps) {\n const readOnly = useReadOnly();\n const selected = useSelected();\n const editor = useEditorState();\n\n const isOpen = !readOnly && selected && isCollapsed(editor.selection);\n const isEditing = useFloatingMediaSelectors().isEditing();\n\n useEffect(() => {\n if (!isOpen && isEditing) {\n floatingMediaActions.isEditing(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isOpen]);\n\n const element = useElement();\n const { props: buttonProps } = useRemoveNodeButton({ element });\n\n if (readOnly) return <>{children};\n\n return (\n \n {children}\n\n e.preventDefault()}\n >\n {isEditing ? (\n
\n
\n
\n \n
\n\n \n
\n
\n ) : (\n
\n \n Edit link\n \n\n \n\n \n
\n )}\n \n
\n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/mention-combobox.json b/apps/www/public/registry/styles/default/mention-combobox.json index 3d829f6dc5..8b5d014c3c 100644 --- a/apps/www/public/registry/styles/default/mention-combobox.json +++ b/apps/www/public/registry/styles/default/mention-combobox.json @@ -10,7 +10,7 @@ "files": [ { "name": "mention-combobox.tsx", - "content": "import React from 'react';\nimport { ComboboxProps, Data, NoData } from '@udecode/plate-combobox';\nimport { getPluginOptions, usePlateEditorRef } from '@udecode/plate-common';\nimport {\n ELEMENT_MENTION,\n getMentionOnSelectItem,\n MentionPlugin,\n} from '@udecode/plate-mention';\n\nimport { Combobox } from './combobox';\n\nexport interface MentionComboboxProps\n extends Partial> {\n pluginKey?: string;\n}\n\nexport function MentionCombobox({\n pluginKey = ELEMENT_MENTION,\n id = pluginKey,\n ...props\n}: MentionComboboxProps) {\n const editor = usePlateEditorRef();\n\n const { trigger } = getPluginOptions(editor, pluginKey);\n\n return (\n \n );\n}\n" + "content": "import React from 'react';\nimport { ComboboxProps, Data, NoData } from '@udecode/plate-combobox';\nimport { getPluginOptions, useEditorRef } from '@udecode/plate-common';\nimport {\n ELEMENT_MENTION,\n getMentionOnSelectItem,\n MentionPlugin,\n} from '@udecode/plate-mention';\n\nimport { Combobox } from './combobox';\n\nexport interface MentionComboboxProps\n extends Partial> {\n pluginKey?: string;\n}\n\nexport function MentionCombobox({\n pluginKey = ELEMENT_MENTION,\n id = pluginKey,\n ...props\n}: MentionComboboxProps) {\n const editor = useEditorRef();\n\n const { trigger } = getPluginOptions(editor, pluginKey);\n\n return (\n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/mode-dropdown-menu.json b/apps/www/public/registry/styles/default/mode-dropdown-menu.json index 0bd74ec628..4529b82da9 100644 --- a/apps/www/public/registry/styles/default/mode-dropdown-menu.json +++ b/apps/www/public/registry/styles/default/mode-dropdown-menu.json @@ -8,7 +8,7 @@ "files": [ { "name": "mode-dropdown-menu.tsx", - "content": "import React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport {\n focusEditor,\n usePlateEditorState,\n usePlateReadOnly,\n usePlateStore,\n} from '@udecode/plate-common';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nexport function ModeDropdownMenu(props: DropdownMenuProps) {\n const editor = usePlateEditorState();\n const setReadOnly = usePlateStore().set.readOnly();\n const readOnly = usePlateReadOnly();\n const openState = useOpenState();\n\n let value = 'editing';\n if (readOnly) value = 'viewing';\n\n const item: any = {\n editing: (\n <>\n \n Editing\n \n ),\n viewing: (\n <>\n \n Viewing\n \n ),\n };\n\n return (\n \n \n \n {item[value]}\n \n \n\n \n {\n if (newValue !== 'viewing') {\n setReadOnly(false);\n }\n\n if (newValue === 'viewing') {\n setReadOnly(true);\n return;\n }\n\n if (newValue === 'editing') {\n focusEditor(editor);\n return;\n }\n }}\n >\n \n {item.editing}\n \n\n \n {item.viewing}\n \n \n \n \n );\n}\n" + "content": "import React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport {\n focusEditor,\n useEditorReadOnly,\n useEditorState,\n usePlateStore,\n} from '@udecode/plate-common';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nexport function ModeDropdownMenu(props: DropdownMenuProps) {\n const editor = useEditorState();\n const setReadOnly = usePlateStore().set.readOnly();\n const readOnly = useEditorReadOnly();\n const openState = useOpenState();\n\n let value = 'editing';\n if (readOnly) value = 'viewing';\n\n const item: any = {\n editing: (\n <>\n \n Editing\n \n ),\n viewing: (\n <>\n \n Viewing\n \n ),\n };\n\n return (\n \n \n \n {item[value]}\n \n \n\n \n {\n if (newValue !== 'viewing') {\n setReadOnly(false);\n }\n\n if (newValue === 'viewing') {\n setReadOnly(true);\n return;\n }\n\n if (newValue === 'editing') {\n focusEditor(editor);\n return;\n }\n }}\n >\n \n {item.editing}\n \n\n \n {item.viewing}\n \n \n \n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/more-dropdown-menu.json b/apps/www/public/registry/styles/default/more-dropdown-menu.json index 19b0913eb9..370b6e375d 100644 --- a/apps/www/public/registry/styles/default/more-dropdown-menu.json +++ b/apps/www/public/registry/styles/default/more-dropdown-menu.json @@ -10,7 +10,7 @@ "files": [ { "name": "more-dropdown-menu.tsx", - "content": "import React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport { MARK_SUBSCRIPT, MARK_SUPERSCRIPT } from '@udecode/plate-basic-marks';\nimport {\n focusEditor,\n toggleMark,\n usePlateEditorState,\n} from '@udecode/plate-common';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nexport function MoreDropdownMenu(props: DropdownMenuProps) {\n const editor = usePlateEditorState();\n const openState = useOpenState();\n\n return (\n \n \n \n \n \n \n\n \n {\n toggleMark(editor, {\n key: MARK_SUBSCRIPT,\n clear: MARK_SUPERSCRIPT,\n });\n focusEditor(editor);\n }}\n >\n \n Superscript\n {/* (⌘+,) */}\n \n {\n toggleMark(editor, {\n key: MARK_SUPERSCRIPT,\n clear: MARK_SUBSCRIPT,\n });\n focusEditor(editor);\n }}\n >\n \n Subscript\n {/* (⌘+.) */}\n \n \n \n );\n}\n" + "content": "import React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport { MARK_SUBSCRIPT, MARK_SUPERSCRIPT } from '@udecode/plate-basic-marks';\nimport { focusEditor, toggleMark, useEditorState } from '@udecode/plate-common';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nexport function MoreDropdownMenu(props: DropdownMenuProps) {\n const editor = useEditorState();\n const openState = useOpenState();\n\n return (\n \n \n \n \n \n \n\n \n {\n toggleMark(editor, {\n key: MARK_SUBSCRIPT,\n clear: MARK_SUPERSCRIPT,\n });\n focusEditor(editor);\n }}\n >\n \n Superscript\n {/* (⌘+,) */}\n \n {\n toggleMark(editor, {\n key: MARK_SUPERSCRIPT,\n clear: MARK_SUBSCRIPT,\n });\n focusEditor(editor);\n }}\n >\n \n Subscript\n {/* (⌘+.) */}\n \n \n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/popover.json b/apps/www/public/registry/styles/default/popover.json index dfdb9277b9..1015a1aeaf 100644 --- a/apps/www/public/registry/styles/default/popover.json +++ b/apps/www/public/registry/styles/default/popover.json @@ -7,7 +7,7 @@ "files": [ { "name": "popover.tsx", - "content": "'use client';\n\nimport * as React from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { cva } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nexport const popoverVariants = cva(\n 'z-[100] w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2'\n);\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (\n \n \n \n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };\n" + "content": "'use client';\n\nimport * as React from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { cva } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nexport const popoverVariants = cva(\n 'w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 print:hidden'\n);\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, style, align = 'center', sideOffset = 4, ...props }, ref) => (\n \n \n \n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/table-dropdown-menu.json b/apps/www/public/registry/styles/default/table-dropdown-menu.json index 8c4089cdef..6563232559 100644 --- a/apps/www/public/registry/styles/default/table-dropdown-menu.json +++ b/apps/www/public/registry/styles/default/table-dropdown-menu.json @@ -10,7 +10,7 @@ "files": [ { "name": "table-dropdown-menu.tsx", - "content": "import React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport {\n focusEditor,\n someNode,\n usePlateEditorState,\n} from '@udecode/plate-common';\nimport {\n deleteColumn,\n deleteRow,\n deleteTable,\n ELEMENT_TABLE,\n insertTable,\n insertTableColumn,\n insertTableRow,\n} from '@udecode/plate-table';\n\nimport { Icons, iconVariants } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nexport function TableDropdownMenu(props: DropdownMenuProps) {\n const editor = usePlateEditorState();\n\n const tableSelected = someNode(editor, {\n match: { type: ELEMENT_TABLE },\n });\n\n const openState = useOpenState();\n\n return (\n \n \n \n \n \n \n\n \n \n \n \n Table\n \n \n {\n insertTable(editor);\n focusEditor(editor);\n }}\n >\n \n Insert table\n \n {\n deleteTable(editor);\n focusEditor(editor);\n }}\n >\n \n Delete table\n \n \n \n\n \n \n \n Column\n \n \n {\n insertTableColumn(editor);\n focusEditor(editor);\n }}\n >\n \n Insert column after\n \n {\n deleteColumn(editor);\n focusEditor(editor);\n }}\n >\n \n Delete column\n \n \n \n\n \n \n \n Row\n \n \n {\n insertTableRow(editor);\n focusEditor(editor);\n }}\n >\n \n Insert row after\n \n {\n deleteRow(editor);\n focusEditor(editor);\n }}\n >\n \n Delete row\n \n \n \n \n \n );\n}\n" + "content": "import React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport { focusEditor, someNode, useEditorState } from '@udecode/plate-common';\nimport {\n deleteColumn,\n deleteRow,\n deleteTable,\n ELEMENT_TABLE,\n insertTable,\n insertTableColumn,\n insertTableRow,\n} from '@udecode/plate-table';\n\nimport { Icons, iconVariants } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nexport function TableDropdownMenu(props: DropdownMenuProps) {\n const editor = useEditorState();\n\n const tableSelected = someNode(editor, {\n match: { type: ELEMENT_TABLE },\n });\n\n const openState = useOpenState();\n\n return (\n \n \n \n \n \n \n\n \n \n \n \n Table\n \n \n {\n insertTable(editor);\n focusEditor(editor);\n }}\n >\n \n Insert table\n \n {\n deleteTable(editor);\n focusEditor(editor);\n }}\n >\n \n Delete table\n \n \n \n\n \n \n \n Column\n \n \n {\n insertTableColumn(editor);\n focusEditor(editor);\n }}\n >\n \n Insert column after\n \n {\n deleteColumn(editor);\n focusEditor(editor);\n }}\n >\n \n Delete column\n \n \n \n\n \n \n \n Row\n \n \n {\n insertTableRow(editor);\n focusEditor(editor);\n }}\n >\n \n Insert row after\n \n {\n deleteRow(editor);\n focusEditor(editor);\n }}\n >\n \n Delete row\n \n \n \n \n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/table-element.json b/apps/www/public/registry/styles/default/table-element.json index 61399ed210..eaa8db65bc 100644 --- a/apps/www/public/registry/styles/default/table-element.json +++ b/apps/www/public/registry/styles/default/table-element.json @@ -3,11 +3,13 @@ "dependencies": [ "@udecode/plate-table" ], - "registryDependencies": [], + "registryDependencies": [ + "dropdown-menu" + ], "files": [ { "name": "table-element.tsx", - "content": "import React, { forwardRef } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { PopoverAnchor, PopoverContentProps } from '@radix-ui/react-popover';\nimport {\n isCollapsed,\n PlateElement,\n PlateElementProps,\n someNode,\n useElement,\n usePlateEditorState,\n useRemoveNodeButton,\n} from '@udecode/plate-common';\nimport {\n TTableElement,\n useTableBordersDropdownMenuContentState,\n useTableElement,\n useTableElementState,\n} from '@udecode/plate-table';\nimport { useReadOnly } from 'slate-react';\n\nimport { cn } from '@/lib/utils';\nimport { Icons, iconVariants } from '@/components/icons';\n\nimport { Button } from './button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n} from './dropdown-menu';\nimport { Popover, PopoverContent, popoverVariants } from './popover';\nimport { Separator } from './separator';\n\nconst TableBordersDropdownMenuContent = forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>((props, ref) => {\n const {\n getOnSelectTableBorder,\n hasOuterBorders,\n hasBottomBorder,\n hasLeftBorder,\n hasNoBorders,\n hasRightBorder,\n hasTopBorder,\n } = useTableBordersDropdownMenuContentState();\n\n return (\n \n \n \n
Bottom Border
\n \n \n \n
Top Border
\n \n \n \n
Left Border
\n \n \n \n
Right Border
\n \n\n \n\n \n \n
No Border
\n \n \n \n
Outside Borders
\n \n \n );\n});\nTableBordersDropdownMenuContent.displayName = 'TableBordersDropdownMenuContent';\n\nconst TableFloatingToolbar = React.forwardRef<\n React.ElementRef,\n PopoverContentProps\n>(({ children, ...props }, ref) => {\n const element = useElement();\n const { props: buttonProps } = useRemoveNodeButton({ element });\n\n const readOnly = useReadOnly();\n const editor = usePlateEditorState();\n const open =\n !readOnly &&\n someNode(editor, {\n match: (n) => n === element,\n }) &&\n isCollapsed(editor.selection);\n\n return (\n \n {children}\n e.preventDefault()}\n {...props}\n >\n \n \n \n \n\n \n \n \n \n\n \n \n \n );\n});\nTableFloatingToolbar.displayName = 'TableFloatingToolbar';\n\nconst TableElement = React.forwardRef<\n React.ElementRef,\n PlateElementProps\n>(({ className, children, ...props }, ref) => {\n const { colSizes, isSelectingCell, minColumnWidth, marginLeft } =\n useTableElementState();\n const { props: tableProps, colGroupProps } = useTableElement();\n\n return (\n \n
\n \n \n \n {colSizes.map((width, index) => (\n \n ))}\n \n\n {children}\n
\n \n
\n
\n );\n});\nTableElement.displayName = 'TableElement';\n\nexport { TableElement, TableFloatingToolbar, TableBordersDropdownMenuContent };\n" + "content": "import React, { forwardRef } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { PopoverAnchor, PopoverContentProps } from '@radix-ui/react-popover';\nimport {\n isCollapsed,\n PlateElement,\n PlateElementProps,\n useEditorState,\n useElement,\n useRemoveNodeButton,\n} from '@udecode/plate-common';\nimport {\n TTableElement,\n useTableBordersDropdownMenuContentState,\n useTableElement,\n useTableElementState,\n} from '@udecode/plate-table';\nimport { useReadOnly, useSelected } from 'slate-react';\n\nimport { cn } from '@/lib/utils';\nimport { Icons, iconVariants } from '@/components/icons';\n\nimport { Button } from './button';\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n} from './dropdown-menu';\nimport { Popover, PopoverContent, popoverVariants } from './popover';\nimport { Separator } from './separator';\n\nconst TableBordersDropdownMenuContent = forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>((props, ref) => {\n const {\n getOnSelectTableBorder,\n hasOuterBorders,\n hasBottomBorder,\n hasLeftBorder,\n hasNoBorders,\n hasRightBorder,\n hasTopBorder,\n } = useTableBordersDropdownMenuContentState();\n\n return (\n \n \n \n
Bottom Border
\n \n \n \n
Top Border
\n \n \n \n
Left Border
\n \n \n \n
Right Border
\n \n\n \n\n \n \n
No Border
\n \n \n \n
Outside Borders
\n \n \n );\n});\nTableBordersDropdownMenuContent.displayName = 'TableBordersDropdownMenuContent';\n\nconst TableFloatingToolbar = React.forwardRef<\n React.ElementRef,\n PopoverContentProps\n>(({ children, ...props }, ref) => {\n const element = useElement();\n const { props: buttonProps } = useRemoveNodeButton({ element });\n\n const readOnly = useReadOnly();\n const selected = useSelected();\n const editor = useEditorState();\n const open = !readOnly && selected && isCollapsed(editor.selection);\n\n return (\n \n {children}\n e.preventDefault()}\n {...props}\n >\n \n \n \n \n\n \n \n \n \n\n \n \n \n );\n});\nTableFloatingToolbar.displayName = 'TableFloatingToolbar';\n\nconst TableElement = React.forwardRef<\n React.ElementRef,\n PlateElementProps\n>(({ className, children, ...props }, ref) => {\n const { colSizes, isSelectingCell, minColumnWidth, marginLeft } =\n useTableElementState();\n const { props: tableProps, colGroupProps } = useTableElement();\n\n return (\n \n
\n \n \n \n {colSizes.map((width, index) => (\n \n ))}\n \n\n {children}\n
\n \n
\n
\n );\n});\nTableElement.displayName = 'TableElement';\n\nexport { TableElement, TableFloatingToolbar, TableBordersDropdownMenuContent };\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/styles/default/todo-list-element.json b/apps/www/public/registry/styles/default/todo-list-element.json index ef465f4906..8a291a4973 100644 --- a/apps/www/public/registry/styles/default/todo-list-element.json +++ b/apps/www/public/registry/styles/default/todo-list-element.json @@ -3,7 +3,9 @@ "dependencies": [ "@udecode/plate-list" ], - "registryDependencies": [], + "registryDependencies": [ + "checkbox" + ], "files": [ { "name": "todo-list-element.tsx", diff --git a/apps/www/public/registry/styles/default/turn-into-dropdown-menu.json b/apps/www/public/registry/styles/default/turn-into-dropdown-menu.json index 3858b742d2..8a274b7346 100644 --- a/apps/www/public/registry/styles/default/turn-into-dropdown-menu.json +++ b/apps/www/public/registry/styles/default/turn-into-dropdown-menu.json @@ -12,7 +12,7 @@ "files": [ { "name": "turn-into-dropdown-menu.tsx", - "content": "import React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport { ELEMENT_BLOCKQUOTE } from '@udecode/plate-block-quote';\nimport {\n collapseSelection,\n findNode,\n focusEditor,\n isBlock,\n isCollapsed,\n TElement,\n toggleNodeType,\n usePlateEditorState,\n} from '@udecode/plate-common';\nimport { ELEMENT_H1, ELEMENT_H2, ELEMENT_H3 } from '@udecode/plate-heading';\nimport { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nconst items = [\n {\n value: ELEMENT_PARAGRAPH,\n label: 'Paragraph',\n description: 'Paragraph',\n icon: Icons.paragraph,\n },\n {\n value: ELEMENT_H1,\n label: 'Heading 1',\n description: 'Heading 1',\n icon: Icons.h1,\n },\n {\n value: ELEMENT_H2,\n label: 'Heading 2',\n description: 'Heading 2',\n icon: Icons.h2,\n },\n {\n value: ELEMENT_H3,\n label: 'Heading 3',\n description: 'Heading 3',\n icon: Icons.h3,\n },\n {\n value: ELEMENT_BLOCKQUOTE,\n label: 'Quote',\n description: 'Quote (⌘+⇧+.)',\n icon: Icons.blockquote,\n },\n // {\n // value: 'ul',\n // label: 'Bulleted list',\n // description: 'Bulleted list',\n // icon: Icons.ul,\n // },\n // {\n // value: 'ol',\n // label: 'Numbered list',\n // description: 'Numbered list',\n // icon: Icons.ol,\n // },\n];\n\nconst defaultItem = items.find((item) => item.value === ELEMENT_PARAGRAPH)!;\n\nexport function TurnIntoDropdownMenu(props: DropdownMenuProps) {\n const editor = usePlateEditorState();\n const openState = useOpenState();\n\n let value: string = ELEMENT_PARAGRAPH;\n if (isCollapsed(editor?.selection)) {\n const entry = findNode(editor!, {\n match: (n) => isBlock(editor, n),\n });\n if (entry) {\n value =\n items.find((item) => item.value === entry[0].type)?.value ??\n ELEMENT_PARAGRAPH;\n }\n }\n\n const selectedItem =\n items.find((item) => item.value === value) ?? defaultItem;\n const { icon: SelectedItemIcon, label: selectedItemLabel } = selectedItem;\n\n return (\n \n \n \n \n {selectedItemLabel}\n \n \n\n \n Turn into\n\n {\n // if (type === 'ul' || type === 'ol') {\n // if (settingsStore.get.checkedId(KEY_LIST_STYLE_TYPE)) {\n // toggleIndentList(editor, {\n // listStyleType: type === 'ul' ? 'disc' : 'decimal',\n // });\n // } else if (settingsStore.get.checkedId('list')) {\n // toggleList(editor, { type });\n // }\n // } else {\n // unwrapList(editor);\n toggleNodeType(editor, { activeType: type });\n // }\n\n collapseSelection(editor);\n focusEditor(editor);\n }}\n >\n {items.map(({ value: itemValue, label, icon: Icon }) => (\n \n \n {label}\n \n ))}\n \n \n \n );\n}\n" + "content": "import React from 'react';\nimport { DropdownMenuProps } from '@radix-ui/react-dropdown-menu';\nimport { ELEMENT_BLOCKQUOTE } from '@udecode/plate-block-quote';\nimport {\n collapseSelection,\n findNode,\n focusEditor,\n isBlock,\n isCollapsed,\n TElement,\n toggleNodeType,\n useEditorState,\n} from '@udecode/plate-common';\nimport { ELEMENT_H1, ELEMENT_H2, ELEMENT_H3 } from '@udecode/plate-heading';\nimport { ELEMENT_PARAGRAPH } from '@udecode/plate-paragraph';\n\nimport { Icons } from '@/components/icons';\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n useOpenState,\n} from './dropdown-menu';\nimport { ToolbarButton } from './toolbar';\n\nconst items = [\n {\n value: ELEMENT_PARAGRAPH,\n label: 'Paragraph',\n description: 'Paragraph',\n icon: Icons.paragraph,\n },\n {\n value: ELEMENT_H1,\n label: 'Heading 1',\n description: 'Heading 1',\n icon: Icons.h1,\n },\n {\n value: ELEMENT_H2,\n label: 'Heading 2',\n description: 'Heading 2',\n icon: Icons.h2,\n },\n {\n value: ELEMENT_H3,\n label: 'Heading 3',\n description: 'Heading 3',\n icon: Icons.h3,\n },\n {\n value: ELEMENT_BLOCKQUOTE,\n label: 'Quote',\n description: 'Quote (⌘+⇧+.)',\n icon: Icons.blockquote,\n },\n // {\n // value: 'ul',\n // label: 'Bulleted list',\n // description: 'Bulleted list',\n // icon: Icons.ul,\n // },\n // {\n // value: 'ol',\n // label: 'Numbered list',\n // description: 'Numbered list',\n // icon: Icons.ol,\n // },\n];\n\nconst defaultItem = items.find((item) => item.value === ELEMENT_PARAGRAPH)!;\n\nexport function TurnIntoDropdownMenu(props: DropdownMenuProps) {\n const editor = useEditorState();\n const openState = useOpenState();\n\n let value: string = ELEMENT_PARAGRAPH;\n if (isCollapsed(editor?.selection)) {\n const entry = findNode(editor!, {\n match: (n) => isBlock(editor, n),\n });\n if (entry) {\n value =\n items.find((item) => item.value === entry[0].type)?.value ??\n ELEMENT_PARAGRAPH;\n }\n }\n\n const selectedItem =\n items.find((item) => item.value === value) ?? defaultItem;\n const { icon: SelectedItemIcon, label: selectedItemLabel } = selectedItem;\n\n return (\n \n \n \n \n {selectedItemLabel}\n \n \n\n \n Turn into\n\n {\n // if (type === 'ul' || type === 'ol') {\n // if (settingsStore.get.checkedId(KEY_LIST_STYLE_TYPE)) {\n // toggleIndentList(editor, {\n // listStyleType: type === 'ul' ? 'disc' : 'decimal',\n // });\n // } else if (settingsStore.get.checkedId('list')) {\n // toggleList(editor, { type });\n // }\n // } else {\n // unwrapList(editor);\n toggleNodeType(editor, { activeType: type });\n // }\n\n collapseSelection(editor);\n focusEditor(editor);\n }}\n >\n {items.map(({ value: itemValue, label, icon: Icon }) => (\n \n \n {label}\n \n ))}\n \n \n \n );\n}\n" } ], "type": "components:plate-ui" diff --git a/apps/www/public/registry/themes.css b/apps/www/public/registry/themes.css index 6c4d9b8c7d..d3f75bc426 100644 --- a/apps/www/public/registry/themes.css +++ b/apps/www/public/registry/themes.css @@ -1,5 +1,69 @@ - .theme-default { + .theme-zinc { + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; + + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + + --popover: 0 0% 100%; + --popover-foreground: 240 10% 3.9%; + + --card: 0 0% 100%; + --card-foreground: 240 10% 3.9%; + + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + + --ring: 240 5.9% 10%; + + --radius: 0.5rem; + } + + .dark .theme-zinc { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + + --border: 240 3.7% 25%; + --input: 240 3.7% 25%; + + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + + --ring: 240 4.9% 83.9%; + } + + .theme-slate { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; @@ -15,7 +79,7 @@ --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; - --primary: 160 90% 46%; + --primary: 222.2 47.4% 11.2%; --primary-foreground: 210 40% 98%; --secondary: 210 40% 96.1%; @@ -32,7 +96,7 @@ --radius: 0.5rem; } - .dark .theme-default { + .dark .theme-slate { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; @@ -58,12 +122,268 @@ --accent-foreground: 210 40% 98%; --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 85.7% 97.3%; + --destructive-foreground: 210 40% 98%; --ring: 217.2 32.6% 17.5%; } - .theme-zinc { + .theme-stone { + --background: 0 0% 100%; + --foreground: 20 14.3% 4.1%; + + --muted: 60 4.8% 95.9%; + --muted-foreground: 25 5.3% 44.7%; + + --popover: 0 0% 100%; + --popover-foreground: 20 14.3% 4.1%; + + --card: 0 0% 100%; + --card-foreground: 20 14.3% 4.1%; + + --border: 20 5.9% 90%; + --input: 20 5.9% 90%; + + --primary: 24 9.8% 10%; + --primary-foreground: 60 9.1% 97.8%; + + --secondary: 60 4.8% 95.9%; + --secondary-foreground: 24 9.8% 10%; + + --accent: 60 4.8% 95.9%; + --accent-foreground: 24 9.8% 10%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 60 9.1% 97.8%; + + --ring: 20 14.3% 4.1%; + + --radius: 0.95rem; + } + + .dark .theme-stone { + --background: 20 14.3% 4.1%; + --foreground: 60 9.1% 97.8%; + + --muted: 12 6.5% 15.1%; + --muted-foreground: 24 5.4% 63.9%; + + --popover: 20 14.3% 4.1%; + --popover-foreground: 60 9.1% 97.8%; + + --card: 20 14.3% 4.1%; + --card-foreground: 60 9.1% 97.8%; + + --border: 12 6.5% 15.1%; + --input: 12 6.5% 15.1%; + + --primary: 60 9.1% 97.8%; + --primary-foreground: 24 9.8% 10%; + + --secondary: 12 6.5% 15.1%; + --secondary-foreground: 60 9.1% 97.8%; + + --accent: 12 6.5% 15.1%; + --accent-foreground: 60 9.1% 97.8%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 60 9.1% 97.8%; + + --ring: 24 5.7% 82.9%; + } + + .theme-gray { + --background: 0 0% 100%; + --foreground: 224 71.4% 4.1%; + + --muted: 220 14.3% 95.9%; + --muted-foreground: 220 8.9% 46.1%; + + --popover: 0 0% 100%; + --popover-foreground: 224 71.4% 4.1%; + + --card: 0 0% 100%; + --card-foreground: 224 71.4% 4.1%; + + --border: 220 13% 91%; + --input: 220 13% 91%; + + --primary: 220.9 39.3% 11%; + --primary-foreground: 210 20% 98%; + + --secondary: 220 14.3% 95.9%; + --secondary-foreground: 220.9 39.3% 11%; + + --accent: 220 14.3% 95.9%; + --accent-foreground: 220.9 39.3% 11%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 20% 98%; + + --ring: 224 71.4% 4.1%; + + --radius: 0.35rem; + } + + .dark .theme-gray { + --background: 224 71.4% 4.1%; + --foreground: 210 20% 98%; + + --muted: 215 27.9% 16.9%; + --muted-foreground: 217.9 10.6% 64.9%; + + --popover: 224 71.4% 4.1%; + --popover-foreground: 210 20% 98%; + + --card: 224 71.4% 4.1%; + --card-foreground: 210 20% 98%; + + --border: 215 27.9% 16.9%; + --input: 215 27.9% 16.9%; + + --primary: 210 20% 98%; + --primary-foreground: 220.9 39.3% 11%; + + --secondary: 215 27.9% 16.9%; + --secondary-foreground: 210 20% 98%; + + --accent: 215 27.9% 16.9%; + --accent-foreground: 210 20% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 20% 98%; + + --ring: 216 12.2% 83.9%; + } + + .theme-neutral { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + + --ring: 0 0% 3.9%; + + --radius: ; + } + + .dark .theme-neutral { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + + --ring: 0 0% 83.1%; + } + + .theme-red { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + + --primary: 0 72.2% 50.6%; + --primary-foreground: 0 85.7% 97.3%; + + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + + --ring: 0 72.2% 50.6%; + + --radius: 0.4rem; + } + + .dark .theme-red { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + + --primary: 0 72.2% 50.6%; + --primary-foreground: 0 85.7% 97.3%; + + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + + --ring: 0 72.2% 50.6%; + } + + .theme-rose { --background: 0 0% 100%; --foreground: 240 10% 3.9%; @@ -79,8 +399,8 @@ --border: 240 5.9% 90%; --input: 240 5.9% 90%; - --primary: 240 5.9% 10%; - --primary-foreground: 0 0% 98%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 97.3%; --secondary: 240 4.8% 95.9%; --secondary-foreground: 240 5.9% 10%; @@ -91,43 +411,107 @@ --destructive: 0 84.2% 60.2%; --destructive-foreground: 0 0% 98%; - --ring: 240 5% 64.9%; + --ring: 346.8 77.2% 49.8%; --radius: 0.5rem; } - .dark .theme-zinc { - --background: 240 10% 3.9%; - --foreground: 0 0% 98%; + .dark .theme-rose { + --background: 20 14.3% 4.1%; + --foreground: 0 0% 95%; - --muted: 240 3.7% 15.9%; + --muted: 0 0% 15%; --muted-foreground: 240 5% 64.9%; - --popover: 240 10% 3.9%; - --popover-foreground: 0 0% 98%; + --popover: 0 0% 9%; + --popover-foreground: 0 0% 95%; - --card: 240 10% 3.9%; - --card-foreground: 0 0% 98%; + --card: 24 9.8% 10%; + --card-foreground: 0 0% 95%; - --border: 240 3.7% 15.9%; - --input: 240 3.7% 15.9%; + --border: 240 3.7% 25%; + --input: 240 3.7% 25%; - --primary: 0 0% 98%; - --primary-foreground: 240 5.9% 10%; + --primary: 346.8 77.2% 49.8%; + --primary-foreground: 355.7 100% 97.3%; --secondary: 240 3.7% 15.9%; --secondary-foreground: 0 0% 98%; - --accent: 240 3.7% 15.9%; + --accent: 12 6.5% 15.1%; --accent-foreground: 0 0% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 0 85.7% 97.3%; - --ring: 240 3.7% 15.9%; + --ring: 346.8 77.2% 49.8%; } - .theme-lime { + .theme-orange { + --background: 0 0% 100%; + --foreground: 20 14.3% 4.1%; + + --muted: 60 4.8% 95.9%; + --muted-foreground: 25 5.3% 44.7%; + + --popover: 0 0% 100%; + --popover-foreground: 20 14.3% 4.1%; + + --card: 0 0% 100%; + --card-foreground: 20 14.3% 4.1%; + + --border: 20 5.9% 90%; + --input: 20 5.9% 90%; + + --primary: 24.6 95% 53.1%; + --primary-foreground: 60 9.1% 97.8%; + + --secondary: 60 4.8% 95.9%; + --secondary-foreground: 24 9.8% 10%; + + --accent: 60 4.8% 95.9%; + --accent-foreground: 24 9.8% 10%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 60 9.1% 97.8%; + + --ring: 24.6 95% 53.1%; + + --radius: 0.95rem; + } + + .dark .theme-orange { + --background: 20 14.3% 4.1%; + --foreground: 60 9.1% 97.8%; + + --muted: 12 6.5% 15.1%; + --muted-foreground: 24 5.4% 63.9%; + + --popover: 20 14.3% 4.1%; + --popover-foreground: 60 9.1% 97.8%; + + --card: 20 14.3% 4.1%; + --card-foreground: 60 9.1% 97.8%; + + --border: 12 6.5% 15.1%; + --input: 12 6.5% 15.1%; + + --primary: 20.5 90.2% 48.2%; + --primary-foreground: 60 9.1% 97.8%; + + --secondary: 12 6.5% 15.1%; + --secondary-foreground: 60 9.1% 97.8%; + + --accent: 12 6.5% 15.1%; + --accent-foreground: 60 9.1% 97.8%; + + --destructive: 0 72.2% 50.6%; + --destructive-foreground: 60 9.1% 97.8%; + + --ring: 20.5 90.2% 48.2%; + } + + .theme-green { --background: 0 0% 100%; --foreground: 240 10% 3.9%; @@ -143,8 +527,8 @@ --border: 240 5.9% 90%; --input: 240 5.9% 90%; - --primary: 87.6 61.2% 20.2%; - --primary-foreground: 0 0% 98%; + --primary: 142.1 76.2% 36.3%; + --primary-foreground: 355.7 100% 97.3%; --secondary: 240 4.8% 95.9%; --secondary-foreground: 240 5.9% 10%; @@ -155,38 +539,230 @@ --destructive: 0 84.2% 60.2%; --destructive-foreground: 0 0% 98%; - --ring: 240 5% 64.9%; + --ring: 142.1 76.2% 36.3%; - --radius: 0.5rem; + --radius: ; } - .dark .theme-lime { - --background: 240 10% 3.9%; - --foreground: 0 0% 98%; + .dark .theme-green { + --background: 20 14.3% 4.1%; + --foreground: 0 0% 95%; - --muted: 240 3.7% 15.9%; + --muted: 0 0% 15%; --muted-foreground: 240 5% 64.9%; - --popover: 240 10% 3.9%; - --popover-foreground: 0 0% 98%; + --popover: 0 0% 9%; + --popover-foreground: 0 0% 95%; - --card: 240 10% 3.9%; - --card-foreground: 0 0% 98%; + --card: 24 9.8% 10%; + --card-foreground: 0 0% 95%; - --border: 240 3.7% 15.9%; - --input: 240 3.7% 15.9%; + --border: 240 3.7% 25%; + --input: 240 3.7% 25%; - --primary: 82 84.5% 67.1%; - --primary-foreground: 240 5.9% 10%; + --primary: 142.1 70.6% 45.3%; + --primary-foreground: 144.9 80.4% 10%; --secondary: 240 3.7% 15.9%; --secondary-foreground: 0 0% 98%; - --accent: 240 3.7% 15.9%; + --accent: 12 6.5% 15.1%; --accent-foreground: 0 0% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 0 85.7% 97.3%; - --ring: 240 3.7% 15.9%; + --ring: 142.4 71.8% 29.2%; + } + + .theme-blue { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + + --primary: 221.2 83.2% 53.3%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + + --ring: 221.2 83.2% 53.3%; + + --radius: ; + } + + .dark .theme-blue { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + + --primary: 217.2 91.2% 59.8%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --ring: 224.3 76.3% 48%; + } + + .theme-yellow { + --background: 0 0% 100%; + --foreground: 20 14.3% 4.1%; + + --muted: 60 4.8% 95.9%; + --muted-foreground: 25 5.3% 44.7%; + + --popover: 0 0% 100%; + --popover-foreground: 20 14.3% 4.1%; + + --card: 0 0% 100%; + --card-foreground: 20 14.3% 4.1%; + + --border: 20 5.9% 90%; + --input: 20 5.9% 90%; + + --primary: 47.9 95.8% 53.1%; + --primary-foreground: 26 83.3% 14.1%; + + --secondary: 60 4.8% 95.9%; + --secondary-foreground: 24 9.8% 10%; + + --accent: 60 4.8% 95.9%; + --accent-foreground: 24 9.8% 10%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 60 9.1% 97.8%; + + --ring: 20 14.3% 4.1%; + + --radius: 0.95rem; + } + + .dark .theme-yellow { + --background: 20 14.3% 4.1%; + --foreground: 60 9.1% 97.8%; + + --muted: 12 6.5% 15.1%; + --muted-foreground: 24 5.4% 63.9%; + + --popover: 20 14.3% 4.1%; + --popover-foreground: 60 9.1% 97.8%; + + --card: 20 14.3% 4.1%; + --card-foreground: 60 9.1% 97.8%; + + --border: 12 6.5% 15.1%; + --input: 12 6.5% 15.1%; + + --primary: 47.9 95.8% 53.1%; + --primary-foreground: 26 83.3% 14.1%; + + --secondary: 12 6.5% 15.1%; + --secondary-foreground: 60 9.1% 97.8%; + + --accent: 12 6.5% 15.1%; + --accent-foreground: 60 9.1% 97.8%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 60 9.1% 97.8%; + + --ring: 35.5 91.7% 32.9%; + } + + .theme-violet { + --background: 0 0% 100%; + --foreground: 224 71.4% 4.1%; + + --muted: 220 14.3% 95.9%; + --muted-foreground: 220 8.9% 46.1%; + + --popover: 0 0% 100%; + --popover-foreground: 224 71.4% 4.1%; + + --card: 0 0% 100%; + --card-foreground: 224 71.4% 4.1%; + + --border: 220 13% 91%; + --input: 220 13% 91%; + + --primary: 262.1 83.3% 57.8%; + --primary-foreground: 210 20% 98%; + + --secondary: 220 14.3% 95.9%; + --secondary-foreground: 220.9 39.3% 11%; + + --accent: 220 14.3% 95.9%; + --accent-foreground: 220.9 39.3% 11%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 20% 98%; + + --ring: 262.1 83.3% 57.8%; + + --radius: ; + } + + .dark .theme-violet { + --background: 224 71.4% 4.1%; + --foreground: 210 20% 98%; + + --muted: 215 27.9% 16.9%; + --muted-foreground: 217.9 10.6% 64.9%; + + --popover: 224 71.4% 4.1%; + --popover-foreground: 210 20% 98%; + + --card: 224 71.4% 4.1%; + --card-foreground: 210 20% 98%; + + --border: 215 27.9% 16.9%; + --input: 215 27.9% 16.9%; + + --primary: 263.4 70% 50.4%; + --primary-foreground: 210 20% 98%; + + --secondary: 215 27.9% 16.9%; + --secondary-foreground: 210 20% 98%; + + --accent: 215 27.9% 16.9%; + --accent-foreground: 210 20% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 20% 98%; + + --ring: 263.4 70% 50.4%; } \ No newline at end of file diff --git a/apps/www/public/registry/themes/gray.json b/apps/www/public/registry/themes/gray.json new file mode 100644 index 0000000000..81742502ab --- /dev/null +++ b/apps/www/public/registry/themes/gray.json @@ -0,0 +1,48 @@ +{ + "name": "gray", + "label": "Gray", + "cssVars": { + "light": { + "background": "0 0% 100%", + "foreground": "224 71.4% 4.1%", + "card": "0 0% 100%", + "card-foreground": "224 71.4% 4.1%", + "popover": "0 0% 100%", + "popover-foreground": "224 71.4% 4.1%", + "primary": "220.9 39.3% 11%", + "primary-foreground": "210 20% 98%", + "secondary": "220 14.3% 95.9%", + "secondary-foreground": "220.9 39.3% 11%", + "muted": "220 14.3% 95.9%", + "muted-foreground": "220 8.9% 46.1%", + "accent": "220 14.3% 95.9%", + "accent-foreground": "220.9 39.3% 11%", + "destructive": "0 84.2% 60.2%", + "destructive-foreground": "210 20% 98%", + "border": "220 13% 91%", + "input": "220 13% 91%", + "ring": "224 71.4% 4.1%" + }, + "dark": { + "background": "224 71.4% 4.1%", + "foreground": "210 20% 98%", + "card": "224 71.4% 4.1%", + "card-foreground": "210 20% 98%", + "popover": "224 71.4% 4.1%", + "popover-foreground": "210 20% 98%", + "primary": "210 20% 98%", + "primary-foreground": "220.9 39.3% 11%", + "secondary": "215 27.9% 16.9%", + "secondary-foreground": "210 20% 98%", + "muted": "215 27.9% 16.9%", + "muted-foreground": "217.9 10.6% 64.9%", + "accent": "215 27.9% 16.9%", + "accent-foreground": "210 20% 98%", + "destructive": "0 62.8% 30.6%", + "destructive-foreground": "210 20% 98%", + "border": "215 27.9% 16.9%", + "input": "215 27.9% 16.9%", + "ring": "216 12.2% 83.9%" + } + } +} \ No newline at end of file diff --git a/apps/www/public/registry/themes/neutral.json b/apps/www/public/registry/themes/neutral.json new file mode 100644 index 0000000000..e00dec7f4a --- /dev/null +++ b/apps/www/public/registry/themes/neutral.json @@ -0,0 +1,48 @@ +{ + "name": "neutral", + "label": "Neutral", + "cssVars": { + "light": { + "background": "0 0% 100%", + "foreground": "0 0% 3.9%", + "card": "0 0% 100%", + "card-foreground": "0 0% 3.9%", + "popover": "0 0% 100%", + "popover-foreground": "0 0% 3.9%", + "primary": "0 0% 9%", + "primary-foreground": "0 0% 98%", + "secondary": "0 0% 96.1%", + "secondary-foreground": "0 0% 9%", + "muted": "0 0% 96.1%", + "muted-foreground": "0 0% 45.1%", + "accent": "0 0% 96.1%", + "accent-foreground": "0 0% 9%", + "destructive": "0 84.2% 60.2%", + "destructive-foreground": "0 0% 98%", + "border": "0 0% 89.8%", + "input": "0 0% 89.8%", + "ring": "0 0% 3.9%" + }, + "dark": { + "background": "0 0% 3.9%", + "foreground": "0 0% 98%", + "card": "0 0% 3.9%", + "card-foreground": "0 0% 98%", + "popover": "0 0% 3.9%", + "popover-foreground": "0 0% 98%", + "primary": "0 0% 98%", + "primary-foreground": "0 0% 9%", + "secondary": "0 0% 14.9%", + "secondary-foreground": "0 0% 98%", + "muted": "0 0% 14.9%", + "muted-foreground": "0 0% 63.9%", + "accent": "0 0% 14.9%", + "accent-foreground": "0 0% 98%", + "destructive": "0 62.8% 30.6%", + "destructive-foreground": "0 0% 98%", + "border": "0 0% 14.9%", + "input": "0 0% 14.9%", + "ring": "0 0% 83.1%" + } + } +} \ No newline at end of file diff --git a/apps/www/public/registry/themes/slate.json b/apps/www/public/registry/themes/slate.json new file mode 100644 index 0000000000..7c72a9d6db --- /dev/null +++ b/apps/www/public/registry/themes/slate.json @@ -0,0 +1,48 @@ +{ + "name": "slate", + "label": "Slate", + "cssVars": { + "light": { + "background": "0 0% 100%", + "foreground": "222.2 84% 4.9%", + "card": "0 0% 100%", + "card-foreground": "222.2 84% 4.9%", + "popover": "0 0% 100%", + "popover-foreground": "222.2 84% 4.9%", + "primary": "222.2 47.4% 11.2%", + "primary-foreground": "210 40% 98%", + "secondary": "210 40% 96.1%", + "secondary-foreground": "222.2 47.4% 11.2%", + "muted": "210 40% 96.1%", + "muted-foreground": "215.4 16.3% 46.9%", + "accent": "210 40% 96.1%", + "accent-foreground": "222.2 47.4% 11.2%", + "destructive": "0 84.2% 60.2%", + "destructive-foreground": "210 40% 98%", + "border": "214.3 31.8% 91.4%", + "input": "214.3 31.8% 91.4%", + "ring": "222.2 84% 4.9%" + }, + "dark": { + "background": "222.2 84% 4.9%", + "foreground": "210 40% 98%", + "card": "222.2 84% 4.9%", + "card-foreground": "210 40% 98%", + "popover": "222.2 84% 4.9%", + "popover-foreground": "210 40% 98%", + "primary": "210 40% 98%", + "primary-foreground": "222.2 47.4% 11.2%", + "secondary": "217.2 32.6% 17.5%", + "secondary-foreground": "210 40% 98%", + "muted": "217.2 32.6% 17.5%", + "muted-foreground": "215 20.2% 65.1%", + "accent": "217.2 32.6% 17.5%", + "accent-foreground": "210 40% 98%", + "destructive": "0 62.8% 30.6%", + "destructive-foreground": "210 40% 98%", + "border": "217.2 32.6% 17.5%", + "input": "217.2 32.6% 17.5%", + "ring": "212.7 26.8% 83.9%" + } + } +} \ No newline at end of file diff --git a/apps/www/public/registry/themes/stone.json b/apps/www/public/registry/themes/stone.json new file mode 100644 index 0000000000..8ff9ab5cad --- /dev/null +++ b/apps/www/public/registry/themes/stone.json @@ -0,0 +1,48 @@ +{ + "name": "stone", + "label": "Stone", + "cssVars": { + "light": { + "background": "0 0% 100%", + "foreground": "20 14.3% 4.1%", + "card": "0 0% 100%", + "card-foreground": "20 14.3% 4.1%", + "popover": "0 0% 100%", + "popover-foreground": "20 14.3% 4.1%", + "primary": "24 9.8% 10%", + "primary-foreground": "60 9.1% 97.8%", + "secondary": "60 4.8% 95.9%", + "secondary-foreground": "24 9.8% 10%", + "muted": "60 4.8% 95.9%", + "muted-foreground": "25 5.3% 44.7%", + "accent": "60 4.8% 95.9%", + "accent-foreground": "24 9.8% 10%", + "destructive": "0 84.2% 60.2%", + "destructive-foreground": "60 9.1% 97.8%", + "border": "20 5.9% 90%", + "input": "20 5.9% 90%", + "ring": "20 14.3% 4.1%" + }, + "dark": { + "background": "20 14.3% 4.1%", + "foreground": "60 9.1% 97.8%", + "card": "20 14.3% 4.1%", + "card-foreground": "60 9.1% 97.8%", + "popover": "20 14.3% 4.1%", + "popover-foreground": "60 9.1% 97.8%", + "primary": "60 9.1% 97.8%", + "primary-foreground": "24 9.8% 10%", + "secondary": "12 6.5% 15.1%", + "secondary-foreground": "60 9.1% 97.8%", + "muted": "12 6.5% 15.1%", + "muted-foreground": "24 5.4% 63.9%", + "accent": "12 6.5% 15.1%", + "accent-foreground": "60 9.1% 97.8%", + "destructive": "0 62.8% 30.6%", + "destructive-foreground": "60 9.1% 97.8%", + "border": "12 6.5% 15.1%", + "input": "12 6.5% 15.1%", + "ring": "24 5.7% 82.9%" + } + } +} \ No newline at end of file diff --git a/apps/www/public/registry/themes/zinc.json b/apps/www/public/registry/themes/zinc.json new file mode 100644 index 0000000000..b69bd36288 --- /dev/null +++ b/apps/www/public/registry/themes/zinc.json @@ -0,0 +1,48 @@ +{ + "name": "zinc", + "label": "Zinc", + "cssVars": { + "light": { + "background": "0 0% 100%", + "foreground": "240 10% 3.9%", + "card": "0 0% 100%", + "card-foreground": "240 10% 3.9%", + "popover": "0 0% 100%", + "popover-foreground": "240 10% 3.9%", + "primary": "240 5.9% 10%", + "primary-foreground": "0 0% 98%", + "secondary": "240 4.8% 95.9%", + "secondary-foreground": "240 5.9% 10%", + "muted": "240 4.8% 95.9%", + "muted-foreground": "240 3.8% 46.1%", + "accent": "240 4.8% 95.9%", + "accent-foreground": "240 5.9% 10%", + "destructive": "0 84.2% 60.2%", + "destructive-foreground": "0 0% 98%", + "border": "240 5.9% 90%", + "input": "240 5.9% 90%", + "ring": "240 10% 3.9%" + }, + "dark": { + "background": "240 10% 3.9%", + "foreground": "0 0% 98%", + "card": "240 10% 3.9%", + "card-foreground": "0 0% 98%", + "popover": "240 10% 3.9%", + "popover-foreground": "0 0% 98%", + "primary": "0 0% 98%", + "primary-foreground": "240 5.9% 10%", + "secondary": "240 3.7% 15.9%", + "secondary-foreground": "0 0% 98%", + "muted": "240 3.7% 15.9%", + "muted-foreground": "240 5% 64.9%", + "accent": "240 3.7% 15.9%", + "accent-foreground": "0 0% 98%", + "destructive": "0 62.8% 30.6%", + "destructive-foreground": "0 0% 98%", + "border": "240 3.7% 15.9%", + "input": "240 3.7% 15.9%", + "ring": "240 4.9% 83.9%" + } + } +} \ No newline at end of file diff --git a/apps/www/public/schema.json b/apps/www/public/schema.json new file mode 100644 index 0000000000..bca169a2e8 --- /dev/null +++ b/apps/www/public/schema.json @@ -0,0 +1,44 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "style": { + "type": "string", + "enum": ["default"] + }, + "tailwind": { + "type": "object", + "properties": { + "config": { + "type": "string" + }, + "css": { + "type": "string" + }, + "baseColor": { + "type": "string" + }, + "cssVariables": { + "type": "boolean" + } + }, + "required": ["config", "css", "baseColor", "cssVariables"] + }, + "rsc": { + "type": "boolean" + }, + "aliases": { + "type": "object", + "properties": { + "utils": { + "type": "string" + }, + "components": { + "type": "string" + } + }, + "required": ["utils", "components"] + } + }, + "required": ["style", "tailwind", "rsc", "aliases"] +} diff --git a/apps/www/scripts/build-registry.ts b/apps/www/scripts/build-registry.ts index a7c933fc66..2f17e9abc1 100644 --- a/apps/www/scripts/build-registry.ts +++ b/apps/www/scripts/build-registry.ts @@ -224,18 +224,12 @@ export const BASE_STYLES_WITH_VARIABLES = `@tailwind base; :root { --background: <%- colors.light["background"] %>; --foreground: <%- colors.light["foreground"] %>; - - --muted: <%- colors.light["muted"] %>; - --muted-foreground: <%- colors.light["muted-foreground"] %>; - - --popover: <%- colors.light["popover"] %>; - --popover-foreground: <%- colors.light["popover-foreground"] %>; - + --card: <%- colors.light["card"] %>; --card-foreground: <%- colors.light["card-foreground"] %>; - --border: <%- colors.light["border"] %>; - --input: <%- colors.light["input"] %>; + --popover: <%- colors.light["popover"] %>; + --popover-foreground: <%- colors.light["popover-foreground"] %>; --primary: <%- colors.light["primary"] %>; --primary-foreground: <%- colors.light["primary-foreground"] %>; @@ -243,12 +237,17 @@ export const BASE_STYLES_WITH_VARIABLES = `@tailwind base; --secondary: <%- colors.light["secondary"] %>; --secondary-foreground: <%- colors.light["secondary-foreground"] %>; + --muted: <%- colors.light["muted"] %>; + --muted-foreground: <%- colors.light["muted-foreground"] %>; + --accent: <%- colors.light["accent"] %>; --accent-foreground: <%- colors.light["accent-foreground"] %>; --destructive: <%- colors.light["destructive"] %>; --destructive-foreground: <%- colors.light["destructive-foreground"] %>; - + + --border: <%- colors.light["border"] %>; + --input: <%- colors.light["input"] %>; --ring: <%- colors.light["ring"] %>; --radius: 0.5rem; @@ -258,17 +257,11 @@ export const BASE_STYLES_WITH_VARIABLES = `@tailwind base; --background: <%- colors.dark["background"] %>; --foreground: <%- colors.dark["foreground"] %>; - --muted: <%- colors.dark["muted"] %>; - --muted-foreground: <%- colors.dark["muted-foreground"] %>; - - --popover: <%- colors.dark["popover"] %>; - --popover-foreground: <%- colors.dark["popover-foreground"] %>; - --card: <%- colors.dark["card"] %>; --card-foreground: <%- colors.dark["card-foreground"] %>; - --border: <%- colors.dark["border"] %>; - --input: <%- colors.dark["input"] %>; + --popover: <%- colors.dark["popover"] %>; + --popover-foreground: <%- colors.dark["popover-foreground"] %>; --primary: <%- colors.dark["primary"] %>; --primary-foreground: <%- colors.dark["primary-foreground"] %>; @@ -276,12 +269,17 @@ export const BASE_STYLES_WITH_VARIABLES = `@tailwind base; --secondary: <%- colors.dark["secondary"] %>; --secondary-foreground: <%- colors.dark["secondary-foreground"] %>; + --muted: <%- colors.dark["muted"] %>; + --muted-foreground: <%- colors.dark["muted-foreground"] %>; + --accent: <%- colors.dark["accent"] %>; --accent-foreground: <%- colors.dark["accent-foreground"] %>; --destructive: <%- colors.dark["destructive"] %>; --destructive-foreground: <%- colors.dark["destructive-foreground"] %>; + --border: <%- colors.dark["border"] %>; + --input: <%- colors.dark["input"] %>; --ring: <%- colors.dark["ring"] %>; } } @@ -295,7 +293,7 @@ export const BASE_STYLES_WITH_VARIABLES = `@tailwind base; } }`; -for (const baseColor of ['slate', 'gray', 'zinc', 'neutral', 'stone', 'lime']) { +for (const baseColor of ['slate', 'gray', 'zinc', 'neutral', 'stone']) { const base: Record = { inlineColors: {}, cssVars: {}, @@ -371,7 +369,7 @@ export const THEME_STYLES_WITH_VARIABLES = ` --ring: <%- colors.light["ring"] %>; - --radius: 0.5rem; + --radius: <%- colors.light["radius"] %>; } .dark .theme-<%- theme %> { @@ -417,4 +415,49 @@ for (const theme of themes) { writeFile(path.join(REGISTRY_PATH, `themes.css`), themeCSS.join('\n'), 'utf8'); +// ---------------------------------------------------------------------------- +// Build registry/themes/[theme].json +// ---------------------------------------------------------------------------- +rimraf.sync(path.join(REGISTRY_PATH, 'themes')); +for (const baseColor of ['slate', 'gray', 'zinc', 'neutral', 'stone']) { + const payload = { + name: baseColor, + label: baseColor.charAt(0).toUpperCase() + baseColor.slice(1), + cssVars: {}, + }; + + for (const [mode, values] of Object.entries(colorMapping)) { + payload['cssVars'][mode] = {}; + for (const [key, value] of Object.entries(values)) { + if (typeof value === 'string') { + const resolvedColor = value.replaceAll('{{base}}-', `${baseColor}-`); + payload['cssVars'][mode][key] = resolvedColor; + + const [resolvedBase, scale] = resolvedColor.split('-'); + const color = scale + ? colorsData[resolvedBase].find( + (item) => item.scale === Number.parseInt(scale) + ) + : colorsData[resolvedBase]; + if (color) { + payload['cssVars'][mode][key] = color.hslChannel; + } + } + } + } + + const targetPath = path.join(REGISTRY_PATH, 'themes'); + + // Create directory if it doesn't exist. + if (!fs.existsSync(targetPath)) { + fs.mkdirSync(targetPath, { recursive: true }); + } + + fs.writeFileSync( + path.join(targetPath, `${payload.name}.json`), + JSON.stringify(payload, null, 2), + 'utf8' + ); +} + console.info('✅ Done!'); diff --git a/apps/www/src/__registry__/index.tsx b/apps/www/src/__registry__/index.tsx index e84e2be308..9d95513583 100644 --- a/apps/www/src/__registry__/index.tsx +++ b/apps/www/src/__registry__/index.tsx @@ -4,6 +4,13 @@ import * as React from 'react' export const Index: Record = { 'default': { + 'editor': { + name: 'editor', + type: 'components:plate-ui', + registryDependencies: [], + files: ['registry/default/plate-ui/editor.tsx'], + component: React.lazy(() => import('@/registry/default/plate-ui/editor')), + }, 'cloud': { name: 'cloud', type: 'components:plate-ui', @@ -616,7 +623,7 @@ export const Index: Record = { 'table-element': { name: 'table-element', type: 'components:plate-ui', - registryDependencies: [], + registryDependencies: ["dropdown-menu"], files: ['registry/default/plate-ui/table-element.tsx'], component: React.lazy(() => import('@/registry/default/plate-ui/table-element')), }, @@ -630,7 +637,7 @@ export const Index: Record = { 'todo-list-element': { name: 'todo-list-element', type: 'components:plate-ui', - registryDependencies: [], + registryDependencies: ["checkbox"], files: ['registry/default/plate-ui/todo-list-element.tsx'], component: React.lazy(() => import('@/registry/default/plate-ui/todo-list-element')), }, @@ -669,6 +676,55 @@ export const Index: Record = { files: ['registry/default/plate-ui/resizable.tsx'], component: React.lazy(() => import('@/registry/default/plate-ui/resizable')), }, + 'editor-default': { + name: 'editor-default', + type: 'components:example', + registryDependencies: [], + files: ['registry/default/example/editor-default.tsx'], + component: React.lazy(() => import('@/registry/default/example/editor-default')), + }, + 'editor-disabled': { + name: 'editor-disabled', + type: 'components:example', + registryDependencies: [], + files: ['registry/default/example/editor-disabled.tsx'], + component: React.lazy(() => import('@/registry/default/example/editor-disabled')), + }, + 'editor-ghost': { + name: 'editor-ghost', + type: 'components:example', + registryDependencies: [], + files: ['registry/default/example/editor-ghost.tsx'], + component: React.lazy(() => import('@/registry/default/example/editor-ghost')), + }, + 'editor-label': { + name: 'editor-label', + type: 'components:example', + registryDependencies: [], + files: ['registry/default/example/editor-label.tsx'], + component: React.lazy(() => import('@/registry/default/example/editor-label')), + }, + 'editor-text': { + name: 'editor-text', + type: 'components:example', + registryDependencies: [], + files: ['registry/default/example/editor-text.tsx'], + component: React.lazy(() => import('@/registry/default/example/editor-text')), + }, + 'editor-button': { + name: 'editor-button', + type: 'components:example', + registryDependencies: [], + files: ['registry/default/example/editor-button.tsx'], + component: React.lazy(() => import('@/registry/default/example/editor-button')), + }, + 'editor-form': { + name: 'editor-form', + type: 'components:example', + registryDependencies: [], + files: ['registry/default/example/editor-form.tsx'], + component: React.lazy(() => import('@/registry/default/example/editor-form')), + }, 'basic-editor-default-demo': { name: 'basic-editor-default-demo', type: 'components:example', @@ -676,6 +732,13 @@ export const Index: Record = { files: ['registry/default/example/basic-editor-default-demo.tsx'], component: React.lazy(() => import('@/registry/default/example/basic-editor-default-demo')), }, + 'basic-editor-styling-demo': { + name: 'basic-editor-styling-demo', + type: 'components:example', + registryDependencies: [], + files: ['registry/default/example/basic-editor-styling-demo.tsx'], + component: React.lazy(() => import('@/registry/default/example/basic-editor-styling-demo')), + }, 'basic-editor-handler-demo': { name: 'basic-editor-handler-demo', type: 'components:example', diff --git a/apps/www/src/app/_components/home-tabs.tsx b/apps/www/src/app/_components/home-tabs.tsx new file mode 100644 index 0000000000..d3ea6515ee --- /dev/null +++ b/apps/www/src/app/_components/home-tabs.tsx @@ -0,0 +1,79 @@ +'use client'; + +import { useEffect } from 'react'; +import dynamic from 'next/dynamic'; +import { Settings2 } from 'lucide-react'; +import { useQueryState } from 'next-usequerystate'; + +import { cn } from '@/lib/utils'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { settingsStore } from '@/components/context/settings-store'; +import PlaygroundDemo from '@/registry/default/example/playground-demo'; +import { Button } from '@/registry/default/plate-ui/button'; + +const InstallationTab = dynamic(() => import('./installation-tab')); + +export default function HomeTabs() { + const active = settingsStore.use.showSettings(); + const homeTab = settingsStore.use.homeTab(); + const [builder, setBuilder] = useQueryState('builder'); + + useEffect(() => { + if (builder === 'true') { + settingsStore.set.showSettings(true); + } + }, [builder]); + + useEffect(() => { + if (active) { + void setBuilder('true'); + } else { + void setBuilder(null); + } + }, [active, setBuilder]); + + return ( +
+ { + settingsStore.set.homeTab(value); + }} + > + + Playground + Installation + + + + + +
+ +
+
+ +
+ +
+
+
+
+ ); +} diff --git a/apps/www/src/app/_components/installation-code.tsx b/apps/www/src/app/_components/installation-code.tsx new file mode 100644 index 0000000000..86c43a7225 --- /dev/null +++ b/apps/www/src/app/_components/installation-code.tsx @@ -0,0 +1,51 @@ +// Pre is deeply coupled to Contentlayer, so we need a wrapper to make it work +import * as React from 'react'; +import { ReactNode } from 'react'; +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; +import { vscDarkPlus as theme } from 'react-syntax-highlighter/dist/esm/styles/prism'; + +import { cn } from '@/lib/utils'; +import { CopyButton, CopyNpmCommandButton } from '@/components/copy-button'; +import * as Typography from '@/components/typography'; + +export function InstallationCode({ + code, + children, + bash, +}: { + code: string; + children?: ReactNode; + bash?: boolean; +}) { + const npmCommand = code.startsWith('npm install'); + + return ( +
+ {!!children && {children}} + +
+ + {code} + + + {npmCommand ? ( + + ) : ( + + )} +
+
+ ); +} diff --git a/apps/www/src/app/_components/installation-tab.tsx b/apps/www/src/app/_components/installation-tab.tsx new file mode 100644 index 0000000000..a74c5acdec --- /dev/null +++ b/apps/www/src/app/_components/installation-tab.tsx @@ -0,0 +1,458 @@ +'use client'; + +import * as React from 'react'; +import { useMemo } from 'react'; +import { KEY_DND } from '@udecode/plate-dnd'; +import { uniqBy } from 'lodash'; + +import { allPlugins, orderedPluginKeys } from '@/config/customizer-list'; +import { useMounted } from '@/hooks/use-mounted'; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from '@/components/ui/accordion'; +import { settingsStore } from '@/components/context/settings-store'; +import { Link } from '@/components/link'; +import * as Typography from '@/components/typography'; +import { H2, Step, Steps } from '@/components/typography'; + +import { InstallationCode } from './installation-code'; + +function getEditorCodeGeneratorResult({ checkedPlugins, checkedComponents }) { + const plugins = allPlugins.filter((plugin) => { + return checkedPlugins[plugin.id]; + }); + + const components = plugins + .flatMap((plugin) => plugin.components ?? []) + .filter((component) => checkedComponents[component.id]); + + const componentsById = uniqBy(components, 'id'); + + const orderedPlugins = plugins.sort((a, b) => { + const indexOfA = orderedPluginKeys.indexOf(a.id); + const indexOfB = orderedPluginKeys.indexOf(b.id); + + if (indexOfA === -1 || indexOfB === -1) { + return 0; + } + + return indexOfA - indexOfB; + }); + + return { + plugins: orderedPlugins, + components, + componentsById, + }; +} + +export default function InstallationTab() { + const checkedPlugins = settingsStore.use.checkedPlugins(); + const checkedComponents = settingsStore.use.checkedComponents(); + const mounted = useMounted(); + + // Assign initial values to plugins and components using useMemo + const { plugins, components } = useMemo( + () => getEditorCodeGeneratorResult({ checkedPlugins, checkedComponents }), + [checkedComponents, checkedPlugins] + ); + const somePlugins = useMemo(() => plugins.length > 0, [plugins]); + const someComponents = useMemo(() => components.length > 0, [components]); + + // Assign componentsWithPluginKey using useMemo + const componentsWithPluginKey = useMemo( + () => components.filter((component) => component.pluginKey), + [components] + ); + + // Create plateImports string + const plateImports = useMemo(() => { + const combinedArray = [...plugins, ...components]; + + const uniqueImports = combinedArray.reduce( + (acc, { plateImports: _plateImports }) => { + if (_plateImports) { + _plateImports.forEach((importItem) => acc.add(importItem)); + } + return acc; + }, + new Set() + ); + + return Array.from(uniqueImports).join(', '); + }, [plugins, components]); + + const installCommands = useMemo(() => { + return { + plugins: `npm install ${Array.from( + plugins.reduce((uniquePackages, { npmPackage }) => { + if (npmPackage) { + uniquePackages.add(npmPackage); + } + return uniquePackages; + }, new Set()) + ).join(' ')}`, + components: `npx @udecode/plate-ui@latest add ${Array.from( + components.reduce( + (uniqueFilenames, { id, registry, filename, noImport }) => { + if (noImport) return uniqueFilenames; + + uniqueFilenames.add(registry ?? filename ?? id); + return uniqueFilenames; + }, + new Set() + ) + ).join(' ')}`, + }; + }, [plugins, components]); + + const componentImports = useMemo(() => { + return components.reduce( + (acc, component) => { + if (component.noImport) return acc; + + const importKey = component.filename ?? component.id; + const importValue = component.import ?? component.usage; + + if (!acc[importKey]) { + acc[importKey] = new Set(); + } + acc[importKey].add(importValue); + + return acc; + }, + {} as Record> + ); + }, [components]); + + const groupedImportsByPackage = useMemo(() => { + const grouped = {} as Record>; + + // Add pluginFactory and pluginKey from plugins + plugins.forEach((plugin) => { + if (!plugin.npmPackage) return; + + if (!grouped[plugin.npmPackage]) { + grouped[plugin.npmPackage] = new Set(); + } + + if (plugin.pluginFactory) { + grouped[plugin.npmPackage].add(plugin.pluginFactory); + } + + plugin.packageImports?.forEach((packageImport) => { + if (plugin.npmPackage) { + grouped[plugin.npmPackage].add(packageImport); + } + }); + + plugin.components?.forEach((component) => { + if ( + plugin.npmPackage && + component.pluginKey && + componentsWithPluginKey.includes(component) + ) { + grouped[plugin.npmPackage].add(component.pluginKey); + } + }); + }); + + return grouped; + }, [componentsWithPluginKey, plugins]); + + const customImports = useMemo(() => { + const res: string[] = []; + + for (const plugin of plugins) { + if (plugin.customImports) { + // add each custom import to the customImportGroups + for (const importLine of plugin.customImports) { + res.push(importLine); + } + } + } + return res; + }, [plugins]); + + const hasEditor = components.some((comp) => comp.id === 'editor'); + + const importsCode = useMemo(() => { + const importsGroups = Object.entries(groupedImportsByPackage).map( + ([packageName, imports]) => + `import { ${Array.from(imports).join(', ')} } from '${packageName}';` + ); + const componentImportsGroup = Object.entries(componentImports).map( + ([componentId, importValues]) => + `import { ${Array.from(importValues).join( + ', ' + )} } from '@/components/plate-ui/${componentId}';` + ); + return [ + `import { createPlugins, Plate${hasEditor ? '' : ', PlateContent'}${ + plateImports.length > 0 ? ', ' + plateImports : '' + } } from '@udecode/plate-common';`, + ...importsGroups, + ...customImports, + '', + ...componentImportsGroup, + ].join('\n'); + }, [componentImports, customImports, groupedImportsByPackage, plateImports]); + + const pluginsCode: string[] = []; + + plugins.forEach( + ({ pluginFactory, pluginOptions, components: pluginComponents }) => { + if (!pluginFactory) return; + + let componentOptions = ''; + pluginComponents?.forEach((component) => { + if (component.pluginOptions && components.includes(component)) { + componentOptions = [ + `${component.pluginOptions + .map((option) => `${option}`) + .join('\n ')}`, + ].join('\n'); + } + }); + + let options = ''; + if (pluginOptions) { + options = pluginOptions.map((option) => `${option}`).join('\n '); + } + + let allOptions: string[] = []; + if (componentOptions || pluginOptions) { + allOptions = [`{`, ` ${options}${componentOptions}`, ` }`]; + } + + pluginsCode.push(` ${pluginFactory}(${allOptions.join('\n')}),`); + } + ); + + const hasDraggable = components.some((comp) => comp.id === 'draggable'); + const hasPlaceholder = components.some((comp) => comp.id === 'placeholder'); + + const usageCode = [ + 'const plugins = createPlugins(', + ' [', + pluginsCode.join('\n'), + ' ],', + ' {', + ` components: ${hasDraggable ? 'withDraggables(' : ''}${ + hasPlaceholder ? 'withPlaceholders(' : '' + }{`, + ...componentsWithPluginKey.map( + ({ pluginKey, usage }) => ` [${pluginKey}]: ${usage},` + ), + ` }${hasPlaceholder ? ')' : ''}${hasDraggable ? ')' : ''},`, + ` }`, + ');', + ].join('\n'); + + const hasDnd = plugins.some((plugin) => plugin.id === KEY_DND); + + const hasCommentsPopover = components.some( + (comp) => comp.id === 'comments-popover' + ); + const hasMentionCombobox = components.some( + (comp) => comp.id === 'mention-combobox' + ); + const hasFixedToolbar = components.some( + (comp) => comp.id === 'fixed-toolbar' + ); + const hasFixedToolbarButtons = components.some( + (comp) => comp.id === 'fixed-toolbar-buttons' + ); + const hasFloatingToolbar = components.some( + (comp) => comp.id === 'floating-toolbar' + ); + const hasFloatingToolbarButtons = components.some( + (comp) => comp.id === 'floating-toolbar-buttons' + ); + + let indentLevel = 0; + const jsxCode: string[] = []; + + const addLine = ( + line: string, + opensBlock: boolean = false, + closesBlock: boolean = false + ) => { + if (closesBlock && indentLevel > 0) { + indentLevel--; + } + + const tabs = Array.from({ length: indentLevel }).fill(' ').join(''); // double spaces for each level + jsxCode.push(`${tabs}${line}`); + + if (opensBlock) { + indentLevel++; + } + }; + + if (hasDnd) { + addLine(``, true); + } + + if (hasCommentsPopover) { + addLine(``, true); + } + + addLine(``, true); + + if (hasFixedToolbar) { + addLine(``, true); + } + + if (hasFixedToolbarButtons) { + addLine(``); + } + + if (hasFixedToolbar) { + addLine(``, false, true); + addLine(``); + } + + addLine(`<${hasEditor ? 'Editor' : 'PlateContent'} />`); + + if (hasFloatingToolbar) { + addLine(``); + addLine(``, true); + } + + if (hasFloatingToolbarButtons) { + addLine(``); + } + + if (hasFloatingToolbar) { + addLine(``, false, true); + } + + if (hasMentionCombobox) { + addLine(``); + } + + if (hasCommentsPopover) { + addLine(``); + } + + addLine(``, false, true); + + if (hasCommentsPopover) { + addLine(``, false, true); + } + + if (hasDnd) { + addLine(``, false, true); + } + + const plateCode = [ + `const initialValue = [`, + ` {`, + ` id: '1',`, + ` type: 'p',`, + ` children: [{ text: 'Hello, World!' }],`, + ` },`, + `];`, + ``, + `export function PlateEditor() {`, + ` return (`, + ` ${jsxCode.join('\n ')}`, + ` );`, + `}`, + ].join('\n'); + + const fullCode = [`'use client';`, importsCode, usageCode, plateCode].join( + '\n\n' + ); + + if (!mounted) return null; + + return ( + <> +

Installation

+ + + Here is your personalized installation guide based on the + plugins and components you have selected.
+ For a more general guide, please refer to the{' '} + + Getting Started + {' '} + section. +
+ + + Install Plate + + Start from our{' '} + + template + {' '} + or install the peer dependencies and Plate: + + {somePlugins && ( + <> + Install Plugins + + Install your selected plugins: + + + )} + {someComponents && ( + <> + Add Components + + + Install the dependencies for the components + {' '} + and{' '} + + configure the CLI + + . Then, add the components you have selected: + + + )} + Imports + + All the imports you need: + + Create Plugins + + Create your plugins and link your components into them. + + Finally, render the editor + + + + + + Full code + + + + + + + + + ); +} diff --git a/apps/www/src/app/announcement-button.tsx b/apps/www/src/app/announcement-button.tsx new file mode 100644 index 0000000000..883e1d3f95 --- /dev/null +++ b/apps/www/src/app/announcement-button.tsx @@ -0,0 +1,25 @@ +'use client'; + +import * as React from 'react'; +import { ChevronRight } from 'lucide-react'; + +import { settingsStore } from '@/components/context/settings-store'; +import { Button } from '@/registry/default/plate-ui/button'; +import { Separator } from '@/registry/default/plate-ui/separator'; + +export function AnnouncementButton() { + return ( + + ); +} diff --git a/apps/www/src/app/docs/[[...slug]]/page.tsx b/apps/www/src/app/docs/[[...slug]]/page.tsx index a33eabda4b..822ed92a57 100644 --- a/apps/www/src/app/docs/[[...slug]]/page.tsx +++ b/apps/www/src/app/docs/[[...slug]]/page.tsx @@ -201,9 +201,11 @@ export default async function DocPage({ params }: DocPageProps) { {doc.toc && (
-
+
- +
+ +
diff --git a/apps/www/src/app/layout.tsx b/apps/www/src/app/layout.tsx index 15cbd3a72d..d4ddb87dbe 100644 --- a/apps/www/src/app/layout.tsx +++ b/apps/www/src/app/layout.tsx @@ -11,6 +11,7 @@ import { Toaster as NewYorkToaster, } from '@/components/ui/toaster'; import { Analytics } from '@/components/analytics'; +import { Body } from '@/components/body'; import { Providers } from '@/components/context/providers'; import { SiteFooter } from '@/components/site-footer'; import { SiteHeader } from '@/components/site-header'; @@ -84,9 +85,11 @@ export default function RootLayout({ children }: RootLayoutProps) { return ( - {children}
- + - + ); } diff --git a/apps/www/src/app/page.tsx b/apps/www/src/app/page.tsx index fbc8827dc6..e99de64a1a 100644 --- a/apps/www/src/app/page.tsx +++ b/apps/www/src/app/page.tsx @@ -1,5 +1,13 @@ +import dynamic from 'next/dynamic'; import Link from 'next/link'; -import { ChevronRight } from 'lucide-react'; + +import { ThemesButton } from '@/components/themes-button'; + +import { AnnouncementButton } from './announcement-button'; + +import '../../public/registry/themes.css'; + +import * as React from 'react'; import { siteConfig } from '@/config/site'; import { cn } from '@/lib/utils'; @@ -9,55 +17,51 @@ import { PageHeaderDescription, PageHeaderHeading, } from '@/components/page-header'; -import PlaygroundDemo from '@/registry/default/example/playground-demo'; import { buttonVariants } from '@/registry/default/plate-ui/button'; -import { Separator } from '@/registry/default/plate-ui/separator'; + +const HomeTabs = dynamic(() => import('./_components/home-tabs')); +const CustomizerDrawer = dynamic( + () => import('@/components/customizer-drawer') +); export default function IndexPage() { return (
- - - 🎉 {' '} - Introducing Plate UI, a new CLI and more. - - - Build your rich-text editor. - - Plugin system & primitive component library.
- CLI for styled components. Customizable. Open Source. -
-
- - Get Started - - - - GitHub - -
-
+
+ + - {/*
*/} - {/*

Playground

*/} - {/*
*/} - {/* */} - {/*
*/} - {/*
*/} +
+ Build your rich-text editor. +
+ +
+
+ + Plugin system & primitive component library.
+ CLI for styled components. Customizable. Open Source. +
+
+ + Get Started + + + + GitHub + +
+
+
-
- -
+ + +
); diff --git a/apps/www/src/components/body.tsx b/apps/www/src/components/body.tsx new file mode 100644 index 0000000000..120e21f005 --- /dev/null +++ b/apps/www/src/components/body.tsx @@ -0,0 +1,44 @@ +'use client'; + +/* eslint-disable tailwindcss/no-custom-classname */ +import { usePathname } from 'next/navigation'; + +import { cn } from '@/lib/utils'; +import { useConfig } from '@/hooks/use-config'; +import { useMounted } from '@/hooks/use-mounted'; + +interface ThemeBodyProps extends React.ComponentProps<'body'> { + defaultTheme?: string; +} + +export function Body({ + defaultTheme, + children, + className, + ...props +}: ThemeBodyProps) { + const [config] = useConfig(); + const pathname = usePathname(); + const mounted = useMounted(); + + const theme = + mounted && pathname === '/' + ? `theme-${config.theme ?? defaultTheme}` + : `theme-${defaultTheme}`; + + return ( + + {children} + + ); +} diff --git a/apps/www/src/components/command-menu.tsx b/apps/www/src/components/command-menu.tsx index 4f71122cc4..aa8acc7b42 100644 --- a/apps/www/src/components/command-menu.tsx +++ b/apps/www/src/components/command-menu.tsx @@ -46,7 +46,7 @@ export function CommandItems({ {item.headings?.map((heading) => { return ( { runCommand(() => router.push( diff --git a/apps/www/src/components/component-preview.tsx b/apps/www/src/components/component-preview.tsx index e6722f1d66..1561e40f33 100644 --- a/apps/www/src/components/component-preview.tsx +++ b/apps/www/src/components/component-preview.tsx @@ -10,7 +10,6 @@ import { styles } from '@/registry/styles'; import { CopyButton, CopyWithClassNames } from './copy-button'; import { Icons } from './icons'; import { StyleSwitcher } from './style-switcher'; -import { ThemeWrapper } from './theme-wrapper'; import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; interface ComponentPreviewProps extends React.HTMLAttributes { @@ -100,32 +99,30 @@ export function ComponentPreview({ )} )} - - - - Loading... - - } - > -
-
{Preview}
+ + + Loading...
-
-
+ } + > +
+
{Preview}
+
+
diff --git a/apps/www/src/components/context/providers.tsx b/apps/www/src/components/context/providers.tsx index ac5dfd23cc..38e71a8258 100644 --- a/apps/www/src/components/context/providers.tsx +++ b/apps/www/src/components/context/providers.tsx @@ -6,7 +6,12 @@ import { ThemeProvider } from './theme-provider'; export function Providers({ children }) { return ( - + item.id); +export const categoryIds = customizerList.map((item) => item.id); + +const defaultCheckedComponents = {} as Record; -const defaultCheckedPlugins = settingPlugins.reduce( +const defaultCheckedPlugins = customizerList.reduce( (acc, item) => { item.children.forEach((child) => { + child.components?.forEach((component) => { + defaultCheckedComponents[component.id] = true; + }); + acc[child.id] = true; }); return acc; }, - {} as Record + {} as Record ); export const getDefaultCheckedPlugins = () => { @@ -27,20 +31,32 @@ export const getDefaultCheckedPlugins = () => { normalizeTypes: false, singleLine: false, list: false, - } as Record; + } as Record; +}; + +export const getDefaultCheckedComponents = () => { + return { + ...defaultCheckedComponents, + } as Record; }; export const settingsStore = createStore('settings')({ - showSettings: true, + showSettings: false, + loadingSettings: true, + showComponents: true, + homeTab: 'playground', + // homeTab: 'installation', + customizerTab: 'plugins', - valueId: settingValues.playground.id, + valueId: customizerPlugins.playground.id, checkedPluginsNext: getDefaultCheckedPlugins(), checkedPlugins: getDefaultCheckedPlugins(), + checkedComponents: getDefaultCheckedComponents(), }) .extendActions((set) => ({ - reset: ({ + resetPlugins: ({ exclude, }: { exclude?: string[]; @@ -53,19 +69,32 @@ export const settingsStore = createStore('settings')({ }); }); }, - setCheckedIdNext: (id: CheckedId | CheckedId[], checked: boolean) => { + resetComponents: ({ + exclude, + }: { + exclude?: string[]; + } = {}) => { + set.state((draft) => { + draft.checkedComponents = getDefaultCheckedComponents(); + + exclude?.forEach((item) => { + draft.checkedComponents[item] = false; + }); + }); + }, + setCheckedIdNext: (id: string | string[], checked: boolean) => { set.state((draft) => { draft.checkedPluginsNext = { ...draft.checkedPluginsNext }; const conflicts = - (settingPluginItems[id as string] as SettingPlugin)?.conflicts ?? []; + (customizerItems[id as string] as SettingPlugin)?.conflicts ?? []; conflicts.forEach((item) => { if (!draft.checkedPluginsNext[item]) return; draft.checkedPluginsNext[item] = false; - const label = settingPluginItems[item]?.label; + const label = customizerItems[item]?.label; if (label) { toast({ description: `${label} plugin disabled.`, @@ -77,6 +106,11 @@ export const settingsStore = createStore('settings')({ draft.checkedPluginsNext[id as string] = checked; }); }, + setCheckedComponentId: (id: string | string[], checked: boolean) => { + set.state((draft) => { + draft.checkedComponents[id as string] = checked; + }); + }, syncChecked: () => { set.state((draft) => { draft.checkedPlugins = { ...draft.checkedPluginsNext }; @@ -84,6 +118,7 @@ export const settingsStore = createStore('settings')({ }, })) .extendSelectors((get) => ({ - checkedIdNext: (id: CheckedId) => get.checkedPluginsNext[id], - checkedId: (id: CheckedId) => get.checkedPlugins[id], + checkedIdNext: (id: string) => get.checkedPluginsNext[id], + checkedId: (id: string) => get.checkedPlugins[id], + checkedComponentId: (id: string) => get.checkedComponents[id], })); diff --git a/apps/www/src/components/copy-button.tsx b/apps/www/src/components/copy-button.tsx index 3bb4f951d4..0c8bb437eb 100644 --- a/apps/www/src/components/copy-button.tsx +++ b/apps/www/src/components/copy-button.tsx @@ -22,7 +22,7 @@ interface CopyButtonProps extends React.HTMLAttributes { event?: Event['name']; } -async function copyToClipboardWithMeta(value: string, event?: Event) { +export async function copyToClipboardWithMeta(value: string, event?: Event) { navigator.clipboard.writeText(value); if (event) { trackEvent(event); @@ -49,7 +49,7 @@ export function CopyButton({ size="icon" variant="ghost" className={cn( - 'relative z-10 h-6 w-6 text-zinc-50 hover:bg-zinc-700 hover:text-zinc-50', + 'relative z-10 h-6 w-6 text-slate-50 hover:bg-slate-700 hover:text-slate-50', className )} onClick={() => { @@ -109,7 +109,7 @@ export function CopyWithClassNames({ size="icon" variant="ghost" className={cn( - 'relative z-10 h-6 w-6 text-zinc-50 hover:bg-zinc-700 hover:text-zinc-50', + 'relative z-10 h-6 w-6 text-slate-50 hover:bg-slate-700 hover:text-slate-50', className )} > @@ -172,7 +172,7 @@ export function CopyNpmCommandButton({ size="icon" variant="ghost" className={cn( - 'relative z-10 h-6 w-6 text-zinc-50 hover:bg-zinc-700 hover:text-zinc-50', + 'relative z-10 h-6 w-6 text-slate-50 hover:bg-slate-700 hover:text-slate-50', className )} > diff --git a/apps/www/src/components/copy-code-button.tsx b/apps/www/src/components/copy-code-button.tsx new file mode 100644 index 0000000000..4d986924ba --- /dev/null +++ b/apps/www/src/components/copy-code-button.tsx @@ -0,0 +1,284 @@ +import * as React from 'react'; +import { CheckIcon, CopyIcon } from '@radix-ui/react-icons'; +import template from 'lodash.template'; + +import { useConfig } from '@/hooks/use-config'; +import { Button } from '@/registry/default/plate-ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from '@/registry/default/plate-ui/dialog'; +import { Theme, themes } from '@/registry/themes'; + +import { copyToClipboardWithMeta } from './copy-button'; + +export function CopyCodeButton() { + const [config] = useConfig(); + const activeTheme = themes.find((theme) => theme.name === config.theme); + const [hasCopied, setHasCopied] = React.useState(false); + + React.useEffect(() => { + setTimeout(() => { + setHasCopied(false); + }, 2000); + }, [hasCopied]); + + return ( + <> + {activeTheme && ( + + )} + + + + + + + Theme + + Copy and paste the following code into your CSS file. + + +
+ + {activeTheme && ( + + )} +
+
+
+ + ); +} + +function CustomizerCode() { + const [config] = useConfig(); + const activeTheme = themes.find((theme) => theme.name === config.theme); + + return ( +
+
+
+          
+            @layer base {
+              :root {
+            
+                  --background:{' '}
+              {activeTheme?.cssVars.light['background']};
+            
+            
+                  --foreground:{' '}
+              {activeTheme?.cssVars.light['foreground']};
+            
+            {[
+              'card',
+              'popover',
+              'primary',
+              'secondary',
+              'muted',
+              'accent',
+              'destructive',
+            ].map((prefix) => (
+              <>
+                
+                      --{prefix}:{' '}
+                  {
+                    activeTheme?.cssVars.light[
+                      prefix as keyof typeof activeTheme.cssVars.light
+                    ]
+                  }
+                  ;
+                
+                
+                      --{prefix}-foreground:{' '}
+                  {
+                    activeTheme?.cssVars.light[
+                      `${prefix}-foreground` as keyof typeof activeTheme.cssVars.light
+                    ]
+                  }
+                  ;
+                
+              
+            ))}
+            
+                  --border:{' '}
+              {activeTheme?.cssVars.light['border']};
+            
+            
+                  --input:{' '}
+              {activeTheme?.cssVars.light['input']};
+            
+            
+                  --ring:{' '}
+              {activeTheme?.cssVars.light['ring']};
+            
+            
+                  --radius: {config.radius}rem;
+            
+              }
+             
+              .dark {
+            
+                  --background:{' '}
+              {activeTheme?.cssVars.dark['background']};
+            
+            
+                  --foreground:{' '}
+              {activeTheme?.cssVars.dark['foreground']};
+            
+            {[
+              'card',
+              'popover',
+              'primary',
+              'secondary',
+              'muted',
+              'accent',
+              'destructive',
+            ].map((prefix) => (
+              <>
+                
+                      --{prefix}:{' '}
+                  {
+                    activeTheme?.cssVars.dark[
+                      prefix as keyof typeof activeTheme.cssVars.dark
+                    ]
+                  }
+                  ;
+                
+                
+                      --{prefix}-foreground:{' '}
+                  {
+                    activeTheme?.cssVars.dark[
+                      `${prefix}-foreground` as keyof typeof activeTheme.cssVars.dark
+                    ]
+                  }
+                  ;
+                
+              
+            ))}
+            
+                  --border:{' '}
+              {activeTheme?.cssVars.dark['border']};
+            
+            
+                  --input:{' '}
+              {activeTheme?.cssVars.dark['input']};
+            
+            
+                  --ring:{' '}
+              {activeTheme?.cssVars.dark['ring']};
+            
+              }
+            }
+          
+        
+
+
+ ); +} + +function getThemeCode(theme: Theme, radius: number) { + if (!theme) { + return ''; + } + + return template(BASE_STYLES_WITH_VARIABLES)({ + colors: theme.cssVars, + radius, + }); +} + +const BASE_STYLES_WITH_VARIABLES = ` +@layer base { + :root { + --background: <%- colors.light["background"] %>; + --foreground: <%- colors.light["foreground"] %>; + --card: <%- colors.light["card"] %>; + --card-foreground: <%- colors.light["card-foreground"] %>; + --popover: <%- colors.light["popover"] %>; + --popover-foreground: <%- colors.light["popover-foreground"] %>; + --primary: <%- colors.light["primary"] %>; + --primary-foreground: <%- colors.light["primary-foreground"] %>; + --secondary: <%- colors.light["secondary"] %>; + --secondary-foreground: <%- colors.light["secondary-foreground"] %>; + --muted: <%- colors.light["muted"] %>; + --muted-foreground: <%- colors.light["muted-foreground"] %>; + --accent: <%- colors.light["accent"] %>; + --accent-foreground: <%- colors.light["accent-foreground"] %>; + --destructive: <%- colors.light["destructive"] %>; + --destructive-foreground: <%- colors.light["destructive-foreground"] %>; + --border: <%- colors.light["border"] %>; + --input: <%- colors.light["input"] %>; + --ring: <%- colors.light["ring"] %>; + --radius: <%- radius %>rem; + } + + .dark { + --background: <%- colors.dark["background"] %>; + --foreground: <%- colors.dark["foreground"] %>; + --card: <%- colors.dark["card"] %>; + --card-foreground: <%- colors.dark["card-foreground"] %>; + --popover: <%- colors.dark["popover"] %>; + --popover-foreground: <%- colors.dark["popover-foreground"] %>; + --primary: <%- colors.dark["primary"] %>; + --primary-foreground: <%- colors.dark["primary-foreground"] %>; + --secondary: <%- colors.dark["secondary"] %>; + --secondary-foreground: <%- colors.dark["secondary-foreground"] %>; + --muted: <%- colors.dark["muted"] %>; + --muted-foreground: <%- colors.dark["muted-foreground"] %>; + --accent: <%- colors.dark["accent"] %>; + --accent-foreground: <%- colors.dark["accent-foreground"] %>; + --destructive: <%- colors.dark["destructive"] %>; + --destructive-foreground: <%- colors.dark["destructive-foreground"] %>; + --border: <%- colors.dark["border"] %>; + --input: <%- colors.dark["input"] %>; + --ring: <%- colors.dark["ring"] %>; + } +} +`; diff --git a/apps/www/src/components/customizer-drawer.tsx b/apps/www/src/components/customizer-drawer.tsx new file mode 100644 index 0000000000..c6d5754920 --- /dev/null +++ b/apps/www/src/components/customizer-drawer.tsx @@ -0,0 +1,95 @@ +'use client'; + +import { useEffect, useRef } from 'react'; + +import { useMounted } from '@/hooks/use-mounted'; +import { useViewport } from '@/hooks/use-viewport'; +import { Button } from '@/registry/default/plate-ui/button'; + +import { CustomizerTabs } from './customizer-tabs'; + +import '@/styles/mdx.css'; + +import * as React from 'react'; +import * as SheetPrimitive from '@radix-ui/react-dialog'; +import { ChevronsRight } from 'lucide-react'; +import { Drawer } from 'vaul'; + +import { settingsStore } from './context/settings-store'; +import { DrawerContent } from './drawer'; +import { Sheet, SheetContent } from './ui/sheet'; + +export default function CustomizerDrawer() { + const open = settingsStore.use.showSettings(); + const setOpen = settingsStore.set.showSettings; + const { width } = useViewport(); + const cancelLoadingRef = useRef(''); + const mounted = useMounted(); + + useEffect(() => { + if (open) { + settingsStore.set.loadingSettings(true); + + if (cancelLoadingRef.current) { + clearTimeout(cancelLoadingRef.current); + cancelLoadingRef.current = ''; + } + + cancelLoadingRef.current = setTimeout(() => { + settingsStore.set.loadingSettings(false); + }, 600); + } + }, [open]); + + if (!mounted) return null; + + return ( +
+ {width <= 768 && ( + { + setOpen(value); + }} + // modal={false} + > + + + + + )} + +
+ { + if (value) setOpen(true); + }} + modal={false} + > + + setOpen(false)}> + + + + + + +
+
+ ); +} diff --git a/apps/www/src/components/customizer-tabs.tsx b/apps/www/src/components/customizer-tabs.tsx new file mode 100644 index 0000000000..8a155758fa --- /dev/null +++ b/apps/www/src/components/customizer-tabs.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; + +import { settingsStore } from './context/settings-store'; +import { PluginsTabContent } from './plugins-tab-content'; +import { ThemesTabContent } from './themes-tab-content'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from './ui/tabs'; + +export function CustomizerTabs() { + const customizerTab = settingsStore.use.customizerTab(); + + return ( +
+ { + settingsStore.set.customizerTab(value); + }} + > +
+ + Plugins + Themes + +
+ + + + + + + +
+
+ ); +} diff --git a/apps/www/src/components/drawer.tsx b/apps/www/src/components/drawer.tsx new file mode 100644 index 0000000000..ee23b3b40b --- /dev/null +++ b/apps/www/src/components/drawer.tsx @@ -0,0 +1,42 @@ +'use client'; + +import { forwardRef } from 'react'; +import { Drawer as DrawerPrimitive } from 'vaul'; + +import { cn } from '@/lib/utils'; + +const DrawerTrigger = DrawerPrimitive.Trigger; + +const DrawerContent = forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + portalClassName?: string; + overlayClassName?: string; + } +>( + ( + { className, portalClassName, overlayClassName, style, children, ...props }, + ref + ) => ( + + + +
+ {children} + + + ) +); +DrawerContent.displayName = 'DrawerContent'; + +export { DrawerTrigger, DrawerContent }; diff --git a/apps/www/src/components/icons.tsx b/apps/www/src/components/icons.tsx index b3c9cf9a3f..bc3fb4ef83 100644 --- a/apps/www/src/components/icons.tsx +++ b/apps/www/src/components/icons.tsx @@ -18,8 +18,6 @@ import { Combine, Copy, DownloadCloud, - Edit2, - Edit3, ExternalLink, Eye, File, @@ -54,6 +52,8 @@ import { Outdent, PaintBucket, Paperclip, + Pen, + PenLine, PenTool, Pilcrow, Plus, @@ -295,7 +295,7 @@ export const Icons = { discord, downloadCloud: DownloadCloud, dragHandle: GripVertical, - editing: Edit2, + editing: Pen, ellipsis: MoreVertical, embed: Film, emoji: Smile, @@ -338,7 +338,7 @@ export const Icons = { spinner: Loader2, strikethrough: Strikethrough, subscript: Subscript, - suggesting: Edit3, + suggesting: PenLine, sun: SunMedium, superscript: Superscript, table: Table, diff --git a/apps/www/src/components/link.tsx b/apps/www/src/components/link.tsx new file mode 100644 index 0000000000..9fec214b35 --- /dev/null +++ b/apps/www/src/components/link.tsx @@ -0,0 +1,16 @@ +import * as React from 'react'; +import LinkPrimitive from 'next/link'; + +import { cn } from '@/lib/utils'; + +export function Link({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} diff --git a/apps/www/src/components/mdx-components.tsx b/apps/www/src/components/mdx-components.tsx index b8210bc612..de578d7c4a 100644 --- a/apps/www/src/components/mdx-components.tsx +++ b/apps/www/src/components/mdx-components.tsx @@ -3,16 +3,12 @@ import * as React from 'react'; import { ReactNode } from 'react'; import Image from 'next/image'; -import Link from 'next/link'; import { Provider } from 'jotai'; import { useMDXComponent } from 'next-contentlayer/hooks'; -import { NpmCommands } from '@/types/unist'; -import { Event } from '@/lib/events'; import { cn } from '@/lib/utils'; import { useConfig } from '@/hooks/use-config'; import { packageInfoAtom } from '@/hooks/use-package-info'; -import { Style } from '@/registry/styles'; import { APIAttributes, @@ -34,10 +30,10 @@ import { ComponentExample } from './component-example'; import { ComponentPreview } from './component-preview'; import { ComponentSource } from './component-source'; import { HydrateAtoms } from './context/hydrate-atoms'; -import { CopyButton, CopyNpmCommandButton } from './copy-button'; import { FrameworkDocs } from './framework-docs'; +import { Link } from './link'; import { PackageInfo } from './package-info'; -import { StyleWrapper } from './style-wrapper'; +import * as Typography from './typography'; import { Accordion, AccordionContent, @@ -64,175 +60,25 @@ const components = { Alert, AlertTitle, AlertDescription, - h1: ({ className, ...props }: React.HTMLAttributes) => ( -

- ), - h2: ({ className, ...props }: React.HTMLAttributes) => ( -

- ), - h3: ({ className, ...props }: React.HTMLAttributes) => ( -

- ), - h4: ({ className, ...props }: React.HTMLAttributes) => ( -

- ), - h5: ({ className, ...props }: React.HTMLAttributes) => ( -
- ), - h6: ({ className, ...props }: React.HTMLAttributes) => ( -
- ), - a: ({ className, ...props }: React.HTMLAttributes) => ( - - ), - p: ({ className, ...props }: React.HTMLAttributes) => ( -

- ), - ul: ({ className, ...props }: React.HTMLAttributes) => ( -