tailwind-styled-v4 5.1.11 → 5.1.13

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/dist/index.d.mts CHANGED
@@ -253,19 +253,34 @@ declare function cv<C extends ComponentConfig>(config: C, componentId?: string):
253
253
 
254
254
  /**
255
255
  * tailwind-styled-v4 v2 — cx / cn
256
- * Pure Node.js — requires native Rust binding.
256
+ *
257
+ * Native Rust binding dipakai di Node.js/SSR untuk performa maksimal.
258
+ *
259
+ * Browser fallback (Bug 2 — "Native binding 'resolveClassNames' is required
260
+ * but not available." crash di browser):
261
+ *
262
+ * getNativeBinding() return `null` di browser (bukan throw). Ketika itu terjadi
263
+ * kita gunakan pure-TS fallback yang semantiknya identik dengan implementasi Rust:
264
+ * - cn(): filter falsy + join spasi (identik dengan resolve_class_names di Rust)
265
+ * - cx(): conflict-aware merge via twMergeRawJs (port dari tw_merge.rs)
266
+ * - cxn(): flatten nested array + filter falsy + join spasi
267
+ *
268
+ * Server path TIDAK DIUBAH: throw Error tetap dijalankan jika native null di
269
+ * Node.js (menandakan miskonfigurasi). Fallback hanya aktif saat isBrowser=true.
257
270
  */
258
271
  type ClassValue = string | undefined | null | false | 0;
259
272
  /**
260
273
  * cn — simple class name joiner (no conflict resolution).
261
- * Delegates ke Rust `resolve_class_names`.
274
+ * Node.js: delegates ke Rust `resolve_class_names`.
275
+ * Browser: pure-TS fallback — filter falsy + join spasi.
262
276
  *
263
277
  * @example cn("p-4", isActive && "opacity-100") → "p-4 opacity-100"
264
278
  */
265
279
  declare function cn(...inputs: (ClassValue | ClassValue[])[]): string;
266
280
  /**
267
281
  * cx — conflict-aware class merger.
268
- * Delegates ke Rust `tw_merge_many`.
282
+ * Node.js: delegates ke Rust `tw_merge_many`.
283
+ * Browser: pure-TS fallback via twMergeRawJs (port algoritma Rust).
269
284
  *
270
285
  * @example cx("p-4 p-8") → "p-8"
271
286
  * @example cx("bg-red-500", "bg-blue-500") → "bg-blue-500"
package/dist/index.d.ts CHANGED
@@ -253,19 +253,34 @@ declare function cv<C extends ComponentConfig>(config: C, componentId?: string):
253
253
 
254
254
  /**
255
255
  * tailwind-styled-v4 v2 — cx / cn
256
- * Pure Node.js — requires native Rust binding.
256
+ *
257
+ * Native Rust binding dipakai di Node.js/SSR untuk performa maksimal.
258
+ *
259
+ * Browser fallback (Bug 2 — "Native binding 'resolveClassNames' is required
260
+ * but not available." crash di browser):
261
+ *
262
+ * getNativeBinding() return `null` di browser (bukan throw). Ketika itu terjadi
263
+ * kita gunakan pure-TS fallback yang semantiknya identik dengan implementasi Rust:
264
+ * - cn(): filter falsy + join spasi (identik dengan resolve_class_names di Rust)
265
+ * - cx(): conflict-aware merge via twMergeRawJs (port dari tw_merge.rs)
266
+ * - cxn(): flatten nested array + filter falsy + join spasi
267
+ *
268
+ * Server path TIDAK DIUBAH: throw Error tetap dijalankan jika native null di
269
+ * Node.js (menandakan miskonfigurasi). Fallback hanya aktif saat isBrowser=true.
257
270
  */
258
271
  type ClassValue = string | undefined | null | false | 0;
259
272
  /**
260
273
  * cn — simple class name joiner (no conflict resolution).
261
- * Delegates ke Rust `resolve_class_names`.
274
+ * Node.js: delegates ke Rust `resolve_class_names`.
275
+ * Browser: pure-TS fallback — filter falsy + join spasi.
262
276
  *
263
277
  * @example cn("p-4", isActive && "opacity-100") → "p-4 opacity-100"
264
278
  */
265
279
  declare function cn(...inputs: (ClassValue | ClassValue[])[]): string;
