@adobe-commerce/elsie 1.6.0 → 1.7.0-beta2

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.
@@ -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
  // https://storybook.js.org/docs/7.0/preact/writing-stories/introduction
@@ -153,3 +153,42 @@ export const Secondary: Story = {
153
153
  await expect(await canvas.findByDisplayValue('')).toBeTruthy();
154
154
  },
155
155
  };
156
+
157
+ /**
158
+ * Input with a floating label that includes a required asterisk.
159
+ * The asterisk is automatically wrapped in a `<span class="dropin-label-required">` for consistent styling.
160
+ *
161
+ * ```ts
162
+ * import { Input } from '@adobe-commerce/elsie/components/Input';
163
+ * ```
164
+ *
165
+ * This example demonstrates:
166
+ * - Automatic asterisk wrapping in floating labels
167
+ * - The asterisk can be styled independently using `.dropin-label-required`
168
+ * - The label floats above the input when it has a value
169
+ */
170
+ export const WithRequiredAsterisk: Story = {
171
+ args: {
172
+ name: 'emailField',
173
+ value: 'user@example.com',
174
+ variant: 'primary',
175
+ size: 'medium',
176
+ floatingLabel: 'Email Address',
177
+ required: true,
178
+ disabled: false,
179
+ error: false,
180
+ success: false,
181
+ onValue: action('onValue'),
182
+ },
183
+ play: async ({ canvasElement }) => {
184
+ // Verify the floating label is rendered
185
+ const label = canvasElement.querySelector('.dropin-input__label--floating');
186
+ await expect(label).toBeTruthy();
187
+ await expect(label?.textContent).toBe('Email Address *');
188
+
189
+ // Verify the asterisk is wrapped in a span with required class
190
+ const asteriskSpan = label?.querySelector('.dropin-label-required');
191
+ await expect(asteriskSpan).toBeTruthy();
192
+ await expect(asteriskSpan?.textContent).toBe('*');
193
+ },
194
+ };
@@ -2,15 +2,23 @@
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
  import { Icon } from '@adobe-commerce/elsie/components/Icon';
11
11
  import '@adobe-commerce/elsie/components/Input/Input.css';
12
- import { CheckWithCircle, WarningWithCircle } from '@adobe-commerce/elsie/icons';
13
- import { VComponent, classes, debounce } from '@adobe-commerce/elsie/lib';
12
+ import {
13
+ CheckWithCircle,
14
+ WarningWithCircle,
15
+ } from '@adobe-commerce/elsie/icons';
16
+ import {
17
+ VComponent,
18
+ classes,
19
+ debounce,
20
+ wrapRequiredAsterisk,
21
+ } from '@adobe-commerce/elsie/lib';
14
22
  import { FunctionComponent, VNode } from 'preact';
15
23
  import { HTMLAttributes } from 'preact/compat';
16
24
  import { useCallback } from 'preact/hooks';
@@ -123,7 +131,7 @@ export const Input: FunctionComponent<InputProps> = ({
123
131
  [`dropin-input__label--floating--error`, !!error],
124
132
  ])}
125
133
  >
126
- {floatingLabel}
134
+ {wrapRequiredAsterisk(floatingLabel, !!props.required)}
127
135
  </label>
128
136
  )}
129
137
  </div>
@@ -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
  /* https://cssguidelin.es/#bem-like-naming */
@@ -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
  // https://storybook.js.org/docs/7.0/preact/writing-stories/introduction
@@ -316,3 +316,74 @@ export const MandatoryFieldFloatingLabelWithValue: Story = {
316
316
  ],
317
317
  },
318
318
  };
