From aaf2f10eeb4e8535aff12862b43989dfa283df46 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Fri, 30 Jan 2026 11:57:02 -0300 Subject: [PATCH 1/5] feat: add template-builder package to monorepo Move template-builder from standalone repo into superdoc monorepo. Add CI workflows for validation and demo deployment. --- .../{pr-validation.yml => ci-superdoc.yml} | 21 +- .github/workflows/ci-template-builder.yml | 42 + .github/workflows/deploy-demos.yml | 36 + .github/workflows/release.yml | 10 +- packages/template-builder/.gitignore | 4 + packages/template-builder/.releaserc.cjs | 34 + packages/template-builder/LICENSE | 661 +++++++++++++++ packages/template-builder/README.md | 285 +++++++ packages/template-builder/demo/index.html | 17 + packages/template-builder/demo/package.json | 24 + packages/template-builder/demo/public/CNAME | 1 + packages/template-builder/demo/src/App.css | 283 +++++++ packages/template-builder/demo/src/App.tsx | 271 +++++++ packages/template-builder/demo/src/index.css | 22 + packages/template-builder/demo/src/main.tsx | 10 + packages/template-builder/demo/tsconfig.json | 13 + packages/template-builder/demo/vite.config.ts | 7 + packages/template-builder/package.json | 80 ++ .../src/defaults/FieldList.tsx | 258 ++++++ .../src/defaults/FieldMenu.tsx | 444 ++++++++++ .../template-builder/src/defaults/index.ts | 5 + packages/template-builder/src/index.tsx | 713 +++++++++++++++++ packages/template-builder/src/test/setup.ts | 1 + packages/template-builder/src/types.ts | 150 ++++ packages/template-builder/tsconfig.json | 16 + packages/template-builder/vite.config.ts | 25 + pnpm-lock.yaml | 756 +++++++++++++++--- pnpm-workspace.yaml | 12 + 28 files changed, 4096 insertions(+), 105 deletions(-) rename .github/workflows/{pr-validation.yml => ci-superdoc.yml} (90%) create mode 100644 .github/workflows/ci-template-builder.yml create mode 100644 .github/workflows/deploy-demos.yml create mode 100644 packages/template-builder/.gitignore create mode 100644 packages/template-builder/.releaserc.cjs create mode 100644 packages/template-builder/LICENSE create mode 100644 packages/template-builder/README.md create mode 100644 packages/template-builder/demo/index.html create mode 100644 packages/template-builder/demo/package.json create mode 100644 packages/template-builder/demo/public/CNAME create mode 100644 packages/template-builder/demo/src/App.css create mode 100644 packages/template-builder/demo/src/App.tsx create mode 100644 packages/template-builder/demo/src/index.css create mode 100644 packages/template-builder/demo/src/main.tsx create mode 100644 packages/template-builder/demo/tsconfig.json create mode 100644 packages/template-builder/demo/vite.config.ts create mode 100644 packages/template-builder/package.json create mode 100644 packages/template-builder/src/defaults/FieldList.tsx create mode 100644 packages/template-builder/src/defaults/FieldMenu.tsx create mode 100644 packages/template-builder/src/defaults/index.ts create mode 100644 packages/template-builder/src/index.tsx create mode 100644 packages/template-builder/src/test/setup.ts create mode 100644 packages/template-builder/src/types.ts create mode 100644 packages/template-builder/tsconfig.json create mode 100644 packages/template-builder/vite.config.ts diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/ci-superdoc.yml similarity index 90% rename from .github/workflows/pr-validation.yml rename to .github/workflows/ci-superdoc.yml index ac2a462200..c1fc397542 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/ci-superdoc.yml @@ -1,4 +1,4 @@ -name: PR Validation [auto] +name: CI SuperDoc permissions: contents: read @@ -8,10 +8,11 @@ on: branches: [main, 'release/**'] paths-ignore: - 'apps/docs/**' + - 'packages/template-builder/**' - '**/*.md' concurrency: - group: pr-${{ github.event.pull_request.number }} + group: ci-superdoc-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: @@ -23,7 +24,7 @@ jobs: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} - - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # Pinned commit hash for @v4 + - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: @@ -44,14 +45,14 @@ jobs: - name: Install dependencies run: pnpm install - + - name: Validate commits run: | BASE=$(git merge-base ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) pnpx commitlint \ --from "$BASE" \ --to ${{ github.event.pull_request.head.sha }} - + run-unit-tests: runs-on: ubuntu-latest steps: @@ -59,7 +60,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # Pinned commit hash for @v4 + - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: @@ -104,7 +105,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # Pinned commit hash for @v4 + - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: @@ -129,7 +130,7 @@ jobs: - name: Build SuperDoc run: | pnpm run build - + - name: Install Playwright browsers run: | cd e2e-tests @@ -138,7 +139,7 @@ jobs: - name: Run e2e tests id: run-e2e-tests if: always() - run: cd e2e-tests && pnpm test + run: cd e2e-tests && pnpm test - name: Upload e2e test results id: upload_artifact @@ -156,7 +157,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # Pinned commit hash for @v4 + - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: diff --git a/.github/workflows/ci-template-builder.yml b/.github/workflows/ci-template-builder.yml new file mode 100644 index 0000000000..4dd3a1cb5d --- /dev/null +++ b/.github/workflows/ci-template-builder.yml @@ -0,0 +1,42 @@ +name: CI Template Builder + +on: + pull_request: + paths: + - 'packages/template-builder/**' + workflow_dispatch: + +concurrency: + group: ci-template-builder-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + + - uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + cache: pnpm + + - name: Install dependencies + run: pnpm install + + - name: Build superdoc (dependency) + run: pnpm run build:superdoc + + - name: Lint + run: pnpm --filter @superdoc-dev/template-builder lint + + - name: Type check + run: pnpm --filter @superdoc-dev/template-builder type-check + + - name: Build + run: pnpm --filter @superdoc-dev/template-builder build + + - name: Test + run: pnpm --filter @superdoc-dev/template-builder test diff --git a/.github/workflows/deploy-demos.yml b/.github/workflows/deploy-demos.yml new file mode 100644 index 0000000000..6e5f7a7188 --- /dev/null +++ b/.github/workflows/deploy-demos.yml @@ -0,0 +1,36 @@ +name: Deploy Demos + +on: + push: + branches: [main] + paths: + - 'packages/template-builder/**' + # Add more demo paths here as needed + workflow_dispatch: + +jobs: + deploy-template-builder-demo: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + cache: pnpm + - run: pnpm install + - name: Build template-builder + run: pnpm --filter @superdoc-dev/template-builder build + - name: Build demo + run: pnpm --filter superdoc-template-builder-demo build + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./packages/template-builder/demo/dist + cname: template-builder.superdoc.dev + + # Add more demo deploy jobs here as needed + # deploy-another-demo: + # runs-on: ubuntu-latest + # steps: ... diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4cbdd3fdca..fde8176b49 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -69,7 +69,7 @@ jobs: - name: Build packages run: pnpm run build - - name: Release + - name: Release superdoc env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -77,6 +77,14 @@ jobs: LINEAR_TOKEN: ${{ secrets.LINEAR_TOKEN }} run: pnpx semantic-release + - name: Release template-builder + env: + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + working-directory: packages/template-builder + run: pnpx semantic-release + # Sync stable back to main after stable release # - name: Sync stable to main # if: github.ref == 'refs/heads/stable' diff --git a/packages/template-builder/.gitignore b/packages/template-builder/.gitignore new file mode 100644 index 0000000000..e0fc267f5b --- /dev/null +++ b/packages/template-builder/.gitignore @@ -0,0 +1,4 @@ +dist/ +node_modules/ +*.log +.DS_Store diff --git a/packages/template-builder/.releaserc.cjs b/packages/template-builder/.releaserc.cjs new file mode 100644 index 0000000000..4fe45f6bf9 --- /dev/null +++ b/packages/template-builder/.releaserc.cjs @@ -0,0 +1,34 @@ +/* eslint-env node */ +const branch = process.env.GITHUB_REF_NAME || process.env.CI_COMMIT_BRANCH; + +const config = { + branches: [ + { name: 'stable', channel: 'latest' }, + { name: 'main', prerelease: 'next', channel: 'next' }, + ], + tagFormat: 'template-builder-v${version}', + plugins: [ + '@semantic-release/commit-analyzer', + '@semantic-release/release-notes-generator', + ['@semantic-release/npm', { npmPublish: true }], + ], +}; + +const isPrerelease = config.branches.some( + (b) => typeof b === 'object' && b.name === branch && b.prerelease +); + +if (!isPrerelease) { + config.plugins.push([ + '@semantic-release/git', + { + assets: ['package.json'], + message: + 'chore(template-builder): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}', + }, + ]); +} + +config.plugins.push('@semantic-release/github'); + +module.exports = config; diff --git a/packages/template-builder/LICENSE b/packages/template-builder/LICENSE new file mode 100644 index 0000000000..0ad25db4bd --- /dev/null +++ b/packages/template-builder/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/packages/template-builder/README.md b/packages/template-builder/README.md new file mode 100644 index 0000000000..6d7eb72ec3 --- /dev/null +++ b/packages/template-builder/README.md @@ -0,0 +1,285 @@ +# @superdoc-dev/template-builder + +React template building component for SuperDoc that enables document field management using structured content (SDT). + +## Installation + +```bash +npm install @superdoc-dev/template-builder +``` + +## Quick Start + +```jsx +import SuperDocTemplateBuilder from '@superdoc-dev/template-builder'; +import 'superdoc/dist/style.css'; + +function TemplateEditor() { + return ( + { + console.log('User typed trigger at', event.position); + }} + onFieldInsert={(field) => { + console.log('Field inserted:', field.alias); + }} + /> + ); +} +``` + +## What You Receive + +```javascript +{ + fields: [ + { id: "1324567890", alias: "Customer Name", tag: "contact" }, + { id: "1324567891", alias: "Invoice Date", tag: "invoice" } + ], + document: { /* ProseMirror document JSON */ } +} +``` + +## Features + +- **🎯 Trigger Detection** - Type `{{` (customizable) to insert fields +- **📝 Field Management** - Insert, update, delete, and navigate fields +- **🔍 Field Discovery** - Automatically finds existing fields in documents +- **🎨 UI Agnostic** - Bring your own menus, panels, and components +- **📄 SDT Based** - Uses structured content tags for Word compatibility +- **⚡ Simple API** - Clear callbacks for trigger events and field changes + +## API + +### Component Props + +```typescript + {}} + onTrigger={(event) => {}} + onFieldInsert={(field) => {}} + onFieldUpdate={(field) => {}} + onFieldDelete={(fieldId) => {}} + onFieldsChange={(fields) => {}} + onFieldSelect={(field) => {}} +/> +``` + +### Ref Methods + +```jsx +const ref = useRef(); + +// Insert fields +ref.current.insertField({ alias: 'Customer Name' }); +ref.current.insertBlockField({ alias: 'Terms Block' }); + +// Update/delete fields +ref.current.updateField(fieldId, { alias: 'New Name' }); +ref.current.deleteField(fieldId); + +// Navigation +ref.current.selectField(fieldId); +ref.current.nextField(); // Tab behavior +ref.current.previousField(); // Shift+Tab behavior + +// Get data +const fields = ref.current.getFields(); +const template = await ref.current.exportTemplate(); +``` + +## Custom Components + +### Field Menu + +```jsx +const CustomFieldMenu = ({ isVisible, position, availableFields, onSelect, onClose }) => { + if (!isVisible) return null; + + return ( +
+ {availableFields.map((field) => ( + + ))} + +
+ ); +}; +``` + +### Field List + +```jsx +const CustomFieldList = ({ fields, onSelect, onDelete, selectedFieldId }) => { + return ( +
+

Fields ({fields.length})

+ {fields.map((field) => ( +
onSelect(field)} + style={{ background: selectedFieldId === field.id ? '#blue' : '#gray' }} + > + {field.alias} + +
+ ))} +
+ ); +}; +``` + +## Field Navigation + +Enable Tab/Shift+Tab navigation: + +```jsx +function TemplateEditor() { + const ref = useRef(); + + const handleKeyDown = (e) => { + if (e.key === 'Tab') { + e.preventDefault(); + if (e.shiftKey) { + ref.current?.previousField(); + } else { + ref.current?.nextField(); + } + } + }; + + return ( +
+ +
+ ); +} +``` + +## Export Template + +The `exportTemplate` method supports two modes of operation via the `ExportConfig` interface: + +### 1. Download Mode (Default) + +Automatically downloads the template as a file in the browser: + +```jsx +const handleDownload = async () => { + // Download with default filename "document.docx" + await ref.current?.exportTemplate(); + + // Or with custom filename + await ref.current?.exportTemplate({ + fileName: 'invoice-template.docx', + }); +}; +``` + +### 2. Blob Mode (for Database/API) + +Get the template as a Blob for saving to your database or API: + +```jsx +const handleSave = async () => { + // Get the blob without triggering download + const blob = await ref.current?.exportTemplate({ + fileName: 'invoice-template.docx', + triggerDownload: false, + }); + + if (blob) { + // Send to your API/database + const formData = new FormData(); + formData.append('template', blob, 'invoice-template.docx'); + + await fetch('/api/templates', { + method: 'POST', + body: formData, + }); + } +}; +``` + +### ExportConfig Interface + +```typescript +interface ExportConfig { + fileName?: string; // Default: "document" + triggerDownload?: boolean; // Default: true +} + +// Method signature +exportTemplate(config?: ExportConfig): Promise +``` + +**Return value:** + +- `Promise` when `triggerDownload: true` (download happens automatically) +- `Promise` when `triggerDownload: false` (returns the docx data) + +## TypeScript + +Full TypeScript support included: + +```typescript +import SuperDocTemplateBuilder from '@superdoc-dev/template-builder'; +import type { + TemplateField, + FieldDefinition, + TriggerEvent, + ExportConfig, + SuperDocTemplateBuilderHandle, +} from '@superdoc-dev/template-builder'; + +const ref = useRef(null); +``` + +## License + +AGPLv3 diff --git a/packages/template-builder/demo/index.html b/packages/template-builder/demo/index.html new file mode 100644 index 0000000000..40a4939e7b --- /dev/null +++ b/packages/template-builder/demo/index.html @@ -0,0 +1,17 @@ + + + + + + + @superdoc-dev/template-builder - Interactive Demo + + + + + +
+ + + + diff --git a/packages/template-builder/demo/package.json b/packages/template-builder/demo/package.json new file mode 100644 index 0000000000..57ed361ec5 --- /dev/null +++ b/packages/template-builder/demo/package.json @@ -0,0 +1,24 @@ +{ + "name": "superdoc-template-builder-demo", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@superdoc-dev/template-builder": "link:..", + "react": "catalog:", + "react-dom": "catalog:", + "superdoc": "workspace:*" + }, + "devDependencies": { + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@vitejs/plugin-react": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" + } +} diff --git a/packages/template-builder/demo/public/CNAME b/packages/template-builder/demo/public/CNAME new file mode 100644 index 0000000000..5d77985c86 --- /dev/null +++ b/packages/template-builder/demo/public/CNAME @@ -0,0 +1 @@ +template-builder.superdoc.dev diff --git a/packages/template-builder/demo/src/App.css b/packages/template-builder/demo/src/App.css new file mode 100644 index 0000000000..f998dcbb20 --- /dev/null +++ b/packages/template-builder/demo/src/App.css @@ -0,0 +1,283 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: + system-ui, + -apple-system, + sans-serif; + background: #f5f5f7; +} + +.demo { + min-height: 100vh; +} + +/* Header */ +header { + background: white; + padding: 1.5rem 2rem; + border-bottom: 1px solid #e5e5e7; +} + +.header-content { + max-width: 1600px; + margin: 0 auto; + display: flex; + justify-content: space-between; + align-items: center; +} + +.header-left h1 { + font-size: 1.5rem; + margin: 0; +} + +.header-left h1 a { + color: inherit; + text-decoration: none; +} + +.header-left h1 a:hover { + color: #007aff; +} + +.header-left p { + color: #86868b; + margin: 0.25rem 0 0 0; +} + +.header-nav { + display: flex; + gap: 2rem; +} + +.header-nav a { + color: #1d1d1f; + text-decoration: none; + font-weight: 500; + font-size: 0.95rem; + transition: color 0.2s; +} + +.header-nav a:hover { + color: #007aff; +} + +/* Container */ +.container { + max-width: 1600px; + margin: 2rem auto; + padding: 0 2rem; +} + +/* Toolbar */ +.toolbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 1.5rem; + background: white; + border-radius: 12px; + margin-bottom: 1.5rem; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); +} + +.toolbar-right { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.toolbar-left { + display: flex; + align-items: center; + gap: 1rem; +} + +.hint { + color: #86868b; + font-size: 0.875rem; +} + +.divider { + color: #d2d2d7; +} + +.export-button { + padding: 0.5rem 1.25rem; + background: #007aff; + color: white; + border: none; + border-radius: 8px; + font-weight: 600; + cursor: pointer; + transition: background 0.2s; +} + +.export-button:hover { + background: #0051d5; +} + +.export-button:disabled, +.import-button:disabled { + cursor: not-allowed; + opacity: 0.7; +} + +.import-button { + padding: 0.5rem 1.25rem; + background: white; + color: #007aff; + border: 1px solid #b0d4ff; + border-radius: 8px; + font-weight: 600; + cursor: pointer; + transition: + background 0.2s, + color 0.2s, + border-color 0.2s; +} + +.import-button:hover { + background: #e8f2ff; + border-color: #007aff; +} + +.toolbar-error { + margin-top: 0.75rem; + padding: 0.75rem 1rem; + background: #fef2f2; + color: #b91c1c; + border: 1px solid #fecaca; + border-radius: 8px; + font-size: 0.875rem; +} + +/* Template Builder Container */ +.superdoc-template-builder { + background: white; + border-radius: 12px; + padding: 1.5rem; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); +} + +.superdoc-template-builder-editor { + border: 2px solid #007aff; + border-radius: 8px; + overflow: auto; + background: white; +} + +/* Event Log */ +.event-log { + margin-top: 1.5rem; + padding: 1rem; + background: white; + border: 1px solid #e5e7eb; + border-radius: 8px; + font-family: 'SF Mono', Monaco, monospace; + font-size: 0.8125rem; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); +} + +.event-log-header { + font-weight: bold; + margin-bottom: 0.5rem; + font-size: 0.75rem; + color: #6b7280; + letter-spacing: 0.05em; +} + +.event-log-item { + padding: 0.125rem 0; + color: #374151; +} + +/* Export Modal */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 10000; +} + +.modal { + background: white; + border-radius: 12px; + padding: 2rem; + max-width: 600px; + max-height: 80vh; + overflow: auto; + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1); +} + +.modal h2 { + margin-bottom: 1.5rem; +} + +.modal h3 { + margin: 1.5rem 0 0.75rem 0; + font-size: 1rem; + color: #6b7280; +} + +.export-content pre { + background: #f5f5f7; + padding: 1rem; + border-radius: 8px; + overflow: auto; + font-size: 0.8125rem; + max-height: 300px; +} + +.modal-close { + margin-top: 1.5rem; + padding: 0.75rem 1.5rem; + background: #ef4444; + color: white; + border: none; + border-radius: 8px; + font-weight: 600; + cursor: pointer; +} + +.modal-close:hover { + background: #dc2626; +} + +/* Responsive */ +@media (max-width: 768px) { + .header-content { + flex-direction: column; + gap: 1rem; + text-align: center; + } + + .toolbar { + flex-direction: column; + gap: 1rem; + } + + .toolbar-left { + flex-direction: column; + gap: 0.5rem; + } + + .superdoc-template-builder > div { + flex-direction: column !important; + } + + .superdoc-field-list { + width: 100% !important; + } +} diff --git a/packages/template-builder/demo/src/App.tsx b/packages/template-builder/demo/src/App.tsx new file mode 100644 index 0000000000..8f7094ce54 --- /dev/null +++ b/packages/template-builder/demo/src/App.tsx @@ -0,0 +1,271 @@ +import type { KeyboardEvent, ChangeEvent } from 'react'; +import { useState, useRef, useCallback, useMemo } from 'react'; +import SuperDocTemplateBuilder from '@superdoc-dev/template-builder'; +import type { + SuperDocTemplateBuilderHandle, + TemplateField, + FieldDefinition, + ExportEvent, +} from '@superdoc-dev/template-builder'; +import 'superdoc/style.css'; +import './App.css'; + +const availableFields: FieldDefinition[] = [ + { id: '1242142770', label: 'Agreement Date' }, + { id: '1242142771', label: 'User Name' }, + { id: '1242142772', label: 'Company Name' }, + { id: '1242142773', label: 'Service Type' }, + { id: '1242142774', label: 'Agreement Jurisdiction' }, + { id: '1242142775', label: 'Company Address' }, + { id: '1242142776', label: 'Signature', mode: 'block' }, +]; + +export function App() { + const [, setFields] = useState([]); + const [events, setEvents] = useState([]); + const [isDownloading, setIsDownloading] = useState(false); + const [isImporting, setIsImporting] = useState(false); + const [importError, setImportError] = useState(null); + const [documentSource, setDocumentSource] = useState( + 'https://storage.googleapis.com/public_static_hosting/public_demo_docs/new_service_agreement.docx', + ); + const builderRef = useRef(null); + const fileInputRef = useRef(null); + const importingRef = useRef(false); + + const log = useCallback((msg: string) => { + const time = new Date().toLocaleTimeString(); + console.log(`[${time}] ${msg}`); + setEvents((prev) => [...prev.slice(-4), `${time} - ${msg}`]); + }, []); + + const handleFieldsChange = useCallback( + (updatedFields: TemplateField[]) => { + setFields(updatedFields); + log(`Fields: ${updatedFields.length} total`); + }, + [log], + ); + + const handleFieldInsert = useCallback( + (field: TemplateField) => { + log(`✓ Inserted: ${field.alias}`); + }, + [log], + ); + + const handleFieldDelete = useCallback( + (fieldId: string | number) => { + log(`✗ Deleted: ${fieldId}`); + }, + [log], + ); + + const handleFieldSelect = useCallback( + (field: TemplateField | null) => { + if (field) { + log(`Selected: ${field.alias}`); + } + }, + [log], + ); + + const handleReady = useCallback(() => { + log('✓ Template builder ready'); + if (importingRef.current) { + log('📄 Document imported'); + importingRef.current = false; + setImportError(null); + setIsImporting(false); + } + }, [log]); + + const handleTrigger = useCallback(() => { + log('⌨ Trigger detected'); + }, [log]); + + const handleExport = useCallback( + (event: ExportEvent) => { + console.log('Export Event:', event); + console.log('Fields:', JSON.stringify(event.fields, null, 2)); + log(`Exported ${event.fields.length} fields`); + event.fields.forEach((f) => { + console.log(` - ${f.alias} (id: ${f.id}, mode: ${f.mode}, group: ${f.group || 'none'})`); + }); + }, + [log], + ); + + const handleExportTemplate = useCallback(async () => { + if (!builderRef.current) { + return; + } + + try { + setIsDownloading(true); + + await builderRef.current.exportTemplate({ + fileName: 'template.docx', + }); + + log('📤 Template exported'); + } catch (error) { + log('⚠️ Export failed'); + console.error('Failed to export template', error); + } finally { + setIsDownloading(false); + } + }, [log]); + + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Tab') { + e.preventDefault(); + if (e.shiftKey) { + builderRef.current?.previousField(); + } else { + builderRef.current?.nextField(); + } + } + }; + + const documentConfig = useMemo( + () => ({ + source: documentSource, + mode: 'editing' as const, + }), + [documentSource], + ); + + const handleImportButtonClick = useCallback(() => { + if (isImporting) return; + fileInputRef.current?.click(); + }, [isImporting]); + + const handleFileInputChange = useCallback( + (event: ChangeEvent) => { + const file = event.target.files?.[0]; + event.target.value = ''; + + if (!file) return; + + const extension = file.name.split('.').pop()?.toLowerCase(); + if (extension !== 'docx') { + const message = 'Invalid file type. Please choose a .docx file.'; + setImportError(message); + log('⚠️ ' + message); + return; + } + + importingRef.current = true; + setImportError(null); + setIsImporting(true); + setDocumentSource(file); + log(`📥 Importing "${file.name}"`); + }, + [log], + ); + + const fieldsConfig = useMemo( + () => ({ + available: availableFields, + allowCreate: true, + }), + [], + ); + + const listConfig = useMemo( + () => ({ + position: 'right' as const, + }), + [], + ); + + return ( +
+
+
+
+

+ + @superdoc-dev/template-builder + +

+

+ React template builder from{' '} + + SuperDoc + +

+
+ +
+
+ +
+
+
+ Type {'{{'} to insert a field + | + Tab/Shift+Tab to navigate +
+
+ + + +
+
+ + {importError && ( +
+ {importError} +
+ )} + + + + {/* Event Log */} + {events.length > 0 && ( +
+
EVENT LOG
+ {events.map((evt, i) => ( +
+ {evt} +
+ ))} +
+ )} +
+
+ ); +} diff --git a/packages/template-builder/demo/src/index.css b/packages/template-builder/demo/src/index.css new file mode 100644 index 0000000000..f83e987453 --- /dev/null +++ b/packages/template-builder/demo/src/index.css @@ -0,0 +1,22 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: + system-ui, + -apple-system, + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.superdoc-template-builder-document { + background: #ffffff; +} + +.superdoc-template-builder-editor { + background: #ffffff; +} diff --git a/packages/template-builder/demo/src/main.tsx b/packages/template-builder/demo/src/main.tsx new file mode 100644 index 0000000000..f7c32b7615 --- /dev/null +++ b/packages/template-builder/demo/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { App } from './App'; +import './index.css'; + +createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/packages/template-builder/demo/tsconfig.json b/packages/template-builder/demo/tsconfig.json new file mode 100644 index 0000000000..ec93aab0fd --- /dev/null +++ b/packages/template-builder/demo/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "jsx": "react-jsx" + }, + "include": ["src"] +} diff --git a/packages/template-builder/demo/vite.config.ts b/packages/template-builder/demo/vite.config.ts new file mode 100644 index 0000000000..5797d20807 --- /dev/null +++ b/packages/template-builder/demo/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + base: '/', +}); diff --git a/packages/template-builder/package.json b/packages/template-builder/package.json new file mode 100644 index 0000000000..b83160444c --- /dev/null +++ b/packages/template-builder/package.json @@ -0,0 +1,80 @@ +{ + "name": "@superdoc-dev/template-builder", + "version": "0.1.0", + "description": "React template builder component for SuperDoc", + "type": "module", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js" + } + }, + "files": [ + "dist", + "README.md" + ], + "scripts": { + "dev": "vite build --watch", + "build": "tsc && vite build", + "type-check": "tsc --noEmit", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "test": "vitest run", + "test:watch": "vitest --watch", + "prepublishOnly": "pnpm run build" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/superdoc-dev/superdoc.git", + "directory": "packages/template-builder" + }, + "keywords": [ + "superdoc", + "template", + "template-builder", + "document", + "fields", + "sdt", + "docx", + "react" + ], + "author": "SuperDoc Team", + "license": "AGPL-3.0", + "bugs": { + "url": "https://github.com/superdoc-dev/superdoc/issues" + }, + "homepage": "https://github.com/superdoc-dev/superdoc/tree/main/packages/template-builder#readme", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "superdoc": "^1.9.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "catalog:", + "@testing-library/react": "catalog:", + "@testing-library/user-event": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@vitejs/plugin-react": "catalog:", + "eslint-plugin-react": "catalog:", + "eslint-plugin-react-hooks": "catalog:", + "react": "catalog:", + "react-dom": "catalog:", + "superdoc": "workspace:*", + "typescript": "catalog:", + "vite": "catalog:", + "vite-plugin-dts": "catalog:", + "vitest": "catalog:", + "jsdom": "catalog:" + }, + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=18" + } +} diff --git a/packages/template-builder/src/defaults/FieldList.tsx b/packages/template-builder/src/defaults/FieldList.tsx new file mode 100644 index 0000000000..8db1aa7cf5 --- /dev/null +++ b/packages/template-builder/src/defaults/FieldList.tsx @@ -0,0 +1,258 @@ +import type { FC } from 'react'; +import { useMemo, useState } from 'react'; +import type { FieldListProps, TemplateField } from '../types'; + +const shortenGroupId = (group: string): string => { + const parts = group.split('-'); + return parts.length > 2 ? parts[parts.length - 1].substring(0, 6) : group.substring(0, 6); +}; +const FieldItem: FC<{ + field: TemplateField; + onSelect: (field: TemplateField) => void; + onDelete: (id: string | number) => void; + isSelected: boolean; + isGrouped?: boolean; +}> = ({ field, onSelect, onDelete, isSelected, isGrouped = false }) => { + return ( +
onSelect(field)} + style={{ + position: 'relative', + padding: '10px 12px', + background: isSelected ? '#eff6ff' : '#f9fafb', + border: isSelected ? '1px solid #3b82f6' : '1px solid #e5e7eb', + borderRadius: '6px', + cursor: 'pointer', + transition: 'all 0.2s', + fontSize: isGrouped ? '13px' : '14px', + }} + onMouseEnter={(e) => { + if (!isSelected) { + e.currentTarget.style.background = '#f3f4f6'; + } + }} + onMouseLeave={(e) => { + if (!isSelected) { + e.currentTarget.style.background = '#f9fafb'; + } + }} + title={field.alias} + > + +
+
+ {field.alias || field.id} +
+
+ ID: {field.id} + {field.mode && ( + + {field.mode} + + )} +
+
+
+ ); +}; + +export const FieldList: FC = ({ fields, onSelect, onDelete, selectedFieldId }) => { + const [expandedGroups, setExpandedGroups] = useState>(new Set()); + + const { groupedFields, ungroupedFields } = useMemo(() => { + const grouped: Record = {}; + const ungrouped: typeof fields = []; + + fields.forEach((field) => { + if (field.group) { + if (!grouped[field.group]) { + grouped[field.group] = []; + } + grouped[field.group].push(field); + } else { + ungrouped.push(field); + } + }); + + return { groupedFields: grouped, ungroupedFields: ungrouped }; + }, [fields]); + + const toggleGroup = (groupId: string) => { + setExpandedGroups((prev) => { + const next = new Set(prev); + if (next.has(groupId)) { + next.delete(groupId); + } else { + next.add(groupId); + } + return next; + }); + }; + + return ( +
+

Template Fields ({fields.length})

+ + {fields.length === 0 ? ( +
+ No fields yet. Type {'{{'} to add a field. +
+ ) : ( +
+ {ungroupedFields.map((field) => ( + + ))} + + {Object.entries(groupedFields).map(([groupId, groupFields]) => { + const isExpanded = expandedGroups.has(groupId); + const firstField = groupFields[0]; + + return ( +
+
toggleGroup(groupId)} + onMouseEnter={(e) => { + e.currentTarget.style.background = '#f3f4f6'; + }} + onMouseLeave={(e) => { + e.currentTarget.style.background = '#f9fafb'; + }} + > +
+ {isExpanded ? '▼' : '▶'} +
+
{firstField.alias}
+
+ group: {shortenGroupId(groupId)} ({groupFields.length} fields) +
+
+
+
+ + {isExpanded && ( +
+ {groupFields.map((field) => ( + + ))} +
+ )} +
+ ); + })} +
+ )} +
+ ); +}; diff --git a/packages/template-builder/src/defaults/FieldMenu.tsx b/packages/template-builder/src/defaults/FieldMenu.tsx new file mode 100644 index 0000000000..bdb8c2e3f2 --- /dev/null +++ b/packages/template-builder/src/defaults/FieldMenu.tsx @@ -0,0 +1,444 @@ +import { useEffect, useMemo, useState } from 'react'; +import type { FieldDefinition, FieldMenuProps } from '../types'; + +export const FieldMenu: React.FC = ({ + isVisible, + position, + availableFields, + filteredFields, + filterQuery, + allowCreate, + onSelect, + onClose, + onCreateField, + existingFields = [], + onSelectExisting, +}) => { + const [isCreating, setIsCreating] = useState(false); + const [newFieldName, setNewFieldName] = useState(''); + const [fieldMode, setFieldMode] = useState<'inline' | 'block'>('inline'); + const [existingExpanded, setExistingExpanded] = useState(true); + const [availableExpanded, setAvailableExpanded] = useState(true); + + useEffect(() => { + if (!isVisible) { + setIsCreating(false); + setNewFieldName(''); + setFieldMode('inline'); + } + }, [isVisible]); + + const menuStyle = useMemo(() => { + return { + position: 'absolute' as const, + left: position?.left, + top: position?.top, + zIndex: 1000, + background: 'white', + border: '1px solid #ddd', + borderRadius: '4px', + boxShadow: '0 2px 8px rgba(0,0,0,0.1)', + padding: '8px 0', + width: '280px', + }; + }, [position]); + + const fieldsToDisplay = filteredFields ?? availableFields; + const hasFilter = Boolean(filterQuery); + + useEffect(() => { + if (hasFilter) { + setAvailableExpanded(true); + } + }, [hasFilter]); + + if (!isVisible) return null; + + const handleCreateField = async () => { + const trimmedName = newFieldName.trim(); + if (!trimmedName) return; + + const newField: FieldDefinition = { + id: `custom_${Date.now()}`, + label: trimmedName, + mode: fieldMode, + }; + + try { + if (onCreateField) { + const result = await onCreateField(newField); + void onSelect(result || newField); + } else { + void onSelect(newField); + } + } finally { + setIsCreating(false); + setNewFieldName(''); + setFieldMode('inline'); + } + }; + + return ( +
+ {hasFilter && ( +
+
+ Filtering results for + {filterQuery} +
+
+ )} + + {allowCreate && !isCreating && ( +
setIsCreating(true)} + style={{ + padding: '8px 16px', + cursor: 'pointer', + color: '#0066cc', + fontWeight: 500, + }} + > + + Create New Field +
+ )} + + {allowCreate && isCreating && ( +
+ setNewFieldName(event.target.value)} + onKeyDown={(event) => { + if (event.key === 'Enter') handleCreateField(); + if (event.key === 'Escape') { + setIsCreating(false); + setNewFieldName(''); + setFieldMode('inline'); + } + }} + autoFocus + style={{ + width: '100%', + padding: '4px 8px', + border: '1px solid #ddd', + borderRadius: '3px', + }} + /> +
+ + +
+
+ + +
+
+ )} + + {allowCreate && availableFields.length > 0 && ( +
+ )} + + {existingFields.length > 0 && + (() => { + const groupedExisting = new Map(); + + existingFields.forEach((field) => { + const key = field.group || `individual-${field.id}`; + const existing = groupedExisting.get(key) || []; + existing.push(field); + groupedExisting.set(key, existing); + }); + + const uniqueEntries = Array.from(groupedExisting.values()).map((fields) => { + const representative = fields[0]; + return { + ...representative, + count: fields.length, + }; + }); + + return ( +
+ + {existingExpanded && ( +
+ {uniqueEntries.map((entry) => ( +
onSelectExisting?.(entry)} + style={{ + padding: '8px 16px', + cursor: 'pointer', + display: 'flex', + alignItems: 'flex-start', + justifyContent: 'space-between', + gap: '8px', + }} + > +
+
{entry.alias || entry.id}
+
+ {entry.group ? `group (${entry.count} fields)` : `ID: ${entry.id}`} +
+
+ + {entry.mode || 'inline'} + +
+ ))} +
+ )} +
+ ); + })()} + + {fieldsToDisplay.length === 0 ? ( +
+ No matching fields +
+ ) : ( +
+ + {availableExpanded && ( +
+ {fieldsToDisplay.map((field) => ( +
onSelect(field)} + style={{ + padding: '8px 16px', + cursor: 'pointer', + display: 'flex', + alignItems: 'flex-start', + justifyContent: 'space-between', + gap: '8px', + }} + > +
+
{field.label || field.id}
+
+ ID: {field.id} +
+
+ + {field.mode || 'inline'} + +
+ ))} +
+ )} +
+ )} + +
+ +
+
+ ); +}; diff --git a/packages/template-builder/src/defaults/index.ts b/packages/template-builder/src/defaults/index.ts new file mode 100644 index 0000000000..7b67cedb27 --- /dev/null +++ b/packages/template-builder/src/defaults/index.ts @@ -0,0 +1,5 @@ +/** + * Default components for template builder + */ +export { FieldMenu } from './FieldMenu'; +export { FieldList } from './FieldList'; diff --git a/packages/template-builder/src/index.tsx b/packages/template-builder/src/index.tsx new file mode 100644 index 0000000000..99d50d5ed7 --- /dev/null +++ b/packages/template-builder/src/index.tsx @@ -0,0 +1,713 @@ +import { useRef, useState, useEffect, useCallback, useMemo, forwardRef, useImperativeHandle } from 'react'; +import type { SuperDoc } from 'superdoc'; +import type * as Types from './types'; +import { FieldMenu, FieldList } from './defaults'; + +export * from './types'; +export { FieldMenu, FieldList }; + +type Editor = NonNullable; + +const getTemplateFieldsFromEditor = (editor: Editor): Types.TemplateField[] => { + const structuredContentHelpers = (editor.helpers as any)?.structuredContentCommands; + + if (!structuredContentHelpers?.getStructuredContentTags) { + return []; + } + + const tags = structuredContentHelpers.getStructuredContentTags(editor.state) || []; + + return tags.map((entry: any) => { + const node = entry?.node ?? entry; + const attrs = node?.attrs ?? {}; + const nodeType = node?.type?.name || ''; + const mode = nodeType.includes('Block') ? 'block' : 'inline'; + + return { + id: attrs.id, + alias: attrs.alias || attrs.label || '', + tag: attrs.tag, + mode, + group: structuredContentHelpers.getGroup?.(attrs.tag) ?? undefined, + } as Types.TemplateField; + }); +}; + +const areTemplateFieldsEqual = (a: Types.TemplateField[], b: Types.TemplateField[]): boolean => { + if (a === b) return true; + if (a.length !== b.length) return false; + + for (let index = 0; index < a.length; index += 1) { + const left = a[index]; + const right = b[index]; + + if (!right) return false; + + if ( + left.id !== right.id || + left.alias !== right.alias || + left.tag !== right.tag || + left.position !== right.position || + left.mode !== right.mode || + left.group !== right.group + ) { + return false; + } + } + + return true; +}; + +const resolveToolbar = (toolbar: Types.SuperDocTemplateBuilderProps['toolbar']) => { + if (!toolbar) return null; + + if (toolbar === true) { + return { + selector: '#superdoc-toolbar', + config: {} as Omit, + renderDefaultContainer: true, + }; + } + + if (typeof toolbar === 'string') { + return { + selector: toolbar, + config: {} as Omit, + renderDefaultContainer: false, + }; + } + + const { selector, ...config } = toolbar; + return { + selector: selector || '#superdoc-toolbar', + config, + renderDefaultContainer: selector === undefined, + }; +}; + +const MENU_VIEWPORT_PADDING = 10; +const MENU_APPROX_WIDTH = 250; +const MENU_APPROX_HEIGHT = 300; + +const clampToViewport = (rect: DOMRect): DOMRect => { + const maxLeft = window.innerWidth - MENU_APPROX_WIDTH - MENU_VIEWPORT_PADDING; + const maxTop = window.innerHeight - MENU_APPROX_HEIGHT - MENU_VIEWPORT_PADDING; + + const clampedLeft = Math.min(rect.left, maxLeft); + const clampedTop = Math.min(rect.top, maxTop); + + return new DOMRect( + Math.max(clampedLeft, MENU_VIEWPORT_PADDING), + Math.max(clampedTop, MENU_VIEWPORT_PADDING), + rect.width, + rect.height, + ); +}; + +const SuperDocTemplateBuilder = forwardRef( + (props, ref) => { + const { + document, + fields = {}, + menu = {}, + list = {}, + toolbar, + onReady, + onTrigger, + onFieldInsert, + onFieldUpdate, + onFieldDelete, + onFieldsChange, + onFieldSelect, + onFieldCreate, + onExport, + className, + style, + documentHeight = '600px', + } = props; + + const [templateFields, setTemplateFields] = useState(fields.initial || []); + const [selectedFieldId, setSelectedFieldId] = useState(null); + const [menuVisible, setMenuVisible] = useState(false); + const [menuPosition, setMenuPosition] = useState(); + const [menuQuery, setMenuQuery] = useState(''); + const [menuFilteredFields, setMenuFilteredFields] = useState(() => fields.available || []); + + const containerRef = useRef(null); + const superdocRef = useRef(null); + const triggerCleanupRef = useRef<(() => void) | null>(null); + const fieldsRef = useRef(fields); + fieldsRef.current = fields; + + const menuTriggerFromRef = useRef(null); + const menuVisibleRef = useRef(menuVisible); + useEffect(() => { + menuVisibleRef.current = menuVisible; + }, [menuVisible]); + + const trigger = menu.trigger || '{{'; + + const availableFields = fieldsRef.current.available || []; + const toolbarSettings = useMemo(() => resolveToolbar(toolbar), [toolbar]); + + const computeFilteredFields = useCallback( + (query: string) => { + const normalized = query.trim().toLowerCase(); + if (!normalized) return availableFields; + + return availableFields.filter((field) => { + const label = field.label.toLowerCase(); + return label.includes(normalized); + }); + }, + [availableFields], + ); + + const updateMenuFilter = useCallback( + (query: string) => { + setMenuQuery(query); + setMenuFilteredFields(computeFilteredFields(query)); + }, + [computeFilteredFields], + ); + + const resetMenuFilter = useCallback(() => { + updateMenuFilter(''); + }, [updateMenuFilter]); + + const insertFieldInternal = useCallback( + (mode: 'inline' | 'block', field: Partial & { alias: string }): boolean => { + if (!superdocRef.current?.activeEditor) return false; + + const editor = superdocRef.current.activeEditor; + const previousFields = templateFields; + + const success = + mode === 'inline' + ? editor.commands.insertStructuredContentInline?.({ + attrs: { + alias: field.alias, + tag: field.metadata ? JSON.stringify(field.metadata) : undefined, + }, + text: field.defaultValue || field.alias, + }) + : editor.commands.insertStructuredContentBlock?.({ + attrs: { + alias: field.alias, + tag: field.metadata ? JSON.stringify(field.metadata) : undefined, + }, + text: field.defaultValue || field.alias, + }); + + if (success) { + const updatedFields = getTemplateFieldsFromEditor(editor); + + setTemplateFields(updatedFields); + onFieldsChange?.(updatedFields); + + const insertedField = updatedFields.find( + (candidate) => !previousFields.some((existing) => existing.id === candidate.id), + ); + + if (insertedField) { + onFieldInsert?.(insertedField); + } + } + + return success ?? false; + }, + [onFieldInsert, onFieldsChange, templateFields], + ); + + const updateField = useCallback( + (id: string | number, updates: Partial): boolean => { + if (!superdocRef.current?.activeEditor) return false; + + const editor = superdocRef.current.activeEditor; + const success = editor.commands.updateStructuredContentById?.(id, { + attrs: updates, + }); + + if (success) { + setTemplateFields((prev) => { + const updated = prev.map((f) => (f.id === id ? { ...f, ...updates } : f)); + onFieldsChange?.(updated); + const field = updated.find((f) => f.id === id); + if (field) onFieldUpdate?.(field); + return updated; + }); + } + + return success ?? false; + }, + [onFieldUpdate, onFieldsChange], + ); + + const deleteField = useCallback( + (id: string | number): boolean => { + const editor = superdocRef.current?.activeEditor; + + if (!editor) { + let removed = false; + setTemplateFields((prev) => { + if (!prev.some((field) => field.id === id)) return prev; + + const updated = prev.filter((field) => field.id !== id); + removed = true; + onFieldsChange?.(updated); + onFieldDelete?.(id); + return updated; + }); + + if (removed) { + setSelectedFieldId((current) => (current === id ? null : current)); + } + + return removed; + } + + const fieldToDelete = templateFields.find((f) => f.id === id); + const groupId = fieldToDelete?.group; + + let commandResult = false; + try { + commandResult = editor.commands.deleteStructuredContentById?.(id) ?? false; + } catch { + commandResult = false; + } + + let documentFields = getTemplateFieldsFromEditor(editor); + const fieldStillPresent = documentFields.some((field) => field.id === id); + + if (!commandResult && fieldStillPresent) { + documentFields = documentFields.filter((field) => field.id !== id); + } + + if (groupId) { + const remainingFieldsInGroup = documentFields.filter((field) => field.group === groupId); + + if (remainingFieldsInGroup.length === 1) { + const lastField = remainingFieldsInGroup[0]; + editor.commands.updateStructuredContentById?.(lastField.id, { + attrs: { tag: undefined }, + }); + documentFields = getTemplateFieldsFromEditor(editor); + } + } + + let removedFromState = false; + + setTemplateFields((prev) => { + if (areTemplateFieldsEqual(prev, documentFields)) { + return prev; + } + + const prevHadField = prev.some((field) => field.id === id); + const nextHasField = documentFields.some((field) => field.id === id); + + if (prevHadField && !nextHasField) { + removedFromState = true; + } + + onFieldsChange?.(documentFields); + if (removedFromState) { + onFieldDelete?.(id); + } + + return documentFields; + }); + + if (removedFromState) { + setSelectedFieldId((current) => (current === id ? null : current)); + } + + return commandResult || removedFromState; + }, + [onFieldDelete, onFieldsChange, templateFields], + ); + + const selectField = useCallback( + (id: string | number) => { + if (!superdocRef.current?.activeEditor) return; + + const editor = superdocRef.current.activeEditor; + editor.commands.selectStructuredContentById?.(id); + setSelectedFieldId(id); + + const field = templateFields.find((f) => f.id === id); + if (field) onFieldSelect?.(field); + }, + [templateFields, onFieldSelect], + ); + + const discoverFields = useCallback( + (editor: Editor) => { + if (!editor) return; + + const discovered = getTemplateFieldsFromEditor(editor); + + setTemplateFields((prev) => { + if (areTemplateFieldsEqual(prev, discovered)) { + return prev; + } + + onFieldsChange?.(discovered); + return discovered; + }); + }, + [onFieldsChange], + ); + + // Initialize SuperDoc - uses abort pattern to handle React 18 Strict Mode + // which intentionally double-invokes effects to help identify cleanup issues + useEffect(() => { + if (!containerRef.current) return; + + let aborted = false; + let instance: SuperDoc | null = null; + + const initSuperDoc = async () => { + const { SuperDoc } = await import('superdoc'); + + // If cleanup ran while we were importing, abort + if (aborted) return; + + const modules: Record = { + comments: false, + ...(toolbarSettings && { + toolbar: { + selector: toolbarSettings.selector, + toolbarGroups: toolbarSettings.config.toolbarGroups || ['center'], + excludeItems: toolbarSettings.config.excludeItems || [], + ...toolbarSettings.config, + }, + }), + }; + + const handleReady = () => { + // Guard callback execution if cleanup already ran + if (aborted) return; + if (instance?.activeEditor) { + const editor = instance.activeEditor; + + editor.on('update', ({ editor: e }: any) => { + const { state } = e; + const { from } = state.selection; + + if (from >= trigger.length) { + const triggerStart = from - trigger.length; + const text = state.doc.textBetween(triggerStart, from); + + if (text === trigger) { + const coords = e.view.coordsAtPos(from); + const bounds = clampToViewport(new DOMRect(coords.left, coords.top, 0, 0)); + + const cleanup = () => { + const editor = superdocRef.current?.activeEditor; + if (!editor) return; + const currentPos = editor.state.selection.from; + const tr = editor.state.tr.delete(triggerStart, currentPos); + (editor as any).view.dispatch(tr); + }; + + triggerCleanupRef.current = cleanup; + menuTriggerFromRef.current = from; + setMenuPosition(bounds); + setMenuVisible(true); + resetMenuFilter(); + + onTrigger?.({ + position: { from: triggerStart, to: from }, + bounds, + cleanup, + }); + + return; + } + } + + if (!menuVisibleRef.current) { + return; + } + + if (menuTriggerFromRef.current == null) { + setMenuVisible(false); + resetMenuFilter(); + return; + } + + if (from < menuTriggerFromRef.current) { + setMenuVisible(false); + menuTriggerFromRef.current = null; + resetMenuFilter(); + return; + } + + const queryText = state.doc.textBetween(menuTriggerFromRef.current, from); + updateMenuFilter(queryText); + + const coords = e.view.coordsAtPos(from); + const bounds = clampToViewport(new DOMRect(coords.left, coords.top, 0, 0)); + setMenuPosition(bounds); + }); + + editor.on('update', () => { + discoverFields(editor); + }); + + discoverFields(editor); + } + + onReady?.(); + }; + + instance = new SuperDoc({ + selector: containerRef.current!, + document: document?.source, + documentMode: document?.mode || 'editing', + modules, + toolbar: toolbarSettings?.selector, + onReady: handleReady, + }); + + superdocRef.current = instance; + }; + + initSuperDoc(); + + return () => { + aborted = true; + triggerCleanupRef.current = null; + menuTriggerFromRef.current = null; + + if (instance) { + if (typeof instance.destroy === 'function') { + instance.destroy(); + } + } + + superdocRef.current = null; + }; + }, [document?.source, document?.mode, trigger, discoverFields, onReady, onTrigger, toolbarSettings]); + + const handleMenuSelect = useCallback( + async (field: Types.FieldDefinition) => { + if (triggerCleanupRef.current) { + triggerCleanupRef.current(); + triggerCleanupRef.current = null; + } + menuTriggerFromRef.current = null; + resetMenuFilter(); + + const mode = field.mode || 'inline'; + + if (field.id.startsWith('custom_') && onFieldCreate) { + const createdField = await onFieldCreate(field); + + if (createdField) { + const createdMode = createdField.mode || mode; + insertFieldInternal(createdMode, { + alias: createdField.label, + metadata: createdField.metadata, + defaultValue: createdField.defaultValue, + }); + setMenuVisible(false); + return; + } + } + + insertFieldInternal(mode, { + alias: field.label, + metadata: field.metadata, + defaultValue: field.defaultValue, + }); + setMenuVisible(false); + }, + [insertFieldInternal, onFieldCreate, resetMenuFilter], + ); + + const handleSelectExisting = useCallback( + (field: Types.TemplateField) => { + if (triggerCleanupRef.current) { + triggerCleanupRef.current(); + triggerCleanupRef.current = null; + } + menuTriggerFromRef.current = null; + resetMenuFilter(); + + const editor = superdocRef.current?.activeEditor; + if (!editor) return; + + const structuredContentHelpers = (editor.helpers as any)?.structuredContentCommands; + + if (!structuredContentHelpers) return; + + const groupId = field.group || `group-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`; + + const tagWithGroup = structuredContentHelpers.createTagObject?.({ + group: groupId, + }); + + const mode = field.mode || 'inline'; + + const success = + mode === 'inline' + ? editor.commands.insertStructuredContentInline?.({ + attrs: { + alias: field.alias, + tag: tagWithGroup, + }, + text: field.alias, + }) + : editor.commands.insertStructuredContentBlock?.({ + attrs: { + alias: field.alias, + tag: tagWithGroup, + }, + text: field.alias, + }); + + if (success) { + if (!field.group) { + updateField(field.id, { tag: tagWithGroup }); + } + + setMenuVisible(false); + + const updatedFields = getTemplateFieldsFromEditor(editor); + setTemplateFields(updatedFields); + onFieldsChange?.(updatedFields); + } + }, + [updateField, resetMenuFilter, onFieldsChange], + ); + + const handleMenuClose = useCallback(() => { + setMenuVisible(false); + menuTriggerFromRef.current = null; + resetMenuFilter(); + if (triggerCleanupRef.current) { + triggerCleanupRef.current(); + triggerCleanupRef.current = null; + } + }, [resetMenuFilter]); + + const nextField = useCallback(() => { + if (!superdocRef.current?.activeEditor || templateFields.length === 0) return; + + const currentIndex = templateFields.findIndex((f) => f.id === selectedFieldId); + const nextIndex = currentIndex >= 0 ? (currentIndex + 1) % templateFields.length : 0; + selectField(templateFields[nextIndex].id); + }, [templateFields, selectedFieldId, selectField]); + + const previousField = useCallback(() => { + if (!superdocRef.current?.activeEditor || templateFields.length === 0) return; + + const currentIndex = templateFields.findIndex((f) => f.id === selectedFieldId); + const prevIndex = currentIndex > 0 ? currentIndex - 1 : templateFields.length - 1; + selectField(templateFields[prevIndex].id); + }, [templateFields, selectedFieldId, selectField]); + + const exportTemplate = useCallback( + async (config?: Types.ExportConfig): Promise => { + const { fileName = 'document', triggerDownload = true } = config || {}; + + const result = await superdocRef.current?.export({ + exportType: ['docx'], + exportedName: fileName, + triggerDownload, + }); + + const editor = superdocRef.current?.activeEditor; + if (editor) { + const fields = getTemplateFieldsFromEditor(editor); + const blob = triggerDownload ? undefined : (result as Blob); + onExport?.({ fields, blob, fileName }); + } + + return result; + }, + [onExport], + ); + + useImperativeHandle(ref, () => ({ + insertField: (field) => insertFieldInternal('inline', field), + insertBlockField: (field) => insertFieldInternal('block', field), + updateField, + deleteField, + selectField, + nextField, + previousField, + getFields: () => templateFields, + exportTemplate, + getSuperDoc: () => superdocRef.current, + })); + + const MenuComponent = menu.component || FieldMenu; + const ListComponent = list.component || FieldList; + + return ( +
+
+ {list.position === 'left' && ( +
+ selectField(field.id)} + onDelete={deleteField} + onUpdate={(field) => updateField(field.id, field)} + selectedFieldId={selectedFieldId || undefined} + /> +
+ )} + +
+ {toolbarSettings?.renderDefaultContainer && ( +
+ )} +
+
+ + {list.position === 'right' && ( +
+ selectField(field.id)} + onDelete={deleteField} + onUpdate={(field) => updateField(field.id, field)} + selectedFieldId={selectedFieldId || undefined} + /> +
+ )} +
+ + +
+ ); + }, +); + +SuperDocTemplateBuilder.displayName = 'SuperDocTemplateBuilder'; + +export default SuperDocTemplateBuilder; diff --git a/packages/template-builder/src/test/setup.ts b/packages/template-builder/src/test/setup.ts new file mode 100644 index 0000000000..7b0828bfa8 --- /dev/null +++ b/packages/template-builder/src/test/setup.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom'; diff --git a/packages/template-builder/src/types.ts b/packages/template-builder/src/types.ts new file mode 100644 index 0000000000..d09a201feb --- /dev/null +++ b/packages/template-builder/src/types.ts @@ -0,0 +1,150 @@ +import type { SuperDoc } from 'superdoc'; + +export interface FieldDefinition { + id: string; + label: string; + defaultValue?: string; + metadata?: Record; + mode?: 'inline' | 'block'; + group?: string; +} + +export interface TemplateField { + id: string | number; + alias: string; + tag?: string; + position?: number; + mode?: 'inline' | 'block'; + group?: string; +} + +export interface TriggerEvent { + position: { from: number; to: number }; + bounds?: DOMRect; + cleanup: () => void; +} + +export interface ExportEvent { + fields: TemplateField[]; + blob?: Blob; + fileName: string; +} + +export interface FieldMenuProps { + isVisible: boolean; + position?: DOMRect; + availableFields: FieldDefinition[]; + filteredFields?: FieldDefinition[]; + filterQuery?: string; + allowCreate?: boolean; + onSelect: (field: FieldDefinition) => void; + onClose: () => void; + onCreateField?: (field: FieldDefinition) => void | Promise; + existingFields?: TemplateField[]; + onSelectExisting?: (field: TemplateField) => void; +} + +export interface FieldListProps { + fields: TemplateField[]; + onSelect: (field: TemplateField) => void; + onDelete: (fieldId: string | number) => void; + onUpdate?: (field: TemplateField) => void; + selectedFieldId?: string | number; +} + +export interface DocumentConfig { + source?: string | File | Blob; + mode?: 'editing' | 'viewing'; +} + +export interface FieldsConfig { + available?: FieldDefinition[]; + initial?: TemplateField[]; + allowCreate?: boolean; +} + +export interface MenuConfig { + component?: React.ComponentType; + trigger?: string; +} + +export interface ListConfig { + component?: React.ComponentType; + position?: 'left' | 'right'; +} + +export interface ToolbarConfig { + selector?: string; + toolbarGroups?: string[]; + groups?: Record; + fonts?: string[] | null; + hideButtons?: boolean; + responsiveToContainer?: boolean; + excludeItems?: string[]; + texts?: Record; + icons?: Record; +} + +/** + * Configuration options for exporting templates + */ +export interface ExportConfig { + /** + * The name of the exported file (without extension) + * @default "document" + */ + fileName?: string; + /** + * Whether to trigger an automatic download in the browser + * - true: Automatically downloads the file + * - false: Returns the Blob data for manual handling (e.g., saving to database) + * @default true + */ + triggerDownload?: boolean; +} + +export interface SuperDocTemplateBuilderProps { + document?: DocumentConfig; + fields?: FieldsConfig; + menu?: MenuConfig; + list?: ListConfig; + toolbar?: boolean | string | ToolbarConfig; + + // Events + onReady?: () => void; + onTrigger?: (event: TriggerEvent) => void; + onFieldInsert?: (field: TemplateField) => void; + onFieldUpdate?: (field: TemplateField) => void; + onFieldDelete?: (fieldId: string | number) => void; + onFieldsChange?: (fields: TemplateField[]) => void; + onFieldSelect?: (field: TemplateField | null) => void; + onFieldCreate?: (field: FieldDefinition) => void | Promise; + onExport?: (event: ExportEvent) => void; + + // UI + className?: string; + style?: React.CSSProperties; + documentHeight?: string; +} + +export interface SuperDocTemplateBuilderHandle { + insertField: (field: Partial & { alias: string }) => boolean; + insertBlockField: (field: Partial & { alias: string }) => boolean; + updateField: (id: string | number, updates: Partial) => boolean; + deleteField: (id: string | number) => boolean; + selectField: (id: string | number) => void; + nextField: () => void; + previousField: () => void; + getFields: () => TemplateField[]; + exportTemplate: (config?: ExportConfig) => Promise; + /** + * Returns the SuperDoc instance. + * Use this to access the full SuperDoc API, including: + * - The active editor: `getSuperDoc()?.activeEditor` + * - Editor commands: `getSuperDoc()?.activeEditor?.commands.*` + * - Editor state and helpers: `getSuperDoc()?.activeEditor?.state` + * + * Note: Full TypeScript types for SuperDoc will be available in a future update. + */ + getSuperDoc: () => SuperDoc | null; +} diff --git a/packages/template-builder/tsconfig.json b/packages/template-builder/tsconfig.json new file mode 100644 index 0000000000..615d67bd4d --- /dev/null +++ b/packages/template-builder/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "declaration": true, + "declarationDir": "./dist", + "outDir": "./dist", + "jsx": "react-jsx" + }, + "include": ["src"] +} diff --git a/packages/template-builder/vite.config.ts b/packages/template-builder/vite.config.ts new file mode 100644 index 0000000000..da339b73c0 --- /dev/null +++ b/packages/template-builder/vite.config.ts @@ -0,0 +1,25 @@ +import { defineConfig } from 'vite'; +import dts from 'vite-plugin-dts'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + build: { + lib: { + entry: 'src/index.tsx', + formats: ['es', 'cjs'], + fileName: (format) => (format === 'es' ? 'index.mjs' : 'index.js'), + }, + rollupOptions: { + external: ['react', 'react-dom', 'react/jsx-runtime', 'react/jsx-dev-runtime', 'superdoc'], + }, + }, + plugins: [react(), dts()], + test: { + environment: 'jsdom', + setupFiles: ['./src/test/setup.ts'], + globals: true, + clearMocks: true, + restoreMocks: true, + passWithNoTests: true, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b812e81ef2..4718044ca2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,15 +39,33 @@ catalogs: '@semantic-release/git': specifier: ^10.0.1 version: 10.0.1 + '@testing-library/jest-dom': + specifier: ^6.9.1 + version: 6.9.1 + '@testing-library/react': + specifier: ^16.3.0 + version: 16.3.2 + '@testing-library/user-event': + specifier: ^14.6.1 + version: 14.6.1 '@types/node': specifier: 22.19.2 version: 22.19.2 + '@types/react': + specifier: ^19.2.6 + version: 19.2.9 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3 '@typescript-eslint/eslint-plugin': specifier: ^8.49.0 version: 8.49.0 '@typescript-eslint/parser': specifier: ^8.49.0 version: 8.49.0 + '@vitejs/plugin-react': + specifier: ^5.1.1 + version: 5.1.2 '@vitejs/plugin-vue': specifier: 6.0.2 version: 6.0.2 @@ -84,6 +102,12 @@ catalogs: eslint-plugin-jsdoc: specifier: ^54.1.0 version: 54.7.0 + eslint-plugin-react: + specifier: ^7.37.5 + version: 7.37.5 + eslint-plugin-react-hooks: + specifier: ^7.0.1 + version: 7.0.1 eventemitter3: specifier: ^5.0.1 version: 5.0.1 @@ -186,6 +210,12 @@ catalogs: prosemirror-view: specifier: ^1.33.8 version: 1.41.4 + react: + specifier: ^19.2.0 + version: 19.2.3 + react-dom: + specifier: ^19.2.0 + version: 19.2.4 rehype-parse: specifier: ^9.0.1 version: 9.0.1 @@ -361,7 +391,7 @@ importers: version: 14.0.3 mintlify: specifier: ^4.2.295 - version: 4.2.295(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(typescript@5.9.3) + version: 4.2.295(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3) e2e-tests: dependencies: @@ -961,6 +991,88 @@ importers: specifier: 'catalog:' version: 1.6.11 + packages/template-builder: + devDependencies: + '@testing-library/jest-dom': + specifier: 'catalog:' + version: 6.9.1 + '@testing-library/react': + specifier: 'catalog:' + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) + '@testing-library/user-event': + specifier: 'catalog:' + version: 14.6.1(@testing-library/dom@10.4.1) + '@types/react': + specifier: 'catalog:' + version: 19.2.9 + '@types/react-dom': + specifier: 'catalog:' + version: 19.2.3(@types/react@19.2.9) + '@vitejs/plugin-react': + specifier: 'catalog:' + version: 5.1.2(vite@7.2.7(@types/node@22.19.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) + eslint-plugin-react: + specifier: 'catalog:' + version: 7.37.5(eslint@9.39.1(jiti@2.6.1)) + eslint-plugin-react-hooks: + specifier: 'catalog:' + version: 7.0.1(eslint@9.39.1(jiti@2.6.1)) + jsdom: + specifier: 'catalog:' + version: 27.3.0(canvas@3.2.0)(postcss@8.5.6) + react: + specifier: 'catalog:' + version: 19.2.3 + react-dom: + specifier: 'catalog:' + version: 19.2.4(react@19.2.3) + superdoc: + specifier: workspace:* + version: link:../superdoc + typescript: + specifier: 'catalog:' + version: 5.9.3 + vite: + specifier: 'catalog:' + version: 7.2.7(@types/node@22.19.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) + vite-plugin-dts: + specifier: 'catalog:' + version: 4.5.4(@types/node@22.19.2)(rollup@4.53.3)(typescript@5.9.3)(vite@7.2.7(@types/node@22.19.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) + vitest: + specifier: 'catalog:' + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.2)(happy-dom@20.3.4)(jiti@2.6.1)(jsdom@27.3.0(canvas@3.2.0)(postcss@8.5.6))(tsx@4.21.0)(yaml@2.8.2) + + packages/template-builder/demo: + dependencies: + '@superdoc-dev/template-builder': + specifier: link:.. + version: link:.. + react: + specifier: 'catalog:' + version: 19.2.3 + react-dom: + specifier: 'catalog:' + version: 19.2.4(react@19.2.3) + superdoc: + specifier: workspace:* + version: link:../../superdoc + devDependencies: + '@types/react': + specifier: 'catalog:' + version: 19.2.9 + '@types/react-dom': + specifier: 'catalog:' + version: 19.2.3(@types/react@19.2.9) + '@vitejs/plugin-react': + specifier: 'catalog:' + version: 5.1.2(vite@7.2.7(@types/node@22.19.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) + typescript: + specifier: 'catalog:' + version: 5.9.3 + vite: + specifier: 'catalog:' + version: 7.2.7(@types/node@22.19.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) + packages/word-layout: devDependencies: vitest: @@ -996,6 +1108,9 @@ packages: '@acemir/cssom@0.9.29': resolution: {integrity: sha512-G90x0VW+9nW4dFajtjCoT+NM0scAfH9Mb08IcjgFHYbfiL/lU04dTF9JuVOi3/OH+DJCQdcIseSXkdCB9Ky6JA==} + '@adobe/css-tools@4.4.4': + resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} + '@alcalzone/ansi-tokenize@0.2.3': resolution: {integrity: sha512-jsElTJ0sQ4wHRz+C45tfect76BwbTbgkgKByOzpCN9xG61N5V6u/glvg1CsNJhq2xJIFpKHSwG3D2wPPuEYOrQ==} engines: {node: '>=18'} @@ -1073,6 +1188,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -1094,6 +1213,22 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.28.6': + resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} + engines: {node: '>=6.9.0'} + '@babel/template@7.28.6': resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} @@ -2479,6 +2614,9 @@ packages: '@rolldown/pluginutils@1.0.0-beta.50': resolution: {integrity: sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==} + '@rolldown/pluginutils@1.0.0-beta.53': + resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} + '@rollup/plugin-inject@5.0.5': resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} engines: {node: '>=14.0.0'} @@ -2816,6 +2954,35 @@ packages: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.3.2': + resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@testing-library/user-event@14.6.1': + resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} @@ -2831,6 +2998,21 @@ packages: '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -2922,6 +3104,11 @@ packages: '@types/parse5@6.0.3': resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + '@types/react@19.2.9': resolution: {integrity: sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==} @@ -3190,6 +3377,12 @@ packages: resolution: {integrity: sha512-/AYNGafG9T90NPGsq6eDMuXx+41tlWfiYsCchgwz074GWEitZ2nAZQWWNvYvFVB2hXzord52muEVTWjgaZPOdQ==} engines: {node: '>=18'} + '@vitejs/plugin-react@5.1.2': + resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitejs/plugin-vue@6.0.2': resolution: {integrity: sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3423,6 +3616,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} @@ -3469,6 +3666,13 @@ packages: resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + arkregex@0.0.3: resolution: {integrity: sha512-bU21QJOJEFJK+BPNgv+5bVXkvRxyAvgnon75D92newgHxkBJTgiFwQxusyViYyJkETsddPlHyspshDQcCzmkNg==} @@ -3502,6 +3706,10 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + array.prototype.findlastindex@1.2.6: resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} engines: {node: '>= 0.4'} @@ -3514,6 +3722,10 @@ packages: resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} engines: {node: '>= 0.4'} + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + arraybuffer.prototype.slice@1.0.4: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} @@ -4210,6 +4422,9 @@ packages: resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -4456,6 +4671,12 @@ packages: engines: {node: '>=14'} hasBin: true + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + domain-browser@4.22.0: resolution: {integrity: sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==} engines: {node: '>=10'} @@ -4572,6 +4793,10 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-iterator-helpers@1.2.2: + resolution: {integrity: sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==} + engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -4719,6 +4944,18 @@ packages: peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + eslint-plugin-react-hooks@7.0.1: + resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5405,6 +5642,12 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + hex-rgb@5.0.0: resolution: {integrity: sha512-NQO+lgVUCtHxZ792FodgW0zflK+ozS9X9dwGp9XvvmPlH7pyxd588cn24TD3rmPm/N0AIRXF10Otah8yKqGw4w==} engines: {node: '>=12'} @@ -5920,6 +6163,10 @@ packages: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -6071,6 +6318,10 @@ packages: resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} engines: {'0': node >=0.6.0} + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + jszip@3.10.1: resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} @@ -6318,6 +6569,10 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -6764,6 +7019,10 @@ packages: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -7191,6 +7450,10 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + object.fromentries@2.0.8: resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} engines: {node: '>= 0.4'} @@ -7714,6 +7977,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-ms@9.3.0: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} engines: {node: '>=18'} @@ -7735,6 +8002,9 @@ packages: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} @@ -7887,10 +8157,16 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - react-dom@18.3.1: - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + react-dom@19.2.4: + resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} peerDependencies: - react: ^18.3.1 + react: ^19.2.4 + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} react-reconciler@0.32.0: resolution: {integrity: sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ==} @@ -7898,6 +8174,10 @@ packages: peerDependencies: react: ^19.1.0 + react-refresh@0.18.0: + resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} + engines: {node: '>=0.10.0'} + react-remove-scroll-bar@2.3.8: resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} @@ -7996,6 +8276,10 @@ packages: recma-stringify@1.0.0: resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -8126,6 +8410,10 @@ packages: engines: {node: '>= 0.4'} hasBin: true + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} @@ -8236,12 +8524,12 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} - scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + seemly@0.3.10: resolution: {integrity: sha512-2+SMxtG1PcsL0uyhkumlOU6Qo9TAQ/WyH7tthnPIOQB05/12jz9naq6GZ6iZ6ApVsO3rr2gsnTf3++OV63kE1Q==} @@ -8569,6 +8857,13 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -8614,6 +8909,10 @@ packages: resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} engines: {node: '>=18'} + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -9640,6 +9939,12 @@ packages: peerDependencies: zod: ^3.20.0 + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + zod@3.21.4: resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} @@ -9656,6 +9961,8 @@ snapshots: '@acemir/cssom@0.9.29': {} + '@adobe/css-tools@4.4.4': {} + '@alcalzone/ansi-tokenize@0.2.3': dependencies: ansi-styles: 6.2.3 @@ -9794,6 +10101,8 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-plugin-utils@7.28.6': {} + '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.28.5': {} @@ -9809,6 +10118,18 @@ snapshots: dependencies: '@babel/types': 7.28.6 + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.6)': + dependencies: + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.6)': + dependencies: + '@babel/core': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/runtime@7.28.6': {} + '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.28.6 @@ -10239,11 +10560,11 @@ snapshots: '@floating-ui/core': 1.7.3 '@floating-ui/utils': 0.2.10 - '@floating-ui/react-dom@2.1.6(react-dom@18.3.1(react@19.2.3))(react@19.2.3)': + '@floating-ui/react-dom@2.1.6(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': dependencies: '@floating-ui/dom': 1.7.4 react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) '@floating-ui/utils@0.2.10': {} @@ -10833,15 +11154,15 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@mintlify/cli@4.0.899(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(typescript@5.9.3)': + '@mintlify/cli@4.0.899(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3)': dependencies: '@inquirer/prompts': 7.9.0(@types/node@22.19.2) - '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) - '@mintlify/link-rot': 3.0.838(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/link-rot': 3.0.838(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/models': 0.0.258 - '@mintlify/prebuild': 1.0.816(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) - '@mintlify/previewing': 4.0.872(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(typescript@5.9.3) - '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/prebuild': 1.0.816(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/previewing': 4.0.872(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3) + '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) adm-zip: 0.5.16 chalk: 5.2.0 color: 4.2.3 @@ -10873,13 +11194,13 @@ snapshots: - typescript - utf-8-validate - '@mintlify/common@1.0.661(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@mintlify/common@1.0.661(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: '@asyncapi/parser': 3.4.0 - '@mintlify/mdx': 3.0.4(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/mdx': 3.0.4(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/models': 0.0.255 '@mintlify/openapi-parser': 0.0.8 - '@mintlify/validation': 0.1.555(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/validation': 0.1.555(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@sindresorhus/slugify': 2.2.0 '@types/mdast': 4.0.4 acorn: 8.11.2 @@ -10933,13 +11254,13 @@ snapshots: - ts-node - typescript - '@mintlify/common@1.0.681(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@mintlify/common@1.0.681(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: '@asyncapi/parser': 3.4.0 - '@mintlify/mdx': 3.0.4(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/mdx': 3.0.4(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/models': 0.0.258 '@mintlify/openapi-parser': 0.0.8 - '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@sindresorhus/slugify': 2.2.0 '@types/mdast': 4.0.4 acorn: 8.11.2 @@ -10993,13 +11314,13 @@ snapshots: - ts-node - typescript - '@mintlify/link-rot@3.0.838(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@mintlify/link-rot@3.0.838(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: - '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) - '@mintlify/prebuild': 1.0.816(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) - '@mintlify/previewing': 4.0.872(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(typescript@5.9.3) - '@mintlify/scraping': 4.0.522(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) - '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/prebuild': 1.0.816(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/previewing': 4.0.872(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3) + '@mintlify/scraping': 4.0.522(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) fs-extra: 11.1.0 unist-util-visit: 4.1.2 transitivePeerDependencies: @@ -11019,9 +11340,9 @@ snapshots: - typescript - utf-8-validate - '@mintlify/mdx@3.0.4(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@mintlify/mdx@3.0.4(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: - '@radix-ui/react-popover': 1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) '@shikijs/transformers': 3.21.0 '@shikijs/twoslash': 3.21.0(typescript@5.9.3) arktype: 2.1.29 @@ -11030,9 +11351,9 @@ snapshots: mdast-util-gfm: 3.1.0 mdast-util-mdx-jsx: 3.2.0 mdast-util-to-hast: 13.2.1 - next-mdx-remote-client: 1.1.4(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(unified@11.0.5) + next-mdx-remote-client: 1.1.4(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(unified@11.0.5) react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) rehype-katex: 7.0.1 remark-gfm: 4.0.1 remark-math: 6.0.0 @@ -11068,12 +11389,12 @@ snapshots: leven: 4.1.0 yaml: 2.8.2 - '@mintlify/prebuild@1.0.816(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@mintlify/prebuild@1.0.816(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: - '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/openapi-parser': 0.0.8 - '@mintlify/scraping': 4.0.542(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) - '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/scraping': 4.0.542(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) chalk: 5.3.0 favicons: 7.2.0 front-matter: 4.0.2 @@ -11100,11 +11421,11 @@ snapshots: - typescript - utf-8-validate - '@mintlify/previewing@4.0.872(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(typescript@5.9.3)': + '@mintlify/previewing@4.0.872(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3)': dependencies: - '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) - '@mintlify/prebuild': 1.0.816(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) - '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/prebuild': 1.0.816(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/validation': 0.1.567(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) better-opn: 3.0.2 chalk: 5.2.0 chokidar: 3.5.3 @@ -11138,9 +11459,9 @@ snapshots: - typescript - utf-8-validate - '@mintlify/scraping@4.0.522(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@mintlify/scraping@4.0.522(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: - '@mintlify/common': 1.0.661(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/common': 1.0.661(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/openapi-parser': 0.0.8 fs-extra: 11.1.1 hast-util-to-mdast: 10.1.0 @@ -11173,9 +11494,9 @@ snapshots: - typescript - utf-8-validate - '@mintlify/scraping@4.0.542(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@mintlify/scraping@4.0.542(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: - '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/common': 1.0.681(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/openapi-parser': 0.0.8 fs-extra: 11.1.1 hast-util-to-mdast: 10.1.0 @@ -11208,9 +11529,9 @@ snapshots: - typescript - utf-8-validate - '@mintlify/validation@0.1.555(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@mintlify/validation@0.1.555(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: - '@mintlify/mdx': 3.0.4(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/mdx': 3.0.4(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/models': 0.0.255 arktype: 2.1.27 js-yaml: 4.1.0 @@ -11230,9 +11551,9 @@ snapshots: - supports-color - typescript - '@mintlify/validation@0.1.567(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': + '@mintlify/validation@0.1.567(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3)': dependencies: - '@mintlify/mdx': 3.0.4(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(typescript@5.9.3) + '@mintlify/mdx': 3.0.4(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(typescript@5.9.3) '@mintlify/models': 0.0.258 arktype: 2.1.27 js-yaml: 4.1.0 @@ -11383,13 +11704,14 @@ snapshots: '@radix-ui/primitive@1.1.3': {} - '@radix-ui/react-arrow@1.1.7(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)': + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) optionalDependencies: '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.9)(react@19.2.3)': dependencies: @@ -11403,17 +11725,18 @@ snapshots: optionalDependencies: '@types/react': 19.2.9 - '@radix-ui/react-dismissable-layer@1.1.11(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)': + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/primitive': 1.1.3 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.9)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.9)(react@19.2.3) '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.9)(react@19.2.3) react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) optionalDependencies: '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.9)(react@19.2.3)': dependencies: @@ -11421,15 +11744,16 @@ snapshots: optionalDependencies: '@types/react': 19.2.9 - '@radix-ui/react-focus-scope@1.1.7(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)': + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.9)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.9)(react@19.2.3) react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) optionalDependencies: '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) '@radix-ui/react-id@1.1.1(@types/react@19.2.9)(react@19.2.3)': dependencies: @@ -11438,70 +11762,75 @@ snapshots: optionalDependencies: '@types/react': 19.2.9 - '@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)': + '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/primitive': 1.1.3 '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.9)(react@19.2.3) '@radix-ui/react-context': 1.1.2(@types/react@19.2.9)(react@19.2.3) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.9)(react@19.2.3) - '@radix-ui/react-focus-scope': 1.1.7(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) '@radix-ui/react-id': 1.1.1(@types/react@19.2.9)(react@19.2.3) - '@radix-ui/react-popper': 1.2.8(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) - '@radix-ui/react-portal': 1.1.9(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) - '@radix-ui/react-presence': 1.1.5(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) '@radix-ui/react-slot': 1.2.3(@types/react@19.2.9)(react@19.2.3) '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.9)(react@19.2.3) aria-hidden: 1.2.6 react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) react-remove-scroll: 2.7.2(@types/react@19.2.9)(react@19.2.3) optionalDependencies: '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) - '@radix-ui/react-popper@1.2.8(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)': + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': dependencies: - '@floating-ui/react-dom': 2.1.6(react-dom@18.3.1(react@19.2.3))(react@19.2.3) - '@radix-ui/react-arrow': 1.1.7(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@floating-ui/react-dom': 2.1.6(react-dom@19.2.4(react@19.2.3))(react@19.2.3) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.9)(react@19.2.3) '@radix-ui/react-context': 1.1.2(@types/react@19.2.9)(react@19.2.3) - '@radix-ui/react-primitive': 2.1.3(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.9)(react@19.2.3) '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.9)(react@19.2.3) '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.9)(react@19.2.3) '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.9)(react@19.2.3) '@radix-ui/rect': 1.1.1 react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) optionalDependencies: '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) - '@radix-ui/react-portal@1.1.9(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)': + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3) '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.9)(react@19.2.3) react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) optionalDependencies: '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) - '@radix-ui/react-presence@1.1.5(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)': + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.9)(react@19.2.3) '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.9)(react@19.2.3) react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) optionalDependencies: '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) - '@radix-ui/react-primitive@2.1.3(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)': + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/react-slot': 1.2.3(@types/react@19.2.9)(react@19.2.3) react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) optionalDependencies: '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) '@radix-ui/react-slot@1.2.3(@types/react@19.2.9)(react@19.2.3)': dependencies: @@ -11562,6 +11891,8 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.50': {} + '@rolldown/pluginutils@1.0.0-beta.53': {} + '@rollup/plugin-inject@5.0.5(rollup@4.53.3)': dependencies: '@rollup/pluginutils': 5.3.0(rollup@4.53.3) @@ -11998,6 +12329,40 @@ snapshots: dependencies: defer-to-connect: 2.0.1 + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.28.6 + '@babel/runtime': 7.28.6 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.4.4 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)': + dependencies: + '@babel/runtime': 7.28.6 + '@testing-library/dom': 10.4.1 + react: 19.2.3 + react-dom: 19.2.4(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) + + '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': + dependencies: + '@testing-library/dom': 10.4.1 + '@tokenizer/token@0.3.0': {} '@tootallnate/quickjs-emscripten@0.23.0': {} @@ -12013,6 +12378,29 @@ snapshots: '@types/argparse@1.0.38': {} + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.28.6 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.28.6 + '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 @@ -12108,6 +12496,10 @@ snapshots: '@types/parse5@6.0.3': {} + '@types/react-dom@19.2.3(@types/react@19.2.9)': + dependencies: + '@types/react': 19.2.9 + '@types/react@19.2.9': dependencies: csstype: 3.2.3 @@ -12451,6 +12843,18 @@ snapshots: lodash: 4.17.21 minimatch: 7.4.6 + '@vitejs/plugin-react@5.1.2(vite@7.2.7(@types/node@22.19.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@babel/core': 7.28.6 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.6) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.6) + '@rolldown/pluginutils': 1.0.0-beta.53 + '@types/babel__core': 7.20.5 + react-refresh: 0.18.0 + vite: 7.2.7(@types/node@22.19.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - supports-color + '@vitejs/plugin-vue@6.0.2(vite@7.2.7(@types/node@22.19.2)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))(vue@3.5.25(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.50 @@ -12743,6 +13147,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.3: {} any-base@1.1.0: {} @@ -12781,6 +13187,12 @@ snapshots: dependencies: tslib: 2.8.1 + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + arkregex@0.0.3: dependencies: '@ark/util': 0.55.0 @@ -12820,12 +13232,20 @@ snapshots: get-intrinsic: 1.3.0 is-string: 1.1.1 math-intrinsics: 1.1.0 - optional: true array-iterate@2.0.1: {} array-union@2.1.0: {} + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + array.prototype.findlastindex@1.2.6: dependencies: call-bind: 1.0.8 @@ -12843,7 +13263,6 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.24.1 es-shim-unscopables: 1.1.0 - optional: true array.prototype.flatmap@1.3.3: dependencies: @@ -12851,7 +13270,14 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.24.1 es-shim-unscopables: 1.1.0 - optional: true + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 arraybuffer.prototype.slice@1.0.4: dependencies: @@ -13609,6 +14035,8 @@ snapshots: mdn-data: 2.12.2 source-map-js: 1.2.1 + css.escape@1.5.1: {} + cssesc@3.0.0: {} cssstyle@5.3.4(postcss@8.5.6): @@ -13822,7 +14250,6 @@ snapshots: doctrine@2.1.0: dependencies: esutils: 2.0.3 - optional: true documentation@14.0.3: dependencies: @@ -13869,6 +14296,10 @@ snapshots: transitivePeerDependencies: - supports-color + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + domain-browser@4.22.0: {} dot-prop@5.3.0: @@ -14050,6 +14481,25 @@ snapshots: es-errors@1.3.0: {} + es-iterator-helpers@1.2.2: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + safe-array-concat: 1.1.3 + es-module-lexer@1.7.0: {} es-object-atoms@1.1.1: @@ -14066,7 +14516,6 @@ snapshots: es-shim-unscopables@1.1.0: dependencies: hasown: 2.0.2 - optional: true es-to-primitive@1.3.0: dependencies: @@ -14280,6 +14729,39 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-plugin-react-hooks@7.0.1(eslint@9.39.1(jiti@2.6.1)): + dependencies: + '@babel/core': 7.28.6 + '@babel/parser': 7.28.6 + eslint: 9.39.1(jiti@2.6.1) + hermes-parser: 0.25.1 + zod: 3.25.76 + zod-validation-error: 4.0.2(zod@3.25.76) + transitivePeerDependencies: + - supports-color + + eslint-plugin-react@7.37.5(eslint@9.39.1(jiti@2.6.1)): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.2 + eslint: 9.39.1(jiti@2.6.1) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -15359,6 +15841,12 @@ snapshots: he@1.2.0: {} + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + hex-rgb@5.0.0: {} highlight.js@10.7.3: {} @@ -15853,6 +16341,15 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -16041,6 +16538,13 @@ snapshots: json-schema: 0.4.0 verror: 1.10.0 + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.9 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + jszip@3.10.1: dependencies: lie: 3.3.0 @@ -16260,6 +16764,8 @@ snapshots: lru-cache@7.18.3: {} + lz-string@1.5.0: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -17178,6 +17684,8 @@ snapshots: mimic-response@4.0.0: {} + min-indent@1.0.1: {} + minimalistic-assert@1.0.1: {} minimalistic-crypto-utils@1.0.1: {} @@ -17225,9 +17733,9 @@ snapshots: minipass: 3.3.6 yallist: 4.0.0 - mintlify@4.2.295(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(typescript@5.9.3): + mintlify@4.2.295(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3): dependencies: - '@mintlify/cli': 4.0.899(@radix-ui/react-popover@1.1.15(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(typescript@5.9.3) + '@mintlify/cli': 4.0.899(@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3))(@types/node@22.19.2)(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(typescript@5.9.3) transitivePeerDependencies: - '@radix-ui/react-popover' - '@types/node' @@ -17320,13 +17828,13 @@ snapshots: netmask@2.0.2: {} - next-mdx-remote-client@1.1.4(@types/react@19.2.9)(react-dom@18.3.1(react@19.2.3))(react@19.2.3)(unified@11.0.5): + next-mdx-remote-client@1.1.4(@types/react@19.2.9)(react-dom@19.2.4(react@19.2.3))(react@19.2.3)(unified@11.0.5): dependencies: '@babel/code-frame': 7.28.6 '@mdx-js/mdx': 3.1.1 '@mdx-js/react': 3.1.1(@types/react@19.2.9)(react@19.2.3) react: 19.2.3 - react-dom: 18.3.1(react@19.2.3) + react-dom: 19.2.4(react@19.2.3) remark-mdx-remove-esm: 1.2.2(unified@11.0.5) serialize-error: 12.0.0 vfile: 6.0.3 @@ -17506,13 +18014,19 @@ snapshots: has-symbols: 1.1.0 object-keys: 1.1.1 + object.entries@1.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + object.fromentries@2.0.8: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 es-abstract: 1.24.1 es-object-atoms: 1.1.1 - optional: true object.groupby@1.0.3: dependencies: @@ -17527,7 +18041,6 @@ snapshots: call-bound: 1.0.4 define-properties: 1.2.1 es-object-atoms: 1.1.1 - optional: true omggif@1.0.10: {} @@ -18037,6 +18550,12 @@ snapshots: prettier@3.7.4: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + pretty-ms@9.3.0: dependencies: parse-ms: 4.0.0 @@ -18051,6 +18570,12 @@ snapshots: progress@2.0.3: {} + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + property-information@6.5.0: {} property-information@7.1.0: {} @@ -18280,17 +18805,22 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-dom@18.3.1(react@19.2.3): + react-dom@19.2.4(react@19.2.3): dependencies: - loose-envify: 1.4.0 react: 19.2.3 - scheduler: 0.23.2 + scheduler: 0.27.0 + + react-is@16.13.1: {} + + react-is@17.0.2: {} react-reconciler@0.32.0(react@19.2.3): dependencies: react: 19.2.3 scheduler: 0.26.0 + react-refresh@0.18.0: {} + react-remove-scroll-bar@2.3.8(@types/react@19.2.9)(react@19.2.3): dependencies: react: 19.2.3 @@ -18423,6 +18953,11 @@ snapshots: unified: 11.0.5 vfile: 6.0.3 + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -18676,6 +19211,12 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + responselike@2.0.1: dependencies: lowercase-keys: 2.0.0 @@ -18821,12 +19362,10 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.23.2: - dependencies: - loose-envify: 1.4.0 - scheduler@0.26.0: {} + scheduler@0.27.0: {} + seemly@0.3.10: {} semantic-release-linear-app@0.5.1(semantic-release@24.2.9(typescript@5.9.3)): @@ -19307,6 +19846,27 @@ snapshots: get-east-asian-width: 1.4.0 strip-ansi: 7.1.2 + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.24.1 + string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.8 @@ -19359,6 +19919,10 @@ snapshots: strip-final-newline@4.0.0: {} + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + strip-json-comments@2.0.1: {} strip-json-comments@3.1.1: {} @@ -20569,6 +21133,10 @@ snapshots: dependencies: zod: 3.21.4 + zod-validation-error@4.0.2(zod@3.25.76): + dependencies: + zod: 3.25.76 + zod@3.21.4: {} zod@3.23.8: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 78c6cfe49d..c3663a0bf4 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,6 +6,18 @@ packages: - shared/* catalog: + # React dependencies (for template-builder) + '@vitejs/plugin-react': ^5.1.1 + '@testing-library/react': ^16.3.0 + '@testing-library/jest-dom': ^6.9.1 + '@testing-library/user-event': ^14.6.1 + '@types/react': ^19.2.6 + '@types/react-dom': ^19.2.3 + react: ^19.2.0 + react-dom: ^19.2.0 + eslint-plugin-react: ^7.37.5 + eslint-plugin-react-hooks: ^7.0.1 + # Core dependencies '@commitlint/cli': ^19.8.1 '@commitlint/config-conventional': ^19.8.1 '@eslint/js': ^9.31.0 From 8400741202d8f4aa160d22340a921cdda9c3eec7 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Fri, 30 Jan 2026 12:19:21 -0300 Subject: [PATCH 2/5] ci: fix permissions --- .github/workflows/ci-template-builder.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci-template-builder.yml b/.github/workflows/ci-template-builder.yml index 4dd3a1cb5d..fe39ff2d3f 100644 --- a/.github/workflows/ci-template-builder.yml +++ b/.github/workflows/ci-template-builder.yml @@ -1,5 +1,8 @@ name: CI Template Builder +permissions: + contents: read + on: pull_request: paths: From 030c97a7caeebe5a0a8b54867266388dffb69a3e Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Fri, 30 Jan 2026 12:19:39 -0300 Subject: [PATCH 3/5] fix: ref link --- packages/template-builder/demo/src/App.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/template-builder/demo/src/App.tsx b/packages/template-builder/demo/src/App.tsx index 8f7094ce54..68bd9605b1 100644 --- a/packages/template-builder/demo/src/App.tsx +++ b/packages/template-builder/demo/src/App.tsx @@ -198,7 +198,11 @@ export function App() {

- + GitHub From c4c05bf3d9bf46972e595e63e92accd368788505 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Fri, 30 Jan 2026 12:19:59 -0300 Subject: [PATCH 4/5] chore: add logs --- packages/template-builder/src/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/template-builder/src/index.tsx b/packages/template-builder/src/index.tsx index 99d50d5ed7..2aeb07e276 100644 --- a/packages/template-builder/src/index.tsx +++ b/packages/template-builder/src/index.tsx @@ -272,7 +272,8 @@ const SuperDocTemplateBuilder = forwardRef Date: Fri, 30 Jan 2026 13:43:20 -0300 Subject: [PATCH 5/5] docs: update repo ref link --- apps/docs/ai/ai-builder/overview.mdx | 2 +- apps/docs/api-reference/introduction.mdx | 2 +- apps/docs/core/supereditor/configuration.mdx | 2 +- apps/docs/docs.json | 2 +- apps/docs/getting-started/ai-agents.mdx | 2 +- apps/docs/getting-started/frameworks/react.mdx | 2 +- apps/docs/getting-started/frameworks/vue.mdx | 2 +- apps/docs/getting-started/introduction.mdx | 2 +- apps/docs/guides/migration/prosemirror.mdx | 2 +- apps/docs/modules/collaboration/cloud/liveblocks.mdx | 2 +- apps/docs/modules/collaboration/cloud/tiptap-cloud.mdx | 2 +- apps/docs/modules/collaboration/quickstart.mdx | 2 +- apps/docs/modules/collaboration/self-hosted/hocuspocus.mdx | 2 +- apps/docs/modules/collaboration/self-hosted/superdoc-yjs.mdx | 4 ++-- apps/docs/modules/collaboration/self-hosted/y-sweet.mdx | 2 +- apps/docs/openapi.json | 2 +- apps/docs/resources/license.mdx | 4 ++-- apps/docs/scripts/sync-api-docs.js | 2 +- apps/docs/snippets/components/source-code-link.jsx | 2 +- 19 files changed, 21 insertions(+), 21 deletions(-) diff --git a/apps/docs/ai/ai-builder/overview.mdx b/apps/docs/ai/ai-builder/overview.mdx index f7333223b7..6b6c83c43c 100644 --- a/apps/docs/ai/ai-builder/overview.mdx +++ b/apps/docs/ai/ai-builder/overview.mdx @@ -23,4 +23,4 @@ See the [AI Actions Quick Start](/ai/ai-actions/overview#quick-start) to get sta ## Get notified -Want to be notified when AI Builder launches? [Join our Discord](https://discord.com/invite/b9UuaZRyaB) or [watch on GitHub](https://github.com/Harbour-Enterprises/SuperDoc). +Want to be notified when AI Builder launches? [Join our Discord](https://discord.com/invite/b9UuaZRyaB) or [watch on GitHub](https://github.com/superdoc-dev/superdoc). diff --git a/apps/docs/api-reference/introduction.mdx b/apps/docs/api-reference/introduction.mdx index eecdf0c626..c663635492 100644 --- a/apps/docs/api-reference/introduction.mdx +++ b/apps/docs/api-reference/introduction.mdx @@ -70,4 +70,4 @@ Your Word documents work because we built for Word documents. Not markdown. Not ## Resources **[Status Page](https://status.superdoc.dev)** - Uptime and incidents -**[GitHub](https://github.com/Harbour-Enterprises/SuperDoc)** - Examples and issues +**[GitHub](https://github.com/superdoc-dev/superdoc)** - Examples and issues diff --git a/apps/docs/core/supereditor/configuration.mdx b/apps/docs/core/supereditor/configuration.mdx index 874ae10e2b..e0f88a938e 100644 --- a/apps/docs/core/supereditor/configuration.mdx +++ b/apps/docs/core/supereditor/configuration.mdx @@ -238,7 +238,7 @@ Convert DOCX files server-side without a browser using JSDOM. See the [headless-converter - example](https://github.com/Harbour-Enterprises/superdoc/tree/main/examples/advanced/headless-converter) + example](https://github.com/superdoc-dev/superdoc/tree/main/examples/advanced/headless-converter) for a complete implementation. diff --git a/apps/docs/docs.json b/apps/docs/docs.json index 92eee0362b..a0a8d97c98 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -285,7 +285,7 @@ "links": [ { "type": "button", - "href": "https://github.com/Harbour-Enterprises/SuperDoc", + "href": "https://github.com/superdoc-dev/superdoc", "label": "", "icon": "github" }, diff --git a/apps/docs/getting-started/ai-agents.mdx b/apps/docs/getting-started/ai-agents.mdx index 89f829f197..6c21759890 100644 --- a/apps/docs/getting-started/ai-agents.mdx +++ b/apps/docs/getting-started/ai-agents.mdx @@ -35,7 +35,7 @@ const editor = new Editor({ editor.commands.insertContent(aiContent, { contentType: 'html' }); ``` -[See complete example →](https://github.com/Harbour-Enterprises/SuperDoc/tree/develop/examples/agentic-slack-redlining-example) +[See complete example →](https://github.com/superdoc-dev/superdoc/tree/develop/examples/agentic-slack-redlining-example) ## The AI Document Workflow diff --git a/apps/docs/getting-started/frameworks/react.mdx b/apps/docs/getting-started/frameworks/react.mdx index a23c1e324f..1cdf37a43d 100644 --- a/apps/docs/getting-started/frameworks/react.mdx +++ b/apps/docs/getting-started/frameworks/react.mdx @@ -265,4 +265,4 @@ function useSuperDoc(config) { - [Vue Integration](/getting-started/frameworks/vue) - Vue setup - [API Reference](/core/superdoc/configuration) - Configuration options -- [Examples](https://github.com/Harbour-Enterprises/SuperDoc/tree/main/examples/react-example) - Working examples +- [Examples](https://github.com/superdoc-dev/superdoc/tree/main/examples/react-example) - Working examples diff --git a/apps/docs/getting-started/frameworks/vue.mdx b/apps/docs/getting-started/frameworks/vue.mdx index 1198fbc8d1..c5289e77a6 100644 --- a/apps/docs/getting-started/frameworks/vue.mdx +++ b/apps/docs/getting-started/frameworks/vue.mdx @@ -206,4 +206,4 @@ defineExpose({ - [React Integration](/getting-started/frameworks/react) - React setup - [API Reference](/core/superdoc/configuration) - Configuration options -- [Examples](https://github.com/Harbour-Enterprises/SuperDoc/tree/main/examples/vue-example) - Working examples \ No newline at end of file +- [Examples](https://github.com/superdoc-dev/superdoc/tree/main/examples/vue-example) - Working examples \ No newline at end of file diff --git a/apps/docs/getting-started/introduction.mdx b/apps/docs/getting-started/introduction.mdx index 9bcb1c3326..811350ee06 100644 --- a/apps/docs/getting-started/introduction.mdx +++ b/apps/docs/getting-started/introduction.mdx @@ -45,7 +45,7 @@ Get started with SuperDoc in minutes Working demos and templates diff --git a/apps/docs/guides/migration/prosemirror.mdx b/apps/docs/guides/migration/prosemirror.mdx index f625b4f49f..ea9d359aaa 100644 --- a/apps/docs/guides/migration/prosemirror.mdx +++ b/apps/docs/guides/migration/prosemirror.mdx @@ -60,6 +60,6 @@ If you need features SuperDoc doesn't provide, you have limited options: ## Need help? -- [GitHub Issues](https://github.com/Harbour-Enterprises/SuperDoc/issues) +- [GitHub Issues](https://github.com/superdoc-dev/superdoc/issues) - [Discord Community](https://discord.com/invite/b9UuaZRyaB) - Email: q@superdoc.dev diff --git a/apps/docs/modules/collaboration/cloud/liveblocks.mdx b/apps/docs/modules/collaboration/cloud/liveblocks.mdx index c4553c6c5d..d87815a248 100644 --- a/apps/docs/modules/collaboration/cloud/liveblocks.mdx +++ b/apps/docs/modules/collaboration/cloud/liveblocks.mdx @@ -229,7 +229,7 @@ useEffect(() => { Complete source code diff --git a/apps/docs/modules/collaboration/cloud/tiptap-cloud.mdx b/apps/docs/modules/collaboration/cloud/tiptap-cloud.mdx index 09423394a0..179483fd5a 100644 --- a/apps/docs/modules/collaboration/cloud/tiptap-cloud.mdx +++ b/apps/docs/modules/collaboration/cloud/tiptap-cloud.mdx @@ -188,7 +188,7 @@ superdoc.destroy(); Complete source code diff --git a/apps/docs/modules/collaboration/quickstart.mdx b/apps/docs/modules/collaboration/quickstart.mdx index 193ef4d0a8..498ba9402c 100644 --- a/apps/docs/modules/collaboration/quickstart.mdx +++ b/apps/docs/modules/collaboration/quickstart.mdx @@ -268,7 +268,7 @@ const client = createClient({ Complete source code on GitHub diff --git a/apps/docs/modules/collaboration/self-hosted/hocuspocus.mdx b/apps/docs/modules/collaboration/self-hosted/hocuspocus.mdx index ab4d576d73..50f53bf159 100644 --- a/apps/docs/modules/collaboration/self-hosted/hocuspocus.mdx +++ b/apps/docs/modules/collaboration/self-hosted/hocuspocus.mdx @@ -275,7 +275,7 @@ Server.configure({ Complete source code diff --git a/apps/docs/modules/collaboration/self-hosted/superdoc-yjs.mdx b/apps/docs/modules/collaboration/self-hosted/superdoc-yjs.mdx index b57f5b381c..881c19800f 100644 --- a/apps/docs/modules/collaboration/self-hosted/superdoc-yjs.mdx +++ b/apps/docs/modules/collaboration/self-hosted/superdoc-yjs.mdx @@ -353,7 +353,7 @@ fastify.get('/health', (request, reply) => { Complete working example @@ -361,7 +361,7 @@ fastify.get('/health', (request, reply) => { Fastify server setup diff --git a/apps/docs/modules/collaboration/self-hosted/y-sweet.mdx b/apps/docs/modules/collaboration/self-hosted/y-sweet.mdx index 23c78cdc27..429f2a9e79 100644 --- a/apps/docs/modules/collaboration/self-hosted/y-sweet.mdx +++ b/apps/docs/modules/collaboration/self-hosted/y-sweet.mdx @@ -248,7 +248,7 @@ For production, consider: Complete source code diff --git a/apps/docs/openapi.json b/apps/docs/openapi.json index 2ddf92d9dd..d6b1e41a79 100644 --- a/apps/docs/openapi.json +++ b/apps/docs/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "SuperDoc API", "version": "0.9.0", - "description": "## Quick Start\n\n1 - **Register**: https://api.superdoc.dev/v1/auth/register?email=you@email.com\n\n2 - **Verify**: Check email, then https://api.superdoc.dev/v1/auth/verify?email=you@email.com&code=123456\n\n3 - **Convert**\n```bash\ncurl -X POST https://api.superdoc.dev/v1/convert?from=docx \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -F \"file=@document.docx\" \\\n -o converted.pdf\n```\n\n\nOr use our Playground:\nhttps://api.superdoc.dev/docs/#tag/documents/post/v1/convert\n\nThat's it! Your DOCX is now a PDF.\n\n---\n\n[Status](https://status.superdoc.dev) • [GitHub](https://github.com/Harbour-Enterprises/SuperDoc)", + "description": "## Quick Start\n\n1 - **Register**: https://api.superdoc.dev/v1/auth/register?email=you@email.com\n\n2 - **Verify**: Check email, then https://api.superdoc.dev/v1/auth/verify?email=you@email.com&code=123456\n\n3 - **Convert**\n```bash\ncurl -X POST https://api.superdoc.dev/v1/convert?from=docx \\\n -H \"Authorization: Bearer YOUR_API_KEY\" \\\n -F \"file=@document.docx\" \\\n -o converted.pdf\n```\n\n\nOr use our Playground:\nhttps://api.superdoc.dev/docs/#tag/documents/post/v1/convert\n\nThat's it! Your DOCX is now a PDF.\n\n---\n\n[Status](https://status.superdoc.dev) • [GitHub](https://github.com/superdoc-dev/superdoc)", "contact": { "name": "Support", "email": "api@superdoc.dev", diff --git a/apps/docs/resources/license.mdx b/apps/docs/resources/license.mdx index a0f106c650..c0553aae7a 100644 --- a/apps/docs/resources/license.mdx +++ b/apps/docs/resources/license.mdx @@ -9,9 +9,9 @@ For questions about licensing, please contact [q@superdoc.dev](mailto:q@superdoc We welcome contributions from the community! Here's how you can help: -1. Check our [issue tracker](https://github.com/Harbour-Enterprises/SuperDoc/issues) for open issues +1. Check our [issue tracker](https://github.com/superdoc-dev/superdoc/issues) for open issues 2. Fork the repository and create a feature/bugfix branch 3. Write clear, documented code following our style guidelines 4. Submit a PR with detailed description of your changes -See our [Contributing Guide](https://github.com/Harbour-Enterprises/SuperDoc/blob/main/CONTRIBUTING.md) for more details. +See our [Contributing Guide](https://github.com/superdoc-dev/superdoc/blob/main/CONTRIBUTING.md) for more details. diff --git a/apps/docs/scripts/sync-api-docs.js b/apps/docs/scripts/sync-api-docs.js index 9fa68ee051..748f1914d2 100755 --- a/apps/docs/scripts/sync-api-docs.js +++ b/apps/docs/scripts/sync-api-docs.js @@ -6,7 +6,7 @@ const https = require('https'); function fetchOpenAPI() { return new Promise((resolve, reject) => { https - .get('https://raw.githubusercontent.com/Harbour-Enterprises/SuperDoc-API/main/openapi.yaml', (res) => { + .get('https://raw.githubusercontent.com/superdoc-dev/superdoc-api/main/openapi.yaml', (res) => { let data = ''; res.on('data', (chunk) => (data += chunk)); res.on('end', () => resolve(data)); diff --git a/apps/docs/snippets/components/source-code-link.jsx b/apps/docs/snippets/components/source-code-link.jsx index 51b3da5130..cead8356cb 100644 --- a/apps/docs/snippets/components/source-code-link.jsx +++ b/apps/docs/snippets/components/source-code-link.jsx @@ -1,7 +1,7 @@ export const SourceCodeLink = ({ extension, path }) => { // Default to standard extension path if no custom path provided const githubPath = path || `packages/super-editor/src/extensions/${extension.toLowerCase()}`; - const githubUrl = `https://github.com/Harbour-Enterprises/SuperDoc/tree/main/${githubPath}`; + const githubUrl = `https://github.com/superdoc-dev/superdoc/tree/main/${githubPath}`; return (