@marwes-ui/react 1.3.0 → 1.4.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/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { MarwesThemeScript, MarwesThemeStyle, createMarwesThemeScript, createMarwesThemeStyle } from './chunk-VFY2GW62.js';
2
2
  import '@marwes-ui/presets/firstEdition/styles.css';
3
- import { createRichTextRecipe, resolveRichTextAllowedFormats, normalizeRichTextHtml, isRichTextHtmlEmpty, createDividerRecipe, createSpacingRecipe, createSliderRecipe, richTextCommandByFormat, resolveIconSize, resolveIconStrokeWidth, iconRegistry, resolveIconA11y, ThemeMode, resolveThemePreference, nextThemeMode, resolveThemeInput, createSpinnerRecipe, createButtonRecipe, ButtonAction, ButtonVariant, IconName, createInputRecipe, createSelectRecipe, resolveSelectMode, createTextareaRecipe, paragraphRecipe, buildInputFieldA11yIds, sanitizeInputOtpValue, createInputOtpRecipe, buildRichTextFieldA11yIds, buildCurrencyHelperText, getCurrencySymbol, createAvatarRecipe, createPurposeSemanticAttributes, checkboxRecipe, buildCheckboxFieldA11yIds, buildCheckboxGroupFieldA11yIds, createSkeletonRecipe, headingRecipe, createStatTileRecipe, createDatePickerRecipe, createCardRecipe, createToastRecipe, createTooltipRecipe, createAccordionRecipe, buildAccordionFieldA11yIds, radioRecipe, buildRadioGroupFieldA11yIds, createBadgeRecipe, createSwitchRecipe, buildSwitchFieldA11yIds, buildSliderFieldA11yIds, createTabRecipe, resolveTabValue, buildTabGroupA11yIds, moveTabSelection, createDialogRecipe, sanitizeCurrencyValue, isThemePreference, themeToCSSVars, extractUsedWeights, extractFontFamilyName, shouldLoadGoogleFont, buildGoogleFontsUrl } from '@marwes-ui/core';
4
- export { AvatarSize, AvatarType, BadgeVariant, ButtonAction, ButtonSize, ButtonVariant, IconName, Spacings, SwitchSize, ThemeMode, createFontStack, mwAvailableFonts, mwFontFallbacks, mwGoogleFontFamilies, mwStyledTheme, mwThemeVarNames, mwThemeVars, mwVar } from '@marwes-ui/core';
3
+ import { createRichTextRecipe, resolveRichTextAllowedFormats, normalizeRichTextHtml, isRichTextHtmlEmpty, createDividerRecipe, createSpacingRecipe, createSliderRecipe, richTextCommandByFormat, resolveIconSize, resolveIconStrokeWidth, iconRegistry, resolveIconA11y, ThemeMode, resolveThemePreference, nextThemeMode, resolveThemeInput, createMwTheme, createSpinnerRecipe, createButtonRecipe, ButtonVariant, ButtonAction, IconName, textRecipe, buildInputFieldA11yIds, resolveSelectMode, buildRichTextFieldA11yIds, buildCurrencyHelperText, getCurrencySymbol, createAvatarRecipe, createPurposeSemanticAttributes, createContextMenuRecipe, createBreadcrumbRecipe, createSkeletonRecipe, createProgressBarRecipe, headingRecipe, paragraphRecipe, createStatTileRecipe, createDrawerRecipe, createCardRecipe, createToastRecipe, createTooltipRecipe, buildAccordionFieldA11yIds, buildRadioGroupFieldA11yIds, createBadgeRecipe, createBannerRecipe, buildSwitchFieldA11yIds, buildSliderFieldA11yIds, createTabRecipe, resolveTabValue, buildTabGroupA11yIds, moveTabSelection, createSkipLinkRecipe, createDialogRecipe, buildCheckboxFieldA11yIds, buildCheckboxGroupFieldA11yIds, sanitizeCurrencyValue, isThemePreference, themeToCSSVars, extractUsedWeights, extractFontFamilyName, shouldLoadGoogleFont, createInputRecipe, sanitizeInputOtpValue, createInputOtpRecipe, createSelectRecipe, createTextareaRecipe, createDatePickerRecipe, createAccordionRecipe, radioRecipe, createSwitchRecipe, resolveSegmentedControlValue, moveSegmentedControlSelection, createSegmentedControlRecipe, createSegmentedControlItemRecipe, clampPaginationPage, createPaginationRecipe, createPaginationListRecipe, createPaginationListItemRecipe, createPaginationControlRecipe, resolvePaginationItemAriaLabel, createPaginationEllipsisRecipe, createPaginationPageRecipe, checkboxRecipe, buildGoogleFontsUrl, resolvePaginationAdaptiveProfile } from '@marwes-ui/core';
4
+ export { AvatarSize, AvatarType, BadgeVariant, BannerVariant, ButtonAction, ButtonSize, ButtonVariant, IconName, Spacings, SwitchSize, TextVariant, ThemeMode, createFontStack, createMwTheme, createMwThemeMedia, mwAvailableFonts, mwFontFallbacks, mwGoogleFontFamilies, mwStyledTheme, mwTheme, mwThemeVarNames, mwThemeVars, mwVar } from '@marwes-ui/core';
5
5
  import * as React2 from 'react';
6
6
  import { useEffect } from 'react';
7
7
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -157,7 +157,7 @@ function MarwesProvider({
157
157
  variableStrategy = "inline",
158
158
  children
159
159
  }) {
160
- const rootRef = React2.useRef(null);
160
+ const [providerElement, setProviderElement] = React2.useState(null);
161
161
  const [internalPreference, setInternalPreference] = React2.useState(
162
162
  defaultPreference ?? defaultMode ?? ThemeMode.light
163
163
  );
@@ -208,22 +208,24 @@ function MarwesProvider({
208
208
  () => resolveThemeInput({ ...theme ?? {}, mode: activeMode }),
209
209
  [activeMode, theme]
210
210
  );
211
+ const mwTheme2 = React2.useMemo(() => createMwTheme(resolved), [resolved]);
212
+ const renderedChildren = typeof children === "function" ? children(mwTheme2) : children;
211
213
  const rootStyle = React2.useMemo(() => {
212
214
  if (variableStrategy === "style-tag") return void 0;
213
215
  return themeToRootStyle(resolved);
214
216
  }, [resolved, variableStrategy]);
215
217
  React2.useEffect(() => {
216
218
  if (variableStrategy === "style-tag") return;
217
- if (rootRef.current) {
218
- applyThemeToElement(rootRef.current, resolved);
219
+ if (providerElement) {
220
+ applyThemeToElement(providerElement, resolved);
219
221
  }
220
- }, [resolved, variableStrategy]);
222
+ }, [providerElement, resolved, variableStrategy]);
221
223
  React2.useEffect(() => {
222
224
  if (target === "provider") return;
223
225
  const apply = () => {
224
226
  applyModeAttribute({
225
227
  target,
226
- providerElement: rootRef.current,
228
+ providerElement: null,
227
229
  mode: activeMode,
228
230
  attribute
229
231
  });
@@ -245,19 +247,30 @@ function MarwesProvider({
245
247
  systemMode,
246
248
  setMode,
247
249
  setPreference,
248
- toggleMode
250
+ toggleMode,
251
+ providerElement
249
252
  }),
250
- [activeMode, activePreference, resolved, setMode, setPreference, systemMode, toggleMode]
253
+ [
254
+ activeMode,
255
+ activePreference,
256
+ providerElement,
257
+ resolved,
258
+ setMode,
259
+ setPreference,
260
+ systemMode,
261
+ toggleMode
262
+ ]
251
263
  );
252
264
  return /* @__PURE__ */ jsx(MarwesContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
253
265
  "div",
254
266
  {
255
- ref: rootRef,
267
+ ref: setProviderElement,
256
268
  className: `mw-theme--${resolved.mode}`,
257
269
  "data-marwes-theme": "true",
258
270
  "data-marwes-mode": resolved.mode,
271
+ "data-marwes-personality": resolved.personality,
259
272
  style: rootStyle,
260
- children
273
+ children: renderedChildren
261
274
  }
262
275
  ) });
263
276
  }
@@ -285,14 +298,7 @@ function useThemeMode() {
285
298
  isSystem: ctx.preference === "system"
286
299
  };
287
300
  }
288
- function Icon({
289
- name,
290
- size,
291
- strokeWidth,
292
- className,
293
- "aria-label": ariaLabel,
294
- decorative
295
- }) {
301
+ function Icon({ name, size, strokeWidth, className, ariaLabel, decorative }) {
296
302
  const px = resolveIconSize(size ?? "sm");
297
303
  const sw = resolveIconStrokeWidth(strokeWidth ?? "md");
298
304
  const def = iconRegistry[name];
@@ -416,7 +422,12 @@ function EmptyStateSpinner(props) {
416
422
  );
417
423
  }
418
424
  function isFilledButtonVariant(variant) {
419
- return variant === "primary" || variant === "success";
425
+ return variant === "primary" || variant === "success" || variant === "danger";
426
+ }
427
+ function hasRenderableLabel(label) {
428
+ if (label === void 0 || label === null || label === false) return false;
429
+ if (typeof label === "string") return label.length > 0;
430
+ return true;
420
431
  }
421
432
  function Button(props) {
422
433
  const kit = createButtonRecipe(props);
@@ -433,7 +444,7 @@ function Button(props) {
433
444
  inverted: isFilledButtonVariant(resolvedVariant)
434
445
  }
435
446
  ) : props.iconLeft ? /* @__PURE__ */ jsx(Icon, { name: props.iconLeft, size: "xs", strokeWidth: "sm", decorative: true }) : null,
436
- visibleLabel,
447
+ hasRenderableLabel(visibleLabel) ? /* @__PURE__ */ jsx("span", { className: "mw-btn__label", children: visibleLabel }) : null,
437
448
  !resolvedLoading.isLoading && props.iconRight ? /* @__PURE__ */ jsx(Icon, { name: props.iconRight, size: "xs", strokeWidth: "sm", decorative: true }) : null
438
449
  ] });
