@adobe-commerce/elsie 1.6.0-alpha999 → 1.6.0-beta1

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/config/jest.js CHANGED
@@ -2,9 +2,9 @@
2
2
  * Copyright 2024 Adobe
3
3
  * All Rights Reserved.
4
4
  *
5
- * NOTICE: Adobe permits you to use, modify, and distribute this
6
- * file in accordance with the terms of the Adobe license agreement
7
- * accompanying it.
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
8
  *******************************************************************/
9
9
 
10
10
  const path = require('path');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe-commerce/elsie",
3
- "version": "1.6.0-alpha999",
3
+ "version": "1.6.0-beta1",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
5
  "description": "Domain Package SDK",
6
6
  "engines": {
@@ -27,8 +27,8 @@
27
27
  },
28
28
  "devDependencies": {
29
29
  "@adobe-commerce/event-bus": "~1.0.1",
30
- "@adobe-commerce/fetch-graphql": "~1.1.0",
31
- "@adobe-commerce/recaptcha": "~1.0.1",
30
+ "@adobe-commerce/fetch-graphql": "~1.2.0",
31
+ "@adobe-commerce/recaptcha": "~1.0.2",
32
32
  "@adobe-commerce/storefront-design": "~1.0.0",
33
33
  "@dropins/build-tools": "~1.0.1",
34
34
  "preact": "~10.22.1",
@@ -25,6 +25,8 @@ export interface ButtonProps
25
25
  active?: boolean;
26
26
  activeChildren?: ComponentChildren;
27
27
  activeIcon?: VNode<HTMLAttributes<SVGSVGElement>>;
28
+ href?: string;
29
+ type?: 'button' | 'submit' | 'reset';
28
30
  }
29
31
 
30
32
  export const Button: FunctionComponent<ButtonProps> = ({
@@ -8,7 +8,7 @@
8
8
  *******************************************************************/
9
9
 
10
10
  import '@adobe-commerce/elsie/components/Field/Field.css';
11
- import { classes } from '@adobe-commerce/elsie/lib';
11
+ import { classes, VComponent } from '@adobe-commerce/elsie/lib';
12
12
  import { FunctionComponent, VNode } from 'preact';
13
13
  import { HTMLAttributes } from 'preact/compat';
14
14
 
@@ -36,8 +36,23 @@ export const Field: FunctionComponent<FieldProps> = ({
36
36
  }) => {
37
37
  const id =
38
38
  children?.props?.id ?? `dropin-field-${Math.random().toString(36)}`;
39
- const ChildComponent =
40
- children && typeof children.type !== 'string' ? children.type : null;
39
+
40
+ let fieldContent: VNode | string | null = null;
41
+
42
+ if (children && typeof children !== 'string') {
43
+ fieldContent = (
44
+ <VComponent
45
+ node={children}
46
+ id={id}
47
+ key={children.key}
48
+ disabled={disabled}
49
+ size={size}
50
+ error={!!error}
51
+ success={!!success && !error}
52
+ />
53
+ );
54
+ }
55
+
41
56
 
42
57
  return (
43
58
  <div {...props} className={classes(['dropin-field', className])}>
@@ -55,17 +70,7 @@ export const Field: FunctionComponent<FieldProps> = ({
55
70
  )}
56
71
 
57
72
  <div className={classes(['dropin-field__content'])}>
58
- {ChildComponent && children && (
59
- <ChildComponent
60
- {...children.props}
61
- id={id}
62
- key={children.key}
63
- disabled={disabled}
64
- size={size}
65
- error={!!error}
66
- success={!!success && !error}
67
- />
68
- )}
73
+ {fieldContent}
69
74
  </div>
70
75
 
71
76
  <div
@@ -19,6 +19,12 @@
19
19
  opacity: 1;
20
20
  }
21
21
 
22
+ .dropin-incrementer__content--no-buttons {
23
+ grid-template-columns: max-content;
24
+ width: fit-content;
25
+ margin-inline: auto;
26
+ }
27
+
22
28
  .dropin-incrementer__content--disabled {
23
29
  background: var(--color-neutral-300);
24
30
  border-radius: var(--shape-border-radius-1);
@@ -79,6 +79,10 @@ const meta: Meta<IncrementerProps> = {
79
79
  description: 'Maximum length of the input field',
80
80
  type: 'number',
81
81
  },
82
+ showButtons: {
83
+ description: 'Show increase/decrease buttons',
84
+ control: 'boolean',
85
+ },
82
86
  },
83
87
  };
84
88
 
@@ -170,3 +174,17 @@ export const WithError = {
170
174
  await expect(error).toHaveTextContent('Maximum quantity is 100');
171
175
  },
172
176
  };
177
+
178
+ export const WithoutButtons: Story = {
179
+ args: {
180
+ size: 'medium',
181
+ onValue: action('onValue'),
182
+ name: 'incrementerField',
183
+ value: '1',
184
+ min: 1,
185
+ max: 100,
186
+ disabled: false,
187
+ 'aria-label': 'Quantity',
188
+ showButtons: false,
189
+ },
190
+ };
@@ -28,6 +28,7 @@ export interface IncrementerProps
28
28
  max?: number;
29
29
  disabled?: boolean;
30
30
  maxLength?: number;
31
+ showButtons?: boolean;
31
32
  }
