@tinybigui/react 0.13.0 → 0.15.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
  );
@@ -7944,37 +7983,150 @@ InteractiveListItem.displayName = "InteractiveListItem";
7944
7983
  var listVariants = cva("w-full bg-surface");
7945
7984
  var listItemVariants = cva(
7946
7985
  [
7947
- "group relative flex items-center overflow-hidden px-4 py-2 cursor-pointer",
7948
- "transition-[background-color] duration-short4 ease-standard"
7986
+ // Layout
7987
+ "relative flex items-center overflow-hidden px-4 py-2 select-none",
7988
+ // Color transition — effects spring (no spatial overshoot on color)
7989
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
7990
+ // Cursor: non-interactive base; data-[interactive] overrides
7991
+ "cursor-default",
7992
+ "data-[interactive]:cursor-pointer",
7993
+ // Selected: secondary-container background
7994
+ "group-data-[selected]/list-item:bg-secondary-container",
7995
+ // Disabled: self-targeting selectors (not group, since root is the group)
7996
+ "data-[disabled]:opacity-38 data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed"
7949
7997
  ],
7950
7998
  {
7951
7999
  variants: {
8000
+ /**
8001
+ * Visual density — derived from content, not a user prop.
8002
+ * one-line: headline only (56dp)
8003
+ * two-line: headline + supportingText (72dp)
8004
+ * three-line: overline + headline + supportingText (88dp)
8005
+ */
7952
8006
  density: {
7953
8007
  "one-line": "min-h-14",
7954
8008
  "two-line": "min-h-18",
7955
8009
  "three-line": "min-h-22 items-start"
7956
- },
7957
- isSelected: {
7958
- true: "bg-secondary-container text-on-secondary-container",
7959
- false: ""
7960
- },
7961
- isDisabled: {
7962
- true: "opacity-38 pointer-events-none",
7963
- false: ""
7964
- },
7965
- isInteractive: {
7966
- true: "",
7967
- false: "cursor-default"
7968
8010
  }
7969
8011
  },
7970
8012
  defaultVariants: {
7971
- density: "one-line",
7972
- isSelected: false,
7973
- isDisabled: false,
7974
- isInteractive: true
8013
+ density: "one-line"
7975
8014
  }
7976
8015
  }
7977
8016
  );