439
450
  if (kit.tag === "button") {
@@ -443,6 +454,7 @@ function Button(props) {
443
454
  type: kit.a11y.type,
444
455
  disabled: kit.a11y.disabled,
445
456
  "aria-label": kit.a11y.ariaLabel,
457
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
446
458
  "aria-busy": kit.a11y.ariaBusy,
447
459
  "aria-disabled": kit.a11y.ariaDisabled,
448
460
  "aria-pressed": kit.a11y.ariaPressed,
@@ -464,6 +476,7 @@ function Button(props) {
464
476
  role: kit.a11y.role,
465
477
  tabIndex: kit.a11y.tabIndex,
466
478
  "aria-label": kit.a11y.ariaLabel,
479
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
467
480
  "aria-busy": kit.a11y.ariaBusy,
468
481
  "aria-disabled": kit.a11y.ariaDisabled,
469
482
  "aria-pressed": kit.a11y.ariaPressed,
@@ -484,6 +497,19 @@ function Button(props) {
484
497
  }
485
498
  );
486
499
  }
500
+ function IconButton(props) {
501
+ const { icon, variant = ButtonVariant.neutral, ...buttonProps } = props;
502
+ return /* @__PURE__ */ jsx(
503
+ Button,
504
+ {
505
+ ...buttonProps,
506
+ variant,
507
+ iconLeft: icon,
508
+ iconOnly: true,
509
+ hasVisibleText: false
510
+ }
511
+ );
512
+ }
487
513
  function isDevelopmentEnvironment() {
488
514
  const nodeProcess = globalThis.process;
489
515
  const nodeEnv = nodeProcess?.env?.NODE_ENV;
@@ -541,9 +567,8 @@ function DestructiveButton(props) {
541
567
  {
542
568
  ...forwardedProps,
543
569
  as: "button",
544
- variant: ButtonVariant.primary,
570
+ variant: ButtonVariant.danger,
545
571
  action: ButtonAction.delete,
546
- error: true,
547
572
  confirmation,
548
573
  dataAttributes: createPurposeButtonDataAttributes(
549
574
  "destructive",
@@ -858,6 +883,16 @@ function SuccessButton(props) {
858
883
  }
859
884
  );
860
885
  }
886
+ function Text(props) {
887
+ const { children, className: customClassName, style: customStyle, ...opts } = props;
888
+ const theme = useTheme();
889
+ const kit = textRecipe(opts, theme);
890
+ const Tag = kit.tag;
891
+ const style = { ...kit.vars, ...customStyle };
892
+ const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
893
+ return /* @__PURE__ */ jsx(Tag, { id: kit.a11y.id, className, style, children });
894
+ }
895
+ var TypographyText = Text;
861
896
  var RENDERKIT_EVENT = "marwes/renderkit/renderkit-update";
862
897
  var RENDERKIT_DEBUG_FLAG = "__MARWES_RENDERKIT_DEBUG__";
863
898
  function isRenderKitDebugEnabled() {
@@ -904,6 +939,7 @@ function Input(props) {
904
939
  readOnly: kit.a11y.readOnly,
905
940
  required: kit.a11y.required,
906
941
  "aria-label": kit.a11y.ariaLabel,
942
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
907
943
  "aria-invalid": kit.a11y.ariaInvalid,
908
944
  "aria-describedby": kit.a11y.ariaDescribedBy,
909
945
  value: props.value,
@@ -912,6 +948,234 @@ function Input(props) {
912
948
  }
913
949
  );
914
950
  }
951
+ function cx(...parts) {
952
+ return parts.filter(Boolean).join(" ");
953
+ }
954
+ function hasTextContent(value) {
955
+ return value !== void 0 && value.trim().length > 0;
956
+ }
957
+ function InputField(props) {
958
+ const reactId = React2.useId();
959
+ const id = props.id ?? `mw-input-${reactId}`;
960
+ const isPasswordField = props.input.type === "password";
961
+ const [showPassword, setShowPassword] = React2.useState(false);
962
+ const isSearchField = props.input.type === "search";
963
+ const [searchValue, setSearchValue] = React2.useState(
964
+ props.input.value || props.input.defaultValue || ""
965
+ );
966
+ const hasSearchValue = isSearchField && (props.input.value !== void 0 ? String(props.input.value).length > 0 : String(searchValue).length > 0);
967
+ const hasHelperText = hasTextContent(props.helperText);
968
+ const hasError = hasTextContent(props.error);
969
+ const {
970
+ helperTextId,
971
+ errorId,
972
+ describedBy: mergedDescribedBy
973
+ } = buildInputFieldA11yIds({
974
+ id,
975
+ hasHelperText,
976
+ hasError,
977
+ externalDescribedBy: props.ariaDescribedBy
978
+ });
979
+ const disabled = props.input.disabled || false;
980
+ const readOnly = props.input.readOnly || false;
981
+ const invalid = hasError || props.input.invalid || false;
982
+ const showSearchClearButton = hasSearchValue && !disabled && !readOnly;
983
+ const showSearchIcon = isSearchField && !showSearchClearButton;
984
+ const wrapperClass = cx(
985
+ "mw-input-field",
986
+ disabled && "mw-input-field--disabled",
987
+ invalid && "mw-input-field--invalid",
988
+ readOnly && "mw-input-field--readonly"
989
+ );
990
+ const inputProps = {
991
+ ...props.input,
992
+ id,
993
+ invalid
994
+ };
995
+ if (isPasswordField && showPassword) {
996
+ inputProps.type = "text";
997
+ }
998
+ if (isSearchField) {
999
+ const originalOnValueChange = props.input.onValueChange;
1000
+ if (props.input.value === void 0) {
1001
+ inputProps.value = searchValue;
1002
+ }
1003
+ inputProps.onValueChange = (value) => {
1004
+ setSearchValue(value);
1005
+ originalOnValueChange?.(value);
1006
+ };
1007
+ }
1008
+ if (mergedDescribedBy) {
1009
+ inputProps.describedBy = mergedDescribedBy;
1010
+ }
1011
+ const handleTogglePassword = () => {
1012
+ setShowPassword((prev) => !prev);
1013
+ };
1014
+ const handleClearSearch = () => {
1015
+ setSearchValue("");
1016
+ props.input.onValueChange?.("");
1017
+ };
1018
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
1019
+ /* @__PURE__ */ jsx("label", { className: "mw-input-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
1020
+ /* @__PURE__ */ jsxs("div", { className: "mw-input-field__input-wrapper", children: [
1021
+ props.leadingSymbol && /* @__PURE__ */ jsx("span", { className: "mw-input-field__leading-symbol", "aria-hidden": "true", children: props.leadingSymbol }),
1022
+ /* @__PURE__ */ jsx(Input, { ...inputProps }),
1023
+ isPasswordField && !disabled && /* @__PURE__ */ jsx(
1024
+ "button",
1025
+ {
1026
+ type: "button",
1027
+ className: "mw-input-field__toggle-password",
1028
+ onClick: handleTogglePassword,
1029
+ "aria-label": showPassword ? "Hide password" : "Show password",
1030
+ tabIndex: 0,
1031
+ children: /* @__PURE__ */ jsx(Icon, { name: showPassword ? "eyeOff" : "eye", size: "xs", decorative: true })
1032
+ }
1033
+ ),
1034
+ showSearchIcon && /* @__PURE__ */ jsx("span", { className: "mw-input-field__search-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon, { name: "search", size: "xs", decorative: true }) }),
1035
+ showSearchClearButton && /* @__PURE__ */ jsx(
1036
+ "button",
1037
+ {
1038
+ type: "button",
1039
+ className: "mw-input-field__clear-search",
1040
+ onClick: handleClearSearch,
1041
+ "aria-label": "Clear search",
1042
+ tabIndex: 0,
1043
+ children: /* @__PURE__ */ jsx(Icon, { name: "x", size: "xs", decorative: true })
1044
+ }
1045
+ )
1046
+ ] }),
1047
+ hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.helperText }) }),
1048
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
1049
+ ] });
1050
+ }
1051
+ function cx2(...parts) {
1052
+ return parts.filter(Boolean).join(" ");
1053
+ }
1054
+ function InputOtp(props) {
1055
+ const reactId = React2.useId();
1056
+ const id = props.id ?? `mw-input-otp-${reactId}`;
1057
+ const otpLength = Math.max(1, props.length ?? 6);
1058
+ const isControlled = props.value !== void 0;
1059
+ const [uncontrolledValue, setUncontrolledValue] = React2.useState(() => {
1060
+ return sanitizeInputOtpValue(props.defaultValue, otpLength);
1061
+ });
1062
+ const currentValue = sanitizeInputOtpValue(
1063
+ isControlled ? props.value : uncontrolledValue,
1064
+ otpLength
1065
+ );
1066
+ const recipeOptions = {
1067
+ id,
1068
+ value: currentValue,
1069
+ length: otpLength
1070
+ };
1071
+ if (props.name) recipeOptions.name = props.name;
1072
+ if (props.placeholderCharacter) recipeOptions.placeholderCharacter = props.placeholderCharacter;
1073
+ if (props.disabled) recipeOptions.disabled = true;
1074
+ if (props.readOnly) recipeOptions.readOnly = true;
1075
+ if (props.required) recipeOptions.required = true;
1076
+ if (props.invalid) recipeOptions.invalid = true;
1077
+ if (props.describedBy) recipeOptions.describedBy = props.describedBy;
1078
+ if (props.ariaLabel) recipeOptions.ariaLabel = props.ariaLabel;
1079
+ if (props.label) recipeOptions.label = props.label;
1080
+ if (props.ariaLabelledBy) recipeOptions.ariaLabelledBy = props.ariaLabelledBy;
1081
+ const kit = createInputOtpRecipe(recipeOptions);
1082
+ const className = cx2(kit.className, props.className);
1083
+ const style = kit.vars;
1084
+ const handleChange = (event) => {
1085
+ const nextValue = sanitizeInputOtpValue(event.target.value, otpLength);
1086
+ if (!isControlled) {
1087
+ setUncontrolledValue(nextValue);
1088
+ }
1089
+ props.onValueChange?.(nextValue);
1090
+ };
1091
+ return /* @__PURE__ */ jsx(
1092
+ "div",
1093
+ {
1094
+ className,
1095
+ style,
1096
+ "data-component": "input-otp",
1097
+ "data-invalid": props.invalid ? "true" : void 0,
1098
+ "data-disabled": props.disabled ? "true" : void 0,
1099
+ children: /* @__PURE__ */ jsxs("div", { className: "mw-input-otp__cells", children: [
1100
+ kit.displayCells.map((displayCell) => /* @__PURE__ */ jsx(
1101
+ "span",
1102
+ {
1103
+ className: cx2("mw-input-otp__cell", displayCell.filled && "mw-input-otp__cell--filled"),
1104
+ "aria-hidden": "true",
1105
+ children: displayCell.character
1106
+ },
1107
+ displayCell.key
1108
+ )),
1109
+ /* @__PURE__ */ jsx(
1110
+ "input",
1111
+ {
1112
+ id: kit.a11y.id,
1113
+ className: "mw-input-otp__input",
1114
+ type: "text",
1115
+ name: kit.a11y.name,
1116
+ inputMode: kit.a11y.inputMode,
1117
+ autoComplete: kit.a11y.autoComplete,
1118
+ maxLength: kit.a11y.maxLength,
1119
+ pattern: kit.a11y.pattern,
1120
+ disabled: kit.a11y.disabled,
1121
+ readOnly: kit.a11y.readOnly,
1122
+ required: kit.a11y.required,
1123
+ "aria-label": kit.a11y.ariaLabel,
1124
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
1125
+ "aria-invalid": kit.a11y.ariaInvalid,
1126
+ "aria-describedby": kit.a11y.ariaDescribedBy,
1127
+ value: kit.displayValue,
1128
+ onChange: handleChange
1129
+ }
1130
+ )
1131
+ ] })
1132
+ }
1133
+ );
1134
+ }
1135
+ function cx3(...parts) {
1136
+ return parts.filter(Boolean).join(" ");
1137
+ }
1138
+ function hasTextContent2(value) {
1139
+ return value !== void 0 && value.trim().length > 0;
1140
+ }
1141
+ function InputOtpField(props) {
1142
+ const reactId = React2.useId();
1143
+ const id = props.id ?? `mw-input-otp-${reactId}`;
1144
+ const inputOtp = props.inputOtp ?? {};
1145
+ const hasHelperText = hasTextContent2(props.helperText);
1146
+ const hasError = hasTextContent2(props.error);
1147
+ const invalid = hasError || inputOtp.invalid === true;
1148
+ const {
1149
+ helperTextId,
1150
+ errorId,
1151
+ describedBy: mergedDescribedBy
1152
+ } = buildInputFieldA11yIds({
1153
+ id,
1154
+ hasHelperText,
1155
+ hasError,
1156
+ externalDescribedBy: props.ariaDescribedBy
1157
+ });
1158
+ const wrapperClass = cx3(
1159
+ "mw-input-otp-field",
1160
+ hasError && "mw-input-otp-field--invalid",
1161
+ inputOtp.disabled && "mw-input-otp-field--disabled",
1162
+ props.className
1163
+ );
1164
+ const otpProps = {
1165
+ ...inputOtp,
1166
+ id,
1167
+ invalid,
1168
+ ariaLabelledBy: `${id}-label`
1169
+ };
1170
+ if (mergedDescribedBy) {
1171
+ otpProps.describedBy = mergedDescribedBy;
1172
+ }
1173
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
1174
+ /* @__PURE__ */ jsx("label", { className: "mw-input-otp-field__label", htmlFor: id, id: `${id}-label`, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
1175
+ /* @__PURE__ */ jsx(InputOtp, { ...otpProps }),
1176
+ hasError ? /* @__PURE__ */ jsx("div", { className: "mw-input-otp-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) }) : hasHelperText ? /* @__PURE__ */ jsx("div", { className: "mw-input-otp-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.helperText }) }) : null
1177
+ ] });
1178
+ }
915
1179
  function SelectArrowIcon(props) {
916
1180
  return /* @__PURE__ */ jsx(
917
1181
  "svg",
@@ -948,7 +1212,6 @@ function getInitialSelectValue(props) {
948
1212
  }
949
1213
  function Select(props) {
950
1214
  const kit = createSelectRecipe(props);
951
- const mode = resolveSelectMode(props);
952
1215
  const isControlled = props.value !== void 0;
953
1216
  const [uncontrolledValue, setUncontrolledValue] = React2.useState(
954
1217
  () => getInitialSelectValue(props)
@@ -977,6 +1240,7 @@ function Select(props) {
977
1240
  disabled: kit.a11y.disabled,
978
1241
  required: kit.a11y.required,
979
1242
  "aria-label": kit.a11y.ariaLabel,
1243
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
980
1244
  "aria-invalid": kit.a11y.ariaInvalid,
981
1245
  "aria-describedby": kit.a11y.ariaDescribedBy,
982
1246
  value,
@@ -995,386 +1259,305 @@ function Select(props) {
995
1259
  ]
996
1260
  }
997
1261
  );
998
- if (mode === "native") {
999
- return selectElement;
1000
- }
1001
1262
  return /* @__PURE__ */ jsxs("span", { className: "mw-select__control", children: [
1002
1263
  selectElement,
1003
1264
  /* @__PURE__ */ jsx(SelectArrowIcon, { className: "mw-select__control-icon" })
1004
1265
  ] });
1005
1266
  }
1006
- function Textarea(props) {
1007
- const kit = createTextareaRecipe(props);
1008
- useRenderKitDebug(kit, "Textarea");
1009
- const style = kit.vars;
1010
- const className = props.className ? `${kit.className} ${props.className}` : kit.className;
1011
- const handleChange = (e) => {
1012
- props.onValueChange?.(e.target.value);
1013
- };
1014
- return /* @__PURE__ */ jsx(
1015
- "textarea",
1016
- {
1017
- className,
1018
- style,
1019
- id: kit.a11y.id,
1020
- name: kit.a11y.name,
1021
- inputMode: kit.a11y.inputMode,
1022
- autoComplete: kit.a11y.autoComplete,
1023
- placeholder: kit.a11y.placeholder,
1024
- disabled: kit.a11y.disabled,
1025
- readOnly: kit.a11y.readOnly,
1026
- required: kit.a11y.required,
1027
- rows: kit.a11y.rows,
1028
- cols: kit.a11y.cols,
1029
- "aria-label": kit.a11y.ariaLabel,
1030
- "aria-invalid": kit.a11y.ariaInvalid,
1031
- "aria-describedby": kit.a11y.ariaDescribedBy,
1032
- value: props.value,
1033
- defaultValue: props.defaultValue,
1034
- onChange: handleChange
1035
- }
1036
- );
1267
+ function cx4(...parts) {
1268
+ return parts.filter(Boolean).join(" ");
1037
1269
  }
1038
- var formatLabels = {
1039
- bold: "Bold",
1040
- italic: "Italic",
1041
- underline: "Underline"
1042
- };
1043
- function getRichTextCommandDocument() {
1044
- return document;
1270
+ function hasTextContent3(value) {
1271
+ return value !== void 0 && value.trim().length > 0;
1045
1272
  }
1046
- function mergeRefs(...refs) {
1047
- return (value) => {
1048
- for (const ref of refs) {
1049
- if (!ref) continue;
1050
- if (typeof ref === "function") {
1051
- ref(value);
1052
- continue;
1053
- }
1054
- ref.current = value;
1055
- }
1056
- };
1057
- }
1058
- function isNodeWithinEditor(node, editorElement) {
1059
- if (!node || !editorElement) {
1060
- return false;
1061
- }
1062
- return editorElement.contains(node.nodeType === Node.TEXT_NODE ? node.parentNode : node);
1063
- }
1064
- function getActiveFormatsFromSelection(editorElement) {
1065
- if (!editorElement || typeof window === "undefined" || typeof document === "undefined") {
1066
- return [];
1067
- }
1068
- const commandDocument = getRichTextCommandDocument();
1069
- const selection = window.getSelection();
1070
- const anchorNode = selection?.anchorNode ?? null;
1071
- if (!anchorNode || !isNodeWithinEditor(anchorNode, editorElement)) {
1072
- return [];
1073
- }
1074
- const activeFormats = /* @__PURE__ */ new Set();
1075
- if (typeof commandDocument.queryCommandState === "function") {
1076
- for (const format of Object.keys(richTextCommandByFormat)) {
1077
- try {
1078
- if (commandDocument.queryCommandState(richTextCommandByFormat[format])) {
1079
- activeFormats.add(format);
1080
- }
1081
- } catch {
1082
- }
1083
- }
1084
- }
1085
- if (activeFormats.size > 0) {
1086
- return Array.from(activeFormats);
1087
- }
1088
- let currentNode = anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentNode : anchorNode;
1089
- while (currentNode && currentNode !== editorElement) {
1090
- if (!(currentNode instanceof HTMLElement)) {
1091
- currentNode = currentNode.parentNode;
1092
- continue;
1093
- }
1094
- const tagName = currentNode.tagName.toLowerCase();
1095
- if (tagName === "strong" || tagName === "b") activeFormats.add("bold");
1096
- if (tagName === "em" || tagName === "i") activeFormats.add("italic");
1097
- if (tagName === "u") activeFormats.add("underline");
1098
- currentNode = currentNode.parentNode;
1273
+ function getInitialSelectValue2(props) {
1274
+ if (props.value !== void 0) {
1275
+ return props.value;
1099
1276
  }
1100
- return Array.from(activeFormats);
1101
- }
1102
- function ensureEditorSelection(editorElement) {
1103
- if (typeof window === "undefined") {
1104
- return;
1277
+ if (props.defaultValue !== void 0) {
1278
+ return props.defaultValue;
1105
1279
  }
1106
- editorElement.focus();
1107
- const selection = window.getSelection();
1108
- const anchorNode = selection?.anchorNode ?? null;
1109
- if (anchorNode && isNodeWithinEditor(anchorNode, editorElement)) {
1110
- return;
1280
+ if (props.placeholder !== void 0) {
1281
+ return "";
1111
1282
  }
1112
- const range = document.createRange();
1113
- range.selectNodeContents(editorElement);
1114
- range.collapse(false);
1115
- selection?.removeAllRanges();
1116
- selection?.addRange(range);
1283
+ return props.options[0]?.value ?? "";
1117
1284
  }
1118
- function getFormatTagNames(format) {
1119
- if (format === "bold") return ["strong", "b"];
1120
- if (format === "italic") return ["em", "i"];
1121
- return ["u"];
1285
+ function getFirstEnabledOptionIndex(options) {
1286
+ return options.findIndex((option) => !option.disabled);
1122
1287
  }
1123
- function findNearestFormatElement(node, editorElement, format) {
1124
- const tagNames = getFormatTagNames(format);
1125
- let currentNode = node?.nodeType === Node.TEXT_NODE ? node.parentNode : node;
1126
- while (currentNode && currentNode !== editorElement) {
1127
- if (currentNode instanceof HTMLElement && tagNames.includes(currentNode.tagName.toLowerCase())) {
1128
- return currentNode;
1288
+ function getLastEnabledOptionIndex(options) {
1289
+ for (let index = options.length - 1; index >= 0; index -= 1) {
1290
+ if (!options[index]?.disabled) {
1291
+ return index;
1129
1292
  }
1130
- currentNode = currentNode.parentNode;
1131
1293
  }
1132
- return null;
1294
+ return -1;
1133
1295
  }
1134
- function exitActiveFormatAtCaret(editorElement, format) {
1135
- if (typeof window === "undefined") {
1136
- return false;
1137
- }
1138
- const selection = window.getSelection();
1139
- if (!selection || selection.rangeCount === 0) {
1140
- return false;
1141
- }
1142
- const range = selection.getRangeAt(0);
1143
- const anchorNode = selection.anchorNode;
1144
- if (!range.collapsed || !anchorNode || !isNodeWithinEditor(anchorNode, editorElement)) {
1145
- return false;
1296
+ function getSelectedOptionIndex(options, value) {
1297
+ return options.findIndex((option) => option.value === value && !option.disabled);
1298
+ }
1299
+ function getInitialActiveOptionIndex(options, value) {
1300
+ const selectedIndex = getSelectedOptionIndex(options, value);
1301
+ if (selectedIndex !== -1) {
1302
+ return selectedIndex;
1146
1303
  }
1147
- const formatElement = findNearestFormatElement(anchorNode, editorElement, format);
1148
- if (!formatElement || !formatElement.parentNode) {
1149
- return false;
1304
+ return getFirstEnabledOptionIndex(options);
1305
+ }
1306
+ function getNextEnabledOptionIndex(options, currentIndex, direction) {
1307
+ if (options.length === 0) {
1308
+ return -1;
1150
1309
  }
1151
- const trailingRange = document.createRange();
1152
- trailingRange.setStart(range.startContainer, range.startOffset);
1153
- trailingRange.setEndAfter(formatElement);
1154
- const trailingFragment = trailingRange.extractContents();
1155
- const caretTextNode = document.createTextNode("\u200B");
1156
- const parentNode = formatElement.parentNode;
1157
- parentNode.insertBefore(caretTextNode, formatElement.nextSibling);
1158
- parentNode.insertBefore(trailingFragment, caretTextNode.nextSibling);
1159
- if (formatElement.textContent?.replaceAll("\u200B", "").trim().length === 0) {
1160
- formatElement.remove();
1310
+ let nextIndex = currentIndex;
1311
+ for (let attempts = 0; attempts < options.length; attempts += 1) {
1312
+ nextIndex = (nextIndex + direction + options.length) % options.length;
1313
+ if (!options[nextIndex]?.disabled) {
1314
+ return nextIndex;
1315
+ }
1161
1316
  }
1162
- const nextRange = document.createRange();
1163
- nextRange.setStart(caretTextNode, 1);
1164
- nextRange.collapse(true);
1165
- selection.removeAllRanges();
1166
- selection.addRange(nextRange);
1167
- return true;
1317
+ return currentIndex;
1168
1318
  }
1169
- var RichText = React2.forwardRef((props, forwardedRef) => {
1170
- const kit = createRichTextRecipe(props);
1171
- const allowedFormats = React2.useMemo(
1172
- () => resolveRichTextAllowedFormats(props.allowedFormats),
1173
- [props.allowedFormats]
1174
- );
1175
- const normalizedControlledValue = React2.useMemo(
1176
- () => normalizeRichTextHtml(props.value),
1177
- [props.value]
1178
- );
1179
- const initialUncontrolledValue = React2.useMemo(
1180
- () => normalizeRichTextHtml(props.defaultValue),
1181
- [props.defaultValue]
1182
- );
1183
- const isControlled = props.value !== void 0;
1184
- const [uncontrolledHtml, setUncontrolledHtml] = React2.useState(initialUncontrolledValue);
1185
- const [isEditorEmpty, setIsEditorEmpty] = React2.useState(
1186
- isRichTextHtmlEmpty(isControlled ? normalizedControlledValue : initialUncontrolledValue)
1187
- );
1188
- const [activeFormats, setActiveFormats] = React2.useState([]);
1189
- const editorElementRef = React2.useRef(null);
1190
- useRenderKitDebug(kit, "RichText");
1191
- const editorHtml = isControlled ? normalizedControlledValue : uncontrolledHtml;
1192
- const style = kit.vars;
1193
- const className = props.className ? `${kit.className} ${props.className}` : kit.className;
1194
- const showToolbar = !props.readOnly;
1195
- const syncEditorState = React2.useCallback(
1196
- (nextHtml) => {
1197
- const normalizedHtml = normalizeRichTextHtml(nextHtml);
1198
- const emptyState = isRichTextHtmlEmpty(normalizedHtml);
1199
- if (!isControlled) {
1200
- setUncontrolledHtml(normalizedHtml);
1201
- }
1202
- setIsEditorEmpty(emptyState);
1203
- props.onValueChange?.(normalizedHtml);
1204
- return normalizedHtml;
1205
- },
1206
- [isControlled, props]
1319
+ function MarwesSelectFieldControl(props) {
1320
+ const { id, label, select } = props;
1321
+ const listboxId = `${id}-listbox`;
1322
+ const isControlled = select.value !== void 0;
1323
+ const [internalValue, setInternalValue] = React2.useState(() => getInitialSelectValue2(select));
1324
+ const value = isControlled ? select.value ?? "" : internalValue;
1325
+ const [open, setOpen] = React2.useState(false);
1326
+ const [activeIndex, setActiveIndex] = React2.useState(
1327
+ () => getInitialActiveOptionIndex(select.options, value)
1207
1328
  );
1208
- const refreshActiveFormats = React2.useCallback(() => {
1209
- setActiveFormats(getActiveFormatsFromSelection(editorElementRef.current));
1210
- }, []);
1211
- React2.useLayoutEffect(() => {
1212
- const editorElement = editorElementRef.current;
1213
- if (!editorElement) {
1329
+ const rootRef = React2.useRef(null);
1330
+ const buttonRef = React2.useRef(null);
1331
+ const selectedOption = select.options.find((option) => option.value === value) ?? (select.placeholder === void 0 ? select.options[0] : void 0);
1332
+ const placeholderSelected = select.placeholder !== void 0 && value === "";
1333
+ const displayText = placeholderSelected ? select.placeholder : selectedOption?.label ?? "";
1334
+ const accessibleName = select.ariaLabel ?? (hasTextContent3(label) ? label : void 0) ?? (hasTextContent3(displayText) ? displayText : void 0);
1335
+ React2.useEffect(() => {
1336
+ if (!open) {
1214
1337
  return;
1215
1338
  }
1216
- const normalizedDomHtml = normalizeRichTextHtml(editorElement.innerHTML);
1217
- if (normalizedDomHtml !== editorHtml) {
1218
- editorElement.innerHTML = editorHtml;
1219
- }
1220
- setIsEditorEmpty(isRichTextHtmlEmpty(editorHtml));
1221
- }, [editorHtml]);
1222
- React2.useEffect(() => {
1223
- if (typeof document === "undefined") {
1224
- return void 0;
1339
+ function handlePointerDown(event) {
1340
+ if (rootRef.current?.contains(event.target)) {
1341
+ return;
1342
+ }
1343
+ setOpen(false);
1225
1344
  }
1226
- const handleSelectionChange = () => {
1227
- refreshActiveFormats();
1228
- };
1229
- document.addEventListener("selectionchange", handleSelectionChange);
1345
+ document.addEventListener("pointerdown", handlePointerDown);
1230
1346
  return () => {
1231
- document.removeEventListener("selectionchange", handleSelectionChange);
1347
+ document.removeEventListener("pointerdown", handlePointerDown);
1232
1348
  };
1233
- }, [refreshActiveFormats]);
1234
- const handleInput = () => {
1235
- const editorElement = editorElementRef.current;
1236
- if (!editorElement || props.disabled || props.readOnly) {
1349
+ }, [open]);
1350
+ React2.useEffect(() => {
1351
+ if (!open) {
1237
1352
  return;
1238
1353
  }
1239
- syncEditorState(editorElement.innerHTML);
1240
- refreshActiveFormats();
1354
+ setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1355
+ }, [open, select.options, value]);
1356
+ React2.useEffect(() => {
1357
+ if (!select.disabled) {
1358
+ return;
1359
+ }
1360
+ setOpen(false);
1361
+ }, [select.disabled]);
1362
+ const commitValue = (nextValue) => {
1363
+ if (!isControlled) {
1364
+ setInternalValue(nextValue);
1365
+ }
1366
+ select.onValueChange?.(nextValue);
1241
1367
  };
1242
- const toggleFormat = (format) => {
1243
- if (props.disabled || props.readOnly || typeof document === "undefined") {
1368
+ const selectOptionAtIndex = (index) => {
1369
+ const option = select.options[index];
1370
+ if (!option || option.disabled) {
1244
1371
  return;
1245
1372
  }
1246
- const commandDocument = getRichTextCommandDocument();
1247
- const editorElement = editorElementRef.current;
1248
- if (!editorElement) {
1373
+ commitValue(option.value);
1374
+ setOpen(false);
1375
+ buttonRef.current?.focus();
1376
+ };
1377
+ const handleKeyDown = (event) => {
1378
+ if (select.disabled) {
1249
1379
  return;
1250
1380
  }
1251
- ensureEditorSelection(editorElement);
1252
- const activeFormatsBeforeToggle = getActiveFormatsFromSelection(editorElement);
1253
- if (exitActiveFormatAtCaret(editorElement, format)) {
1254
- if (typeof commandDocument.queryCommandState === "function" && commandDocument.queryCommandState(richTextCommandByFormat[format]) && typeof commandDocument.execCommand === "function") {
1255
- commandDocument.execCommand(richTextCommandByFormat[format]);
1381
+ switch (event.key) {
1382
+ case "ArrowDown": {
1383
+ event.preventDefault();
1384
+ if (!open) {
1385
+ setOpen(true);
1386
+ setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1387
+ return;
1388
+ }
1389
+ setActiveIndex((currentIndex) => getNextEnabledOptionIndex(select.options, currentIndex, 1));
1390
+ return;
1256
1391
  }
1257
- if (typeof commandDocument.queryCommandState === "function" && typeof commandDocument.execCommand === "function") {
1258
- for (const activeFormat of activeFormatsBeforeToggle) {
1259
- if (activeFormat === format) {
1260
- continue;
1261
- }
1262
- if (!commandDocument.queryCommandState(richTextCommandByFormat[activeFormat])) {
1263
- commandDocument.execCommand(richTextCommandByFormat[activeFormat]);
1264
- }
1392
+ case "ArrowUp": {
1393
+ event.preventDefault();
1394
+ if (!open) {
1395
+ setOpen(true);
1396
+ setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1397
+ return;
1265
1398
  }
1399
+ setActiveIndex(
1400
+ (currentIndex) => getNextEnabledOptionIndex(select.options, currentIndex, -1)
1401
+ );
1402
+ return;
1266
1403
  }
1267
- syncEditorState(editorElement.innerHTML);
1268
- refreshActiveFormats();
1269
- return;
1270
- }
1271
- if (typeof commandDocument.execCommand === "function") {
1272
- commandDocument.execCommand(richTextCommandByFormat[format]);
1404
+ case "Home": {
1405
+ if (!open) {
1406
+ return;
1407
+ }
1408
+ event.preventDefault();
1409
+ setActiveIndex(getFirstEnabledOptionIndex(select.options));
1410
+ return;
1411
+ }
1412
+ case "End": {
1413
+ if (!open) {
1414
+ return;
1415
+ }
1416
+ event.preventDefault();
1417
+ setActiveIndex(getLastEnabledOptionIndex(select.options));
1418
+ return;
1419
+ }
1420
+ case "Enter":
1421
+ case " ": {
1422
+ event.preventDefault();
1423
+ if (!open) {
1424
+ setOpen(true);
1425
+ setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1426
+ return;
1427
+ }
1428
+ if (activeIndex !== -1) {
1429
+ selectOptionAtIndex(activeIndex);
1430
+ }
1431
+ return;
1432
+ }
1433
+ case "Escape": {
1434
+ if (!open) {
1435
+ return;
1436
+ }
1437
+ event.preventDefault();
1438
+ setOpen(false);
1439
+ return;
1440
+ }
1441
+ case "Tab": {
1442
+ setOpen(false);
1443
+ return;
1444
+ }
1445
+ default:
1446
+ return;
1273
1447
  }
1274
- syncEditorState(editorElement.innerHTML);
1275
- refreshActiveFormats();
1276
1448
  };
1277
- const handleKeyDown = (event) => {
1278
- if (!(event.metaKey || event.ctrlKey) || event.altKey) {
1279
- return;
1280
- }
1281
- const formatByKey = {
1282
- b: "bold",
1283
- i: "italic",
1284
- u: "underline"
1285
- };
1286
- const requestedFormat = formatByKey[event.key.toLowerCase()];
1287
- if (!requestedFormat || !allowedFormats.includes(requestedFormat)) {
1288
- return;
1449
+ return /* @__PURE__ */ jsxs(
1450
+ "div",
1451
+ {
1452
+ ref: rootRef,
1453
+ className: cx4("mw-select-field__control", open && "mw-select-field__control--open"),
1454
+ children: [
1455
+ /* @__PURE__ */ jsxs(
1456
+ "button",
1457
+ {
1458
+ ref: buttonRef,
1459
+ id,
1460
+ type: "button",
1461
+ className: cx4(
1462
+ "mw-select-field__trigger",
1463
+ placeholderSelected && "mw-select-field__trigger--placeholder",
1464
+ select.invalid && "is-invalid",
1465
+ open && "mw-select-field__trigger--open"
1466
+ ),
1467
+ role: "combobox",
1468
+ "aria-controls": listboxId,
1469
+ "aria-expanded": open,
1470
+ "aria-haspopup": "listbox",
1471
+ "aria-label": accessibleName,
1472
+ "aria-describedby": select.describedBy,
1473
+ "aria-invalid": select.invalid ? "true" : void 0,
1474
+ "aria-required": select.required ? "true" : void 0,
1475
+ "aria-activedescendant": open && activeIndex !== -1 ? `${id}-option-${activeIndex}` : void 0,
1476
+ disabled: select.disabled,
1477
+ "data-placeholder-selected": placeholderSelected ? "true" : void 0,
1478
+ onClick: () => {
1479
+ if (select.disabled) {
1480
+ return;
1481
+ }
1482
+ setOpen((currentOpen) => !currentOpen);
1483
+ },
1484
+ onKeyDown: handleKeyDown,
1485
+ children: [
1486
+ /* @__PURE__ */ jsx("span", { className: "mw-select-field__trigger-text", children: displayText }),
1487
+ /* @__PURE__ */ jsx(SelectArrowIcon, { className: "mw-select-field__trigger-icon" })
1488
+ ]
1489
+ }
1490
+ ),
1491
+ select.name ? /* @__PURE__ */ jsx(
1492
+ "input",
1493
+ {
1494
+ "aria-hidden": "true",
1495
+ className: "mw-select-field__proxy-input",
1496
+ name: select.name,
1497
+ type: "hidden",
1498
+ value,
1499
+ readOnly: true
1500
+ }
1501
+ ) : null,
1502
+ open ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { className: "mw-select-field__list", id: listboxId, role: "listbox", tabIndex: -1, children: select.options.map((option, optionIndex) => {
1503
+ const selected = option.value === value;
1504
+ const active = optionIndex === activeIndex;
1505
+ return /* @__PURE__ */ jsxs(
1506
+ "div",
1507
+ {
1508
+ id: `${id}-option-${optionIndex}`,
1509
+ className: cx4(
1510
+ "mw-select-field__option",
1511
+ active && "mw-select-field__option--active",
1512
+ selected && "mw-select-field__option--selected",
1513
+ option.disabled && "mw-select-field__option--disabled"
1514
+ ),
1515
+ role: "option",
1516
+ "aria-selected": selected,
1517
+ "aria-disabled": option.disabled ? "true" : void 0,
1518
+ tabIndex: -1,
1519
+ onClick: () => selectOptionAtIndex(optionIndex),
1520
+ onKeyDown: (event) => {
1521
+ if (option.disabled) {
1522
+ return;
1523
+ }
1524
+ if (event.key === "Enter" || event.key === " ") {
1525
+ event.preventDefault();
1526
+ selectOptionAtIndex(optionIndex);
1527
+ }
1528
+ },
1529
+ onMouseDown: (event) => event.preventDefault(),
1530
+ onMouseEnter: () => {
1531
+ if (!option.disabled) {
1532
+ setActiveIndex(optionIndex);
1533
+ }
1534
+ },
1535
+ children: [
1536
+ /* @__PURE__ */ jsx("span", { className: "mw-select-field__option-label", children: option.label }),
1537
+ selected ? /* @__PURE__ */ jsx(
1538
+ Icon,
1539
+ {
1540
+ className: "mw-select-field__option-check",
1541
+ name: IconName.Check,
1542
+ size: "xs",
1543
+ decorative: true
1544
+ }
1545
+ ) : null
1546
+ ]
1547
+ },
1548
+ option.value
1549
+ );
1550
+ }) }) }) : null
1551
+ ]
1289
1552
  }
1290
- event.preventDefault();
1291
- toggleFormat(requestedFormat);
1292
- };
1293
- return /* @__PURE__ */ jsxs("div", { className, style, ...kit.dataAttributes, children: [
1294
- showToolbar && /* @__PURE__ */ jsx("div", { className: "mw-rich-text__toolbar", "data-rich-text-toolbar": true, children: allowedFormats.map((format) => {
1295
- const isActive = activeFormats.includes(format);
1296
- const iconName = format === "bold" ? "bold" : format === "italic" ? "italic" : "underline";
1297
- return /* @__PURE__ */ jsx(
1298
- "button",
1299
- {
1300
- type: "button",
1301
- className: "mw-rich-text__toolbar-button",
1302
- "data-format": format,
1303
- "data-active": isActive ? "true" : void 0,
1304
- "aria-label": formatLabels[format],
1305
- "aria-pressed": isActive,
1306
- disabled: props.disabled,
1307
- onMouseDown: (event) => {
1308
- event.preventDefault();
1309
- },
1310
- onClick: () => {
1311
- toggleFormat(format);
1312
- },
1313
- children: /* @__PURE__ */ jsx(Icon, { name: iconName, size: "xs", decorative: true })
1314
- },
1315
- format
1316
- );
1317
- }) }),
1318
- /* @__PURE__ */ jsx(
1319
- "div",
1320
- {
1321
- ref: mergeRefs(editorElementRef, forwardedRef),
1322
- className: "mw-rich-text__editor",
1323
- "data-rich-text-editor": true,
1324
- "data-empty": isEditorEmpty ? "true" : void 0,
1325
- "data-placeholder": props.placeholder,
1326
- id: kit.a11y.id,
1327
- role: kit.a11y.role,
1328
- tabIndex: kit.a11y.tabIndex,
1329
- "aria-label": kit.a11y.ariaLabel,
1330
- "aria-labelledby": kit.a11y.ariaLabelledBy,
1331
- "aria-describedby": kit.a11y.ariaDescribedBy,
1332
- "aria-invalid": kit.a11y.ariaInvalid,
1333
- "aria-disabled": kit.a11y.ariaDisabled,
1334
- "aria-readonly": kit.a11y.ariaReadOnly,
1335
- "aria-required": kit.a11y.ariaRequired,
1336
- "aria-multiline": kit.a11y.ariaMultiline,
1337
- contentEditable: !props.disabled && !props.readOnly,
1338
- suppressContentEditableWarning: true,
1339
- onInput: handleInput,
1340
- onKeyDown: handleKeyDown,
1341
- onFocus: refreshActiveFormats,
1342
- onBlur: () => {
1343
- syncEditorState(editorElementRef.current?.innerHTML ?? "");
1344
- setActiveFormats([]);
1345
- }
1346
- }
1347
- ),
1348
- props.name && /* @__PURE__ */ jsx("input", { type: "hidden", name: props.name, value: editorHtml, disabled: props.disabled })
1349
- ] });
1350
- });
1351
- RichText.displayName = "RichText";
1352
- function Paragraph(props) {
1353
- const { children, className: customClassName, style: customStyle, ...opts } = props;
1354
- const theme = useTheme();
1355
- const kit = paragraphRecipe(opts, theme);
1356
- const style = { ...kit.vars, ...customStyle };
1357
- const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
1358
- return /* @__PURE__ */ jsx("p", { id: kit.a11y.id, className, style, children });
1359
- }
1360
- function cx(...parts) {
1361
- return parts.filter(Boolean).join(" ");
1362
- }
1363
- function hasTextContent(value) {
1364
- return value !== void 0 && value.trim().length > 0;
1365
- }
1366
- function InputField(props) {
1367
- const reactId = React2.useId();
1368
- const id = props.id ?? `mw-input-${reactId}`;
1369
- const isPasswordField = props.input.type === "password";
1370
- const [showPassword, setShowPassword] = React2.useState(false);
1371
- const isSearchField = props.input.type === "search";
1372
- const [searchValue, setSearchValue] = React2.useState(
1373
- props.input.value || props.input.defaultValue || ""
1374
1553
  );
1375
- const hasSearchValue = isSearchField && (props.input.value !== void 0 ? String(props.input.value).length > 0 : String(searchValue).length > 0);
1376
- const hasHelperText = hasTextContent(props.helperText);
1377
- const hasError = hasTextContent(props.error);
1554
+ }
1555
+ function SelectField(props) {
1556
+ const reactId = React2.useId();
1557
+ const id = props.id ?? `mw-select-${reactId}`;
1558
+ const mode = resolveSelectMode(props.select);
1559
+ const hasHelperText = hasTextContent3(props.helperText);
1560
+ const hasError = hasTextContent3(props.error);
1378
1561
  const {
1379
1562
  helperTextId,
1380
1563
  errorId,
@@ -1385,99 +1568,76 @@ function InputField(props) {
1385
1568
  hasError,
1386
1569
  externalDescribedBy: props.ariaDescribedBy
1387
1570
  });
1388
- const disabled = props.input.disabled || false;
1389
- const readOnly = props.input.readOnly || false;
1390
- const invalid = hasError || props.input.invalid || false;
1391
- const showSearchClearButton = hasSearchValue && !disabled && !readOnly;
1392
- const showSearchIcon = isSearchField && !showSearchClearButton;
1393
- const wrapperClass = cx(
1571
+ const disabled = props.select.disabled || false;
1572
+ const invalid = hasError || props.select.invalid || false;
1573
+ const wrapperClass = cx4(
1394
1574
  "mw-input-field",
1575
+ "mw-input-field--select",
1576
+ mode === "marwes" && "mw-input-field--select-marwes",
1577
+ props.variant === "date" && "mw-input-field--select-date",
1395
1578
  disabled && "mw-input-field--disabled",
1396
- invalid && "mw-input-field--invalid",
1397
- readOnly && "mw-input-field--readonly"
1579
+ invalid && "mw-input-field--invalid"
1398
1580
  );
1399
- const inputProps = {
1400
- ...props.input,
1581
+ const selectProps = {
1582
+ ...props.select,
1401
1583
  id,
1402
1584
  invalid
1403
1585
  };
1404
- if (isPasswordField && showPassword) {
1405
- inputProps.type = "text";
1406
- }
1407
- if (isSearchField) {
1408
- const originalOnValueChange = props.input.onValueChange;
1409
- if (props.input.value === void 0) {
1410
- inputProps.value = searchValue;
1411
- }
1412
- inputProps.onValueChange = (value) => {
1413
- setSearchValue(value);
1414
- originalOnValueChange?.(value);
1415
- };
1416
- }
1417
1586
  if (mergedDescribedBy) {
1418
- inputProps.describedBy = mergedDescribedBy;
1587
+ selectProps.describedBy = mergedDescribedBy;
1419
1588
  }
1420
- const handleTogglePassword = () => {
1421
- setShowPassword((prev) => !prev);
1422
- };
1423
- const handleClearSearch = () => {
1424
- setSearchValue("");
1425
- props.input.onValueChange?.("");
1426
- };
1427
1589
  return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
1428
- /* @__PURE__ */ jsx("label", { className: "mw-input-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
1429
- /* @__PURE__ */ jsxs("div", { className: "mw-input-field__input-wrapper", children: [
1430
- props.leadingSymbol && /* @__PURE__ */ jsx("span", { className: "mw-input-field__leading-symbol", "aria-hidden": "true", children: props.leadingSymbol }),
1431
- /* @__PURE__ */ jsx(Input, { ...inputProps }),
1432
- isPasswordField && !disabled && /* @__PURE__ */ jsx(
1433
- "button",
1434
- {
1435
- type: "button",
1436
- className: "mw-input-field__toggle-password",
1437
- onClick: handleTogglePassword,
1438
- "aria-label": showPassword ? "Hide password" : "Show password",
1439
- tabIndex: 0,
1440
- children: /* @__PURE__ */ jsx(Icon, { name: showPassword ? "eyeOff" : "eye", size: "xs", decorative: true })
1441
- }
1442
- ),
1443
- showSearchIcon && /* @__PURE__ */ jsx("span", { className: "mw-input-field__search-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon, { name: "search", size: "xs", decorative: true }) }),
1444
- showSearchClearButton && /* @__PURE__ */ jsx(
1445
- "button",
1446
- {
1447
- type: "button",
1448
- className: "mw-input-field__clear-search",
1449
- onClick: handleClearSearch,
1450
- "aria-label": "Clear search",
1451
- tabIndex: 0,
1452
- children: /* @__PURE__ */ jsx(Icon, { name: "x", size: "xs", decorative: true })
1453
- }
1454
- )
1455
- ] }),
1456
- hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.helperText }) }),
1457
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
1590
+ /* @__PURE__ */ jsx("label", { className: "mw-input-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
1591
+ /* @__PURE__ */ jsx("div", { className: "mw-input-field__input-wrapper", children: mode === "native" ? /* @__PURE__ */ jsx(Select, { ...selectProps, native: true }) : /* @__PURE__ */ jsx(MarwesSelectFieldControl, { id, label: props.label, select: selectProps }) }),
1592
+ hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.helperText }) }),
1593
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
1458
1594
  ] });
1459
1595
  }
1460
- function cx2(...parts) {
1596
+ function Textarea(props) {
1597
+ const kit = createTextareaRecipe(props);
1598
+ useRenderKitDebug(kit, "Textarea");
1599
+ const style = kit.vars;
1600
+ const className = props.className ? `${kit.className} ${props.className}` : kit.className;
1601
+ const handleChange = (e) => {
1602
+ props.onValueChange?.(e.target.value);
1603
+ };
1604
+ return /* @__PURE__ */ jsx(
1605
+ "textarea",
1606
+ {
1607
+ className,
1608
+ style,
1609
+ id: kit.a11y.id,
1610
+ name: kit.a11y.name,
1611
+ inputMode: kit.a11y.inputMode,
1612
+ autoComplete: kit.a11y.autoComplete,
1613
+ placeholder: kit.a11y.placeholder,
1614
+ disabled: kit.a11y.disabled,
1615
+ readOnly: kit.a11y.readOnly,
1616
+ required: kit.a11y.required,
1617
+ rows: kit.a11y.rows,
1618
+ cols: kit.a11y.cols,
1619
+ "aria-label": kit.a11y.ariaLabel,
1620
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
1621
+ "aria-invalid": kit.a11y.ariaInvalid,
1622
+ "aria-describedby": kit.a11y.ariaDescribedBy,
1623
+ value: props.value,
1624
+ defaultValue: props.defaultValue,
1625
+ onChange: handleChange
1626
+ }
1627
+ );
1628
+ }
1629
+ function cx5(...parts) {
1461
1630
  return parts.filter(Boolean).join(" ");
1462
1631
  }
1463
- function hasTextContent2(value) {
1632
+ function hasTextContent4(value) {
1464
1633
  return value !== void 0 && value.trim().length > 0;
1465
1634
  }
1466
- function InputOtp(props) {
1635
+ function TextareaField(props) {
1467
1636
  const reactId = React2.useId();
1468
- const id = props.id ?? `mw-input-otp-${reactId}`;
1469
- const otpLength = Math.max(1, props.length ?? 6);
1470
- const hasHelperText = hasTextContent2(props.helperText);
1471
- const hasError = hasTextContent2(props.error);
1472
- const invalid = hasError || props.invalid === true;
1473
- const isControlled = props.value !== void 0;
1474
- const [uncontrolledValue, setUncontrolledValue] = React2.useState(() => {
1475
- return sanitizeInputOtpValue(props.defaultValue, otpLength);
1476
- });
1477
- const currentValue = sanitizeInputOtpValue(
1478
- isControlled ? props.value : uncontrolledValue,
1479
- otpLength
1480
- );
1637
+ const id = props.id ?? `mw-textarea-${reactId}`;
1638
+ const hasHelperText = hasTextContent4(props.helperText);
1639
+ const hasCounterText = hasTextContent4(props.counterText);
1640
+ const hasError = hasTextContent4(props.error);
1481
1641
  const {
1482
1642
  helperTextId,
1483
1643
  errorId,
@@ -1488,466 +1648,349 @@ function InputOtp(props) {
1488
1648
  hasError,
1489
1649
  externalDescribedBy: props.ariaDescribedBy
1490
1650
  });
1491
- const recipeOptions = {
1651
+ const disabled = props.textarea.disabled || false;
1652
+ const readOnly = props.textarea.readOnly || false;
1653
+ const invalid = hasError || props.textarea.invalid || false;
1654
+ const wrapperClass = cx5(
1655
+ "mw-input-field",
1656
+ "mw-input-field--textarea",
1657
+ disabled && "mw-input-field--disabled",
1658
+ invalid && "mw-input-field--invalid",
1659
+ readOnly && "mw-input-field--readonly"
1660
+ );
1661
+ const textareaProps = {
1662
+ ...props.textarea,
1492
1663
  id,
1493
- value: currentValue,
1494
- length: otpLength,
1495
1664
  invalid
1496
1665
  };
1497
- if (props.name) {
1498
- recipeOptions.name = props.name;
1499
- }
1500
- if (props.placeholderCharacter) {
1501
- recipeOptions.placeholderCharacter = props.placeholderCharacter;
1666
+ if (mergedDescribedBy) {
1667
+ textareaProps.describedBy = mergedDescribedBy;
1502
1668
  }
1503
- if (props.disabled) {
1504
- recipeOptions.disabled = true;
1669
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
1670
+ /* @__PURE__ */ jsx("label", { className: "mw-input-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
1671
+ /* @__PURE__ */ jsx("div", { className: "mw-input-field__input-wrapper", children: /* @__PURE__ */ jsx(Textarea, { ...textareaProps }) }),
1672
+ (hasHelperText || hasCounterText) && !hasError && /* @__PURE__ */ jsxs("div", { className: "mw-input-field__meta", children: [
1673
+ hasHelperText ? /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.helperText }) }) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true" }),
1674
+ hasCounterText && /* @__PURE__ */ jsx("div", { className: "mw-input-field__counter", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.counterText }) })
1675
+ ] }),
1676
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
1677
+ ] });
1678
+ }
1679
+ var formatLabels = {
1680
+ bold: "Bold",
1681
+ italic: "Italic",
1682
+ underline: "Underline"
1683
+ };
1684
+ function getRichTextCommandDocument() {
1685
+ return document;
1686
+ }
1687
+ function mergeRefs(...refs) {
1688
+ return (value) => {
1689
+ for (const ref of refs) {
1690
+ if (!ref) continue;
1691
+ if (typeof ref === "function") {
1692
+ ref(value);
1693
+ continue;
1694
+ }
1695
+ ref.current = value;
1696
+ }
1697
+ };
1698
+ }
1699
+ function isNodeWithinEditor(node, editorElement) {
1700
+ if (!node || !editorElement) {
1701
+ return false;
1505
1702
  }
1506
- if (props.readOnly) {
1507
- recipeOptions.readOnly = true;
1703
+ return editorElement.contains(node.nodeType === Node.TEXT_NODE ? node.parentNode : node);
1704
+ }
1705
+ function getActiveFormatsFromSelection(editorElement) {
1706
+ if (!editorElement || typeof window === "undefined" || typeof document === "undefined") {
1707
+ return [];
1508
1708
  }
1509
- if (props.required) {
1510
- recipeOptions.required = true;
1709
+ const commandDocument = getRichTextCommandDocument();
1710
+ const selection = window.getSelection();
1711
+ const anchorNode = selection?.anchorNode ?? null;
1712
+ if (!anchorNode || !isNodeWithinEditor(anchorNode, editorElement)) {
1713
+ return [];
1511
1714
  }
1512
- if (mergedDescribedBy) {
1513
- recipeOptions.describedBy = mergedDescribedBy;
1715
+ const activeFormats = /* @__PURE__ */ new Set();
1716
+ if (typeof commandDocument.queryCommandState === "function") {
1717
+ for (const format of Object.keys(richTextCommandByFormat)) {
1718
+ try {
1719
+ if (commandDocument.queryCommandState(richTextCommandByFormat[format])) {
1720
+ activeFormats.add(format);
1721
+ }
1722
+ } catch {
1723
+ }
1724
+ }
1514
1725
  }
1515
- if (props.ariaLabel) {
1516
- recipeOptions.ariaLabel = props.ariaLabel;
1726
+ if (activeFormats.size > 0) {
1727
+ return Array.from(activeFormats);
1517
1728
  }
1518
- const kit = createInputOtpRecipe(recipeOptions);
1519
- const className = cx2(kit.className, props.className);
1520
- const style = kit.vars;
1521
- const handleChange = (event) => {
1522
- const nextValue = sanitizeInputOtpValue(event.target.value, otpLength);
1523
- if (!isControlled) {
1524
- setUncontrolledValue(nextValue);
1525
- }
1526
- props.onValueChange?.(nextValue);
1527
- };
1528
- return /* @__PURE__ */ jsxs(
1529
- "div",
1530
- {
1531
- className,
1532
- style,
1533
- "data-component": "input-otp",
1534
- "data-invalid": invalid ? "true" : void 0,
1535
- "data-disabled": props.disabled ? "true" : void 0,
1536
- children: [
1537
- /* @__PURE__ */ jsx("label", { className: "mw-input-otp__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
1538
- /* @__PURE__ */ jsxs("div", { className: "mw-input-otp__cells", children: [
1539
- kit.displayCells.map((displayCell) => /* @__PURE__ */ jsx(
1540
- "span",
1541
- {
1542
- className: cx2("mw-input-otp__cell", displayCell.filled && "mw-input-otp__cell--filled"),
1543
- "aria-hidden": "true",
1544
- children: displayCell.character
1545
- },
1546
- displayCell.key
1547
- )),
1548
- /* @__PURE__ */ jsx(
1549
- "input",
1550
- {
1551
- id: kit.a11y.id,
1552
- className: "mw-input-otp__input",
1553
- type: "text",
1554
- name: kit.a11y.name,
1555
- inputMode: kit.a11y.inputMode,
1556
- autoComplete: kit.a11y.autoComplete,
1557
- maxLength: kit.a11y.maxLength,
1558
- pattern: kit.a11y.pattern,
1559
- disabled: kit.a11y.disabled,
1560
- readOnly: kit.a11y.readOnly,
1561
- required: kit.a11y.required,
1562
- "aria-label": kit.a11y.ariaLabel,
1563
- "aria-invalid": kit.a11y.ariaInvalid,
1564
- "aria-describedby": kit.a11y.ariaDescribedBy,
1565
- value: kit.displayValue,
1566
- onChange: handleChange
1567
- }
1568
- )
1569
- ] }),
1570
- hasError ? /* @__PURE__ */ jsx("div", { className: "mw-input-otp__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) }) : hasHelperText ? /* @__PURE__ */ jsx("div", { className: "mw-input-otp__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.helperText }) }) : null
1571
- ]
1729
+ let currentNode = anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentNode : anchorNode;
1730
+ while (currentNode && currentNode !== editorElement) {
1731
+ if (!(currentNode instanceof HTMLElement)) {
1732
+ currentNode = currentNode.parentNode;
1733
+ continue;
1572
1734
  }
1573
- );
1574
- }
1575
- function cx3(...parts) {
1576
- return parts.filter(Boolean).join(" ");
1577
- }
1578
- function hasTextContent3(value) {
1579
- return value !== void 0 && value.trim().length > 0;
1580
- }
1581
- function getInitialSelectValue2(props) {
1582
- if (props.value !== void 0) {
1583
- return props.value;
1735
+ const tagName = currentNode.tagName.toLowerCase();
1736
+ if (tagName === "strong" || tagName === "b") activeFormats.add("bold");
1737
+ if (tagName === "em" || tagName === "i") activeFormats.add("italic");
1738
+ if (tagName === "u") activeFormats.add("underline");
1739
+ currentNode = currentNode.parentNode;
1584
1740
  }
1585
- if (props.defaultValue !== void 0) {
1586
- return props.defaultValue;
1741
+ return Array.from(activeFormats);
1742
+ }
1743
+ function ensureEditorSelection(editorElement) {
1744
+ if (typeof window === "undefined") {
1745
+ return;
1587
1746
  }
1588
- if (props.placeholder !== void 0) {
1589
- return "";
1747
+ editorElement.focus();
1748
+ const selection = window.getSelection();
1749
+ const anchorNode = selection?.anchorNode ?? null;
1750
+ if (anchorNode && isNodeWithinEditor(anchorNode, editorElement)) {
1751
+ return;
1590
1752
  }
1591
- return props.options[0]?.value ?? "";
1753
+ const range = document.createRange();
1754
+ range.selectNodeContents(editorElement);
1755
+ range.collapse(false);
1756
+ selection?.removeAllRanges();
1757
+ selection?.addRange(range);
1592
1758
  }
1593
- function getFirstEnabledOptionIndex(options) {
1594
- return options.findIndex((option) => !option.disabled);
1759
+ function getFormatTagNames(format) {
1760
+ if (format === "bold") return ["strong", "b"];
1761
+ if (format === "italic") return ["em", "i"];
1762
+ return ["u"];
1595
1763
  }
1596
- function getLastEnabledOptionIndex(options) {
1597
- for (let index = options.length - 1; index >= 0; index -= 1) {
1598
- if (!options[index]?.disabled) {
1599
- return index;
1764
+ function findNearestFormatElement(node, editorElement, format) {
1765
+ const tagNames = getFormatTagNames(format);
1766
+ let currentNode = node?.nodeType === Node.TEXT_NODE ? node.parentNode : node;
1767
+ while (currentNode && currentNode !== editorElement) {
1768
+ if (currentNode instanceof HTMLElement && tagNames.includes(currentNode.tagName.toLowerCase())) {
1769
+ return currentNode;
1600
1770
  }
1771
+ currentNode = currentNode.parentNode;
1601
1772
  }
1602
- return -1;
1603
- }
1604
- function getSelectedOptionIndex(options, value) {
1605
- return options.findIndex((option) => option.value === value && !option.disabled);
1773
+ return null;
1606
1774
  }
1607
- function getInitialActiveOptionIndex(options, value) {
1608
- const selectedIndex = getSelectedOptionIndex(options, value);
1609
- if (selectedIndex !== -1) {
1610
- return selectedIndex;
1775
+ function exitActiveFormatAtCaret(editorElement, format) {
1776
+ if (typeof window === "undefined") {
1777
+ return false;
1611
1778
  }
1612
- return getFirstEnabledOptionIndex(options);
1613
- }
1614
- function getNextEnabledOptionIndex(options, currentIndex, direction) {
1615
- if (options.length === 0) {
1616
- return -1;
1779
+ const selection = window.getSelection();
1780
+ if (!selection || selection.rangeCount === 0) {
1781
+ return false;
1617
1782
  }
1618
- let nextIndex = currentIndex;
1619
- for (let attempts = 0; attempts < options.length; attempts += 1) {
1620
- nextIndex = (nextIndex + direction + options.length) % options.length;
1621
- if (!options[nextIndex]?.disabled) {
1622
- return nextIndex;
1623
- }
1783
+ const range = selection.getRangeAt(0);
1784
+ const anchorNode = selection.anchorNode;
1785
+ if (!range.collapsed || !anchorNode || !isNodeWithinEditor(anchorNode, editorElement)) {
1786
+ return false;
1624
1787
  }
1625
- return currentIndex;
1788
+ const formatElement = findNearestFormatElement(anchorNode, editorElement, format);
1789
+ if (!formatElement || !formatElement.parentNode) {
1790
+ return false;
1791
+ }
1792
+ const trailingRange = document.createRange();
1793
+ trailingRange.setStart(range.startContainer, range.startOffset);
1794
+ trailingRange.setEndAfter(formatElement);
1795
+ const trailingFragment = trailingRange.extractContents();
1796
+ const caretTextNode = document.createTextNode("\u200B");
1797
+ const parentNode = formatElement.parentNode;
1798
+ parentNode.insertBefore(caretTextNode, formatElement.nextSibling);
1799
+ parentNode.insertBefore(trailingFragment, caretTextNode.nextSibling);
1800
+ if (formatElement.textContent?.replaceAll("\u200B", "").trim().length === 0) {
1801
+ formatElement.remove();
1802
+ }
1803
+ const nextRange = document.createRange();
1804
+ nextRange.setStart(caretTextNode, 1);
1805
+ nextRange.collapse(true);
1806
+ selection.removeAllRanges();
1807
+ selection.addRange(nextRange);
1808
+ return true;
1626
1809
  }
1627
- function MarwesSelectFieldControl(props) {
1628
- const { id, label, select } = props;
1629
- const listboxId = `${id}-listbox`;
1630
- const isControlled = select.value !== void 0;
1631
- const [internalValue, setInternalValue] = React2.useState(() => getInitialSelectValue2(select));
1632
- const value = isControlled ? select.value ?? "" : internalValue;
1633
- const [open, setOpen] = React2.useState(false);
1634
- const [activeIndex, setActiveIndex] = React2.useState(
1635
- () => getInitialActiveOptionIndex(select.options, value)
1810
+ var RichText = React2.forwardRef((props, forwardedRef) => {
1811
+ const kit = createRichTextRecipe(props);
1812
+ const allowedFormats = React2.useMemo(
1813
+ () => resolveRichTextAllowedFormats(props.allowedFormats),
1814
+ [props.allowedFormats]
1636
1815
  );
1637
- const rootRef = React2.useRef(null);
1638
- const buttonRef = React2.useRef(null);
1639
- const selectedOption = select.options.find((option) => option.value === value) ?? (select.placeholder === void 0 ? select.options[0] : void 0);
1640
- const placeholderSelected = select.placeholder !== void 0 && value === "";
1641
- const displayText = placeholderSelected ? select.placeholder : selectedOption?.label ?? "";
1642
- const accessibleName = select.ariaLabel ?? (hasTextContent3(label) ? label : void 0) ?? (hasTextContent3(displayText) ? displayText : void 0);
1643
- React2.useEffect(() => {
1644
- if (!open) {
1645
- return;
1646
- }
1647
- function handlePointerDown(event) {
1648
- if (rootRef.current?.contains(event.target)) {
1649
- return;
1816
+ const normalizedControlledValue = React2.useMemo(
1817
+ () => normalizeRichTextHtml(props.value),
1818
+ [props.value]
1819
+ );
1820
+ const initialUncontrolledValue = React2.useMemo(
1821
+ () => normalizeRichTextHtml(props.defaultValue),
1822
+ [props.defaultValue]
1823
+ );
1824
+ const isControlled = props.value !== void 0;
1825
+ const [uncontrolledHtml, setUncontrolledHtml] = React2.useState(initialUncontrolledValue);
1826
+ const [isEditorEmpty, setIsEditorEmpty] = React2.useState(
1827
+ isRichTextHtmlEmpty(isControlled ? normalizedControlledValue : initialUncontrolledValue)
1828
+ );
1829
+ const [activeFormats, setActiveFormats] = React2.useState([]);
1830
+ const editorElementRef = React2.useRef(null);
1831
+ useRenderKitDebug(kit, "RichText");
1832
+ const editorHtml = isControlled ? normalizedControlledValue : uncontrolledHtml;
1833
+ const style = kit.vars;
1834
+ const className = props.className ? `${kit.className} ${props.className}` : kit.className;
1835
+ const showToolbar = !props.readOnly;
1836
+ const syncEditorState = React2.useCallback(
1837
+ (nextHtml) => {
1838
+ const normalizedHtml = normalizeRichTextHtml(nextHtml);
1839
+ const emptyState = isRichTextHtmlEmpty(normalizedHtml);
1840
+ if (!isControlled) {
1841
+ setUncontrolledHtml(normalizedHtml);
1650
1842
  }
1651
- setOpen(false);
1652
- }
1653
- document.addEventListener("pointerdown", handlePointerDown);
1654
- return () => {
1655
- document.removeEventListener("pointerdown", handlePointerDown);
1656
- };
1657
- }, [open]);
1658
- React2.useEffect(() => {
1659
- if (!open) {
1660
- return;
1661
- }
1662
- setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1663
- }, [open, select.options, value]);
1664
- React2.useEffect(() => {
1665
- if (!select.disabled) {
1843
+ setIsEditorEmpty(emptyState);
1844
+ props.onValueChange?.(normalizedHtml);
1845
+ return normalizedHtml;
1846
+ },
1847
+ [isControlled, props]
1848
+ );
1849
+ const refreshActiveFormats = React2.useCallback(() => {
1850
+ setActiveFormats(getActiveFormatsFromSelection(editorElementRef.current));
1851
+ }, []);
1852
+ React2.useLayoutEffect(() => {
1853
+ const editorElement = editorElementRef.current;
1854
+ if (!editorElement) {
1666
1855
  return;
1667
1856
  }
1668
- setOpen(false);
1669
- }, [select.disabled]);
1670
- const commitValue = (nextValue) => {
1671
- if (!isControlled) {
1672
- setInternalValue(nextValue);
1673
- }
1674
- select.onValueChange?.(nextValue);
1675
- };
1676
- const selectOptionAtIndex = (index) => {
1677
- const option = select.options[index];
1678
- if (!option || option.disabled) {
1679
- return;
1857
+ const normalizedDomHtml = normalizeRichTextHtml(editorElement.innerHTML);
1858
+ if (normalizedDomHtml !== editorHtml) {
1859
+ editorElement.innerHTML = editorHtml;
1680
1860
  }
1681
- commitValue(option.value);
1682
- setOpen(false);
1683
- buttonRef.current?.focus();
1684
- };
1685
- const handleKeyDown = (event) => {
1686
- if (select.disabled) {
1687
- return;
1861
+ setIsEditorEmpty(isRichTextHtmlEmpty(editorHtml));
1862
+ }, [editorHtml]);
1863
+ React2.useEffect(() => {
1864
+ if (typeof document === "undefined") {
1865
+ return void 0;
1688
1866
  }
1689
- switch (event.key) {
1690
- case "ArrowDown": {
1691
- event.preventDefault();
1692
- if (!open) {
1693
- setOpen(true);
1694
- setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1695
- return;
1696
- }
1697
- setActiveIndex((currentIndex) => getNextEnabledOptionIndex(select.options, currentIndex, 1));
1698
- return;
1699
- }
1700
- case "ArrowUp": {
1701
- event.preventDefault();
1702
- if (!open) {
1703
- setOpen(true);
1704
- setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1705
- return;
1706
- }
1707
- setActiveIndex(
1708
- (currentIndex) => getNextEnabledOptionIndex(select.options, currentIndex, -1)
1709
- );
1710
- return;
1711
- }
1712
- case "Home": {
1713
- if (!open) {
1714
- return;
1715
- }
1716
- event.preventDefault();
1717
- setActiveIndex(getFirstEnabledOptionIndex(select.options));
1718
- return;
1719
- }
1720
- case "End": {
1721
- if (!open) {
1722
- return;
1723
- }
1724
- event.preventDefault();
1725
- setActiveIndex(getLastEnabledOptionIndex(select.options));
1726
- return;
1727
- }
1728
- case "Enter":
1729
- case " ": {
1730
- event.preventDefault();
1731
- if (!open) {
1732
- setOpen(true);
1733
- setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1734
- return;
1735
- }
1736
- if (activeIndex !== -1) {
1737
- selectOptionAtIndex(activeIndex);
1738
- }
1739
- return;
1740
- }
1741
- case "Escape": {
1742
- if (!open) {
1743
- return;
1744
- }
1745
- event.preventDefault();
1746
- setOpen(false);
1747
- return;
1748
- }
1749
- case "Tab": {
1750
- setOpen(false);
1751
- return;
1752
- }
1753
- default:
1754
- return;
1867
+ const handleSelectionChange = () => {
1868
+ refreshActiveFormats();
1869
+ };
1870
+ document.addEventListener("selectionchange", handleSelectionChange);
1871
+ return () => {
1872
+ document.removeEventListener("selectionchange", handleSelectionChange);
1873
+ };
1874
+ }, [refreshActiveFormats]);
1875
+ const handleInput = () => {
1876
+ const editorElement = editorElementRef.current;
1877
+ if (!editorElement || props.disabled || props.readOnly) {
1878
+ return;
1755
1879
  }
1880
+ syncEditorState(editorElement.innerHTML);
1881
+ refreshActiveFormats();
1756
1882
  };
1757
- return /* @__PURE__ */ jsxs(
1758
- "div",
1759
- {
1760
- ref: rootRef,
1761
- className: cx3("mw-select-field__control", open && "mw-select-field__control--open"),
1762
- children: [
1763
- /* @__PURE__ */ jsxs(
1764
- "button",
1765
- {
1766
- ref: buttonRef,
1767
- id,
1768
- type: "button",
1769
- className: cx3(
1770
- "mw-select-field__trigger",
1771
- placeholderSelected && "mw-select-field__trigger--placeholder",
1772
- select.invalid && "is-invalid",
1773
- open && "mw-select-field__trigger--open"
1774
- ),
1775
- role: "combobox",
1776
- "aria-controls": listboxId,
1777
- "aria-expanded": open,
1778
- "aria-haspopup": "listbox",
1779
- "aria-label": accessibleName,
1780
- "aria-describedby": select.describedBy,
1781
- "aria-invalid": select.invalid ? "true" : void 0,
1782
- "aria-required": select.required ? "true" : void 0,
1783
- "aria-activedescendant": open && activeIndex !== -1 ? `${id}-option-${activeIndex}` : void 0,
1784
- disabled: select.disabled,
1785
- "data-placeholder-selected": placeholderSelected ? "true" : void 0,
1786
- onClick: () => {
1787
- if (select.disabled) {
1788
- return;
1789
- }
1790
- setOpen((currentOpen) => !currentOpen);
1791
- },
1792
- onKeyDown: handleKeyDown,
1793
- children: [
1794
- /* @__PURE__ */ jsx("span", { className: "mw-select-field__trigger-text", children: displayText }),
1795
- /* @__PURE__ */ jsx(SelectArrowIcon, { className: "mw-select-field__trigger-icon" })
1796
- ]
1883
+ const toggleFormat = (format) => {
1884
+ if (props.disabled || props.readOnly || typeof document === "undefined") {
1885
+ return;
1886
+ }
1887
+ const commandDocument = getRichTextCommandDocument();
1888
+ const editorElement = editorElementRef.current;
1889
+ if (!editorElement) {
1890
+ return;
1891
+ }
1892
+ ensureEditorSelection(editorElement);
1893
+ const activeFormatsBeforeToggle = getActiveFormatsFromSelection(editorElement);
1894
+ if (exitActiveFormatAtCaret(editorElement, format)) {
1895
+ if (typeof commandDocument.queryCommandState === "function" && commandDocument.queryCommandState(richTextCommandByFormat[format]) && typeof commandDocument.execCommand === "function") {
1896
+ commandDocument.execCommand(richTextCommandByFormat[format]);
1897
+ }
1898
+ if (typeof commandDocument.queryCommandState === "function" && typeof commandDocument.execCommand === "function") {
1899
+ for (const activeFormat of activeFormatsBeforeToggle) {
1900
+ if (activeFormat === format) {
1901
+ continue;
1797
1902
  }
1798
- ),
1799
- select.name ? /* @__PURE__ */ jsx(
1800
- "input",
1801
- {
1802
- "aria-hidden": "true",
1803
- className: "mw-select-field__proxy-input",
1804
- name: select.name,
1805
- type: "hidden",
1806
- value,
1807
- readOnly: true
1903
+ if (!commandDocument.queryCommandState(richTextCommandByFormat[activeFormat])) {
1904
+ commandDocument.execCommand(richTextCommandByFormat[activeFormat]);
1808
1905
  }
1809
- ) : null,
1810
- open ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { className: "mw-select-field__list", id: listboxId, role: "listbox", tabIndex: -1, children: select.options.map((option, optionIndex) => {
1811
- const selected = option.value === value;
1812
- const active = optionIndex === activeIndex;
1813
- return /* @__PURE__ */ jsxs(
1814
- "div",
1815
- {
1816
- id: `${id}-option-${optionIndex}`,
1817
- className: cx3(
1818
- "mw-select-field__option",
1819
- active && "mw-select-field__option--active",
1820
- selected && "mw-select-field__option--selected",
1821
- option.disabled && "mw-select-field__option--disabled"
1822
- ),
1823
- role: "option",
1824
- "aria-selected": selected,
1825
- "aria-disabled": option.disabled ? "true" : void 0,
1826
- tabIndex: -1,
1827
- onClick: () => selectOptionAtIndex(optionIndex),
1828
- onKeyDown: (event) => {
1829
- if (option.disabled) {
1830
- return;
1831
- }
1832
- if (event.key === "Enter" || event.key === " ") {
1833
- event.preventDefault();
1834
- selectOptionAtIndex(optionIndex);
1835
- }
1836
- },
1837
- onMouseDown: (event) => event.preventDefault(),
1838
- onMouseEnter: () => {
1839
- if (!option.disabled) {
1840
- setActiveIndex(optionIndex);
1841
- }
1842
- },
1843
- children: [
1844
- /* @__PURE__ */ jsx("span", { className: "mw-select-field__option-label", children: option.label }),
1845
- selected ? /* @__PURE__ */ jsx(
1846
- Icon,
1847
- {
1848
- className: "mw-select-field__option-check",
1849
- name: IconName.Check,
1850
- size: "xs",
1851
- decorative: true
1852
- }
1853
- ) : null
1854
- ]
1855
- },
1856
- option.value
1857
- );
1858
- }) }) }) : null
1859
- ]
1906
+ }
1907
+ }
1908
+ syncEditorState(editorElement.innerHTML);
1909
+ refreshActiveFormats();
1910
+ return;
1860
1911
  }
1861
- );
1862
- }
1863
- function SelectField(props) {
1864
- const reactId = React2.useId();
1865
- const id = props.id ?? `mw-select-${reactId}`;
1866
- const mode = resolveSelectMode(props.select);
1867
- const hasHelperText = hasTextContent3(props.helperText);
1868
- const hasError = hasTextContent3(props.error);
1869
- const {
1870
- helperTextId,
1871
- errorId,
1872
- describedBy: mergedDescribedBy
1873
- } = buildInputFieldA11yIds({
1874
- id,
1875
- hasHelperText,
1876
- hasError,
1877
- externalDescribedBy: props.ariaDescribedBy
1878
- });
1879
- const disabled = props.select.disabled || false;
1880
- const invalid = hasError || props.select.invalid || false;
1881
- const wrapperClass = cx3(
1882
- "mw-input-field",
1883
- "mw-input-field--select",
1884
- mode === "marwes" && "mw-input-field--select-marwes",
1885
- props.variant === "date" && "mw-input-field--select-date",
1886
- disabled && "mw-input-field--disabled",
1887
- invalid && "mw-input-field--invalid"
1888
- );
1889
- const selectProps = {
1890
- ...props.select,
1891
- id,
1892
- invalid
1912
+ if (typeof commandDocument.execCommand === "function") {
1913
+ commandDocument.execCommand(richTextCommandByFormat[format]);
1914
+ }
1915
+ syncEditorState(editorElement.innerHTML);
1916
+ refreshActiveFormats();
1893
1917
  };
1894
- if (mergedDescribedBy) {
1895
- selectProps.describedBy = mergedDescribedBy;
1896
- }
1897
- return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
1898
- /* @__PURE__ */ jsx("label", { className: "mw-input-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
1899
- /* @__PURE__ */ jsx("div", { className: "mw-input-field__input-wrapper", children: mode === "native" ? /* @__PURE__ */ jsx(Select, { ...selectProps, native: true }) : /* @__PURE__ */ jsx(MarwesSelectFieldControl, { id, label: props.label, select: selectProps }) }),
1900
- hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.helperText }) }),
1901
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
1902
- ] });
1903
- }
1904
- function cx4(...parts) {
1905
- return parts.filter(Boolean).join(" ");
1906
- }
1907
- function hasTextContent4(value) {
1908
- return value !== void 0 && value.trim().length > 0;
1909
- }
1910
- function TextareaField(props) {
1911
- const reactId = React2.useId();
1912
- const id = props.id ?? `mw-textarea-${reactId}`;
1913
- const hasHelperText = hasTextContent4(props.helperText);
1914
- const hasError = hasTextContent4(props.error);
1915
- const {
1916
- helperTextId,
1917
- errorId,
1918
- describedBy: mergedDescribedBy
1919
- } = buildInputFieldA11yIds({
1920
- id,
1921
- hasHelperText,
1922
- hasError,
1923
- externalDescribedBy: props.ariaDescribedBy
1924
- });
1925
- const disabled = props.textarea.disabled || false;
1926
- const readOnly = props.textarea.readOnly || false;
1927
- const invalid = hasError || props.textarea.invalid || false;
1928
- const wrapperClass = cx4(
1929
- "mw-input-field",
1930
- "mw-input-field--textarea",
1931
- disabled && "mw-input-field--disabled",
1932
- invalid && "mw-input-field--invalid",
1933
- readOnly && "mw-input-field--readonly"
1934
- );
1935
- const textareaProps = {
1936
- ...props.textarea,
1937
- id,
1938
- invalid
1918
+ const handleKeyDown = (event) => {
1919
+ if (!(event.metaKey || event.ctrlKey) || event.altKey) {
1920
+ return;
1921
+ }
1922
+ const formatByKey = {
1923
+ b: "bold",
1924
+ i: "italic",
1925
+ u: "underline"
1926
+ };
1927
+ const requestedFormat = formatByKey[event.key.toLowerCase()];
1928
+ if (!requestedFormat || !allowedFormats.includes(requestedFormat)) {
1929
+ return;
1930
+ }
1931
+ event.preventDefault();
1932
+ toggleFormat(requestedFormat);
1939
1933
  };
1940
- if (mergedDescribedBy) {
1941
- textareaProps.describedBy = mergedDescribedBy;
1942
- }
1943
- return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
1944
- /* @__PURE__ */ jsx("label", { className: "mw-input-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
1945
- /* @__PURE__ */ jsx("div", { className: "mw-input-field__input-wrapper", children: /* @__PURE__ */ jsx(Textarea, { ...textareaProps }) }),
1946
- hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.helperText }) }),
1947
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
1934
+ return /* @__PURE__ */ jsxs("div", { className, style, ...kit.dataAttributes, children: [
1935
+ showToolbar && /* @__PURE__ */ jsx("div", { className: "mw-rich-text__toolbar", "data-rich-text-toolbar": true, children: allowedFormats.map((format) => {
1936
+ const isActive = activeFormats.includes(format);
1937
+ const iconName = format === "bold" ? "bold" : format === "italic" ? "italic" : "underline";
1938
+ return /* @__PURE__ */ jsx(
1939
+ "button",
1940
+ {
1941
+ type: "button",
1942
+ className: "mw-rich-text__toolbar-button",
1943
+ "data-format": format,
1944
+ "data-active": isActive ? "true" : void 0,
1945
+ "aria-label": formatLabels[format],
1946
+ "aria-pressed": isActive,
1947
+ disabled: props.disabled,
1948
+ onMouseDown: (event) => {
1949
+ event.preventDefault();
1950
+ },
1951
+ onClick: () => {
1952
+ toggleFormat(format);
1953
+ },
1954
+ children: /* @__PURE__ */ jsx(Icon, { name: iconName, size: "xs", decorative: true })
1955
+ },
1956
+ format
1957
+ );
1958
+ }) }),
1959
+ /* @__PURE__ */ jsx(
1960
+ "div",
1961
+ {
1962
+ ref: mergeRefs(editorElementRef, forwardedRef),
1963
+ className: "mw-rich-text__editor",
1964
+ "data-rich-text-editor": true,
1965
+ "data-empty": isEditorEmpty ? "true" : void 0,
1966
+ "data-placeholder": props.placeholder,
1967
+ id: kit.a11y.id,
1968
+ role: kit.a11y.role,
1969
+ tabIndex: kit.a11y.tabIndex,
1970
+ "aria-label": kit.a11y.ariaLabel,
1971
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
1972
+ "aria-describedby": kit.a11y.ariaDescribedBy,
1973
+ "aria-invalid": kit.a11y.ariaInvalid,
1974
+ "aria-disabled": kit.a11y.ariaDisabled,
1975
+ "aria-readonly": kit.a11y.ariaReadOnly,
1976
+ "aria-required": kit.a11y.ariaRequired,
1977
+ "aria-multiline": kit.a11y.ariaMultiline,
1978
+ contentEditable: !props.disabled && !props.readOnly,
1979
+ suppressContentEditableWarning: true,
1980
+ onInput: handleInput,
1981
+ onKeyDown: handleKeyDown,
1982
+ onFocus: refreshActiveFormats,
1983
+ onBlur: () => {
1984
+ syncEditorState(editorElementRef.current?.innerHTML ?? "");
1985
+ setActiveFormats([]);
1986
+ }
1987
+ }
1988
+ ),
1989
+ props.name && /* @__PURE__ */ jsx("input", { type: "hidden", name: props.name, value: editorHtml, disabled: props.disabled })
1948
1990
  ] });
1949
- }
1950
- function cx5(...parts) {
1991
+ });
1992
+ RichText.displayName = "RichText";
1993
+ function cx6(...parts) {
1951
1994
  return parts.filter(Boolean).join(" ");
1952
1995
  }
1953
1996
  function hasTextContent5(value) {
@@ -1968,7 +2011,7 @@ function RichTextField(props) {
1968
2011
  const disabled = props.editor.disabled || false;
1969
2012
  const readOnly = props.editor.readOnly || false;
1970
2013
  const invalid = hasError || props.editor.invalid || false;
1971
- const wrapperClass = cx5(
2014
+ const wrapperClass = cx6(
1972
2015
  "mw-input-field",
1973
2016
  "mw-input-field--rich-text",
1974
2017
  disabled && "mw-input-field--disabled",
@@ -1994,12 +2037,12 @@ function RichTextField(props) {
1994
2037
  onClick: () => {
1995
2038
  editorRef.current?.focus();
1996
2039
  },
1997
- children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label })
2040
+ children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label })
1998
2041
  }
1999
2042
  ),
2000
2043
  /* @__PURE__ */ jsx("div", { className: "mw-input-field__input-wrapper", children: /* @__PURE__ */ jsx(RichText, { ref: editorRef, ...editorProps }) }),
2001
- hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.helperText }) }),
2002
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
2044
+ hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.helperText }) }),
2045
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
2003
2046
  ] });
2004
2047
  }
2005
2048
  function DropdownField(props) {
@@ -2273,239 +2316,53 @@ function AvatarGroup(props) {
2273
2316
  {
2274
2317
  className: "mw-avatar-group__item",
2275
2318
  children: /* @__PURE__ */ jsx(Avatar, { ...item, size: "medium" })
2276
- },
2277
- item.id ?? `${itemIndex}-${item.initials ?? item.alt ?? "avatar"}`
2278
- )),
2279
- shouldRenderOverflowCounter ? /* @__PURE__ */ jsxs("span", { "aria-label": resolvedOverflowLabel, className: "mw-avatar-group__counter", role: "img", children: [
2280
- "+",
2281
- overflowCount
2282
- ] }) : null
2283
- ]
2284
- }
2285
- );
2286
- }
2287
- function ProfileAvatar(props) {
2288
- return /* @__PURE__ */ jsx(
2289
- Avatar,
2290
- {
2291
- ...props,
2292
- dataAttributes: {
2293
- ...props.dataAttributes,
2294
- ...createPurposeSemanticAttributes("profile")
2295
- }
2296
- }
2297
- );
2298
- }
2299
- function PresenceAvatar(props) {
2300
- return /* @__PURE__ */ jsx(
2301
- AvatarBadge,
2302
- {
2303
- ...props,
2304
- dataAttributes: {
2305
- ...props.dataAttributes,
2306
- ...createPurposeSemanticAttributes("presence")
2307
- }
2308
- }
2309
- );
2310
- }
2311
- function TeamAvatarGroup(props) {
2312
- return /* @__PURE__ */ jsx(
2313
- AvatarGroup,
2314
- {
2315
- ...props,
2316
- dataAttributes: {
2317
- ...props.dataAttributes,
2318
- ...createPurposeSemanticAttributes("team")
2319
- }
2320
- }
2321
- );
2322
- }
2323
- function Checkbox(props) {
2324
- const { onCheckedChange, onChange, ...coreProps } = props;
2325
- const kit = checkboxRecipe({ ...coreProps });
2326
- const inputRef = React2.useRef(null);
2327
- React2.useLayoutEffect(() => {
2328
- const el = inputRef.current;
2329
- if (!el) return;
2330
- el.indeterminate = kit.indeterminate;
2331
- }, [kit.indeterminate]);
2332
- const handleChange = (e) => {
2333
- onChange?.(e);
2334
- onCheckedChange?.(e.currentTarget.checked);
2335
- };
2336
- const { a11y } = kit;
2337
- return /* @__PURE__ */ jsx(
2338
- "input",
2339
- {
2340
- ref: inputRef,
2341
- type: "checkbox",
2342
- className: kit.className,
2343
- style: kit.vars,
2344
- id: a11y.id,
2345
- name: a11y.name,
2346
- value: a11y.value,
2347
- disabled: a11y.disabled === true,
2348
- required: a11y.required === true,
2349
- "aria-label": a11y.ariaLabel,
2350
- "aria-labelledby": a11y.ariaLabelledBy,
2351
- "aria-describedby": a11y.ariaDescribedBy,
2352
- "aria-checked": a11y.ariaChecked,
2353
- "aria-invalid": a11y.ariaInvalid === true ? true : void 0,
2354
- checked: kit.checked,
2355
- defaultChecked: kit.defaultChecked,
2356
- onChange: handleChange
2357
- }
2358
- );
2359
- }
2360
- function cx6(...parts) {
2361
- return parts.filter(Boolean).join(" ");
2362
- }
2363
- function hasContent(value) {
2364
- if (value === void 0 || value === null || value === false) {
2365
- return false;
2366
- }
2367
- if (typeof value === "string") {
2368
- return value.trim().length > 0;
2369
- }
2370
- return true;
2371
- }
2372
- function CheckboxField(props) {
2373
- const reactId = React2.useId();
2374
- const id = props.id ?? `mw-checkbox-${reactId}`;
2375
- const hasDescription = hasContent(props.description);
2376
- const hasError = hasContent(props.error);
2377
- const {
2378
- descriptionId: descId,
2379
- errorId,
2380
- describedBy: mergedDescribedBy
2381
- } = buildCheckboxFieldA11yIds({
2382
- id,
2383
- hasDescription,
2384
- hasError,
2385
- externalDescribedBy: props.ariaDescribedBy
2386
- });
2387
- const disabled = props.checkbox.disabled || false;
2388
- const invalid = hasError || props.checkbox.invalid || false;
2389
- const wrapperClass = cx6(
2390
- "mw-checkbox-field",
2391
- disabled && "mw-checkbox-field--disabled",
2392
- invalid && "mw-checkbox-field--invalid"
2393
- );
2394
- const checkboxProps = {
2395
- ...props.checkbox,
2396
- id,
2397
- invalid
2398
- };
2399
- if (mergedDescribedBy) {
2400
- checkboxProps.ariaDescribedBy = mergedDescribedBy;
2401
- }
2402
- return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
2403
- /* @__PURE__ */ jsxs("div", { className: "mw-checkbox-field__row", children: [
2404
- /* @__PURE__ */ jsx(Checkbox, { ...checkboxProps }),
2405
- /* @__PURE__ */ jsx("label", { className: "mw-checkbox-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) })
2406
- ] }),
2407
- hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-field__description", id: descId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
2408
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
2409
- ] });
2410
- }
2411
- function hasContent2(value) {
2412
- if (value === void 0 || value === null || value === false) return false;
2413
- if (typeof value === "string") return value.trim().length > 0;
2414
- return true;
2415
- }
2416
- function cx7(...parts) {
2417
- return parts.filter(Boolean).join(" ");
2418
- }
2419
- function orderSelectedValues(values, options) {
2420
- const optionValues = new Set(options.map((option) => option.value));
2421
- const selectedValues = new Set(values);
2422
- const knownValues = options.map((option) => option.value).filter((value) => selectedValues.has(value));
2423
- const unknownValues = values.filter((value) => !optionValues.has(value));
2424
- return [...knownValues, ...unknownValues];
2425
- }
2426
- function CheckboxGroupField(props) {
2427
- const reactId = React2.useId();
2428
- const id = props.id ?? `mw-checkbox-group-${reactId}`;
2429
- const hasDescription = hasContent2(props.description);
2430
- const hasError = hasContent2(props.error);
2431
- const isInvalid = hasError;
2432
- const { labelId, descriptionId, errorId, describedBy } = buildCheckboxGroupFieldA11yIds({
2433
- id,
2434
- hasDescription,
2435
- hasError,
2436
- externalDescribedBy: props.ariaDescribedBy
2437
- });
2438
- const isControlled = props.value !== void 0;
2439
- const [internalValue, setInternalValue] = React2.useState(
2440
- orderSelectedValues(props.defaultValue ?? [], props.options)
2441
- );
2442
- const selectedValues = orderSelectedValues(
2443
- isControlled ? props.value ?? [] : internalValue,
2444
- props.options
2445
- );
2446
- const selectedValueSet = new Set(selectedValues);
2447
- const handleToggle = (nextValue) => {
2448
- const rawNextValue = selectedValueSet.has(nextValue) ? selectedValues.filter((value) => value !== nextValue) : [...selectedValues, nextValue];
2449
- const orderedNextValue = orderSelectedValues(rawNextValue, props.options);
2450
- if (!isControlled) {
2451
- setInternalValue(orderedNextValue);
2452
- }
2453
- props.onChange?.(orderedNextValue);
2454
- };
2455
- const wrapperClass = cx7(
2456
- "mw-checkbox-group-field",
2457
- props.disabled && "mw-checkbox-group-field--disabled",
2458
- isInvalid && "mw-checkbox-group-field--invalid"
2459
- );
2460
- return /* @__PURE__ */ jsxs(
2461
- "fieldset",
2462
- {
2463
- className: wrapperClass,
2464
- "aria-labelledby": labelId,
2465
- "aria-describedby": describedBy,
2466
- "aria-invalid": isInvalid ? true : void 0,
2467
- "aria-required": props.required ? true : void 0,
2468
- disabled: props.disabled ? true : void 0,
2469
- ...props.dataAttributes,
2470
- children: [
2471
- /* @__PURE__ */ jsx("legend", { className: "mw-checkbox-group-field__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
2472
- hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-group-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
2473
- /* @__PURE__ */ jsx("div", { className: "mw-checkbox-group-field__options", children: props.options.map((option, index) => {
2474
- const optionId = `${id}-option-${index}`;
2475
- const isOptionDisabled = props.disabled || option.disabled || false;
2476
- const checkboxProps = {
2477
- ...props.checkbox ?? {},
2478
- id: optionId,
2479
- value: option.value,
2480
- checked: selectedValueSet.has(option.value),
2481
- disabled: isOptionDisabled,
2482
- invalid: isInvalid,
2483
- onCheckedChange: () => handleToggle(option.value)
2484
- };
2485
- if (props.name !== void 0) {
2486
- checkboxProps.name = props.name;
2487
- }
2488
- if (option.indeterminate !== void 0) {
2489
- checkboxProps.indeterminate = option.indeterminate;
2490
- }
2491
- return /* @__PURE__ */ jsxs(
2492
- "label",
2493
- {
2494
- className: "mw-checkbox-group-field__option",
2495
- htmlFor: optionId,
2496
- children: [
2497
- /* @__PURE__ */ jsx(Checkbox, { ...checkboxProps }),
2498
- /* @__PURE__ */ jsx(Paragraph, { size: "md", children: option.label })
2499
- ]
2500
- },
2501
- option.value
2502
- );
2503
- }) }),
2504
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-group-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
2319
+ },
2320
+ item.id ?? `${itemIndex}-${item.initials ?? item.alt ?? "avatar"}`
2321
+ )),
2322
+ shouldRenderOverflowCounter ? /* @__PURE__ */ jsxs("span", { "aria-label": resolvedOverflowLabel, className: "mw-avatar-group__counter", role: "img", children: [
2323
+ "+",
2324
+ overflowCount
2325
+ ] }) : null
2505
2326
  ]
2506
2327
  }
2507
2328
  );
2508
2329
  }
2330
+ function ProfileAvatar(props) {
2331
+ return /* @__PURE__ */ jsx(
2332
+ Avatar,
2333
+ {
2334
+ ...props,
2335
+ dataAttributes: {
2336
+ ...props.dataAttributes,
2337
+ ...createPurposeSemanticAttributes("profile")
2338
+ }
2339
+ }
2340
+ );
2341
+ }
2342
+ function PresenceAvatar(props) {
2343
+ return /* @__PURE__ */ jsx(
2344
+ AvatarBadge,
2345
+ {
2346
+ ...props,
2347
+ dataAttributes: {
2348
+ ...props.dataAttributes,
2349
+ ...createPurposeSemanticAttributes("presence")
2350
+ }
2351
+ }
2352
+ );
2353
+ }
2354
+ function TeamAvatarGroup(props) {
2355
+ return /* @__PURE__ */ jsx(
2356
+ AvatarGroup,
2357
+ {
2358
+ ...props,
2359
+ dataAttributes: {
2360
+ ...props.dataAttributes,
2361
+ ...createPurposeSemanticAttributes("team")
2362
+ }
2363
+ }
2364
+ );
2365
+ }
2509
2366
  var Divider = React2.forwardRef((props, ref) => {
2510
2367
  const { className: customClassName, style: customStyle, ...opts } = props;
2511
2368
  const kit = createDividerRecipe(opts);
@@ -2514,6 +2371,166 @@ var Divider = React2.forwardRef((props, ref) => {
2514
2371
  return /* @__PURE__ */ jsx("hr", { ref, ...kit.a11y, ...kit.dataAttributes, className, style });
2515
2372
  });
2516
2373
  Divider.displayName = "Divider";
2374
+ function cx7(...parts) {
2375
+ return parts.filter(Boolean).join(" ");
2376
+ }
2377
+ function ContextMenu(props) {
2378
+ const { items, ariaLabel, dataAttributes, onSelect, className, ...restProps } = props;
2379
+ const recipeOptions = { items };
2380
+ if (ariaLabel !== void 0) {
2381
+ recipeOptions.ariaLabel = ariaLabel;
2382
+ }
2383
+ if (dataAttributes !== void 0) {
2384
+ recipeOptions.dataAttributes = dataAttributes;
2385
+ }
2386
+ const kit = createContextMenuRecipe(recipeOptions);
2387
+ return /* @__PURE__ */ jsx(
2388
+ "div",
2389
+ {
2390
+ ...restProps,
2391
+ ...kit.dataAttributes,
2392
+ className: cx7(kit.className, className),
2393
+ role: kit.a11y.role,
2394
+ "aria-label": kit.a11y.ariaLabel,
2395
+ children: kit.items.map((item) => {
2396
+ if (item.kind === "divider") {
2397
+ return /* @__PURE__ */ jsx(
2398
+ "div",
2399
+ {
2400
+ className: item.className,
2401
+ role: item.a11y.role,
2402
+ "aria-orientation": item.a11y.ariaOrientation,
2403
+ ...item.dataAttributes
2404
+ },
2405
+ item.key
2406
+ );
2407
+ }
2408
+ return /* @__PURE__ */ jsxs(
2409
+ "button",
2410
+ {
2411
+ type: item.a11y.type,
2412
+ role: item.a11y.role,
2413
+ disabled: item.a11y.disabled,
2414
+ "aria-disabled": item.a11y.ariaDisabled,
2415
+ className: item.className,
2416
+ onClick: () => {
2417
+ if (item.item.disabled) return;
2418
+ onSelect?.(item.value, item.item);
2419
+ },
2420
+ ...item.dataAttributes,
2421
+ children: [
2422
+ item.icon && /* @__PURE__ */ jsx("span", { className: "mw-context-menu__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon, { name: item.icon, decorative: true }) }),
2423
+ /* @__PURE__ */ jsx("span", { className: "mw-context-menu__label", children: item.label })
2424
+ ]
2425
+ },
2426
+ item.key
2427
+ );
2428
+ })
2429
+ }
2430
+ );
2431
+ }
2432
+ function cx8(...parts) {
2433
+ return parts.filter(Boolean).join(" ");
2434
+ }
2435
+ function Breadcrumb(props) {
2436
+ const {
2437
+ items,
2438
+ ariaLabel,
2439
+ showHome,
2440
+ homeHref,
2441
+ homeLabel,
2442
+ dataAttributes,
2443
+ onItemSelect,
2444
+ onHomeClick,
2445
+ className,
2446
+ ...restProps
2447
+ } = props;
2448
+ const kit = createBreadcrumbRecipe({
2449
+ items,
2450
+ ...ariaLabel !== void 0 ? { ariaLabel } : {},
2451
+ ...showHome !== void 0 ? { showHome } : {},
2452
+ ...homeHref !== void 0 ? { homeHref } : {},
2453
+ ...homeLabel !== void 0 ? { homeLabel } : {},
2454
+ ...dataAttributes !== void 0 ? { dataAttributes } : {}
2455
+ });
2456
+ return /* @__PURE__ */ jsx(
2457
+ "nav",
2458
+ {
2459
+ ...restProps,
2460
+ ...kit.dataAttributes,
2461
+ className: cx8(kit.className, className),
2462
+ "aria-label": kit.a11y.ariaLabel,
2463
+ children: /* @__PURE__ */ jsx("ol", { className: kit.list.className, role: kit.list.a11y.role, children: kit.items.map((item, index) => /* @__PURE__ */ jsxs("li", { className: item.className, ...item.dataAttributes, children: [
2464
+ index > 0 && /* @__PURE__ */ jsx("span", { className: kit.separator.className, "aria-hidden": kit.separator.a11y.ariaHidden, children: /* @__PURE__ */ jsx(Icon, { name: IconName.ChevronRight, decorative: true, size: 12 }) }),
2465
+ item.kind === "home" ? renderHomeItem(item, onHomeClick) : /* @__PURE__ */ jsx(BreadcrumbAction, { item, onItemSelect })
2466
+ ] }, item.key)) })
2467
+ }
2468
+ );
2469
+ }
2470
+ function renderHomeItem(item, onHomeClick) {
2471
+ const commonProps = {
2472
+ className: item.actionClassName,
2473
+ "aria-label": item.a11y.ariaLabel,
2474
+ "aria-current": item.current ? "page" : void 0
2475
+ };
2476
+ if (item.href) {
2477
+ return /* @__PURE__ */ jsx(
2478
+ "a",
2479
+ {
2480
+ ...commonProps,
2481
+ href: item.href,
2482
+ onClick: (event) => {
2483
+ onHomeClick?.(event);
2484
+ },
2485
+ children: /* @__PURE__ */ jsx(Icon, { name: IconName.Home, decorative: true, size: 14 })
2486
+ }
2487
+ );
2488
+ }
2489
+ if (onHomeClick && !item.current) {
2490
+ return /* @__PURE__ */ jsx("button", { type: "button", ...commonProps, onClick: onHomeClick, children: /* @__PURE__ */ jsx(Icon, { name: IconName.Home, decorative: true, size: 14 }) });
2491
+ }
2492
+ return /* @__PURE__ */ jsx("span", { ...commonProps, children: /* @__PURE__ */ jsx(Icon, { name: IconName.Home, decorative: true, size: 14 }) });
2493
+ }
2494
+ function BreadcrumbAction({ item, onItemSelect }) {
2495
+ const sourceItem = item.item ?? {
2496
+ label: item.label,
2497
+ ...item.value ? { value: item.value } : {},
2498
+ ...item.href ? { href: item.href } : {},
2499
+ current: item.current
2500
+ };
2501
+ const commonProps = {
2502
+ className: item.actionClassName,
2503
+ "aria-label": item.a11y.ariaLabel,
2504
+ "aria-current": item.a11y.ariaCurrent
2505
+ };
2506
+ if (item.current) {
2507
+ return /* @__PURE__ */ jsx("span", { ...commonProps, children: item.label });
2508
+ }
2509
+ if (item.href) {
2510
+ return /* @__PURE__ */ jsx(
2511
+ "a",
2512
+ {
2513
+ ...commonProps,
2514
+ href: item.href,
2515
+ onClick: (event) => {
2516
+ onItemSelect?.(item.value ?? item.label, sourceItem, event);
2517
+ },
2518
+ children: item.label
2519
+ }
2520
+ );
2521
+ }
2522
+ return /* @__PURE__ */ jsx(
2523
+ "button",
2524
+ {
2525
+ type: "button",
2526
+ ...commonProps,
2527
+ onClick: (event) => {
2528
+ onItemSelect?.(item.value ?? item.label, sourceItem, event);
2529
+ },
2530
+ children: item.label
2531
+ }
2532
+ );
2533
+ }
2517
2534
  function Skeleton(props) {
2518
2535
  const {
2519
2536
  className,
@@ -2559,6 +2576,76 @@ function Skeleton(props) {
2559
2576
  }
2560
2577
  );
2561
2578
  }
2579
+ function ProgressBar(props) {
2580
+ const {
2581
+ className,
2582
+ style,
2583
+ dataAttributes,
2584
+ id,
2585
+ label,
2586
+ value,
2587
+ min,
2588
+ max,
2589
+ size,
2590
+ state,
2591
+ disabled,
2592
+ showLabel,
2593
+ showPercentage,
2594
+ valueLabel,
2595
+ ariaLabel,
2596
+ ariaLabelledBy,
2597
+ ariaDescribedBy,
2598
+ ...nativeDivProps
2599
+ } = props;
2600
+ const resolvedAriaLabel = ariaLabel ?? (typeof nativeDivProps["aria-label"] === "string" ? nativeDivProps["aria-label"] : void 0);
2601
+ const kit = createProgressBarRecipe({
2602
+ ...id !== void 0 ? { id } : {},
2603
+ ...label !== void 0 ? { label } : {},
2604
+ ...value !== void 0 ? { value } : {},
2605
+ ...min !== void 0 ? { min } : {},
2606
+ ...max !== void 0 ? { max } : {},
2607
+ ...size !== void 0 ? { size } : {},
2608
+ ...state !== void 0 ? { state } : {},
2609
+ ...disabled !== void 0 ? { disabled } : {},
2610
+ ...showLabel !== void 0 ? { showLabel } : {},
2611
+ ...showPercentage !== void 0 ? { showPercentage } : {},
2612
+ ...valueLabel !== void 0 ? { valueLabel } : {},
2613
+ ...resolvedAriaLabel !== void 0 ? { ariaLabel: resolvedAriaLabel } : {},
2614
+ ...ariaLabelledBy !== void 0 ? { ariaLabelledBy } : {},
2615
+ ...ariaDescribedBy !== void 0 ? { ariaDescribedBy } : {}
2616
+ });
2617
+ useRenderKitDebug(kit, "ProgressBar");
2618
+ const mergedClassName = [kit.className, className].filter(Boolean).join(" ");
2619
+ const mergedStyle = { ...kit.vars, ...style };
2620
+ const hasLabelRow = kit.showLabel || kit.showPercentage;
2621
+ return /* @__PURE__ */ jsxs(
2622
+ "div",
2623
+ {
2624
+ ...nativeDivProps,
2625
+ ...kit.dataAttributes,
2626
+ ...dataAttributes,
2627
+ id: kit.a11y.id,
2628
+ role: kit.a11y.role,
2629
+ "aria-valuemin": kit.a11y.ariaValueMin,
2630
+ "aria-valuemax": kit.a11y.ariaValueMax,
2631
+ "aria-valuenow": kit.a11y.ariaValueNow,
2632
+ "aria-valuetext": kit.a11y.ariaValueText,
2633
+ "aria-label": kit.a11y.ariaLabel,
2634
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
2635
+ "aria-describedby": kit.a11y.ariaDescribedBy,
2636
+ "aria-disabled": kit.a11y.ariaDisabled ? "true" : void 0,
2637
+ className: mergedClassName,
2638
+ style: mergedStyle,
2639
+ children: [
2640
+ hasLabelRow ? /* @__PURE__ */ jsxs("div", { className: "mw-progress-bar__label-row", children: [
2641
+ kit.showLabel ? /* @__PURE__ */ jsx("span", { id: kit.labelId, className: kit.labelClassName, children: kit.label }) : null,
2642
+ kit.showPercentage ? /* @__PURE__ */ jsx("span", { className: kit.percentageClassName, children: kit.percentageLabel }) : null
2643
+ ] }) : null,
2644
+ /* @__PURE__ */ jsx("div", { className: kit.trackClassName, "aria-hidden": "true", children: /* @__PURE__ */ jsx("span", { className: kit.fillClassName }) })
2645
+ ]
2646
+ }
2647
+ );
2648
+ }
2562
2649
  var Spacing = React2.forwardRef((props, ref) => {
2563
2650
  const { className: customClassName, scale, size, spacing, style: customStyle } = props;
2564
2651
  const resolvedSize = spacing ?? size;
@@ -2596,6 +2683,14 @@ function H3(props) {
2596
2683
  const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
2597
2684
  return /* @__PURE__ */ jsx("h3", { id: kit.a11y.id, "aria-label": kit.a11y.ariaLabel, className, style, children });
2598
2685
  }
2686
+ function Paragraph(props) {
2687
+ const { children, className: customClassName, style: customStyle, ...opts } = props;
2688
+ const theme = useTheme();
2689
+ const kit = paragraphRecipe(opts, theme);
2690
+ const style = { ...kit.vars, ...customStyle };
2691
+ const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
2692
+ return /* @__PURE__ */ jsx("p", { id: kit.a11y.id, className, style, children });
2693
+ }
2599
2694
  function StatTile(props) {
2600
2695
  const {
2601
2696
  className,
@@ -2648,6 +2743,9 @@ function DatePicker(props) {
2648
2743
  nextYearLabel,
2649
2744
  cancelLabel,
2650
2745
  applyLabel,
2746
+ ariaLabel,
2747
+ ariaLabelledBy,
2748
+ ariaDescribedBy,
2651
2749
  calendarLabel,
2652
2750
  dataAttributes,
2653
2751
  onPreviousYear,
@@ -2670,6 +2768,9 @@ function DatePicker(props) {
2670
2768
  ...nextYearLabel !== void 0 ? { nextYearLabel } : {},
2671
2769
  ...cancelLabel !== void 0 ? { cancelLabel } : {},
2672
2770
  ...applyLabel !== void 0 ? { applyLabel } : {},
2771
+ ...ariaLabel !== void 0 ? { ariaLabel } : {},
2772
+ ...ariaLabelledBy !== void 0 ? { ariaLabelledBy } : {},
2773
+ ...ariaDescribedBy !== void 0 ? { ariaDescribedBy } : {},
2673
2774
  ...calendarLabel !== void 0 ? { calendarLabel } : {},
2674
2775
  ...dataAttributes !== void 0 ? { dataAttributes } : {}
2675
2776
  });
@@ -2680,7 +2781,9 @@ function DatePicker(props) {
2680
2781
  ...nativeProps,
2681
2782
  ...kit.dataAttributes,
2682
2783
  className: mergedClassName,
2683
- "aria-label": kit.labels.calendar,
2784
+ "aria-label": kit.a11y.ariaLabel,
2785
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
2786
+ "aria-describedby": kit.a11y.ariaDescribedBy,
2684
2787
  children: [
2685
2788
  /* @__PURE__ */ jsxs("header", { className: kit.slots.headerClassName, children: [
2686
2789
  /* @__PURE__ */ jsxs("div", { className: kit.slots.navGroupClassName, children: [
@@ -2779,6 +2882,151 @@ function DatePicker(props) {
2779
2882
  }
2780
2883
  );
2781
2884
  }
2885
+ function cx9(...parts) {
2886
+ return parts.filter(Boolean).join(" ");
2887
+ }
2888
+ function hasTextContent6(value) {
2889
+ return value !== void 0 && value.trim().length > 0;
2890
+ }
2891
+ function DatePickerField(props) {
2892
+ const reactId = React2.useId();
2893
+ const id = props.id ?? `mw-date-picker-${reactId}`;
2894
+ const labelId = `${id}-label`;
2895
+ const hasHelperText = hasTextContent6(props.helperText);
2896
+ const hasError = hasTextContent6(props.error);
2897
+ const {
2898
+ helperTextId,
2899
+ errorId,
2900
+ describedBy: mergedDescribedBy
2901
+ } = buildInputFieldA11yIds({
2902
+ id,
2903
+ hasHelperText,
2904
+ hasError,
2905
+ externalDescribedBy: props.ariaDescribedBy
2906
+ });
2907
+ const wrapperClass = cx9(
2908
+ "mw-date-picker-field",
2909
+ hasError && "mw-date-picker-field--invalid",
2910
+ props.className
2911
+ );
2912
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
2913
+ /* @__PURE__ */ jsx("span", { className: "mw-date-picker-field__label", id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
2914
+ /* @__PURE__ */ jsx(
2915
+ DatePicker,
2916
+ {
2917
+ ...props.datePicker,
2918
+ ariaLabelledBy: labelId,
2919
+ ...mergedDescribedBy ? { ariaDescribedBy: mergedDescribedBy } : {}
2920
+ }
2921
+ ),
2922
+ hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-date-picker-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.helperText }) }),
2923
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-date-picker-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
2924
+ ] });
2925
+ }
2926
+ function cx10(...parts) {
2927
+ return parts.filter(Boolean).join(" ");
2928
+ }
2929
+ function hasContent(value) {
2930
+ if (value === void 0 || value === null || value === false) {
2931
+ return false;
2932
+ }
2933
+ if (typeof value === "string") {
2934
+ return value.trim().length > 0;
2935
+ }
2936
+ return true;
2937
+ }
2938
+ function Drawer(props) {
2939
+ const reactId = React2.useId();
2940
+ const id = props.id ?? `mw-drawer-${reactId}`;
2941
+ const titleId = `${id}-title`;
2942
+ const descriptionId = `${id}-description`;
2943
+ const hasTitle = hasContent(props.title);
2944
+ const hasDescription = hasContent(props.description);
2945
+ const hasFooter = hasContent(props.footer) && (props.showFooter ?? true);
2946
+ const dismissible = (props.dismissible ?? true) && props.onClose !== void 0;
2947
+ const drawerOptions = {
2948
+ showFooter: hasFooter,
2949
+ dismissible,
2950
+ ...props.modal !== void 0 ? { modal: props.modal } : {},
2951
+ ...props.showScrim !== void 0 ? { showScrim: props.showScrim } : {}
2952
+ };
2953
+ if (props.dataAttributes) {
2954
+ drawerOptions.dataAttributes = props.dataAttributes;
2955
+ }
2956
+ if (props.size) {
2957
+ drawerOptions.size = props.size;
2958
+ }
2959
+ if (props.placement) {
2960
+ drawerOptions.placement = props.placement;
2961
+ }
2962
+ if (props.ariaLabel) {
2963
+ drawerOptions.ariaLabel = props.ariaLabel;
2964
+ }
2965
+ if (props.ariaLabelledBy) {
2966
+ drawerOptions.ariaLabelledBy = props.ariaLabelledBy;
2967
+ } else if (props.ariaLabel === void 0 && hasTitle) {
2968
+ drawerOptions.ariaLabelledBy = titleId;
2969
+ }
2970
+ if (props.ariaDescribedBy) {
2971
+ drawerOptions.ariaDescribedBy = props.ariaDescribedBy;
2972
+ } else if (hasDescription) {
2973
+ drawerOptions.ariaDescribedBy = descriptionId;
2974
+ }
2975
+ const kit = createDrawerRecipe(drawerOptions);
2976
+ return /* @__PURE__ */ jsxs("div", { className: cx10(kit.className, props.className), style: kit.vars, ...kit.dataAttributes, children: [
2977
+ kit.showScrim && /* @__PURE__ */ jsx(
2978
+ "div",
2979
+ {
2980
+ className: kit.scrim.className,
2981
+ style: kit.scrim.vars,
2982
+ "aria-hidden": "true",
2983
+ onClick: dismissible ? props.onClose : void 0,
2984
+ ...kit.scrim.dataAttributes
2985
+ }
2986
+ ),
2987
+ /* @__PURE__ */ jsxs(
2988
+ "div",
2989
+ {
2990
+ id,
2991
+ className: cx10(kit.panel.className, props.panelClassName),
2992
+ style: kit.panel.vars,
2993
+ role: kit.panel.a11y.role,
2994
+ ...kit.panel.a11y.ariaModal ? { "aria-modal": "true" } : {},
2995
+ ...kit.panel.a11y.ariaLabel ? { "aria-label": kit.panel.a11y.ariaLabel } : {},
2996
+ ...kit.panel.a11y.ariaLabelledBy ? { "aria-labelledby": kit.panel.a11y.ariaLabelledBy } : {},
2997
+ ...kit.panel.a11y.ariaDescribedBy ? { "aria-describedby": kit.panel.a11y.ariaDescribedBy } : {},
2998
+ tabIndex: -1,
2999
+ ...kit.panel.dataAttributes,
3000
+ children: [
3001
+ (hasTitle || kit.showCloseButton) && /* @__PURE__ */ jsxs(Fragment, { children: [
3002
+ /* @__PURE__ */ jsxs("div", { className: "mw-drawer__header", children: [
3003
+ hasTitle ? /* @__PURE__ */ jsx("div", { className: "mw-drawer__heading-group", children: /* @__PURE__ */ jsx("h2", { className: "mw-drawer__title", id: titleId, children: props.title }) }) : /* @__PURE__ */ jsx("span", { className: "mw-drawer__spacer", "aria-hidden": "true" }),
3004
+ kit.showCloseButton && props.onClose && /* @__PURE__ */ jsx(
3005
+ "button",
3006
+ {
3007
+ type: "button",
3008
+ className: "mw-drawer__close",
3009
+ "aria-label": "Close drawer",
3010
+ onClick: props.onClose,
3011
+ children: /* @__PURE__ */ jsx(Icon, { name: IconName.X, decorative: true })
3012
+ }
3013
+ )
3014
+ ] }),
3015
+ /* @__PURE__ */ jsx("div", { className: "mw-drawer__header-divider", "aria-hidden": "true" })
3016
+ ] }),
3017
+ /* @__PURE__ */ jsxs("div", { className: "mw-drawer__content", children: [
3018
+ hasDescription && /* @__PURE__ */ jsx("p", { className: "mw-drawer__description", id: descriptionId, children: props.description }),
3019
+ props.children
3020
+ ] }),
3021
+ hasFooter && /* @__PURE__ */ jsxs(Fragment, { children: [
3022
+ /* @__PURE__ */ jsx("div", { className: "mw-drawer__footer-divider", "aria-hidden": "true" }),
3023
+ /* @__PURE__ */ jsx("div", { className: "mw-drawer__footer", children: props.footer })
3024
+ ] })
3025
+ ]
3026
+ }
3027
+ )
3028
+ ] });
3029
+ }
2782
3030
  function Card(props) {
2783
3031
  const { title, children, className, dataAttributes, ...nativeDivProps } = props;
2784
3032
  const kit = createCardRecipe(dataAttributes ? { dataAttributes } : {});
@@ -2831,7 +3079,7 @@ function StatCard(props) {
2831
3079
  }
2832
3080
  );
2833
3081
  }
2834
- function cx8(...parts) {
3082
+ function cx11(...parts) {
2835
3083
  return parts.filter(Boolean).join(" ");
2836
3084
  }
2837
3085
  function Toast(props) {
@@ -2842,7 +3090,7 @@ function Toast(props) {
2842
3090
  "div",
2843
3091
  {
2844
3092
  id,
2845
- className: cx8(kit.className, className),
3093
+ className: cx11(kit.className, className),
2846
3094
  role: a11y.role,
2847
3095
  "aria-live": a11y.ariaLive,
2848
3096
  "aria-atomic": "true",
@@ -2930,7 +3178,7 @@ function InfoToast(props) {
2930
3178
  }
2931
3179
  );
2932
3180
  }
2933
- function cx9(...parts) {
3181
+ function cx12(...parts) {
2934
3182
  return parts.filter(Boolean).join(" ");
2935
3183
  }
2936
3184
  function renderToastByIntent(toast, onDismiss) {
@@ -3072,7 +3320,7 @@ function ToastViewportItem(props) {
3072
3320
  function ToastContainer(props) {
3073
3321
  const placement = props.placement ?? "top-right";
3074
3322
  const visibleToasts = props.maxVisible && props.maxVisible > 0 ? props.toasts.slice(-props.maxVisible) : props.toasts;
3075
- return /* @__PURE__ */ jsx("div", { className: cx9("mw-toast-container", `mw-toast-container--${placement}`, props.className), children: visibleToasts.map((toast) => /* @__PURE__ */ jsx(
3323
+ return /* @__PURE__ */ jsx("div", { className: cx12("mw-toast-container", `mw-toast-container--${placement}`, props.className), children: visibleToasts.map((toast) => /* @__PURE__ */ jsx(
3076
3324
  ToastViewportItem,
3077
3325
  {
3078
3326
  toast,
@@ -3169,7 +3417,7 @@ function Tooltip(props) {
3169
3417
  );
3170
3418
  }
3171
3419
  var TOOLTIP_EXIT_DURATION_MS = 160;
3172
- function cx10(...parts) {
3420
+ function cx13(...parts) {
3173
3421
  return parts.filter(Boolean).join(" ");
3174
3422
  }
3175
3423
  function TooltipGroup(props) {
@@ -3229,7 +3477,7 @@ function TooltipGroup(props) {
3229
3477
  ...nativeSpanProps,
3230
3478
  ...dataAttributes,
3231
3479
  id,
3232
- className: cx10("mw-tooltip-group", className),
3480
+ className: cx13("mw-tooltip-group", className),
3233
3481
  "data-component": "tooltip-group",
3234
3482
  "data-open": resolvedOpen ? "true" : void 0,
3235
3483
  onMouseEnter: (event) => {
@@ -3273,7 +3521,7 @@ function TooltipGroup(props) {
3273
3521
  "button",
3274
3522
  {
3275
3523
  type: "button",
3276
- className: cx10("mw-tooltip-group__trigger", triggerClassName),
3524
+ className: cx13("mw-tooltip-group__trigger", triggerClassName),
3277
3525
  "aria-label": triggerLabel,
3278
3526
  "aria-describedby": resolvedOpen ? resolvedTooltipId : void 0,
3279
3527
  children: /* @__PURE__ */ jsx(Icon, { name: icon, decorative: true })
@@ -3326,12 +3574,12 @@ function Accordion(props) {
3326
3574
  )
3327
3575
  ] });
3328
3576
  }
3329
- function hasContent3(value) {
3577
+ function hasContent2(value) {
3330
3578
  if (value === void 0 || value === null || value === false) return false;
3331
3579
  if (typeof value === "string") return value.trim().length > 0;
3332
3580
  return true;
3333
3581
  }
3334
- function cx11(...parts) {
3582
+ function cx14(...parts) {
3335
3583
  return parts.filter(Boolean).join(" ");
3336
3584
  }
3337
3585
  function resolveAccordionItemContent(item) {
@@ -3341,8 +3589,8 @@ function AccordionField(props) {
3341
3589
  const reactId = React2.useId();
3342
3590
  const id = props.id ?? `mw-accordion-field-${reactId}`;
3343
3591
  const multipleAllowed = props.multiple ?? true;
3344
- const hasDescription = hasContent3(props.description);
3345
- const hasError = hasContent3(props.error);
3592
+ const hasDescription = hasContent2(props.description);
3593
+ const hasError = hasContent2(props.error);
3346
3594
  const isInvalid = hasError || false;
3347
3595
  const { labelId, descriptionId, errorId, describedBy } = buildAccordionFieldA11yIds({
3348
3596
  id,
@@ -3370,7 +3618,7 @@ function AccordionField(props) {
3370
3618
  }
3371
3619
  props.onOpenItemsChange?.(nextOpenItems);
3372
3620
  };
3373
- const wrapperClass = cx11(
3621
+ const wrapperClass = cx14(
3374
3622
  "mw-accordion-field",
3375
3623
  props.disabled && "mw-accordion-field--disabled",
3376
3624
  isInvalid && "mw-accordion-field--invalid"
@@ -3384,7 +3632,7 @@ function AccordionField(props) {
3384
3632
  "aria-invalid": isInvalid ? true : void 0,
3385
3633
  ...props.dataAttributes,
3386
3634
  children: [
3387
- /* @__PURE__ */ jsx("legend", { className: "mw-accordion-field__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
3635
+ /* @__PURE__ */ jsx("legend", { className: "mw-accordion-field__label", id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
3388
3636
  /* @__PURE__ */ jsx("div", { className: "mw-accordion-field__items", children: props.items.map((item) => {
3389
3637
  const isDisabled = props.disabled || item.disabled || false;
3390
3638
  const isOpen = openItems.includes(item.value);
@@ -3401,8 +3649,8 @@ function AccordionField(props) {
3401
3649
  item.value
3402
3650
  );
3403
3651
  }) }),
3404
- hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-accordion-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
3405
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-accordion-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
3652
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-accordion-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.description }) }),
3653
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-accordion-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
3406
3654
  ]
3407
3655
  }
3408
3656
  );
@@ -3473,19 +3721,19 @@ function Radio(props) {
3473
3721
  }
3474
3722
  );
3475
3723
  }
3476
- function hasContent4(value) {
3724
+ function hasContent3(value) {
3477
3725
  if (value === void 0 || value === null || value === false) return false;
3478
3726
  if (typeof value === "string") return value.trim().length > 0;
3479
3727
  return true;
3480
3728
  }
3481
- function cx12(...parts) {
3729
+ function cx15(...parts) {
3482
3730
  return parts.filter(Boolean).join(" ");
3483
3731
  }
3484
3732
  function RadioGroupField(props) {
3485
3733
  const reactId = React2.useId();
3486
3734
  const id = props.id ?? `mw-radio-group-${reactId}`;
3487
- const hasDescription = hasContent4(props.description);
3488
- const hasError = hasContent4(props.error);
3735
+ const hasDescription = hasContent3(props.description);
3736
+ const hasError = hasContent3(props.error);
3489
3737
  const isInvalid = hasError || false;
3490
3738
  const { labelId, descriptionId, errorId, describedBy } = buildRadioGroupFieldA11yIds({
3491
3739
  id,
@@ -3502,14 +3750,14 @@ function RadioGroupField(props) {
3502
3750
  }
3503
3751
  props.onChange?.(optionValue);
3504
3752
  };
3505
- const wrapperClass = cx12(
3753
+ const wrapperClass = cx15(
3506
3754
  "mw-radio-group-field",
3507
3755
  props.disabled && "mw-radio-group-field--disabled",
3508
3756
  isInvalid && "mw-radio-group-field--invalid"
3509
3757
  );
3510
3758
  return /* @__PURE__ */ jsxs("div", { className: wrapperClass, ...props.dataAttributes, children: [
3511
- /* @__PURE__ */ jsx("div", { className: "mw-radio-group-field__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.label }) }),
3512
- hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-radio-group-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
3759
+ /* @__PURE__ */ jsx("div", { className: "mw-radio-group-field__label", id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
3760
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-radio-group-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.description }) }),
3513
3761
  /* @__PURE__ */ jsx(
3514
3762
  "div",
3515
3763
  {
@@ -3519,31 +3767,66 @@ function RadioGroupField(props) {
3519
3767
  "aria-invalid": isInvalid ? true : void 0,
3520
3768
  "aria-required": props.required ? true : void 0,
3521
3769
  className: "mw-radio-group-field__options",
3522
- children: props.options.map(({ value, label, disabled: optionDisabled }) => {
3770
+ children: props.options.map(({ value, label, description, disabled: optionDisabled }) => {
3523
3771
  const optionId = `${id}-option-${value}`;
3772
+ const optionLabelId = `${optionId}-label`;
3773
+ const optionDescriptionId = `${optionId}-description`;
3774
+ const hasOptionDescription = hasContent3(description);
3524
3775
  const isDisabled = props.disabled || optionDisabled || false;
3525
- return /* @__PURE__ */ jsxs("label", { className: "mw-radio-group-field__option", htmlFor: optionId, children: [
3526
- /* @__PURE__ */ jsx(
3527
- Radio,
3528
- {
3529
- id: optionId,
3530
- name: props.name,
3531
- value,
3532
- checked: selectedValue === value,
3533
- disabled: isDisabled,
3534
- invalid: isInvalid,
3535
- ...props.required ? { required: true } : {},
3536
- onCheckedChange: (checked) => {
3537
- if (checked) handleSelect(value);
3538
- }
3539
- }
3540
- ),
3541
- /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: label })
3542
- ] }, value);
3776
+ return /* @__PURE__ */ jsxs(
3777
+ "label",
3778
+ {
3779
+ className: cx15(
3780
+ "mw-radio-group-field__option",
3781
+ hasOptionDescription && "mw-radio-group-field__option--with-description"
3782
+ ),
3783
+ htmlFor: optionId,
3784
+ children: [
3785
+ /* @__PURE__ */ jsx(
3786
+ Radio,
3787
+ {
3788
+ id: optionId,
3789
+ name: props.name,
3790
+ value,
3791
+ ariaLabelledBy: optionLabelId,
3792
+ ...hasOptionDescription ? { ariaDescribedBy: optionDescriptionId } : {},
3793
+ checked: selectedValue === value,
3794
+ disabled: isDisabled,
3795
+ invalid: isInvalid,
3796
+ ...props.required ? { required: true } : {},
3797
+ onCheckedChange: (checked) => {
3798
+ if (checked) handleSelect(value);
3799
+ }
3800
+ }
3801
+ ),
3802
+ /* @__PURE__ */ jsxs("span", { className: "mw-radio-group-field__option-content", children: [
3803
+ /* @__PURE__ */ jsx(
3804
+ Text,
3805
+ {
3806
+ id: optionLabelId,
3807
+ variant: "label",
3808
+ className: "mw-radio-group-field__option-label",
3809
+ children: label
3810
+ }
3811
+ ),
3812
+ hasOptionDescription && /* @__PURE__ */ jsx(
3813
+ Text,
3814
+ {
3815
+ id: optionDescriptionId,
3816
+ variant: "label-small",
3817
+ className: "mw-radio-group-field__option-description",
3818
+ children: description
3819
+ }
3820
+ )
3821
+ ] })
3822
+ ]
3823
+ },
3824
+ value
3825
+ );
3543
3826
  })
3544
3827
  }
3545
3828
  ),
3546
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-radio-group-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
3829
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-radio-group-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
3547
3830
  ] });
3548
3831
  }
3549
3832
  function YesNoRadioGroup(props) {
@@ -3609,16 +3892,16 @@ function Badge(props) {
3609
3892
  }
3610
3893
  );
3611
3894
  }
3612
- function cx13(...parts) {
3895
+ function cx16(...parts) {
3613
3896
  return parts.filter(Boolean).join(" ");
3614
3897
  }
3615
3898
  function BadgeGroup(props) {
3616
3899
  const reactId = React2.useId();
3617
3900
  const id = props.id ?? `mw-badge-group-${reactId}`;
3618
3901
  const labelId = `${id}-label`;
3619
- const className = cx13("mw-badge-group", props.className);
3902
+ const className = cx16("mw-badge-group", props.className);
3620
3903
  return /* @__PURE__ */ jsxs("fieldset", { className, "aria-labelledby": labelId, ...props.dataAttributes, children: [
3621
- /* @__PURE__ */ jsx("legend", { className: "mw-badge-group__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.label }) }),
3904
+ /* @__PURE__ */ jsx("legend", { className: "mw-badge-group__label", id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.label }) }),
3622
3905
  /* @__PURE__ */ jsx("div", { className: "mw-badge-group__items", children: props.children })
3623
3906
  ] });
3624
3907
  }
@@ -3658,6 +3941,88 @@ function NotificationBadge(props) {
3658
3941
  }
3659
3942
  );
3660
3943
  }
3944
+ function Banner(props) {
3945
+ const { children, action, icon, onDismiss, className, id, ...coreProps } = props;
3946
+ const kit = createBannerRecipe({
3947
+ ...coreProps,
3948
+ showAction: coreProps.showAction ?? Boolean(action)
3949
+ });
3950
+ return /* @__PURE__ */ jsxs(
3951
+ "div",
3952
+ {
3953
+ id,
3954
+ className: [kit.root.className, className].filter(Boolean).join(" "),
3955
+ role: kit.root.a11y.role,
3956
+ "aria-label": kit.root.a11y.ariaLabel,
3957
+ "aria-live": kit.root.a11y.ariaLive,
3958
+ ...kit.root.dataAttributes,
3959
+ children: [
3960
+ /* @__PURE__ */ jsxs("div", { className: kit.content.className, children: [
3961
+ kit.icon.visible && /* @__PURE__ */ jsx("span", { className: kit.icon.className, children: icon ?? /* @__PURE__ */ jsx(Icon, { name: IconName.Info, decorative: true }) }),
3962
+ /* @__PURE__ */ jsx("span", { className: kit.message.className, children })
3963
+ ] }),
3964
+ kit.action.visible && action && /* @__PURE__ */ jsx("div", { className: kit.action.className, children: action }),
3965
+ kit.dismiss.visible && /* @__PURE__ */ jsx(
3966
+ "button",
3967
+ {
3968
+ type: "button",
3969
+ className: kit.dismiss.className,
3970
+ "aria-label": kit.dismiss.ariaLabel,
3971
+ onClick: onDismiss
3972
+ }
3973
+ )
3974
+ ]
3975
+ }
3976
+ );
3977
+ }
3978
+ function InfoBanner(props) {
3979
+ const purposeAttrs = createPurposeSemanticAttributes("info-banner");
3980
+ return /* @__PURE__ */ jsx(
3981
+ Banner,
3982
+ {
3983
+ ...props,
3984
+ variant: "info",
3985
+ "data-purpose": purposeAttrs["data-purpose"],
3986
+ "data-intent": purposeAttrs["data-intent"]
3987
+ }
3988
+ );
3989
+ }
3990
+ function SuccessBanner(props) {
3991
+ const purposeAttrs = createPurposeSemanticAttributes("success-banner");
3992
+ return /* @__PURE__ */ jsx(
3993
+ Banner,
3994
+ {
3995
+ ...props,
3996
+ variant: "success",
3997
+ "data-purpose": purposeAttrs["data-purpose"],
3998
+ "data-intent": purposeAttrs["data-intent"]
3999
+ }
4000
+ );
4001
+ }
4002
+ function WarningBanner(props) {
4003
+ const purposeAttrs = createPurposeSemanticAttributes("warning-banner");
4004
+ return /* @__PURE__ */ jsx(
4005
+ Banner,
4006
+ {
4007
+ ...props,
4008
+ variant: "warning",
4009
+ "data-purpose": purposeAttrs["data-purpose"],
4010
+ "data-intent": purposeAttrs["data-intent"]
4011
+ }
4012
+ );
4013
+ }
4014
+ function ErrorBanner(props) {
4015
+ const purposeAttrs = createPurposeSemanticAttributes("error-banner");
4016
+ return /* @__PURE__ */ jsx(
4017
+ Banner,
4018
+ {
4019
+ ...props,
4020
+ variant: "error",
4021
+ "data-purpose": purposeAttrs["data-purpose"],
4022
+ "data-intent": purposeAttrs["data-intent"]
4023
+ }
4024
+ );
4025
+ }
3661
4026
  function Switch(props) {
3662
4027
  const { children, className, id, onCheckedChange, onClick, ...coreProps } = props;
3663
4028
  const kit = createSwitchRecipe(coreProps);
@@ -3680,7 +4045,7 @@ function Switch(props) {
3680
4045
  "aria-checked": a11y.ariaChecked,
3681
4046
  "aria-disabled": a11y.ariaDisabled,
3682
4047
  "aria-label": a11y.ariaLabel,
3683
- "aria-labelledby": a11y.ariaLabelledby,
4048
+ "aria-labelledby": a11y.ariaLabelledBy,
3684
4049
  "aria-describedby": a11y.ariaDescribedBy,
3685
4050
  className: [kit.className, className].filter(Boolean).join(" "),
3686
4051
  style: kit.vars,
@@ -3692,10 +4057,10 @@ function Switch(props) {
3692
4057
  }
3693
4058
  );
3694
4059
  }
3695
- function cx14(...parts) {
4060
+ function cx17(...parts) {
3696
4061
  return parts.filter(Boolean).join(" ");
3697
4062
  }
3698
- function hasContent5(value) {
4063
+ function hasContent4(value) {
3699
4064
  if (value === void 0 || value === null || value === false) {
3700
4065
  return false;
3701
4066
  }
@@ -3707,8 +4072,8 @@ function hasContent5(value) {
3707
4072
  function SwitchField(props) {
3708
4073
  const reactId = React2.useId();
3709
4074
  const id = props.id ?? `mw-switch-${reactId}`;
3710
- const hasDescription = hasContent5(props.description);
3711
- const hasError = hasContent5(props.error);
4075
+ const hasDescription = hasContent4(props.description);
4076
+ const hasError = hasContent4(props.error);
3712
4077
  const { labelId, descriptionId, errorId, describedBy } = buildSwitchFieldA11yIds({
3713
4078
  id,
3714
4079
  hasDescription,
@@ -3717,14 +4082,14 @@ function SwitchField(props) {
3717
4082
  });
3718
4083
  const disabled = props.switch.disabled || false;
3719
4084
  const invalid = hasError;
3720
- const wrapperClass = cx14(
4085
+ const wrapperClass = cx17(
3721
4086
  "mw-switch-field",
3722
4087
  disabled && "mw-switch-field--disabled",
3723
4088
  invalid && "mw-switch-field--invalid"
3724
4089
  );
3725
4090
  const {
3726
4091
  ariaLabel: _ignoredAriaLabel,
3727
- ariaLabelledby: _ignoredAriaLabelledby,
4092
+ ariaLabelledBy: _ignoredAriaLabelledby,
3728
4093
  ariaDescribedBy: _ignoredAriaDescribedBy,
3729
4094
  children: _ignoredChildren,
3730
4095
  ...switchProps
@@ -3736,14 +4101,14 @@ function SwitchField(props) {
3736
4101
  {
3737
4102
  ...switchProps,
3738
4103
  id,
3739
- ariaLabelledby: labelId,
4104
+ ariaLabelledBy: labelId,
3740
4105
  ...describedBy ? { ariaDescribedBy: describedBy } : {}
3741
4106
  }
3742
4107
  ),
3743
- /* @__PURE__ */ jsx("span", { className: "mw-switch-field__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) })
4108
+ /* @__PURE__ */ jsx("span", { className: "mw-switch-field__label", id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) })
3744
4109
  ] }),
3745
- hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-switch-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
3746
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-switch-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
4110
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-switch-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.description }) }),
4111
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-switch-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
3747
4112
  ] });
3748
4113
  }
3749
4114
  function FeatureToggle(props) {
@@ -3903,10 +4268,10 @@ var Slider = React2.forwardRef((props, ref) => {
3903
4268
  ] }) });
3904
4269
  });
3905
4270
  Slider.displayName = "Slider";
3906
- function cx15(...parts) {
4271
+ function cx18(...parts) {
3907
4272
  return parts.filter(Boolean).join(" ");
3908
4273
  }
3909
- function hasContent6(value) {
4274
+ function hasContent5(value) {
3910
4275
  if (value === void 0 || value === null || value === false) {
3911
4276
  return false;
3912
4277
  }
@@ -3921,8 +4286,8 @@ function resolveEdgeValueLabel(value, fallback) {
3921
4286
  function SliderField(props) {
3922
4287
  const reactId = React2.useId();
3923
4288
  const id = props.id ?? `mw-slider-${reactId}`;
3924
- const hasDescription = hasContent6(props.description);
3925
- const hasError = hasContent6(props.error);
4289
+ const hasDescription = hasContent5(props.description);
4290
+ const hasError = hasContent5(props.error);
3926
4291
  const { labelId, descriptionId, errorId, describedBy } = buildSliderFieldA11yIds({
3927
4292
  id,
3928
4293
  hasDescription,
@@ -3936,7 +4301,7 @@ function SliderField(props) {
3936
4301
  const maxValue = props.slider.max ?? 100;
3937
4302
  const minValueLabel = resolveEdgeValueLabel(props.minValueLabel, minValue);
3938
4303
  const maxValueLabel = resolveEdgeValueLabel(props.maxValueLabel, maxValue);
3939
- const wrapperClass = cx15(
4304
+ const wrapperClass = cx18(
3940
4305
  "mw-slider-field",
3941
4306
  labelPosition === "top" && "mw-slider-field--label-top",
3942
4307
  labelPosition === "inline" && "mw-slider-field--label-inline",
@@ -3950,10 +4315,10 @@ function SliderField(props) {
3950
4315
  style: sliderStyle,
3951
4316
  ...sliderProps
3952
4317
  } = props.slider;
3953
- const renderEdgeValue = (position, value) => /* @__PURE__ */ jsx("span", { className: `mw-slider-field__edge-value mw-slider-field__edge-value--${position}`, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: value }) });
4318
+ const renderEdgeValue = (position, value) => /* @__PURE__ */ jsx("span", { className: `mw-slider-field__edge-value mw-slider-field__edge-value--${position}`, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: value }) });
3954
4319
  return /* @__PURE__ */ jsxs("div", { className: wrapperClass, "data-label-position": labelPosition, ...props.dataAttributes, children: [
3955
- /* @__PURE__ */ jsx("div", { className: "mw-slider-field__header", children: /* @__PURE__ */ jsx("div", { className: "mw-slider-field__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }) }),
3956
- hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-slider-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
4320
+ /* @__PURE__ */ jsx("div", { className: "mw-slider-field__header", children: /* @__PURE__ */ jsx("div", { className: "mw-slider-field__label", id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }) }),
4321
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-slider-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.description }) }),
3957
4322
  labelPosition === "top" && showEdgeValues ? /* @__PURE__ */ jsxs("div", { className: "mw-slider-field__values-row", children: [
3958
4323
  renderEdgeValue("min", minValueLabel),
3959
4324
  renderEdgeValue("max", maxValueLabel)
@@ -3973,7 +4338,7 @@ function SliderField(props) {
3973
4338
  ) }),
3974
4339
  labelPosition === "inline" && showEdgeValues ? renderEdgeValue("max", maxValueLabel) : null
3975
4340
  ] }),
3976
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-slider-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
4341
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-slider-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
3977
4342
  ] });
3978
4343
  }
3979
4344
  function VolumeSlider(props) {
@@ -4071,10 +4436,10 @@ function Tab(props) {
4071
4436
  }
4072
4437
  );
4073
4438
  }
4074
- function cx16(...parts) {
4439
+ function cx19(...parts) {
4075
4440
  return parts.filter(Boolean).join(" ");
4076
4441
  }
4077
- function hasContent7(value) {
4442
+ function hasContent6(value) {
4078
4443
  if (value === void 0 || value === null || value === false) {
4079
4444
  return false;
4080
4445
  }
@@ -4112,7 +4477,7 @@ function TabPanel(props) {
4112
4477
  id: props.id,
4113
4478
  role: "tabpanel",
4114
4479
  "aria-labelledby": props.tabId,
4115
- className: cx16("mw-tab-group__panel", props.className),
4480
+ className: cx19("mw-tab-group__panel", props.className),
4116
4481
  hidden: props.hidden,
4117
4482
  tabIndex: props.hidden ? void 0 : 0,
4118
4483
  children: renderPanelContent(props.children)
@@ -4122,7 +4487,7 @@ function TabPanel(props) {
4122
4487
  function TabGroup(props) {
4123
4488
  const reactId = React2.useId();
4124
4489
  const id = props.id ?? `mw-tab-group-${reactId}`;
4125
- const hasLabel = hasContent7(props.label);
4490
+ const hasLabel = hasContent6(props.label);
4126
4491
  const itemStates = React2.useMemo(
4127
4492
  () => props.tabs.map((tab) => toItemState(tab)),
4128
4493
  [props.tabs]
@@ -4197,8 +4562,8 @@ function TabGroup(props) {
4197
4562
  },
4198
4563
  [a11yIds.tabIds, itemStates, resolvedActiveTab, selectTab]
4199
4564
  );
4200
- return /* @__PURE__ */ jsxs("section", { className: cx16("mw-tab-group", props.className), ...props.dataAttributes, children: [
4201
- hasLabel && /* @__PURE__ */ jsx("div", { className: "mw-tab-group__header", children: /* @__PURE__ */ jsx(Paragraph, { size: "md", id: a11yIds.labelId ?? `${id}-label`, children: props.label }) }),
4565
+ return /* @__PURE__ */ jsxs("section", { className: cx19("mw-tab-group", props.className), ...props.dataAttributes, children: [
4566
+ hasLabel && /* @__PURE__ */ jsx("div", { className: "mw-tab-group__header", children: /* @__PURE__ */ jsx(Text, { variant: "label", id: a11yIds.labelId ?? `${id}-label`, children: props.label }) }),
4202
4567
  /* @__PURE__ */ jsx(
4203
4568
  "div",
4204
4569
  {
@@ -4253,39 +4618,573 @@ function NavigationTabs(props) {
4253
4618
  ...props.dataAttributes,
4254
4619
  "data-purpose": "navigation-tabs"
4255
4620
  }
4256
- }
4257
- );
4258
- }
4259
- function ContentTabs(props) {
4260
- return /* @__PURE__ */ jsx(
4261
- TabGroup,
4621
+ }
4622
+ );
4623
+ }
4624
+ function ContentTabs(props) {
4625
+ return /* @__PURE__ */ jsx(
4626
+ TabGroup,
4627
+ {
4628
+ ...props,
4629
+ ariaLabel: props.ariaLabel ?? "Content tabs",
4630
+ dataAttributes: {
4631
+ ...props.dataAttributes,
4632
+ "data-purpose": "content-tabs"
4633
+ }
4634
+ }
4635
+ );
4636
+ }
4637
+ function SettingsTabs(props) {
4638
+ return /* @__PURE__ */ jsx(
4639
+ TabGroup,
4640
+ {
4641
+ ...props,
4642
+ ariaLabel: props.ariaLabel ?? "Settings tabs",
4643
+ dataAttributes: {
4644
+ ...props.dataAttributes,
4645
+ "data-purpose": "settings-tabs"
4646
+ }
4647
+ }
4648
+ );
4649
+ }
4650
+ function toItemState2(item) {
4651
+ const state = { value: item.value };
4652
+ if (item.disabled) state.disabled = true;
4653
+ return state;
4654
+ }
4655
+ function SegmentedControl(props) {
4656
+ const {
4657
+ items,
4658
+ value: controlledValue,
4659
+ defaultValue,
4660
+ onValueChange,
4661
+ variant,
4662
+ size,
4663
+ disabled,
4664
+ ariaLabel,
4665
+ ariaLabelledBy,
4666
+ ariaDescribedBy,
4667
+ fullWidth,
4668
+ className,
4669
+ id,
4670
+ style
4671
+ } = props;
4672
+ const itemStates = React2.useMemo(
4673
+ () => items.map(toItemState2),
4674
+ [items]
4675
+ );
4676
+ const isControlled = controlledValue !== void 0;
4677
+ const [internalValue, setInternalValue] = React2.useState(
4678
+ () => resolveSegmentedControlValue(itemStates, defaultValue)
4679
+ );
4680
+ const resolvedValue = React2.useMemo(
4681
+ () => resolveSegmentedControlValue(itemStates, isControlled ? controlledValue : internalValue),
4682
+ [itemStates, isControlled, controlledValue, internalValue]
4683
+ );
4684
+ const selectItem = React2.useCallback(
4685
+ (nextValue) => {
4686
+ const resolved = resolveSegmentedControlValue(itemStates, nextValue);
4687
+ if (!resolved || resolved === resolvedValue) return;
4688
+ if (!isControlled) setInternalValue(resolved);
4689
+ onValueChange?.(resolved);
4690
+ },
4691
+ [itemStates, isControlled, resolvedValue, onValueChange]
4692
+ );
4693
+ const handleKeyDown = React2.useCallback(
4694
+ (event) => {
4695
+ let direction;
4696
+ switch (event.key) {
4697
+ case "ArrowRight":
4698
+ direction = "next";
4699
+ break;
4700
+ case "ArrowLeft":
4701
+ direction = "previous";
4702
+ break;
4703
+ case "Home":
4704
+ direction = "start";
4705
+ break;
4706
+ case "End":
4707
+ direction = "end";
4708
+ break;
4709
+ default:
4710
+ return;
4711
+ }
4712
+ event.preventDefault();
4713
+ const nextValue = moveSegmentedControlSelection(itemStates, resolvedValue, direction);
4714
+ if (nextValue) {
4715
+ selectItem(nextValue);
4716
+ const btn = event.currentTarget.querySelector(
4717
+ `[data-value="${nextValue}"]`
4718
+ );
4719
+ btn?.focus();
4720
+ }
4721
+ },
4722
+ [itemStates, resolvedValue, selectItem]
4723
+ );
4724
+ const trackKit = createSegmentedControlRecipe({
4725
+ value: resolvedValue,
4726
+ variant,
4727
+ size,
4728
+ disabled,
4729
+ ariaLabel,
4730
+ ariaLabelledBy,
4731
+ ariaDescribedBy,
4732
+ fullWidth
4733
+ });
4734
+ const trackClassName = [trackKit.className, className].filter(Boolean).join(" ");
4735
+ return /* @__PURE__ */ jsx(
4736
+ "div",
4737
+ {
4738
+ id,
4739
+ className: trackClassName,
4740
+ role: trackKit.a11y.role,
4741
+ "aria-label": trackKit.a11y.ariaLabel,
4742
+ "aria-labelledby": trackKit.a11y.ariaLabelledBy,
4743
+ "aria-describedby": trackKit.a11y.ariaDescribedBy,
4744
+ "aria-disabled": trackKit.a11y.ariaDisabled,
4745
+ onKeyDown: handleKeyDown,
4746
+ style,
4747
+ children: items.map((item) => {
4748
+ const isSelected = item.value === resolvedValue;
4749
+ const isItemDisabled = disabled || item.disabled;
4750
+ const isIconOnly = item.icon != null && item.label == null;
4751
+ const itemKit = createSegmentedControlItemRecipe({
4752
+ value: item.value,
4753
+ selected: isSelected,
4754
+ disabled: isItemDisabled,
4755
+ ariaLabel: item.ariaLabel,
4756
+ iconOnly: isIconOnly
4757
+ });
4758
+ return /* @__PURE__ */ jsxs(
4759
+ "button",
4760
+ {
4761
+ type: "button",
4762
+ className: itemKit.className,
4763
+ role: itemKit.a11y.role,
4764
+ "aria-checked": itemKit.a11y.ariaChecked,
4765
+ "aria-disabled": itemKit.a11y.ariaDisabled,
4766
+ "aria-label": itemKit.a11y.ariaLabel,
4767
+ tabIndex: itemKit.a11y.tabIndex,
4768
+ disabled: isItemDisabled,
4769
+ "data-value": item.value,
4770
+ onClick: () => selectItem(item.value),
4771
+ children: [
4772
+ item.icon,
4773
+ item.label
4774
+ ]
4775
+ },
4776
+ item.value
4777
+ );
4778
+ })
4779
+ }
4780
+ );
4781
+ }
4782
+ function cx20(...parts) {
4783
+ return parts.filter(Boolean).join(" ");
4784
+ }
4785
+ function hasContent7(value) {
4786
+ if (value === void 0 || value === null || value === false) {
4787
+ return false;
4788
+ }
4789
+ if (typeof value === "string") {
4790
+ return value.trim().length > 0;
4791
+ }
4792
+ return true;
4793
+ }
4794
+ function SegmentedControlField(props) {
4795
+ const reactId = React2.useId();
4796
+ const id = props.id ?? `mw-segmented-control-${reactId}`;
4797
+ const labelId = `${id}-label`;
4798
+ const hasDescription = hasContent7(props.description);
4799
+ const hasError = hasContent7(props.error);
4800
+ const {
4801
+ helperTextId: descriptionId,
4802
+ errorId,
4803
+ describedBy: mergedDescribedBy
4804
+ } = buildInputFieldA11yIds({
4805
+ id,
4806
+ hasHelperText: hasDescription,
4807
+ hasError,
4808
+ externalDescribedBy: props.ariaDescribedBy
4809
+ });
4810
+ const wrapperClass = cx20(
4811
+ "mw-segmented-control-field",
4812
+ hasError && "mw-segmented-control-field--invalid",
4813
+ props.className
4814
+ );
4815
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
4816
+ /* @__PURE__ */ jsx("span", { className: "mw-segmented-control-field__label", id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
4817
+ hasDescription && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-segmented-control-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.description }) }),
4818
+ /* @__PURE__ */ jsx(
4819
+ SegmentedControl,
4820
+ {
4821
+ ...props.segmentedControl,
4822
+ ariaLabelledBy: labelId,
4823
+ ...mergedDescribedBy ? { ariaDescribedBy: mergedDescribedBy } : {}
4824
+ }
4825
+ ),
4826
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-segmented-control-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
4827
+ ] });
4828
+ }
4829
+ function Pagination(props) {
4830
+ const {
4831
+ pageCount,
4832
+ page: controlledPage,
4833
+ defaultPage,
4834
+ onPageChange,
4835
+ siblingCount,
4836
+ boundaryCount,
4837
+ maxVisibleItems,
4838
+ controlDisplay = "auto",
4839
+ adaptive = true,
4840
+ showPrevNext,
4841
+ showFirstLast,
4842
+ disabled,
4843
+ firstLabel = "First",
4844
+ previousLabel = "Previous",
4845
+ nextLabel = "Next",
4846
+ lastLabel = "Last",
4847
+ ariaLabel,
4848
+ ariaLabelledBy,
4849
+ ariaDescribedBy,
4850
+ getItemAriaLabel,
4851
+ className,
4852
+ id,
4853
+ style,
4854
+ ...rest
4855
+ } = props;
4856
+ const isControlled = controlledPage !== void 0;
4857
+ const rootRef = React2.useRef(null);
4858
+ const adaptiveProfile = useAdaptivePaginationProfile(rootRef, {
4859
+ adaptive,
4860
+ pageCount,
4861
+ ...siblingCount !== void 0 ? { siblingCount } : {},
4862
+ ...boundaryCount !== void 0 ? { boundaryCount } : {},
4863
+ ...maxVisibleItems !== void 0 ? { maxVisibleItems } : {},
4864
+ controlDisplay
4865
+ });
4866
+ const [internalPage, setInternalPage] = React2.useState(
4867
+ () => clampPaginationPage(defaultPage, pageCount)
4868
+ );
4869
+ const resolvedPage = clampPaginationPage(isControlled ? controlledPage : internalPage, pageCount);
4870
+ const resolvedControlDisplay = adaptive && adaptiveProfile ? adaptiveProfile.controlDisplay : controlDisplay === "icon" ? "icon" : "label";
4871
+ const resolvedMaxVisibleItems = adaptive && adaptiveProfile ? adaptiveProfile.maxVisibleItems : maxVisibleItems;
4872
+ const rootKit = createPaginationRecipe({
4873
+ page: resolvedPage,
4874
+ pageCount,
4875
+ ...siblingCount !== void 0 ? { siblingCount } : {},
4876
+ ...boundaryCount !== void 0 ? { boundaryCount } : {},
4877
+ ...resolvedMaxVisibleItems !== void 0 ? { maxVisibleItems: resolvedMaxVisibleItems } : {},
4878
+ controlDisplay: resolvedControlDisplay,
4879
+ ...showPrevNext !== void 0 ? { showPrevNext } : {},
4880
+ ...showFirstLast !== void 0 ? { showFirstLast } : {},
4881
+ ...disabled !== void 0 ? { disabled } : {},
4882
+ ...ariaLabel !== void 0 ? { ariaLabel } : {},
4883
+ ...ariaLabelledBy !== void 0 ? { ariaLabelledBy } : {},
4884
+ ...ariaDescribedBy !== void 0 ? { ariaDescribedBy } : {},
4885
+ firstLabel,
4886
+ previousLabel,
4887
+ nextLabel,
4888
+ lastLabel,
4889
+ ...getItemAriaLabel !== void 0 ? { getItemAriaLabel } : {}
4890
+ });
4891
+ const listKit = createPaginationListRecipe();
4892
+ const listItemKit = createPaginationListItemRecipe();
4893
+ const rootClassName = [rootKit.className, className].filter(Boolean).join(" ");
4894
+ const selectPage = React2.useCallback(
4895
+ (nextPage) => {
4896
+ if (disabled) return;
4897
+ const resolved = clampPaginationPage(nextPage, pageCount);
4898
+ if (resolved === 0 || resolved === resolvedPage) return;
4899
+ if (!isControlled) setInternalPage(resolved);
4900
+ onPageChange?.(resolved);
4901
+ },
4902
+ [disabled, isControlled, onPageChange, pageCount, resolvedPage]
4903
+ );
4904
+ const previousDisabled = disabled || resolvedPage <= 1;
4905
+ const nextDisabled = disabled || resolvedPage <= 0 || resolvedPage >= pageCount;
4906
+ const firstDisabled = disabled || resolvedPage <= 1;
4907
+ const lastDisabled = disabled || resolvedPage <= 0 || resolvedPage >= pageCount;
4908
+ const firstKit = createPaginationControlRecipe({
4909
+ direction: "first",
4910
+ disabled: firstDisabled,
4911
+ label: firstLabel,
4912
+ ...getItemAriaLabel !== void 0 ? {
4913
+ ariaLabel: resolvePaginationItemAriaLabel(getItemAriaLabel, {
4914
+ type: "first",
4915
+ page: 1,
4916
+ selected: false
4917
+ })
4918
+ } : {}
4919
+ });
4920
+ const previousKit = createPaginationControlRecipe({
4921
+ direction: "previous",
4922
+ disabled: previousDisabled,
4923
+ label: previousLabel,
4924
+ ...getItemAriaLabel !== void 0 ? {
4925
+ ariaLabel: resolvePaginationItemAriaLabel(getItemAriaLabel, {
4926
+ type: "previous",
4927
+ page: resolvedPage - 1,
4928
+ selected: false
4929
+ })
4930
+ } : {}
4931
+ });
4932
+ const nextKit = createPaginationControlRecipe({
4933
+ direction: "next",
4934
+ disabled: nextDisabled,
4935
+ label: nextLabel,
4936
+ ...getItemAriaLabel !== void 0 ? {
4937
+ ariaLabel: resolvePaginationItemAriaLabel(getItemAriaLabel, {
4938
+ type: "next",
4939
+ page: resolvedPage + 1,
4940
+ selected: false
4941
+ })
4942
+ } : {}
4943
+ });
4944
+ const lastKit = createPaginationControlRecipe({
4945
+ direction: "last",
4946
+ disabled: lastDisabled,
4947
+ label: lastLabel,
4948
+ ...getItemAriaLabel !== void 0 ? {
4949
+ ariaLabel: resolvePaginationItemAriaLabel(getItemAriaLabel, {
4950
+ type: "last",
4951
+ page: pageCount,
4952
+ selected: false
4953
+ })
4954
+ } : {}
4955
+ });
4956
+ const renderControl = (direction, kit, controlDisabled, targetPage, label, iconName) => {
4957
+ const isLeadingIcon = direction === "first" || direction === "previous";
4958
+ const icon = /* @__PURE__ */ jsx("span", { className: "mw-pagination__control-icon", children: /* @__PURE__ */ jsx(Icon, { name: iconName, decorative: true, size: 12 }) });
4959
+ return /* @__PURE__ */ jsxs(
4960
+ "button",
4961
+ {
4962
+ type: "button",
4963
+ className: kit.className,
4964
+ "aria-label": kit.a11y.ariaLabel,
4965
+ "aria-disabled": kit.a11y.ariaDisabled,
4966
+ disabled: controlDisabled,
4967
+ onClick: () => selectPage(targetPage),
4968
+ children: [
4969
+ isLeadingIcon && icon,
4970
+ /* @__PURE__ */ jsx("span", { className: "mw-pagination__control-label", children: label }),
4971
+ !isLeadingIcon && icon
4972
+ ]
4973
+ }
4974
+ );
4975
+ };
4976
+ return /* @__PURE__ */ jsxs(
4977
+ "nav",
4262
4978
  {
4263
- ...props,
4264
- ariaLabel: props.ariaLabel ?? "Content tabs",
4265
- dataAttributes: {
4266
- ...props.dataAttributes,
4267
- "data-purpose": "content-tabs"
4268
- }
4979
+ ...rest,
4980
+ ref: rootRef,
4981
+ id,
4982
+ className: rootClassName,
4983
+ style: { ...rootKit.vars, ...style },
4984
+ "aria-label": rootKit.a11y.ariaLabel,
4985
+ "aria-labelledby": rootKit.a11y.ariaLabelledBy,
4986
+ "aria-describedby": rootKit.a11y.ariaDescribedBy,
4987
+ "data-component": "pagination",
4988
+ "data-control-display": rootKit.controlDisplay,
4989
+ children: [
4990
+ rootKit.showFirstLast && renderControl("first", firstKit, firstDisabled, 1, firstLabel, IconName.ChevronsLeft),
4991
+ rootKit.showPrevNext && renderControl(
4992
+ "previous",
4993
+ previousKit,
4994
+ previousDisabled,
4995
+ resolvedPage - 1,
4996
+ previousLabel,
4997
+ IconName.ChevronLeft
4998
+ ),
4999
+ /* @__PURE__ */ jsx("ul", { className: listKit.className, role: listKit.a11y.role, children: rootKit.items.map((item) => {
5000
+ if (item.type !== "page") {
5001
+ const ellipsisKit = createPaginationEllipsisRecipe();
5002
+ return /* @__PURE__ */ jsx("li", { className: listItemKit.className, children: /* @__PURE__ */ jsx("span", { className: ellipsisKit.className, "aria-hidden": ellipsisKit.a11y.ariaHidden, children: "..." }) }, item.key);
5003
+ }
5004
+ const pageKit = createPaginationPageRecipe({
5005
+ page: item.page,
5006
+ selected: item.selected,
5007
+ ...disabled !== void 0 ? { disabled } : {},
5008
+ ...getItemAriaLabel !== void 0 ? {
5009
+ ariaLabel: resolvePaginationItemAriaLabel(getItemAriaLabel, {
5010
+ type: "page",
5011
+ page: item.page,
5012
+ selected: item.selected
5013
+ })
5014
+ } : {}
5015
+ });
5016
+ return /* @__PURE__ */ jsx("li", { className: listItemKit.className, children: /* @__PURE__ */ jsx(
5017
+ "button",
5018
+ {
5019
+ type: "button",
5020
+ className: pageKit.className,
5021
+ "aria-label": pageKit.a11y.ariaLabel,
5022
+ "aria-current": pageKit.a11y.ariaCurrent,
5023
+ "aria-disabled": pageKit.a11y.ariaDisabled,
5024
+ disabled,
5025
+ onClick: () => selectPage(item.page),
5026
+ children: item.page
5027
+ }
5028
+ ) }, item.key);
5029
+ }) }),
5030
+ rootKit.showPrevNext && renderControl(
5031
+ "next",
5032
+ nextKit,
5033
+ nextDisabled,
5034
+ resolvedPage + 1,
5035
+ nextLabel,
5036
+ IconName.ChevronRight
5037
+ ),
5038
+ rootKit.showFirstLast && renderControl("last", lastKit, lastDisabled, pageCount, lastLabel, IconName.ChevronsRight)
5039
+ ]
4269
5040
  }
4270
5041
  );
4271
5042
  }
4272
- function SettingsTabs(props) {
4273
- return /* @__PURE__ */ jsx(
4274
- TabGroup,
4275
- {
4276
- ...props,
4277
- ariaLabel: props.ariaLabel ?? "Settings tabs",
4278
- dataAttributes: {
4279
- ...props.dataAttributes,
4280
- "data-purpose": "settings-tabs"
4281
- }
5043
+ function parsePxValue(value, fallback) {
5044
+ const parsed = Number.parseFloat(value);
5045
+ return Number.isFinite(parsed) ? parsed : fallback;
5046
+ }
5047
+ function resolveControlWidths(controls, itemSize) {
5048
+ const labelControlWidth = controls.reduce((total, control) => {
5049
+ const icon = control.querySelector(".mw-pagination__control-icon");
5050
+ const label = control.querySelector(".mw-pagination__control-label");
5051
+ const iconWidth = icon?.getBoundingClientRect().width ?? 0;
5052
+ const labelWidth = label?.scrollWidth ?? label?.getBoundingClientRect().width ?? 0;
5053
+ const labelGap = iconWidth > 0 && labelWidth > 0 ? 4 : 0;
5054
+ const measuredLabelWidth = iconWidth + labelGap + labelWidth;
5055
+ return total + Math.max(control.getBoundingClientRect().width, measuredLabelWidth);
5056
+ }, 0);
5057
+ return {
5058
+ labelControlWidth,
5059
+ iconControlWidth: controls.length * itemSize
5060
+ };
5061
+ }
5062
+ function useAdaptivePaginationProfile(rootRef, opts) {
5063
+ const [profile, setProfile] = React2.useState(void 0);
5064
+ React2.useLayoutEffect(() => {
5065
+ const root = rootRef.current;
5066
+ if (!opts.adaptive || !root || typeof window === "undefined") {
5067
+ setProfile(void 0);
5068
+ return;
4282
5069
  }
5070
+ const parent = root.parentElement;
5071
+ if (!parent) return;
5072
+ let frame = 0;
5073
+ const measure = () => {
5074
+ window.cancelAnimationFrame(frame);
5075
+ frame = window.requestAnimationFrame(() => {
5076
+ const rootStyles = window.getComputedStyle(root);
5077
+ const parentStyles = window.getComputedStyle(parent);
5078
+ const itemSize = parsePxValue(rootStyles.getPropertyValue("--mw-pagination-size"), 32);
5079
+ const itemGap = parsePxValue(rootStyles.getPropertyValue("--mw-pagination-gap"), 2);
5080
+ const sectionGap = parsePxValue(
5081
+ rootStyles.getPropertyValue("--mw-pagination-section-gap"),
5082
+ 12
5083
+ );
5084
+ const parentWidth = parent.getBoundingClientRect().width - parsePxValue(parentStyles.paddingLeft, 0) - parsePxValue(parentStyles.paddingRight, 0);
5085
+ if (parentWidth <= 0) {
5086
+ setProfile(void 0);
5087
+ return;
5088
+ }
5089
+ const controls = Array.from(root.querySelectorAll(".mw-pagination__control"));
5090
+ const { labelControlWidth, iconControlWidth } = resolveControlWidths(controls, itemSize);
5091
+ const nextProfile = resolvePaginationAdaptiveProfile({
5092
+ containerWidth: parentWidth,
5093
+ labelControlWidth,
5094
+ iconControlWidth,
5095
+ controlCount: controls.length,
5096
+ itemSize,
5097
+ itemGap,
5098
+ sectionGap,
5099
+ pageCount: opts.pageCount,
5100
+ ...opts.siblingCount !== void 0 ? { siblingCount: opts.siblingCount } : {},
5101
+ ...opts.boundaryCount !== void 0 ? { boundaryCount: opts.boundaryCount } : {},
5102
+ ...opts.maxVisibleItems !== void 0 ? { maxVisibleItems: opts.maxVisibleItems } : {},
5103
+ controlDisplay: opts.controlDisplay
5104
+ });
5105
+ setProfile(
5106
+ (previous) => previous?.controlDisplay === nextProfile.controlDisplay && previous?.maxVisibleItems === nextProfile.maxVisibleItems && previous?.reservedItemCount === nextProfile.reservedItemCount ? previous : nextProfile
5107
+ );
5108
+ });
5109
+ };
5110
+ measure();
5111
+ const Observer = window.ResizeObserver;
5112
+ const resizeObserver = Observer ? new Observer(measure) : void 0;
5113
+ resizeObserver?.observe(parent);
5114
+ resizeObserver?.observe(root);
5115
+ window.addEventListener("resize", measure);
5116
+ return () => {
5117
+ window.cancelAnimationFrame(frame);
5118
+ resizeObserver?.disconnect();
5119
+ window.removeEventListener("resize", measure);
5120
+ };
5121
+ }, [
5122
+ opts.adaptive,
5123
+ opts.boundaryCount,
5124
+ opts.controlDisplay,
5125
+ opts.maxVisibleItems,
5126
+ opts.pageCount,
5127
+ opts.siblingCount,
5128
+ rootRef
5129
+ ]);
5130
+ return profile;
5131
+ }
5132
+ function cx21(...parts) {
5133
+ return parts.filter(Boolean).join(" ");
5134
+ }
5135
+ function hasContent8(value) {
5136
+ if (value === void 0 || value === null || value === false) {
5137
+ return false;
5138
+ }
5139
+ if (typeof value === "string") {
5140
+ return value.trim().length > 0;
5141
+ }
5142
+ return true;
5143
+ }
5144
+ function PaginationField(props) {
5145
+ const reactId = React2.useId();
5146
+ const id = props.id ?? `mw-pagination-${reactId}`;
5147
+ const labelId = `${id}-label`;
5148
+ const hasDescription = hasContent8(props.description);
5149
+ const hasError = hasContent8(props.error);
5150
+ const {
5151
+ helperTextId: descriptionId,
5152
+ errorId,
5153
+ describedBy: mergedDescribedBy
5154
+ } = buildInputFieldA11yIds({
5155
+ id,
5156
+ hasHelperText: hasDescription,
5157
+ hasError,
5158
+ externalDescribedBy: props.ariaDescribedBy
5159
+ });
5160
+ const wrapperClass = cx21(
5161
+ "mw-pagination-field",
5162
+ hasError && "mw-pagination-field--invalid",
5163
+ props.className
4283
5164
  );
5165
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
5166
+ /* @__PURE__ */ jsx("span", { className: "mw-pagination-field__label", id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
5167
+ hasDescription && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-pagination-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.description }) }),
5168
+ /* @__PURE__ */ jsx(
5169
+ Pagination,
5170
+ {
5171
+ ...props.pagination,
5172
+ ariaLabelledBy: labelId,
5173
+ ...mergedDescribedBy ? { ariaDescribedBy: mergedDescribedBy } : {}
5174
+ }
5175
+ ),
5176
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-pagination-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
5177
+ ] });
4284
5178
  }
4285
- function cx17(...parts) {
5179
+ function SkipLink(props) {
5180
+ const { href, children, className } = props;
5181
+ const kit = createSkipLinkRecipe({ href, className });
5182
+ return /* @__PURE__ */ jsx("a", { href, className: kit.className, children });
5183
+ }
5184
+ function cx22(...parts) {
4286
5185
  return parts.filter(Boolean).join(" ");
4287
5186
  }
4288
- function hasContent8(value) {
5187
+ function hasContent9(value) {
4289
5188
  if (value === void 0 || value === null || value === false) {
4290
5189
  return false;
4291
5190
  }
@@ -4299,9 +5198,9 @@ function Dialog(props) {
4299
5198
  const id = props.id ?? `mw-dialog-${reactId}`;
4300
5199
  const titleId = `${id}-title`;
4301
5200
  const descriptionId = `${id}-description`;
4302
- const hasTitle = hasContent8(props.title);
4303
- const hasDescription = hasContent8(props.description);
4304
- const hasFooter = hasContent8(props.footer) && (props.showFooter ?? true);
5201
+ const hasTitle = hasContent9(props.title);
5202
+ const hasDescription = hasContent9(props.description);
5203
+ const hasFooter = hasContent9(props.footer) && (props.showFooter ?? true);
4305
5204
  const dismissible = (props.dismissible ?? true) && props.onClose !== void 0;
4306
5205
  const dialogOptions = {
4307
5206
  showFooter: hasFooter,
@@ -4332,7 +5231,7 @@ function Dialog(props) {
4332
5231
  "section",
4333
5232
  {
4334
5233
  id,
4335
- className: cx17(kit.className, props.className),
5234
+ className: cx22(kit.className, props.className),
4336
5235
  role: kit.a11y.role,
4337
5236
  ...kit.a11y.ariaModal ? { "aria-modal": "true" } : {},
4338
5237
  ...kit.a11y.ariaLabel ? { "aria-label": kit.a11y.ariaLabel } : {},
@@ -4369,7 +5268,7 @@ function Dialog(props) {
4369
5268
  }
4370
5269
  );
4371
5270
  }
4372
- function cx18(...parts) {
5271
+ function cx23(...parts) {
4373
5272
  return parts.filter(Boolean).join(" ");
4374
5273
  }
4375
5274
  function getFocusableElements(container) {
@@ -4400,6 +5299,9 @@ function focusFirstElement(container) {
4400
5299
  }
4401
5300
  container?.focus();
4402
5301
  }
5302
+ function toCSSDimension(value) {
5303
+ return typeof value === "number" ? `${value}px` : value;
5304
+ }
4403
5305
  function DialogModal(props) {
4404
5306
  const {
4405
5307
  open,
@@ -4410,12 +5312,16 @@ function DialogModal(props) {
4410
5312
  restoreFocus = true,
4411
5313
  portalTarget,
4412
5314
  overlayClassName,
5315
+ surfaceWidth,
5316
+ tone = "default",
5317
+ divider = "visible",
4413
5318
  footer,
4414
5319
  ...dialogProps
4415
5320
  } = props;
4416
5321
  const isControlled = open !== void 0;
4417
5322
  const [internalOpen, setInternalOpen] = React2.useState(defaultOpen);
4418
5323
  const resolvedOpen = isControlled ? open : internalOpen;
5324
+ const marwesContext = React2.useContext(MarwesContext);
4419
5325
  const overlayRef = React2.useRef(null);
4420
5326
  const surfaceRef = React2.useRef(null);
4421
5327
  const lastFocusedElementRef = React2.useRef(null);
@@ -4500,11 +5406,16 @@ function DialogModal(props) {
4500
5406
  if (!resolvedOpen || typeof document === "undefined") {
4501
5407
  return null;
4502
5408
  }
5409
+ const modalStyle = surfaceWidth === void 0 ? void 0 : { "--mw-dialog-surface-width": toCSSDimension(surfaceWidth) };
4503
5410
  const modalMarkup = /* @__PURE__ */ jsxs(
4504
5411
  "div",
4505
5412
  {
4506
5413
  ref: overlayRef,
4507
- className: cx18("mw-dialog-modal", overlayClassName),
5414
+ className: cx23("mw-dialog-modal", overlayClassName),
5415
+ style: modalStyle,
5416
+ "data-surface-width": surfaceWidth === void 0 ? void 0 : "custom",
5417
+ "data-tone": tone,
5418
+ "data-divider": divider,
4508
5419
  onClick: (event) => {
4509
5420
  if (!closeOnScrimClick) {
4510
5421
  return;
@@ -4528,7 +5439,8 @@ function DialogModal(props) {
4528
5439
  if (portalTarget === null) {
4529
5440
  return modalMarkup;
4530
5441
  }
4531
- return createPortal(modalMarkup, portalTarget ?? document.body);
5442
+ const resolvedTarget = portalTarget ?? marwesContext?.providerElement ?? document.body;
5443
+ return createPortal(modalMarkup, resolvedTarget);
4532
5444
  }
4533
5445
  function ConfirmDialog(props) {
4534
5446
  const {
@@ -4637,7 +5549,222 @@ function InfoDialog(props) {
4637
5549
  }
4638
5550
  );
4639
5551
  }
5552
+ function Checkbox(props) {
5553
+ const { onCheckedChange, onChange, ...coreProps } = props;
5554
+ const kit = checkboxRecipe({ ...coreProps });
5555
+ const inputRef = React2.useRef(null);
5556
+ React2.useLayoutEffect(() => {
5557
+ const el = inputRef.current;
5558
+ if (!el) return;
5559
+ el.indeterminate = kit.indeterminate;
5560
+ }, [kit.indeterminate]);
5561
+ const handleChange = (e) => {
5562
+ onChange?.(e);
5563
+ onCheckedChange?.(e.currentTarget.checked);
5564
+ };
5565
+ const { a11y } = kit;
5566
+ return /* @__PURE__ */ jsx(
5567
+ "input",
5568
+ {
5569
+ ref: inputRef,
5570
+ type: "checkbox",
5571
+ className: kit.className,
5572
+ style: kit.vars,
5573
+ id: a11y.id,
5574
+ name: a11y.name,
5575
+ value: a11y.value,
5576
+ disabled: a11y.disabled === true,
5577
+ required: a11y.required === true,
5578
+ "aria-label": a11y.ariaLabel,
5579
+ "aria-labelledby": a11y.ariaLabelledBy,
5580
+ "aria-describedby": a11y.ariaDescribedBy,
5581
+ "aria-checked": a11y.ariaChecked,
5582
+ "aria-invalid": a11y.ariaInvalid === true ? true : void 0,
5583
+ checked: kit.checked,
5584
+ defaultChecked: kit.defaultChecked,
5585
+ onChange: handleChange
5586
+ }
5587
+ );
5588
+ }
5589
+ function cx24(...parts) {
5590
+ return parts.filter(Boolean).join(" ");
5591
+ }
5592
+ function hasContent10(value) {
5593
+ if (value === void 0 || value === null || value === false) {
5594
+ return false;
5595
+ }
5596
+ if (typeof value === "string") {
5597
+ return value.trim().length > 0;
5598
+ }
5599
+ return true;
5600
+ }
5601
+ function CheckboxField(props) {
5602
+ const reactId = React2.useId();
5603
+ const id = props.id ?? `mw-checkbox-${reactId}`;
5604
+ const hasDescription = hasContent10(props.description);
5605
+ const hasError = hasContent10(props.error);
5606
+ const {
5607
+ descriptionId: descId,
5608
+ errorId,
5609
+ describedBy: mergedDescribedBy
5610
+ } = buildCheckboxFieldA11yIds({
5611
+ id,
5612
+ hasDescription,
5613
+ hasError,
5614
+ externalDescribedBy: props.ariaDescribedBy
5615
+ });
5616
+ const disabled = props.checkbox.disabled || false;
5617
+ const invalid = hasError || props.checkbox.invalid || false;
5618
+ const wrapperClass = cx24(
5619
+ "mw-checkbox-field",
5620
+ disabled && "mw-checkbox-field--disabled",
5621
+ invalid && "mw-checkbox-field--invalid"
5622
+ );
5623
+ const checkboxProps = {
5624
+ ...props.checkbox,
5625
+ id,
5626
+ invalid
5627
+ };
5628
+ if (mergedDescribedBy) {
5629
+ checkboxProps.ariaDescribedBy = mergedDescribedBy;
5630
+ }
5631
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
5632
+ /* @__PURE__ */ jsxs("div", { className: "mw-checkbox-field__row", children: [
5633
+ /* @__PURE__ */ jsx(Checkbox, { ...checkboxProps }),
5634
+ /* @__PURE__ */ jsx("label", { className: "mw-checkbox-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) })
5635
+ ] }),
5636
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-field__description", id: descId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.description }) }),
5637
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
5638
+ ] });
5639
+ }
5640
+ function hasContent11(value) {
5641
+ if (value === void 0 || value === null || value === false) return false;
5642
+ if (typeof value === "string") return value.trim().length > 0;
5643
+ return true;
5644
+ }
5645
+ function cx25(...parts) {
5646
+ return parts.filter(Boolean).join(" ");
5647
+ }
5648
+ function orderSelectedValues(values, options) {
5649
+ const optionValues = new Set(options.map((option) => option.value));
5650
+ const selectedValues = new Set(values);
5651
+ const knownValues = options.map((option) => option.value).filter((value) => selectedValues.has(value));
5652
+ const unknownValues = values.filter((value) => !optionValues.has(value));
5653
+ return [...knownValues, ...unknownValues];
5654
+ }
5655
+ function CheckboxGroupField(props) {
5656
+ const reactId = React2.useId();
5657
+ const id = props.id ?? `mw-checkbox-group-${reactId}`;
5658
+ const hasDescription = hasContent11(props.description);
5659
+ const hasError = hasContent11(props.error);
5660
+ const isInvalid = hasError;
5661
+ const { labelId, descriptionId, errorId, describedBy } = buildCheckboxGroupFieldA11yIds({
5662
+ id,
5663
+ hasDescription,
5664
+ hasError,
5665
+ externalDescribedBy: props.ariaDescribedBy
5666
+ });
5667
+ const isControlled = props.value !== void 0;
5668
+ const [internalValue, setInternalValue] = React2.useState(
5669
+ orderSelectedValues(props.defaultValue ?? [], props.options)
5670
+ );
5671
+ const selectedValues = orderSelectedValues(
5672
+ isControlled ? props.value ?? [] : internalValue,
5673
+ props.options
5674
+ );
5675
+ const selectedValueSet = new Set(selectedValues);
5676
+ const handleToggle = (nextValue) => {
5677
+ const rawNextValue = selectedValueSet.has(nextValue) ? selectedValues.filter((value) => value !== nextValue) : [...selectedValues, nextValue];
5678
+ const orderedNextValue = orderSelectedValues(rawNextValue, props.options);
5679
+ if (!isControlled) {
5680
+ setInternalValue(orderedNextValue);
5681
+ }
5682
+ props.onChange?.(orderedNextValue);
5683
+ };
5684
+ const wrapperClass = cx25(
5685
+ "mw-checkbox-group-field",
5686
+ props.disabled && "mw-checkbox-group-field--disabled",
5687
+ isInvalid && "mw-checkbox-group-field--invalid"
5688
+ );
5689
+ return /* @__PURE__ */ jsxs(
5690
+ "fieldset",
5691
+ {
5692
+ className: wrapperClass,
5693
+ "aria-labelledby": labelId,
5694
+ "aria-describedby": describedBy,
5695
+ "aria-invalid": isInvalid ? true : void 0,
5696
+ "aria-required": props.required ? true : void 0,
5697
+ disabled: props.disabled ? true : void 0,
5698
+ ...props.dataAttributes,
5699
+ children: [
5700
+ /* @__PURE__ */ jsx("legend", { className: "mw-checkbox-group-field__label", id: labelId, children: /* @__PURE__ */ jsx(Text, { variant: "label", children: props.label }) }),
5701
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-group-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.description }) }),
5702
+ /* @__PURE__ */ jsx("div", { className: "mw-checkbox-group-field__options", children: props.options.map((option, index) => {
5703
+ const optionId = `${id}-option-${index}`;
5704
+ const optionLabelId = `${optionId}-label`;
5705
+ const optionDescriptionId = `${optionId}-description`;
5706
+ const hasOptionDescription = hasContent11(option.description);
5707
+ const isOptionDisabled = props.disabled || option.disabled || false;
5708
+ const checkboxProps = {
5709
+ ...props.checkbox ?? {},
5710
+ id: optionId,
5711
+ value: option.value,
5712
+ ariaLabelledBy: optionLabelId,
5713
+ checked: selectedValueSet.has(option.value),
5714
+ disabled: isOptionDisabled,
5715
+ invalid: isInvalid,
5716
+ onCheckedChange: () => handleToggle(option.value)
5717
+ };
5718
+ if (hasOptionDescription) {
5719
+ checkboxProps.ariaDescribedBy = optionDescriptionId;
5720
+ }
5721
+ if (props.name !== void 0) {
5722
+ checkboxProps.name = props.name;
5723
+ }
5724
+ if (option.indeterminate !== void 0) {
5725
+ checkboxProps.indeterminate = option.indeterminate;
5726
+ }
5727
+ return /* @__PURE__ */ jsxs(
5728
+ "label",
5729
+ {
5730
+ className: cx25(
5731
+ "mw-checkbox-group-field__option",
5732
+ hasOptionDescription && "mw-checkbox-group-field__option--with-description"
5733
+ ),
5734
+ htmlFor: optionId,
5735
+ children: [
5736
+ /* @__PURE__ */ jsx(Checkbox, { ...checkboxProps }),
5737
+ /* @__PURE__ */ jsxs("span", { className: "mw-checkbox-group-field__option-content", children: [
5738
+ /* @__PURE__ */ jsx(
5739
+ Text,
5740
+ {
5741
+ id: optionLabelId,
5742
+ variant: "label",
5743
+ className: "mw-checkbox-group-field__option-label",
5744
+ children: option.label
5745
+ }
5746
+ ),
5747
+ hasOptionDescription && /* @__PURE__ */ jsx(
5748
+ Text,
5749
+ {
5750
+ id: optionDescriptionId,
5751
+ variant: "caption",
5752
+ className: "mw-checkbox-group-field__option-description",
5753
+ children: option.description
5754
+ }
5755
+ )
5756
+ ] })
5757
+ ]
5758
+ },
5759
+ option.value
5760
+ );
5761
+ }) }),
5762
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-group-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Text, { variant: "caption", children: props.error }) })
5763
+ ]
5764
+ }
5765
+ );
5766
+ }
4640
5767
 
4641
- export { Accordion, AccordionField, Avatar, AvatarBadge, AvatarGroup, Badge, BadgeGroup, BrightnessSlider, Button, ButtonSpinner, CancelButton, Card, Checkbox, CheckboxField, CheckboxGroupField, CloseButton, ConfirmButton, ConfirmDialog, ContentTabs, CopyButton, CreateButton, CurrencyField, DateOfBirthField, DatePicker, DestructiveButton, DestructiveDialog, Dialog, DialogModal, Divider, DownloadButton, DropdownButton, DropdownField, EditButton, EmailField, EmptyStateSpinner, ErrorToast, FAQAccordion, FeatureToggle, FilterButton, H1, H2, H3, Icon, InfoDialog, InfoToast, Input, InputField, InputOtp, LinkButton, MarwesProvider, NavigationTabs, NotificationBadge, OptionRadioGroup, Paragraph, PasswordField, PermissionSwitch, PhoneField, PreferenceSwitch, PresenceAvatar, PrimaryButton, PriorityBadge, ProductCard, ProfileAvatar, ProfileCard, Radio, RadioGroupField, RadiusSlider, RatingRadioGroup, RefreshButton, RichText, RichTextField, SaveButton, SearchButton, SearchField, SecondaryButton, SectionsAccordion, Select, SelectField, SettingsAccordion, SettingsTabs, Skeleton, Slider, SliderField, SortButton, Spacer, Spacing, Spinner, StatCard, StatTile, StatusBadge, SubmitButton, SuccessButton, SuccessToast, Switch, SwitchField, Tab, TabGroup, TabPanel, TeamAvatarGroup, TextButton, Textarea, TextareaField, Toast, ToastContainer, ToastProvider, Tooltip, TooltipGroup, URLField, UploadButton, VerifyButton, VolumeSlider, WarningToast, YesNoRadioGroup, ZipCodeField, useTheme, useThemeMode, useToast };
5768
+ export { AccordionField, Avatar, AvatarBadge, AvatarGroup, Badge, BadgeGroup, Banner, Breadcrumb, BrightnessSlider, Button, ButtonSpinner, CancelButton, Card, CheckboxField, CheckboxGroupField, CloseButton, ConfirmButton, ConfirmDialog, ContentTabs, ContextMenu, CopyButton, CreateButton, CurrencyField, DateOfBirthField, DatePickerField, DestructiveButton, DestructiveDialog, Dialog, DialogModal, Divider, DownloadButton, Drawer, DropdownButton, DropdownField, EditButton, EmailField, EmptyStateSpinner, ErrorBanner, ErrorToast, FAQAccordion, FeatureToggle, FilterButton, H1, H2, H3, Icon, IconButton, InfoBanner, InfoDialog, InfoToast, InputField, InputOtpField, LinkButton, MarwesProvider, NavigationTabs, NotificationBadge, OptionRadioGroup, PaginationField, Paragraph, PasswordField, PermissionSwitch, PhoneField, PreferenceSwitch, PresenceAvatar, PrimaryButton, PriorityBadge, ProductCard, ProfileAvatar, ProfileCard, ProgressBar, RadioGroupField, RadiusSlider, RatingRadioGroup, RefreshButton, RichTextField, SaveButton, SearchButton, SearchField, SecondaryButton, SectionsAccordion, SegmentedControlField, SelectField, SettingsAccordion, SettingsTabs, Skeleton, SkipLink, SliderField, SortButton, Spacer, Spacing, Spinner, StatCard, StatTile, StatusBadge, SubmitButton, SuccessBanner, SuccessButton, SuccessToast, SwitchField, Tab, TabGroup, TabPanel, TeamAvatarGroup, Text, TextButton, TextareaField, Toast, ToastContainer, ToastProvider, Tooltip, TooltipGroup, TypographyText, URLField, UploadButton, VerifyButton, VolumeSlider, WarningBanner, WarningToast, YesNoRadioGroup, ZipCodeField, useTheme, useThemeMode, useToast };
4642
5769
  //# sourceMappingURL=index.js.map
4643
5770
  //# sourceMappingURL=index.js.map