@crab-dev/rc-select 0.0.5 → 0.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # @crab-dev/rc-select
2
2
 
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903) Thanks [@hotlif](https://github.com/hotlif)! - Rebuild the component library around a single package inventory, independent architecture and usage classifications, and three design systems: MD3 Expressive (md3), Apple (apple), and shadcn/ui (shadcn).
8
+
9
+ This is a breaking pre-1.0 migration: unify controlled/uncontrolled values, selection callbacks, component APIs, sizes, and density contracts; replace legacy theme identifiers and remove old API aliases. Only stored browser appearance preferences are migrated automatically.
10
+
11
+ Declare required React/ReactDOM ^19.2.0 peers through runtime dependency chains while retaining development dependencies. Correct runtime token dependencies, public/internal exports, strict declaration consumption, and independent offline PnP package verification.
12
+
13
+ Correct RTL layout and overlay placement, field validation placement, embedded editor composition and focus, native virtual-scroll synchronization, and composed button feedback. Define independent multiline field geometry and preserve all eight configuration axes across controlled previews and PDF Web Components. Built-in error messages follow locale without replacing application-owned error data.
14
+
15
+ Restore compiled focus and disabled styles by using valid CSS template comments, keep Tree focus indicators inside measured containers and above selected row backgrounds, accommodate localized color-channel labels, preserve physical Table column geometry with RTL content, and accept PDF byte sources from iframe realms without treating them as URLs. Respect reduced motion in the property-driven Canvas animation example and let the pill Tabs example inherit the configured size.
16
+
17
+ Follow .website/docs/guides/migration.mdx before upgrading. All affected packages remain experimental; minor bumps represent the coordinated pre-1.0 breaking release and do not declare a stable 1.0 contract.
18
+
19
+ ### Patch Changes
20
+
21
+ - [`ec1f759`](https://github.com/hotlif/crab-dev/commit/ec1f759d51a83a456b4eb7f608f2e4908d4d46da) Thanks [@hotlif](https://github.com/hotlif)! - 补齐选择、导航和浮层的三体系规格、公开示例与包内 Playwright 状态矩阵,覆盖真实键盘、Portal 配置与草稿保留。颜色面板的轨道、宽度与操作间距归入组件令牌,窄屏操作区支持换行,强制颜色下保留清晰的触发器焦点边界。
22
+
23
+ 恢复颜色选择器公开的 showEyeDropper 屏幕取色入口,按所属浏览器能力显示,取消或拒绝不改值,卸载中止原生取色会话。
24
+
25
+ 补充水平与折叠菜单真实展开、Dialog 确认/取消 pending 动态场景,以及 Drawer 包公开的 iframe/Shadow DOM 组合示例;分别记录共享底层回归与真实浏览器验收范围,保留未运行、未复审部分。
26
+
27
+ - [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903) Thanks [@hotlif](https://github.com/hotlif)! - Restore focus after an accepted keyboard tab close, position Select popups outside their own supporting text, preserve design-specific disabled placeholders, and keep menu focus and color trigger feedback visible. Fix the appointment dialog example to retain Form's grid layout.
28
+
29
+ Register dropdown Escape layers when delayed Portal elements actually mount, and preserve explicit close reasons and native events through consumer dispatch.
30
+
31
+ Use the date placeholder for the appointment form's empty state instead of presenting a fake selected value.
32
+ - Updated dependencies [[`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`ec1f759`](https://github.com/hotlif/crab-dev/commit/ec1f759d51a83a456b4eb7f608f2e4908d4d46da), [`ec1f759`](https://github.com/hotlif/crab-dev/commit/ec1f759d51a83a456b4eb7f608f2e4908d4d46da), [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`ec1f759`](https://github.com/hotlif/crab-dev/commit/ec1f759d51a83a456b4eb7f608f2e4908d4d46da), [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`ec1f759`](https://github.com/hotlif/crab-dev/commit/ec1f759d51a83a456b4eb7f608f2e4908d4d46da), [`ec1f759`](https://github.com/hotlif/crab-dev/commit/ec1f759d51a83a456b4eb7f608f2e4908d4d46da), [`ec1f759`](https://github.com/hotlif/crab-dev/commit/ec1f759d51a83a456b4eb7f608f2e4908d4d46da), [`ec1f759`](https://github.com/hotlif/crab-dev/commit/ec1f759d51a83a456b4eb7f608f2e4908d4d46da), [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`d11001f`](https://github.com/hotlif/crab-dev/commit/d11001fa35d4af4f53d0571c074de4b3e9806903), [`ec1f759`](https://github.com/hotlif/crab-dev/commit/ec1f759d51a83a456b4eb7f608f2e4908d4d46da)]:
33
+ - @crab-dev/rc-dropdown-container@0.1.0
34
+ - @crab-dev/rc-hooks@0.1.0
35
+ - @crab-dev/rc-tag@0.1.0
36
+ - @crab-dev/rc-button@1.0.0
37
+ - @crab-dev/rc-checkbox@0.1.0
38
+ - @crab-dev/rc-config-provider@0.1.0
39
+ - @crab-dev/rc-line-edit@0.1.0
40
+ - @crab-dev/rc-spin@0.1.0
41
+ - @crab-dev/rc-token-semantic@1.0.0
42
+ - @crab-dev/rc-virtual@0.2.0
43
+
3
44
  ## 0.0.5
4
45
 
5
46
  ### Patch Changes
@@ -2,11 +2,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
2
2
  const __wake_namespace_0 = require("react/jsx-runtime");
3
3
  const __wake_namespace_1 = require("@crab-dev/rc-config-provider");
4
4
  const __wake_namespace_2 = require("@crab-dev/rc-dropdown-container");
5
- const __wake_namespace_3 = require("react");
6
- const __wake_namespace_4 = require("@crab-dev/rc-hooks");
7
- const __wake_namespace_5 = require("./hooks/useKeyboardNavigation.cjs");
8
- const __wake_namespace_6 = require("./selectInput.cjs");
9
- const __wake_namespace_7 = require("./selectOverlay.cjs");
5
+ const __wake_namespace_3 = require("@crab-dev/rc-dropdown-container/internal");
6
+ require("@crab-dev/rc-token-semantic");
7
+ const __wake_namespace_4 = require("react");
8
+ ;
9
+ const __wake_namespace_5 = require("@crab-dev/rc-hooks");
10
+ const __wake_namespace_6 = require("./hooks/useKeyboardNavigation.cjs");
11
+ const __wake_namespace_7 = require("./selectInput.cjs");
12
+ const __wake_namespace_8 = require("./selectOverlay.cjs");
10
13
  require("./token.cjs");
11
14
  ;
12
15
  const isGroup = (item) => "options" in item && Array.isArray(item.options);
@@ -61,26 +64,30 @@ const filterOptions = (flatOptions, searchable, searchText) => {
61
64
  const firstEnabledIndex = (flatOptions) => flatOptions.findIndex((opt) => !opt.disabled && !opt.isGroupLabel);
62
65
  const fieldStyle = "rc-select-0f3ecf945b98";
63
66
  const supportingStyle = "rc-select-3bd2a27273ad";
64
- const Select = ({ ref, id, options, placeholder = "请选择", disabled = false, searchable = false, multiple = false, size: sizeProp, status, appearance = "outlined", label, supportingText, errorText, required, allowClear = false, loading = false, maxTagCount, autoFocus = false, notFoundContent, popupClassName, popupMatchSelectWidth = true, optionRender, tagRender, dropdownRender, value, defaultValue, onChange, onOpenChange, onFocus, onBlur, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, ...restProps }) => {
67
+ function SelectField({ children }) {
68
+ const setPositionReference = (0, __wake_namespace_3["useDropdownPositionReference"])();
69
+ return (0, __wake_namespace_0["jsx"])("div", { className: fieldStyle, ref: setPositionReference, children: children });
70
+ }
71
+ function Select({ ref, id, options, placeholder, disabled = false, searchable = false, multiple = false, size: sizeProp, status, appearance = "outlined", label, supportingText, errorText, required, allowClear = false, loading = false, maxTagCount, autoFocus = false, notFoundContent, popupClassName, popupMatchSelectWidth = true, optionRender, tagRender, dropdownRender, value, defaultValue, onValueChange, open, defaultOpen, onOpenChange, onFocus, onBlur, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, ...restProps }) {
65
72
  const size = (0, __wake_namespace_1["useComponentSize"])(sizeProp);
66
- const listboxId = (0, __wake_namespace_3["useId"])();
67
- const generatedId = (0, __wake_namespace_3["useId"])();
73
+ const { messages } = (0, __wake_namespace_1["useLocale"])();
74
+ const listboxId = (0, __wake_namespace_4["useId"])();
75
+ const generatedId = (0, __wake_namespace_4["useId"])();
68
76
  const inputId = id ?? generatedId;
69
77
  const labelId = `${generatedId}-label`;
70
78
  const descriptionId = `${generatedId}-description`;
71
79
  const fieldStatus = errorText ? "error" : status;
72
80
  const description = errorText || supportingText;
73
- const [searchText, setSearchText] = (0, __wake_namespace_3["useState"])("");
74
- const [selectedValues, setSelectedValues] = (0, __wake_namespace_4["useControllableValue"])({ value: value !== undefined ? asArray(value) : undefined, defaultValue: asArray(defaultValue) });
75
- const [triggerWidth, setTriggerWidth] = (0, __wake_namespace_3["useState"])(0);
76
- const onOpenChangeRef = (0, __wake_namespace_3["useRef"])(onOpenChange);
77
- onOpenChangeRef.current = onOpenChange;
81
+ const [searchText, setSearchText] = (0, __wake_namespace_4["useState"])("");
82
+ const [selectedValues, setSelectedValues] = (0, __wake_namespace_5["useControllableValue"])({ value: value !== undefined ? asArray(value) : undefined, defaultValue: asArray(defaultValue) });
83
+ const [triggerWidth, setTriggerWidth] = (0, __wake_namespace_4["useState"])(0);
84
+ const controlRef = (0, __wake_namespace_4["useRef"])(null);
78
85
  const allPlainOptions = flattenPlainOptions(options);
79
86
  const selectedOptions = allPlainOptions.filter((opt) => selectedValues.includes(opt.value));
80
87
  const flatOptions = flattenOptions(options);
81
88
  const filteredOptions = filterOptions(flatOptions, searchable, searchText);
82
- const { highlightIndex, highlightedOption, moveHighlight, resetHighlight, setHighlightIndex } = (0, __wake_namespace_5 && __wake_namespace_5.__esModule ? __wake_namespace_5.default : __wake_namespace_5)({ filteredOptions, open: true });
83
- const emitOpenChange = (nextOpen) => {
89
+ const { highlightIndex, highlightedOption, moveHighlight, resetHighlight, setHighlightIndex } = (0, __wake_namespace_6 && __wake_namespace_6.__esModule ? __wake_namespace_6.default : __wake_namespace_6)({ filteredOptions, open: true });
90
+ const syncOpenState = (nextOpen) => {
84
91
  if (nextOpen) {
85
92
  if (!multiple && selectedValues.length > 0) {
86
93
  const selectedIndex = filteredOptions.findIndex((opt) => opt.value === selectedValues[0]);
@@ -90,49 +97,58 @@ const Select = ({ ref, id, options, placeholder = "请选择", disabled = false,
90
97
  setSearchText("");
91
98
  resetHighlight();
92
99
  }
93
- onOpenChangeRef.current?.(nextOpen);
94
100
  };
95
- const updateValue = (nextValues) => {
101
+ const emitOpenChange = (nextOpen, details) => {
102
+ onOpenChange?.(nextOpen, details);
103
+ };
104
+ const openProps = open === undefined ? { defaultOpen } : { open };
105
+ const updateValue = (nextValues, reason, event) => {
106
+ if (disabled) return;
107
+ if (nextValues.length === selectedValues.length && nextValues.every((item, index) => item === selectedValues[index])) return;
96
108
  setSelectedValues(nextValues);
97
109
  if (multiple) {
98
110
  const nextOptions = allPlainOptions.filter((opt) => nextValues.includes(opt.value));
99
- onChange?.(nextValues, nextOptions);
111
+ onValueChange?.(nextValues, { reason, options: nextOptions, event });
100
112
  return;
101
113
  }
102
114
  const nextValue = nextValues[0] ?? null;
103
115
  const nextOption = allPlainOptions.find((opt) => opt.value === nextValue);
104
- onChange?.(nextValue, nextOption);
116
+ onValueChange?.(nextValue, { reason, option: nextOption, options: nextOption ? [nextOption] : [], event });
105
117
  };
106
- const handleOptionSelect = (option) => {
107
- if (option.disabled || option.isGroupLabel) {
118
+ const handleOptionSelect = (option, event) => {
119
+ if (disabled || option.disabled || option.isGroupLabel) {
108
120
  return;
109
121
  }
110
122
  if (multiple) {
111
123
  const exists = selectedValues.includes(option.value);
112
124
  const nextValues = exists ? selectedValues.filter((v) => v !== option.value) : [...selectedValues, option.value];
113
- updateValue(nextValues);
125
+ updateValue(nextValues, exists ? "deselect" : "select", event);
114
126
  return;
115
127
  }
116
- updateValue([option.value]);
128
+ controlRef.current?.focus();
129
+ updateValue([option.value], "select", event);
117
130
  };
118
- const handleClear = () => {
119
- updateValue([]);
131
+ const handleClear = (event) => {
132
+ if (disabled) return;
133
+ updateValue([], "clear", event);
120
134
  setSearchText("");
121
135
  };
122
- const handleRemoveTag = (val) => {
123
- updateValue(selectedValues.filter((v) => v !== val));
136
+ const handleRemoveTag = (val, event) => {
137
+ updateValue(selectedValues.filter((v) => v !== val), "remove", event);
124
138
  };
125
139
  const handleTriggerWidthChange = (width) => {
126
140
  setTriggerWidth(width);
127
141
  };
128
142
  const handleSearchTextChange = (text) => {
143
+ if (disabled) return;
129
144
  setSearchText(text);
130
145
  const nextFiltered = filterOptions(flatOptions, searchable, text);
131
146
  setHighlightIndex(firstEnabledIndex(nextFiltered));
132
147
  };
133
148
  const floatingStyle = popupMatchSelectWidth ? { width: triggerWidth } : { minWidth: triggerWidth };
134
- return (0, __wake_namespace_0["jsx"])(__wake_namespace_2 && __wake_namespace_2.__esModule ? __wake_namespace_2.default : __wake_namespace_2, { size: size, ...restProps, className: className, overlay: (0, __wake_namespace_0["jsx"])(__wake_namespace_7 && __wake_namespace_7.__esModule ? __wake_namespace_7.default : __wake_namespace_7, { multiple: multiple, loading: loading, filteredOptions: filteredOptions, selectedValues: selectedValues, triggerWidth: triggerWidth, highlightIndex: highlightIndex, listboxId: listboxId, notFoundContent: notFoundContent, popupClassName: popupClassName, optionRender: optionRender, dropdownRender: dropdownRender, onOptionSelect: handleOptionSelect, onOpenChange: emitOpenChange, onHighlightChange: setHighlightIndex }), floatingContainerProps: { style: floatingStyle }, children: (0, __wake_namespace_0["jsxs"])("div", { className: fieldStyle, children: [(0, __wake_namespace_0["jsx"])(__wake_namespace_6 && __wake_namespace_6.__esModule ? __wake_namespace_6.default : __wake_namespace_6, { ref: ref, id: inputId, ariaLabel: ariaLabel, ariaLabelledBy: ariaLabelledBy ?? (label ? labelId : undefined), ariaDescribedBy: [ariaDescribedBy, description ? descriptionId : undefined].filter(Boolean).join(" ") || undefined, disabled: disabled, searchable: searchable, multiple: multiple, size: size, status: fieldStatus, appearance: appearance, label: label, labelId: labelId, required: required, allowClear: allowClear, loading: loading, maxTagCount: maxTagCount, autoFocus: autoFocus, placeholder: placeholder, selectedOptions: selectedOptions, searchText: searchText, highlightIndex: highlightIndex, highlightedOption: highlightedOption, listboxId: listboxId, tagRender: tagRender, onSearchTextChange: handleSearchTextChange, onOpenChange: emitOpenChange, onWidthChange: handleTriggerWidthChange, onMoveHighlight: moveHighlight, onSelectHighlighted: handleOptionSelect, onClear: handleClear, onRemoveTag: handleRemoveTag, onFocus: onFocus, onBlur: onBlur }), description && (0, __wake_namespace_0["jsx"])("div", { id: descriptionId, className: supportingStyle, "data-status": fieldStatus, children: description })] }) });
135
- };
149
+ return (0, __wake_namespace_0["jsx"])(__wake_namespace_2 && __wake_namespace_2.__esModule ? __wake_namespace_2.default : __wake_namespace_2, { ...openProps, onOpenChange: emitOpenChange, size: size, ...restProps, className: className, overlay: (0, __wake_namespace_0["jsx"])(__wake_namespace_8 && __wake_namespace_8.__esModule ? __wake_namespace_8.default : __wake_namespace_8, { size: size, multiple: multiple, disabled: disabled, loading: loading, filteredOptions: filteredOptions, selectedValues: selectedValues, triggerWidth: triggerWidth, highlightIndex: highlightIndex, listboxId: listboxId, notFoundContent: notFoundContent, popupClassName: popupClassName, optionRender: optionRender, dropdownRender: dropdownRender, onOptionSelect: handleOptionSelect, onHighlightChange: setHighlightIndex }), floatingContainerProps: { style: floatingStyle }, children: (0, __wake_namespace_0["jsxs"])(SelectField, { children: [(0, __wake_namespace_0["jsx"])(__wake_namespace_7 && __wake_namespace_7.__esModule ? __wake_namespace_7.default : __wake_namespace_7, { ref: ref, controlRef: controlRef, id: inputId, ariaLabel: ariaLabel, ariaLabelledBy: ariaLabelledBy ?? (label ? labelId : undefined), ariaDescribedBy: [ariaDescribedBy, description ? descriptionId : undefined].filter(Boolean).join(" ") || undefined, disabled: disabled, searchable: searchable, multiple: multiple, size: size, status: fieldStatus, appearance: appearance, label: label, labelId: labelId, required: required, allowClear: allowClear, loading: loading, maxTagCount: maxTagCount, autoFocus: autoFocus, placeholder: placeholder ?? messages.select.placeholder, selectedOptions: selectedOptions, searchText: searchText, highlightIndex: highlightIndex, highlightedOption: highlightedOption, listboxId: listboxId, tagRender: tagRender, onSearchTextChange: handleSearchTextChange, onOpenStateChange: syncOpenState, onWidthChange: handleTriggerWidthChange, onMoveHighlight: moveHighlight, onSelectHighlighted: handleOptionSelect, onClear: handleClear, onRemoveTag: handleRemoveTag, onFocus: onFocus, onBlur: onBlur }), description && (0, __wake_namespace_0["jsx"])("div", { id: descriptionId, className: supportingStyle, "data-status": fieldStatus, role: errorText ? "alert" : undefined, children: description })] }) });
150
+ }
151
+ ;
136
152
  const __wake_default_export = Select;
137
153
  Object.defineProperty(exports, "default", { enumerable: true, get: function() {
138
154
  return __wake_default_export;
@@ -6,9 +6,11 @@ const __wake_namespace_3 = require("@crab-dev/rc-button");
6
6
  const __wake_namespace_4 = require("@crab-dev/rc-spin");
7
7
  const __wake_namespace_5 = require("@crab-dev/rc-tag");
8
8
  const __wake_namespace_6 = require("@crab-dev/css");
9
- const __wake_namespace_7 = require("react");
9
+ const __wake_namespace_7 = require("@crab-dev/rc-config-provider");
10
+ const __wake_namespace_8 = require("react");
10
11
  require("./token.cjs");
11
12
  ;
13
+ const __wake_namespace_9 = require("./selectInput.styles.cjs");
12
14
  const setRef = (ref, node) => {
13
15
  if (typeof ref === "function") {
14
16
  ref(node);
@@ -16,37 +18,21 @@ const setRef = (ref, node) => {
16
18
  ref.current = node;
17
19
  }
18
20
  };
19
- const controlStyle = "rc-select-208f8e064cef";
20
- const materialFieldStyle = "rc-select-de4f87d60f05";
21
- const fieldLabelStyle = "rc-select-608ca49a02dc";
22
- const controlDisabledStyle = "rc-select-238e884e6a17";
23
- const controlErrorStyle = "rc-select-e0726e9ad481";
24
- const controlWarningStyle = "rc-select-79b739b32fcb";
25
- const valueWrapStyle = "rc-select-1356dfc74a7f";
26
- const singleValueStyle = "rc-select-52cbc5cc4f0f";
27
- const placeholderStyle = "rc-select-37ce25dfcd13";
28
- const searchInputStyle = "rc-select-50dd3c70bcdc";
29
- const caretStyle = "rc-select-d7edabfe7361";
30
- const caretOpenStyle = "rc-select-30173f5e3d41";
31
- const tagLabelStyle = "rc-select-2e4337f305d8";
32
- const suffixWrapStyle = "rc-select-ee9f2054c459";
33
- const actionStyle = "rc-select-8504d95b52bc";
34
- const loadingIconStyle = "rc-select-3ab2c2f8c427";
35
- const sizeMetricsMap = { large: "rc-select-df4a743b55e1", middle: "rc-select-de4a743b542e", small: "rc-select-dd4a743b527b" };
36
- const sizeHeightFixedMap = { large: "rc-select-b8fc5925a597", middle: "rc-select-b7fc5925a3e4", small: "rc-select-bafc5925a8fd" };
37
- const sizeHeightFlexibleMap = { large: "rc-select-5d07f79a2f4a", middle: "rc-select-5e07f79a30fd", small: "rc-select-5b07f79a2be4" };
21
+ const sizeMetricsMap = { large: "rc-select-df4a743b55e1", medium: "rc-select-de4a743b542e", small: "rc-select-dd4a743b527b" };
22
+ const sizeHeightFixedMap = { large: "rc-select-b8fc5925a597", medium: "rc-select-b7fc5925a3e4", small: "rc-select-bafc5925a8fd" };
23
+ const sizeHeightFlexibleMap = { large: "rc-select-5d07f79a2f4a", medium: "rc-select-5e07f79a30fd", small: "rc-select-5b07f79a2be4" };
38
24
  const CaretIcon = () => (0, __wake_namespace_0["jsx"])("svg", { "aria-hidden": "true", focusable: "false", viewBox: "0 0 24 24", fill: "currentColor", children: (0, __wake_namespace_0["jsx"])("path", { d: "m7 10 5 5 5-5z" }) });
39
25
  const ClearIcon = () => (0, __wake_namespace_0["jsx"])("svg", { "aria-hidden": "true", focusable: "false", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: (0, __wake_namespace_0["jsx"])("path", { d: "m18 6-12 12M6 6l12 12" }) });
40
26
  ;
41
- const SelectInput = ({ ref, id, ariaLabel, ariaLabelledBy, ariaDescribedBy, disabled, searchable, multiple, size, status, appearance, label, labelId, required, allowClear, loading, maxTagCount, autoFocus, placeholder, selectedOptions, searchText, highlightIndex, highlightedOption, listboxId, tagRender, onSearchTextChange, onOpenChange, onWidthChange, onMoveHighlight, onSelectHighlighted, onClear, onRemoveTag, onFocus, onBlur }) => {
27
+ const SelectInput = ({ ref, controlRef, id, ariaLabel, ariaLabelledBy, ariaDescribedBy, disabled, searchable, multiple, size, status, appearance, label, labelId, required, allowClear, loading, maxTagCount, autoFocus, placeholder, selectedOptions, searchText, highlightIndex, highlightedOption, listboxId, tagRender, onSearchTextChange, onOpenStateChange, onWidthChange, onMoveHighlight, onSelectHighlighted, onClear, onRemoveTag, onFocus, onBlur }) => {
42
28
  const { state, refs, dispatch } = (0, __wake_namespace_1["useDropdownContext"])();
43
- const controlRef = (0, __wake_namespace_7["useRef"])(null);
44
- const inputRef = (0, __wake_namespace_7["useRef"])(null);
29
+ const { messages } = (0, __wake_namespace_7["useLocale"])();
30
+ const inputRef = (0, __wake_namespace_8["useRef"])(null);
45
31
  const open = state.open;
46
- const [hovered, setHovered] = (0, __wake_namespace_7["useState"])(false);
47
- const [actionFocused, setActionFocused] = (0, __wake_namespace_7["useState"])(false);
48
- const [withoutHover, setWithoutHover] = (0, __wake_namespace_7["useState"])(false);
49
- (0, __wake_namespace_7["useEffect"])(() => {
32
+ const [hovered, setHovered] = (0, __wake_namespace_8["useState"])(false);
33
+ const [actionFocused, setActionFocused] = (0, __wake_namespace_8["useState"])(false);
34
+ const [withoutHover, setWithoutHover] = (0, __wake_namespace_8["useState"])(false);
35
+ (0, __wake_namespace_8["useEffect"])(() => {
50
36
  const media = window.matchMedia?.("(hover: none)");
51
37
  if (!media) return;
52
38
  const update = () => setWithoutHover(media.matches);
@@ -54,16 +40,15 @@ const SelectInput = ({ ref, id, ariaLabel, ariaLabelledBy, ariaDescribedBy, disa
54
40
  media.addEventListener("change", update);
55
41
  return () => media.removeEventListener("change", update);
56
42
  }, []);
57
- const onOpenChangeRef = (0, __wake_namespace_7["useRef"])(onOpenChange);
58
- onOpenChangeRef.current = onOpenChange;
59
- const mergeRef = (0, __wake_namespace_7["useCallback"])((node) => {
43
+ const syncOpen = (0, __wake_namespace_8["useEffectEvent"])(onOpenStateChange);
44
+ const mergeRef = (0, __wake_namespace_8["useCallback"])((node) => {
60
45
  controlRef.current = node;
61
46
  if (typeof refs.setReference === "function") {
62
47
  refs.setReference(node);
63
48
  }
64
49
  setRef(ref, node);
65
- }, [refs.setReference, ref]);
66
- (0, __wake_namespace_7["useEffect"])(() => {
50
+ }, [refs.setReference, ref, controlRef]);
51
+ (0, __wake_namespace_8["useEffect"])(() => {
67
52
  const el = controlRef.current;
68
53
  if (!el) {
69
54
  return;
@@ -76,23 +61,18 @@ const SelectInput = ({ ref, id, ariaLabel, ariaLabelledBy, ariaDescribedBy, disa
76
61
  observer.observe(el);
77
62
  return () => observer.disconnect();
78
63
  }, [onWidthChange]);
79
- (0, __wake_namespace_7["useEffect"])(() => {
80
- if (open && searchable) {
64
+ (0, __wake_namespace_8["useEffect"])(() => {
65
+ if (open && searchable && !disabled) {
81
66
  queueMicrotask(() => inputRef.current?.focus());
82
67
  }
83
- }, [open, searchable]);
84
- (0, __wake_namespace_7["useEffect"])(() => {
85
- if (autoFocus && controlRef.current) {
68
+ }, [disabled, open, searchable]);
69
+ (0, __wake_namespace_8["useEffect"])(() => {
70
+ if (autoFocus && !disabled && controlRef.current) {
86
71
  controlRef.current.focus();
87
72
  }
88
- }, [autoFocus]);
89
- const isFirstOpenRender = (0, __wake_namespace_7["useRef"])(true);
90
- (0, __wake_namespace_7["useEffect"])(() => {
91
- if (isFirstOpenRender.current) {
92
- isFirstOpenRender.current = false;
93
- return;
94
- }
95
- onOpenChangeRef.current(open);
73
+ }, [autoFocus, disabled]);
74
+ (0, __wake_namespace_8["useEffect"])(() => {
75
+ syncOpen(open);
96
76
  }, [open]);
97
77
  const handleClick = () => {
98
78
  if (disabled) {
@@ -122,7 +102,7 @@ const SelectInput = ({ ref, id, ariaLabel, ariaLabelledBy, ariaDescribedBy, disa
122
102
  case "Enter":
123
103
  e.preventDefault();
124
104
  if (open && highlightedOption) {
125
- onSelectHighlighted(highlightedOption);
105
+ onSelectHighlighted(highlightedOption, e);
126
106
  if (!multiple) {
127
107
  dispatch({ type: "setOpen", payload: false });
128
108
  }
@@ -141,29 +121,30 @@ const SelectInput = ({ ref, id, ariaLabel, ariaLabelledBy, ariaDescribedBy, disa
141
121
  case "Escape":
142
122
  if (open) {
143
123
  e.preventDefault();
144
- dispatch({ type: "setOpen", payload: false });
124
+ controlRef.current?.focus();
125
+ dispatch({ type: "setOpen", payload: false, details: { reason: "escape", event: e.nativeEvent } });
145
126
  }
146
127
  break;
147
128
  case "Backspace":
148
129
  if (multiple && searchText === "" && selectedOptions.length > 0) {
149
130
  const lastOption = selectedOptions[selectedOptions.length - 1];
150
- onRemoveTag(lastOption.value);
131
+ onRemoveTag(lastOption.value, e);
151
132
  }
152
133
  break;
153
134
  default:
154
135
  break;
155
136
  }
156
137
  };
157
- const triggerClear = () => {
138
+ const triggerClear = (event) => {
158
139
  controlRef.current?.focus();
159
- onClear();
140
+ onClear(event);
160
141
  if (open) {
161
142
  dispatch({ type: "setOpen", payload: false });
162
143
  }
163
144
  };
164
145
  const handleClearClick = (e) => {
165
146
  e.stopPropagation();
166
- triggerClear();
147
+ triggerClear(e);
167
148
  };
168
149
  const handleClearKeyDown = (e) => {
169
150
  if (e.key === "Enter" || e.key === " ") {
@@ -173,11 +154,13 @@ const SelectInput = ({ ref, id, ariaLabel, ariaLabelledBy, ariaDescribedBy, disa
173
154
  const canClear = allowClear && !disabled && selectedOptions.length > 0;
174
155
  const showClear = canClear && (hovered || actionFocused || withoutHover);
175
156
  const renderTag = (opt) => {
176
- const handleClose = () => onRemoveTag(opt.value);
157
+ const handleClose = (event) => {
158
+ if (!disabled) onRemoveTag(opt.value, event);
159
+ };
177
160
  if (tagRender) {
178
161
  return (0, __wake_namespace_0["jsx"])("span", { children: tagRender(opt, handleClose) }, opt.value);
179
162
  }
180
- return (0, __wake_namespace_0["jsx"])(__wake_namespace_5 && __wake_namespace_5.__esModule ? __wake_namespace_5.default : __wake_namespace_5, { size: "small", closable: true, closeAriaLabel: `Remove ${typeof opt.label === "string" ? opt.label : opt.value}`, onClose: handleClose, children: (0, __wake_namespace_0["jsx"])("span", { className: tagLabelStyle, children: opt.label }) }, opt.value);
163
+ return (0, __wake_namespace_0["jsx"])(__wake_namespace_5 && __wake_namespace_5.__esModule ? __wake_namespace_5.default : __wake_namespace_5, { size: "small", closable: !disabled, closeAriaLabel: messages.select.removeTag(typeof opt.label === "string" ? opt.label : opt.value), onClose: handleClose, children: (0, __wake_namespace_0["jsx"])("span", { className: __wake_namespace_9["tagLabelStyle"], children: opt.label }) }, opt.value);
181
164
  };
182
165
  const renderTags = () => {
183
166
  if (maxTagCount !== undefined && selectedOptions.length > maxTagCount) {
@@ -189,32 +172,32 @@ const SelectInput = ({ ref, id, ariaLabel, ariaLabelledBy, ariaDescribedBy, disa
189
172
  };
190
173
  const renderContent = () => {
191
174
  if (searchable && open) {
192
- return (0, __wake_namespace_0["jsxs"])(__wake_namespace_0["Fragment"], { children: [multiple && renderTags(), (0, __wake_namespace_0["jsx"])(__wake_namespace_2 && __wake_namespace_2.__esModule ? __wake_namespace_2.default : __wake_namespace_2, { ref: inputRef, bordered: false, value: searchText, placeholder: multiple && selectedOptions.length > 0 ? "" : placeholder, onChange: (e) => onSearchTextChange(e.target.value), onClick: (e) => e.stopPropagation(), className: searchInputStyle })] });
175
+ return (0, __wake_namespace_0["jsxs"])(__wake_namespace_0["Fragment"], { children: [multiple && renderTags(), (0, __wake_namespace_0["jsx"])(__wake_namespace_2 && __wake_namespace_2.__esModule ? __wake_namespace_2.default : __wake_namespace_2, { ref: inputRef, "aria-label": ariaLabel ?? label ?? placeholder, bordered: false, disabled: disabled, value: searchText, placeholder: multiple && selectedOptions.length > 0 ? "" : placeholder, onChange: (e) => onSearchTextChange(e.target.value), onClick: (e) => e.stopPropagation(), className: __wake_namespace_9["searchInputStyle"] })] });
193
176
  }
194
177
  if (multiple) {
195
178
  if (selectedOptions.length === 0) {
196
- return (0, __wake_namespace_0["jsx"])("span", { className: placeholderStyle, children: placeholder });
179
+ return (0, __wake_namespace_0["jsx"])("span", { "data-role": "select-placeholder", className: __wake_namespace_9["placeholderStyle"], children: placeholder });
197
180
  }
198
181
  return renderTags();
199
182
  }
200
183
  if (selectedOptions.length === 0) {
201
- return (0, __wake_namespace_0["jsx"])("span", { className: placeholderStyle, children: placeholder });
184
+ return (0, __wake_namespace_0["jsx"])("span", { "data-role": "select-placeholder", className: __wake_namespace_9["placeholderStyle"], children: placeholder });
202
185
  }
203
- return (0, __wake_namespace_0["jsx"])("span", { className: singleValueStyle, children: selectedOptions[0]?.label });
186
+ return (0, __wake_namespace_0["jsx"])("span", { className: __wake_namespace_9["singleValueStyle"], children: selectedOptions[0]?.label });
204
187
  };
205
188
  const activeDescendantId = open && highlightIndex >= 0 ? `${listboxId}-option-${highlightIndex}` : undefined;
206
- return (0, __wake_namespace_0["jsxs"])("div", { id: id, role: "combobox", "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-required": required || undefined, "aria-expanded": open, "aria-disabled": disabled, "aria-busy": loading || undefined, "aria-haspopup": "listbox", "aria-controls": open ? listboxId : undefined, "aria-activedescendant": activeDescendantId, "aria-invalid": status === "error" ? true : undefined, "data-appearance": appearance, "data-clearable": canClear, "data-labeled": Boolean(label), "data-floating": Boolean(open || selectedOptions.length > 0 || searchText), "data-status": status, tabIndex: disabled ? -1 : 0, ref: mergeRef, className: __wake_namespace_6["cx"].call(undefined, controlStyle, sizeMetricsMap[size], multiple ? sizeHeightFlexibleMap[size] : sizeHeightFixedMap[size], disabled && controlDisabledStyle, status === "error" && controlErrorStyle, status === "warning" && controlWarningStyle, materialFieldStyle), onClick: handleClick, onKeyDown: handleKeyDown, onFocus: onFocus, onBlur: onBlur, onPointerOver: (event) => {
189
+ return (0, __wake_namespace_0["jsxs"])("div", { className: __wake_namespace_9["fieldLayoutStyle"], "data-labeled": Boolean(label), "data-appearance": appearance, "data-floating": Boolean(open || selectedOptions.length > 0 || searchText), "data-open": open, "data-status": status, "data-disabled": disabled || undefined, children: [label && (0, __wake_namespace_0["jsxs"])("span", { "data-role": "select-label", children: [(0, __wake_namespace_0["jsx"])("span", { id: labelId, children: label }), required && (0, __wake_namespace_0["jsx"])("span", { "data-required-marker": "", "aria-hidden": "true", children: "*" })] }), (0, __wake_namespace_0["jsxs"])("div", { id: id, role: "combobox", "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-required": required || undefined, "aria-expanded": open, "aria-disabled": disabled, "aria-busy": loading || undefined, "aria-haspopup": "listbox", "aria-controls": open ? listboxId : undefined, "aria-activedescendant": activeDescendantId, "aria-invalid": status === "error" ? true : undefined, "data-appearance": appearance, "data-clearable": canClear, "data-labeled": Boolean(label), "data-floating": Boolean(open || selectedOptions.length > 0 || searchText), "data-status": status, tabIndex: disabled ? -1 : 0, ref: mergeRef, className: __wake_namespace_6["cx"].call(undefined, __wake_namespace_9["controlStyle"], sizeMetricsMap[size], multiple ? sizeHeightFlexibleMap[size] : sizeHeightFixedMap[size], disabled && __wake_namespace_9["controlDisabledStyle"], status === "error" && __wake_namespace_9["controlErrorStyle"], status === "warning" && __wake_namespace_9["controlWarningStyle"], __wake_namespace_9["fieldControlStyle"]), onClick: handleClick, onKeyDown: handleKeyDown, onFocus: onFocus, onBlur: onBlur, onPointerOver: (event) => {
207
190
  if (event.pointerType !== "touch") setHovered(true);
208
191
  }, onPointerOut: (event) => {
209
192
  if (!(event.relatedTarget instanceof Node) || !event.currentTarget.contains(event.relatedTarget)) {
210
193
  setHovered(false);
211
194
  }
212
- }, children: [label && (0, __wake_namespace_0["jsxs"])("span", { id: labelId, "data-role": "select-label", className: fieldLabelStyle, children: [label, required ? " *" : ""] }), (0, __wake_namespace_0["jsx"])("div", { "data-role": "select-value", className: valueWrapStyle, children: renderContent() }), (0, __wake_namespace_0["jsxs"])("span", { "data-role": "select-suffix", className: suffixWrapStyle, children: [loading ? (0, __wake_namespace_0["jsx"])("span", { "aria-hidden": "true", className: loadingIconStyle, children: (0, __wake_namespace_0["jsx"])(__wake_namespace_4["SpinIndicator"], {}) }) : null, (0, __wake_namespace_0["jsx"])(__wake_namespace_3 && __wake_namespace_3.__esModule ? __wake_namespace_3.default : __wake_namespace_3, { "data-role": showClear ? "select-clear" : "select-caret", className: actionStyle, type: "button", appearance: "text", shape: "circle", size: size, disabled: disabled, "aria-label": showClear ? "Clear" : open ? "Close options" : "Open options", "aria-expanded": showClear ? undefined : open, icon: showClear ? (0, __wake_namespace_0["jsx"])(ClearIcon, {}) : (0, __wake_namespace_0["jsx"])("span", { "aria-hidden": "true", className: __wake_namespace_6["cx"].call(undefined, caretStyle, open && caretOpenStyle), children: (0, __wake_namespace_0["jsx"])(CaretIcon, {}) }), onFocus: () => setActionFocused(true), onBlur: () => setActionFocused(false), onClick: (event) => {
195
+ }, children: [label && appearance === "outlined" && (0, __wake_namespace_0["jsx"])("fieldset", { "aria-hidden": "true", children: (0, __wake_namespace_0["jsxs"])("legend", { children: [label, required ? " *" : ""] }) }), (0, __wake_namespace_0["jsx"])("div", { "data-role": "select-value", className: __wake_namespace_9["valueWrapStyle"], children: renderContent() }), (0, __wake_namespace_0["jsxs"])("span", { "data-role": "select-suffix", className: __wake_namespace_9["suffixWrapStyle"], children: [loading ? (0, __wake_namespace_0["jsx"])("span", { "aria-hidden": "true", className: __wake_namespace_9["loadingIconStyle"], children: (0, __wake_namespace_0["jsx"])(__wake_namespace_4["SpinIndicator"], {}) }) : null, (0, __wake_namespace_0["jsx"])(__wake_namespace_3 && __wake_namespace_3.__esModule ? __wake_namespace_3.default : __wake_namespace_3, { "data-role": showClear ? "select-clear" : "select-caret", className: __wake_namespace_9["actionStyle"], type: "button", appearance: "text", shape: "circle", size: size === "small" ? "xs" : size === "large" ? "m" : "s", disabled: disabled, "aria-label": showClear ? messages.common.clear : open ? messages.select.closeOptions : messages.select.openOptions, "aria-expanded": showClear ? undefined : open, icon: showClear ? (0, __wake_namespace_0["jsx"])(ClearIcon, {}) : (0, __wake_namespace_0["jsx"])("span", { "aria-hidden": "true", className: __wake_namespace_6["cx"].call(undefined, __wake_namespace_9["caretStyle"], open && __wake_namespace_9["caretOpenStyle"]), children: (0, __wake_namespace_0["jsx"])(CaretIcon, {}) }), onFocus: () => setActionFocused(true), onBlur: () => setActionFocused(false), onClick: (event) => {
213
196
  if (showClear) handleClearClick(event); else {
214
197
  event.stopPropagation();
215
198
  handleClick();
216
199
  }
217
- }, onKeyDown: handleClearKeyDown })] })] });
200
+ }, onKeyDown: handleClearKeyDown })] })] })] });
218
201
  };
219
202
  const __wake_default_export = SelectInput;
220
203
  Object.defineProperty(exports, "default", { enumerable: true, get: function() {
@@ -0,0 +1,69 @@
1
+ Object.defineProperty(exports, "__esModule", { value: true });
2
+ require("@crab-dev/rc-button");
3
+ require("@crab-dev/rc-spin");
4
+ require("@crab-dev/rc-token-semantic");
5
+ require("./token.cjs");
6
+ const controlStyle = "rc-select-5e896678dc89";
7
+ Object.defineProperty(exports, "controlStyle", { enumerable: true, get: function() {
8
+ return controlStyle;
9
+ } });
10
+ const fieldControlStyle = "rc-select-29edc097b42b";
11
+ Object.defineProperty(exports, "fieldControlStyle", { enumerable: true, get: function() {
12
+ return fieldControlStyle;
13
+ } });
14
+ const fieldLayoutStyle = "rc-select-910e459fbbe0";
15
+ Object.defineProperty(exports, "fieldLayoutStyle", { enumerable: true, get: function() {
16
+ return fieldLayoutStyle;
17
+ } });
18
+ const controlDisabledStyle = "rc-select-82fbf3807561";
19
+ Object.defineProperty(exports, "controlDisabledStyle", { enumerable: true, get: function() {
20
+ return controlDisabledStyle;
21
+ } });
22
+ const controlErrorStyle = "rc-select-6d2a034155e7";
23
+ Object.defineProperty(exports, "controlErrorStyle", { enumerable: true, get: function() {
24
+ return controlErrorStyle;
25
+ } });
26
+ const controlWarningStyle = "rc-select-36466465840d";
27
+ Object.defineProperty(exports, "controlWarningStyle", { enumerable: true, get: function() {
28
+ return controlWarningStyle;
29
+ } });
30
+ const valueWrapStyle = "rc-select-f0b8a9c0c369";
31
+ Object.defineProperty(exports, "valueWrapStyle", { enumerable: true, get: function() {
32
+ return valueWrapStyle;
33
+ } });
34
+ const singleValueStyle = "rc-select-bcd33343d38d";
35
+ Object.defineProperty(exports, "singleValueStyle", { enumerable: true, get: function() {
36
+ return singleValueStyle;
37
+ } });
38
+ const placeholderStyle = "rc-select-30719d992205";
39
+ Object.defineProperty(exports, "placeholderStyle", { enumerable: true, get: function() {
40
+ return placeholderStyle;
41
+ } });
42
+ const searchInputStyle = "rc-select-c91210473c12";
43
+ Object.defineProperty(exports, "searchInputStyle", { enumerable: true, get: function() {
44
+ return searchInputStyle;
45
+ } });
46
+ const caretStyle = "rc-select-8ca15a371517";
47
+ Object.defineProperty(exports, "caretStyle", { enumerable: true, get: function() {
48
+ return caretStyle;
49
+ } });
50
+ const caretOpenStyle = "rc-select-72a72768a0ef";
51
+ Object.defineProperty(exports, "caretOpenStyle", { enumerable: true, get: function() {
52
+ return caretOpenStyle;
53
+ } });
54
+ const tagLabelStyle = "rc-select-113a9493f812";
55
+ Object.defineProperty(exports, "tagLabelStyle", { enumerable: true, get: function() {
56
+ return tagLabelStyle;
57
+ } });
58
+ const suffixWrapStyle = "rc-select-5032f5885db7";
59
+ Object.defineProperty(exports, "suffixWrapStyle", { enumerable: true, get: function() {
60
+ return suffixWrapStyle;
61
+ } });
62
+ const actionStyle = "rc-select-aa51540f6a1a";
63
+ Object.defineProperty(exports, "actionStyle", { enumerable: true, get: function() {
64
+ return actionStyle;
65
+ } });
66
+ const loadingIconStyle = "rc-select-14f1c2e4ccd5";
67
+ Object.defineProperty(exports, "loadingIconStyle", { enumerable: true, get: function() {
68
+ return loadingIconStyle;
69
+ } });