8017
+ var listItemStateLayerVariants = cva([
8018
+ "absolute inset-0 pointer-events-none opacity-0",
8019
+ "bg-on-surface",
8020
+ // Effects transition for opacity — no spatial overshoot
8021
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
8022
+ // Hover: 8%
8023
+ "group-data-[hovered]/list-item:opacity-8",
8024
+ // Focus: 10%
8025
+ "group-data-[focus-visible]/list-item:opacity-10",
8026
+ // Pressed: 10%, doubled selector beats hover
8027
+ "group-data-[pressed]/list-item:group-data-[pressed]/list-item:opacity-10",
8028
+ // No state layer when disabled
8029
+ "group-data-[disabled]/list-item:hidden"
8030
+ ]);
8031
+ var listItemFocusRingVariants = cva([
8032
+ "pointer-events-none absolute inset-0",
8033
+ "outline outline-2 -outline-offset-2 outline-secondary",
8034
+ // Effects transition — opacity must NOT overshoot
8035
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
8036
+ "opacity-0",
8037
+ "group-data-[focus-visible]/list-item:opacity-100"
8038
+ ]);
8039
+ var listItemLeadingVariants = cva(
8040
+ [
8041
+ "mr-4 flex shrink-0 items-center",
8042
+ // Effects transition for icon color changes
8043
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
8044
+ ],
8045
+ {
8046
+ variants: {
8047
+ type: {
8048
+ icon: [
8049
+ "size-6",
8050
+ "text-on-surface-variant",
8051
+ // Selected: icon color changes to on-secondary-container
8052
+ "group-data-[selected]/list-item:text-on-secondary-container",
8053
+ // Disabled: 38% (inherited from root opacity-38, but also explicit for color accuracy)
8054
+ "group-data-[disabled]/list-item:text-on-surface/38"
8055
+ ],
8056
+ avatar: [
8057
+ "size-10 overflow-hidden rounded-full"
8058
+ // Avatar color provided by content; no token overrides needed
8059
+ ],
8060
+ checkbox: [],
8061
+ radio: []
8062
+ }
8063
+ },
8064
+ defaultVariants: {
8065
+ type: "icon"
8066
+ }
8067
+ }
8068
+ );
8069
+ var listItemTrailingVariants = cva(
8070
+ [
8071
+ "ml-auto flex shrink-0 items-center",
8072
+ // Effects transition for color changes
8073
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
8074
+ ],
8075
+ {
8076
+ variants: {
8077
+ type: {
8078
+ icon: [
8079
+ "size-6",
8080
+ "text-on-surface-variant",
8081
+ "group-data-[selected]/list-item:text-on-secondary-container",
8082
+ "group-data-[disabled]/list-item:text-on-surface/38"
8083
+ ],
8084
+ text: [
8085
+ "text-label-small",
8086
+ "text-on-surface-variant",
8087
+ "group-data-[selected]/list-item:text-on-secondary-container",
8088
+ "group-data-[disabled]/list-item:text-on-surface/38"
8089
+ ],
8090
+ checkbox: [],
8091
+ radio: []
8092
+ }
8093
+ },
8094
+ defaultVariants: {
8095
+ type: "icon"
8096
+ }
8097
+ }
8098
+ );
8099
+ var listItemOverlineVariants = cva([
8100
+ "text-label-small",
8101
+ "text-on-surface-variant",
8102
+ // Effects transition for color
8103
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
8104
+ // Selected: on-secondary-container
8105
+ "group-data-[selected]/list-item:text-on-secondary-container",
8106
+ // Disabled: opacity inherited from root; explicit for color
8107
+ "group-data-[disabled]/list-item:text-on-surface/38"
8108
+ ]);
8109
+ var listItemHeadlineVariants = cva([
8110
+ "text-body-large",
8111
+ "text-on-surface",
8112
+ // Effects transition for color
8113
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
8114
+ // Selected: on-secondary-container
8115
+ "group-data-[selected]/list-item:text-on-secondary-container",
8116
+ // Disabled: 38% color via CSS (opacity-38 on root handles all descendants, but
8117
+ // explicit token ensures predictable rendering when color is specified).
8118
+ "group-data-[disabled]/list-item:text-on-surface/38"
8119
+ ]);
8120
+ var listItemSupportingTextVariants = cva([
8121
+ "text-body-medium",
8122
+ "text-on-surface-variant",
8123
+ // Effects transition for color
8124
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
8125
+ // Selected: on-secondary-container
8126
+ "group-data-[selected]/list-item:text-on-secondary-container",
8127
+ // Disabled: 38% color
8128
+ "group-data-[disabled]/list-item:text-on-surface/38"
8129
+ ]);
7978
8130
  function interleaveWithDividers(children) {
7979
8131
  const items = Children.toArray(children);
7980
8132
  return items.reduce((acc, child, index) => {
@@ -7999,51 +8151,25 @@ var List = forwardRef(function List2({ className, showDividers = false, children
7999
8151
  return /* @__PURE__ */ jsx(ListHeadless, { ref, className: cn(listVariants(), className), ...props, children: renderedChildren });
8000
8152
  });
8001
8153
  List.displayName = "List";
8002
- var typeClasses = {
8003
- icon: "size-6 text-on-surface-variant",
8004
- avatar: "size-10 overflow-hidden rounded-full",
8005
- checkbox: "",
8006
- radio: ""
8007
- };
8008
8154
  var ListItemLeading = forwardRef(
8009
8155
  function ListItemLeading2({ type, children, className }, ref) {
8010
8156
  const isControl = type === "checkbox" || type === "radio";
8011
- return /* @__PURE__ */ jsx(
8012
- "div",
8013
- {
8014
- ref,
8015
- className: cn("mr-4 flex shrink-0 items-center", typeClasses[type], className),
8016
- children: isControl ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", tabIndex: -1, children }) : children
8017
- }
8018
- );
8157
+ return /* @__PURE__ */ jsx("div", { ref, className: cn(listItemLeadingVariants({ type }), className), children: isControl ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", tabIndex: -1, children }) : children });
8019
8158
  }
8020
8159
  );
8021
8160
  ListItemLeading.displayName = "ListItemLeading";
8022
- var typeClasses2 = {
8023
- icon: "size-6 text-on-surface-variant",
8024
- text: "text-on-surface-variant text-label-small",
8025
- checkbox: "",
8026
- radio: ""
8027
- };
8028
8161
  var ListItemTrailing = forwardRef(
8029
8162
  function ListItemTrailing2({ type, children, className }, ref) {
8030
8163
  const isControl = type === "checkbox" || type === "radio";
8031
- return /* @__PURE__ */ jsx(
8032
- "div",
8033
- {
8034
- ref,
8035
- className: cn("ml-auto flex shrink-0 items-center", typeClasses2[type], className),
8036
- children: isControl ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", tabIndex: -1, children }) : children
8037
- }
8038
- );
8164
+ return /* @__PURE__ */ jsx("div", { ref, className: cn(listItemTrailingVariants({ type }), className), children: isControl ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", tabIndex: -1, children }) : children });
8039
8165
  }
8040
8166
  );
8041
8167
  ListItemTrailing.displayName = "ListItemTrailing";
8042
8168
  var ListItemText = forwardRef(function ListItemText2({ headline, supportingText, overline, className }, ref) {
8043
8169
  return /* @__PURE__ */ jsxs("div", { ref, className: cn("min-w-0 flex-1", className), children: [
8044
- overline && /* @__PURE__ */ jsx("p", { className: "text-on-surface-variant text-label-small", children: overline }),
8045
- /* @__PURE__ */ jsx("p", { className: "text-on-surface text-body-large", children: headline }),
8046
- supportingText && /* @__PURE__ */ jsx("p", { className: "text-on-surface-variant text-body-medium", children: supportingText })
8170
+ overline && /* @__PURE__ */ jsx("p", { className: cn(listItemOverlineVariants()), children: overline }),
8171
+ /* @__PURE__ */ jsx("p", { className: cn(listItemHeadlineVariants()), children: headline }),
8172
+ supportingText && /* @__PURE__ */ jsx("p", { className: cn(listItemSupportingTextVariants()), children: supportingText })
8047
8173
  ] });
8048
8174
  });
8049
8175
  ListItemText.displayName = "ListItemText";
@@ -8087,44 +8213,72 @@ var ListItem = forwardRef(function ListItem2({
8087
8213
  }
8088
8214
  );
8089
8215
  }
8090
- return /* @__PURE__ */ jsxs(
8091
- "li",
8216
+ return /* @__PURE__ */ jsx(
8217
+ StaticStyledListItem,
8092
8218
  {
8093
8219
  ref: forwardedRef,
8094
- role: "listitem",
8095
- className: cn(
8096
- listItemVariants({
8097
- density,
8098
- isSelected: false,
8099
- isDisabled,
8100
- isInteractive: false
8101
- }),
8102
- className
8103
- ),
8104
- children: [
8105
- leadingSlot && /* @__PURE__ */ jsx(ListItemLeading, { type: leadingType ?? "icon", children: leadingSlot }),
8106
- /* @__PURE__ */ jsx(
8107
- ListItemText,
8108
- {
8109
- headline,
8110
- ...supportingText !== void 0 ? { supportingText } : {},
8111
- ...overline !== void 0 ? { overline } : {}
8112
- }
8113
- ),
8114
- trailingSlot && /* @__PURE__ */ jsx(ListItemTrailing, { type: trailingType ?? "icon", children: trailingSlot }),
8115
- insetDivider && /* @__PURE__ */ jsx(
8116
- Divider,
8117
- {
8118
- orientation: "horizontal",
8119
- inset: "start",
8120
- className: "absolute right-0 bottom-0 left-0"
8121
- }
8122
- )
8123
- ]
8220
+ value,
8221
+ headline,
8222
+ ...supportingText !== void 0 ? { supportingText } : {},
8223
+ ...overline !== void 0 ? { overline } : {},
8224
+ ...leadingSlot !== void 0 ? { leadingSlot } : {},
8225
+ ...leadingType !== void 0 ? { leadingType } : {},
8226
+ ...trailingSlot !== void 0 ? { trailingSlot } : {},
8227
+ ...trailingType !== void 0 ? { trailingType } : {},
8228
+ density,
8229
+ isDisabled,
8230
+ insetDivider,
8231
+ ...className !== void 0 ? { className } : {}
8124
8232
  }
8125
8233
  );
8126
8234
  });
8127
8235
  ListItem.displayName = "ListItem";
8236
+ var StaticStyledListItem = forwardRef(
8237
+ function StaticStyledListItem2({
8238
+ headline,
8239
+ supportingText,
8240
+ overline,
8241
+ leadingSlot,
8242
+ leadingType,
8243
+ trailingSlot,
8244
+ trailingType,
8245
+ density,
8246
+ isDisabled,
8247
+ insetDivider,
8248
+ className
8249
+ }, ref) {
8250
+ return /* @__PURE__ */ jsxs(
8251
+ "li",
8252
+ {
8253
+ ref,
8254
+ role: "listitem",
8255
+ className: cn(listItemVariants({ density }), "group/list-item", className),
8256
+ ...getInteractionDataAttributes({ isDisabled }),
8257
+ children: [
8258
+ leadingSlot && /* @__PURE__ */ jsx(ListItemLeading, { type: leadingType ?? "icon", children: leadingSlot }),
8259
+ /* @__PURE__ */ jsx(
8260
+ ListItemText,
8261
+ {
8262
+ headline,
8263
+ ...supportingText !== void 0 ? { supportingText } : {},
8264
+ ...overline !== void 0 ? { overline } : {}
8265
+ }
8266
+ ),
8267
+ trailingSlot && /* @__PURE__ */ jsx(ListItemTrailing, { type: trailingType ?? "icon", children: trailingSlot }),
8268
+ insetDivider && /* @__PURE__ */ jsx(
8269
+ Divider,
8270
+ {
8271
+ orientation: "horizontal",
8272
+ inset: "start",
8273
+ className: "absolute right-0 bottom-0 left-0"
8274
+ }
8275
+ )
8276
+ ]
8277
+ }
8278
+ );
8279
+ }
8280
+ );
8281
+ StaticStyledListItem.displayName = "StaticStyledListItem";
8128
8282
  var InteractiveStyledListItem = forwardRef(
8129
8283
  function InteractiveStyledListItem2({
8130
8284
  value,
@@ -8142,36 +8296,36 @@ var InteractiveStyledListItem = forwardRef(
8142
8296
  }, forwardedRef) {
8143
8297
  const internalRef = useRef(null);
8144
8298
  const ref = forwardedRef ?? internalRef;
8145
- const { optionProps, isSelected, isDisabled } = useOption({ key: value }, state, ref);
8146
- const { onMouseDown: handleRipple, ripples } = useRipple({
8147
- disabled: isDisabled
8148
- });
8149
- const mergedProps = mergeProps(optionProps, { onMouseDown: handleRipple });
8299
+ const { optionProps, isSelected, isDisabled, isPressed, isFocusVisible } = useOption(
8300
+ { key: value },
8301
+ state,
8302
+ ref
8303
+ );
8304
+ const { isHovered, hoverProps } = useHover({ isDisabled });
8305
+ const { onMouseDown: handleRipple, ripples } = useRipple({ disabled: isDisabled });
8306
+ const mergedProps = mergeProps(optionProps, hoverProps, { onMouseDown: handleRipple });
8307
+ const hasLeading = !!leadingSlot;
8308
+ const hasTrailing = !!trailingSlot;
8150
8309
  return /* @__PURE__ */ jsxs(
8151
8310
  "li",
8152
8311
  {
8153
8312
  ...mergedProps,
8154
8313
  ref,
8155
- className: cn(
8156
- listItemVariants({
8157
- density,
8158
- isSelected,
8159
- isDisabled,
8160
- isInteractive: true
8161
- }),
8162
- className
8163
- ),
8164
- "data-selected": isSelected || void 0,
8165
- "data-disabled": isDisabled || void 0,
8314
+ className: cn(listItemVariants({ density }), "group/list-item", className),
8315
+ ...getInteractionDataAttributes({
8316
+ isHovered,
8317
+ isFocusVisible,
8318
+ isPressed,
8319
+ isSelected,
8320
+ isDisabled
8321
+ }),
8322
+ "data-interactive": "",
8323
+ "data-with-leading": hasLeading ? "" : void 0,
8324
+ "data-with-trailing": hasTrailing ? "" : void 0,
8166
8325
  children: [
8167
- /* @__PURE__ */ jsx(
8168
- "div",
8169
- {
8170
- "aria-hidden": "true",
8171
- className: "bg-on-surface duration-short2 ease-standard pointer-events-none absolute inset-0 opacity-0 transition-opacity group-hover:opacity-8 group-active:opacity-12"
8172
- }
8173
- ),
8174
8326
  ripples,
8327
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn(listItemStateLayerVariants()) }),
8328
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn(listItemFocusRingVariants()) }),
8175
8329
  leadingSlot && /* @__PURE__ */ jsx(ListItemLeading, { type: leadingType ?? "icon", children: leadingSlot }),
8176
8330
  /* @__PURE__ */ jsx(
8177
8331
  ListItemText,