@greenfinity/rescript-typed-css-modules 0.1.1 → 0.2.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
@@ -24,15 +24,13 @@ Only tested with Next.js and might not work with other frameworks out of the box
24
24
 
25
25
  ### Why global CSS support?
26
26
 
27
- The use case is to access classes in a type safe way from third party css libraries, that emit HTML markup with predefined class names without the use of css modules (e.g. React Aria Components).
28
-
29
- Global CSS files (`.global.css` / `.global.scss`) also get type-safe bindings, but they are not imported, and their class names are **not hashed**. This is useful when working with third-party libraries (such as React Aria Components) that emit HTML markup with predefined class names that you need to style.
27
+ TL;DR: Global CSS files behave just like CSS Modules, except their class names are **not hashed** but kept as-is.
30
28
 
31
- Even though global CSS classes aren't scoped, generating typed bindings provides the benefit of compile-time checking that class names exist.
29
+ Support for global CSS is provided in addition to CSS Modules.
32
30
 
33
- The imports are not done because these css typically has to be imported from the top of the component hierarchy. So the import has to be done manually. To get type safe access, simply rename the file to `.global.css` (or create one and import the original css from it).
31
+ The use case is to access classes in a type safe way from third party css libraries, that emit HTML markup with predefined class names without the use of css modules (e.g. React Aria Components).
34
32
 
35
- (Remark: we could also provide a way to import the css automatically, but this would open issues with removing duplicates during bundling, and handling the css on route changes. NextJs does not support these use cases out of the box, so we revert to the manual import for global css.)
33
+ Even though global CSS classes aren't scoped, generating typed bindings provides the benefit of compile-time checking that class names exist. If the framework you are using supports bundling by routes (such as NextJS), the global css files will also be bundled together with JavaScript. Regarding duplicates, they should be handled the same way as CSS Modules, or ordinary JavaScript imports. (Checked with NextJS with both the Webpack and the Turbopack builder.)
36
34
 
37
35
  ## Installation
38
36
 
@@ -175,6 +173,7 @@ type t = {
175
173
  "light-mode": string,
176
174
  "primary-color": string
177
175
  }
176
+ @module("./Button.module.css") external css: t = "default"
178
177
 
179
178
  // Class names are returned as-is (no hashing)
180
179
  let css = ...
@@ -183,10 +182,7 @@ let css = ...
183
182
  Usage:
184
183
 
185
184
  ```rescript
186
- // Import the CSS manually at your app root
187
- %%raw(`import "./Theme.global.css"`)
188
-
189
- // Then use type-safe class names anywhere
185
+ // Use type-safe class names anywhere
190
186
  <div className={Theme_CssGlobal.css["dark-mode"]}>
191
187
  ```
192
188
 
@@ -26620,14 +26620,14 @@ type t = {
26620
26620
  }
26621
26621
  `;
26622
26622
  if (importType === "Module") {
26623
- return prelude + (`@module("./` + baseName + `") external css: t = "default"
26623
+ return prelude + (`
26624
+ @module("./` + baseName + `") external css: t = "default"
26624
26625
 
26625
26626
  // Access class names from the fields of the css object.
26626
26627
  // For scoped classses, the hashed class name is returned.
26627
26628
  // For :global() classes, the class name is returned as-is: no scoping.
26628
26629
  // Classes from @import are also available.
26629
26630
 
26630
- @module("./` + baseName + `") external _imported: t = "default"
26631
26631
  @new external proxy: ('a, 'b) => 'c = "Proxy"
26632
26632
  %%private(
26633
26633
  external toDict: t => dict<string> = "%identity"
@@ -26649,10 +26649,10 @@ let css = withProxy(css)
26649
26649
 
26650
26650
  `);
26651
26651
  } else {
26652
- return prelude + `
26652
+ return prelude + (`
26653
+ @module("./` + baseName + `") external _imported: t = "default"
26654
+
26653
26655
  // Access class names from the fields of the css object.
26654
- // Import is not done, the css has to be manually imported
26655
- // from the top of the component hierarchy.
26656
26656
  // For all classes, the class name is returned as-is: no scoping.
26657
26657
  // Classes from @import are also available.
26658
26658
 
@@ -26668,7 +26668,7 @@ type empty = {}
26668
26668
  )
26669
26669
  )
26670
26670
  let css = withProxy({})
26671
- `;
26671
+ `);
26672
26672
  }
26673
26673
  }
26674
26674
  function getBaseNameAndImportType(cssFilePath) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@greenfinity/rescript-typed-css-modules",
3
3
  "description": "Typed CSS Modules for ReScript",
