diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..07f60e1
--- /dev/null
+++ b/.github/CODE_OF_CONDUCT.md
@@ -0,0 +1,76 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, sex characteristics, gender identity and expression,
+level of experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+- The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at mathieu.acthernoene@swan.io. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see
+https://www.contributor-covenant.org/faq
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..14ecd51
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,69 @@
+name: 🐛 Bug report
+description: Report a reproducible bug or regression in this library.
+labels: [bug]
+assignees:
+ - zoontek
+body:
+ - type: markdown
+ attributes:
+ value: |
+ # Bug report
+
+ 👋 Hi!
+
+ **🚨 Please read the following carefully before opening a new issue 🚨**
+ *(Your issue may be closed if it doesn't provide the required pieces of information)*
+
+ Before submitting a new issue, please:
+
+ - Test using the latest release of the library, as maybe your bug has been already fixed.
+ - Check for possible duplicate issues, with possible answers.
+
+ Is this still needed? Fill the form 👇
+ - type: textarea
+ id: summary
+ attributes:
+ label: Bug summary
+ description: |
+ Provide a clear and concise description of what the bug is.
+ If needed, you can also provide other samples: error messages / stack traces, screenshots, videos, etc.
+ validations:
+ required: true
+ - type: input
+ id: library-version
+ attributes:
+ label: Library version
+ description: What version of the library are you using?
+ placeholder: "x.x.x"
+ validations:
+ required: true
+ - type: textarea
+ id: browser-info
+ attributes:
+ label: Environment info
+ description: Go to [WhatIsMyBrowser](https://www.whatismybrowser.com) and copy / paste your browser & OS names + versions.
+ render: shell
+ validations:
+ required: true
+ - type: textarea
+ id: steps-to-reproduce
+ attributes:
+ label: Steps to reproduce
+ description: |
+ - You must provide a clear list of steps and code to reproduce the problem.
+ - Keep the code reproducing the bug as simple as possible, with the minimum amount of code required to reproduce the issue. See https://stackoverflow.com/help/mcve.
+ - Either re-create the bug using the repository's example app or link to a GitHub repository with code that reproduces the bug.
+ - Explain the steps we need to take to reproduce the issue:
+ value: |
+ 1. …
+ 2. …
+ validations:
+ required: true
+ - type: textarea
+ id: reproducible-sample-code
+ attributes:
+ label: Reproducible sample code
+ description: Please add minimal runnable repro as explained above so that the bug can be tested in isolation.
+ render: ts
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000..a8d9f75
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,34 @@
+name: 💡 Feature request
+description: Submit your idea for a change in the codebase.
+labels: [feature request]
+assignees:
+ - zoontek
+body:
+ - type: markdown
+ attributes:
+ value: |
+ # Feature request
+
+ This issue should serve for you to present or pitch an idea to the maintainers - but remember that it would be better if you were to submit a PR instead 🤗
+ - type: textarea
+ id: why-is-this-needed
+ attributes:
+ label: Why it is needed?
+ description: Please tell us a bit more of why you want this feature to be added, what's its origin.
+ validations:
+ required: true
+ - type: textarea
+ id: possible-implementation
+ attributes:
+ label: Possible implementation
+ description: It really helps if you could describe from a technical POV how this new feature would work, which code it rely on, etc.
+ validations:
+ required: false
+ - type: textarea
+ id: code-sample
+ attributes:
+ label: Code sample
+ description: Please show how the new code could work, if doable.
+ render: ts
+ validations:
+ required: false
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..97ef465
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,27 @@
+
+
+# Summary
+
+
+
+## Test Plan
+
+
+
+### What's required for testing (prerequisites)?
+
+### What are the steps to reproduce (after prerequisites)?
+
+## Checklist
+
+
+
+- [ ] I added the documentation in `README.md`
+- [ ] I wrote / updated some tests (`__tests__/`)
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 0000000..427567c
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,32 @@
+# Number of days of inactivity before an Issue or Pull Request becomes stale
+daysUntilStale: 60
+# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
+daysUntilClose: 7
+# Issues or Pull Requests.
+exemptLabels:
+ - pinned
+ - security
+ - discussion
+# Set to true to ignore issues in a project (defaults to false)
+exemptProjects: false
+# Set to true to ignore issues in a milestone (defaults to false)
+exemptMilestones: false
+# Set to true to ignore issues with an assignee (defaults to false)
+exemptAssignees: false
+# Label to use when marking as stale
+staleLabel: stale
+# Comment to post when marking as stale. Set to `false` to disable
+markComment: >
+ This issue has been automatically marked as stale because it has not had
+ recent activity. It will be closed if no further activity occurs. Thank you
+ for your contributions. You may also mark this issue as a "discussion" and I
+ will leave this open.
+# Comment to post when closing a stale Issue or Pull Request.
+closeComment: >
+ Closing this issue after a prolonged period of inactivity. Fell free to reopen
+ this issue, if this still affecting you.
+# Limit the number of actions per hour, from 1-30. Default is 30
+limitPerRun:
+ 30
+ # Limit to only `issues` or `pulls`
+only: issues
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..7b00f10
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,33 @@
+name: Build
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ timeout-minutes: 60
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: pnpm/action-setup@v4
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: lts/*
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Typecheck
+ run: pnpm typecheck
+
+ - name: Run tests
+ run: pnpm test:ci
+
+ - name: Build
+ run: pnpm build
diff --git a/README.md b/README.md
index 8b55b6e..b85d6d7 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,130 @@
-# css
+# @swan-io/css
-An atomic CSS-in-JS library inspired by React Native `StyleSheet`
+[![mit licence](https://img.shields.io/dub/l/vibe-d.svg?style=for-the-badge)](https://github.com/swan-io/css/blob/main/LICENSE)
+[![npm version](https://img.shields.io/npm/v/@swan-io/css?style=for-the-badge)](https://www.npmjs.org/package/@swan-io/css)
+[![bundlephobia](https://img.shields.io/bundlephobia/minzip/@swan-io/css?label=size&style=for-the-badge)](https://bundlephobia.com/result?p=@swan-io/css)
+
+A lightweight and performant atomic CSS-in-JS library.
+
+## Installation
+
+```bash
+$ yarn add @swan-io/css
+# --- or ---
+$ npm install --save @swan-io/css
+```
+
+## Quickstart
+
+```tsx
+import { css, cx } from "@swan-io/css";
+
+const sheet = css.make({
+ box: {
+ backgroundColor: "blue",
+ padding: 16,
+ },
+ large: {
+ padding: 24,
+ },
+ text: {
+ color: "white",
+ fontSize: 20,
+ ":hover": {
+ color: "gray",
+ },
+ },
+});
+
+const Component = ({ large }: { large: boolean }) => (
+
+ Hello world
+
+);
+```
+
+## API
+
+### css.make
+
+Create a new sheet object and inject the associated styles.
+
+```tsx
+const sheet = css.make({
+ box: {
+ backgroundColor: "hotpink",
+ paddingHorizontal: 16,
+
+ // supports :hover, :focus and :active
+ ":hover": { color: "red" },
+ ":focus": { color: "green" },
+ ":active": { color: "blue" },
+ },
+});
+
+console.log(sheet.box); // a string list of generated classes
+```
+
+> [!TIP]
+> Styles prefixed with `$` will be inserted as non-atomic CSS-in-JS, which is particularly useful for resetting the styles of an HTML element.
+
+```tsx
+const sheet = css.make({
+ // generates a single class, inserted before the rest
+ $reset: {
+ margin: 0,
+ padding: 0,
+ },
+ // generates multiple classes
+ input: {
+ color: "grey",
+ display: "flex",
+ },
+});
+```
+
+### css.keyframes
+
+Inject a keyframes rule and generate a unique name for it.
+
+```tsx
+const sheet = css.make({
+ box: {
+ animationDuration: "300ms",
+ animationName: css.keyframes({
+ "0%": { opacity: 0 },
+ "100%": { opacity: 1 },
+ }),
+ },
+});
+```
+
+### cx
+
+Concatenate the generated classes from left to right, with subsequent styles overwriting the property values of earlier ones.
+
+```tsx
+const sheet = css.make({
+ box: {
+ display: "flex",
+ color: "red",
+ },
+ inline: {
+ display: "inline-flex",
+ },
+});
+
+// with inline={false}, applied style will be display: flex; color: red;
+// with inline={true}, applied style will be display: inline-flex; color: red;
+const Component = ({ inline }: { inline: boolean }) => (
+
+);
+```
+
+## Links
+
+- ⚖️ [**License**](./LICENSE)
+
+## 🙌 Acknowledgements
+
+- [react-native-web](https://github.com/necolas/react-native-web) by [@necolas](https://github.com/necolas)
diff --git a/__tests__/cache.ts b/__tests__/cache.ts
new file mode 100644
index 0000000..063de7c
--- /dev/null
+++ b/__tests__/cache.ts
@@ -0,0 +1,58 @@
+import { expect, test } from "vitest";
+import { css } from "../src";
+import { getSheets } from "./utils";
+
+test("cache don't insert identical property + value pairs", () => {
+ css.make({
+ foo: {
+ color: "red",
+ ":hover": { color: "green" },
+ ":focus": { color: "blue" },
+ ":active": { color: "rebeccapurple" },
+ },
+ bar: {
+ color: "red",
+ ":hover": { color: "green" },
+ ":focus": { color: "blue" },
+ ":active": { color: "rebeccapurple" },
+ },
+ baz: {
+ // insert identical colors (they are normalized)
+ color: "color: rgb(255, 0, 0)",
+ ":hover": { color: "rgb(0, 128, 0)" },
+ ":focus": { color: "rgb(0, 0, 255)" },
+ ":active": { color: "rgb(102, 51, 153)" },
+ },
+ // insert identical resets
+ $qux: { margin: 0, padding: 0 },
+ $quux: { margin: 0, padding: 0 },
+ });
+
+ const { reset, atomic, hover, focus, active } = getSheets();
+
+ expect(reset.rules).toHaveLength(1);
+ expect(atomic.rules).toHaveLength(1);
+ expect(hover.rules).toHaveLength(1);
+ expect(focus.rules).toHaveLength(1);
+ expect(active.rules).toHaveLength(1);
+
+ expect(reset.rules.join("\n")).toMatchInlineSnapshot(
+ `".r-1je9j89 { margin: 0px; padding: 0px; }"`,
+ );
+
+ expect(atomic.rules.join("\n")).toMatchInlineSnapshot(
+ `".x-1tkyx38 { color: rgb(255, 0, 0); }"`,
+ );
+
+ expect(hover.rules.join("\n")).toMatchInlineSnapshot(
+ `".h-1w6oenc:hover { color: rgb(0, 128, 0); }"`,
+ );
+
+ expect(focus.rules.join("\n")).toMatchInlineSnapshot(
+ `".f-rc30ek:focus-visible { color: rgb(0, 0, 255); }"`,
+ );
+
+ expect(active.rules.join("\n")).toMatchInlineSnapshot(
+ `".a-1ngrkn9:active { color: rgb(102, 51, 153); }"`,
+ );
+});
diff --git a/__tests__/cx.tsx b/__tests__/cx.tsx
new file mode 100644
index 0000000..887f42d
--- /dev/null
+++ b/__tests__/cx.tsx
@@ -0,0 +1,71 @@
+import * as React from "react";
+import { expect, test } from "vitest";
+import { render } from "vitest-browser-react";
+import { css, cx } from "../src";
+
+test("cx concatenates atomic classes", () => {
+ const sheet = css.make({
+ foo: {
+ backgroundColor: "red",
+ color: "blue",
+ },
+ bar: {
+ color: "green",
+ },
+ });
+
+ expect(sheet.foo).toMatchInlineSnapshot(`"x-7ogb2w x-rc30ek"`);
+ expect(sheet.bar).toMatchInlineSnapshot(`"x-1w6oenc"`);
+
+ expect(cx(sheet.foo, sheet.bar)).toMatchInlineSnapshot(
+ `"x-7ogb2w x-1w6oenc"`,
+ );
+});
+
+test("cx allows one reset style", async () => {
+ const sheet = css.make({
+ $foo: {
+ backgroundColor: "red",
+ color: "blue",
+ },
+ $bar: {
+ color: "green",
+ },
+ baz: {
+ color: "rebeccapurple",
+ ":hover": {
+ color: "gray",
+ },
+ },
+ });
+
+ expect(sheet.$foo).toMatchInlineSnapshot(`"r-1vjaegw"`);
+ expect(sheet.$bar).toMatchInlineSnapshot(`"r-1w6oenc"`);
+ expect(sheet.baz).toMatchInlineSnapshot(`"x-1ngrkn9 h-1g5wjl1"`);
+
+ const className = cx(sheet.$foo, sheet.$bar, sheet.baz);
+ expect(className).toMatchInlineSnapshot(`"r-1vjaegw x-1ngrkn9 h-1g5wjl1"`);
+
+ const screen = render(
);
+ const div = await screen.getByTestId("div");
+ const style = window.getComputedStyle(div.element());
+
+ expect(style.backgroundColor).toBe("rgb(255, 0, 0)");
+ expect(style.color).toBe("rgb(102, 51, 153)");
+});
+
+test("cx allows external classes", async () => {
+ const sheet = css.make({
+ foo: { lineClamp: 1 },
+ bar: { lineClamp: 2 },
+ });
+
+ const className = cx(sheet.foo, false && sheet.bar, true && ["foo"]);
+ expect(className).toMatchInlineSnapshot(`"foo x-1acs8jx"`);
+
+ const screen = render( );
+ const div = await screen.getByTestId("div");
+ const style = window.getComputedStyle(div.element());
+
+ expect(style.webkitLineClamp).toBe("1");
+});
diff --git a/__tests__/index.ts b/__tests__/index.ts
deleted file mode 100644
index d3b08e2..0000000
--- a/__tests__/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { expect, test } from "vitest";
-
-test("adds 1 + 2 to equal 3", () => {
- expect(1 + 2).toBe(3);
-});
diff --git a/__tests__/preprocess.ts b/__tests__/preprocess.ts
new file mode 100644
index 0000000..cae9d7a
--- /dev/null
+++ b/__tests__/preprocess.ts
@@ -0,0 +1,60 @@
+import { expect, test } from "vitest";
+import { css } from "../src";
+import { getSheets } from "./utils";
+
+test("longhands properties are expanded", () => {
+ const sheet = css.make({
+ box: {
+ backgroundPosition: "top",
+ borderColor: "red",
+ borderRadius: 4,
+ borderStyle: "dotted",
+ borderWidth: 2,
+ flex: 1,
+ inset: 10,
+ margin: 10,
+ padding: 10,
+ },
+ });
+
+ expect(sheet.box).toMatchInlineSnapshot(
+ `"x-1ajv4b8 x-1gj51ll x-19tkz8q x-1ogglhr x-yx774m x-1h88r7n x-1bdvcgl x-misotl x-qirwg6 x-1ppxwh4 x-1o74rcf x-1vqxhxy x-9xwnqj x-29ghif x-1h9xl6o x-s861vp x-1a0ix0g x-fh1clx x-1t1j3t x-tklrwr x-o0zst5 x-zs882z x-4esd6u x-jwnrsh x-8wdww5 x-1f13l4q x-lx60ht x-cl7tym x-jm3jfd x-jlcvdv x-6rz8sj x-h002ba"`,
+ );
+
+ const { atomic } = getSheets();
+
+ expect(atomic.rules.join("\n")).toMatchInlineSnapshot(`
+ ".x-1ajv4b8 { background-position-y: 0%; }
+ .x-1gj51ll { border-top-color: rgb(255, 0, 0); }
+ .x-19tkz8q { border-right-color: rgb(255, 0, 0); }
+ .x-1ogglhr { border-bottom-color: rgb(255, 0, 0); }
+ .x-yx774m { border-left-color: rgb(255, 0, 0); }
+ .x-1h88r7n { border-top-left-radius: 4px; }
+ .x-1bdvcgl { border-top-right-radius: 4px; }
+ .x-misotl { border-bottom-right-radius: 4px; }
+ .x-qirwg6 { border-bottom-left-radius: 4px; }
+ .x-1ppxwh4 { border-top-style: dotted; }
+ .x-1o74rcf { border-right-style: dotted; }
+ .x-1vqxhxy { border-bottom-style: dotted; }
+ .x-9xwnqj { border-left-style: dotted; }
+ .x-29ghif { border-top-width: 2px; }
+ .x-1h9xl6o { border-right-width: 2px; }
+ .x-s861vp { border-bottom-width: 2px; }
+ .x-1a0ix0g { border-left-width: 2px; }
+ .x-fh1clx { flex-grow: 1; }
+ .x-1t1j3t { flex-shrink: 1; }
+ .x-tklrwr { flex-basis: 0%; }
+ .x-o0zst5 { top: 10px; }
+ .x-zs882z { right: 10px; }
+ .x-4esd6u { bottom: 10px; }
+ .x-jwnrsh { left: 10px; }
+ .x-8wdww5 { margin-top: 10px; }
+ .x-1f13l4q { margin-right: 10px; }
+ .x-lx60ht { margin-bottom: 10px; }
+ .x-cl7tym { margin-left: 10px; }
+ .x-jm3jfd { padding-top: 10px; }
+ .x-jlcvdv { padding-right: 10px; }
+ .x-6rz8sj { padding-bottom: 10px; }
+ .x-h002ba { padding-left: 10px; }"
+ `);
+});
diff --git a/__tests__/sheet.ts b/__tests__/sheet.ts
new file mode 100644
index 0000000..e697ba5
--- /dev/null
+++ b/__tests__/sheet.ts
@@ -0,0 +1,71 @@
+import { expect, test } from "vitest";
+import { css } from "../src";
+import { getSheets } from "./utils";
+
+test("sheet create and use different subsheets", async () => {
+ css.make({
+ $reset: {
+ display: "flex",
+ width: 100,
+ height: 100,
+ },
+ box: {
+ animationDuration: "200ms",
+ backgroundColor: "white",
+ color: "red",
+
+ animationName: css.keyframes({
+ from: { opacity: 0 },
+ to: { opacity: 1 },
+ }),
+
+ ":hover": { color: "green" },
+ ":focus": { color: "blue" },
+ ":active": { color: "rebeccapurple" },
+ },
+ });
+
+ const { main, keyframes, reset, atomic, hover, focus, active } = getSheets();
+
+ expect(keyframes.media).toBe("all");
+ expect(reset.media).toBe("all");
+ expect(atomic.media).toBe("all");
+ expect(hover.media).toBe("(hover: hover)");
+ expect(focus.media).toBe("all");
+ expect(active.media).toBe("all");
+
+ expect(main.rules).toHaveLength(6);
+ expect(keyframes.rules).toHaveLength(1);
+ expect(reset.rules).toHaveLength(1);
+ expect(atomic.rules).toHaveLength(4);
+ expect(hover.rules).toHaveLength(1);
+ expect(focus.rules).toHaveLength(1);
+ expect(active.rules).toHaveLength(1);
+
+ expect(keyframes.rules.join("\n")).toMatchInlineSnapshot(
+ `"@keyframes k-1mf61dn { 0% { opacity: 0; } 100% { opacity: 1; } }"`,
+ );
+
+ expect(reset.rules.join("\n")).toMatchInlineSnapshot(
+ `".r-1wfww0e { display: flex; width: 100px; height: 100px; }"`,
+ );
+
+ expect(atomic.rules.join("\n")).toMatchInlineSnapshot(`
+ ".x-brsnw3 { animation-duration: 200ms; }
+ .x-15y6h4w { background-color: rgb(255, 255, 255); }
+ .x-1tkyx38 { color: rgb(255, 0, 0); }
+ .x-j8yzpo { animation-name: k-1mf61dn; }"
+ `);
+
+ expect(hover.rules.join("\n")).toMatchInlineSnapshot(
+ `".h-1w6oenc:hover { color: rgb(0, 128, 0); }"`,
+ );
+
+ expect(focus.rules.join("\n")).toMatchInlineSnapshot(
+ `".f-rc30ek:focus-visible { color: rgb(0, 0, 255); }"`,
+ );
+
+ expect(active.rules.join("\n")).toMatchInlineSnapshot(
+ `".a-1ngrkn9:active { color: rgb(102, 51, 153); }"`,
+ );
+});
diff --git a/__tests__/utils.ts b/__tests__/utils.ts
new file mode 100644
index 0000000..6b92eb5
--- /dev/null
+++ b/__tests__/utils.ts
@@ -0,0 +1,53 @@
+const isMediaRule = (rule: CSSRule | undefined) =>
+ rule != null && rule instanceof CSSMediaRule;
+
+const convertSheet = (sheet: CSSStyleSheet | CSSMediaRule) => ({
+ media: sheet.media.toString(),
+ rules: [...sheet.cssRules].map((rule) => rule.cssText.replace(/\s+/g, " ")),
+});
+
+export const getSheets = () => {
+ const main = document.querySelector(
+ `style[id="swan-stylesheet"]`,
+ )?.sheet;
+
+ if (main == null) {
+ throw new Error("Cannot get main CSSStyleSheet");
+ }
+
+ const keyframes = main.cssRules[0];
+ const reset = main.cssRules[1];
+ const atomic = main.cssRules[2];
+ const hover = main.cssRules[3];
+ const focus = main.cssRules[4];
+ const active = main.cssRules[5];
+
+ if (!isMediaRule(keyframes)) {
+ throw new Error("Cannot get keyframes CSSMediaRule");
+ }
+ if (!isMediaRule(reset)) {
+ throw new Error("Cannot get reset CSSMediaRule");
+ }
+ if (!isMediaRule(atomic)) {
+ throw new Error("Cannot get atomic CSSMediaRule");
+ }
+ if (!isMediaRule(hover)) {
+ throw new Error("Cannot get hover CSSMediaRule");
+ }
+ if (!isMediaRule(focus)) {
+ throw new Error("Cannot get focus CSSMediaRule");
+ }
+ if (!isMediaRule(active)) {
+ throw new Error("Cannot get active CSSMediaRule");
+ }
+
+ return {
+ main: convertSheet(main),
+ keyframes: convertSheet(keyframes),
+ reset: convertSheet(reset),
+ atomic: convertSheet(atomic),
+ hover: convertSheet(hover),
+ focus: convertSheet(focus),
+ active: convertSheet(active),
+ };
+};
diff --git a/package.json b/package.json
index 3925fdc..7092fd6 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,11 @@
"type": "git",
"url": "https://github.com/swan-io/bot-detector.git"
},
+ "packageManager": "pnpm@9.15.3",
+ "engines": {
+ "node": ">=22.13.0",
+ "pnpm": "^9.15.3"
+ },
"source": "src/index.ts",
"main": "dist/index.js",
"module": "dist/index.mjs",
@@ -32,10 +37,12 @@
"clean": "rm -rf dist",
"test:ci": "playwright install --with-deps --only-shell chromium && CI=true vitest --run",
"test": "vitest --run",
+ "test:webkit": "BROWSER=webkit vitest --run",
+ "test:firefox": "BROWSER=firefox vitest --run",
"test:watch": "vitest --watch",
"typecheck": "tsc --noEmit",
"build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",
- "prepack": "pnpm test && pnpm build"
+ "prepack": "pnpm typecheck && pnpm test && pnpm build"
},
"prettier": {
"plugins": [
@@ -43,15 +50,23 @@
]
},
"dependencies": {
- "@emotion/hash": "^0.9.2"
+ "@emotion/hash": "^0.9.2",
+ "@react-native/normalize-colors": "^0.76.5",
+ "csstype": "^3.1.3",
+ "postcss-value-parser": "^4.2.0"
},
"devDependencies": {
+ "@types/react": "^19.0.3",
+ "@types/react-dom": "^19.0.2",
"@vitest/browser": "^2.1.8",
"playwright": "^1.49.1",
"prettier": "^3.4.2",
"prettier-plugin-organize-imports": "^4.1.0",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
"tsup": "^8.3.5",
"typescript": "^5.7.2",
- "vitest": "^2.1.8"
+ "vitest": "^2.1.8",
+ "vitest-browser-react": "^0.0.4"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index da335d1..8a2c9b7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,10 +11,25 @@ importers:
'@emotion/hash':
specifier: ^0.9.2
version: 0.9.2
+ '@react-native/normalize-colors':
+ specifier: ^0.76.5
+ version: 0.76.5
+ csstype:
+ specifier: ^3.1.3
+ version: 3.1.3
+ postcss-value-parser:
+ specifier: ^4.2.0
+ version: 4.2.0
devDependencies:
+ '@types/react':
+ specifier: ^19.0.3
+ version: 19.0.3
+ '@types/react-dom':
+ specifier: ^19.0.2
+ version: 19.0.2(@types/react@19.0.3)
'@vitest/browser':
specifier: ^2.1.8
- version: 2.1.8(@types/node@22.10.2)(playwright@1.49.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.2))(vitest@2.1.8)
+ version: 2.1.8(@types/node@22.10.5)(playwright@1.49.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.5))(vitest@2.1.8)
playwright:
specifier: ^1.49.1
version: 1.49.1
@@ -24,6 +39,12 @@ importers:
prettier-plugin-organize-imports:
specifier: ^4.1.0
version: 4.1.0(prettier@3.4.2)(typescript@5.7.2)
+ react:
+ specifier: ^19.0.0
+ version: 19.0.0
+ react-dom:
+ specifier: ^19.0.0
+ version: 19.0.0(react@19.0.0)
tsup:
specifier: ^8.3.5
version: 8.3.5(postcss@8.4.49)(typescript@5.7.2)
@@ -32,7 +53,10 @@ importers:
version: 5.7.2
vitest:
specifier: ^2.1.8
- version: 2.1.8(@types/node@22.10.2)(@vitest/browser@2.1.8)(msw@2.7.0(@types/node@22.10.2)(typescript@5.7.2))
+ version: 2.1.8(@types/node@22.10.5)(@vitest/browser@2.1.8)(msw@2.7.0(@types/node@22.10.5)(typescript@5.7.2))
+ vitest-browser-react:
+ specifier: ^0.0.4
+ version: 0.0.4(@types/react-dom@19.0.2(@types/react@19.0.3))(@types/react@19.0.3)(@vitest/browser@2.1.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(vitest@2.1.8)
packages:
@@ -66,8 +90,8 @@ packages:
cpu: [ppc64]
os: [aix]
- '@esbuild/aix-ppc64@0.24.0':
- resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
+ '@esbuild/aix-ppc64@0.24.2':
+ resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
@@ -78,8 +102,8 @@ packages:
cpu: [arm64]
os: [android]
- '@esbuild/android-arm64@0.24.0':
- resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
+ '@esbuild/android-arm64@0.24.2':
+ resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
@@ -90,8 +114,8 @@ packages:
cpu: [arm]
os: [android]
- '@esbuild/android-arm@0.24.0':
- resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
+ '@esbuild/android-arm@0.24.2':
+ resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
@@ -102,8 +126,8 @@ packages:
cpu: [x64]
os: [android]
- '@esbuild/android-x64@0.24.0':
- resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
+ '@esbuild/android-x64@0.24.2':
+ resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
@@ -114,8 +138,8 @@ packages:
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-arm64@0.24.0':
- resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
+ '@esbuild/darwin-arm64@0.24.2':
+ resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
@@ -126,8 +150,8 @@ packages:
cpu: [x64]
os: [darwin]
- '@esbuild/darwin-x64@0.24.0':
- resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
+ '@esbuild/darwin-x64@0.24.2':
+ resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
@@ -138,8 +162,8 @@ packages:
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-arm64@0.24.0':
- resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
+ '@esbuild/freebsd-arm64@0.24.2':
+ resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
@@ -150,8 +174,8 @@ packages:
cpu: [x64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.24.0':
- resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
+ '@esbuild/freebsd-x64@0.24.2':
+ resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
@@ -162,8 +186,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm64@0.24.0':
- resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
+ '@esbuild/linux-arm64@0.24.2':
+ resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
@@ -174,8 +198,8 @@ packages:
cpu: [arm]
os: [linux]
- '@esbuild/linux-arm@0.24.0':
- resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
+ '@esbuild/linux-arm@0.24.2':
+ resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
@@ -186,8 +210,8 @@ packages:
cpu: [ia32]
os: [linux]
- '@esbuild/linux-ia32@0.24.0':
- resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
+ '@esbuild/linux-ia32@0.24.2':
+ resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
@@ -198,8 +222,8 @@ packages:
cpu: [loong64]
os: [linux]
- '@esbuild/linux-loong64@0.24.0':
- resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
+ '@esbuild/linux-loong64@0.24.2':
+ resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
@@ -210,8 +234,8 @@ packages:
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-mips64el@0.24.0':
- resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
+ '@esbuild/linux-mips64el@0.24.2':
+ resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
@@ -222,8 +246,8 @@ packages:
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-ppc64@0.24.0':
- resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
+ '@esbuild/linux-ppc64@0.24.2':
+ resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
@@ -234,8 +258,8 @@ packages:
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-riscv64@0.24.0':
- resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
+ '@esbuild/linux-riscv64@0.24.2':
+ resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
@@ -246,8 +270,8 @@ packages:
cpu: [s390x]
os: [linux]
- '@esbuild/linux-s390x@0.24.0':
- resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
+ '@esbuild/linux-s390x@0.24.2':
+ resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
@@ -258,26 +282,32 @@ packages:
cpu: [x64]
os: [linux]
- '@esbuild/linux-x64@0.24.0':
- resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
+ '@esbuild/linux-x64@0.24.2':
+ resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
+ '@esbuild/netbsd-arm64@0.24.2':
+ resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
'@esbuild/netbsd-x64@0.21.5':
resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.24.0':
- resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
+ '@esbuild/netbsd-x64@0.24.2':
+ resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
- '@esbuild/openbsd-arm64@0.24.0':
- resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
+ '@esbuild/openbsd-arm64@0.24.2':
+ resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
@@ -288,8 +318,8 @@ packages:
cpu: [x64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.24.0':
- resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
+ '@esbuild/openbsd-x64@0.24.2':
+ resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
@@ -300,8 +330,8 @@ packages:
cpu: [x64]
os: [sunos]
- '@esbuild/sunos-x64@0.24.0':
- resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
+ '@esbuild/sunos-x64@0.24.2':
+ resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
@@ -312,8 +342,8 @@ packages:
cpu: [arm64]
os: [win32]
- '@esbuild/win32-arm64@0.24.0':
- resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
+ '@esbuild/win32-arm64@0.24.2':
+ resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
@@ -324,8 +354,8 @@ packages:
cpu: [ia32]
os: [win32]
- '@esbuild/win32-ia32@0.24.0':
- resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
+ '@esbuild/win32-ia32@0.24.2':
+ resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
@@ -336,28 +366,28 @@ packages:
cpu: [x64]
os: [win32]
- '@esbuild/win32-x64@0.24.0':
- resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
+ '@esbuild/win32-x64@0.24.2':
+ resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
- '@inquirer/confirm@5.1.0':
- resolution: {integrity: sha512-osaBbIMEqVFjTX5exoqPXs6PilWQdjaLhGtMDXMXg/yxkHXNq43GlxGyTA35lK2HpzUgDN+Cjh/2AmqCN0QJpw==}
+ '@inquirer/confirm@5.1.1':
+ resolution: {integrity: sha512-vVLSbGci+IKQvDOtzpPTCOiEJCNidHcAq9JYVoWTW0svb5FiwSLotkM+JXNXejfjnzVYV9n0DTBythl9+XgTxg==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
- '@inquirer/core@10.1.1':
- resolution: {integrity: sha512-rmZVXy9iZvO3ZStEe/ayuuwIJ23LSF13aPMlLMTQARX6lGUBDHGV8UB5i9MRrfy0+mZwt5/9bdy8llszSD3NQA==}
+ '@inquirer/core@10.1.2':
+ resolution: {integrity: sha512-bHd96F3ezHg1mf/J0Rb4CV8ndCN0v28kUlrHqP7+ECm1C/A+paB7Xh2lbMk6x+kweQC+rZOxM/YeKikzxco8bQ==}
engines: {node: '>=18'}
- '@inquirer/figures@1.0.8':
- resolution: {integrity: sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==}
+ '@inquirer/figures@1.0.9':
+ resolution: {integrity: sha512-BXvGj0ehzrngHTPTDqUoDT3NXL8U0RxUk2zJm2A66RhCEIWdtU1v6GuUqNAgArW4PQ9CinqIWyHdQgdwOj06zQ==}
engines: {node: '>=18'}
- '@inquirer/type@3.0.1':
- resolution: {integrity: sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==}
+ '@inquirer/type@3.0.2':
+ resolution: {integrity: sha512-ZhQ4TvhwHZF+lGhQ2O/rsjo80XoZR5/5qhOY3t6FJuX5XBg5Be8YzYTvaUGJnc12AUGI2nr4QSUE4PhKSigx7g==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
@@ -384,8 +414,8 @@ packages:
'@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
- '@mswjs/interceptors@0.37.3':
- resolution: {integrity: sha512-USvgCL/uOGFtVa6SVyRrC8kIAedzRohxIXN5LISlg5C5vLZCn7dgMFVSNhSF9cuBEFrm/O2spDWEZeMnw4ZXYg==}
+ '@mswjs/interceptors@0.37.5':
+ resolution: {integrity: sha512-AAwRb5vXFcY4L+FvZ7LZusDuZ0vEe0Zm8ohn1FM6/X7A3bj4mqmkAcGRWuvC2JwSygNwHAAmMnAI73vPHeqsHA==}
engines: {node: '>=18'}
'@open-draft/deferred-promise@2.2.0':
@@ -404,98 +434,101 @@ packages:
'@polka/url@1.0.0-next.28':
resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==}
- '@rollup/rollup-android-arm-eabi@4.28.1':
- resolution: {integrity: sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==}
+ '@react-native/normalize-colors@0.76.5':
+ resolution: {integrity: sha512-6QRLEok1r55gLqj+94mEWUENuU5A6wsr2OoXpyq/CgQ7THWowbHtru/kRGRr6o3AQXrVnZheR60JNgFcpNYIug==}
+
+ '@rollup/rollup-android-arm-eabi@4.30.1':
+ resolution: {integrity: sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==}
cpu: [arm]
os: [android]
- '@rollup/rollup-android-arm64@4.28.1':
- resolution: {integrity: sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==}
+ '@rollup/rollup-android-arm64@4.30.1':
+ resolution: {integrity: sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==}
cpu: [arm64]
os: [android]
- '@rollup/rollup-darwin-arm64@4.28.1':
- resolution: {integrity: sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==}
+ '@rollup/rollup-darwin-arm64@4.30.1':
+ resolution: {integrity: sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==}
cpu: [arm64]
os: [darwin]
- '@rollup/rollup-darwin-x64@4.28.1':
- resolution: {integrity: sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==}
+ '@rollup/rollup-darwin-x64@4.30.1':
+ resolution: {integrity: sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==}
cpu: [x64]
os: [darwin]
- '@rollup/rollup-freebsd-arm64@4.28.1':
- resolution: {integrity: sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==}
+ '@rollup/rollup-freebsd-arm64@4.30.1':
+ resolution: {integrity: sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==}
cpu: [arm64]
os: [freebsd]
- '@rollup/rollup-freebsd-x64@4.28.1':
- resolution: {integrity: sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==}
+ '@rollup/rollup-freebsd-x64@4.30.1':
+ resolution: {integrity: sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==}
cpu: [x64]
os: [freebsd]
- '@rollup/rollup-linux-arm-gnueabihf@4.28.1':
- resolution: {integrity: sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==}
+ '@rollup/rollup-linux-arm-gnueabihf@4.30.1':
+ resolution: {integrity: sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==}
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm-musleabihf@4.28.1':
- resolution: {integrity: sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==}
+ '@rollup/rollup-linux-arm-musleabihf@4.30.1':
+ resolution: {integrity: sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==}
cpu: [arm]
os: [linux]
- '@rollup/rollup-linux-arm64-gnu@4.28.1':
- resolution: {integrity: sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==}
+ '@rollup/rollup-linux-arm64-gnu@4.30.1':
+ resolution: {integrity: sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==}
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-arm64-musl@4.28.1':
- resolution: {integrity: sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==}
+ '@rollup/rollup-linux-arm64-musl@4.30.1':
+ resolution: {integrity: sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==}
cpu: [arm64]
os: [linux]
- '@rollup/rollup-linux-loongarch64-gnu@4.28.1':
- resolution: {integrity: sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==}
+ '@rollup/rollup-linux-loongarch64-gnu@4.30.1':
+ resolution: {integrity: sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==}
cpu: [loong64]
os: [linux]
- '@rollup/rollup-linux-powerpc64le-gnu@4.28.1':
- resolution: {integrity: sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==}
+ '@rollup/rollup-linux-powerpc64le-gnu@4.30.1':
+ resolution: {integrity: sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==}
cpu: [ppc64]
os: [linux]
- '@rollup/rollup-linux-riscv64-gnu@4.28.1':
- resolution: {integrity: sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==}
+ '@rollup/rollup-linux-riscv64-gnu@4.30.1':
+ resolution: {integrity: sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==}
cpu: [riscv64]
os: [linux]
- '@rollup/rollup-linux-s390x-gnu@4.28.1':
- resolution: {integrity: sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==}
+ '@rollup/rollup-linux-s390x-gnu@4.30.1':
+ resolution: {integrity: sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==}
cpu: [s390x]
os: [linux]
- '@rollup/rollup-linux-x64-gnu@4.28.1':
- resolution: {integrity: sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==}
+ '@rollup/rollup-linux-x64-gnu@4.30.1':
+ resolution: {integrity: sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==}
cpu: [x64]
os: [linux]
- '@rollup/rollup-linux-x64-musl@4.28.1':
- resolution: {integrity: sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==}
+ '@rollup/rollup-linux-x64-musl@4.30.1':
+ resolution: {integrity: sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==}
cpu: [x64]
os: [linux]
- '@rollup/rollup-win32-arm64-msvc@4.28.1':
- resolution: {integrity: sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==}
+ '@rollup/rollup-win32-arm64-msvc@4.30.1':
+ resolution: {integrity: sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==}
cpu: [arm64]
os: [win32]
- '@rollup/rollup-win32-ia32-msvc@4.28.1':
- resolution: {integrity: sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==}
+ '@rollup/rollup-win32-ia32-msvc@4.30.1':
+ resolution: {integrity: sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==}
cpu: [ia32]
os: [win32]
- '@rollup/rollup-win32-x64-msvc@4.28.1':
- resolution: {integrity: sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==}
+ '@rollup/rollup-win32-x64-msvc@4.30.1':
+ resolution: {integrity: sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==}
cpu: [x64]
os: [win32]
@@ -518,8 +551,16 @@ packages:
'@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
- '@types/node@22.10.2':
- resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==}
+ '@types/node@22.10.5':
+ resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==}
+
+ '@types/react-dom@19.0.2':
+ resolution: {integrity: sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==}
+ peerDependencies:
+ '@types/react': ^19.0.0
+
+ '@types/react@19.0.3':
+ resolution: {integrity: sha512-UavfHguIjnnuq9O67uXfgy/h3SRJbidAYvNjLceB+2RIKVRBzVsh0QO+Pw6BCSQqFS9xwzKfwstXx0m6AbAREA==}
'@types/statuses@2.0.5':
resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==}
@@ -611,8 +652,8 @@ packages:
brace-expansion@2.0.1:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
- bundle-require@5.0.0:
- resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==}
+ bundle-require@5.1.0:
+ resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
peerDependencies:
esbuild: '>=0.18'
@@ -633,8 +674,8 @@ packages:
resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
engines: {node: '>= 16'}
- chokidar@4.0.2:
- resolution: {integrity: sha512-/b57FK+bblSU+dfewfFe0rT1YjVDfOmeLQwCAuC+vwvgLkXboATqqmy+Ipux6JrF6L5joe5CBnFOw+gLWH6yKg==}
+ chokidar@4.0.3:
+ resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
cli-width@4.1.0:
@@ -656,8 +697,8 @@ packages:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
- consola@3.2.3:
- resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==}
+ consola@3.3.3:
+ resolution: {integrity: sha512-Qil5KwghMzlqd51UXM0b6fyaGHtOC22scxrwrz4A2882LyUMwQjnvaedN1HAeXzphspQ6CpHkzMAWxBTUruDLg==}
engines: {node: ^14.18.0 || >=16.10.0}
cookie@0.7.2:
@@ -668,6 +709,9 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
debug@4.4.0:
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
engines: {node: '>=6.0'}
@@ -697,16 +741,16 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
- es-module-lexer@1.5.4:
- resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
+ es-module-lexer@1.6.0:
+ resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==}
esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'}
hasBin: true
- esbuild@0.24.0:
- resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
+ esbuild@0.24.2:
+ resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==}
engines: {node: '>=18'}
hasBin: true
@@ -913,6 +957,9 @@ packages:
yaml:
optional: true
+ postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
postcss@8.4.49:
resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
engines: {node: ^10 || ^12 || >=14}
@@ -946,9 +993,18 @@ packages:
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
+ react-dom@19.0.0:
+ resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==}
+ peerDependencies:
+ react: ^19.0.0
+
react-is@17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
+ react@19.0.0:
+ resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
+ engines: {node: '>=0.10.0'}
+
readdirp@4.0.2:
resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
engines: {node: '>= 14.16.0'}
@@ -967,11 +1023,14 @@ packages:
resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
engines: {node: '>=8'}
- rollup@4.28.1:
- resolution: {integrity: sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==}
+ rollup@4.30.1:
+ resolution: {integrity: sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
+ scheduler@0.25.0:
+ resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
+
shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'}
@@ -1047,8 +1106,8 @@ packages:
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
- tinyexec@0.3.1:
- resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==}
+ tinyexec@0.3.2:
+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
tinyglobby@0.2.10:
resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==}
@@ -1107,8 +1166,8 @@ packages:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
- type-fest@4.30.2:
- resolution: {integrity: sha512-UJShLPYi1aWqCdq9HycOL/gwsuqda1OISdBO3t8RlXQC4QvtuIz4b5FCfe2dQIWEpmlRExKmcTBfP1r9bhY7ig==}
+ type-fest@4.31.0:
+ resolution: {integrity: sha512-yCxltHW07Nkhv/1F6wWBr8kz+5BGMfP+RbRSYFnegVb0qV/UMT0G0ElBloPVerqn4M2ZV80Ir1FtCcYv1cT6vQ==}
engines: {node: '>=16'}
typescript@5.7.2:
@@ -1162,6 +1221,22 @@ packages:
terser:
optional: true
+ vitest-browser-react@0.0.4:
+ resolution: {integrity: sha512-4uK8zgo5eHlhrBVEPX8ejRt8Bn4gzV6OZFTPdb1en3FtgjEhhst400XkIQHUC875Q90rOO5Tc4zPpCl8YXvoxg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ peerDependencies:
+ '@types/react': '>18.0.0'
+ '@types/react-dom': '>18.0.0'
+ '@vitest/browser': '>=2.1.0'
+ react: '>18.0.0'
+ react-dom: '>18.0.0'
+ vitest: '>=2.1.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
vitest@2.1.8:
resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -1275,154 +1350,157 @@ snapshots:
'@esbuild/aix-ppc64@0.21.5':
optional: true
- '@esbuild/aix-ppc64@0.24.0':
+ '@esbuild/aix-ppc64@0.24.2':
optional: true
'@esbuild/android-arm64@0.21.5':
optional: true
- '@esbuild/android-arm64@0.24.0':
+ '@esbuild/android-arm64@0.24.2':
optional: true
'@esbuild/android-arm@0.21.5':
optional: true
- '@esbuild/android-arm@0.24.0':
+ '@esbuild/android-arm@0.24.2':
optional: true
'@esbuild/android-x64@0.21.5':
optional: true
- '@esbuild/android-x64@0.24.0':
+ '@esbuild/android-x64@0.24.2':
optional: true
'@esbuild/darwin-arm64@0.21.5':
optional: true
- '@esbuild/darwin-arm64@0.24.0':
+ '@esbuild/darwin-arm64@0.24.2':
optional: true
'@esbuild/darwin-x64@0.21.5':
optional: true
- '@esbuild/darwin-x64@0.24.0':
+ '@esbuild/darwin-x64@0.24.2':
optional: true
'@esbuild/freebsd-arm64@0.21.5':
optional: true
- '@esbuild/freebsd-arm64@0.24.0':
+ '@esbuild/freebsd-arm64@0.24.2':
optional: true
'@esbuild/freebsd-x64@0.21.5':
optional: true
- '@esbuild/freebsd-x64@0.24.0':
+ '@esbuild/freebsd-x64@0.24.2':
optional: true
'@esbuild/linux-arm64@0.21.5':
optional: true
- '@esbuild/linux-arm64@0.24.0':
+ '@esbuild/linux-arm64@0.24.2':
optional: true
'@esbuild/linux-arm@0.21.5':
optional: true
- '@esbuild/linux-arm@0.24.0':
+ '@esbuild/linux-arm@0.24.2':
optional: true
'@esbuild/linux-ia32@0.21.5':
optional: true
- '@esbuild/linux-ia32@0.24.0':
+ '@esbuild/linux-ia32@0.24.2':
optional: true
'@esbuild/linux-loong64@0.21.5':
optional: true
- '@esbuild/linux-loong64@0.24.0':
+ '@esbuild/linux-loong64@0.24.2':
optional: true
'@esbuild/linux-mips64el@0.21.5':
optional: true
- '@esbuild/linux-mips64el@0.24.0':
+ '@esbuild/linux-mips64el@0.24.2':
optional: true
'@esbuild/linux-ppc64@0.21.5':
optional: true
- '@esbuild/linux-ppc64@0.24.0':
+ '@esbuild/linux-ppc64@0.24.2':
optional: true
'@esbuild/linux-riscv64@0.21.5':
optional: true
- '@esbuild/linux-riscv64@0.24.0':
+ '@esbuild/linux-riscv64@0.24.2':
optional: true
'@esbuild/linux-s390x@0.21.5':
optional: true
- '@esbuild/linux-s390x@0.24.0':
+ '@esbuild/linux-s390x@0.24.2':
optional: true
'@esbuild/linux-x64@0.21.5':
optional: true
- '@esbuild/linux-x64@0.24.0':
+ '@esbuild/linux-x64@0.24.2':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.24.2':
optional: true
'@esbuild/netbsd-x64@0.21.5':
optional: true
- '@esbuild/netbsd-x64@0.24.0':
+ '@esbuild/netbsd-x64@0.24.2':
optional: true
- '@esbuild/openbsd-arm64@0.24.0':
+ '@esbuild/openbsd-arm64@0.24.2':
optional: true
'@esbuild/openbsd-x64@0.21.5':
optional: true
- '@esbuild/openbsd-x64@0.24.0':
+ '@esbuild/openbsd-x64@0.24.2':
optional: true
'@esbuild/sunos-x64@0.21.5':
optional: true
- '@esbuild/sunos-x64@0.24.0':
+ '@esbuild/sunos-x64@0.24.2':
optional: true
'@esbuild/win32-arm64@0.21.5':
optional: true
- '@esbuild/win32-arm64@0.24.0':
+ '@esbuild/win32-arm64@0.24.2':
optional: true
'@esbuild/win32-ia32@0.21.5':
optional: true
- '@esbuild/win32-ia32@0.24.0':
+ '@esbuild/win32-ia32@0.24.2':
optional: true
'@esbuild/win32-x64@0.21.5':
optional: true
- '@esbuild/win32-x64@0.24.0':
+ '@esbuild/win32-x64@0.24.2':
optional: true
- '@inquirer/confirm@5.1.0(@types/node@22.10.2)':
+ '@inquirer/confirm@5.1.1(@types/node@22.10.5)':
dependencies:
- '@inquirer/core': 10.1.1(@types/node@22.10.2)
- '@inquirer/type': 3.0.1(@types/node@22.10.2)
- '@types/node': 22.10.2
+ '@inquirer/core': 10.1.2(@types/node@22.10.5)
+ '@inquirer/type': 3.0.2(@types/node@22.10.5)
+ '@types/node': 22.10.5
- '@inquirer/core@10.1.1(@types/node@22.10.2)':
+ '@inquirer/core@10.1.2(@types/node@22.10.5)':
dependencies:
- '@inquirer/figures': 1.0.8
- '@inquirer/type': 3.0.1(@types/node@22.10.2)
+ '@inquirer/figures': 1.0.9
+ '@inquirer/type': 3.0.2(@types/node@22.10.5)
ansi-escapes: 4.3.2
cli-width: 4.1.0
mute-stream: 2.0.0
@@ -1433,11 +1511,11 @@ snapshots:
transitivePeerDependencies:
- '@types/node'
- '@inquirer/figures@1.0.8': {}
+ '@inquirer/figures@1.0.9': {}
- '@inquirer/type@3.0.1(@types/node@22.10.2)':
+ '@inquirer/type@3.0.2(@types/node@22.10.5)':
dependencies:
- '@types/node': 22.10.2
+ '@types/node': 22.10.5
'@isaacs/cliui@8.0.2':
dependencies:
@@ -1465,7 +1543,7 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
- '@mswjs/interceptors@0.37.3':
+ '@mswjs/interceptors@0.37.5':
dependencies:
'@open-draft/deferred-promise': 2.2.0
'@open-draft/logger': 0.3.0
@@ -1488,61 +1566,63 @@ snapshots:
'@polka/url@1.0.0-next.28': {}
- '@rollup/rollup-android-arm-eabi@4.28.1':
+ '@react-native/normalize-colors@0.76.5': {}
+
+ '@rollup/rollup-android-arm-eabi@4.30.1':
optional: true
- '@rollup/rollup-android-arm64@4.28.1':
+ '@rollup/rollup-android-arm64@4.30.1':
optional: true
- '@rollup/rollup-darwin-arm64@4.28.1':
+ '@rollup/rollup-darwin-arm64@4.30.1':
optional: true
- '@rollup/rollup-darwin-x64@4.28.1':
+ '@rollup/rollup-darwin-x64@4.30.1':
optional: true
- '@rollup/rollup-freebsd-arm64@4.28.1':
+ '@rollup/rollup-freebsd-arm64@4.30.1':
optional: true
- '@rollup/rollup-freebsd-x64@4.28.1':
+ '@rollup/rollup-freebsd-x64@4.30.1':
optional: true
- '@rollup/rollup-linux-arm-gnueabihf@4.28.1':
+ '@rollup/rollup-linux-arm-gnueabihf@4.30.1':
optional: true
- '@rollup/rollup-linux-arm-musleabihf@4.28.1':
+ '@rollup/rollup-linux-arm-musleabihf@4.30.1':
optional: true
- '@rollup/rollup-linux-arm64-gnu@4.28.1':
+ '@rollup/rollup-linux-arm64-gnu@4.30.1':
optional: true
- '@rollup/rollup-linux-arm64-musl@4.28.1':
+ '@rollup/rollup-linux-arm64-musl@4.30.1':
optional: true
- '@rollup/rollup-linux-loongarch64-gnu@4.28.1':
+ '@rollup/rollup-linux-loongarch64-gnu@4.30.1':
optional: true
- '@rollup/rollup-linux-powerpc64le-gnu@4.28.1':
+ '@rollup/rollup-linux-powerpc64le-gnu@4.30.1':
optional: true
- '@rollup/rollup-linux-riscv64-gnu@4.28.1':
+ '@rollup/rollup-linux-riscv64-gnu@4.30.1':
optional: true
- '@rollup/rollup-linux-s390x-gnu@4.28.1':
+ '@rollup/rollup-linux-s390x-gnu@4.30.1':
optional: true
- '@rollup/rollup-linux-x64-gnu@4.28.1':
+ '@rollup/rollup-linux-x64-gnu@4.30.1':
optional: true
- '@rollup/rollup-linux-x64-musl@4.28.1':
+ '@rollup/rollup-linux-x64-musl@4.30.1':
optional: true
- '@rollup/rollup-win32-arm64-msvc@4.28.1':
+ '@rollup/rollup-win32-arm64-msvc@4.30.1':
optional: true
- '@rollup/rollup-win32-ia32-msvc@4.28.1':
+ '@rollup/rollup-win32-ia32-msvc@4.30.1':
optional: true
- '@rollup/rollup-win32-x64-msvc@4.28.1':
+ '@rollup/rollup-win32-x64-msvc@4.30.1':
optional: true
'@testing-library/dom@10.4.0':
@@ -1566,25 +1646,33 @@ snapshots:
'@types/estree@1.0.6': {}
- '@types/node@22.10.2':
+ '@types/node@22.10.5':
dependencies:
undici-types: 6.20.0
+ '@types/react-dom@19.0.2(@types/react@19.0.3)':
+ dependencies:
+ '@types/react': 19.0.3
+
+ '@types/react@19.0.3':
+ dependencies:
+ csstype: 3.1.3
+
'@types/statuses@2.0.5': {}
'@types/tough-cookie@4.0.5': {}
- '@vitest/browser@2.1.8(@types/node@22.10.2)(playwright@1.49.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.2))(vitest@2.1.8)':
+ '@vitest/browser@2.1.8(@types/node@22.10.5)(playwright@1.49.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.5))(vitest@2.1.8)':
dependencies:
'@testing-library/dom': 10.4.0
'@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0)
- '@vitest/mocker': 2.1.8(msw@2.7.0(@types/node@22.10.2)(typescript@5.7.2))(vite@5.4.11(@types/node@22.10.2))
+ '@vitest/mocker': 2.1.8(msw@2.7.0(@types/node@22.10.5)(typescript@5.7.2))(vite@5.4.11(@types/node@22.10.5))
'@vitest/utils': 2.1.8
magic-string: 0.30.17
- msw: 2.7.0(@types/node@22.10.2)(typescript@5.7.2)
+ msw: 2.7.0(@types/node@22.10.5)(typescript@5.7.2)
sirv: 3.0.0
tinyrainbow: 1.2.0
- vitest: 2.1.8(@types/node@22.10.2)(@vitest/browser@2.1.8)(msw@2.7.0(@types/node@22.10.2)(typescript@5.7.2))
+ vitest: 2.1.8(@types/node@22.10.5)(@vitest/browser@2.1.8)(msw@2.7.0(@types/node@22.10.5)(typescript@5.7.2))
ws: 8.18.0
optionalDependencies:
playwright: 1.49.1
@@ -1602,14 +1690,14 @@ snapshots:
chai: 5.1.2
tinyrainbow: 1.2.0
- '@vitest/mocker@2.1.8(msw@2.7.0(@types/node@22.10.2)(typescript@5.7.2))(vite@5.4.11(@types/node@22.10.2))':
+ '@vitest/mocker@2.1.8(msw@2.7.0(@types/node@22.10.5)(typescript@5.7.2))(vite@5.4.11(@types/node@22.10.5))':
dependencies:
'@vitest/spy': 2.1.8
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
- msw: 2.7.0(@types/node@22.10.2)(typescript@5.7.2)
- vite: 5.4.11(@types/node@22.10.2)
+ msw: 2.7.0(@types/node@22.10.5)(typescript@5.7.2)
+ vite: 5.4.11(@types/node@22.10.5)
'@vitest/pretty-format@2.1.8':
dependencies:
@@ -1666,9 +1754,9 @@ snapshots:
dependencies:
balanced-match: 1.0.2
- bundle-require@5.0.0(esbuild@0.24.0):
+ bundle-require@5.1.0(esbuild@0.24.2):
dependencies:
- esbuild: 0.24.0
+ esbuild: 0.24.2
load-tsconfig: 0.2.5
cac@6.7.14: {}
@@ -1688,7 +1776,7 @@ snapshots:
check-error@2.1.1: {}
- chokidar@4.0.2:
+ chokidar@4.0.3:
dependencies:
readdirp: 4.0.2
@@ -1708,7 +1796,7 @@ snapshots:
commander@4.1.1: {}
- consola@3.2.3: {}
+ consola@3.3.3: {}
cookie@0.7.2: {}
@@ -1718,6 +1806,8 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
+ csstype@3.1.3: {}
+
debug@4.4.0:
dependencies:
ms: 2.1.3
@@ -1734,7 +1824,7 @@ snapshots:
emoji-regex@9.2.2: {}
- es-module-lexer@1.5.4: {}
+ es-module-lexer@1.6.0: {}
esbuild@0.21.5:
optionalDependencies:
@@ -1762,32 +1852,33 @@ snapshots:
'@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5
- esbuild@0.24.0:
+ esbuild@0.24.2:
optionalDependencies:
- '@esbuild/aix-ppc64': 0.24.0
- '@esbuild/android-arm': 0.24.0
- '@esbuild/android-arm64': 0.24.0
- '@esbuild/android-x64': 0.24.0
- '@esbuild/darwin-arm64': 0.24.0
- '@esbuild/darwin-x64': 0.24.0
- '@esbuild/freebsd-arm64': 0.24.0
- '@esbuild/freebsd-x64': 0.24.0
- '@esbuild/linux-arm': 0.24.0
- '@esbuild/linux-arm64': 0.24.0
- '@esbuild/linux-ia32': 0.24.0
- '@esbuild/linux-loong64': 0.24.0
- '@esbuild/linux-mips64el': 0.24.0
- '@esbuild/linux-ppc64': 0.24.0
- '@esbuild/linux-riscv64': 0.24.0
- '@esbuild/linux-s390x': 0.24.0
- '@esbuild/linux-x64': 0.24.0
- '@esbuild/netbsd-x64': 0.24.0
- '@esbuild/openbsd-arm64': 0.24.0
- '@esbuild/openbsd-x64': 0.24.0
- '@esbuild/sunos-x64': 0.24.0
- '@esbuild/win32-arm64': 0.24.0
- '@esbuild/win32-ia32': 0.24.0
- '@esbuild/win32-x64': 0.24.0
+ '@esbuild/aix-ppc64': 0.24.2
+ '@esbuild/android-arm': 0.24.2
+ '@esbuild/android-arm64': 0.24.2
+ '@esbuild/android-x64': 0.24.2
+ '@esbuild/darwin-arm64': 0.24.2
+ '@esbuild/darwin-x64': 0.24.2
+ '@esbuild/freebsd-arm64': 0.24.2
+ '@esbuild/freebsd-x64': 0.24.2
+ '@esbuild/linux-arm': 0.24.2
+ '@esbuild/linux-arm64': 0.24.2
+ '@esbuild/linux-ia32': 0.24.2
+ '@esbuild/linux-loong64': 0.24.2
+ '@esbuild/linux-mips64el': 0.24.2
+ '@esbuild/linux-ppc64': 0.24.2
+ '@esbuild/linux-riscv64': 0.24.2
+ '@esbuild/linux-s390x': 0.24.2
+ '@esbuild/linux-x64': 0.24.2
+ '@esbuild/netbsd-arm64': 0.24.2
+ '@esbuild/netbsd-x64': 0.24.2
+ '@esbuild/openbsd-arm64': 0.24.2
+ '@esbuild/openbsd-x64': 0.24.2
+ '@esbuild/sunos-x64': 0.24.2
+ '@esbuild/win32-arm64': 0.24.2
+ '@esbuild/win32-ia32': 0.24.2
+ '@esbuild/win32-x64': 0.24.2
escalade@3.2.0: {}
@@ -1873,13 +1964,13 @@ snapshots:
ms@2.1.3: {}
- msw@2.7.0(@types/node@22.10.2)(typescript@5.7.2):
+ msw@2.7.0(@types/node@22.10.5)(typescript@5.7.2):
dependencies:
'@bundled-es-modules/cookie': 2.0.1
'@bundled-es-modules/statuses': 1.0.1
'@bundled-es-modules/tough-cookie': 0.1.6
- '@inquirer/confirm': 5.1.0(@types/node@22.10.2)
- '@mswjs/interceptors': 0.37.3
+ '@inquirer/confirm': 5.1.1(@types/node@22.10.5)
+ '@mswjs/interceptors': 0.37.5
'@open-draft/deferred-promise': 2.2.0
'@open-draft/until': 2.1.0
'@types/cookie': 0.6.0
@@ -1891,7 +1982,7 @@ snapshots:
path-to-regexp: 6.3.0
picocolors: 1.1.1
strict-event-emitter: 0.5.1
- type-fest: 4.30.2
+ type-fest: 4.31.0
yargs: 17.7.2
optionalDependencies:
typescript: 5.7.2
@@ -1947,6 +2038,8 @@ snapshots:
optionalDependencies:
postcss: 8.4.49
+ postcss-value-parser@4.2.0: {}
+
postcss@8.4.49:
dependencies:
nanoid: 3.3.8
@@ -1974,8 +2067,15 @@ snapshots:
querystringify@2.2.0: {}
+ react-dom@19.0.0(react@19.0.0):
+ dependencies:
+ react: 19.0.0
+ scheduler: 0.25.0
+
react-is@17.0.2: {}
+ react@19.0.0: {}
+
readdirp@4.0.2: {}
regenerator-runtime@0.14.1: {}
@@ -1986,31 +2086,33 @@ snapshots:
resolve-from@5.0.0: {}
- rollup@4.28.1:
+ rollup@4.30.1:
dependencies:
'@types/estree': 1.0.6
optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.28.1
- '@rollup/rollup-android-arm64': 4.28.1
- '@rollup/rollup-darwin-arm64': 4.28.1
- '@rollup/rollup-darwin-x64': 4.28.1
- '@rollup/rollup-freebsd-arm64': 4.28.1
- '@rollup/rollup-freebsd-x64': 4.28.1
- '@rollup/rollup-linux-arm-gnueabihf': 4.28.1
- '@rollup/rollup-linux-arm-musleabihf': 4.28.1
- '@rollup/rollup-linux-arm64-gnu': 4.28.1
- '@rollup/rollup-linux-arm64-musl': 4.28.1
- '@rollup/rollup-linux-loongarch64-gnu': 4.28.1
- '@rollup/rollup-linux-powerpc64le-gnu': 4.28.1
- '@rollup/rollup-linux-riscv64-gnu': 4.28.1
- '@rollup/rollup-linux-s390x-gnu': 4.28.1
- '@rollup/rollup-linux-x64-gnu': 4.28.1
- '@rollup/rollup-linux-x64-musl': 4.28.1
- '@rollup/rollup-win32-arm64-msvc': 4.28.1
- '@rollup/rollup-win32-ia32-msvc': 4.28.1
- '@rollup/rollup-win32-x64-msvc': 4.28.1
+ '@rollup/rollup-android-arm-eabi': 4.30.1
+ '@rollup/rollup-android-arm64': 4.30.1
+ '@rollup/rollup-darwin-arm64': 4.30.1
+ '@rollup/rollup-darwin-x64': 4.30.1
+ '@rollup/rollup-freebsd-arm64': 4.30.1
+ '@rollup/rollup-freebsd-x64': 4.30.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.30.1
+ '@rollup/rollup-linux-arm-musleabihf': 4.30.1
+ '@rollup/rollup-linux-arm64-gnu': 4.30.1
+ '@rollup/rollup-linux-arm64-musl': 4.30.1
+ '@rollup/rollup-linux-loongarch64-gnu': 4.30.1
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.30.1
+ '@rollup/rollup-linux-riscv64-gnu': 4.30.1
+ '@rollup/rollup-linux-s390x-gnu': 4.30.1
+ '@rollup/rollup-linux-x64-gnu': 4.30.1
+ '@rollup/rollup-linux-x64-musl': 4.30.1
+ '@rollup/rollup-win32-arm64-msvc': 4.30.1
+ '@rollup/rollup-win32-ia32-msvc': 4.30.1
+ '@rollup/rollup-win32-x64-msvc': 4.30.1
fsevents: 2.3.3
+ scheduler@0.25.0: {}
+
shebang-command@2.0.0:
dependencies:
shebang-regex: 3.0.0
@@ -2085,7 +2187,7 @@ snapshots:
tinybench@2.9.0: {}
- tinyexec@0.3.1: {}
+ tinyexec@0.3.2: {}
tinyglobby@0.2.10:
dependencies:
@@ -2117,20 +2219,20 @@ snapshots:
tsup@8.3.5(postcss@8.4.49)(typescript@5.7.2):
dependencies:
- bundle-require: 5.0.0(esbuild@0.24.0)
+ bundle-require: 5.1.0(esbuild@0.24.2)
cac: 6.7.14
- chokidar: 4.0.2
- consola: 3.2.3
+ chokidar: 4.0.3
+ consola: 3.3.3
debug: 4.4.0
- esbuild: 0.24.0
+ esbuild: 0.24.2
joycon: 3.1.1
picocolors: 1.1.1
postcss-load-config: 6.0.1(postcss@8.4.49)
resolve-from: 5.0.0
- rollup: 4.28.1
+ rollup: 4.30.1
source-map: 0.8.0-beta.0
sucrase: 3.35.0
- tinyexec: 0.3.1
+ tinyexec: 0.3.2
tinyglobby: 0.2.10
tree-kill: 1.2.2
optionalDependencies:
@@ -2144,7 +2246,7 @@ snapshots:
type-fest@0.21.3: {}
- type-fest@4.30.2: {}
+ type-fest@4.31.0: {}
typescript@5.7.2: {}
@@ -2157,13 +2259,13 @@ snapshots:
querystringify: 2.2.0
requires-port: 1.0.0
- vite-node@2.1.8(@types/node@22.10.2):
+ vite-node@2.1.8(@types/node@22.10.5):
dependencies:
cac: 6.7.14
debug: 4.4.0
- es-module-lexer: 1.5.4
+ es-module-lexer: 1.6.0
pathe: 1.1.2
- vite: 5.4.11(@types/node@22.10.2)
+ vite: 5.4.11(@types/node@22.10.5)
transitivePeerDependencies:
- '@types/node'
- less
@@ -2175,19 +2277,29 @@ snapshots:
- supports-color
- terser
- vite@5.4.11(@types/node@22.10.2):
+ vite@5.4.11(@types/node@22.10.5):
dependencies:
esbuild: 0.21.5
postcss: 8.4.49
- rollup: 4.28.1
+ rollup: 4.30.1
optionalDependencies:
- '@types/node': 22.10.2
+ '@types/node': 22.10.5
fsevents: 2.3.3
- vitest@2.1.8(@types/node@22.10.2)(@vitest/browser@2.1.8)(msw@2.7.0(@types/node@22.10.2)(typescript@5.7.2)):
+ vitest-browser-react@0.0.4(@types/react-dom@19.0.2(@types/react@19.0.3))(@types/react@19.0.3)(@vitest/browser@2.1.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(vitest@2.1.8):
+ dependencies:
+ '@vitest/browser': 2.1.8(@types/node@22.10.5)(playwright@1.49.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.5))(vitest@2.1.8)
+ react: 19.0.0
+ react-dom: 19.0.0(react@19.0.0)
+ vitest: 2.1.8(@types/node@22.10.5)(@vitest/browser@2.1.8)(msw@2.7.0(@types/node@22.10.5)(typescript@5.7.2))
+ optionalDependencies:
+ '@types/react': 19.0.3
+ '@types/react-dom': 19.0.2(@types/react@19.0.3)
+
+ vitest@2.1.8(@types/node@22.10.5)(@vitest/browser@2.1.8)(msw@2.7.0(@types/node@22.10.5)(typescript@5.7.2)):
dependencies:
'@vitest/expect': 2.1.8
- '@vitest/mocker': 2.1.8(msw@2.7.0(@types/node@22.10.2)(typescript@5.7.2))(vite@5.4.11(@types/node@22.10.2))
+ '@vitest/mocker': 2.1.8(msw@2.7.0(@types/node@22.10.5)(typescript@5.7.2))(vite@5.4.11(@types/node@22.10.5))
'@vitest/pretty-format': 2.1.8
'@vitest/runner': 2.1.8
'@vitest/snapshot': 2.1.8
@@ -2200,15 +2312,15 @@ snapshots:
pathe: 1.1.2
std-env: 3.8.0
tinybench: 2.9.0
- tinyexec: 0.3.1
+ tinyexec: 0.3.2
tinypool: 1.0.2
tinyrainbow: 1.2.0
- vite: 5.4.11(@types/node@22.10.2)
- vite-node: 2.1.8(@types/node@22.10.2)
+ vite: 5.4.11(@types/node@22.10.5)
+ vite-node: 2.1.8(@types/node@22.10.5)
why-is-node-running: 2.3.0
optionalDependencies:
- '@types/node': 22.10.2
- '@vitest/browser': 2.1.8(@types/node@22.10.2)(playwright@1.49.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.2))(vitest@2.1.8)
+ '@types/node': 22.10.5
+ '@vitest/browser': 2.1.8(@types/node@22.10.5)(playwright@1.49.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.5))(vitest@2.1.8)
transitivePeerDependencies:
- less
- lightningcss
diff --git a/src/hyphenateName.ts b/src/hyphenateName.ts
new file mode 100644
index 0000000..f1295a2
--- /dev/null
+++ b/src/hyphenateName.ts
@@ -0,0 +1,12 @@
+// https://github.com/facebook/react/blob/v19.0.0/packages/react-dom-bindings/src/shared/hyphenateStyleName.js
+
+const uppercasePattern = /([A-Z])/g;
+const hyphenateNameCache: Record = {};
+
+export const hyphenateName = (name: string): string => {
+ hyphenateNameCache[name] ??= name
+ .replace(uppercasePattern, "-$1")
+ .toLowerCase();
+
+ return hyphenateNameCache[name];
+};
diff --git a/src/index.ts b/src/index.ts
index 1fd4236..abb0d21 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,3 +1,31 @@
-export const helloWorld = () => {
- console.log("Hello world");
+import {
+ preprocessAtomicStyle,
+ preprocessKeyframes,
+ preprocessResetStyle,
+} from "./preprocess";
+import { createSheet } from "./sheet";
+import { Keyframes, Nestable, Style } from "./types";
+import { forEach } from "./utils";
+
+const sheet = createSheet();
+
+const keyframes = (keyframes: Keyframes): string | undefined =>
+ sheet.insertKeyframes(preprocessKeyframes(keyframes));
+
+const make = (
+ styles: Record>,
+): Record => {
+ const output = {} as Record;
+
+ forEach(styles, (key, value) => {
+ output[key] =
+ key[0] === "$"
+ ? sheet.insertResetRule(preprocessResetStyle(value))
+ : sheet.insertAtomicRules(preprocessAtomicStyle(value));
+ });
+
+ return output;
};
+
+export const css = { keyframes, make };
+export const cx = sheet.cx;
diff --git a/src/normalizeValue.ts b/src/normalizeValue.ts
new file mode 100644
index 0000000..0ba0467
--- /dev/null
+++ b/src/normalizeValue.ts
@@ -0,0 +1,100 @@
+import normalizeColor from "@react-native/normalize-colors";
+import { Property } from "./types";
+
+const normalizeValueCache: Record = {};
+
+/**
+ * CSS properties which accept numbers but are not in units of "px"
+ * From https://github.com/facebook/react/blob/v19.0.0/packages/react-dom-bindings/src/shared/isUnitlessNumber.js
+ */
+const unitlessProperties = new Set([
+ "animationIterationCount",
+ "aspectRatio",
+ "borderImageOutset",
+ "borderImageSlice",
+ "borderImageWidth",
+ "columnCount",
+ "flex",
+ "flexGrow",
+ "flexShrink",
+ "fontWeight",
+ "gridColumnEnd",
+ "gridColumnStart",
+ "gridRowEnd",
+ "gridRowStart",
+ "lineClamp",
+ "lineHeight",
+ "opacity",
+ "order",
+ "orphans",
+ "scale",
+ "tabSize",
+ "widows",
+ "zIndex",
+ "zoom",
+
+ // SVG-related properties
+ "fillOpacity",
+ "floodOpacity",
+ "stopOpacity",
+ "strokeDasharray",
+ "strokeDashoffset",
+ "strokeMiterlimit",
+ "strokeOpacity",
+ "strokeWidth",
+] satisfies Property[]);
+
+/**
+ * From https://github.com/necolas/react-native-web/blob/0.19.13/packages/react-native-web/src/exports/StyleSheet/compiler/normalizeValueWithProperty.js#L13
+ */
+const colorProperties = new Set([
+ "backgroundColor",
+ "borderBottomColor",
+ "borderColor",
+ "borderLeftColor",
+ "borderRightColor",
+ "borderTopColor",
+ "color",
+ "textDecorationColor",
+] satisfies Property[]);
+
+const isWebColor = (color: string): boolean =>
+ color === "currentcolor" ||
+ color === "currentColor" ||
+ color === "inherit" ||
+ color.indexOf("var(") === 0;
+
+export const normalizeValue = (
+ value: string | number | undefined,
+ property: string,
+): string | undefined => {
+ if (typeof value === "number") {
+ return unitlessProperties.has(property) ? String(value) : `${value}px`;
+ }
+
+ if (colorProperties.has(property)) {
+ if (value == null || isWebColor(value)) {
+ return value;
+ }
+
+ if (normalizeValueCache[value] != null) {
+ return normalizeValueCache[value];
+ }
+
+ const normalizedColor = normalizeColor(value);
+
+ if (normalizedColor != null) {
+ const int = ((normalizedColor << 24) | (normalizedColor >>> 8)) >>> 0;
+
+ const r = (int >> 16) & 255;
+ const g = (int >> 8) & 255;
+ const b = int & 255;
+ const a = ((int >> 24) & 255) / 255;
+
+ normalizeValueCache[value] = `rgba(${r}, ${g}, ${b}, ${a.toFixed(2)})`;
+ return normalizeValueCache[value];
+ }
+ }
+
+ return value;
+};
diff --git a/src/preprocess.ts b/src/preprocess.ts
new file mode 100644
index 0000000..0726632
--- /dev/null
+++ b/src/preprocess.ts
@@ -0,0 +1,178 @@
+import valueParser from "postcss-value-parser";
+import {
+ Keyframes,
+ LonghandProperty,
+ Nestable,
+ Property,
+ ShorthandProperty,
+ Style,
+ ValueOf,
+} from "./types";
+import { forEach } from "./utils";
+
+const shorthands: Partial> = {
+ borderColor: [
+ "borderTopColor",
+ "borderRightColor",
+ "borderBottomColor",
+ "borderLeftColor",
+ ],
+ borderRadius: [
+ "borderTopLeftRadius",
+ "borderTopRightRadius",
+ "borderBottomRightRadius",
+ "borderBottomLeftRadius",
+ ],
+ borderStyle: [
+ "borderTopStyle",
+ "borderRightStyle",
+ "borderBottomStyle",
+ "borderLeftStyle",
+ ],
+ borderWidth: [
+ "borderTopWidth",
+ "borderRightWidth",
+ "borderBottomWidth",
+ "borderLeftWidth",
+ ],
+ gap: ["rowGap", "columnGap"],
+ inset: ["top", "right", "bottom", "left"],
+ insetBlock: ["insetBlockStart", "insetBlockEnd"],
+ insetInline: ["insetInlineStart", "insetInlineEnd"],
+ margin: ["marginTop", "marginRight", "marginBottom", "marginLeft"],
+ marginBlock: ["marginBlockStart", "marginBlockEnd"],
+ marginHorizontal: ["marginRight", "marginLeft"],
+ marginInline: ["marginInlineStart", "marginInlineEnd"],
+ marginVertical: ["marginTop", "marginBottom"],
+ overflow: ["overflowX", "overflowY"],
+ overscrollBehavior: ["overscrollBehaviorX", "overscrollBehaviorY"],
+ padding: ["paddingTop", "paddingRight", "paddingBottom", "paddingLeft"],
+ paddingBlock: ["paddingBlockStart", "paddingBlockEnd"],
+ paddingHorizontal: ["paddingRight", "paddingLeft"],
+ paddingInline: ["paddingInlineStart", "paddingInlineEnd"],
+ paddingVertical: ["paddingTop", "paddingBottom"],
+ scrollMarginBlock: ["scrollMarginBlockStart", "scrollMarginBlockEnd"],
+ scrollMarginInline: ["scrollMarginInlineStart", "scrollMarginInlineEnd"],
+ scrollPaddingBlock: ["scrollPaddingBlockStart", "scrollPaddingBlockEnd"],
+ scrollPaddingInline: ["scrollPaddingInlineStart", "scrollPaddingInlineEnd"],
+} satisfies Record<
+ Exclude,
+ LonghandProperty[]
+>;
+
+const preprocessRule = (
+ acc: Style,
+ key: Property,
+ value: ValueOf