@wix/editor-react-components 1.2358.0 → 1.2359.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.
@@ -6,10 +6,11 @@ import { useService } from "@wix/services-manager-react";
6
6
  import { E as EnvironmentDefinition } from "../chunks/index2.js";
7
7
  import { f as formatClassNames } from "../chunks/classNames.js";
8
8
  import { a as getDataAttributes } from "../chunks/dataUtils.js";
9
- import { R as RequiredIndicator, I as InfoCircleSmall_default } from "../chunks/RequiredIndicator.js";
9
+ import { R as RequiredIndicator } from "../chunks/RequiredIndicator.js";
10
10
  import { d as directionStyles } from "../chunks/direction.module.js";
11
11
  import { p as presetWrapperStyles } from "../chunks/presetWrapper.module.js";
12
12
  import { d as defaultValues, s as selectors, T as TestIds, a as semanticClassNames } from "../chunks/constants37.js";
13
+ import { I as InfoCircleSmall_default } from "../chunks/InfoCircleSmall.js";
13
14
  const root = "root__0DpH8";
14
15
  const field = "field__R0D8f";
15
16
  const item = "item__EzhwB";
@@ -6,10 +6,11 @@ import { useService } from "@wix/services-manager-react";
6
6
  import { E as EnvironmentDefinition } from "../chunks/index2.js";
7
7
  import { f as formatClassNames } from "../chunks/classNames.js";
8
8
  import { a as getDataAttributes } from "../chunks/dataUtils.js";
9
- import { R as RequiredIndicator, I as InfoCircleSmall_default } from "../chunks/RequiredIndicator.js";
9
+ import { R as RequiredIndicator } from "../chunks/RequiredIndicator.js";
10
10
  import { d as directionStyles } from "../chunks/direction.module.js";
11
11
  import { p as presetWrapperStyles } from "../chunks/presetWrapper.module.js";
12
12
  import { d as defaultValues, a as defaultOptions, s as selectors, T as TestIds, b as semanticClassNames } from "../chunks/constants36.js";
13
+ import { I as InfoCircleSmall_default } from "../chunks/InfoCircleSmall.js";
13
14
  const root = "root__raraS";
14
15
  const fieldset = "fieldset__pDERL";
15
16
  const labelRow = "labelRow__CTw2X";
@@ -17,7 +17,8 @@ import { d as directionStyles } from "../chunks/direction.module.js";
17
17
  import { p as presetWrapperStyles } from "../chunks/presetWrapper.module.js";
18
18
  import { E as EMPTY_VALUE, T as TestIds, s as selectors, D as DesignStates, A as ARIA_LABEL_NAMESPACE, d as defaultValues, S as SelectionModeValues, G as GranularityValues, V as VALUE_MISSING_MESSAGE, a as AriaLabels } from "../chunks/constants34.js";
19
19
  import { u as useValidatedField } from "../chunks/useValidatedField.js";
20
- import { I as InfoCircleSmall_default, R as RequiredIndicator } from "../chunks/RequiredIndicator.js";
20
+ import { R as RequiredIndicator } from "../chunks/RequiredIndicator.js";
21
+ import { I as InfoCircleSmall_default } from "../chunks/InfoCircleSmall.js";
21
22
  import { D as DismissSmall_default } from "../chunks/DismissSmall.js";
22
23
  createContext(null);
23
24
  createContext(null);
@@ -1,5 +1,6 @@
1
1
  import { A11y, Direction } from '@wix/editor-react-types';
2
2
  import { SdkFunctionChangeableProps, SdkFunctionFocusableProps, SdkFunctionInputableProps } from '../../../utils/functions/sdkFunctionCallbackProps';
