@spark-web/action-dropdown 1.0.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,38 @@
1
+ # @spark-web/action-dropdown
2
+
3
+ ## 1.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#748](https://github.com/brighte-labs/spark-web/pull/748)
8
+ [`17d237b`](https://github.com/brighte-labs/spark-web/commit/17d237b97cf01c3b97f0440d49c6d82dd821c905)
9
+ Thanks [@jacobporci-brighte](https://github.com/jacobporci-brighte)! - add
10
+ @spark-web/combobox as a dependency
11
+
12
+ ## 1.0.0
13
+
14
+ ### Major Changes
15
+
16
+ - [#745](https://github.com/brighte-labs/spark-web/pull/745)
17
+ [`d64cd8f`](https://github.com/brighte-labs/spark-web/commit/d64cd8f8e1692992b4597b563b9ba0bdcda25f6c)
18
+ Thanks [@jacobporci-brighte](https://github.com/jacobporci-brighte)! - New
19
+ Action Dropdown component
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies
24
+ [[`80d9c15`](https://github.com/brighte-labs/spark-web/commit/80d9c156a40bbcd2b1a91a2d0403b3c8e9b47b4e)]:
25
+ - @spark-web/theme@5.13.0
26
+ - @spark-web/utils@5.1.0
27
+ - @spark-web/a11y@5.3.0
28
+ - @spark-web/icon@5.1.0
29
+ - @spark-web/text@5.3.0
30
+ - @spark-web/box@6.0.0
31
+
32
+ ## 1.0.0
33
+
34
+ ### Major Changes
35
+
36
+ - Initial release of ActionDropdown component
37
+ - Pill-shaped button that opens dropdown menu of actions
38
+ - Each action triggers onClick callback when selected
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # @spark-web/action-dropdown
2
+
3
+ A pill-shaped button component that displays a dropdown menu of actions when
4
+ clicked.
5
+
6
+ ## Usage
7
+
8
+ ```tsx
9
+ import { ActionDropdown } from '@spark-web/action-dropdown';
10
+
11
+ const MyComponent = () => (
12
+ <ActionDropdown
13
+ label="Actions"
14
+ actions={[
15
+ {
16
+ label: 'Edit',
17
+ value: 'edit',
18
+ onClick: data => console.log('Edit clicked', data),
19
+ data: { id: 1 },
20
+ },
21
+ {
22
+ label: 'Delete',
23
+ value: 'delete',
24
+ onClick: data => console.log('Delete clicked', data),
25
+ data: { id: 1 },
26
+ },
27
+ ]}
28
+ />
29
+ );
30
+ ```
@@ -0,0 +1,31 @@
1
+ import type { DataAttributeMap } from '@spark-web/utils/internal';
2
+ type ActionItem<T = unknown> = {
3
+ /** Display label for the action */
4
+ label: string;
5
+ /** Unique identifier for the action */
6
+ value: string;
7
+ /** Callback when this action is clicked */
8
+ onClick: (item: T) => void;
9
+ /** Additional data to pass to onClick */
10
+ data?: T;
11
+ /** Whether this action is disabled */
12
+ disabled?: boolean;
13
+ };
14
+ export type ActionDropdownProps<T = unknown> = {
15
+ /** Sets data attributes on the component. */
16
+ data?: DataAttributeMap;
17
+ /** The text to display on the button */
18
+ label: string;
19
+ /** Array of actions the user can select from */
20
+ actions: ActionItem<T>[];
21
+ /** Whether the dropdown is disabled */
22
+ disabled?: boolean;
23
+ /** Whether the menu should use a portal, and where it should attach. */
24
+ menuPortalTarget?: HTMLElement | null;
25
+ /** Width of the control button */
26
+ controlWidth?: string | number;
27
+ /** Width of the dropdown menu */
28
+ menuWidth?: string | number;
29
+ };
30
+ export declare const ActionDropdown: <T>({ data, label, actions, disabled, menuPortalTarget, controlWidth, menuWidth, }: ActionDropdownProps<T>) => import("@emotion/react/jsx-runtime").JSX.Element;
31
+ export {};
@@ -0,0 +1,2 @@
1
+ export type { ActionDropdownProps } from "./action-dropdown.js";
2
+ export { ActionDropdown } from "./action-dropdown.js";
@@ -0,0 +1,2 @@
1
+ export * from "./declarations/src/index.js";
2
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Bhcmstd2ViLWFjdGlvbi1kcm9wZG93bi5janMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4vZGVjbGFyYXRpb25zL3NyYy9pbmRleC5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIn0=
@@ -0,0 +1,169 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
6
+ var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
7
+ var a11y = require('@spark-web/a11y');
8
+ var reactSelectOverrides = require('@spark-web/combobox/src/react-select-overrides');
9
+ var icon = require('@spark-web/icon');
10
+ var text = require('@spark-web/text');
11
+ var theme = require('@spark-web/theme');
12
+ var ReactSelect = require('react-select');
13
+ var jsxRuntime = require('@emotion/react/jsx-runtime');
14
+
15
+ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
16
+
17
+ var ReactSelect__default = /*#__PURE__*/_interopDefault(ReactSelect);
18
+
19
+ var isBrowser = typeof window !== 'undefined';
20
+ var ActionDropdown = function ActionDropdown(_ref) {
21
+ _ref.data;
22
+ var label = _ref.label,
23
+ actions = _ref.actions,
24
+ _ref$disabled = _ref.disabled,
25
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
26
+ menuPortalTarget = _ref.menuPortalTarget,
27
+ controlWidth = _ref.controlWidth,
28
+ _ref$menuWidth = _ref.menuWidth,
29
+ menuWidth = _ref$menuWidth === void 0 ? '100%' : _ref$menuWidth;
30
+ var theme$1 = theme.useTheme();
31
+ var reactSelectTheme = reactSelectOverrides.useReactSelectThemeOverride();
32
+
33
+ // Use the same text styling as combobox
34
+ var _useText = text.useText({
35
+ baseline: false,
36
+ tone: 'neutral',
37
+ size: 'standard',
38
+ weight: 'regular'
39
+ }),
40
+ _useText2 = _slicedToArray(_useText, 2),
41
+ responsiveTextStyles = _useText2[0],
42
+ textStyles = _useText2[1];
43
+ var focusRingStyles = a11y.useFocusRing({
44
+ always: true
45
+ });
46
+
47
+ // Handle option selection - trigger the onClick callback
48
+ var handleChange = function handleChange(selectedOption) {
49
+ if (selectedOption !== null && selectedOption !== void 0 && selectedOption.onClick) {
50
+ selectedOption.onClick(selectedOption.data);
51
+ }
52
+ };
53
+
54
+ // Custom components
55
+ var customComponents = {
56
+ DropdownIndicator: function DropdownIndicator(props) {
57
+ return jsxRuntime.jsx(ReactSelect.components.DropdownIndicator, _objectSpread(_objectSpread({}, props), {}, {
58
+ children: jsxRuntime.jsx(icon.ChevronDownIcon, {
59
+ size: "xxsmall",
60
+ tone: "muted"
61
+ })
62
+ }));
63
+ },
64
+ IndicatorSeparator: function IndicatorSeparator() {
65
+ return null;
66
+ }
67
+ };
68
+
69
+ // Custom styles with text styling from combobox
70
+ var customStyles = {
71
+ control: function control(provided, state) {
72
+ var _theme$components$tex, _theme$components$tex2, _theme$components$tex3, _theme$components$tex4, _theme$components$tex5, _theme$components$tex6, _theme$components$tex7;
73
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), responsiveTextStyles), textStyles), {}, {
74
+ borderRadius: '24px',
75
+ minHeight: '48px',
76
+ paddingLeft: '16px',
77
+ paddingRight: '8px',
78
+ cursor: 'pointer',
79
+ width: controlWidth || 'auto',
80
+ minWidth: controlWidth || 'auto',
81
+ marginLeft: 'auto'
82
+ }, {
83
+ borderColor: (_theme$components$tex = theme$1.components.textInput) === null || _theme$components$tex === void 0 ? void 0 : _theme$components$tex.borderColor
84
+ }), state.isFocused ? (_theme$components$tex2 = (_theme$components$tex3 = theme$1.components.textInput) === null || _theme$components$tex3 === void 0 ? void 0 : _theme$components$tex3.focused) !== null && _theme$components$tex2 !== void 0 ? _theme$components$tex2 : focusRingStyles : (_theme$components$tex4 = theme$1.components.textInput) !== null && _theme$components$tex4 !== void 0 && _theme$components$tex4.boxShadow ? {
85
+ boxShadow: (_theme$components$tex5 = theme$1.components.textInput) === null || _theme$components$tex5 === void 0 ? void 0 : _theme$components$tex5.boxShadow
86
+ } : {}), (_theme$components$tex6 = theme$1.components.textInput) !== null && _theme$components$tex6 !== void 0 && _theme$components$tex6.hover ? {
87
+ ':hover': (_theme$components$tex7 = theme$1.components.textInput) === null || _theme$components$tex7 === void 0 ? void 0 : _theme$components$tex7.hover
88
+ } : {});
89
+ },
90
+ dropdownIndicator: function dropdownIndicator(provided, state) {
91
+ return _objectSpread(_objectSpread({}, provided), {}, {
92
+ transitionProperty: 'transform',
93
+ transitionTimingFunction: 'linear',
94
+ transitionDuration: '150ms'
95
+ }, state.isFocused ? {
96
+ transform: 'rotate(180deg)'
97
+ } : {});
98
+ },
99
+ singleValue: function singleValue(provided) {
100
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), responsiveTextStyles), textStyles), {}, {
101
+ fontWeight: '500',
102
+ color: 'inherit' // Use inherited text color
103
+ });
104
+ },
105
+ option: function option(provided, state) {
106
+ var _theme$components$tex8, _theme$components$tex9, _theme$components$tex0, _theme$components$tex1, _theme$components$tex10;
107
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), responsiveTextStyles), textStyles), {}, {
108
+ backgroundColor: 'transparent',
109
+ // Remove default background
110
+ color: 'inherit',
111
+ // Use inherited text color
112
+ borderRadius: (_theme$components$tex8 = theme$1.components.textInput) === null || _theme$components$tex8 === void 0 || (_theme$components$tex8 = _theme$components$tex8.menuOption) === null || _theme$components$tex8 === void 0 ? void 0 : _theme$components$tex8.borderRadius
113
+ }, state.isSelected && {
114
+ backgroundColor: (_theme$components$tex9 = theme$1.components.textInput) === null || _theme$components$tex9 === void 0 || (_theme$components$tex9 = _theme$components$tex9.menuOption) === null || _theme$components$tex9 === void 0 || (_theme$components$tex9 = _theme$components$tex9.selected) === null || _theme$components$tex9 === void 0 ? void 0 : _theme$components$tex9.backgroundColor,
115
+ color: (_theme$components$tex0 = theme$1.components.textInput) === null || _theme$components$tex0 === void 0 || (_theme$components$tex0 = _theme$components$tex0.menuOption) === null || _theme$components$tex0 === void 0 || (_theme$components$tex0 = _theme$components$tex0.selected) === null || _theme$components$tex0 === void 0 ? void 0 : _theme$components$tex0.color
116
+ }), state.isFocused && {
117
+ backgroundColor: (_theme$components$tex1 = theme$1.components.textInput) === null || _theme$components$tex1 === void 0 || (_theme$components$tex1 = _theme$components$tex1.menuOption) === null || _theme$components$tex1 === void 0 || (_theme$components$tex1 = _theme$components$tex1.focused) === null || _theme$components$tex1 === void 0 ? void 0 : _theme$components$tex1.backgroundColor,
118
+ color: 'inherit'
119
+ }), {}, {
120
+ '&:active': {
121
+ backgroundColor: (_theme$components$tex10 = theme$1.components.textInput) === null || _theme$components$tex10 === void 0 || (_theme$components$tex10 = _theme$components$tex10.menuOption) === null || _theme$components$tex10 === void 0 || (_theme$components$tex10 = _theme$components$tex10.active) === null || _theme$components$tex10 === void 0 ? void 0 : _theme$components$tex10.backgroundColor
122
+ }
123
+ });
124
+ },
125
+ menu: function menu(provided) {
126
+ var _theme$components$tex11, _theme$components$tex12, _theme$components$tex13;
127
+ return _objectSpread(_objectSpread({}, provided), {}, {
128
+ width: menuWidth,
129
+ minWidth: menuWidth,
130
+ padding: (_theme$components$tex11 = theme$1.components.textInput) === null || _theme$components$tex11 === void 0 || (_theme$components$tex11 = _theme$components$tex11.menu) === null || _theme$components$tex11 === void 0 ? void 0 : _theme$components$tex11.padding,
131
+ boxShadow: (_theme$components$tex12 = theme$1.components.textInput) === null || _theme$components$tex12 === void 0 || (_theme$components$tex12 = _theme$components$tex12.menu) === null || _theme$components$tex12 === void 0 ? void 0 : _theme$components$tex12.boxShadow,
132
+ borderRadius: (_theme$components$tex13 = theme$1.components.textInput) === null || _theme$components$tex13 === void 0 || (_theme$components$tex13 = _theme$components$tex13.menu) === null || _theme$components$tex13 === void 0 ? void 0 : _theme$components$tex13.borderRadius
133
+ });
134
+ },
135
+ menuList: function menuList(provided) {
136
+ return _objectSpread(_objectSpread({}, provided), {}, {
137
+ padding: 0,
138
+ display: 'flex',
139
+ flexDirection: 'column',
140
+ gap: theme$1.spacing.xsmall
141
+ });
142
+ }
143
+ };
144
+ return jsxRuntime.jsx(ReactSelect__default["default"], {
145
+ value: {
146
+ label: label,
147
+ value: 'current'
148
+ },
149
+ options: actions,
150
+ onChange: handleChange,
151
+ isDisabled: disabled,
152
+ isSearchable: false,
153
+ components: customComponents,
154
+ styles: _objectSpread(_objectSpread({}, customStyles), {}, {
155
+ menuPortal: function menuPortal(provided) {
156
+ return _objectSpread(_objectSpread({}, provided), {}, {
157
+ zIndex: theme$1.elevation.modal,
158
+ pointerEvents: 'all'
159
+ });
160
+ }
161
+ }),
162
+ menuPortalTarget: menuPortalTarget !== null && menuPortalTarget !== void 0 ? menuPortalTarget : isBrowser ? document.body : undefined,
163
+ blurInputOnSelect: true,
164
+ closeMenuOnSelect: true,
165
+ theme: reactSelectTheme
166
+ });
167
+ };
168
+
169
+ exports.ActionDropdown = ActionDropdown;
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ if (process.env.NODE_ENV === "production") {
4
+ module.exports = require("./spark-web-action-dropdown.cjs.prod.js");
5
+ } else {
6
+ module.exports = require("./spark-web-action-dropdown.cjs.dev.js");
7
+ }
@@ -0,0 +1,169 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
6
+ var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
7
+ var a11y = require('@spark-web/a11y');
8
+ var reactSelectOverrides = require('@spark-web/combobox/src/react-select-overrides');
9
+ var icon = require('@spark-web/icon');
10
+ var text = require('@spark-web/text');
11
+ var theme = require('@spark-web/theme');
12
+ var ReactSelect = require('react-select');
13
+ var jsxRuntime = require('@emotion/react/jsx-runtime');
14
+
15
+ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
16
+
17
+ var ReactSelect__default = /*#__PURE__*/_interopDefault(ReactSelect);
18
+
19
+ var isBrowser = typeof window !== 'undefined';
20
+ var ActionDropdown = function ActionDropdown(_ref) {
21
+ _ref.data;
22
+ var label = _ref.label,
23
+ actions = _ref.actions,
24
+ _ref$disabled = _ref.disabled,
25
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
26
+ menuPortalTarget = _ref.menuPortalTarget,
27
+ controlWidth = _ref.controlWidth,
28
+ _ref$menuWidth = _ref.menuWidth,
29
+ menuWidth = _ref$menuWidth === void 0 ? '100%' : _ref$menuWidth;
30
+ var theme$1 = theme.useTheme();
31
+ var reactSelectTheme = reactSelectOverrides.useReactSelectThemeOverride();
32
+
33
+ // Use the same text styling as combobox
34
+ var _useText = text.useText({
35
+ baseline: false,
36
+ tone: 'neutral',
37
+ size: 'standard',
38
+ weight: 'regular'
39
+ }),
40
+ _useText2 = _slicedToArray(_useText, 2),
41
+ responsiveTextStyles = _useText2[0],
42
+ textStyles = _useText2[1];
43
+ var focusRingStyles = a11y.useFocusRing({
44
+ always: true
45
+ });
46
+
47
+ // Handle option selection - trigger the onClick callback
48
+ var handleChange = function handleChange(selectedOption) {
49
+ if (selectedOption !== null && selectedOption !== void 0 && selectedOption.onClick) {
50
+ selectedOption.onClick(selectedOption.data);
51
+ }
52
+ };
53
+
54
+ // Custom components
55
+ var customComponents = {
56
+ DropdownIndicator: function DropdownIndicator(props) {
57
+ return jsxRuntime.jsx(ReactSelect.components.DropdownIndicator, _objectSpread(_objectSpread({}, props), {}, {
58
+ children: jsxRuntime.jsx(icon.ChevronDownIcon, {
59
+ size: "xxsmall",
60
+ tone: "muted"
61
+ })
62
+ }));
63
+ },
64
+ IndicatorSeparator: function IndicatorSeparator() {
65
+ return null;
66
+ }
67
+ };
68
+
69
+ // Custom styles with text styling from combobox
70
+ var customStyles = {
71
+ control: function control(provided, state) {
72
+ var _theme$components$tex, _theme$components$tex2, _theme$components$tex3, _theme$components$tex4, _theme$components$tex5, _theme$components$tex6, _theme$components$tex7;
73
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), responsiveTextStyles), textStyles), {}, {
74
+ borderRadius: '24px',
75
+ minHeight: '48px',
76
+ paddingLeft: '16px',
77
+ paddingRight: '8px',
78
+ cursor: 'pointer',
79
+ width: controlWidth || 'auto',
80
+ minWidth: controlWidth || 'auto',
81
+ marginLeft: 'auto'
82
+ }, {
83
+ borderColor: (_theme$components$tex = theme$1.components.textInput) === null || _theme$components$tex === void 0 ? void 0 : _theme$components$tex.borderColor
84
+ }), state.isFocused ? (_theme$components$tex2 = (_theme$components$tex3 = theme$1.components.textInput) === null || _theme$components$tex3 === void 0 ? void 0 : _theme$components$tex3.focused) !== null && _theme$components$tex2 !== void 0 ? _theme$components$tex2 : focusRingStyles : (_theme$components$tex4 = theme$1.components.textInput) !== null && _theme$components$tex4 !== void 0 && _theme$components$tex4.boxShadow ? {
85
+ boxShadow: (_theme$components$tex5 = theme$1.components.textInput) === null || _theme$components$tex5 === void 0 ? void 0 : _theme$components$tex5.boxShadow
86
+ } : {}), (_theme$components$tex6 = theme$1.components.textInput) !== null && _theme$components$tex6 !== void 0 && _theme$components$tex6.hover ? {
87
+ ':hover': (_theme$components$tex7 = theme$1.components.textInput) === null || _theme$components$tex7 === void 0 ? void 0 : _theme$components$tex7.hover
88
+ } : {});
89
+ },
90
+ dropdownIndicator: function dropdownIndicator(provided, state) {
91
+ return _objectSpread(_objectSpread({}, provided), {}, {
92
+ transitionProperty: 'transform',
93
+ transitionTimingFunction: 'linear',
94
+ transitionDuration: '150ms'
95
+ }, state.isFocused ? {
96
+ transform: 'rotate(180deg)'
97
+ } : {});
98
+ },
99
+ singleValue: function singleValue(provided) {
100
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), responsiveTextStyles), textStyles), {}, {
101
+ fontWeight: '500',
102
+ color: 'inherit' // Use inherited text color
103
+ });
104
+ },
105
+ option: function option(provided, state) {
106
+ var _theme$components$tex8, _theme$components$tex9, _theme$components$tex0, _theme$components$tex1, _theme$components$tex10;
107
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), responsiveTextStyles), textStyles), {}, {
108
+ backgroundColor: 'transparent',
109
+ // Remove default background
110
+ color: 'inherit',
111
+ // Use inherited text color
112
+ borderRadius: (_theme$components$tex8 = theme$1.components.textInput) === null || _theme$components$tex8 === void 0 || (_theme$components$tex8 = _theme$components$tex8.menuOption) === null || _theme$components$tex8 === void 0 ? void 0 : _theme$components$tex8.borderRadius
113
+ }, state.isSelected && {
114
+ backgroundColor: (_theme$components$tex9 = theme$1.components.textInput) === null || _theme$components$tex9 === void 0 || (_theme$components$tex9 = _theme$components$tex9.menuOption) === null || _theme$components$tex9 === void 0 || (_theme$components$tex9 = _theme$components$tex9.selected) === null || _theme$components$tex9 === void 0 ? void 0 : _theme$components$tex9.backgroundColor,
115
+ color: (_theme$components$tex0 = theme$1.components.textInput) === null || _theme$components$tex0 === void 0 || (_theme$components$tex0 = _theme$components$tex0.menuOption) === null || _theme$components$tex0 === void 0 || (_theme$components$tex0 = _theme$components$tex0.selected) === null || _theme$components$tex0 === void 0 ? void 0 : _theme$components$tex0.color
116
+ }), state.isFocused && {
117
+ backgroundColor: (_theme$components$tex1 = theme$1.components.textInput) === null || _theme$components$tex1 === void 0 || (_theme$components$tex1 = _theme$components$tex1.menuOption) === null || _theme$components$tex1 === void 0 || (_theme$components$tex1 = _theme$components$tex1.focused) === null || _theme$components$tex1 === void 0 ? void 0 : _theme$components$tex1.backgroundColor,
118
+ color: 'inherit'
119
+ }), {}, {
120
+ '&:active': {
121
+ backgroundColor: (_theme$components$tex10 = theme$1.components.textInput) === null || _theme$components$tex10 === void 0 || (_theme$components$tex10 = _theme$components$tex10.menuOption) === null || _theme$components$tex10 === void 0 || (_theme$components$tex10 = _theme$components$tex10.active) === null || _theme$components$tex10 === void 0 ? void 0 : _theme$components$tex10.backgroundColor
122
+ }
123
+ });
124
+ },
125
+ menu: function menu(provided) {
126
+ var _theme$components$tex11, _theme$components$tex12, _theme$components$tex13;
127
+ return _objectSpread(_objectSpread({}, provided), {}, {
128
+ width: menuWidth,
129
+ minWidth: menuWidth,
130
+ padding: (_theme$components$tex11 = theme$1.components.textInput) === null || _theme$components$tex11 === void 0 || (_theme$components$tex11 = _theme$components$tex11.menu) === null || _theme$components$tex11 === void 0 ? void 0 : _theme$components$tex11.padding,
131
+ boxShadow: (_theme$components$tex12 = theme$1.components.textInput) === null || _theme$components$tex12 === void 0 || (_theme$components$tex12 = _theme$components$tex12.menu) === null || _theme$components$tex12 === void 0 ? void 0 : _theme$components$tex12.boxShadow,
132
+ borderRadius: (_theme$components$tex13 = theme$1.components.textInput) === null || _theme$components$tex13 === void 0 || (_theme$components$tex13 = _theme$components$tex13.menu) === null || _theme$components$tex13 === void 0 ? void 0 : _theme$components$tex13.borderRadius
133
+ });
134
+ },
135
+ menuList: function menuList(provided) {
136
+ return _objectSpread(_objectSpread({}, provided), {}, {
137
+ padding: 0,
138
+ display: 'flex',
139
+ flexDirection: 'column',
140
+ gap: theme$1.spacing.xsmall
141
+ });
142
+ }
143
+ };
144
+ return jsxRuntime.jsx(ReactSelect__default["default"], {
145
+ value: {
146
+ label: label,
147
+ value: 'current'
148
+ },
149
+ options: actions,
150
+ onChange: handleChange,
151
+ isDisabled: disabled,
152
+ isSearchable: false,
153
+ components: customComponents,
154
+ styles: _objectSpread(_objectSpread({}, customStyles), {}, {
155
+ menuPortal: function menuPortal(provided) {
156
+ return _objectSpread(_objectSpread({}, provided), {}, {
157
+ zIndex: theme$1.elevation.modal,
158
+ pointerEvents: 'all'
159
+ });
160
+ }
161
+ }),
162
+ menuPortalTarget: menuPortalTarget !== null && menuPortalTarget !== void 0 ? menuPortalTarget : isBrowser ? document.body : undefined,
163
+ blurInputOnSelect: true,
164
+ closeMenuOnSelect: true,
165
+ theme: reactSelectTheme
166
+ });
167
+ };
168
+
169
+ exports.ActionDropdown = ActionDropdown;
@@ -0,0 +1,161 @@
1
+ import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
2
+ import _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray';
3
+ import { useFocusRing } from '@spark-web/a11y';
4
+ import { useReactSelectThemeOverride } from '@spark-web/combobox/src/react-select-overrides';
5
+ import { ChevronDownIcon } from '@spark-web/icon';
6
+ import { useText } from '@spark-web/text';
7
+ import { useTheme } from '@spark-web/theme';
8
+ import ReactSelect, { components } from 'react-select';
9
+ import { jsx } from '@emotion/react/jsx-runtime';
10
+
11
+ var isBrowser = typeof window !== 'undefined';
12
+ var ActionDropdown = function ActionDropdown(_ref) {
13
+ _ref.data;
14
+ var label = _ref.label,
15
+ actions = _ref.actions,
16
+ _ref$disabled = _ref.disabled,
17
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
18
+ menuPortalTarget = _ref.menuPortalTarget,
19
+ controlWidth = _ref.controlWidth,
20
+ _ref$menuWidth = _ref.menuWidth,
21
+ menuWidth = _ref$menuWidth === void 0 ? '100%' : _ref$menuWidth;
22
+ var theme = useTheme();
23
+ var reactSelectTheme = useReactSelectThemeOverride();
24
+
25
+ // Use the same text styling as combobox
26
+ var _useText = useText({
27
+ baseline: false,
28
+ tone: 'neutral',
29
+ size: 'standard',
30
+ weight: 'regular'
31
+ }),
32
+ _useText2 = _slicedToArray(_useText, 2),
33
+ responsiveTextStyles = _useText2[0],
34
+ textStyles = _useText2[1];
35
+ var focusRingStyles = useFocusRing({
36
+ always: true
37
+ });
38
+
39
+ // Handle option selection - trigger the onClick callback
40
+ var handleChange = function handleChange(selectedOption) {
41
+ if (selectedOption !== null && selectedOption !== void 0 && selectedOption.onClick) {
42
+ selectedOption.onClick(selectedOption.data);
43
+ }
44
+ };
45
+
46
+ // Custom components
47
+ var customComponents = {
48
+ DropdownIndicator: function DropdownIndicator(props) {
49
+ return jsx(components.DropdownIndicator, _objectSpread(_objectSpread({}, props), {}, {
50
+ children: jsx(ChevronDownIcon, {
51
+ size: "xxsmall",
52
+ tone: "muted"
53
+ })
54
+ }));
55
+ },
56
+ IndicatorSeparator: function IndicatorSeparator() {
57
+ return null;
58
+ }
59
+ };
60
+
61
+ // Custom styles with text styling from combobox
62
+ var customStyles = {
63
+ control: function control(provided, state) {
64
+ var _theme$components$tex, _theme$components$tex2, _theme$components$tex3, _theme$components$tex4, _theme$components$tex5, _theme$components$tex6, _theme$components$tex7;
65
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), responsiveTextStyles), textStyles), {}, {
66
+ borderRadius: '24px',
67
+ minHeight: '48px',
68
+ paddingLeft: '16px',
69
+ paddingRight: '8px',
70
+ cursor: 'pointer',
71
+ width: controlWidth || 'auto',
72
+ minWidth: controlWidth || 'auto',
73
+ marginLeft: 'auto'
74
+ }, {
75
+ borderColor: (_theme$components$tex = theme.components.textInput) === null || _theme$components$tex === void 0 ? void 0 : _theme$components$tex.borderColor
76
+ }), state.isFocused ? (_theme$components$tex2 = (_theme$components$tex3 = theme.components.textInput) === null || _theme$components$tex3 === void 0 ? void 0 : _theme$components$tex3.focused) !== null && _theme$components$tex2 !== void 0 ? _theme$components$tex2 : focusRingStyles : (_theme$components$tex4 = theme.components.textInput) !== null && _theme$components$tex4 !== void 0 && _theme$components$tex4.boxShadow ? {
77
+ boxShadow: (_theme$components$tex5 = theme.components.textInput) === null || _theme$components$tex5 === void 0 ? void 0 : _theme$components$tex5.boxShadow
78
+ } : {}), (_theme$components$tex6 = theme.components.textInput) !== null && _theme$components$tex6 !== void 0 && _theme$components$tex6.hover ? {
79
+ ':hover': (_theme$components$tex7 = theme.components.textInput) === null || _theme$components$tex7 === void 0 ? void 0 : _theme$components$tex7.hover
80
+ } : {});
81
+ },
82
+ dropdownIndicator: function dropdownIndicator(provided, state) {
83
+ return _objectSpread(_objectSpread({}, provided), {}, {
84
+ transitionProperty: 'transform',
85
+ transitionTimingFunction: 'linear',
86
+ transitionDuration: '150ms'
87
+ }, state.isFocused ? {
88
+ transform: 'rotate(180deg)'
89
+ } : {});
90
+ },
91
+ singleValue: function singleValue(provided) {
92
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), responsiveTextStyles), textStyles), {}, {
93
+ fontWeight: '500',
94
+ color: 'inherit' // Use inherited text color
95
+ });
96
+ },
97
+ option: function option(provided, state) {
98
+ var _theme$components$tex8, _theme$components$tex9, _theme$components$tex0, _theme$components$tex1, _theme$components$tex10;
99
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, provided), responsiveTextStyles), textStyles), {}, {
100
+ backgroundColor: 'transparent',
101
+ // Remove default background
102
+ color: 'inherit',
103
+ // Use inherited text color
104
+ borderRadius: (_theme$components$tex8 = theme.components.textInput) === null || _theme$components$tex8 === void 0 || (_theme$components$tex8 = _theme$components$tex8.menuOption) === null || _theme$components$tex8 === void 0 ? void 0 : _theme$components$tex8.borderRadius
105
+ }, state.isSelected && {
106
+ backgroundColor: (_theme$components$tex9 = theme.components.textInput) === null || _theme$components$tex9 === void 0 || (_theme$components$tex9 = _theme$components$tex9.menuOption) === null || _theme$components$tex9 === void 0 || (_theme$components$tex9 = _theme$components$tex9.selected) === null || _theme$components$tex9 === void 0 ? void 0 : _theme$components$tex9.backgroundColor,
107
+ color: (_theme$components$tex0 = theme.components.textInput) === null || _theme$components$tex0 === void 0 || (_theme$components$tex0 = _theme$components$tex0.menuOption) === null || _theme$components$tex0 === void 0 || (_theme$components$tex0 = _theme$components$tex0.selected) === null || _theme$components$tex0 === void 0 ? void 0 : _theme$components$tex0.color
108
+ }), state.isFocused && {
109
+ backgroundColor: (_theme$components$tex1 = theme.components.textInput) === null || _theme$components$tex1 === void 0 || (_theme$components$tex1 = _theme$components$tex1.menuOption) === null || _theme$components$tex1 === void 0 || (_theme$components$tex1 = _theme$components$tex1.focused) === null || _theme$components$tex1 === void 0 ? void 0 : _theme$components$tex1.backgroundColor,
110
+ color: 'inherit'
111
+ }), {}, {
112
+ '&:active': {
113
+ backgroundColor: (_theme$components$tex10 = theme.components.textInput) === null || _theme$components$tex10 === void 0 || (_theme$components$tex10 = _theme$components$tex10.menuOption) === null || _theme$components$tex10 === void 0 || (_theme$components$tex10 = _theme$components$tex10.active) === null || _theme$components$tex10 === void 0 ? void 0 : _theme$components$tex10.backgroundColor
114
+ }
115
+ });
116
+ },
117
+ menu: function menu(provided) {
118
+ var _theme$components$tex11, _theme$components$tex12, _theme$components$tex13;
119
+ return _objectSpread(_objectSpread({}, provided), {}, {
120
+ width: menuWidth,
121
+ minWidth: menuWidth,
122
+ padding: (_theme$components$tex11 = theme.components.textInput) === null || _theme$components$tex11 === void 0 || (_theme$components$tex11 = _theme$components$tex11.menu) === null || _theme$components$tex11 === void 0 ? void 0 : _theme$components$tex11.padding,
123
+ boxShadow: (_theme$components$tex12 = theme.components.textInput) === null || _theme$components$tex12 === void 0 || (_theme$components$tex12 = _theme$components$tex12.menu) === null || _theme$components$tex12 === void 0 ? void 0 : _theme$components$tex12.boxShadow,
124
+ borderRadius: (_theme$components$tex13 = theme.components.textInput) === null || _theme$components$tex13 === void 0 || (_theme$components$tex13 = _theme$components$tex13.menu) === null || _theme$components$tex13 === void 0 ? void 0 : _theme$components$tex13.borderRadius
125
+ });
126
+ },
127
+ menuList: function menuList(provided) {
128
+ return _objectSpread(_objectSpread({}, provided), {}, {
129
+ padding: 0,
130
+ display: 'flex',
131
+ flexDirection: 'column',
132
+ gap: theme.spacing.xsmall
133
+ });
134
+ }
135
+ };
136
+ return jsx(ReactSelect, {
137
+ value: {
138
+ label: label,
139
+ value: 'current'
140
+ },
141
+ options: actions,
142
+ onChange: handleChange,
143
+ isDisabled: disabled,
144
+ isSearchable: false,
145
+ components: customComponents,
146
+ styles: _objectSpread(_objectSpread({}, customStyles), {}, {
147
+ menuPortal: function menuPortal(provided) {
148
+ return _objectSpread(_objectSpread({}, provided), {}, {
149
+ zIndex: theme.elevation.modal,
150
+ pointerEvents: 'all'
151
+ });
152
+ }
153
+ }),
154
+ menuPortalTarget: menuPortalTarget !== null && menuPortalTarget !== void 0 ? menuPortalTarget : isBrowser ? document.body : undefined,
155
+ blurInputOnSelect: true,
156
+ closeMenuOnSelect: true,
157
+ theme: reactSelectTheme
158
+ });
159
+ };
160
+
161
+ export { ActionDropdown };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@spark-web/action-dropdown",
3
+ "version": "1.0.1",
4
+ "homepage": "https://github.com/brighte-labs/spark-web#readme",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/brighte-labs/spark-web.git",
8
+ "directory": "packages/action-dropdown"
9
+ },
10
+ "main": "dist/spark-web-action-dropdown.cjs.js",
11
+ "module": "dist/spark-web-action-dropdown.esm.js",
12
+ "files": [
13
+ "CHANGELOG.md",
14
+ "dist",
15
+ "README.md"
16
+ ],
17
+ "dependencies": {
18
+ "@babel/runtime": "^7.25.0",
19
+ "@emotion/react": "^11.14.0",
20
+ "@spark-web/a11y": "^5.3.0",
21
+ "@spark-web/box": "^6.0.0",
22
+ "@spark-web/combobox": "^6.0.0",
23
+ "@spark-web/icon": "^5.1.0",
24
+ "@spark-web/text": "^5.3.0",
25
+ "@spark-web/utils": "^5.1.0",
26
+ "react-select": "^5.4.0"
27
+ },
28
+ "devDependencies": {
29
+ "@spark-web/theme": "^5.13.0",
30
+ "@types/react": "^19.1.0",
31
+ "react": "^19.1.0"
32
+ },
33
+ "peerDependencies": {
34
+ "@spark-web/theme": "^5.13.0",
35
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
36
+ },
37
+ "engines": {
38
+ "node": ">=14"
39
+ }
40
+ }