praxis-kit 3.1.1 → 4.0.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.
@@ -1,6 +1,7 @@
1
- import { VariantMap, ClassPipelineOptions, StrictMode, ClassPlugin } from '@praxis-kit/core';
1
+ import { VariantMap, ClassPipelineOptions, ClassPlugin } from '@praxis-kit/core';
2
2
  import { Simplify } from 'type-fest';
3
- import { EmptyRecord } from '@praxis-kit/shared';
3
+ import { Diagnostics } from '@praxis-kit/diagnostics';
4
+ import { EmptyRecord } from '@praxis-kit/primitive';
4
5
 
5
6
  declare const LAYOUT_FAMILY_MAP: {
6
7
  readonly flex: "flex";
@@ -56,7 +57,7 @@ type GapToken = Token<'gap'>;
56
57
  type UtilityToken = Token<'utility', {
57
58
  base: string;
58
59
  }>;
59
- type ClassifiedToken = LayoutToken | ConditionalToken | GapToken | UtilityToken;
60
+ type ClassifiedToken = Simplify<LayoutToken | ConditionalToken | GapToken | UtilityToken>;
60
61
 
61
62
  type VariantSelection = Record<string, string>;
62
63
  type CompoundVariant = {
@@ -96,7 +97,7 @@ type CompoundVariant = {
96
97
  * flex-family modes strip `grid-*`; grid-family modes strip `flex-*`; all other
97
98
  * display values (and no prop) strip both `flex-*` and `grid-*`.
98
99
  */
99
- declare function createTailwindPipeline<V extends VariantMap = VariantMap>(options: ClassPipelineOptions<V>, strict: StrictMode): ClassPlugin<LayoutProps>;
100
+ declare function createTailwindPipeline<V extends VariantMap = VariantMap>(options: ClassPipelineOptions<V>, diagnostics: Diagnostics): ClassPlugin<LayoutProps>;
100
101
 
101
102
  declare class ClassBuilder {
102
103
  #private;
@@ -14,6 +14,288 @@ function cn(...inputs) {
14
14
  return clsx(...inputs);
15
15
  }
16
16
 
17
+ // ../../lib/primitive/src/utils/iterate.ts
18
+ function find(iterable, callback) {
19
+ for (const value of iterable) {
20
+ const result = callback(value);
21
+ if (result != null) {
22
+ return result;
23
+ }
24
+ }
25
+ return null;
26
+ }
27
+ function some(iterable, predicate) {
28
+ for (const value of iterable) {
29
+ if (predicate(value)) return true;
30
+ }
31
+ return false;
32
+ }
33
+ function every(iterable, predicate) {
34
+ let index = 0;
35
+ for (const value of iterable) {
36
+ if (!predicate(value, index++)) {
37
+ return false;
38
+ }
39
+ }
40
+ return true;
41
+ }
42
+ function* filter(iterable, predicate) {
43
+ let index = 0;
44
+ for (const value of iterable) {
45
+ if (predicate(value, index++)) {
46
+ yield value;
47
+ }
48
+ }
49
+ }
50
+ function* map(iterable, callback) {
51
+ let index = 0;
52
+ for (const value of iterable) {
53
+ yield callback(value, index++);
54
+ }
55
+ }
56
+ function forEach(iterable, callback) {
57
+ let index = 0;
58
+ for (const value of iterable) {
59
+ callback(value, index++);
60
+ }
61
+ }
62
+ function reduce(iterable, initial, callback) {
63
+ let accumulator = initial;
64
+ let index = 0;
65
+ for (const value of iterable) {
66
+ accumulator = callback(accumulator, value, index++);
67
+ }
68
+ return accumulator;
69
+ }
70
+ function collect(iterable, callback) {
71
+ const result = {};
72
+ let index = 0;
73
+ for (const value of iterable) {
74
+ const entry = callback(value, index++);
75
+ if (entry === null) {
76
+ return null;
77
+ }
78
+ result[entry[0]] = entry[1];
79
+ }
80
+ return result;
81
+ }
82
+ function findLast(value, callback) {
83
+ for (let index = value.length - 1; index >= 0; index--) {
84
+ const result = callback(value[index], index);
85
+ if (result != null) {
86
+ return result;
87
+ }
88
+ }
89
+ return null;
90
+ }
91
+ function* items(collection) {
92
+ for (let i = 0; i < collection.length; i++) {
93
+ const item = collection.item(i);
94
+ if (item !== null) {
95
+ yield item;
96
+ }
97
+ }
98
+ }
99
+ function nodeList(list) {
100
+ return {
101
+ *[Symbol.iterator]() {
102
+ for (let i = 0; i < list.length; i++) {
103
+ const node = list.item(i);
104
+ if (node !== null) {
105
+ yield node;
106
+ }
107
+ }
108
+ }
109
+ };
110
+ }
111
+ function mapEntries(m) {
112
+ return m.entries();
113
+ }
114
+ function set(s) {
115
+ return s.values();
116
+ }
117
+ function hasOwn(object, key) {
118
+ return Object.hasOwn(object, key);
119
+ }
120
+ function* entries(object) {
121
+ for (const key in object) {
122
+ if (!hasOwn(object, key)) continue;
123
+ yield [key, object[key]];
124
+ }
125
+ }
126
+ function* keys(object) {
127
+ for (const [key] of entries(object)) {
128
+ yield key;
129
+ }
130
+ }
131
+ function* values(object) {
132
+ for (const [, value] of entries(object)) {
133
+ yield value;
134
+ }
135
+ }
136
+ function mapValues(object, callback) {
137
+ const result = {};
138
+ for (const [key, value] of entries(object)) {
139
+ result[key] = callback(value, key);
140
+ }
141
+ return result;
142
+ }
143
+ function forEachEntry(object, callback) {
144
+ for (const [key, value] of entries(object)) {
145
+ callback(key, value);
146
+ }
147
+ }
148
+ function forEachKey(object, callback) {
149
+ for (const key of keys(object)) {
150
+ callback(key);
151
+ }
152
+ }
153
+ function forEachValue(object, callback) {
154
+ for (const value of values(object)) {
155
+ callback(value);
156
+ }
157
+ }
158
+ function forEachSet(s, callback) {
159
+ for (const value of s) {
160
+ callback(value);
161
+ }
162
+ }
163
+ var iterate = Object.freeze({
164
+ entries,
165
+ filter,
166
+ find,
167
+ findLast,
168
+ forEach,
169
+ forEachEntry,
170
+ forEachKey,
171
+ forEachSet,
172
+ forEachValue,
173
+ items,
174
+ keys,
175
+ map,
176
+ mapEntries,
177
+ mapValues,
178
+ nodeList,
179
+ reduce,
180
+ collect,
181
+ set,
182
+ some,
183
+ every,
184
+ values
185
+ });
186
+
187
+ // ../../lib/diagnostics/src/category.ts
188
+ var DiagnosticCategory = /* @__PURE__ */ ((DiagnosticCategory2) => {
189
+ DiagnosticCategory2[DiagnosticCategory2["Contract"] = 0] = "Contract";
190
+ DiagnosticCategory2[DiagnosticCategory2["HTML"] = 1] = "HTML";
191
+ DiagnosticCategory2[DiagnosticCategory2["ARIA"] = 2] = "ARIA";
192
+ DiagnosticCategory2[DiagnosticCategory2["Composition"] = 3] = "Composition";
193
+ DiagnosticCategory2[DiagnosticCategory2["Rendering"] = 4] = "Rendering";
194
+ DiagnosticCategory2[DiagnosticCategory2["Accessibility"] = 5] = "Accessibility";
195
+ DiagnosticCategory2[DiagnosticCategory2["Performance"] = 6] = "Performance";
196
+ DiagnosticCategory2[DiagnosticCategory2["Internal"] = 7] = "Internal";
197
+ DiagnosticCategory2[DiagnosticCategory2["Deprecation"] = 8] = "Deprecation";
198
+ DiagnosticCategory2[DiagnosticCategory2["Lint"] = 9] = "Lint";
199
+ return DiagnosticCategory2;
200
+ })(DiagnosticCategory || {});
201
+
202
+ // ../../lib/diagnostics/src/error.ts
203
+ var PraxisError = class extends Error {
204
+ diagnostic;
205
+ constructor(diagnostic) {
206
+ super(diagnostic.message);
207
+ this.name = "PraxisError";
208
+ this.diagnostic = diagnostic;
209
+ }
210
+ };
211
+
212
+ // ../../lib/diagnostics/src/severity.ts
213
+ var Severity = /* @__PURE__ */ ((Severity2) => {
214
+ Severity2[Severity2["Debug"] = 0] = "Debug";
215
+ Severity2[Severity2["Info"] = 1] = "Info";
216
+ Severity2[Severity2["Warning"] = 2] = "Warning";
217
+ Severity2[Severity2["Error"] = 3] = "Error";
218
+ Severity2[Severity2["Fatal"] = 4] = "Fatal";
219
+ return Severity2;
220
+ })(Severity || {});
221
+
222
+ // ../../lib/diagnostics/src/policy.ts
223
+ var DefaultPolicy = class {
224
+ reportThreshold;
225
+ throwThreshold;
226
+ constructor({
227
+ reportThreshold = 1 /* Info */,
228
+ throwThreshold = 4 /* Fatal */
229
+ } = {}) {
230
+ this.reportThreshold = reportThreshold;
231
+ this.throwThreshold = throwThreshold;
232
+ }
233
+ resolve(diagnostic) {
234
+ if (diagnostic.severity >= this.throwThreshold) return 2 /* Throw */;
235
+ if (diagnostic.severity >= this.reportThreshold) return 1 /* Report */;
236
+ return 0 /* Ignore */;
237
+ }
238
+ };
239
+
240
+ // ../../lib/diagnostics/src/diagnostics.ts
241
+ var Diagnostics = class {
242
+ reporter;
243
+ policy;
244
+ // Pre-computed at construction time: true if Warning-level diagnostics are not ignored.
245
+ active;
246
+ constructor(reporter, policy = new DefaultPolicy()) {
247
+ this.reporter = reporter;
248
+ this.policy = policy;
249
+ this.active = policy.resolve({ severity: 2 /* Warning */ }) !== 0 /* Ignore */;
250
+ }
251
+ report(diagnostic) {
252
+ const enforcement = this.policy.resolve(diagnostic);
253
+ if (enforcement === 0 /* Ignore */) return diagnostic;
254
+ if (enforcement === 2 /* Throw */) throw new PraxisError(diagnostic);
255
+ this.reporter.report(diagnostic);
256
+ return diagnostic;
257
+ }
258
+ warn(input) {
259
+ return this.report({ ...input, severity: 2 /* Warning */ });
260
+ }
261
+ error(input) {
262
+ return this.report({ ...input, severity: 3 /* Error */ });
263
+ }
264
+ info(input) {
265
+ return this.report({ ...input, severity: 1 /* Info */ });
266
+ }
267
+ };
268
+
269
+ // ../../lib/diagnostics/src/formatter.ts
270
+ function formatDiagnostic(diagnostic) {
271
+ const level = Severity[diagnostic.severity];
272
+ const category = DiagnosticCategory[diagnostic.category];
273
+ const prefix = category !== void 0 ? `[${category}] ` : "";
274
+ return `${level} ${diagnostic.code}: ${prefix}${diagnostic.message}`;
275
+ }
276
+
277
+ // ../../lib/diagnostics/src/console-reporter.ts
278
+ var ConsoleReporter = class {
279
+ report(diagnostic) {
280
+ const message = formatDiagnostic(diagnostic);
281
+ switch (diagnostic.severity) {
282
+ case 0 /* Debug */:
283
+ console.debug(message);
284
+ break;
285
+ case 1 /* Info */:
286
+ console.info(message);
287
+ break;
288
+ case 2 /* Warning */:
289
+ console.warn(message);
290
+ break;
291
+ case 3 /* Error */:
292
+ case 4 /* Fatal */:
293
+ console.error(message);
294
+ break;
295
+ }
296
+ }
297
+ };
298
+
17
299
  // ../../node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.mjs
18
300
  import { clsx as clsx2 } from "clsx";
19
301
  var falsyToString = (value) => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
@@ -143,15 +425,15 @@ var VariantClassResolver = class _VariantClassResolver {
143
425
  #createCacheKey(props, recipe) {
144
426
  if (this.#variantKeys !== null) {
145
427
  let key2 = recipe;
146
- for (const k of this.#variantKeys) {
428
+ iterate.forEachSet(this.#variantKeys, (k) => {
147
429
  if (k in props) key2 += `|${k}:${_VariantClassResolver.#serializeValue(props[k])}`;
148
- }
430
+ });
149
431
  return key2;
150
432
  }
151
433
  let key = recipe;
152
- for (const k of Object.keys(props).sort()) {
434
+ iterate.forEach(Object.keys(props).sort(), (k) => {
153
435
  key += `|${k}:${_VariantClassResolver.#serializeValue(props[k])}`;
154
- }
436
+ });
155
437
  return key;
156
438
  }
157
439
  static #serializeValue(value) {
@@ -188,12 +470,12 @@ function createClassPipeline(resolved) {
188
470
  };
189
471
  }
190
472
 
191
- // ../tailwind/src/class-builder.ts
473
+ // ../../lib/tailwind/src/class-builder.ts
192
474
  var ClassBuilder = class {
193
475
  build(tokens) {
194
476
  const layout = [];
195
477
  const normal = [];
196
- for (const token of tokens) {
478
+ iterate.forEach(tokens, (token) => {
197
479
  switch (token.kind) {
198
480
  case "layout": {
199
481
  layout.push(token.raw);
@@ -208,7 +490,7 @@ var ClassBuilder = class {
208
490
  default:
209
491
  throw assertNever(token);
210
492
  }
211
- }
493
+ });
212
494
  return [...this.#dedupe(layout).toSorted(), ...this.#dedupe(normal)].join(" ");
213
495
  }
214
496
  #dedupe(arr) {
@@ -216,7 +498,7 @@ var ClassBuilder = class {
216
498
  }
217
499
  };
218
500
 
219
- // ../tailwind/src/layout-keys.ts
501
+ // ../../lib/tailwind/src/layout-keys.ts
220
502
  var layoutKeys = [
221
503
  "flex",
222
504
  "inline-flex",
@@ -240,7 +522,7 @@ var layoutKeys = [
240
522
  "table-row"
241
523
  ];
242
524
 
243
- // ../tailwind/src/constants.ts
525
+ // ../../lib/tailwind/src/constants.ts
244
526
  var LAYOUT_OWNED_KEYS = new Set(layoutKeys);
245
527
  var LAYOUT_FAMILY_MAP = {
246
528
  flex: "flex",
@@ -267,7 +549,7 @@ var LAYOUT_FAMILY_MAP = {
267
549
  var EMPTY_SET = /* @__PURE__ */ new Set();
268
550
  var COMPOUND_META_KEYS = /* @__PURE__ */ new Set(["class"]);
269
551
 
270
- // ../tailwind/src/class-classifier.ts
552
+ // ../../lib/tailwind/src/class-classifier.ts
271
553
  var CONDITIONALS = {
272
554
  "[&.flex": "flex",
273
555
  "[&.grid": "grid"
@@ -275,15 +557,14 @@ var CONDITIONALS = {
275
557
  var ClassClassifier = class _ClassClassifier {
276
558
  static #getBaseUtility(token) {
277
559
  let depth = 0;
278
- for (let i = token.length - 1; i >= 0; i--) {
279
- const char = token[i];
560
+ return iterate.findLast(token, (char, index) => {
280
561
  if (char === "]") depth++;
281
562
  else if (char === "[") depth--;
282
- else if (char === ":" && depth === 0 && token[i - 1] !== "\\") {
283
- return token.slice(i + 1);
563
+ else if (char === ":" && depth === 0 && token[index - 1] !== "\\") {
564
+ return token.slice(index + 1);
284
565
  }
285
- }
286
- return token;
566
+ return null;
567
+ }) ?? token;
287
568
  }
288
569
  classify(token) {
289
570
  const base = _ClassClassifier.#getBaseUtility(token);
@@ -294,15 +575,17 @@ var ClassClassifier = class _ClassClassifier {
294
575
  raw: token
295
576
  };
296
577
  }
297
- for (const [prefix, requires] of Object.entries(CONDITIONALS)) {
298
- if (token.startsWith(prefix)) {
299
- return {
578
+ const conditional = iterate.find(
579
+ Object.entries(CONDITIONALS),
580
+ ([prefix, requires]) => {
581
+ return token.startsWith(prefix) ? {
300
582
  kind: "conditional",
301
583
  requires,
302
584
  raw: token
303
- };
585
+ } : null;
304
586
  }
305
- }
587
+ );
588
+ if (conditional !== null) return conditional;
306
589
  return base === "gap" || base.startsWith("gap-") ? {
307
590
  kind: "gap",
308
591
  raw: token
@@ -314,13 +597,13 @@ var ClassClassifier = class _ClassClassifier {
314
597
  }
315
598
  };
316
599
 
317
- // ../tailwind/src/dependency-rules.ts
600
+ // ../../lib/tailwind/src/dependency-rules.ts
318
601
  var defaultDependencyRules = {
319
602
  flex: [/^flex-/, /^grow/, /^shrink/, /^basis-/],
320
603
  grid: [/^grid-/, /^col-/, /^row-/, /^auto-cols-/, /^auto-rows-/]
321
604
  };
322
605
 
323
- // ../tailwind/src/dependency-evaluator.ts
606
+ // ../../lib/tailwind/src/dependency-evaluator.ts
324
607
  var DependencyEvaluator = class {
325
608
  constructor(rules) {
326
609
  this.rules = rules;
@@ -335,12 +618,10 @@ var DependencyEvaluator = class {
335
618
  return token.requires === state.family;
336
619
  }
337
620
  case "utility": {
338
- for (const layout of Object.keys(this.rules)) {
339
- if (this.rules[layout].some((r) => r.test(token.base))) {
340
- return state.family === layout;
341
- }
342
- }
343
- return true;
621
+ return iterate.find(
622
+ Object.keys(this.rules),
623
+ (layout) => this.rules[layout].some((rule) => rule.test(token.base)) ? state.family === layout : null
624
+ ) ?? true;
344
625
  }
345
626
  case "gap": {
346
627
  return state.family !== "none";
@@ -351,7 +632,7 @@ var DependencyEvaluator = class {
351
632
  }
352
633
  };
353
634
 
354
- // ../tailwind/src/layout-state.ts
635
+ // ../../lib/tailwind/src/layout-state.ts
355
636
  var LayoutState = class {
356
637
  #mode;
357
638
  #family;
@@ -368,31 +649,37 @@ var LayoutState = class {
368
649
  }
369
650
  };
370
651
 
371
- // ../tailwind/src/create-tailwind-pipeline.ts
372
- var DEV = process.env.NODE_ENV !== "production";
373
- var pendingAsyncWarns = /* @__PURE__ */ new Set();
374
- var asyncWarnScheduled = false;
375
- function flushAsyncWarns() {
376
- asyncWarnScheduled = false;
377
- const messages = [...pendingAsyncWarns];
378
- pendingAsyncWarns.clear();
379
- for (const msg of messages) {
380
- console.warn(msg);
381
- }
382
- }
383
- function pipelineWarn(strict, message) {
384
- if (!strict) return;
385
- if (strict === "async-warn") {
386
- if (pendingAsyncWarns.has(message)) return;
387
- pendingAsyncWarns.add(message);
388
- if (!asyncWarnScheduled) {
389
- asyncWarnScheduled = true;
390
- queueMicrotask(flushAsyncWarns);
391
- }
392
- return;
652
+ // ../../lib/tailwind/src/diagnostics.ts
653
+ var TailwindDiagnostics = {
654
+ multipleDisplayProps(active) {
655
+ return {
656
+ code: "CSS6001" /* TailwindMultipleDisplayProps */,
657
+ category: 0 /* Contract */,
658
+ message: `[createTailwindPipeline] Multiple display props set (${active.join(", ")}); "${active[0]}" takes precedence.`
659
+ };
660
+ },
661
+ reservedLayoutLiteral(reserved) {
662
+ return {
663
+ code: "CSS6002" /* TailwindReservedLayoutLiteral */,
664
+ category: 0 /* Contract */,
665
+ message: `[createTailwindPipeline] Reserved display class(es) ${reserved.map((r) => `"${r}"`).join(", ")} found in resolved classes. The display mode is controlled by the display props (flex, inline-flex, grid, block, hidden, etc.), not by class strings.`
666
+ };
667
+ },
668
+ deadVariantClass(dim, value, mode, classStr) {
669
+ return {
670
+ code: "CSS6003" /* TailwindDeadVariantClass */,
671
+ category: 0 /* Contract */,
672
+ message: `[createTailwindPipeline] Variant "${dim}=${value}" contributes only classes stripped under layout mode "${mode}" ("${classStr}") \u2014 it produces nothing in this mode.`
673
+ };
393
674
  }
394
- console.warn(message);
395
- }
675
+ };
676
+
677
+ // ../../lib/tailwind/src/create-tailwind-pipeline.ts
678
+ var DEV = process.env.NODE_ENV !== "production";
679
+ var devDiagnostics = new Diagnostics(
680
+ new ConsoleReporter(),
681
+ new DefaultPolicy({ reportThreshold: 2 /* Warning */, throwThreshold: 4 /* Fatal */ })
682
+ );
396
683
  var classifier = new ClassClassifier();
397
684
  var evaluator = new DependencyEvaluator(defaultDependencyRules);
398
685
  var builder = new ClassBuilder();
@@ -400,29 +687,23 @@ function normalizeVariantValue(value) {
400
687
  if (isString(value)) return value;
401
688
  return value.join(" ");
402
689
  }
403
- function resolveLayout(props) {
690
+ function resolveLayout(diagnostics, props) {
404
691
  const active = [];
405
- for (const key of layoutKeys) {
692
+ iterate.forEach(layoutKeys, (key) => {
406
693
  if (props[key]) active.push(key);
407
- }
694
+ });
408
695
  if (DEV && active.length > 1) {
409
- console.warn(
410
- `[createTailwindPipeline] Multiple display props set (${active.join(", ")}); "${active[0]}" takes precedence.`
411
- );
696
+ diagnostics.warn(TailwindDiagnostics.multipleDisplayProps(active));
412
697
  }
413
698
  return active[0] ?? "none";
414
699
  }
415
- function warnReservedLayoutLiterals(strict, tokens) {
416
- if (!strict) return;
700
+ function warnReservedLayoutLiterals(diagnostics, tokens) {
417
701
  const reserved = [];
418
- for (const token of tokens) {
702
+ iterate.forEach(tokens, (token) => {
419
703
  if (token.kind === "layout") reserved.push(token.raw);
420
- }
704
+ });
421
705
  if (reserved.length === 0) return;
422
- pipelineWarn(
423
- strict,
424
- `[createTailwindPipeline] Reserved display class(es) ${reserved.map((r) => `"${r}"`).join(", ")} found in resolved classes. The display mode is controlled by the display props (flex, inline-flex, grid, block, hidden, etc.), not by class strings.`
425
- );
706
+ diagnostics.warn(TailwindDiagnostics.reservedLayoutLiteral(reserved));
426
707
  }
427
708
  function getVariantConfig(options) {
428
709
  return options.variants;
@@ -436,11 +717,11 @@ function classifyTokens(className) {
436
717
  function compoundDimensions(compounds) {
437
718
  if (compounds.length === 0) return EMPTY_SET;
438
719
  const dims = /* @__PURE__ */ new Set();
439
- for (const compound of compounds) {
440
- for (const key in compound) {
720
+ iterate.forEach(compounds, (compound) => {
721
+ iterate.forEachKey(compound, (key) => {
441
722
  if (!COMPOUND_META_KEYS.has(key)) dims.add(key);
442
- }
443
- }
723
+ });
724
+ });
444
725
  return dims;
445
726
  }
446
727
  function getDefaultVariants(options) {
@@ -450,46 +731,41 @@ function resolveActiveSelection(options, variants, props, recipe) {
450
731
  const preset = recipe ? options.recipeMap?.[recipe] : void 0;
451
732
  const defaults = getDefaultVariants(options);
452
733
  const selection = {};
453
- for (const dim in variants) {
734
+ iterate.forEachKey(variants, (dim) => {
454
735
  const value = props[dim] ?? preset?.[dim] ?? defaults?.[dim];
455
736
  if (value !== void 0 && value !== null) selection[dim] = String(value);
456
- }
737
+ });
457
738
  return selection;
458
739
  }
459
- function warnDeadVariants(strict, options, compoundDims, props, recipe, state) {
460
- if (!strict) return;
740
+ function warnDeadVariants(diagnostics, options, compoundDims, props, recipe, state) {
461
741
  const variants = getVariantConfig(options);
462
742
  if (!variants) return;
463
743
  const selection = resolveActiveSelection(options, variants, props, recipe);
464
- for (const dim in selection) {
465
- if (compoundDims.has(dim)) continue;
466
- const value = selection[dim];
744
+ iterate.forEachEntry(selection, (dim, value) => {
745
+ if (compoundDims.has(dim)) return;
467
746
  const raw = variants[dim]?.[value];
468
- if (raw == null) continue;
747
+ if (raw == null) return;
469
748
  const classStr = normalizeVariantValue(raw);
470
749
  const tokens = classifyTokens(classStr);
471
- if (tokens.length === 0) continue;
750
+ if (tokens.length === 0) return;
472
751
  if (tokens.every((t) => !evaluator.evaluate(t, state))) {
473
- pipelineWarn(
474
- strict,
475
- `[createTailwindPipeline] Variant "${dim}=${value}" contributes only classes stripped under layout mode "${state.mode}" ("${classStr}") \u2014 it produces nothing in this mode.`
476
- );
752
+ diagnostics.warn(TailwindDiagnostics.deadVariantClass(dim, value, state.mode, classStr));
477
753
  }
478
- }
754
+ });
479
755
  }
480
- function createTailwindPipeline(options, strict) {
756
+ function createTailwindPipeline(options, diagnostics) {
481
757
  const pipeline = createClassPipeline(options);
482
758
  const compoundDims = compoundDimensions(getCompoundVariants(options));
483
759
  return {
484
760
  ownedKeys: LAYOUT_OWNED_KEYS,
485
761
  pipeline(tag, props, className, recipe) {
486
- const mode = resolveLayout(props);
762
+ const mode = resolveLayout(devDiagnostics, props);
487
763
  const raw = pipeline(tag, props, className, recipe);
488
764
  const tokens = classifyTokens(raw);
489
765
  const state = new LayoutState(mode);
490
766
  if (DEV) {
491
- warnReservedLayoutLiterals(strict, tokens);
492
- warnDeadVariants(strict, options, compoundDims, props, recipe, state);
767
+ warnReservedLayoutLiterals(diagnostics, tokens);
768
+ warnDeadVariants(diagnostics, options, compoundDims, props, recipe, state);
493
769
  }
494
770
  const filtered = tokens.filter((token) => evaluator.evaluate(token, state));
495
771
  const built = builder.build(filtered);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- // ../ts-plugin/src/ast.ts
3
+ // ../../plugins/typescript/src/ast.ts
4
4
  function getObjectProperty(ts, obj, key) {
5
5
  for (const prop of obj.properties) {
6
6
  if (!ts.isPropertyAssignment(prop)) continue;
@@ -39,7 +39,7 @@ function getFirstObjectArg(ts, node) {
39
39
  return ts.isObjectLiteralExpression(first) ? first : void 0;
40
40
  }
41
41
 
42
- // ../ts-plugin/src/diagnostics/walk-enforcement.ts
42
+ // ../../plugins/typescript/src/diagnostics/walk-enforcement.ts
43
43
  function walkEnforcement(ts, sourceFile, calleeNames, cb) {
44
44
  function visit(node) {
45
45
  if (ts.isCallExpression(node) && isFactoryCall(ts, node, calleeNames)) {
@@ -57,7 +57,7 @@ function walkEnforcement(ts, sourceFile, calleeNames, cb) {
57
57
  visit(sourceFile);
58
58
  }
59
59
 
60
- // ../ts-plugin/src/diagnostics/no-enforcement-without-strict.ts
60
+ // ../../plugins/typescript/src/diagnostics/no-enforcement-without-strict.ts
61
61
  var MISSING_STRICT_CODE = 90001;
62
62
  function checkNoEnforcementWithoutStrict(ts, sourceFile, calleeNames) {
63
63
  const diagnostics = [];
@@ -87,7 +87,7 @@ function checkNoEnforcementWithoutStrict(ts, sourceFile, calleeNames) {
87
87
  return diagnostics;
88
88
  }
89
89
 
90
- // ../ts-plugin/src/diagnostics/valid-cardinality.ts
90
+ // ../../plugins/typescript/src/diagnostics/valid-cardinality.ts
91
91
  var NEGATIVE_MIN_CODE = 90002;
92
92
  var NEGATIVE_MAX_CODE = 90003;
93
93
  var MAX_LESS_THAN_MIN_CODE = 90004;
@@ -158,7 +158,7 @@ function checkValidCardinality(ts, sourceFile, calleeNames) {
158
158
  return diagnostics;
159
159
  }
160
160
 
161
- // ../ts-plugin/src/index.ts
161
+ // ../../plugins/typescript/src/index.ts
162
162
  var DEFAULT_CALLEE_NAMES = ["createContractComponent"];
163
163
  function init(modules) {
164
164
  const ts = modules.typescript;