tailwind-styled-v4 5.1.19 → 5.1.20

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
@@ -126,6 +126,42 @@ type InferSubFromConfig<C extends ComponentConfig> = C extends {
126
126
  } ? {
127
127
  [K in keyof S]: S[K] extends string ? K extends string ? ExtractSubName<K> : never : S[K] extends Record<infer N extends string, string> ? N : never;
128
128
  }[keyof S] : never;
129
+ /**
130
+ * HTML tags yang otomatis dikenali sebagai tag dari bare sub-key (tanpa "tag:name" syntax).
131
+ * HARUS identik dengan SEMANTIC_HTML_TAGS di createComponent.ts (parseSubKey) — kalau
132
+ * drift, sub-component bisa di-tipe-kan dengan native attributes yang salah (tag yang
133
+ * benar2 di-render di runtime beda dari yang dipakai untuk inference type-nya).
134
+ */
135
+ type SemanticSubTag = "article" | "aside" | "details" | "figcaption" | "figure" | "footer" | "header" | "main" | "mark" | "nav" | "section" | "summary" | "time" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "ul" | "ol" | "li" | "dl" | "dt" | "dd" | "table" | "thead" | "tbody" | "tfoot" | "tr" | "th" | "td" | "form" | "fieldset" | "legend" | "label" | "a" | "button" | "img" | "span" | "div" | "blockquote" | "pre" | "code" | "em" | "strong" | "small";
136
+ /**
137
+ * Resolve tag HTML dari satu sub-key string — mirror logic `parseSubKey()` runtime
138
+ * di createComponent.ts:
139
+ * - "a:link" → tag eksplisit sebelum colon ("a")
140
+ * - "header" → bare key, fallback ke key itu sendiri kalau termasuk SemanticSubTag
141
+ * - "icon" → bare key, bukan semantic tag → fallback "span" (default runtime)
142
+ */
143
+ type ResolveSubTag<K extends string> = K extends `${infer Tag}:${string}` ? Tag extends HtmlTagName ? Tag : "span" : K extends SemanticSubTag ? K : "span";
144
+ /** Gabungkan union of object types jadi satu intersection — dipakai untuk merge per-key tag map. */
145
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
146
+ /**
147
+ * Infer mapping { subComponentName: htmlTag } dari config.sub — dipakai supaya setiap
148
+ * sub-component (Card.icon, Breadcrumb.link, dst) punya native HTML attributes yang
149
+ * SESUAI tag yang benar2 di-render (href untuk <a>, src untuk <img>, dst), bukan cuma
150
+ * `{ children?, className? }` generik.
151
+ *
152
+ * @example
153
+ * sub: { "a:link": "...", "span:sep": "..." } → { link: "a"; sep: "span" }
154
+ * sub: { header: { topBar: "..." } } → { topBar: "header" }
155
+ */
156
+ type InferSubTagsFromConfig<C extends ComponentConfig> = C extends {
157
+ sub: infer S extends Record<string, SubValue>;
158
+ } ? UnionToIntersection<{
159
+ [K in keyof S]: K extends string ? S[K] extends string ? {
160
+ [N in ExtractSubName<K>]: ResolveSubTag<K>;
161
+ } : S[K] extends Record<string, string> ? {
162
+ [N in keyof S[K]]: K extends HtmlTagName ? K : "span";
163
+ } : never : never;
164
+ }[keyof S]> : Record<string, never>;
129
165
  interface ContainerConfig {
130
166
  base?: string;
131
167
  queries?: Record<string, string>;
@@ -149,7 +185,7 @@ interface StyledComponentProps {
149
185
  [key: string]: unknown;
150
186
  }
151
187
  type SubComponentMap = Record<string, unknown>;
152
- type TwSubComponentAccessor = React.FC<{
188
+ type TwSubComponentAccessor<Tag extends HtmlTagName = "span"> = React.FC<Omit<React.ComponentPropsWithoutRef<Tag>, "ref"> & {
153
189
  children?: React.ReactNode;
154
190
  className?: string;
155
191
  }>;
@@ -161,24 +197,22 @@ type TrimRight<S extends string> = S extends `${infer L} ` | `${infer L}
161
197
  ` ? TrimRight<L> : S;
162
198
  type Trim<S extends string> = TrimLeft<TrimRight<S>>;
163
199
  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;
164
- type SubComponentKeys<S extends string> = string extends S ? {
165
- [key: string]: TwSubComponentAccessor;
166
- } : {
167
- [K in S]: TwSubComponentAccessor;
200
+ type SubComponentKeys<S extends string, TagMap extends Record<string, string> = Record<string, never>> = {
201
+ [K in S]: TwSubComponentAccessor<K extends keyof TagMap ? (TagMap[K] extends HtmlTagName ? TagMap[K] : "span") : "span">;
168
202
  };
169
- type TwStyledComponent<Config extends ComponentConfig = ComponentConfig, S extends string = string> = {
203
+ type TwStyledComponent<Config extends ComponentConfig = ComponentConfig, S extends string = string, TagMap extends Record<string, string> = Record<string, never>> = {
170
204
  (props: StyledComponentProps & InferVariantProps<Config> & InferSizeProps<Config> & InferStatesProps<Config>): React.ReactElement | null;
171
205
  displayName?: string;
172
206
  extend: {
173
- (strings: TemplateStringsArray, ...exprs: unknown[]): TwStyledComponent<Config, S>;
207
+ (strings: TemplateStringsArray, ...exprs: unknown[]): TwStyledComponent<Config, S, TagMap>;
174
208
  (config: {
175
209
  classes?: string;
176
210
  variants?: ComponentConfig["variants"];
177
211
  defaultVariants?: ComponentConfig["defaultVariants"];
178
212
  compoundVariants?: ComponentConfig["compoundVariants"];
179
- }): TwStyledComponent<Config, S>;
213
+ }): TwStyledComponent<Config, S, TagMap>;
180
214
  };
181
- withVariants: (config: Partial<Config>) => TwStyledComponent<Config, S>;
215
+ withVariants: (config: Partial<Config>) => TwStyledComponent<Config, S, TagMap>;
182
216
  /**
183
217
  * Declare sub-component names secara eksplisit untuk autocomplete + type safety.
184
218
  *
@@ -192,9 +226,9 @@ type TwStyledComponent<Config extends ComponentConfig = ComponentConfig, S exten
192
226
  * Button.footer // ✅ autocomplete
193
227
  * Button.xyz // ❌ TypeScript error
194
228
  */
195
- withSub<NewS extends string>(): TwStyledComponent<Config, NewS>;
196
- animate: (opts: AnimateOptions) => Promise<TwStyledComponent<Config, S>>;
197
- } & SubComponentKeys<S>;
229
+ withSub<NewS extends string>(): TwStyledComponent<Config, NewS, TagMap>;
230
+ animate: (opts: AnimateOptions) => Promise<TwStyledComponent<Config, S, TagMap>>;
231
+ } & SubComponentKeys<S, TagMap>;
198
232
  interface TwSubComponent<P = unknown> {
199
233
  (props: P): React.ReactElement | null;
200
234
  displayName?: string;
@@ -202,7 +236,7 @@ interface TwSubComponent<P = unknown> {
202
236
  interface TwTemplateFactory<Config extends ComponentConfig = ComponentConfig> {
203
237
  <const T extends string>(strings: readonly [T], ...exprs: []): TwStyledComponent<Config, ExtractSubNames<T>>;
204
238
  (strings: TemplateStringsArray, ...exprs: unknown[]): TwStyledComponent<Config, string>;
205
- <C extends ComponentConfig>(config: C): TwStyledComponent<C, InferSubFromConfig<C>>;
239
+ <C extends ComponentConfig>(config: C): TwStyledComponent<C, InferSubFromConfig<C>, InferSubTagsFromConfig<C> extends Record<string, string> ? InferSubTagsFromConfig<C> : Record<string, never>>;
206
240
  }
207
241
  type TwTagFactory = {
208
242
  [K in HtmlTagName]: TwTemplateFactory;
package/dist/index.d.ts CHANGED
@@ -126,6 +126,42 @@ type InferSubFromConfig<C extends ComponentConfig> = C extends {
126
126
  } ? {
127
127
  [K in keyof S]: S[K] extends string ? K extends string ? ExtractSubName<K> : never : S[K] extends Record<infer N extends string, string> ? N : never;
128
128
  }[keyof S] : never;
129
+ /**
130
+ * HTML tags yang otomatis dikenali sebagai tag dari bare sub-key (tanpa "tag:name" syntax).
131
+ * HARUS identik dengan SEMANTIC_HTML_TAGS di createComponent.ts (parseSubKey) — kalau
132
+ * drift, sub-component bisa di-tipe-kan dengan native attributes yang salah (tag yang
133
+ * benar2 di-render di runtime beda dari yang dipakai untuk inference type-nya).
134
+ */
135
+ type SemanticSubTag = "article" | "aside" | "details" | "figcaption" | "figure" | "footer" | "header" | "main" | "mark" | "nav" | "section" | "summary" | "time" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "ul" | "ol" | "li" | "dl" | "dt" | "dd" | "table" | "thead" | "tbody" | "tfoot" | "tr" | "th" | "td" | "form" | "fieldset" | "legend" | "label" | "a" | "button" | "img" | "span" | "div" | "blockquote" | "pre" | "code" | "em" | "strong" | "small";
136
+ /**
137
+ * Resolve tag HTML dari satu sub-key string — mirror logic `parseSubKey()` runtime
138
+ * di createComponent.ts:
139
+ * - "a:link" → tag eksplisit sebelum colon ("a")
140
+ * - "header" → bare key, fallback ke key itu sendiri kalau termasuk SemanticSubTag
141
+ * - "icon" → bare key, bukan semantic tag → fallback "span" (default runtime)
142
+ */
143
+ type ResolveSubTag<K extends string> = K extends `${infer Tag}:${string}` ? Tag extends HtmlTagName ? Tag : "span" : K extends SemanticSubTag ? K : "span";
144
+ /** Gabungkan union of object types jadi satu intersection — dipakai untuk merge per-key tag map. */
145
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
146
+ /**
147
+ * Infer mapping { subComponentName: htmlTag } dari config.sub — dipakai supaya setiap
148
+ * sub-component (Card.icon, Breadcrumb.link, dst) punya native HTML attributes yang
149
+ * SESUAI tag yang benar2 di-render (href untuk <a>, src untuk <img>, dst), bukan cuma
150
+ * `{ children?, className? }` generik.
151
+ *
152
+ * @example
153
+ * sub: { "a:link": "...", "span:sep": "..." } → { link: "a"; sep: "span" }
154
+ * sub: { header: { topBar: "..." } } → { topBar: "header" }
155
+ */
156
+ type InferSubTagsFromConfig<C extends ComponentConfig> = C extends {
157
+ sub: infer S extends Record<string, SubValue>;
158
+ } ? UnionToIntersection<{
159
+ [K in keyof S]: K extends string ? S[K] extends string ? {
160
+ [N in ExtractSubName<K>]: ResolveSubTag<K>;
161
+ } : S[K] extends Record<string, string> ? {
162
+ [N in keyof S[K]]: K extends HtmlTagName ? K : "span";
163
+ } : never : never;
164
+ }[keyof S]> : Record<string, never>;
129
165
  interface ContainerConfig {
130
166
  base?: string;
131
167
  queries?: Record<string, string>;
@@ -149,7 +185,7 @@ interface StyledComponentProps {
149
185
  [key: string]: unknown;
150
186
  }
151
187
  type SubComponentMap = Record<string, unknown>;
152
- type TwSubComponentAccessor = React.FC<{
188
+ type TwSubComponentAccessor<Tag extends HtmlTagName = "span"> = React.FC<Omit<React.ComponentPropsWithoutRef<Tag>, "ref"> & {
153
189
  children?: React.ReactNode;
154
190
  className?: string;
155
191
  }>;
@@ -161,24 +197,22 @@ type TrimRight<S extends string> = S extends `${infer L} ` | `${infer L}
161
197
  ` ? TrimRight<L> : S;
162
198
  type Trim<S extends string> = TrimLeft<TrimRight<S>>;
163
199
  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;
164
- type SubComponentKeys<S extends string> = string extends S ? {
165
- [key: string]: TwSubComponentAccessor;
166
- } : {
167
- [K in S]: TwSubComponentAccessor;
200
+ type SubComponentKeys<S extends string, TagMap extends Record<string, string> = Record<string, never>> = {
201
+ [K in S]: TwSubComponentAccessor<K extends keyof TagMap ? (TagMap[K] extends HtmlTagName ? TagMap[K] : "span") : "span">;
168
202
  };
169
- type TwStyledComponent<Config extends ComponentConfig = ComponentConfig, S extends string = string> = {
203
+ type TwStyledComponent<Config extends ComponentConfig = ComponentConfig, S extends string = string, TagMap extends Record<string, string> = Record<string, never>> = {
170
204
  (props: StyledComponentProps & InferVariantProps<Config> & InferSizeProps<Config> & InferStatesProps<Config>): React.ReactElement | null;
171
205
  displayName?: string;
172
206
  extend: {
173
- (strings: TemplateStringsArray, ...exprs: unknown[]): TwStyledComponent<Config, S>;
207
+ (strings: TemplateStringsArray, ...exprs: unknown[]): TwStyledComponent<Config, S, TagMap>;
174
208
  (config: {
175
209
  classes?: string;
176
210
  variants?: ComponentConfig["variants"];
177
211
  defaultVariants?: ComponentConfig["defaultVariants"];
178
212
  compoundVariants?: ComponentConfig["compoundVariants"];
179
- }): TwStyledComponent<Config, S>;
213
+ }): TwStyledComponent<Config, S, TagMap>;
180
214
  };
181
- withVariants: (config: Partial<Config>) => TwStyledComponent<Config, S>;
215
+ withVariants: (config: Partial<Config>) => TwStyledComponent<Config, S, TagMap>;
182
216
  /**
183
217
  * Declare sub-component names secara eksplisit untuk autocomplete + type safety.
184
218
  *
@@ -192,9 +226,9 @@ type TwStyledComponent<Config extends ComponentConfig = ComponentConfig, S exten
192
226
  * Button.footer // ✅ autocomplete
193
227
  * Button.xyz // ❌ TypeScript error
194
228
  */
195
- withSub<NewS extends string>(): TwStyledComponent<Config, NewS>;
196
- animate: (opts: AnimateOptions) => Promise<TwStyledComponent<Config, S>>;
197
- } & SubComponentKeys<S>;
229
+ withSub<NewS extends string>(): TwStyledComponent<Config, NewS, TagMap>;
230
+ animate: (opts: AnimateOptions) => Promise<TwStyledComponent<Config, S, TagMap>>;
231
+ } & SubComponentKeys<S, TagMap>;
198
232
  interface TwSubComponent<P = unknown> {
199
233
  (props: P): React.ReactElement | null;
200
234
  displayName?: string;
@@ -202,7 +236,7 @@ interface TwSubComponent<P = unknown> {
202
236
  interface TwTemplateFactory<Config extends ComponentConfig = ComponentConfig> {
203
237
  <const T extends string>(strings: readonly [T], ...exprs: []): TwStyledComponent<Config, ExtractSubNames<T>>;
204
238
  (strings: TemplateStringsArray, ...exprs: unknown[]): TwStyledComponent<Config, string>;
205
- <C extends ComponentConfig>(config: C): TwStyledComponent<C, InferSubFromConfig<C>>;
239
+ <C extends ComponentConfig>(config: C): TwStyledComponent<C, InferSubFromConfig<C>, InferSubTagsFromConfig<C> extends Record<string, string> ? InferSubTagsFromConfig<C> : Record<string, never>>;
206
240
  }
207
241
  type TwTagFactory = {
208
242
  [K in HtmlTagName]: TwTemplateFactory;
package/dist/index.js CHANGED
@@ -741,16 +741,19 @@ function parseSubKey(key) {
741
741
  function createSubComponentAccessor(parentDisplayName, name, classes, tag = "span", asChild = false) {
742
742
  const SubComponent = ({
743
743
  children,
744
- className
744
+ className,
745
+ ...rest
746
+ // tangkap semua native HTML props (href, onClick, src, alt, dll)
745
747
  }) => {
746
748
  const mergedClass = className ? `${classes} ${className}` : classes;
747
749
  if (asChild && import_react.default.isValidElement(children)) {
748
750
  const child = import_react.default.Children.only(children);
749
751
  return import_react.default.cloneElement(child, {
752
+ ...rest,
750
753
  className: child.props.className ? `${mergedClass} ${child.props.className}` : mergedClass
751
754
  });
752
755
  }
753
- return import_react.default.createElement(tag, { className: mergedClass }, children);
756
+ return import_react.default.createElement(tag, { ...rest, className: mergedClass }, children);
754
757
  };
755
758
  SubComponent.displayName = `${parentDisplayName}[${name}]`;
756
759
  return SubComponent;
@@ -1026,8 +1029,9 @@ function wrapWithSubProxy(component, tagLabel) {
1026
1029
  if (SKIP_PROXY_KEYS.has(prop)) return value;
1027
1030
  const Fallback = ({
1028
1031
  children,
1029
- className
1030
- }) => import_react.default.createElement("span", { className }, children);
1032
+ className,
1033
+ ...rest
1034
+ }) => import_react.default.createElement("span", { ...rest, className }, children);
1031
1035
  Fallback.displayName = `tw.${tagLabel}.${prop}(fallback)`;
1032
1036
  return Fallback;
1033
1037
  }