clava 0.1.1 → 0.1.2

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/src/types.ts CHANGED
@@ -49,26 +49,57 @@ export type GetVariants<V> = (variants?: VariantValues<V>) => VariantValues<V>;
49
49
  export type KeySourceArray = readonly string[];
50
50
  export type KeySourceComponent = {
51
51
  keys: readonly (string | number | symbol)[];
52
+ variantKeys: readonly (string | number | symbol)[];
52
53
  getVariants: () => Record<string, unknown>;
53
54
  };
54
55
  export type KeySource = KeySourceArray | KeySourceComponent;
55
56
 
56
- // Extract keys from a source
57
+ // Check if source is a component (has getVariants)
58
+ type IsComponent<S> = S extends { getVariants: () => unknown } ? true : false;
59
+
60
+ // Extract keys from a source (includes class/style for components)
57
61
  type SourceKeys<S> = S extends readonly (infer K)[]
58
62
  ? K
59
63
  : S extends { keys: readonly (infer K)[] }
60
64
  ? K
61
65
  : never;
62
66
 
67
+ // Extract variant keys from a source (only variant keys, no class/style)
68
+ type SourceVariantKeys<S> = S extends readonly (infer K)[]
69
+ ? K
70
+ : S extends { variantKeys: readonly (infer K)[] }
71
+ ? K
72
+ : never;
73
+
63
74
  // Extract defaults from a source (components have defaults, arrays don't)
64
75
  type SourceDefaults<S> = S extends { getVariants: () => infer Defaults }
65
76
  ? Defaults
66
77
  : {};
67
78
 
68
- // Result type for one source - pick keys from T and add defaults
69
- type SourceResult<T, S> = Pick<T, Extract<keyof T, SourceKeys<S>>> &
79
+ // Result type for a source when styling is NOT yet claimed
80
+ // - Arrays: use listed keys (no defaults)
81
+ // - Components: use full keys including class/style (with defaults)
82
+ type SourceResultWithStyling<T, S> = Pick<T, Extract<keyof T, SourceKeys<S>>> &
70
83
  Omit<SourceDefaults<S>, keyof T>;
71
84
 
85
+ // Result type for a source when styling IS already claimed
86
+ // - Arrays: use listed keys (no defaults)
87
+ // - Components: use only variant keys (with defaults)
88
+ type SourceResultWithoutStyling<T, S> =
89
+ IsComponent<S> extends true
90
+ ? Pick<T, Extract<keyof T, SourceVariantKeys<S>>> &
91
+ Omit<SourceDefaults<S>, keyof T>
92
+ : Pick<T, Extract<keyof T, SourceKeys<S>>>;
93
+
94
+ // Check if any source in a tuple is a component (to track if styling is claimed)
95
+ type HasComponent<Sources> = Sources extends readonly []
96
+ ? false
97
+ : Sources extends readonly [infer First, ...infer Rest]
98
+ ? IsComponent<First> extends true
99
+ ? true
100
+ : HasComponent<Rest>
101
+ : false;
102
+
72
103
  // Standalone splitProps function type - first source is required
73
104
  export type SplitPropsFunction = <
74
105
  T,
@@ -81,16 +112,20 @@ export type SplitPropsFunction = <
81
112
  ) => SplitPropsFunctionResult<T, S1, Sources>;
82
113
 
83
114
  // Result type for standalone splitProps function
115
+ // S1: First source - uses SourceResultWithStyling (either array or first component gets styling)
116
+ // S2+: Subsequent sources - use SourceResultWithStyling if no prior component, else SourceResultWithoutStyling
84
117
  type SplitPropsFunctionResult<
85
118
  T,
86
119
  S1 extends KeySource,
87
120
  Sources extends readonly KeySource[],
88
121
  > = Sources extends readonly []
89
- ? [SourceResult<T, S1>, Omit<T, SourceKeys<S1>>]
122
+ ? [SourceResultWithStyling<T, S1>, Omit<T, SourceKeys<S1>>]
90
123
  : Sources extends readonly [infer S2 extends KeySource]
91
124
  ? [
92
- SourceResult<T, S1>,
93
- SourceResult<T, S2>,
125
+ SourceResultWithStyling<T, S1>,
126
+ IsComponent<S1> extends true
127
+ ? SourceResultWithoutStyling<T, S2>
128
+ : SourceResultWithStyling<T, S2>,
94
129
  Omit<T, SourceKeys<S1> | SourceKeys<S2>>,
95
130
  ]
96
131
  : Sources extends readonly [
@@ -98,9 +133,13 @@ type SplitPropsFunctionResult<
98
133
  infer S3 extends KeySource,
99
134
  ]
