@marwes-ui/react 0.0.3 → 1.0.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,59 +1,104 @@
1
- import { createDividerRecipe, createSystem, switchMode, resolveIconSize, resolveIconStrokeWidth, iconRegistry, createButtonRecipe, createInputRecipe, checkboxRecipe, headingRecipe, paragraphRecipe } from '@marwes-ui/core';
2
- import { firstEdition } from '@marwes-ui/presets';
3
- import * as React2 from 'react';
1
+ import '@marwes-ui/presets/firstEdition/styles.css';
2
+ import { createRichTextRecipe, resolveRichTextAllowedFormats, normalizeRichTextHtml, isRichTextHtmlEmpty, createDividerRecipe, createSpacingRecipe, createSliderRecipe, richTextCommandByFormat, resolveIconSize, resolveIconStrokeWidth, iconRegistry, resolveIconA11y, resolveThemeInput, createSpinnerRecipe, createButtonRecipe, ButtonAction, ButtonVariant, IconName, createInputRecipe, createSelectRecipe, resolveSelectMode, createTextareaRecipe, paragraphRecipe, buildInputFieldA11yIds, sanitizeInputOtpValue, createInputOtpRecipe, buildRichTextFieldA11yIds, buildCurrencyHelperText, getCurrencySymbol, createAvatarRecipe, createPurposeSemanticAttributes, checkboxRecipe, buildCheckboxFieldA11yIds, buildCheckboxGroupFieldA11yIds, headingRecipe, createCardRecipe, createToastRecipe, createTooltipRecipe, createAccordionRecipe, buildAccordionFieldA11yIds, radioRecipe, buildRadioGroupFieldA11yIds, createBadgeRecipe, createSwitchRecipe, buildSwitchFieldA11yIds, buildSliderFieldA11yIds, createTabRecipe, resolveTabValue, buildTabGroupA11yIds, moveTabSelection, createDialogRecipe, sanitizeCurrencyValue, themeToCSSVars, extractUsedWeights, extractFontFamilyName, shouldLoadGoogleFont, buildGoogleFontsUrl } from '@marwes-ui/core';
3
+ export { AvatarSize, AvatarType, BadgeVariant, ButtonAction, ButtonSize, ButtonVariant, IconName, Spacings, SwitchSize, createFontStack, mwAvailableFonts, mwFontFallbacks, mwGoogleFontFamilies, mwStyledTheme, mwThemeVarNames, mwThemeVars, mwVar } from '@marwes-ui/core';
4
+ import * as React5 from 'react';
4
5
  import { useEffect } from 'react';
5
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+ import { createPortal } from 'react-dom';
6
8
 
7
- // src/provider/marwes-provider.tsx
8
- var MarwesContext = React2.createContext(null);
9
+ // src/index.ts
10
+ var MarwesContext = React5.createContext(null);
11
+ var loadedFonts = /* @__PURE__ */ new Set();
12
+ var preconnected = false;
13
+ function themeToRootStyle(theme) {
14
+ return {
15
+ ...themeToCSSVars(theme),
16
+ backgroundColor: theme.color.background,
17
+ color: theme.color.text
18
+ };
19
+ }
20
+ function applyThemeToElement(element, theme) {
21
+ element.setAttribute("data-marwes-theme", "true");
22
+ for (const [property, value] of Object.entries(themeToRootStyle(theme))) {
23
+ if (property === "backgroundColor") {
24
+ element.style.backgroundColor = value;
25
+ continue;
26
+ }
27
+ element.style.setProperty(property, value);
28
+ }
29
+ }
30
+ function ensureFontPreconnect() {
31
+ if (preconnected || typeof document === "undefined") return;
32
+ preconnected = true;
33
+ for (const href of ["https://fonts.googleapis.com", "https://fonts.gstatic.com"]) {
34
+ const linkElement = document.createElement("link");
35
+ linkElement.rel = "preconnect";
36
+ linkElement.href = href;
37
+ if (href.includes("gstatic")) {
38
+ linkElement.crossOrigin = "anonymous";
39
+ }
40
+ document.head.appendChild(linkElement);
41
+ }
42
+ }
43
+ function loadGoogleFontToDocument(family, weights) {
44
+ if (typeof document === "undefined") return;
45
+ const cacheKey = `${family}:${weights.join(",")}`;
46
+ if (loadedFonts.has(cacheKey)) return;
47
+ loadedFonts.add(cacheKey);
48
+ ensureFontPreconnect();
49
+ const linkElement = document.createElement("link");
50
+ linkElement.rel = "stylesheet";
51
+ linkElement.href = buildGoogleFontsUrl(family, weights);
52
+ linkElement.dataset.marwesFont = family;
53
+ document.head.appendChild(linkElement);
54
+ }
55
+ function loadThemeFonts(theme, config = "auto") {
56
+ const weights = extractUsedWeights(theme.typography);
57
+ const fontStacks = [theme.font.primary, theme.font.secondary];
58
+ for (const fontStack of fontStacks) {
59
+ const familyName = extractFontFamilyName(fontStack);
60
+ if (familyName && shouldLoadGoogleFont(familyName, config)) {
61
+ loadGoogleFontToDocument(familyName, weights);
62
+ }
63
+ }
64
+ }
9
65
  function MarwesProvider({
10
- preset = firstEdition,
11
66
  theme,
12
- mode = "light",
67
+ fontLoading = "auto",
13
68
  onModeChange,
14
69
  children
15
70
  }) {
16
- const initialSystem = React2.useMemo(() => {
17
- return createSystem({
18
- preset,
19
- theme: theme ? { ...theme, mode } : { mode }
20
- });
21
- }, [preset, theme, mode]);
22
- const system = React2.useMemo(() => {
23
- if (mode === initialSystem.theme.mode) {
24
- return initialSystem;
25
- }
26
- return switchMode(initialSystem, mode);
27
- }, [initialSystem, mode]);
28
- const themeClass = `mw-theme--${system.theme.mode}`;
29
- return /* @__PURE__ */ jsx(MarwesContext.Provider, { value: { system, onModeChange }, children: /* @__PURE__ */ jsx("div", { className: themeClass, children }) });
30
- }
31
- function useSystem() {
32
- const ctx = React2.useContext(MarwesContext);
71
+ const rootRef = React5.useRef(null);
72
+ const resolved = React5.useMemo(() => resolveThemeInput(theme ?? {}), [theme]);
73
+ const rootStyle = React5.useMemo(
74
+ () => themeToRootStyle(resolved),
75
+ [resolved]
76
+ );
77
+ React5.useEffect(() => {
78
+ if (rootRef.current) {
79
+ applyThemeToElement(rootRef.current, resolved);
80
+ }
81
+ }, [resolved]);
82
+ React5.useEffect(() => {
83
+ loadThemeFonts(resolved, fontLoading);
84
+ }, [resolved, fontLoading]);
85
+ return /* @__PURE__ */ jsx(MarwesContext.Provider, { value: { theme: resolved, onModeChange }, children: /* @__PURE__ */ jsx(
86
+ "div",
87
+ {
88
+ ref: rootRef,
89
+ className: `mw-theme--${resolved.mode}`,
90
+ "data-marwes-theme": "true",
91
+ style: rootStyle,
92
+ children
93
+ }
94
+ ) });
95
+ }
96
+ function useTheme() {
97
+ const ctx = React5.useContext(MarwesContext);
33
98
  if (!ctx) {
34
99
  throw new Error("MarwesProvider is missing. Wrap your app in <MarwesProvider />.");
35
100
  }
36
- return ctx.system;
37
- }
38
-
39
- // src/provider/use-theme.ts
40
- function useTheme() {
41
- return useSystem().theme;
42
- }
43
- var RENDERKIT_EVENT = "marwes/renderkit/renderkit-update";
44
- function useRenderKitDebug(renderKit, componentName) {
45
- useEffect(() => {
46
- if (typeof window !== "undefined") {
47
- console.log(`[RenderKit Debug] ${componentName}:`, renderKit);
48
- const event = new CustomEvent(RENDERKIT_EVENT, {
49
- detail: {
50
- ...renderKit,
51
- _meta: { component: componentName }
52
- }
53
- });
54
- window.dispatchEvent(event);
55
- }
56
- }, [renderKit, componentName]);
101
+ return ctx.theme;
57
102
  }
