@tinybigui/react 0.14.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
@@ -7983,37 +7983,150 @@ InteractiveListItem.displayName = "InteractiveListItem";
7983
7983
  var listVariants = cva("w-full bg-surface");
7984
7984
  var listItemVariants = cva(
7985
7985
  [
7986
- "group relative flex items-center overflow-hidden px-4 py-2 cursor-pointer",
7987
- "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"
7988
7997
  ],
7989
7998
  {
7990
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
+ */
7991
8006
  density: {
7992
8007
  "one-line": "min-h-14",
7993
8008
  "two-line": "min-h-18",
7994
8009
  "three-line": "min-h-22 items-start"
7995
- },
7996
- isSelected: {
7997
- true: "bg-secondary-container text-on-secondary-container",
7998
- false: ""
7999
- },
8000
- isDisabled: {
8001
- true: "opacity-38 pointer-events-none",
8002
- false: ""
8003
- },
8004
- isInteractive: {
8005
- true: "",
8006
- false: "cursor-default"
8007
8010
  }
8008
8011
  },
8009
8012
  defaultVariants: {
8010
- density: "one-line",
8011
- isSelected: false,
8012
- isDisabled: false,
8013
- isInteractive: true
8013
+ density: "one-line"
8014
+ }
8015
+ }
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"
8014
8066
  }
8015
8067
  }