319
+
320
+ export const SingleOption: Story = {
321
+ name: 'Single option',
322
+ args: {
323
+ name: 'pickerField',
324
+ variant: 'primary',
325
+ defaultOption: {
326
+ value: 'option1',
327
+ text: 'Only Option',
328
+ },
329
+ options: [
330
+ {
331
+ value: 'option1',
332
+ text: 'Only Option',
333
+ },
334
+ ],
335
+ },
336
+ };
337
+
338
+ /**
339
+ * Picker with a floating label that includes a required asterisk.
340
+ * The asterisk is automatically wrapped in a `<span class="dropin-label-required">` for consistent styling.
341
+ *
342
+ * ```ts
343
+ * import { Picker } from '@adobe-commerce/elsie/components/Picker';
344
+ * ```
345
+ *
346
+ * This example demonstrates:
347
+ * - Automatic asterisk wrapping in floating labels
348
+ * - The asterisk can be styled independently using `.dropin-label-required`
349
+ * - The label floats above the picker when an option is selected
350
+ */
351
+ export const WithRequiredAsterisk: Story = {
352
+ name: 'With required asterisk',
353
+ args: {
354
+ name: 'countryPicker',
355
+ variant: 'primary',
356
+ floatingLabel: 'Country',
357
+ required: true,
358
+ value: 'us',
359
+ options: [
360
+ {
361
+ value: 'us',
362
+ text: 'United States',
363
+ },
364
+ {
365
+ value: 'ca',
366
+ text: 'Canada',
367
+ },
368
+ {
369
+ value: 'mx',
370
+ text: 'Mexico',
371
+ },
372
+ {
373
+ value: 'uk',
374
+ text: 'United Kingdom',
375
+ },
376
+ ],
377
+ },
378
+ play: async ({ canvasElement }) => {
379
+ // Verify the floating label is rendered
380
+ const label = canvasElement.querySelector('.dropin-picker__floatingLabel');
381
+ await expect(label).toBeTruthy();
382
+ await expect(label?.textContent).toBe('Country *');
383
+
384
+ // Verify the asterisk is wrapped in a span with required class
385
+ const asteriskSpan = label?.querySelector('.dropin-label-required');
386
+ await expect(asteriskSpan).toBeTruthy();
387
+ await expect(asteriskSpan?.textContent).toBe('*');
388
+ },
389
+ };
@@ -2,14 +2,14 @@
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
  import { Icon } from '@adobe-commerce/elsie/components';
11
11
  import { ChevronDown } from '@adobe-commerce/elsie/icons';
12
- import { classes } from '@adobe-commerce/elsie/lib';
12
+ import { classes, wrapRequiredAsterisk } from '@adobe-commerce/elsie/lib';
13
13
  import { FunctionComponent, VNode } from 'preact';
14
14
  import { HTMLAttributes, useEffect, useState } from 'preact/compat';
15
15
 
@@ -74,6 +74,7 @@ export const Picker: FunctionComponent<PickerProps> = ({
74
74
  }) => {
75
75
  const uniqueId = id ?? name ?? `dropin-picker-${Math.random().toString(36)}`;
76
76
  const isRequired = !!props?.required;
77
+ const isDisabled = disabled || options?.length === 1;
77
78
 
78
79
  // find the first option that is not disabled
79
80
  const firstAvailableOption = options?.find((option) => !option.disabled);
@@ -143,7 +144,7 @@ export const Picker: FunctionComponent<PickerProps> = ({
143
144
  ['dropin-picker__floating', !!floatingLabel],
144
145
  ['dropin-picker__selected', isSelected],
145
146
  ['dropin-picker__error', error],
146
- ['dropin-picker__disabled', disabled],
147
+ ['dropin-picker__disabled', isDisabled],
147
148
  ['dropin-picker__icon', icon],
148
149
  ])}
149
150
  >
@@ -165,7 +166,7 @@ export const Picker: FunctionComponent<PickerProps> = ({
165
166
  ])}
166
167
  name={name}
167
168
  aria-label={name}
168
- disabled={disabled}
169
+ disabled={isDisabled}
169
170
  onChange={handleOptionClick}
170
171
  {...props}
171
172
  >
@@ -197,7 +198,7 @@ export const Picker: FunctionComponent<PickerProps> = ({
197
198
  htmlFor={id}
198
199
  className={classes(['dropin-picker__floatingLabel', !!floatingLabel])}
199
200
  >
200
- {floatingLabel}
201
+ {wrapRequiredAsterisk(floatingLabel, isRequired)}
201
202
  </label>
202
203
  )}
