@macive/ui 0.0.21 → 0.0.22

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.
@@ -26,10 +26,7 @@ exports.Banner = (0, react_1.forwardRef)(function Banner({ icon, action, seconda
26
26
  const { wrapperRef, handleKeyUp, handleBlur, handleMouseUp, shouldShowFocus } = useBannerFocus(bannerRef);
27
27
  const { defaultIcon, iconColor, ariaRoleType } = useBannerAttributes(status);
28
28
  const iconName = icon || defaultIcon;
29
- const className = (0, css_1.classNames)(Banner_classnames_1.default.Banner,
30
- // status && styles[variationName('status', status)],
31
- //@ts-expect-error unknown
32
- status && Banner_classnames_1.default[status], onDismiss && Banner_classnames_1.default.hasDismiss, shouldShowFocus && Banner_classnames_1.default.keyFocused, withinContentContainer ? Banner_classnames_1.default.withinContentContainer : Banner_classnames_1.default.withinPage);
29
+ const className = (0, css_1.classNames)(Banner_classnames_1.default.Banner, status && Banner_classnames_1.default[(0, css_1.variationName)('status', status)], onDismiss && Banner_classnames_1.default.hasDismiss, shouldShowFocus && Banner_classnames_1.default.keyFocused, withinContentContainer ? Banner_classnames_1.default.withinContentContainer : Banner_classnames_1.default.withinPage);
33
30
  let headingMarkup = null;
34
31
  if (title) {
35
32
  headingMarkup = ((0, jsx_runtime_1.jsx)(Text_1.Text, { as: 'h2', variant: 'headingMd', breakWord: true, children: title }));
@@ -0,0 +1,128 @@
1
+ 'use client';
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ComboSelect = void 0;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const HorizontalStack_1 = require("../HorizontalStack");
7
+ const Icons_1 = require("../Icons");
8
+ const react_1 = require("react");
9
+ const Tag_1 = require("../Tag");
10
+ const ActionList_1 = require("../ActionList");
11
+ const Checkbox_1 = require("../Checkbox");
12
+ const Icon_1 = require("../Icon");
13
+ const Text_1 = require("../Text");
14
+ const Popover_1 = require("../Popover");
15
+ const Button_1 = require("../Button");
16
+ const Spinner_1 = require("../Spinner");
17
+ const Listbox_1 = require("../Listbox");
18
+ const Combobox_1 = require("../Combobox");
19
+ function ComboSelect({ label, options: initialOptions, value, onChange, placeholder = 'Select options', disabled = false, error, allowCustom = true, loading = false, }) {
20
+ const [inputValue, setInputValue] = (0, react_1.useState)('');
21
+ const [filteredOptions, setFilteredOptions] = (0, react_1.useState)(initialOptions);
22
+ const [popoverActive, setPopoverActive] = (0, react_1.useState)(false);
23
+ // Include "Custom" option if allowed
24
+ const allOptions = (0, react_1.useMemo)(() => allowCustom ? [...initialOptions, { label: 'Custom', value: 'Custom' }] : initialOptions, [initialOptions, allowCustom]);
25
+ // Non-custom options for "Select All"
26
+ const nonCustomOptions = (0, react_1.useMemo)(() => allOptions.filter((option) => option.value !== 'Custom'), [allOptions]);
27
+ // Check if all non-custom options are selected
28
+ const isAllSelected = (0, react_1.useMemo)(() => nonCustomOptions.length > 0 &&
29
+ nonCustomOptions.every((option) => value.includes(option.value)), [nonCustomOptions, value]);
30
+ // Sync filteredOptions with allOptions when initialOptions changes
31
+ (0, react_1.useEffect)(() => {
32
+ if (inputValue === '') {
33
+ setFilteredOptions(allOptions);
34
+ }
35
+ else {
36
+ const filterRegex = new RegExp(escapeSpecialRegExCharacters(inputValue), 'i');
37
+ setFilteredOptions(allOptions.filter((option) => option.label.match(filterRegex)));
38
+ }
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40
+ }, [allOptions, inputValue]);
41
+ // Escape special regex characters for filtering
42
+ const escapeSpecialRegExCharacters = (0, react_1.useCallback)((str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), []);
43
+ // Update filtered options based on input
44
+ const updateText = (0, react_1.useCallback)((text) => {
45
+ setInputValue(text);
46
+ if (text === '') {
47
+ setFilteredOptions(allOptions);
48
+ return;
49
+ }
50
+ const filterRegex = new RegExp(escapeSpecialRegExCharacters(text), 'i');
51
+ setFilteredOptions(allOptions.filter((option) => option.label.match(filterRegex)));
52
+ }, [allOptions, escapeSpecialRegExCharacters]);
53
+ // Handle individual option selection
54
+ const handleSelect = (0, react_1.useCallback)((selectedValue) => {
55
+ if (!value.includes(selectedValue)) {
56
+ const newValues = [...value, selectedValue];
57
+ onChange(newValues);
58
+ }
59
+ setInputValue('');
60
+ setFilteredOptions(allOptions);
61
+ }, [value, onChange, allOptions]);
62
+ // Handle tag removal
63
+ const handleRemove = (0, react_1.useCallback)((removedValue) => {
64
+ const newValues = value.filter((v) => v !== removedValue);
65
+ onChange(newValues);
66
+ }, [value, onChange]);
67
+ // Handle "Select All" checkbox toggle
68
+ const handleSelectAll = (0, react_1.useCallback)((checked) => {
69
+ if (checked) {
70
+ // Select all non-custom options, preserving existing custom selections
71
+ const newValues = [
72
+ ...value.filter((v) => v === 'Custom' || !nonCustomOptions.some((o) => o.value === v)),
73
+ ...nonCustomOptions.map((o) => o.value),
74
+ ];
75
+ onChange(newValues);
76
+ }
77
+ else {
78
+ // Deselect all non-custom options, preserving custom selections
79
+ const newValues = value.filter((v) => v === 'Custom' || !nonCustomOptions.some((o) => o.value === v));
80
+ onChange(newValues);
81
+ }
82
+ }, [value, onChange, nonCustomOptions]);
83
+ // Toggle popover visibility
84
+ const togglePopoverActive = (0, react_1.useCallback)(() => {
85
+ setPopoverActive((prev) => !prev);
86
+ }, []);
87
+ // Compute insightful popover trigger text
88
+ const popoverTriggerText = (0, react_1.useMemo)(() => {
89
+ if (value.length === 0)
90
+ return 'No items selected';
91
+ const selectedLabels = value
92
+ .map((val) => { var _a; return ((_a = allOptions.find((opt) => opt.value === val)) === null || _a === void 0 ? void 0 : _a.label) || val; })
93
+ .filter(Boolean);
94
+ if (value.length === 1)
95
+ return `${selectedLabels[0]} selected`;
96
+ if (value.length === 2)
97
+ return `${selectedLabels[0]}, ${selectedLabels[1]} selected`;
98
+ return `${selectedLabels[0]}, ${selectedLabels[1]}, and ${value.length - 2} others selected`;
99
+ }, [value, allOptions]);
100
+ // Compute accessibility label for popover button
101
+ const popoverAccessibilityLabel = (0, react_1.useMemo)(() => {
102
+ const selectedLabels = value
103
+ .map((val) => { var _a; return ((_a = allOptions.find((opt) => opt.value === val)) === null || _a === void 0 ? void 0 : _a.label) || val; })
104
+ .filter(Boolean);
105
+ return `View ${value.length} selected items: ${selectedLabels.join(', ')}`;
106
+ }, [value, allOptions]);
107
+ // Render selected values as inline tags (up to 4)
108
+ const inlineTagsMarkup = value.length > 0 && value.length <= 4 && ((0, jsx_runtime_1.jsx)(HorizontalStack_1.HorizontalStack, { blockAlign: 'center', gap: '2', children: value.map((val) => {
109
+ const option = allOptions.find((opt) => opt.value === val);
110
+ return ((0, jsx_runtime_1.jsx)(Tag_1.Tag, { onRemove: () => handleRemove(val), disabled: disabled, children: (option === null || option === void 0 ? void 0 : option.label) || val }, val));
111
+ }) }));
112
+ // Render selected values in popover (when > 4)
113
+ const popoverContent = ((0, jsx_runtime_1.jsx)("div", { style: { padding: '1rem', maxHeight: '10rem', overflowY: 'auto', width: '300px' }, children: value.length > 0 ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(ActionList_1.ActionList, { items: value.map((val) => {
114
+ var _a, _b;
115
+ return ({
116
+ content: `${((_a = allOptions.find((opt) => opt.value === val)) === null || _a === void 0 ? void 0 : _a.label) || val}`,
117
+ onAction: () => handleRemove(val),
118
+ prefix: ((0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { label: `${((_b = allOptions.find((opt) => opt.value === val)) === null || _b === void 0 ? void 0 : _b.label) || val}`, labelHidden: true, readOnly: true, checked: true })),
119
+ suffix: (0, jsx_runtime_1.jsx)(Icon_1.Icon, { color: 'critical', source: Icons_1.MaClose }),
120
+ });
121
+ }) }) })) : ((0, jsx_runtime_1.jsx)(Text_1.Text, { as: 'p', variant: 'bodySm', color: 'subdued', children: "No items selected" })) }));
122
+ // Render popover trigger when > 4 items
123
+ const popoverMarkup = value.length > 4 && ((0, jsx_runtime_1.jsx)("div", { className: 'mt-2', children: (0, jsx_runtime_1.jsx)(Popover_1.Popover, { active: popoverActive, activator: (0, jsx_runtime_1.jsx)(Button_1.Button, { onClick: togglePopoverActive, disclosure: true, variant: 'tertiary', plain: true, accessibilityLabel: popoverAccessibilityLabel, children: popoverTriggerText }), onClose: togglePopoverActive, ariaHaspopup: 'listbox', children: popoverContent }) }));
124
+ // Render dropdown content
125
+ const dropdownContent = loading ? ((0, jsx_runtime_1.jsx)("div", { className: 'p-2 flex justify-center', children: (0, jsx_runtime_1.jsx)(Spinner_1.Spinner, { accessibilityLabel: 'Loading options', size: 'small' }) })) : filteredOptions.length > 0 ? ((0, jsx_runtime_1.jsx)(Listbox_1.Listbox, { onSelect: handleSelect, children: filteredOptions.map((option) => ((0, jsx_runtime_1.jsx)(Listbox_1.Listbox.Option, { value: option.value, selected: value.includes(option.value), accessibilityLabel: option.label, children: option.label }, option.value))) })) : inputValue && !loading ? ((0, jsx_runtime_1.jsx)(Text_1.Text, { as: 'p', variant: 'bodySm', color: 'subdued', children: "No options found" })) : null;
126
+ return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(Combobox_1.Combobox, { allowMultiple: true, activator: (0, jsx_runtime_1.jsx)(Combobox_1.Combobox.TextField, { label: label, value: inputValue, onChange: updateText, placeholder: placeholder, autoComplete: 'off', disabled: disabled, error: error, suffix: (0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { label: 'Select All', labelHidden: true, checked: isAllSelected, onChange: handleSelectAll, disabled: disabled, "aria-label": 'Toggle selection of all options' }) }), children: dropdownContent }), inlineTagsMarkup || popoverMarkup] }));
127
+ }
128
+ exports.ComboSelect = ComboSelect;
@@ -32,6 +32,6 @@ function EmptyState({ children, heading, image, largeImage, imageContained, full
32
32
  const detailsMarkup = textContentMarkup || actionsMarkup || footerContentMarkup ? ((0, jsx_runtime_1.jsx)(Box_1.Box, { maxWidth: fullWidth ? '100%' : '400px', children: (0, jsx_runtime_1.jsxs)(VerticalStack_1.VerticalStack, { inlineAlign: 'center',
33
33
  //@ts-expect-error
34
34
  gap: 4, children: [textContentMarkup, actionsMarkup, footerContentMarkup] }) })) : null;
35
- return ((0, jsx_runtime_1.jsx)(Box_1.Box, { paddingInlineStart: '0', paddingInlineEnd: '0', paddingBlockStart: '5', paddingBlockEnd: '16', children: (0, jsx_runtime_1.jsxs)(VerticalStack_1.VerticalStack, { inlineAlign: 'center', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex w-full items-center justify-center', children: [" ", imageMarkup] }), detailsMarkup] }) }));
35
+ return ((0, jsx_runtime_1.jsx)(Box_1.Box, { paddingInlineStart: '0', paddingInlineEnd: '0', paddingBlockStart: '5', paddingBlockEnd: '16', children: (0, jsx_runtime_1.jsxs)(VerticalStack_1.VerticalStack, { inlineAlign: 'center', children: [(0, jsx_runtime_1.jsxs)("div", { children: [" ", imageMarkup] }), detailsMarkup] }) }));
36
36
  }
37
37
  exports.EmptyState = EmptyState;
package/dist/src/index.js CHANGED
@@ -16,7 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.hsbToHex = exports.hexToRgb = exports.capitalize = exports.Upload = exports.FileViewer = exports.TopBar = exports.Toast = exports.Switch = exports.SkeletonThumbnail = exports.SkeletonTabs = exports.SkeletonTable = exports.SkeletonPage = exports.SkeletonDisplayText = exports.SkeletonBodyText = exports.Scrollable = exports.ResourceList = exports.ResourceItem = exports.PaginationV1 = exports.VerticalSingleMenuItem = exports.VerticalCollapsedMenuItem = exports.CollapsedMenuItemList = exports.isNavigationItemActive = exports.Navigation = exports.Loading = exports.Layout = exports.Input = exports.InlineError = exports.Indicator = exports.IndexTable = exports.useSetIndexFiltersMode = exports.IndexFiltersMode = exports.IndexFilters = exports.FlexBox = exports.DatePicker = exports.DataTable = exports.ContextualSaveBar = exports.ChoiceCard = exports.CheckboxTree = exports.ButtonGroup = exports.buttonsFrom = exports.buttonFrom = exports.CopyButton = exports.Button = exports.BadgeStatusValue = exports.BadgeProgressValue = exports.Badge = exports.Avatar = exports.Tabs = exports.AlphaTabs = exports.ActionList = void 0;
19
- exports.useIndexResourceState = exports.renderSafeTemplate = exports.useFrame = exports.useDeviceType = exports.cn = exports.rgbaString = exports.rgbToHsl = exports.rgbToHsb = exports.rgbToHex = exports.rgbString = exports.hslToRgb = exports.hsbToRgb = void 0;
19
+ exports.ComboSelect = exports.useIndexResourceState = exports.renderSafeTemplate = exports.useFrame = exports.useDeviceType = exports.cn = exports.rgbaString = exports.rgbToHsl = exports.rgbToHsb = exports.rgbToHex = exports.rgbString = exports.hslToRgb = exports.hsbToRgb = void 0;
20
20
  __exportStar(require("./components"), exports);
21
21
  var ActionList_1 = require("./components/ActionList");
22
22
  Object.defineProperty(exports, "ActionList", { enumerable: true, get: function () { return ActionList_1.ActionList; } });
@@ -122,3 +122,5 @@ var renderSafeTemplate_1 = require("./utilities/renderSafeTemplate");
122
122
  Object.defineProperty(exports, "renderSafeTemplate", { enumerable: true, get: function () { return renderSafeTemplate_1.renderSafeTemplate; } });
123
123
  var use_index_resource_state_1 = require("./utilities/use-index-resource-state");
124
124
  Object.defineProperty(exports, "useIndexResourceState", { enumerable: true, get: function () { return use_index_resource_state_1.useIndexResourceState; } });
125
+ var ComboSelect_1 = require("./components/ComboSelect/ComboSelect");
126
+ Object.defineProperty(exports, "ComboSelect", { enumerable: true, get: function () { return ComboSelect_1.ComboSelect; } });