@gtkx/css 0.14.0 → 0.16.0

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 CHANGED
@@ -71,6 +71,7 @@ render(<App />, "com.example.counter");
71
71
  - **React 19** — Hooks, concurrent features, and the component model you know
72
72
  - **Native GTK4 widgets** — Real native controls, not web components in a webview
73
73
  - **Adwaita support** — Modern GNOME styling with Libadwaita components
74
+ - **Declarative animations** — Framer Motion-like API using native Adwaita animations
74
75
  - **Hot Module Replacement** — Fast refresh during development
75
76
  - **TypeScript first** — Full type safety with auto-generated bindings
76
77
  - **CSS-in-JS styling** — Familiar styling patterns adapted for GTK
@@ -80,11 +81,11 @@ render(<App />, "com.example.counter");
80
81
 
81
82
  Explore complete applications in the [`examples/`](./examples) directory:
82
83
 
83
- - **[browser](./examples/browser)** — Simple browser using WebKitWebView
84
84
  - **[gtk-demo](./examples/gtk-demo)** — Full replica of the official GTK demo app
85
85
  - **[hello-world](./examples/hello-world)** — Minimal application showing a counter
86
86
  - **[todo](./examples/todo)** — Full-featured todo application with Adwaita styling and testing
87
87
  - **[x-showcase](./examples/x-showcase)** — Showcase of all x.\* virtual components
88
+ - **[browser](./examples/browser)** — Simple browser using WebKitWebView
88
89
  - **[deploying](./examples/deploying)** — Example of packaging and distributing a GTKX app
89
90
 
90
91
  ## Documentation