203
204
  </div>
@@ -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
  /* https://cssguidelin.es/#bem-like-naming */
@@ -64,6 +64,11 @@
64
64
  box-shadow: 0 0 0 var(--shape-icon-stroke-4) var(--color-neutral-400);
65
65
  }
66
66
 
67
+ .dropin-radio-button__icon {
68
+ margin-right: var(--spacing-xsmall);
69
+ flex-shrink: 0;
70
+ }
71
+
67
72
  .dropin-radio-button__description {
68
73
  clear: both;
69
74
  color: var(--color-neutral-700);
@@ -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
  // https://storybook.js.org/docs/7.0/preact/writing-stories/introduction
@@ -14,6 +14,7 @@ import {
14
14
  RadioButtonProps,
15
15
  } from '@adobe-commerce/elsie/components/RadioButton';
16
16
  import { expect, userEvent, within } from '@storybook/test';
17
+ import { IconsList } from '@adobe-commerce/elsie/components/Icon/Icon.stories.helpers';
17
18
 
18
19
  /**
19
20
  * Use Radio Buttons to let users select one option from a set of mutually exclusive choices.
@@ -91,6 +92,15 @@ const meta: Meta<RadioButtonProps> = {
91
92
  name: 'boolean',
92
93
  },
93
94
  },
95
+ icon: {
96
+ description:
97
+ 'Optional icon to display before the label (SVG or img element)',
98
+ options: Object.keys(IconsList),
99
+ mapping: IconsList,
100
+ control: {
101
+ type: 'select',
102
+ },
103
+ },
94
104
  },
95
105
  };
96
106
 
@@ -124,3 +134,27 @@ export const RadioButtonStory: Story = {
124
134
  await expect(radioButton).toBeChecked();
125
135
  },
126
136
  };
137
+
138
+ export const RadioButtonWithIcon: Story = {
139
+ name: 'Radio button with icon',
140
+ args: {
141
+ name: 'shipping',
142
+ label: 'Free Shipping',
143
+ value: 'free-shipping',
144
+ description: 'Delivery in 5-7 business days',
145
+ size: 'medium',
146
+ disabled: false,
147
+ error: false,
148
+ // @ts-ignore - icon is mapped from IconsList
149
+ icon: 'Delivery',
150
+ },
151
+ play: async ({ canvasElement }) => {
152
+ const canvas = within(canvasElement);
153
+ const radioButton = await canvas.findByRole('radio');
154
+ const radioButtonContainer = radioButton.closest('.dropin-radio-button');
155
+ const icon = radioButtonContainer?.querySelector(
156
+ '.dropin-radio-button__icon'
157
+ );
158
+ await expect(icon).toBeInTheDocument();
159
+ },
160
+ };
@@ -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
  import { FunctionComponent, VNode } from 'preact';
@@ -13,7 +13,7 @@ import { classes } from '@adobe-commerce/elsie/lib';
13
13
  import '@adobe-commerce/elsie/components/RadioButton/RadioButton.css';
14
14
 
15
15
  export interface RadioButtonProps
16
- extends Omit<HTMLAttributes<HTMLInputElement>, 'size' | 'label'> {
16
+ extends Omit<HTMLAttributes<HTMLInputElement>, 'size' | 'label' | 'icon'> {
17
17
  label: string | VNode<HTMLAttributes<HTMLElement>>;
18
18
  name: string;
19
19
  value: string;
@@ -23,6 +23,9 @@ export interface RadioButtonProps
23
23
  error?: boolean;
24
24
  description?: string;
25
25
  busy?: boolean;
26
+ icon?:
27
+ | VNode<HTMLAttributes<SVGSVGElement>>
28
+ | VNode<HTMLAttributes<HTMLImageElement>>;
26
29
  }
27
30
 
28
31
  export const RadioButton: FunctionComponent<RadioButtonProps> = ({
@@ -35,6 +38,7 @@ export const RadioButton: FunctionComponent<RadioButtonProps> = ({
35
38
  error = false,
36
39
  description = '',
37
40
  busy = false,
41
+ icon,
38
42
  className,
39
43
  children,
40
44
  ...props
@@ -70,6 +74,16 @@ export const RadioButton: FunctionComponent<RadioButtonProps> = ({
70
74
  ['dropin-radio-button__label--disabled', disabled],
71
75
  ])}
72
76
  >
77
+ {icon && (
78
+ // @ts-ignore
79
+ <icon.type
80
+ {...icon?.props}
81
+ className={classes([
82
+ 'dropin-radio-button__icon',
83
+ icon?.props?.className,
84
+ ])}
85
+ />
86
+ )}
73
87
  {label}
74
88
  </span>
75
89
  <span
@@ -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
  export * from '@adobe-commerce/elsie/components/RadioButton/RadioButton';
@@ -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
  .dropin-textarea-container {
@@ -135,6 +135,6 @@
135
135
  .dropin-textarea__label--floating--error {
136
136
  font: var(--type-details-caption-1-font);
137
137
  letter-spacing: var(--type-details-caption-1-letter-spacing);
138
- color: var(--color-alert-800);
138
+ color: var(--color-alert-500);
139
139
  padding-top: var(--spacing-xsmall);
140
140
  }
@@ -2,14 +2,17 @@
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
  // https://storybook.js.org/docs/7.0/preact/writing-stories/introduction
11
11
  import type { Meta, StoryObj } from '@storybook/preact';
12
- import { TextArea, TextAreaProps } from '@adobe-commerce/elsie/components/TextArea';
12
+ import {
13
+ TextArea,
14
+ TextAreaProps,
15
+ } from '@adobe-commerce/elsie/components/TextArea';
13
16
  import { expect, userEvent, within } from '@storybook/test';
14
17
  import { useState, useCallback } from 'preact/hooks';
15
18
 
@@ -75,7 +78,7 @@ const Template: StoryObj<TextAreaProps> = {
75
78
  render: (args) => {
76
79
  const [value, setValue] = useState(args.value);
77
80
 
78
- const setTextAreaValue = useCallback((event) => {
81
+ const setTextAreaValue = useCallback((event: any) => {
79
82
  setValue(event.target.value);
80
83
  }, []);
81
84
 
@@ -83,7 +86,7 @@ const Template: StoryObj<TextAreaProps> = {
83
86
  },
84
87
  };
85
88
 
86
- export const DefaultWithValue = {
89
+ export const DefaultWithValue: StoryObj<TextAreaProps> = {
87
90
  ...Template,
88
91
  parameters: {
89
92
  layout: 'centered',
@@ -112,7 +115,7 @@ export const DefaultWithValue = {
112
115
  },
113
116
  };
114
117
 
115
- export const WithError = {
118
+ export const WithError: StoryObj<TextAreaProps> = {
116
119
  ...Template,
117
120
  parameters: {
118
121
  layout: 'centered',
@@ -128,3 +131,47 @@ export const WithError = {
128
131
  errorMessage: 'Message cannot be empty',
129
132
  },
130
133
  };
134
+
135
+ /**
136
+ * TextArea with a label that includes a required asterisk.
137
+ * The asterisk is automatically wrapped in a `<span class="dropin-label-required">` for consistent styling.
138
+ *
139
+ * ```ts
140
+ * import { TextArea } from '@adobe-commerce/elsie/components/TextArea';
141
+ * ```
142
+ *
143
+ * This example demonstrates:
144
+ * - Automatic asterisk wrapping in textarea labels
145
+ * - The asterisk can be styled independently using `.dropin-label-required`
146
+ * - The label floats above the textarea when it has content
147
+ */
148
+ export const WithRequiredAsterisk: StoryObj<TextAreaProps> = {
149
+ ...Template,
150
+ parameters: {
151
+ layout: 'centered',
152
+ a11y: {
153
+ config: {
154
+ rules: [{ id: 'color-contrast', enabled: false }],
155
+ },
156
+ },
157
+ },
158
+ args: {
159
+ label: 'Comments',
160
+ name: 'comments',
161
+ required: true,
162
+ value: 'Please provide additional details about your request.',
163
+ },
164
+ play: async ({ canvasElement }) => {
165
+ // Verify the floating label is rendered
166
+ const label = canvasElement.querySelector(
167
+ '.dropin-textarea__label--floating'
168
+ );
169
+ await expect(label).toBeTruthy();
170
+ await expect(label?.textContent).toBe('Comments *');
171
+
172
+ // Verify the asterisk is wrapped in a span with required class
173
+ const asteriskSpan = label?.querySelector('.dropin-label-required');
174
+ await expect(asteriskSpan).toBeTruthy();
175
+ await expect(asteriskSpan?.textContent).toBe('*');
176
+ },
177
+ };
@@ -2,13 +2,13 @@
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
  import { FunctionComponent } from 'preact';
11
- import { classes } from '@adobe-commerce/elsie/lib';
11
+ import { classes, wrapRequiredAsterisk } from '@adobe-commerce/elsie/lib';
12
12
  import { HTMLAttributes } from 'preact/compat';
13
13
  import '@adobe-commerce/elsie/components/TextArea/TextArea.css';
14
14
  import { useRef, useEffect, useId } from 'preact/hooks';
@@ -72,7 +72,7 @@ export const TextArea: FunctionComponent<TextAreaProps> = ({
72
72
  [`dropin-textarea__label--floating--error`, error],
73
73
  ])}