266
280
  /**
267
281
  * cx — conflict-aware class merger.
268
- * Delegates ke Rust `tw_merge_many`.
282
+ * Node.js: delegates ke Rust `tw_merge_many`.
283
+ * Browser: pure-TS fallback via twMergeRawJs (port algoritma Rust).
269
284
  *
270
285
  * @example cx("p-4 p-8") → "p-8"
271
286
  * @example cx("bg-red-500", "bg-blue-500") → "bg-blue-500"
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  "use strict";
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
@@ -289,22 +290,27 @@ if (typeof window !== "undefined") {
289
290
  window.__TW_CONTAINER_REGISTRY__ = containerRegistry;
290
291
  }
291
292
  var _hashContainerCache = /* @__PURE__ */ new Map();
293
+ function _fnvHash6(s) {
294
+ let h = 2166136261;
295
+ for (let i = 0; i < s.length; i++) {
296
+ h ^= s.charCodeAt(i);
297
+ h = Math.imul(h, 16777619) >>> 0;
298
+ }
299
+ return (h >>> 0).toString(16).padStart(8, "0").slice(0, 6);
300
+ }
292
301
  function hashContainer(tag, container, name) {
293
302
  const sortedKey = tag + (name ?? "") + JSON.stringify(Object.entries(container).sort());
294
303
  const cached = _hashContainerCache.get(sortedKey);
295
304
  if (cached) return cached;
296
305
  const native = getNativeBinding();
297
- if (!native?.hashContent) {
298
- throw new Error("FATAL: Native binding 'hashContent' is required but not available.");
299
- }
300
- const id = `tw-cq-${native.hashContent(sortedKey, "fnv", 6)}`;
306
+ const id = native?.hashContent ? `tw-cq-${native.hashContent(sortedKey, "fnv", 6)}` : `tw-cq-${_fnvHash6(sortedKey)}`;
301
307
  _hashContainerCache.set(sortedKey, id);
302
308
  return id;
303
309
  }
304
310
  function layoutClassesToCss(classes) {
305
311
  const native = getNativeBinding();
306
312
  if (!native?.layoutClassesToCss) {
307
- throw new Error("FATAL: Native binding 'layoutClassesToCss' is required but not available.");
313
+ return "";
308
314
  }
309
315
  return native.layoutClassesToCss(classes);
310
316
  }
