@tinybigui/react 0.7.0 → 0.8.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/README.md +10 -10
- package/dist/index.cjs +118 -101
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +145 -157
- package/dist/index.d.ts +145 -157
- package/dist/index.js +118 -101
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ A modern, accessible React component library implementing Google's Material Desi
|
|
|
12
12
|
|
|
13
13
|
## ✅ Status
|
|
14
14
|
|
|
15
|
-
> **Latest Release: v0.
|
|
15
|
+
> **Latest Release: v0.8.0** (2026-06-09)
|
|
16
16
|
>
|
|
17
17
|
> **29 MD3 components** published to npm with full TypeScript support and WCAG 2.1 AA accessibility.
|
|
18
18
|
>
|
|
@@ -170,15 +170,15 @@ See [THEMING.md](./THEMING.md) for the full customization guide.
|
|
|
170
170
|
|
|
171
171
|
### Phase 4: Data Display ✅
|
|
172
172
|
|
|
173
|
-
| Component | Status | Description
|
|
174
|
-
| ------------ | ------ |
|
|
175
|
-
| `Card` | ✅ | Elevated, filled, outlined variants
|
|
176
|
-
| `List` | ✅ | Static and interactive list items
|
|
177
|
-
| `Chip` | ✅ | Assist, Filter, Input, Suggestion types
|
|
178
|
-
| `Badge` | ✅ |
|
|
179
|
-
| `Divider` | ✅ | Horizontal/vertical, inset variants
|
|
180
|
-
| `DatePicker` | ✅ | Docked, modal, and input variants
|
|
181
|
-
| `TimePicker` | ✅ | 12h/24h clock dial, range selection
|
|
173
|
+
| Component | Status | Description |
|
|
174
|
+
| ------------ | ------ | --------------------------------------------------------------- |
|
|
175
|
+
| `Card` | ✅ | Elevated, filled, outlined variants |
|
|
176
|
+
| `List` | ✅ | Static and interactive list items |
|
|
177
|
+
| `Chip` | ✅ | Assist, Filter, Input, Suggestion types |
|
|
178
|
+
| `Badge` | ✅ | MD3 expressive dot/count badges, icon-corner anchoring (v0.8.0) |
|
|
179
|
+
| `Divider` | ✅ | Horizontal/vertical, inset variants |
|
|
180
|
+
| `DatePicker` | ✅ | Docked, modal, and input variants |
|
|
181
|
+
| `TimePicker` | ✅ | 12h/24h clock dial, range selection |
|
|
182
182
|
|
|
183
183
|
### Planned
|
|
184
184
|
|
package/dist/index.cjs
CHANGED
|
@@ -5070,106 +5070,48 @@ var Drawer = React.forwardRef(
|
|
|
5070
5070
|
}
|
|
5071
5071
|
);
|
|
5072
5072
|
Drawer.displayName = "Drawer";
|
|
5073
|
-
var
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
)
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
);
|
|
5108
|
-
|
|
5073
|
+
var badgeAppearance = [
|
|
5074
|
+
// ── Shape ─────────────────────────────────────────────────────────────────────
|
|
5075
|
+
"flex items-center justify-center",
|
|
5076
|
+
"rounded-full",
|
|
5077
|
+
// ── Large (count) sizing — base defaults ──────────────────────────────────────
|
|
5078
|
+
// Height 16dp, min-width 16dp, horizontal padding 4dp
|
|
5079
|
+
"h-4 min-w-4 px-1",
|
|
5080
|
+
// ── Color — error role (only MD3-spec role for badges) ────────────────────────
|
|
5081
|
+
"bg-error text-on-error",
|
|
5082
|
+
// ── Typography — label-small, tight leading, tabular numbers ──────────────────
|
|
5083
|
+
"text-label-small leading-none tabular-nums",
|
|
5084
|
+
// ── Visibility (runtime flag) ──────────────────────────────────────────────────
|
|
5085
|
+
// Base: fully visible
|
|
5086
|
+
"scale-100",
|
|
5087
|
+
// data-invisible: scale to zero (visually hidden; aria-label still readable by SR)
|
|
5088
|
+
"data-[invisible]:scale-0",
|
|
5089
|
+
// ── Dot content flag overrides (placed last — cascade wins over base sizing) ───
|
|
5090
|
+
// Clear out the count-pill sizing, set 6dp circle
|
|
5091
|
+
"data-[dot]:size-1.5",
|
|
5092
|
+
"data-[dot]:min-w-0",
|
|
5093
|
+
"data-[dot]:p-0",
|
|
5094
|
+
"data-[dot]:text-[0]"
|
|
5095
|
+
// suppress any stray text rendering on dot
|
|
5096
|
+
];
|
|
5097
|
+
var badgeVariants2 = classVarianceAuthority.cva([
|
|
5098
|
+
// ── Anchored placement — badge center on host's top-right corner ──────────────
|
|
5099
|
+
// top-0 right-0 places the badge's own top-right at the host's top-right,
|
|
5100
|
+
// then the 1/2-element translate moves the badge center onto that corner.
|
|
5101
|
+
// Host-size-agnostic: works for any wrapped element (icon, avatar, nav chip).
|
|
5102
|
+
"absolute top-0 right-0 -translate-y-1/2 translate-x-1/2",
|
|
5103
|
+
...badgeAppearance
|
|
5104
|
+
]);
|
|
5105
|
+
var badgeStaticVariants = classVarianceAuthority.cva(["inline-flex", ...badgeAppearance]);
|
|
5106
|
+
function isBadgeConfig(badge) {
|
|
5107
|
+
return typeof badge === "object" && badge !== null && !React.isValidElement(badge) && "count" in badge;
|
|
5108
|
+
}
|
|
5109
|
+
function getBadgeDisplayValue(count, max) {
|
|
5109
5110
|
if (count === void 0) return "";
|
|
5110
5111
|
return count > max ? `${max}+` : count.toString();
|
|
5111
|
-
}
|
|
5112
|
-
|
|
5113
|
-
if (override) return override;
|
|
5112
|
+
}
|
|
5113
|
+
function getBadgeAriaLabel(count) {
|
|
5114
5114
|
return count === void 0 ? "New" : `${count} notifications`;
|
|
5115
|
-
};
|
|
5116
|
-
var BadgeContent = React.forwardRef(
|
|
5117
|
-
({
|
|
5118
|
-
count,
|
|
5119
|
-
max = 999,
|
|
5120
|
-
color = "error",
|
|
5121
|
-
invisible = false,
|
|
5122
|
-
"aria-label": ariaLabelOverride,
|
|
5123
|
-
reducedMotion = false,
|
|
5124
|
-
className
|
|
5125
|
-
}, ref) => {
|
|
5126
|
-
const size = count === void 0 ? "small" : "large";
|
|
5127
|
-
const displayValue = getDisplayValue(count, max);
|
|
5128
|
-
const ariaLabel = getAriaLabel(count, ariaLabelOverride);
|
|
5129
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5130
|
-
"span",
|
|
5131
|
-
{
|
|
5132
|
-
ref,
|
|
5133
|
-
role: "status",
|
|
5134
|
-
"aria-label": ariaLabel,
|
|
5135
|
-
className: cn(badgeVariants2({ size, color, invisible, reducedMotion }), className),
|
|
5136
|
-
children: displayValue
|
|
5137
|
-
}
|
|
5138
|
-
);
|
|
5139
|
-
}
|
|
5140
|
-
);
|
|
5141
|
-
BadgeContent.displayName = "BadgeContent";
|
|
5142
|
-
var Badge = React.forwardRef(
|
|
5143
|
-
({
|
|
5144
|
-
count,
|
|
5145
|
-
max = 999,
|
|
5146
|
-
color = "error",
|
|
5147
|
-
invisible = false,
|
|
5148
|
-
"aria-label": ariaLabel,
|
|
5149
|
-
className,
|
|
5150
|
-
children
|
|
5151
|
-
}, ref) => {
|
|
5152
|
-
const isReduced = useReducedMotion();
|
|
5153
|
-
const shouldShow = !invisible && (count === void 0 || count > 0);
|
|
5154
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(BadgeHeadless, { ref, className, children: [
|
|
5155
|
-
children,
|
|
5156
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5157
|
-
BadgeContent,
|
|
5158
|
-
{
|
|
5159
|
-
count,
|
|
5160
|
-
max,
|
|
5161
|
-
color,
|
|
5162
|
-
invisible: !shouldShow,
|
|
5163
|
-
"aria-label": ariaLabel,
|
|
5164
|
-
reducedMotion: isReduced
|
|
5165
|
-
}
|
|
5166
|
-
)
|
|
5167
|
-
] });
|
|
5168
|
-
}
|
|
5169
|
-
);
|
|
5170
|
-
Badge.displayName = "Badge";
|
|
5171
|
-
function isBadgeConfig(badge) {
|
|
5172
|
-
return typeof badge === "object" && badge !== null && !React.isValidElement(badge) && ("count" in badge || "color" in badge);
|
|
5173
5115
|
}
|
|
5174
5116
|
var DrawerItem = React.forwardRef(
|
|
5175
5117
|
({
|
|
@@ -5197,12 +5139,18 @@ var DrawerItem = React.forwardRef(
|
|
|
5197
5139
|
const renderBadge = () => {
|
|
5198
5140
|
if (!badge) return null;
|
|
5199
5141
|
if (isBadgeConfig(badge)) {
|
|
5142
|
+
const max = 999;
|
|
5143
|
+
const isDot = badge.count === void 0;
|
|
5144
|
+
const displayValue = getBadgeDisplayValue(badge.count, max);
|
|
5145
|
+
const ariaLabel = getBadgeAriaLabel(badge.count);
|
|
5200
5146
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative z-10 ml-auto flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5201
|
-
|
|
5147
|
+
"span",
|
|
5202
5148
|
{
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5149
|
+
role: "status",
|
|
5150
|
+
"aria-label": ariaLabel,
|
|
5151
|
+
"data-dot": isDot ? "" : void 0,
|
|
5152
|
+
className: cn(badgeStaticVariants()),
|
|
5153
|
+
children: displayValue
|
|
5206
5154
|
}
|
|
5207
5155
|
) });
|
|
5208
5156
|
}
|
|
@@ -8701,6 +8649,75 @@ var Search = React.forwardRef(
|
|
|
8701
8649
|
}
|
|
8702
8650
|
);
|
|
8703
8651
|
Search.displayName = "Search";
|
|
8652
|
+
var BadgeHeadless = React.forwardRef(
|
|
8653
|
+
({ className, children, ...props }, ref) => {
|
|
8654
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-flex", className), ...props, children });
|
|
8655
|
+
}
|
|
8656
|
+
);
|
|
8657
|
+
BadgeHeadless.displayName = "BadgeHeadless";
|
|
8658
|
+
var getDisplayValue = (count, max) => {
|
|
8659
|
+
if (count === void 0) return "";
|
|
8660
|
+
return count > max ? `${max}+` : count.toString();
|
|
8661
|
+
};
|
|
8662
|
+
var getAriaLabel = (count, override) => {
|
|
8663
|
+
if (override) return override;
|
|
8664
|
+
return count === void 0 ? "New" : `${count} notifications`;
|
|
8665
|
+
};
|
|
8666
|
+
var BadgeContent = React.forwardRef(
|
|
8667
|
+
({
|
|
8668
|
+
count,
|
|
8669
|
+
max = 999,
|
|
8670
|
+
invisible = false,
|
|
8671
|
+
"aria-label": ariaLabelOverride,
|
|
8672
|
+
reducedMotion = false,
|
|
8673
|
+
className
|
|
8674
|
+
}, ref) => {
|
|
8675
|
+
const isDot = count === void 0;
|
|
8676
|
+
const displayValue = getDisplayValue(count, max);
|
|
8677
|
+
const ariaLabel = getAriaLabel(count, ariaLabelOverride);
|
|
8678
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8679
|
+
"span",
|
|
8680
|
+
{
|
|
8681
|
+
ref,
|
|
8682
|
+
role: "status",
|
|
8683
|
+
"aria-label": ariaLabel,
|
|
8684
|
+
"data-dot": isDot ? "" : void 0,
|
|
8685
|
+
"data-invisible": invisible ? "" : void 0,
|
|
8686
|
+
className: cn(
|
|
8687
|
+
badgeVariants2(),
|
|
8688
|
+
// MD3 Expressive spatial motion for show/hide scale animation.
|
|
8689
|
+
// Spatial pairing: scale transform → expressive-fast-spatial token.
|
|
8690
|
+
// Guarded at the component level; do NOT use CSS-only reduced-motion
|
|
8691
|
+
// because this is a JS-conditional class, not a persistent transition.
|
|
8692
|
+
!reducedMotion && "duration-expressive-fast-spatial ease-expressive-fast-spatial transition-transform",
|
|
8693
|
+
className
|
|
8694
|
+
),
|
|
8695
|
+
children: displayValue
|
|
8696
|
+
}
|
|
8697
|
+
);
|
|
8698
|
+
}
|
|
8699
|
+
);
|
|
8700
|
+
BadgeContent.displayName = "BadgeContent";
|
|
8701
|
+
var Badge = React.forwardRef(
|
|
8702
|
+
({ count, max = 999, invisible = false, "aria-label": ariaLabel, className, children }, ref) => {
|
|
8703
|
+
const isReduced = useReducedMotion();
|
|
8704
|
+
const shouldShow = !invisible && (count === void 0 || count > 0);
|
|
8705
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(BadgeHeadless, { ref, className, children: [
|
|
8706
|
+
children,
|
|
8707
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8708
|
+
BadgeContent,
|
|
8709
|
+
{
|
|
8710
|
+
count,
|
|
8711
|
+
max,
|
|
8712
|
+
invisible: !shouldShow,
|
|
8713
|
+
"aria-label": ariaLabel,
|
|
8714
|
+
reducedMotion: isReduced
|
|
8715
|
+
}
|
|
8716
|
+
)
|
|
8717
|
+
] });
|
|
8718
|
+
}
|
|
8719
|
+
);
|
|
8720
|
+
Badge.displayName = "Badge";
|
|
8704
8721
|
var splitButtonContainerVariants = classVarianceAuthority.cva(
|
|
8705
8722
|
["inline-flex items-center rounded-full overflow-hidden"],
|
|
8706
8723
|
{
|