100
135
  ? [
101
- SourceResult<T, S1>,
102
- SourceResult<T, S2>,
103
- SourceResult<T, S3>,
136
+ SourceResultWithStyling<T, S1>,
137
+ IsComponent<S1> extends true
138
+ ? SourceResultWithoutStyling<T, S2>
139
+ : SourceResultWithStyling<T, S2>,
140
+ HasComponent<[S1, S2]> extends true
141
+ ? SourceResultWithoutStyling<T, S3>
142
+ : SourceResultWithStyling<T, S3>,
104
143
  Omit<T, SourceKeys<S1> | SourceKeys<S2> | SourceKeys<S3>>,
105
144
  ]
106
145
  : Sources extends readonly [
@@ -109,10 +148,16 @@ type SplitPropsFunctionResult<
109
148
  infer S4 extends KeySource,
110
149
  ]
111
150
  ? [
112
- SourceResult<T, S1>,
113
- SourceResult<T, S2>,
114
- SourceResult<T, S3>,
115
- SourceResult<T, S4>,
151
+ SourceResultWithStyling<T, S1>,
152
+ IsComponent<S1> extends true
153
+ ? SourceResultWithoutStyling<T, S2>
154
+ : SourceResultWithStyling<T, S2>,
155
+ HasComponent<[S1, S2]> extends true
156
+ ? SourceResultWithoutStyling<T, S3>
157
+ : SourceResultWithStyling<T, S3>,
158
+ HasComponent<[S1, S2, S3]> extends true
159
+ ? SourceResultWithoutStyling<T, S4>
160
+ : SourceResultWithStyling<T, S4>,
116
161
  Omit<
117
162
  T,
118
163
  SourceKeys<S1> | SourceKeys<S2> | SourceKeys<S3> | SourceKeys<S4>
@@ -125,11 +170,19 @@ type SplitPropsFunctionResult<
125
170
  infer S5 extends KeySource,
126
171
  ]
127
172
  ? [
128
- SourceResult<T, S1>,
129
- SourceResult<T, S2>,
130
- SourceResult<T, S3>,
131
- SourceResult<T, S4>,
132
- SourceResult<T, S5>,
173
+ SourceResultWithStyling<T, S1>,
174
+ IsComponent<S1> extends true
175
+ ? SourceResultWithoutStyling<T, S2>
176
+ : SourceResultWithStyling<T, S2>,
177
+ HasComponent<[S1, S2]> extends true
178
+ ? SourceResultWithoutStyling<T, S3>
179
+ : SourceResultWithStyling<T, S3>,
180
+ HasComponent<[S1, S2, S3]> extends true
181
+ ? SourceResultWithoutStyling<T, S4>
182
+ : SourceResultWithStyling<T, S4>,
183
+ HasComponent<[S1, S2, S3, S4]> extends true
184
+ ? SourceResultWithoutStyling<T, S5>
185
+ : SourceResultWithStyling<T, S5>,
133
186
  Omit<
134
187
  T,
135
188
  | SourceKeys<S1>
@@ -147,12 +200,22 @@ type SplitPropsFunctionResult<
147
200
  infer S6 extends KeySource,
148
201
  ]
149
202
  ? [
150
- SourceResult<T, S1>,
151
- SourceResult<T, S2>,
152
- SourceResult<T, S3>,
153
- SourceResult<T, S4>,
154
- SourceResult<T, S5>,
155
- SourceResult<T, S6>,
203
+ SourceResultWithStyling<T, S1>,
204
+ IsComponent<S1> extends true
205
+ ? SourceResultWithoutStyling<T, S2>
206
+ : SourceResultWithStyling<T, S2>,
207
+ HasComponent<[S1, S2]> extends true
208
+ ? SourceResultWithoutStyling<T, S3>
209
+ : SourceResultWithStyling<T, S3>,
210
+ HasComponent<[S1, S2, S3]> extends true
211
+ ? SourceResultWithoutStyling<T, S4>
212
+ : SourceResultWithStyling<T, S4>,
213
+ HasComponent<[S1, S2, S3, S4]> extends true
214
+ ? SourceResultWithoutStyling<T, S5>
215
+ : SourceResultWithStyling<T, S5>,
216
+ HasComponent<[S1, S2, S3, S4, S5]> extends true
217
+ ? SourceResultWithoutStyling<T, S6>
218
+ : SourceResultWithStyling<T, S6>,
156
219
  Omit<
157
220
  T,
158
221
  | SourceKeys<S1>
@@ -172,13 +235,25 @@ type SplitPropsFunctionResult<
172
235
  infer S7 extends KeySource,
173
236
  ]