package/dist/css.d.ts CHANGED
@@ -43,12 +43,12 @@ type CSSClassName = string & {
43
43
  */
44
44
  export declare const css: (...args: CSSInterpolation[]) => CSSClassName;
45
45
  /**
46
- * Combines multiple class names into a single space-separated string.
46
+ * Combines multiple class names into an array for use with cssClasses prop.
47
47
  *
48
48
  * Filters out falsy values, allowing conditional class application.
49
49
  *
50
50
  * @param classNames - Class names, booleans, undefined, or null values
51
- * @returns Space-separated string of valid class names
51
+ * @returns Array of valid class names
52
52
  *
53
53
  * @example
54
54
  * ```tsx
@@ -58,12 +58,12 @@ export declare const css: (...args: CSSInterpolation[]) => CSSClassName;
58
58
  * const active = css({ backgroundColor: "@accent_bg_color" });
59
59
  *
60
60
  * <GtkButton
61
- * cssClasses={[cx(base, isActive && active, "custom-class")]}
61
+ * cssClasses={cx(base, isActive && active, "custom-class")}
62
62
  * label="Button"
63
63
  * />
64
64
  * ```
65
65
  */
66
- export declare const cx: (...classNames: (string | boolean | undefined | null)[]) => string;
66
+ export declare const cx: (...classNames: (string | boolean | undefined | null)[]) => string[];
67
67
  /**
68
68
  * Injects global CSS styles without a wrapping class.
69
69
  *
package/dist/css.js CHANGED
@@ -4,48 +4,37 @@ function expandNestedRules(styles, className) {
4
4
  const selector = `.${className}`;
5
5
  const expandedStyles = styles.replace(/&/g, selector);
6
6
  const rules = [];
7
- let currentRule = "";
7
+ let topLevelProperties = "";
8
+ let currentSegment = "";
8
9
  let braceDepth = 0;
9
- let inSelector = false;
10
- let mainProperties = "";
11
10
  for (let i = 0; i < expandedStyles.length; i++) {
12
11
  const char = expandedStyles[i];
13
12
  if (char === "{") {
13
+ currentSegment += char;
14
14
  braceDepth++;
15
- if (braceDepth === 1 && currentRule.includes(selector)) {
16
- inSelector = true;
17
- currentRule += char;
18
- }
19
- else {
20
- currentRule += char;
21
- }
22
15
  }
23
16
  else if (char === "}") {
24
17
  braceDepth--;
25
- currentRule += char;
26
- if (braceDepth === 0 && inSelector) {
27
- rules.push(currentRule.trim());
28
- currentRule = "";
29
- inSelector = false;
18
+ currentSegment += char;
19
+ if (braceDepth === 0) {
20
+ rules.push(currentSegment.trim());
21
+ currentSegment = "";
30
22
  }
31
23
  }
32
- else if (braceDepth === 0 && char === "." && expandedStyles.slice(i).startsWith(selector)) {
33
- if (mainProperties.length > 0 || currentRule.length > 0) {
34
- mainProperties += currentRule;
35
- currentRule = "";
36
- }
37
- currentRule += char;
24
+ else if (char === ";" && braceDepth === 0) {
25
+ topLevelProperties += currentSegment + char;
26
+ currentSegment = "";
38
27
  }
39
28
  else {
40
- currentRule += char;
29
+ currentSegment += char;
41
30
  }
42
31
  }
43
- if (currentRule.trim()) {
44
- mainProperties += currentRule;
32
+ if (currentSegment.trim() && braceDepth === 0) {
33
+ topLevelProperties += currentSegment;
45
34
  }
46
35
  const allRules = [];
47
- if (mainProperties.trim()) {
48
- allRules.push(`${selector}{${mainProperties.trim()}}`);
36
+ if (topLevelProperties.trim()) {
37
+ allRules.push(`${selector}{${topLevelProperties.trim()}}`);
49
38
  }
50
39
  allRules.push(...rules);
51
40
  return allRules.join("\n");
@@ -99,12 +88,12 @@ export const css = (...args) => {
99
88
  return className;
100
89
  };
101
90
  /**
102
- * Combines multiple class names into a single space-separated string.
91
+ * Combines multiple class names into an array for use with cssClasses prop.
103
92
  *
104
93
  * Filters out falsy values, allowing conditional class application.
105
94
  *
106
95
  * @param classNames - Class names, booleans, undefined, or null values
107
- * @returns Space-separated string of valid class names
96
+ * @returns Array of valid class names
108
97
  *
109
98
  * @example
110
99
  * ```tsx
@@ -114,12 +103,12 @@ export const css = (...args) => {
114
103
  * const active = css({ backgroundColor: "@accent_bg_color" });
115
104
  *
116
105
  * <GtkButton
117
- * cssClasses={[cx(base, isActive && active, "custom-class")]}
106
+ * cssClasses={cx(base, isActive && active, "custom-class")}
118
107
  * label="Button"
119
108
  * />
120
109
  * ```
121
110
  */
122
- export const cx = (...classNames) => classNames.filter((cn) => typeof cn === "string" && cn.length > 0).join(" ");
111
+ export const cx = (...classNames) => classNames.filter((cn) => typeof cn === "string" && cn.length > 0);
123
112
  /**
124
113
  * Injects global CSS styles without a wrapping class.
125
114
  *
@@ -12,7 +12,7 @@ const flushPendingStyles = () => {
12
12
  const registerStartListener = () => {
13
13
  events.once("start", flushPendingStyles);
14
14
  };
15
- if (!isStarted()) {
15
+ if (!isStarted) {
16
16
  registerStartListener();
17
17
  }
18
18
  export class StyleSheet {
@@ -43,7 +43,7 @@ export class StyleSheet {
43
43
  }
44
44
  insert(rule) {
45
45
  this.rules.push(rule);
46
- if (isStarted()) {
46
+ if (isStarted) {
47
47
  this.ensureProvider();
48
48
  this.updateProvider();
49
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/css",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "Emotion-style CSS-in-JS for GTKX applications",
5
5
  "keywords": [
6
6
  "gtkx",
@@ -39,10 +39,10 @@
39
39
  "dependencies": {
40
40
  "@emotion/cache": "^11.14.0",
41
41
  "@emotion/serialize": "^1.3.3",
42
- "@gtkx/ffi": "0.14.0"
42
+ "@gtkx/ffi": "0.16.0"
43
43
  },
44
44
  "devDependencies": {
45
- "@gtkx/vitest": "0.14.0"
45
+ "@gtkx/vitest": "0.16.0"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "tsc -b && cp ../../README.md .",