4
- "version": "0.1.1",
4
+ "version": "0.2.0",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "bin": {
@@ -56,14 +56,14 @@ type t = {
56
56
  }
57
57
  `;
58
58
  if (importType === "Module") {
59
- return prelude + (`@module("./` + baseName + `") external css: t = "default"
59
+ return prelude + (`
60
+ @module("./` + baseName + `") external css: t = "default"
60
61
 
61
62
  // Access class names from the fields of the css object.
62
63
  // For scoped classses, the hashed class name is returned.
63
64
  // For :global() classes, the class name is returned as-is: no scoping.
64
65
  // Classes from @import are also available.
65
66
 
66
- @module("./` + baseName + `") external _imported: t = "default"
67
67
  @new external proxy: ('a, 'b) => 'c = "Proxy"
68
68
  %%private(
69
69
  external toDict: t => dict<string> = "%identity"
@@ -85,10 +85,10 @@ let css = withProxy(css)
85
85
 
86
86
  `);
87
87
  } else {
88
- return prelude + `
88
+ return prelude + (`
89
+ @module("./` + baseName + `") external _imported: t = "default"
90
+
89
91
  // Access class names from the fields of the css object.
90
- // Import is not done, the css has to be manually imported
91
- // from the top of the component hierarchy.
92
92
  // For all classes, the class name is returned as-is: no scoping.
93
93
  // Classes from @import are also available.
94
94
 
@@ -104,7 +104,7 @@ type empty = {}
104
104
  )
105
105
  )
106
106
  let css = withProxy({})
107
- `;
107
+ `);
108
108
  }
109
109
  }
110
110
 
@@ -9,7 +9,14 @@ module Meow = {
9
9
  default?: bool,
10
10
  }
11
11
 
12
- type flags = {"watch": flag, "outputDir": flag, "skipInitial": flag, "force": flag, "silent": flag, "quiet": flag}
12
+ type flags = {
13
+ "watch": flag,
14
+ "outputDir": flag,
15
+ "skipInitial": flag,
16
+ "force": flag,
17
+ "silent": flag,
18
+ "quiet": flag,
19
+ }
13
20
 
14
21
  type importMeta
15
22
 
@@ -21,7 +28,14 @@ module Meow = {
21
28
 
22
29
  type result = {
23
30
  input: array<string>,
24
- flags: {"watch": bool, "outputDir": option<string>, "skipInitial": bool, "force": bool, "silent": bool, "quiet": bool},
31
+ flags: {
32
+ "watch": bool,
33
+ "outputDir": option<string>,
34
+ "skipInitial": bool,
35
+ "force": bool,
36
+ "silent": bool,
37
+ "quiet": bool,
38
+ },
25
39
  showHelp: unit => unit,
26
40
  }
27
41
 
@@ -109,14 +123,14 @@ ${recordFields->Array.join(",\n")}
109
123
  // CSS Module import will get access to the object mapping returned
110
124
  // by the import. Hashing will happen automatically.
111
125
  prelude +
112
- `@module("./${baseName}") external css: t = "default"
126
+ `
127
+ @module("./${baseName}") external css: t = "default"
113
128
 
114
129
  // Access class names from the fields of the css object.
115
130
  // For scoped classses, the hashed class name is returned.
116
131
  // For :global() classes, the class name is returned as-is: no scoping.
117
132
  // Classes from @import are also available.
118
133
 
119
- @module("./${baseName}") external _imported: t = "default"
120
134
  @new external proxy: ('a, 'b) => 'c = "Proxy"
121
135
  %%private(
122
136
  external toDict: t => dict<string> = "%identity"
@@ -139,11 +153,11 @@ let css = withProxy(css)
139
153
  `
140
154
  | Global =>
141
155
  // Global css will return the css class name as-is: no scoping.
142
- // Import is not done.
143
- prelude + `
156
+ prelude +
157
+ `
158
+ @module("./${baseName}") external _imported: t = "default"
159
+
144
160
  // Access class names from the fields of the css object.
145
- // Import is not done, the css has to be manually imported
146
- // from the top of the component hierarchy.
147
161
  // For all classes, the class name is returned as-is: no scoping.
148
162
  // Classes from @import are also available.
149
163
 
@@ -238,7 +252,9 @@ let processFile = async (cssFilePath, outputDir, ~force=false, ~silent=false, ~q
238
252
 
239
253
  NodeJs.Fs.writeFileSync(outputPath, NodeJs.Buffer.fromString(bindings))
240
254
  if !quiet {
241
- Console.log(`✅ Generated ${outputPath} (${classNames->Array.length->Int.toString} classes)`)
255
+ Console.log(
256
+ `✅ Generated ${outputPath} (${classNames->Array.length->Int.toString} classes)`,
257
+ )
242
258
  }
243
259
 
244
260
  (outputPath, classNames)->Some