3
+ import { FieldValidationProps } from '../../../utils/validation/types';
3
4
  export type DropdownOption = {
4
5
  /** Text shown to the visitor in the list. */
5
6
  label: string;
@@ -8,13 +9,15 @@ export type DropdownOption = {
8
9
  };
9
10
  /** When the filter value is committed: immediately on pick, or only on an Apply click. */
10
11
  export type DropdownTriggerMode = 'onSelection' | 'onApply';
11
- /** Multi-select `value` item; a bare `string[]` is also accepted on read. */
12
+ /** Legacy multi-select item shape; still accepted on read for back-compat. */
12
13
  export type DropdownValueItem = {
13
14
  value: string;
14
15
  };
16
+ /** The selection emitted/validated: a value string (single) or `string[]` (multi). */
17
+ export type DropdownValue = string | Array<string>;
15
18
  /** Match rule for searchable mode; defaults to case-insensitive "contains". */
16
19
  export type DropdownFilter = (item: DropdownOption, query: string) => boolean;
17
- export type DropdownProps = Omit<SdkFunctionChangeableProps, 'onChange'> & SdkFunctionFocusableProps & Omit<SdkFunctionInputableProps, 'onInput'> & {
20
+ export type DropdownProps = Omit<SdkFunctionChangeableProps, 'onChange'> & SdkFunctionFocusableProps & Omit<SdkFunctionInputableProps, 'onInput'> & FieldValidationProps<DropdownValue> & {
18
21
  /** DOM `id` on the root `.dropdown` wrapper. */
19
22
  id: string;
20
23
  /** Appended to the root `.dropdown`. Use this for CSS-variable and per-element overrides. */
@@ -24,21 +27,31 @@ export type DropdownProps = Omit<SdkFunctionChangeableProps, 'onChange'> & SdkFu
24
27
  /** Single-select selection: a value string (empty = cleared). */
25
28
  value: string;
26
29
  /**
27
- * Multi-select selection (`multiple: true`): an array of `{ value }` items
28
- * (a bare `string[]` is also accepted on read).
30
+ * Multi-select selection (`multiple: true`): a `string[]` of selected
31
+ * values (a legacy `{ value }[]` is also accepted on read).
29
32
  */
30
33
  values?: Array<string> | Array<DropdownValueItem>;
34
+ /**
35
+ * Uncontrolled initial single-select selection. Used only when `value`
36
+ * is not provided (component owns its state).
37
+ */
38
+ defaultValue?: string;
39
+ /**
40
+ * Uncontrolled initial multi-select selection. Used only when `values`
41
+ * is not provided.
42
+ */
43
+ defaultValues?: Array<string> | Array<DropdownValueItem>;
31
44
  /** Bindable filter for searchable mode; defaults to case-insensitive "contains". */
32
45
  filter?: DropdownFilter;
33
46
  /** Live typed search query, separate from `value`; two-way bindable via `onInput`. */
34
47
  inputValue?: string;
35
48
  /**
36
49
  * Fires with the new selection so the bound field's setter stores it: a
37
- * value string (single-select) or `{ value }[]` (multi-select). The value
50
+ * value string (single-select) or `string[]` (multi-select). The value
38
51
  * is passed plainly (not a DOM change event) — the binding wires
39
52
  * `onChange → <field>.setValue`.
40
53
  */
41
- onChange?: (value: string | Array<DropdownValueItem>) => void;
54
+ onChange?: (value: string | Array<string>) => void;
42
55
  /** Fires with the new typed query string (bound via `onInput → <field>.setValue`). */
43
56
  onInput?: (value: string) => void;
44
57
  /** Text shown on the trigger when nothing is selected. */
@@ -67,6 +80,11 @@ export type DropdownProps = Omit<SdkFunctionChangeableProps, 'onChange'> & SdkFu
67
80
  required: boolean;
68
81
  /** Shows the current selection but blocks editing it. */
69
82
  readOnly: boolean;
83
+ /**
84
+ * Validation surface (`fieldValidity`, `showValidityIndication`,
85
+ * `onValidate`, `onValidityChange`) comes from `FieldValidationProps` — see
86
+ * the shared validation contract in `utils/validation`.
87
+ */
70
88
  /** Form field name used on submit. */
71
89
  name: string;
72
90
  /** Helper text shown under the field (and as the field's accessible description). */
@@ -2,15 +2,17 @@ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { useState, useCallback, useLayoutEffect, useEffect, useRef } from "react";
4
4
  import { c as clsx } from "../chunks/clsx.js";
5
- import { C as Combobox, B as Button_Button_Button } from "../chunks/index10.js";
5
+ import { C as Combobox, F as Field, B as Button_Button_Button } from "../chunks/index10.js";
6
6
  import { useService } from "@wix/services-manager-react";
7
7
  import { E as EnvironmentDefinition } from "../chunks/index2.js";
8
8
  import { T as TranslationsDefinition } from "../chunks/index5.js";
9
9
  import { f as formatClassNames } from "../chunks/classNames.js";
10
10
  import { a as getDataAttributes } from "../chunks/dataUtils.js";
11
+ import { R as RequiredIndicator } from "../chunks/RequiredIndicator.js";
11
12
  import { d as directionStyles } from "../chunks/direction.module.js";
12
13
  import { p as presetWrapperStyles } from "../chunks/presetWrapper.module.js";
13
- import { A as ALL_VALUE, s as selectors, a as semanticClassNames, T as TestIds, d as defaultValues, b as TriggerModeValues, c as ARIA_LABEL_NAMESPACE, e as AriaLabels } from "../chunks/constants33.js";
14
+ import { A as ALL_VALUE, s as selectors, a as semanticClassNames, T as TestIds, d as defaultValues, b as TriggerModeValues, c as ARIA_LABEL_NAMESPACE, e as AriaLabels, V as VALUE_MISSING_MESSAGE } from "../chunks/constants33.js";
15
+ import { u as useValidatedField } from "../chunks/useValidatedField.js";
14
16
  import { u as useResizeObserver } from "../chunks/useResizeObserver.js";
15
17
  import { D as DismissSmall_default } from "../chunks/DismissSmall.js";
16
18
  import { g as getDefaultExportFromCjs } from "../chunks/_commonjsHelpers.js";
@@ -165,6 +167,7 @@ const trigger = "trigger__J7jn7";
165
167
  const option = "option__QJeiF";
166
168
  const multiple = "multiple__ay77b";
167
169
  const select = "select__Lo-N7";
170
+ const errorMessage = "errorMessage__iMuAa";
168
171
  const label = "label__Q7fZH";
169
172
  const description = "description__77blZ";
170
173
  const clear = "clear__isa6G";
@@ -190,6 +193,7 @@ const styles = {
190
193
  option,
191
194
  multiple,
192
195
  select,
196
+ errorMessage,
193
197
  label,
194
198
  description,
195
199
  clear,
@@ -278,7 +282,7 @@ const useDropdownSelection = (params) => {
278
282
  const selectedOptionLabel = selectedKey ? labelForKey(selectedKey) : "";
279
283
  const commitValue = (keys) => {
280
284
  const values = keys.map((key) => valueForKey(key)).filter((value2) => value2 !== ALL_VALUE);
281
- const next = isMultiple ? values.map((value2) => ({ value: value2 })) : values[0] ?? ALL_VALUE;
285
+ const next = isMultiple ? values : values[0] ?? ALL_VALUE;
282
286
  emitChange(onChange, next);
283
287
  };
284
288
  const handleSelectionChange = (keys) => {
@@ -450,7 +454,8 @@ const DropdownTrigger = ({
450
454
  labelId,
451
455
  clearLabel,
452
456
  removeItemLabel,
453
- descriptionId,
457
+ describedById,
458
+ isInvalid,
454
459
  onFocus,
455
460
  onBlur
456
461
  }) => {
@@ -486,7 +491,8 @@ const DropdownTrigger = ({
486
491
  placeholder: isMultiple && selectedItems.length > 0 ? "" : placeholder,
487
492
  "aria-label": ariaLabel,
488
493
  "aria-labelledby": labelId,
489
- "aria-describedby": descriptionId,
494
+ "aria-describedby": describedById,
495
+ "aria-invalid": isInvalid || void 0,
490
496
  onFocus,
491
497
  onBlur
492
498
  }
@@ -516,7 +522,8 @@ const DropdownTrigger = ({
516
522
  className: triggerClassName,
517
523
  "data-testid": TestIds.trigger,
518
524
  "aria-label": ariaLabel,
519
- "aria-describedby": descriptionId,
525
+ "aria-describedby": describedById,
526
+ "aria-invalid": isInvalid || void 0,
520
527
  onFocus,
521
528
  onBlur,
522
529
  children: [
@@ -650,6 +657,11 @@ function Dropdown(props) {
650
657
  const [popoverContainer, setPopoverContainer] = useState(null);
651
658
  const optionItems = toOptionItems(options);
652
659
  const isControlDisabled = isDisabled || optionItems.length === 0;
660
+ const boundValue = isMultiple ? props.values : props.value;
661
+ const defaultValue = isMultiple ? props.defaultValues : props.defaultValue;
662
+ const isControlled = boundValue !== void 0;
663
+ const sourceValue = isControlled ? boundValue : defaultValue;
664
+ const selectedValues = readSelectedValues(sourceValue, isMultiple);
653
665
  const {
654
666
  selectedItems,
655
667
  selectedKey,
@@ -658,10 +670,7 @@ function Dropdown(props) {
658
670
  handleApply
659
671
  } = useDropdownSelection({
660
672
  optionItems,
661
- selectedValues: readSelectedValues(
662
- isMultiple ? props.values : props.value,
663
- isMultiple
664
- ),
673
+ selectedValues,
665
674
  isMultiple,
666
675
  isApplyMode,
667
676
  onChange
@@ -685,6 +694,27 @@ function Dropdown(props) {
685
694
  const ariaLabel = label2 ? void 0 : t(AriaLabels.root.key) || (a11y == null ? void 0 : a11y.ariaLabel) || AriaLabels.root.default;
686
695
  const clearLabel = t(AriaLabels.clear.key) || AriaLabels.clear.default;
687
696
  const removeItemLabel = t(AriaLabels.removeItem.key) || AriaLabels.removeItem.default;
697
+ const selectedItemValues = selectedItems.map((item) => item.value).filter((value2) => value2 !== "");
698
+ const currentValue = isMultiple ? selectedItemValues : selectedItemValues[0] ?? "";
699
+ const intrinsic = required && selectedItemValues.length === 0 ? { valid: false, validationMessage: VALUE_MISSING_MESSAGE } : { valid: true, validationMessage: "" };
700
+ const {
701
+ validity,
702
+ showValidityIndication: showIndication,
703
+ handleBlur: validateOnBlur
704
+ } = useValidatedField({
705
+ value: currentValue,
706
+ valueKey: JSON.stringify(selectedItemValues),
707
+ intrinsic,
708
+ fieldValidity: props.fieldValidity,
709
+ showValidityIndication: props.showValidityIndication,
710
+ onValidate: props.onValidate,
711
+ onValidityChange: props.onValidityChange
712
+ });
713
+ const isInvalid = showIndication && !validity.valid;
714
+ const handleBlur = (event) => {
715
+ onBlur(event);
716
+ validateOnBlur();
717
+ };
688
718
  const rootClassName = clsx(
689
719
  className,
690
720
  styles.root,
@@ -711,9 +741,10 @@ function Dropdown(props) {
711
741
  labelId,
712
742
  clearLabel,
713
743
  removeItemLabel,
714
- descriptionId,
744
+ describedById: descriptionId,
745
+ isInvalid,
715
746
  onFocus,
716
- onBlur
747
+ onBlur: handleBlur
717
748
  }
718
749
  );
719
750
  const list2 = /* @__PURE__ */ jsx(
@@ -766,7 +797,7 @@ function Dropdown(props) {
766
797
  ...inline ? {} : { open: popupOpen, onOpenChange: setIsOpen },
767
798
  ...isSearchable ? { inputValue, onInputValueChange: handleInputValueChange } : {},
768
799
  children: [
769
- label2 && /* @__PURE__ */ jsx(
800
+ label2 && /* @__PURE__ */ jsxs(
770
801
  Combobox.Label,
771
802
  {
772
803
  className: clsx(
@@ -775,7 +806,16 @@ function Dropdown(props) {
775
806
  formatClassNames(semanticClassNames.label)
776
807
  ),
777
808
  "data-testid": TestIds.label,
778
- children: label2
809
+ children: [
810
+ label2,
811
+ required && /* @__PURE__ */ jsx(
812
+ RequiredIndicator,
813
+ {
814
+ className: formatClassNames(semanticClassNames.requiredIndicator),
815
+ "data-testid": TestIds.requiredIndicator
816
+ }
817
+ )
818
+ ]
779
819
  }
780
820
  ),
781
821
  triggerRegion,
@@ -795,12 +835,13 @@ function Dropdown(props) {
795
835
  "data-testid": TestIds.root,
796
836
  children: [
797
837
  /* @__PURE__ */ jsxs(
798
- "div",
838
+ Field.Root,
799
839
  {
800
840
  className: clsx(
801
841
  styles.select,
802
842
  formatClassNames(semanticClassNames.root)
803
843
  ),
844
+ invalid: isInvalid,
804
845
  children: [
805
846
  field,
806
847
  description2 && /* @__PURE__ */ jsx(
@@ -811,6 +852,18 @@ function Dropdown(props) {
811
852
  "data-testid": TestIds.description,
812
853
  children: description2
813
854
  }
855
+ ),
856
+ isInvalid && validity.validationMessage && /* @__PURE__ */ jsx(
857
+ Field.Error,
858
+ {
859
+ match: true,
860
+ className: clsx(
861
+ styles.errorMessage,
862
+ formatClassNames(semanticClassNames.errorMessage)
863
+ ),
864
+ "data-testid": TestIds.errorMessage,
865
+ children: validity.validationMessage
866
+ }
814
867
  )
815
868
  ]
816
869
  }
@@ -11,9 +11,10 @@ type DropdownTriggerProps = {
11
11
  labelId: string | undefined;
12
12
  clearLabel: string;
13
13
  removeItemLabel: string;
14
- descriptionId: string | undefined;
14
+ describedById: string | undefined;
15
+ isInvalid: boolean;
15
16
  onFocus: (event: React.FocusEvent) => void;
16
17
  onBlur: (event: React.FocusEvent) => void;
17
18
  };
18
- export declare const DropdownTrigger: ({ isMultiple, isSearchable, clearable, selectedLabel, selectedItems, placeholder, ariaLabel, labelId, clearLabel, removeItemLabel, descriptionId, onFocus, onBlur, }: DropdownTriggerProps) => React.ReactElement;
19
+ export declare const DropdownTrigger: ({ isMultiple, isSearchable, clearable, selectedLabel, selectedItems, placeholder, ariaLabel, labelId, clearLabel, removeItemLabel, describedById, isInvalid, onFocus, onBlur, }: DropdownTriggerProps) => React.ReactElement;
19
20
  export {};
@@ -86,6 +86,8 @@ export declare const DisplayNames: {
86
86
  optionValue: string;
87
87
  value: string;
88
88
  values: string;
89
+ defaultValue: string;
90
+ defaultValues: string;
89
91
  inputValue: string;
90
92
  open: string;
91
93
  isDisabled: string;
@@ -187,11 +189,13 @@ export declare const ALL_VALUE = "";
187
189
  export declare const TestIds: {
188
190
  readonly root: "dropdown-root";
189
191
  readonly label: "dropdown-label";
192
+ readonly requiredIndicator: "dropdown-required-indicator";
190
193
  readonly trigger: "dropdown-trigger";
191
194
  readonly listbox: "dropdown-listbox";
192
195
  readonly clear: "dropdown-clear";
193
196
  readonly applyButton: "dropdown-apply-button";
194
197
  readonly description: "dropdown-description";
198
+ readonly errorMessage: "dropdown-error-message";
195
199
  };
196
200
  export declare const selectors: {
197
201
  readonly root: "dropdown";
@@ -206,6 +210,7 @@ export declare const selectors: {
206
210
  export declare const semanticClassNames: {
207
211
  readonly root: "dropdown";
208
212
  readonly label: "dropdown__label";
213
+ readonly requiredIndicator: "dropdown__required-indicator";
209
214
  readonly input: "dropdown__input";
210
215
  readonly trigger: "dropdown__trigger";
211
216
  readonly clear: "dropdown__clear";
@@ -214,6 +219,7 @@ export declare const semanticClassNames: {
214
219
  readonly chips: "dropdown__chips";
215
220
  readonly chip: "dropdown__chip";
216
221
  readonly applyButton: "dropdown__apply-button";
222
+ readonly errorMessage: "dropdown__error-message";
217
223
  };
218
224
  export declare const ARIA_LABEL_NAMESPACE = "ariaLabels";
219
225
  export declare const AriaLabels: {
@@ -230,3 +236,5 @@ export declare const AriaLabels: {
230
236
  readonly default: "Remove";
231
237
  };
232
238
  };
239
+ /** Intrinsic `required` failure message (pre-resolved; i18n is a shared TODO). */
240
+ export declare const VALUE_MISSING_MESSAGE = "Please select an option.";
@@ -1,3 +1,177 @@
1
+ .root-ECdHfF {
2
+ flex-direction: column;
3
+ gap: 4px;
4
+ display: flex;
5
+ }
6
+
7
+ .label-YSWZBs {
8
+ font: var(--wst-paragraph-3-font);
9
+ color: var(--wst-paragraph-2-color, #000);
10
+ margin-bottom: 4px;
11
+ }
12
+
13
+ .root-ECdHfF:has([disabled]) .label-YSWZBs, .root-ECdHfF[data-disabled] .label-YSWZBs {
14
+ color: var(--wst-system-disabled-color, #939393);
15
+ }
16
+
17
+ .error-BUDKWp {
18
+ font: var(--wst-paragraph-3-font);
19
+ color: var(--wst-system-error-color, #df3131);
20
+ align-items: center;
21
+ gap: 4px;
22
+ display: flex;
23
+ }
24
+
25
+ .error-BUDKWp svg {
26
+ flex-shrink: 0;
27
+ width: 1lh;
28
+ height: 1lh;
29
+ }
30
+
31
+ .description-IVviYU {
32
+ font: var(--wst-paragraph-3-font);
33
+ color: var(--wst-shade-3-color, #767676);
34
+ }
35
+
36
+ .descriptionEnd-O3mOtW {
37
+ text-align: end;
38
+ align-self: flex-end;
39
+ }
40
+
41
+ .control-fRhDZ8 {
42
+ width: 100%;
43
+ }
44
+
45
+ .control-fRhDZ8.controlLine-cAw0CF {
46
+ border: 0;
47
+ border-block-end-width: var(--wst-system-line-1-width, 1px);
48
+ border-block-end-style: solid;
49
+ border-block-end-color: color-mix(in srgb,
50
+ var(--wst-system-line-1-color, #000) 60%,
51
+ transparent);
52
+ border-radius: 0;
53
+ padding-inline: 0;
54
+ }
55
+
56
+ .control-fRhDZ8.controlLine-cAw0CF:hover, .control-fRhDZ8.controlLine-cAw0CF:focus {
57
+ border-block-end-color: var(--wst-system-line-1-color, #000);
58
+ }
59
+
60
+ .root-ECdHfF:has(.labelFloating-io8BLN) {
61
+ position: relative;
62
+ }
63
+
64
+ .root-ECdHfF:has(.labelFloating-io8BLN) .control-fRhDZ8 {
65
+ block-size: 50px;
66
+ padding-block: 24px 6px;
67
+ }
68
+
69
+ .root-ECdHfF:has(.labelFloating-io8BLN) .group-XazO1A {
70
+ align-items: end;
71
+ padding-block: 0;
72
+ }
73
+
74
+ .root-ECdHfF:has(.labelFloating-io8BLN) .adornment-Z1N0NF {
75
+ padding-block-end: 6px;
76
+ }
77
+
78
+ .labelFloating-io8BLN {
79
+ z-index: 2;
80
+ color: var(--wst-shade-3-color, #767676);
81
+ pointer-events: none;
82
+ margin: 0;
83
+ transition: inset-block-start .12s, transform .12s, font-size .12s;
84
+ position: absolute;
85
+ inset-block-start: 50%;
86
+ inset-inline-start: 12px;
87
+ transform: translateY(-50%);
88
+ }
89
+
90
+ .labelFloating-io8BLN[data-filled], .labelFloating-io8BLN[data-focused], .root-ECdHfF:has(.control-fRhDZ8[placeholder]:not([placeholder=""])) .labelFloating-io8BLN, .root-ECdHfF:has(.labelFloating-io8BLN):has(.adornment-Z1N0NF) .labelFloating-io8BLN {
91
+ font-size: 12px;
92
+ inset-block-start: 8px;
93
+ transform: translateY(0);
94
+ }
95
+
96
+ .item-kQeHOQ {
97
+ width: 100%;
98
+ }
99
+
100
+ div.group-XazO1A {
101
+ align-items: center;
102
+ gap: 8px;
103
+ display: flex;
104
+ }
105
+
106
+ .group-XazO1A:focus-within {
107
+ border-color: var(--wst-system-line-1-color, #000);
108
+ }
109
+
110
+ .group-XazO1A:has(.control-fRhDZ8:focus) {
111
+ box-shadow: 0 0 0 2px var(--wst-links-and-actions-color, #116dff);
112
+ }
113
+
114
+ .group-XazO1A:has(.control-fRhDZ8[aria-invalid="true"]) {
115
+ border-color: color-mix(in srgb,
116
+ var(--wst-system-error-color, #df3131) 60%,
117
+ transparent);
118
+ }
119
+
120
+ .group-XazO1A:has(.control-fRhDZ8[aria-invalid="true"]):hover, .group-XazO1A:has(.control-fRhDZ8[aria-invalid="true"]):focus-within {
121
+ border-color: var(--wst-system-error-color, #df3131);
122
+ }
123
+
124
+ .group-XazO1A:has(.control-fRhDZ8[data-valid]) {
125
+ border-color: color-mix(in srgb,
126
+ var(--wst-system-success-color, #008250) 60%,
127
+ transparent);
128
+ }
129
+
130
+ .group-XazO1A:has(.control-fRhDZ8:disabled) {
131
+ cursor: not-allowed;
132
+ }
133
+
134
+ .group-XazO1A:has(.control-fRhDZ8:disabled):hover {
135
+ border-color: color-mix(in srgb,
136
+ var(--wst-system-line-1-color, #000) 60%,
137
+ transparent);
138
+ }
139
+
140
+ .group-XazO1A:has(.control-fRhDZ8:disabled) .adornment-Z1N0NF {
141
+ color: var(--wst-system-disabled-color, #939393);
142
+ }
143
+
144
+ .group-XazO1A.groupLine-vlna4V {
145
+ border-width: 0;
146
+ border-block-end-width: var(--wst-system-line-1-width, 1px);
147
+ border-radius: 0;
148
+ padding-inline: 0;
149
+ }
150
+
151
+ .group-XazO1A .control-fRhDZ8 {
152
+ background-color: #0000;
153
+ border: 0;
154
+ flex: auto;
155
+ width: auto;
156
+ min-width: 0;
157
+ padding-block: 0;
158
+ padding-inline: 0;
159
+ }
160
+
161
+ .adornment-Z1N0NF {
162
+ font: var(--wst-paragraph-2-font);
163
+ color: var(--wst-shade-3-color, #767676);
164
+ flex-shrink: 0;
165
+ align-items: center;
166
+ display: inline-flex;
167
+ }
168
+
169
+ .adornment-Z1N0NF > svg {
170
+ width: 20px;
171
+ height: 20px;
172
+ display: block;
173
+ }
174
+
1
175
  .root__WnTks {
2
176
  box-sizing: border-box;
3
177
  display: inline-flex;
@@ -65,6 +239,15 @@
65
239
  flex-direction: column;
66
240
  gap: var(--gap, 4px);
67
241
  }
242
+ .select__Lo-N7[data-invalid] .trigger__J7jn7 {
243
+ border-color: var(--errorColor, var(--wst-error-color, #e21c21));
244
+ }
245
+
246
+ .errorMessage__iMuAa {
247
+ margin: 0;
248
+ font: var(--helperFont, var(--wst-paragraph-3-font));
249
+ color: var(--errorColor, var(--wst-error-color, #e21c21));
250
+ }
68
251
 
69
252
  .label__Q7fZH {
70
253
  font: var(--labelFont, var(--wst-paragraph-2-font));
@@ -254,6 +437,14 @@
254
437
  --gap: 8px;
255
438
  --textAlign: start;
256
439
  }
440
+ .requiredIndicator__j5mIH {
441
+ display: inline-block;
442
+ width: 0.6em;
443
+ height: 0.6em;
444
+ margin-inline-start: 0.2em;
445
+ vertical-align: super;
446
+ color: inherit;
447
+ }
257
448
  .fallbackDirection__HeRgn:not([dir]) {
258
449
  direction: var(--wix-opt-in-direction);
259
450
  }
@@ -18,7 +18,5 @@ export declare const createFilterItem: (params: {
18
18
  isMultiple: boolean;
19
19
  inline: boolean;
20
20
  }) => (item: DropdownItem, typed: string) => boolean;
21
- export declare const emitChange: (onChange: NonNullable<DropdownProps["onChange"]>, value: string | Array<{
22
- value: string;
23
- }>) => void;
21
+ export declare const emitChange: (onChange: NonNullable<DropdownProps["onChange"]>, value: string | Array<string>) => void;
24
22
  export declare const emitInput: (onInput: NonNullable<DropdownProps["onInput"]>, value: string) => void;
@@ -3,9 +3,10 @@ import { D as DesignStates, f as DisplayNames, d as defaultValues, F as Function
3
3
  import { w as withSpec, g as getSelector } from "../chunks/manifest.js";
4
4
  import { I as IS_SUPPORT_DESIGN_STATE_SPEC } from "../chunks/specs.js";
5
5
  import { m as manifestFocusable, b as manifestInputable, a as manifestChangeable } from "../chunks/manifestSdkMixins.js";
6
+ import { m as manifestValidation } from "../chunks/manifest2.js";
6
7
  const manifest = {
7
- id: "f49b3649-fff3-42b4-8e18-a3cd2b23c2eb",
8
- type: "wixEditorElements.Dropdown__DEV__v3",
8
+ id: "f49b3649-fff3-42b4-8e18-a3cd2b23c2ec",
9
+ type: "wixEditorElements.Dropdown__DEV__v4",
9
10
  description: "A single-select dropdown input. Visitors pick a value from a list of options (and can clear it when enabled). Options can be set statically or fed dynamically by a connected data source. Turn on search to filter a long list.",
10
11
  installation: {
11
12
  initialSize: {
@@ -341,13 +342,25 @@ const manifest = {
341
342
  dataType: DATA.DATA_TYPE.arrayItems,
342
343
  displayName: DisplayNames.root.data.values,
343
344
  [DATA.DATA_TYPE.arrayItems]: {
344
- data: {
345
- items: {
346
- value: {
347
- dataType: DATA.DATA_TYPE.text,
348
- displayName: DisplayNames.root.data.optionValue
349
- }
350
- }
345
+ dataItem: {
346
+ dataType: DATA.DATA_TYPE.text,
347
+ displayName: DisplayNames.root.data.optionValue
348
+ }
349
+ }
350
+ },
351
+ // Uncontrolled counterparts of value/values, used only when the
352
+ // controlled field isn't bound.
353
+ defaultValue: {
354
+ dataType: DATA.DATA_TYPE.text,
355
+ displayName: DisplayNames.root.data.defaultValue
356
+ },
357
+ defaultValues: {
358
+ dataType: DATA.DATA_TYPE.arrayItems,
359
+ displayName: DisplayNames.root.data.defaultValues,
360
+ [DATA.DATA_TYPE.arrayItems]: {
361
+ dataItem: {
362
+ dataType: DATA.DATA_TYPE.text,
363
+ displayName: DisplayNames.root.data.optionValue
351
364
  }
352
365
  }
353
366
  },
@@ -473,7 +486,8 @@ const manifest = {
473
486
  },
474
487
  ...manifestChangeable(),
475
488
  ...manifestInputable(),
476
- ...manifestFocusable()
489
+ ...manifestFocusable(),
490
+ ...manifestValidation({ valueDataType: DATA.DATA_TYPE.text })
477
491
  },
478
492
  displayGroups: {
479
493
  optionsGroup: {
@@ -490,6 +504,7 @@ const manifest = {
490
504
  items: [
491
505
  "required",
492
506
  "readOnly",
507
+ "isDisabled",
493
508
  "searchable",
494
509
  "multiple",
495
510
  "clearable",
@@ -2273,16 +2273,22 @@ const Menu = (props) => {
2273
2273
  TranslationsDefinition
2274
2274
  );
2275
2275
  const translations = {
2276
- menuNavAriaLabel: translate(ARIA_LABEL_NAMESPACE)(translationsKeys.menuNavAriaLabel) || defaultTranslations.menuNavAriaLabel,
2276
+ menuNavAriaLabel: translate(ARIA_LABEL_NAMESPACE)(
2277
+ translationsKeys.menuNavAriaLabel,
2278
+ defaultTranslations.menuNavAriaLabel
2279
+ ),
2277
2280
  dropdownButtonAriaLabel: translate(ARIA_LABEL_NAMESPACE)(
2278
- translationsKeys.dropdownButtonAriaLabel
2279
- ) || defaultTranslations.dropdownButtonAriaLabel,
2281
+ translationsKeys.dropdownButtonAriaLabel,
2282
+ defaultTranslations.dropdownButtonAriaLabel
2283
+ ),
2280
2284
  hamburgerOpenButtonAriaLabel: translate(ARIA_LABEL_NAMESPACE)(
2281
- translationsKeys.hamburgerOpenButtonAriaLabel
2282
- ) || defaultTranslations.hamburgerOpenButtonAriaLabel,
2285
+ translationsKeys.hamburgerOpenButtonAriaLabel,
2286
+ defaultTranslations.hamburgerOpenButtonAriaLabel
2287
+ ),
2283
2288
  hamburgerCloseButtonAriaLabel: translate(ARIA_LABEL_NAMESPACE)(
2284
- translationsKeys.hamburgerCloseButtonAriaLabel
2285
- ) || defaultTranslations.hamburgerCloseButtonAriaLabel
2289
+ translationsKeys.hamburgerCloseButtonAriaLabel,
2290
+ defaultTranslations.hamburgerCloseButtonAriaLabel
2291
+ )
2286
2292
  };
2287
2293
  const presetsWrapperProps = (wix == null ? void 0 : wix.presetsWrapperProps) || {};
2288
2294
  return /* @__PURE__ */ jsx("div", { className: presetWrapperStyles.presetWrapper, ...presetsWrapperProps, children: /* @__PURE__ */ jsx(
@@ -312,7 +312,12 @@ export type Translations = {
312
312
  hamburgerCloseButtonAriaLabel?: string;
313
313
  };
314
314
  };
315
- export declare const defaultTranslations: Translations['translations'];
315
+ export declare const defaultTranslations: {
316
+ menuNavAriaLabel: string;
317
+ dropdownButtonAriaLabel: string;
318
+ hamburgerOpenButtonAriaLabel: string;
319
+ hamburgerCloseButtonAriaLabel: string;
320
+ };
316
321
  export declare const MenuParts: {
317
322
  readonly Root: "menu-root";
318
323
  readonly Navbar: "navbar";
@@ -6,11 +6,12 @@ import { useService } from "@wix/services-manager-react";
6
6
  import { E as EnvironmentDefinition } from "../chunks/index2.js";
7
7
  import { f as formatClassNames } from "../chunks/classNames.js";
8
8
  import { a as getDataAttributes } from "../chunks/dataUtils.js";
9
- import { R as RequiredIndicator, I as InfoCircleSmall_default } from "../chunks/RequiredIndicator.js";
9
+ import { R as RequiredIndicator } from "../chunks/RequiredIndicator.js";
10
10
  import { u as useValidatedField } from "../chunks/useValidatedField.js";
11
11
  import { d as directionStyles } from "../chunks/direction.module.js";
12
12
  import { p as presetWrapperStyles } from "../chunks/presetWrapper.module.js";
13
13
  import { d as defaultValues, a as defaultOptions, V as VALUE_MISSING_MESSAGE, s as selectors, T as TestIds, b as semanticClassNames } from "../chunks/constants24.js";
14
+ import { I as InfoCircleSmall_default } from "../chunks/InfoCircleSmall.js";
14
15
  const root = "root__4SkBh";
15
16
  const fieldset = "fieldset__2OxuS";
16
17
  const labelRow = "labelRow__xKUgE";
@@ -6,11 +6,12 @@ import { useService } from "@wix/services-manager-react";
6
6
  import { E as EnvironmentDefinition } from "../chunks/index2.js";
7
7
  import { f as formatClassNames } from "../chunks/classNames.js";
8
8
  import { a as getDataAttributes } from "../chunks/dataUtils.js";
9
- import { R as RequiredIndicator, I as InfoCircleSmall_default } from "../chunks/RequiredIndicator.js";
9
+ import { R as RequiredIndicator } from "../chunks/RequiredIndicator.js";
10
10
  import { d as directionStyles } from "../chunks/direction.module.js";
11
11
  import { p as presetWrapperStyles } from "../chunks/presetWrapper.module.js";
12
12
  import { d as defaultValues, s as selectors, T as TestIds, V as VALIDATION_MESSAGES, a as semanticClassNames } from "../chunks/constants18.js";
13
13
  import { u as useValidatedField } from "../chunks/useValidatedField.js";
14
+ import { I as InfoCircleSmall_default } from "../chunks/InfoCircleSmall.js";
14
15
  const root = "root__dlp5n";
15
16
  const field = "field__i7dfL";
16
17
  const errorMessage = "errorMessage__K0qsG";
@@ -5,7 +5,7 @@ import { c as clsx } from "../chunks/clsx.js";
5
5
  import { E as EnvironmentDefinition } from "../chunks/index2.js";
6
6
  import { b as getAccessibilityAttributes, H as HAS_CUSTOM_FOCUS_CLASSNAME } from "../chunks/a11y.js";
7
7
  import { a as getDataAttributes } from "../chunks/dataUtils.js";
8
- import { R as RequiredIndicator, I as InfoCircleSmall_default } from "../chunks/RequiredIndicator.js";
8
+ import { R as RequiredIndicator } from "../chunks/RequiredIndicator.js";
9
9
  import { u as useValidatedField } from "../chunks/useValidatedField.js";
10
10
  import { s as selectors, T as TestIds, V as VALUE_MISSING_MESSAGE } from "../chunks/constants3.js";
11
11
  import { useService } from "@wix/services-manager-react";
@@ -14,6 +14,7 @@ import { c as $3e6197669829fe11$export$40bfa8c7b0832715, d as $d1116acdf220c2da$
14
14
  import { d as $fd2148440a13ec26$export$fc1a364ae1f3ff10, e as $191c9b6d48a0a4e2$export$294aa081a6c6f55d, f as $860f7da480e22816$export$b8473d3665f3a75a, g as $d3e0e05bdfcf66bd$export$c24727297075ec6a, h as $3985021b0ad6602f$export$37fb8590cf2c088c, i as $514c0188e459b4c0$export$9afb8bc826b033ea, j as $ee014567cb39d3f0$export$ff05c3ac10437e03, $ as $4e3b923658d69c60$export$8c610744efcf8a1d, a as $4e3b923658d69c60$export$28c660c63b792dea, k as $3985021b0ad6602f$export$f5b8910cec6cf069 } from "../chunks/Tooltip.js";
15
15
  import { a as $8e9d2fae0ecb9001$export$457c3d6518dd4c6f, b as $f39a9eba43920ace$export$86427a43e3e48ebb, c as $64fa3d84918910a7$export$29f1550f4b0d4415, d as $64fa3d84918910a7$export$fabf2dc03a41866e, e as $64fa3d84918910a7$export$9d4c57ee4c6ffdd8, f as $64fa3d84918910a7$export$ef03459518577ad4, g as $64fa3d84918910a7$export$4d86445c2cf5e3, h as $65484d02dcb7eb3e$export$457c3d6518dd4c6f, i as $64fa3d84918910a7$export$2881499e37b75b9a } from "../chunks/filterDOMProps.js";
16
16
  import { S as SdkStateDefinition } from "../chunks/index6.js";
17
+ import { I as InfoCircleSmall_default } from "../chunks/InfoCircleSmall.js";
17
18
  const $8e6cc465cc68f603$export$698f465ec27e93df = /* @__PURE__ */ createContext(null);
18
19
  function $054f71d2330da2e3$export$712718f7aec83d5(props, ref) {
19
20
  let { inputElementType = "input", isDisabled = false, isRequired = false, isReadOnly = false, type = "text", validationBehavior = "aria" } = props;
@@ -13,8 +13,9 @@ import { d as directionStyles } from "../chunks/direction.module.js";
13
13
  import { p as presetWrapperStyles } from "../chunks/presetWrapper.module.js";
14
14
  import { E as EMPTY_VALUE, T as TestIds, s as selectors, a as TRANSLATIONS_NAMESPACE, d as defaultValues, V as VALUE_MISSING_MESSAGE, H as HourCycleValues, D as DefaultTranslations, b as TranslationKeys } from "../chunks/constants2.js";
15
15
  import { u as useValidatedField } from "../chunks/useValidatedField.js";
16
- import { R as RequiredIndicator, I as InfoCircleSmall_default } from "../chunks/RequiredIndicator.js";
16
+ import { R as RequiredIndicator } from "../chunks/RequiredIndicator.js";
17
17
  import { D as DismissSmall_default } from "../chunks/DismissSmall.js";
18
+ import { I as InfoCircleSmall_default } from "../chunks/InfoCircleSmall.js";
18
19
  const getTranslation = (translate, key, translationKeys, defaultTranslations) => {
19
20
  const translationKey = translationKeys[key];
20
21
  const translated = translate(translationKey);
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ const InfoCircleSmall = ({ size, ...props }) => /* @__PURE__ */ React.createElement("svg", { viewBox: "0 0 18 18", fill: "currentColor", width: size || "18", height: size || "18", ...props }, /* @__PURE__ */ React.createElement("path", { d: "M9,16 C5.13400675,16 2,12.8659932 2,9 C2,5.13400675 5.13400675,2 9,2 C12.8659932,2 16,5.13400675 16,9 C16,12.8659932 12.8659932,16 9,16 Z M9,15 C12.3137085,15 15,12.3137085 15,9 C15,5.6862915 12.3137085,3 9,3 C5.6862915,3 3,5.6862915 3,9 C3,12.3137085 5.6862915,15 9,15 Z M8,8 L10,8 L10,12 L11,13 L7,13 L8,12 L8,8.85714286 L7,8.85714286 L8,8 Z M9,5 C9.55228475,5 10,5.44771525 10,6 C10,6.55228475 9.55228475,7 9,7 C8.44771525,7 8,6.55228475 8,6 C8,5.44771525 8.44771525,5 9,5 Z" }));
3
+ InfoCircleSmall.displayName = "InfoCircleSmall";
4
+ var InfoCircleSmall_default = InfoCircleSmall;
5
+ export {
6
+ InfoCircleSmall_default as I
7
+ };
@@ -1,9 +1,6 @@
1
- import * as React from "react";
2
1
  import { jsx } from "react/jsx-runtime";
3
2
  import { c as clsx } from "./clsx.js";
4
- const InfoCircleSmall = ({ size, ...props }) => /* @__PURE__ */ React.createElement("svg", { viewBox: "0 0 18 18", fill: "currentColor", width: size || "18", height: size || "18", ...props }, /* @__PURE__ */ React.createElement("path", { d: "M9,16 C5.13400675,16 2,12.8659932 2,9 C2,5.13400675 5.13400675,2 9,2 C12.8659932,2 16,5.13400675 16,9 C16,12.8659932 12.8659932,16 9,16 Z M9,15 C12.3137085,15 15,12.3137085 15,9 C15,5.6862915 12.3137085,3 9,3 C5.6862915,3 3,5.6862915 3,9 C3,12.3137085 5.6862915,15 9,15 Z M8,8 L10,8 L10,12 L11,13 L7,13 L8,12 L8,8.85714286 L7,8.85714286 L8,8 Z M9,5 C9.55228475,5 10,5.44771525 10,6 C10,6.55228475 9.55228475,7 9,7 C8.44771525,7 8,6.55228475 8,6 C8,5.44771525 8.44771525,5 9,5 Z" }));
5
- InfoCircleSmall.displayName = "InfoCircleSmall";
6
- var InfoCircleSmall_default = InfoCircleSmall;
3
+ import * as React from "react";
7
4
  const Asterisk = ({ size, ...props }) => /* @__PURE__ */ React.createElement("svg", { viewBox: "0 0 7 7", fill: "currentColor", width: size || "7", height: size || "7", ...props }, /* @__PURE__ */ React.createElement("path", { d: "M1.809 7 1 6.397 2.74 3.94 0 3.026l.31-.974L3 2.948V0h1v2.976l2.69-.924.31.975-2.719.934L6 6.397 5.19 7 3.503 4.609 1.809 7Z" }));
8
5
  Asterisk.displayName = "Asterisk";
9
6
  var Asterisk_default = Asterisk;
@@ -24,6 +21,5 @@ const RequiredIndicator = ({
24
21
  }
25
22
  );
26
23
  export {
27
- InfoCircleSmall_default as I,
28
24
  RequiredIndicator as R
29
25
  };
@@ -53,6 +53,8 @@ const DisplayNames = {
53
53
  optionValue: "Value",
54
54
  value: "Selected value",
55
55
  values: "Selected values",
56
+ defaultValue: "Default value",
57
+ defaultValues: "Default values",
56
58
  inputValue: "Search query",
57
59
  open: "Open",
58
60
  isDisabled: "Disabled",
@@ -154,11 +156,13 @@ const ALL_VALUE = "";
154
156
  const TestIds = {
155
157
  root: "dropdown-root",
156
158
  label: "dropdown-label",
159
+ requiredIndicator: "dropdown-required-indicator",
157
160
  trigger: "dropdown-trigger",
158
161
  listbox: "dropdown-listbox",
159
162
  clear: "dropdown-clear",
160
163
  applyButton: "dropdown-apply-button",
161
- description: "dropdown-description"
164
+ description: "dropdown-description",
165
+ errorMessage: "dropdown-error-message"
162
166
  };
163
167
  const selectors = {
164
168
  root: "dropdown",
@@ -173,6 +177,7 @@ const selectors = {
173
177
  const semanticClassNames = {
174
178
  root: "dropdown",
175
179
  label: "dropdown__label",
180
+ requiredIndicator: "dropdown__required-indicator",
176
181
  input: "dropdown__input",
177
182
  trigger: "dropdown__trigger",
178
183
  clear: "dropdown__clear",
@@ -180,7 +185,8 @@ const semanticClassNames = {
180
185
  option: "dropdown__option",
181
186
  chips: "dropdown__chips",
182
187
  chip: "dropdown__chip",
183
- applyButton: "dropdown__apply-button"
188
+ applyButton: "dropdown__apply-button",
189
+ errorMessage: "dropdown__error-message"
184
190
  };
185
191
  const ARIA_LABEL_NAMESPACE = "ariaLabels";
186
192
  const AriaLabels = {
@@ -188,11 +194,13 @@ const AriaLabels = {
188
194
  clear: { key: "Dropdown_AriaLabel_Clear", default: "Clear" },
189
195
  removeItem: { key: "Dropdown_AriaLabel_RemoveItem", default: "Remove" }
190
196
  };
197
+ const VALUE_MISSING_MESSAGE = "Please select an option.";
191
198
  export {
192
199
  ALL_VALUE as A,
193
200
  DesignStates as D,
194
201
  FunctionalStateKeys as F,
195
202
  TestIds as T,
203
+ VALUE_MISSING_MESSAGE as V,
196
204
  semanticClassNames as a,
197
205
  TriggerModeValues as b,
198
206
  ARIA_LABEL_NAMESPACE as c,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/editor-react-components",
3
- "version": "1.2358.0",
3
+ "version": "1.2359.0",
4
4
  "description": "React components for the Wix Editor",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -143,7 +143,7 @@
143
143
  "@wix/viewer-service-sdk-state": "^1.0.28",
144
144
  "@wix/viewer-service-site-scroll-blocker": "^1.0.63",
145
145
  "@wix/viewer-service-topology": "^1.0.26",
146
- "@wix/viewer-service-translations": "^1.0.22",
146
+ "@wix/viewer-service-translations": "^1.0.23",
147
147
  "@wix/viewer-service-url": "^1.0.69",
148
148
  "astro": "^5.16.6",
149
149
  "clsx": "2.0.0",
@@ -199,5 +199,5 @@
199
199
  "registry": "https://registry.npmjs.org/",
200
200
  "access": "public"
201
201
  },
202
- "falconPackageHash": "d4bfc9da268b29efe1ddb1073eee5deb49e827b001018a694cf859ad"
202
+ "falconPackageHash": "161e4b7e541ef3b527e8626a785456eb4e6659d13805356f786a18ab"
203
203
  }