174
237
  ? [
175
- SourceResult<T, S1>,
176
- SourceResult<T, S2>,
177
- SourceResult<T, S3>,
178
- SourceResult<T, S4>,
179
- SourceResult<T, S5>,
180
- SourceResult<T, S6>,
181
- SourceResult<T, S7>,
238
+ SourceResultWithStyling<T, S1>,
239
+ IsComponent<S1> extends true
240
+ ? SourceResultWithoutStyling<T, S2>
241
+ : SourceResultWithStyling<T, S2>,
242
+ HasComponent<[S1, S2]> extends true
243
+ ? SourceResultWithoutStyling<T, S3>
244
+ : SourceResultWithStyling<T, S3>,
245
+ HasComponent<[S1, S2, S3]> extends true
246
+ ? SourceResultWithoutStyling<T, S4>
247
+ : SourceResultWithStyling<T, S4>,
248
+ HasComponent<[S1, S2, S3, S4]> extends true
249
+ ? SourceResultWithoutStyling<T, S5>
250
+ : SourceResultWithStyling<T, S5>,
251
+ HasComponent<[S1, S2, S3, S4, S5]> extends true
252
+ ? SourceResultWithoutStyling<T, S6>
253
+ : SourceResultWithStyling<T, S6>,
254
+ HasComponent<[S1, S2, S3, S4, S5, S6]> extends true
255
+ ? SourceResultWithoutStyling<T, S7>
256
+ : SourceResultWithStyling<T, S7>,
182
257
  Omit<
183
258
  T,
184
259
  | SourceKeys<S1>
@@ -200,14 +275,28 @@ type SplitPropsFunctionResult<
200
275
  infer S8 extends KeySource,
201
276
  ]
202
277
  ? [
203
- SourceResult<T, S1>,
204
- SourceResult<T, S2>,
205
- SourceResult<T, S3>,
206
- SourceResult<T, S4>,
207
- SourceResult<T, S5>,
208
- SourceResult<T, S6>,
209
- SourceResult<T, S7>,
210
- SourceResult<T, S8>,
278
+ SourceResultWithStyling<T, S1>,
279
+ IsComponent<S1> extends true
280
+ ? SourceResultWithoutStyling<T, S2>
281
+ : SourceResultWithStyling<T, S2>,
282
+ HasComponent<[S1, S2]> extends true
283
+ ? SourceResultWithoutStyling<T, S3>
284
+ : SourceResultWithStyling<T, S3>,
285
+ HasComponent<[S1, S2, S3]> extends true
286
+ ? SourceResultWithoutStyling<T, S4>
287
+ : SourceResultWithStyling<T, S4>,
288
+ HasComponent<[S1, S2, S3, S4]> extends true
289
+ ? SourceResultWithoutStyling<T, S5>
290
+ : SourceResultWithStyling<T, S5>,
291
+ HasComponent<[S1, S2, S3, S4, S5]> extends true
292
+ ? SourceResultWithoutStyling<T, S6>
293
+ : SourceResultWithStyling<T, S6>,
294
+ HasComponent<[S1, S2, S3, S4, S5, S6]> extends true
295
+ ? SourceResultWithoutStyling<T, S7>
296
+ : SourceResultWithStyling<T, S7>,
297
+ HasComponent<[S1, S2, S3, S4, S5, S6, S7]> extends true
298
+ ? SourceResultWithoutStyling<T, S8>
299
+ : SourceResultWithStyling<T, S8>,
211
300
  Omit<
212
301
  T,
213
302
  | SourceKeys<S1>
@@ -222,18 +311,14 @@ type SplitPropsFunctionResult<
222
311
  ]
223
312
  : unknown[];
224
313
 
225
- export interface OnlyVariantsComponent<V> {
226
- getVariants: GetVariants<V>;
227
- keys: (keyof V)[];
228
- }
229
-
230
314
  export interface ModalComponent<V, R extends ComponentResult> {
231
315
  (props?: ComponentProps<V>): R;
232
316
  class: (props?: ComponentProps<V>) => string;
233
317
  style: (props?: ComponentProps<V>) => R["style"];
234
318
  getVariants: GetVariants<V>;
235
319
  keys: (keyof V | keyof R)[];
236
- onlyVariants: OnlyVariantsComponent<V>;
320
+ variantKeys: (keyof V)[];
321
+ propKeys: (keyof V | keyof R)[];
237
322
  /** @internal Base class without variants */
238
323
  _baseClass: string;
239
324
  }
package/src/utils.ts CHANGED
@@ -1,10 +1,23 @@
1
1
  import type * as CSS from "csstype";
2
2
  import type {
3
- StyleValue,
4
- JSXCSSProperties,
5
3
  HTMLCSSProperties,
4
+ JSXCSSProperties,
5
+ StyleValue,
6
6
  } from "./types.ts";
7
7
 
8
+ export const MODES = ["jsx", "html", "htmlObj"] as const;
9
+ export type Mode = (typeof MODES)[number];
10
+
11
+ /**
12
+ * Returns the appropriate class property name based on the mode.
13
+ * @example
14
+ * getClassPropertyName("jsx") // "className"
15
+ * getClassPropertyName("html") // "class"
16
+ */
17
+ export function getClassPropertyName(mode: Mode) {
18
+ return mode === "jsx" ? "className" : "class";
19
+ }
20
+
8
21
  /**
9
22
  * Converts a hyphenated CSS property name to camelCase.
10
23
  * @example