@nucleux/md3-button-group 0.0.0-stage → 0.7.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/LICENSE +21 -0
- package/README.md +38 -2
- package/dist/index.cjs +225 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +52 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +202 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nucleux
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @nucleux/md3-button-group
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Material 3 button group — Nucleux agentic UI for React.
|
|
4
|
+
|
|
5
|
+
Part of **[Nucleux](https://github.com/intelligaia-open-labs/nucleux)** — agentic UI components for React. Install a single component, or the full kit via [`@nucleux/react`](https://www.npmjs.com/package/@nucleux/react).
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Exports
|
|
9
|
+
|
|
10
|
+
- **`Md3ButtonGroup`** — root (`variant="standard" | "connected"`, `size="xs" | "sm" | "md" | "lg" | "xl"`, `shape="round" | "square"`, `buttonVariant`, `selectionMode="none" | "single" | "multiple"`, `selectionRequired`, `value` / `defaultValue` / `onValueChange`)
|
|
11
|
+
- **`Md3ButtonGroupItem`** — a button in the group (`value`, `variant`, `icon`); toggles with `aria-pressed` when the group is selectable
|
|
12
|
+
- Types: `Md3ButtonGroupProps`, `Md3ButtonGroupItemProps`, `Md3ButtonGroupVariant`, `Md3ButtonGroupSize`, `Md3ButtonGroupShape`, `Md3ButtonGroupSelectionMode`, `Md3ButtonGroupItemVariant`
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @nucleux/md3-button-group @nucleux/tokens
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`react` / `react-dom` are peer dependencies.
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { Md3ButtonGroup, Md3ButtonGroupItem } from "@nucleux/md3-button-group";
|
|
26
|
+
|
|
27
|
+
<Md3ButtonGroup aria-label="Time range" variant="connected" selectionMode="single" defaultValue="week">
|
|
28
|
+
<Md3ButtonGroupItem value="day">Day</Md3ButtonGroupItem>
|
|
29
|
+
<Md3ButtonGroupItem value="week">Week</Md3ButtonGroupItem>
|
|
30
|
+
<Md3ButtonGroupItem value="month">Month</Md3ButtonGroupItem>
|
|
31
|
+
</Md3ButtonGroup>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Requires the theme once in your app: `import "@nucleux/tokens/styles.css";`
|
|
35
|
+
and the Tailwind preset from `@nucleux/tokens/preset`.
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT © Nucleux
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var utils = require('@nucleux/utils');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
|
|
8
|
+
function _interopNamespace(e) {
|
|
9
|
+
if (e && e.__esModule) return e;
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
27
|
+
|
|
28
|
+
// src/index.tsx
|
|
29
|
+
var ButtonGroupContext = React__namespace.createContext(null);
|
|
30
|
+
var asArray = (v) => v === void 0 ? [] : Array.isArray(v) ? v : [v];
|
|
31
|
+
var gaps = {
|
|
32
|
+
xs: "gap-[18px]",
|
|
33
|
+
sm: "gap-3",
|
|
34
|
+
md: "gap-2",
|
|
35
|
+
lg: "gap-2",
|
|
36
|
+
xl: "gap-2"
|
|
37
|
+
};
|
|
38
|
+
var Md3ButtonGroup = React__namespace.forwardRef(
|
|
39
|
+
({
|
|
40
|
+
variant = "standard",
|
|
41
|
+
size = "sm",
|
|
42
|
+
shape = "round",
|
|
43
|
+
buttonVariant = "filled",
|
|
44
|
+
selectionMode = "none",
|
|
45
|
+
selectionRequired = false,
|
|
46
|
+
value,
|
|
47
|
+
defaultValue,
|
|
48
|
+
onValueChange,
|
|
49
|
+
className,
|
|
50
|
+
children,
|
|
51
|
+
...props
|
|
52
|
+
}, ref) => {
|
|
53
|
+
const multiple = selectionMode === "multiple";
|
|
54
|
+
const isControlled = value !== void 0;
|
|
55
|
+
const [internal, setInternal] = React__namespace.useState(asArray(defaultValue));
|
|
56
|
+
const current = isControlled ? asArray(value) : internal;
|
|
57
|
+
const toggle = (v) => {
|
|
58
|
+
let next;
|
|
59
|
+
if (multiple) next = current.includes(v) ? current.filter((x) => x !== v) : [...current, v];
|
|
60
|
+
else next = current[0] === v ? [] : [v];
|
|
61
|
+
if (selectionRequired && next.length === 0) return;
|
|
62
|
+
if (!isControlled) setInternal(next);
|
|
63
|
+
onValueChange?.(multiple ? next : next[0] ?? "");
|
|
64
|
+
};
|
|
65
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
66
|
+
"div",
|
|
67
|
+
{
|
|
68
|
+
ref,
|
|
69
|
+
role: "group",
|
|
70
|
+
className: utils.cn(
|
|
71
|
+
"inline-flex items-center",
|
|
72
|
+
variant === "connected" ? "gap-0.5" : gaps[size],
|
|
73
|
+
className
|
|
74
|
+
),
|
|
75
|
+
...props,
|
|
76
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
77
|
+
ButtonGroupContext.Provider,
|
|
78
|
+
{
|
|
79
|
+
value: {
|
|
80
|
+
variant,
|
|
81
|
+
size,
|
|
82
|
+
shape,
|
|
83
|
+
buttonVariant,
|
|
84
|
+
selectable: selectionMode !== "none",
|
|
85
|
+
value: current,
|
|
86
|
+
toggle
|
|
87
|
+
},
|
|
88
|
+
children
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
Md3ButtonGroup.displayName = "Md3ButtonGroup";
|
|
96
|
+
var sizes = {
|
|
97
|
+
xs: { base: "h-8 gap-1 text-sm [&_svg]:size-5", label: "px-3", labelPressed: "motion-safe:active:px-4", iconOnly: "w-8", iconOnlyPressed: "motion-safe:active:w-[37px]" },
|
|
98
|
+
sm: { base: "h-10 gap-2 text-sm [&_svg]:size-5", label: "px-4", labelPressed: "motion-safe:active:px-5", iconOnly: "w-10", iconOnlyPressed: "motion-safe:active:w-[46px]" },
|
|
99
|
+
md: { base: "h-14 gap-2 text-base [&_svg]:size-6", label: "px-6", labelPressed: "motion-safe:active:px-8", iconOnly: "w-14", iconOnlyPressed: "motion-safe:active:w-16" },
|
|
100
|
+
lg: { base: "h-24 gap-3 text-2xl [&_svg]:size-8", label: "px-12", labelPressed: "motion-safe:active:px-14", iconOnly: "w-24", iconOnlyPressed: "motion-safe:active:w-[110px]" },
|
|
101
|
+
xl: { base: "h-[136px] gap-4 text-[32px] [&_svg]:size-10", label: "px-16", labelPressed: "motion-safe:active:px-[72px]", iconOnly: "w-[136px]", iconOnlyPressed: "motion-safe:active:w-[156px]" }
|
|
102
|
+
};
|
|
103
|
+
var squareRadius = {
|
|
104
|
+
xs: "rounded-md-md",
|
|
105
|
+
sm: "rounded-md-md",
|
|
106
|
+
md: "rounded-md-lg",
|
|
107
|
+
lg: "rounded-md-xl",
|
|
108
|
+
xl: "rounded-md-xl"
|
|
109
|
+
};
|
|
110
|
+
var pressedRadius = {
|
|
111
|
+
xs: "active:rounded-md-sm",
|
|
112
|
+
sm: "active:rounded-md-sm",
|
|
113
|
+
md: "active:rounded-md-md",
|
|
114
|
+
lg: "active:rounded-md-lg",
|
|
115
|
+
xl: "active:rounded-md-lg"
|
|
116
|
+
};
|
|
117
|
+
var innerRadius = {
|
|
118
|
+
xs: "rounded-md-xs",
|
|
119
|
+
sm: "rounded-md-sm",
|
|
120
|
+
md: "rounded-md-sm",
|
|
121
|
+
lg: "rounded-md-lg",
|
|
122
|
+
xl: "rounded-[20px]"
|
|
123
|
+
};
|
|
124
|
+
var outerRadius = {
|
|
125
|
+
round: {
|
|
126
|
+
xs: "first:rounded-l-full last:rounded-r-full",
|
|
127
|
+
sm: "first:rounded-l-full last:rounded-r-full",
|
|
128
|
+
md: "first:rounded-l-full last:rounded-r-full",
|
|
129
|
+
lg: "first:rounded-l-full last:rounded-r-full",
|
|
130
|
+
xl: "first:rounded-l-full last:rounded-r-full"
|
|
131
|
+
},
|
|
132
|
+
square: {
|
|
133
|
+
xs: "first:rounded-l-md-md last:rounded-r-md-md",
|
|
134
|
+
sm: "first:rounded-l-md-md last:rounded-r-md-md",
|
|
135
|
+
md: "first:rounded-l-md-lg last:rounded-r-md-lg",
|
|
136
|
+
lg: "first:rounded-l-md-xl last:rounded-r-md-xl",
|
|
137
|
+
xl: "first:rounded-l-md-xl last:rounded-r-md-xl"
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var actionColors = {
|
|
141
|
+
filled: "bg-md-primary text-md-on-primary hover:shadow-md-1",
|
|
142
|
+
tonal: "bg-md-secondary-container text-md-on-secondary-container hover:shadow-md-1",
|
|
143
|
+
elevated: "bg-md-surface-container-low text-md-primary shadow-md-1 hover:shadow-md-2",
|
|
144
|
+
outlined: "border border-md-outline bg-transparent text-md-primary",
|
|
145
|
+
text: "bg-transparent text-md-primary"
|
|
146
|
+
};
|
|
147
|
+
var toggleColors = {
|
|
148
|
+
filled: ["bg-md-surface-container text-md-on-surface-variant", "bg-md-primary text-md-on-primary"],
|
|
149
|
+
tonal: [
|
|
150
|
+
"bg-md-secondary-container text-md-on-secondary-container",
|
|
151
|
+
"bg-md-secondary text-md-on-secondary"
|
|
152
|
+
],
|
|
153
|
+
elevated: [
|
|
154
|
+
"bg-md-surface-container-low text-md-primary shadow-md-1 hover:shadow-md-2",
|
|
155
|
+
"bg-md-primary text-md-on-primary shadow-md-1 hover:shadow-md-2"
|
|
156
|
+
],
|
|
157
|
+
outlined: [
|
|
158
|
+
"border border-md-outline-variant bg-transparent text-md-on-surface-variant",
|
|
159
|
+
"border border-md-inverse-surface bg-md-inverse-surface text-md-inverse-on-surface"
|
|
160
|
+
],
|
|
161
|
+
text: ["bg-transparent text-md-primary", "bg-md-secondary-container text-md-on-secondary-container"]
|
|
162
|
+
};
|
|
163
|
+
var Md3ButtonGroupItem = React__namespace.forwardRef(
|
|
164
|
+
({ value, variant, icon, className, children, onClick, type = "button", ...props }, ref) => {
|
|
165
|
+
const ctx = React__namespace.useContext(ButtonGroupContext);
|
|
166
|
+
if (!ctx) throw new Error("Md3ButtonGroupItem must be used within a Md3ButtonGroup");
|
|
167
|
+
const toggleable = ctx.selectable && value !== void 0;
|
|
168
|
+
const selected = toggleable && ctx.value.includes(value);
|
|
169
|
+
const iconOnly = icon != null && (children == null || children === false);
|
|
170
|
+
const s = sizes[ctx.size];
|
|
171
|
+
const colorVariant = variant ?? ctx.buttonVariant;
|
|
172
|
+
let shapeClasses;
|
|
173
|
+
if (ctx.variant === "connected") {
|
|
174
|
+
shapeClasses = selected ? "rounded-full" : utils.cn(innerRadius[ctx.size], outerRadius[ctx.shape][ctx.size]);
|
|
175
|
+
} else {
|
|
176
|
+
const round = ctx.shape === "round" !== selected;
|
|
177
|
+
shapeClasses = utils.cn(round ? "rounded-full" : squareRadius[ctx.size], pressedRadius[ctx.size]);
|
|
178
|
+
}
|
|
179
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
180
|
+
"button",
|
|
181
|
+
{
|
|
182
|
+
ref,
|
|
183
|
+
type,
|
|
184
|
+
"aria-pressed": toggleable ? selected : props["aria-pressed"],
|
|
185
|
+
"data-state": toggleable ? selected ? "on" : "off" : void 0,
|
|
186
|
+
onClick: (e) => {
|
|
187
|
+
onClick?.(e);
|
|
188
|
+
if (!e.defaultPrevented && toggleable) ctx.toggle(value);
|
|
189
|
+
},
|
|
190
|
+
className: utils.cn(
|
|
191
|
+
// Layout + typography
|
|
192
|
+
"relative inline-flex shrink-0 items-center justify-center overflow-hidden font-medium",
|
|
193
|
+
s.base,
|
|
194
|
+
iconOnly ? s.iconOnly : s.label,
|
|
195
|
+
// Standard groups widen the pressed button (no movement under reduced motion)
|
|
196
|
+
ctx.variant === "standard" && (iconOnly ? s.iconOnlyPressed : s.labelPressed),
|
|
197
|
+
ctx.variant === "connected" && "flex-1",
|
|
198
|
+
// Shape morph + colour change
|
|
199
|
+
"transition-[border-radius,padding,width,background-color,color,box-shadow] duration-200 ease-out",
|
|
200
|
+
"motion-reduce:transition-[background-color,color,box-shadow]",
|
|
201
|
+
shapeClasses,
|
|
202
|
+
toggleable ? toggleColors[colorVariant][selected ? 1 : 0] : actionColors[colorVariant],
|
|
203
|
+
// State layer (Material 3): on-color overlay at 8% hover / 12% focus+press
|
|
204
|
+
"before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-['']",
|
|
205
|
+
"hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12]",
|
|
206
|
+
// Focus ring + disabled
|
|
207
|
+
"outline-none focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-md-primary focus-visible:ring-offset-2 focus-visible:ring-offset-md-surface",
|
|
208
|
+
"disabled:pointer-events-none disabled:opacity-[0.38] disabled:shadow-none",
|
|
209
|
+
className
|
|
210
|
+
),
|
|
211
|
+
...props,
|
|
212
|
+
children: [
|
|
213
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative inline-flex shrink-0", children: icon }),
|
|
214
|
+
!iconOnly && children != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative", children })
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
Md3ButtonGroupItem.displayName = "Md3ButtonGroupItem";
|
|
221
|
+
|
|
222
|
+
exports.Md3ButtonGroup = Md3ButtonGroup;
|
|
223
|
+
exports.Md3ButtonGroupItem = Md3ButtonGroupItem;
|
|
224
|
+
//# sourceMappingURL=index.cjs.map
|
|
225
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"names":["React","jsx","cn","jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,IAAM,kBAAA,GAA2BA,+BAA8C,IAAI,CAAA;AAsBnF,IAAM,OAAA,GAAU,CAAC,CAAA,KAAsC,CAAA,KAAM,MAAA,GAAY,EAAC,GAAI,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,GAAI,CAAA,GAAI,CAAC,CAAC,CAAA;AAEvG,IAAM,IAAA,GAA2C;AAAA,EAC/C,EAAA,EAAI,YAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAWO,IAAM,cAAA,GAAuBA,gBAAA,CAAA,UAAA;AAAA,EAClC,CACE;AAAA,IACE,OAAA,GAAU,UAAA;AAAA,IACV,IAAA,GAAO,IAAA;AAAA,IACP,KAAA,GAAQ,OAAA;AAAA,IACR,aAAA,GAAgB,QAAA;AAAA,IAChB,aAAA,GAAgB,MAAA;AAAA,IAChB,iBAAA,GAAoB,KAAA;AAAA,IACpB,KAAA;AAAA,IACA,YAAA;AAAA,IACA,aAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,WAAW,aAAA,KAAkB,UAAA;AACnC,IAAA,MAAM,eAAe,KAAA,KAAU,MAAA;AAC/B,IAAA,MAAM,CAAC,QAAA,EAAU,WAAW,IAAUA,gBAAA,CAAA,QAAA,CAAmB,OAAA,CAAQ,YAAY,CAAC,CAAA;AAC9E,IAAA,MAAM,OAAA,GAAU,YAAA,GAAe,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAA;AAEhD,IAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAc;AAC5B,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI,UAAU,IAAA,GAAO,OAAA,CAAQ,QAAA,CAAS,CAAC,IAAI,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,MAAM,CAAC,CAAA,GAAI,CAAC,GAAG,SAAS,CAAC,CAAA;AAAA,WACrF,IAAA,GAAO,QAAQ,CAAC,CAAA,KAAM,IAAI,EAAC,GAAI,CAAC,CAAC,CAAA;AACtC,MAAA,IAAI,iBAAA,IAAqB,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAC5C,MAAA,IAAI,CAAC,YAAA,EAAc,WAAA,CAAY,IAAI,CAAA;AACnC,MAAA,aAAA,GAAgB,QAAA,GAAW,IAAA,GAAQ,IAAA,CAAK,CAAC,KAAK,EAAG,CAAA;AAAA,IACnD,CAAA;AAEA,IAAA,uBACEC,cAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,IAAA,EAAK,OAAA;AAAA,QACL,SAAA,EAAWC,QAAA;AAAA,UACT,0BAAA;AAAA,UACA,OAAA,KAAY,WAAA,GAAc,SAAA,GAAY,IAAA,CAAK,IAAI,CAAA;AAAA,UAC/C;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEJ,QAAA,kBAAAD,cAAA;AAAA,UAAC,kBAAA,CAAmB,QAAA;AAAA,UAAnB;AAAA,YACC,KAAA,EAAO;AAAA,cACL,OAAA;AAAA,cACA,IAAA;AAAA,cACA,KAAA;AAAA,cACA,aAAA;AAAA,cACA,YAAY,aAAA,KAAkB,MAAA;AAAA,cAC9B,KAAA,EAAO,OAAA;AAAA,cACP;AAAA,aACF;AAAA,YAEC;AAAA;AAAA;AACH;AAAA,KACF;AAAA,EAEJ;AACF;AACA,cAAA,CAAe,WAAA,GAAc,gBAAA;AAW7B,IAAM,KAAA,GAGF;AAAA,EACF,EAAA,EAAI,EAAE,IAAA,EAAM,kCAAA,EAAoC,KAAA,EAAO,MAAA,EAAQ,YAAA,EAAc,yBAAA,EAA2B,QAAA,EAAU,KAAA,EAAO,eAAA,EAAiB,6BAAA,EAA8B;AAAA,EACxK,EAAA,EAAI,EAAE,IAAA,EAAM,mCAAA,EAAqC,KAAA,EAAO,MAAA,EAAQ,YAAA,EAAc,yBAAA,EAA2B,QAAA,EAAU,MAAA,EAAQ,eAAA,EAAiB,6BAAA,EAA8B;AAAA,EAC1K,EAAA,EAAI,EAAE,IAAA,EAAM,qCAAA,EAAuC,KAAA,EAAO,MAAA,EAAQ,YAAA,EAAc,yBAAA,EAA2B,QAAA,EAAU,MAAA,EAAQ,eAAA,EAAiB,yBAAA,EAA0B;AAAA,EACxK,EAAA,EAAI,EAAE,IAAA,EAAM,oCAAA,EAAsC,KAAA,EAAO,OAAA,EAAS,YAAA,EAAc,0BAAA,EAA4B,QAAA,EAAU,MAAA,EAAQ,eAAA,EAAiB,8BAAA,EAA+B;AAAA,EAC9K,EAAA,EAAI,EAAE,IAAA,EAAM,6CAAA,EAA+C,KAAA,EAAO,OAAA,EAAS,YAAA,EAAc,8BAAA,EAAgC,QAAA,EAAU,WAAA,EAAa,eAAA,EAAiB,8BAAA;AACnK,CAAA;AAEA,IAAM,YAAA,GAAmD;AAAA,EACvD,EAAA,EAAI,eAAA;AAAA,EACJ,EAAA,EAAI,eAAA;AAAA,EACJ,EAAA,EAAI,eAAA;AAAA,EACJ,EAAA,EAAI,eAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEA,IAAM,aAAA,GAAoD;AAAA,EACxD,EAAA,EAAI,sBAAA;AAAA,EACJ,EAAA,EAAI,sBAAA;AAAA,EACJ,EAAA,EAAI,sBAAA;AAAA,EACJ,EAAA,EAAI,sBAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEA,IAAM,WAAA,GAAkD;AAAA,EACtD,EAAA,EAAI,eAAA;AAAA,EACJ,EAAA,EAAI,eAAA;AAAA,EACJ,EAAA,EAAI,eAAA;AAAA,EACJ,EAAA,EAAI,eAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEA,IAAM,WAAA,GAA+E;AAAA,EACnF,KAAA,EAAO;AAAA,IACL,EAAA,EAAI,0CAAA;AAAA,IACJ,EAAA,EAAI,0CAAA;AAAA,IACJ,EAAA,EAAI,0CAAA;AAAA,IACJ,EAAA,EAAI,0CAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,EAAA,EAAI,4CAAA;AAAA,IACJ,EAAA,EAAI,4CAAA;AAAA,IACJ,EAAA,EAAI,4CAAA;AAAA,IACJ,EAAA,EAAI,4CAAA;AAAA,IACJ,EAAA,EAAI;AAAA;AAER,CAAA;AAGA,IAAM,YAAA,GAA0D;AAAA,EAC9D,MAAA,EAAQ,oDAAA;AAAA,EACR,KAAA,EAAO,4EAAA;AAAA,EACP,QAAA,EAAU,2EAAA;AAAA,EACV,QAAA,EAAU,yDAAA;AAAA,EACV,IAAA,EAAM;AACR,CAAA;AAGA,IAAM,YAAA,GAAoE;AAAA,EACxE,MAAA,EAAQ,CAAC,oDAAA,EAAsD,kCAAkC,CAAA;AAAA,EACjG,KAAA,EAAO;AAAA,IACL,0DAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,2EAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,4EAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,IAAA,EAAM,CAAC,gCAAA,EAAkC,0DAA0D;AACrG,CAAA;AAQO,IAAM,kBAAA,GAA2BD,gBAAA,CAAA,UAAA;AAAA,EACtC,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,IAAA,EAAM,SAAA,EAAW,QAAA,EAAU,OAAA,EAAS,IAAA,GAAO,QAAA,EAAU,GAAG,KAAA,IAAS,GAAA,KAAQ;AAC1F,IAAA,MAAM,GAAA,GAAYA,4BAAW,kBAAkB,CAAA;AAC/C,IAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,yDAAyD,CAAA;AACnF,IAAA,MAAM,UAAA,GAAa,GAAA,CAAI,UAAA,IAAc,KAAA,KAAU,MAAA;AAC/C,IAAA,MAAM,QAAA,GAAW,UAAA,IAAc,GAAA,CAAI,KAAA,CAAM,SAAS,KAAK,CAAA;AACvD,IAAA,MAAM,QAAA,GAAW,IAAA,IAAQ,IAAA,KAAS,QAAA,IAAY,QAAQ,QAAA,KAAa,KAAA,CAAA;AACnE,IAAA,MAAM,CAAA,GAAI,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA;AACxB,IAAA,MAAM,YAAA,GAAe,WAAW,GAAA,CAAI,aAAA;AAEpC,IAAA,IAAI,YAAA;AACJ,IAAA,IAAI,GAAA,CAAI,YAAY,WAAA,EAAa;AAC/B,MAAA,YAAA,GAAe,QAAA,GAAW,cAAA,GAAiBE,QAAA,CAAG,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA,EAAG,WAAA,CAAY,GAAA,CAAI,KAAK,CAAA,CAAE,GAAA,CAAI,IAAI,CAAC,CAAA;AAAA,IACvG,CAAA,MAAO;AAEL,MAAA,MAAM,KAAA,GAAS,GAAA,CAAI,KAAA,KAAU,OAAA,KAAa,QAAA;AAC1C,MAAA,YAAA,GAAeA,QAAA,CAAG,KAAA,GAAQ,cAAA,GAAiB,YAAA,CAAa,GAAA,CAAI,IAAI,CAAA,EAAG,aAAA,CAAc,GAAA,CAAI,IAAI,CAAC,CAAA;AAAA,IAC5F;AAEA,IAAA,uBACEC,eAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,IAAA;AAAA,QACA,cAAA,EAAc,UAAA,GAAa,QAAA,GAAW,KAAA,CAAM,cAAc,CAAA;AAAA,QAC1D,YAAA,EAAY,UAAA,GAAc,QAAA,GAAW,IAAA,GAAO,KAAA,GAAS,MAAA;AAAA,QACrD,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,UAAA,OAAA,GAAU,CAAC,CAAA;AACX,UAAA,IAAI,CAAC,CAAA,CAAE,gBAAA,IAAoB,UAAA,EAAY,GAAA,CAAI,OAAO,KAAK,CAAA;AAAA,QACzD,CAAA;AAAA,QACA,SAAA,EAAWD,QAAA;AAAA;AAAA,UAET,uFAAA;AAAA,UACA,CAAA,CAAE,IAAA;AAAA,UACF,QAAA,GAAW,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,KAAA;AAAA;AAAA,UAE1B,IAAI,OAAA,KAAY,UAAA,KAAe,QAAA,GAAW,CAAA,CAAE,kBAAkB,CAAA,CAAE,YAAA,CAAA;AAAA,UAChE,GAAA,CAAI,YAAY,WAAA,IAAe,QAAA;AAAA;AAAA,UAE/B,kGAAA;AAAA,UACA,8DAAA;AAAA,UACA,YAAA;AAAA,UACA,UAAA,GAAa,aAAa,YAAY,CAAA,CAAE,WAAW,CAAA,GAAI,CAAC,CAAA,GAAI,YAAA,CAAa,YAAY,CAAA;AAAA;AAAA,UAErF,iHAAA;AAAA,UACA,8FAAA;AAAA;AAAA,UAEA,qJAAA;AAAA,UACA,2EAAA;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,IAAA,oBAAQD,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+BAAA,EAAiC,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,UAC9D,CAAC,YAAY,QAAA,IAAY,IAAA,mCAAS,MAAA,EAAA,EAAK,SAAA,EAAU,YAAY,QAAA,EAAS;AAAA;AAAA;AAAA,KACzE;AAAA,EAEJ;AACF;AACA,kBAAA,CAAmB,WAAA,GAAc,oBAAA","file":"index.cjs","sourcesContent":["import * as React from \"react\";\nimport { cn } from \"@nucleux/utils\";\n\nexport type Md3ButtonGroupVariant = \"standard\" | \"connected\";\nexport type Md3ButtonGroupSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\nexport type Md3ButtonGroupShape = \"round\" | \"square\";\nexport type Md3ButtonGroupSelectionMode = \"none\" | \"single\" | \"multiple\";\nexport type Md3ButtonGroupItemVariant = \"filled\" | \"tonal\" | \"elevated\" | \"outlined\" | \"text\";\n\ninterface ButtonGroupContextValue {\n variant: Md3ButtonGroupVariant;\n size: Md3ButtonGroupSize;\n shape: Md3ButtonGroupShape;\n buttonVariant: Md3ButtonGroupItemVariant;\n selectable: boolean;\n value: string[];\n toggle: (v: string) => void;\n}\nconst ButtonGroupContext = React.createContext<ButtonGroupContextValue | null>(null);\n\nexport interface Md3ButtonGroupProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onChange\" | \"defaultValue\"> {\n /** `standard` keeps each button's own shape; `connected` joins them with 2px gaps and small inner corners. */\n variant?: Md3ButtonGroupVariant;\n /** Button size applied to every item: XS 32px, S 40px, M 56px, L 96px, XL 136px tall. */\n size?: Md3ButtonGroupSize;\n /** Default shape of the buttons. Selected toggle buttons morph to the other shape. */\n shape?: Md3ButtonGroupShape;\n /** Colour style applied to items that don't set their own `variant`. */\n buttonVariant?: Md3ButtonGroupItemVariant;\n /** `none` for plain action buttons, `single`/`multiple` to make items with a `value` toggle. */\n selectionMode?: Md3ButtonGroupSelectionMode;\n /** When true, the last selected item can't be deselected. */\n selectionRequired?: boolean;\n value?: string | string[];\n defaultValue?: string | string[];\n /** Called with a string in `single` mode (\"\" when cleared) and a string array in `multiple` mode. */\n onValueChange?: (value: string | string[]) => void;\n}\n\nconst asArray = (v: string | string[] | undefined) => (v === undefined ? [] : Array.isArray(v) ? v : [v]);\n\nconst gaps: Record<Md3ButtonGroupSize, string> = {\n xs: \"gap-[18px]\",\n sm: \"gap-3\",\n md: \"gap-2\",\n lg: \"gap-2\",\n xl: \"gap-2\",\n};\n\n/**\n * A Material 3 Expressive button group: an invisible container that spaces related\n * buttons and adjusts their shape. The `standard` variant keeps each button's shape\n * and widens a button while it is pressed; the `connected` variant (the successor to\n * segmented buttons) joins buttons with 2px gaps, small inner corners and fully\n * rounded outer corners. Set `selectionMode` to turn items with a `value` into\n * single- or multi-select toggle buttons whose shape morphs when selected.\n * Compose with Md3ButtonGroupItem.\n */\nexport const Md3ButtonGroup = React.forwardRef<HTMLDivElement, Md3ButtonGroupProps>(\n (\n {\n variant = \"standard\",\n size = \"sm\",\n shape = \"round\",\n buttonVariant = \"filled\",\n selectionMode = \"none\",\n selectionRequired = false,\n value,\n defaultValue,\n onValueChange,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const multiple = selectionMode === \"multiple\";\n const isControlled = value !== undefined;\n const [internal, setInternal] = React.useState<string[]>(asArray(defaultValue));\n const current = isControlled ? asArray(value) : internal;\n\n const toggle = (v: string) => {\n let next: string[];\n if (multiple) next = current.includes(v) ? current.filter((x) => x !== v) : [...current, v];\n else next = current[0] === v ? [] : [v];\n if (selectionRequired && next.length === 0) return;\n if (!isControlled) setInternal(next);\n onValueChange?.(multiple ? next : (next[0] ?? \"\"));\n };\n\n return (\n <div\n ref={ref}\n role=\"group\"\n className={cn(\n \"inline-flex items-center\",\n variant === \"connected\" ? \"gap-0.5\" : gaps[size],\n className,\n )}\n {...props}\n >\n <ButtonGroupContext.Provider\n value={{\n variant,\n size,\n shape,\n buttonVariant,\n selectable: selectionMode !== \"none\",\n value: current,\n toggle,\n }}\n >\n {children}\n </ButtonGroupContext.Provider>\n </div>\n );\n },\n);\nMd3ButtonGroup.displayName = \"Md3ButtonGroup\";\n\nexport interface Md3ButtonGroupItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Identifies the item for selection. Items without a value act as plain buttons. */\n value?: string;\n /** Colour style; defaults to the group's `buttonVariant`. */\n variant?: Md3ButtonGroupItemVariant;\n /** Leading icon. Pass an icon with no children (and an `aria-label`) for an icon button. */\n icon?: React.ReactNode;\n}\n\nconst sizes: Record<\n Md3ButtonGroupSize,\n { base: string; label: string; labelPressed: string; iconOnly: string; iconOnlyPressed: string }\n> = {\n xs: { base: \"h-8 gap-1 text-sm [&_svg]:size-5\", label: \"px-3\", labelPressed: \"motion-safe:active:px-4\", iconOnly: \"w-8\", iconOnlyPressed: \"motion-safe:active:w-[37px]\" },\n sm: { base: \"h-10 gap-2 text-sm [&_svg]:size-5\", label: \"px-4\", labelPressed: \"motion-safe:active:px-5\", iconOnly: \"w-10\", iconOnlyPressed: \"motion-safe:active:w-[46px]\" },\n md: { base: \"h-14 gap-2 text-base [&_svg]:size-6\", label: \"px-6\", labelPressed: \"motion-safe:active:px-8\", iconOnly: \"w-14\", iconOnlyPressed: \"motion-safe:active:w-16\" },\n lg: { base: \"h-24 gap-3 text-2xl [&_svg]:size-8\", label: \"px-12\", labelPressed: \"motion-safe:active:px-14\", iconOnly: \"w-24\", iconOnlyPressed: \"motion-safe:active:w-[110px]\" },\n xl: { base: \"h-[136px] gap-4 text-[32px] [&_svg]:size-10\", label: \"px-16\", labelPressed: \"motion-safe:active:px-[72px]\", iconOnly: \"w-[136px]\", iconOnlyPressed: \"motion-safe:active:w-[156px]\" },\n};\n\nconst squareRadius: Record<Md3ButtonGroupSize, string> = {\n xs: \"rounded-md-md\",\n sm: \"rounded-md-md\",\n md: \"rounded-md-lg\",\n lg: \"rounded-md-xl\",\n xl: \"rounded-md-xl\",\n};\n\nconst pressedRadius: Record<Md3ButtonGroupSize, string> = {\n xs: \"active:rounded-md-sm\",\n sm: \"active:rounded-md-sm\",\n md: \"active:rounded-md-md\",\n lg: \"active:rounded-md-lg\",\n xl: \"active:rounded-md-lg\",\n};\n\nconst innerRadius: Record<Md3ButtonGroupSize, string> = {\n xs: \"rounded-md-xs\",\n sm: \"rounded-md-sm\",\n md: \"rounded-md-sm\",\n lg: \"rounded-md-lg\",\n xl: \"rounded-[20px]\",\n};\n\nconst outerRadius: Record<Md3ButtonGroupShape, Record<Md3ButtonGroupSize, string>> = {\n round: {\n xs: \"first:rounded-l-full last:rounded-r-full\",\n sm: \"first:rounded-l-full last:rounded-r-full\",\n md: \"first:rounded-l-full last:rounded-r-full\",\n lg: \"first:rounded-l-full last:rounded-r-full\",\n xl: \"first:rounded-l-full last:rounded-r-full\",\n },\n square: {\n xs: \"first:rounded-l-md-md last:rounded-r-md-md\",\n sm: \"first:rounded-l-md-md last:rounded-r-md-md\",\n md: \"first:rounded-l-md-lg last:rounded-r-md-lg\",\n lg: \"first:rounded-l-md-xl last:rounded-r-md-xl\",\n xl: \"first:rounded-l-md-xl last:rounded-r-md-xl\",\n },\n};\n\n/** Colours for plain action buttons (same as Md3Button). */\nconst actionColors: Record<Md3ButtonGroupItemVariant, string> = {\n filled: \"bg-md-primary text-md-on-primary hover:shadow-md-1\",\n tonal: \"bg-md-secondary-container text-md-on-secondary-container hover:shadow-md-1\",\n elevated: \"bg-md-surface-container-low text-md-primary shadow-md-1 hover:shadow-md-2\",\n outlined: \"border border-md-outline bg-transparent text-md-primary\",\n text: \"bg-transparent text-md-primary\",\n};\n\n/** Colours for toggle buttons: [unselected, selected]. */\nconst toggleColors: Record<Md3ButtonGroupItemVariant, [string, string]> = {\n filled: [\"bg-md-surface-container text-md-on-surface-variant\", \"bg-md-primary text-md-on-primary\"],\n tonal: [\n \"bg-md-secondary-container text-md-on-secondary-container\",\n \"bg-md-secondary text-md-on-secondary\",\n ],\n elevated: [\n \"bg-md-surface-container-low text-md-primary shadow-md-1 hover:shadow-md-2\",\n \"bg-md-primary text-md-on-primary shadow-md-1 hover:shadow-md-2\",\n ],\n outlined: [\n \"border border-md-outline-variant bg-transparent text-md-on-surface-variant\",\n \"border border-md-inverse-surface bg-md-inverse-surface text-md-inverse-on-surface\",\n ],\n text: [\"bg-transparent text-md-primary\", \"bg-md-secondary-container text-md-on-secondary-container\"],\n};\n\n/**\n * A button inside a {@link Md3ButtonGroup}. Takes its size and shape from the group;\n * when the group is selectable and the item has a `value`, it is a toggle button\n * exposing `aria-pressed`. Icon-only items (an `icon` and no children) need an\n * `aria-label`.\n */\nexport const Md3ButtonGroupItem = React.forwardRef<HTMLButtonElement, Md3ButtonGroupItemProps>(\n ({ value, variant, icon, className, children, onClick, type = \"button\", ...props }, ref) => {\n const ctx = React.useContext(ButtonGroupContext);\n if (!ctx) throw new Error(\"Md3ButtonGroupItem must be used within a Md3ButtonGroup\");\n const toggleable = ctx.selectable && value !== undefined;\n const selected = toggleable && ctx.value.includes(value);\n const iconOnly = icon != null && (children == null || children === false);\n const s = sizes[ctx.size];\n const colorVariant = variant ?? ctx.buttonVariant;\n\n let shapeClasses: string;\n if (ctx.variant === \"connected\") {\n shapeClasses = selected ? \"rounded-full\" : cn(innerRadius[ctx.size], outerRadius[ctx.shape][ctx.size]);\n } else {\n // Selected toggle buttons morph between round and square.\n const round = (ctx.shape === \"round\") !== selected;\n shapeClasses = cn(round ? \"rounded-full\" : squareRadius[ctx.size], pressedRadius[ctx.size]);\n }\n\n return (\n <button\n ref={ref}\n type={type}\n aria-pressed={toggleable ? selected : props[\"aria-pressed\"]}\n data-state={toggleable ? (selected ? \"on\" : \"off\") : undefined}\n onClick={(e) => {\n onClick?.(e);\n if (!e.defaultPrevented && toggleable) ctx.toggle(value);\n }}\n className={cn(\n // Layout + typography\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden font-medium\",\n s.base,\n iconOnly ? s.iconOnly : s.label,\n // Standard groups widen the pressed button (no movement under reduced motion)\n ctx.variant === \"standard\" && (iconOnly ? s.iconOnlyPressed : s.labelPressed),\n ctx.variant === \"connected\" && \"flex-1\",\n // Shape morph + colour change\n \"transition-[border-radius,padding,width,background-color,color,box-shadow] duration-200 ease-out\",\n \"motion-reduce:transition-[background-color,color,box-shadow]\",\n shapeClasses,\n toggleable ? toggleColors[colorVariant][selected ? 1 : 0] : actionColors[colorVariant],\n // State layer (Material 3): on-color overlay at 8% hover / 12% focus+press\n \"before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-['']\",\n \"hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12]\",\n // Focus ring + disabled\n \"outline-none focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-md-primary focus-visible:ring-offset-2 focus-visible:ring-offset-md-surface\",\n \"disabled:pointer-events-none disabled:opacity-[0.38] disabled:shadow-none\",\n className,\n )}\n {...props}\n >\n {icon && <span className=\"relative inline-flex shrink-0\">{icon}</span>}\n {!iconOnly && children != null && <span className=\"relative\">{children}</span>}\n </button>\n );\n },\n);\nMd3ButtonGroupItem.displayName = \"Md3ButtonGroupItem\";\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
type Md3ButtonGroupVariant = "standard" | "connected";
|
|
4
|
+
type Md3ButtonGroupSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
5
|
+
type Md3ButtonGroupShape = "round" | "square";
|
|
6
|
+
type Md3ButtonGroupSelectionMode = "none" | "single" | "multiple";
|
|
7
|
+
type Md3ButtonGroupItemVariant = "filled" | "tonal" | "elevated" | "outlined" | "text";
|
|
8
|
+
interface Md3ButtonGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
|
|
9
|
+
/** `standard` keeps each button's own shape; `connected` joins them with 2px gaps and small inner corners. */
|
|
10
|
+
variant?: Md3ButtonGroupVariant;
|
|
11
|
+
/** Button size applied to every item: XS 32px, S 40px, M 56px, L 96px, XL 136px tall. */
|
|
12
|
+
size?: Md3ButtonGroupSize;
|
|
13
|
+
/** Default shape of the buttons. Selected toggle buttons morph to the other shape. */
|
|
14
|
+
shape?: Md3ButtonGroupShape;
|
|
15
|
+
/** Colour style applied to items that don't set their own `variant`. */
|
|
16
|
+
buttonVariant?: Md3ButtonGroupItemVariant;
|
|
17
|
+
/** `none` for plain action buttons, `single`/`multiple` to make items with a `value` toggle. */
|
|
18
|
+
selectionMode?: Md3ButtonGroupSelectionMode;
|
|
19
|
+
/** When true, the last selected item can't be deselected. */
|
|
20
|
+
selectionRequired?: boolean;
|
|
21
|
+
value?: string | string[];
|
|
22
|
+
defaultValue?: string | string[];
|
|
23
|
+
/** Called with a string in `single` mode ("" when cleared) and a string array in `multiple` mode. */
|
|
24
|
+
onValueChange?: (value: string | string[]) => void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A Material 3 Expressive button group: an invisible container that spaces related
|
|
28
|
+
* buttons and adjusts their shape. The `standard` variant keeps each button's shape
|
|
29
|
+
* and widens a button while it is pressed; the `connected` variant (the successor to
|
|
30
|
+
* segmented buttons) joins buttons with 2px gaps, small inner corners and fully
|
|
31
|
+
* rounded outer corners. Set `selectionMode` to turn items with a `value` into
|
|
32
|
+
* single- or multi-select toggle buttons whose shape morphs when selected.
|
|
33
|
+
* Compose with Md3ButtonGroupItem.
|
|
34
|
+
*/
|
|
35
|
+
declare const Md3ButtonGroup: React.ForwardRefExoticComponent<Md3ButtonGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
36
|
+
interface Md3ButtonGroupItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
37
|
+
/** Identifies the item for selection. Items without a value act as plain buttons. */
|
|
38
|
+
value?: string;
|
|
39
|
+
/** Colour style; defaults to the group's `buttonVariant`. */
|
|
40
|
+
variant?: Md3ButtonGroupItemVariant;
|
|
41
|
+
/** Leading icon. Pass an icon with no children (and an `aria-label`) for an icon button. */
|
|
42
|
+
icon?: React.ReactNode;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A button inside a {@link Md3ButtonGroup}. Takes its size and shape from the group;
|
|
46
|
+
* when the group is selectable and the item has a `value`, it is a toggle button
|
|
47
|
+
* exposing `aria-pressed`. Icon-only items (an `icon` and no children) need an
|
|
48
|
+
* `aria-label`.
|
|
49
|
+
*/
|
|
50
|
+
declare const Md3ButtonGroupItem: React.ForwardRefExoticComponent<Md3ButtonGroupItemProps & React.RefAttributes<HTMLButtonElement>>;
|
|
51
|
+
|
|
52
|
+
export { Md3ButtonGroup, Md3ButtonGroupItem, type Md3ButtonGroupItemProps, type Md3ButtonGroupItemVariant, type Md3ButtonGroupProps, type Md3ButtonGroupSelectionMode, type Md3ButtonGroupShape, type Md3ButtonGroupSize, type Md3ButtonGroupVariant };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
type Md3ButtonGroupVariant = "standard" | "connected";
|
|
4
|
+
type Md3ButtonGroupSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
5
|
+
type Md3ButtonGroupShape = "round" | "square";
|
|
6
|
+
type Md3ButtonGroupSelectionMode = "none" | "single" | "multiple";
|
|
7
|
+
type Md3ButtonGroupItemVariant = "filled" | "tonal" | "elevated" | "outlined" | "text";
|
|
8
|
+
interface Md3ButtonGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
|
|
9
|
+
/** `standard` keeps each button's own shape; `connected` joins them with 2px gaps and small inner corners. */
|
|
10
|
+
variant?: Md3ButtonGroupVariant;
|
|
11
|
+
/** Button size applied to every item: XS 32px, S 40px, M 56px, L 96px, XL 136px tall. */
|
|
12
|
+
size?: Md3ButtonGroupSize;
|
|
13
|
+
/** Default shape of the buttons. Selected toggle buttons morph to the other shape. */
|
|
14
|
+
shape?: Md3ButtonGroupShape;
|
|
15
|
+
/** Colour style applied to items that don't set their own `variant`. */
|
|
16
|
+
buttonVariant?: Md3ButtonGroupItemVariant;
|
|
17
|
+
/** `none` for plain action buttons, `single`/`multiple` to make items with a `value` toggle. */
|
|
18
|
+
selectionMode?: Md3ButtonGroupSelectionMode;
|
|
19
|
+
/** When true, the last selected item can't be deselected. */
|
|
20
|
+
selectionRequired?: boolean;
|
|
21
|
+
value?: string | string[];
|
|
22
|
+
defaultValue?: string | string[];
|
|
23
|
+
/** Called with a string in `single` mode ("" when cleared) and a string array in `multiple` mode. */
|
|
24
|
+
onValueChange?: (value: string | string[]) => void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A Material 3 Expressive button group: an invisible container that spaces related
|
|
28
|
+
* buttons and adjusts their shape. The `standard` variant keeps each button's shape
|
|
29
|
+
* and widens a button while it is pressed; the `connected` variant (the successor to
|
|
30
|
+
* segmented buttons) joins buttons with 2px gaps, small inner corners and fully
|
|
31
|
+
* rounded outer corners. Set `selectionMode` to turn items with a `value` into
|
|
32
|
+
* single- or multi-select toggle buttons whose shape morphs when selected.
|
|
33
|
+
* Compose with Md3ButtonGroupItem.
|
|
34
|
+
*/
|
|
35
|
+
declare const Md3ButtonGroup: React.ForwardRefExoticComponent<Md3ButtonGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
36
|
+
interface Md3ButtonGroupItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
37
|
+
/** Identifies the item for selection. Items without a value act as plain buttons. */
|
|
38
|
+
value?: string;
|
|
39
|
+
/** Colour style; defaults to the group's `buttonVariant`. */
|
|
40
|
+
variant?: Md3ButtonGroupItemVariant;
|
|
41
|
+
/** Leading icon. Pass an icon with no children (and an `aria-label`) for an icon button. */
|
|
42
|
+
icon?: React.ReactNode;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A button inside a {@link Md3ButtonGroup}. Takes its size and shape from the group;
|
|
46
|
+
* when the group is selectable and the item has a `value`, it is a toggle button
|
|
47
|
+
* exposing `aria-pressed`. Icon-only items (an `icon` and no children) need an
|
|
48
|
+
* `aria-label`.
|
|
49
|
+
*/
|
|
50
|
+
declare const Md3ButtonGroupItem: React.ForwardRefExoticComponent<Md3ButtonGroupItemProps & React.RefAttributes<HTMLButtonElement>>;
|
|
51
|
+
|
|
52
|
+
export { Md3ButtonGroup, Md3ButtonGroupItem, type Md3ButtonGroupItemProps, type Md3ButtonGroupItemVariant, type Md3ButtonGroupProps, type Md3ButtonGroupSelectionMode, type Md3ButtonGroupShape, type Md3ButtonGroupSize, type Md3ButtonGroupVariant };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { cn } from '@nucleux/utils';
|
|
4
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/index.tsx
|
|
7
|
+
var ButtonGroupContext = React.createContext(null);
|
|
8
|
+
var asArray = (v) => v === void 0 ? [] : Array.isArray(v) ? v : [v];
|
|
9
|
+
var gaps = {
|
|
10
|
+
xs: "gap-[18px]",
|
|
11
|
+
sm: "gap-3",
|
|
12
|
+
md: "gap-2",
|
|
13
|
+
lg: "gap-2",
|
|
14
|
+
xl: "gap-2"
|
|
15
|
+
};
|
|
16
|
+
var Md3ButtonGroup = React.forwardRef(
|
|
17
|
+
({
|
|
18
|
+
variant = "standard",
|
|
19
|
+
size = "sm",
|
|
20
|
+
shape = "round",
|
|
21
|
+
buttonVariant = "filled",
|
|
22
|
+
selectionMode = "none",
|
|
23
|
+
selectionRequired = false,
|
|
24
|
+
value,
|
|
25
|
+
defaultValue,
|
|
26
|
+
onValueChange,
|
|
27
|
+
className,
|
|
28
|
+
children,
|
|
29
|
+
...props
|
|
30
|
+
}, ref) => {
|
|
31
|
+
const multiple = selectionMode === "multiple";
|
|
32
|
+
const isControlled = value !== void 0;
|
|
33
|
+
const [internal, setInternal] = React.useState(asArray(defaultValue));
|
|
34
|
+
const current = isControlled ? asArray(value) : internal;
|
|
35
|
+
const toggle = (v) => {
|
|
36
|
+
let next;
|
|
37
|
+
if (multiple) next = current.includes(v) ? current.filter((x) => x !== v) : [...current, v];
|
|
38
|
+
else next = current[0] === v ? [] : [v];
|
|
39
|
+
if (selectionRequired && next.length === 0) return;
|
|
40
|
+
if (!isControlled) setInternal(next);
|
|
41
|
+
onValueChange?.(multiple ? next : next[0] ?? "");
|
|
42
|
+
};
|
|
43
|
+
return /* @__PURE__ */ jsx(
|
|
44
|
+
"div",
|
|
45
|
+
{
|
|
46
|
+
ref,
|
|
47
|
+
role: "group",
|
|
48
|
+
className: cn(
|
|
49
|
+
"inline-flex items-center",
|
|
50
|
+
variant === "connected" ? "gap-0.5" : gaps[size],
|
|
51
|
+
className
|
|
52
|
+
),
|
|
53
|
+
...props,
|
|
54
|
+
children: /* @__PURE__ */ jsx(
|
|
55
|
+
ButtonGroupContext.Provider,
|
|
56
|
+
{
|
|
57
|
+
value: {
|
|
58
|
+
variant,
|
|
59
|
+
size,
|
|
60
|
+
shape,
|
|
61
|
+
buttonVariant,
|
|
62
|
+
selectable: selectionMode !== "none",
|
|
63
|
+
value: current,
|
|
64
|
+
toggle
|
|
65
|
+
},
|
|
66
|
+
children
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
Md3ButtonGroup.displayName = "Md3ButtonGroup";
|
|
74
|
+
var sizes = {
|
|
75
|
+
xs: { base: "h-8 gap-1 text-sm [&_svg]:size-5", label: "px-3", labelPressed: "motion-safe:active:px-4", iconOnly: "w-8", iconOnlyPressed: "motion-safe:active:w-[37px]" },
|
|
76
|
+
sm: { base: "h-10 gap-2 text-sm [&_svg]:size-5", label: "px-4", labelPressed: "motion-safe:active:px-5", iconOnly: "w-10", iconOnlyPressed: "motion-safe:active:w-[46px]" },
|
|
77
|
+
md: { base: "h-14 gap-2 text-base [&_svg]:size-6", label: "px-6", labelPressed: "motion-safe:active:px-8", iconOnly: "w-14", iconOnlyPressed: "motion-safe:active:w-16" },
|
|
78
|
+
lg: { base: "h-24 gap-3 text-2xl [&_svg]:size-8", label: "px-12", labelPressed: "motion-safe:active:px-14", iconOnly: "w-24", iconOnlyPressed: "motion-safe:active:w-[110px]" },
|
|
79
|
+
xl: { base: "h-[136px] gap-4 text-[32px] [&_svg]:size-10", label: "px-16", labelPressed: "motion-safe:active:px-[72px]", iconOnly: "w-[136px]", iconOnlyPressed: "motion-safe:active:w-[156px]" }
|
|
80
|
+
};
|
|
81
|
+
var squareRadius = {
|
|
82
|
+
xs: "rounded-md-md",
|
|
83
|
+
sm: "rounded-md-md",
|
|
84
|
+
md: "rounded-md-lg",
|
|
85
|
+
lg: "rounded-md-xl",
|
|
86
|
+
xl: "rounded-md-xl"
|
|
87
|
+
};
|
|
88
|
+
var pressedRadius = {
|
|
89
|
+
xs: "active:rounded-md-sm",
|
|
90
|
+
sm: "active:rounded-md-sm",
|
|
91
|
+
md: "active:rounded-md-md",
|
|
92
|
+
lg: "active:rounded-md-lg",
|
|
93
|
+
xl: "active:rounded-md-lg"
|
|
94
|
+
};
|
|
95
|
+
var innerRadius = {
|
|
96
|
+
xs: "rounded-md-xs",
|
|
97
|
+
sm: "rounded-md-sm",
|
|
98
|
+
md: "rounded-md-sm",
|
|
99
|
+
lg: "rounded-md-lg",
|
|
100
|
+
xl: "rounded-[20px]"
|
|
101
|
+
};
|
|
102
|
+
var outerRadius = {
|
|
103
|
+
round: {
|
|
104
|
+
xs: "first:rounded-l-full last:rounded-r-full",
|
|
105
|
+
sm: "first:rounded-l-full last:rounded-r-full",
|
|
106
|
+
md: "first:rounded-l-full last:rounded-r-full",
|
|
107
|
+
lg: "first:rounded-l-full last:rounded-r-full",
|
|
108
|
+
xl: "first:rounded-l-full last:rounded-r-full"
|
|
109
|
+
},
|
|
110
|
+
square: {
|
|
111
|
+
xs: "first:rounded-l-md-md last:rounded-r-md-md",
|
|
112
|
+
sm: "first:rounded-l-md-md last:rounded-r-md-md",
|
|
113
|
+
md: "first:rounded-l-md-lg last:rounded-r-md-lg",
|
|
114
|
+
lg: "first:rounded-l-md-xl last:rounded-r-md-xl",
|
|
115
|
+
xl: "first:rounded-l-md-xl last:rounded-r-md-xl"
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
var actionColors = {
|
|
119
|
+
filled: "bg-md-primary text-md-on-primary hover:shadow-md-1",
|
|
120
|
+
tonal: "bg-md-secondary-container text-md-on-secondary-container hover:shadow-md-1",
|
|
121
|
+
elevated: "bg-md-surface-container-low text-md-primary shadow-md-1 hover:shadow-md-2",
|
|
122
|
+
outlined: "border border-md-outline bg-transparent text-md-primary",
|
|
123
|
+
text: "bg-transparent text-md-primary"
|
|
124
|
+
};
|
|
125
|
+
var toggleColors = {
|
|
126
|
+
filled: ["bg-md-surface-container text-md-on-surface-variant", "bg-md-primary text-md-on-primary"],
|
|
127
|
+
tonal: [
|
|
128
|
+
"bg-md-secondary-container text-md-on-secondary-container",
|
|
129
|
+
"bg-md-secondary text-md-on-secondary"
|
|
130
|
+
],
|
|
131
|
+
elevated: [
|
|
132
|
+
"bg-md-surface-container-low text-md-primary shadow-md-1 hover:shadow-md-2",
|
|
133
|
+
"bg-md-primary text-md-on-primary shadow-md-1 hover:shadow-md-2"
|
|
134
|
+
],
|
|
135
|
+
outlined: [
|
|
136
|
+
"border border-md-outline-variant bg-transparent text-md-on-surface-variant",
|
|
137
|
+
"border border-md-inverse-surface bg-md-inverse-surface text-md-inverse-on-surface"
|
|
138
|
+
],
|
|
139
|
+
text: ["bg-transparent text-md-primary", "bg-md-secondary-container text-md-on-secondary-container"]
|
|
140
|
+
};
|
|
141
|
+
var Md3ButtonGroupItem = React.forwardRef(
|
|
142
|
+
({ value, variant, icon, className, children, onClick, type = "button", ...props }, ref) => {
|
|
143
|
+
const ctx = React.useContext(ButtonGroupContext);
|
|
144
|
+
if (!ctx) throw new Error("Md3ButtonGroupItem must be used within a Md3ButtonGroup");
|
|
145
|
+
const toggleable = ctx.selectable && value !== void 0;
|
|
146
|
+
const selected = toggleable && ctx.value.includes(value);
|
|
147
|
+
const iconOnly = icon != null && (children == null || children === false);
|
|
148
|
+
const s = sizes[ctx.size];
|
|
149
|
+
const colorVariant = variant ?? ctx.buttonVariant;
|
|
150
|
+
let shapeClasses;
|
|
151
|
+
if (ctx.variant === "connected") {
|
|
152
|
+
shapeClasses = selected ? "rounded-full" : cn(innerRadius[ctx.size], outerRadius[ctx.shape][ctx.size]);
|
|
153
|
+
} else {
|
|
154
|
+
const round = ctx.shape === "round" !== selected;
|
|
155
|
+
shapeClasses = cn(round ? "rounded-full" : squareRadius[ctx.size], pressedRadius[ctx.size]);
|
|
156
|
+
}
|
|
157
|
+
return /* @__PURE__ */ jsxs(
|
|
158
|
+
"button",
|
|
159
|
+
{
|
|
160
|
+
ref,
|
|
161
|
+
type,
|
|
162
|
+
"aria-pressed": toggleable ? selected : props["aria-pressed"],
|
|
163
|
+
"data-state": toggleable ? selected ? "on" : "off" : void 0,
|
|
164
|
+
onClick: (e) => {
|
|
165
|
+
onClick?.(e);
|
|
166
|
+
if (!e.defaultPrevented && toggleable) ctx.toggle(value);
|
|
167
|
+
},
|
|
168
|
+
className: cn(
|
|
169
|
+
// Layout + typography
|
|
170
|
+
"relative inline-flex shrink-0 items-center justify-center overflow-hidden font-medium",
|
|
171
|
+
s.base,
|
|
172
|
+
iconOnly ? s.iconOnly : s.label,
|
|
173
|
+
// Standard groups widen the pressed button (no movement under reduced motion)
|
|
174
|
+
ctx.variant === "standard" && (iconOnly ? s.iconOnlyPressed : s.labelPressed),
|
|
175
|
+
ctx.variant === "connected" && "flex-1",
|
|
176
|
+
// Shape morph + colour change
|
|
177
|
+
"transition-[border-radius,padding,width,background-color,color,box-shadow] duration-200 ease-out",
|
|
178
|
+
"motion-reduce:transition-[background-color,color,box-shadow]",
|
|
179
|
+
shapeClasses,
|
|
180
|
+
toggleable ? toggleColors[colorVariant][selected ? 1 : 0] : actionColors[colorVariant],
|
|
181
|
+
// State layer (Material 3): on-color overlay at 8% hover / 12% focus+press
|
|
182
|
+
"before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-['']",
|
|
183
|
+
"hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12]",
|
|
184
|
+
// Focus ring + disabled
|
|
185
|
+
"outline-none focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-md-primary focus-visible:ring-offset-2 focus-visible:ring-offset-md-surface",
|
|
186
|
+
"disabled:pointer-events-none disabled:opacity-[0.38] disabled:shadow-none",
|
|
187
|
+
className
|
|
188
|
+
),
|
|
189
|
+
...props,
|
|
190
|
+
children: [
|
|
191
|
+
icon && /* @__PURE__ */ jsx("span", { className: "relative inline-flex shrink-0", children: icon }),
|
|
192
|
+
!iconOnly && children != null && /* @__PURE__ */ jsx("span", { className: "relative", children })
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
Md3ButtonGroupItem.displayName = "Md3ButtonGroupItem";
|
|
199
|
+
|
|
200
|
+
export { Md3ButtonGroup, Md3ButtonGroupItem };
|
|
201
|
+
//# sourceMappingURL=index.js.map
|
|
202
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import * as React from \"react\";\nimport { cn } from \"@nucleux/utils\";\n\nexport type Md3ButtonGroupVariant = \"standard\" | \"connected\";\nexport type Md3ButtonGroupSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\nexport type Md3ButtonGroupShape = \"round\" | \"square\";\nexport type Md3ButtonGroupSelectionMode = \"none\" | \"single\" | \"multiple\";\nexport type Md3ButtonGroupItemVariant = \"filled\" | \"tonal\" | \"elevated\" | \"outlined\" | \"text\";\n\ninterface ButtonGroupContextValue {\n variant: Md3ButtonGroupVariant;\n size: Md3ButtonGroupSize;\n shape: Md3ButtonGroupShape;\n buttonVariant: Md3ButtonGroupItemVariant;\n selectable: boolean;\n value: string[];\n toggle: (v: string) => void;\n}\nconst ButtonGroupContext = React.createContext<ButtonGroupContextValue | null>(null);\n\nexport interface Md3ButtonGroupProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onChange\" | \"defaultValue\"> {\n /** `standard` keeps each button's own shape; `connected` joins them with 2px gaps and small inner corners. */\n variant?: Md3ButtonGroupVariant;\n /** Button size applied to every item: XS 32px, S 40px, M 56px, L 96px, XL 136px tall. */\n size?: Md3ButtonGroupSize;\n /** Default shape of the buttons. Selected toggle buttons morph to the other shape. */\n shape?: Md3ButtonGroupShape;\n /** Colour style applied to items that don't set their own `variant`. */\n buttonVariant?: Md3ButtonGroupItemVariant;\n /** `none` for plain action buttons, `single`/`multiple` to make items with a `value` toggle. */\n selectionMode?: Md3ButtonGroupSelectionMode;\n /** When true, the last selected item can't be deselected. */\n selectionRequired?: boolean;\n value?: string | string[];\n defaultValue?: string | string[];\n /** Called with a string in `single` mode (\"\" when cleared) and a string array in `multiple` mode. */\n onValueChange?: (value: string | string[]) => void;\n}\n\nconst asArray = (v: string | string[] | undefined) => (v === undefined ? [] : Array.isArray(v) ? v : [v]);\n\nconst gaps: Record<Md3ButtonGroupSize, string> = {\n xs: \"gap-[18px]\",\n sm: \"gap-3\",\n md: \"gap-2\",\n lg: \"gap-2\",\n xl: \"gap-2\",\n};\n\n/**\n * A Material 3 Expressive button group: an invisible container that spaces related\n * buttons and adjusts their shape. The `standard` variant keeps each button's shape\n * and widens a button while it is pressed; the `connected` variant (the successor to\n * segmented buttons) joins buttons with 2px gaps, small inner corners and fully\n * rounded outer corners. Set `selectionMode` to turn items with a `value` into\n * single- or multi-select toggle buttons whose shape morphs when selected.\n * Compose with Md3ButtonGroupItem.\n */\nexport const Md3ButtonGroup = React.forwardRef<HTMLDivElement, Md3ButtonGroupProps>(\n (\n {\n variant = \"standard\",\n size = \"sm\",\n shape = \"round\",\n buttonVariant = \"filled\",\n selectionMode = \"none\",\n selectionRequired = false,\n value,\n defaultValue,\n onValueChange,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const multiple = selectionMode === \"multiple\";\n const isControlled = value !== undefined;\n const [internal, setInternal] = React.useState<string[]>(asArray(defaultValue));\n const current = isControlled ? asArray(value) : internal;\n\n const toggle = (v: string) => {\n let next: string[];\n if (multiple) next = current.includes(v) ? current.filter((x) => x !== v) : [...current, v];\n else next = current[0] === v ? [] : [v];\n if (selectionRequired && next.length === 0) return;\n if (!isControlled) setInternal(next);\n onValueChange?.(multiple ? next : (next[0] ?? \"\"));\n };\n\n return (\n <div\n ref={ref}\n role=\"group\"\n className={cn(\n \"inline-flex items-center\",\n variant === \"connected\" ? \"gap-0.5\" : gaps[size],\n className,\n )}\n {...props}\n >\n <ButtonGroupContext.Provider\n value={{\n variant,\n size,\n shape,\n buttonVariant,\n selectable: selectionMode !== \"none\",\n value: current,\n toggle,\n }}\n >\n {children}\n </ButtonGroupContext.Provider>\n </div>\n );\n },\n);\nMd3ButtonGroup.displayName = \"Md3ButtonGroup\";\n\nexport interface Md3ButtonGroupItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Identifies the item for selection. Items without a value act as plain buttons. */\n value?: string;\n /** Colour style; defaults to the group's `buttonVariant`. */\n variant?: Md3ButtonGroupItemVariant;\n /** Leading icon. Pass an icon with no children (and an `aria-label`) for an icon button. */\n icon?: React.ReactNode;\n}\n\nconst sizes: Record<\n Md3ButtonGroupSize,\n { base: string; label: string; labelPressed: string; iconOnly: string; iconOnlyPressed: string }\n> = {\n xs: { base: \"h-8 gap-1 text-sm [&_svg]:size-5\", label: \"px-3\", labelPressed: \"motion-safe:active:px-4\", iconOnly: \"w-8\", iconOnlyPressed: \"motion-safe:active:w-[37px]\" },\n sm: { base: \"h-10 gap-2 text-sm [&_svg]:size-5\", label: \"px-4\", labelPressed: \"motion-safe:active:px-5\", iconOnly: \"w-10\", iconOnlyPressed: \"motion-safe:active:w-[46px]\" },\n md: { base: \"h-14 gap-2 text-base [&_svg]:size-6\", label: \"px-6\", labelPressed: \"motion-safe:active:px-8\", iconOnly: \"w-14\", iconOnlyPressed: \"motion-safe:active:w-16\" },\n lg: { base: \"h-24 gap-3 text-2xl [&_svg]:size-8\", label: \"px-12\", labelPressed: \"motion-safe:active:px-14\", iconOnly: \"w-24\", iconOnlyPressed: \"motion-safe:active:w-[110px]\" },\n xl: { base: \"h-[136px] gap-4 text-[32px] [&_svg]:size-10\", label: \"px-16\", labelPressed: \"motion-safe:active:px-[72px]\", iconOnly: \"w-[136px]\", iconOnlyPressed: \"motion-safe:active:w-[156px]\" },\n};\n\nconst squareRadius: Record<Md3ButtonGroupSize, string> = {\n xs: \"rounded-md-md\",\n sm: \"rounded-md-md\",\n md: \"rounded-md-lg\",\n lg: \"rounded-md-xl\",\n xl: \"rounded-md-xl\",\n};\n\nconst pressedRadius: Record<Md3ButtonGroupSize, string> = {\n xs: \"active:rounded-md-sm\",\n sm: \"active:rounded-md-sm\",\n md: \"active:rounded-md-md\",\n lg: \"active:rounded-md-lg\",\n xl: \"active:rounded-md-lg\",\n};\n\nconst innerRadius: Record<Md3ButtonGroupSize, string> = {\n xs: \"rounded-md-xs\",\n sm: \"rounded-md-sm\",\n md: \"rounded-md-sm\",\n lg: \"rounded-md-lg\",\n xl: \"rounded-[20px]\",\n};\n\nconst outerRadius: Record<Md3ButtonGroupShape, Record<Md3ButtonGroupSize, string>> = {\n round: {\n xs: \"first:rounded-l-full last:rounded-r-full\",\n sm: \"first:rounded-l-full last:rounded-r-full\",\n md: \"first:rounded-l-full last:rounded-r-full\",\n lg: \"first:rounded-l-full last:rounded-r-full\",\n xl: \"first:rounded-l-full last:rounded-r-full\",\n },\n square: {\n xs: \"first:rounded-l-md-md last:rounded-r-md-md\",\n sm: \"first:rounded-l-md-md last:rounded-r-md-md\",\n md: \"first:rounded-l-md-lg last:rounded-r-md-lg\",\n lg: \"first:rounded-l-md-xl last:rounded-r-md-xl\",\n xl: \"first:rounded-l-md-xl last:rounded-r-md-xl\",\n },\n};\n\n/** Colours for plain action buttons (same as Md3Button). */\nconst actionColors: Record<Md3ButtonGroupItemVariant, string> = {\n filled: \"bg-md-primary text-md-on-primary hover:shadow-md-1\",\n tonal: \"bg-md-secondary-container text-md-on-secondary-container hover:shadow-md-1\",\n elevated: \"bg-md-surface-container-low text-md-primary shadow-md-1 hover:shadow-md-2\",\n outlined: \"border border-md-outline bg-transparent text-md-primary\",\n text: \"bg-transparent text-md-primary\",\n};\n\n/** Colours for toggle buttons: [unselected, selected]. */\nconst toggleColors: Record<Md3ButtonGroupItemVariant, [string, string]> = {\n filled: [\"bg-md-surface-container text-md-on-surface-variant\", \"bg-md-primary text-md-on-primary\"],\n tonal: [\n \"bg-md-secondary-container text-md-on-secondary-container\",\n \"bg-md-secondary text-md-on-secondary\",\n ],\n elevated: [\n \"bg-md-surface-container-low text-md-primary shadow-md-1 hover:shadow-md-2\",\n \"bg-md-primary text-md-on-primary shadow-md-1 hover:shadow-md-2\",\n ],\n outlined: [\n \"border border-md-outline-variant bg-transparent text-md-on-surface-variant\",\n \"border border-md-inverse-surface bg-md-inverse-surface text-md-inverse-on-surface\",\n ],\n text: [\"bg-transparent text-md-primary\", \"bg-md-secondary-container text-md-on-secondary-container\"],\n};\n\n/**\n * A button inside a {@link Md3ButtonGroup}. Takes its size and shape from the group;\n * when the group is selectable and the item has a `value`, it is a toggle button\n * exposing `aria-pressed`. Icon-only items (an `icon` and no children) need an\n * `aria-label`.\n */\nexport const Md3ButtonGroupItem = React.forwardRef<HTMLButtonElement, Md3ButtonGroupItemProps>(\n ({ value, variant, icon, className, children, onClick, type = \"button\", ...props }, ref) => {\n const ctx = React.useContext(ButtonGroupContext);\n if (!ctx) throw new Error(\"Md3ButtonGroupItem must be used within a Md3ButtonGroup\");\n const toggleable = ctx.selectable && value !== undefined;\n const selected = toggleable && ctx.value.includes(value);\n const iconOnly = icon != null && (children == null || children === false);\n const s = sizes[ctx.size];\n const colorVariant = variant ?? ctx.buttonVariant;\n\n let shapeClasses: string;\n if (ctx.variant === \"connected\") {\n shapeClasses = selected ? \"rounded-full\" : cn(innerRadius[ctx.size], outerRadius[ctx.shape][ctx.size]);\n } else {\n // Selected toggle buttons morph between round and square.\n const round = (ctx.shape === \"round\") !== selected;\n shapeClasses = cn(round ? \"rounded-full\" : squareRadius[ctx.size], pressedRadius[ctx.size]);\n }\n\n return (\n <button\n ref={ref}\n type={type}\n aria-pressed={toggleable ? selected : props[\"aria-pressed\"]}\n data-state={toggleable ? (selected ? \"on\" : \"off\") : undefined}\n onClick={(e) => {\n onClick?.(e);\n if (!e.defaultPrevented && toggleable) ctx.toggle(value);\n }}\n className={cn(\n // Layout + typography\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden font-medium\",\n s.base,\n iconOnly ? s.iconOnly : s.label,\n // Standard groups widen the pressed button (no movement under reduced motion)\n ctx.variant === \"standard\" && (iconOnly ? s.iconOnlyPressed : s.labelPressed),\n ctx.variant === \"connected\" && \"flex-1\",\n // Shape morph + colour change\n \"transition-[border-radius,padding,width,background-color,color,box-shadow] duration-200 ease-out\",\n \"motion-reduce:transition-[background-color,color,box-shadow]\",\n shapeClasses,\n toggleable ? toggleColors[colorVariant][selected ? 1 : 0] : actionColors[colorVariant],\n // State layer (Material 3): on-color overlay at 8% hover / 12% focus+press\n \"before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-['']\",\n \"hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12]\",\n // Focus ring + disabled\n \"outline-none focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-md-primary focus-visible:ring-offset-2 focus-visible:ring-offset-md-surface\",\n \"disabled:pointer-events-none disabled:opacity-[0.38] disabled:shadow-none\",\n className,\n )}\n {...props}\n >\n {icon && <span className=\"relative inline-flex shrink-0\">{icon}</span>}\n {!iconOnly && children != null && <span className=\"relative\">{children}</span>}\n </button>\n );\n },\n);\nMd3ButtonGroupItem.displayName = \"Md3ButtonGroupItem\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nucleux/md3-button-group",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"description": "Material 3 button group — Nucleux agentic UI for React.",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"nucleux",
|
|
9
|
+
"react",
|
|
10
|
+
"ui",
|
|
11
|
+
"components",
|
|
12
|
+
"agentic",
|
|
13
|
+
"ai",
|
|
14
|
+
"tailwind",
|
|
15
|
+
"md3",
|
|
16
|
+
"material",
|
|
17
|
+
"button-group",
|
|
18
|
+
"md3-button-group"
|
|
19
|
+
],
|
|
20
|
+
"main": "./dist/index.cjs",
|
|
21
|
+
"module": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.js",
|
|
27
|
+
"require": "./dist/index.cjs"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"react": ">=18",
|
|
36
|
+
"react-dom": ">=18"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@nucleux/utils": "0.7.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"tsup": "^8.3.5",
|
|
43
|
+
"typescript": "^5.7.2",
|
|
44
|
+
"@types/react": "^18.3.18",
|
|
45
|
+
"react": "^18.3.1",
|
|
46
|
+
"lucide-react": "^0.469.0"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"repository": {
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "git+https://github.com/intelligaia-open-labs/nucleux.git",
|
|
55
|
+
"directory": "packages/md3-button-group"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/intelligaia-open-labs/nucleux#readme",
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsup"
|
|
60
|
+
}
|
|
6
61
|
}
|