@@ -465,96 +471,97 @@ var FONT_WEIGHT_NAMES = /* @__PURE__ */ new Set([
465
471
  var TEXT_ALIGN_VALUES = /* @__PURE__ */ new Set(["left", "center", "right", "justify", "start", "end"]);
466
472
  var BORDER_SIDE_PREFIXES = ["t-", "r-", "b-", "l-", "x-", "y-", "s-", "e-"];
467
473
  var BORDER_STYLE_VALUES = /* @__PURE__ */ new Set(["solid", "dashed", "dotted", "double", "hidden", "none"]);
468
- function conflictGroup(base) {
469
- const bracket = base.indexOf("[");
474
+ function conflictGroup(base, prefix = "") {
475
+ const b = prefix && base.startsWith(prefix) ? base.slice(prefix.length) : base;
476
+ const bracket = b.indexOf("[");
470
477
  if (bracket !== -1) {
471
- const prefix = base.slice(0, bracket).replace(/-+$/, "");
472
- return prefix.length > 0 ? prefix : "arbitrary";
473
- }
474
- if (DISPLAY_VALUES.has(base)) return "display";
475
- if (POSITION_VALUES.has(base)) return "position";
476
- if (base.startsWith("overflow-x-")) return "overflow-x";
477
- if (base.startsWith("overflow-y-")) return "overflow-y";
478
- if (base.startsWith("overflow-")) return "overflow";
479
- if (base.startsWith("flex-")) return "flex";
480
- if (base.startsWith("grid-cols-")) return "grid-cols";
481
- if (base.startsWith("grid-rows-")) return "grid-rows";
482
- if (base.startsWith("grid-flow-")) return "grid-flow";
483
- if (base.startsWith("col-")) return "col";
484
- if (base.startsWith("row-")) return "row";
485
- if (base === "grow" || base.startsWith("grow-")) return "grow";
486
- if (base === "shrink" || base.startsWith("shrink-")) return "shrink";
487
- if (base.startsWith("gap-x-")) return "gap-x";
488
- if (base.startsWith("gap-y-")) return "gap-y";
489
- if (base.startsWith("gap-")) return "gap";
490
- if (base.startsWith("justify-items-")) return "justify-items";
491
- if (base.startsWith("justify-self-")) return "justify-self";
492
- if (base.startsWith("justify-")) return "justify";
493
- if (base.startsWith("items-")) return "items";
494
- if (base.startsWith("self-")) return "self";
495
- if (base.startsWith("place-content-")) return "place-content";
496
- if (base.startsWith("place-items-")) return "place-items";
497
- if (base.startsWith("place-self-")) return "place-self";
498
- if (base.startsWith("content-")) return "content";
499
- if (base.startsWith("px-")) return "px";
500
- if (base.startsWith("py-")) return "py";
501
- if (base.startsWith("pt-")) return "pt";
502
- if (base.startsWith("pr-")) return "pr";
503
- if (base.startsWith("pb-")) return "pb";
504
- if (base.startsWith("pl-")) return "pl";
505
- if (base.startsWith("ps-")) return "ps";
506
- if (base.startsWith("pe-")) return "pe";
507
- if (base.startsWith("p-")) return "p";
508
- if (base.startsWith("mx-")) return "mx";
509
- if (base.startsWith("my-")) return "my";
510
- if (base.startsWith("mt-")) return "mt";
511
- if (base.startsWith("mr-")) return "mr";
512
- if (base.startsWith("mb-")) return "mb";
513
- if (base.startsWith("ml-")) return "ml";
514
- if (base.startsWith("ms-")) return "ms";
515
- if (base.startsWith("me-")) return "me";
516
- if (base === "-m" || base.startsWith("m-") || base.startsWith("-m-")) return "m";
517
- if (base.startsWith("space-x-")) return "space-x";
518
- if (base.startsWith("space-y-")) return "space-y";
519
- if (base.startsWith("size-")) return "size";
520
- if (base.startsWith("min-w-")) return "min-w";
521
- if (base.startsWith("max-w-")) return "max-w";
522
- if (base.startsWith("w-")) return "w";
523
- if (base.startsWith("min-h-")) return "min-h";
524
- if (base.startsWith("max-h-")) return "max-h";
525
- if (base.startsWith("h-")) return "h";
526
- if (base.startsWith("inset-x-")) return "inset-x";
527
- if (base.startsWith("inset-y-")) return "inset-y";
528
- if (base.startsWith("inset-")) return "inset";
529
- if (base.startsWith("top-")) return "top";
530
- if (base.startsWith("right-") || base.startsWith("end-")) return "right";
531
- if (base.startsWith("bottom-")) return "bottom";
532
- if (base.startsWith("left-") || base.startsWith("start-")) return "left";
533
- if (base.startsWith("z-")) return "z";
534
- if (base.startsWith("opacity-")) return "opacity";
535
- if (base.startsWith("bg-")) {
536
- if (base.startsWith("bg-opacity-")) return "bg-opacity";
478
+ const grp = b.slice(0, bracket).replace(/-+$/, "");
479
+ return grp.length > 0 ? grp : "arbitrary";
480
+ }
481
+ if (DISPLAY_VALUES.has(b)) return "display";
482
+ if (POSITION_VALUES.has(b)) return "position";
483
+ if (b.startsWith("overflow-x-")) return "overflow-x";
484
+ if (b.startsWith("overflow-y-")) return "overflow-y";
485
+ if (b.startsWith("overflow-")) return "overflow";
486
+ if (b.startsWith("flex-")) return "flex";
487
+ if (b.startsWith("grid-cols-")) return "grid-cols";
488
+ if (b.startsWith("grid-rows-")) return "grid-rows";
489
+ if (b.startsWith("grid-flow-")) return "grid-flow";
490
+ if (b.startsWith("col-")) return "col";
491
+ if (b.startsWith("row-")) return "row";
492
+ if (b === "grow" || b.startsWith("grow-")) return "grow";
493
+ if (b === "shrink" || b.startsWith("shrink-")) return "shrink";
494
+ if (b.startsWith("gap-x-")) return "gap-x";
495
+ if (b.startsWith("gap-y-")) return "gap-y";
496
+ if (b.startsWith("gap-")) return "gap";
497
+ if (b.startsWith("justify-items-")) return "justify-items";
498
+ if (b.startsWith("justify-self-")) return "justify-self";
499
+ if (b.startsWith("justify-")) return "justify";
500
+ if (b.startsWith("items-")) return "items";
501
+ if (b.startsWith("self-")) return "self";
502
+ if (b.startsWith("place-content-")) return "place-content";
503
+ if (b.startsWith("place-items-")) return "place-items";
504
+ if (b.startsWith("place-self-")) return "place-self";
505
+ if (b.startsWith("content-")) return "content";
506
+ if (b.startsWith("px-")) return "px";
507
+ if (b.startsWith("py-")) return "py";
508
+ if (b.startsWith("pt-")) return "pt";
509
+ if (b.startsWith("pr-")) return "pr";
510
+ if (b.startsWith("pb-")) return "pb";
511
+ if (b.startsWith("pl-")) return "pl";
512
+ if (b.startsWith("ps-")) return "ps";
513
+ if (b.startsWith("pe-")) return "pe";
514
+ if (b.startsWith("p-")) return "p";
515
+ if (b.startsWith("mx-")) return "mx";
516
+ if (b.startsWith("my-")) return "my";
517
+ if (b.startsWith("mt-")) return "mt";
518
+ if (b.startsWith("mr-")) return "mr";
519
+ if (b.startsWith("mb-")) return "mb";
520
+ if (b.startsWith("ml-")) return "ml";
521
+ if (b.startsWith("ms-")) return "ms";
522
+ if (b.startsWith("me-")) return "me";
523
+ if (b === "-m" || b.startsWith("m-") || b.startsWith("-m-")) return "m";
524
+ if (b.startsWith("space-x-")) return "space-x";
525
+ if (b.startsWith("space-y-")) return "space-y";
526
+ if (b.startsWith("size-")) return "size";
527
+ if (b.startsWith("min-w-")) return "min-w";
528
+ if (b.startsWith("max-w-")) return "max-w";
529
+ if (b.startsWith("w-")) return "w";
530
+ if (b.startsWith("min-h-")) return "min-h";
531
+ if (b.startsWith("max-h-")) return "max-h";
532
+ if (b.startsWith("h-")) return "h";
533
+ if (b.startsWith("inset-x-")) return "inset-x";
534
+ if (b.startsWith("inset-y-")) return "inset-y";
535
+ if (b.startsWith("inset-")) return "inset";
536
+ if (b.startsWith("top-")) return "top";
537
+ if (b.startsWith("right-") || b.startsWith("end-")) return "right";
538
+ if (b.startsWith("bottom-")) return "bottom";
539
+ if (b.startsWith("left-") || b.startsWith("start-")) return "left";
540
+ if (b.startsWith("z-")) return "z";
541
+ if (b.startsWith("opacity-")) return "opacity";
542
+ if (b.startsWith("bg-")) {
543
+ if (b.startsWith("bg-opacity-")) return "bg-opacity";
537
544
  return "bg";
538
545
  }
539
- if (base.startsWith("from-")) return "from";
540
- if (base.startsWith("via-")) return "via";
541
- if (base.startsWith("to-")) return "to";
542
- if (base.startsWith("text-")) {
543
- const suffix = base.slice("text-".length);
546
+ if (b.startsWith("from-")) return "from";
547
+ if (b.startsWith("via-")) return "via";
548
+ if (b.startsWith("to-")) return "to";
549
+ if (b.startsWith("text-")) {
550
+ const suffix = b.slice("text-".length);
544
551
  if (isTextSize(suffix)) return "text-size";
545
552
  if (suffix.startsWith("opacity-")) return "text-opacity";
546
553
  if (TEXT_ALIGN_VALUES.has(suffix)) return "text-align";
547
554
  return "text-color";
548
555
  }
549
- if (base.startsWith("font-")) {
550
- const suffix = base.slice("font-".length);
556
+ if (b.startsWith("font-")) {
557
+ const suffix = b.slice("font-".length);
551
558
  if (FONT_WEIGHT_NAMES.has(suffix) || isAsciiDigits(suffix)) return "font-weight";
552
559
  return "font-family";
553
560
  }
554
- if (base.startsWith("leading-")) return "leading";
555
- if (base.startsWith("tracking-")) return "tracking";
556
- if (base.startsWith("border-")) {
557
- const suffix = base.slice("border-".length);
561
+ if (b.startsWith("leading-")) return "leading";
562
+ if (b.startsWith("tracking-")) return "tracking";
563
+ if (b.startsWith("border-")) {
564
+ const suffix = b.slice("border-".length);
558
565
  const sidePrefix = BORDER_SIDE_PREFIXES.find((p) => suffix.startsWith(p));
559
566
  if (sidePrefix) {
560
567
  const side = suffix.slice(0, 1);
@@ -568,67 +575,67 @@ function conflictGroup(base) {
568
575
  if (BORDER_STYLE_VALUES.has(suffix)) return "border-style";
569
576
  return "border-color";
570
577
  }
571
- if (base === "border") return "border-width";
572
- if (base.startsWith("outline-")) return "outline";
573
- if (base === "outline") return "outline";
574
- if (base.startsWith("rounded-t") || base.startsWith("rounded-r") || base.startsWith("rounded-b") || base.startsWith("rounded-l") || base.startsWith("rounded-s") || base.startsWith("rounded-e")) {
575
- const firstChar = base.slice("rounded-".length).charAt(0) || "x";
578
+ if (b === "border") return "border-width";
579
+ if (b.startsWith("outline-")) return "outline";
580
+ if (b === "outline") return "outline";
581
+ if (b.startsWith("rounded-t") || b.startsWith("rounded-r") || b.startsWith("rounded-b") || b.startsWith("rounded-l") || b.startsWith("rounded-s") || b.startsWith("rounded-e")) {
582
+ const firstChar = b.slice("rounded-".length).charAt(0) || "x";
576
583
  return `rounded-${firstChar}`;
577
584
  }
578
- if (base === "rounded" || base.startsWith("rounded-")) return "rounded";
579
- if (base === "shadow" || base.startsWith("shadow-")) return "shadow";
580
- if (base.startsWith("ring-offset-")) return "ring-offset";
581
- if (base === "ring") return "ring-width";
582
- if (base.startsWith("ring-")) {
583
- const rest = base.slice("ring-".length);
585
+ if (b === "rounded" || b.startsWith("rounded-")) return "rounded";
586
+ if (b === "shadow" || b.startsWith("shadow-")) return "shadow";
587
+ if (b.startsWith("ring-offset-")) return "ring-offset";
588
+ if (b === "ring") return "ring-width";
589
+ if (b.startsWith("ring-")) {
590
+ const rest = b.slice("ring-".length);
584
591
  const isWidth = rest === "0" || rest === "1" || rest === "2" || rest === "4" || rest === "8" || /^-?\d+(\.\d+)?$/.test(rest) || rest.startsWith("[") && rest.endsWith("]");
585
592
  if (isWidth) return "ring-width";
586
593
  if (rest === "inset") return "ring-inset";
587
594
  return "ring-color";
588
595
  }
589
- if (base.startsWith("rotate-")) return "rotate";
590
- if (base.startsWith("scale-x-")) return "scale-x";
591
- if (base.startsWith("scale-y-")) return "scale-y";
592
- if (base.startsWith("scale-")) return "scale";
593
- if (base.startsWith("translate-x-")) return "translate-x";
594
- if (base.startsWith("translate-y-")) return "translate-y";
595
- if (base.startsWith("skew-x-")) return "skew-x";
596
- if (base.startsWith("skew-y-")) return "skew-y";
597
- if (base === "transition" || base.startsWith("transition-")) return "transition";
598
- if (base.startsWith("duration-")) return "duration";
599
- if (base.startsWith("ease-")) return "ease";
600
- if (base.startsWith("delay-")) return "delay";
601
- if (base === "animate" || base.startsWith("animate-")) return "animate";
602
- if (base.startsWith("cursor-")) return "cursor";
603
- if (base.startsWith("pointer-events-")) return "pointer-events";
604
- if (base.startsWith("select-")) return "select";
605
- if (base === "visible" || base === "invisible" || base === "collapse") return "visibility";
606
- if (base.startsWith("object-")) return "object";
607
- if (base.startsWith("aspect-")) return "aspect";
608
- if (base.startsWith("order-")) return "order";
609
- if (base.startsWith("whitespace-")) return "whitespace";
610
- if (base.startsWith("list-")) return "list";
611
- if (base.startsWith("fill-")) return "fill";
612
- if (base.startsWith("stroke-")) return "stroke";
613
- if (base.startsWith("backdrop-")) {
614
- const rest = base.slice("backdrop-".length);
596
+ if (b.startsWith("rotate-")) return "rotate";
597
+ if (b.startsWith("scale-x-")) return "scale-x";
598
+ if (b.startsWith("scale-y-")) return "scale-y";
599
+ if (b.startsWith("scale-")) return "scale";
600
+ if (b.startsWith("translate-x-")) return "translate-x";
601
+ if (b.startsWith("translate-y-")) return "translate-y";
602
+ if (b.startsWith("skew-x-")) return "skew-x";
603
+ if (b.startsWith("skew-y-")) return "skew-y";
604
+ if (b === "transition" || b.startsWith("transition-")) return "transition";
605
+ if (b.startsWith("duration-")) return "duration";
606
+ if (b.startsWith("ease-")) return "ease";
607
+ if (b.startsWith("delay-")) return "delay";
608
+ if (b === "animate" || b.startsWith("animate-")) return "animate";
609
+ if (b.startsWith("cursor-")) return "cursor";
610
+ if (b.startsWith("pointer-events-")) return "pointer-events";
611
+ if (b.startsWith("select-")) return "select";
612
+ if (b === "visible" || b === "invisible" || b === "collapse") return "visibility";
613
+ if (b.startsWith("object-")) return "object";
614
+ if (b.startsWith("aspect-")) return "aspect";
615
+ if (b.startsWith("order-")) return "order";
616
+ if (b.startsWith("whitespace-")) return "whitespace";
617
+ if (b.startsWith("list-")) return "list";
618
+ if (b.startsWith("fill-")) return "fill";
619
+ if (b.startsWith("stroke-")) return "stroke";
620
+ if (b.startsWith("backdrop-")) {
621
+ const rest = b.slice("backdrop-".length);
615
622
  const seg = rest.split("-")[0] || "x";
616
623
  return `backdrop-${seg}`;
617
624
  }
618
- if (base.startsWith("scroll-")) return "scroll";
619
- if (base.startsWith("snap-")) return "snap";
620
- if (base.startsWith("touch-")) return "touch";
621
- if (base.startsWith("decoration-")) return "text-decoration";
622
- if (base.startsWith("caret-")) return "caret";
623
- if (base.startsWith("accent-")) return "accent";
624
- if (base.startsWith("appearance-")) return "appearance";
625
- if (base === "isolate" || base === "isolation-auto") return "isolation";
626
- if (base.startsWith("mix-blend-")) return "mix-blend";
627
- if (base.startsWith("bg-blend-")) return "bg-blend";
628
- if (base.startsWith("float-")) return "float";
629
- if (base.startsWith("clear-")) return "clear";
630
- if (base.startsWith("break-")) return "break";
631
- if (base.startsWith("columns-")) return "columns";
625
+ if (b.startsWith("scroll-")) return "scroll";
626
+ if (b.startsWith("snap-")) return "snap";
627
+ if (b.startsWith("touch-")) return "touch";
628
+ if (b.startsWith("decoration-")) return "text-decoration";
629
+ if (b.startsWith("caret-")) return "caret";
630
+ if (b.startsWith("accent-")) return "accent";
631
+ if (b.startsWith("appearance-")) return "appearance";
632
+ if (b === "isolate" || b === "isolation-auto") return "isolation";
633
+ if (b.startsWith("mix-blend-")) return "mix-blend";
634
+ if (b.startsWith("bg-blend-")) return "bg-blend";
635
+ if (b.startsWith("float-")) return "float";
636
+ if (b.startsWith("clear-")) return "clear";
637
+ if (b.startsWith("break-")) return "break";
638
+ if (b.startsWith("columns-")) return "columns";
632
639
  return null;
633
640
  }
634
641
  function splitVariants(klass) {
@@ -643,7 +650,7 @@ function splitVariants(klass) {
643
650
  if (lastColon === 0) return ["", klass];
644
651
  return [klass.slice(0, lastColon), klass.slice(lastColon)];
645
652
  }
646
- function mergeClassStringJs(input) {
653
+ function mergeClassStringJs(input, prefix = "") {
647
654
  const tokens = input.split(/\s+/).filter(Boolean);
648
655
  if (tokens.length === 0) return "";
649
656
  if (tokens.length === 1) return tokens[0];
@@ -651,7 +658,7 @@ function mergeClassStringJs(input) {
651
658
  const slots = [];
652
659
  for (const token of tokens) {
653
660
  const [variants, base] = splitVariants(token);
654
- const group = conflictGroup(base);
661
+ const group = conflictGroup(base, prefix);
655
662
  if (group !== null) {
656
663
  const key = `${variants}::${group}`;
657
664
  const prevIdx = groupOwner.get(key);
@@ -664,10 +671,10 @@ function mergeClassStringJs(input) {
664
671
  }
665
672
  return slots.filter((s) => s !== null).join(" ");
666
673
  }
667
- function twMergeRawJs(classLists) {
674
+ function twMergeRawJs(classLists, prefix = "") {
668
675
  const joined = classLists.map((s) => s.trim()).filter((s) => s.length > 0).join(" ");
669
676
  if (joined.length === 0) return "";
670
- return mergeClassStringJs(joined);
677
+ return mergeClassStringJs(joined, prefix);
671
678
  }
672
679
 
673
680
  // packages/domain/core/src/merge.ts
@@ -682,6 +689,7 @@ function warnFallbackOnce() {
682
689
  }
683
690
  }
684
691
  function createTwMerge(options = {}) {
692
+ const prefix = options.prefix ?? "";
685
693
  return function twMerge2(...classLists) {
686
694
  const inputs = [];
687
695
  for (let i = 0; i < classLists.length; i++) {
@@ -690,11 +698,16 @@ function createTwMerge(options = {}) {
690
698
  }
691
699
  if (inputs.length === 0) return "";
692
700
  const native = getNativeBinding();
693
- if (native?.twMergeRaw) {
694
- return native.twMergeRaw(inputs);
701
+ if (native) {
702
+ if (prefix && native.twMergeRawWithOptions) {
703
+ return native.twMergeRawWithOptions(inputs, { prefix });
704
+ }
705
+ if (native.twMergeRaw) {
706
+ return native.twMergeRaw(inputs);
707
+ }
695
708
  }
696
709
  warnFallbackOnce();
697
- return twMergeRawJs(inputs);
710
+ return twMergeRawJs(inputs, prefix);
698
711
  };
699
712
  }
700
713
  var twMerge = createTwMerge();
@@ -707,6 +720,37 @@ function mergeWithRules(rules, ...classLists) {
707
720
  return classes.join(" ");
708
721
  }
709
722
 
723
+ // packages/domain/core/src/parseTemplateFallback.ts
724
+ init_cjs_shims();
725
+ var SUB_RE = /(?:\[([a-zA-Z][a-zA-Z0-9_-]*)\]|([a-zA-Z][a-zA-Z0-9_-]*))\s*\{([^}]*)\}/g;
726
+ var COMMENT_RE = /\/\/[^\n]*/g;
727
+ function collapseSpaces(s) {
728
+ return s.replace(/\s+/g, " ").trim();
729
+ }
730
+ function cleanBlock(raw) {
731
+ const noComments = raw.replace(COMMENT_RE, "");
732
+ const lines = noComments.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
733
+ return collapseSpaces(lines.join(" "));
734
+ }
735
+ function parseTemplateJs(raw) {
736
+ const subs = {};
737
+ let base = raw;
738
+ for (const match of raw.matchAll(SUB_RE)) {
739
+ const fullMatch = match[0];
740
+ const name = match[1] ?? match[2] ?? "";
741
+ const innerRaw = match[3] ?? "";
742
+ if (name) {
743
+ subs[name] = cleanBlock(innerRaw);
744
+ }
745
+ base = base.replace(fullMatch, "");
746
+ }
747
+ return {
748
+ base: collapseSpaces(base),
749
+ subs,
750
+ hasSubs: Object.keys(subs).length > 0
751
+ };
752
+ }
753
+
710
754
  // packages/domain/core/src/stateEngine.ts
711
755
  init_cjs_shims();
712
756
  var stateRegistry = /* @__PURE__ */ new Map();
@@ -714,22 +758,27 @@ if (typeof window !== "undefined") {
714
758
  window.__TW_STATE_REGISTRY__ = stateRegistry;
715
759
  }
716
760
  var _hashStateCache = /* @__PURE__ */ new Map();
761
+ function _fnvHash62(s) {
762
+ let h = 2166136261;
763
+ for (let i = 0; i < s.length; i++) {
764
+ h ^= s.charCodeAt(i);
765
+ h = Math.imul(h, 16777619) >>> 0;
766
+ }
767
+ return (h >>> 0).toString(16).padStart(8, "0").slice(0, 6);
768
+ }
717
769
  function hashState(tag, state) {
718
770
  const sortedKey = tag + JSON.stringify(Object.entries(state).sort());
719
771
  const cached = _hashStateCache.get(sortedKey);
720
772
  if (cached) return cached;
721
773
  const native = getNativeBinding();
722
- if (!native?.hashContent) {
723
- throw new Error("FATAL: Native binding 'hashContent' is required but not available.");
724
- }
725
- const id = `tw-s-${native.hashContent(sortedKey, "fnv", 6)}`;
774
+ const id = native?.hashContent ? `tw-s-${native.hashContent(sortedKey, "fnv", 6)}` : `tw-s-${_fnvHash62(sortedKey)}`;
726
775
  _hashStateCache.set(sortedKey, id);
727
776
  return id;
728
777
  }
729
778
  function generateStateRules(id, state) {
730
779
  const native = getNativeBinding();
731
780
  if (!native?.generateRuntimeStateCss) {
732
- throw new Error("FATAL: Native binding 'generateRuntimeStateCss' is required but not available.");
781
+ return [];
733
782
  }
734
783
  return native.generateRuntimeStateCss(id, JSON.stringify(state), null).map((rule) => rule.cssRule);
735
784
  }
@@ -817,7 +866,13 @@ function _getParsedTemplate(template) {
817
866
  }
818
867
  const native = getNativeBinding();
819
868
  if (!native?.parseSubcomponentBlocksNapi) {
820
- throw new Error("FATAL: Native binding 'parseSubcomponentBlocksNapi' is required but not available.");
869
+ const fb = parseTemplateJs(template);
870
+ const result2 = {
871
+ baseClasses: fb.base,
872
+ subMap: new Map(Object.entries(fb.subs))
873
+ };
874
+ _templateParseCache.set(template, result2);
875
+ return result2;
821
876
  }
822
877
  const r = native.parseSubcomponentBlocksNapi(template, "tw");
823
878
  const raw = JSON.parse(r.subMapJson);
@@ -969,10 +1024,16 @@ function resolveVariants(variants, props, defaults) {
969
1024
  }
970
1025
  const binding = getNativeBinding();
971
1026
  if (!binding?.resolveSimpleVariants) {
972
- throw new Error("FATAL: Native binding 'resolveSimpleVariants' is required but not available.");
1027
+ const classes = [];
1028
+ for (const key of Object.keys(variants)) {
1029
+ const propValue = cleanProps[key] ?? defaults[key];
1030
+ if (propValue !== void 0 && variants[key]?.[propValue]) {
1031
+ classes.push(variants[key][propValue]);
1032
+ }
1033
+ }
1034
+ return classes.join(" ").trim().replace(/\s+/g, " ");
973
1035
  }
974
- const result = binding.resolveSimpleVariants(null, variants, defaults, cleanProps);
975
- return result.trim().replace(/\s+/g, " ");
1036
+ return binding.resolveSimpleVariants(null, variants, defaults, cleanProps).trim().replace(/\s+/g, " ");
976
1037
  }
977
1038
  function resolveStates(statesConfig, stateKeys, statesLookup, props) {
978
1039
  if (statesLookup && stateKeys.length > 0) {
@@ -1196,7 +1257,10 @@ function parseTemplate(strings, exprs) {
1196
1257
  if (cached) return cached;
1197
1258
  const binding = getNativeBinding();
1198
1259
  if (!binding?.parseTemplate) {
1199
- throw new Error("FATAL: Native binding 'parseTemplate' is required but not available.");
1260
+ const fb = parseTemplateJs(raw);
1261
+ const result2 = { base: fb.base, subs: fb.subs, hasSubs: fb.hasSubs };
1262
+ _parsedTemplateCache.set(raw, result2);
1263
+ return result2;
1200
1264
  }
1201
1265
  const r = binding.parseTemplate(raw);
1202
1266
  const subs = r.hasSubs ? JSON.parse(r.subsJson) : {};
@@ -1513,19 +1577,25 @@ function cn(...inputs) {
1513
1577
  }
1514
1578
  if (strings.length === 0) return "";
1515
1579
  const native = getNativeBinding();
1516
- if (!native?.resolveClassNames) {
1580
+ if (native?.resolveClassNames) {
1581
+ return native.resolveClassNames(strings);
1582
+ }
1583
+ if (native !== null) {
1517
1584
  throw new Error("Native binding 'resolveClassNames' is required but not available.");
1518
1585
  }
1519
- return native.resolveClassNames(strings);
1586
+ return strings.filter(Boolean).join(" ");
1520
1587
  }
1521
1588
  function cx(...inputs) {
1522
1589
  const filtered = inputs.flat().filter(Boolean);
1523
1590
  if (filtered.length === 0) return "";
1524
1591
  const native = getNativeBinding();
1525
- if (!native?.twMergeMany) {
1592
+ if (native?.twMergeMany) {
1593
+ return native.twMergeMany(filtered);
1594
+ }
1595
+ if (native !== null) {
1526
1596
  throw new Error("Native binding 'twMergeMany' is required but not available.");
1527
1597
  }
1528
- return native.twMergeMany(filtered);
1598
+ return twMergeRawJs(filtered);
1529
1599
  }
1530
1600
  var cxm = cx;
1531
1601