@mantine-vue/core 3.4.0 → 3.5.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/cjs/index.cjs CHANGED
@@ -8725,21 +8725,21 @@ var AccordionChevron = /* @__PURE__ */ (0, vue.defineComponent)({
8725
8725
  //#region src/components/Accordion/Accordion.context.ts
8726
8726
  var [provideAccordionContext, useAccordionContext] = createSafeContext("Accordion component was not found in the tree");
8727
8727
  var Accordion_module_default = {
8728
- root: "_root_ltqd9_1",
8729
- panel: "_panel_ltqd9_5",
8730
- content: "_content_ltqd9_9",
8731
- itemTitle: "_itemTitle_ltqd9_14",
8732
- control: "_control_ltqd9_20",
8733
- "control--default": "_control--default_ltqd9_42",
8734
- "control--contained": "_control--contained_ltqd9_43",
8735
- label: "_label_ltqd9_57",
8736
- chevron: "_chevron_ltqd9_67",
8737
- icon: "_icon_ltqd9_86",
8738
- item: "_item_ltqd9_14",
8739
- "item--default": "_item--default_ltqd9_110",
8740
- "item--contained": "_item--contained_ltqd9_114",
8741
- "item--filled": "_item--filled_ltqd9_147",
8742
- "item--separated": "_item--separated_ltqd9_155"
8728
+ root: "_root_1ysxv_1",
8729
+ panel: "_panel_1ysxv_5",
8730
+ content: "_content_1ysxv_9",
8731
+ itemTitle: "_itemTitle_1ysxv_14",
8732
+ control: "_control_1ysxv_20",
8733
+ "control--default": "_control--default_1ysxv_42",
8734
+ "control--contained": "_control--contained_1ysxv_43",
8735
+ label: "_label_1ysxv_57",
8736
+ chevron: "_chevron_1ysxv_67",
8737
+ icon: "_icon_1ysxv_86",
8738
+ item: "_item_1ysxv_14",
8739
+ "item--default": "_item--default_1ysxv_110",
8740
+ "item--contained": "_item--contained_1ysxv_114",
8741
+ "item--filled": "_item--filled_1ysxv_149",
8742
+ "item--separated": "_item--separated_1ysxv_157"
8743
8743
  };
8744
8744
  //#endregion
8745
8745
  //#region src/components/Accordion/Accordion.vue?vue&type=script&setup=true&lang.ts
@@ -13915,16 +13915,58 @@ function sanitizeNumberInputString(rawValue, allowDecimal, allowNegative, decima
13915
13915
  }
13916
13916
  return normalized;
13917
13917
  }
13918
- function clampAndSanitizeInput(sanitizedValue, max, min) {
13919
- const stringValue = sanitizedValue.toString();
13920
- const hasTrailingDecimalSeparator = trailingDecimalSeparatorPattern.test(stringValue);
13921
- const replaced = stringValue.replace(/^0+(?=\d)/, "");
13922
- const parsedValue = parseFloat(replaced);
13923
- if (Number.isNaN(parsedValue)) return replaced;
13924
- if (parsedValue > Number.MAX_SAFE_INTEGER) return max !== void 0 ? max : replaced;
13925
- const clamped = clamp$3(parsedValue, min, max);
13926
- if (hasTrailingDecimalSeparator) return `${clamped.toString().replace(/^0+(?=\d)/, "")}.`;
13927
- return clamped;
13918
+ function withTrailingSeparator(value, hasTrailingDecimalSeparator) {
13919
+ return hasTrailingDecimalSeparator ? `${value}.` : value;
13920
+ }
13921
+ function sanitizeInputOnBlur(value, options) {
13922
+ const hasTrailingDecimalSeparator = trailingDecimalSeparatorPattern.test(value);
13923
+ const trimmed = options.trim ? value.replace(/^0+(?=\d)/, "") : value;
13924
+ const parsedValue = parseFloat(trimmed);
13925
+ if (Number.isNaN(parsedValue)) return trimmed;
13926
+ if (!options.clamp) return options.trim ? withTrailingSeparator(parsedValue, hasTrailingDecimalSeparator) : value;
13927
+ const clamped = parsedValue > Number.MAX_SAFE_INTEGER && options.max !== void 0 ? options.max : clamp$3(parsedValue, options.min, options.max);
13928
+ if (!options.trim && clamped === parsedValue) return value;
13929
+ return withTrailingSeparator(clamped, hasTrailingDecimalSeparator);
13930
+ }
13931
+ function countTrailingDigits(value, from) {
13932
+ let count = 0;
13933
+ while (from + count < value.length && /\d/.test(value[from + count])) count += 1;
13934
+ return count;
13935
+ }
13936
+ function normalizePastedValue(value, options) {
13937
+ const candidates = new Set([...options.allowedDecimalSeparators, options.decimalSeparator].filter((separator) => separator.length === 1));
13938
+ const chars = value.split("");
13939
+ const occurrences = chars.reduce((result, char, index) => {
13940
+ if (candidates.has(char)) result.push(index);
13941
+ return result;
13942
+ }, []);
13943
+ if (occurrences.length === 0) return value;
13944
+ const lastIndex = occurrences[occurrences.length - 1];
13945
+ const lastChar = chars[lastIndex];
13946
+ const lastCharCount = occurrences.filter((index) => chars[index] === lastChar).length;
13947
+ const lastGroupSize = options.thousandsGroupStyle === "wan" ? 4 : 3;
13948
+ let decimalIndex = -1;
13949
+ if (lastCharCount === 1) if (lastChar === options.decimalSeparator) decimalIndex = lastIndex;
13950
+ else if (lastChar === options.thousandSeparator) decimalIndex = countTrailingDigits(value, lastIndex + 1) === lastGroupSize ? -1 : lastIndex;
13951
+ else decimalIndex = lastIndex;
13952
+ return chars.map((char, index) => {
13953
+ if (index === decimalIndex) return options.decimalSeparator;
13954
+ if (candidates.has(char) && char !== options.thousandSeparator) return "";
13955
+ return char;
13956
+ }).join("");
13957
+ }
13958
+ function isSignificant(char, decimalSeparator) {
13959
+ return /\d/.test(char) || char === decimalSeparator;
13960
+ }
13961
+ function getCaretPositionAfterPaste(rawValue, rawCaret, formattedValue, decimalSeparator) {
13962
+ let remaining = 0;
13963
+ for (let index = 0; index < rawCaret && index < rawValue.length; index += 1) if (isSignificant(rawValue[index], decimalSeparator)) remaining += 1;
13964
+ if (remaining === 0) return Math.min(rawCaret, formattedValue.length);
13965
+ for (let index = 0; index < formattedValue.length; index += 1) if (isSignificant(formattedValue[index], decimalSeparator)) {
13966
+ remaining -= 1;
13967
+ if (remaining === 0) return index + 1;
13968
+ }
13969
+ return formattedValue.length;
13928
13970
  }
13929
13971
  function isInRange(value, min, max) {
13930
13972
  if (value === void 0) return true;
@@ -14377,12 +14419,41 @@ var NumberInput = factory(/* @__PURE__ */ (0, vue.defineComponent)({
14377
14419
  if (props.selectAllOnFocus) window.setTimeout(() => inputRef.value?.select(), 0);
14378
14420
  else scheduleCaretClamp(event.currentTarget);
14379
14421
  }
14422
+ function onPaste(event) {
14423
+ const pastedText = event.clipboardData?.getData("text") ?? "";
14424
+ const decimalSeparator = props.decimalSeparator || ".";
14425
+ const modifiedText = normalizePastedValue(pastedText, {
14426
+ decimalSeparator,
14427
+ thousandSeparator: props.thousandSeparator === true ? "," : props.thousandSeparator === false ? void 0 : props.thousandSeparator,
14428
+ allowedDecimalSeparators: props.allowedDecimalSeparators,
14429
+ thousandsGroupStyle: props.thousandsGroupStyle
14430
+ });
14431
+ if (modifiedText !== pastedText && inputRef.value) {
14432
+ event.preventDefault();
14433
+ const input = inputRef.value;
14434
+ const start = input.selectionStart ?? 0;
14435
+ const end = input.selectionEnd ?? 0;
14436
+ const newValue = input.value.slice(0, start) + modifiedText + input.value.slice(end);
14437
+ input.value = newValue;
14438
+ input.dispatchEvent(new Event("input", { bubbles: true }));
14439
+ const rawCaret = start + modifiedText.length;
14440
+ setTimeout(() => {
14441
+ const caret = getCaretPositionAfterPaste(newValue, rawCaret, input.value, decimalSeparator);
14442
+ input.setSelectionRange(caret, caret);
14443
+ }, 0);
14444
+ }
14445
+ }
14380
14446
  function onBlur() {
14381
14447
  let sanitizedValue = value.value;
14382
14448
  const min = typeof props.min === "number" ? props.min : void 0;
14383
14449
  const max = typeof props.max === "number" ? props.max : void 0;
14384
14450
  if (props.clampBehavior === "blur" && typeof sanitizedValue === "number") sanitizedValue = clamp$3(sanitizedValue, min, max);
14385
- if (props.trimLeadingZeroesOnBlur && typeof sanitizedValue === "string" && getDecimalPlaces(sanitizedValue) < 15) sanitizedValue = clampAndSanitizeInput(sanitizedValue, max, min);
14451
+ if (!isBigIntMode.value && typeof sanitizedValue === "string") sanitizedValue = sanitizeInputOnBlur(sanitizedValue, {
14452
+ min,
14453
+ max,
14454
+ trim: props.trimLeadingZeroesOnBlur && getDecimalPlaces(sanitizedValue) < 15,
14455
+ clamp: props.clampBehavior === "blur"
14456
+ });
14386
14457
  if (sanitizedValue !== value.value) commitValue(sanitizedValue, "blur");
14387
14458
  }
14388
14459
  return (_ctx, _cache) => {
@@ -14416,6 +14487,7 @@ var NumberInput = factory(/* @__PURE__ */ (0, vue.defineComponent)({
14416
14487
  onKeyup,
14417
14488
  onClick,
14418
14489
  onFocus,
14490
+ onPaste,
14419
14491
  onBlur
14420
14492
  }), (0, vue.createSlots)({ _: 2 }, [
14421
14493
  (0, vue.unref)(slots).label ? {
@@ -16532,8 +16604,16 @@ var SegmentedControl = Object.assign(/* @__PURE__ */ (0, vue.defineComponent)({
16532
16604
  parent.value = node?.$el ?? node ?? null;
16533
16605
  };
16534
16606
  const setItemRef = (key, node) => {
16535
- itemRefs[key] = node?.$el ?? node ?? null;
16607
+ const element = node?.$el ?? node ?? null;
16608
+ if (element === null) delete itemRefs[key];
16609
+ else itemRefs[key] = element;
16536
16610
  };
16611
+ (0, vue.watch)(normalizedData, (items) => {
16612
+ const values = new Set(items.map((item) => String(item.value)));
16613
+ Object.keys(itemRefs).forEach((key) => {
16614
+ if (!values.has(key)) delete itemRefs[key];
16615
+ });
16616
+ });
16537
16617
  const ItemLabel = (item) => (0, vue.h)("span", getStyles("innerLabel"), resolveNode(item.label));
16538
16618
  const handleClick = (event) => {
16539
16619
  if (props.readOnly) event.preventDefault();
@@ -18274,6 +18354,7 @@ var Autosize_default = /* @__PURE__ */ (0, vue.defineComponent)({
18274
18354
  }
18275
18355
  }
18276
18356
  const cleanupFns = [];
18357
+ let resizeFrame = 0;
18277
18358
  (0, vue.onMounted)(() => {
18278
18359
  resizeTextarea();
18279
18360
  const onResize = () => resizeTextarea();
@@ -18285,11 +18366,15 @@ var Autosize_default = /* @__PURE__ */ (0, vue.defineComponent)({
18285
18366
  const observer = new ResizeObserver(() => {
18286
18367
  if (textareaRef.value && textareaRef.value.offsetWidth !== widthRef.value) {
18287
18368
  widthRef.value = textareaRef.value.offsetWidth;
18288
- resizeTextarea();
18369
+ cancelAnimationFrame(resizeFrame);
18370
+ resizeFrame = requestAnimationFrame(resizeTextarea);
18289
18371
  }
18290
18372
  });
18291
18373
  observer.observe(node);
18292
- cleanupFns.push(() => observer.disconnect());
18374
+ cleanupFns.push(() => {
18375
+ cancelAnimationFrame(resizeFrame);
18376
+ observer.disconnect();
18377
+ });
18293
18378
  }
18294
18379
  const onFontsLoaded = () => resizeTextarea();
18295
18380
  document.fonts.addEventListener("loadingdone", onFontsLoaded);
@@ -18306,6 +18391,7 @@ var Autosize_default = /* @__PURE__ */ (0, vue.defineComponent)({
18306
18391
  cleanupFns.push(() => document.body.removeEventListener("reset", onReset));
18307
18392
  });
18308
18393
  (0, vue.onUnmounted)(() => {
18394
+ cancelAnimationFrame(resizeFrame);
18309
18395
  cleanupFns.forEach((fn) => fn());
18310
18396
  cleanupFns.length = 0;
18311
18397
  });
@@ -22819,20 +22905,30 @@ function getEl$1(value) {
22819
22905
  function useDimensions(element) {
22820
22906
  const dimensions = (0, vue.ref)(null);
22821
22907
  let observer = null;
22908
+ let frame = 0;
22822
22909
  (0, vue.onMounted)(() => {
22823
22910
  const el = getEl$1(element.value);
22824
22911
  if (!el || typeof ResizeObserver === "undefined") return;
22825
22912
  observer = new ResizeObserver(([entry]) => {
22826
- if (entry) dimensions.value = {
22827
- width: entry.borderBoxSize?.[0]?.inlineSize ?? entry.target.clientWidth,
22828
- height: entry.borderBoxSize?.[0]?.blockSize ?? entry.target.clientHeight,
22829
- contentWidth: entry.contentRect.width,
22830
- contentHeight: entry.contentRect.height
22831
- };
22913
+ if (entry) {
22914
+ const nextDimensions = {
22915
+ width: entry.borderBoxSize?.[0]?.inlineSize ?? entry.target.clientWidth,
22916
+ height: entry.borderBoxSize?.[0]?.blockSize ?? entry.target.clientHeight,
22917
+ contentWidth: entry.contentRect.width,
22918
+ contentHeight: entry.contentRect.height
22919
+ };
22920
+ cancelAnimationFrame(frame);
22921
+ frame = requestAnimationFrame(() => {
22922
+ dimensions.value = nextDimensions;
22923
+ });
22924
+ }
22832
22925
  });
22833
22926
  observer.observe(el);
22834
22927
  });
22835
- (0, vue.onBeforeUnmount)(() => observer?.disconnect());
22928
+ (0, vue.onBeforeUnmount)(() => {
22929
+ cancelAnimationFrame(frame);
22930
+ observer?.disconnect();
22931
+ });
22836
22932
  return dimensions;
22837
22933
  }
22838
22934
  var OverflowList_module_default = { root: "_root_uggjd_1" };
@@ -28261,7 +28357,10 @@ function useModal(input) {
28261
28357
  const bodyMounted = (0, vue.ref)(false);
28262
28358
  (0, _mantine_vue_hooks.useWindowEvent)("keydown", (event) => {
28263
28359
  const stopped = event.target?.getAttribute?.("data-mantine-stop-propagation") === "true";
28264
- if (event.key === "Escape" && !event.isComposing && input.opened() && input.closeOnEscape() && !stopped) input.onClose();
28360
+ if (event.key === "Escape" && !event.isComposing && input.opened() && input.closeOnEscape() && !input.handledEscapeEvents?.has(event) && !stopped) {
28361
+ input.handledEscapeEvents?.add(event);
28362
+ input.onClose();
28363
+ }
28265
28364
  }, { capture: true });
28266
28365
  (0, _mantine_vue_hooks.useFocusReturn)({
28267
28366
  opened: input.opened,
@@ -28280,6 +28379,7 @@ var ModalBase = factory(/* @__PURE__ */ (0, vue.defineComponent)({
28280
28379
  inheritAttrs: false,
28281
28380
  __name: "ModalBase",
28282
28381
  props: {
28382
+ __handledEscapeEvents: {},
28283
28383
  rootRef: {},
28284
28384
  opened: { type: Boolean },
28285
28385
  id: { default: void 0 },
@@ -28341,7 +28441,8 @@ var ModalBase = factory(/* @__PURE__ */ (0, vue.defineComponent)({
28341
28441
  onClose: () => emit("close"),
28342
28442
  trapFocus: () => props.trapFocus,
28343
28443
  closeOnEscape: () => props.closeOnEscape,
28344
- returnFocus: () => props.returnFocus
28444
+ returnFocus: () => props.returnFocus,
28445
+ handledEscapeEvents: props.__handledEscapeEvents
28345
28446
  });
28346
28447
  useLockScroll((0, vue.computed)(() => props.opened && props.lockScroll));
28347
28448
  provideModalBaseContext({
@@ -28772,6 +28873,7 @@ var ModalRoot_default = /* @__PURE__ */ (0, vue.defineComponent)({
28772
28873
  classNames: {},
28773
28874
  styles: {},
28774
28875
  vars: {},
28876
+ __handledEscapeEvents: {},
28775
28877
  rootRef: {},
28776
28878
  opened: { type: Boolean },
28777
28879
  id: {},
@@ -28935,6 +29037,7 @@ var Modal_default = /* @__PURE__ */ (0, vue.defineComponent)({
28935
29037
  classNames: {},
28936
29038
  styles: {},
28937
29039
  vars: {},
29040
+ __handledEscapeEvents: {},
28938
29041
  rootRef: {},
28939
29042
  opened: { type: Boolean },
28940
29043
  id: {},
@@ -29157,6 +29260,7 @@ var DrawerRoot_default = /* @__PURE__ */ (0, vue.defineComponent)({
29157
29260
  offset: { default: 0 },
29158
29261
  size: { default: "md" },
29159
29262
  scrollAreaComponent: {},
29263
+ __handledEscapeEvents: {},
29160
29264
  rootRef: {},
29161
29265
  opened: { type: Boolean },
29162
29266
  id: {},
@@ -29320,6 +29424,7 @@ var Drawer_default = /* @__PURE__ */ (0, vue.defineComponent)({
29320
29424
  offset: {},
29321
29425
  size: {},
29322
29426
  scrollAreaComponent: {},
29427
+ __handledEscapeEvents: {},
29323
29428
  rootRef: {},
29324
29429
  opened: { type: Boolean },
29325
29430
  id: {},
@@ -29391,7 +29496,8 @@ var Drawer_default = /* @__PURE__ */ (0, vue.defineComponent)({
29391
29496
  const isCurrent = stackCtx.currentId === props.stackId;
29392
29497
  return {
29393
29498
  closeOnEscape: isCurrent,
29394
- trapFocus: isCurrent
29499
+ trapFocus: isCurrent,
29500
+ __handledEscapeEvents: stackCtx.handledEscapeEvents
29395
29501
  };
29396
29502
  });
29397
29503
  /** One overlay for the whole stack: only the topmost drawer renders it. */
@@ -29496,7 +29602,8 @@ var DrawerStack_default = /* @__PURE__ */ (0, vue.defineComponent)({
29496
29602
  },
29497
29603
  get maxZIndex() {
29498
29604
  return maxZIndex.value;
29499
- }
29605
+ },
29606
+ handledEscapeEvents: /* @__PURE__ */ new WeakSet()
29500
29607
  }));
29501
29608
  return (_ctx, _cache) => {
29502
29609
  return (0, vue.renderSlot)(_ctx.$slots, "default");
@@ -32242,6 +32349,8 @@ var MenuSub_default = /* @__PURE__ */ (0, vue.defineComponent)({
32242
32349
  inheritAttrs: false,
32243
32350
  __name: "MenuSub",
32244
32351
  props: {
32352
+ withinPortal: {},
32353
+ portalProps: {},
32245
32354
  opened: {
32246
32355
  type: Boolean,
32247
32356
  default: void 0
@@ -32275,7 +32384,7 @@ var MenuSub_default = /* @__PURE__ */ (0, vue.defineComponent)({
32275
32384
  transitionProps: props.transitionProps,
32276
32385
  middlewares: props.middlewares,
32277
32386
  closeOnItemClick: false,
32278
- withinPortal: attrs.withinPortal ?? false
32387
+ withinPortal: false
32279
32388
  }));
32280
32389
  return (_ctx, _cache) => {
32281
32390
  return (0, vue.openBlock)(), (0, vue.createBlock)(Menu_default, (0, vue.normalizeProps)((0, vue.guardReactiveProps)(menuBindings.value)), {
@@ -33261,7 +33370,6 @@ function useCombobox(options = {}) {
33261
33370
  const items = () => Array.from(list()?.querySelectorAll("[data-combobox-option]") ?? []);
33262
33371
  const clearSelected = () => items().forEach((item) => {
33263
33372
  item.removeAttribute("data-combobox-selected");
33264
- item.removeAttribute("aria-selected");
33265
33373
  });
33266
33374
  const selectOption = (index) => {
33267
33375
  const optionsList = items();
@@ -33276,7 +33384,6 @@ function useCombobox(options = {}) {
33276
33384
  selectedIndex.value = next;
33277
33385
  clearSelected();
33278
33386
  optionsList[next].setAttribute("data-combobox-selected", "true");
33279
- optionsList[next].setAttribute("aria-selected", "true");
33280
33387
  optionsList[next].scrollIntoView?.({
33281
33388
  block: "nearest",
33282
33389
  behavior: options.scrollBehavior ?? "instant"
@@ -34728,7 +34835,6 @@ var ComboboxPopover_default = /* @__PURE__ */ (0, vue.defineComponent)({
34728
34835
  onDropdownClose: () => {
34729
34836
  emit("dropdown-close");
34730
34837
  combobox.resetSelectedOption();
34731
- if (props.searchable) combobox.focusTarget();
34732
34838
  }
34733
34839
  });
34734
34840
  function handleSearchChange(val) {
@@ -34764,6 +34870,7 @@ var ComboboxPopover_default = /* @__PURE__ */ (0, vue.defineComponent)({
34764
34870
  styles: props.styles,
34765
34871
  unstyled: props.unstyled,
34766
34872
  onOptionSubmit: handleOptionSubmit,
34873
+ returnFocus: true,
34767
34874
  ...props.comboboxProps,
34768
34875
  ...attrs
34769
34876
  }));