8016
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
+ ]);
8017
8130
  function interleaveWithDividers(children) {
8018
8131
  const items = Children.toArray(children);
8019
8132
  return items.reduce((acc, child, index) => {
@@ -8038,51 +8151,25 @@ var List = forwardRef(function List2({ className, showDividers = false, children
8038
8151
  return /* @__PURE__ */ jsx(ListHeadless, { ref, className: cn(listVariants(), className), ...props, children: renderedChildren });
8039
8152
  });
8040
8153
  List.displayName = "List";
8041
- var typeClasses = {
8042
- icon: "size-6 text-on-surface-variant",
8043
- avatar: "size-10 overflow-hidden rounded-full",
8044
- checkbox: "",
8045
- radio: ""
8046
- };
8047
8154
  var ListItemLeading = forwardRef(
8048
8155
  function ListItemLeading2({ type, children, className }, ref) {
8049
8156
  const isControl = type === "checkbox" || type === "radio";
8050
- return /* @__PURE__ */ jsx(
8051
- "div",
8052
- {
8053
- ref,
8054
- className: cn("mr-4 flex shrink-0 items-center", typeClasses[type], className),
8055
- children: isControl ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", tabIndex: -1, children }) : children
8056
- }
8057
- );
8157
+ return /* @__PURE__ */ jsx("div", { ref, className: cn(listItemLeadingVariants({ type }), className), children: isControl ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", tabIndex: -1, children }) : children });
8058
8158
  }
8059
8159
  );
8060
8160
  ListItemLeading.displayName = "ListItemLeading";
8061
- var typeClasses2 = {
8062
- icon: "size-6 text-on-surface-variant",
8063
- text: "text-on-surface-variant text-label-small",
8064
- checkbox: "",
8065
- radio: ""
8066
- };
8067
8161
  var ListItemTrailing = forwardRef(
8068
8162
  function ListItemTrailing2({ type, children, className }, ref) {
8069
8163
  const isControl = type === "checkbox" || type === "radio";
8070
- return /* @__PURE__ */ jsx(
8071
- "div",
8072
- {
8073
- ref,
8074
- className: cn("ml-auto flex shrink-0 items-center", typeClasses2[type], className),
8075
- children: isControl ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", tabIndex: -1, children }) : children
8076
- }
8077
- );
8164
+ return /* @__PURE__ */ jsx("div", { ref, className: cn(listItemTrailingVariants({ type }), className), children: isControl ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", tabIndex: -1, children }) : children });
8078
8165
  }
8079
8166
  );
8080
8167
  ListItemTrailing.displayName = "ListItemTrailing";
8081
8168
  var ListItemText = forwardRef(function ListItemText2({ headline, supportingText, overline, className }, ref) {
8082
8169
  return /* @__PURE__ */ jsxs("div", { ref, className: cn("min-w-0 flex-1", className), children: [
8083
- overline && /* @__PURE__ */ jsx("p", { className: "text-on-surface-variant text-label-small", children: overline }),
8084
- /* @__PURE__ */ jsx("p", { className: "text-on-surface text-body-large", children: headline }),
8085
- 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 })
8086
8173
  ] });
8087
8174
  });
8088
8175
  ListItemText.displayName = "ListItemText";
@@ -8126,44 +8213,72 @@ var ListItem = forwardRef(function ListItem2({
8126
8213
  }
8127
8214
  );
8128
8215
  }
8129
- return /* @__PURE__ */ jsxs(
8130
- "li",
8216
+ return /* @__PURE__ */ jsx(
8217
+ StaticStyledListItem,
8131
8218
  {
8132
8219
  ref: forwardedRef,
8133
- role: "listitem",
8134
- className: cn(
8135
- listItemVariants({
8136
- density,
8137
- isSelected: false,
8138
- isDisabled,
8139
- isInteractive: false
8140
- }),
8141
- className
8142
- ),
8143
- children: [
8144
- leadingSlot && /* @__PURE__ */ jsx(ListItemLeading, { type: leadingType ?? "icon", children: leadingSlot }),
8145
- /* @__PURE__ */ jsx(
8146
- ListItemText,
8147
- {
8148
- headline,
8149
- ...supportingText !== void 0 ? { supportingText } : {},
8150
- ...overline !== void 0 ? { overline } : {}
8151
- }
8152
- ),
8153
- trailingSlot && /* @__PURE__ */ jsx(ListItemTrailing, { type: trailingType ?? "icon", children: trailingSlot }),
8154
- insetDivider && /* @__PURE__ */ jsx(
8155
- Divider,
8156
- {
8157
- orientation: "horizontal",
8158
- inset: "start",
8159
- className: "absolute right-0 bottom-0 left-0"
8160
- }
8161
- )
8162
- ]
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 } : {}
8163
8232
  }
8164
8233
  );
8165
8234
  });
8166
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";
8167
8282
  var InteractiveStyledListItem = forwardRef(
8168
8283
  function InteractiveStyledListItem2({
8169
8284
  value,
@@ -8181,36 +8296,36 @@ var InteractiveStyledListItem = forwardRef(
8181
8296
  }, forwardedRef) {
8182
8297
  const internalRef = useRef(null);
8183
8298
  const ref = forwardedRef ?? internalRef;
8184
- const { optionProps, isSelected, isDisabled } = useOption({ key: value }, state, ref);
8185
- const { onMouseDown: handleRipple, ripples } = useRipple({
8186
- disabled: isDisabled
8187
- });
8188
- 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;
8189
8309
  return /* @__PURE__ */ jsxs(
8190
8310
  "li",
8191
8311
  {
8192
8312
  ...mergedProps,
8193
8313
  ref,
8194
- className: cn(
8195
- listItemVariants({
8196
- density,
8197
- isSelected,
8198
- isDisabled,
8199
- isInteractive: true
8200
- }),
8201
- className
8202
- ),
8203
- "data-selected": isSelected || void 0,
8204
- "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,
8205
8325
  children: [
8206
- /* @__PURE__ */ jsx(
8207
- "div",
8208
- {
8209
- "aria-hidden": "true",
8210
- 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"
8211
- }
8212
- ),
8213
8326
  ripples,
8327
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn(listItemStateLayerVariants()) }),
8328
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn(listItemFocusRingVariants()) }),
8214
8329
  leadingSlot && /* @__PURE__ */ jsx(ListItemLeading, { type: leadingType ?? "icon", children: leadingSlot }),
8215
8330
  /* @__PURE__ */ jsx(
8216
8331
  ListItemText,