@tinybigui/react 0.13.0 → 0.14.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.
package/dist/index.js CHANGED
@@ -2113,277 +2113,332 @@ var FAB = forwardRef(
2113
2113
  }
2114
2114
  );
2115
2115
  FAB.displayName = "FAB";
2116
- var textFieldContainerVariants = cva(
2116
+ var textFieldRootVariants = cva(["relative inline-flex flex-col"], {
2117
+ variants: {
2118
+ fullWidth: {
2119
+ true: "w-full",
2120
+ false: "w-auto"
2121
+ }
2122
+ },
2123
+ defaultVariants: {
2124
+ fullWidth: false
2125
+ }
2126
+ });
2127
+ var textFieldFieldVariants = cva(
2117
2128
  [
2118
- // Base container styles
2119
- "relative inline-flex flex-col"
2129
+ "relative flex items-center w-full min-h-14",
2130
+ // Cursor — disabled via group-data
2131
+ "group-data-[disabled]/text-field:cursor-not-allowed",
2132
+ "group-data-[disabled]/text-field:pointer-events-none"
2120
2133
  ],
2121
2134
  {
2122
2135
  variants: {
2123
- fullWidth: {
2124
- true: "w-full",
2125
- false: "w-auto"
2136
+ variant: {
2137
+ filled: [
2138
+ "rounded-t-xs bg-surface-container-highest",
2139
+ // Disabled: background fades to on-surface/4
2140
+ "group-data-[disabled]/text-field:bg-on-surface/4"
2141
+ ],
2142
+ outlined: ["rounded-xs bg-transparent"]
2126
2143
  }
2127
2144
  },
2128
2145
  defaultVariants: {
2129
- fullWidth: false
2146
+ variant: "filled"
2130
2147
  }
2131
2148
  }
2132
2149
  );
2133
- var textFieldWrapperVariants = cva(
2150
+ var textFieldStateLayerVariants = cva([
2151
+ "absolute inset-0 rounded-t-xs pointer-events-none opacity-0",
2152
+ "bg-on-surface",
2153
+ // Effects transition — no spatial overshoot on opacity
2154
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2155
+ // Hover: 8%
2156
+ "group-data-[hovered]/text-field:opacity-8",
2157
+ // Focus: 10% (focus wins over hover via cascade order — placed after)
2158
+ "group-data-[focused]/text-field:opacity-10",
2159
+ // No state layer when disabled
2160
+ "group-data-[disabled]/text-field:hidden"
2161
+ ]);
2162
+ var textFieldActiveIndicatorVariants = cva([
2163
+ "absolute bottom-0 left-0 right-0 pointer-events-none",
2164
+ // Spatial transition: height is a spatial property
2165
+ "transition-[height,background-color]",
2166
+ "duration-spring-standard-fast-spatial ease-spring-standard-fast-spatial",
2167
+ // Base
2168
+ "h-px bg-on-surface-variant",
2169
+ // Hover
2170
+ "group-data-[hovered]/text-field:bg-on-surface",
2171
+ // Focused — 2px + primary color (focused placed after hovered to win cascade)
2172
+ "group-data-[focused]/text-field:h-0.5 group-data-[focused]/text-field:bg-primary",
2173
+ // Invalid
2174
+ "group-data-[invalid]/text-field:bg-error",
2175
+ // Invalid + focused
2176
+ "group-data-[invalid]/text-field:group-data-[focused]/text-field:bg-error",
2177
+ // Disabled: hidden
2178
+ "group-data-[disabled]/text-field:hidden"
2179
+ ]);
2180
+ var textFieldOutlineVariants = cva([
2181
+ "absolute inset-0 rounded-xs m-0 px-2 pointer-events-none",
2182
+ "border border-outline",
2183
+ // Effects transition for color; spatial for border-width
2184
+ "transition-[border-color,border-width]",
2185
+ "duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2186
+ // Hover
2187
+ "group-data-[hovered]/text-field:border-on-surface",
2188
+ // Focused — 2px + primary color
2189
+ "group-data-[focused]/text-field:border-2 group-data-[focused]/text-field:border-primary",
2190
+ // Invalid
2191
+ "group-data-[invalid]/text-field:border-error",
2192
+ // Invalid + focused
2193
+ "group-data-[invalid]/text-field:group-data-[focused]/text-field:border-2",
2194
+ "group-data-[invalid]/text-field:group-data-[focused]/text-field:border-error",
2195
+ // Disabled
2196
+ "group-data-[disabled]/text-field:border-on-surface/12"
2197
+ ]);
2198
+ var textFieldNotchVariants = cva([
2199
+ "invisible whitespace-nowrap text-body-small px-1",
2200
+ // 0 width when not floating (no gap)
2201
+ "max-w-0 overflow-hidden",
2202
+ // Full width when floating (gap opens)
2203
+ "group-data-[float]/text-field:max-w-full",
2204
+ // Spatial transition for max-width change
2205
+ "transition-[max-width] duration-spring-standard-fast-spatial ease-spring-standard-fast-spatial"
2206
+ ]);
2207
+ var textFieldLabelVariants = cva(
2134
2208
  [
2135
- // Base wrapper styles
2136
- "relative inline-flex items-center w-full",
2137
- "transition-all duration-200",
2138
- "rounded-t"
2209
+ "absolute pointer-events-none origin-top-left select-none",
2210
+ "text-body-large text-on-surface-variant",
2211
+ // Spatial + effects both use standard fast — no overshoot on font/color
2212
+ "transition-[transform,font-size,color,line-height]",
2213
+ "duration-spring-standard-fast-spatial ease-spring-standard-fast-spatial",
2214
+ // Disabled
2215
+ "group-data-[disabled]/text-field:text-on-surface/38",
2216
+ // Invalid (placed after default, before focused so focused invalid wins)
2217
+ "group-data-[invalid]/text-field:text-error",
2218
+ // Focused (singly-chained wins by cascade order)
2219
+ "group-data-[focused]/text-field:text-primary",
2220
+ // Invalid + focused — doubly-chained, wins over single-chained focused
2221
+ "group-data-[invalid]/text-field:group-data-[focused]/text-field:text-error"
2139
2222
  ],
2140
2223
  {
2141
2224
  variants: {
2142
2225
  variant: {
2143
- filled: ["bg-surface-container-highest", "border-b-2 border-on-surface-variant"],
2144
- outlined: ["bg-transparent", "border border-outline", "rounded-b"]
2145
- },
2146
- size: {
2147
- small: "min-h-10",
2148
- medium: "min-h-12",
2149
- large: "min-h-14"
2150
- },
2151
- disabled: {
2152
- true: ["cursor-not-allowed", "opacity-38"],
2153
- false: ""
2154
- },
2155
- error: {
2156
- true: "",
2157
- false: ""
2158
- },
2159
- focused: {
2160
- true: "",
2161
- false: ""
2226
+ /**
2227
+ * Filled: label rests at center (top-1/2 -translate-y-1/2).
2228
+ * When floating: moves up to top-2 (8dp) with body-small size.
2229
+ */
2230
+ filled: [
2231
+ "top-1/2 -translate-y-1/2 left-4",
2232
+ // Floated position — sits in the top 8dp zone
2233
+ "group-data-[float]/text-field:top-2 group-data-[float]/text-field:-translate-y-0",
2234
+ "group-data-[float]/text-field:text-body-small",
2235
+ // Leading-icon offset
2236
+ "group-data-[with-leading-icon]/text-field:left-[52px]"
2237
+ ],
2238
+ /**
2239
+ * Outlined: label rests at center (top-1/2 -translate-y-1/2).
2240
+ * When floating: moves up to sit on the top border (-translate-y-1/2 from top-0).
2241
+ */
2242
+ outlined: [
2243
+ "top-1/2 -translate-y-1/2 left-3",
2244
+ // bg-surface ensures label text punches through the border
2245
+ "bg-surface px-1",
2246
+ // Floated: sits on the top border
2247
+ "group-data-[float]/text-field:top-0 group-data-[float]/text-field:-translate-y-1/2",
2248
+ "group-data-[float]/text-field:text-body-small",
2249
+ // Leading-icon offset
2250
+ "group-data-[with-leading-icon]/text-field:left-[52px]"
2251
+ ]
2162
2252
  }
2163
2253
  },
2164
- compoundVariants: [
2165
- // FILLED VARIANT - Focused state
2166
- {
2167
- variant: "filled",
2168
- focused: true,
2169
- error: false,
2170
- className: "border-primary"
2171
- },
2172
- // FILLED VARIANT - Error state
2173
- {
2174
- variant: "filled",
2175
- error: true,
2176
- className: "border-error"
2177
- },
2178
- // FILLED VARIANT - Hover state (handled via group-hover in parent)
2179
- {
2180
- variant: "filled",
2181
- disabled: false,
2182
- className: "hover:bg-on-surface/[0.08]"
2183
- },
2184
- // OUTLINED VARIANT - Focused state
2185
- {
2186
- variant: "outlined",
2187
- focused: true,
2188
- error: false,
2189
- className: "border-2 border-primary"
2190
- },
2191
- // OUTLINED VARIANT - Error state
2192
- {
2193
- variant: "outlined",
2194
- error: true,
2195
- className: "border-2 border-error"
2196
- },
2197
- // OUTLINED VARIANT - Hover state
2198
- {
2199
- variant: "outlined",
2200
- disabled: false,
2201
- className: "hover:border-on-surface"
2202
- }
2203
- ],
2204
2254
  defaultVariants: {
2205
- variant: "filled",
2206
- size: "medium",
2207
- disabled: false,
2208
- error: false,
2209
- focused: false
2255
+ variant: "filled"
2210
2256
  }
2211
2257
  }
2212
2258
  );
2213
2259
  var textFieldInputVariants = cva(
2214
2260
  [
2215
- // Base input styles
2216
- "w-full bg-transparent outline-none",
2217
- "text-on-surface text-base",
2218
- "placeholder:text-on-surface-variant placeholder:opacity-60",
2219
- "transition-colors duration-200"
2261
+ "relative z-10 w-full bg-transparent outline-none border-none",
2262
+ "text-body-large text-on-surface",
2263
+ "placeholder:text-on-surface-variant",
2264
+ // Placeholder hidden unless field is floating (avoids overlap with label)
2265
+ "placeholder:opacity-0",
2266
+ "group-data-[float]/text-field:placeholder:opacity-100",
2267
+ // Disabled
2268
+ "group-data-[disabled]/text-field:text-on-surface/38",
2269
+ "group-data-[disabled]/text-field:cursor-not-allowed",
2270
+ // Readonly
2271
+ "group-data-[readonly]/text-field:cursor-default",
2272
+ // Effects transition for color
2273
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
2220
2274
  ],
2221
2275
  {
2222
2276
  variants: {
2223
2277
  variant: {
2224
- filled: "px-4",
2225
- outlined: "px-4"
2226
- },
2227
- size: {
2228
- small: "h-10 py-2 text-sm",
2229
- medium: "h-12 py-3 text-base",
2230
- large: "h-14 py-4 text-lg"
2231
- },
2232
- disabled: {
2233
- true: "cursor-not-allowed",
2234
- false: ""
2235
- },
2236
- hasLeadingIcon: {
2237
- true: "pl-12",
2238
- false: ""
2239
- },
2240
- hasTrailingIcon: {
2241
- true: "pr-12",
2242
- false: ""
2278
+ /**
2279
+ * Filled: top padding creates room for floating label (label rests at 8dp).
2280
+ * Horizontal padding: 16dp left / 16dp right — but yielded to prefix/suffix
2281
+ * when they are present so the affix handles the edge spacing instead.
2282
+ */
2283
+ filled: [
2284
+ "pt-6 pb-2 px-4",
2285
+ // No label present: vertically center
2286
+ "group-data-[no-label]/text-field:py-4",
2287
+ // Leading icon horizontal offset
2288
+ "group-data-[with-leading-icon]/text-field:pl-[52px]",
2289
+ // Trailing icon horizontal offset
2290
+ "group-data-[with-trailing-icon]/text-field:pr-[52px]",
2291
+ // Prefix present: prefix handles left edge — remove input's left padding
2292
+ "group-data-[with-prefix]/text-field:pl-0",
2293
+ // Leading icon + prefix together: compound wins over both singles
2294
+ "group-data-[with-leading-icon]/text-field:group-data-[with-prefix]/text-field:pl-0",
2295
+ // Suffix present: suffix handles right edge — remove input's right padding
2296
+ "group-data-[with-suffix]/text-field:pr-0",
2297
+ // Trailing icon + suffix together: compound wins over both singles
2298
+ "group-data-[with-trailing-icon]/text-field:group-data-[with-suffix]/text-field:pr-0"
2299
+ ],
2300
+ /**
2301
+ * Outlined: label sits on the border, no extra top padding needed.
2302
+ * Horizontal padding: 16dp — yielded to prefix/suffix when present.
2303
+ */
2304
+ outlined: [
2305
+ "py-4 px-4",
2306
+ // Leading icon horizontal offset
2307
+ "group-data-[with-leading-icon]/text-field:pl-[52px]",
2308
+ // Trailing icon horizontal offset
2309
+ "group-data-[with-trailing-icon]/text-field:pr-[52px]",
2310
+ // Prefix present: prefix handles left edge
2311
+ "group-data-[with-prefix]/text-field:pl-0",
2312
+ "group-data-[with-leading-icon]/text-field:group-data-[with-prefix]/text-field:pl-0",
2313
+ // Suffix present: suffix handles right edge
2314
+ "group-data-[with-suffix]/text-field:pr-0",
2315
+ "group-data-[with-trailing-icon]/text-field:group-data-[with-suffix]/text-field:pr-0"
2316
+ ]
2243
2317
  },
2244
2318
  multiline: {
2245
- true: "resize-y",
2246
- false: ""
2319
+ true: "resize-y min-h-[1.5rem]",
2320
+ false: "h-full"
2247
2321
  }
2248
2322
  },
2249
2323
  defaultVariants: {
2250
2324
  variant: "filled",
2251
- size: "medium",
2252
- disabled: false,
2253
- hasLeadingIcon: false,
2254
- hasTrailingIcon: false,
2255
2325
  multiline: false
2256
2326
  }
2257
2327
  }
2258
2328
  );
2259
- var textFieldLabelVariants = cva(
2329
+ var textFieldIconVariants = cva(
2260
2330
  [
2261
- // Base label styles
2262
- "absolute left-4 transition-all duration-200 pointer-events-none",
2263
- "text-on-surface-variant origin-top-left"
2331
+ "absolute z-10 flex items-center justify-center size-6 pointer-events-none",
2332
+ "text-on-surface-variant",
2333
+ // Effects transition
2334
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2335
+ // Disabled
2336
+ "group-data-[disabled]/text-field:text-on-surface/38"
2264
2337
  ],
2265
2338
  {
2266
2339
  variants: {
2267
- variant: {
2268
- filled: "top-2.5",
2269
- outlined: "top-2.5 bg-surface px-1"
2270
- },
2271
- size: {
2272
- small: "text-sm",
2273
- medium: "text-base",
2274
- large: "text-lg"
2275
- },
2276
- floating: {
2277
- true: "-translate-y-5 scale-75",
2278
- false: "scale-100"
2279
- },
2280
- focused: {
2281
- true: "text-primary",
2282
- false: ""
2283
- },
2284
- error: {
2285
- true: "text-error",
2286
- false: ""
2287
- },
2288
- disabled: {
2289
- true: "text-on-surface/38",
2290
- false: ""
2291
- },
2292
- hasLeadingIcon: {
2293
- true: "left-12",
2294
- false: ""
2340
+ position: {
2341
+ leading: "left-3",
2342
+ trailing: [
2343
+ "right-3",
2344
+ // Trailing → error color when invalid
2345
+ "group-data-[invalid]/text-field:text-error"
2346
+ ]
2295
2347
  }
2296
2348
  },
2297
- compoundVariants: [
2298
- // Outlined variant floating label positioning
2299
- {
2300
- variant: "outlined",
2301
- floating: true,
2302
- className: "top-2.5"
2303
- }
2304
- ],
2305
2349
  defaultVariants: {
2306
- variant: "filled",
2307
- size: "medium",
2308
- floating: false,
2309
- focused: false,
2310
- error: false,
2311
- disabled: false,
2312
- hasLeadingIcon: false
2350
+ position: "leading"
2313
2351
  }
2314
2352
  }
2315
2353
  );
2316
- var textFieldIconVariants = cva(
2354
+ var textFieldAffixVariants = cva(
2317
2355
  [
2318
- // Base icon styles
2319
- "absolute flex items-center justify-center",
2320
- "text-on-surface-variant transition-colors duration-200",
2321
- "pointer-events-none"
2356
+ "relative z-10 text-body-large text-on-surface-variant select-none shrink-0",
2357
+ "opacity-0 pointer-events-none",
2358
+ // Visible once label is floated
2359
+ "group-data-[float]/text-field:opacity-100 group-data-[float]/text-field:pointer-events-auto",
2360
+ // Effects transition
2361
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2362
+ // Disabled
2363
+ "group-data-[disabled]/text-field:text-on-surface/38"
2322
2364
  ],
2323
2365
  {
2324
2366
  variants: {
2325
- position: {
2326
- leading: "left-3",
2327
- trailing: "right-3"
2328
- },
2329
- size: {
2330
- small: "w-5 h-5",
2331
- medium: "w-6 h-6",
2332
- large: "w-7 h-7"
2367
+ variant: {
2368
+ /**
2369
+ * Filled: mirror the input's pt-6 pb-2 so the text sits in the same
2370
+ * vertical zone. When no label is present, the input uses py-4 — match
2371
+ * that too so the affix stays centred with the input text.
2372
+ */
2373
+ filled: [
2374
+ "pt-6 pb-2",
2375
+ "group-data-[no-label]/text-field:pt-4 group-data-[no-label]/text-field:pb-4"
2376
+ ],
2377
+ /**
2378
+ * Outlined: input uses py-4 and h-full; items-center on the content
2379
+ * column already centres the naturally-sized affix at the same 28px
2380
+ * midpoint as the input text. No extra vertical padding needed.
2381
+ */
2382
+ outlined: []
2333
2383
  },
2334
- disabled: {
2335
- true: "opacity-38",
2336
- false: ""
2384
+ position: {
2385
+ /**
2386
+ * Prefix: sits before the input in the flex row.
2387
+ * pl-4 aligns the left text edge to the 16dp field margin.
2388
+ * With a leading icon that shifts to 52dp to clear the icon.
2389
+ * pr-0.5 is a small gap between prefix text and the input cursor.
2390
+ */
2391
+ prefix: ["pl-4", "group-data-[with-leading-icon]/text-field:pl-[52px]", "pr-0.5"],
2392
+ /**
2393
+ * Suffix: sits after the input in the flex row.
2394
+ * pl-0.5 is a small gap between the input text and the suffix.
2395
+ * pr-4 keeps 16dp from the right field edge.
2396
+ * With a trailing icon that shifts to 52dp to avoid overlap.
2397
+ */
2398
+ suffix: ["pl-0.5", "pr-4", "group-data-[with-trailing-icon]/text-field:pr-[52px]"]
2337
2399
  }
2338
2400
  },
2339
2401
  defaultVariants: {
2340
- position: "leading",
2341
- size: "medium",
2342
- disabled: false
2402
+ variant: "filled",
2403
+ position: "prefix"
2343
2404
  }
2344
2405
  }
2345
2406
  );
2346
- var textFieldHelperTextVariants = cva(
2407
+ var textFieldSupportingRowVariants = cva([
2408
+ "flex items-start justify-between w-full gap-4 px-4 pt-1"
2409
+ ]);
2410
+ var textFieldSupportingTextVariants = cva(
2347
2411
  [
2348
- // Base helper text styles
2349
- "text-xs mt-1 px-4 transition-colors duration-200"
2412
+ "text-body-small",
2413
+ // Effects transition for color
2414
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
2350
2415
  ],
2351
2416
  {
2352
2417
  variants: {
2353
2418
  type: {
2354
2419
  description: "text-on-surface-variant",
2355
2420
  error: "text-error"
2356
- },
2357
- disabled: {
2358
- true: "opacity-38",
2359
- false: ""
2360
2421
  }
2361
2422
  },
2362
2423
  defaultVariants: {
2363
- type: "description",
2364
- disabled: false
2424
+ type: "description"
2365
2425
  }
2366
2426
  }
2367
2427
  );
2368
- var textFieldCharacterCountVariants = cva(
2428
+ var textFieldCounterVariants = cva(
2369
2429
  [
2370
- // Base character counter styles
2371
- "text-xs mt-1 px-4 text-right text-on-surface-variant transition-colors duration-200"
2430
+ "text-body-small shrink-0 text-right",
2431
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
2372
2432
  ],
2373
2433
  {
2374
2434
  variants: {
2375
2435
  exceeded: {
2376
2436
  true: "text-error",
2377
- false: ""
2378
- },
2379
- disabled: {
2380
- true: "opacity-38",
2381
- false: ""
2437
+ false: "text-on-surface-variant"
2382
2438
  }
2383
2439
  },
2384
2440
  defaultVariants: {
2385
- exceeded: false,
2386
- disabled: false
2441
+ exceeded: false
2387
2442
  }
2388
2443
  }
2389
2444
  );
@@ -2495,12 +2550,13 @@ TextFieldHeadless.displayName = "TextFieldHeadless";
2495
2550
  var TextField = forwardRef(
2496
2551
  ({
2497
2552
  variant = "filled",
2498
- size = "medium",
2499
2553
  label,
2500
2554
  description,
2501
2555
  errorMessage,
2502
2556
  leadingIcon,
2503
2557
  trailingIcon,
2558
+ prefix,
2559
+ suffix,
2504
2560
  characterCount = false,
2505
2561
  maxLength,
2506
2562
  fullWidth = false,
@@ -2520,6 +2576,7 @@ var TextField = forwardRef(
2520
2576
  ...props
2521
2577
  }, ref) => {
2522
2578
  const spellCheckProp = spellCheck === void 0 ? void 0 : typeof spellCheck === "string" ? spellCheck === "true" : spellCheck;
2579
+ const { isHovered, hoverProps } = useHover({ isDisabled });
2523
2580
  const headlessProps = {
2524
2581
  ...label !== void 0 ? { label } : {},
2525
2582
  ...description !== void 0 ? { description } : {},
@@ -2546,149 +2603,131 @@ var TextField = forwardRef(
2546
2603
  errorMessageProps,
2547
2604
  isInvalid: fieldIsInvalid,
2548
2605
  isFocused,
2606
+ isFocusVisible,
2549
2607
  currentValue,
2550
2608
  inputRef
2551
2609
  }) => {
2552
2610
  const hasValue = currentValue.length > 0;
2553
- const shouldFloatLabel = isFocused || hasValue;
2611
+ const hasPlaceholder = !!props.placeholder;
2612
+ const hasPrefix = !!prefix;
2613
+ const hasSuffix = !!suffix;
2614
+ const shouldFloat = isFocused || hasValue || hasPlaceholder || hasPrefix;
2554
2615
  const characterLength = currentValue.length;
2555
2616
  const isCharacterLimitExceeded = maxLength ? characterLength > maxLength : false;
2556
- return /* @__PURE__ */ jsxs("div", { className: cn(textFieldContainerVariants({ fullWidth }), className), children: [
2557
- /* @__PURE__ */ jsxs(
2558
- "div",
2559
- {
2560
- className: cn(
2561
- textFieldWrapperVariants({
2562
- variant,
2563
- size,
2564
- disabled: isDisabled,
2565
- error: fieldIsInvalid,
2566
- focused: isFocused
2567
- })
2568
- ),
2569
- children: [
2617
+ const hasLeadingIcon = !!leadingIcon;
2618
+ const hasTrailingIcon = !!trailingIcon;
2619
+ const hasLabel = !!label;
2620
+ const showDescription = !!description && !fieldIsInvalid;
2621
+ const showError = fieldIsInvalid && !!errorMessage;
2622
+ const showCounter = characterCount && maxLength !== void 0;
2623
+ const showSupportingRow = showDescription || showError || showCounter;
2624
+ return /* @__PURE__ */ jsxs(
2625
+ "div",
2626
+ {
2627
+ className: cn(textFieldRootVariants({ fullWidth }), "group/text-field", className),
2628
+ ...getInteractionDataAttributes({
2629
+ isHovered,
2630
+ isFocusVisible,
2631
+ isDisabled,
2632
+ isReadOnly,
2633
+ isInvalid: fieldIsInvalid
2634
+ }),
2635
+ "data-focused": isFocused ? "" : void 0,
2636
+ "data-float": shouldFloat ? "" : void 0,
2637
+ "data-with-leading-icon": hasLeadingIcon ? "" : void 0,
2638
+ "data-with-trailing-icon": hasTrailingIcon ? "" : void 0,
2639
+ "data-with-prefix": hasPrefix ? "" : void 0,
2640
+ "data-with-suffix": hasSuffix ? "" : void 0,
2641
+ "data-no-label": !hasLabel ? "" : void 0,
2642
+ "data-multiline": multiline ? "" : void 0,
2643
+ children: [
2644
+ /* @__PURE__ */ jsxs("div", { ...hoverProps, className: cn(textFieldFieldVariants({ variant })), children: [
2645
+ variant === "filled" && /* @__PURE__ */ jsx("span", { className: cn(textFieldStateLayerVariants()), "aria-hidden": "true" }),
2570
2646
  leadingIcon && /* @__PURE__ */ jsx(
2571
2647
  "span",
2572
2648
  {
2573
- className: textFieldIconVariants({
2574
- position: "leading",
2575
- size,
2576
- disabled: isDisabled
2577
- }),
2649
+ className: cn(textFieldIconVariants({ position: "leading" })),
2650
+ "aria-hidden": "true",
2578
2651
  children: leadingIcon
2579
2652
  }
2580
2653
  ),
2581
- label && /* @__PURE__ */ jsxs(
2582
- "label",
2654
+ /* @__PURE__ */ jsxs("div", { className: "relative flex h-full min-w-0 flex-1 items-center", children: [
2655
+ label && /* @__PURE__ */ jsxs("label", { ...labelProps, className: cn(textFieldLabelVariants({ variant })), children: [
2656
+ label,
2657
+ isRequired && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2009*" })
2658
+ ] }),
2659
+ prefix && /* @__PURE__ */ jsx("span", { className: cn(textFieldAffixVariants({ variant, position: "prefix" })), children: prefix }),
2660
+ multiline ? /* @__PURE__ */ jsx(
2661
+ "textarea",
2662
+ {
2663
+ ...inputProps,
2664
+ ref: inputRef,
2665
+ className: cn(textFieldInputVariants({ variant, multiline: true })),
2666
+ rows,
2667
+ spellCheck: spellCheckProp
2668
+ }
2669
+ ) : /* @__PURE__ */ jsx(
2670
+ "input",
2671
+ {
2672
+ ...inputProps,
2673
+ ref: inputRef,
2674
+ className: cn(textFieldInputVariants({ variant, multiline: false })),
2675
+ spellCheck: spellCheckProp
2676
+ }
2677
+ ),
2678
+ suffix && /* @__PURE__ */ jsx("span", { className: cn(textFieldAffixVariants({ variant, position: "suffix" })), children: suffix })
2679
+ ] }),
2680
+ trailingIcon && /* @__PURE__ */ jsx(
2681
+ "span",
2583
2682
  {
2584
- ...labelProps,
2585
- className: cn(
2586
- textFieldLabelVariants({
2587
- variant,
2588
- size,
2589
- floating: shouldFloatLabel,
2590
- focused: isFocused,
2591
- error: fieldIsInvalid,
2592
- disabled: isDisabled,
2593
- hasLeadingIcon: !!leadingIcon
2594
- })
2595
- ),
2596
- children: [
2597
- label,
2598
- isRequired && " *"
2599
- ]
2683
+ className: cn(textFieldIconVariants({ position: "trailing" })),
2684
+ "aria-hidden": "true",
2685
+ children: trailingIcon
2600
2686
  }
2601
2687
  ),
2602
- multiline ? /* @__PURE__ */ jsx(
2603
- "textarea",
2604
- {
2605
- ...inputProps,
2606
- ref: inputRef,
2607
- className: cn(
2608
- textFieldInputVariants({
2609
- variant,
2610
- size,
2611
- disabled: isDisabled,
2612
- hasLeadingIcon: !!leadingIcon,
2613
- hasTrailingIcon: !!trailingIcon,
2614
- multiline: true
2615
- }),
2616
- label && "placeholder:opacity-0"
2617
- ),
2618
- rows,
2619
- spellCheck: spellCheckProp
2620
- }
2621
- ) : /* @__PURE__ */ jsx(
2622
- "input",
2688
+ variant === "filled" && /* @__PURE__ */ jsx("span", { className: cn(textFieldActiveIndicatorVariants()), "aria-hidden": "true" }),
2689
+ variant === "outlined" && /* @__PURE__ */ jsx("fieldset", { "aria-hidden": "true", className: cn(textFieldOutlineVariants()), children: /* @__PURE__ */ jsx("legend", { className: cn(textFieldNotchVariants()), children: label && /* @__PURE__ */ jsxs("span", { children: [
2690
+ label,
2691
+ isRequired && "\u2009*"
2692
+ ] }) }) })
2693
+ ] }),
2694
+ showSupportingRow && /* @__PURE__ */ jsxs("div", { className: cn(textFieldSupportingRowVariants()), children: [
2695
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
2696
+ showDescription && /* @__PURE__ */ jsx(
2697
+ "p",
2698
+ {
2699
+ ...descriptionProps,
2700
+ className: cn(textFieldSupportingTextVariants({ type: "description" })),
2701
+ children: description
2702
+ }
2703
+ ),
2704
+ showError && /* @__PURE__ */ jsx(
2705
+ "p",
2706
+ {
2707
+ ...errorMessageProps,
2708
+ className: cn(textFieldSupportingTextVariants({ type: "error" })),
2709
+ children: errorMessage
2710
+ }
2711
+ )
2712
+ ] }),
2713
+ showCounter && /* @__PURE__ */ jsxs(
2714
+ "span",
2623
2715
  {
2624
- ...inputProps,
2625
- ref: inputRef,
2626
2716
  className: cn(
2627
- textFieldInputVariants({
2628
- variant,
2629
- size,
2630
- disabled: isDisabled,
2631
- hasLeadingIcon: !!leadingIcon,
2632
- hasTrailingIcon: !!trailingIcon,
2633
- multiline: false
2634
- }),
2635
- label && "placeholder:opacity-0"
2636
- // Hide placeholder when there's a value to prevent overlap with floating label
2717
+ textFieldCounterVariants({ exceeded: isCharacterLimitExceeded })
2637
2718
  ),
2638
- spellCheck: spellCheckProp
2639
- }
2640
- ),
2641
- trailingIcon && /* @__PURE__ */ jsx(
2642
- "span",
2643
- {
2644
- className: textFieldIconVariants({
2645
- position: "trailing",
2646
- size,
2647
- disabled: isDisabled
2648
- }),
2649
- children: trailingIcon
2719
+ "aria-live": "polite",
2720
+ children: [
2721
+ characterLength,
2722
+ "\u2009/\u2009",
2723
+ maxLength
2724
+ ]
2650
2725
  }
2651
2726
  )
2652
- ]
2653
- }
2654
- ),
2655
- description && !fieldIsInvalid && /* @__PURE__ */ jsx(
2656
- "div",
2657
- {
2658
- ...descriptionProps,
2659
- className: textFieldHelperTextVariants({
2660
- type: "description",
2661
- disabled: isDisabled
2662
- }),
2663
- children: description
2664
- }
2665
- ),
2666
- fieldIsInvalid && errorMessage && /* @__PURE__ */ jsx(
2667
- "div",
2668
- {
2669
- ...errorMessageProps,
2670
- className: textFieldHelperTextVariants({
2671
- type: "error",
2672
- disabled: isDisabled
2673
- }),
2674
- children: errorMessage
2675
- }
2676
- ),
2677
- characterCount && maxLength && /* @__PURE__ */ jsxs(
2678
- "div",
2679
- {
2680
- className: textFieldCharacterCountVariants({
2681
- exceeded: isCharacterLimitExceeded,
2682
- disabled: isDisabled
2683
- }),
2684
- children: [
2685
- characterLength,
2686
- " / ",
2687
- maxLength
2688
- ]
2689
- }
2690
- )
2691
- ] });
2727
+ ] })
2728
+ ]
2729
+ }
2730
+ );
2692
2731
  } });
2693
2732
  }
2694
2733
  );