@flairjs/client 0.0.1-beta.6 → 0.0.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.
Files changed (2) hide show
  1. package/README.md +341 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,341 @@
1
+ # @flairjs/client
2
+
3
+ Client-side utilities and types for Flair CSS-in-JSX.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @flairjs/client
9
+ ```
10
+
11
+ ## Exports
12
+
13
+ ### Styling Functions
14
+
15
+ ```typescript
16
+ import { flair, css, c, cn } from '@flairjs/client'
17
+ ```
18
+
19
+ #### `flair(styles)`
20
+
21
+ Create component styles using CSS-in-JS object syntax:
22
+
23
+ ```jsx
24
+ import { flair } from '@flairjs/client'
25
+
26
+ const Button = () => <button className="button">Click me</button>
27
+
28
+ Button.flair = flair({
29
+ ".button": {
30
+ backgroundColor: 'blue',
31
+ color: 'white',
32
+ padding: '12px 24px',
33
+ '&:hover': {
34
+ backgroundColor: 'darkblue'
35
+ }
36
+ }
37
+ })
38
+ ```
39
+
40
+ #### `css` Template Literal
41
+
42
+ Write CSS using template literal syntax:
43
+
44
+ ```jsx
45
+ import { css } from '@flairjs/client'
46
+
47
+ const Button = () => <button className="button">Click me</button>
48
+
49
+ Button.flair = css`
50
+ .button {
51
+ background-color: blue;
52
+ color: white;
53
+ padding: 12px 24px;
54
+
55
+ &:hover {
56
+ background-color: darkblue;
57
+ }
58
+ }
59
+ `
60
+ ```
61
+
62
+ #### `c()` and `cn()` Class Name Utilities
63
+
64
+ Simple pass-through functions that help Flair's static analyzer find class names in your code.
65
+
66
+ **Important**: `c()` and `cn()` are **not** like `clsx` or `classnames`. They don't merge or conditionally apply classes - they simply return whatever you pass to them.
67
+
68
+ ```jsx
69
+ import { c, cn } from '@flairjs/client'
70
+
71
+ // Both c() and cn() are identical - they just return their input
72
+ // Their purpose is to signal to Flair's build-time analyzer which class names to include
73
+
74
+ function getButtonClass() {
75
+ // ✅ Signal to Flair that 'btn' and 'btn-primary' should be included
76
+ return c('btn btn-primary')
77
+ }
78
+
79
+ const Button = () => {
80
+ return <button className={getButtonClass()}>Click me</button>
81
+ }
82
+
83
+ Button.flair = flair({
84
+ '.btn': { padding: '12px 24px' },
85
+ '.btn-primary': { backgroundColor: 'blue' }
86
+ })
87
+ ```
88
+
89
+ **Why use them?** Since Flair is a build-time library, it needs to statically analyze your code to find class names. When you return a class name from a function like `<button className={someFunction()}>`, Flair can't infer what class name will be used. Wrapping the class name in `c()` or `cn()` inside the function signals to Flair which classes to include.
90
+
91
+ **Runtime behavior**: Zero overhead - they literally just return their input:
92
+ ```js
93
+ c('foo') === 'foo' // true
94
+ cn('bar') === 'bar' // true
95
+ ```
96
+
97
+ ### Theme System
98
+
99
+ ```typescript
100
+ import { defineConfig } from '@flairjs/client'
101
+ ```
102
+
103
+ **Setup**: To enable theming, import the theme CSS in your top-level file (e.g., `main.tsx`, `App.tsx`, or `index.tsx`):
104
+
105
+ ```jsx
106
+ import '@flairjs/client/theme.css'
107
+ ```
108
+
109
+ #### `defineConfig(config)`
110
+
111
+ Define your project's theme configuration:
112
+
113
+ ```typescript
114
+ // flair.theme.ts
115
+ import { defineConfig } from '@flairjs/client'
116
+
117
+ const theme = defineConfig({
118
+ prefix: 'my-app',
119
+ selector: 'body',
120
+ tokens: {
121
+ colors: {
122
+ primary: '#3b82f6',
123
+ secondary: '#64748b'
124
+ },
125
+ fonts: {
126
+ family: "'Inter', sans-serif",
127
+ size: {
128
+ sm: '14px',
129
+ md: '16px',
130
+ lg: '18px'
131
+ }
132
+ },
133
+ space: {
134
+ 1: '4px',
135
+ 2: '8px',
136
+ 3: '12px',
137
+ 4: '16px'
138
+ }
139
+ },
140
+ breakpoints: {
141
+ sm: '640px',
142
+ md: '768px',
143
+ lg: '1024px'
144
+ }
145
+ })
146
+
147
+ export default theme
148
+ export type Theme = typeof theme
149
+ ```
150
+
151
+ ### Component Libraries
152
+
153
+ #### React
154
+
155
+ ```jsx
156
+ import { Style } from '@flairjs/client/react'
157
+
158
+ const MyComponent = () => {
159
+ return (
160
+ <>
161
+ <div className="my-class">Styled content</div>
162
+ <Style>{`
163
+ .my-class {
164
+ color: red;
165
+ }
166
+ `}</Style>
167
+ </>
168
+ )
169
+ }
170
+
171
+ // Global styles
172
+ const App = () => {
173
+ return (
174
+ <>
175
+ <Style global>{`
176
+ body {
177
+ margin: 0;
178
+ font-family: sans-serif;
179
+ }
180
+ `}</Style>
181
+ {/* App content */}
182
+ </>
183
+ )
184
+ }
185
+ ```
186
+
187
+ #### Preact
188
+
189
+ ```jsx
190
+ import { Style } from '@flairjs/client/preact'
191
+
192
+ // Usage is identical to React
193
+ const MyComponent = () => {
194
+ return (
195
+ <>
196
+ <div className="my-class">Styled content</div>
197
+ <Style>{`
198
+ .my-class { color: red; }
199
+ `}</Style>
200
+ </>
201
+ )
202
+ }
203
+ ```
204
+
205
+ #### SolidJS
206
+
207
+ ```jsx
208
+ import { Style } from '@flairjs/client/solidjs'
209
+
210
+ const MyComponent = () => {
211
+ return (
212
+ <>
213
+ <div class="my-class">Styled content</div>
214
+ <Style>{`
215
+ .my-class { color: red; }
216
+ `}</Style>
217
+ </>
218
+ )
219
+ }
220
+ ```
221
+
222
+ ## TypeScript Support
223
+
224
+ ### Theme Intellisense
225
+
226
+ Extend the `FlairTheme` interface for theme token autocomplete:
227
+
228
+ ```typescript
229
+ // types/flair.d.ts
230
+ import { Theme } from '../flair.theme'
231
+
232
+ declare module '@flairjs/client' {
233
+ export interface FlairTheme extends Theme {}
234
+ }
235
+ ```
236
+
237
+ After this setup, you'll get autocomplete for theme tokens:
238
+
239
+ ```jsx
240
+ Button.flair = flair({
241
+ ".selector": {
242
+ backgroundColor: '$colors.primary', // ← Autocomplete available
243
+ padding: '$space.3 $space.4', // ← Autocomplete available
244
+ fontSize: '$fonts.size.md' // ← Autocomplete available
245
+ }
246
+ })
247
+ ```
248
+
249
+ ### Type Definitions
250
+
251
+ ```typescript
252
+ // Theme token types
253
+ type ThemeTokens<T extends FlairTheme = FlairTheme> =
254
+ T extends { tokens: any } ? TokensOf<T['tokens']> : never
255
+
256
+ type BreakPointTokens<T extends FlairTheme = FlairTheme> =
257
+ T extends { breakpoints: any } ? `$screen ${keyof T['breakpoints']}` : never
258
+
259
+ // CSS object with theme support
260
+ type FlairCSS = {
261
+ [K in string]?: FlairObject | FlairCSS
262
+ } & {
263
+ [K in BreakPointTokens]?: FlairObject | FlairCSS
264
+ }
265
+ ```
266
+
267
+ ## Usage Patterns
268
+
269
+ ### Responsive Design
270
+
271
+ ```jsx
272
+ const Card = () => <div className="card">Content</div>
273
+
274
+ Card.flair = flair({
275
+ '.card': {
276
+ padding: '$space.2',
277
+ fontSize: '$fonts.size.sm',
278
+
279
+ // Responsive breakpoints
280
+ '$screen md': {
281
+ padding: '$space.4',
282
+ fontSize: '$fonts.size.md'
283
+ },
284
+
285
+ '$screen lg': {
286
+ padding: '$space.6',
287
+ fontSize: '$fonts.size.lg'
288
+ }
289
+ }
290
+ })
291
+ ```
292
+
293
+ ### Nested Selectors
294
+
295
+ ```jsx
296
+ Card.flair = flair({
297
+ '.card': {
298
+ backgroundColor: 'white',
299
+
300
+ '&:hover': {
301
+ backgroundColor: '#f9f9f9'
302
+ },
303
+
304
+ '&.active': {
305
+ borderColor: '$colors.primary'
306
+ },
307
+
308
+ '& .title': {
309
+ fontSize: '$fonts.size.lg',
310
+ fontWeight: 'bold'
311
+ },
312
+
313
+ '& > .content': {
314
+ padding: '$space.4'
315
+ }
316
+ }
317
+ })
318
+ ```
319
+
320
+ ### Global Styles
321
+
322
+ ```jsx
323
+ // Using globalFlair property
324
+ const App = () => <div>App content</div>
325
+
326
+ App.globalFlair = css`
327
+ * {
328
+ box-sizing: border-box;
329
+ }
330
+
331
+ body {
332
+ margin: 0;
333
+ font-family: '$fonts.family';
334
+ background-color: '$colors.background';
335
+ }
336
+ `
337
+ ```
338
+
339
+ ## License
340
+
341
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flairjs/client",
3
- "version": "0.0.1-beta.6",
3
+ "version": "0.0.1",
4
4
  "module": "./dist/esm/index.js",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -67,7 +67,7 @@
67
67
  "csstype": "^3.1.3",
68
68
  "rolldown": "1.0.0-beta.37",
69
69
  "typescript": "^5.8.3",
70
- "@flairjs/core": "0.0.1-beta.7"
70
+ "@flairjs/core": "0.0.1"
71
71
  },
72
72
  "scripts": {
73
73
  "build": "rolldown -c",