diff --git a/.github/RELEASE-NOTE-TEMPLATE.md b/.github/RELEASE-NOTE-TEMPLATE.md new file mode 100644 index 0000000..307945b --- /dev/null +++ b/.github/RELEASE-NOTE-TEMPLATE.md @@ -0,0 +1,30 @@ +# What's new in Faz X.X.X + +## YYYY-MM-DD + +We are pleased to announce the release of Faz X.X.X. + + + + +Here are the highlights: + +## Features + +* Describe new features here. [#issue-number](https://github.com/candango/faz/issues/issue-number) + +## Build + +* Describe build changes or improvements here. [#issue-number](https://github.com/candango/faz/issues/issue-number) + +## Refactory + +* Describe refactoring efforts or code structure improvements here. [#issue-number](https://github.com/candango/faz/issues/issue-number) + +## Bug Fixes + +* List bug fixes here, if any. [#issue-number](https://github.com/candango/faz/issues/issue-number) + +## Other Notes + +* Add any additional notes or acknowledgments here. diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 12b7c41..c7972e1 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -2,27 +2,31 @@ name: Run faz tests on: [push, pull_request] +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest strategy: matrix: - node-version: ["18", "20", "21"] + node-version: ["22", "24", "26"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Set up Node ${{ matrix.node-version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} + - name: Set up pnpm + uses: pnpm/action-setup@v6 - name: Install dependencies - # Solution from: https://stackoverflow.com/a/67740771/2887989 run: | - export YARN_ENABLE_IMMUTABLE_INSTALLS=false - npm install -g yarn - npm run yarn - yarn install - - name: Run jest unit tests + pnpm install --frozen-lockfile + - name: Run build + run: | + pnpm run build + - name: Run vitest unit tests run: | - npm test + pnpm test diff --git a/.gitignore b/.gitignore index 5b2910b..9165514 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ yarn-error.log # Less stylesheets/*.css stylesheets/*.css.map + +# Project +.gemini/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..40bbe5c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,81 @@ +# AGENTS.md + +## Project Identity + +Candango Faz is a Web Components toolkit for incremental modernization of legacy applications. + +This repository is not primarily an application. It is a substrate for building reusable custom elements that can be embedded into existing systems, including legacy PHP applications, server-rendered pages, and mixed frontend stacks. + +The strategic goal is to let teams replace tangled combinations of business logic, control flow, markup, Bootstrap classes, and imperative JavaScript with focused HTML tags that encapsulate UI behavior and presentation. + +## Core Mission + +Faz exists to support gradual migration, not big-bang rewrites. + +A typical target environment may contain legacy PHP templates with conditionals, echoes, inline markup, duplicated Bootstrap snippets, and procedural JavaScript. Faz should make it possible to replace those fragments incrementally with reusable custom elements, one screen or one UI island at a time. + +The intended migration pattern is: + +1. Identify a painful legacy UI fragment. +2. Extract the behavior and presentation into a Faz component. +3. Replace the legacy fragment with a single custom element tag. +4. Keep the surrounding legacy system running. +5. Repeat until the system becomes easier to maintain. + +This avoids the common failure mode where a team disappears for months attempting a full rewrite and returns with an incomplete proof of concept while the legacy system remains unchanged. + +## Architectural Implications + +Agents working in this repository must preserve the following priorities: + +- **HTML-first integration:** Components must be easy to consume from plain HTML and server-rendered templates. +- **Attribute-driven APIs:** Public component APIs should work naturally through HTML attributes and properties. +- **Legacy compatibility:** Do not assume a clean SPA environment. Components may be mounted inside old pages with existing CSS and JavaScript. +- **Incremental adoption:** Changes should support partial replacement of legacy UI, not require full application rewrites. +- **Reusable UI islands:** Components should encapsulate behavior, state, and presentation cleanly enough to be reused across legacy screens. +- **Bootstrap-aware presentation:** Faz builds on Bootstrap conventions and should cooperate with Bootstrap-based layouts. +- **Small blast radius:** Prefer changes that can be adopted component-by-component without forcing consumers to reorganize their whole frontend. + +## Development Guidance + +When designing or changing APIs, ask: + +- Can this be used from a legacy PHP template with a simple tag? +- Does the component expose enough behavior through attributes/properties? +- Does this require consumers to adopt a full frontend runtime architecture? +- Can this replace a small legacy fragment without rewriting the whole page? +- Will this behave predictably when embedded into an existing Bootstrap page? + +Avoid designs that only make sense in a modern greenfield SPA. + +## Security and Build Hardening TODOs + +The current build and CI setup needs supply-chain hardening before release automation becomes trusted. + +TODO: + +- Replace the mutable Yarn CI install flow with a reproducible package-manager workflow. + - Current GitHub Actions disables immutable installs and runs `npm run yarn`, which deletes and regenerates `yarn.lock`, `.yarnrc.yml`, and `node_modules`. + - Prefer a committed lockfile and an immutable install command. + - The project may migrate from Yarn to pnpm, but the migration must preserve reproducibility. +- Add explicit least-privilege permissions to GitHub Actions. + - The test workflow should start with `permissions: contents: read` unless a job needs more. +- Decide whether to pin GitHub Actions by SHA. + - Current workflow uses tag references such as `actions/checkout@v4` and `actions/setup-node@v4`. + - Pinning by SHA reduces tag-compromise risk. +- Retire or modernize Travis CI. + - `.travis.yml` still targets Node.js 12 and caches `node_modules`. + - If Travis is no longer used, remove it to avoid stale CI behavior. +- Decide release sourcemap policy. + - `build.mjs` currently emits sourcemaps into `dist/js`. + - Keep them intentionally for open-source/debuggability or disable them for release builds. +- Review bundled legal comment handling. + - `build.mjs` uses `legalComments: "none"`. + - Consider `legalComments: "eof"` or another policy that preserves required dependency notices. +- Audit legacy `eval()` usage before exposing related code paths. + - `input/filterbox.js` contains callback evaluation via `eval(...)`. + - If that code is still reachable, replace it with an explicit callback registry or allowlist. + +## Working Definition + +Candango Faz is a toolkit for replacing legacy UI fragments with reusable Web Components, enabling progressive modernization without stopping the business for a rewrite. diff --git a/LICENSE b/LICENSE index d096af3..1257355 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,21 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018-2023 Flavio Garcia. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +MIT License + +Copyright (c) 2026 Flavio Garcia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE-apache-old b/LICENSE-apache-old new file mode 100644 index 0000000..39e3663 --- /dev/null +++ b/LICENSE-apache-old @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2025 Flavio Garcia. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index d1175fb..dead1c8 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,110 @@ # Candango Faz -**master:** [![Build Status](https://travis-ci.org/candango/faz.svg?branch=master)](https://travis-ci.org/candango/faz) +Candango Faz is a Web Components toolkit for incremental modernization of legacy applications. -**develop:** [![Build Status develop](https://travis-ci.org/candango/faz.svg?branch=develop)](https://travis-ci.org/candango/faz) +It provides a small substrate for replacing tangled server-rendered UI fragments with reusable custom elements. A common target is an existing PHP or server-rendered application where markup, conditionals, Bootstrap classes, and imperative JavaScript are mixed together. Faz lets teams replace those fragments gradually with focused HTML tags instead of stopping the business for a full rewrite. -## Introduction +## Purpose -Candango faz is a toolkit based on bootstrap and solid-js. +Faz is designed for progressive migration: -# Installation +1. Find a painful legacy UI fragment. +2. Extract its behavior and presentation into a Faz component. +3. Replace the legacy fragment with a custom element tag. +4. Keep the surrounding application running. +5. Repeat safely, one UI island at a time. -## npm +The project is intentionally HTML-first. Components should be easy to consume from plain HTML, server-rendered templates, and older Bootstrap-based pages. +## Installation + +```bash +npm i faz ``` -> npm i faz + +```bash +pnpm add faz ``` -## yarn +## Package entrypoints + +The package exposes built ESM and declaration artifacts through the package export map: +```ts +import { + FazElement, + FazFormElement, + FazPaginator, + bindReactive, + randomId, + toBoolean, +} from "faz"; ``` -> yarn add faz + +Additional public entrypoints: + +```ts +import { bindReactive } from "faz/reactivity"; +import { FazPaginator } from "faz/paginator"; ``` -# Development +The `faz/src` entrypoint is still published for compatibility with existing Faz-based packages, but consumers should prefer the built package entrypoints whenever possible. + +## Development -## At the command line +This project uses pnpm. +Install dependencies: + +```bash +pnpm install ``` -> yarn -> npm run lessc:dev -> npm run run + +Run the full build: + +```bash +pnpm run build ``` -## Running tests +Run tests: +```bash +pnpm test ``` -> yarn + +Run development stylesheet compilation: + +```bash +pnpm run lessc:dev ``` - - Add new Node.Js at the Run/Debug configurations. - - Java Script file: node_modules/http-server/bin/http-server - - Working directory: the faz project root directory +Run the showcase watcher: + +```bash +pnpm run showcase +``` + +## Build and distribution + +The build generates: + +- `dist/js/*` bundled ESM artifacts; +- `dist/types/*` TypeScript declarations; +- `dist/css/*` compiled stylesheets. + +The package entrypoint is `dist/js/index.js`, and the public type entrypoint is `dist/types/index.d.ts`. + +Before publishing or testing downstream consumers, run: + +```bash +pnpm install --frozen-lockfile +pnpm run build +pnpm test +pnpm pack +``` + +## License + +Candango Faz was licensed under Apache-2.0 from 2018 to 2025. + +Since 2026 it is licensed under the MIT License. diff --git a/app/breadcrumb.js b/app/breadcrumb.js index a11e006..d6e0062 100644 --- a/app/breadcrumb.js +++ b/app/breadcrumb.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2020 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazNavbar, FazBreadcrumb } from "../faz"; diff --git a/app/code-highlight.js b/app/code-highlight.js index 61bf1db..d9139ea 100644 --- a/app/code-highlight.js +++ b/app/code-highlight.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2020 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import hljs from "highlight.js/lib/highlight"; import "highlightjs-line-numbers.js"; diff --git a/app/datepicker.js b/app/datepicker.js index 625174f..4dbf2f2 100644 --- a/app/datepicker.js +++ b/app/datepicker.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2020 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazInputDatepicker, FazDatepicker, FazNavbar } from "../faz"; diff --git a/app/filterbox.js b/app/filterbox.js index 50c64c6..8247bad 100644 --- a/app/filterbox.js +++ b/app/filterbox.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2022 Flávio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazFilterbox, FazNavbar } from "../faz"; diff --git a/app/form.js b/app/form.js index 59d959e..1a0fda6 100644 --- a/app/form.js +++ b/app/form.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2022 Flavio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { fixture } from "can" import {default as MainNavbar} from "./main-navbar" diff --git a/app/global.js b/app/global.js index 7b34458..78b7960 100644 --- a/app/global.js +++ b/app/global.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2022 Flavio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ window.codemirrorit = function(id) { let referenceNode = document.getElementById(id) diff --git a/app/input.js b/app/input.js index 90913c5..53bd8ab 100644 --- a/app/input.js +++ b/app/input.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazNavbar } from "../faz"; diff --git a/app/main-navbar.js b/app/main-navbar.js index fae4858..30845ba 100644 --- a/app/main-navbar.js +++ b/app/main-navbar.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { ObservableObject } from "can"; import {FazStacheItem} from "../item"; diff --git a/app/nav.js b/app/nav.js index dd532cc..5cf46d9 100644 --- a/app/nav.js +++ b/app/nav.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2022 Flávio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazAlert, FazNavElement, FazNavbar } from "../faz"; diff --git a/app/navbar.js b/app/navbar.js index 7f28679..45942bb 100644 --- a/app/navbar.js +++ b/app/navbar.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2020 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazNavbar } from "../faz"; diff --git a/app/pagination.js b/app/pagination.js index cb28116..6de8806 100644 --- a/app/pagination.js +++ b/app/pagination.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2022 Flavio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazNavbar, FazPaginationElement } from "../faz"; diff --git a/app/picklist.js b/app/picklist.js index 3e658b6..3aba25b 100644 --- a/app/picklist.js +++ b/app/picklist.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazPicklist, FazNavbar } from "../faz"; diff --git a/app/sidebar.js b/app/sidebar.js index f2a5007..978630b 100644 --- a/app/sidebar.js +++ b/app/sidebar.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2022 Flavio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazSidebarElement, FazNavbar } from "../faz"; diff --git a/assets.mjs b/assets.mjs new file mode 100644 index 0000000..58c5ef8 --- /dev/null +++ b/assets.mjs @@ -0,0 +1,5 @@ + +export const assets = { + assets:[ + ] +} diff --git a/breadcrumb/breadcrumb-item.js b/breadcrumb/breadcrumb-item.js deleted file mode 100644 index c5ffb41..0000000 --- a/breadcrumb/breadcrumb-item.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright 2018-2020 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ObservableArray, type } from "can"; -import { default as FazItem } from "../item"; -import itemTemplate from "./stache/breadcrumb-item.stache"; - -export class FazBreadcrumbItem extends FazItem { - - static get props() { - return $.extend(super.props, { - disabled: {type: type.convert(Boolean), default: false}, - target: {type: type.convert(String), default: ""}, - }); - } - - get classes() { - let classes = ["breadcrumb-item"]; - if(this.active) { - classes.push("active"); - } - return classes.join(" "); - } - - get html() { - return itemTemplate(this); - } - - setParent(parent) { - this.parent = parent; - } - - processElement(parent, element) { - this.setParent(parent); - for(let attribute of element.attributes) { - switch (attribute.name.toLowerCase()) { - case "id": - this.id = attribute.value; - break; - case "href": - this.href = attribute.value; - break; - } - } - this.content = element.innerHTML; - } - - process(parent, element, activeItem) { - - } -} - -export class FazBreadcrumbItemList extends ObservableArray { - static get props() { - return { - get enabled() { - return this.filter({disabled: false}); - }, - get last() { - return this[this.length-1]; - }, - get active() { - return this.filter({active: true}); - } - }; - } - - constructor(items) { - super(items); - this.on( "add", function ( ev, items, index ) { - console.log( "add", items, index ); - }); - } - - clearAll() { - while(this.length>0) { - this.pop(); - } - } - - static items = type.convert(FazBreadcrumbItem); -} diff --git a/breadcrumb/breadcrumb.js b/breadcrumb/breadcrumb.js deleted file mode 100644 index f65f73d..0000000 --- a/breadcrumb/breadcrumb.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright 2018-2022 Flávio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {StacheElement, type} from "can"; -import { FazBreadcrumbItem, FazBreadcrumbItemList } from "./breadcrumb-item"; -import breadcrumbTemplate from "./stache/breadcrumb.stache"; - -export default class FazBreadcrumb extends StacheElement { - static view = breadcrumbTemplate; - - static get props() { - return { - isLoading: {type: Boolean, default: true}, - content: {type: type.convert(String)}, - source: {type: type.convert(String)}, - items: {type: FazBreadcrumbItemList, get default() { - return new FazBreadcrumbItemList([]); - }}, - set jsonString(value) { - try { - let data = JSON.parse(value); - this.items.clearAll(); - data.items.forEach(function(item){ - this.items.push(item); - }.bind(this)); - } catch (e) { - console.error(e); - } - } - }; - } - - connectedCallback() { - this.content = this.innerHTML; - for(let attribute of this.attributes) { - switch (attribute.name.toLowerCase()) { - case "json-string": - this.jsonString = attribute.value; - break; - case "source": - this.source = attribute.value; - break; - } - } - this.querySelectorAll("faz-breadcrumb > faz-breadcrumb-item").forEach( - function(item) { - let breadcrumbItem = new FazBreadcrumbItem(); - breadcrumbItem.processElement(this, item); - this.items.push(breadcrumbItem); - }.bind(this) - ); - super.connectedCallback(); - - if (this.items.last!==undefined) { - this.items.last.active = true; - } - - } - - static get seal() { - return true; - } -} - -customElements.define("faz-breadcrumb", FazBreadcrumb); diff --git a/breadcrumb/fixtures/breadcrumb.json b/breadcrumb/fixtures/breadcrumb.json deleted file mode 100644 index e7c16ce..0000000 --- a/breadcrumb/fixtures/breadcrumb.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "items": [ - { - "content": "Root From Source" - }, - { - "content": "First Level From Source", - "href": "#firstLevelFromSrouce" - }, - { - "content": "Edge From Source", - "href": "#edgeFromSrouce" - } - ] -} diff --git a/breadcrumb/index.html b/breadcrumb/index.html deleted file mode 100644 index 528f801..0000000 --- a/breadcrumb/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - Candango Faz Toolkit - Breadcrumbs - - - - - - - - - - - -
- -

Breadcrumbs

