@adobe-commerce/elsie 1.9.0 → 1.9.1-alpha-20260702101934

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,11 @@
1
1
  # @adobe-commerce/elsie
2
2
 
3
+ ## 1.9.1-alpha-20260702101934
4
+
5
+ ### Patch Changes
6
+
7
+ - fa16e7d: fix(Picker): auto-select and emit the sole option when the control auto-disables, so single-option narrowing on configurable PDPs no longer leaves the value unselected and Add to Cart permanently disabled
8
+
3
9
  ## 1.9.0
4
10
 
5
11
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe-commerce/elsie",
3
- "version": "1.9.0",
3
+ "version": "1.9.1-alpha-20260702101934",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
5
  "description": "Domain Package SDK",
6
6
  "engines": {
@@ -11,7 +11,7 @@ import { Icon } from '@adobe-commerce/elsie/components';
11
11
  import { ChevronDown } from '@adobe-commerce/elsie/icons';
12
12
  import { classes } from '@adobe-commerce/elsie/lib';
13
13
  import { FunctionComponent, VNode } from 'preact';
14
- import { HTMLAttributes, useEffect, useState } from 'preact/compat';
14
+ import { HTMLAttributes, useEffect, useRef, useState } from 'preact/compat';
15
15
 
16
16
  import '@adobe-commerce/elsie/components/Picker/Picker.css';
17
17
 
@@ -46,10 +46,13 @@ function findSelectedValue(
46
46
  defaultOption?: PickerOption,
47
47
  placeholder?: string,
48
48
  floatingLabel?: string,
49
- firstAvailableOption?: PickerOption
49
+ firstAvailableOption?: PickerOption,
50
+ singleOption?: PickerOption
50
51
  ) {
51
52
  if (value) return value;
52
53
  if (defaultOption) return defaultOption.value;
54
+ // sole option wins over the placeholder so it stays selected, not blank
55
+ if (singleOption) return singleOption.value;
53
56
  if (placeholder || floatingLabel) return '';
54
57
  if (firstAvailableOption) return firstAvailableOption.value;
55
58
  return null;
@@ -75,17 +78,26 @@ export const Picker: FunctionComponent<PickerProps> = ({
75
78
  const uniqueId = id ?? name ?? `dropin-picker-${Math.random().toString(36)}`;
76
79
  const isRequired = !!props?.required;
77
80
  const isDisabled = disabled || options?.length === 1;
81
+ const selectRef = useRef<HTMLSelectElement>(null);
78
82
 
79
83
  // find the first option that is not disabled
80
84
  const firstAvailableOption = options?.find((option) => !option.disabled);
81
85
 
86
+ // the only selectable option when the picker auto-disables; a disabled
87
+ // <select> never fires change, so we must emit it ourselves (see below)
88
+ const singleOption =
89
+ !disabled && options?.length === 1 && !options[0]?.disabled
90
+ ? options[0]
91
+ : undefined;
92
+
82
93
  const [selectedValue, setSelectedValue] = useState<PickerValue>(() => {
83
94
  return findSelectedValue(
84
95
  value,
85
96
  defaultOption,
86
97
  placeholder,
87
98
  floatingLabel,
88
- firstAvailableOption
99
+ firstAvailableOption,
100
+ singleOption
89
101
  );
90
102
  });
91
103
 
@@ -96,10 +108,32 @@ export const Picker: FunctionComponent<PickerProps> = ({
96
108
  defaultOption,
97
109
  placeholder,
98
110
  floatingLabel,
99
- firstAvailableOption
111
+ firstAvailableOption,
112
+ singleOption
100
113
  )
101
114
  );
102
- }, [value, defaultOption, placeholder, floatingLabel, firstAvailableOption]);
115
+ }, [
116
+ value,
117
+ defaultOption,
118
+ placeholder,
119
+ floatingLabel,
120
+ firstAvailableOption,
121
+ singleOption,
122
+ ]);
123
+
124
+ // commit the sole option to the consumer; skip once value has come back in.
125
+ // dispatch a real change event so handleOptionClick emits it: consumers get
126
+ // a genuine Event (some call preventDefault) identical to a user selection.
127
+ useEffect(() => {
128
+ if (!singleOption || value === singleOption.value) return;
129
+
130
+ const select = selectRef.current;
131
+ if (!select) return;
132
+
133
+ select.value = singleOption.value as string;
134
+ select.dispatchEvent(new Event('change', { bubbles: true }));
135
+ // eslint-disable-next-line react-hooks/exhaustive-deps
136
+ }, [singleOption?.value, value]);
103
137
 
104
138
  const handleOptionClick = (event: Event) => {
105
139
  const { options, value } = event.target as HTMLSelectElement;
@@ -157,6 +191,7 @@ export const Picker: FunctionComponent<PickerProps> = ({
157
191
  )}
158
192
 
159
193
  <select
194
+ ref={selectRef}
160
195
  id={uniqueId}
161
196
  className={classes([
162
197
  'dropin-picker__select',