58
103
  function Icon({
59
104
  name,
@@ -63,12 +108,13 @@ function Icon({
63
108
  "aria-label": ariaLabel,
64
109
  decorative
65
110
  }) {
66
- const theme = useTheme();
67
- const themeIcon = theme.icon;
68
- const px = resolveIconSize(size ?? themeIcon.size);
69
- const sw = resolveIconStrokeWidth(strokeWidth ?? themeIcon.strokeWidth);
111
+ const px = resolveIconSize(size ?? "sm");
112
+ const sw = resolveIconStrokeWidth(strokeWidth ?? "md");
70
113
  const def = iconRegistry[name];
71
- const isDecorative = decorative || !ariaLabel;
114
+ const a11y = resolveIconA11y({
115
+ ...ariaLabel !== void 0 ? { ariaLabel } : {},
116
+ ...decorative !== void 0 ? { decorative } : {}
117
+ });
72
118
  return /* @__PURE__ */ jsx(
73
119
  "svg",
74
120
  {
@@ -81,9 +127,9 @@ function Icon({
81
127
  strokeLinecap: "round",
82
128
  strokeLinejoin: "round",
83
129
  className,
84
- "aria-hidden": isDecorative ? "true" : void 0,
85
- "aria-label": ariaLabel,
86
- role: isDecorative ? void 0 : "img",
130
+ "aria-hidden": a11y.ariaHidden ? "true" : void 0,
131
+ "aria-label": a11y.ariaLabel,
132
+ role: a11y.role,
87
133
  focusable: "false",
88
134
  children: def.nodes.map((iconNode, nodeIndex) => {
89
135
  const TagName = iconNode.tag;
@@ -92,16 +138,118 @@ function Icon({
92
138
  }
93
139
  );
94
140
  }
141
+ function renderSpinnerSvgNode(spinnerSvgNode, nodeIndex) {
142
+ const TagName = spinnerSvgNode.tag;
143
+ return /* @__PURE__ */ jsx(TagName, { ...spinnerSvgNode.attrs }, nodeIndex);
144
+ }
145
+ function Spinner(props) {
146
+ const {
147
+ className,
148
+ style,
149
+ dataAttributes,
150
+ variant,
151
+ size,
152
+ decorative,
153
+ ariaLabel,
154
+ id,
155
+ ...nativeSpanProps
156
+ } = props;
157
+ const resolvedAriaLabel = ariaLabel ?? (typeof nativeSpanProps["aria-label"] === "string" ? nativeSpanProps["aria-label"] : void 0);
158
+ const spinnerOptions = {
159
+ ...variant !== void 0 ? { variant } : {},
160
+ ...size !== void 0 ? { size } : {},
161
+ ...decorative !== void 0 ? { decorative } : {},
162
+ ...resolvedAriaLabel !== void 0 ? { ariaLabel: resolvedAriaLabel } : {},
163
+ ...id !== void 0 ? { id } : {}
164
+ };
165
+ const renderKit = createSpinnerRecipe(spinnerOptions);
166
+ const mergedClassName = [renderKit.className, className].filter(Boolean).join(" ");
167
+ const mergedStyle = { ...renderKit.vars, ...style };
168
+ return /* @__PURE__ */ jsx(
169
+ "span",
170
+ {
171
+ ...nativeSpanProps,
172
+ ...renderKit.dataAttributes,
173
+ ...dataAttributes,
174
+ className: mergedClassName,
175
+ style: mergedStyle,
176
+ role: renderKit.a11y.role,
177
+ id: renderKit.a11y.id,
178
+ "aria-hidden": renderKit.a11y.ariaHidden ? "true" : void 0,
179
+ "aria-label": renderKit.a11y.ariaLabel,
180
+ "aria-live": renderKit.a11y.ariaLive,
181
+ children: /* @__PURE__ */ jsx(
182
+ "svg",
183
+ {
184
+ className: "mw-spinner__svg",
185
+ viewBox: renderKit.svg.viewBox,
186
+ "aria-hidden": "true",
187
+ focusable: "false",
188
+ children: renderKit.svg.nodes.map(renderSpinnerSvgNode)
189
+ }
190
+ )
191
+ }
192
+ );
193
+ }
194
+ function ButtonSpinner(props) {
195
+ const { inverted = false, style, dataAttributes, ...spinnerProps } = props;
196
+ const spinnerStyle = {
197
+ "--mw-spinner-track-color": inverted ? "color-mix(in srgb, currentColor 80%, transparent)" : "color-mix(in srgb, currentColor 35%, transparent)",
198
+ "--mw-spinner-indicator-color": "currentColor",
199
+ ...style
200
+ };
201
+ return /* @__PURE__ */ jsx(
202
+ Spinner,
203
+ {
204
+ ...spinnerProps,
205
+ variant: props.variant ?? "classic",
206
+ size: props.size ?? "xs",
207
+ decorative: props.decorative ?? true,
208
+ style: spinnerStyle,
209
+ dataAttributes: {
210
+ ...dataAttributes,
211
+ "data-purpose": "button-loading",
212
+ "data-context": "button-loading"
213
+ }
214
+ }
215
+ );
216
+ }
217
+ function EmptyStateSpinner(props) {
218
+ return /* @__PURE__ */ jsx(
219
+ Spinner,
220
+ {
221
+ ...props,
222
+ variant: props.variant ?? "dots-round",
223
+ size: props.size ?? "lg",
224
+ decorative: props.decorative ?? true,
225
+ dataAttributes: {
226
+ ...props.dataAttributes,
227
+ "data-purpose": "empty-state",
228
+ "data-context": "empty-state"
229
+ }
230
+ }
231
+ );
232
+ }
233
+ function isFilledButtonVariant(variant) {
234
+ return variant === "primary" || variant === "success";
235
+ }
95
236
  function Button(props) {
96
- const theme = useTheme();
97
- const kit = createButtonRecipe(theme, props);
98
- useRenderKitDebug(kit, "Button");
237
+ const kit = createButtonRecipe(props);
99
238
  const style = kit.vars;
100
239
  const className = props.className ? `${kit.className} ${props.className}` : kit.className;
240
+ const resolvedVariant = props.variant ?? "primary";
241
+ const resolvedLoading = kit.loading;
242
+ const visibleLabel = resolvedLoading.isLoading && resolvedLoading.loadingLabel !== void 0 ? resolvedLoading.loadingLabel : props.children;
101
243
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
102
- props.iconLeft && /* @__PURE__ */ jsx(Icon, { name: props.iconLeft, size: "xs", decorative: true }),
103
- props.children,
104
- props.iconRight && /* @__PURE__ */ jsx(Icon, { name: props.iconRight, size: "xs", decorative: true })
244
+ resolvedLoading.isLoading ? /* @__PURE__ */ jsx(
245
+ ButtonSpinner,
246
+ {
247
+ variant: resolvedLoading.spinnerVariant,
248
+ inverted: isFilledButtonVariant(resolvedVariant)
249
+ }
250
+ ) : props.iconLeft ? /* @__PURE__ */ jsx(Icon, { name: props.iconLeft, size: "xs", strokeWidth: "sm", decorative: true }) : null,
251
+ visibleLabel,
252
+ !resolvedLoading.isLoading && props.iconRight ? /* @__PURE__ */ jsx(Icon, { name: props.iconRight, size: "xs", strokeWidth: "sm", decorative: true }) : null
105
253
  ] });
106
254
  if (kit.tag === "button") {
107
255
  return /* @__PURE__ */ jsx(
@@ -151,91 +299,405 @@ function Button(props) {
151
299
  }
152
300
  );
153
301
  }
154
- function DangerButton(props) {
155
- const { confirmation = true, ...restProps } = props;
302
+ function isDevelopmentEnvironment() {
303
+ const nodeProcess = globalThis.process;
304
+ const nodeEnv = nodeProcess?.env?.NODE_ENV;
305
+ if (nodeEnv) {
306
+ return nodeEnv !== "production";
307
+ }
308
+ const meta = import.meta;
309
+ if (typeof meta.env?.PROD === "boolean") {
310
+ return !meta.env.PROD;
311
+ }
312
+ if (meta.env?.MODE) {
313
+ return meta.env.MODE !== "production";
314
+ }
315
+ return true;
316
+ }
317
+ function warnForForbiddenPurposeProps(componentName, rawProps, forbiddenProps) {
318
+ if (!isDevelopmentEnvironment()) {
319
+ return;
320
+ }
321
+ const warningByProp = {
322
+ variant: "Use Button if you need a custom visual treatment.",
323
+ action: "Use Button if you need a custom semantic action.",
324
+ as: "Use Button if you need a custom element mode."
325
+ };
326
+ for (const forbiddenProp of forbiddenProps) {
327
+ if (!Object.prototype.hasOwnProperty.call(rawProps, forbiddenProp)) {
328
+ continue;
329
+ }
330
+ console.warn(
331
+ `[marwes] ${componentName} does not support \`${forbiddenProp}\`. ${warningByProp[forbiddenProp]}`
332
+ );
333
+ }
334
+ }
335
+ function omitButtonProps(rawProps, omittedKeys) {
336
+ const forwardedProps = { ...rawProps };
337
+ for (const omittedKey of omittedKeys) {
338
+ delete forwardedProps[omittedKey];
339
+ }
340
+ return forwardedProps;
341
+ }
342
+ function createPurposeButtonDataAttributes(purpose, existingDataAttributes, localDataAttributes = {}) {
343
+ return {
344
+ ...existingDataAttributes,
345
+ ...createPurposeSemanticAttributes(purpose),
346
+ ...localDataAttributes
347
+ };
348
+ }
349
+ function DestructiveButton(props) {
350
+ const rawProps = props;
351
+ warnForForbiddenPurposeProps("DestructiveButton", rawProps, ["variant", "action", "as"]);
352
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action", "as", "href"]);
353
+ const confirmation = props.confirmation ?? true;
156
354
  return /* @__PURE__ */ jsx(
157
355
  Button,
158
356
  {
159
- ...restProps,
160
- tone: "primary",
161
- action: "delete",
357
+ ...forwardedProps,
358
+ as: "button",
359
+ variant: ButtonVariant.primary,
360
+ action: ButtonAction.delete,
361
+ error: true,
162
362
  confirmation,
163
- dataAttributes: {
164
- ...props.dataAttributes,
165
- "data-destructive": "true",
166
- "data-confirmation-required": confirmation ? "true" : "false"
167
- }
363
+ dataAttributes: createPurposeButtonDataAttributes(
364
+ "destructive",
365
+ forwardedProps.dataAttributes,
366
+ {
367
+ "data-confirmation-required": confirmation ? "true" : "false"
368
+ }
369
+ )
168
370
  }
169
371
  );
170
372
  }
171
373
  function CreateButton(props) {
374
+ const rawProps = props;
375
+ warnForForbiddenPurposeProps("CreateButton", rawProps, ["variant", "action"]);
376
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
172
377
  return /* @__PURE__ */ jsx(
173
378
  Button,
174
379
  {
175
- ...props,
176
- action: "create",
177
- tone: props.tone ?? "primary",
178
- dataAttributes: {
179
- ...props.dataAttributes,
380
+ ...forwardedProps,
381
+ action: ButtonAction.create,
382
+ variant: ButtonVariant.primary,
383
+ dataAttributes: createPurposeButtonDataAttributes("create", forwardedProps.dataAttributes, {
180
384
  "data-creative": "true"
181
- }
385
+ })
182
386
  }
183
387
  );
184
388
  }
185
389
  function SubmitButton(props) {
390
+ const rawProps = props;
391
+ warnForForbiddenPurposeProps("SubmitButton", rawProps, ["variant", "action", "as"]);
392
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action", "as", "href"]);
186
393
  return /* @__PURE__ */ jsx(
187
394
  Button,
188
395
  {
189
- ...props,
396
+ ...forwardedProps,
190
397
  as: "button",
191
- action: "submit",
192
- dataAttributes: {
193
- "data-context": "form-submit",
194
- ...props.dataAttributes
195
- }
398
+ action: ButtonAction.submit,
399
+ variant: ButtonVariant.primary,
400
+ dataAttributes: createPurposeButtonDataAttributes("submit", forwardedProps.dataAttributes)
196
401
  }
197
402
  );
198
403
  }
199
404
  function CancelButton(props) {
405
+ const rawProps = props;
406
+ warnForForbiddenPurposeProps("CancelButton", rawProps, ["variant", "action"]);
407
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
200
408
  return /* @__PURE__ */ jsx(
201
409
  Button,
202
410
  {
203
- ...props,
204
- action: "cancel",
205
- tone: props.tone ?? "secondary",
206
- dataAttributes: {
207
- ...props.dataAttributes,
411
+ ...forwardedProps,
412
+ action: ButtonAction.cancel,
413
+ variant: ButtonVariant.neutral,
414
+ dataAttributes: createPurposeButtonDataAttributes("cancel", forwardedProps.dataAttributes, {
208
415
  "data-cancel": "true"
209
- }
416
+ })
210
417
  }
211
418
  );
212
419
  }
213
420
  function LinkButton(props) {
421
+ const rawProps = props;
422
+ warnForForbiddenPurposeProps("LinkButton", rawProps, ["variant", "action", "as"]);
423
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action", "as"]);
214
424
  return /* @__PURE__ */ jsx(
215
425
  Button,
216
426
  {
217
- ...props,
427
+ ...forwardedProps,
218
428
  as: "a",
219
- action: "navigate",
220
- dataAttributes: {
221
- ...props.dataAttributes,
222
- "data-navigation": "true"
223
- }
429
+ action: ButtonAction.navigate,
430
+ variant: ButtonVariant.text,
431
+ dataAttributes: createPurposeButtonDataAttributes(
432
+ "navigation",
433
+ forwardedProps.dataAttributes,
434
+ {
435
+ "data-navigation": "true"
436
+ }
437
+ )
438
+ }
439
+ );
440
+ }
441
+ function SaveButton(props) {
442
+ const rawProps = props;
443
+ warnForForbiddenPurposeProps("SaveButton", rawProps, ["variant", "action"]);
444
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
445
+ return /* @__PURE__ */ jsx(
446
+ Button,
447
+ {
448
+ ...forwardedProps,
449
+ action: ButtonAction.submit,
450
+ variant: ButtonVariant.primary,
451
+ dataAttributes: createPurposeButtonDataAttributes("save", forwardedProps.dataAttributes, {
452
+ "data-persist": "true"
453
+ })
454
+ }
455
+ );
456
+ }
457
+ function ConfirmButton(props) {
458
+ const rawProps = props;
459
+ warnForForbiddenPurposeProps("ConfirmButton", rawProps, ["variant", "action", "as"]);
460
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action", "as", "href"]);
461
+ return /* @__PURE__ */ jsx(
462
+ Button,
463
+ {
464
+ ...forwardedProps,
465
+ as: "button",
466
+ action: ButtonAction.button,
467
+ variant: ButtonVariant.success,
468
+ dataAttributes: createPurposeButtonDataAttributes("confirm", forwardedProps.dataAttributes)
469
+ }
470
+ );
471
+ }
472
+ function VerifyButton(props) {
473
+ const rawProps = props;
474
+ warnForForbiddenPurposeProps("VerifyButton", rawProps, ["variant", "action", "as"]);
475
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action", "as", "href"]);
476
+ return /* @__PURE__ */ jsx(
477
+ Button,
478
+ {
479
+ ...forwardedProps,
480
+ as: "button",
481
+ action: ButtonAction.button,
482
+ variant: ButtonVariant.secondary,
483
+ iconRight: forwardedProps.iconRight ?? IconName.CheckCircle,
484
+ dataAttributes: createPurposeButtonDataAttributes("verify", forwardedProps.dataAttributes, {
485
+ "data-verification": "true"
486
+ })
487
+ }
488
+ );
489
+ }
490
+ function EditButton(props) {
491
+ const rawProps = props;
492
+ warnForForbiddenPurposeProps("EditButton", rawProps, ["variant", "action"]);
493
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
494
+ return /* @__PURE__ */ jsx(
495
+ Button,
496
+ {
497
+ ...forwardedProps,
498
+ action: ButtonAction.edit,
499
+ variant: ButtonVariant.secondary,
500
+ iconRight: forwardedProps.iconRight ?? IconName.Edit,
501
+ dataAttributes: createPurposeButtonDataAttributes("edit", forwardedProps.dataAttributes, {
502
+ "data-edit": "true"
503
+ })
504
+ }
505
+ );
506
+ }
507
+ function CloseButton(props) {
508
+ const rawProps = props;
509
+ warnForForbiddenPurposeProps("CloseButton", rawProps, ["variant", "action"]);
510
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
511
+ return /* @__PURE__ */ jsx(
512
+ Button,
513
+ {
514
+ ...forwardedProps,
515
+ action: ButtonAction.cancel,
516
+ variant: ButtonVariant.neutral,
517
+ dataAttributes: createPurposeButtonDataAttributes("close", forwardedProps.dataAttributes, {
518
+ "data-close": "true"
519
+ })
520
+ }
521
+ );
522
+ }
523
+ function RefreshButton(props) {
524
+ const rawProps = props;
525
+ warnForForbiddenPurposeProps("RefreshButton", rawProps, ["variant", "action"]);
526
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
527
+ return /* @__PURE__ */ jsx(
528
+ Button,
529
+ {
530
+ ...forwardedProps,
531
+ action: ButtonAction.button,
532
+ variant: ButtonVariant.neutral,
533
+ iconRight: forwardedProps.iconRight ?? IconName.RefreshCw,
534
+ dataAttributes: createPurposeButtonDataAttributes("refresh", forwardedProps.dataAttributes, {
535
+ "data-refresh": "true"
536
+ })
537
+ }
538
+ );
539
+ }
540
+ function UploadButton(props) {
541
+ const rawProps = props;
542
+ warnForForbiddenPurposeProps("UploadButton", rawProps, ["variant", "action"]);
543
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
544
+ return /* @__PURE__ */ jsx(
545
+ Button,
546
+ {
547
+ ...forwardedProps,
548
+ action: ButtonAction.button,
549
+ variant: ButtonVariant.secondary,
550
+ iconRight: forwardedProps.iconRight ?? IconName.Upload,
551
+ dataAttributes: createPurposeButtonDataAttributes("upload", forwardedProps.dataAttributes, {
552
+ "data-transfer": "upload"
553
+ })
554
+ }
555
+ );
556
+ }
557
+ function DownloadButton(props) {
558
+ const rawProps = props;
559
+ warnForForbiddenPurposeProps("DownloadButton", rawProps, ["variant", "action"]);
560
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
561
+ return /* @__PURE__ */ jsx(
562
+ Button,
563
+ {
564
+ ...forwardedProps,
565
+ action: ButtonAction.button,
566
+ variant: ButtonVariant.secondary,
567
+ iconRight: forwardedProps.iconRight ?? IconName.Download,
568
+ dataAttributes: createPurposeButtonDataAttributes("download", forwardedProps.dataAttributes, {
569
+ "data-transfer": "download"
570
+ })
571
+ }
572
+ );
573
+ }
574
+ function CopyButton(props) {
575
+ const rawProps = props;
576
+ warnForForbiddenPurposeProps("CopyButton", rawProps, ["variant", "action"]);
577
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
578
+ return /* @__PURE__ */ jsx(
579
+ Button,
580
+ {
581
+ ...forwardedProps,
582
+ action: ButtonAction.button,
583
+ variant: ButtonVariant.neutral,
584
+ dataAttributes: createPurposeButtonDataAttributes("copy", forwardedProps.dataAttributes, {
585
+ "data-copy": "true"
586
+ })
587
+ }
588
+ );
589
+ }
590
+ function SearchButton(props) {
591
+ const rawProps = props;
592
+ warnForForbiddenPurposeProps("SearchButton", rawProps, ["variant", "action"]);
593
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
594
+ return /* @__PURE__ */ jsx(
595
+ Button,
596
+ {
597
+ ...forwardedProps,
598
+ action: ButtonAction.button,
599
+ variant: ButtonVariant.primary,
600
+ iconRight: forwardedProps.iconRight ?? IconName.Search,
601
+ dataAttributes: createPurposeButtonDataAttributes("search", forwardedProps.dataAttributes, {
602
+ "data-search": "true"
603
+ })
604
+ }
605
+ );
606
+ }
607
+ function FilterButton(props) {
608
+ const rawProps = props;
609
+ warnForForbiddenPurposeProps("FilterButton", rawProps, ["variant", "action"]);
610
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
611
+ return /* @__PURE__ */ jsx(
612
+ Button,
613
+ {
614
+ ...forwardedProps,
615
+ action: ButtonAction.button,
616
+ variant: ButtonVariant.neutral,
617
+ dataAttributes: createPurposeButtonDataAttributes("filter", forwardedProps.dataAttributes, {
618
+ "data-filter": "true"
619
+ })
620
+ }
621
+ );
622
+ }
623
+ function SortButton(props) {
624
+ const rawProps = props;
625
+ warnForForbiddenPurposeProps("SortButton", rawProps, ["variant", "action"]);
626
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
627
+ return /* @__PURE__ */ jsx(
628
+ Button,
629
+ {
630
+ ...forwardedProps,
631
+ action: ButtonAction.button,
632
+ variant: ButtonVariant.neutral,
633
+ dataAttributes: createPurposeButtonDataAttributes("sort", forwardedProps.dataAttributes, {
634
+ "data-sort": "true"
635
+ })
636
+ }
637
+ );
638
+ }
639
+ function DropdownButton(props) {
640
+ const rawProps = props;
641
+ warnForForbiddenPurposeProps("DropdownButton", rawProps, ["variant", "action"]);
642
+ const forwardedProps = omitButtonProps(rawProps, ["variant", "action"]);
643
+ return /* @__PURE__ */ jsx(
644
+ Button,
645
+ {
646
+ ...forwardedProps,
647
+ action: ButtonAction.button,
648
+ variant: ButtonVariant.secondary,
649
+ iconRight: forwardedProps.iconRight ?? IconName.ChevronDown,
650
+ dataAttributes: createPurposeButtonDataAttributes("dropdown", forwardedProps.dataAttributes, {
651
+ "data-dropdown": "true"
652
+ })
224
653
  }
225
654
  );
226
655
  }
227
656
  function PrimaryButton(props) {
228
- return /* @__PURE__ */ jsx(Button, { ...props, tone: "primary", as: "button" });
657
+ return /* @__PURE__ */ jsx(Button, { ...props, variant: "primary", as: "button" });
229
658
  }
230
659
  function SecondaryButton(props) {
231
- return /* @__PURE__ */ jsx(Button, { ...props, tone: "secondary", as: "button" });
660
+ return /* @__PURE__ */ jsx(Button, { ...props, variant: "secondary", as: "button" });
232
661
  }
233
662
  function TextButton(props) {
234
- return /* @__PURE__ */ jsx(Button, { ...props, tone: "text", as: "button" });
663
+ return /* @__PURE__ */ jsx(Button, { ...props, variant: "text", as: "button" });
664
+ }
665
+ function SuccessButton(props) {
666
+ return /* @__PURE__ */ jsx(
667
+ Button,
668
+ {
669
+ ...props,
670
+ variant: "success",
671
+ as: "button",
672
+ dataAttributes: createPurposeButtonDataAttributes("success", props.dataAttributes)
673
+ }
674
+ );
675
+ }
676
+ var RENDERKIT_EVENT = "marwes/renderkit/renderkit-update";
677
+ var RENDERKIT_DEBUG_FLAG = "__MARWES_RENDERKIT_DEBUG__";
678
+ function isRenderKitDebugEnabled() {
679
+ if (typeof window === "undefined") {
680
+ return false;
681
+ }
682
+ const renderKitDebugWindow = window;
683
+ return renderKitDebugWindow[RENDERKIT_DEBUG_FLAG] === true;
684
+ }
685
+ function useRenderKitDebug(renderKit, componentName) {
686
+ useEffect(() => {
687
+ if (!isRenderKitDebugEnabled()) {
688
+ return;
689
+ }
690
+ const event = new CustomEvent(RENDERKIT_EVENT, {
691
+ detail: {
692
+ ...renderKit,
693
+ _meta: { component: componentName }
694
+ }
695
+ });
696
+ window.dispatchEvent(event);
697
+ }, [renderKit, componentName]);
235
698
  }
236
699
  function Input(props) {
237
- const theme = useTheme();
238
- const kit = createInputRecipe(theme, props);
700
+ const kit = createInputRecipe(props);
239
701
  useRenderKitDebug(kit, "Input");
240
702
  const style = kit.vars;
241
703
  const className = props.className ? `${kit.className} ${props.className}` : kit.className;
@@ -265,77 +727,443 @@ function Input(props) {
265
727
  }
266
728
  );
267
729
  }
268
- function Checkbox(props) {
269
- const { onCheckedChange, onChange, ...coreProps } = props;
270
- const theme = useTheme();
271
- const kit = checkboxRecipe({ ...coreProps, theme });
272
- const inputRef = React2.useRef(null);
273
- React2.useLayoutEffect(() => {
274
- const el = inputRef.current;
275
- if (!el) return;
276
- el.indeterminate = kit.indeterminate;
277
- }, [kit.indeterminate]);
278
- const handleChange = (e) => {
279
- onChange?.(e);
280
- onCheckedChange?.(e.currentTarget.checked);
281
- };
282
- const { a11y } = kit;
730
+ function SelectArrowIcon(props) {
283
731
  return /* @__PURE__ */ jsx(
284
- "input",
732
+ "svg",
285
733
  {
286
- ref: inputRef,
287
- type: "checkbox",
288
- className: kit.className,
289
- style: kit.vars,
290
- id: a11y.id,
291
- name: a11y.name,
292
- value: a11y.value,
293
- disabled: a11y.disabled === true,
294
- required: a11y.required === true,
295
- "aria-label": a11y.ariaLabel,
296
- "aria-labelledby": a11y.ariaLabelledBy,
297
- "aria-describedby": a11y.ariaDescribedBy,
298
- "aria-checked": a11y.ariaChecked,
299
- "aria-invalid": a11y.ariaInvalid === true ? true : void 0,
300
- checked: kit.checked,
301
- defaultChecked: kit.defaultChecked,
302
- onChange: handleChange
734
+ width: "16",
735
+ height: "16",
736
+ viewBox: "0 0 16 16",
737
+ fill: "none",
738
+ xmlns: "http://www.w3.org/2000/svg",
739
+ className: props.className,
740
+ "aria-hidden": "true",
741
+ focusable: "false",
742
+ children: /* @__PURE__ */ jsx(
743
+ "path",
744
+ {
745
+ d: "M11.5288 5.52876C11.7891 5.26841 12.2111 5.26841 12.4715 5.52876C12.7318 5.78911 12.7318 6.21114 12.4715 6.47147L8.47148 10.4715C8.21115 10.7318 7.78912 10.7318 7.52877 10.4715L3.52876 6.47147C3.26841 6.21112 3.26841 5.78911 3.52876 5.52876C3.78911 5.26841 4.21112 5.26841 4.47147 5.52876L6.58591 7.6432C7.36696 8.42425 8.63329 8.42425 9.41434 7.6432L11.5288 5.52876Z",
746
+ fill: "currentColor"
747
+ }
748
+ )
303
749
  }
304
750
  );
305
751
  }
306
- var Divider = React2.forwardRef((props, ref) => {
307
- const { className: customClassName, style: customStyle, ...opts } = props;
308
- const theme = useTheme();
309
- const kit = createDividerRecipe(theme, opts);
310
- const style = { ...kit.vars, ...customStyle };
311
- const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
312
- return /* @__PURE__ */ jsx("hr", { ref, ...kit.a11y, ...kit.dataAttributes, className, style });
313
- });
314
- Divider.displayName = "Divider";
315
- function H1(props) {
316
- const { children, className: customClassName, style: customStyle, ...opts } = props;
317
- const theme = useTheme();
318
- const kit = headingRecipe({ ...opts, level: 1 }, theme);
319
- const style = { ...kit.vars, ...customStyle };
320
- const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
321
- return /* @__PURE__ */ jsx("h1", { id: kit.a11y.id, "aria-label": kit.a11y.ariaLabel, className, style, children });
752
+ function getInitialSelectValue(props) {
753
+ if (props.value !== void 0) {
754
+ return props.value;
755
+ }
756
+ if (props.defaultValue !== void 0) {
757
+ return props.defaultValue;
758
+ }
759
+ if (props.placeholder !== void 0) {
760
+ return "";
761
+ }
762
+ return props.options[0]?.value ?? "";
322
763
  }
323
- function H2(props) {
324
- const { children, className: customClassName, style: customStyle, ...opts } = props;
325
- const theme = useTheme();
326
- const kit = headingRecipe({ ...opts, level: 2 }, theme);
327
- const style = { ...kit.vars, ...customStyle };
328
- const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
329
- return /* @__PURE__ */ jsx("h2", { id: kit.a11y.id, "aria-label": kit.a11y.ariaLabel, className, style, children });
764
+ function Select(props) {
765
+ const kit = createSelectRecipe(props);
766
+ const mode = resolveSelectMode(props);
767
+ const isControlled = props.value !== void 0;
768
+ const [uncontrolledValue, setUncontrolledValue] = React5.useState(
769
+ () => getInitialSelectValue(props)
770
+ );
771
+ useRenderKitDebug(kit, "Select");
772
+ const style = kit.vars;
773
+ const className = props.className ? `${kit.className} ${props.className}` : kit.className;
774
+ const value = isControlled ? props.value ?? "" : uncontrolledValue;
775
+ const hasPlaceholder = props.placeholder !== void 0;
776
+ const placeholderSelected = hasPlaceholder && value === "";
777
+ const handleChange = (e) => {
778
+ const nextValue = e.target.value;
779
+ if (!isControlled) {
780
+ setUncontrolledValue(nextValue);
781
+ }
782
+ props.onValueChange?.(nextValue);
783
+ };
784
+ const selectElement = /* @__PURE__ */ jsxs(
785
+ "select",
786
+ {
787
+ className,
788
+ style,
789
+ "data-placeholder-selected": placeholderSelected ? "true" : void 0,
790
+ id: kit.a11y.id,
791
+ name: kit.a11y.name,
792
+ disabled: kit.a11y.disabled,
793
+ required: kit.a11y.required,
794
+ "aria-label": kit.a11y.ariaLabel,
795
+ "aria-invalid": kit.a11y.ariaInvalid,
796
+ "aria-describedby": kit.a11y.ariaDescribedBy,
797
+ value,
798
+ onChange: handleChange,
799
+ children: [
800
+ props.placeholder ? /* @__PURE__ */ jsx("option", { value: "", disabled: props.required ? true : void 0, children: props.placeholder }) : null,
801
+ props.options.map((option) => /* @__PURE__ */ jsx(
802
+ "option",
803
+ {
804
+ value: option.value,
805
+ disabled: option.disabled ? true : void 0,
806
+ children: option.label
807
+ },
808
+ option.value
809
+ ))
810
+ ]
811
+ }
812
+ );
813
+ if (mode === "native") {
814
+ return selectElement;
815
+ }
816
+ return /* @__PURE__ */ jsxs("span", { className: "mw-select__control", children: [
817
+ selectElement,
818
+ /* @__PURE__ */ jsx(SelectArrowIcon, { className: "mw-select__control-icon" })
819
+ ] });
330
820
  }
331
- function H3(props) {
332
- const { children, className: customClassName, style: customStyle, ...opts } = props;
333
- const theme = useTheme();
334
- const kit = headingRecipe({ ...opts, level: 3 }, theme);
335
- const style = { ...kit.vars, ...customStyle };
336
- const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
337
- return /* @__PURE__ */ jsx("h3", { id: kit.a11y.id, "aria-label": kit.a11y.ariaLabel, className, style, children });
821
+ function Textarea(props) {
822
+ const kit = createTextareaRecipe(props);
823
+ useRenderKitDebug(kit, "Textarea");
824
+ const style = kit.vars;
825
+ const className = props.className ? `${kit.className} ${props.className}` : kit.className;
826
+ const handleChange = (e) => {
827
+ props.onValueChange?.(e.target.value);
828
+ };
829
+ return /* @__PURE__ */ jsx(
830
+ "textarea",
831
+ {
832
+ className,
833
+ style,
834
+ id: kit.a11y.id,
835
+ name: kit.a11y.name,
836
+ inputMode: kit.a11y.inputMode,
837
+ autoComplete: kit.a11y.autoComplete,
838
+ placeholder: kit.a11y.placeholder,
839
+ disabled: kit.a11y.disabled,
840
+ readOnly: kit.a11y.readOnly,
841
+ required: kit.a11y.required,
842
+ rows: kit.a11y.rows,
843
+ cols: kit.a11y.cols,
844
+ "aria-label": kit.a11y.ariaLabel,
845
+ "aria-invalid": kit.a11y.ariaInvalid,
846
+ "aria-describedby": kit.a11y.ariaDescribedBy,
847
+ value: props.value,
848
+ defaultValue: props.defaultValue,
849
+ onChange: handleChange
850
+ }
851
+ );
852
+ }
853
+ var formatLabels = {
854
+ bold: "Bold",
855
+ italic: "Italic",
856
+ underline: "Underline"
857
+ };
858
+ function getRichTextCommandDocument() {
859
+ return document;
860
+ }
861
+ function mergeRefs(...refs) {
862
+ return (value) => {
863
+ for (const ref of refs) {
864
+ if (!ref) continue;
865
+ if (typeof ref === "function") {
866
+ ref(value);
867
+ continue;
868
+ }
869
+ ref.current = value;
870
+ }
871
+ };
872
+ }
873
+ function isNodeWithinEditor(node, editorElement) {
874
+ if (!node || !editorElement) {
875
+ return false;
876
+ }
877
+ return editorElement.contains(node.nodeType === Node.TEXT_NODE ? node.parentNode : node);
878
+ }
879
+ function getActiveFormatsFromSelection(editorElement) {
880
+ if (!editorElement || typeof window === "undefined" || typeof document === "undefined") {
881
+ return [];
882
+ }
883
+ const commandDocument = getRichTextCommandDocument();
884
+ const selection = window.getSelection();
885
+ const anchorNode = selection?.anchorNode ?? null;
886
+ if (!anchorNode || !isNodeWithinEditor(anchorNode, editorElement)) {
887
+ return [];
888
+ }
889
+ const activeFormats = /* @__PURE__ */ new Set();
890
+ if (typeof commandDocument.queryCommandState === "function") {
891
+ for (const format of Object.keys(richTextCommandByFormat)) {
892
+ try {
893
+ if (commandDocument.queryCommandState(richTextCommandByFormat[format])) {
894
+ activeFormats.add(format);
895
+ }
896
+ } catch {
897
+ }
898
+ }
899
+ }
900
+ if (activeFormats.size > 0) {
901
+ return Array.from(activeFormats);
902
+ }
903
+ let currentNode = anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentNode : anchorNode;
904
+ while (currentNode && currentNode !== editorElement) {
905
+ if (!(currentNode instanceof HTMLElement)) {
906
+ currentNode = currentNode.parentNode;
907
+ continue;
908
+ }
909
+ const tagName = currentNode.tagName.toLowerCase();
910
+ if (tagName === "strong" || tagName === "b") activeFormats.add("bold");
911
+ if (tagName === "em" || tagName === "i") activeFormats.add("italic");
912
+ if (tagName === "u") activeFormats.add("underline");
913
+ currentNode = currentNode.parentNode;
914
+ }
915
+ return Array.from(activeFormats);
916
+ }
917
+ function ensureEditorSelection(editorElement) {
918
+ if (typeof window === "undefined") {
919
+ return;
920
+ }
921
+ editorElement.focus();
922
+ const selection = window.getSelection();
923
+ const anchorNode = selection?.anchorNode ?? null;
924
+ if (anchorNode && isNodeWithinEditor(anchorNode, editorElement)) {
925
+ return;
926
+ }
927
+ const range = document.createRange();
928
+ range.selectNodeContents(editorElement);
929
+ range.collapse(false);
930
+ selection?.removeAllRanges();
931
+ selection?.addRange(range);
932
+ }
933
+ function getFormatTagNames(format) {
934
+ if (format === "bold") return ["strong", "b"];
935
+ if (format === "italic") return ["em", "i"];
936
+ return ["u"];
937
+ }
938
+ function findNearestFormatElement(node, editorElement, format) {
939
+ const tagNames = getFormatTagNames(format);
940
+ let currentNode = node?.nodeType === Node.TEXT_NODE ? node.parentNode : node;
941
+ while (currentNode && currentNode !== editorElement) {
942
+ if (currentNode instanceof HTMLElement && tagNames.includes(currentNode.tagName.toLowerCase())) {
943
+ return currentNode;
944
+ }
945
+ currentNode = currentNode.parentNode;
946
+ }
947
+ return null;
948
+ }
949
+ function exitActiveFormatAtCaret(editorElement, format) {
950
+ if (typeof window === "undefined") {
951
+ return false;
952
+ }
953
+ const selection = window.getSelection();
954
+ if (!selection || selection.rangeCount === 0) {
955
+ return false;
956
+ }
957
+ const range = selection.getRangeAt(0);
958
+ const anchorNode = selection.anchorNode;
959
+ if (!range.collapsed || !anchorNode || !isNodeWithinEditor(anchorNode, editorElement)) {
960
+ return false;
961
+ }
962
+ const formatElement = findNearestFormatElement(anchorNode, editorElement, format);
963
+ if (!formatElement || !formatElement.parentNode) {
964
+ return false;
965
+ }
966
+ const trailingRange = document.createRange();
967
+ trailingRange.setStart(range.startContainer, range.startOffset);
968
+ trailingRange.setEndAfter(formatElement);
969
+ const trailingFragment = trailingRange.extractContents();
970
+ const caretTextNode = document.createTextNode("\u200B");
971
+ const parentNode = formatElement.parentNode;
972
+ parentNode.insertBefore(caretTextNode, formatElement.nextSibling);
973
+ parentNode.insertBefore(trailingFragment, caretTextNode.nextSibling);
974
+ if (formatElement.textContent?.replaceAll("\u200B", "").trim().length === 0) {
975
+ formatElement.remove();
976
+ }
977
+ const nextRange = document.createRange();
978
+ nextRange.setStart(caretTextNode, 1);
979
+ nextRange.collapse(true);
980
+ selection.removeAllRanges();
981
+ selection.addRange(nextRange);
982
+ return true;
338
983
  }
984
+ var RichText = React5.forwardRef((props, forwardedRef) => {
985
+ const kit = createRichTextRecipe(props);
986
+ const allowedFormats = React5.useMemo(
987
+ () => resolveRichTextAllowedFormats(props.allowedFormats),
988
+ [props.allowedFormats]
989
+ );
990
+ const normalizedControlledValue = React5.useMemo(
991
+ () => normalizeRichTextHtml(props.value),
992
+ [props.value]
993
+ );
994
+ const initialUncontrolledValue = React5.useMemo(
995
+ () => normalizeRichTextHtml(props.defaultValue),
996
+ [props.defaultValue]
997
+ );
998
+ const isControlled = props.value !== void 0;
999
+ const [uncontrolledHtml, setUncontrolledHtml] = React5.useState(initialUncontrolledValue);
1000
+ const [isEditorEmpty, setIsEditorEmpty] = React5.useState(
1001
+ isRichTextHtmlEmpty(isControlled ? normalizedControlledValue : initialUncontrolledValue)
1002
+ );
1003
+ const [activeFormats, setActiveFormats] = React5.useState([]);
1004
+ const editorElementRef = React5.useRef(null);
1005
+ useRenderKitDebug(kit, "RichText");
1006
+ const editorHtml = isControlled ? normalizedControlledValue : uncontrolledHtml;
1007
+ const style = kit.vars;
1008
+ const className = props.className ? `${kit.className} ${props.className}` : kit.className;
1009
+ const showToolbar = !props.readOnly;
1010
+ const syncEditorState = React5.useCallback(
1011
+ (nextHtml) => {
1012
+ const normalizedHtml = normalizeRichTextHtml(nextHtml);
1013
+ const emptyState = isRichTextHtmlEmpty(normalizedHtml);
1014
+ if (!isControlled) {
1015
+ setUncontrolledHtml(normalizedHtml);
1016
+ }
1017
+ setIsEditorEmpty(emptyState);
1018
+ props.onValueChange?.(normalizedHtml);
1019
+ return normalizedHtml;
1020
+ },
1021
+ [isControlled, props]
1022
+ );
1023
+ const refreshActiveFormats = React5.useCallback(() => {
1024
+ setActiveFormats(getActiveFormatsFromSelection(editorElementRef.current));
1025
+ }, []);
1026
+ React5.useLayoutEffect(() => {
1027
+ const editorElement = editorElementRef.current;
1028
+ if (!editorElement) {
1029
+ return;
1030
+ }
1031
+ const normalizedDomHtml = normalizeRichTextHtml(editorElement.innerHTML);
1032
+ if (normalizedDomHtml !== editorHtml) {
1033
+ editorElement.innerHTML = editorHtml;
1034
+ }
1035
+ setIsEditorEmpty(isRichTextHtmlEmpty(editorHtml));
1036
+ }, [editorHtml]);
1037
+ React5.useEffect(() => {
1038
+ if (typeof document === "undefined") {
1039
+ return void 0;
1040
+ }
1041
+ const handleSelectionChange = () => {
1042
+ refreshActiveFormats();
1043
+ };
1044
+ document.addEventListener("selectionchange", handleSelectionChange);
1045
+ return () => {
1046
+ document.removeEventListener("selectionchange", handleSelectionChange);
1047
+ };
1048
+ }, [refreshActiveFormats]);
1049
+ const handleInput = () => {
1050
+ const editorElement = editorElementRef.current;
1051
+ if (!editorElement || props.disabled || props.readOnly) {
1052
+ return;
1053
+ }
1054
+ syncEditorState(editorElement.innerHTML);
1055
+ refreshActiveFormats();
1056
+ };
1057
+ const toggleFormat = (format) => {
1058
+ if (props.disabled || props.readOnly || typeof document === "undefined") {
1059
+ return;
1060
+ }
1061
+ const commandDocument = getRichTextCommandDocument();
1062
+ const editorElement = editorElementRef.current;
1063
+ if (!editorElement) {
1064
+ return;
1065
+ }
1066
+ ensureEditorSelection(editorElement);
1067
+ const activeFormatsBeforeToggle = getActiveFormatsFromSelection(editorElement);
1068
+ if (exitActiveFormatAtCaret(editorElement, format)) {
1069
+ if (typeof commandDocument.queryCommandState === "function" && commandDocument.queryCommandState(richTextCommandByFormat[format]) && typeof commandDocument.execCommand === "function") {
1070
+ commandDocument.execCommand(richTextCommandByFormat[format]);
1071
+ }
1072
+ if (typeof commandDocument.queryCommandState === "function" && typeof commandDocument.execCommand === "function") {
1073
+ for (const activeFormat of activeFormatsBeforeToggle) {
1074
+ if (activeFormat === format) {
1075
+ continue;
1076
+ }
1077
+ if (!commandDocument.queryCommandState(richTextCommandByFormat[activeFormat])) {
1078
+ commandDocument.execCommand(richTextCommandByFormat[activeFormat]);
1079
+ }
1080
+ }
1081
+ }
1082
+ syncEditorState(editorElement.innerHTML);
1083
+ refreshActiveFormats();
1084
+ return;
1085
+ }
1086
+ if (typeof commandDocument.execCommand === "function") {
1087
+ commandDocument.execCommand(richTextCommandByFormat[format]);
1088
+ }
1089
+ syncEditorState(editorElement.innerHTML);
1090
+ refreshActiveFormats();
1091
+ };
1092
+ const handleKeyDown = (event) => {
1093
+ if (!(event.metaKey || event.ctrlKey) || event.altKey) {
1094
+ return;
1095
+ }
1096
+ const formatByKey = {
1097
+ b: "bold",
1098
+ i: "italic",
1099
+ u: "underline"
1100
+ };
1101
+ const requestedFormat = formatByKey[event.key.toLowerCase()];
1102
+ if (!requestedFormat || !allowedFormats.includes(requestedFormat)) {
1103
+ return;
1104
+ }
1105
+ event.preventDefault();
1106
+ toggleFormat(requestedFormat);
1107
+ };
1108
+ return /* @__PURE__ */ jsxs("div", { className, style, ...kit.dataAttributes, children: [
1109
+ showToolbar && /* @__PURE__ */ jsx("div", { className: "mw-rich-text__toolbar", "data-rich-text-toolbar": true, children: allowedFormats.map((format) => {
1110
+ const isActive = activeFormats.includes(format);
1111
+ const iconName = format === "bold" ? "bold" : format === "italic" ? "italic" : "underline";
1112
+ return /* @__PURE__ */ jsx(
1113
+ "button",
1114
+ {
1115
+ type: "button",
1116
+ className: "mw-rich-text__toolbar-button",
1117
+ "data-format": format,
1118
+ "data-active": isActive ? "true" : void 0,
1119
+ "aria-label": formatLabels[format],
1120
+ "aria-pressed": isActive,
1121
+ disabled: props.disabled,
1122
+ onMouseDown: (event) => {
1123
+ event.preventDefault();
1124
+ },
1125
+ onClick: () => {
1126
+ toggleFormat(format);
1127
+ },
1128
+ children: /* @__PURE__ */ jsx(Icon, { name: iconName, size: "xs", decorative: true })
1129
+ },
1130
+ format
1131
+ );
1132
+ }) }),
1133
+ /* @__PURE__ */ jsx(
1134
+ "div",
1135
+ {
1136
+ ref: mergeRefs(editorElementRef, forwardedRef),
1137
+ className: "mw-rich-text__editor",
1138
+ "data-rich-text-editor": true,
1139
+ "data-empty": isEditorEmpty ? "true" : void 0,
1140
+ "data-placeholder": props.placeholder,
1141
+ id: kit.a11y.id,
1142
+ role: kit.a11y.role,
1143
+ tabIndex: kit.a11y.tabIndex,
1144
+ "aria-label": kit.a11y.ariaLabel,
1145
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
1146
+ "aria-describedby": kit.a11y.ariaDescribedBy,
1147
+ "aria-invalid": kit.a11y.ariaInvalid,
1148
+ "aria-disabled": kit.a11y.ariaDisabled,
1149
+ "aria-readonly": kit.a11y.ariaReadOnly,
1150
+ "aria-required": kit.a11y.ariaRequired,
1151
+ "aria-multiline": kit.a11y.ariaMultiline,
1152
+ contentEditable: !props.disabled && !props.readOnly,
1153
+ suppressContentEditableWarning: true,
1154
+ onInput: handleInput,
1155
+ onKeyDown: handleKeyDown,
1156
+ onFocus: refreshActiveFormats,
1157
+ onBlur: () => {
1158
+ syncEditorState(editorElementRef.current?.innerHTML ?? "");
1159
+ setActiveFormats([]);
1160
+ }
1161
+ }
1162
+ ),
1163
+ props.name && /* @__PURE__ */ jsx("input", { type: "hidden", name: props.name, value: editorHtml, disabled: props.disabled })
1164
+ ] });
1165
+ });
1166
+ RichText.displayName = "RichText";
339
1167
  function Paragraph(props) {
340
1168
  const { children, className: customClassName, style: customStyle, ...opts } = props;
341
1169
  const theme = useTheme();
@@ -347,76 +1175,3053 @@ function Paragraph(props) {
347
1175
  function cx(...parts) {
348
1176
  return parts.filter(Boolean).join(" ");
349
1177
  }
350
- function CheckboxField(props) {
351
- const reactId = React2.useId();
352
- const id = props.id ?? `mw-checkbox-${reactId}`;
353
- const hasDescription = props.description !== void 0;
354
- const hasError = props.error !== void 0;
355
- const descId = hasDescription ? `${id}-desc` : void 0;
356
- const errorId = hasError ? `${id}-error` : void 0;
357
- const describedByParts = [props.ariaDescribedBy, descId, errorId].filter(Boolean);
358
- const mergedDescribedBy = describedByParts.length > 0 ? describedByParts.join(" ") : void 0;
359
- const disabled = props.checkbox.disabled || false;
360
- const invalid = hasError || props.checkbox.invalid || false;
1178
+ function hasTextContent(value) {
1179
+ return value !== void 0 && value.trim().length > 0;
1180
+ }
1181
+ function InputField(props) {
1182
+ const reactId = React5.useId();
1183
+ const id = props.id ?? `mw-input-${reactId}`;
1184
+ const isPasswordField = props.input.type === "password";
1185
+ const [showPassword, setShowPassword] = React5.useState(false);
1186
+ const isSearchField = props.input.type === "search";
1187
+ const [searchValue, setSearchValue] = React5.useState(
1188
+ props.input.value || props.input.defaultValue || ""
1189
+ );
1190
+ const hasSearchValue = isSearchField && (props.input.value !== void 0 ? String(props.input.value).length > 0 : String(searchValue).length > 0);
1191
+ const hasHelperText = hasTextContent(props.helperText);
1192
+ const hasError = hasTextContent(props.error);
1193
+ const {
1194
+ helperTextId,
1195
+ errorId,
1196
+ describedBy: mergedDescribedBy
1197
+ } = buildInputFieldA11yIds({
1198
+ id,
1199
+ hasHelperText,
1200
+ hasError,
1201
+ externalDescribedBy: props.ariaDescribedBy
1202
+ });
1203
+ const disabled = props.input.disabled || false;
1204
+ const readOnly = props.input.readOnly || false;
1205
+ const invalid = hasError || props.input.invalid || false;
1206
+ const showSearchClearButton = hasSearchValue && !disabled && !readOnly;
1207
+ const showSearchIcon = isSearchField && !showSearchClearButton;
361
1208
  const wrapperClass = cx(
362
- "mw-checkbox-field",
363
- disabled && "mw-checkbox-field--disabled",
364
- invalid && "mw-checkbox-field--invalid"
1209
+ "mw-input-field",
1210
+ disabled && "mw-input-field--disabled",
1211
+ invalid && "mw-input-field--invalid",
1212
+ readOnly && "mw-input-field--readonly"
365
1213
  );
366
- const checkboxProps = {
367
- ...props.checkbox,
1214
+ const inputProps = {
1215
+ ...props.input,
368
1216
  id,
369
1217
  invalid
370
1218
  };
1219
+ if (isPasswordField && showPassword) {
1220
+ inputProps.type = "text";
1221
+ }
1222
+ if (isSearchField) {
1223
+ const originalOnValueChange = props.input.onValueChange;
1224
+ if (props.input.value === void 0) {
1225
+ inputProps.value = searchValue;
1226
+ }
1227
+ inputProps.onValueChange = (value) => {
1228
+ setSearchValue(value);
1229
+ originalOnValueChange?.(value);
1230
+ };
1231
+ }
371
1232
  if (mergedDescribedBy) {
372
- checkboxProps.ariaDescribedBy = mergedDescribedBy;
1233
+ inputProps.describedBy = mergedDescribedBy;
373
1234
  }
1235
+ const handleTogglePassword = () => {
1236
+ setShowPassword((prev) => !prev);
1237
+ };
1238
+ const handleClearSearch = () => {
1239
+ setSearchValue("");
1240
+ props.input.onValueChange?.("");
1241
+ };
374
1242
  return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
375
- /* @__PURE__ */ jsxs("div", { className: "mw-checkbox-field__row", children: [
376
- /* @__PURE__ */ jsx(Checkbox, { ...checkboxProps }),
377
- /* @__PURE__ */ jsx("label", { className: "mw-checkbox-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) })
1243
+ /* @__PURE__ */ jsx("label", { className: "mw-input-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
1244
+ /* @__PURE__ */ jsxs("div", { className: "mw-input-field__input-wrapper", children: [
1245
+ props.leadingSymbol && /* @__PURE__ */ jsx("span", { className: "mw-input-field__leading-symbol", "aria-hidden": "true", children: props.leadingSymbol }),
1246
+ /* @__PURE__ */ jsx(Input, { ...inputProps }),
1247
+ isPasswordField && !disabled && /* @__PURE__ */ jsx(
1248
+ "button",
1249
+ {
1250
+ type: "button",
1251
+ className: "mw-input-field__toggle-password",
1252
+ onClick: handleTogglePassword,
1253
+ "aria-label": showPassword ? "Hide password" : "Show password",
1254
+ tabIndex: 0,
1255
+ children: /* @__PURE__ */ jsx(Icon, { name: showPassword ? "eyeOff" : "eye", size: "xs", decorative: true })
1256
+ }
1257
+ ),
1258
+ showSearchIcon && /* @__PURE__ */ jsx("span", { className: "mw-input-field__search-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon, { name: "search", size: "xs", decorative: true }) }),
1259
+ showSearchClearButton && /* @__PURE__ */ jsx(
1260
+ "button",
1261
+ {
1262
+ type: "button",
1263
+ className: "mw-input-field__clear-search",
1264
+ onClick: handleClearSearch,
1265
+ "aria-label": "Clear search",
1266
+ tabIndex: 0,
1267
+ children: /* @__PURE__ */ jsx(Icon, { name: "x", size: "xs", decorative: true })
1268
+ }
1269
+ )
378
1270
  ] }),
379
- hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-field__description", id: descId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
380
- hasError && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
1271
+ hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.helperText }) }),
1272
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
381
1273
  ] });
382
1274
  }
383
1275
  function cx2(...parts) {
384
1276
  return parts.filter(Boolean).join(" ");
385
1277
  }
386
- function InputField(props) {
387
- const reactId = React2.useId();
388
- const id = props.id ?? `mw-input-${reactId}`;
389
- const hasHelperText = props.helperText !== void 0;
390
- const hasError = props.error !== void 0;
391
- const helperTextId = hasHelperText ? `${id}-helper` : void 0;
392
- const errorId = hasError ? `${id}-error` : void 0;
393
- const describedByParts = [props.ariaDescribedBy, helperTextId, errorId].filter(Boolean);
394
- const mergedDescribedBy = describedByParts.length > 0 ? describedByParts.join(" ") : void 0;
395
- const disabled = props.input.disabled || false;
396
- const readOnly = props.input.readOnly || false;
397
- const invalid = hasError || props.input.invalid || false;
398
- const wrapperClass = cx2(
1278
+ function hasTextContent2(value) {
1279
+ return value !== void 0 && value.trim().length > 0;
1280
+ }
1281
+ function InputOtp(props) {
1282
+ const reactId = React5.useId();
1283
+ const id = props.id ?? `mw-input-otp-${reactId}`;
1284
+ const otpLength = Math.max(1, props.length ?? 6);
1285
+ const hasHelperText = hasTextContent2(props.helperText);
1286
+ const hasError = hasTextContent2(props.error);
1287
+ const invalid = hasError || props.invalid === true;
1288
+ const isControlled = props.value !== void 0;
1289
+ const [uncontrolledValue, setUncontrolledValue] = React5.useState(() => {
1290
+ return sanitizeInputOtpValue(props.defaultValue, otpLength);
1291
+ });
1292
+ const currentValue = sanitizeInputOtpValue(
1293
+ isControlled ? props.value : uncontrolledValue,
1294
+ otpLength
1295
+ );
1296
+ const {
1297
+ helperTextId,
1298
+ errorId,
1299
+ describedBy: mergedDescribedBy
1300
+ } = buildInputFieldA11yIds({
1301
+ id,
1302
+ hasHelperText,
1303
+ hasError,
1304
+ externalDescribedBy: props.ariaDescribedBy
1305
+ });
1306
+ const recipeOptions = {
1307
+ id,
1308
+ value: currentValue,
1309
+ length: otpLength,
1310
+ invalid
1311
+ };
1312
+ if (props.name) {
1313
+ recipeOptions.name = props.name;
1314
+ }
1315
+ if (props.placeholderCharacter) {
1316
+ recipeOptions.placeholderCharacter = props.placeholderCharacter;
1317
+ }
1318
+ if (props.disabled) {
1319
+ recipeOptions.disabled = true;
1320
+ }
1321
+ if (props.readOnly) {
1322
+ recipeOptions.readOnly = true;
1323
+ }
1324
+ if (props.required) {
1325
+ recipeOptions.required = true;
1326
+ }
1327
+ if (mergedDescribedBy) {
1328
+ recipeOptions.describedBy = mergedDescribedBy;
1329
+ }
1330
+ if (props.ariaLabel) {
1331
+ recipeOptions.ariaLabel = props.ariaLabel;
1332
+ }
1333
+ const kit = createInputOtpRecipe(recipeOptions);
1334
+ const className = cx2(kit.className, props.className);
1335
+ const style = kit.vars;
1336
+ const handleChange = (event) => {
1337
+ const nextValue = sanitizeInputOtpValue(event.target.value, otpLength);
1338
+ if (!isControlled) {
1339
+ setUncontrolledValue(nextValue);
1340
+ }
1341
+ props.onValueChange?.(nextValue);
1342
+ };
1343
+ return /* @__PURE__ */ jsxs(
1344
+ "div",
1345
+ {
1346
+ className,
1347
+ style,
1348
+ "data-component": "input-otp",
1349
+ "data-invalid": invalid ? "true" : void 0,
1350
+ "data-disabled": props.disabled ? "true" : void 0,
1351
+ children: [
1352
+ /* @__PURE__ */ jsx("label", { className: "mw-input-otp__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
1353
+ /* @__PURE__ */ jsxs("div", { className: "mw-input-otp__cells", children: [
1354
+ kit.displayCells.map((displayCell) => /* @__PURE__ */ jsx(
1355
+ "span",
1356
+ {
1357
+ className: cx2("mw-input-otp__cell", displayCell.filled && "mw-input-otp__cell--filled"),
1358
+ "aria-hidden": "true",
1359
+ children: displayCell.character
1360
+ },
1361
+ displayCell.key
1362
+ )),
1363
+ /* @__PURE__ */ jsx(
1364
+ "input",
1365
+ {
1366
+ id: kit.a11y.id,
1367
+ className: "mw-input-otp__input",
1368
+ type: "text",
1369
+ name: kit.a11y.name,
1370
+ inputMode: kit.a11y.inputMode,
1371
+ autoComplete: kit.a11y.autoComplete,
1372
+ maxLength: kit.a11y.maxLength,
1373
+ pattern: kit.a11y.pattern,
1374
+ disabled: kit.a11y.disabled,
1375
+ readOnly: kit.a11y.readOnly,
1376
+ required: kit.a11y.required,
1377
+ "aria-label": kit.a11y.ariaLabel,
1378
+ "aria-invalid": kit.a11y.ariaInvalid,
1379
+ "aria-describedby": kit.a11y.ariaDescribedBy,
1380
+ value: kit.displayValue,
1381
+ onChange: handleChange
1382
+ }
1383
+ )
1384
+ ] }),
1385
+ 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
1386
+ ]
1387
+ }
1388
+ );
1389
+ }
1390
+ function cx3(...parts) {
1391
+ return parts.filter(Boolean).join(" ");
1392
+ }
1393
+ function hasTextContent3(value) {
1394
+ return value !== void 0 && value.trim().length > 0;
1395
+ }
1396
+ function getInitialSelectValue2(props) {
1397
+ if (props.value !== void 0) {
1398
+ return props.value;
1399
+ }
1400
+ if (props.defaultValue !== void 0) {
1401
+ return props.defaultValue;
1402
+ }
1403
+ if (props.placeholder !== void 0) {
1404
+ return "";
1405
+ }
1406
+ return props.options[0]?.value ?? "";
1407
+ }
1408
+ function getFirstEnabledOptionIndex(options) {
1409
+ return options.findIndex((option) => !option.disabled);
1410
+ }
1411
+ function getLastEnabledOptionIndex(options) {
1412
+ for (let index = options.length - 1; index >= 0; index -= 1) {
1413
+ if (!options[index]?.disabled) {
1414
+ return index;
1415
+ }
1416
+ }
1417
+ return -1;
1418
+ }
1419
+ function getSelectedOptionIndex(options, value) {
1420
+ return options.findIndex((option) => option.value === value && !option.disabled);
1421
+ }
1422
+ function getInitialActiveOptionIndex(options, value) {
1423
+ const selectedIndex = getSelectedOptionIndex(options, value);
1424
+ if (selectedIndex !== -1) {
1425
+ return selectedIndex;
1426
+ }
1427
+ return getFirstEnabledOptionIndex(options);
1428
+ }
1429
+ function getNextEnabledOptionIndex(options, currentIndex, direction) {
1430
+ if (options.length === 0) {
1431
+ return -1;
1432
+ }
1433
+ let nextIndex = currentIndex;
1434
+ for (let attempts = 0; attempts < options.length; attempts += 1) {
1435
+ nextIndex = (nextIndex + direction + options.length) % options.length;
1436
+ if (!options[nextIndex]?.disabled) {
1437
+ return nextIndex;
1438
+ }
1439
+ }
1440
+ return currentIndex;
1441
+ }
1442
+ function MarwesSelectFieldControl(props) {
1443
+ const { id, select } = props;
1444
+ const listboxId = `${id}-listbox`;
1445
+ const isControlled = select.value !== void 0;
1446
+ const [internalValue, setInternalValue] = React5.useState(() => getInitialSelectValue2(select));
1447
+ const value = isControlled ? select.value ?? "" : internalValue;
1448
+ const [open, setOpen] = React5.useState(false);
1449
+ const [activeIndex, setActiveIndex] = React5.useState(
1450
+ () => getInitialActiveOptionIndex(select.options, value)
1451
+ );
1452
+ const rootRef = React5.useRef(null);
1453
+ const buttonRef = React5.useRef(null);
1454
+ const selectedOption = select.options.find((option) => option.value === value) ?? (select.placeholder === void 0 ? select.options[0] : void 0);
1455
+ const placeholderSelected = select.placeholder !== void 0 && value === "";
1456
+ const displayText = placeholderSelected ? select.placeholder : selectedOption?.label ?? "";
1457
+ React5.useEffect(() => {
1458
+ if (!open) {
1459
+ return;
1460
+ }
1461
+ function handlePointerDown(event) {
1462
+ if (rootRef.current?.contains(event.target)) {
1463
+ return;
1464
+ }
1465
+ setOpen(false);
1466
+ }
1467
+ document.addEventListener("pointerdown", handlePointerDown);
1468
+ return () => {
1469
+ document.removeEventListener("pointerdown", handlePointerDown);
1470
+ };
1471
+ }, [open]);
1472
+ React5.useEffect(() => {
1473
+ if (!open) {
1474
+ return;
1475
+ }
1476
+ setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1477
+ }, [open, select.options, value]);
1478
+ React5.useEffect(() => {
1479
+ if (!select.disabled) {
1480
+ return;
1481
+ }
1482
+ setOpen(false);
1483
+ }, [select.disabled]);
1484
+ const commitValue = (nextValue) => {
1485
+ if (!isControlled) {
1486
+ setInternalValue(nextValue);
1487
+ }
1488
+ select.onValueChange?.(nextValue);
1489
+ };
1490
+ const selectOptionAtIndex = (index) => {
1491
+ const option = select.options[index];
1492
+ if (!option || option.disabled) {
1493
+ return;
1494
+ }
1495
+ commitValue(option.value);
1496
+ setOpen(false);
1497
+ buttonRef.current?.focus();
1498
+ };
1499
+ const handleKeyDown = (event) => {
1500
+ if (select.disabled) {
1501
+ return;
1502
+ }
1503
+ switch (event.key) {
1504
+ case "ArrowDown": {
1505
+ event.preventDefault();
1506
+ if (!open) {
1507
+ setOpen(true);
1508
+ setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1509
+ return;
1510
+ }
1511
+ setActiveIndex((currentIndex) => getNextEnabledOptionIndex(select.options, currentIndex, 1));
1512
+ return;
1513
+ }
1514
+ case "ArrowUp": {
1515
+ event.preventDefault();
1516
+ if (!open) {
1517
+ setOpen(true);
1518
+ setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1519
+ return;
1520
+ }
1521
+ setActiveIndex(
1522
+ (currentIndex) => getNextEnabledOptionIndex(select.options, currentIndex, -1)
1523
+ );
1524
+ return;
1525
+ }
1526
+ case "Home": {
1527
+ if (!open) {
1528
+ return;
1529
+ }
1530
+ event.preventDefault();
1531
+ setActiveIndex(getFirstEnabledOptionIndex(select.options));
1532
+ return;
1533
+ }
1534
+ case "End": {
1535
+ if (!open) {
1536
+ return;
1537
+ }
1538
+ event.preventDefault();
1539
+ setActiveIndex(getLastEnabledOptionIndex(select.options));
1540
+ return;
1541
+ }
1542
+ case "Enter":
1543
+ case " ": {
1544
+ event.preventDefault();
1545
+ if (!open) {
1546
+ setOpen(true);
1547
+ setActiveIndex(getInitialActiveOptionIndex(select.options, value));
1548
+ return;
1549
+ }
1550
+ if (activeIndex !== -1) {
1551
+ selectOptionAtIndex(activeIndex);
1552
+ }
1553
+ return;
1554
+ }
1555
+ case "Escape": {
1556
+ if (!open) {
1557
+ return;
1558
+ }
1559
+ event.preventDefault();
1560
+ setOpen(false);
1561
+ return;
1562
+ }
1563
+ case "Tab": {
1564
+ setOpen(false);
1565
+ return;
1566
+ }
1567
+ default:
1568
+ return;
1569
+ }
1570
+ };
1571
+ return /* @__PURE__ */ jsxs(
1572
+ "div",
1573
+ {
1574
+ ref: rootRef,
1575
+ className: cx3("mw-select-field__control", open && "mw-select-field__control--open"),
1576
+ children: [
1577
+ /* @__PURE__ */ jsxs(
1578
+ "button",
1579
+ {
1580
+ ref: buttonRef,
1581
+ id,
1582
+ type: "button",
1583
+ className: cx3(
1584
+ "mw-select-field__trigger",
1585
+ placeholderSelected && "mw-select-field__trigger--placeholder",
1586
+ select.invalid && "is-invalid",
1587
+ open && "mw-select-field__trigger--open"
1588
+ ),
1589
+ role: "combobox",
1590
+ "aria-controls": listboxId,
1591
+ "aria-expanded": open,
1592
+ "aria-haspopup": "listbox",
1593
+ "aria-describedby": select.describedBy,
1594
+ "aria-invalid": select.invalid ? "true" : void 0,
1595
+ "aria-required": select.required ? "true" : void 0,
1596
+ "aria-activedescendant": open && activeIndex !== -1 ? `${id}-option-${activeIndex}` : void 0,
1597
+ disabled: select.disabled,
1598
+ "data-placeholder-selected": placeholderSelected ? "true" : void 0,
1599
+ onClick: () => {
1600
+ if (select.disabled) {
1601
+ return;
1602
+ }
1603
+ setOpen((currentOpen) => !currentOpen);
1604
+ },
1605
+ onKeyDown: handleKeyDown,
1606
+ children: [
1607
+ /* @__PURE__ */ jsx("span", { className: "mw-select-field__trigger-text", children: displayText }),
1608
+ /* @__PURE__ */ jsx(SelectArrowIcon, { className: "mw-select-field__trigger-icon" })
1609
+ ]
1610
+ }
1611
+ ),
1612
+ select.name ? /* @__PURE__ */ jsx(
1613
+ "input",
1614
+ {
1615
+ "aria-hidden": "true",
1616
+ className: "mw-select-field__proxy-input",
1617
+ name: select.name,
1618
+ type: "hidden",
1619
+ value,
1620
+ readOnly: true
1621
+ }
1622
+ ) : null,
1623
+ 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) => {
1624
+ const selected = option.value === value;
1625
+ const active = optionIndex === activeIndex;
1626
+ return /* @__PURE__ */ jsxs(
1627
+ "div",
1628
+ {
1629
+ id: `${id}-option-${optionIndex}`,
1630
+ className: cx3(
1631
+ "mw-select-field__option",
1632
+ active && "mw-select-field__option--active",
1633
+ selected && "mw-select-field__option--selected",
1634
+ option.disabled && "mw-select-field__option--disabled"
1635
+ ),
1636
+ role: "option",
1637
+ "aria-selected": selected,
1638
+ "aria-disabled": option.disabled ? "true" : void 0,
1639
+ tabIndex: -1,
1640
+ onClick: () => selectOptionAtIndex(optionIndex),
1641
+ onKeyDown: (event) => {
1642
+ if (option.disabled) {
1643
+ return;
1644
+ }
1645
+ if (event.key === "Enter" || event.key === " ") {
1646
+ event.preventDefault();
1647
+ selectOptionAtIndex(optionIndex);
1648
+ }
1649
+ },
1650
+ onMouseDown: (event) => event.preventDefault(),
1651
+ onMouseEnter: () => {
1652
+ if (!option.disabled) {
1653
+ setActiveIndex(optionIndex);
1654
+ }
1655
+ },
1656
+ children: [
1657
+ /* @__PURE__ */ jsx("span", { className: "mw-select-field__option-label", children: option.label }),
1658
+ selected ? /* @__PURE__ */ jsx(
1659
+ Icon,
1660
+ {
1661
+ className: "mw-select-field__option-check",
1662
+ name: IconName.Check,
1663
+ size: "xs",
1664
+ decorative: true
1665
+ }
1666
+ ) : null
1667
+ ]
1668
+ },
1669
+ option.value
1670
+ );
1671
+ }) }) }) : null
1672
+ ]
1673
+ }
1674
+ );
1675
+ }
1676
+ function SelectField(props) {
1677
+ const reactId = React5.useId();
1678
+ const id = props.id ?? `mw-select-${reactId}`;
1679
+ const mode = resolveSelectMode(props.select);
1680
+ const hasHelperText = hasTextContent3(props.helperText);
1681
+ const hasError = hasTextContent3(props.error);
1682
+ const {
1683
+ helperTextId,
1684
+ errorId,
1685
+ describedBy: mergedDescribedBy
1686
+ } = buildInputFieldA11yIds({
1687
+ id,
1688
+ hasHelperText,
1689
+ hasError,
1690
+ externalDescribedBy: props.ariaDescribedBy
1691
+ });
1692
+ const disabled = props.select.disabled || false;
1693
+ const invalid = hasError || props.select.invalid || false;
1694
+ const wrapperClass = cx3(
399
1695
  "mw-input-field",
1696
+ "mw-input-field--select",
1697
+ mode === "marwes" && "mw-input-field--select-marwes",
400
1698
  disabled && "mw-input-field--disabled",
401
- invalid && "mw-input-field--invalid",
402
- readOnly && "mw-input-field--readonly"
1699
+ invalid && "mw-input-field--invalid"
403
1700
  );
404
- const inputProps = {
405
- ...props.input,
1701
+ const selectProps = {
1702
+ ...props.select,
406
1703
  id,
407
1704
  invalid
408
1705
  };
409
1706
  if (mergedDescribedBy) {
410
- inputProps.describedBy = mergedDescribedBy;
1707
+ selectProps.describedBy = mergedDescribedBy;
411
1708
  }
412
1709
  return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
413
1710
  /* @__PURE__ */ jsx("label", { className: "mw-input-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
414
- /* @__PURE__ */ jsx(Input, { ...inputProps }),
1711
+ /* @__PURE__ */ jsx("div", { className: "mw-input-field__input-wrapper", children: mode === "native" ? /* @__PURE__ */ jsx(Select, { ...selectProps, native: true }) : /* @__PURE__ */ jsx(MarwesSelectFieldControl, { id, select: selectProps }) }),
415
1712
  hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.helperText }) }),
416
1713
  hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
417
1714
  ] });
418
1715
  }
1716
+ function cx4(...parts) {
1717
+ return parts.filter(Boolean).join(" ");
1718
+ }
1719
+ function hasTextContent4(value) {
1720
+ return value !== void 0 && value.trim().length > 0;
1721
+ }
1722
+ function TextareaField(props) {
1723
+ const reactId = React5.useId();
1724
+ const id = props.id ?? `mw-textarea-${reactId}`;
1725
+ const hasHelperText = hasTextContent4(props.helperText);
1726
+ const hasError = hasTextContent4(props.error);
1727
+ const {
1728
+ helperTextId,
1729
+ errorId,
1730
+ describedBy: mergedDescribedBy
1731
+ } = buildInputFieldA11yIds({
1732
+ id,
1733
+ hasHelperText,
1734
+ hasError,
1735
+ externalDescribedBy: props.ariaDescribedBy
1736
+ });
1737
+ const disabled = props.textarea.disabled || false;
1738
+ const readOnly = props.textarea.readOnly || false;
1739
+ const invalid = hasError || props.textarea.invalid || false;
1740
+ const wrapperClass = cx4(
1741
+ "mw-input-field",
1742
+ "mw-input-field--textarea",
1743
+ disabled && "mw-input-field--disabled",
1744
+ invalid && "mw-input-field--invalid",
1745
+ readOnly && "mw-input-field--readonly"
1746
+ );
1747
+ const textareaProps = {
1748
+ ...props.textarea,
1749
+ id,
1750
+ invalid
1751
+ };
1752
+ if (mergedDescribedBy) {
1753
+ textareaProps.describedBy = mergedDescribedBy;
1754
+ }
1755
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
1756
+ /* @__PURE__ */ jsx("label", { className: "mw-input-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
1757
+ /* @__PURE__ */ jsx("div", { className: "mw-input-field__input-wrapper", children: /* @__PURE__ */ jsx(Textarea, { ...textareaProps }) }),
1758
+ hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.helperText }) }),
1759
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
1760
+ ] });
1761
+ }
1762
+ function cx5(...parts) {
1763
+ return parts.filter(Boolean).join(" ");
1764
+ }
1765
+ function hasTextContent5(value) {
1766
+ return value !== void 0 && value.trim().length > 0;
1767
+ }
1768
+ function RichTextField(props) {
1769
+ const reactId = React5.useId();
1770
+ const id = props.id ?? `mw-rich-text-${reactId}`;
1771
+ const editorRef = React5.useRef(null);
1772
+ const hasHelperText = hasTextContent5(props.helperText);
1773
+ const hasError = hasTextContent5(props.error);
1774
+ const { labelId, helperTextId, errorId, describedBy } = buildRichTextFieldA11yIds({
1775
+ id,
1776
+ hasHelperText,
1777
+ hasError,
1778
+ externalDescribedBy: props.ariaDescribedBy
1779
+ });
1780
+ const disabled = props.editor.disabled || false;
1781
+ const readOnly = props.editor.readOnly || false;
1782
+ const invalid = hasError || props.editor.invalid || false;
1783
+ const wrapperClass = cx5(
1784
+ "mw-input-field",
1785
+ "mw-input-field--rich-text",
1786
+ disabled && "mw-input-field--disabled",
1787
+ invalid && "mw-input-field--invalid",
1788
+ readOnly && "mw-input-field--readonly"
1789
+ );
1790
+ const editorProps = {
1791
+ ...props.editor,
1792
+ id,
1793
+ invalid,
1794
+ labelledBy: labelId
1795
+ };
1796
+ if (describedBy) {
1797
+ editorProps.describedBy = describedBy;
1798
+ }
1799
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
1800
+ /* @__PURE__ */ jsx(
1801
+ "button",
1802
+ {
1803
+ type: "button",
1804
+ className: "mw-input-field__label",
1805
+ id: labelId,
1806
+ onClick: () => {
1807
+ editorRef.current?.focus();
1808
+ },
1809
+ children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label })
1810
+ }
1811
+ ),
1812
+ /* @__PURE__ */ jsx("div", { className: "mw-input-field__input-wrapper", children: /* @__PURE__ */ jsx(RichText, { ref: editorRef, ...editorProps }) }),
1813
+ hasHelperText && !hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__helper", id: helperTextId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.helperText }) }),
1814
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-input-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
1815
+ ] });
1816
+ }
1817
+ function DropdownField(props) {
1818
+ return /* @__PURE__ */ jsx("div", { "data-purpose": "dropdown", children: /* @__PURE__ */ jsx(
1819
+ SelectField,
1820
+ {
1821
+ ...props,
1822
+ select: {
1823
+ ...props.select,
1824
+ native: props.select.native ?? false
1825
+ }
1826
+ }
1827
+ ) });
1828
+ }
1829
+ function SearchField(props) {
1830
+ const enhancedInput = {
1831
+ ...props.input,
1832
+ type: "search",
1833
+ inputMode: "search"
1834
+ };
1835
+ return /* @__PURE__ */ jsx("div", { "data-purpose": "search", children: /* @__PURE__ */ jsx(InputField, { ...props, input: enhancedInput }) });
1836
+ }
1837
+ function PasswordField(props) {
1838
+ const { autoComplete = "current-password", ...restProps } = props;
1839
+ const enhancedInput = {
1840
+ ...props.input,
1841
+ type: "password",
1842
+ autoComplete
1843
+ };
1844
+ return /* @__PURE__ */ jsx("div", { "data-purpose": "password", children: /* @__PURE__ */ jsx(InputField, { ...restProps, input: enhancedInput }) });
1845
+ }
1846
+ function EmailField(props) {
1847
+ const enhancedInput = {
1848
+ ...props.input,
1849
+ type: "email",
1850
+ inputMode: "email",
1851
+ autoComplete: "email"
1852
+ };
1853
+ return /* @__PURE__ */ jsx("div", { "data-purpose": "email", children: /* @__PURE__ */ jsx(InputField, { ...props, input: enhancedInput }) });
1854
+ }
1855
+ function DateOfBirthField(props) {
1856
+ const enhancedInput = {
1857
+ ...props.input,
1858
+ type: "date",
1859
+ autoComplete: "bday"
1860
+ };
1861
+ return /* @__PURE__ */ jsx("div", { "data-purpose": "date-of-birth", children: /* @__PURE__ */ jsx(InputField, { ...props, input: enhancedInput }) });
1862
+ }
1863
+ function ZipCodeField(props) {
1864
+ const enhancedInput = {
1865
+ ...props.input,
1866
+ type: "text",
1867
+ inputMode: "numeric",
1868
+ autoComplete: "postal-code"
1869
+ };
1870
+ return /* @__PURE__ */ jsx("div", { "data-purpose": "zip-code", children: /* @__PURE__ */ jsx(InputField, { ...props, input: enhancedInput }) });
1871
+ }
1872
+ function PhoneField(props) {
1873
+ const enhancedInput = {
1874
+ ...props.input,
1875
+ type: "tel",
1876
+ inputMode: "tel",
1877
+ autoComplete: "tel"
1878
+ };
1879
+ return /* @__PURE__ */ jsx("div", { "data-purpose": "phone", children: /* @__PURE__ */ jsx(InputField, { ...props, input: enhancedInput }) });
1880
+ }
1881
+ function URLField(props) {
1882
+ const enhancedInput = {
1883
+ ...props.input,
1884
+ type: "url",
1885
+ inputMode: "url",
1886
+ autoComplete: "url"
1887
+ };
1888
+ return /* @__PURE__ */ jsx("div", { "data-purpose": "url", children: /* @__PURE__ */ jsx(InputField, { ...props, input: enhancedInput }) });
1889
+ }
1890
+ function CurrencyField(props) {
1891
+ const { currency, ...restProps } = props;
1892
+ const enhancedInput = {
1893
+ ...props.input,
1894
+ type: "text",
1895
+ inputMode: "decimal",
1896
+ onValueChange: (rawValue) => {
1897
+ const sanitizedValue = sanitizeCurrencyValue(rawValue);
1898
+ props.input?.onValueChange?.(sanitizedValue);
1899
+ }
1900
+ };
1901
+ const helperText = buildCurrencyHelperText(props.helperText, currency);
1902
+ const leadingSymbol = getCurrencySymbol(currency);
1903
+ return /* @__PURE__ */ jsx("div", { "data-purpose": "currency", "data-currency": currency, children: /* @__PURE__ */ jsx(
1904
+ InputField,
1905
+ {
1906
+ ...restProps,
1907
+ input: enhancedInput,
1908
+ helperText: helperText || "",
1909
+ ...leadingSymbol ? { leadingSymbol } : {}
1910
+ }
1911
+ ) });
1912
+ }
1913
+ function renderAvatarContent(content, isOuterShellAccessible, isDecorative) {
1914
+ if (content.type === "image") {
1915
+ return /* @__PURE__ */ jsx(
1916
+ "img",
1917
+ {
1918
+ className: "mw-avatar__image",
1919
+ src: content.src,
1920
+ alt: isDecorative ? "" : content.alt ?? ""
1921
+ }
1922
+ );
1923
+ }
1924
+ if (content.type === "initials") {
1925
+ return /* @__PURE__ */ jsx(
1926
+ "span",
1927
+ {
1928
+ "aria-hidden": isOuterShellAccessible ? "true" : void 0,
1929
+ className: "mw-avatar__initials",
1930
+ children: content.initials
1931
+ }
1932
+ );
1933
+ }
1934
+ return /* @__PURE__ */ jsx(Icon, { name: content.iconName ?? "user", className: "mw-avatar__icon", decorative: true });
1935
+ }
1936
+ function Avatar(props) {
1937
+ const {
1938
+ className,
1939
+ style,
1940
+ dataAttributes,
1941
+ size,
1942
+ type,
1943
+ initials,
1944
+ src,
1945
+ alt,
1946
+ iconName,
1947
+ decorative,
1948
+ ariaLabel,
1949
+ ...nativeSpanProps
1950
+ } = props;
1951
+ const ariaLabelFromNativeProps = typeof nativeSpanProps["aria-label"] === "string" ? nativeSpanProps["aria-label"] : void 0;
1952
+ const avatarOptions = {};
1953
+ if (size !== void 0) avatarOptions.size = size;
1954
+ if (type !== void 0) avatarOptions.type = type;
1955
+ if (initials !== void 0) avatarOptions.initials = initials;
1956
+ if (src !== void 0) avatarOptions.src = src;
1957
+ if (alt !== void 0) avatarOptions.alt = alt;
1958
+ if (iconName !== void 0) avatarOptions.iconName = iconName;
1959
+ if (decorative !== void 0) avatarOptions.decorative = decorative;
1960
+ const resolvedAriaLabel = ariaLabel ?? ariaLabelFromNativeProps;
1961
+ if (resolvedAriaLabel !== void 0) {
1962
+ avatarOptions.ariaLabel = resolvedAriaLabel;
1963
+ }
1964
+ const kit = createAvatarRecipe(avatarOptions);
1965
+ const mergedClassName = [kit.className, className].filter(Boolean).join(" ");
1966
+ const mergedStyle = { ...kit.vars, ...style };
1967
+ const isOuterShellAccessible = kit.a11y.role === "img";
1968
+ const isDecorative = kit.a11y.ariaHidden === true;
1969
+ return /* @__PURE__ */ jsx(
1970
+ "span",
1971
+ {
1972
+ ...nativeSpanProps,
1973
+ ...kit.dataAttributes,
1974
+ ...dataAttributes,
1975
+ className: mergedClassName,
1976
+ style: mergedStyle,
1977
+ role: kit.a11y.role,
1978
+ "aria-hidden": isDecorative ? "true" : void 0,
1979
+ "aria-label": kit.a11y.ariaLabel,
1980
+ children: renderAvatarContent(kit.content, isOuterShellAccessible, isDecorative)
1981
+ }
1982
+ );
1983
+ }
1984
+ function buildAvatarOptions(props) {
1985
+ const avatarOptions = {};
1986
+ if (props.size !== void 0) avatarOptions.size = props.size;
1987
+ if (props.type !== void 0) avatarOptions.type = props.type;
1988
+ if (props.initials !== void 0) avatarOptions.initials = props.initials;
1989
+ if (props.src !== void 0) avatarOptions.src = props.src;
1990
+ if (props.alt !== void 0) avatarOptions.alt = props.alt;
1991
+ if (props.iconName !== void 0) avatarOptions.iconName = props.iconName;
1992
+ if (props.decorative !== void 0) avatarOptions.decorative = props.decorative;
1993
+ const nativeAriaLabel = typeof props["aria-label"] === "string" ? props["aria-label"] : void 0;
1994
+ const resolvedAriaLabel = props.ariaLabel ?? nativeAriaLabel;
1995
+ if (resolvedAriaLabel !== void 0) {
1996
+ avatarOptions.ariaLabel = resolvedAriaLabel;
1997
+ }
1998
+ return avatarOptions;
1999
+ }
2000
+ function resolveAvatarBadgeLabel(avatarOptions, statusLabel) {
2001
+ const avatarKit = createAvatarRecipe(avatarOptions);
2002
+ if (avatarKit.a11y.ariaHidden) {
2003
+ return void 0;
2004
+ }
2005
+ if (avatarKit.content.type === "image") {
2006
+ return avatarKit.content.alt ? `${avatarKit.content.alt}, ${statusLabel}` : statusLabel;
2007
+ }
2008
+ return avatarKit.a11y.ariaLabel ? `${avatarKit.a11y.ariaLabel}, ${statusLabel}` : statusLabel;
2009
+ }
2010
+ function AvatarBadge(props) {
2011
+ const {
2012
+ className,
2013
+ dataAttributes,
2014
+ statusLabel = "Online",
2015
+ decorative,
2016
+ style,
2017
+ size,
2018
+ type,
2019
+ initials,
2020
+ src,
2021
+ alt,
2022
+ iconName,
2023
+ ariaLabel,
2024
+ ...nativeSpanProps
2025
+ } = props;
2026
+ const avatarOptions = buildAvatarOptions(props);
2027
+ const avatarKit = createAvatarRecipe(avatarOptions);
2028
+ const accessibleLabel = resolveAvatarBadgeLabel(avatarOptions, statusLabel);
2029
+ const resolvedSize = avatarKit.dataAttributes["data-size"];
2030
+ const mergedClassName = ["mw-avatar-badge", `mw-avatar-badge--${resolvedSize}`, className].filter(Boolean).join(" ");
2031
+ const innerAvatarProps = { decorative: true };
2032
+ if (size !== void 0) innerAvatarProps.size = size;
2033
+ if (type !== void 0) innerAvatarProps.type = type;
2034
+ if (initials !== void 0) innerAvatarProps.initials = initials;
2035
+ if (src !== void 0) innerAvatarProps.src = src;
2036
+ if (alt !== void 0) innerAvatarProps.alt = alt;
2037
+ if (iconName !== void 0) innerAvatarProps.iconName = iconName;
2038
+ if (ariaLabel !== void 0) innerAvatarProps.ariaLabel = ariaLabel;
2039
+ return /* @__PURE__ */ jsxs(
2040
+ "span",
2041
+ {
2042
+ ...nativeSpanProps,
2043
+ ...dataAttributes,
2044
+ className: mergedClassName,
2045
+ style,
2046
+ "data-component": "avatar-badge",
2047
+ "data-size": resolvedSize,
2048
+ "data-status": "online",
2049
+ role: decorative ? void 0 : "img",
2050
+ "aria-hidden": decorative ? "true" : void 0,
2051
+ "aria-label": decorative ? void 0 : accessibleLabel,
2052
+ children: [
2053
+ /* @__PURE__ */ jsx(Avatar, { ...innerAvatarProps }),
2054
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "mw-avatar-badge__indicator" })
2055
+ ]
2056
+ }
2057
+ );
2058
+ }
2059
+ function AvatarGroup(props) {
2060
+ const {
2061
+ items,
2062
+ overflowCount,
2063
+ overflowLabel,
2064
+ ariaLabel,
2065
+ className,
2066
+ dataAttributes,
2067
+ ...nativeFieldsetProps
2068
+ } = props;
2069
+ const nativeAriaLabel = typeof nativeFieldsetProps["aria-label"] === "string" ? nativeFieldsetProps["aria-label"] : void 0;
2070
+ const groupLabel = ariaLabel ?? nativeAriaLabel ?? "Avatar group";
2071
+ const mergedClassName = ["mw-avatar-group", className].filter(Boolean).join(" ");
2072
+ const shouldRenderOverflowCounter = overflowCount !== void 0 && overflowCount > 0;
2073
+ const resolvedOverflowLabel = overflowLabel ?? `${overflowCount} more people`;
2074
+ return /* @__PURE__ */ jsxs(
2075
+ "fieldset",
2076
+ {
2077
+ ...nativeFieldsetProps,
2078
+ ...dataAttributes,
2079
+ className: mergedClassName,
2080
+ "data-component": "avatar-group",
2081
+ "aria-label": groupLabel,
2082
+ children: [
2083
+ items.map((item, itemIndex) => /* @__PURE__ */ jsx(
2084
+ "span",
2085
+ {
2086
+ className: "mw-avatar-group__item",
2087
+ children: /* @__PURE__ */ jsx(Avatar, { ...item, size: "medium" })
2088
+ },
2089
+ item.id ?? `${itemIndex}-${item.initials ?? item.alt ?? "avatar"}`
2090
+ )),
2091
+ shouldRenderOverflowCounter ? /* @__PURE__ */ jsxs("span", { "aria-label": resolvedOverflowLabel, className: "mw-avatar-group__counter", role: "img", children: [
2092
+ "+",
2093
+ overflowCount
2094
+ ] }) : null
2095
+ ]
2096
+ }
2097
+ );
2098
+ }
2099
+ function ProfileAvatar(props) {
2100
+ return /* @__PURE__ */ jsx(
2101
+ Avatar,
2102
+ {
2103
+ ...props,
2104
+ dataAttributes: {
2105
+ ...props.dataAttributes,
2106
+ ...createPurposeSemanticAttributes("profile")
2107
+ }
2108
+ }
2109
+ );
2110
+ }
2111
+ function PresenceAvatar(props) {
2112
+ return /* @__PURE__ */ jsx(
2113
+ AvatarBadge,
2114
+ {
2115
+ ...props,
2116
+ dataAttributes: {
2117
+ ...props.dataAttributes,
2118
+ ...createPurposeSemanticAttributes("presence")
2119
+ }
2120
+ }
2121
+ );
2122
+ }
2123
+ function TeamAvatarGroup(props) {
2124
+ return /* @__PURE__ */ jsx(
2125
+ AvatarGroup,
2126
+ {
2127
+ ...props,
2128
+ dataAttributes: {
2129
+ ...props.dataAttributes,
2130
+ ...createPurposeSemanticAttributes("team")
2131
+ }
2132
+ }
2133
+ );
2134
+ }
2135
+ function Checkbox(props) {
2136
+ const { onCheckedChange, onChange, ...coreProps } = props;
2137
+ const kit = checkboxRecipe({ ...coreProps });
2138
+ const inputRef = React5.useRef(null);
2139
+ React5.useLayoutEffect(() => {
2140
+ const el = inputRef.current;
2141
+ if (!el) return;
2142
+ el.indeterminate = kit.indeterminate;
2143
+ }, [kit.indeterminate]);
2144
+ const handleChange = (e) => {
2145
+ onChange?.(e);
2146
+ onCheckedChange?.(e.currentTarget.checked);
2147
+ };
2148
+ const { a11y } = kit;
2149
+ return /* @__PURE__ */ jsx(
2150
+ "input",
2151
+ {
2152
+ ref: inputRef,
2153
+ type: "checkbox",
2154
+ className: kit.className,
2155
+ style: kit.vars,
2156
+ id: a11y.id,
2157
+ name: a11y.name,
2158
+ value: a11y.value,
2159
+ disabled: a11y.disabled === true,
2160
+ required: a11y.required === true,
2161
+ "aria-label": a11y.ariaLabel,
2162
+ "aria-labelledby": a11y.ariaLabelledBy,
2163
+ "aria-describedby": a11y.ariaDescribedBy,
2164
+ "aria-checked": a11y.ariaChecked,
2165
+ "aria-invalid": a11y.ariaInvalid === true ? true : void 0,
2166
+ checked: kit.checked,
2167
+ defaultChecked: kit.defaultChecked,
2168
+ onChange: handleChange
2169
+ }
2170
+ );
2171
+ }
2172
+ function cx6(...parts) {
2173
+ return parts.filter(Boolean).join(" ");
2174
+ }
2175
+ function hasContent(value) {
2176
+ if (value === void 0 || value === null || value === false) {
2177
+ return false;
2178
+ }
2179
+ if (typeof value === "string") {
2180
+ return value.trim().length > 0;
2181
+ }
2182
+ return true;
2183
+ }
2184
+ function CheckboxField(props) {
2185
+ const reactId = React5.useId();
2186
+ const id = props.id ?? `mw-checkbox-${reactId}`;
2187
+ const hasDescription = hasContent(props.description);
2188
+ const hasError = hasContent(props.error);
2189
+ const {
2190
+ descriptionId: descId,
2191
+ errorId,
2192
+ describedBy: mergedDescribedBy
2193
+ } = buildCheckboxFieldA11yIds({
2194
+ id,
2195
+ hasDescription,
2196
+ hasError,
2197
+ externalDescribedBy: props.ariaDescribedBy
2198
+ });
2199
+ const disabled = props.checkbox.disabled || false;
2200
+ const invalid = hasError || props.checkbox.invalid || false;
2201
+ const wrapperClass = cx6(
2202
+ "mw-checkbox-field",
2203
+ disabled && "mw-checkbox-field--disabled",
2204
+ invalid && "mw-checkbox-field--invalid"
2205
+ );
2206
+ const checkboxProps = {
2207
+ ...props.checkbox,
2208
+ id,
2209
+ invalid
2210
+ };
2211
+ if (mergedDescribedBy) {
2212
+ checkboxProps.ariaDescribedBy = mergedDescribedBy;
2213
+ }
2214
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, children: [
2215
+ /* @__PURE__ */ jsxs("div", { className: "mw-checkbox-field__row", children: [
2216
+ /* @__PURE__ */ jsx(Checkbox, { ...checkboxProps }),
2217
+ /* @__PURE__ */ jsx("label", { className: "mw-checkbox-field__label", htmlFor: id, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) })
2218
+ ] }),
2219
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-field__description", id: descId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
2220
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
2221
+ ] });
2222
+ }
2223
+ function hasContent2(value) {
2224
+ if (value === void 0 || value === null || value === false) return false;
2225
+ if (typeof value === "string") return value.trim().length > 0;
2226
+ return true;
2227
+ }
2228
+ function cx7(...parts) {
2229
+ return parts.filter(Boolean).join(" ");
2230
+ }
2231
+ function orderSelectedValues(values, options) {
2232
+ const optionValues = new Set(options.map((option) => option.value));
2233
+ const selectedValues = new Set(values);
2234
+ const knownValues = options.map((option) => option.value).filter((value) => selectedValues.has(value));
2235
+ const unknownValues = values.filter((value) => !optionValues.has(value));
2236
+ return [...knownValues, ...unknownValues];
2237
+ }
2238
+ function CheckboxGroupField(props) {
2239
+ const reactId = React5.useId();
2240
+ const id = props.id ?? `mw-checkbox-group-${reactId}`;
2241
+ const hasDescription = hasContent2(props.description);
2242
+ const hasError = hasContent2(props.error);
2243
+ const isInvalid = hasError;
2244
+ const { labelId, descriptionId, errorId, describedBy } = buildCheckboxGroupFieldA11yIds({
2245
+ id,
2246
+ hasDescription,
2247
+ hasError,
2248
+ externalDescribedBy: props.ariaDescribedBy
2249
+ });
2250
+ const isControlled = props.value !== void 0;
2251
+ const [internalValue, setInternalValue] = React5.useState(
2252
+ orderSelectedValues(props.defaultValue ?? [], props.options)
2253
+ );
2254
+ const selectedValues = orderSelectedValues(
2255
+ isControlled ? props.value ?? [] : internalValue,
2256
+ props.options
2257
+ );
2258
+ const selectedValueSet = new Set(selectedValues);
2259
+ const handleToggle = (nextValue) => {
2260
+ const rawNextValue = selectedValueSet.has(nextValue) ? selectedValues.filter((value) => value !== nextValue) : [...selectedValues, nextValue];
2261
+ const orderedNextValue = orderSelectedValues(rawNextValue, props.options);
2262
+ if (!isControlled) {
2263
+ setInternalValue(orderedNextValue);
2264
+ }
2265
+ props.onChange?.(orderedNextValue);
2266
+ };
2267
+ const wrapperClass = cx7(
2268
+ "mw-checkbox-group-field",
2269
+ props.disabled && "mw-checkbox-group-field--disabled",
2270
+ isInvalid && "mw-checkbox-group-field--invalid"
2271
+ );
2272
+ return /* @__PURE__ */ jsxs(
2273
+ "fieldset",
2274
+ {
2275
+ className: wrapperClass,
2276
+ "aria-labelledby": labelId,
2277
+ "aria-describedby": describedBy,
2278
+ "aria-invalid": isInvalid ? true : void 0,
2279
+ "aria-required": props.required ? true : void 0,
2280
+ disabled: props.disabled ? true : void 0,
2281
+ ...props.dataAttributes,
2282
+ children: [
2283
+ /* @__PURE__ */ jsx("legend", { className: "mw-checkbox-group-field__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
2284
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-group-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
2285
+ /* @__PURE__ */ jsx("div", { className: "mw-checkbox-group-field__options", children: props.options.map((option, index) => {
2286
+ const optionId = `${id}-option-${index}`;
2287
+ const isOptionDisabled = props.disabled || option.disabled || false;
2288
+ const checkboxProps = {
2289
+ ...props.checkbox ?? {},
2290
+ id: optionId,
2291
+ value: option.value,
2292
+ checked: selectedValueSet.has(option.value),
2293
+ disabled: isOptionDisabled,
2294
+ invalid: isInvalid,
2295
+ onCheckedChange: () => handleToggle(option.value)
2296
+ };
2297
+ if (props.name !== void 0) {
2298
+ checkboxProps.name = props.name;
2299
+ }
2300
+ if (option.indeterminate !== void 0) {
2301
+ checkboxProps.indeterminate = option.indeterminate;
2302
+ }
2303
+ return /* @__PURE__ */ jsxs(
2304
+ "label",
2305
+ {
2306
+ className: "mw-checkbox-group-field__option",
2307
+ htmlFor: optionId,
2308
+ children: [
2309
+ /* @__PURE__ */ jsx(Checkbox, { ...checkboxProps }),
2310
+ /* @__PURE__ */ jsx(Paragraph, { size: "md", children: option.label })
2311
+ ]
2312
+ },
2313
+ option.value
2314
+ );
2315
+ }) }),
2316
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-checkbox-group-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
2317
+ ]
2318
+ }
2319
+ );
2320
+ }
2321
+ var Divider = React5.forwardRef((props, ref) => {
2322
+ const { className: customClassName, style: customStyle, ...opts } = props;
2323
+ const kit = createDividerRecipe(opts);
2324
+ const style = { ...kit.vars, ...customStyle };
2325
+ const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
2326
+ return /* @__PURE__ */ jsx("hr", { ref, ...kit.a11y, ...kit.dataAttributes, className, style });
2327
+ });
2328
+ Divider.displayName = "Divider";
2329
+ var Spacing = React5.forwardRef((props, ref) => {
2330
+ const { className: customClassName, scale, size, spacing, style: customStyle } = props;
2331
+ const resolvedSize = spacing ?? size;
2332
+ const kit = createSpacingRecipe({
2333
+ ...resolvedSize !== void 0 ? { size: resolvedSize } : {},
2334
+ ...scale !== void 0 ? { scale } : {}
2335
+ });
2336
+ const style = { ...kit.vars, ...customStyle };
2337
+ const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
2338
+ return /* @__PURE__ */ jsx("div", { ref, ...kit.a11y, ...kit.dataAttributes, className, style });
2339
+ });
2340
+ Spacing.displayName = "Spacing";
2341
+ var Spacer = Spacing;
2342
+ function H1(props) {
2343
+ const { children, className: customClassName, style: customStyle, ...opts } = props;
2344
+ const theme = useTheme();
2345
+ const kit = headingRecipe({ ...opts, level: 1 }, theme);
2346
+ const style = { ...kit.vars, ...customStyle };
2347
+ const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
2348
+ return /* @__PURE__ */ jsx("h1", { id: kit.a11y.id, "aria-label": kit.a11y.ariaLabel, className, style, children });
2349
+ }
2350
+ function H2(props) {
2351
+ const { children, className: customClassName, style: customStyle, ...opts } = props;
2352
+ const theme = useTheme();
2353
+ const kit = headingRecipe({ ...opts, level: 2 }, theme);
2354
+ const style = { ...kit.vars, ...customStyle };
2355
+ const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
2356
+ return /* @__PURE__ */ jsx("h2", { id: kit.a11y.id, "aria-label": kit.a11y.ariaLabel, className, style, children });
2357
+ }
2358
+ function H3(props) {
2359
+ const { children, className: customClassName, style: customStyle, ...opts } = props;
2360
+ const theme = useTheme();
2361
+ const kit = headingRecipe({ ...opts, level: 3 }, theme);
2362
+ const style = { ...kit.vars, ...customStyle };
2363
+ const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
2364
+ return /* @__PURE__ */ jsx("h3", { id: kit.a11y.id, "aria-label": kit.a11y.ariaLabel, className, style, children });
2365
+ }
2366
+ function Card(props) {
2367
+ const { title, children, className, dataAttributes, ...nativeDivProps } = props;
2368
+ const kit = createCardRecipe(dataAttributes ? { dataAttributes } : {});
2369
+ return /* @__PURE__ */ jsxs(
2370
+ "div",
2371
+ {
2372
+ ...nativeDivProps,
2373
+ ...kit.dataAttributes,
2374
+ className: [kit.className, className].filter(Boolean).join(" "),
2375
+ children: [
2376
+ title ? /* @__PURE__ */ jsx("div", { className: "mw-card__header", children: /* @__PURE__ */ jsx("span", { className: "mw-card__title", children: title }) }) : null,
2377
+ /* @__PURE__ */ jsx("div", { className: "mw-card__body", children })
2378
+ ]
2379
+ }
2380
+ );
2381
+ }
2382
+ function ProductCard(props) {
2383
+ return /* @__PURE__ */ jsx(
2384
+ Card,
2385
+ {
2386
+ ...props,
2387
+ dataAttributes: {
2388
+ ...props.dataAttributes,
2389
+ "data-purpose": "product-card"
2390
+ }
2391
+ }
2392
+ );
2393
+ }
2394
+ function ProfileCard(props) {
2395
+ return /* @__PURE__ */ jsx(
2396
+ Card,
2397
+ {
2398
+ ...props,
2399
+ dataAttributes: {
2400
+ ...props.dataAttributes,
2401
+ "data-purpose": "profile-card"
2402
+ }
2403
+ }
2404
+ );
2405
+ }
2406
+ function StatCard(props) {
2407
+ return /* @__PURE__ */ jsx(
2408
+ Card,
2409
+ {
2410
+ ...props,
2411
+ dataAttributes: {
2412
+ ...props.dataAttributes,
2413
+ "data-purpose": "stat-card"
2414
+ }
2415
+ }
2416
+ );
2417
+ }
2418
+ function cx8(...parts) {
2419
+ return parts.filter(Boolean).join(" ");
2420
+ }
2421
+ function Toast(props) {
2422
+ const { children, icon, action, onDismiss, className, id, dataAttributes, ...coreProps } = props;
2423
+ const kit = createToastRecipe(coreProps);
2424
+ const { a11y } = kit;
2425
+ return /* @__PURE__ */ jsxs(
2426
+ "div",
2427
+ {
2428
+ id,
2429
+ className: cx8(kit.className, className),
2430
+ role: a11y.role,
2431
+ "aria-live": a11y.ariaLive,
2432
+ "aria-atomic": "true",
2433
+ ...kit.dataAttributes,
2434
+ ...dataAttributes,
2435
+ children: [
2436
+ icon && /* @__PURE__ */ jsx("span", { className: "mw-toast__icon", "aria-hidden": "true", children: icon }),
2437
+ /* @__PURE__ */ jsxs("div", { className: "mw-toast__body", children: [
2438
+ /* @__PURE__ */ jsx("span", { className: "mw-toast__text", children }),
2439
+ action && /* @__PURE__ */ jsx("span", { className: "mw-toast__action", children: action })
2440
+ ] }),
2441
+ onDismiss && /* @__PURE__ */ jsx(
2442
+ "button",
2443
+ {
2444
+ type: "button",
2445
+ className: "mw-toast__dismiss",
2446
+ "aria-label": "Dismiss",
2447
+ onClick: onDismiss
2448
+ }
2449
+ )
2450
+ ]
2451
+ }
2452
+ );
2453
+ }
2454
+ function getDefaultIcon(iconName) {
2455
+ return /* @__PURE__ */ jsx(Icon, { name: iconName, decorative: true });
2456
+ }
2457
+ function SuccessToast(props) {
2458
+ return /* @__PURE__ */ jsx(
2459
+ Toast,
2460
+ {
2461
+ ...props,
2462
+ variant: props.variant ?? "outline",
2463
+ ariaLive: props.ariaLive ?? "polite",
2464
+ icon: props.icon ?? getDefaultIcon(IconName.Check),
2465
+ dataAttributes: {
2466
+ ...props.dataAttributes,
2467
+ ...createPurposeSemanticAttributes("success-toast")
2468
+ }
2469
+ }
2470
+ );
2471
+ }
2472
+ function ErrorToast(props) {
2473
+ return /* @__PURE__ */ jsx(
2474
+ Toast,
2475
+ {
2476
+ ...props,
2477
+ variant: props.variant ?? "outline",
2478
+ ariaLive: props.ariaLive ?? "assertive",
2479
+ icon: props.icon ?? getDefaultIcon(IconName.XCircle),
2480
+ dataAttributes: {
2481
+ ...props.dataAttributes,
2482
+ ...createPurposeSemanticAttributes("error-toast")
2483
+ }
2484
+ }
2485
+ );
2486
+ }
2487
+ function WarningToast(props) {
2488
+ return /* @__PURE__ */ jsx(
2489
+ Toast,
2490
+ {
2491
+ ...props,
2492
+ variant: props.variant ?? "outline",
2493
+ ariaLive: props.ariaLive ?? "polite",
2494
+ icon: props.icon ?? getDefaultIcon(IconName.AlertTriangle),
2495
+ dataAttributes: {
2496
+ ...props.dataAttributes,
2497
+ ...createPurposeSemanticAttributes("warning-toast")
2498
+ }
2499
+ }
2500
+ );
2501
+ }
2502
+ function InfoToast(props) {
2503
+ return /* @__PURE__ */ jsx(
2504
+ Toast,
2505
+ {
2506
+ ...props,
2507
+ variant: props.variant ?? "outline",
2508
+ ariaLive: props.ariaLive ?? "polite",
2509
+ icon: props.icon ?? getDefaultIcon(IconName.Info),
2510
+ dataAttributes: {
2511
+ ...props.dataAttributes,
2512
+ ...createPurposeSemanticAttributes("info-toast")
2513
+ }
2514
+ }
2515
+ );
2516
+ }
2517
+ function cx9(...parts) {
2518
+ return parts.filter(Boolean).join(" ");
2519
+ }
2520
+ function renderToastByIntent(toast, onDismiss) {
2521
+ const sharedProps = {
2522
+ id: toast.id,
2523
+ children: toast.children
2524
+ };
2525
+ const dismissHandler = onDismiss ? () => onDismiss(toast.id) : void 0;
2526
+ if (toast.icon !== void 0) {
2527
+ sharedProps.icon = toast.icon;
2528
+ }
2529
+ if (toast.action !== void 0) {
2530
+ sharedProps.action = toast.action;
2531
+ }
2532
+ if (dismissHandler) {
2533
+ sharedProps.onDismiss = dismissHandler;
2534
+ }
2535
+ if (toast.className !== void 0) {
2536
+ sharedProps.className = toast.className;
2537
+ }
2538
+ if (toast.variant !== void 0) {
2539
+ sharedProps.variant = toast.variant;
2540
+ }
2541
+ if (toast.ariaLive !== void 0) {
2542
+ sharedProps.ariaLive = toast.ariaLive;
2543
+ }
2544
+ if (toast.dataAttributes !== void 0 || toast.intent !== void 0) {
2545
+ sharedProps.dataAttributes = {
2546
+ ...toast.dataAttributes ?? {},
2547
+ ...toast.intent !== void 0 ? { "data-intent": toast.intent } : {}
2548
+ };
2549
+ }
2550
+ switch (toast.intent) {
2551
+ case "success":
2552
+ return /* @__PURE__ */ jsx(SuccessToast, { ...sharedProps });
2553
+ case "error":
2554
+ return /* @__PURE__ */ jsx(ErrorToast, { ...sharedProps });
2555
+ case "warning":
2556
+ return /* @__PURE__ */ jsx(WarningToast, { ...sharedProps });
2557
+ case "info":
2558
+ return /* @__PURE__ */ jsx(InfoToast, { ...sharedProps });
2559
+ default:
2560
+ return /* @__PURE__ */ jsx(Toast, { ...sharedProps });
2561
+ }
2562
+ }
2563
+ function ToastViewportItem(props) {
2564
+ const timerHandleRef = React5.useRef(null);
2565
+ const timerStartedAtRef = React5.useRef(null);
2566
+ const remainingDurationRef = React5.useRef(null);
2567
+ const pointerInsideRef = React5.useRef(false);
2568
+ const focusInsideRef = React5.useRef(false);
2569
+ const clearDismissTimer = React5.useCallback(() => {
2570
+ if (timerHandleRef.current === null) {
2571
+ return;
2572
+ }
2573
+ window.clearTimeout(timerHandleRef.current);
2574
+ timerHandleRef.current = null;
2575
+ timerStartedAtRef.current = null;
2576
+ }, []);
2577
+ const scheduleDismissTimer = React5.useCallback(
2578
+ (delay) => {
2579
+ if (!props.onDismiss || delay <= 0 || pointerInsideRef.current || focusInsideRef.current || timerHandleRef.current !== null) {
2580
+ return;
2581
+ }
2582
+ timerStartedAtRef.current = Date.now();
2583
+ timerHandleRef.current = window.setTimeout(() => {
2584
+ timerHandleRef.current = null;
2585
+ timerStartedAtRef.current = null;
2586
+ remainingDurationRef.current = 0;
2587
+ props.onDismiss?.(props.toast.id);
2588
+ }, delay);
2589
+ },
2590
+ [props.onDismiss, props.toast.id]
2591
+ );
2592
+ const pauseDismissTimer = React5.useCallback(() => {
2593
+ if (timerHandleRef.current === null || timerStartedAtRef.current === null) {
2594
+ return;
2595
+ }
2596
+ const elapsed = Date.now() - timerStartedAtRef.current;
2597
+ const remainingDuration = remainingDurationRef.current ?? 0;
2598
+ remainingDurationRef.current = Math.max(remainingDuration - elapsed, 0);
2599
+ clearDismissTimer();
2600
+ }, [clearDismissTimer]);
2601
+ const resumeDismissTimer = React5.useCallback(() => {
2602
+ if (pointerInsideRef.current || focusInsideRef.current) {
2603
+ return;
2604
+ }
2605
+ const remainingDuration = remainingDurationRef.current;
2606
+ if (remainingDuration === null || remainingDuration === void 0 || remainingDuration <= 0) {
2607
+ return;
2608
+ }
2609
+ scheduleDismissTimer(remainingDuration);
2610
+ }, [scheduleDismissTimer]);
2611
+ React5.useEffect(() => {
2612
+ clearDismissTimer();
2613
+ pointerInsideRef.current = false;
2614
+ focusInsideRef.current = false;
2615
+ if (!props.onDismiss || props.toast.duration === void 0 || props.toast.duration === null) {
2616
+ remainingDurationRef.current = null;
2617
+ return;
2618
+ }
2619
+ if (props.toast.duration <= 0) {
2620
+ remainingDurationRef.current = 0;
2621
+ return;
2622
+ }
2623
+ remainingDurationRef.current = props.toast.duration;
2624
+ scheduleDismissTimer(props.toast.duration);
2625
+ return () => {
2626
+ clearDismissTimer();
2627
+ };
2628
+ }, [clearDismissTimer, props.onDismiss, props.toast.duration, scheduleDismissTimer]);
2629
+ return /* @__PURE__ */ jsx(
2630
+ "div",
2631
+ {
2632
+ className: "mw-toast-container__item",
2633
+ onMouseEnter: () => {
2634
+ pointerInsideRef.current = true;
2635
+ pauseDismissTimer();
2636
+ },
2637
+ onMouseLeave: () => {
2638
+ pointerInsideRef.current = false;
2639
+ resumeDismissTimer();
2640
+ },
2641
+ onFocusCapture: () => {
2642
+ focusInsideRef.current = true;
2643
+ pauseDismissTimer();
2644
+ },
2645
+ onBlurCapture: (event) => {
2646
+ if (event.currentTarget.contains(event.relatedTarget)) {
2647
+ return;
2648
+ }
2649
+ focusInsideRef.current = false;
2650
+ resumeDismissTimer();
2651
+ },
2652
+ children: renderToastByIntent(props.toast, props.onDismiss)
2653
+ }
2654
+ );
2655
+ }
2656
+ function ToastContainer(props) {
2657
+ const placement = props.placement ?? "top-right";
2658
+ const visibleToasts = props.maxVisible && props.maxVisible > 0 ? props.toasts.slice(-props.maxVisible) : props.toasts;
2659
+ return /* @__PURE__ */ jsx("div", { className: cx9("mw-toast-container", `mw-toast-container--${placement}`, props.className), children: visibleToasts.map((toast) => /* @__PURE__ */ jsx(
2660
+ ToastViewportItem,
2661
+ {
2662
+ toast,
2663
+ ...props.onDismiss ? { onDismiss: props.onDismiss } : {}
2664
+ },
2665
+ toast.id
2666
+ )) });
2667
+ }
2668
+ var ToastContext = React5.createContext(null);
2669
+ function ToastProvider(props) {
2670
+ const [toasts, setToasts] = React5.useState([]);
2671
+ const idRef = React5.useRef(0);
2672
+ const dismiss = React5.useCallback((id) => {
2673
+ setToasts((currentToasts) => {
2674
+ const toast = currentToasts.find((item) => item.id === id);
2675
+ toast?.onDismiss?.();
2676
+ return currentToasts.filter((item) => item.id !== id);
2677
+ });
2678
+ }, []);
2679
+ const clear = React5.useCallback(() => {
2680
+ setToasts((currentToasts) => {
2681
+ for (const toast of currentToasts) {
2682
+ toast.onDismiss?.();
2683
+ }
2684
+ return [];
2685
+ });
2686
+ }, []);
2687
+ const show = React5.useCallback(
2688
+ (toast) => {
2689
+ idRef.current += 1;
2690
+ const id = `mw-toast-${idRef.current}`;
2691
+ setToasts((currentToasts) => [
2692
+ ...currentToasts,
2693
+ {
2694
+ ...toast,
2695
+ id,
2696
+ duration: toast.duration === void 0 ? props.defaultDuration === void 0 ? 4e3 : props.defaultDuration : toast.duration
2697
+ }
2698
+ ]);
2699
+ return id;
2700
+ },
2701
+ [props.defaultDuration]
2702
+ );
2703
+ const value = React5.useMemo(
2704
+ () => ({
2705
+ show,
2706
+ dismiss,
2707
+ clear
2708
+ }),
2709
+ [clear, dismiss, show]
2710
+ );
2711
+ return /* @__PURE__ */ jsxs(ToastContext.Provider, { value, children: [
2712
+ props.children,
2713
+ /* @__PURE__ */ jsx(
2714
+ ToastContainer,
2715
+ {
2716
+ toasts,
2717
+ onDismiss: dismiss,
2718
+ ...props.placement ? { placement: props.placement } : {},
2719
+ ...props.maxVisible !== void 0 ? { maxVisible: props.maxVisible } : {},
2720
+ ...props.className ? { className: props.className } : {}
2721
+ }
2722
+ )
2723
+ ] });
2724
+ }
2725
+ function useToast() {
2726
+ const context = React5.useContext(ToastContext);
2727
+ if (!context) {
2728
+ throw new Error("ToastProvider is missing. Wrap your app in <ToastProvider />.");
2729
+ }
2730
+ return context;
2731
+ }
2732
+ function Tooltip(props) {
2733
+ const { children, className, style, dataAttributes, id, ...nativeSpanProps } = props;
2734
+ const tooltipOptions = {};
2735
+ if (id !== void 0) {
2736
+ tooltipOptions.id = id;
2737
+ }
2738
+ const kit = createTooltipRecipe(tooltipOptions);
2739
+ const mergedClassName = [kit.className, className].filter(Boolean).join(" ");
2740
+ const mergedStyle = { ...kit.vars, ...style };
2741
+ return /* @__PURE__ */ jsx(
2742
+ "span",
2743
+ {
2744
+ ...nativeSpanProps,
2745
+ ...kit.dataAttributes,
2746
+ ...dataAttributes,
2747
+ id: kit.a11y.id,
2748
+ className: mergedClassName,
2749
+ style: mergedStyle,
2750
+ role: kit.a11y.role,
2751
+ children
2752
+ }
2753
+ );
2754
+ }
2755
+ var TOOLTIP_EXIT_DURATION_MS = 160;
2756
+ function cx10(...parts) {
2757
+ return parts.filter(Boolean).join(" ");
2758
+ }
2759
+ function TooltipGroup(props) {
2760
+ const reactId = React5.useId();
2761
+ const {
2762
+ content,
2763
+ icon = IconName.HelpCircle,
2764
+ triggerLabel = "Show tooltip",
2765
+ open,
2766
+ defaultOpen = false,
2767
+ onOpenChange,
2768
+ tooltipId,
2769
+ tooltipClassName,
2770
+ triggerClassName,
2771
+ dataAttributes,
2772
+ className,
2773
+ id,
2774
+ onMouseEnter,
2775
+ onMouseLeave,
2776
+ onFocus,
2777
+ onBlur,
2778
+ onKeyDown,
2779
+ ...nativeSpanProps
2780
+ } = props;
2781
+ const [internalOpen, setInternalOpen] = React5.useState(defaultOpen);
2782
+ const isControlled = open !== void 0;
2783
+ const resolvedOpen = isControlled ? open : internalOpen;
2784
+ const [isTooltipMounted, setIsTooltipMounted] = React5.useState(resolvedOpen);
2785
+ const resolvedTooltipId = tooltipId ?? `${id ?? `mw-tooltip-group-${reactId}`}-tooltip`;
2786
+ React5.useEffect(() => {
2787
+ if (resolvedOpen) {
2788
+ setIsTooltipMounted(true);
2789
+ return;
2790
+ }
2791
+ const timeoutId = window.setTimeout(() => {
2792
+ setIsTooltipMounted(false);
2793
+ }, TOOLTIP_EXIT_DURATION_MS);
2794
+ return () => {
2795
+ window.clearTimeout(timeoutId);
2796
+ };
2797
+ }, [resolvedOpen]);
2798
+ const updateOpen = React5.useCallback(
2799
+ (nextOpen) => {
2800
+ if (resolvedOpen === nextOpen) {
2801
+ return;
2802
+ }
2803
+ if (!isControlled) {
2804
+ setInternalOpen(nextOpen);
2805
+ }
2806
+ onOpenChange?.(nextOpen);
2807
+ },
2808
+ [isControlled, onOpenChange, resolvedOpen]
2809
+ );
2810
+ return /* @__PURE__ */ jsxs(
2811
+ "span",
2812
+ {
2813
+ ...nativeSpanProps,
2814
+ ...dataAttributes,
2815
+ id,
2816
+ className: cx10("mw-tooltip-group", className),
2817
+ "data-component": "tooltip-group",
2818
+ "data-open": resolvedOpen ? "true" : void 0,
2819
+ onMouseEnter: (event) => {
2820
+ onMouseEnter?.(event);
2821
+ updateOpen(true);
2822
+ },
2823
+ onMouseLeave: (event) => {
2824
+ onMouseLeave?.(event);
2825
+ updateOpen(false);
2826
+ },
2827
+ onFocus: (event) => {
2828
+ onFocus?.(event);
2829
+ updateOpen(true);
2830
+ },
2831
+ onBlur: (event) => {
2832
+ onBlur?.(event);
2833
+ const nextFocusedElement = event.relatedTarget;
2834
+ if (nextFocusedElement instanceof Node && event.currentTarget.contains(nextFocusedElement)) {
2835
+ return;
2836
+ }
2837
+ updateOpen(false);
2838
+ },
2839
+ onKeyDown: (event) => {
2840
+ onKeyDown?.(event);
2841
+ if (event.key === "Escape") {
2842
+ updateOpen(false);
2843
+ }
2844
+ },
2845
+ children: [
2846
+ isTooltipMounted ? /* @__PURE__ */ jsx(
2847
+ Tooltip,
2848
+ {
2849
+ id: resolvedTooltipId,
2850
+ className: tooltipClassName,
2851
+ "data-state": resolvedOpen ? "open" : "closed",
2852
+ "aria-hidden": resolvedOpen ? void 0 : "true",
2853
+ children: content
2854
+ }
2855
+ ) : null,
2856
+ /* @__PURE__ */ jsx(
2857
+ "button",
2858
+ {
2859
+ type: "button",
2860
+ className: cx10("mw-tooltip-group__trigger", triggerClassName),
2861
+ "aria-label": triggerLabel,
2862
+ "aria-describedby": resolvedOpen ? resolvedTooltipId : void 0,
2863
+ children: /* @__PURE__ */ jsx(Icon, { name: icon, decorative: true })
2864
+ }
2865
+ )
2866
+ ]
2867
+ }
2868
+ );
2869
+ }
2870
+ function Accordion(props) {
2871
+ const { title, children, className, onToggle, id: idProp, open, disabled } = props;
2872
+ const autoId = React5.useId();
2873
+ const resolvedId = idProp ?? autoId.replace(/:/g, "");
2874
+ const opts = { id: resolvedId };
2875
+ if (open !== void 0) opts.open = open;
2876
+ if (disabled !== void 0) opts.disabled = disabled;
2877
+ const kit = createAccordionRecipe(opts);
2878
+ const { a11y } = kit;
2879
+ function handleTriggerClick() {
2880
+ if (disabled) return;
2881
+ onToggle?.();
2882
+ }
2883
+ return /* @__PURE__ */ jsxs("div", { className: [kit.className, className].filter(Boolean).join(" "), children: [
2884
+ /* @__PURE__ */ jsxs(
2885
+ "button",
2886
+ {
2887
+ id: a11y.triggerId,
2888
+ type: "button",
2889
+ className: "mw-accordion__trigger",
2890
+ "aria-expanded": a11y.ariaExpanded,
2891
+ "aria-controls": a11y.panelId,
2892
+ "aria-disabled": a11y.ariaDisabled,
2893
+ disabled,
2894
+ onClick: handleTriggerClick,
2895
+ children: [
2896
+ /* @__PURE__ */ jsx("span", { className: "mw-accordion__title", children: title }),
2897
+ /* @__PURE__ */ jsx("span", { className: "mw-accordion__icon", "aria-hidden": "true" })
2898
+ ]
2899
+ }
2900
+ ),
2901
+ /* @__PURE__ */ jsx(
2902
+ "section",
2903
+ {
2904
+ id: a11y.panelId,
2905
+ "aria-labelledby": a11y.triggerId,
2906
+ className: "mw-accordion__panel",
2907
+ hidden: !open,
2908
+ children: /* @__PURE__ */ jsx("div", { className: "mw-accordion__content", children })
2909
+ }
2910
+ )
2911
+ ] });
2912
+ }
2913
+ function hasContent3(value) {
2914
+ if (value === void 0 || value === null || value === false) return false;
2915
+ if (typeof value === "string") return value.trim().length > 0;
2916
+ return true;
2917
+ }
2918
+ function cx11(...parts) {
2919
+ return parts.filter(Boolean).join(" ");
2920
+ }
2921
+ function resolveAccordionItemContent(item) {
2922
+ return item.content ?? item.children;
2923
+ }
2924
+ function AccordionField(props) {
2925
+ const reactId = React5.useId();
2926
+ const id = props.id ?? `mw-accordion-field-${reactId}`;
2927
+ const multipleAllowed = props.multiple ?? true;
2928
+ const hasDescription = hasContent3(props.description);
2929
+ const hasError = hasContent3(props.error);
2930
+ const isInvalid = hasError || false;
2931
+ const { labelId, descriptionId, errorId, describedBy } = buildAccordionFieldA11yIds({
2932
+ id,
2933
+ hasDescription,
2934
+ hasError,
2935
+ externalDescribedBy: props.ariaDescribedBy
2936
+ });
2937
+ const isControlled = props.openItems !== void 0;
2938
+ const [internalOpenItems, setInternalOpenItems] = React5.useState(
2939
+ props.defaultOpenItems ?? []
2940
+ );
2941
+ const openItems = isControlled ? props.openItems ?? [] : internalOpenItems;
2942
+ const handleToggle = (itemValue) => {
2943
+ const isCurrentlyOpen = openItems.includes(itemValue);
2944
+ let nextOpenItems;
2945
+ if (isCurrentlyOpen) {
2946
+ nextOpenItems = openItems.filter((v) => v !== itemValue);
2947
+ } else if (multipleAllowed) {
2948
+ nextOpenItems = [...openItems, itemValue];
2949
+ } else {
2950
+ nextOpenItems = [itemValue];
2951
+ }
2952
+ if (!isControlled) {
2953
+ setInternalOpenItems(nextOpenItems);
2954
+ }
2955
+ props.onOpenItemsChange?.(nextOpenItems);
2956
+ };
2957
+ const wrapperClass = cx11(
2958
+ "mw-accordion-field",
2959
+ props.disabled && "mw-accordion-field--disabled",
2960
+ isInvalid && "mw-accordion-field--invalid"
2961
+ );
2962
+ return /* @__PURE__ */ jsxs(
2963
+ "fieldset",
2964
+ {
2965
+ className: wrapperClass,
2966
+ "aria-labelledby": labelId,
2967
+ "aria-describedby": describedBy,
2968
+ "aria-invalid": isInvalid ? true : void 0,
2969
+ ...props.dataAttributes,
2970
+ children: [
2971
+ /* @__PURE__ */ jsx("legend", { className: "mw-accordion-field__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
2972
+ /* @__PURE__ */ jsx("div", { className: "mw-accordion-field__items", children: props.items.map((item) => {
2973
+ const isDisabled = props.disabled || item.disabled || false;
2974
+ const isOpen = openItems.includes(item.value);
2975
+ return /* @__PURE__ */ jsx(
2976
+ Accordion,
2977
+ {
2978
+ id: `${id}-item-${item.value}`,
2979
+ title: item.title,
2980
+ open: isOpen,
2981
+ disabled: isDisabled,
2982
+ onToggle: () => handleToggle(item.value),
2983
+ children: resolveAccordionItemContent(item)
2984
+ },
2985
+ item.value
2986
+ );
2987
+ }) }),
2988
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-accordion-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
2989
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-accordion-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
2990
+ ]
2991
+ }
2992
+ );
2993
+ }
2994
+ function FAQAccordion(props) {
2995
+ return /* @__PURE__ */ jsx(
2996
+ AccordionField,
2997
+ {
2998
+ ...props,
2999
+ multiple: false,
3000
+ dataAttributes: {
3001
+ ...props.dataAttributes,
3002
+ "data-purpose": "faq"
3003
+ }
3004
+ }
3005
+ );
3006
+ }
3007
+ function SettingsAccordion(props) {
3008
+ return /* @__PURE__ */ jsx(
3009
+ AccordionField,
3010
+ {
3011
+ ...props,
3012
+ multiple: true,
3013
+ dataAttributes: {
3014
+ ...props.dataAttributes,
3015
+ "data-purpose": "settings"
3016
+ }
3017
+ }
3018
+ );
3019
+ }
3020
+ function SectionsAccordion(props) {
3021
+ return /* @__PURE__ */ jsx(
3022
+ AccordionField,
3023
+ {
3024
+ ...props,
3025
+ dataAttributes: {
3026
+ ...props.dataAttributes,
3027
+ "data-purpose": "sections"
3028
+ }
3029
+ }
3030
+ );
3031
+ }
3032
+ function Radio(props) {
3033
+ const { onCheckedChange, onChange, ...coreProps } = props;
3034
+ const kit = radioRecipe(coreProps);
3035
+ const { a11y } = kit;
3036
+ const handleChange = (e) => {
3037
+ onChange?.(e);
3038
+ onCheckedChange?.(e.currentTarget.checked);
3039
+ };
3040
+ return /* @__PURE__ */ jsx(
3041
+ "input",
3042
+ {
3043
+ type: "radio",
3044
+ className: kit.className,
3045
+ id: a11y.id,
3046
+ name: a11y.name,
3047
+ value: a11y.value,
3048
+ disabled: a11y.disabled === true,
3049
+ required: a11y.required === true,
3050
+ "aria-label": a11y.ariaLabel,
3051
+ "aria-labelledby": a11y.ariaLabelledBy,
3052
+ "aria-describedby": a11y.ariaDescribedBy,
3053
+ "aria-invalid": a11y.ariaInvalid === true ? true : void 0,
3054
+ checked: kit.checked,
3055
+ defaultChecked: kit.defaultChecked,
3056
+ onChange: handleChange
3057
+ }
3058
+ );
3059
+ }
3060
+ function hasContent4(value) {
3061
+ if (value === void 0 || value === null || value === false) return false;
3062
+ if (typeof value === "string") return value.trim().length > 0;
3063
+ return true;
3064
+ }
3065
+ function cx12(...parts) {
3066
+ return parts.filter(Boolean).join(" ");
3067
+ }
3068
+ function RadioGroupField(props) {
3069
+ const reactId = React5.useId();
3070
+ const id = props.id ?? `mw-radio-group-${reactId}`;
3071
+ const hasDescription = hasContent4(props.description);
3072
+ const hasError = hasContent4(props.error);
3073
+ const isInvalid = hasError || false;
3074
+ const { labelId, descriptionId, errorId, describedBy } = buildRadioGroupFieldA11yIds({
3075
+ id,
3076
+ hasDescription,
3077
+ hasError,
3078
+ externalDescribedBy: props.ariaDescribedBy
3079
+ });
3080
+ const isControlled = props.value !== void 0;
3081
+ const [internalValue, setInternalValue] = React5.useState(props.defaultValue);
3082
+ const selectedValue = isControlled ? props.value : internalValue;
3083
+ const handleSelect = (optionValue) => {
3084
+ if (!isControlled) {
3085
+ setInternalValue(optionValue);
3086
+ }
3087
+ props.onChange?.(optionValue);
3088
+ };
3089
+ const wrapperClass = cx12(
3090
+ "mw-radio-group-field",
3091
+ props.disabled && "mw-radio-group-field--disabled",
3092
+ isInvalid && "mw-radio-group-field--invalid"
3093
+ );
3094
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, ...props.dataAttributes, children: [
3095
+ /* @__PURE__ */ jsx("div", { className: "mw-radio-group-field__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) }),
3096
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-radio-group-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
3097
+ /* @__PURE__ */ jsx(
3098
+ "div",
3099
+ {
3100
+ role: "radiogroup",
3101
+ "aria-labelledby": labelId,
3102
+ "aria-describedby": describedBy,
3103
+ "aria-invalid": isInvalid ? true : void 0,
3104
+ "aria-required": props.required ? true : void 0,
3105
+ className: "mw-radio-group-field__options",
3106
+ children: props.options.map(({ value, label, disabled: optionDisabled }) => {
3107
+ const optionId = `${id}-option-${value}`;
3108
+ const isDisabled = props.disabled || optionDisabled || false;
3109
+ return /* @__PURE__ */ jsxs("label", { className: "mw-radio-group-field__option", htmlFor: optionId, children: [
3110
+ /* @__PURE__ */ jsx(
3111
+ Radio,
3112
+ {
3113
+ id: optionId,
3114
+ name: props.name,
3115
+ value,
3116
+ checked: selectedValue === value,
3117
+ disabled: isDisabled,
3118
+ invalid: isInvalid,
3119
+ ...props.required ? { required: true } : {},
3120
+ onCheckedChange: (checked) => {
3121
+ if (checked) handleSelect(value);
3122
+ }
3123
+ }
3124
+ ),
3125
+ /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: label })
3126
+ ] }, value);
3127
+ })
3128
+ }
3129
+ ),
3130
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-radio-group-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
3131
+ ] });
3132
+ }
3133
+ function YesNoRadioGroup(props) {
3134
+ const { yesLabel = "Yes", noLabel = "No", ...restProps } = props;
3135
+ const options = [
3136
+ { value: "yes", label: yesLabel },
3137
+ { value: "no", label: noLabel }
3138
+ ];
3139
+ return /* @__PURE__ */ jsx(
3140
+ RadioGroupField,
3141
+ {
3142
+ ...restProps,
3143
+ options,
3144
+ dataAttributes: {
3145
+ ...props.dataAttributes,
3146
+ "data-purpose": "binary-choice"
3147
+ }
3148
+ }
3149
+ );
3150
+ }
3151
+ function RatingRadioGroup(props) {
3152
+ const { min = 1, max = 5, labelFn = String, ...restProps } = props;
3153
+ const options = Array.from({ length: max - min + 1 }, (_, i) => {
3154
+ const value = min + i;
3155
+ return { value: String(value), label: labelFn(value) };
3156
+ });
3157
+ return /* @__PURE__ */ jsx(
3158
+ RadioGroupField,
3159
+ {
3160
+ ...restProps,
3161
+ options,
3162
+ dataAttributes: {
3163
+ ...props.dataAttributes,
3164
+ "data-purpose": "rating"
3165
+ }
3166
+ }
3167
+ );
3168
+ }
3169
+ function OptionRadioGroup(props) {
3170
+ return /* @__PURE__ */ jsx(
3171
+ RadioGroupField,
3172
+ {
3173
+ ...props,
3174
+ dataAttributes: {
3175
+ ...props.dataAttributes,
3176
+ "data-purpose": "selection"
3177
+ }
3178
+ }
3179
+ );
3180
+ }
3181
+ function Badge(props) {
3182
+ const { children, className, id, dataAttributes, ...coreProps } = props;
3183
+ const kit = createBadgeRecipe(coreProps);
3184
+ return /* @__PURE__ */ jsx(
3185
+ "span",
3186
+ {
3187
+ id,
3188
+ className: [kit.className, className].filter(Boolean).join(" "),
3189
+ "aria-label": kit.a11y.ariaLabel,
3190
+ ...kit.dataAttributes,
3191
+ ...dataAttributes,
3192
+ children
3193
+ }
3194
+ );
3195
+ }
3196
+ function cx13(...parts) {
3197
+ return parts.filter(Boolean).join(" ");
3198
+ }
3199
+ function BadgeGroup(props) {
3200
+ const reactId = React5.useId();
3201
+ const id = props.id ?? `mw-badge-group-${reactId}`;
3202
+ const labelId = `${id}-label`;
3203
+ const className = cx13("mw-badge-group", props.className);
3204
+ return /* @__PURE__ */ jsxs("fieldset", { className, "aria-labelledby": labelId, ...props.dataAttributes, children: [
3205
+ /* @__PURE__ */ jsx("legend", { className: "mw-badge-group__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.label }) }),
3206
+ /* @__PURE__ */ jsx("div", { className: "mw-badge-group__items", children: props.children })
3207
+ ] });
3208
+ }
3209
+ function StatusBadge(props) {
3210
+ return /* @__PURE__ */ jsx(
3211
+ Badge,
3212
+ {
3213
+ ...props,
3214
+ dataAttributes: {
3215
+ ...props.dataAttributes,
3216
+ ...createPurposeSemanticAttributes("status")
3217
+ }
3218
+ }
3219
+ );
3220
+ }
3221
+ function PriorityBadge(props) {
3222
+ return /* @__PURE__ */ jsx(
3223
+ Badge,
3224
+ {
3225
+ ...props,
3226
+ dataAttributes: {
3227
+ ...props.dataAttributes,
3228
+ ...createPurposeSemanticAttributes("priority")
3229
+ }
3230
+ }
3231
+ );
3232
+ }
3233
+ function NotificationBadge(props) {
3234
+ return /* @__PURE__ */ jsx(
3235
+ Badge,
3236
+ {
3237
+ ...props,
3238
+ dataAttributes: {
3239
+ ...props.dataAttributes,
3240
+ ...createPurposeSemanticAttributes("notification")
3241
+ }
3242
+ }
3243
+ );
3244
+ }
3245
+ function Switch(props) {
3246
+ const { children, className, id, onCheckedChange, onClick, ...coreProps } = props;
3247
+ const kit = createSwitchRecipe(coreProps);
3248
+ const { a11y } = kit;
3249
+ const isDisabled = a11y.ariaDisabled === true;
3250
+ const handleClick = (event) => {
3251
+ onClick?.(event);
3252
+ if (isDisabled || event.defaultPrevented) {
3253
+ return;
3254
+ }
3255
+ onCheckedChange?.(!a11y.ariaChecked);
3256
+ };
3257
+ return /* @__PURE__ */ jsxs(
3258
+ "button",
3259
+ {
3260
+ id,
3261
+ type: "button",
3262
+ role: a11y.role,
3263
+ disabled: isDisabled,
3264
+ "aria-checked": a11y.ariaChecked,
3265
+ "aria-disabled": a11y.ariaDisabled,
3266
+ "aria-label": a11y.ariaLabel,
3267
+ "aria-labelledby": a11y.ariaLabelledby,
3268
+ "aria-describedby": a11y.ariaDescribedBy,
3269
+ className: [kit.className, className].filter(Boolean).join(" "),
3270
+ style: kit.vars,
3271
+ onClick: handleClick,
3272
+ children: [
3273
+ /* @__PURE__ */ jsx("span", { className: "mw-switch__track", children: /* @__PURE__ */ jsx("span", { className: "mw-switch__thumb" }) }),
3274
+ children
3275
+ ]
3276
+ }
3277
+ );
3278
+ }
3279
+ function cx14(...parts) {
3280
+ return parts.filter(Boolean).join(" ");
3281
+ }
3282
+ function hasContent5(value) {
3283
+ if (value === void 0 || value === null || value === false) {
3284
+ return false;
3285
+ }
3286
+ if (typeof value === "string") {
3287
+ return value.trim().length > 0;
3288
+ }
3289
+ return true;
3290
+ }
3291
+ function SwitchField(props) {
3292
+ const reactId = React5.useId();
3293
+ const id = props.id ?? `mw-switch-${reactId}`;
3294
+ const hasDescription = hasContent5(props.description);
3295
+ const hasError = hasContent5(props.error);
3296
+ const { labelId, descriptionId, errorId, describedBy } = buildSwitchFieldA11yIds({
3297
+ id,
3298
+ hasDescription,
3299
+ hasError,
3300
+ externalDescribedBy: props.ariaDescribedBy
3301
+ });
3302
+ const disabled = props.switch.disabled || false;
3303
+ const invalid = hasError;
3304
+ const wrapperClass = cx14(
3305
+ "mw-switch-field",
3306
+ disabled && "mw-switch-field--disabled",
3307
+ invalid && "mw-switch-field--invalid"
3308
+ );
3309
+ const {
3310
+ ariaLabel: _ignoredAriaLabel,
3311
+ ariaLabelledby: _ignoredAriaLabelledby,
3312
+ ariaDescribedBy: _ignoredAriaDescribedBy,
3313
+ children: _ignoredChildren,
3314
+ ...switchProps
3315
+ } = props.switch;
3316
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, ...props.dataAttributes, children: [
3317
+ /* @__PURE__ */ jsxs("div", { className: "mw-switch-field__row", children: [
3318
+ /* @__PURE__ */ jsx(
3319
+ Switch,
3320
+ {
3321
+ ...switchProps,
3322
+ id,
3323
+ ariaLabelledby: labelId,
3324
+ ...describedBy ? { ariaDescribedBy: describedBy } : {}
3325
+ }
3326
+ ),
3327
+ /* @__PURE__ */ jsx("span", { className: "mw-switch-field__label", id: labelId, children: /* @__PURE__ */ jsx(Paragraph, { size: "md", children: props.label }) })
3328
+ ] }),
3329
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-switch-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
3330
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-switch-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
3331
+ ] });
3332
+ }
3333
+ function FeatureToggle(props) {
3334
+ return /* @__PURE__ */ jsx(
3335
+ SwitchField,
3336
+ {
3337
+ ...props,
3338
+ dataAttributes: {
3339
+ ...props.dataAttributes,
3340
+ "data-purpose": "feature-toggle"
3341
+ }
3342
+ }
3343
+ );
3344
+ }
3345
+ function PreferenceSwitch(props) {
3346
+ return /* @__PURE__ */ jsx(
3347
+ SwitchField,
3348
+ {
3349
+ ...props,
3350
+ dataAttributes: {
3351
+ ...props.dataAttributes,
3352
+ "data-purpose": "preference"
3353
+ }
3354
+ }
3355
+ );
3356
+ }
3357
+ function PermissionSwitch(props) {
3358
+ return /* @__PURE__ */ jsx(
3359
+ SwitchField,
3360
+ {
3361
+ ...props,
3362
+ dataAttributes: {
3363
+ ...props.dataAttributes,
3364
+ "data-purpose": "permission"
3365
+ }
3366
+ }
3367
+ );
3368
+ }
3369
+ function buildSliderOptions(options) {
3370
+ const sliderOptions = {};
3371
+ if (options.id !== void 0) sliderOptions.id = options.id;
3372
+ if (options.name !== void 0) sliderOptions.name = options.name;
3373
+ if (options.min !== void 0) sliderOptions.min = options.min;
3374
+ if (options.max !== void 0) sliderOptions.max = options.max;
3375
+ if (options.step !== void 0) sliderOptions.step = options.step;
3376
+ if (options.value !== void 0) sliderOptions.value = options.value;
3377
+ if (options.defaultValue !== void 0) sliderOptions.defaultValue = options.defaultValue;
3378
+ if (options.disabled !== void 0) sliderOptions.disabled = options.disabled;
3379
+ if (options.required !== void 0) sliderOptions.required = options.required;
3380
+ if (options.showTooltip !== void 0) sliderOptions.showTooltip = options.showTooltip;
3381
+ if (options.showTouchArea !== void 0) sliderOptions.showTouchArea = options.showTouchArea;
3382
+ if (options.orientation !== void 0) sliderOptions.orientation = options.orientation;
3383
+ if (options.ariaLabel !== void 0) sliderOptions.ariaLabel = options.ariaLabel;
3384
+ if (options.ariaLabelledBy !== void 0) sliderOptions.ariaLabelledBy = options.ariaLabelledBy;
3385
+ if (options.ariaDescribedBy !== void 0) sliderOptions.ariaDescribedBy = options.ariaDescribedBy;
3386
+ if (options.ariaValueText !== void 0) sliderOptions.ariaValueText = options.ariaValueText;
3387
+ return sliderOptions;
3388
+ }
3389
+ function resolveSliderValue(options) {
3390
+ return createSliderRecipe(buildSliderOptions(options)).value;
3391
+ }
3392
+ var Slider = React5.forwardRef((props, ref) => {
3393
+ const {
3394
+ id,
3395
+ name,
3396
+ min,
3397
+ max,
3398
+ step,
3399
+ value,
3400
+ defaultValue,
3401
+ disabled,
3402
+ required,
3403
+ showTooltip,
3404
+ showTouchArea,
3405
+ orientation,
3406
+ ariaLabel,
3407
+ ariaLabelledBy,
3408
+ ariaDescribedBy,
3409
+ ariaValueText,
3410
+ className: customClassName,
3411
+ style: customStyle,
3412
+ onValueChange,
3413
+ onChange,
3414
+ ...inputProps
3415
+ } = props;
3416
+ const isControlled = value !== void 0;
3417
+ const [uncontrolledValue, setUncontrolledValue] = React5.useState(
3418
+ () => resolveSliderValue({ min, max, step, value, defaultValue })
3419
+ );
3420
+ React5.useEffect(() => {
3421
+ if (!isControlled) {
3422
+ setUncontrolledValue(resolveSliderValue({ min, max, step, defaultValue }));
3423
+ }
3424
+ }, [defaultValue, isControlled, max, min, step]);
3425
+ const currentValue = isControlled ? resolveSliderValue({ min, max, step, value }) : uncontrolledValue;
3426
+ const kit = createSliderRecipe(
3427
+ buildSliderOptions({
3428
+ id,
3429
+ name,
3430
+ min,
3431
+ max,
3432
+ step,
3433
+ value: currentValue,
3434
+ disabled,
3435
+ required,
3436
+ showTooltip,
3437
+ showTouchArea,
3438
+ orientation,
3439
+ ariaLabel,
3440
+ ariaLabelledBy,
3441
+ ariaDescribedBy,
3442
+ ariaValueText
3443
+ })
3444
+ );
3445
+ useRenderKitDebug(kit, "Slider");
3446
+ const className = customClassName ? `${kit.className} ${customClassName}` : kit.className;
3447
+ const style = { ...kit.vars, ...customStyle };
3448
+ const handleChange = (event) => {
3449
+ const nextValue = Number(event.currentTarget.value);
3450
+ if (!isControlled) {
3451
+ setUncontrolledValue(nextValue);
3452
+ }
3453
+ onChange?.(event);
3454
+ onValueChange?.(nextValue);
3455
+ };
3456
+ return /* @__PURE__ */ jsx("div", { className, style, ...kit.dataAttributes, children: /* @__PURE__ */ jsxs("div", { className: "mw-slider__control", children: [
3457
+ /* @__PURE__ */ jsx(
3458
+ "input",
3459
+ {
3460
+ ...inputProps,
3461
+ ref,
3462
+ type: kit.a11y.type,
3463
+ id: kit.a11y.id,
3464
+ name: kit.a11y.name,
3465
+ min: kit.a11y.min,
3466
+ max: kit.a11y.max,
3467
+ step: kit.a11y.step,
3468
+ disabled: kit.a11y.disabled === true,
3469
+ required: kit.a11y.required === true,
3470
+ "aria-label": kit.a11y.ariaLabel,
3471
+ "aria-labelledby": kit.a11y.ariaLabelledBy,
3472
+ "aria-describedby": kit.a11y.ariaDescribedBy,
3473
+ "aria-valuetext": kit.a11y.ariaValueText,
3474
+ "aria-orientation": kit.a11y.ariaOrientation,
3475
+ className: kit.inputClassName,
3476
+ value: currentValue,
3477
+ onChange: handleChange
3478
+ }
3479
+ ),
3480
+ /* @__PURE__ */ jsxs("div", { className: "mw-slider__visual", "aria-hidden": "true", children: [
3481
+ /* @__PURE__ */ jsx("span", { className: "mw-slider__track" }),
3482
+ /* @__PURE__ */ jsx("span", { className: "mw-slider__fill" }),
3483
+ /* @__PURE__ */ jsx("span", { className: "mw-slider__touch-area" }),
3484
+ /* @__PURE__ */ jsx("span", { className: "mw-slider__thumb" })
3485
+ ] }),
3486
+ kit.showTooltip ? /* @__PURE__ */ jsx("span", { className: "mw-slider__tooltip", "aria-hidden": "true", children: currentValue }) : null
3487
+ ] }) });
3488
+ });
3489
+ Slider.displayName = "Slider";
3490
+ function cx15(...parts) {
3491
+ return parts.filter(Boolean).join(" ");
3492
+ }
3493
+ function hasContent6(value) {
3494
+ if (value === void 0 || value === null || value === false) {
3495
+ return false;
3496
+ }
3497
+ if (typeof value === "string") {
3498
+ return value.trim().length > 0;
3499
+ }
3500
+ return true;
3501
+ }
3502
+ function resolveEdgeValueLabel(value, fallback) {
3503
+ return value ?? `${fallback}`;
3504
+ }
3505
+ function SliderField(props) {
3506
+ const reactId = React5.useId();
3507
+ const id = props.id ?? `mw-slider-${reactId}`;
3508
+ const hasDescription = hasContent6(props.description);
3509
+ const hasError = hasContent6(props.error);
3510
+ const { labelId, descriptionId, errorId, describedBy } = buildSliderFieldA11yIds({
3511
+ id,
3512
+ hasDescription,
3513
+ hasError,
3514
+ externalDescribedBy: props.ariaDescribedBy
3515
+ });
3516
+ const disabled = props.slider.disabled || false;
3517
+ const labelPosition = props.labelPosition ?? "top";
3518
+ const showEdgeValues = props.showEdgeValues !== false;
3519
+ const minValue = props.slider.min ?? 0;
3520
+ const maxValue = props.slider.max ?? 100;
3521
+ const minValueLabel = resolveEdgeValueLabel(props.minValueLabel, minValue);
3522
+ const maxValueLabel = resolveEdgeValueLabel(props.maxValueLabel, maxValue);
3523
+ const wrapperClass = cx15(
3524
+ "mw-slider-field",
3525
+ labelPosition === "top" && "mw-slider-field--label-top",
3526
+ labelPosition === "inline" && "mw-slider-field--label-inline",
3527
+ disabled && "mw-slider-field--disabled",
3528
+ hasError && "mw-slider-field--invalid"
3529
+ );
3530
+ const {
3531
+ ariaLabel: _ignoredAriaLabel,
3532
+ ariaLabelledBy: _ignoredAriaLabelledBy,
3533
+ ariaDescribedBy: _ignoredAriaDescribedBy,
3534
+ style: sliderStyle,
3535
+ ...sliderProps
3536
+ } = props.slider;
3537
+ 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 }) });
3538
+ return /* @__PURE__ */ jsxs("div", { className: wrapperClass, "data-label-position": labelPosition, ...props.dataAttributes, children: [
3539
+ /* @__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 }) }) }),
3540
+ hasDescription && /* @__PURE__ */ jsx("div", { className: "mw-slider-field__description", id: descriptionId, children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.description }) }),
3541
+ labelPosition === "top" && showEdgeValues ? /* @__PURE__ */ jsxs("div", { className: "mw-slider-field__values-row", children: [
3542
+ renderEdgeValue("min", minValueLabel),
3543
+ renderEdgeValue("max", maxValueLabel)
3544
+ ] }) : null,
3545
+ /* @__PURE__ */ jsxs("div", { className: "mw-slider-field__control-row", children: [
3546
+ labelPosition === "inline" && showEdgeValues ? renderEdgeValue("min", minValueLabel) : null,
3547
+ /* @__PURE__ */ jsx("div", { className: "mw-slider-field__slider", children: /* @__PURE__ */ jsx(
3548
+ Slider,
3549
+ {
3550
+ ...sliderProps,
3551
+ id,
3552
+ ariaLabelledBy: labelId,
3553
+ ...describedBy ? { ariaDescribedBy: describedBy } : {},
3554
+ "aria-invalid": hasError ? true : void 0,
3555
+ style: { width: "100%", ...sliderStyle ?? {} }
3556
+ }
3557
+ ) }),
3558
+ labelPosition === "inline" && showEdgeValues ? renderEdgeValue("max", maxValueLabel) : null
3559
+ ] }),
3560
+ hasError && /* @__PURE__ */ jsx("div", { className: "mw-slider-field__error", id: errorId, "aria-live": "polite", children: /* @__PURE__ */ jsx(Paragraph, { size: "sm", children: props.error }) })
3561
+ ] });
3562
+ }
3563
+ function VolumeSlider(props) {
3564
+ const { orientation, slider, ...fieldProps } = props;
3565
+ return /* @__PURE__ */ jsx(
3566
+ SliderField,
3567
+ {
3568
+ ...fieldProps,
3569
+ label: props.label ?? "Volume",
3570
+ minValueLabel: props.minValueLabel ?? "0",
3571
+ maxValueLabel: props.maxValueLabel ?? "100",
3572
+ slider: {
3573
+ min: 0,
3574
+ max: 100,
3575
+ step: 1,
3576
+ showTooltip: true,
3577
+ ...orientation !== void 0 ? { orientation } : {},
3578
+ ...slider
3579
+ },
3580
+ dataAttributes: {
3581
+ ...props.dataAttributes,
3582
+ "data-purpose": "volume"
3583
+ }
3584
+ }
3585
+ );
3586
+ }
3587
+ function BrightnessSlider(props) {
3588
+ const { orientation, slider, ...fieldProps } = props;
3589
+ return /* @__PURE__ */ jsx(
3590
+ SliderField,
3591
+ {
3592
+ ...fieldProps,
3593
+ label: props.label ?? "Brightness",
3594
+ minValueLabel: props.minValueLabel ?? "0",
3595
+ maxValueLabel: props.maxValueLabel ?? "100",
3596
+ slider: {
3597
+ min: 0,
3598
+ max: 100,
3599
+ step: 1,
3600
+ showTooltip: true,
3601
+ ...orientation !== void 0 ? { orientation } : {},
3602
+ ...slider
3603
+ },
3604
+ dataAttributes: {
3605
+ ...props.dataAttributes,
3606
+ "data-purpose": "brightness"
3607
+ }
3608
+ }
3609
+ );
3610
+ }
3611
+ function RadiusSlider(props) {
3612
+ const { orientation, slider, ...fieldProps } = props;
3613
+ return /* @__PURE__ */ jsx(
3614
+ SliderField,
3615
+ {
3616
+ ...fieldProps,
3617
+ label: props.label ?? "Radius",
3618
+ minValueLabel: props.minValueLabel ?? "0px",
3619
+ maxValueLabel: props.maxValueLabel ?? "48px",
3620
+ slider: {
3621
+ min: 0,
3622
+ max: 48,
3623
+ step: 2,
3624
+ showTooltip: true,
3625
+ ...orientation !== void 0 ? { orientation } : {},
3626
+ ...slider
3627
+ },
3628
+ dataAttributes: {
3629
+ ...props.dataAttributes,
3630
+ "data-purpose": "radius"
3631
+ }
3632
+ }
3633
+ );
3634
+ }
3635
+ function Tab(props) {
3636
+ const { children, className, onClick, id, ...coreProps } = props;
3637
+ const kit = createTabRecipe(coreProps);
3638
+ const { a11y } = kit;
3639
+ return /* @__PURE__ */ jsx(
3640
+ "button",
3641
+ {
3642
+ id,
3643
+ className: [kit.className, className].filter(Boolean).join(" "),
3644
+ style: Object.keys(kit.vars).length > 0 ? kit.vars : void 0,
3645
+ role: a11y.role,
3646
+ "aria-selected": a11y.ariaSelected,
3647
+ "aria-disabled": a11y.ariaDisabled,
3648
+ "aria-label": a11y.ariaLabel,
3649
+ "aria-controls": a11y.ariaControls,
3650
+ tabIndex: a11y.tabIndex,
3651
+ disabled: coreProps.disabled,
3652
+ onClick,
3653
+ type: "button",
3654
+ children
3655
+ }
3656
+ );
3657
+ }
3658
+ function cx16(...parts) {
3659
+ return parts.filter(Boolean).join(" ");
3660
+ }
3661
+ function hasContent7(value) {
3662
+ if (value === void 0 || value === null || value === false) {
3663
+ return false;
3664
+ }
3665
+ if (typeof value === "string") {
3666
+ return value.trim().length > 0;
3667
+ }
3668
+ return true;
3669
+ }
3670
+ function focusTab(tabId) {
3671
+ if (typeof document === "undefined") {
3672
+ return;
3673
+ }
3674
+ const tab = document.getElementById(tabId);
3675
+ if (tab instanceof HTMLButtonElement) {
3676
+ tab.focus();
3677
+ }
3678
+ }
3679
+ function toItemState(tab) {
3680
+ const itemState = { value: tab.value };
3681
+ if (tab.disabled) {
3682
+ itemState.disabled = true;
3683
+ }
3684
+ return itemState;
3685
+ }
3686
+ function renderPanelContent(children) {
3687
+ if (typeof children === "string" || typeof children === "number") {
3688
+ return /* @__PURE__ */ jsx(Paragraph, { size: "md", children });
3689
+ }
3690
+ return children;
3691
+ }
3692
+ function TabPanel(props) {
3693
+ return /* @__PURE__ */ jsx(
3694
+ "div",
3695
+ {
3696
+ id: props.id,
3697
+ role: "tabpanel",
3698
+ "aria-labelledby": props.tabId,
3699
+ className: cx16("mw-tab-group__panel", props.className),
3700
+ hidden: props.hidden,
3701
+ tabIndex: props.hidden ? void 0 : 0,
3702
+ children: renderPanelContent(props.children)
3703
+ }
3704
+ );
3705
+ }
3706
+ function TabGroup(props) {
3707
+ const reactId = React5.useId();
3708
+ const id = props.id ?? `mw-tab-group-${reactId}`;
3709
+ const hasLabel = hasContent7(props.label);
3710
+ const itemStates = React5.useMemo(
3711
+ () => props.tabs.map((tab) => toItemState(tab)),
3712
+ [props.tabs]
3713
+ );
3714
+ const isControlled = props.activeTab !== void 0;
3715
+ const [internalActiveTab, setInternalActiveTab] = React5.useState(
3716
+ () => resolveTabValue(itemStates, props.defaultActiveTab)
3717
+ );
3718
+ const resolvedActiveTab = React5.useMemo(
3719
+ () => resolveTabValue(itemStates, isControlled ? props.activeTab : internalActiveTab),
3720
+ [internalActiveTab, isControlled, itemStates, props.activeTab]
3721
+ );
3722
+ React5.useEffect(() => {
3723
+ if (!isControlled) {
3724
+ setInternalActiveTab(
3725
+ (currentValue) => resolveTabValue(itemStates, currentValue ?? props.defaultActiveTab)
3726
+ );
3727
+ }
3728
+ }, [isControlled, itemStates, props.defaultActiveTab]);
3729
+ const a11yIds = React5.useMemo(
3730
+ () => buildTabGroupA11yIds({
3731
+ id,
3732
+ itemValues: props.tabs.map((tab) => tab.value),
3733
+ hasLabel
3734
+ }),
3735
+ [hasLabel, id, props.tabs]
3736
+ );
3737
+ const selectTab = React5.useCallback(
3738
+ (nextValue) => {
3739
+ const resolvedValue = resolveTabValue(itemStates, nextValue);
3740
+ if (!resolvedValue) {
3741
+ return;
3742
+ }
3743
+ if (!isControlled) {
3744
+ setInternalActiveTab(resolvedValue);
3745
+ }
3746
+ if (resolvedValue !== resolvedActiveTab) {
3747
+ props.onActiveTabChange?.(resolvedValue);
3748
+ }
3749
+ },
3750
+ [isControlled, itemStates, props.onActiveTabChange, resolvedActiveTab]
3751
+ );
3752
+ const handleKeyDown = React5.useCallback(
3753
+ (event) => {
3754
+ let direction;
3755
+ switch (event.key) {
3756
+ case "ArrowRight":
3757
+ direction = "next";
3758
+ break;
3759
+ case "ArrowLeft":
3760
+ direction = "previous";
3761
+ break;
3762
+ case "Home":
3763
+ direction = "start";
3764
+ break;
3765
+ case "End":
3766
+ direction = "end";
3767
+ break;
3768
+ default:
3769
+ return;
3770
+ }
3771
+ event.preventDefault();
3772
+ const nextValue = moveTabSelection(itemStates, resolvedActiveTab, direction);
3773
+ if (!nextValue) {
3774
+ return;
3775
+ }
3776
+ selectTab(nextValue);
3777
+ const nextTabId = a11yIds.tabIds[nextValue];
3778
+ if (nextTabId) {
3779
+ focusTab(nextTabId);
3780
+ }
3781
+ },
3782
+ [a11yIds.tabIds, itemStates, resolvedActiveTab, selectTab]
3783
+ );
3784
+ return /* @__PURE__ */ jsxs("section", { className: cx16("mw-tab-group", props.className), ...props.dataAttributes, children: [
3785
+ hasLabel && /* @__PURE__ */ jsx("div", { className: "mw-tab-group__header", children: /* @__PURE__ */ jsx(Paragraph, { size: "md", id: a11yIds.labelId ?? `${id}-label`, children: props.label }) }),
3786
+ /* @__PURE__ */ jsx(
3787
+ "div",
3788
+ {
3789
+ id: a11yIds.tabListId,
3790
+ className: "mw-tab-group__list",
3791
+ role: "tablist",
3792
+ "aria-label": hasLabel ? void 0 : props.ariaLabel ?? "Tabs",
3793
+ "aria-labelledby": hasLabel ? a11yIds.labelId : void 0,
3794
+ onKeyDown: handleKeyDown,
3795
+ children: props.tabs.map((tab) => {
3796
+ const tabId = a11yIds.tabIds[tab.value] ?? `${id}-tab-${tab.value}`;
3797
+ const panelId = a11yIds.panelIds[tab.value] ?? `${id}-panel-${tab.value}`;
3798
+ const tabProps = {
3799
+ id: tabId,
3800
+ selected: tab.value === resolvedActiveTab,
3801
+ ariaControls: panelId,
3802
+ onClick: () => selectTab(tab.value)
3803
+ };
3804
+ if (tab.disabled) {
3805
+ tabProps.disabled = true;
3806
+ }
3807
+ if (tab.ariaLabel) {
3808
+ tabProps.ariaLabel = tab.ariaLabel;
3809
+ }
3810
+ return /* @__PURE__ */ jsx(Tab, { ...tabProps, children: tab.label }, tab.value);
3811
+ })
3812
+ }
3813
+ ),
3814
+ /* @__PURE__ */ jsx("div", { className: "mw-tab-group__panels", children: props.tabs.map((tab) => {
3815
+ const panelId = a11yIds.panelIds[tab.value] ?? `${id}-panel-${tab.value}`;
3816
+ const tabId = a11yIds.tabIds[tab.value] ?? `${id}-tab-${tab.value}`;
3817
+ return /* @__PURE__ */ jsx(
3818
+ TabPanel,
3819
+ {
3820
+ id: panelId,
3821
+ tabId,
3822
+ hidden: tab.value !== resolvedActiveTab,
3823
+ children: tab.panel
3824
+ },
3825
+ tab.value
3826
+ );
3827
+ }) })
3828
+ ] });
3829
+ }
3830
+ function NavigationTabs(props) {
3831
+ return /* @__PURE__ */ jsx(
3832
+ TabGroup,
3833
+ {
3834
+ ...props,
3835
+ ariaLabel: props.ariaLabel ?? "Navigation tabs",
3836
+ dataAttributes: {
3837
+ ...props.dataAttributes,
3838
+ "data-purpose": "navigation-tabs"
3839
+ }
3840
+ }
3841
+ );
3842
+ }
3843
+ function ContentTabs(props) {
3844
+ return /* @__PURE__ */ jsx(
3845
+ TabGroup,
3846
+ {
3847
+ ...props,
3848
+ ariaLabel: props.ariaLabel ?? "Content tabs",
3849
+ dataAttributes: {
3850
+ ...props.dataAttributes,
3851
+ "data-purpose": "content-tabs"
3852
+ }
3853
+ }
3854
+ );
3855
+ }
3856
+ function SettingsTabs(props) {
3857
+ return /* @__PURE__ */ jsx(
3858
+ TabGroup,
3859
+ {
3860
+ ...props,
3861
+ ariaLabel: props.ariaLabel ?? "Settings tabs",
3862
+ dataAttributes: {
3863
+ ...props.dataAttributes,
3864
+ "data-purpose": "settings-tabs"
3865
+ }
3866
+ }
3867
+ );
3868
+ }
3869
+ function cx17(...parts) {
3870
+ return parts.filter(Boolean).join(" ");
3871
+ }
3872
+ function hasContent8(value) {
3873
+ if (value === void 0 || value === null || value === false) {
3874
+ return false;
3875
+ }
3876
+ if (typeof value === "string") {
3877
+ return value.trim().length > 0;
3878
+ }
3879
+ return true;
3880
+ }
3881
+ function Dialog(props) {
3882
+ const reactId = React5.useId();
3883
+ const id = props.id ?? `mw-dialog-${reactId}`;
3884
+ const titleId = `${id}-title`;
3885
+ const descriptionId = `${id}-description`;
3886
+ const hasTitle = hasContent8(props.title);
3887
+ const hasDescription = hasContent8(props.description);
3888
+ const hasFooter = hasContent8(props.footer) && (props.showFooter ?? true);
3889
+ const dismissible = (props.dismissible ?? true) && props.onClose !== void 0;
3890
+ const dialogOptions = {
3891
+ showFooter: hasFooter,
3892
+ dismissible,
3893
+ ...props.modal !== void 0 ? { modal: props.modal } : {}
3894
+ };
3895
+ if (props.dataAttributes) {
3896
+ dialogOptions.dataAttributes = props.dataAttributes;
3897
+ }
3898
+ if (props.size) {
3899
+ dialogOptions.size = props.size;
3900
+ }
3901
+ if (props.ariaLabel) {
3902
+ dialogOptions.ariaLabel = props.ariaLabel;
3903
+ }
3904
+ if (props.ariaLabelledBy) {
3905
+ dialogOptions.ariaLabelledBy = props.ariaLabelledBy;
3906
+ } else if (props.ariaLabel === void 0 && hasTitle) {
3907
+ dialogOptions.ariaLabelledBy = titleId;
3908
+ }
3909
+ if (props.ariaDescribedBy) {
3910
+ dialogOptions.ariaDescribedBy = props.ariaDescribedBy;
3911
+ } else if (hasDescription) {
3912
+ dialogOptions.ariaDescribedBy = descriptionId;
3913
+ }
3914
+ const kit = createDialogRecipe(dialogOptions);
3915
+ return /* @__PURE__ */ jsxs(
3916
+ "section",
3917
+ {
3918
+ id,
3919
+ className: cx17(kit.className, props.className),
3920
+ role: kit.a11y.role,
3921
+ ...kit.a11y.ariaModal ? { "aria-modal": "true" } : {},
3922
+ ...kit.a11y.ariaLabel ? { "aria-label": kit.a11y.ariaLabel } : {},
3923
+ ...kit.a11y.ariaLabelledBy ? { "aria-labelledby": kit.a11y.ariaLabelledBy } : {},
3924
+ ...kit.a11y.ariaDescribedBy ? { "aria-describedby": kit.a11y.ariaDescribedBy } : {},
3925
+ tabIndex: -1,
3926
+ ...kit.dataAttributes,
3927
+ children: [
3928
+ (hasTitle || kit.showCloseButton) && /* @__PURE__ */ jsxs(Fragment, { children: [
3929
+ /* @__PURE__ */ jsxs("header", { className: "mw-dialog__header", children: [
3930
+ hasTitle ? /* @__PURE__ */ jsx("div", { className: "mw-dialog__heading-group", children: /* @__PURE__ */ jsx("h2", { className: "mw-dialog__title", id: titleId, children: props.title }) }) : /* @__PURE__ */ jsx("span", { className: "mw-dialog__spacer", "aria-hidden": "true" }),
3931
+ kit.showCloseButton && props.onClose && /* @__PURE__ */ jsx(
3932
+ "button",
3933
+ {
3934
+ type: "button",
3935
+ className: "mw-dialog__close",
3936
+ "aria-label": "Close dialog",
3937
+ onClick: props.onClose,
3938
+ children: /* @__PURE__ */ jsx(Icon, { name: IconName.X, decorative: true })
3939
+ }
3940
+ )
3941
+ ] }),
3942
+ /* @__PURE__ */ jsx("div", { className: "mw-dialog__header-divider", "aria-hidden": "true" })
3943
+ ] }),
3944
+ /* @__PURE__ */ jsxs("div", { className: "mw-dialog__content", children: [
3945
+ hasDescription && /* @__PURE__ */ jsx("p", { className: "mw-dialog__description", id: descriptionId, children: props.description }),
3946
+ props.children
3947
+ ] }),
3948
+ hasFooter && /* @__PURE__ */ jsxs(Fragment, { children: [
3949
+ /* @__PURE__ */ jsx("div", { className: "mw-dialog__footer-divider", "aria-hidden": "true" }),
3950
+ /* @__PURE__ */ jsx("footer", { className: "mw-dialog__footer", children: props.footer })
3951
+ ] })
3952
+ ]
3953
+ }
3954
+ );
3955
+ }
3956
+ function cx18(...parts) {
3957
+ return parts.filter(Boolean).join(" ");
3958
+ }
3959
+ function getFocusableElements(container) {
3960
+ if (!container) {
3961
+ return [];
3962
+ }
3963
+ return Array.from(
3964
+ container.querySelectorAll(
3965
+ [
3966
+ "button:not([disabled])",
3967
+ "[href]",
3968
+ "input:not([disabled])",
3969
+ "select:not([disabled])",
3970
+ "textarea:not([disabled])",
3971
+ "[tabindex]:not([tabindex='-1'])"
3972
+ ].join(",")
3973
+ )
3974
+ ).filter(
3975
+ (element) => !element.hasAttribute("hidden") && element.getAttribute("aria-hidden") !== "true"
3976
+ );
3977
+ }
3978
+ function focusFirstElement(container) {
3979
+ const focusableElements = getFocusableElements(container);
3980
+ const firstFocusable = focusableElements[0];
3981
+ if (firstFocusable) {
3982
+ firstFocusable.focus();
3983
+ return;
3984
+ }
3985
+ container?.focus();
3986
+ }
3987
+ function DialogModal(props) {
3988
+ const {
3989
+ open,
3990
+ defaultOpen = false,
3991
+ onOpenChange,
3992
+ closeOnEscape = true,
3993
+ closeOnScrimClick = true,
3994
+ restoreFocus = true,
3995
+ portalTarget,
3996
+ overlayClassName,
3997
+ footer,
3998
+ ...dialogProps
3999
+ } = props;
4000
+ const isControlled = open !== void 0;
4001
+ const [internalOpen, setInternalOpen] = React5.useState(defaultOpen);
4002
+ const resolvedOpen = isControlled ? open : internalOpen;
4003
+ const overlayRef = React5.useRef(null);
4004
+ const surfaceRef = React5.useRef(null);
4005
+ const lastFocusedElementRef = React5.useRef(null);
4006
+ const close = React5.useCallback(() => {
4007
+ if (!resolvedOpen) {
4008
+ return;
4009
+ }
4010
+ if (!isControlled) {
4011
+ setInternalOpen(false);
4012
+ }
4013
+ onOpenChange?.(false);
4014
+ }, [isControlled, onOpenChange, resolvedOpen]);
4015
+ React5.useEffect(() => {
4016
+ if (!resolvedOpen || typeof document === "undefined") {
4017
+ return;
4018
+ }
4019
+ const previousOverflow = document.body.style.overflow;
4020
+ lastFocusedElementRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
4021
+ document.body.style.overflow = "hidden";
4022
+ const frameId = window.requestAnimationFrame(() => {
4023
+ const dialogElement = overlayRef.current?.querySelector(".mw-dialog") ?? null;
4024
+ focusFirstElement(dialogElement);
4025
+ });
4026
+ return () => {
4027
+ window.cancelAnimationFrame(frameId);
4028
+ document.body.style.overflow = previousOverflow;
4029
+ if (restoreFocus) {
4030
+ lastFocusedElementRef.current?.focus();
4031
+ }
4032
+ };
4033
+ }, [resolvedOpen, restoreFocus]);
4034
+ React5.useEffect(() => {
4035
+ if (!resolvedOpen || !closeOnEscape || typeof document === "undefined") {
4036
+ return;
4037
+ }
4038
+ const handleKeyDown2 = (event) => {
4039
+ if (event.key === "Escape") {
4040
+ event.preventDefault();
4041
+ close();
4042
+ }
4043
+ };
4044
+ document.addEventListener("keydown", handleKeyDown2);
4045
+ return () => {
4046
+ document.removeEventListener("keydown", handleKeyDown2);
4047
+ };
4048
+ }, [close, closeOnEscape, resolvedOpen]);
4049
+ const handleKeyDown = React5.useCallback(
4050
+ (event) => {
4051
+ if (event.key === "Escape" && closeOnEscape) {
4052
+ event.preventDefault();
4053
+ event.stopPropagation();
4054
+ close();
4055
+ return;
4056
+ }
4057
+ if (event.key !== "Tab") {
4058
+ return;
4059
+ }
4060
+ const dialogElement = overlayRef.current?.querySelector(".mw-dialog") ?? null;
4061
+ const focusableElements = getFocusableElements(dialogElement);
4062
+ if (focusableElements.length === 0) {
4063
+ event.preventDefault();
4064
+ dialogElement?.focus();
4065
+ return;
4066
+ }
4067
+ const firstFocusable = focusableElements[0];
4068
+ const lastFocusable = focusableElements[focusableElements.length - 1];
4069
+ const activeElement = document.activeElement;
4070
+ if (event.shiftKey && activeElement === firstFocusable) {
4071
+ event.preventDefault();
4072
+ lastFocusable?.focus();
4073
+ } else if (!event.shiftKey && activeElement === lastFocusable) {
4074
+ event.preventDefault();
4075
+ firstFocusable?.focus();
4076
+ }
4077
+ },
4078
+ [close, closeOnEscape]
4079
+ );
4080
+ const renderedFooter = React5.useMemo(
4081
+ () => typeof footer === "function" ? footer({ close }) : footer,
4082
+ [close, footer]
4083
+ );
4084
+ if (!resolvedOpen || typeof document === "undefined") {
4085
+ return null;
4086
+ }
4087
+ const modalMarkup = /* @__PURE__ */ jsxs(
4088
+ "div",
4089
+ {
4090
+ ref: overlayRef,
4091
+ className: cx18("mw-dialog-modal", overlayClassName),
4092
+ onClick: (event) => {
4093
+ if (!closeOnScrimClick) {
4094
+ return;
4095
+ }
4096
+ const clickTarget = event.target;
4097
+ if (!(clickTarget instanceof Node)) {
4098
+ return;
4099
+ }
4100
+ if (surfaceRef.current?.contains(clickTarget)) {
4101
+ return;
4102
+ }
4103
+ close();
4104
+ },
4105
+ onKeyDown: handleKeyDown,
4106
+ children: [
4107
+ /* @__PURE__ */ jsx("div", { className: "mw-dialog-modal__scrim", "aria-hidden": "true" }),
4108
+ /* @__PURE__ */ jsx("div", { ref: surfaceRef, className: "mw-dialog-modal__surface", children: /* @__PURE__ */ jsx(Dialog, { ...dialogProps, modal: true, footer: renderedFooter, onClose: close }) })
4109
+ ]
4110
+ }
4111
+ );
4112
+ if (portalTarget === null) {
4113
+ return modalMarkup;
4114
+ }
4115
+ return createPortal(modalMarkup, portalTarget ?? document.body);
4116
+ }
4117
+ function ConfirmDialog(props) {
4118
+ const {
4119
+ confirmLabel = "Confirm",
4120
+ cancelLabel = "Cancel",
4121
+ onConfirm,
4122
+ onCancel,
4123
+ dataAttributes,
4124
+ ...dialogProps
4125
+ } = props;
4126
+ return /* @__PURE__ */ jsx(
4127
+ DialogModal,
4128
+ {
4129
+ ...dialogProps,
4130
+ dataAttributes: {
4131
+ ...dataAttributes,
4132
+ ...createPurposeSemanticAttributes("confirm-dialog")
4133
+ },
4134
+ footer: ({ close }) => /* @__PURE__ */ jsxs(Fragment, { children: [
4135
+ /* @__PURE__ */ jsx(
4136
+ CancelButton,
4137
+ {
4138
+ onClick: () => {
4139
+ onCancel?.();
4140
+ close();
4141
+ },
4142
+ children: cancelLabel
4143
+ }
4144
+ ),
4145
+ /* @__PURE__ */ jsx(
4146
+ ConfirmButton,
4147
+ {
4148
+ onClick: () => {
4149
+ onConfirm?.();
4150
+ close();
4151
+ },
4152
+ children: confirmLabel
4153
+ }
4154
+ )
4155
+ ] })
4156
+ }
4157
+ );
4158
+ }
4159
+ function DestructiveDialog(props) {
4160
+ const {
4161
+ confirmLabel = "Delete",
4162
+ cancelLabel = "Cancel",
4163
+ onConfirm,
4164
+ onCancel,
4165
+ dataAttributes,
4166
+ ...dialogProps
4167
+ } = props;
4168
+ return /* @__PURE__ */ jsx(
4169
+ DialogModal,
4170
+ {
4171
+ ...dialogProps,
4172
+ dataAttributes: {
4173
+ ...dataAttributes,
4174
+ ...createPurposeSemanticAttributes("destructive-dialog")
4175
+ },
4176
+ footer: ({ close }) => /* @__PURE__ */ jsxs(Fragment, { children: [
4177
+ /* @__PURE__ */ jsx(
4178
+ CancelButton,
4179
+ {
4180
+ onClick: () => {
4181
+ onCancel?.();
4182
+ close();
4183
+ },
4184
+ children: cancelLabel
4185
+ }
4186
+ ),
4187
+ /* @__PURE__ */ jsx(
4188
+ DestructiveButton,
4189
+ {
4190
+ onClick: () => {
4191
+ onConfirm?.();
4192
+ close();
4193
+ },
4194
+ children: confirmLabel
4195
+ }
4196
+ )
4197
+ ] })
4198
+ }
4199
+ );
4200
+ }
4201
+ function InfoDialog(props) {
4202
+ const { acknowledgeLabel = "Okay", onAcknowledge, dataAttributes, ...dialogProps } = props;
4203
+ return /* @__PURE__ */ jsx(
4204
+ DialogModal,
4205
+ {
4206
+ ...dialogProps,
4207
+ dataAttributes: {
4208
+ ...dataAttributes,
4209
+ ...createPurposeSemanticAttributes("info-dialog")
4210
+ },
4211
+ footer: ({ close }) => /* @__PURE__ */ jsx(
4212
+ ConfirmButton,
4213
+ {
4214
+ onClick: () => {
4215
+ onAcknowledge?.();
4216
+ close();
4217
+ },
4218
+ children: acknowledgeLabel
4219
+ }
4220
+ )
4221
+ }
4222
+ );
4223
+ }
419
4224
 
420
- export { Button, CancelButton, Checkbox, CheckboxField, CreateButton, DangerButton, Divider, H1, H2, H3, Icon, Input, InputField, LinkButton, MarwesProvider, Paragraph, PrimaryButton, SecondaryButton, SubmitButton, TextButton, useRenderKitDebug, useSystem, useTheme };
4225
+ export { Accordion, AccordionField, Avatar, AvatarBadge, AvatarGroup, Badge, BadgeGroup, BrightnessSlider, Button, ButtonSpinner, CancelButton, Card, Checkbox, CheckboxField, CheckboxGroupField, CloseButton, ConfirmButton, ConfirmDialog, ContentTabs, CopyButton, CreateButton, CurrencyField, DateOfBirthField, 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, Slider, SliderField, SortButton, Spacer, Spacing, Spinner, StatCard, 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, useToast };
421
4226
  //# sourceMappingURL=index.js.map
422
4227
  //# sourceMappingURL=index.js.map