- -
- -
-
- - - - - - - - - - - - diff --git a/breadcrumb/stache/breadcrumb-item.stache b/breadcrumb/stache/breadcrumb-item.stache deleted file mode 100644 index 4461a7d..0000000 --- a/breadcrumb/stache/breadcrumb-item.stache +++ /dev/null @@ -1,7 +0,0 @@ -
  • - {{# if(isLink) }} - {{{ content }}} - {{ else }} - {{{ content }}} - {{/ if }} -
  • diff --git a/breadcrumb/stache/breadcrumb.stache b/breadcrumb/stache/breadcrumb.stache deleted file mode 100644 index 6ba5703..0000000 --- a/breadcrumb/stache/breadcrumb.stache +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/build.mjs b/build.mjs index 3563740..d1d936f 100644 --- a/build.mjs +++ b/build.mjs @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2023 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import * as esbuild from "esbuild"; import {entryPoints} from "./entryPoints.mjs"; @@ -31,7 +16,7 @@ await esbuild.build({ format: "esm", define: { gobal: "window" }, target: ["esnext"], - outdir: "dist/esm", + outdir: "dist/js", logLevel: "info", legalComments: "none", // outExtension: { '.js': '.cjs' }, diff --git a/date.js b/date.js index 94246ae..133234f 100644 --- a/date.js +++ b/date.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2019 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ export default class DateUtil { @@ -28,7 +13,7 @@ export default class DateUtil { let days = []; Array.from( {length: new Date(year, month + 1, 0).getDate()}, - (x, day)=> days.push( + (_, day)=> days.push( new Date(year, month, day + 1) ) ); @@ -41,7 +26,7 @@ export default class DateUtil { let dayMatrix = new Array(weeks); Array.from( {length: weeks}, - (x, i)=> dayMatrix[i] = new Array(7) + (_, i)=> dayMatrix[i] = new Array(7) ); let week = 0; DateUtil.daysOfMonthArray(year, month).forEach(day=>{ diff --git a/datepicker/datepicker.js b/datepicker/datepicker.js index 3cf335a..715fcce 100644 --- a/datepicker/datepicker.js +++ b/datepicker/datepicker.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2020 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { domEvents } from "can"; diff --git a/entryPoints.mjs b/entryPoints.mjs index 486ea3f..704736f 100644 --- a/entryPoints.mjs +++ b/entryPoints.mjs @@ -1,22 +1,8 @@ -/** - * Copyright 2018-2023 Flávio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ export const entryPoints = [ { out: "form", in: "src/form.tsx" }, - { out: "id", in: "src/id.ts" }, { out: "index", in: "src/index.ts" }, - { out: "item", in: "src/item.ts" }, + { out: "element", in: "src/element.ts" }, + { out: "test", in: "src/test.ts" }, + { out: "values", in: "src/values.ts" }, ]; diff --git a/form/form.js b/form/form.js deleted file mode 100644 index 1c6b970..0000000 --- a/form/form.js +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Copyright 2018-2022 Flavio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {FazElementItem, FazReactItem} from "../item" -import React from "react" - - -export class FazFormReact extends FazReactItem { - - defineStates(props) { - this.values = {} - this.state['action'] = undefined - this.state['method'] = "get" - this.state['type'] = "primary" - this.state['message'] = undefined - this.state['errors'] = [] - this.state['valueUpdated'] = 0 - if (props.action) { - this.state['action'] = props.action - } - if (props.method) { - this.state['method'] = props.method.toLowerCase() - } - if (props.message) { - this.state['message'] = props.message - } - if (props.errors) { - this.state['errors'] = props.errors - } - this.from = this.from.bind(this) - this.to = this.to.bind(this) - } - - hasValue(index) { - return this.values[index] !== undefined - } - - valueIsEmpty(index) { - if (this.hasValue(index)) { - return this.values[index] === "" - } - return false - } - - /** - * - * @param {String} index - * @param defaultValue - */ - from(index, defaultValue="") { - if(!this.hasValue(index)) { - this.values[index] = defaultValue - } - return this.values[index] - } - - /** - * - * @param {Event} event - * @param {string} index - */ - to(event, index) { - this.values[index] = event.target.value - this.incrementState(index) - } - - get prefix() { - return "faz-form-react" - } - - get hasMessage() { - return this.state.message !== ""; - } - - get hasErrors() { - return this.state.errors.length > 0; - } - -} - -export default class FazFormElement extends FazElementItem { - - constructor(props) { - super(props) - } - - attributesToStates() { - super.attributesToStates() - for (let attribute of this.attributes) { - switch (attribute.name.toLowerCase()) { - case "action": - this.reactItem.state['action'] = attribute.value - break - case "method": - this.reactItem.state['method'] = attribute.value - break - case "active": - this.reactItem.state['active'] = attribute.value - break - } - } - } -} diff --git a/input/datepicker.js b/input/datepicker.js index f2c68a1..961d8c5 100644 --- a/input/datepicker.js +++ b/input/datepicker.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2020 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import FazDatepicker from "../datepicker/datepicker"; import { domEvents } from "can"; diff --git a/input/filterbox.js b/input/filterbox.js index 3000678..58a4f86 100644 --- a/input/filterbox.js +++ b/input/filterbox.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2022 Flávio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import {FazElementItem, FazReactItem} from "../item" import {isString} from "lodash" diff --git a/input/picklist.js b/input/picklist.js index cea9553..3551076 100644 --- a/input/picklist.js +++ b/input/picklist.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import {ObservableArray, type} from "can"; import { FazStacheItem } from "../item"; diff --git a/jest.config.ts b/jest.config.ts deleted file mode 100644 index dcf4919..0000000 --- a/jest.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Config } from "@jest/types"; - -// Solutions for jest: -// jsdom: https://stackoverflow.com/a/69228464/2887989 -// watch: https://stackoverflow.com/a/39091907/2887989 -// this file: https://stackoverflow.com/a/76995084/2887989 -const config: Config.InitialOptions = { - verbose: true, - testEnvironment: "jsdom", - transform: { - "^.+\\.ts?$": ["ts-jest", {tsconfig: "./tsconfig.json"}], - }, - preset: "ts-jest", - moduleNameMapper: { - "React": "/node_modules/solid-js/h/jsx-runtime/dist/jsx.cjs", - "solid-js/web": "/node_modules/solid-js/web/dist/web.cjs", - "solid-js": "/node_modules/solid-js/dist/solid.cjs" - } -}; - -export default config; diff --git a/karma.conf.js b/karma.conf.js deleted file mode 100644 index cc1af1e..0000000 --- a/karma.conf.js +++ /dev/null @@ -1,149 +0,0 @@ -const path = require("path"); -const webpack = require("webpack"); - -// This is related to the new jsx transform -// SEE: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html -// Yanked from the create react app. O.o -const hasJsxRuntime = (() => { - if (process.env.DISABLE_NEW_JSX_TRANSFORM === "true") { - return false; - } - try { - require.resolve("react/jsx-runtime"); - return true; - } catch (e) { - return false; - } -})(); - -const defaultWebpackOptions = { - mode: 'development', - output: { - filename: '[name]-test.js', - path: path.resolve(__dirname, "test/dist") - }, - stats: { - modules: false, - colors: true, - }, - watch: false, - module: { - rules: [ - { - test: /\.stache$/, - use: { - loader: "can-stache-loader" - } - }, - { - test: /\.js|\.jsx$/, - exclude: /node_modules/, - use: { - loader: 'babel-loader', - options: { - presets: [ - [ - require.resolve("@babel/preset-env") - ], - [ - require.resolve("@babel/preset-react"), - { - runtime: hasJsxRuntime ? "automatic" : - "classic", - } - ], - ], - // SEE: https://newbedev.com/babel-7-referenceerror-regeneratorruntime-is-not-defined - plugins: [ - require.resolve("@babel/plugin-transform-runtime") - ], - } - } - } - ] - }, - // optimization: { - // runtimeChunk: 'single', - // splitChunks: { - // chunks: 'all', - // minSize: 0, - // cacheGroups: { - // commons: { - // name: 'commons', - // chunks: 'initial', - // minChunks: 1, - // }, - // }, - // }, - // }, - plugins: [ - new webpack.SourceMapDevToolPlugin({ - append: '\n//# sourceMappingURL=[url]', - filename: '[name].bundle.map', - }) - ], -}; - -module.exports = (config) => { - config.set({ - // ... normal karma configuration - browsers: ['Electron'], - client: { - captureConsole: true, - useIframe: false, - clearContext: false, - qunit: { - showUI: true, - testTimeout: 500 - } - - }, - // make sure to include webpack as a framework - frameworks: ['webpack', "qunit"], - reporters: ['dots'], - //browserNoActivityTimeout: 15000, - customLaunchers: { - CustomElectron: { - base: 'Electron', - browserWindowOptions: { - show: true, - // DEV: More preferentially, should link your own `webPreferences` from your Electron app instead - webPreferences: { - // Preferred `preload` mechanism to expose `require` - - - // Alternative non-preload mechanism to expose `require` - // nodeIntegration: true, - // contextIsolation: false - - - - // nativeWindowOpen is set to `true` by default by `karma-electron` as well, see #50 - nativeWindowOpen: false - } - } - } - }, - plugins: [ - 'karma-qunit', - 'karma-electron', - 'karma-webpack' - - ], - - files: [ - "./node_modules/jquery/dist/jquery.min.js", - // all files ending in ".test.js" - // !!! use watched: false as we use webpacks watch - { pattern: './test/**/*-test.js', watched: false }, - { pattern: "./test/dist/*-test.*.js", watched: false } - ], - - preprocessors: { - // add webpack as preprocessor - './test/**/*-test.js': ["webpack"] - }, - - webpack: defaultWebpackOptions, - }); -} diff --git a/nav/index.html b/nav/index.html deleted file mode 100644 index c865261..0000000 --- a/nav/index.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - - - - Candango Faz Toolkit - - - - - - - - - - - - -
    - -

    Navs

    - -
    -
    -
    Basic example
    - - -
    -
    -

    -

    Horizontal alignment

    -
    -
    -
    Centered
    - - -
    -
    -

    -
    -
    -
    Right Aligned and pills
    - -
    -
    -

    -
    -
    -
    Fill and pills
    - -
    -
    -

    -

    Vertical alignment

    -
    -
    -
    Just vertical
    - - -
    -
    -

    -
    -
    -
    Vertical and pills
    - - -
    -
    -

    -

    From a json data source

    -
    -
    -
    Basic example.
    - -
    -
    -

    -
    -
    -
    With children.
    - -
    -
    -

    -

    With children, justified to the right

    -
    -
    -
    With children.
    - -
    -
    -

    -

    With tabs

    - -

    -
    -
    -
    Horizontal.
    - -
    -
    -
    -
    -
    -
    -
    Vertical.
    - -
    -
    -
    -
    -
    - - - - - - - - - - - - diff --git a/nav/nav-data-example1.json b/nav/nav-data-example1.json deleted file mode 100644 index cad6f03..0000000 --- a/nav/nav-data-example1.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "items": [ - { - "active": true, - "type": "faz-nav-item", - "id": "activeData", - "value": "Active Data" - }, - { - "type": "faz-nav-item", - "id": "item1Data1", - "value": "Item 1 Data" - }, - { - "type": "faz-nav-item", - "id": "item2Data", - "value": "Item 2 Data" - }, - { - "type": "faz-nav-item", - "id": "disabledData", - "value": "Disabled Data", - "disabled": true - } - ] -} diff --git a/nav/nav-data-example2.json b/nav/nav-data-example2.json deleted file mode 100644 index c54290e..0000000 --- a/nav/nav-data-example2.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "items": [ - { - "type": "faz-nav-item", - "id": "activeData1", - "value": "Active Data 1" - }, - { - "type": "faz-nav-item", - "id": "item1Data1", - "value": "Item 1 Data 1", - "items": [ - { - "type": "faz-nav-item", - "id": "item1Data1Child1", - "value": "Item1 Data1 Child 1" - }, - { - "type": "faz-nav-item", - "id": "item1Data1Child2", - "value": "Item1 Data1 Child 2", - "items": [ - { - "type": "faz-nav-item", - "id": "item1Data1Child2Grandchild1", - "value": "Item1 Data1 Child 2 Grandchild 1" - }, - { - "type": "faz-nav-item", - "id": "item1Data1Child2Grandchild2", - "value": "Item1 Data1 Child 2 Grandchild 2" - } - ] - } - ] - }, - { - "type": "faz-nav-item", - "id": "item2Data", - "active": true, - "value": "Item 2 Data 1" - }, - { - "type": "faz-nav-item", - "id": "disabledData", - "value": "Disabled Data 1", - "disabled": "true" - } - ] -} diff --git a/nav/nav-item.js b/nav/nav-item.js deleted file mode 100644 index 4a7d963..0000000 --- a/nav/nav-item.js +++ /dev/null @@ -1,246 +0,0 @@ -/** - * Copyright 2018-2023 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {FazReactItem} from "../item"; -import React from 'react' -import FazNavElement from "./nav"; - - -export default class FazNavItemReact extends FazReactItem { - - processProps(props) { - super.processProps(props) - this.previousItem = undefined - for(let key in props) { - switch (key) { - case "children": - this.state['items'] = props[key] - break - case "parent": - this.parent = props[key] - let filterMe = this.parent.renderedItems.filter( - item => item.hash === this.hash) - if (!filterMe.length) { - this.parent.renderedItems.push(this) - } - break - case "root": - this.root = props[key] - break - } - } - this.handleClick = this.handleClick.bind(this) - } - - get isDropdown() { - return this.state.items.length > 0 - } - - get isRoot() { - return this.parent === this.root - } - - defineStates(props) { - super.defineStates(props) - if (this.element) { - let elementProps = [] - for (let attribute of this.element.attributes) { - if (attribute.name.toLowerCase() !== "id") { - elementProps[attribute.name.toLowerCase()] = - attribute.value.toLowerCase() - } - } - } - } - - get hasTabs() { - return !!this.state.tabs.length; - } - - get orientation() { - return this.state.vertical ? "vertical" : undefined - } - - get prefix() { - return "faz-nav-react" - } - - get classNames() { - let classes = [] - if(this.isRoot) { - classes.push("nav-item") - if (this.isDropdown) { - classes.push("dropdown") - } - } else { - if (this.isDropdown) { - classes.push("dropdown-submenu") - } - } - return classes.join(" ") - } - - get linkClassNames() { - let classes = ["nav-link"] - - if (!this.isRoot) { - classes.pop() - classes.push("dropdown-item") - } - - if (this.state.active && !this.state.disabled) { - this.root.current = this - classes.push("active") - } - if (this.state.disabled) { - classes.push("disabled") - } - if (this.isDropdown) { - classes.push("dropdown-toggle") - } - return classes.join(" ") - } - - get dropdownClassNames() { - let classes = ["dropdown-menu"] - if (this.state.active && !this.state.disabled) { - classes.push("show") - } - return classes.join(" ") - } - - get containerId() { - return "faz-nav-item-container-".concat(this.state.id) - } - - get link() { - if (!this.isDropdown) { - if (this.isRoot && this.root.hasTabs) { - return `#${super.link}` - } - return super.link; - } - } - - renderItems() { - return
      - {this.state.items.map((item) => { - let content = item.content ? item.content : item.value - return - })} -
    - } - - get role() { - if (this.isDropdown && this.isRoot) { - return "button" - } - if (!this.isDropdown && !this.isRoot) { - return "tab" - } - } - - get dataBsToggle() { - if (this.isDropdown && this.isRoot) { - return "dropdown" - } - } - - get ariaExpanded() { - if (this.isDropdown) { - return this.state.active - } - } - - get content() { - if (this.isDropdown && this.isRoot) { - return this.state.content - } - return super.content - } - - render() { - return ( -
  • - {this.handleClick(event)}} - aria-expanded={this.ariaExpanded} - data-bs-toggle={this.dataBsToggle} - >{this.content} - {this.isDropdown ? this.renderItems() : ""} -
  • - ) - } - - handleClick(event) { - if (this.linkIsVoid && !this.isDropdown) { - event.preventDefault() - } - this.activate() - } - - get activeItems() { - return this.renderedItems.filter(item => { - return item.state.active - }) - } - - setDisabled(value) { - let items = this.parent.state.items - items.filter((item) => item.id === this.state.id).forEach((item)=> { - item.disabled = value - }) - this.parent.updateState({items: items}) - } - - activate() { - this.parent.activeItems.forEach((item) => { - if (item instanceof FazNavItemReact) { - this.previousItem = item - item.deactivate() - } - }) - if (this.root.hasTabs) { - this.root.renderedTabItems.forEach((item) => { - if(item.state.id === this.link.replace("#", "")){ - item.updateState({active: true}) - return - } - item.deactivate() - }) - } - this.updateState({active: true}) - } - - deactivate() { - this.previousItem = undefined - this.updateState({active: false}) - this.renderedItems.forEach((item)=> { - item.deactivate() - }) - } -} diff --git a/nav/nav-tab.js b/nav/nav-tab.js deleted file mode 100644 index 2fb5b28..0000000 --- a/nav/nav-tab.js +++ /dev/null @@ -1,172 +0,0 @@ -/** - * Copyright 2018-2022 Flávio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {FazReactItem} from "../item" -import React from "react" - - -export default class FazNavTabReact extends FazReactItem { - - processProps(props) { - super.processProps(props) - this.previousItem = undefined - for(let key in props) { - switch (key) { - case "fade": - this.state['fade'] = props[key] - break - case "parent": - this.parent = props[key] - let filterMe = this.parent.renderedItems.filter( - item => item.hash === this.hash) - if (!filterMe.length) { - this.parent.renderedItems.push(this) - } - break - } - } - this.handleClick = this.handleClick.bind(this) - } - - defineStates(props) { - super.defineStates(props) - if (this.element) { - let elementProps = [] - for (let attribute of this.element.attributes) { - if (attribute.name.toLowerCase() !== "id") { - elementProps[attribute.name.toLowerCase()] = - attribute.value.toLowerCase() - } - } - } - } - - get hasTabs() { - return !!this.state.tabs.length; - } - - get orientation() { - return this.state.vertical ? "vertical" : undefined - } - - get prefix() { - return "faz-nav-tab-content-react" - } - - get classNames() { - let classes = ["tab-pane"] - if (this.state.fade) { - classes.push("fade") - if (this.state.active) { - classes.push("show") - } - } - if (this.state.active) { - classes.push("anchor") - classes.push("active") - } - - return classes.join(" ") - } - - get dropdownClassNames() { - let classes = ["dropdown-menu"] - if (this.state.active && !this.state.disabled) { - classes.push("show") - } - return classes.join(" ") - } - - get containerId() { - return "faz-nav-item-container-".concat(this.state.id) - } - - get link() { - if(!this.isDropdown) { - return super.link - } - } - - get role() { - if (this.isDropdown && this.isRoot) { - return "button" - } - if (!this.isDropdown && !this.isRoot) { - return "tab" - } - } - - get dataBsToggle() { - if (this.isDropdown && this.isRoot) { - return "dropdown" - } - } - - get ariaLabelledby() { - let labelledby = "" - this.parent.navItems.forEach((item) => { - if (this.state.id === item.href) { - labelledby = item.id - return - } - }) - return labelledby - } - - render() { - return
    - {this.content} -
    ; - } - - handleClick(event) { - if (this.linkIsVoid && !this.isDropdown) { - event.preventDefault() - } - this.activate() - } - - get activeItems() { - return this.renderedItems.filter(item => { - return item.state.active - }) - } - - setDisabled(value) { - let items = this.parent.state.items - items.filter((item) => item.id === this.state.id).forEach((item)=> { - item.disabled = value - }) - this.parent.updateState({items: items}) - } - - activate() { - this.parent.activeItems.forEach((item)=> { - this.previousItem = item - item.deactivate() - }) - this.updateState({active: true}) - } - - deactivate() { - this.previousItem = undefined - this.updateState({active: false}) - this.renderedItems.forEach((item)=> { - item.deactivate() - }) - } -} diff --git a/nav/nav.js b/nav/nav.js deleted file mode 100644 index 8ef1b84..0000000 --- a/nav/nav.js +++ /dev/null @@ -1,419 +0,0 @@ -/** - * Copyright 2018-2023 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {FazElementItem, FazReactItem} from "../item" -import FazNavItemReact from "./nav-item" -import FazNavTabReact from "./nav-tab" -import React from "react" -import ReactDOM from "react-dom" -import includes from "lodash/includes" - - -class FazNavReact extends FazReactItem { - - defineStates(props) { - this.state['fill'] = false - this.state['justify'] = "left" - this.state['pills'] = false - this.state['source'] = undefined - this.state['vertical'] = false - this.state['loaded'] = false - this.timeout = 0 - this.current = undefined - - this.state['tabs'] = [] - for (let key in props) { - switch (key) { - case "children": - this.state['items'] = props[key] - break - case "fill": - this.state['fill'] = props[key].toLowerCase() === "true" - break - case "justify": - this.state['justify'] = props[key].toLowerCase() - break - case "pills": - this.state['pills'] = props[key].toLowerCase() === "true" - break - case "source": - this.state['source'] = props[key] - break - case "vertical": - this.state['vertical'] = props[key].toLowerCase() === "true" - break - } - } - this.beOverMe = this.beOverMe.bind(this) - this.leaveMe = this.leaveMe.bind(this) - } - - get onEdge() { - if(this.current) { - return !this.current.isDropdown - } - return false - } - - get renderedNavItems() { - return this.renderedItems.filter(item => { - return item instanceof FazNavItemReact - }) - } - - get renderedTabItems() { - return this.renderedItems.filter(item => { - return item instanceof FazNavTabReact - }) - } - - get activeNavItems() { - return this.renderedNavItems.filter(item => { - return item.state.active - }) - } - - get activeItems() { - return this.renderedItems.filter(item => { - return item.state.active - }) - } - - get hasTabs() { - return !!this.tabItems.length; - } - - get orientation() { - return this.state.vertical ? "vertical" : undefined - } - - get isVertical() { - return this.orientation === "vertical" - } - - get prefix() { - return "faz-nav-react" - } - - get classNames() { - let classes = ["nav"] - - if (this.state.pills && !this.hasTabs) { - classes.push("nav-pills") - } - - if (this.state.fill) { - classes.push("nav-fill") - } - - if (this.state.justify === "center") { - classes.push("justify-content-center") - } else if (this.state.justify === "right") { - classes.push("justify-content-end") - } - - if (this.hasTabs) { - classes.push("nav-tabs") - } - - if (this.state.vertical) { - classes.push("flex-column") - } - return classes.join(" ") - } - - get containerId() { - return "faz-nav-container-".concat(this.state.id) - } - - get navItems() { - let itemsToRender = [ - "faz-nav-item", - "faz-nav-item-el" - ] - return this.state.items.filter( - item => includes(itemsToRender, item['type'])) - } - - get tabItems() { - let itemsToRender = [ - "faz-nav-tab" - ] - return this.state.items.filter( - item => includes(itemsToRender, item['type'])) - } - - componentDidMount() { - super.componentDidMount() - // Activate first item if no nav items are selected and nav has tabs - if (this.hasTabs) { - if (!this.activeNavItems.length) { - this.renderedNavItems[0].activate() - } - } - } - - requestDataCallback(response) { - this.updateState({items:response.data.items}) - } - - afterMount() { - if(this.state.source) { - this.requestData().then( - this.updateState({loaded: true}) - ) - } - } - - renderItems() { - return this.navItems.map((item) => { - if (item.element) { - return item.element.toReact(item, this, this) - } - let content = item.content ? item.content : item.value - return - }) - } - - renderTabs() { - return this.tabItems.map((item) => { - if(item.element) { - return item.element.toReact(item, this, this) - } - let content = item.content ? item.content : item.value - return - }) - } - - beOverMe(event) { - clearTimeout(this.timeout) - } - - leaveMe(event) { - clearTimeout(this.timeout) - this.timeout = setTimeout(() => { - this.activeItems.forEach(item => { - if (item.isDropdown && !this.onEdge) { - if (item.previousItem) { - item.previousItem.updateState({active: true}) - } - item.deactivate() - } - }) - }, 250) - } - - render() { - if (this.hasTabs && this.isVertical) { - return ( -
    -
    - {this.renderNav()} -
    -
    -
    - {this.renderTabs()} -
    -
    -
    - ) - } - return ( -
    - {this.renderNav()} - {this.hasTabs ? -
    - {this.renderTabs()} -
    : ""} -
    - ) - } - - renderNav() { - return( -
      - {this.renderItems()} -
    - ) - } - -} - -Object.assign(FazNavReact, { - Item: FazNavItemReact, - Tab: FazNavTabReact -}) - - -export default class FazNavElement extends FazElementItem { - constructor() { - super() - } - - contentLoaded(event) { - super.contentLoaded(event) - let reactItem = - {this.items.map(item=>item.attributesToProps({}))} - - ReactDOM.render(reactItem, this) - this.classList.add("faz-nav-rendered") - } - - attributesToStates() { - super.attributesToStates() - for (let attribute of this.attributes) { - switch (attribute.name) { - case "fill": - this.reactItem.state['fill'] = - attribute.value.toLowerCase() === "true" - break - case "justify": - this.reactItem.state['justify'] = - attribute.value.toLowerCase() - break - case "pills": - this.reactItem.state['pills'] = - attribute.value.toLowerCase() === "true" - break - case "vertical": - this.reactItem.state['vertical'] = - attribute.value.toLowerCase() === "true" - break - } - } - } -} - - -export class FazNavItemElement extends FazElementItem { - constructor() { - super() - this.detach = true - } - - toReact(props, parent, root) { - props['parent'] = parent - if (root) { - props['root'] = root - } - return - {this.items.map(item=>item.attributesToProps({root: root, - parent: parent}))} - - } - - attributesToProps(addProps = []) { - let props = super.attributesToProps(addProps) - // Fixing with original nodes and not dropdowns - if (this.originalNodes.length && !this.items.length) { - if (this.parentElement.tagName.toLowerCase() === "faz-nav-el") { - props['content'] = undefined - } - } - let hasTitle = false - if (this.items.length) { - this.items.forEach(item => { - if (item.constructor.name === "FazNavItemTitleElement") { - props['content'] = item.innerHTML - } - }) - } - if (hasTitle) { - console.log(props) - } - return props; - } -} - -export class FazNavItemTitleElement extends FazElementItem { - constructor() { - super() - this.detach = true - } -} - - -export class FazNavTabElement extends FazElementItem { - constructor() { - super() - this.detach = true - this.fade = false - for(let attribute of this.attributes) { - switch (attribute.name) { - case "fade": - this.fade = attribute.value - break - } - } - } - - toReact(props, parent, root) { - props['parent'] = parent - if (root) { - props['root'] = root - } - return - - } -} - -customElements.define("faz-nav", FazNavElement) -customElements.define("faz-nav-item", FazNavItemElement) -customElements.define("faz-nav-item-content", FazNavItemTitleElement) -customElements.define("faz-nav-tab", FazNavTabElement) diff --git a/nav/stache/nav-item.stache b/nav/stache/nav-item.stache deleted file mode 100644 index 4ca7946..0000000 --- a/nav/stache/nav-item.stache +++ /dev/null @@ -1,36 +0,0 @@ -{{# isRoot }} - {{# ../dropdown }} - - - {{else}} - - - - {{/ ../dropdown }} -{{else}} - {{# dropdown }} - - - {{else}} -
  • - - {{ content }} -
  • - {{/ dropdown }} -{{/ isRoot }} diff --git a/nav/stache/nav-tab-content.stache b/nav/stache/nav-tab-content.stache deleted file mode 100644 index 5686ab4..0000000 --- a/nav/stache/nav-tab-content.stache +++ /dev/null @@ -1 +0,0 @@ -
    {{{ content }}}
    diff --git a/nav/stache/nav.stache b/nav/stache/nav.stache deleted file mode 100644 index 1bbeca2..0000000 --- a/nav/stache/nav.stache +++ /dev/null @@ -1,41 +0,0 @@ -{{# this.isLoading}} -
    Loading...
    -{{ else }} - {{#hasTabs}} - {{#if(../vertical)}} -
    -
    -
    - {{#each (scope.top.items, item=value)}} - {{ item.html }} - {{/each}} -
    -
    -
    -
    - {{#each (scope.top.tabs, tab=value)}} - {{ tab.html }} - {{/each}} -
    -
    -
    - {{else}} -
    - {{#each (../items, item=value)}} - {{ item.html }} - {{/each}} -
    - {{/if}} -
    - {{#each (../tabs, tab=value)}} - {{ tab.html }} - {{/each}} -
    - {{else}} - - {{/hasTabs}} -{{/ this.isLoading }} diff --git a/navbar/navbar-brand.js b/navbar/navbar-brand.js index ee7fa83..2c61a64 100644 --- a/navbar/navbar-brand.js +++ b/navbar/navbar-brand.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import {FazStacheItem} from "../item"; diff --git a/navbar/navbar-collapse.js b/navbar/navbar-collapse.js index 6408116..e407fe8 100644 --- a/navbar/navbar-collapse.js +++ b/navbar/navbar-collapse.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazStacheItem, FazStacheItemList } from "../item"; import {default as FazNavbarBrand} from "./navbar-brand"; diff --git a/navbar/navbar-nav-item-title.js b/navbar/navbar-nav-item-title.js index 2c7cce5..d2947b0 100644 --- a/navbar/navbar-nav-item-title.js +++ b/navbar/navbar-nav-item-title.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazStacheItem } from "../item"; diff --git a/navbar/navbar-nav-item.js b/navbar/navbar-nav-item.js index 6db965b..0d0fa19 100644 --- a/navbar/navbar-nav-item.js +++ b/navbar/navbar-nav-item.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { type } from "can"; import { FazStacheItem, FazStacheItemList } from "../item"; diff --git a/navbar/navbar-nav.js b/navbar/navbar-nav.js index c0a037e..1e34b13 100644 --- a/navbar/navbar-nav.js +++ b/navbar/navbar-nav.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazStacheItem, FazStacheItemList} from "../item"; import navTemplate from "./stache/navbar-nav.stache"; diff --git a/navbar/navbar-toggler.js b/navbar/navbar-toggler.js index a239881..0f19225 100644 --- a/navbar/navbar-toggler.js +++ b/navbar/navbar-toggler.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { FazStacheItem } from "../item"; import navbarTogglerTemplate from "./stache/navbar-toggler.stache"; diff --git a/navbar/navbar.js b/navbar/navbar.js index d993f51..bf2b1f3 100644 --- a/navbar/navbar.js +++ b/navbar/navbar.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2021 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import { ajax, DeepObservable, ObservableObject, type diff --git a/package.json b/package.json index 30c5ba8..5416719 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,35 @@ { "name": "faz", - "version": "0.1.9", - "description": "Vanilla JS HTML Web Components", - "main": "./dist/index.js", - "module": "./dist/esm/index.js", + "version": "0.5.3", + "description": "JS HTML Web Components", + "main": "dist/js/index.js", + "module": "dist/js/index.js", "mainFields": [ "module", "main" ], - "types": "./src/types/index.d.ts", + "types": "dist/types/index.d.ts", "files": [ "dist", - "src" + "src", + "types" ], + "exports": { + ".": { + "types": "./dist/types/index.d.ts", + "import": "./dist/js/index.js" + }, + "./reactivity": { + "types": "./dist/types/reactivity.d.ts", + "import": "./dist/js/reactivity.js" + }, + "./paginator": { + "types": "./dist/types/paginator.d.ts", + "import": "./dist/js/paginator.js" + }, + "./src": "./src/index.ts", + "./src/*": "./src/*" + }, "repository": { "type": "git", "url": "git+https://github.com/candango/faz.git" @@ -22,7 +39,8 @@ }, "homepage": "https://github.com/candango/faz#readme", "author": "Flavio Garcia ", - "license": "Apache-2.0", + "license": "MIT", + "type": "module", "keywords": [ "webcomponent", "solidjs", @@ -30,59 +48,51 @@ "toolkit" ], "dependencies": { - "axios": "1.6.1", - "bootstrap": "5.3.2", - "bootstrap-icons": "1.11.2", - "bootswatch": "5.3.2", - "can": "6.6.2", - "jquery": "3.7.0", - "less": "4.2.0", - "lodash": "4.17.21", - "solid-js": "1.8.5" + "less": "4.5.1", + "solid-js": "1.9.13" }, "devDependencies": { - "@codemirror/lang-html": "6.4.5", - "@codemirror/language": "6.8.0", - "@codemirror/view": "6.16.0", - "@testing-library/dom": "9.3.3", - "@testing-library/jest-dom": "6.1.5", - "@types/jest": "29.5.11", - "@types/lodash": "4.14.197", + "@testing-library/jest-dom": "6.9.1", + "@types/jest": "30.0.0", + "@types/nise": "1.4.5", + "@types/node": "25.0.3", "can-stache-loader": "3.0.0", - "electron": "27.0.4", - "esbuild": "0.19.10", - "esbuild-jest": "0.5.0", + "esbuild": "0.27.2", "esbuild-plugin-copy": "2.1.1", - "esbuild-plugin-solid": "0.5.0", + "esbuild-plugin-solid": "0.6.0", "http-server": "14.1.1", - "jest": "29.7.0", - "jest-environment-jsdom": "29.7.0", - "prettier": "3.1.1", - "qunit": "2.17.2", - "ts-jest": "29.1.1", - "ts-loader": "9.5.1", + "jsdom": "27.0.0", + "nise": "6.1.5", + "prettier": "3.7.4", "ts-node": "10.9.2", - "typescript": "5.3.3" + "typescript": "5.9.3", + "vite": "8.0.16", + "vite-plugin-solid": "2.11.12", + "vitest": "4.0.18" }, "scripts": { - "watch": "node watch.mjs", - "showcase": "http-server & npm run watch", + "watch": "pnpm run watch:clean && node watch.mjs", + "watch:clean": "rm -rf watch/dist", + "showcase": "http-server & pnpm run watch", "esbuild": "node build.mjs", - "build": "npm run build:clean && npm run lessc && npm run esbuild", - "build:prod": "npm run build:clean && webpack --config webpack.config.prod.js && npm run lessc", + "ts:build": "pnpm run ts:clean && pnpm run ts:declaration && cp -r types dist", + "ts:declaration": "tsc -p tsconfig.types.json -d --declarationDir types --emitDeclarationOnly && rm -rf tsconfig.types.tsbuildinfo", + "ts:clean": "rm -rf tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo types/*", + "build": "pnpm run build:clean && pnpm run lessc && pnpm run esbuild && pnpm run ts:build", "build:clean": "rm -rf dist", "build:vendors": "rm -rf dist", - "lessc": "npm run lessc:faz && npm run lessc:showcase", + "lessc": "pnpm run lessc:faz && pnpm run lessc:showcase", "lessc:faz": "lessc stylesheets/faz.less dist/css/faz.css --source-map", "lessc:showcase": "lessc stylesheets/showcase.less dist/css/showcase.css --source-map", - "lessc:dev": "npm run lessc:dev:faz && npm run lessc:dev:showcase", + "lessc:dev": "pnpm run lessc:dev:faz && pnpm run lessc:dev:showcase", "lessc:dev:faz": "lessc stylesheets/faz.less stylesheets/faz.css --source-map", "lessc:dev:showcase": "lessc stylesheets/showcase.less stylesheets/showcase.css --source-map", - "test": "jest", - "test:browser": "karma start --single-run", - "yarn": "npm run yarn:clean && npm run yarn:v2 && npm run yarn:install", - "yarn:install": "yarn install", - "yarn:clean": "rm -rf yarn.lock .yarn .yarnrc.yml .next node_modules", - "yarn:v2": "yarn set version berry && yarn config set nodeLinker node-modules" + "test": "vitest run" + }, + "packageManager": "pnpm@10.25.0", + "pnpm": { + "overrides": { + "@asamuzakjp/css-color": "4.1.1" + } } } diff --git a/pagination/index.html b/pagination/index.html deleted file mode 100644 index 5039f72..0000000 --- a/pagination/index.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - Candango Faz Toolkit - Alerts - - - - - - - - - - - - - -
    -

    Pagination

    -
    -
    -

    One page

    -

    Pagination has count equals 9 (9 records counted).

    -

    Records per page(perPage property) by default is 10 resulting in a pagination with only one page.

    -

    All navigation buttons won't be displayed.

    -
    -
    -
    -
    -
    -
    -

    Multiple pages and one block

    -

    A pagination with count equals 91 resulting in multiple pages.

    -

    Pages per page(perBlock property) by default is 10 resulting in a pagination with only one block.

    -

    All block navigation buttons won't be displayed.

    -
    -
    -
    -
    -
    -
    -

    Multiple pages and multiple blocks

    -

    A pagination with count equals 340 resulting in multiple pages and multiple blocks.

    -
    -
    -
    -
    -
    -
    -

    Start on a defined page

    -

    Set current page as 173.

    -

    The pagination will be rendered with the page 173 selected at the block of pages 18, displaying pages from 171 to 180.

    -

    Block navigation buttons will be displayed.

    -
    -
    -
    -
    -
    -
    -

    Disabled pagination

    -

    Pagination is disabled but we still show the - current page.

    -
    -
    - -
    -
    -
    -
    -

    Initial callback to be called after pagination is rendered

    -
    -
    -
    -
    -
    -
    -

    Page callback to be called after page is changed

    -
    -
    -
    -
    -
    -
    -

    Negative page value

    -

    A negative page value will be informed - defaulting the current page value to 1 and sending a warning at - the console.

    -
    -
    -
    -
    -
    -
    -

    Page value bigger than the page count

    -

    A page valu bigger than the page count will be - informed defaulting the current page value as the page count - and sending a warning at the console.

    -
    -
    -
    -
    -
    - - -
    - - - - - - - - - - - - - - diff --git a/pagination/pagination.js b/pagination/pagination.js deleted file mode 100644 index 17b33b4..0000000 --- a/pagination/pagination.js +++ /dev/null @@ -1,565 +0,0 @@ -/** - * Copyright 2018-2022 Flávio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {FazElementItem, FazReactItem} from "../item" -import ReactDOM from "react-dom" -import React from "react" - -export class FazReactPagination extends FazReactItem { - - defineStates(props) { - super.defineStates(props); - this.state['ariaLabel'] = undefined - // Used to be records - this.state['count'] = 0 - // Used to be currentPage - this.state['page'] = 1 - // Used to be pagesPerBlock - this.state['perBlock'] = 10 - // Used to be pagesPerPage - this.state['perPage'] = 10 - - this.state['labels'] = { - first : "First", - firstTooltip : "Go to the first page", - last : "Last", - lastTooltip : "Go to the last page", - previous : "Previous", - previousBlock : "Previous {perBlock}", - previousTooltip : "Go to the previous page", - previousBlockTooltip : "Go to the previous {perBlock} pages", - next : "Next", - nextBlock : "Next {perBlock}", - nextBlockTooltip : "Go to the next {perBlock} pages", - nextTooltip : "Go to the next page", - } - this.state['initCallback'] = undefined - this.state['pageCallback'] = undefined - - for(let key in props) { - switch (key) { - case "ariaLabel": - this.state['ariaLabel'] = props[key] - break - case "count": - this.state['count'] = parseInt(props[key]) - break - case "page": - this.state['page'] =parseInt(props[key]) - break - case "perBlock": - this.state['perBlock'] = parseInt(props[key]) - break - case "perPage": - this.state['perPage'] = parseInt(props[key]) - break - } - } - - } - - afterMount() { - this.callInitCallback() - } - - get prefix() { - return "faz-react-pagination" - } - - get containerId() { - return "faz-pagination-container-".concat(this.state.id) - } - - render() { - return
    - {this.state.debug ? this.renderDebug() : ""}
    - } - - renderFirstPage() { - return
  • - {this.isFirstPage ? - {this.state.labels.first} : - this.goToFirstPage(event)} - href={this.paginatedLink(1)} - data-bs-toggle="tooltip" - data-bs-placement="top" - title={this.state.labels.firstTooltip} - >{this.state.labels.first}} -
  • - } - - renderLastPage() { - return
  • - {this.isLastPage ? - {this.state.labels.last} : - this.goToLastPage(event)} - href={this.paginatedLink(this.pages)} - data-bs-toggle="tooltip" - data-bs-placement="top" - title={this.state.labels.lastTooltip} - >{this.state.labels.last}} -
  • - } - - renderPreviousPage() { - let page = this.state.page - 1 - return
  • - {this.isFirstPage ? - {this.state.labels.previous} : - this.goToPreviousPage(event)} - href={this.paginatedLink(page)} - data-bs-toggle="tooltip" - data-bs-placement="top" - title={this.state.labels.previousTooltip} - >{this.state.labels.previous}} -
  • - } - - renderPreviousBlock() { - let page = this.currentFirstPage - 1 - let label = this.state.labels.previousBlock.replace("{perBlock}", - this.state.perBlock) - let tooltipLabel = this.state.labels.previousBlockTooltip.replace( - "{perBlock}", this.state.perBlock) - return
  • - {this.isFirstBlock ? - "" : - this.goToPreviousBlock(event)} - href={this.paginatedLink(page)} - data-bs-toggle="tooltip" - data-bs-placement="top" - title={tooltipLabel}>{label}} -
  • - } - - renderNextPage() { - let page = this.state.page + 1 - return
  • - {this.isLastPage ? - {this.state.labels.next} : - this.goToNextPage(event)} - href={this.paginatedLink(page)} - data-bs-toggle="tooltip" - data-bs-placement="top" - title={this.state.labels.nextTooltip} - >{this.state.labels.next}} -
  • - } - - renderNextBlock() { - let page = this.currentLastPage + 1 - let label = this.state.labels.nextBlock.replace("{perBlock}", - this.state.perBlock) - let tooltipLabel = this.state.labels.nextBlockTooltip.replace( - "{perBlock}", this.state.perBlock) - return
  • - {this.isLastPage ? - "" : - this.goToNextBlock(event)} - href={this.paginatedLink(page)} - data-bs-toggle="tooltip" - data-bs-placement="top" - title={tooltipLabel}>{label}} -
  • - } - - renderNumberedPages() { - return this.pagesInCurrentBlock.map((page) => -
  • - {this.isCurrentPage(page) ? - {page} : - this.goToPage(event, page)} - href={this.paginatedLink(page)}>{page}} -
  • - ) - } - - renderDebug() { - let accordionId = "faz-pagination-debug-".concat(this.state.id) - let collapseId = accordionId.concat("-", this.state.id) - return (
    -
    -

    - -

    -
    -
    -
    Component State Information
    -
    -
    Disabled:
    -
    {this.disabled}
    -
    -
    Records Information
    -
    -
    Records:
    -
    {this.state.count}
    -
    Current First Record:
    -
    {this.currentFirstRecord}
    -
    Current Last Record:
    -
    {this.currentLastRecord}
    -
    -
    Pages Information
    -
    -
    Pages:
    -
    {this.pages}
    -
    Current Page:
    -
    {this.state.page}
    -
    Current Page Computed:
    -
    {this.pageComputed}
    -
    Current First Page:
    -
    {this.currentFirstPage}
    -
    Current Last Page:
    -
    {this.currentLastPage}
    -
    Records per page:
    -
    {this.state.perPage}
    -
    Records in last page:
    -
    {this.recordsInLastPage}
    -
    Is first page:
    -
    - {this.isFirstPage ? "True" : "False"} -
    -
    Is last page:
    -
    - {this.isLastPage ? "True" : "False"} -
    -
    -
    Blocks Information
    -
    -
    Blocks:
    -
    {this.blocks}
    -
    Current Block:
    -
    {this.currentBlock}
    -
    Pages per Block:
    -
    {this.state.perBlock}
    -
    Pages in last Block:
    -
    {this.pagesInLastBlock}
    -
    Is Last Block:
    -
    - {this.isLastBlock ? "True" : "False"} -
    -
    Has Multiple Blocks:
    -
    - {this.hasMultipleBlocks ? "True" : "False"} -
    -
    -
    -
    -
    -
    ) - } - - get firstPreviousButtonClass() { - let classes = ["page-item"] - if (this.isFirstPage || this.disabled) { - classes.push("disabled") - } - return classes.join(" ") - } - - get previousBlockButtonClass() { - let classes = ["page-item"] - if (this.isFirstBlock || this.disabled) { - classes.push("disabled") - } - return classes.join(" ") - } - - get lastNextButtonClass() { - let classes = ["page-item"] - if (this.isLastPage || this.disabled) { - classes.push("disabled") - } - return classes.join(" ") - } - - get nextBlockButtonClass() { - let classes = ["page-item"] - if (this.isLastBlock || this.disabled) { - classes.push("disabled") - } - return classes.join(" ") - } - - getButtonClass(page) { - let classes = ["page-item"] - if (this.isCurrentPage(page)) { - classes.push("active") - } - if (this.disabled && !this.isCurrentPage(page)) { - classes.push("disabled") - } - return classes.join(" ") - } - - get pages() { - if (this.state.count === 0) { - return 1 - } - let pagesFloor = Math.floor(this.state.count/this.state.perPage) - let remainder = this.state.count % this.state.perPage - let addRemainder = remainder > 0 ? 1 : 0 - return pagesFloor + addRemainder - } - - /** - * Page computed is used to protect the page limit. - * - * If the state page is out of limits of 1 and pages we fix the state - * page value. - * - * @returns {number|*} - */ - get pageComputed() { - if (this.state.page < 1) { - this.updateState({page: 1}) - } - if (this.pages < this.state.page) { - this.updateState({page: this.pages}) - } - return this.state.page - } - - get recordsInLastPage() { - let lastPageRemainder = this.state.count % this.state.perPage; - return lastPageRemainder > 0 ? lastPageRemainder : this.state.perPage - } - - get blocks() { - let blocksFloor = Math.floor(this.pages / this.state.perBlock); - let addReminder = this.pages % this.state.perBlock > 0 ? 1 : 0; - return blocksFloor + addReminder; - } - - get pagesInLastBlock() { - let lastBlockRemainder = this.pages % this.state.perBlock - return lastBlockRemainder > 0 ? lastBlockRemainder : - this.state.perBlock - } - - get currentFirstRecord() { - return (this.pageComputed * this.state.perPage) - this.state.perPage + 1 - } - - get currentLastRecord() { - if (this.isLastPage) { - return this.currentFirstRecord + this.recordsInLastPage - 1 - } - return this.pageComputed * this.state.perPage - } - - get currentBlock() { - if (this.pageComputed <= this.state.perBlock) { - return 1 - } - let currentBlockFloor = Math.floor( - this.pageComputed / this.state.perBlock) - let remainder = this.pageComputed % this.state.perBlock - let addRemainder = remainder > 0 ? 1 : 0 - - return currentBlockFloor + addRemainder - } - - get currentFirstPage() { - return (this.currentBlock * this.state.perBlock) - - this.state.perBlock + 1 - } - - get currentLastPage() { - if (this.isLastBlock) { - return this.currentFirstPage + this.pagesInLastBlock - 1 - } - return this.currentBlock * this.state.perBlock - } - - get pagesInCurrentBlock() { - let pages = this.isLastBlock ? - this.pagesInLastBlock : this.state.perBlock - return Array(pages).fill( - undefined).map((_, i) => i + this.currentFirstPage) - } - - isCurrentPage(page) { - return page === this.pageComputed - } - - get isFirstPage() { - return this.pageComputed === 1 - } - - get isFirstBlock() { - return this.currentBlock === 1 - } - - get isLastPage() { - return this.pageComputed >= this.pages - } - - get isLastBlock() { - return this.currentBlock >= this.blocks - } - - get hasMultiplePages() { - return this.pages > 1 - } - - get hasMultipleBlocks() { - return this.blocks > 1 - } - - /** - * Returns the nav item href. If item is disabled a javascript void - * function will be placed to avoid any action. - * - * @param page - * @returns {string} - */ - paginatedLink(page) { - return this.link.replace("{page}", page) - } - - callInitCallback() { - if (this.state.initCallback !== undefined) { - this.state.initCallback(this); - } - } - - callPageCallback(page) { - if (this.state.pageCallback !== undefined) { - this.state.pageCallback(page, this); - } - } - - goToPage(event, page) { - this.updateState({page: page}) - this.callPageCallback(page) - } - - goToFirstPage(event) { - this.goToPage(event, 1); - } - - goToLastPage(event) { - this.goToPage(event, this.pages); - } - - goToPreviousPage(event) { - this.goToPage(event, this.state.page - 1) - } - - goToPreviousBlock(event) { - this.goToPage(event, this.currentFirstPage - 1) - } - - goToNextPage(event) { - this.goToPage(event, this.state.page + 1); - } - - goToNextBlock(event) { - this.goToPage(event, this.currentLastPage + 1) - } -} - -export default class FazPaginationElement extends FazElementItem { - constructor(props) { - super(props) - } - - show() { - ReactDOM.render( - , this) - } - - attributesToStates() { - super.attributesToStates(); - for(let attribute of this.attributes) { - switch (attribute.name) { - case "aria-label": - this.reactItem.state['ariaLabel'] = attribute.value - break; - case "count": - this.reactItem.state['count'] = parseInt(attribute.value) - break; - case "init-callback": - this.reactItem.state['initCallback'] = eval( - attribute.value) - break; - case "page-callback": - this.reactItem.state['pageCallback'] = eval( - attribute.value) - break; - } - } - let pageAttribute = this.attributes.getNamedItem("page") - if (pageAttribute) { - let page = parseInt(pageAttribute.value) - if (page > this.reactItem.pages) { - let warning = "You cannot inform a page bigger than than the " + - "page count(currently {pages} pages). It was informed " + - "{page} as page to be set. The current page will default " + - "to {pages} page(the last page), but please inform a " + - "correct the value next time.\n\nSee element:" - console.warn(warning.replaceAll( - "{pages}", this.reactItem.pages).replaceAll( - "{page}", page.toString())) - console.log(this) - page = this.reactItem.pages - } - if (page > 1) { - this.reactItem.state['page'] = page - } else { - let warning = "You cannot inform a page smaller than than " + - "1(the first page). It was informed " + - "{page} as page to be set. Will keep the current page " + - "will default to 1, but please inform a correct the " + - "value next time.\n\nSee element:" - console.warn(warning.replaceAll("{page}", page.toString())) - console.log(this) - } - - } - } -} - -customElements.define("faz-pagination", FazPaginationElement) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..7781f60 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,3673 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + '@asamuzakjp/css-color': 4.1.1 + +importers: + + .: + dependencies: + less: + specifier: 4.5.1 + version: 4.5.1 + solid-js: + specifier: 1.9.13 + version: 1.9.13 + devDependencies: + '@testing-library/jest-dom': + specifier: 6.9.1 + version: 6.9.1 + '@types/jest': + specifier: 30.0.0 + version: 30.0.0 + '@types/nise': + specifier: 1.4.5 + version: 1.4.5 + '@types/node': + specifier: 25.0.3 + version: 25.0.3 + can-stache-loader: + specifier: 3.0.0 + version: 3.0.0 + esbuild: + specifier: 0.27.2 + version: 0.27.2 + esbuild-plugin-copy: + specifier: 2.1.1 + version: 2.1.1(esbuild@0.27.2) + esbuild-plugin-solid: + specifier: 0.6.0 + version: 0.6.0(esbuild@0.27.2)(solid-js@1.9.13) + http-server: + specifier: 14.1.1 + version: 14.1.1 + jsdom: + specifier: 27.0.0 + version: 27.0.0 + nise: + specifier: 6.1.5 + version: 6.1.5 + prettier: + specifier: 3.7.4 + version: 3.7.4 + ts-node: + specifier: 10.9.2 + version: 10.9.2(@types/node@25.0.3)(typescript@5.9.3) + typescript: + specifier: 5.9.3 + version: 5.9.3 + vite: + specifier: 8.0.16 + version: 8.0.16(@types/node@25.0.3)(esbuild@0.27.2)(less@4.5.1) + vite-plugin-solid: + specifier: 2.11.12 + version: 2.11.12(@testing-library/jest-dom@6.9.1)(solid-js@1.9.13)(vite@8.0.16(@types/node@25.0.3)(esbuild@0.27.2)(less@4.5.1)) + vitest: + specifier: 4.0.18 + version: 4.0.18(@types/node@25.0.3)(jsdom@27.0.0)(less@4.5.1)(lightningcss@1.32.0) + +packages: + + '@adobe/css-tools@4.5.0': + resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==} + + '@asamuzakjp/css-color@4.1.1': + resolution: {integrity: sha512-B0Hv6G3gWGMn0xKJ0txEi/jM5iFpT3MfDxmhZFb4W047GvytCf1DHQ1D69W3zHI4yWe2aTZAA0JnbMZ7Xc8DuQ==} + + '@asamuzakjp/dom-selector@6.8.1': + resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.7': + resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.29.7': + resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.29.7': + resolution: {integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.29.7': + resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.18.6': + resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.29.7': + resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.29.7': + resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-jsx@7.29.7': + resolution: {integrity: sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.29.7': + resolution: {integrity: sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.29.7': + resolution: {integrity: sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.29.7': + resolution: {integrity: sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.29.7': + resolution: {integrity: sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.7': + resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-syntax-patches-for-csstree@1.1.5': + resolution: {integrity: sha512-oNjBvzLq2GPZtJphCjLqXow/cHySHSgtxvKZb7OqSZ/xHgw6NWNhfad+6AB9cLeVm6eA9d/qMll3JdEHjy6M+A==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@jest/diff-sequences@30.4.0': + resolution: {integrity: sha512-zOpzlfUs45l6u7jm39qr87JCHUDsaeCtvL+kQe/Vn9jSnRB4/5IPXISm0h9I1vZW/o00Kn4UTJ2MOlhnUGwv3g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect-utils@30.4.1': + resolution: {integrity: sha512-ZBn5CglH8fBsQsvs4VWNzD4aWfUYks+IdOOQU3MEK71ol/BcVm+P+rtb1KpiFBpSWSCE27uOahyyf1vfqOVbcQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/get-type@30.1.0': + resolution: {integrity: sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/pattern@30.4.0': + resolution: {integrity: sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/schemas@30.4.1': + resolution: {integrity: sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/types@30.4.1': + resolution: {integrity: sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@napi-rs/wasm-runtime@1.1.5': + resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@oxc-project/types@0.133.0': + resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + + '@rolldown/binding-android-arm64@1.0.3': + resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.3': + resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.3': + resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.3': + resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.3': + resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.3': + resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.3': + resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.0.3': + resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.3': + resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.3': + resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@rollup/rollup-android-arm-eabi@4.62.2': + resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.62.2': + resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.62.2': + resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.62.2': + resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.62.2': + resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.62.2': + resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.62.2': + resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.62.2': + resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.62.2': + resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.62.2': + resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.62.2': + resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.62.2': + resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.2': + resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.2': + resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} + cpu: [x64] + os: [win32] + + '@sinclair/typebox@0.34.49': + resolution: {integrity: sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@15.4.0': + resolution: {integrity: sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@tsconfig/node10@1.0.12': + resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@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==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@30.0.0': + resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} + + '@types/nise@1.4.5': + resolution: {integrity: sha512-KNx8h0QdeA+BnH5E8rFPBznTGCl+aQwZ+45TaFWRavTULakVpwu6vis8IMVCGphgGCVtqWD1ne/vO1yOq1QJxg==} + + '@types/node@25.0.3': + resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@vitest/expect@4.0.18': + resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} + + '@vitest/mocker@4.0.18': + resolution: {integrity: sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.0.18': + resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} + + '@vitest/runner@4.0.18': + resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==} + + '@vitest/snapshot@4.0.18': + resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} + + '@vitest/spy@4.0.18': + resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} + + '@vitest/utils@4.0.18': + resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} + + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} + + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + babel-plugin-jsx-dom-expressions@0.40.7: + resolution: {integrity: sha512-/O6JWUmjv03OI9lL2ry9bUjpD5S3PclM55RRJEyCdcFZ5W2SEA/59d+l2hNsk3gI6kiWRdRPdOtqZmsQzFN1pQ==} + peerDependencies: + '@babel/core': ^7.20.12 + + babel-preset-solid@1.9.12: + resolution: {integrity: sha512-LLqnuKVDlKpyBlMPcH6qEvs/wmS9a+NczppxJ3ryS/c0O5IiSFOIBQi9GzyiGDSbcJpx4Gr87jyFTos1MyEuWg==} + peerDependencies: + '@babel/core': ^7.0.0 + solid-js: ^1.9.12 + peerDependenciesMeta: + solid-js: + optional: true + + baseline-browser-mapping@2.10.38: + resolution: {integrity: sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==} + engines: {node: '>=6.0.0'} + hasBin: true + + basic-auth@2.0.1: + resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} + engines: {node: '>= 0.8'} + + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.4: + resolution: {integrity: sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + can-attribute-encoder@1.1.4: + resolution: {integrity: sha512-ZUHwzrTRNdtVM+7BgTLbDOOyO7dohPhCjEisJ8tOIIha1pvnn4D/pKcz3IAnZ+sUnYZgHK5JjGtiwl/0TlrzaA==} + + can-log@1.0.2: + resolution: {integrity: sha512-wmT8aGIb8u82HqKXjjXodb1fCanntC0RvMtluTMtt1GwVDZyPLV9RQHJ1+j3b5PgSPW6ZwCjyiKwnSkI+2swiw==} + + can-namespace@1.0.0: + resolution: {integrity: sha512-1sBY/SLwwcmxz3NhyVhLjt2uD/dZ7V1mII82/MIXSDn5QXnslnosJnjlP8+yTx2uTCRvw1jlFDElRs4pX7AG5w==} + + can-stache-ast@1.1.0: + resolution: {integrity: sha512-3df63QcrsJo6XYj8E3RGerr/Z+nGoKO/Cg0TaSybrdNqJmK7XtLsP42XMc4OrIH/edDQ63BH2DfAtTdSMTEbqQ==} + + can-stache-loader@3.0.0: + resolution: {integrity: sha512-c3eKZtON+Bx/mTIIrm1ARQuljOIo9nIz1jmZVDlNkrqFEQs5WQZHvmO69POUygVra4k6ud6RrPknycUOIu8onQ==} + + can-view-parser@4.1.3: + resolution: {integrity: sha512-+sK9Ntcr+gI8hYo7/6fLUK8R30ER63Vj4FOwZbuIAJrl6MJSJ0cXs+Kljw/NTZyjzLEdynzM3uaqWTNjzP2PLw==} + + caniuse-lite@1.0.30001799: + resolution: {integrity: sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + + corser@2.0.1: + resolution: {integrity: sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==} + engines: {node: '>= 0.4.0'} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + 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==} + + cssstyle@5.3.7: + resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} + engines: {node: '>=20'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-urls@6.0.1: + resolution: {integrity: sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==} + engines: {node: '>=20'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + diff@4.0.4: + resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + electron-to-chromium@1.5.377: + resolution: {integrity: sha512-cH1jZgJHoezfTnKfKwnScpHywTFVnJUNITDPREFdhNjiuD502+QFpG0Qk7G8jhsV/f+CEAFlIrzP1fT+IMb92g==} + + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + esbuild-plugin-copy@2.1.1: + resolution: {integrity: sha512-Bk66jpevTcV8KMFzZI1P7MZKZ+uDcrZm2G2egZ2jNIvVnivDpodZI+/KnpL3Jnap0PBdIHU7HwFGB8r+vV5CVw==} + peerDependencies: + esbuild: '>= 0.14.0' + + esbuild-plugin-solid@0.6.0: + resolution: {integrity: sha512-V1FvDALwLDX6K0XNYM9CMRAnMzA0+Ecu55qBUT9q/eAJh1KIDsTMFoOzMSgyHqbOfvrVfO3Mws3z7TW2GVnIZA==} + peerDependencies: + esbuild: '>=0.20' + solid-js: '>= 1.0' + + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + expect@30.4.1: + resolution: {integrity: sha512-PMARsyh/JtqC20HoGqlFcIlQAyqUtW4PlI1rup1uhYJtKuwAjbvWi3GQMAn+STdHum/dk8xrKfUM1+5SAwpolA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + follow-redirects@1.16.0: + resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + html-encoding-sniffer@3.0.0: + resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} + engines: {node: '>=12'} + + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + html-entities@2.3.3: + resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + + http-server@14.1.1: + resolution: {integrity: sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==} + engines: {node: '>=12'} + hasBin: true + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + + jest-diff@30.4.1: + resolution: {integrity: sha512-CRpFK0RtLriVDGcPPAnR6HMVI8bSR2jnUIgralhauzYQZIb4RH9AtEInTuQr65LmmGggGcRT6HIASxwqsVsmlA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-matcher-utils@30.4.1: + resolution: {integrity: sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-message-util@30.4.1: + resolution: {integrity: sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-mock@30.4.1: + resolution: {integrity: sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-regex-util@30.4.0: + resolution: {integrity: sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-util@30.4.1: + resolution: {integrity: sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + jsdom@27.0.0: + resolution: {integrity: sha512-lIHeR1qlIRrIN5VMccd8tI2Sgw6ieYXSVktcSHaNe3Z5nE/tcPQYQWOq00wxMvYOsz+73eAkNenVvmPC6bba9A==} + engines: {node: '>=20'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@6.2.1: + resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + + just-extend@6.2.0: + resolution: {integrity: sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==} + + less@4.5.1: + resolution: {integrity: sha512-UKgI3/KON4u6ngSsnDADsUERqhZknsVZbnuzlRZXLQCmfC/MDld42fTydUE9B+Mla1AL6SJ/Pp6SlEFi/AVGfw==} + engines: {node: '>=14'} + hasBin: true + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + loader-utils@1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} + engines: {node: '>=4.0.0'} + + lru-cache@11.5.1: + resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + merge-anything@5.1.7: + resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} + engines: {node: '>=12.13'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.15: + resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + needle@3.5.0: + resolution: {integrity: sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==} + engines: {node: '>= 4.4.x'} + hasBin: true + + nise@6.1.5: + resolution: {integrity: sha512-SnRDPDBjxZZoU2n0+gzzLtSvo1OZo7j6jnbXsoh3AFxEGhaFU7ZF0TmefuKERq79wxR2U+MPn7ArW+Tl+clC3A==} + + node-releases@2.0.48: + resolution: {integrity: sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==} + engines: {node: '>=18'} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + obug@2.1.3: + resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} + engines: {node: '>=12.20.0'} + + opener@1.5.2: + resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} + hasBin: true + + parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + path-to-regexp@8.4.2: + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + portfinder@1.0.38: + resolution: {integrity: sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==} + engines: {node: '>= 10.12'} + + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + engines: {node: ^10 || ^12 || >=14} + + prettier@3.7.4: + resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@30.4.1: + resolution: {integrity: sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + prr@1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.15.2: + resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + react-is@19.2.7: + resolution: {integrity: sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rolldown@1.0.3: + resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rollup@4.62.2: + resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.6.0: + resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + engines: {node: '>=11.0.0'} + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + secure-compare@3.0.1: + resolution: {integrity: sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + seroval-plugins@1.5.4: + resolution: {integrity: sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + + seroval@1.5.4: + resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==} + engines: {node: '>=10'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + solid-js@1.9.13: + resolution: {integrity: sha512-6hJeJMOcEX8ktqjpDoJZEmld3ijvcvWBDtiXBm7f4332SiFN66QeAQI1REQshvyUoISsSeJ4PHDauKYbwao9JQ==} + + solid-refresh@0.6.3: + resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} + peerDependencies: + solid-js: ^1.3 + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + + tldts-core@7.4.4: + resolution: {integrity: sha512-vwVLJVvvpslm7vqAH7+XNj/neA/Ynq7DT2EEcMuwc5YzN5XaMyRAqxwU+uX3azZ1FQtB2gvrvnLnAEkvYlVdfg==} + + tldts@7.4.4: + resolution: {integrity: sha512-kFXFK7O4WPextIUAOk8qtnw9dxR9UIXP9CjuH1cTBVBZMDeQcUPgr/IazGiw1B0Yiw5L75gHLWeW4iD793r90g==} + hasBin: true + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tough-cookie@6.0.1: + resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + engines: {node: '>=16'} + + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + union@0.5.0: + resolution: {integrity: sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==} + engines: {node: '>= 0.8.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + url-join@4.0.1: + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + vite-plugin-solid@2.11.12: + resolution: {integrity: sha512-FgjPcx2OwX9h6f28jli7A4bG7PP3te8uyakE5iqsmpq3Jqi1TWLgSroC9N6cMfGRU2zXsl4Q6ISvTr2VL0QHpA==} + peerDependencies: + '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* + solid-js: ^1.7.2 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@testing-library/jest-dom': + optional: true + + vite@7.3.5: + resolution: {integrity: sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vite@8.0.16: + resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.18 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.1.3: + resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + vite: + optional: true + + vitest@4.0.18: + resolution: {integrity: sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.18 + '@vitest/browser-preview': 4.0.18 + '@vitest/browser-webdriverio': 4.0.18 + '@vitest/ui': 4.0.18 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + + whatwg-encoding@2.0.0: + resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} + engines: {node: '>=12'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@15.1.0: + resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} + engines: {node: '>=20'} + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + +snapshots: + + '@adobe/css-tools@4.5.0': {} + + '@asamuzakjp/css-color@4.1.1': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 11.5.1 + + '@asamuzakjp/dom-selector@6.8.1': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.1 + + '@asamuzakjp/nwsapi@2.3.9': {} + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.7': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-member-expression-to-functions': 7.29.7 + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7) + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/traverse': 7.29.7 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-member-expression-to-functions@7.29.7': + dependencies: + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.18.6': + dependencies: + '@babel/types': 7.29.7 + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/helper-plugin-utils@7.29.7': {} + + '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-member-expression-to-functions': 7.29.7 + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/traverse': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + dependencies: + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7) + transitivePeerDependencies: + - supports-color + + '@babel/preset-typescript@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7) + transitivePeerDependencies: + - supports-color + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/traverse@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-syntax-patches-for-csstree@1.1.5(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@3.0.4': {} + + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.27.2': + optional: true + + '@esbuild/android-arm64@0.27.2': + optional: true + + '@esbuild/android-arm@0.27.2': + optional: true + + '@esbuild/android-x64@0.27.2': + optional: true + + '@esbuild/darwin-arm64@0.27.2': + optional: true + + '@esbuild/darwin-x64@0.27.2': + optional: true + + '@esbuild/freebsd-arm64@0.27.2': + optional: true + + '@esbuild/freebsd-x64@0.27.2': + optional: true + + '@esbuild/linux-arm64@0.27.2': + optional: true + + '@esbuild/linux-arm@0.27.2': + optional: true + + '@esbuild/linux-ia32@0.27.2': + optional: true + + '@esbuild/linux-loong64@0.27.2': + optional: true + + '@esbuild/linux-mips64el@0.27.2': + optional: true + + '@esbuild/linux-ppc64@0.27.2': + optional: true + + '@esbuild/linux-riscv64@0.27.2': + optional: true + + '@esbuild/linux-s390x@0.27.2': + optional: true + + '@esbuild/linux-x64@0.27.2': + optional: true + + '@esbuild/netbsd-arm64@0.27.2': + optional: true + + '@esbuild/netbsd-x64@0.27.2': + optional: true + + '@esbuild/openbsd-arm64@0.27.2': + optional: true + + '@esbuild/openbsd-x64@0.27.2': + optional: true + + '@esbuild/openharmony-arm64@0.27.2': + optional: true + + '@esbuild/sunos-x64@0.27.2': + optional: true + + '@esbuild/win32-arm64@0.27.2': + optional: true + + '@esbuild/win32-ia32@0.27.2': + optional: true + + '@esbuild/win32-x64@0.27.2': + optional: true + + '@jest/diff-sequences@30.4.0': {} + + '@jest/expect-utils@30.4.1': + dependencies: + '@jest/get-type': 30.1.0 + + '@jest/get-type@30.1.0': {} + + '@jest/pattern@30.4.0': + dependencies: + '@types/node': 25.0.3 + jest-regex-util: 30.4.0 + + '@jest/schemas@30.4.1': + dependencies: + '@sinclair/typebox': 0.34.49 + + '@jest/types@30.4.1': + dependencies: + '@jest/pattern': 30.4.0 + '@jest/schemas': 30.4.1 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 25.0.3 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@oxc-project/types@0.133.0': {} + + '@rolldown/binding-android-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-x64@1.0.3': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.3': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.3': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.3': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.3': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.3': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.3': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@rollup/rollup-android-arm-eabi@4.62.2': + optional: true + + '@rollup/rollup-android-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-x64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.62.2': + optional: true + + '@rollup/rollup-openbsd-x64@4.62.2': + optional: true + + '@rollup/rollup-openharmony-arm64@4.62.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.62.2': + optional: true + + '@sinclair/typebox@0.34.49': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@15.4.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@standard-schema/spec@1.1.0': {} + + '@testing-library/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.5.0 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@tsconfig/node10@1.0.12': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@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.29.7 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.7 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.9': {} + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@30.0.0': + dependencies: + expect: 30.4.1 + pretty-format: 30.4.1 + + '@types/nise@1.4.5': {} + + '@types/node@25.0.3': + dependencies: + undici-types: 7.16.0 + + '@types/stack-utils@2.0.3': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@vitest/expect@4.0.18': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.0.18(vite@7.3.5(@types/node@25.0.3)(less@4.5.1)(lightningcss@1.32.0))': + dependencies: + '@vitest/spy': 4.0.18 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.5(@types/node@25.0.3)(less@4.5.1)(lightningcss@1.32.0) + + '@vitest/pretty-format@4.0.18': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.0.18': + dependencies: + '@vitest/utils': 4.0.18 + pathe: 2.0.3 + + '@vitest/snapshot@4.0.18': + dependencies: + '@vitest/pretty-format': 4.0.18 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.0.18': {} + + '@vitest/utils@4.0.18': + dependencies: + '@vitest/pretty-format': 4.0.18 + tinyrainbow: 3.1.0 + + acorn-walk@8.3.5: + dependencies: + acorn: 8.17.0 + + acorn@8.17.0: {} + + agent-base@7.1.4: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + arg@4.1.3: {} + + aria-query@5.3.2: {} + + array-union@2.1.0: {} + + assertion-error@2.0.1: {} + + async@3.2.6: {} + + babel-plugin-jsx-dom-expressions@0.40.7(@babel/core@7.29.7): + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.18.6 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/types': 7.29.7 + html-entities: 2.3.3 + parse5: 7.3.0 + + babel-preset-solid@1.9.12(@babel/core@7.29.7)(solid-js@1.9.13): + dependencies: + '@babel/core': 7.29.7 + babel-plugin-jsx-dom-expressions: 0.40.7(@babel/core@7.29.7) + optionalDependencies: + solid-js: 1.9.13 + + baseline-browser-mapping@2.10.38: {} + + basic-auth@2.0.1: + dependencies: + safe-buffer: 5.1.2 + + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + + big.js@5.2.2: {} + + binary-extensions@2.3.0: {} + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.4: + dependencies: + baseline-browser-mapping: 2.10.38 + caniuse-lite: 1.0.30001799 + electron-to-chromium: 1.5.377 + node-releases: 2.0.48 + update-browserslist-db: 1.2.3(browserslist@4.28.4) + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + can-attribute-encoder@1.1.4: + dependencies: + can-log: 1.0.2 + can-namespace: 1.0.0 + + can-log@1.0.2: {} + + can-namespace@1.0.0: {} + + can-stache-ast@1.1.0: + dependencies: + can-view-parser: 4.1.3 + + can-stache-loader@3.0.0: + dependencies: + can-stache-ast: 1.1.0 + loader-utils: 1.4.2 + + can-view-parser@4.1.3: + dependencies: + can-attribute-encoder: 1.1.4 + can-log: 1.0.2 + can-namespace: 1.0.0 + + caniuse-lite@1.0.30001799: {} + + chai@6.2.2: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + ci-info@4.4.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + convert-source-map@2.0.0: {} + + copy-anything@2.0.6: + dependencies: + is-what: 3.14.1 + + corser@2.0.1: {} + + create-require@1.1.1: {} + + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + css.escape@1.5.1: {} + + cssstyle@5.3.7: + dependencies: + '@asamuzakjp/css-color': 4.1.1 + '@csstools/css-syntax-patches-for-csstree': 1.1.5(css-tree@3.2.1) + css-tree: 3.2.1 + lru-cache: 11.5.1 + + csstype@3.2.3: {} + + data-urls@6.0.1: + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 15.1.0 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decimal.js@10.6.0: {} + + detect-libc@2.1.2: {} + + diff@4.0.4: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dom-accessibility-api@0.6.3: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + electron-to-chromium@1.5.377: {} + + emojis-list@3.0.0: {} + + entities@6.0.1: {} + + errno@0.1.8: + dependencies: + prr: 1.0.1 + optional: true + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + esbuild-plugin-copy@2.1.1(esbuild@0.27.2): + dependencies: + chalk: 4.1.2 + chokidar: 3.6.0 + esbuild: 0.27.2 + fs-extra: 10.1.0 + globby: 11.1.0 + + esbuild-plugin-solid@0.6.0(esbuild@0.27.2)(solid-js@1.9.13): + dependencies: + '@babel/core': 7.29.7 + '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7) + babel-preset-solid: 1.9.12(@babel/core@7.29.7)(solid-js@1.9.13) + esbuild: 0.27.2 + solid-js: 1.9.13 + transitivePeerDependencies: + - supports-color + + esbuild@0.27.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 + + escalade@3.2.0: {} + + escape-string-regexp@2.0.0: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + eventemitter3@4.0.7: {} + + expect-type@1.3.0: {} + + expect@30.4.1: + dependencies: + '@jest/expect-utils': 30.4.1 + '@jest/get-type': 30.1.0 + jest-matcher-utils: 30.4.1 + jest-message-util: 30.4.1 + jest-mock: 30.4.1 + jest-util: 30.4.1 + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + follow-redirects@1.16.0: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + html-encoding-sniffer@3.0.0: + dependencies: + whatwg-encoding: 2.0.0 + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + html-entities@2.3.3: {} + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.16.0 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + http-server@14.1.1: + dependencies: + basic-auth: 2.0.1 + chalk: 4.1.2 + corser: 2.0.1 + he: 1.2.0 + html-encoding-sniffer: 3.0.0 + http-proxy: 1.18.1 + mime: 1.6.0 + minimist: 1.2.8 + opener: 1.5.2 + portfinder: 1.0.38 + secure-compare: 3.0.1 + union: 0.5.0 + url-join: 4.0.1 + transitivePeerDependencies: + - debug + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + image-size@0.5.5: + optional: true + + indent-string@4.0.0: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-what@3.14.1: {} + + is-what@4.1.16: {} + + jest-diff@30.4.1: + dependencies: + '@jest/diff-sequences': 30.4.0 + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + pretty-format: 30.4.1 + + jest-matcher-utils@30.4.1: + dependencies: + '@jest/get-type': 30.1.0 + chalk: 4.1.2 + jest-diff: 30.4.1 + pretty-format: 30.4.1 + + jest-message-util@30.4.1: + dependencies: + '@babel/code-frame': 7.29.7 + '@jest/types': 30.4.1 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-util: 30.4.1 + picomatch: 4.0.4 + pretty-format: 30.4.1 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@30.4.1: + dependencies: + '@jest/types': 30.4.1 + '@types/node': 25.0.3 + jest-util: 30.4.1 + + jest-regex-util@30.4.0: {} + + jest-util@30.4.1: + dependencies: + '@jest/types': 30.4.1 + '@types/node': 25.0.3 + chalk: 4.1.2 + ci-info: 4.4.0 + graceful-fs: 4.2.11 + picomatch: 4.0.4 + + js-tokens@4.0.0: {} + + jsdom@27.0.0: + dependencies: + '@asamuzakjp/dom-selector': 6.8.1 + cssstyle: 5.3.7 + data-urls: 6.0.1 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.1 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + ws: 8.21.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@3.1.0: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonfile@6.2.1: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + just-extend@6.2.0: {} + + less@4.5.1: + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.8.1 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.5.0 + source-map: 0.6.1 + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + loader-utils@1.4.2: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 1.0.2 + + lru-cache@11.5.1: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + make-dir@2.1.0: + dependencies: + pify: 4.0.1 + semver: 5.7.2 + optional: true + + make-error@1.3.6: {} + + math-intrinsics@1.1.0: {} + + mdn-data@2.27.1: {} + + merge-anything@5.1.7: + dependencies: + is-what: 4.1.16 + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mime@1.6.0: {} + + min-indent@1.0.1: {} + + minimist@1.2.8: {} + + ms@2.1.3: {} + + nanoid@3.3.15: {} + + needle@3.5.0: + dependencies: + iconv-lite: 0.6.3 + sax: 1.6.0 + optional: true + + nise@6.1.5: + dependencies: + '@sinonjs/commons': 3.0.1 + '@sinonjs/fake-timers': 15.4.0 + just-extend: 6.2.0 + path-to-regexp: 8.4.2 + + node-releases@2.0.48: {} + + normalize-path@3.0.0: {} + + object-inspect@1.13.4: {} + + obug@2.1.3: {} + + opener@1.5.2: {} + + parse-node-version@1.0.1: {} + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + path-to-regexp@8.4.2: {} + + path-type@4.0.0: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.4: {} + + pify@4.0.1: + optional: true + + portfinder@1.0.38: + dependencies: + async: 3.2.6 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + postcss@8.5.15: + dependencies: + nanoid: 3.3.15 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prettier@3.7.4: {} + + pretty-format@30.4.1: + dependencies: + '@jest/schemas': 30.4.1 + ansi-styles: 5.2.0 + react-is-18: react-is@18.3.1 + react-is-19: react-is@19.2.7 + + prr@1.0.1: + optional: true + + punycode@2.3.1: {} + + qs@6.15.2: + dependencies: + side-channel: 1.1.1 + + queue-microtask@1.2.3: {} + + react-is@18.3.1: {} + + react-is@19.2.7: {} + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.2 + + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + require-from-string@2.0.2: {} + + requires-port@1.0.0: {} + + reusify@1.1.0: {} + + rolldown@1.0.3: + dependencies: + '@oxc-project/types': 0.133.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.3 + '@rolldown/binding-darwin-arm64': 1.0.3 + '@rolldown/binding-darwin-x64': 1.0.3 + '@rolldown/binding-freebsd-x64': 1.0.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 + '@rolldown/binding-linux-arm64-gnu': 1.0.3 + '@rolldown/binding-linux-arm64-musl': 1.0.3 + '@rolldown/binding-linux-ppc64-gnu': 1.0.3 + '@rolldown/binding-linux-s390x-gnu': 1.0.3 + '@rolldown/binding-linux-x64-gnu': 1.0.3 + '@rolldown/binding-linux-x64-musl': 1.0.3 + '@rolldown/binding-openharmony-arm64': 1.0.3 + '@rolldown/binding-wasm32-wasi': 1.0.3 + '@rolldown/binding-win32-arm64-msvc': 1.0.3 + '@rolldown/binding-win32-x64-msvc': 1.0.3 + + rollup@4.62.2: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.2 + '@rollup/rollup-android-arm64': 4.62.2 + '@rollup/rollup-darwin-arm64': 4.62.2 + '@rollup/rollup-darwin-x64': 4.62.2 + '@rollup/rollup-freebsd-arm64': 4.62.2 + '@rollup/rollup-freebsd-x64': 4.62.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 + '@rollup/rollup-linux-arm-musleabihf': 4.62.2 + '@rollup/rollup-linux-arm64-gnu': 4.62.2 + '@rollup/rollup-linux-arm64-musl': 4.62.2 + '@rollup/rollup-linux-loong64-gnu': 4.62.2 + '@rollup/rollup-linux-loong64-musl': 4.62.2 + '@rollup/rollup-linux-ppc64-gnu': 4.62.2 + '@rollup/rollup-linux-ppc64-musl': 4.62.2 + '@rollup/rollup-linux-riscv64-gnu': 4.62.2 + '@rollup/rollup-linux-riscv64-musl': 4.62.2 + '@rollup/rollup-linux-s390x-gnu': 4.62.2 + '@rollup/rollup-linux-x64-gnu': 4.62.2 + '@rollup/rollup-linux-x64-musl': 4.62.2 + '@rollup/rollup-openbsd-x64': 4.62.2 + '@rollup/rollup-openharmony-arm64': 4.62.2 + '@rollup/rollup-win32-arm64-msvc': 4.62.2 + '@rollup/rollup-win32-ia32-msvc': 4.62.2 + '@rollup/rollup-win32-x64-gnu': 4.62.2 + '@rollup/rollup-win32-x64-msvc': 4.62.2 + fsevents: 2.3.3 + + rrweb-cssom@0.8.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.1.2: {} + + safer-buffer@2.1.2: {} + + sax@1.6.0: + optional: true + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + secure-compare@3.0.1: {} + + semver@5.7.2: + optional: true + + semver@6.3.1: {} + + seroval-plugins@1.5.4(seroval@1.5.4): + dependencies: + seroval: 1.5.4 + + seroval@1.5.4: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + slash@3.0.0: {} + + solid-js@1.9.13: + dependencies: + csstype: 3.2.3 + seroval: 1.5.4 + seroval-plugins: 1.5.4(seroval@1.5.4) + + solid-refresh@0.6.3(solid-js@1.9.13): + dependencies: + '@babel/generator': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/types': 7.29.7 + solid-js: 1.9.13 + transitivePeerDependencies: + - supports-color + + source-map-js@1.2.1: {} + + source-map@0.6.1: + optional: true + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + stackback@0.0.2: {} + + std-env@3.10.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + symbol-tree@3.2.4: {} + + tinybench@2.9.0: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinyrainbow@3.1.0: {} + + tldts-core@7.4.4: {} + + tldts@7.4.4: + dependencies: + tldts-core: 7.4.4 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tough-cookie@6.0.1: + dependencies: + tldts: 7.4.4 + + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + + ts-node@10.9.2(@types/node@25.0.3)(typescript@5.9.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.12 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 25.0.3 + acorn: 8.17.0 + acorn-walk: 8.3.5 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.4 + make-error: 1.3.6 + typescript: 5.9.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + tslib@2.8.1: {} + + type-detect@4.0.8: {} + + typescript@5.9.3: {} + + undici-types@7.16.0: {} + + union@0.5.0: + dependencies: + qs: 6.15.2 + + universalify@2.0.1: {} + + update-browserslist-db@1.2.3(browserslist@4.28.4): + dependencies: + browserslist: 4.28.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + url-join@4.0.1: {} + + v8-compile-cache-lib@3.0.1: {} + + vite-plugin-solid@2.11.12(@testing-library/jest-dom@6.9.1)(solid-js@1.9.13)(vite@8.0.16(@types/node@25.0.3)(esbuild@0.27.2)(less@4.5.1)): + dependencies: + '@babel/core': 7.29.7 + '@types/babel__core': 7.20.5 + babel-preset-solid: 1.9.12(@babel/core@7.29.7)(solid-js@1.9.13) + merge-anything: 5.1.7 + solid-js: 1.9.13 + solid-refresh: 0.6.3(solid-js@1.9.13) + vite: 8.0.16(@types/node@25.0.3)(esbuild@0.27.2)(less@4.5.1) + vitefu: 1.1.3(vite@8.0.16(@types/node@25.0.3)(esbuild@0.27.2)(less@4.5.1)) + optionalDependencies: + '@testing-library/jest-dom': 6.9.1 + transitivePeerDependencies: + - supports-color + + vite@7.3.5(@types/node@25.0.3)(less@4.5.1)(lightningcss@1.32.0): + dependencies: + esbuild: 0.27.2 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.15 + rollup: 4.62.2 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 25.0.3 + fsevents: 2.3.3 + less: 4.5.1 + lightningcss: 1.32.0 + + vite@8.0.16(@types/node@25.0.3)(esbuild@0.27.2)(less@4.5.1): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.15 + rolldown: 1.0.3 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 25.0.3 + esbuild: 0.27.2 + fsevents: 2.3.3 + less: 4.5.1 + + vitefu@1.1.3(vite@8.0.16(@types/node@25.0.3)(esbuild@0.27.2)(less@4.5.1)): + optionalDependencies: + vite: 8.0.16(@types/node@25.0.3)(esbuild@0.27.2)(less@4.5.1) + + vitest@4.0.18(@types/node@25.0.3)(jsdom@27.0.0)(less@4.5.1)(lightningcss@1.32.0): + dependencies: + '@vitest/expect': 4.0.18 + '@vitest/mocker': 4.0.18(vite@7.3.5(@types/node@25.0.3)(less@4.5.1)(lightningcss@1.32.0)) + '@vitest/pretty-format': 4.0.18 + '@vitest/runner': 4.0.18 + '@vitest/snapshot': 4.0.18 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 + es-module-lexer: 1.7.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.3 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 7.3.5(@types/node@25.0.3)(less@4.5.1)(lightningcss@1.32.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.0.3 + jsdom: 27.0.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + webidl-conversions@8.0.1: {} + + whatwg-encoding@2.0.0: + dependencies: + iconv-lite: 0.6.3 + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-mimetype@5.0.0: {} + + whatwg-url@15.1.0: + dependencies: + tr46: 6.0.0 + webidl-conversions: 8.0.1 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + ws@8.21.0: {} + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + + yallist@3.1.1: {} + + yn@3.1.1: {} diff --git a/showcase/custom/index.html b/showcase/custom/index.html new file mode 100644 index 0000000..0a1de7b --- /dev/null +++ b/showcase/custom/index.html @@ -0,0 +1,30 @@ + + + + + + + + + + Candango Faz Toolkit - Custom component + + + + + + + + +
    +

    Faz - Custom Component

    + +
    + + + + + + diff --git a/form/index.html b/showcase/form/index.html similarity index 57% rename from form/index.html rename to showcase/form/index.html index 92ed51b..1261797 100644 --- a/form/index.html +++ b/showcase/form/index.html @@ -10,29 +10,19 @@ Candango Faz Toolkit - Form - - - - - -
    - +
    - - - diff --git a/showcase/index.html b/showcase/index.html new file mode 100644 index 0000000..a78b0a4 --- /dev/null +++ b/showcase/index.html @@ -0,0 +1,39 @@ + + + + + + + + + + Candango Faz + + + + + + + + + +
    + +
    +

    Faz

    +

    Faz components

    + +
    + +
    + + + + + + diff --git a/showcase/poc/index.html b/showcase/poc/index.html new file mode 100644 index 0000000..afe2b95 --- /dev/null +++ b/showcase/poc/index.html @@ -0,0 +1,52 @@ + + + + + + Candango Faz POC - Blink & Malabarismo + + + + + + + +
    +

    POC: Estratégia de Renderização

    + +
    +

    1. Caso Alert (Simples)

    + + + +
    + +
    +

    2. Caso Breadcrumb (Malabarismo)

    + + + + + +
    +
    + + + + diff --git a/showcase/src/custom-tag.tsx b/showcase/src/custom-tag.tsx new file mode 100644 index 0000000..b4abdb8 --- /dev/null +++ b/showcase/src/custom-tag.tsx @@ -0,0 +1,12 @@ + +import { FazElement } from "../../src/element"; + +class CustomTag extends FazElement { + + constructor() { + super(); + } + +} + +customElements.define("custom-tag", CustomTag); diff --git a/showcase/src/form.tsx b/showcase/src/form.tsx new file mode 100644 index 0000000..00b0787 --- /dev/null +++ b/showcase/src/form.tsx @@ -0,0 +1,55 @@ + +import { FazFormElement } from "../../src"; +import { Accessor, createSignal, JSX, Setter } from "solid-js"; +import { MountableElement, render } from "solid-js/web"; +import { fakeServer, FakeXMLHttpRequest } from "nise"; + +const server = fakeServer.create(); + +server.autoRespond = true; +server.respondWith("GET", "/sometest", function(xhr: FakeXMLHttpRequest) { + xhr.respond( + 200, + { "Content-Type": "application/json" }, + '{"id":1}', + ); +}); +server.respondWith("GET", "/sometest1", function(xhr: FakeXMLHttpRequest) { + xhr.respond( + 200, + { "Content-Type": "application/json" }, + '{"id":2}', + ); +}); + + +export class FormExample extends FazFormElement { + + constructor(){ + super(); + } + + show() { + render(() =>
    , this); + return; + } +} + +fetch("/sometest") + .then((response) => response.json()) + .then((data) => { + console.log(data); + }) + .catch((error) => { + console.log(error); + }); + +fetch("/sometest1") + .then((response) => response.json()) + .then((data) => { + console.log(data); + }) + .catch((error) => { + console.log(error); + }); +customElements.define("faz-form-example", FormExample); diff --git a/showcase/src/global.ts b/showcase/src/global.ts new file mode 100644 index 0000000..e69de29 diff --git a/showcase/src/poc/fast-poc-element.tsx b/showcase/src/poc/fast-poc-element.tsx new file mode 100644 index 0000000..5281b09 --- /dev/null +++ b/showcase/src/poc/fast-poc-element.tsx @@ -0,0 +1,8 @@ + +import { FazElement } from "../../../src/element"; + +// Uma versão do FazElement que renderiza SINCRONAMENTE pra matar a expansão +export class FastPocElement extends FazElement { + // A classe base agora já é síncrona por padrão, mas mantemos aqui + // para garantir o comportamento desejado na POC. +} diff --git a/showcase/src/poc/poc-alert.tsx b/showcase/src/poc/poc-alert.tsx new file mode 100644 index 0000000..ed82354 --- /dev/null +++ b/showcase/src/poc/poc-alert.tsx @@ -0,0 +1,27 @@ +import { FastPocElement } from "./fast-poc-element"; + +export class PocAlert extends FastPocElement { + constructor() { + super(); + } + + connectedCallback() { + const contentAttr = this.getAttribute("content"); + if (contentAttr) this.content = contentAttr; + super.connectedCallback(); + } + + show() { + // Restauramos o display pra que as classes do Bootstrap funcionem no host + this.style.display = "block"; + this.classList.add("alert", "alert-primary"); + this.setAttribute("role", "alert"); + + const content = this.content; + if (content) { + this.innerHTML = `${content}`; + } + } +} + +customElements.define("poc-alert", PocAlert); diff --git a/showcase/src/poc/poc-breadcrumb-item.tsx b/showcase/src/poc/poc-breadcrumb-item.tsx new file mode 100644 index 0000000..37113f3 --- /dev/null +++ b/showcase/src/poc/poc-breadcrumb-item.tsx @@ -0,0 +1,29 @@ +import { FastPocElement } from "./fast-poc-element"; + +export class PocBreadcrumbItem extends FastPocElement { + constructor() { + super(); + } + + connectedCallback() { + const contentAttr = this.getAttribute("content"); + if (contentAttr) this.content = contentAttr; + const linkAttr = this.getAttribute("link"); + if (linkAttr) this.link = linkAttr; + super.connectedCallback(); + } + + show() { + // Removemos o 'contents' pra ele virar um flex-item de verdade + this.style.display = "list-item"; + this.classList.add("breadcrumb-item"); + + const content = this.content; + const link = this.link; + if (content) { + this.innerHTML = link ? `${content}` : `${content}`; + } + } +} + +customElements.define("poc-breadcrumb-item", PocBreadcrumbItem); diff --git a/showcase/src/poc/poc-breadcrumb.tsx b/showcase/src/poc/poc-breadcrumb.tsx new file mode 100644 index 0000000..6daffa6 --- /dev/null +++ b/showcase/src/poc/poc-breadcrumb.tsx @@ -0,0 +1,20 @@ +import { FastPocElement } from "./fast-poc-element"; + +export class PocBreadcrumb extends FastPocElement { + private itemOl: HTMLElement | null = null; + + get contentChild() { + return (this.itemOl as unknown as ChildNode) || this.firstChild; + } + + show() { + this.innerHTML = ` + + `; + this.itemOl = this.querySelector("ol"); + } +} + +customElements.define("poc-breadcrumb", PocBreadcrumb); diff --git a/showcase/src/poc/poc.tsx b/showcase/src/poc/poc.tsx new file mode 100644 index 0000000..3bf399b --- /dev/null +++ b/showcase/src/poc/poc.tsx @@ -0,0 +1,4 @@ + +import "./poc-alert.tsx"; +import "./poc-breadcrumb.tsx"; +import "./poc-breadcrumb-item.tsx"; diff --git a/sidebar/sidebar.js b/sidebar/sidebar.js index 5f4c1b1..91cd866 100644 --- a/sidebar/sidebar.js +++ b/sidebar/sidebar.js @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2022 Flavio Gonçalves Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import {FazElementItem, FazReactItem} from "../item"; import React from 'react' diff --git a/src/app/global.ts b/src/app/global.ts index cb6d44c..e69de29 100644 --- a/src/app/global.ts +++ b/src/app/global.ts @@ -1,60 +0,0 @@ -/** - * Copyright 2018-2023 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { EditorView } from "@codemirror/view"; -import { - syntaxHighlighting, defaultHighlightStyle -} from "@codemirror/language"; -import { html } from "@codemirror/lang-html"; - -declare global { - interface Window { - codemirrorit: (id:string) => void; - } -} - -// TODO: Apply this theme https://palettes.shecodes.io/palettes/1313 -window.codemirrorit = function (id:string) { - let referenceNode = document.getElementById(id) || document.body; - - let theme = EditorView.theme({ - "&": { - color: "#ececec", - backgroundColor: "#142d4c" - }, - ".cm-content": { - caretColor: "#ececec" - }, - "&.cm-focused .cm-cursor": { - borderLeftColor: "#ececec" - }, - "&.cm-focused .cm-selectionBackground, ::selection": { - backgroundColor: "#074" - }, - ".cm-gutters": { - backgroundColor: "#045", - color: "#ddd", - border: "none" - } - }, { dark: true }); - - new EditorView({ - doc: referenceNode.innerHTML, - extensions: [ - html(),theme, syntaxHighlighting(defaultHighlightStyle) - ], - parent: referenceNode, - }); -} diff --git a/src/element-attributes.ts b/src/element-attributes.ts new file mode 100644 index 0000000..07a05fa --- /dev/null +++ b/src/element-attributes.ts @@ -0,0 +1,91 @@ + +import { FazElement } from "./element"; +import { JSX } from "solid-js"; + +export interface FazElementAttributes extends JSX.HTMLAttributes { + fazid?: string; + active?: boolean; + connected?: boolean; + content?: string; + debug?: boolean; + disabled?: boolean; + extraClasses?: string; + fazChildren?: FazElement[]; + loading?: boolean; + parent?: FazElement; + reload?: boolean; + link?: string; +} + +export type FazAttributeRole = + | "alert" + | "alertdialog" + | "application" + | "article" + | "banner" + | "button" + | "cell" + | "checkbox" + | "columnheader" + | "combobox" + | "complementary" + | "contentinfo" + | "definition" + | "dialog" + | "directory" + | "document" + | "feed" + | "figure" + | "form" + | "grid" + | "gridcell" + | "group" + | "heading" + | "img" + | "link" + | "list" + | "listbox" + | "listitem" + | "log" + | "main" + | "marquee" + | "math" + | "menu" + | "menubar" + | "menuitem" + | "menuitemcheckbox" + | "menuitemradio" + | "meter" + | "navigation" + | "none" + | "note" + | "option" + | "presentation" + | "progressbar" + | "radio" + | "radiogroup" + | "region" + | "row" + | "rowgroup" + | "rowheader" + | "scrollbar" + | "search" + | "searchbox" + | "separator" + | "slider" + | "spinbutton" + | "status" + | "switch" + | "tab" + | "table" + | "tablist" + | "tabpanel" + | "term" + | "textbox" + | "timer" + | "toolbar" + | "tooltip" + | "tree" + | "treegrid" + | "treeitem" + | undefined; diff --git a/src/element.ts b/src/element.ts new file mode 100644 index 0000000..fb1f604 --- /dev/null +++ b/src/element.ts @@ -0,0 +1,385 @@ + +import { FazAttributeRole } from "./element-attributes"; +import { randomId, toBoolean } from "./values"; +import { createSignal, createRoot, createEffect } from "solid-js"; +import { bindReactive } from "./reactivity"; + +// FazComment extends the standard Comment node to include FazElement reactivity. +export interface FazComment extends Comment { + fazElement: FazElement | undefined; +} + +// FazNode extends ChildNode to include FazElement reactivity. +export interface FazNode extends ChildNode { + fazElement: FazElement | undefined; +} + +// Main FazElement class, extends HTMLElement to provide custom logic and reactivity for web components. +export class FazElement extends HTMLElement { + + // Reactive properties for component state. + public active!: boolean; + public connected!: boolean; + public content: string|undefined; + public debug!: boolean; + public disabled: boolean|undefined; + public extraClasses!: string; + public fazChildren!: FazElement[]; + public fazElement: FazElement | undefined; + public fazRole: FazAttributeRole; + public idGenerated: boolean = false; + public loading!: boolean; + public parent: FazElement | undefined; + public reload!: boolean; + public link: string|undefined; + + // Prefix for children and rendered child tracking. + public childPrefix: string = ""; + public renderedChild: ChildNode | null = null; + private comment: FazComment | null = null; + public source: any; + private observer: MutationObserver | null = null; + private isMoving: boolean = false; + private hostInitialized: boolean = false; + + // Constructor initializes reactivity, attributes, and default state. + constructor() { + super(); + + const config = { + active: false, + connected: false, + content: undefined as string | undefined, + debug: false, + disabled: undefined as boolean | undefined, + extraClasses: "", + fazChildren: [] as FazElement[], + fazElement: undefined as FazElement | undefined, + fazRole: undefined as FazAttributeRole, + loading: true, + parent: undefined as FazElement | undefined, + reload: true, + link: undefined as string | undefined, + }; + + (Object.keys(config) as Array).forEach((key) => { + bindReactive(this, key as any, config[key]); + }); + + for (const attribute of this.attributes) { + switch (attribute.name.toLowerCase()) { + case "active": + this.active = toBoolean(attribute.value); + break; + case "class": + case "fazclass": + case "faz-class": + this.extraClasses = attribute.value; + break; + case "content": + this.content = attribute.value; + break; + case "debug": + this.debug = toBoolean(attribute.value); + break; + case "disabled": + this.disabled = toBoolean(attribute.value); + break; + case "id": + case "fazid": + case "faz-id": + this.id = attribute.value; + break; + case "href": + case "link": + this.link = attribute.value; + break; + case "role": + case "fazrole": + case "faz-role": + this.fazRole = attribute.value as FazAttributeRole; + break; + } + } + + this.childPrefix = "__child-prefix__"; + // If source is present, remove all child nodes (for virtualized or remote sourced components). + if (this.source) { + console.debug(`The element ${this.id} has a source attribute. All child nodes will be removed.`); + this.childNodes.forEach((node) => { + node.remove(); + }); + } + this.comment = (document.createComment(this.nodeName + " " + this.id) as FazComment); + bindReactive(this.comment, "fazElement", this); + } + + /** + * Initialize host DOM attributes after construction. + * + * Custom element constructors must not mutate attributes or children. + * Keep DOM-affecting setup in the connected lifecycle so elements created + * via document.createElement() can upgrade cleanly in browsers and jsdom. + */ + private initializeHost() { + if (this.hostInitialized) return; + + this.style.display = "contents"; + + if (!this.id) { + this.id = randomId(); + this.idGenerated = true; + } + + this.dataset['faz_element_item'] = this.tagName; + + if (this.comment) { + this.comment.data = this.nodeName + " " + this.id; + } + + this.hostInitialized = true; + } + + /** + * Set up a MutationObserver to handle dynamic DOM changes (e.g., HTMX). + */ + private setupMutationObserver() { + this.observer = new MutationObserver((mutations) => { + if (this.isMoving) return; + + let shouldUpdateChildren = false; + + for (const mutation of mutations) { + if (mutation.type === "childList") { + // Handle additions + if (mutation.addedNodes.length > 0) { + this.isMoving = true; + mutation.addedNodes.forEach((node) => { + if (node.parentElement === this && node !== this.comment && node !== this.contentChild) { + this.addChild(node); + } + }); + this.isMoving = false; + shouldUpdateChildren = true; + } + + // Handle removals + if (mutation.removedNodes.length > 0) { + shouldUpdateChildren = true; + } + } + } + + if (shouldUpdateChildren) { + this.updateFazChildren(); + } + }); + + this.observer.observe(this, { childList: true, subtree: true }); + } + + /** + * Updates the reactive fazChildren list by scanning current child nodes. + */ + private updateFazChildren() { + const items: FazElement[] = []; + // Deep scan for elements that are FazElements + const scan = (root: Node | null) => { + root?.childNodes.forEach((node) => { + if (node.nodeType === 1) { + const el = node as HTMLElement; + // Check if it's a FazElement (via our custom marker or duck typing) + if (el.dataset?.['faz_element_item'] || (el as any).fazChildren !== undefined) { + const item = el as unknown as FazElement; + item.parent = this as FazElement; + items.push(item); + } else { + // Only recurse if it's NOT a FazElement (to find nested ones in wrappers) + // If it IS a FazElement, its own observer will handle its children. + scan(node); + } + } + }); + }; + + scan(this); + this.fazChildren = items; + } + + /** + * The `disconnectedCallback` is a built-in lifecycle method of custom elements. + * It is called automatically by the browser when the element is removed from the DOM. + */ + disconnectedCallback() { + if (this.connected) { + this.observer?.disconnect(); + this.comment?.parentElement?.removeChild(this.comment); + this.disconnect(); + } + } + + /** + * Custom cleanup method for the component. + * Implement additional resource or event listener cleanups here as needed. + * Currently empty. + */ + disconnect() { + } + + // Check if a specific extra class is present. + hasExtraClass(value: string): boolean { + const extraClasses = this.extraClasses.trim().split(" "); + return extraClasses.find( + item => item == value.toLowerCase()) !== undefined; + } + + // Check if any extra classes are present. + hasExtraClasses(): boolean { + return this.extraClasses.trim().split(" ").length > 0; + } + + // Add a new extra class if not already present. + pushExtraClass(value: string) { + value = value.trim(); + if (!this.hasExtraClass(value)) { + const extraClasses = this.extraClasses.trim().split(" "); + extraClasses.push(value); + this.extraClasses = extraClasses.join(" "); + } + } + + // Resolve the link attribute, returning a void href if disabled or missing. + resolveLink(): string | undefined { + // From: https://stackoverflow.com/a/66717705/2887989 + let voidHref = "#!"; + const link = this.link; + if (this.disabled || link === undefined || link === "") { + return voidHref; + } + return this.link; + } + + // Add a FazElement child to the list of reactive children. + addFazChild(child: FazElement) { + if (this.fazChildren.indexOf(child) === -1) { + const children = [...this.fazChildren] as FazElement[]; + children.push(child); + this.fazChildren = children; + } + } + + // Remove a FazElement child from the reactive children array. + removeFazChild(child: FazElement) { + if (this.fazChildren.indexOf(child) !== -1) { + const children = [...this.fazChildren] as FazElement[]; + this.fazChildren = children.filter(i => i !== child); + } + } + + // Get all children that are currently active. + get activeFazChildren(): FazElement[] { + return this.fazChildren.filter(child => { + return child.active; + }) + } + + // Get the first child node (used as content root). + get contentChild(): ChildNode | null { + return this.firstChild; + } + + // Check if the link attribute is void (should not navigate). + get linkIsVoid() { + if (this.disabled) { + return true; + } + const linkResolved = this.resolveLink(); + return linkResolved === undefined || linkResolved === "" || linkResolved === "#" || linkResolved === "#!"; + } + + // Add a child node to the content container. + addChild(node: T): T { + const contentChild = this.contentChild; + if (contentChild && contentChild.nodeType === Node.ELEMENT_NODE) { + contentChild.appendChild(node); + } else { + this.appendChild(node); + } + return node; + } + + // Lifecycle hook, can be overridden by subclasses for logic after showing. + afterShow():void {} + + // Lifecycle hook, can be overridden by subclasses for logic before showing. + beforeShow():void {} + + // Remove and collect all children, update fazChildren list. + collectChildren() { + const children:Node[] = []; + const items: FazElement[] = []; + while(this.firstChild) { + const el = this.firstChild as HTMLElement; + if (this.firstChild.nodeType === 1 && (el.dataset?.['faz_element_item'] || (el as any).fazChildren !== undefined)) { + const item = this.firstChild as unknown as FazElement; + item.parent = this as FazElement; + items.push(item); + item.dataset['parent'] = this.id; + } + children.push(this.firstChild); + this.removeChild(this.firstChild); + } + if (items.length > 0) { + this.fazChildren = items; + } + return children; + } + + // Place previously collected children back into the DOM. + placeBackChildren(children: Node[]) { + children.forEach(child => { + this.addChild(child); + }); + } + + // Standard web component lifecycle method: called when element is inserted + // into the DOM. + connectedCallback() { + this.initializeHost(); + + // Insert the comment node as a placeholder. + if (this.comment){ + this.before(this.comment); + } + + this.setupMutationObserver(); + + // Defer rendering and state updates until the next microtask to ensure + // all child custom elements are upgraded. + // This is necessary because, during connectedCallback, child elements + // may not be fully constructed or upgraded yet. + Promise.resolve().then(()=> { + if (this.loading) { + this.render(); + } + this.connected = true; + this.loading = false; + }); + } + + // Lifecycle method to be overridden for loading logic. + load() {} + + // Lifecycle method to be overridden for showing logic. + show() {} + + // Main render method: load data, prepare, manipulate, and restore children. + render() { + this.load(); + this.beforeShow(); + const children = this.collectChildren(); + this.show(); + this.placeBackChildren(children); + this.afterShow(); + } +} diff --git a/src/form.tsx b/src/form.tsx index 198139d..f521229 100644 --- a/src/form.tsx +++ b/src/form.tsx @@ -1,42 +1,89 @@ -/** - * Copyright 2018-2023 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { FazElementItem } from "./item"; -import { Accessor, createSignal, Setter} from "solid-js"; + +import { FazElement } from "./element"; +import { bindReactive } from "./reactivity"; -export class FazFormElement extends FazElementItem { +export class FazFormElement extends FazElement { - public action: Accessor; - public setAction: Setter; + public action: string|undefined; + public errors!: Record; + public method!: string; - public errors: Accessor>; - public setErrors: Setter>; + constructor() { + super(); + const config = { + action: undefined as string | undefined, + errors: {} as Record, + method: "get", + }; - public method: Accessor; - public setMethod: Setter; + (Object.keys(config) as Array).forEach((key) => { + bindReactive(this, key as any, config[key]); + }); - hasErrors() { - return this.errors().length > 0; + for (const attribute of this.attributes) { + switch (attribute.name.toLowerCase()) { + case "action": + this.action = attribute.value; + break; + case "method": + this.method = attribute.value; + break; + } + } + } + + get form(): HTMLFormElement|undefined { + return undefined } - constructor() { - super(); - [this.action, this.setAction] = createSignal(null); - [this.errors, this.setErrors] = createSignal>([]); - [this.method, this.setMethod] = createSignal("get"); + get values(): Record { + const values: Record = {}; + if (this.form === undefined) { + return values; + } + const formData = new FormData(this.form); + for (const [key, value] of formData.entries()) { + values[key] = value; + } + return values; + } + + public clearErrorsFor(key: string) { + const errors = { ...this.errors }; + if (key in errors) { + delete errors[key]; + } + this.errors = errors; + } + + public clearErrors() { + this.errors = {}; + } + + public hasErrorsFor(key: string): boolean { + return key in this.errors && this.errors[key].length > 0; + } + + public hasErrors(): boolean { + return Object.values(this.errors).some(errors => errors.length > 0); + } + + public getErrorsFor(key: string): string[] { + return this.errors[key] || []; + } + + public pushError(key: string, value: string) { + value = value.trim(); + if (value) { + const errors = { ...this.errors }; + if (!errors[key]) { + errors[key] = []; + } + if (!errors[key].includes(value)) { + errors[key].push(value); + } + this.errors = errors; + } } } diff --git a/src/id.ts b/src/id.ts deleted file mode 100644 index 11c2a01..0000000 --- a/src/id.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright 2018-2023 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export function randomId() { - // SEE: https://gist.github.com/gordonbrander/2230317 - // Math.random should be unique because of its seeding algorithm. - // Convert it to base 36 (numbers + letters), and grab the first - // 9 characters - // after the decimal. - return "_" + Math.random().toString(36).substring(2, 9); -} diff --git a/src/index.ts b/src/index.ts index e00724a..63daddc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,20 +1,7 @@ -/** - * Copyright 2018-2024 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export { randomId } from "./id"; +export { FazElement } from "./element"; +export type { FazElementAttributes } from "./element-attributes"; export { FazFormElement } from "./form"; -export { FazElementItem } from "./item"; -export { toBoolean } from "./values"; +export { randomId, toBoolean } from "./values"; +export { bindReactive } from "./reactivity"; +export { FazPaginator } from "./paginator"; diff --git a/src/item.ts b/src/item.ts deleted file mode 100644 index 4a7eca2..0000000 --- a/src/item.ts +++ /dev/null @@ -1,388 +0,0 @@ -/** - * Copyright 2018-2024 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { randomId } from "./id"; -import { toBoolean } from "./values"; - - -class FazNode extends Node { - public fazElement: FazElementItem | null = null; -} - -export class FazElementItem extends HTMLElement { - private _active: boolean = false; - private _content: string | null = null; - private _disabled: boolean = false; - private _extraClasses: string = ""; - private _items: Array = new Array(); - private _loading: boolean = true; - private _parent: FazElementItem | null = null; - private _reload: boolean = false; - private _link: string | null = null; - - public childPrefix: string = ""; - private connected: boolean = false; - public debug: boolean = false; - public renderedChild: ChildNode | null = null; - private initialOuterHTML: string = ""; - private comment: Comment | null = null; - public source: any; - - constructor() { - super(); - this.initialOuterHTML = this.outerHTML; - if (!this.id) { - this.id = randomId(); - } - for (const attribute of this.attributes) { - switch (attribute.name.toLowerCase()) { - case "active": - this._active = toBoolean(attribute.value); - break; - case "class": - case "faz-class": - this._extraClasses = attribute.value; - break; - case "content": - this._content = attribute.value; - break; - case "disabled": - this._disabled = toBoolean(attribute.value); - break; - case "id": - case "fazid": - case "faz-id": - this.id = attribute.value; - break; - case "href": - case "link": - this._link = attribute.value; - break; - } - } - this.dataset['faz_element_item'] = this.tagName; - this.childPrefix = "__child-prefix__"; - if (this.source) { - console.debug( - "The element" + - this.id + - " has a source " + - "attribute. All child nodes will be removed." - ); - this.childNodes.forEach((node) => { - node.remove(); - }); - } - this.comment = document.createComment(this.nodeName + " " + this.id); - this.before(this.comment); - } - - protected createEvent(eventName: string, value: any, - oldValue: any): CustomEvent { - return new CustomEvent(eventName, { - bubbles: true, - detail: { - value: value, - oldValue: oldValue, - }, - }); - } - - get active(): boolean { - return this._active; - } - - set active(value: boolean) { - if (this._active !== value) { - const oldValue = this._active; - this._active = value; - if (!this.loading) { - const event = this.createEvent("activechanged", value, - oldValue); - this.dispatchEvent(event); - this.onActiveChanged(event); - } - } - } - - onActiveChanged(event: CustomEvent) {} - - get content(): string | null { - return this._content; - } - - set content(value: string | null) { - if (this._content !== value) { - const oldValue = this._content; - this._content = value; - if (!this.loading) { - const event = this.createEvent("contentchanged", value, - oldValue); - this.dispatchEvent(event); - this.onContentChanged(event); - } - } - } - - onContentChanged(event: CustomEvent) {} - - get disabled(): boolean { - return this._disabled; - } - - set disabled(value: boolean) { - if (this._disabled !== value) { - const oldValue = this._disabled; - this._disabled = value; - if (!this.loading) { - const event = this.createEvent("disabledchanged", value, - oldValue); - this.dispatchEvent(event); - this.onDisabledChanged(event); - } - } - } - - onDisabledChanged(event: CustomEvent) {} - - get extraClasses(): string { - return this._extraClasses; - } - - set extraClasses(value: string) { - if (this._extraClasses !== value) { - const oldValue = this._extraClasses; - this._extraClasses = value; - if (!this.loading) { - const event = this.createEvent("extraclasseschanged", value, - oldValue); - this.dispatchEvent(event); - this.onExtraClassesChanged(event); - } - } - } - - onExtraClassesChanged(event: CustomEvent) {} - - get link() { - // From: https://stackoverflow.com/a/66717705/2887989 - let voidHref = "#!"; - if (this.disabled || this._link === null || this._link === "") { - return voidHref; - } - return this._link; - } - - set link(value: string) { - if (this._link !== value) { - const oldValue = this._link; - this._link = value; - if (!this.loading) { - const event = this.createEvent("linkchanged", value, oldValue); - this.dispatchEvent(event); - this.onLinkChanged(event); - } - } - } - - onLinkChanged(event: CustomEvent) {} - - get parent(): FazElementItem | null { - return this._parent; - } - - set parent(value: FazElementItem | null) { - if (this._parent !== value) { - const oldValue = {...this._parent} as FazElementItem | null; - this._parent = value; - if (!this.loading) { - const event = this.createEvent("parentchanged", value, - oldValue); - this.dispatchEvent(event); - this.onParentChanged(event); - } - } - } - - onParentChanged(event: CustomEvent) {} - - get items(): Array { - return this._items; - } - - addItem(item: FazElementItem) { - if (this._items.indexOf(item) === -1) { - const oldItems = {...this._items} as Array; - this._items.push(item); - if (!this.loading) { - const event = this.createEvent("itemschanged", this._items, - oldItems); - this.dispatchEvent(event); - this.onItemsChanged(event); - } - } - } - - removeItem(item: FazElementItem) { - if (this._items.indexOf(item) !== -1) { - const oldItems = {...this._items} as Array; - this._items = this._items.filter(_item => _item !== item); - if (!this.loading) { - const event = this.createEvent("itemschanged", this._items, - oldItems); - this.dispatchEvent(event); - this.onItemsChanged(event); - } - } - } - - setItems(items: Array) { - const oldItems = {...this._items} as Array; - this._items = items; - if (!this.loading) { - const event = this.createEvent("itemschanged", this._items, - oldItems); - this.dispatchEvent(event); - this.onItemsChanged(event); - } - } - - onItemsChanged(event: CustomEvent) {} - - get loading(): boolean { - return this._loading; - } - - set loading(value: boolean) { - if (this._loading !== value) { - const oldValue = this._loading; - this._loading = value; - const event = this.createEvent("loadingchanged", value, oldValue); - this.dispatchEvent(event); - this.onLoadingChanged(event); - } - } - - onLoadingChanged(event: CustomEvent) {} - - get reload(): boolean { - return this._reload; - } - - set reload(value: boolean) { - if (this._reload !== value) { - const oldValue = this._reload; - this._reload = value; - const event = this.createEvent("reloadchanged", value, oldValue); - this.dispatchEvent(event); - this.onReloadChanged(event); - } - } - - onReloadChanged(event: CustomEvent) {} - - get activeItems() { - return this.items.filter(item => { - return item.active; - }) - } - - - get childId() { - return this.childPrefix.concat("-", this.id); - } - - get contentChild(): ChildNode | null { - return this.firstChild; - } - - get linkIsVoid() { - if (this.disabled) { - return true; - } - return this._link === null || this._link === "" || - this._link === "#" || this._link === "#!"; - } - - addChild(node: T): T { - this.contentChild?.appendChild(node) - return node; - } - - afterShow(children:Node[]) { - if (this.loading) { - children.forEach(child => { - this.addChild(child); - }); - } - } - - beforeShow():void {} - - collectChildren() { - const children:Node[] = []; - const items: FazElementItem[] = []; - if (this.loading) { - while(this.firstChild) { - if (this.firstChild instanceof FazElementItem) { - const item = this.firstChild as FazElementItem; - item.parent = this; - items.push(item); - item.dataset['parent'] = this.id; - } - children.push(this.firstChild); - this.removeChild(this.firstChild); - } - if (items.length > 0) { - this.setItems(items); - } - } - return children; - } - - connectedCallback() { - this.render(); - this.connected = true; - } - - load() {} - - show() {} - - render() { - new Promise((resolve) => { - setTimeout(()=>resolve(null), 0); - }).then(()=> { - this.load(); - this.beforeShow(); - const children = this.collectChildren(); - if (this.loading) { - this.show(); - } - this.afterShow(children); - this.loading = false; - }); - } - - cleanFazTag() { - let parentElement = this.parentElement - this.childNodes.forEach((node) => { - ((node as unknown) as FazNode).fazElement = this; - this.before(node); - }); - parentElement?.removeChild(this); - } -} diff --git a/src/paginator.ts b/src/paginator.ts new file mode 100644 index 0000000..2981f52 --- /dev/null +++ b/src/paginator.ts @@ -0,0 +1,188 @@ + +import { bindReactive } from "./reactivity"; + +/** + * FazPaginator is a pagination utility class built for use with Solid.js + * reactive primitives. + * It manages page, block, and record calculations for paginated collections, + * offering helpers for navigation, state, and boundary conditions. + */ +export class FazPaginator { + + // Number of total records/items + public count!: number; + + // Current page number + public page!: number; + + // Number of pages per block + public perBlock!: number; + + // Number of records per page + public perPage!: number; + + constructor() { + bindReactive(this, "count", 0); + bindReactive(this, "page", 1); + bindReactive(this, "perBlock", 10); + bindReactive(this, "perPage", 10); + } + + /** + * Returns the total number of blocks needed for the current settings. + */ + get blocks(): number { + const blocksFloor = Math.floor(this.pages / this.perBlock); + const reminder = this.pages % this.perBlock > 0 ? 1 : 0; + return blocksFloor + reminder; + } + + /** + * Returns the total number of pages based on count and perPage. + */ + get pages(): number { + if (this.count === 0) { + return 1; + } + const pagesFloor = Math.floor(this.count / this.perPage); + let remainder = this.count % this.perPage; + remainder = remainder > 0 ? 1 : 0; + return pagesFloor + remainder; + } + + /** + * Returns a 'safe' current page value, always in the valid range. + * Adjusts the page if it's out of bounds. + */ + get safePage(): number { + if (this.page < 1) { + this.page = 1; + } + if (this.pages < this.page) { + this.page = this.pages; + } + return this.page; + } + + /** + * Returns the current block number (1-based) for the current page. + */ + get block(): number { + if (this.safePage <= this.perBlock) { + return 1; + } + const currentBlockFloor = Math.floor(this.safePage / this.perBlock); + const remainder = this.safePage % this.perBlock; + const addRemainder = remainder > 0 ? 1 : 0; + return currentBlockFloor + addRemainder; + } + + /** + * Returns the first page number in the current block. + */ + get currentFirstPage(): number { + return (this.block * this.perBlock) - this.perBlock + 1; + } + + /** + * Returns the last page number in the current block. + * Handles the last block which may have fewer pages. + */ + get currentLastPage() { + if (this.isLastBlock) { + return this.currentFirstPage + this.pagesInLastBlock - 1; + } + return this.block * this.perBlock; + } + + /** + * Returns the number of pages in the last block. + */ + get pagesInLastBlock(): number { + let lastBlockRemainder = this.pages % this.perBlock; + return lastBlockRemainder > 0 ? lastBlockRemainder : this.perBlock; + } + + /** + * Returns an array of page numbers in the current block. + */ + get blockPages(): number[] { + let pages = this.isLastBlock ? this.pagesInLastBlock : this.perBlock; + return Array(pages).fill(undefined).map((_, i) => i + this.currentFirstPage); + } + + /** + * Checks if a given page is the current page. + * @param page Page number to check + */ + isCurrentPage(page: number): boolean { + return page === this.safePage; + } + + /** + * Is the current page the first page? + */ + get isFirstPage() { + return this.safePage === 1 + } + + /** + * Is the current block the first block? + */ + get isFirstBlock() { + return this.block === 1; + } + + /** + * Is the current page the last page? + */ + get isLastPage() { + return this.safePage >= this.pages; + } + + /** + * Is the current block the last block? + */ + get isLastBlock() { + return this.block >= this.blocks; + } + + /** + * Does the pagination have multiple pages? + */ + get hasMultiplePages() { + return this.pages > 1; + } + + /** + * Does the pagination have multiple blocks? + */ + get hasMultipleBlocks() { + return this.blocks > 1; + } + + /** + * Returns the number of records in the last page. + */ + get recordsInLastPage() { + let lastPageRemainder = this.count % this.perPage; + return lastPageRemainder > 0 ? lastPageRemainder : this.perPage; + } + + /** + * Returns the absolute index of the first record on the current page. + */ + get firstRecord() { + return (this.safePage * this.perPage) - this.perPage + 1; + } + + /** + * Returns the absolute index of the last record on the current page. + */ + get lastRecord() { + if (this.isLastPage) { + return this.firstRecord + this.recordsInLastPage - 1; + } + return this.safePage * this.perPage; + } +} diff --git a/src/reactivity.ts b/src/reactivity.ts new file mode 100644 index 0000000..3101567 --- /dev/null +++ b/src/reactivity.ts @@ -0,0 +1,25 @@ + +import { createSignal } from "solid-js"; + +/** + * Binds a SolidJS signal to an object property, making it reactive. + * This is a decomposed approach that avoids boilerplate and strings-only APIs. + * + * @param target The object to define the property on. + * @param key The key of the property. + * @param initialValue The initial value for the signal. + */ +export function bindReactive( + target: T, + key: K, + initialValue: T[K] +) { + const [getter, setter] = createSignal(initialValue); + + Object.defineProperty(target, key, { + get: () => getter(), + set: (val: T[K]) => setter(() => val), + enumerable: true, + configurable: true + }); +} diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 0000000..4df16f7 --- /dev/null +++ b/src/test.ts @@ -0,0 +1,20 @@ + +import { FazComment } from "./element"; + +// SEE: https://stackoverflow.com/a/25388984/2887989 +export function allComments(context: any): FazComment[] { + const commentsFound = []; + const elementPath = [context]; + while (elementPath.length > 0) { + const el = elementPath.pop(); + for (let i = 0; i < el.childNodes.length; i++) { + const node = el.childNodes[i]; + if (node.nodeType === Node.COMMENT_NODE) { + commentsFound.push(node); + } else { + elementPath.push(node); + } + } + } + return commentsFound; +} diff --git a/src/types/index.d.ts b/src/types/index.d.ts deleted file mode 100644 index a9d2aeb..0000000 --- a/src/types/index.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -// See: https://cutt.ly/RwyeQ7ZT - -export { randomId } from "../id"; -export { FazFormElement } from "../form"; -export { FazElementItem } from "../item"; -export { toBoolean } from "../values"; - -interface FazElementItem extends HTMLElement { - fazid: string; -} - -interface FazElementItemAttributes extends HTMLAttributes { - fazid?: string; -} - -interface FazNavElement extends FazElementItem { -} - -declare global { - declare module "solid-js" { - namespace JSX { - interface IntrinsicElements { - 'faz-nav': FazElementItemAttributes; - 'faz-nav-item': HTMLDivElement; - } - } - } -} diff --git a/src/values.ts b/src/values.ts index 6bd20a7..1224cfe 100644 --- a/src/values.ts +++ b/src/values.ts @@ -1,18 +1,3 @@ -/** - * Copyright 2018-2024 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ export function toBoolean(value: string | null): boolean { if (value === null) { @@ -20,3 +5,12 @@ export function toBoolean(value: string | null): boolean { } return value.toLowerCase() === "true"; } + +export function randomId() { + // SEE: https://gist.github.com/gordonbrander/2230317 + // Math.random should be unique because of its seeding algorithm. + // Convert it to base 36 (numbers + letters), and grab the first + // 9 characters + // after the decimal. + return "_" + Math.random().toString(36).substring(2, 11); +} diff --git a/test/element.test.tsx b/test/element.test.tsx new file mode 100644 index 0000000..4f83d22 --- /dev/null +++ b/test/element.test.tsx @@ -0,0 +1,132 @@ + +import { FazElement } from "../src/element"; +import { afterEach, beforeEach, describe, expect, test, vitest } from "vitest"; +import { createEffect, createRoot } from "solid-js"; +import { render} from "solid-js/web"; +import { allComments} from "../src/test"; + +class TestElement extends FazElement { + + public doActiveChanged: boolean = false; + public doDisabledChanged: boolean = false; + public doExtraClassesChanged: boolean = false; + + constructor() { + super(); + this.disabled = false; + createRoot(() => { + createEffect((prevActive) => { + if (this.active != prevActive) { + this.doActiveChanged = true; + } + }, false); + + createEffect((prevDisabled) => { + if (this.disabled != prevDisabled) { + this.doDisabledChanged = true; + } + }, false); + + createEffect((prevExtraClasses) => { + if (this.extraClasses != prevExtraClasses) { + this.doExtraClassesChanged = true; + } + }, "aclass"); + }); + } + + show() { + render(() =>
    , this); + } +} + +customElements.define("faz-test-element", TestElement); + +describe("Test Element", () => { + const theText = "A text"; + beforeEach(() => { + vitest.useFakeTimers(); + }); + afterEach(() => { + vitest.useRealTimers(); + }); + test("Properties changed", () => { + document.body.innerHTML = ` + + + ${theText} + + + Another inner + + + `; + const comments = allComments(document.body); + const [outerElementComment, innerElementComment, anotherInnerElementComment] = comments; + const outerElement = outerElementComment.fazElement as TestElement; + const innerElement = innerElementComment.fazElement as TestElement; + const anotherInnerElement = anotherInnerElementComment.fazElement as TestElement; + outerElement.active = true; + outerElement.disabled = true; + expect(outerElement.idGenerated).toBeFalsy(); + expect(innerElement.idGenerated).toBeFalsy(); + expect(anotherInnerElement.idGenerated).toBeTruthy(); + expect(outerElement.fazRole).toBe("list"); + expect(innerElement.fazRole).toBe("listitem"); + expect(anotherInnerElement.fazRole).toBe("listitem"); + expect(outerElement.doActiveChanged).toBeTruthy(); + expect(outerElement.doDisabledChanged).toBeTruthy(); + expect(outerElement.doExtraClassesChanged).toBeFalsy(); + outerElement.extraClasses = "aclass"; + expect(outerElement.doExtraClassesChanged).toBeFalsy(); + outerElement.extraClasses = "aclass bclass"; + expect(outerElement.doExtraClassesChanged).toBeTruthy(); + outerElement.doExtraClassesChanged = false; + outerElement.extraClasses = "bclass aclass"; + expect(outerElement.doExtraClassesChanged).toBeTruthy(); + outerElement.doExtraClassesChanged = false; + outerElement.extraClasses = "bclass aclass "; + expect(outerElement.doExtraClassesChanged).toBeTruthy(); + outerElement.doExtraClassesChanged = false; + outerElement.extraClasses = " bclass aclass"; + expect(outerElement.doExtraClassesChanged).toBeTruthy(); + outerElement.doExtraClassesChanged = false; + outerElement.extraClasses = " bclass aclass "; + expect(outerElement.doExtraClassesChanged).toBeTruthy(); + outerElement.doExtraClassesChanged = false; + outerElement.extraClasses = "bclass aclass cclass"; + expect(outerElement.doExtraClassesChanged).toBeTruthy(); + outerElement.doExtraClassesChanged = false; + outerElement.pushExtraClass("aclass"); + outerElement.pushExtraClass("bclass "); + outerElement.pushExtraClass(" cclass"); + outerElement.pushExtraClass(" aclass "); + expect(outerElement.doExtraClassesChanged).toBeFalsy(); + outerElement.pushExtraClass("eclass"); + expect(outerElement.doExtraClassesChanged).toBeTruthy(); + outerElement.active = false; + outerElement.disabled = undefined; + expect(innerElement.doActiveChanged).toBeFalsy(); + expect(innerElement.doDisabledChanged).toBeFalsy(); + }); + + test("Tag rendered", async () => { + document.body.innerHTML = ` + + + ${theText} + + + `; + await vitest.runAllTimersAsync(); + const outerElement = document.getElementById("outer") as unknown as FazElement; + const innerElement = document.getElementById("inner") as unknown as FazElement; + const outerDiv = outerElement.contentChild; + const innerDiv = innerElement.contentChild; + expect(outerElement?.fazChildren.length).toBe(1); + expect(outerElement?.fazChildren[0]).toBe(innerElement); + expect(innerElement?.parent).toBe(outerElement); + expect((outerDiv as unknown as Element).tagName).toBe("DIV"); + expect((innerDiv as unknown as Element).tagName).toBe("DIV"); + }); +}); diff --git a/test/form.test.tsx b/test/form.test.tsx new file mode 100644 index 0000000..ec7729f --- /dev/null +++ b/test/form.test.tsx @@ -0,0 +1,62 @@ + +import { FazFormElement } from "../src/form"; +import { allComments} from "../src/test"; +import { JSX } from "solid-js/jsx-runtime"; +import { render } from "solid-js/web"; +import { afterEach, beforeEach, describe, expect, test, vitest } from "vitest"; + +class TestForm extends FazFormElement { + + public testForm: JSX.Element; + + constructor() { + super(); + } + + get form(): HTMLFormElement|undefined { + return this.testForm as HTMLFormElement; + } + + show() { + this.testForm =
    ; + render(() => this.testForm, this); + } +} + +customElements.define("test-form", TestForm); + + beforeEach(() => { + vitest.useFakeTimers(); + }); + afterEach(() => { + vitest.useRealTimers(); + }); + +describe("Test Forms", () => { + test("Form errors", async() => { + document.body.innerHTML = ` + + + + + `; + const [formComment] = allComments(document.body); + const form = formComment.fazElement as FazFormElement; + await vitest.runAllTimersAsync(); + expect(form.hasErrors()).toBeFalsy(); + form.pushError("field1", "error 1"); + form.pushError("field1", "error 1"); + form.pushError("field1", "error 2"); + form.pushError("field2", "errrr 1"); + expect(form.hasErrors()).toBeTruthy(); + expect(form.hasErrorsFor("field1")).toBeTruthy(); + expect(form.hasErrorsFor("field2")).toBeTruthy(); + expect(form.hasErrorsFor("field3")).toBeFalsy(); + expect(form.getErrorsFor("field1").length).toBe(2); + expect(form.getErrorsFor("field2").length).toBe(1); + form.clearErrors(); + expect(form.hasErrors()).toBeFalsy(); + expect(form.form).toStrictEqual((form as TestForm).testForm); + expect(form.values).toStrictEqual({ input1: '1', input2: '2' }); + }); +}); diff --git a/test/item.test.ts b/test/item.test.ts deleted file mode 100644 index cf0980f..0000000 --- a/test/item.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { FazElementItem } from "../src/item"; -import { describe, expect, test, jest } from "@jest/globals"; -import { screen, waitFor } from "@testing-library/dom"; - -class TestElement extends FazElementItem { - - public doActiveChanged: boolean = false; - public doDisabledChanged: boolean = false; - - constructor() { - super(); - // Add an event listener to catch a faz element property change. - this.addEventListener("activechanged", (_) => - this.doActiveChanged = true); - } - - // Or override the event method to catch a faz element property change. - // This is preferred for the end user(developer), if you are creating a - // component it is preferred to use the addEventListener method. - onDisabledChanged(_: Event) { - this.doDisabledChanged = true; - } - - show() { - const innerDiv = document.createElement("div"); - innerDiv.dataset.testid = "rendered_div_" + this.id; - this.appendChild(innerDiv); - } -} - -customElements.define("faz-test-element", TestElement); - -describe("Test Element", () => { - const theText = "A text"; - beforeEach(() => { - jest.useFakeTimers(); - }); - afterEach(() => { - jest.useRealTimers(); - }); - test("Changed properties", async() => { - document.body.innerHTML = ` - - - ${theText} - - - `; - jest.runAllTimers(); - await waitFor(() => {}).then(() => { - const outerElement = screen.queryByTestId( - "outer_element") as TestElement; - const innerElement = screen.queryByTestId( - "inner_element") as TestElement; - outerElement.active = true; - outerElement.disabled = true; - expect(outerElement.doActiveChanged).toBeTruthy(); - expect(outerElement.doDisabledChanged).toBeTruthy(); - outerElement.active = false; - outerElement.disabled = false; - expect(innerElement.doActiveChanged).toBeFalsy(); - expect(innerElement.doDisabledChanged).toBeFalsy(); - }); - }); - - test("Renderend tag", async () => { - document.body.innerHTML = ` - - - ${theText} - - - `; - jest.runAllTimers(); - await waitFor(() => { - expect( - screen.queryByTestId("rendered_div_outer")?.tagName - ).toBe("DIV"); - }); - }); -}); diff --git a/test/mutation.test.ts b/test/mutation.test.ts new file mode 100644 index 0000000..140ade6 --- /dev/null +++ b/test/mutation.test.ts @@ -0,0 +1,79 @@ + +import { describe, expect, test, vitest, beforeEach, afterEach } from "vitest"; +import { FazElement } from "../src/element"; + +// A simple component to test mutations +class MutationTestElement extends FazElement { + show() { + this.style.display = "block"; + this.innerHTML = `
    `; + } + + get contentChild() { + return this.querySelector(".content-root") as ChildNode; + } +} + +if (!customElements.get("mutation-test-element")) { + customElements.define("mutation-test-element", MutationTestElement); +} + +describe("MutationObserver (HTMX Compatibility)", () => { + beforeEach(() => { + document.body.innerHTML = ""; + }); + + test("should detect and move new children added via innerHTML (HTMX append)", async () => { + document.body.innerHTML = ``; + + // Wait for upgrade + await new Promise(resolve => setTimeout(resolve, 50)); + const parent = document.getElementById("parent") as MutationTestElement; + + parent.innerHTML += `
    I am new
    `; + + // Wait for MutationObserver + await new Promise(resolve => setTimeout(resolve, 100)); + + const newChild = document.getElementById("new-child"); + const contentRoot = parent.querySelector(".content-root"); + + expect(newChild?.parentElement).toBe(contentRoot); + }); + + test("should update fazChildren when a FazElement is added", async () => { + document.body.innerHTML = ``; + await new Promise(resolve => setTimeout(resolve, 50)); + const parent = document.getElementById("parent") as MutationTestElement; + + const child = document.createElement("mutation-test-element"); + child.id = "child"; + parent.appendChild(child); + + // Wait for MutationObserver + await new Promise(resolve => setTimeout(resolve, 100)); + + expect(parent.fazChildren.length).toBe(1); + expect(parent.fazChildren[0]).toBe(child); + }); + + test("should update fazChildren when a child is removed", async () => { + document.body.innerHTML = ` + + + + `; + await new Promise(resolve => setTimeout(resolve, 50)); + const parent = document.getElementById("parent") as MutationTestElement; + const child = document.getElementById("child") as MutationTestElement; + + expect(parent.fazChildren.length).toBe(1); + + child.remove(); + + // Wait for MutationObserver + await new Promise(resolve => setTimeout(resolve, 100)); + + expect(parent.fazChildren.length).toBe(0); + }); +}); diff --git a/test/paginator.test.ts b/test/paginator.test.ts new file mode 100644 index 0000000..89b6e4e --- /dev/null +++ b/test/paginator.test.ts @@ -0,0 +1,143 @@ + +import { FazPaginator } from "../src/paginator"; +import { describe, expect, test } from "vitest"; + +describe("Test Paginator", () => { + test("One page", () => { + const paginator = new FazPaginator(); + paginator.count = 10; + expect(paginator.pages).toBe(1); + expect(paginator.blocks).toBe(1); + + expect(paginator.page).toBe(1); + expect(paginator.safePage).toBe(1); + expect(paginator.block).toBe(1); + expect(paginator.isLastPage).toBeTruthy(); + expect(paginator.isLastBlock).toBeTruthy(); + paginator.page = 0; + expect(paginator.safePage).toBe(1); + expect(paginator.page).toBe(1); + expect(paginator.isLastPage).toBeTruthy(); + expect(paginator.isLastBlock).toBeTruthy(); + expect(paginator.firstRecord).toBe(1); + expect(paginator.lastRecord).toBe(10); + expect(paginator.recordsInLastPage).toBe(10); + paginator.page = 2; + expect(paginator.safePage == 2).toBeFalsy(); + expect(paginator.page == 2).toBeFalsy(); + expect(paginator.safePage).toBe(1); + expect(paginator.page).toBe(1); + expect(paginator.block).toBe(1); + expect(paginator.hasMultiplePages).toBeFalsy(); + expect(paginator.hasMultipleBlocks).toBeFalsy(); + expect(paginator.isLastPage).toBeTruthy(); + expect(paginator.isLastBlock).toBeTruthy(); + expect(paginator.pagesInLastBlock).toBe(1); + expect(paginator.firstRecord).toBe(1); + expect(paginator.lastRecord).toBe(10); + expect(paginator.recordsInLastPage).toBe(10); + }); + test("More than one page, one block", () => { + const paginator = new FazPaginator(); + paginator.count = 91; + expect(paginator.blocks).toBe(1); + expect(paginator.pages).toBe(10); + + expect(paginator.page).toBe(1); + expect(paginator.safePage).toBe(1); + expect(paginator.block).toBe(1); + expect(paginator.isFirstPage).toBeTruthy(); + expect(paginator.isLastPage).toBeFalsy(); + expect(paginator.isLastBlock).toBeTruthy(); + expect(paginator.firstRecord).toBe(1); + expect(paginator.lastRecord).toBe(10); + paginator.page = 2; + expect(paginator.safePage).toBe(2); + expect(paginator.page).toBe(2); + expect(paginator.block).toBe(1); + expect(paginator.isFirstPage).toBeFalsy(); + expect(paginator.isLastPage).toBeFalsy(); + expect(paginator.isLastBlock).toBeTruthy(); + expect(paginator.firstRecord).toBe(11); + expect(paginator.lastRecord).toBe(20); + paginator.page = 8; + expect(paginator.safePage).toBe(8); + expect(paginator.page).toBe(8); + expect(paginator.block).toBe(1); + expect(paginator.isFirstPage).toBeFalsy(); + expect(paginator.isLastPage).toBeFalsy(); + expect(paginator.isLastBlock).toBeTruthy(); + expect(paginator.hasMultiplePages).toBeTruthy(); + expect(paginator.hasMultipleBlocks).toBeFalsy(); + expect(paginator.firstRecord).toBe(71); + expect(paginator.lastRecord).toBe(80); + paginator.page = 10; + expect(paginator.isFirstPage).toBeFalsy(); + expect(paginator.isLastPage).toBeTruthy(); + expect(paginator.isLastBlock).toBeTruthy(); + expect(paginator.safePage).toBe(10); + expect(paginator.page).toBe(10); + expect(paginator.block).toBe(1); + expect(paginator.firstRecord).toBe(91); + expect(paginator.lastRecord).toBe(91); + expect(paginator.recordsInLastPage).toBe(1); + expect(paginator.pagesInLastBlock).toBe(10); + }); + test("More than one page, more than one block", () => { + const paginator = new FazPaginator(); + paginator.count = 340; + expect(paginator.pages).toBe(34); + expect(paginator.blocks).toBe(4); + + expect(paginator.page).toBe(1); + expect(paginator.safePage).toBe(1); + expect(paginator.block).toBe(1); + expect(paginator.isLastPage).toBeFalsy(); + expect(paginator.isLastBlock).toBeFalsy(); + expect(paginator.firstRecord).toBe(1); + expect(paginator.lastRecord).toBe(10); + paginator.page = 11; + expect(paginator.isLastPage).toBeFalsy(); + expect(paginator.isLastBlock).toBeFalsy(); + expect(paginator.safePage).toBe(11); + expect(paginator.page).toBe(11); + expect(paginator.block).toBe(2); + expect(paginator.firstRecord).toBe(101); + expect(paginator.lastRecord).toBe(110); + paginator.page = 25; + expect(paginator.isLastPage).toBeFalsy(); + expect(paginator.isLastBlock).toBeFalsy(); + expect(paginator.safePage).toBe(25); + expect(paginator.page).toBe(25); + expect(paginator.block).toBe(3); + expect(paginator.firstRecord).toBe(241); + expect(paginator.lastRecord).toBe(250); + paginator.page = 32; + expect(paginator.isLastPage).toBeFalsy(); + expect(paginator.isLastBlock).toBeTruthy(); + expect(paginator.pagesInLastBlock).toBe(4); + expect(paginator.safePage).toBe(32); + expect(paginator.page).toBe(32); + expect(paginator.block).toBe(4); + expect(paginator.firstRecord).toBe(311); + expect(paginator.lastRecord).toBe(320); + paginator.page = 34; + expect(paginator.isLastPage).toBeTruthy(); + expect(paginator.isLastBlock).toBeTruthy(); + expect(paginator.pagesInLastBlock).toBe(4); + expect(paginator.safePage).toBe(34); + expect(paginator.page).toBe(34); + expect(paginator.block).toBe(4); + expect(paginator.firstRecord).toBe(331); + expect(paginator.lastRecord).toBe(340); + paginator.page = 35; + expect(paginator.pagesInLastBlock).toBe(4); + expect(paginator.safePage).toBe(34); + expect(paginator.isLastPage).toBeTruthy(); + expect(paginator.isLastBlock).toBeTruthy(); + expect(paginator.page).toBe(34); + expect(paginator.block).toBe(4); + expect(paginator.firstRecord).toBe(331); + expect(paginator.lastRecord).toBe(340); + }); +}); diff --git a/test/reactivity.test.ts b/test/reactivity.test.ts new file mode 100644 index 0000000..55c20e8 --- /dev/null +++ b/test/reactivity.test.ts @@ -0,0 +1,61 @@ + +import { describe, expect, test, vitest } from "vitest"; +import { createEffect, createRoot } from "solid-js"; +import { bindReactive } from "../src/reactivity"; + +describe("Reactivity Engine", () => { + test("bindReactive should link a property to a Solid signal", () => { + const target = { + active: false + }; + + // Bind reactivity to 'active' property + bindReactive(target, "active", false); + + let effectCount = 0; + let lastValue: boolean | undefined; + + createRoot(() => { + createEffect(() => { + lastValue = target.active; + effectCount++; + }); + }); + + // Initial effect run + expect(effectCount).toBe(1); + expect(lastValue).toBe(false); + + // Update target property + target.active = true; + + // Solid effects are scheduled on the next microtask or can be observed + // if we wait or use synchronous patterns. + // In Vitest, we might need a small delay or check after a tick. + + expect(target.active).toBe(true); + expect(effectCount).toBe(2); + expect(lastValue).toBe(true); + }); + + test("bindReactive should handle complex types", () => { + const target = { + data: { name: "initial" } + }; + + bindReactive(target, "data", { name: "initial" }); + + let lastValue: string = ""; + + createRoot(() => { + createEffect(() => { + lastValue = target.data.name; + }); + }); + + expect(lastValue).toBe("initial"); + + target.data = { name: "updated" }; + expect(lastValue).toBe("updated"); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 04b9d0e..45fc421 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ /* Projects */ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ @@ -12,7 +12,7 @@ /* Language and Environment */ "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - "lib": ["esnext", "dom"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "lib": ["esnext", "dom", "dom.iterable"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ @@ -27,13 +27,16 @@ /* Modules */ // "module": "ES6", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ + "rootDir": "./src", /* Specify the root folder within your source files. */ "moduleResolution": "Node", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": ["node", "jest"], /* Specify type package names to be included without being referenced in a source file. */ + "types": [ /* Specify type package names to be included without being referenced in a source file. */ + "vite/client", + "@testing-library/jest-dom" + ], // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ // "resolveJsonModule": true, /* Enable importing .json files. */ @@ -46,7 +49,7 @@ /* Emit */ "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + "declarationMap": true, /* Create sourcemaps for d.ts files. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tsconfig.types.json b/tsconfig.types.json new file mode 100644 index 0000000..76d3ae9 --- /dev/null +++ b/tsconfig.types.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig", + "include": ["src/**/*"], + "exclude": ["jest.config.ts", "vitest.config.ts"], + "compilerOptions": { + "composite": true, + "rootDir": "./src", + "types": [ + "vite/client", + "@testing-library/jest-dom" + ], + "outDir": "./dist", + } +} diff --git a/types/app/global.d.ts b/types/app/global.d.ts new file mode 100644 index 0000000..a223183 --- /dev/null +++ b/types/app/global.d.ts @@ -0,0 +1 @@ +//# sourceMappingURL=global.d.ts.map \ No newline at end of file diff --git a/types/app/global.d.ts.map b/types/app/global.d.ts.map new file mode 100644 index 0000000..fb37d51 --- /dev/null +++ b/types/app/global.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"global.d.ts","sourceRoot":"","sources":["../../src/app/global.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/types/element-attributes.d.ts b/types/element-attributes.d.ts new file mode 100644 index 0000000..d488088 --- /dev/null +++ b/types/element-attributes.d.ts @@ -0,0 +1,18 @@ +import { FazElement } from "./element"; +import { JSX } from "solid-js"; +export interface FazElementAttributes extends JSX.HTMLAttributes { + fazid?: string; + active?: boolean; + connected?: boolean; + content?: string; + debug?: boolean; + disabled?: boolean; + extraClasses?: string; + fazChildren?: FazElement[]; + loading?: boolean; + parent?: FazElement; + reload?: boolean; + link?: string; +} +export type FazAttributeRole = "alert" | "alertdialog" | "application" | "article" | "banner" | "button" | "cell" | "checkbox" | "columnheader" | "combobox" | "complementary" | "contentinfo" | "definition" | "dialog" | "directory" | "document" | "feed" | "figure" | "form" | "grid" | "gridcell" | "group" | "heading" | "img" | "link" | "list" | "listbox" | "listitem" | "log" | "main" | "marquee" | "math" | "menu" | "menubar" | "menuitem" | "menuitemcheckbox" | "menuitemradio" | "meter" | "navigation" | "none" | "note" | "option" | "presentation" | "progressbar" | "radio" | "radiogroup" | "region" | "row" | "rowgroup" | "rowheader" | "scrollbar" | "search" | "searchbox" | "separator" | "slider" | "spinbutton" | "status" | "switch" | "tab" | "table" | "tablist" | "tabpanel" | "term" | "textbox" | "timer" | "toolbar" | "tooltip" | "tree" | "treegrid" | "treeitem" | undefined; +//# sourceMappingURL=element-attributes.d.ts.map \ No newline at end of file diff --git a/types/element-attributes.d.ts.map b/types/element-attributes.d.ts.map new file mode 100644 index 0000000..dbae6e4 --- /dev/null +++ b/types/element-attributes.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"element-attributes.d.ts","sourceRoot":"","sources":["../src/element-attributes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,MAAM,WAAW,oBAAoB,CAAC,CAAC,CAAE,SAAQ,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,gBAAgB,GACpB,OAAO,GACP,aAAa,GACb,aAAa,GACb,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,UAAU,GACV,cAAc,GACd,UAAU,GACV,eAAe,GACf,aAAa,GACb,YAAY,GACZ,QAAQ,GACR,WAAW,GACX,UAAU,GACV,MAAM,GACN,QAAQ,GACR,MAAM,GACN,MAAM,GACN,UAAU,GACV,OAAO,GACP,SAAS,GACT,KAAK,GACL,MAAM,GACN,MAAM,GACN,SAAS,GACT,UAAU,GACV,KAAK,GACL,MAAM,GACN,SAAS,GACT,MAAM,GACN,MAAM,GACN,SAAS,GACT,UAAU,GACV,kBAAkB,GAClB,eAAe,GACf,OAAO,GACP,YAAY,GACZ,MAAM,GACN,MAAM,GACN,QAAQ,GACR,cAAc,GACd,aAAa,GACb,OAAO,GACP,YAAY,GACZ,QAAQ,GACR,KAAK,GACL,UAAU,GACV,WAAW,GACX,WAAW,GACX,QAAQ,GACR,WAAW,GACX,WAAW,GACX,QAAQ,GACR,YAAY,GACZ,QAAQ,GACR,QAAQ,GACR,KAAK,GACL,OAAO,GACP,SAAS,GACT,UAAU,GACV,MAAM,GACN,SAAS,GACT,OAAO,GACP,SAAS,GACT,SAAS,GACT,MAAM,GACN,UAAU,GACV,UAAU,GACV,SAAS,CAAC"} \ No newline at end of file diff --git a/types/element.d.ts b/types/element.d.ts new file mode 100644 index 0000000..d66017f --- /dev/null +++ b/types/element.d.ts @@ -0,0 +1,77 @@ +import { FazAttributeRole } from "./element-attributes"; +export interface FazComment extends Comment { + fazElement: FazElement | undefined; +} +export interface FazNode extends ChildNode { + fazElement: FazElement | undefined; +} +export declare class FazElement extends HTMLElement { + active: boolean; + connected: boolean; + content: string | undefined; + debug: boolean; + disabled: boolean | undefined; + extraClasses: string; + fazChildren: FazElement[]; + fazElement: FazElement | undefined; + fazRole: FazAttributeRole; + idGenerated: boolean; + loading: boolean; + parent: FazElement | undefined; + reload: boolean; + link: string | undefined; + childPrefix: string; + renderedChild: ChildNode | null; + private comment; + source: any; + private observer; + private isMoving; + private hostInitialized; + constructor(); + /** + * Initialize host DOM attributes after construction. + * + * Custom element constructors must not mutate attributes or children. + * Keep DOM-affecting setup in the connected lifecycle so elements created + * via document.createElement() can upgrade cleanly in browsers and jsdom. + */ + private initializeHost; + /** + * Set up a MutationObserver to handle dynamic DOM changes (e.g., HTMX). + */ + private setupMutationObserver; + /** + * Updates the reactive fazChildren list by scanning current child nodes. + */ + private updateFazChildren; + /** + * The `disconnectedCallback` is a built-in lifecycle method of custom elements. + * It is called automatically by the browser when the element is removed from the DOM. + */ + disconnectedCallback(): void; + /** + * Custom cleanup method for the component. + * Implement additional resource or event listener cleanups here as needed. + * Currently empty. + */ + disconnect(): void; + hasExtraClass(value: string): boolean; + hasExtraClasses(): boolean; + pushExtraClass(value: string): void; + resolveLink(): string | undefined; + addFazChild(child: FazElement): void; + removeFazChild(child: FazElement): void; + get activeFazChildren(): FazElement[]; + get contentChild(): ChildNode | null; + get linkIsVoid(): boolean; + addChild(node: T): T; + afterShow(): void; + beforeShow(): void; + collectChildren(): Node[]; + placeBackChildren(children: Node[]): void; + connectedCallback(): void; + load(): void; + show(): void; + render(): void; +} +//# sourceMappingURL=element.d.ts.map \ No newline at end of file diff --git a/types/element.d.ts.map b/types/element.d.ts.map new file mode 100644 index 0000000..568282c --- /dev/null +++ b/types/element.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAMxD,MAAM,WAAW,UAAW,SAAQ,OAAO;IACvC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;CACtC;AAGD,MAAM,WAAW,OAAQ,SAAQ,SAAS;IACtC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;CACtC;AAGD,qBAAa,UAAW,SAAQ,WAAW;IAGhC,MAAM,EAAG,OAAO,CAAC;IACjB,SAAS,EAAG,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,GAAC,SAAS,CAAC;IAC1B,KAAK,EAAG,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAC,SAAS,CAAC;IAC5B,YAAY,EAAG,MAAM,CAAC;IACtB,WAAW,EAAG,UAAU,EAAE,CAAC;IAC3B,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAS;IAC7B,OAAO,EAAG,OAAO,CAAC;IAClB,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAC/B,MAAM,EAAG,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,GAAC,SAAS,CAAC;IAGvB,WAAW,EAAE,MAAM,CAAM;IACzB,aAAa,EAAE,SAAS,GAAG,IAAI,CAAQ;IAC9C,OAAO,CAAC,OAAO,CAA2B;IACnC,MAAM,EAAE,GAAG,CAAC;IACnB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,eAAe,CAAkB;;IA0EzC;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAmC7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAyBzB;;;OAGG;IACH,oBAAoB;IAQpB;;;;OAIG;IACH,UAAU;IAIV,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAOrC,eAAe,IAAI,OAAO;IAK1B,cAAc,CAAC,KAAK,EAAE,MAAM;IAU5B,WAAW,IAAI,MAAM,GAAG,SAAS;IAWjC,WAAW,CAAC,KAAK,EAAE,UAAU;IAS7B,cAAc,CAAC,KAAK,EAAE,UAAU;IAQhC,IAAI,iBAAiB,IAAI,UAAU,EAAE,CAIpC;IAGD,IAAI,YAAY,IAAI,SAAS,GAAG,IAAI,CAEnC;IAGD,IAAI,UAAU,YAMb;IAGD,QAAQ,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC;IAWpC,SAAS,IAAG,IAAI;IAGhB,UAAU,IAAG,IAAI;IAGjB,eAAe;IAqBf,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE;IAQlC,iBAAiB;IAwBjB,IAAI;IAGJ,IAAI;IAGJ,MAAM;CAQT"} \ No newline at end of file diff --git a/types/form.d.ts b/types/form.d.ts new file mode 100644 index 0000000..7e0dac0 --- /dev/null +++ b/types/form.d.ts @@ -0,0 +1,16 @@ +import { FazElement } from "./element"; +export declare class FazFormElement extends FazElement { + action: string | undefined; + errors: Record; + method: string; + constructor(); + get form(): HTMLFormElement | undefined; + get values(): Record; + clearErrorsFor(key: string): void; + clearErrors(): void; + hasErrorsFor(key: string): boolean; + hasErrors(): boolean; + getErrorsFor(key: string): string[]; + pushError(key: string, value: string): void; +} +//# sourceMappingURL=form.d.ts.map \ No newline at end of file diff --git a/types/form.d.ts.map b/types/form.d.ts.map new file mode 100644 index 0000000..339b3cd --- /dev/null +++ b/types/form.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAIvC,qBAAa,cAAe,SAAQ,UAAU;IAEnC,MAAM,EAAE,MAAM,GAAC,SAAS,CAAC;IACzB,MAAM,EAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAClC,MAAM,EAAG,MAAM,CAAC;;IA0BvB,IAAI,IAAI,IAAI,eAAe,GAAC,SAAS,CAEpC;IAED,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAU/C;IAEM,cAAc,CAAC,GAAG,EAAE,MAAM;IAQ1B,WAAW;IAIX,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIlC,SAAS,IAAI,OAAO;IAIpB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;IAInC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAa9C"} \ No newline at end of file diff --git a/types/index.d.ts b/types/index.d.ts index e0fc627..4c2f8e5 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,27 +1,7 @@ -// See: https://cutt.ly/RwyeQ7ZT - -export { randomId } from "../src/id"; -export { FazFormElement } from "../src/form"; -export { FazElementItem } from "../src/item"; - -interface FazElementItem extends HTMLElement { - fazid: string; -} - -interface FazElementItemAttributes extends HTMLAttributes { - fazid?: string; -} - -interface FazNavElement extends FazElementItem { -} - -declare global { - declare module "solid-js" { - namespace JSX { - interface IntrinsicElements { - 'faz-nav': FazElementItemAttributes; - 'faz-nav-item': HTMLDivElement; - } - } - } -} +export { FazElement } from "./element"; +export type { FazElementAttributes } from "./element-attributes"; +export { FazFormElement } from "./form"; +export { randomId, toBoolean } from "./values"; +export { bindReactive } from "./reactivity"; +export { FazPaginator } from "./paginator"; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/types/index.d.ts.map b/types/index.d.ts.map new file mode 100644 index 0000000..6ebde84 --- /dev/null +++ b/types/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/types/paginator.d.ts b/types/paginator.d.ts new file mode 100644 index 0000000..6415bf7 --- /dev/null +++ b/types/paginator.d.ts @@ -0,0 +1,89 @@ +/** + * FazPaginator is a pagination utility class built for use with Solid.js + * reactive primitives. + * It manages page, block, and record calculations for paginated collections, + * offering helpers for navigation, state, and boundary conditions. + */ +export declare class FazPaginator { + count: number; + page: number; + perBlock: number; + perPage: number; + constructor(); + /** + * Returns the total number of blocks needed for the current settings. + */ + get blocks(): number; + /** + * Returns the total number of pages based on count and perPage. + */ + get pages(): number; + /** + * Returns a 'safe' current page value, always in the valid range. + * Adjusts the page if it's out of bounds. + */ + get safePage(): number; + /** + * Returns the current block number (1-based) for the current page. + */ + get block(): number; + /** + * Returns the first page number in the current block. + */ + get currentFirstPage(): number; + /** + * Returns the last page number in the current block. + * Handles the last block which may have fewer pages. + */ + get currentLastPage(): number; + /** + * Returns the number of pages in the last block. + */ + get pagesInLastBlock(): number; + /** + * Returns an array of page numbers in the current block. + */ + get blockPages(): number[]; + /** + * Checks if a given page is the current page. + * @param page Page number to check + */ + isCurrentPage(page: number): boolean; + /** + * Is the current page the first page? + */ + get isFirstPage(): boolean; + /** + * Is the current block the first block? + */ + get isFirstBlock(): boolean; + /** + * Is the current page the last page? + */ + get isLastPage(): boolean; + /** + * Is the current block the last block? + */ + get isLastBlock(): boolean; + /** + * Does the pagination have multiple pages? + */ + get hasMultiplePages(): boolean; + /** + * Does the pagination have multiple blocks? + */ + get hasMultipleBlocks(): boolean; + /** + * Returns the number of records in the last page. + */ + get recordsInLastPage(): number; + /** + * Returns the absolute index of the first record on the current page. + */ + get firstRecord(): number; + /** + * Returns the absolute index of the last record on the current page. + */ + get lastRecord(): number; +} +//# sourceMappingURL=paginator.d.ts.map \ No newline at end of file diff --git a/types/paginator.d.ts.map b/types/paginator.d.ts.map new file mode 100644 index 0000000..66b12ca --- /dev/null +++ b/types/paginator.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"paginator.d.ts","sourceRoot":"","sources":["../src/paginator.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,qBAAa,YAAY;IAGd,KAAK,EAAG,MAAM,CAAC;IAGf,IAAI,EAAG,MAAM,CAAC;IAGd,QAAQ,EAAG,MAAM,CAAC;IAGlB,OAAO,EAAG,MAAM,CAAC;;IASxB;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAInB;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAQlB;IAED;;;OAGG;IACH,IAAI,QAAQ,IAAI,MAAM,CAQrB;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAQlB;IAED;;OAEG;IACH,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED;;;OAGG;IACH,IAAI,eAAe,WAKlB;IAED;;OAEG;IACH,IAAI,gBAAgB,IAAI,MAAM,CAG7B;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,EAAE,CAGzB;IAED;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIpC;;OAEG;IACH,IAAI,WAAW,YAEd;IAED;;OAEG;IACH,IAAI,YAAY,YAEf;IAED;;OAEG;IACH,IAAI,UAAU,YAEb;IAED;;OAEG;IACH,IAAI,WAAW,YAEd;IAED;;OAEG;IACH,IAAI,gBAAgB,YAEnB;IAED;;OAEG;IACH,IAAI,iBAAiB,YAEpB;IAED;;OAEG;IACH,IAAI,iBAAiB,WAGpB;IAED;;OAEG;IACH,IAAI,WAAW,WAEd;IAED;;OAEG;IACH,IAAI,UAAU,WAKb;CACJ"} \ No newline at end of file diff --git a/types/reactivity.d.ts b/types/reactivity.d.ts new file mode 100644 index 0000000..c1332b1 --- /dev/null +++ b/types/reactivity.d.ts @@ -0,0 +1,10 @@ +/** + * Binds a SolidJS signal to an object property, making it reactive. + * This is a decomposed approach that avoids boilerplate and strings-only APIs. + * + * @param target The object to define the property on. + * @param key The key of the property. + * @param initialValue The initial value for the signal. + */ +export declare function bindReactive(target: T, key: K, initialValue: T[K]): void; +//# sourceMappingURL=reactivity.d.ts.map \ No newline at end of file diff --git a/types/reactivity.d.ts.map b/types/reactivity.d.ts.map new file mode 100644 index 0000000..50ccc96 --- /dev/null +++ b/types/reactivity.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"reactivity.d.ts","sourceRoot":"","sources":["../src/reactivity.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,EAC5D,MAAM,EAAE,CAAC,EACT,GAAG,EAAE,CAAC,EACN,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,QAUrB"} \ No newline at end of file diff --git a/types/test.d.ts b/types/test.d.ts new file mode 100644 index 0000000..e6dd963 --- /dev/null +++ b/types/test.d.ts @@ -0,0 +1,3 @@ +import { FazComment } from "./element"; +export declare function allComments(context: any): FazComment[]; +//# sourceMappingURL=test.d.ts.map \ No newline at end of file diff --git a/types/test.d.ts.map b/types/test.d.ts.map new file mode 100644 index 0000000..c1a6cfd --- /dev/null +++ b/types/test.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGvC,wBAAgB,WAAW,CAAC,OAAO,EAAE,GAAG,GAAG,UAAU,EAAE,CAetD"} \ No newline at end of file diff --git a/types/values.d.ts b/types/values.d.ts new file mode 100644 index 0000000..9eadc2e --- /dev/null +++ b/types/values.d.ts @@ -0,0 +1,3 @@ +export declare function toBoolean(value: string | null): boolean; +export declare function randomId(): string; +//# sourceMappingURL=values.d.ts.map \ No newline at end of file diff --git a/types/values.d.ts.map b/types/values.d.ts.map new file mode 100644 index 0000000..1b20b9b --- /dev/null +++ b/types/values.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../src/values.ts"],"names":[],"mappings":"AACA,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAKvD;AAED,wBAAgB,QAAQ,WAOvB"} \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..ae385fc --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,9 @@ +import solid from "vite-plugin-solid" +import { defineConfig } from "vitest/config" + +export default defineConfig({ + plugins: [solid()], + resolve: { + conditions: ["development", "browser"], + } +}) diff --git a/watch.mjs b/watch.mjs index dc48064..84ba4d9 100644 --- a/watch.mjs +++ b/watch.mjs @@ -1,26 +1,18 @@ -/** - * Copyright 2018-2023 Flavio Garcia - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import * as esbuild from "esbuild"; +import { context } from "esbuild"; import { assets } from "./assets.mjs"; import { entryPoints } from "./entryPoints.mjs"; import { copy } from "esbuild-plugin-copy"; import { solidPlugin } from "esbuild-plugin-solid"; -let ctx = await esbuild.context({ +entryPoints.push({ out: "custom-tag.bundle", in: "showcase/src/custom-tag.tsx" }); +entryPoints.push({ out: "form.bundle", in: "showcase/src/form.tsx" }); + +entryPoints.push({ out: "global.bundle", in: "showcase/src/global.ts" }); +entryPoints.push({ out: "poc.bundle", in: "showcase/src/poc/poc.tsx" }); +entryPoints.push({ out: "css/showcase", in: "stylesheets/showcase.css"}); + +let ctx = await context({ entryPoints: entryPoints, bundle: true, minify: true, @@ -28,13 +20,26 @@ let ctx = await esbuild.context({ treeShaking: true, sourcemap: true, logLevel: "info", - outdir: "dist", + outdir: "showcase/dist", legalComments: "none", - allowOverwrite: true, + allowOverwrite: false, plugins:[ copy(assets), solidPlugin() - ] + ], + loader: { '.png': 'binary' }, }); await ctx.watch(); + +await ctx.serve({ + port: 8082, + servedir: "showcase", + onRequest: (args) => { + let logMessage = ""; + for (let key in args) { + logMessage += key + ": " + args[key] + " "; + } + console.log(logMessage); + } +})