@ladder-ui/radio-group 0.3.0 → 0.5.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
@@ -1,43 +1 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var react = require('react');
5
- var concatClassNames = require('@ladder-ui/core/concatClassNames');
6
-
7
- const RadioGroupContext = react.createContext({ name: "" });
8
- function RadioGroup({ ref, className, children, value, defaultValue, onValueChange, name, orientation = "vertical", disabled = false, ...props }) {
9
- const generatedName = react.useId();
10
- const resolvedName = name ?? generatedName;
11
- const classes = concatClassNames("lui-radio-group", orientation === "horizontal" ? "lui-radio-group--horizontal" : undefined, className);
12
- return (jsxRuntime.jsx(RadioGroupContext, { value: { name: resolvedName, value, defaultValue, onValueChange, disabled }, children: jsxRuntime.jsx("div", { ref: ref, "data-slot": "radio-group", role: "radiogroup", className: classes, ...props, children: children }) }));
13
- }
14
- RadioGroup.displayName = "RadioGroup";
15
- function RadioGroupItem({ ref, className, style, value, size = "md", status = "default", disabled, onChange, ...inputProps }) {
16
- const ctx = react.use(RadioGroupContext);
17
- const isDisabled = disabled || ctx.disabled;
18
- // Controlled: pass checked based on context value
19
- const controlledProps = ctx.value !== undefined
20
- ? {
21
- checked: ctx.value === value,
22
- onChange: (e) => {
23
- if (e.target.checked)
24
- ctx.onValueChange?.(value);
25
- onChange?.(e);
26
- },
27
- }
28
- : {
29
- // Uncontrolled: use defaultChecked + native browser behaviour
30
- defaultChecked: ctx.defaultValue === value,
31
- onChange: (e) => {
32
- if (e.target.checked)
33
- ctx.onValueChange?.(value);
34
- onChange?.(e);
35
- },
36
- };
37
- const wrapperClasses = concatClassNames("lui-radio-group-item", `lui-radio-group-item--${size}`, status === "error" ? "lui-radio-group-item--error" : undefined, className);
38
- return (jsxRuntime.jsxs("span", { "data-slot": "radio-group-item", className: wrapperClasses, style: style, children: [jsxRuntime.jsx("input", { ref: ref, type: "radio", className: "lui-radio-group-item__input", name: ctx.name, value: value, disabled: isDisabled, "aria-invalid": status === "error" ? "true" : undefined, ...controlledProps, ...inputProps }), jsxRuntime.jsx("span", { className: "lui-radio-group-item__control", "aria-hidden": "true", children: jsxRuntime.jsx("span", { className: "lui-radio-group-item__dot" }) })] }));
39
- }
40
- RadioGroupItem.displayName = "RadioGroupItem";
41
-
42
- exports.RadioGroup = RadioGroup;
43
- exports.RadioGroupItem = RadioGroupItem;
1
+ "use strict";var a=require("react/jsx-runtime"),e=require("react"),r=require("@ladder-ui/core"),i=require("@ladder-ui/layout"),o=require("@ladder-ui/primitives");const s=e.createContext(null),l=r.cva({base:"lui-radio-group-item",variants:{size:{sm:"lui-radio-group-item--sm",md:"lui-radio-group-item--md",lg:"lui-radio-group-item--lg"},status:{default:"",error:"lui-radio-group-item--error"},disabled:{true:"lui-radio-group-item--disabled",false:""}},defaultVariants:{size:"md",status:"default"}}),u=e.forwardRef(({children:e,className:l,value:u,defaultValue:d,onValueChange:t,name:n,disabled:m,orientation:c="vertical",...p},g)=>{const h=o.useRadioGroup({value:u,defaultValue:d,onValueChange:t,name:n,disabled:m});return a.jsx(s,{value:h,children:a.jsx(i.Flex,{ref:g,role:"radiogroup",direction:"horizontal"===c?"row":"column",gap:"2",className:r.concatClassNames("lui-radio-group","horizontal"===c&&"lui-radio-group--horizontal",l),...p,children:e})})});u.displayName="RadioGroup";const d=e.forwardRef(({className:r,value:o,size:u,status:d,disabled:t,...n},m)=>{const c=e.use(s);if(!c)return null;const p=c.value===o,g=t||c.disabled;return a.jsxs(i.Box,{as:"span","data-slot":"radio-group-item",className:l({size:u,status:d,disabled:g,className:r}),children:[a.jsx("input",{ref:m,type:"radio",name:c.name,value:o,checked:p,disabled:g,"aria-invalid":"error"===d||void 0,className:"lui-radio-group-item__input",onChange:()=>c.onValueChange(o),...n}),a.jsx(i.Box,{as:"span",className:"lui-radio-group-item__control","aria-hidden":"true",children:a.jsx(i.Box,{as:"span",className:"lui-radio-group-item__dot"})})]})});d.displayName="RadioGroupItem",exports.RadioGroup=u,exports.RadioGroupItem=d;
package/dist/index.mjs CHANGED
@@ -1,40 +1 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { createContext, useId, use } from 'react';
3
- import concatClassNames from '@ladder-ui/core/concatClassNames';
4
-
5
- const RadioGroupContext = createContext({ name: "" });
6
- function RadioGroup({ ref, className, children, value, defaultValue, onValueChange, name, orientation = "vertical", disabled = false, ...props }) {
7
- const generatedName = useId();
8
- const resolvedName = name ?? generatedName;
9
- const classes = concatClassNames("lui-radio-group", orientation === "horizontal" ? "lui-radio-group--horizontal" : undefined, className);
10
- return (jsx(RadioGroupContext, { value: { name: resolvedName, value, defaultValue, onValueChange, disabled }, children: jsx("div", { ref: ref, "data-slot": "radio-group", role: "radiogroup", className: classes, ...props, children: children }) }));
11
- }
12
- RadioGroup.displayName = "RadioGroup";
13
- function RadioGroupItem({ ref, className, style, value, size = "md", status = "default", disabled, onChange, ...inputProps }) {
14
- const ctx = use(RadioGroupContext);
15
- const isDisabled = disabled || ctx.disabled;
16
- // Controlled: pass checked based on context value
17
- const controlledProps = ctx.value !== undefined
18
- ? {
19
- checked: ctx.value === value,
20
- onChange: (e) => {
21
- if (e.target.checked)
22
- ctx.onValueChange?.(value);
23
- onChange?.(e);
24
- },
25
- }
26
- : {
27
- // Uncontrolled: use defaultChecked + native browser behaviour
28
- defaultChecked: ctx.defaultValue === value,
29
- onChange: (e) => {
30
- if (e.target.checked)
31
- ctx.onValueChange?.(value);
32
- onChange?.(e);
33
- },
34
- };
35
- const wrapperClasses = concatClassNames("lui-radio-group-item", `lui-radio-group-item--${size}`, status === "error" ? "lui-radio-group-item--error" : undefined, className);
36
- return (jsxs("span", { "data-slot": "radio-group-item", className: wrapperClasses, style: style, children: [jsx("input", { ref: ref, type: "radio", className: "lui-radio-group-item__input", name: ctx.name, value: value, disabled: isDisabled, "aria-invalid": status === "error" ? "true" : undefined, ...controlledProps, ...inputProps }), jsx("span", { className: "lui-radio-group-item__control", "aria-hidden": "true", children: jsx("span", { className: "lui-radio-group-item__dot" }) })] }));
37
- }
38
- RadioGroupItem.displayName = "RadioGroupItem";
39
-
40
- export { RadioGroup, RadioGroupItem };
1
+ import{jsx as a,jsxs as e}from"react/jsx-runtime";import{createContext as i,forwardRef as r,use as o}from"react";import{cva as l,concatClassNames as d}from"@ladder-ui/core";import{Flex as t,Box as u}from"@ladder-ui/layout";import{useRadioGroup as s}from"@ladder-ui/primitives";const n=i(null),m=l({base:"lui-radio-group-item",variants:{size:{sm:"lui-radio-group-item--sm",md:"lui-radio-group-item--md",lg:"lui-radio-group-item--lg"},status:{default:"",error:"lui-radio-group-item--error"},disabled:{true:"lui-radio-group-item--disabled",false:""}},defaultVariants:{size:"md",status:"default"}}),p=r(({children:e,className:i,value:r,defaultValue:o,onValueChange:l,name:u,disabled:m,orientation:p="vertical",...c},g)=>{const f=s({value:r,defaultValue:o,onValueChange:l,name:u,disabled:m});return a(n,{value:f,children:a(t,{ref:g,role:"radiogroup",direction:"horizontal"===p?"row":"column",gap:"2",className:d("lui-radio-group","horizontal"===p&&"lui-radio-group--horizontal",i),...c,children:e})})});p.displayName="RadioGroup";const c=r(({className:i,value:r,size:l,status:d,disabled:t,...s},p)=>{const c=o(n);if(!c)return null;const g=c.value===r,f=t||c.disabled;return e(u,{as:"span","data-slot":"radio-group-item",className:m({size:l,status:d,disabled:f,className:i}),children:[a("input",{ref:p,type:"radio",name:c.name,value:r,checked:g,disabled:f,"aria-invalid":"error"===d||void 0,className:"lui-radio-group-item__input",onChange:()=>c.onValueChange(r),...s}),a(u,{as:"span",className:"lui-radio-group-item__control","aria-hidden":"true",children:a(u,{as:"span",className:"lui-radio-group-item__dot"})})]})});c.displayName="RadioGroupItem";export{p as RadioGroup,c as RadioGroupItem};
@@ -1,96 +1 @@
1
- @layer components {
2
- .lui-radio-group {
3
- display: flex;
4
- flex-direction: column;
5
- gap: 0.625rem;
6
- }
7
- .lui-radio-group--horizontal {
8
- flex-direction: row;
9
- flex-wrap: wrap;
10
- align-items: center;
11
- }
12
- .lui-radio-group-item {
13
- position: relative;
14
- display: inline-flex;
15
- align-items: center;
16
- justify-content: center;
17
- flex-shrink: 0;
18
- vertical-align: middle;
19
- width: var(--lui-radio-size-md);
20
- height: var(--lui-radio-size-md);
21
- }
22
- .lui-radio-group-item__input {
23
- position: absolute;
24
- inset: 0;
25
- width: 100%;
26
- height: 100%;
27
- margin: 0;
28
- padding: 0;
29
- opacity: 0;
30
- cursor: pointer;
31
- z-index: 1;
32
- border-radius: 50%;
33
- }
34
- .lui-radio-group-item__input:disabled {
35
- cursor: not-allowed;
36
- }
37
- .lui-radio-group-item__control {
38
- display: flex;
39
- align-items: center;
40
- justify-content: center;
41
- width: 100%;
42
- height: 100%;
43
- background-color: var(--lui-radio-bg);
44
- border: 1px solid var(--lui-radio-border);
45
- border-radius: 50%;
46
- transition: var(--lui-transition);
47
- pointer-events: none;
48
- flex-shrink: 0;
49
- }
50
- .lui-radio-group-item__dot {
51
- display: none;
52
- width: calc(var(--lui-radio-size-md) * var(--lui-radio-dot-scale));
53
- height: calc(var(--lui-radio-size-md) * var(--lui-radio-dot-scale));
54
- border-radius: 50%;
55
- background-color: var(--lui-radio-checked-dot);
56
- flex-shrink: 0;
57
- }
58
- .lui-radio-group-item:has(.lui-radio-group-item__input:focus-visible) .lui-radio-group-item__control {
59
- outline: none;
60
- border-color: var(--lui-radio-focus-border);
61
- box-shadow: 0 0 0 2px var(--lui-surface), 0 0 0 4px var(--lui-radio-focus-ring-color);
62
- }
63
- .lui-radio-group-item:has(.lui-radio-group-item__input:checked) .lui-radio-group-item__control {
64
- background-color: var(--lui-radio-checked-bg);
65
- border-color: var(--lui-radio-checked-bg);
66
- }
67
- .lui-radio-group-item:has(.lui-radio-group-item__input:checked) .lui-radio-group-item__dot {
68
- display: block;
69
- }
70
- .lui-radio-group-item:has(.lui-radio-group-item__input:disabled) {
71
- opacity: var(--lui-disabled-opacity);
72
- }
73
- .lui-radio-group-item--error .lui-radio-group-item__control {
74
- border-color: var(--lui-error);
75
- }
76
- .lui-radio-group-item--error:has(.lui-radio-group-item__input:focus-visible) .lui-radio-group-item__control {
77
- border-color: var(--lui-error);
78
- box-shadow: 0 0 0 2px var(--lui-surface), 0 0 0 4px color-mix(in srgb, var(--lui-error) 40%, transparent);
79
- }
80
- .lui-radio-group-item--sm {
81
- width: var(--lui-radio-size-sm);
82
- height: var(--lui-radio-size-sm);
83
- }
84
- .lui-radio-group-item--sm .lui-radio-group-item__dot {
85
- width: calc(var(--lui-radio-size-sm) * var(--lui-radio-dot-scale));
86
- height: calc(var(--lui-radio-size-sm) * var(--lui-radio-dot-scale));
87
- }
88
- .lui-radio-group-item--lg {
89
- width: var(--lui-radio-size-lg);
90
- height: var(--lui-radio-size-lg);
91
- }
92
- .lui-radio-group-item--lg .lui-radio-group-item__dot {
93
- width: calc(var(--lui-radio-size-lg) * var(--lui-radio-dot-scale));
94
- height: calc(var(--lui-radio-size-lg) * var(--lui-radio-dot-scale));
95
- }
96
- }
1
+ @layer components{.lui-radio-group{display:flex;flex-direction:column;gap:.625rem}.lui-radio-group--horizontal{align-items:center;flex-direction:row;flex-wrap:wrap}.lui-radio-group-item{align-items:center;display:inline-flex;flex-shrink:0;height:var(--lui-radio-size-md);justify-content:center;position:relative;vertical-align:middle;width:var(--lui-radio-size-md)}.lui-radio-group-item__input{border-radius:50%;cursor:pointer;height:100%;inset:0;margin:0;opacity:0;padding:0;position:absolute;width:100%;z-index:1}.lui-radio-group-item__input:disabled{cursor:not-allowed}.lui-radio-group-item__control{align-items:center;background-color:var(--lui-radio-bg);border:1px solid var(--lui-radio-border);border-radius:50%;display:flex;flex-shrink:0;height:100%;justify-content:center;pointer-events:none;transition:var(--lui-transition);width:100%}.lui-radio-group-item__dot{background-color:var(--lui-radio-checked-dot);border-radius:50%;display:none;flex-shrink:0;height:calc(var(--lui-radio-size-md)*var(--lui-radio-dot-scale));width:calc(var(--lui-radio-size-md)*var(--lui-radio-dot-scale))}.lui-radio-group-item:has(.lui-radio-group-item__input:focus-visible) .lui-radio-group-item__control{border-color:var(--lui-radio-focus-border);box-shadow:0 0 0 2px var(--lui-bg-surface),0 0 0 4px var(--lui-radio-focus-ring-color);outline:none}.lui-radio-group-item:has(.lui-radio-group-item__input:checked) .lui-radio-group-item__control{background-color:var(--lui-radio-checked-bg);border-color:var(--lui-radio-checked-bg)}.lui-radio-group-item:has(.lui-radio-group-item__input:checked) .lui-radio-group-item__dot{display:block}.lui-radio-group-item:has(.lui-radio-group-item__input:disabled){opacity:var(--lui-disabled-opacity)}.lui-radio-group-item--error .lui-radio-group-item__control{border-color:var(--lui-error)}.lui-radio-group-item--error:has(.lui-radio-group-item__input:focus-visible) .lui-radio-group-item__control{border-color:var(--lui-error);box-shadow:0 0 0 2px var(--lui-bg-surface),0 0 0 4px color-mix(in srgb,var(--lui-error) 40%,transparent)}.lui-radio-group-item--sm{height:var(--lui-radio-size-sm);width:var(--lui-radio-size-sm)}.lui-radio-group-item--sm .lui-radio-group-item__dot{height:calc(var(--lui-radio-size-sm)*var(--lui-radio-dot-scale));width:calc(var(--lui-radio-size-sm)*var(--lui-radio-dot-scale))}.lui-radio-group-item--lg{height:var(--lui-radio-size-lg);width:var(--lui-radio-size-lg)}.lui-radio-group-item--lg .lui-radio-group-item__dot{height:calc(var(--lui-radio-size-lg)*var(--lui-radio-dot-scale));width:calc(var(--lui-radio-size-lg)*var(--lui-radio-dot-scale))}}
@@ -1,33 +1,33 @@
1
- import type { Ref } from "react";
2
- export interface RadioGroupProps extends React.HTMLAttributes<HTMLDivElement> {
3
- ref?: Ref<HTMLDivElement>;
4
- /** Controlled selected value. Pair with `onValueChange`. */
5
- value?: string;
6
- /** Uncontrolled initial selected value. */
7
- defaultValue?: string;
8
- /** Called when the user selects a different item. */
9
- onValueChange?: (value: string) => void;
10
- /** HTML `name` attribute shared by all radio inputs in the group. Auto-generated if omitted. */
11
- name?: string;
12
- /** Layout direction of the items. */
1
+ import type { Ref, HTMLAttributes, ReactNode } from "react";
2
+ import { type VariantProps } from "@ladder-ui/core";
3
+ import { type UseRadioGroupProps } from "@ladder-ui/primitives";
4
+ declare const radioGroupItemVariants: (props?: (import("packages/core/dist/cva").ConfigVariants<{
5
+ size: {
6
+ sm: string;
7
+ md: string;
8
+ lg: string;
9
+ };
10
+ status: {
11
+ default: string;
12
+ error: string;
13
+ };
14
+ disabled: {
15
+ true: string;
16
+ false: string;
17
+ };
18
+ }> & {
19
+ className?: string;
20
+ }) | undefined) => string;
21
+ export interface RadioGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, "defaultValue">, UseRadioGroupProps {
22
+ children?: ReactNode;
13
23
  orientation?: "vertical" | "horizontal";
14
- /** Disables all radio items in the group. */
15
- disabled?: boolean;
16
24
  }
17
- export declare function RadioGroup({ ref, className, children, value, defaultValue, onValueChange, name, orientation, disabled, ...props }: RadioGroupProps): import("react/jsx-runtime").JSX.Element;
18
- export declare namespace RadioGroup {
19
- var displayName: string;
20
- }
21
- export interface RadioGroupItemProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "type" | "value"> {
25
+ export declare const RadioGroup: import("react").ForwardRefExoticComponent<RadioGroupProps & import("react").RefAttributes<HTMLDivElement>>;
26
+ export interface RadioGroupItemProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "type" | "value">, VariantProps<typeof radioGroupItemVariants> {
22
27
  ref?: Ref<HTMLInputElement>;
23
- /** The value this item represents. Required. */
24
28
  value: string;
25
- /** Size of the radio control. */
26
29
  size?: "sm" | "md" | "lg";
27
- /** Visual validation state. `"error"` adds a red border and sets `aria-invalid="true"`. */
28
30
  status?: "default" | "error";
29
31
  }
30
- export declare function RadioGroupItem({ ref, className, style, value, size, status, disabled, onChange, ...inputProps }: RadioGroupItemProps): import("react/jsx-runtime").JSX.Element;
31
- export declare namespace RadioGroupItem {
32
- var displayName: string;
33
- }
32
+ export declare const RadioGroupItem: import("react").ForwardRefExoticComponent<Omit<RadioGroupItemProps, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
33
+ export {};
@@ -1,12 +1 @@
1
- :root {
2
- --lui-radio-size-sm: 0.875rem;
3
- --lui-radio-size-md: 1rem;
4
- --lui-radio-size-lg: 1.25rem;
5
- --lui-radio-dot-scale: 0.4;
6
- --lui-radio-bg: var(--lui-surface);
7
- --lui-radio-border: var(--lui-surface-border);
8
- --lui-radio-checked-bg: var(--lui-primary);
9
- --lui-radio-checked-dot: var(--lui-primary-text);
10
- --lui-radio-focus-border: var(--lui-primary);
11
- --lui-radio-focus-ring-color: color-mix(in srgb, var(--lui-primary) 40%, transparent);
12
- }
1
+ :root{--lui-radio-size-sm:0.875rem;--lui-radio-size-md:1rem;--lui-radio-size-lg:1.25rem;--lui-radio-dot-scale:0.4;--lui-radio-bg:var(--lui-bg-surface);--lui-radio-border:color-mix(in srgb,var(--lui-border-default) 93%,var(--lui-text-primary));--lui-radio-checked-bg:var(--lui-bg-interactive);--lui-radio-checked-dot:var(--lui-text-inverse);--lui-radio-focus-border:var(--lui-bg-interactive);--lui-radio-focus-ring-color:color-mix(in srgb,var(--lui-bg-interactive) 40%,transparent)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ladder-ui/radio-group",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -31,7 +31,8 @@
31
31
  "license": "ISC",
32
32
  "repository": {
33
33
  "type": "git",
34
- "url": "git+ssh://git@github.com/ivelaval/ladder-ui.git"
34
+ "url": "https://github.com/ivelaval/ladder-ui.git",
35
+ "directory": "packages/radio-group"
35
36
  },
36
37
  "bugs": {
37
38
  "url": "https://github.com/ivelaval/ladder-ui/issues"
@@ -48,7 +49,7 @@
48
49
  "sass": "^1.90.0",
49
50
  "tslib": "^2.6.2",
50
51
  "typescript": "^5.3.3",
51
- "@ladder-ui/core": "0.3.0"
52
+ "@ladder-ui/core": "0.5.0"
52
53
  },
53
54
  "peerDependencies": {
54
55
  "@ladder-ui/core": ">=0.0.0",
@@ -57,6 +58,10 @@
57
58
  "sideEffects": [
58
59
  "**/*.css"
59
60
  ],
61
+ "dependencies": {
62
+ "@ladder-ui/layout": "^0.5.0",
63
+ "@ladder-ui/primitives": "^0.5.0"
64
+ },
60
65
  "scripts": {
61
66
  "build": "pnpm clean && rollup -c",
62
67
  "dev": "rollup -c -w",