74
74
  >
75
- {label}
75
+ {wrapRequiredAsterisk(label as string, !!props.required)}
76
76
  </label>
77
77
  {error ? (
78
78
  <div
@@ -2,14 +2,15 @@
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
  .dropin-design a {
11
11
  --textColor: var(--color-brand-500);
12
12
  color: var(--textColor);
13
+ border: var(--shape-border-width-1) solid transparent;
13
14
  text-decoration: none;
14
15
  }
15
16
 
@@ -24,3 +25,7 @@
24
25
  border: var(--shape-border-width-1) solid var(--color-neutral-800);
25
26
  border-radius: var(--shape-border-radius-1);
26
27
  }
28
+
29
+ .dropin-design .dropin-label-required {
30
+ color: var(--color-alert-500);
31
+ }
@@ -9,8 +9,12 @@
9
9
 
10
10
  export const debounce = (fn: Function, ms: number) => {
11
11
  let timeoutId: ReturnType<typeof setTimeout>;
12
- return function (this: any, ...args: any[]) {
12
+ const debouncedFn = function (this: any, ...args: any[]) {
13
13
  clearTimeout(timeoutId);
14
14
  timeoutId = setTimeout(() => fn.apply(this, args), ms);
15
15
  };
16
+ debouncedFn.cancel = () => {
17
+ clearTimeout(timeoutId);
18
+ };
19
+ return debouncedFn;
16
20
  };
@@ -53,7 +53,7 @@ export function getPriceFormatter(
53
53
 
54
54
  const params: Intl.NumberFormatOptions = {
55
55
  style: 'currency',
56
- currency: currency || 'USD',
56
+ currency: currency && currency !== 'NONE' ? currency : 'USD',
57
57
  // These options are needed to round to whole numbers if that's what you want.
58
58
  minimumFractionDigits: 2, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
59
59
  maximumFractionDigits: 2, // (causes 2500.99 to be printed as $2,501)
package/src/lib/index.ts CHANGED
@@ -26,3 +26,4 @@ export * from '@adobe-commerce/elsie/lib/deviceUtils';
26
26
  export * from '@adobe-commerce/elsie/lib/get-path-value';
27
27
  export * from '@adobe-commerce/elsie/lib/get-cookie';
28
28
  export * from '@adobe-commerce/elsie/lib/get-price-formatter';
29
+ export * from '@adobe-commerce/elsie/lib/wrap-required-asterisk';