@edux-design/buttons 0.0.2 → 0.0.4

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.mjs CHANGED
@@ -1,7 +1,66 @@
1
- // src/elements/Button.jsx
1
+ // src/elements/IconButton.jsx
2
2
  import React, { forwardRef } from "react";
3
3
  import { cx } from "@edux-design/utils";
4
- var Button = forwardRef(
4
+ import { jsx } from "react/jsx-runtime";
5
+ var IconButton = forwardRef(
6
+ ({
7
+ icon,
8
+ size = "medium",
9
+ isSecondary,
10
+ isDanger,
11
+ isBare,
12
+ disabled,
13
+ className,
14
+ ...props
15
+ }, ref) => {
16
+ let variant = "primary";
17
+ if (isBare) variant = "bare";
18
+ if (isSecondary) variant = "secondary";
19
+ if (isDanger) variant = "danger";
20
+ if (disabled) variant = "disabled";
21
+ if (process.env.NODE_ENV !== "production") {
22
+ const count = [isSecondary, isDanger, isBare].filter(Boolean).length;
23
+ if (count > 1) {
24
+ console.warn(
25
+ "[IconButton]: Multiple variant props passed. Using the highest priority only."
26
+ );
27
+ }
28
+ }
29
+ const defaults = "flex justify-center items-center focus:shadow-focus focus-visible:shadow-focus outline-none transition-all duration-300 ease-in-out rounded-full";
30
+ const sizes = {
31
+ small: "h-[36px] w-[36px] text-sm",
32
+ medium: "h-[44px] w-[44px] text-base",
33
+ large: "h-[56px] w-[56px] text-lg"
34
+ };
35
+ const variants = {
36
+ primary: "border-2 border-border-primary-emphasis bg-bg-primary-base text-white hover:bg-border-focus hover:text-fg-base hover:border-border-emphasis hover:shadow-md active:bg-border-focus active:bg-bg-focus-overlay active:text-fg-base",
37
+ secondary: "border-2 border-border-primary-base bg-bg-base text-fg-primary-emphasis hover:shadow-md hover:bg-bg-primary-subtle active:bg-bg-primary-subtle-90",
38
+ bare: "bg-bg-base text-fg-primary-emphasis hover:bg-bg-minimal active:bg-bg-minimal-5",
39
+ danger: "bg-bg-danger-base border-2 border-border-danger-emphasis text-white hover:bg-bg-danger-base-5 active:bg-bg-danger-base-10",
40
+ disabled: "border-2 border-border-subtle bg-bg-inactive text-fg-inactive hover:no-underline cursor-not-allowed"
41
+ };
42
+ const STYLES = cx(defaults, sizes[size], variants[variant], className);
43
+ return /* @__PURE__ */ jsx(
44
+ "button",
45
+ {
46
+ role: "button",
47
+ type: "button",
48
+ "aria-disabled": disabled,
49
+ disabled,
50
+ className: STYLES,
51
+ ref,
52
+ ...props,
53
+ children: icon
54
+ }
55
+ );
56
+ }
57
+ );
58
+
59
+ // src/elements/Button.jsx
60
+ import React2, { forwardRef as forwardRef2 } from "react";
61
+ import { cx as cx2 } from "@edux-design/utils";
62
+ import { jsx as jsx2 } from "react/jsx-runtime";
63
+ var Button = forwardRef2(
5
64
  ({
6
65
  children,
7
66
  size = "medium",
@@ -41,8 +100,8 @@ var Button = forwardRef(
41
100
  danger: "bg-bg-danger-base border-2 border-border-danger-emphasis text-white hover:bg-bg-danger-base-5 active:bg-bg-danger-base-10",
42
101
  disabled: "border-2 border-border-subtle bg-bg-inactive text-fg-inactive hover:no-underline"
43
102
  };
44
- const STYLES = cx(defaults, sizes[size], width, fonts, variants[variant]);
45
- return /* @__PURE__ */ React.createElement(
103
+ const STYLES = cx2(defaults, sizes[size], width, fonts, variants[variant]);
104
+ return /* @__PURE__ */ jsx2(
46
105
  "button",
47
106
  {
48
107
  role: "button",
@@ -51,22 +110,22 @@ var Button = forwardRef(
51
110
  disabled,
52
111
  className: STYLES,
53
112
  ref,
54
- ...props
55
- },
56
- children
113
+ ...props,
114
+ children
115
+ }
57
116
  );
58
117
  }
59
118
  );
60
119
 
61
120
  // src/elements/MenuButton.jsx
62
- import React3 from "react";
121
+ import React4 from "react";
63
122
 
64
123
  // src/util/MenuButtonContext.jsx
65
- import React2, { createContext, useContext } from "react";
124
+ import React3, { createContext, useContext } from "react";
66
125
  var MenuButtonContext = createContext();
67
126
 
68
127
  // src/elements/MenuButton.jsx
69
- import { cx as cx2 } from "@edux-design/utils";
128
+ import { cx as cx3 } from "@edux-design/utils";
70
129
 
71
130
  // ../icons/dist/index.mjs
72
131
  var __create = Object.create;
@@ -1723,19 +1782,19 @@ var require_react_jsx_runtime_development = __commonJS({
1723
1782
  function validateChildKeys(node) {
1724
1783
  "object" === typeof node && null !== node && node.$$typeof === REACT_ELEMENT_TYPE && node._store && (node._store.validated = 1);
1725
1784
  }
1726
- var React4 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler");
1727
- var REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React4.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
1785
+ var React7 = require_react(), REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler");
1786
+ var REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React7.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
1728
1787
  return null;
1729
1788
  };
1730
- React4 = {
1789
+ React7 = {
1731
1790
  react_stack_bottom_frame: function(callStackForError) {
1732
1791
  return callStackForError();
1733
1792
  }
1734
1793
  };
1735
1794
  var specialPropKeyWarningShown;
1736
1795
  var didWarnAboutElementRef = {};
1737
- var unknownOwnerDebugStack = React4.react_stack_bottom_frame.bind(
1738
- React4,
1796
+ var unknownOwnerDebugStack = React7.react_stack_bottom_frame.bind(
1797
+ React7,
1739
1798
  UnknownOwner
1740
1799
  )();
1741
1800
  var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
@@ -1779,10 +1838,13 @@ var require_jsx_runtime = __commonJS({
1779
1838
  }
1780
1839
  }
1781
1840
  });
1782
- var import_jsx_runtime = __toESM(require_jsx_runtime());
1783
- var import_jsx_runtime2 = __toESM(require_jsx_runtime());
1784
1841
  var import_jsx_runtime3 = __toESM(require_jsx_runtime());
1785
- var SvgChevron = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1842
+ var import_jsx_runtime22 = __toESM(require_jsx_runtime());
1843
+ var import_jsx_runtime32 = __toESM(require_jsx_runtime());
1844
+ var import_jsx_runtime4 = __toESM(require_jsx_runtime());
1845
+ var import_jsx_runtime5 = __toESM(require_jsx_runtime());
1846
+ var import_jsx_runtime6 = __toESM(require_jsx_runtime());
1847
+ var SvgChevron = (props) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1786
1848
  "svg",
1787
1849
  {
1788
1850
  xmlns: "http://www.w3.org/2000/svg",
@@ -1791,7 +1853,7 @@ var SvgChevron = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1791
1853
  fill: "none",
1792
1854
  viewBox: "0 0 24 24",
1793
1855
  ...props,
1794
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1856
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1795
1857
  "path",
1796
1858
  {
1797
1859
  fill: "currentColor",
@@ -1803,9 +1865,6 @@ var SvgChevron = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1803
1865
  }
1804
1866
  );
1805
1867
  var Chevron_default = SvgChevron;
1806
- var import_jsx_runtime4 = __toESM(require_jsx_runtime());
1807
- var import_jsx_runtime5 = __toESM(require_jsx_runtime());
1808
- var import_jsx_runtime6 = __toESM(require_jsx_runtime());
1809
1868
  var import_jsx_runtime7 = __toESM(require_jsx_runtime());
1810
1869
  var import_jsx_runtime8 = __toESM(require_jsx_runtime());
1811
1870
  var import_jsx_runtime9 = __toESM(require_jsx_runtime());
@@ -1821,7 +1880,7 @@ var import_jsx_runtime18 = __toESM(require_jsx_runtime());
1821
1880
  var import_jsx_runtime19 = __toESM(require_jsx_runtime());
1822
1881
  var import_jsx_runtime20 = __toESM(require_jsx_runtime());
1823
1882
  var import_jsx_runtime21 = __toESM(require_jsx_runtime());
1824
- var import_jsx_runtime22 = __toESM(require_jsx_runtime());
1883
+ var import_jsx_runtime222 = __toESM(require_jsx_runtime());
1825
1884
  var import_jsx_runtime23 = __toESM(require_jsx_runtime());
1826
1885
  var import_jsx_runtime24 = __toESM(require_jsx_runtime());
1827
1886
  var import_jsx_runtime25 = __toESM(require_jsx_runtime());
@@ -1830,20 +1889,365 @@ var import_jsx_runtime27 = __toESM(require_jsx_runtime());
1830
1889
  var import_jsx_runtime28 = __toESM(require_jsx_runtime());
1831
1890
  var import_jsx_runtime29 = __toESM(require_jsx_runtime());
1832
1891
  var import_jsx_runtime30 = __toESM(require_jsx_runtime());
1892
+ var import_jsx_runtime31 = __toESM(require_jsx_runtime());
1893
+ var import_jsx_runtime322 = __toESM(require_jsx_runtime());
1894
+ var import_jsx_runtime33 = __toESM(require_jsx_runtime());
1895
+ var import_jsx_runtime34 = __toESM(require_jsx_runtime());
1896
+ var import_jsx_runtime35 = __toESM(require_jsx_runtime());
1897
+ var import_jsx_runtime36 = __toESM(require_jsx_runtime());
1898
+ var import_jsx_runtime37 = __toESM(require_jsx_runtime());
1899
+ var import_jsx_runtime38 = __toESM(require_jsx_runtime());
1900
+ var import_jsx_runtime39 = __toESM(require_jsx_runtime());
1901
+ var import_jsx_runtime40 = __toESM(require_jsx_runtime());
1902
+ var import_jsx_runtime41 = __toESM(require_jsx_runtime());
1903
+ var import_jsx_runtime42 = __toESM(require_jsx_runtime());
1904
+ var import_jsx_runtime43 = __toESM(require_jsx_runtime());
1905
+ var import_jsx_runtime44 = __toESM(require_jsx_runtime());
1906
+ var import_jsx_runtime45 = __toESM(require_jsx_runtime());
1907
+ var import_jsx_runtime46 = __toESM(require_jsx_runtime());
1908
+ var import_jsx_runtime47 = __toESM(require_jsx_runtime());
1909
+ var import_jsx_runtime48 = __toESM(require_jsx_runtime());
1910
+ var import_jsx_runtime49 = __toESM(require_jsx_runtime());
1911
+ var import_jsx_runtime50 = __toESM(require_jsx_runtime());
1912
+ var import_jsx_runtime51 = __toESM(require_jsx_runtime());
1913
+ var import_jsx_runtime52 = __toESM(require_jsx_runtime());
1914
+ var import_jsx_runtime53 = __toESM(require_jsx_runtime());
1915
+ var import_jsx_runtime54 = __toESM(require_jsx_runtime());
1916
+ var import_jsx_runtime55 = __toESM(require_jsx_runtime());
1833
1917
 
1834
1918
  // src/elements/MenuButton.jsx
1919
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
1835
1920
  function MenuButton({ children, size }) {
1836
- const SPLIT_BUTTON_STYLES = cx2(
1921
+ const SPLIT_BUTTON_STYLES = cx3(
1837
1922
  "w-[36px] border-l-[1px] border-l-black flex flex-row justify-center items-center",
1838
1923
  {
1839
1924
  "h-[32px]": size === "small",
1840
1925
  "h-[40px] py-2": size === "medium" || size === void 0
1841
1926
  }
1842
1927
  );
1843
- return /* @__PURE__ */ React3.createElement(MenuButtonContext.Provider, { value: true }, /* @__PURE__ */ React3.createElement("div", null, children), /* @__PURE__ */ React3.createElement(Chevron_default, null));
1928
+ return /* @__PURE__ */ jsxs(MenuButtonContext.Provider, { value: true, children: [
1929
+ /* @__PURE__ */ jsx3("div", { className: SPLIT_BUTTON_STYLES, children }),
1930
+ /* @__PURE__ */ jsx3(Chevron_default, {})
1931
+ ] });
1932
+ }
1933
+
1934
+ // src/elements/ButtonGroup.jsx
1935
+ import React5, {
1936
+ forwardRef as forwardRef3,
1937
+ useCallback,
1938
+ useEffect,
1939
+ useLayoutEffect,
1940
+ useMemo,
1941
+ useRef,
1942
+ useState
1943
+ } from "react";
1944
+ import { cx as cx4, filterChildrenByDisplayName } from "@edux-design/utils";
1945
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1946
+ var SIZE_STYLES = {
1947
+ small: {
1948
+ button: "text-xs px-12 py-6 rounded-md "
1949
+ },
1950
+ medium: {
1951
+ button: "text-sm px-12 py-6 rounded-md "
1952
+ },
1953
+ large: {
1954
+ button: "text-base px-12 py-6 rounded-md"
1955
+ }
1956
+ };
1957
+ var isBrowser = typeof window !== "undefined";
1958
+ var useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;
1959
+ var ButtonGroup = forwardRef3(function ButtonGroup2({
1960
+ value,
1961
+ defaultValue,
1962
+ onChange,
1963
+ size = "medium",
1964
+ isStretched = false,
1965
+ className,
1966
+ children,
1967
+ ...rest
1968
+ }, forwardedRef) {
1969
+ const normalizedOptions = useMemo(() => {
1970
+ const childItems = filterChildrenByDisplayName(children, "ButtonGroupItem");
1971
+ return childItems.map((child, index) => {
1972
+ const props = child.props || {};
1973
+ const hasValue = props.value !== void 0;
1974
+ const safeValue = hasValue && props.value !== null ? props.value : index;
1975
+ return {
1976
+ ...props,
1977
+ label: props.label ?? props.children ?? `Option ${index + 1}`,
1978
+ value: safeValue
1979
+ };
1980
+ });
1981
+ }, [children]);
1982
+ const sizeStyles = SIZE_STYLES[size] ?? SIZE_STYLES.medium;
1983
+ const initialValue = value ?? defaultValue ?? (normalizedOptions.length ? normalizedOptions[0].value : void 0);
1984
+ const [internalValue, setInternalValue] = useState(initialValue);
1985
+ const isControlled = value !== void 0;
1986
+ const selectedValue = isControlled ? value : internalValue;
1987
+ useEffect(() => {
1988
+ if (!isControlled && defaultValue !== void 0) {
1989
+ setInternalValue(defaultValue);
1990
+ }
1991
+ }, [defaultValue, isControlled]);
1992
+ useEffect(() => {
1993
+ if (isControlled) return;
1994
+ if (normalizedOptions.length && !normalizedOptions.some((option) => option.value === internalValue)) {
1995
+ setInternalValue(normalizedOptions[0].value);
1996
+ }
1997
+ }, [internalValue, isControlled, normalizedOptions]);
1998
+ const buttonRefs = useRef(/* @__PURE__ */ new Map());
1999
+ const containerRef = useRef(null);
2000
+ const indicatorRef = useRef({ width: 0, height: 0, x: 0, y: 0 });
2001
+ const [indicator, setIndicator] = useState({
2002
+ width: 0,
2003
+ height: 0,
2004
+ x: 0,
2005
+ y: 0
2006
+ });
2007
+ const setContainerRef = useCallback(
2008
+ (node) => {
2009
+ containerRef.current = node;
2010
+ if (typeof forwardedRef === "function") {
2011
+ forwardedRef(node);
2012
+ } else if (forwardedRef) {
2013
+ forwardedRef.current = node;
2014
+ }
2015
+ },
2016
+ [forwardedRef]
2017
+ );
2018
+ const registerButtonRef = useCallback((optionValue) => {
2019
+ return (node) => {
2020
+ if (!buttonRefs.current) return;
2021
+ if (node) {
2022
+ buttonRefs.current.set(optionValue, node);
2023
+ } else {
2024
+ buttonRefs.current.delete(optionValue);
2025
+ }
2026
+ };
2027
+ }, []);
2028
+ const updateIndicator = useCallback(() => {
2029
+ const container = containerRef.current;
2030
+ const target = buttonRefs.current.get(selectedValue);
2031
+ if (!container || !target) {
2032
+ if (indicatorRef.current.width !== 0) {
2033
+ indicatorRef.current = { width: 0, height: 0, x: 0, y: 0 };
2034
+ setIndicator(indicatorRef.current);
2035
+ }
2036
+ return;
2037
+ }
2038
+ const containerRect = container.getBoundingClientRect();
2039
+ const targetRect = target.getBoundingClientRect();
2040
+ const next = {
2041
+ width: targetRect.width,
2042
+ height: targetRect.height,
2043
+ x: targetRect.left - containerRect.left,
2044
+ y: targetRect.top - containerRect.top
2045
+ };
2046
+ const prev = indicatorRef.current;
2047
+ if (prev.width !== next.width || prev.height !== next.height || prev.x !== next.x || prev.y !== next.y) {
2048
+ indicatorRef.current = next;
2049
+ setIndicator(next);
2050
+ }
2051
+ }, [selectedValue]);
2052
+ useIsomorphicLayoutEffect(() => {
2053
+ updateIndicator();
2054
+ }, [updateIndicator, normalizedOptions.length, size]);
2055
+ useEffect(() => {
2056
+ if (!isBrowser) return;
2057
+ const handleResize = () => updateIndicator();
2058
+ window.addEventListener("resize", handleResize);
2059
+ return () => window.removeEventListener("resize", handleResize);
2060
+ }, [updateIndicator]);
2061
+ useEffect(() => {
2062
+ if (!isBrowser) return;
2063
+ const node = containerRef.current;
2064
+ if (!node || typeof ResizeObserver === "undefined") return;
2065
+ const observer = new ResizeObserver(() => {
2066
+ updateIndicator();
2067
+ });
2068
+ observer.observe(node);
2069
+ return () => observer.disconnect();
2070
+ }, [updateIndicator]);
2071
+ const focusOption = useCallback((option) => {
2072
+ const node = buttonRefs.current.get(option.value);
2073
+ if (node) {
2074
+ node.focus();
2075
+ }
2076
+ }, []);
2077
+ const handleSelect = useCallback(
2078
+ (option) => {
2079
+ if (option.disabled || option.value === selectedValue) {
2080
+ return;
2081
+ }
2082
+ if (!isControlled) {
2083
+ setInternalValue(option.value);
2084
+ }
2085
+ if (typeof onChange === "function") {
2086
+ onChange(option.value, option);
2087
+ }
2088
+ },
2089
+ [isControlled, onChange, selectedValue]
2090
+ );
2091
+ const getNextEnabledIndex = useCallback(
2092
+ (startIndex, direction) => {
2093
+ if (!normalizedOptions.length) return -1;
2094
+ let nextIndex = startIndex;
2095
+ for (let i = 0; i < normalizedOptions.length; i += 1) {
2096
+ nextIndex = (nextIndex + direction + normalizedOptions.length) % normalizedOptions.length;
2097
+ if (!normalizedOptions[nextIndex].disabled) {
2098
+ return nextIndex;
2099
+ }
2100
+ }
2101
+ return startIndex;
2102
+ },
2103
+ [normalizedOptions]
2104
+ );
2105
+ const findFirstEnabledIndex = useCallback(() => {
2106
+ return normalizedOptions.findIndex((option) => !option.disabled);
2107
+ }, [normalizedOptions]);
2108
+ const findLastEnabledIndex = useCallback(() => {
2109
+ for (let i = normalizedOptions.length - 1; i >= 0; i -= 1) {
2110
+ if (!normalizedOptions[i].disabled) {
2111
+ return i;
2112
+ }
2113
+ }
2114
+ return -1;
2115
+ }, [normalizedOptions]);
2116
+ const indicatorVisible = indicator.width > 0 && indicator.height > 0;
2117
+ const rootClasses = cx4(
2118
+ "inline-flex h-[44px] rounded-lg border-2 border-border-subtle bg-bg-base/90 p-2 shadow-inner",
2119
+ isStretched ? "w-full" : "w-auto",
2120
+ className
2121
+ );
2122
+ const trackClasses = cx4(
2123
+ "relative isolate flex w-full items-center gap-8",
2124
+ !isStretched && "w-auto"
2125
+ );
2126
+ const buttonBaseClasses = cx4(
2127
+ "relative z-10 h-[36px] inline-flex items-center justify-center gap-2 whitespace-nowrap font-semibold tracking-tight transition-colors duration-200 ease-out focus-visible:outline-none focus-visible:shadow-focus motion-reduce:duration-0",
2128
+ sizeStyles.button,
2129
+ isStretched ? "flex-1" : "w-auto"
2130
+ );
2131
+ return /* @__PURE__ */ jsx4(
2132
+ "div",
2133
+ {
2134
+ ...rest,
2135
+ ref: setContainerRef,
2136
+ role: "radiogroup",
2137
+ className: rootClasses,
2138
+ children: /* @__PURE__ */ jsxs2("div", { className: trackClasses, children: [
2139
+ /* @__PURE__ */ jsx4(
2140
+ "span",
2141
+ {
2142
+ "aria-hidden": "true",
2143
+ className: cx4(
2144
+ "pointer-events-none h-[44px] absolute rounded-md border-2 border-border-primary-emphasis bg-bg-base shadow-[0_8px_20px_rgb(22_92_131/0.18)] transition-[transform,width,height] duration-300 ease-out motion-reduce:duration-0",
2145
+ !indicatorVisible && "opacity-0"
2146
+ ),
2147
+ style: {
2148
+ width: indicator.width || void 0,
2149
+ height: indicator.height || void 0,
2150
+ transform: `translate(${indicator.x - 4}px`
2151
+ }
2152
+ }
2153
+ ),
2154
+ normalizedOptions.map((option, index) => {
2155
+ const isActive = option.value === selectedValue;
2156
+ const handleKeyDown = (event) => {
2157
+ if (option.disabled) return;
2158
+ if (event.key === "ArrowRight" || event.key === "ArrowDown") {
2159
+ event.preventDefault();
2160
+ const nextIndex = getNextEnabledIndex(index, 1);
2161
+ const nextOption = normalizedOptions[nextIndex];
2162
+ if (nextOption && nextOption !== option) {
2163
+ focusOption(nextOption);
2164
+ handleSelect(nextOption);
2165
+ }
2166
+ } else if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
2167
+ event.preventDefault();
2168
+ const prevIndex = getNextEnabledIndex(index, -1);
2169
+ const prevOption = normalizedOptions[prevIndex];
2170
+ if (prevOption && prevOption !== option) {
2171
+ focusOption(prevOption);
2172
+ handleSelect(prevOption);
2173
+ }
2174
+ } else if (event.key === "Home") {
2175
+ event.preventDefault();
2176
+ const firstIndex = findFirstEnabledIndex();
2177
+ const firstOption = firstIndex >= 0 ? normalizedOptions[firstIndex] : void 0;
2178
+ if (firstOption && firstOption !== option) {
2179
+ focusOption(firstOption);
2180
+ handleSelect(firstOption);
2181
+ }
2182
+ } else if (event.key === "End") {
2183
+ event.preventDefault();
2184
+ const lastIndex = findLastEnabledIndex();
2185
+ const lastOption = lastIndex >= 0 ? normalizedOptions[lastIndex] : void 0;
2186
+ if (lastOption && lastOption !== option) {
2187
+ focusOption(lastOption);
2188
+ handleSelect(lastOption);
2189
+ }
2190
+ }
2191
+ };
2192
+ const buttonClasses = cx4(
2193
+ buttonBaseClasses,
2194
+ option.disabled ? "cursor-not-allowed text-fg-inactive opacity-60" : "cursor-pointer text-fg-subtle hover:text-fg-base",
2195
+ isActive && "text-fg-primary-emphasis",
2196
+ !isActive && "hover:bg-bg-minimal-5 active:bg-bg-inactive"
2197
+ );
2198
+ const hasStartAdornment = option.startAdornment !== void 0 && option.startAdornment !== null;
2199
+ const hasendIcon = option.endIcon !== void 0 && option.endIcon !== null;
2200
+ return /* @__PURE__ */ jsxs2(
2201
+ "button",
2202
+ {
2203
+ ref: registerButtonRef(option.value),
2204
+ type: "button",
2205
+ role: "radio",
2206
+ "aria-checked": isActive,
2207
+ disabled: option.disabled,
2208
+ className: buttonClasses,
2209
+ onClick: () => handleSelect(option),
2210
+ onKeyDown: handleKeyDown,
2211
+ "data-state": isActive ? "active" : "inactive",
2212
+ children: [
2213
+ hasStartAdornment && /* @__PURE__ */ jsx4(
2214
+ "span",
2215
+ {
2216
+ "aria-hidden": "true",
2217
+ className: "flex items-center text-current",
2218
+ children: option.startAdornment
2219
+ }
2220
+ ),
2221
+ /* @__PURE__ */ jsx4("span", { className: "flex items-center gap-1 leading-none text-current", children: option.label ?? `Option ${index + 1}` }),
2222
+ hasendIcon && /* @__PURE__ */ jsx4(
2223
+ "span",
2224
+ {
2225
+ "aria-hidden": "true",
2226
+ className: "flex items-center text-current",
2227
+ children: option.endIcon
2228
+ }
2229
+ )
2230
+ ]
2231
+ },
2232
+ String(option.value)
2233
+ );
2234
+ })
2235
+ ] })
2236
+ }
2237
+ );
2238
+ });
2239
+
2240
+ // src/elements/ButtonGroupItem.jsx
2241
+ import React6 from "react";
2242
+ function ButtonGroupItem(_props) {
2243
+ return null;
1844
2244
  }
2245
+ ButtonGroupItem.displayName = "ButtonGroupItem";
1845
2246
  export {
1846
2247
  Button,
2248
+ ButtonGroup,
2249
+ ButtonGroupItem,
2250
+ IconButton,
1847
2251
  MenuButton
1848
2252
  };
1849
2253
  /*! Bundled license information:
package/package.json CHANGED
@@ -1,20 +1,22 @@
1
1
  {
2
2
  "name": "@edux-design/buttons",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "**/*.css"
7
7
  ],
8
+ "types": "./dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
10
11
  "import": "./dist/index.mjs",
11
- "require": "./dist/index.js"
12
+ "require": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
12
14
  }
13
15
  },
14
16
  "scripts": {
15
17
  "lint": "eslint . --max-warnings 0",
16
- "build": "tsup src/index.js --format esm,cjs",
17
- "dev": "tsup src/index.js --watch --format esm,cjs",
18
+ "build": "tsup src/index.js --format esm,cjs --dts",
19
+ "dev": "tsup src/index.js --watch --format esm,cjs --dts",
18
20
  "generate:component": "turbo gen react-component",
19
21
  "check-types": "tsc --noEmit"
20
22
  },
@@ -0,0 +1,84 @@
1
+ import React from "react";
2
+ import { Button, IconButton } from "./../index";
3
+ import { Close } from "@edux-design/icons";
4
+
5
+ export default {
6
+ title: "Components/Button",
7
+ component: Button,
8
+ argTypes: {
9
+ size: {
10
+ control: { type: "select" },
11
+ options: ["small", "medium", "large"],
12
+ },
13
+ isSecondary: { control: "boolean" },
14
+ isDanger: { control: "boolean" },
15
+ isBare: { control: "boolean" },
16
+ isStretched: { control: "boolean" },
17
+ disabled: { control: "boolean" },
18
+ children: { control: "text" },
19
+ },
20
+ };
21
+
22
+ // Base template
23
+ const Template = (args) => <Button {...args} />;
24
+
25
+ // Default story
26
+ export const Primary = Template.bind({});
27
+ Primary.args = {
28
+ children: "Primary Button",
29
+ size: "medium",
30
+ };
31
+
32
+ // Variants
33
+ export const Secondary = Template.bind({});
34
+ Secondary.args = {
35
+ children: "Secondary Button",
36
+ isSecondary: true,
37
+ };
38
+
39
+ export const Danger = Template.bind({});
40
+ Danger.args = {
41
+ children: "Delete",
42
+ isDanger: true,
43
+ };
44
+
45
+ export const Bare = Template.bind({});
46
+ Bare.args = {
47
+ children: "Bare Button",
48
+ isBare: true,
49
+ };
50
+
51
+ export const Disabled = Template.bind({});
52
+ Disabled.args = {
53
+ children: "Disabled",
54
+ disabled: true,
55
+ };
56
+
57
+ // Sizes
58
+ export const Small = Template.bind({});
59
+ Small.args = {
60
+ children: "Small",
61
+ size: "small",
62
+ };
63
+
64
+ export const Large = Template.bind({});
65
+ Large.args = {
66
+ children: "Large",
67
+ size: "large",
68
+ };
69
+
70
+ // Stretched (full width)
71
+ export const Stretched = Template.bind({});
72
+ Stretched.args = {
73
+ children: "Full Width",
74
+ isStretched: true,
75
+ };
76
+
77
+ export const Default = () => (
78
+ <div className="flex gap-4 items-center">
79
+ <IconButton icon={<Close />} aria-label="Close" isBare />
80
+ <IconButton icon={<Close />} isSecondary aria-label="Close" />
81
+ <IconButton icon={<Close />} isDanger aria-label="Delete" />
82
+ <IconButton icon={<Close />} disabled aria-label="Disabled" />
83
+ </div>
84
+ );