@gtkx/css 0.20.0 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -55
- package/dist/create-css.d.ts +12 -0
- package/dist/create-css.d.ts.map +1 -0
- package/dist/create-css.js +72 -0
- package/dist/create-css.js.map +1 -0
- package/dist/index.d.ts +16 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -2
- package/dist/index.js.map +1 -1
- package/dist/named-colors.d.ts +5 -0
- package/dist/named-colors.d.ts.map +1 -0
- package/dist/named-colors.js +7 -0
- package/dist/named-colors.js.map +1 -0
- package/dist/provider.d.ts +5 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +25 -0
- package/dist/provider.js.map +1 -0
- package/dist/stylesheet.d.ts +9 -0
- package/dist/stylesheet.d.ts.map +1 -0
- package/dist/stylesheet.js +30 -0
- package/dist/stylesheet.js.map +1 -0
- package/package.json +14 -12
- package/src/create-css.ts +98 -0
- package/src/index.ts +18 -2
- package/src/named-colors.ts +14 -0
- package/src/provider.ts +31 -0
- package/src/stylesheet.ts +33 -0
- package/dist/cache.d.ts +0 -3
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js +0 -15
- package/dist/cache.js.map +0 -1
- package/dist/css.d.ts +0 -94
- package/dist/css.d.ts.map +0 -1
- package/dist/css.js +0 -145
- package/dist/css.js.map +0 -1
- package/dist/style-sheet.d.ts +0 -26
- package/dist/style-sheet.d.ts.map +0 -1
- package/dist/style-sheet.js +0 -85
- package/dist/style-sheet.js.map +0 -1
- package/src/cache.ts +0 -20
- package/src/css.ts +0 -162
- package/src/style-sheet.ts +0 -111
package/README.md
CHANGED
|
@@ -1,106 +1,173 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
|
|
2
|
+
<img src="https://raw.githubusercontent.com/gtkx-org/gtkx/main/logo.svg" alt="GTKX" width="100" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">GTKX</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
|
|
8
|
+
The React framework for Linux.<br />
|
|
9
|
+
Build GTK4 and Adwaita apps in TypeScript, with React components and hooks driving GNOME's own widgets. What you ship is a GNOME app.
|
|
9
10
|
</p>
|
|
10
11
|
|
|
11
12
|
<p align="center">
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
<a href="https://www.npmjs.com/package/create-gtkx"><img src="https://img.shields.io/npm/v/create-gtkx?color=cb3837&logo=npm&label=create-gtkx" alt="npm version" /></a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/create-gtkx"><img src="https://img.shields.io/npm/dm/create-gtkx?color=cb3837&logo=npm&label=downloads" alt="npm downloads" /></a>
|
|
15
|
+
<img src="https://img.shields.io/badge/node-%E2%89%A524-339933?logo=node.js&logoColor=white" alt="Node >= 24" />
|
|
16
|
+
<a href="https://github.com/gtkx-org/gtkx/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MPL--2.0-blue.svg" alt="License: MPL-2.0" /></a>
|
|
17
|
+
<a href="https://github.com/gtkx-org/gtkx/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/gtkx-org/gtkx/ci.yml?branch=main&logo=github&label=CI" alt="CI status" /></a>
|
|
18
|
+
<img src="https://img.shields.io/badge/TypeScript-strict-3178c6?logo=typescript&logoColor=white" alt="TypeScript" />
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<a href="https://gtkx.dev">Homepage</a> ·
|
|
23
|
+
<a href="https://gtkx.dev/guide/why-gtkx">Documentation</a> ·
|
|
24
|
+
<a href="https://github.com/gtkx-org/gtkx/tree/main/examples">Examples</a> ·
|
|
25
|
+
<a href="https://github.com/gtkx-org/gtkx/blob/main/CONTRIBUTING.md">Contributing</a>
|
|
16
26
|
</p>
|
|
17
27
|
|
|
18
28
|
---
|
|
19
29
|
|
|
20
|
-
GTKX
|
|
30
|
+
GTKX generates fully typed bindings for the entire GTK4 and Adwaita surface directly from GObject-Introspection. On top of those bindings you get the React programming model: components and hooks driving GObject instances, with Fast Refresh while you develop.
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
<p align="center">
|
|
33
|
+
<img src="https://raw.githubusercontent.com/gtkx-org/gtkx/main/examples/tutorial/assets/screenshot.png" alt="The Tasks app: an Adwaita window with a sidebar of smart views and colored lists on the left, and a boxed task list on the right." />
|
|
34
|
+
</p>
|
|
23
35
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
<p align="center">
|
|
37
|
+
<em>The Tasks app you build in the <a href="https://gtkx.dev/tutorial/">tutorial</a>.</em>
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
## Demo
|
|
29
41
|
|
|
30
|
-
|
|
42
|
+
The intrinsic elements in this snippet render GTK4 widgets, and ordinary React hooks and events drive them:
|
|
31
43
|
|
|
32
44
|
```tsx
|
|
33
|
-
import
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
GtkButton,
|
|
37
|
-
GtkLabel,
|
|
38
|
-
quit,
|
|
39
|
-
render,
|
|
40
|
-
} from "@gtkx/react";
|
|
41
|
-
import * as Gtk from "@gtkx/ffi/gtk";
|
|
45
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
46
|
+
import { GtkApplication, GtkApplicationWindow, GtkBox, GtkButton, GtkLabel } from "@gtkx/jsx/gtk";
|
|
47
|
+
import { createRoot, quit } from "@gtkx/react";
|
|
42
48
|
import { useState } from "react";
|
|
43
49
|
|
|
44
|
-
const
|
|
50
|
+
const Counter = () => {
|
|
45
51
|
const [count, setCount] = useState(0);
|
|
46
52
|
|
|
47
53
|
return (
|
|
48
54
|
<GtkApplicationWindow
|
|
49
|
-
title="
|
|
50
|
-
defaultWidth={
|
|
51
|
-
defaultHeight={
|
|
52
|
-
|
|
55
|
+
title="Hello GTKX"
|
|
56
|
+
defaultWidth={400}
|
|
57
|
+
defaultHeight={300}
|
|
58
|
+
onCloseRequest={quit}
|
|
53
59
|
>
|
|
54
60
|
<GtkBox
|
|
55
61
|
orientation={Gtk.Orientation.VERTICAL}
|
|
56
62
|
spacing={20}
|
|
63
|
+
marginTop={40}
|
|
64
|
+
marginBottom={40}
|
|
65
|
+
marginStart={40}
|
|
66
|
+
marginEnd={40}
|
|
57
67
|
valign={Gtk.Align.CENTER}
|
|
68
|
+
halign={Gtk.Align.CENTER}
|
|
58
69
|
>
|
|
59
|
-
<GtkLabel
|
|
60
|
-
<
|
|
70
|
+
<GtkLabel cssClasses={["title-1"]}>Welcome to GTKX!</GtkLabel>
|
|
71
|
+
<GtkLabel cssClasses={["title-2"]}>{`Count: ${count}`}</GtkLabel>
|
|
72
|
+
<GtkButton
|
|
73
|
+
label="Increment"
|
|
74
|
+
onClicked={() => setCount((c) => c + 1)}
|
|
75
|
+
cssClasses={["suggested-action", "pill"]}
|
|
76
|
+
/>
|
|
61
77
|
</GtkBox>
|
|
62
78
|
</GtkApplicationWindow>
|
|
63
79
|
);
|
|
64
80
|
};
|
|
65
81
|
|
|
66
|
-
|
|
82
|
+
const App = () => (
|
|
83
|
+
<GtkApplication>
|
|
84
|
+
<Counter />
|
|
85
|
+
</GtkApplication>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
createRoot().render(<App />);
|
|
67
89
|
```
|
|
68
90
|
|
|
69
|
-
|
|
91
|
+
This is the [`hello-world`](https://github.com/gtkx-org/gtkx/tree/main/examples/hello-world) example, with `app.tsx` and `index.tsx` combined into a single snippet. `@gtkx/gi` and `@gtkx/jsx` are per-project bindings generated by the CLI, not packages you install from npm.
|
|
70
92
|
|
|
71
|
-
|
|
72
|
-
- **Native GTK4 widgets** — Real native controls, not web components in a webview
|
|
73
|
-
- **Adwaita support** — Modern GNOME styling with Libadwaita components
|
|
74
|
-
- **Declarative animations** — Framer Motion-like API using native Adwaita animations
|
|
75
|
-
- **Hot Module Replacement** — Fast refresh during development
|
|
76
|
-
- **TypeScript first** — Full type safety with auto-generated bindings
|
|
77
|
-
- **CSS-in-JS styling** — Familiar styling patterns adapted for GTK
|
|
78
|
-
- **Testing utilities** — Component testing similar to Testing Library
|
|
93
|
+
## Why GTKX
|
|
79
94
|
|
|
80
|
-
|
|
95
|
+
### A declarative layer for the GNOME stack
|
|
96
|
+
|
|
97
|
+
GTK4 is mature, and GtkBuilder XML can lay out a static interface, but nothing re-renders that interface when your application state changes, and nothing hot-reloads it as you work. GTKX adds that missing layer, and the tooling around it, on top of the stack you already know:
|
|
98
|
+
|
|
99
|
+
- a React reconciler that exposes every GObject as a JSX element,
|
|
100
|
+
- a CLI for scaffolding, development, and production builds,
|
|
101
|
+
- a dev server with Fast Refresh that patches your running UI in place,
|
|
102
|
+
- CSS-in-JS styling and high-level list, grid, and dialog components,
|
|
103
|
+
- a Testing Library-style API for querying and driving your widgets in tests,
|
|
104
|
+
- and a Model Context Protocol (MCP) server that exposes your live app to AI agents.
|
|
105
|
+
|
|
106
|
+
### The full GNOME API surface
|
|
107
|
+
|
|
108
|
+
React Native and similar frameworks hide the native toolkit so one API can run everywhere. GTKX exposes it: GTK4, Adwaita, and any other GObject-Introspection library on your system. Linux-only by design.
|
|
109
|
+
|
|
110
|
+
### Why Node.js, and why generated bindings
|
|
111
|
+
|
|
112
|
+
GTKX runs on Node.js, which puts native modules, the npm ecosystem, and the tooling built for Node.js APIs within reach. GJS is GNOME's own runtime, built on SpiderMonkey rather than V8; node-gtk runs on Node.js but is lightly maintained, on the older nan/V8 ABI rather than N-API, and still centered on GTK3. The [why-gtkx guide](https://gtkx.dev/guide/why-gtkx) covers the comparison in full.
|
|
113
|
+
|
|
114
|
+
GTKX generates the TypeScript types and the native FFI calls from the same GObject-Introspection data, so the types cannot drift from the calls they back. Codegen covers the whole GTK4 and Adwaita surface.
|
|
115
|
+
|
|
116
|
+
At runtime, the native Rust core calls straight into the system GTK4, Adwaita, and GLib libraries through libffi, without loading libgirepository at all.
|
|
81
117
|
|
|
82
|
-
|
|
118
|
+
## Quick start
|
|
83
119
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
120
|
+
GTKX is Linux-only and needs Node.js 24 or later. See [Requirements](#requirements).
|
|
121
|
+
|
|
122
|
+
Scaffold a new app with the `create-gtkx` initializer:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
npm create gtkx@rc
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The same command works with other package managers: `pnpm create gtkx@rc` or `yarn create gtkx@rc`.
|
|
129
|
+
|
|
130
|
+
Then run your new app:
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
cd my-app
|
|
134
|
+
npm run dev
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
To go further, follow the [tutorial](https://gtkx.dev/tutorial/).
|
|
90
138
|
|
|
91
139
|
## Documentation
|
|
92
140
|
|
|
93
|
-
|
|
141
|
+
The documentation at **[gtkx.dev](https://gtkx.dev)** includes a step-by-step tutorial that builds a complete GNOME app, from scaffolding to packaging and shipping, plus guides and a full API reference.
|
|
94
142
|
|
|
95
|
-
|
|
143
|
+
**[Read the docs →](https://gtkx.dev/guide/why-gtkx)**
|
|
96
144
|
|
|
97
|
-
|
|
145
|
+
## Requirements
|
|
98
146
|
|
|
99
|
-
|
|
147
|
+
GTKX is Linux-only. You need:
|
|
148
|
+
|
|
149
|
+
- Linux with the GTK4 (4.20 or later), Adwaita (1.8 or later), and GLib development libraries
|
|
150
|
+
- Node.js 24 or later
|
|
151
|
+
|
|
152
|
+
The `@gtkx/native` addon ships prebuilt for x64 and arm64 glibc Linux; other targets need to build it from the GTKX repository, which requires a Rust toolchain.
|
|
153
|
+
|
|
154
|
+
## Examples
|
|
155
|
+
|
|
156
|
+
Explore the [example apps](https://github.com/gtkx-org/gtkx/tree/main/examples):
|
|
157
|
+
|
|
158
|
+
- [`hello-world`](https://github.com/gtkx-org/gtkx/tree/main/examples/hello-world): the counter above.
|
|
159
|
+
- [`gtk-demo`](https://github.com/gtkx-org/gtkx/tree/main/examples/gtk-demo): a React port of the official GTK4 widget showcase, covering lists, dialogs, gestures, CSS, and OpenGL.
|
|
160
|
+
- [`browser`](https://github.com/gtkx-org/gtkx/tree/main/examples/browser): a WebKitWebView-based web browser.
|
|
161
|
+
- [`tutorial`](https://github.com/gtkx-org/gtkx/tree/main/examples/tutorial): the Tasks app the documentation builds.
|
|
162
|
+
|
|
163
|
+
## Status
|
|
164
|
+
|
|
165
|
+
GTKX 1.0 is at the release candidate stage.
|
|
166
|
+
|
|
167
|
+
## Contributing
|
|
100
168
|
|
|
101
|
-
- [
|
|
102
|
-
- [Issue Tracker](https://github.com/gtkx-org/gtkx/issues) — Bug reports and feature requests
|
|
169
|
+
Contributions are welcome. See [CONTRIBUTING.md](https://github.com/gtkx-org/gtkx/blob/main/CONTRIBUTING.md), the [Code of Conduct](https://github.com/gtkx-org/gtkx/blob/main/CODE_OF_CONDUCT.md), and the [security policy](https://github.com/gtkx-org/gtkx/blob/main/SECURITY.md). Building the repo needs Node.js 24 or later, pnpm, and a Rust toolchain.
|
|
103
170
|
|
|
104
171
|
## License
|
|
105
172
|
|
|
106
|
-
[MPL-2.0](
|
|
173
|
+
GTKX is licensed under [MPL-2.0](https://github.com/gtkx-org/gtkx/blob/main/LICENSE).
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CSSInterpolation } from "@emotion/serialize";
|
|
2
|
+
import type { Element } from "stylis";
|
|
3
|
+
type CxToken = string | boolean | undefined | null;
|
|
4
|
+
export type Css = {
|
|
5
|
+
css: (...args: CSSInterpolation[]) => string;
|
|
6
|
+
cx: (...classNames: CxToken[]) => string[];
|
|
7
|
+
injectGlobal: (...args: CSSInterpolation[]) => void;
|
|
8
|
+
};
|
|
9
|
+
export declare const removeLabel: (element: Element) => void;
|
|
10
|
+
export declare const createCss: () => Css;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=create-css.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-css.d.ts","sourceRoot":"","sources":["../src/create-css.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAqC,MAAM,oBAAoB,CAAC;AAE9F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAUtC,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;AAEnD,MAAM,MAAM,GAAG,GAAG;IACd,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,gBAAgB,EAAE,KAAK,MAAM,CAAC;IAC7C,EAAE,EAAE,CAAC,GAAG,UAAU,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IAC3C,YAAY,EAAE,CAAC,GAAG,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;CACvD,CAAC;AAEF,eAAO,MAAM,WAAW,YAAa,OAAO,KAAG,IAS9C,CAAC;AAiBF,eAAO,MAAM,SAAS,QAAO,GAmD5B,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { serializeStyles } from "@emotion/serialize";
|
|
2
|
+
import { compile, middleware, rulesheet, stringify, serialize as stylisSerialize } from "stylis";
|
|
3
|
+
import { escapeNamedColors, restoreNamedColors } from "./named-colors.js";
|
|
4
|
+
import { StyleSheet } from "./stylesheet.js";
|
|
5
|
+
const KEY = "gtkx";
|
|
6
|
+
const LABEL_DECL_FIRST_CHAR = 108;
|
|
7
|
+
const LABEL_DECL_THIRD_CHAR = 98;
|
|
8
|
+
export const removeLabel = (element) => {
|
|
9
|
+
if (element.type === "decl" &&
|
|
10
|
+
element.value.codePointAt(0) === LABEL_DECL_FIRST_CHAR &&
|
|
11
|
+
element.value.codePointAt(2) === LABEL_DECL_THIRD_CHAR) {
|
|
12
|
+
element.return = "";
|
|
13
|
+
element.value = "";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const classNameFor = (serialized) => `${KEY}-${serialized.name}`;
|
|
17
|
+
const runStylis = (sheet, input) => {
|
|
18
|
+
stylisSerialize(compile(escapeNamedColors(input)), middleware([
|
|
19
|
+
removeLabel,
|
|
20
|
+
stringify,
|
|
21
|
+
rulesheet((rule) => {
|
|
22
|
+
sheet.insert(restoreNamedColors(rule));
|
|
23
|
+
}),
|
|
24
|
+
]));
|
|
25
|
+
};
|
|
26
|
+
export const createCss = () => {
|
|
27
|
+
const sheet = new StyleSheet();
|
|
28
|
+
const inserted = new Set();
|
|
29
|
+
const registered = {};
|
|
30
|
+
const serialize = (args) => serializeStyles(args, registered);
|
|
31
|
+
const insertStyles = (serialized) => {
|
|
32
|
+
if (inserted.has(serialized.name))
|
|
33
|
+
return;
|
|
34
|
+
inserted.add(serialized.name);
|
|
35
|
+
const className = classNameFor(serialized);
|
|
36
|
+
runStylis(sheet, `.${className}{${serialized.styles}}`);
|
|
37
|
+
registered[className] = serialized.styles;
|
|
38
|
+
};
|
|
39
|
+
const insertWithoutScoping = (serialized) => {
|
|
40
|
+
if (inserted.has(serialized.name))
|
|
41
|
+
return;
|
|
42
|
+
inserted.add(serialized.name);
|
|
43
|
+
runStylis(sheet, serialized.styles);
|
|
44
|
+
};
|
|
45
|
+
const css = (...args) => {
|
|
46
|
+
const serialized = serialize(args);
|
|
47
|
+
insertStyles(serialized);
|
|
48
|
+
return classNameFor(serialized);
|
|
49
|
+
};
|
|
50
|
+
const cx = (...classNames) => {
|
|
51
|
+
const tokens = classNames.filter((cn) => typeof cn === "string" && cn.length > 0);
|
|
52
|
+
const rawClasses = [];
|
|
53
|
+
const registeredStyles = [];
|
|
54
|
+
for (const token of tokens) {
|
|
55
|
+
const styles = registered[token];
|
|
56
|
+
if (styles === undefined) {
|
|
57
|
+
rawClasses.push(token);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
registeredStyles.push(styles);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (registeredStyles.length < 2)
|
|
64
|
+
return tokens;
|
|
65
|
+
return [...rawClasses, css(registeredStyles.join(""))];
|
|
66
|
+
};
|
|
67
|
+
const injectGlobal = (...args) => {
|
|
68
|
+
insertWithoutScoping(serialize(args));
|
|
69
|
+
};
|
|
70
|
+
return { css, cx, injectGlobal };
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=create-css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-css.js","sourceRoot":"","sources":["../src/create-css.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CSSInterpolation, RegisteredCache, SerializedStyles } from \"@emotion/serialize\";\nimport { serializeStyles } from \"@emotion/serialize\";\nimport type { Element } from \"stylis\";\nimport { compile, middleware, rulesheet, stringify, serialize as stylisSerialize } from \"stylis\";\nimport { escapeNamedColors, restoreNamedColors } from \"./named-colors.js\";\nimport { StyleSheet } from \"./stylesheet.js\";\n\nconst KEY = \"gtkx\";\n\nconst LABEL_DECL_FIRST_CHAR = 108;\nconst LABEL_DECL_THIRD_CHAR = 98;\n\ntype CxToken = string | boolean | undefined | null;\n\nexport type Css = {\n css: (...args: CSSInterpolation[]) => string;\n cx: (...classNames: CxToken[]) => string[];\n injectGlobal: (...args: CSSInterpolation[]) => void;\n};\n\nexport const removeLabel = (element: Element): void => {\n if (\n element.type === \"decl\" &&\n element.value.codePointAt(0) === LABEL_DECL_FIRST_CHAR &&\n element.value.codePointAt(2) === LABEL_DECL_THIRD_CHAR\n ) {\n element.return = \"\";\n element.value = \"\";\n }\n};\n\nconst classNameFor = (serialized: SerializedStyles): string => `${KEY}-${serialized.name}`;\n\nconst runStylis = (sheet: StyleSheet, input: string): void => {\n stylisSerialize(\n compile(escapeNamedColors(input)),\n middleware([\n removeLabel,\n stringify,\n rulesheet((rule) => {\n sheet.insert(restoreNamedColors(rule));\n }),\n ]),\n );\n};\n\nexport const createCss = (): Css => {\n const sheet = new StyleSheet();\n const inserted = new Set<string>();\n const registered: RegisteredCache = {};\n\n const serialize = (args: CSSInterpolation[]): SerializedStyles => serializeStyles(args, registered);\n\n const insertStyles = (serialized: SerializedStyles): void => {\n if (inserted.has(serialized.name)) return;\n inserted.add(serialized.name);\n const className = classNameFor(serialized);\n runStylis(sheet, `.${className}{${serialized.styles}}`);\n registered[className] = serialized.styles;\n };\n\n const insertWithoutScoping = (serialized: SerializedStyles): void => {\n if (inserted.has(serialized.name)) return;\n inserted.add(serialized.name);\n runStylis(sheet, serialized.styles);\n };\n\n const css = (...args: CSSInterpolation[]): string => {\n const serialized = serialize(args);\n insertStyles(serialized);\n return classNameFor(serialized);\n };\n\n const cx = (...classNames: CxToken[]): string[] => {\n const tokens = classNames.filter((cn): cn is string => typeof cn === \"string\" && cn.length > 0);\n\n const rawClasses: string[] = [];\n const registeredStyles: string[] = [];\n for (const token of tokens) {\n const styles = registered[token];\n if (styles === undefined) {\n rawClasses.push(token);\n } else {\n registeredStyles.push(styles);\n }\n }\n\n if (registeredStyles.length < 2) return tokens;\n\n return [...rawClasses, css(registeredStyles.join(\"\"))];\n };\n\n const injectGlobal = (...args: CSSInterpolation[]): void => {\n insertWithoutScoping(serialize(args));\n };\n\n return { css, cx, injectGlobal };\n};\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { type Css } from "./create-css.js";
|
|
2
|
+
/**
|
|
3
|
+
* Serializes the given style interpolations, inserts the resulting rules into
|
|
4
|
+
* the default stylesheet, and returns the generated GTK4 CSS class name.
|
|
5
|
+
*/
|
|
6
|
+
export declare const css: Css["css"];
|
|
7
|
+
/**
|
|
8
|
+
* Combines class name tokens, filtering out falsy values and merging any
|
|
9
|
+
* gtkx-registered styles into a single generated class.
|
|
10
|
+
*/
|
|
11
|
+
export declare const cx: Css["cx"];
|
|
12
|
+
/**
|
|
13
|
+
* Serializes and inserts the given styles into the default stylesheet globally,
|
|
14
|
+
* without scoping them to a generated class.
|
|
15
|
+
*/
|
|
16
|
+
export declare const injectGlobal: Css["injectGlobal"];
|
|
3
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAa,MAAM,iBAAiB,CAAC;AAItD;;;GAGG;AACH,eAAO,MAAM,GAAG,EAAE,GAAG,CAAC,KAAK,CAAgB,CAAC;AAC5C;;;GAGG;AACH,eAAO,MAAM,EAAE,EAAE,GAAG,CAAC,IAAI,CAAe,CAAC;AACzC;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,GAAG,CAAC,cAAc,CAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { createCss } from "./create-css.js";
|
|
2
|
+
const instance = createCss();
|
|
3
|
+
/**
|
|
4
|
+
* Serializes the given style interpolations, inserts the resulting rules into
|
|
5
|
+
* the default stylesheet, and returns the generated GTK4 CSS class name.
|
|
6
|
+
*/
|
|
7
|
+
export const css = instance.css;
|
|
8
|
+
/**
|
|
9
|
+
* Combines class name tokens, filtering out falsy values and merging any
|
|
10
|
+
* gtkx-registered styles into a single generated class.
|
|
11
|
+
*/
|
|
12
|
+
export const cx = instance.cx;
|
|
13
|
+
/**
|
|
14
|
+
* Serializes and inserts the given styles into the default stylesheet globally,
|
|
15
|
+
* without scoping them to a generated class.
|
|
16
|
+
*/
|
|
17
|
+
export const injectGlobal = instance.injectGlobal;
|
|
3
18
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEtD,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;AAE7B;;;GAGG;AACH,MAAM,CAAC,MAAM,GAAG,GAAe,QAAQ,CAAC,GAAG,CAAC;AAC5C;;;GAGG;AACH,MAAM,CAAC,MAAM,EAAE,GAAc,QAAQ,CAAC,EAAE,CAAC;AACzC;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAwB,QAAQ,CAAC,YAAY,CAAC","sourcesContent":["import { type Css, createCss } from \"./create-css.js\";\n\nconst instance = createCss();\n\n/**\n * Serializes the given style interpolations, inserts the resulting rules into\n * the default stylesheet, and returns the generated GTK4 CSS class name.\n */\nexport const css: Css[\"css\"] = instance.css;\n/**\n * Combines class name tokens, filtering out falsy values and merging any\n * gtkx-registered styles into a single generated class.\n */\nexport const cx: Css[\"cx\"] = instance.cx;\n/**\n * Serializes and inserts the given styles into the default stylesheet globally,\n * without scoping them to a generated class.\n */\nexport const injectGlobal: Css[\"injectGlobal\"] = instance.injectGlobal;\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const AT_RULE_KEYWORDS: Set<string>;
|
|
2
|
+
export declare const NAMED_COLOR_TOKEN = "gtkx-named-color__";
|
|
3
|
+
export declare const escapeNamedColors: (input: string) => string;
|
|
4
|
+
export declare const restoreNamedColors: (rule: string) => string;
|
|
5
|
+
//# sourceMappingURL=named-colors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"named-colors.d.ts","sourceRoot":"","sources":["../src/named-colors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAA6D,CAAC;AAIvG,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAItD,eAAO,MAAM,iBAAiB,UAAW,MAAM,KAAG,MAG7C,CAAC;AAEN,eAAO,MAAM,kBAAkB,SAAU,MAAM,KAAG,MAAwD,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const AT_RULE_KEYWORDS = new Set(["define-color", "import", "keyframes", "media"]);
|
|
2
|
+
const AT_IDENTIFIER_PATTERN = /@([A-Za-z_][\w-]*)/g;
|
|
3
|
+
export const NAMED_COLOR_TOKEN = "gtkx-named-color__";
|
|
4
|
+
const NAMED_COLOR_TOKEN_PATTERN = new RegExp(`${NAMED_COLOR_TOKEN}([\\w-]+)`, "g");
|
|
5
|
+
export const escapeNamedColors = (input) => input.replace(AT_IDENTIFIER_PATTERN, (match, name) => AT_RULE_KEYWORDS.has(name) ? match : `${NAMED_COLOR_TOKEN}${name}`);
|
|
6
|
+
export const restoreNamedColors = (rule) => rule.replace(NAMED_COLOR_TOKEN_PATTERN, "@$1");
|
|
7
|
+
//# sourceMappingURL=named-colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"named-colors.js","sourceRoot":"","sources":["../src/named-colors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAgB,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvG,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAEpD,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAEtD,MAAM,yBAAyB,GAAG,IAAI,MAAM,CAAC,GAAG,iBAAiB,WAAW,EAAE,GAAG,CAAC,CAAC;AAEnF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAU,EAAE,CACvD,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE,CACzD,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,iBAAiB,GAAG,IAAI,EAAE,CACrE,CAAC;AAEN,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC","sourcesContent":["export const AT_RULE_KEYWORDS: Set<string> = new Set([\"define-color\", \"import\", \"keyframes\", \"media\"]);\n\nconst AT_IDENTIFIER_PATTERN = /@([A-Za-z_][\\w-]*)/g;\n\nexport const NAMED_COLOR_TOKEN = \"gtkx-named-color__\";\n\nconst NAMED_COLOR_TOKEN_PATTERN = new RegExp(`${NAMED_COLOR_TOKEN}([\\\\w-]+)`, \"g\");\n\nexport const escapeNamedColors = (input: string): string =>\n input.replace(AT_IDENTIFIER_PATTERN, (match, name: string) =>\n AT_RULE_KEYWORDS.has(name) ? match : `${NAMED_COLOR_TOKEN}${name}`,\n );\n\nexport const restoreNamedColors = (rule: string): string => rule.replace(NAMED_COLOR_TOKEN_PATTERN, \"@$1\");\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { CssProvider } from "@gtkx/gi/gtk";
|
|
2
|
+
import type { Logger } from "@gtkx/utils";
|
|
3
|
+
export declare const registerProviderForDefaultDisplay: (priority?: number) => CssProvider;
|
|
4
|
+
export declare const attachParsingErrorLogger: (provider: CssProvider, log: Logger, subject: string) => void;
|
|
5
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAqD,MAAM,cAAc,CAAC;AAC9F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,eAAO,MAAM,iCAAiC,cAChC,MAAM,KACjB,WAgBF,CAAC;AAEF,eAAO,MAAM,wBAAwB,aAAc,WAAW,OAAO,MAAM,WAAW,MAAM,KAAG,IAM9F,CAAC"}
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DisplayManager } from "@gtkx/gi/gdk";
|
|
2
|
+
import { CssProvider, STYLE_PROVIDER_PRIORITY_APPLICATION, StyleContext } from "@gtkx/gi/gtk";
|
|
3
|
+
export const registerProviderForDefaultDisplay = (priority = STYLE_PROVIDER_PRIORITY_APPLICATION) => {
|
|
4
|
+
const provider = new CssProvider();
|
|
5
|
+
const manager = DisplayManager.get();
|
|
6
|
+
const attach = (display) => {
|
|
7
|
+
StyleContext.addProviderForDisplay(display, provider, priority);
|
|
8
|
+
};
|
|
9
|
+
const initialDisplay = manager.getDefaultDisplay();
|
|
10
|
+
if (initialDisplay) {
|
|
11
|
+
attach(initialDisplay);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
manager.once("display-opened", (openedDisplay) => attach(openedDisplay));
|
|
15
|
+
}
|
|
16
|
+
return provider;
|
|
17
|
+
};
|
|
18
|
+
export const attachParsingErrorLogger = (provider, log, subject) => {
|
|
19
|
+
if (process.env.NODE_ENV !== "production") {
|
|
20
|
+
provider.on("parsing-error", (section, error) => {
|
|
21
|
+
log.warn(`GTK4 rejected ${subject} at ${section.toString()}: ${error.message}`);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,mCAAmC,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG9F,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAC7C,QAAQ,GAAW,mCAAmC,EAC3C,EAAE;IACb,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,CAAC;IAErC,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAQ,EAAE;QACtC,YAAY,CAAC,qBAAqB,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACpE,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IACnD,IAAI,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,cAAc,CAAC,CAAC;IAC3B,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,aAAsB,EAAQ,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;IAC5F,CAAC;IAED,OAAO,QAAQ,CAAC;AACpB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,QAAqB,EAAE,GAAW,EAAE,OAAe,EAAQ,EAAE;IAClG,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QACxC,QAAQ,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;YAC5C,GAAG,CAAC,IAAI,CAAC,iBAAiB,OAAO,OAAO,OAAO,CAAC,QAAQ,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACpF,CAAC,CAAC,CAAC;IACP,CAAC;AACL,CAAC,CAAC","sourcesContent":["import { type Display, DisplayManager } from \"@gtkx/gi/gdk\";\nimport { CssProvider, STYLE_PROVIDER_PRIORITY_APPLICATION, StyleContext } from \"@gtkx/gi/gtk\";\nimport type { Logger } from \"@gtkx/utils\";\n\nexport const registerProviderForDefaultDisplay = (\n priority: number = STYLE_PROVIDER_PRIORITY_APPLICATION,\n): CssProvider => {\n const provider = new CssProvider();\n const manager = DisplayManager.get();\n\n const attach = (display: Display): void => {\n StyleContext.addProviderForDisplay(display, provider, priority);\n };\n\n const initialDisplay = manager.getDefaultDisplay();\n if (initialDisplay) {\n attach(initialDisplay);\n } else {\n manager.once(\"display-opened\", (openedDisplay: Display): void => attach(openedDisplay));\n }\n\n return provider;\n};\n\nexport const attachParsingErrorLogger = (provider: CssProvider, log: Logger, subject: string): void => {\n if (process.env.NODE_ENV !== \"production\") {\n provider.on(\"parsing-error\", (section, error) => {\n log.warn(`GTK4 rejected ${subject} at ${section.toString()}: ${error.message}`);\n });\n }\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stylesheet.d.ts","sourceRoot":"","sources":["../src/stylesheet.ts"],"names":[],"mappings":"AAMA,qBAAa,UAAU;IACnB,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,cAAc;IAStB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGzB;CACJ"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createLogger } from "@gtkx/utils";
|
|
2
|
+
import { attachParsingErrorLogger, registerProviderForDefaultDisplay } from "./provider.js";
|
|
3
|
+
const log = createLogger("css");
|
|
4
|
+
export class StyleSheet {
|
|
5
|
+
css = "";
|
|
6
|
+
provider = null;
|
|
7
|
+
updateScheduled = false;
|
|
8
|
+
ensureProvider() {
|
|
9
|
+
if (this.provider)
|
|
10
|
+
return this.provider;
|
|
11
|
+
const provider = registerProviderForDefaultDisplay();
|
|
12
|
+
this.provider = provider;
|
|
13
|
+
attachParsingErrorLogger(provider, log, "CSS");
|
|
14
|
+
return provider;
|
|
15
|
+
}
|
|
16
|
+
scheduleUpdate() {
|
|
17
|
+
if (this.updateScheduled)
|
|
18
|
+
return;
|
|
19
|
+
this.updateScheduled = true;
|
|
20
|
+
queueMicrotask(() => {
|
|
21
|
+
this.updateScheduled = false;
|
|
22
|
+
this.ensureProvider().loadFromString(this.css);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
insert(rule) {
|
|
26
|
+
this.css += this.css.length > 0 ? `\n${rule}` : rule;
|
|
27
|
+
this.scheduleUpdate();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=stylesheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stylesheet.js","sourceRoot":"","sources":["../src/stylesheet.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,wBAAwB,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAE5F,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;AAEhC,MAAM,OAAO,UAAU;IACX,GAAG,GAAG,EAAE,CAAC;IACT,QAAQ,GAA2B,IAAI,CAAC;IACxC,eAAe,GAAG,KAAK,CAAC;IAExB,cAAc;QAClB,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC;QACxC,MAAM,QAAQ,GAAG,iCAAiC,EAAE,CAAC;QACrD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,wBAAwB,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,QAAQ,CAAC;IACpB,CAAC;IAEO,cAAc;QAClB,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO;QACjC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,cAAc,CAAC,GAAG,EAAE;YAChB,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;YAC7B,IAAI,CAAC,cAAc,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACP,CAAC;IAED,MAAM,CAAC,IAAY;QACf,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACrD,IAAI,CAAC,cAAc,EAAE,CAAC;IAC1B,CAAC;CACJ","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { createLogger } from \"@gtkx/utils\";\nimport { attachParsingErrorLogger, registerProviderForDefaultDisplay } from \"./provider.js\";\n\nconst log = createLogger(\"css\");\n\nexport class StyleSheet {\n private css = \"\";\n private provider: Gtk.CssProvider | null = null;\n private updateScheduled = false;\n\n private ensureProvider(): Gtk.CssProvider {\n if (this.provider) return this.provider;\n const provider = registerProviderForDefaultDisplay();\n this.provider = provider;\n attachParsingErrorLogger(provider, log, \"CSS\");\n return provider;\n }\n\n private scheduleUpdate(): void {\n if (this.updateScheduled) return;\n this.updateScheduled = true;\n queueMicrotask(() => {\n this.updateScheduled = false;\n this.ensureProvider().loadFromString(this.css);\n });\n }\n\n insert(rule: string): void {\n this.css += this.css.length > 0 ? `\\n${rule}` : rule;\n this.scheduleUpdate();\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gtkx/css",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Emotion-
|
|
3
|
+
"version": "1.0.0-rc.1",
|
|
4
|
+
"description": "Emotion-flavored CSS-in-JS that compiles to real GTK4 CSS and installs it on the default display",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gtkx",
|
|
7
7
|
"gtk",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
|
-
"url": "https://github.com/gtkx-org/gtkx.git",
|
|
23
|
+
"url": "git+https://github.com/gtkx-org/gtkx.git",
|
|
24
24
|
"directory": "packages/css"
|
|
25
25
|
},
|
|
26
26
|
"license": "MPL-2.0",
|
|
@@ -33,24 +33,26 @@
|
|
|
33
33
|
"default": "./dist/index.js"
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
|
-
"sideEffects":
|
|
37
|
-
"./dist/index.js"
|
|
38
|
-
],
|
|
36
|
+
"sideEffects": false,
|
|
39
37
|
"files": [
|
|
40
38
|
"dist",
|
|
41
39
|
"src"
|
|
42
40
|
],
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=24"
|
|
43
|
+
},
|
|
43
44
|
"dependencies": {
|
|
44
|
-
"@emotion/cache": "^11.14.0",
|
|
45
45
|
"@emotion/serialize": "^1.3.3",
|
|
46
|
-
"
|
|
46
|
+
"stylis": "^4.4.0",
|
|
47
|
+
"@gtkx/utils": "1.0.0-rc.1"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
|
-
"@
|
|
50
|
+
"@types/stylis": "^4.2.7",
|
|
51
|
+
"@gtkx/vitest": "1.0.0-rc.1"
|
|
50
52
|
},
|
|
51
53
|
"scripts": {
|
|
52
|
-
"build": "tsc -b
|
|
53
|
-
"
|
|
54
|
-
"
|
|
54
|
+
"build": "tsc -b tsconfig.lib.json",
|
|
55
|
+
"typecheck": "tsc -b --emitDeclarationOnly",
|
|
56
|
+
"release": "tsx ../../scripts/release-package.ts"
|
|
55
57
|
}
|
|
56
58
|
}
|