32
33
 
33
34
  export const Incrementer: FunctionComponent<IncrementerProps> = ({
@@ -42,6 +43,7 @@ export const Incrementer: FunctionComponent<IncrementerProps> = ({
42
43
  onValue,
43
44
  onUpdateError,
44
45
  size = 'medium',
46
+ showButtons = true,
45
47
  ...props
46
48
  }) => {
47
49
  const [currentValue, setCurrentValue] = useState<number>(Number(value));
@@ -99,41 +101,44 @@ export const Incrementer: FunctionComponent<IncrementerProps> = ({
99
101
  className={classes([
100
102
  'dropin-incrementer__content',
101
103
  `dropin-incrementer__content--${size}`,
104
+ ['dropin-incrementer__content--no-buttons', !showButtons],
102
105
  [`dropin-incrementer__content--error`, isInvalid],
103
106
  [`dropin-incrementer__content--success`, success],
104
107
  [`dropin-incrementer__content--disabled`, disabled],
105
108
  ])}
106
109
  >
107
110
  {/* Minus Button */}
108
- <div
109
- className={classes([
110
- 'dropin-incrementer__button-container',
111
- [`dropin-incrementer__button-container--disabled`, disabled],
112
- ])}
113
- >
114
- <Localizer>
115
- <button
116
- type="button"
117
- className={classes([
118
- 'dropin-incrementer__decrease-button',
119
- [`dropin-incrementer__decrease-button--disabled`, disabled],
120
- ])}
121
- onClick={() => handleIncrementer(currentValue - 1)}
122
- disabled={disabled || currentValue < minValue + 1}
123
- aria-label={
124
- (<Text id="Dropin.Incrementer.decreaseLabel" />) as any
125
- }
126
- >
127
- <Icon
128
- source={Minus}
129
- size="16"
130
- stroke="1"
131
- viewBox="4 2 20 20"
132
- className="dropin-incrementer__down"
133
- />
134
- </button>
135
- </Localizer>
136
- </div>
111
+ {showButtons && (
112
+ <div
113
+ className={classes([
114
+ 'dropin-incrementer__button-container',
115
+ [`dropin-incrementer__button-container--disabled`, disabled],
116
+ ])}
117
+ >
118
+ <Localizer>
119
+ <button
120
+ type="button"
121
+ className={classes([
122
+ 'dropin-incrementer__decrease-button',
123
+ [`dropin-incrementer__decrease-button--disabled`, disabled],
124
+ ])}
125
+ onClick={() => handleIncrementer(currentValue - 1)}
126
+ disabled={disabled || currentValue < minValue + 1}
127
+ aria-label={
128
+ (<Text id="Dropin.Incrementer.decreaseLabel" />) as any
129
+ }
130
+ >
131
+ <Icon
132
+ source={Minus}
133
+ size="16"
134
+ stroke="1"
135
+ viewBox="4 2 20 20"
136
+ className="dropin-incrementer__down"
137
+ />
138
+ </button>
139
+ </Localizer>
140
+ </div>
141
+ )}
137
142
 
138
143
  {/* Input Field */}
139
144
  <input
@@ -157,36 +162,38 @@ export const Incrementer: FunctionComponent<IncrementerProps> = ({
157
162
  {...props}
158
163
  />
159
164
 
160
- <div
161
- className={classes([
162
- 'dropin-incrementer__button-container',
163
- [`dropin-incrementer__button-container--disabled`, disabled],
164
- ])}
165
- >
166
- {/* Plus/Add button */}
167
- <Localizer>
168
- <button
169
- type="button"
170
- className={classes([
171
- 'dropin-incrementer__increase-button',
172
- [`dropin-incrementer__increase-button--disabled`, disabled],
173
- ])}
174
- onClick={() => handleIncrementer(currentValue + 1)}
175
- disabled={disabled || currentValue > maxValue - 1}
176
- aria-label={
177
- (<Text id="Dropin.Incrementer.increaseLabel" />) as any
178
- }
179
- >
180
- <Icon
181
- source={Add}
182
- size="16"
183
- stroke="1"
184
- viewBox="4 2 20 20"
185
- className="dropin-incrementer__add"
186
- />
187
- </button>
188
- </Localizer>
189
- </div>
165
+ {showButtons && (
166
+ <div
167
+ className={classes([
168
+ 'dropin-incrementer__button-container',
169
+ [`dropin-incrementer__button-container--disabled`, disabled],
170
+ ])}
171
+ >
172
+ {/* Plus/Add button */}
173
+ <Localizer>
174
+ <button
175
+ type="button"
176
+ className={classes([
177
+ 'dropin-incrementer__increase-button',
178
+ [`dropin-incrementer__increase-button--disabled`, disabled],
179
+ ])}
180
+ onClick={() => handleIncrementer(currentValue + 1)}
181
+ disabled={disabled || currentValue > maxValue - 1}
182
+ aria-label={
183
+ (<Text id="Dropin.Incrementer.increaseLabel" />) as any
184
+ }
185
+ >
186
+ <Icon
187
+ source={Add}
188
+ size="16"
189
+ stroke="1"
190
+ viewBox="4 2 20 20"
191
+ className="dropin-incrementer__add"
192
+ />
193
+ </button>
194
+ </Localizer>
195
+ </div>
196
+ )}
190
197
  </div>
191
198
  {isInvalid && (
192
199
  <p className="dropin-incrementer__content--error-message">
@@ -0,0 +1,273 @@
1
+ /********************************************************************
2
+ * Copyright 2025 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ .dropin-multi-select {
11
+ position: relative;
12
+ min-width: 300px;
13
+ }
14
+
15
+ .dropin-multi-select__input-hidden {
16
+ display: none;
17
+ }
18
+
19
+ .dropin-multi-select__container {
20
+ min-height: 56px;
21
+ box-sizing: border-box;
22
+ border: var(--shape-border-width-1) solid var(--color-neutral-600);
23
+ border-radius: var(--shape-border-radius-1);
24
+ padding: var(--spacing-xsmall) var(--spacing-small);
25
+ cursor: text;
26
+ display: flex;
27
+ align-items: center;
28
+ justify-content: space-between;
29
+ gap: var(--spacing-xsmall);
30
+ transition: all 0.2s ease;
31
+ background-color: var(--color-neutral-50);
32
+ }
33
+
34
+ .dropin-multi-select__container--with-floating-label {
35
+ padding: var(--spacing-small) var(--spacing-small) var(--spacing-xsmall)
36
+ var(--spacing-small);
37
+ }
38
+
39
+ .dropin-multi-select__container:hover {
40
+ border-color: var(--color-neutral-700);
41
+ }
42
+
43
+ .dropin-multi-select__container--open {
44
+ border-color: var(--color-neutral-700);
45
+ }
46
+
47
+ .dropin-multi-select__container--disabled {
48
+ background-color: var(--color-neutral-200);
49
+ cursor: not-allowed;
50
+ opacity: 0.6;
51
+ }
52
+
53
+ .dropin-multi-select__container--error {
54
+ border: var(--shape-border-width-2) solid var(--color-alert-500);
55
+ }
56
+
57
+ .dropin-multi-select__container--success {
58
+ border: var(--shape-border-width-2) solid var(--color-positive-500);
59
+ }
60
+
61
+ .dropin-multi-select__tags-area {
62
+ flex: 1;
63
+ display: flex;
64
+ flex-wrap: wrap;
65
+ align-items: center;
66
+ gap: var(--spacing-xsmall);
67
+ max-width: calc(100% - 30px);
68
+ overflow: hidden;
69
+ }
70
+
71
+ .dropin-multi-select__tag {
72
+ padding: 2px 16px;
73
+ }
74
+
75
+ .dropin-multi-select__floating-label {
76
+ position: absolute;
77
+ top: 50%;
78
+ left: 12px;
79
+ transform: translateY(-50%);
80
+ cursor: text;
81
+ background-color: var(--color-neutral-50);
82
+ padding: 0 var(--spacing-xxsmall);
83
+ font: var(--type-body-1-default-font);
84
+ letter-spacing: var(--type-body-1-default-letter-spacing);
85
+ color: var(--color-neutral-500);
86
+ pointer-events: none;
87
+ transition: all 0.2s ease;
88
+ z-index: 1;
89
+ }
90
+
91
+ .dropin-multi-select__container--with-floating-label.dropin-multi-select__container--has-value,
92
+ .dropin-multi-select__container--with-floating-label.dropin-multi-select__container--open,
93
+ .dropin-multi-select__container--with-floating-label:focus-within {
94
+ padding-top: var(--spacing-big);
95
+ }
96
+
97
+ .dropin-multi-select__container--with-floating-label.dropin-multi-select__container--has-value
98
+ .dropin-multi-select__floating-label,
99
+ .dropin-multi-select__container--with-floating-label.dropin-multi-select__container--open
100
+ .dropin-multi-select__floating-label,
101
+ .dropin-multi-select__container--with-floating-label:focus-within
102
+ .dropin-multi-select__floating-label {
103
+ top: 12px;
104
+ left: 12px;
105
+ transform: translateY(0);
106
+ font-size: 12px;
107
+ color: var(--color-neutral-800);
108
+ font: var(--type-details-caption-1-font);
109
+ letter-spacing: var(--type-details-caption-1-letter-spacing);
110
+ background-color: var(--color-neutral-50);
111
+ z-index: 2;
112
+ }
113
+
114
+ .dropin-multi-select__tag-remove {
115
+ background: none;
116
+ border: none;
117
+ cursor: pointer;
118
+ padding: 0;
119
+ display: flex;
120
+ align-items: center;
121
+ transition: color 0.2s ease;
122
+ color: var(--color-neutral-600);
123
+ }
124
+
125
+ .dropin-multi-select__search {
126
+ outline: none;
127
+ background: transparent;
128
+ border: none;
129
+ font: var(--type-body-1-default-font);
130
+ letter-spacing: var(--type-body-1-default-letter-spacing);
131
+ padding: 0;
132
+ }
133
+
134
+ .dropin-multi-select__search:empty {
135
+ width: 100%;
136
+ }
137
+
138
+ .dropin-multi-select__search::placeholder {
139
+ font: var(--type-body-1-default-font);
140
+ }
141
+
142
+ .dropin-multi-select__container--with-floating-label
143
+ .dropin-multi-select__search::placeholder {
144
+ opacity: 0;
145
+ }
146
+
147
+ .dropin-multi-select__container--with-floating-label.dropin-multi-select__container--open
148
+ .dropin-multi-select__search::placeholder {
149
+ opacity: 1;
150
+ }
151
+
152
+ .dropin-multi-select__tags-area--has-values .dropin-multi-select__search {
153
+ width: 30px;
154
+ }
155
+
156
+ .dropin-multi-select__chevron {
157
+ transition: transform 0.2s ease;
158
+ flex-shrink: 0;
159
+ position: absolute;
160
+ top: 50%;
161
+ right: 12px;
162
+ transform: translateY(-50%);
163
+ }
164
+
165
+ .dropin-multi-select__chevron--open {
166
+ transform: translateY(-50%) rotate(180deg);
167
+ }
168
+
169
+ .dropin-multi-select__dropdown {
170
+ position: absolute;
171
+ overflow: hidden;
172
+ z-index: 50;
173
+ width: 100%;
174
+ margin-top: var(--spacing-xxsmall);
175
+ background-color: var(--color-neutral-50);
176
+ border: var(--shape-border-width-1) solid var(--color-neutral-700);
177
+ border-radius: var(--shape-border-radius-1);
178
+ box-shadow: var(--shape-shadow-1);
179
+ box-sizing: border-box;
180
+ }
181
+
182
+ .dropin-multi-select__controls {
183
+ position: sticky;
184
+ top: 0;
185
+ z-index: 10;
186
+ display: flex;
187
+ justify-content: space-between;
188
+ align-items: center;
189
+ gap: var(--spacing-xsmall);
190
+ border-bottom: var(--shape-border-width-1) solid var(--color-neutral-300);
191
+ background-color: var(--color-neutral-200);
192
+ }
193
+
194
+ .dropin-multi-select__button {
195
+ flex: 1;
196
+ font: var(--type-body-1-default-font);
197
+ letter-spacing: var(--type-body-1-default-letter-spacing);
198
+ cursor: pointer;
199
+ }
200
+
201
+ .dropin-multi-select__button--deselect-all:disabled {
202
+ opacity: 0.5;
203
+ cursor: not-allowed;
204
+ }
205
+
206
+ .dropin-multi-select__button--deselect-all:disabled:hover {
207
+ background-color: var(--color-neutral-200);
208
+ }
209
+
210
+ .dropin-multi-select__button--select-all,
211
+ .dropin-multi-select__button--deselect-all {
212
+ padding-left: var(--spacing-xsmall);
213
+ padding-right: var(--spacing-xsmall);
214
+ }
215
+
216
+ .dropin-multi-select__options {
217
+ overflow: auto;
218
+ }
219
+
220
+ .dropin-multi-select__list {
221
+ list-style: none;
222
+ margin: 0;
223
+ padding: var(--spacing-xxsmall) 0;
224
+ }
225
+
226
+ .dropin-multi-select__option {
227
+ padding: var(--spacing-xsmall) 12px;
228
+ cursor: pointer;
229
+ display: flex;
230
+ align-items: center;
231
+ justify-content: space-between;
232
+ transition: background-color 0.15s ease;
233
+ font: var(--type-body-1-default-font);
234
+ letter-spacing: var(--type-body-1-default-letter-spacing);
235
+ }
236
+
237
+ .dropin-multi-select__option:hover {
238
+ background-color: var(--color-neutral-300);
239
+ }
240
+
241
+ .dropin-multi-select__option--focused {
242
+ background-color: var(--color-neutral-200);
243
+ }
244
+
245
+ .dropin-multi-select__option--selected {
246
+ color: var(--color-brand-700);
247
+ font: var(--type-body-1-emphasized-font);
248
+ letter-spacing: var(--type-body-1-emphasized-letter-spacing);
249
+ }
250
+
251
+ .dropin-multi-select__option-label {
252
+ flex: 1;
253
+ }
254
+
255
+ .dropin-multi-select__option-label--disabled {
256
+ color: var(--color-neutral-200);
257
+ }
258
+
259
+ .dropin-multi-select__no-results {
260
+ padding: var(--spacing-small);
261
+ text-align: center;
262
+ font: var(--type-body-1-default-font);
263
+ color: var(--color-neutral-500);
264
+ }
265
+
266
+ .dropin-multi-select__sr-only {
267
+ position: absolute;
268
+ left: -10000px;
269
+ top: auto;
270
+ width: 1px;
271
+ height: 1px;
272
+ overflow: hidden;
273
+ }