tailwind-styled-v4 5.0.7 → 5.0.9
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/CHANGELOG.md +184 -410
- package/README.md +45 -15
- package/dist/cli.js +62 -52
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +62 -52
- package/dist/cli.mjs.map +1 -1
- package/dist/compiler.d.mts +8 -3
- package/dist/compiler.d.ts +8 -3
- package/dist/compiler.js +214 -127
- package/dist/compiler.js.map +1 -1
- package/dist/compiler.mjs +195 -103
- package/dist/compiler.mjs.map +1 -1
- package/dist/engine.js +146 -66
- package/dist/engine.js.map +1 -1
- package/dist/engine.mjs +146 -66
- package/dist/engine.mjs.map +1 -1
- package/dist/index.d.mts +26 -8
- package/dist/index.d.ts +26 -8
- package/dist/index.js +72 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +72 -19
- package/dist/index.mjs.map +1 -1
- package/dist/next.d.mts +12 -40
- package/dist/next.d.ts +12 -40
- package/dist/next.js +27 -320
- package/dist/next.js.map +1 -1
- package/dist/next.mjs +27 -320
- package/dist/next.mjs.map +1 -1
- package/dist/turbopackLoader.js +137 -88
- package/dist/turbopackLoader.js.map +1 -1
- package/dist/turbopackLoader.mjs +137 -88
- package/dist/turbopackLoader.mjs.map +1 -1
- package/dist/tw.js +62 -52
- package/dist/tw.js.map +1 -1
- package/dist/tw.mjs +62 -52
- package/dist/tw.mjs.map +1 -1
- package/dist/vite.js +146 -66
- package/dist/vite.js.map +1 -1
- package/dist/vite.mjs +146 -66
- package/dist/vite.mjs.map +1 -1
- package/dist/webpackLoader.js +92 -83
- package/dist/webpackLoader.js.map +1 -1
- package/dist/webpackLoader.mjs +92 -83
- package/dist/webpackLoader.mjs.map +1 -1
- package/native/tailwind-styled-native.node +0 -0
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -26,7 +26,12 @@ interface ComponentConfig {
|
|
|
26
26
|
state?: Record<string, Record<string, string>>;
|
|
27
27
|
container?: Record<string, string>;
|
|
28
28
|
containerName?: string;
|
|
29
|
+
/** Sub-component definitions — keys di-infer otomatis oleh TypeScript */
|
|
30
|
+
sub?: Record<string, string>;
|
|
29
31
|
}
|
|
32
|
+
type InferSubFromConfig<C extends ComponentConfig> = C extends {
|
|
33
|
+
sub: Record<infer K extends string, string>;
|
|
34
|
+
} ? K : never;
|
|
30
35
|
interface ContainerConfig {
|
|
31
36
|
base?: string;
|
|
32
37
|
queries?: Record<string, string>;
|
|
@@ -54,14 +59,14 @@ type TwSubComponentAccessor = React.FC<{
|
|
|
54
59
|
children?: React.ReactNode;
|
|
55
60
|
className?: string;
|
|
56
61
|
}>;
|
|
57
|
-
type TrimLeft<S extends string> = S extends ` ${infer R}` | `
|
|
58
|
-
${infer R}` | ` ${infer R}` | `
|
|
62
|
+
type TrimLeft<S extends string> = S extends ` ${infer R}` | `
|
|
63
|
+
${infer R}` | ` ${infer R}` | `
|
|
59
64
|
${infer R}` ? TrimLeft<R> : S;
|
|
60
|
-
type TrimRight<S extends string> = S extends `${infer L} ` | `${infer L}
|
|
61
|
-
` | `${infer L} ` | `${infer L}
|
|
65
|
+
type TrimRight<S extends string> = S extends `${infer L} ` | `${infer L}
|
|
66
|
+
` | `${infer L} ` | `${infer L}
|
|
62
67
|
` ? TrimRight<L> : S;
|
|
63
68
|
type Trim<S extends string> = TrimLeft<TrimRight<S>>;
|
|
64
|
-
type ExtractSubNames<T extends string> = T extends `${
|
|
69
|
+
type ExtractSubNames<T extends string> = T extends `${string}[${infer Name}]${string}{${string}}${infer Rest}` ? Trim<Name> | ExtractSubNames<Rest> : T extends `${string}\n${infer Name}{${string}}${infer Rest}` ? (Trim<Name> extends "" ? never : Trim<Name>) | ExtractSubNames<Rest> : never;
|
|
65
70
|
type SubComponentKeys<S extends string> = string extends S ? {
|
|
66
71
|
[key: string]: TwSubComponentAccessor;
|
|
67
72
|
} : {
|
|
@@ -80,7 +85,20 @@ type TwStyledComponent<Config extends ComponentConfig = ComponentConfig, S exten
|
|
|
80
85
|
}): TwStyledComponent<Config, S>;
|
|
81
86
|
};
|
|
82
87
|
withVariants: (config: Partial<Config>) => TwStyledComponent<Config, S>;
|
|
83
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Declare sub-component names secara eksplisit untuk autocomplete + type safety.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* export const Button = tw.button`
|
|
93
|
+
* flex h-12 ...
|
|
94
|
+
* icon { flex h-4 }
|
|
95
|
+
* `.withSub<"icon" | "footer">()
|
|
96
|
+
*
|
|
97
|
+
* Button.icon // ✅ autocomplete
|
|
98
|
+
* Button.footer // ✅ autocomplete
|
|
99
|
+
* Button.xyz // ❌ TypeScript error
|
|
100
|
+
*/
|
|
101
|
+
withSub<NewS extends string>(): TwStyledComponent<Config, NewS>;
|
|
84
102
|
animate: (opts: AnimateOptions) => Promise<TwStyledComponent<Config, S>>;
|
|
85
103
|
} & SubComponentKeys<S>;
|
|
86
104
|
interface TwSubComponent<P = unknown> {
|
|
@@ -88,9 +106,9 @@ interface TwSubComponent<P = unknown> {
|
|
|
88
106
|
displayName?: string;
|
|
89
107
|
}
|
|
90
108
|
interface TwTemplateFactory<Config extends ComponentConfig = ComponentConfig> {
|
|
91
|
-
<const T extends string>(strings: readonly [T
|
|
109
|
+
<const T extends string>(strings: readonly [T], ...exprs: []): TwStyledComponent<Config, ExtractSubNames<T>>;
|
|
92
110
|
(strings: TemplateStringsArray, ...exprs: unknown[]): TwStyledComponent<Config, string>;
|
|
93
|
-
<C extends ComponentConfig>(config: C): TwStyledComponent<C,
|
|
111
|
+
<C extends ComponentConfig>(config: C): TwStyledComponent<C, InferSubFromConfig<C>>;
|
|
94
112
|
}
|
|
95
113
|
type TwTagFactory = {
|
|
96
114
|
[K in HtmlTagName]: TwTemplateFactory;
|
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,12 @@ interface ComponentConfig {
|
|
|
26
26
|
state?: Record<string, Record<string, string>>;
|
|
27
27
|
container?: Record<string, string>;
|
|
28
28
|
containerName?: string;
|
|
29
|
+
/** Sub-component definitions — keys di-infer otomatis oleh TypeScript */
|
|
30
|
+
sub?: Record<string, string>;
|
|
29
31
|
}
|
|
32
|
+
type InferSubFromConfig<C extends ComponentConfig> = C extends {
|
|
33
|
+
sub: Record<infer K extends string, string>;
|
|
34
|
+
} ? K : never;
|
|
30
35
|
interface ContainerConfig {
|
|
31
36
|
base?: string;
|
|
32
37
|
queries?: Record<string, string>;
|
|
@@ -54,14 +59,14 @@ type TwSubComponentAccessor = React.FC<{
|
|
|
54
59
|
children?: React.ReactNode;
|
|
55
60
|
className?: string;
|
|
56
61
|
}>;
|
|
57
|
-
type TrimLeft<S extends string> = S extends ` ${infer R}` | `
|
|
58
|
-
${infer R}` | ` ${infer R}` | `
|
|
62
|
+
type TrimLeft<S extends string> = S extends ` ${infer R}` | `
|
|
63
|
+
${infer R}` | ` ${infer R}` | `
|
|
59
64
|
${infer R}` ? TrimLeft<R> : S;
|
|
60
|
-
type TrimRight<S extends string> = S extends `${infer L} ` | `${infer L}
|
|
61
|
-
` | `${infer L} ` | `${infer L}
|
|
65
|
+
type TrimRight<S extends string> = S extends `${infer L} ` | `${infer L}
|
|
66
|
+
` | `${infer L} ` | `${infer L}
|
|
62
67
|
` ? TrimRight<L> : S;
|
|
63
68
|
type Trim<S extends string> = TrimLeft<TrimRight<S>>;
|
|
64
|
-
type ExtractSubNames<T extends string> = T extends `${
|
|
69
|
+
type ExtractSubNames<T extends string> = T extends `${string}[${infer Name}]${string}{${string}}${infer Rest}` ? Trim<Name> | ExtractSubNames<Rest> : T extends `${string}\n${infer Name}{${string}}${infer Rest}` ? (Trim<Name> extends "" ? never : Trim<Name>) | ExtractSubNames<Rest> : never;
|
|
65
70
|
type SubComponentKeys<S extends string> = string extends S ? {
|
|
66
71
|
[key: string]: TwSubComponentAccessor;
|
|
67
72
|
} : {
|
|
@@ -80,7 +85,20 @@ type TwStyledComponent<Config extends ComponentConfig = ComponentConfig, S exten
|
|
|
80
85
|
}): TwStyledComponent<Config, S>;
|
|
81
86
|
};
|
|
82
87
|
withVariants: (config: Partial<Config>) => TwStyledComponent<Config, S>;
|
|
83
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Declare sub-component names secara eksplisit untuk autocomplete + type safety.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* export const Button = tw.button`
|
|
93
|
+
* flex h-12 ...
|
|
94
|
+
* icon { flex h-4 }
|
|
95
|
+
* `.withSub<"icon" | "footer">()
|
|
96
|
+
*
|
|
97
|
+
* Button.icon // ✅ autocomplete
|
|
98
|
+
* Button.footer // ✅ autocomplete
|
|
99
|
+
* Button.xyz // ❌ TypeScript error
|
|
100
|
+
*/
|
|
101
|
+
withSub<NewS extends string>(): TwStyledComponent<Config, NewS>;
|
|
84
102
|
animate: (opts: AnimateOptions) => Promise<TwStyledComponent<Config, S>>;
|
|
85
103
|
} & SubComponentKeys<S>;
|
|
86
104
|
interface TwSubComponent<P = unknown> {
|
|
@@ -88,9 +106,9 @@ interface TwSubComponent<P = unknown> {
|
|
|
88
106
|
displayName?: string;
|
|
89
107
|
}
|
|
90
108
|
interface TwTemplateFactory<Config extends ComponentConfig = ComponentConfig> {
|
|
91
|
-
<const T extends string>(strings: readonly [T
|
|
109
|
+
<const T extends string>(strings: readonly [T], ...exprs: []): TwStyledComponent<Config, ExtractSubNames<T>>;
|
|
92
110
|
(strings: TemplateStringsArray, ...exprs: unknown[]): TwStyledComponent<Config, string>;
|
|
93
|
-
<C extends ComponentConfig>(config: C): TwStyledComponent<C,
|
|
111
|
+
<C extends ComponentConfig>(config: C): TwStyledComponent<C, InferSubFromConfig<C>>;
|
|
94
112
|
}
|
|
95
113
|
type TwTagFactory = {
|
|
96
114
|
[K in HtmlTagName]: TwTemplateFactory;
|
package/dist/index.js
CHANGED
|
@@ -341,28 +341,44 @@ function getStateRegistry() {
|
|
|
341
341
|
|
|
342
342
|
// packages/domain/core/src/createComponent.ts
|
|
343
343
|
var ALWAYS_BLOCKED = /* @__PURE__ */ new Set(["base", "_ref", "state", "container", "containerName"]);
|
|
344
|
-
function
|
|
345
|
-
const
|
|
346
|
-
|
|
344
|
+
function parseSubComponentBlocks(template) {
|
|
345
|
+
const map = /* @__PURE__ */ new Map();
|
|
346
|
+
const re = /(?:\[([a-zA-Z][a-zA-Z0-9_-]*)\]|([a-zA-Z][a-zA-Z0-9_-]*))\s*\{([^}]*)\}/g;
|
|
347
|
+
let m;
|
|
348
|
+
while ((m = re.exec(template)) !== null) {
|
|
349
|
+
const name = m[1] ?? m[2];
|
|
350
|
+
const classes = m[3].trim().replace(/\s+/g, " ");
|
|
351
|
+
if (classes) map.set(name, classes);
|
|
352
|
+
}
|
|
353
|
+
return map;
|
|
347
354
|
}
|
|
348
355
|
function extractBaseClasses(template) {
|
|
349
|
-
return template.replace(
|
|
356
|
+
return template.replace(/(?:\[[a-zA-Z][a-zA-Z0-9_-]*\]|[a-zA-Z][a-zA-Z0-9_-]*)\s*\{[^}]*\}/g, "").replace(/\s+/g, " ").trim();
|
|
350
357
|
}
|
|
351
|
-
function createSubComponentAccessor(parentDisplayName, name) {
|
|
358
|
+
function createSubComponentAccessor(parentDisplayName, name, classes) {
|
|
352
359
|
const SubComponent = ({
|
|
353
360
|
children,
|
|
354
361
|
className
|
|
355
|
-
}) => React3__default.default.createElement(
|
|
362
|
+
}) => React3__default.default.createElement(
|
|
363
|
+
"span",
|
|
364
|
+
{ className: className ? `${classes} ${className}` : classes },
|
|
365
|
+
children
|
|
366
|
+
);
|
|
356
367
|
SubComponent.displayName = `${parentDisplayName}[${name}]`;
|
|
357
368
|
return SubComponent;
|
|
358
369
|
}
|
|
359
|
-
function registerSubComponents(component, template) {
|
|
360
|
-
const names = parseSubComponentNames(template);
|
|
370
|
+
function registerSubComponents(component, template, configSub) {
|
|
361
371
|
const displayName = component.displayName ?? "tw";
|
|
362
372
|
const map = component;
|
|
363
|
-
|
|
373
|
+
if (configSub) {
|
|
374
|
+
for (const [name, classes] of Object.entries(configSub)) {
|
|
375
|
+
map[name] = createSubComponentAccessor(displayName, name, classes.trim().replace(/\s+/g, " "));
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
const blocks = parseSubComponentBlocks(template);
|
|
379
|
+
for (const [name, classes] of blocks) {
|
|
364
380
|
if (!(name in map)) {
|
|
365
|
-
map[name] = createSubComponentAccessor(displayName, name);
|
|
381
|
+
map[name] = createSubComponentAccessor(displayName, name, classes);
|
|
366
382
|
}
|
|
367
383
|
}
|
|
368
384
|
}
|
|
@@ -413,13 +429,21 @@ function carryOverSubComponents(target, source) {
|
|
|
413
429
|
function attachExtend(component, originalTag, base, config) {
|
|
414
430
|
function extendWithClasses(stringsOrConfig) {
|
|
415
431
|
if (Array.isArray(stringsOrConfig) && "raw" in stringsOrConfig) {
|
|
416
|
-
const
|
|
417
|
-
const merged2 = twMerge(extractBaseClasses(base),
|
|
432
|
+
const rawExtra = stringsOrConfig.raw.join("").trim().replace(/\s+/g, " ");
|
|
433
|
+
const merged2 = twMerge(extractBaseClasses(base), extractBaseClasses(rawExtra));
|
|
418
434
|
const extended2 = createComponent(
|
|
419
435
|
originalTag,
|
|
420
436
|
typeof config === "string" ? merged2 : { ...config, base: merged2 }
|
|
421
437
|
);
|
|
422
438
|
carryOverSubComponents(extended2, component);
|
|
439
|
+
const extendSubBlocks = parseSubComponentBlocks(rawExtra);
|
|
440
|
+
if (extendSubBlocks.size > 0) {
|
|
441
|
+
const extComp = extended2;
|
|
442
|
+
const displayName = extended2.displayName ?? "tw";
|
|
443
|
+
for (const [subName, subClasses] of extendSubBlocks) {
|
|
444
|
+
extComp[subName] = createSubComponentAccessor(displayName, subName, subClasses);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
423
447
|
return extended2;
|
|
424
448
|
}
|
|
425
449
|
const extCfg = stringsOrConfig;
|
|
@@ -477,6 +501,7 @@ function createComponent(tag, config) {
|
|
|
477
501
|
const stateConfig = typeof config === "string" ? void 0 : config.state;
|
|
478
502
|
const containerConfig = typeof config === "string" ? void 0 : config.container;
|
|
479
503
|
const containerName = typeof config === "string" ? void 0 : config.containerName;
|
|
504
|
+
const configSub = typeof config === "string" ? void 0 : config.sub;
|
|
480
505
|
const stateResult = stateConfig ? processState(typeof tag === "string" ? tag : "component", stateConfig) : null;
|
|
481
506
|
const containerResult = containerConfig ? processContainer(typeof tag === "string" ? tag : "component", containerConfig, containerName) : null;
|
|
482
507
|
const engineClasses = [stateResult?.stateClass, containerResult?.containerClass].filter(Boolean).join(" ");
|
|
@@ -495,8 +520,8 @@ function createComponent(tag, config) {
|
|
|
495
520
|
const component2 = baseComponent2;
|
|
496
521
|
component2.displayName = `tw.${tagLabel}`;
|
|
497
522
|
const result2 = attachExtend(component2, tag, base, config);
|
|
498
|
-
registerSubComponents(result2, base);
|
|
499
|
-
return result2;
|
|
523
|
+
registerSubComponents(result2, base, configSub);
|
|
524
|
+
return wrapWithSubProxy(result2, tagLabel);
|
|
500
525
|
}
|
|
501
526
|
const baseComponent = React3__default.default.forwardRef((props, ref) => {
|
|
502
527
|
const { className, ...rest } = props;
|
|
@@ -512,8 +537,36 @@ function createComponent(tag, config) {
|
|
|
512
537
|
const component = baseComponent;
|
|
513
538
|
component.displayName = `tw.${tagLabel}`;
|
|
514
539
|
const result = attachExtend(component, tag, base, config);
|
|
515
|
-
registerSubComponents(result, base);
|
|
516
|
-
return result;
|
|
540
|
+
registerSubComponents(result, base, configSub);
|
|
541
|
+
return wrapWithSubProxy(result, tagLabel);
|
|
542
|
+
}
|
|
543
|
+
var SKIP_PROXY_KEYS = /* @__PURE__ */ new Set([
|
|
544
|
+
"extend",
|
|
545
|
+
"withVariants",
|
|
546
|
+
"animate",
|
|
547
|
+
"withSub",
|
|
548
|
+
"displayName",
|
|
549
|
+
"$$typeof",
|
|
550
|
+
"render",
|
|
551
|
+
"prototype",
|
|
552
|
+
"__esModule",
|
|
553
|
+
"then"
|
|
554
|
+
]);
|
|
555
|
+
function wrapWithSubProxy(component, tagLabel) {
|
|
556
|
+
return new Proxy(component, {
|
|
557
|
+
get(target, prop) {
|
|
558
|
+
const value = target[prop];
|
|
559
|
+
if (value !== void 0) return value;
|
|
560
|
+
if (typeof prop === "symbol") return value;
|
|
561
|
+
if (SKIP_PROXY_KEYS.has(prop)) return value;
|
|
562
|
+
const Fallback = ({
|
|
563
|
+
children,
|
|
564
|
+
className
|
|
565
|
+
}) => React3__default.default.createElement("span", { className }, children);
|
|
566
|
+
Fallback.displayName = `tw.${tagLabel}.${prop}(fallback)`;
|
|
567
|
+
return Fallback;
|
|
568
|
+
}
|
|
569
|
+
});
|
|
517
570
|
}
|
|
518
571
|
var __generatedRegistry = {};
|
|
519
572
|
function lookupGenerated(componentId, props, defaultVariants) {
|
|
@@ -1008,7 +1061,7 @@ function createStyledSystem(config) {
|
|
|
1008
1061
|
tokens
|
|
1009
1062
|
});
|
|
1010
1063
|
}
|
|
1011
|
-
var SUB_RE =
|
|
1064
|
+
var SUB_RE = /(?:\[([a-zA-Z][a-zA-Z0-9_-]*)\]|([a-zA-Z][a-zA-Z0-9_-]*))\s*\{([^}]*)\}/g;
|
|
1012
1065
|
var COMMENT_RE = /\/\/[^\n]*/g;
|
|
1013
1066
|
function parseTemplate(strings, exprs) {
|
|
1014
1067
|
const raw = strings.raw.reduce((acc, str, i) => {
|
|
@@ -1021,8 +1074,8 @@ function parseTemplate(strings, exprs) {
|
|
|
1021
1074
|
let match;
|
|
1022
1075
|
SUB_RE.lastIndex = 0;
|
|
1023
1076
|
while ((match = SUB_RE.exec(raw)) !== null) {
|
|
1024
|
-
const name = match[1];
|
|
1025
|
-
const inner = match[
|
|
1077
|
+
const name = match[1] ?? match[2];
|
|
1078
|
+
const inner = match[3].replace(COMMENT_RE, "").split("\n").map((l) => l.trim()).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
1026
1079
|
subs[name] = inner;
|
|
1027
1080
|
base = base.replace(match[0], "");
|
|
1028
1081
|
}
|