@wistia/vhs 6.0.2 → 6.0.3-beta.09ffba11.342c05b

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,6 +1,6 @@
1
1
 
2
2
  /*
3
- * @license @wistia/vhs v6.0.2
3
+ * @license @wistia/vhs v6.0.3-beta.09ffba11.342c05b
4
4
  *
5
5
  * Copyright (c) 2021-2026, Wistia, Inc. and its affiliates.
6
6
  *
@@ -8,9 +8,8 @@
8
8
  */
9
9
 
10
10
  import { AnimatePresence, MotionConfig, motion } from "motion/react";
11
- import { LiveAnnouncer, LiveMessage } from "react-aria-live";
12
11
  import { hasKey, isArray, isBoolean, isEmptyString, isFunction, isNil, isNonEmptyArray, isNonEmptyString, isNotNil, isNotUndefined, isNumber, isString, isUndefined } from "@wistia/type-guards";
13
- import { Children, Fragment, cloneElement, createContext, forwardRef, isValidElement, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
12
+ import { Children, Fragment, cloneElement, createContext, forwardRef, isValidElement, memo, use, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
14
13
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
15
14
  import { createPortal } from "react-dom";
16
15
  import { ThemeProvider, createGlobalStyle, css, keyframes, styled, useTheme as useTheme$1 } from "styled-components";
@@ -25,7 +24,7 @@ import { withHistory } from "slate-history";
25
24
  import { Editable, ReactEditor, Slate, useFocused, useSelected, useSlate, withReact } from "slate-react";
26
25
  import { jsx as jsx$1 } from "slate-hyperscript";
27
26
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuItemIndicator, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup as MenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu";
28
- import { addDays, addMonths, addYears, compareAsc, differenceInDays, eachDayOfInterval, eachMonthOfInterval, endOfDay, endOfMonth, getDay, getDaysInMonth, getYear, isAfter, isBefore, isEqual as isEqual$1, isFuture, isSameDay, isValid, isWithinInterval, startOfDay, startOfMonth } from "date-fns";
27
+ import { addDays, addMonths, addYears, compareAsc, differenceInDays, differenceInMilliseconds, eachDayOfInterval, eachMonthOfInterval, endOfDay, endOfMonth, getDay, getDaysInMonth, getYear, isAfter, isBefore, isEqual as isEqual$1, isFuture, isSameDay, isValid, isWithinInterval, startOfDay, startOfMonth } from "date-fns";
29
28
  import ReactSlider from "react-slider";
30
29
  //#region \0rolldown/runtime.js
31
30
  var __defProp = Object.defineProperty;
@@ -110,6 +109,123 @@ const useThemeColor = (colorName = null) => {
110
109
  return getColor(colors, colorName);
111
110
  };
112
111
  //#endregion
112
+ //#region src/providers/AriaLiveProvider/AriaLiveContext.tsx
113
+ const warnMissingProvider = () => {
114
+ console.warn("Announcement failed: render VHSProvider (or AriaLiveProvider) above this component");
115
+ };
116
+ const AriaLiveContext = createContext({ announce: warnMissingProvider });
117
+ //#endregion
118
+ //#region src/components/ScreenReaderOnly/ScreenReaderOnly.tsx
119
+ const screenReaderOnlyStyle = css`
120
+ border: 0;
121
+ clip-path: inset(50%);
122
+ height: 1px;
123
+ overflow: hidden;
124
+ padding: 0;
125
+ position: absolute;
126
+ white-space: nowrap;
127
+ width: 1px;
128
+ `;
129
+ const VisuallyHidden = styled.div`
130
+ ${screenReaderOnlyStyle}
131
+ `;
132
+ const VisuallyHiddenButFocusable = styled.div`
133
+ &:not(:focus-within) {
134
+ ${screenReaderOnlyStyle}
135
+ }
136
+ `;
137
+ const ScreenReaderOnly = ({ text, children, focusable = false, ...otherProps }) => {
138
+ const accessibleText = isNotNil(text) ? text : children;
139
+ if (focusable) return /* @__PURE__ */ jsx(VisuallyHiddenButFocusable, {
140
+ ...otherProps,
141
+ children: accessibleText
142
+ });
143
+ return /* @__PURE__ */ jsx(VisuallyHidden, {
144
+ ...otherProps,
145
+ children: accessibleText
146
+ });
147
+ };
148
+ ScreenReaderOnly.displayName = "ScreenReaderOnly_VHS";
149
+ //#endregion
150
+ //#region src/providers/AriaLiveProvider/AriaLiveProvider.tsx
151
+ const ANNOUNCEMENT_CLEAR_DELAY_MS = 5e3;
152
+ const HiddenRegion = styled.div`
153
+ ${screenReaderOnlyStyle}
154
+ margin: -1px;
155
+ `;
156
+ const LiveRegion = ({ announcements, politeness }) => /* @__PURE__ */ jsx(HiddenRegion, {
157
+ "aria-live": politeness,
158
+ role: "log",
159
+ children: announcements.filter((announcement) => announcement.politeness === politeness).map((announcement) => /* @__PURE__ */ jsx("div", { children: announcement.message }, announcement.id))
160
+ });
161
+ const AriaLiveProvider = ({ children }) => {
162
+ const [announcements, setAnnouncements] = useState([]);
163
+ const nextId = useRef(0);
164
+ const pendingKeys = useRef(/* @__PURE__ */ new Set());
165
+ useEffect(() => {
166
+ pendingKeys.current.clear();
167
+ });
168
+ useEffect(() => {
169
+ if (announcements.length === 0) return;
170
+ const soonest = Math.min(...announcements.map((announcement) => announcement.expiresAt));
171
+ const timer = setTimeout(() => {
172
+ const now = Date.now();
173
+ setAnnouncements((current) => current.filter((announcement) => announcement.expiresAt > now));
174
+ }, Math.max(soonest - Date.now(), 0));
175
+ return () => {
176
+ clearTimeout(timer);
177
+ };
178
+ }, [announcements]);
179
+ const announce = useCallback((message, politeness = "polite") => {
180
+ if (!isNonEmptyString(message)) return;
181
+ const key = `${politeness}:${message}`;
182
+ if (pendingKeys.current.has(key)) return;
183
+ pendingKeys.current.add(key);
184
+ const id = nextId.current;
185
+ nextId.current += 1;
186
+ const expiresAt = Date.now() + ANNOUNCEMENT_CLEAR_DELAY_MS;
187
+ setAnnouncements((current) => [...current, {
188
+ expiresAt,
189
+ id,
190
+ message,
191
+ politeness
192
+ }]);
193
+ }, []);
194
+ const value = useMemo(() => ({ announce }), [announce]);
195
+ return /* @__PURE__ */ jsxs(AriaLiveContext, {
196
+ value,
197
+ children: [children, /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(LiveRegion, {
198
+ announcements,
199
+ politeness: "assertive"
200
+ }), /* @__PURE__ */ jsx(LiveRegion, {
201
+ announcements,
202
+ politeness: "polite"
203
+ })] })]
204
+ });
205
+ };
206
+ //#endregion
207
+ //#region src/private/hooks/useAriaLive/useAriaLive.ts
208
+ const useAriaLive = () => use(AriaLiveContext);
209
+ //#endregion
210
+ //#region src/private/components/LiveAnnouncement/LiveAnnouncement.tsx
211
+ /**
212
+ * Announces `message` to screen readers when it mounts and each time `message` changes.
213
+ */
214
+ const LiveAnnouncement = ({ message, politeness = "polite" }) => {
215
+ const { announce } = useAriaLive();
216
+ const announcedMessage = useRef(null);
217
+ useEffect(() => {
218
+ if (announcedMessage.current === message) return;
219
+ announcedMessage.current = message;
220
+ announce(message, politeness);
221
+ }, [
222
+ announce,
223
+ message,
224
+ politeness
225
+ ]);
226
+ return null;
227
+ };
228
+ //#endregion
113
229
  //#region src/private/helpers/coerceToBoolean/coerceToBoolean.ts
114
230
  /**
115
231
  * Converts a boolean string value `value` into a boolean. If passed
@@ -1618,9 +1734,9 @@ const ButtonContent = ({ children, icon, iconName, iconPosition, isLoading, size
1618
1734
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [isLoading ? /* @__PURE__ */ jsxs(ButtonLoadingContainer, {
1619
1735
  $textAlign: textAlign,
1620
1736
  "data-testid": "button-content-loading",
1621
- children: [/* @__PURE__ */ jsx(LiveMessage, {
1622
- "aria-live": "assertive",
1623
- message: "Button has been disabled while action is in progress"
1737
+ children: [/* @__PURE__ */ jsx(LiveAnnouncement, {
1738
+ message: "Button has been disabled while action is in progress",
1739
+ politeness: "assertive"
1624
1740
  }), /* @__PURE__ */ jsx(Icon, {
1625
1741
  size: iconSizeMap$2[size],
1626
1742
  type: "spinner"
@@ -2090,9 +2206,9 @@ const Toast = memo(({ actionInterceptor, actionLabel = defaultActionLabel, color
2090
2206
  ...otherProps,
2091
2207
  children: [/* @__PURE__ */ jsxs(ToastContent, {
2092
2208
  "data-testid": "toast-message",
2093
- children: [/* @__PURE__ */ jsx(LiveMessage, {
2094
- "aria-live": ariaLive,
2095
- message
2209
+ children: [/* @__PURE__ */ jsx(LiveAnnouncement, {
2210
+ message,
2211
+ politeness: ariaLive
2096
2212
  }), message]
2097
2213
  }), /* @__PURE__ */ jsx(Button, {
2098
2214
  colorOverride: accentColor,
@@ -2570,9 +2686,10 @@ const merge = (target, ...sources) => {
2570
2686
  const output = { ...target };
2571
2687
  sources.forEach((source) => {
2572
2688
  if (isObject(source)) Object.keys(source).forEach((key) => {
2573
- if (isObject(source[key])) if (output[key] === null || output[key] === void 0) output[key] = { ...source[key] };
2574
- else output[key] = merge(output[key], source[key]);
2575
- else output[key] = source[key];
2689
+ if (isObject(source[key])) {
2690
+ if (output[key] === null || output[key] === void 0) output[key] = { ...source[key] };
2691
+ else output[key] = merge(output[key], source[key]);
2692
+ } else output[key] = source[key];
2576
2693
  });
2577
2694
  });
2578
2695
  return output;
@@ -2643,7 +2760,7 @@ const DEFAULT_THEME = {};
2643
2760
  const VHSProvider = ({ children, theme = DEFAULT_THEME, globalStylesIncluded = true, skipAnimations = false, Link }) => {
2644
2761
  return /* @__PURE__ */ jsxs(VHSThemeProvider, {
2645
2762
  theme,
2646
- children: [globalStylesIncluded ? /* @__PURE__ */ jsx(GlobalStyle$1, {}) : null, /* @__PURE__ */ jsx(LiveAnnouncer, { children: /* @__PURE__ */ jsx(MotionConfig, {
2763
+ children: [globalStylesIncluded ? /* @__PURE__ */ jsx(GlobalStyle$1, {}) : null, /* @__PURE__ */ jsx(AriaLiveProvider, { children: /* @__PURE__ */ jsx(MotionConfig, {
2647
2764
  reducedMotion: skipAnimations ? "always" : "user",
2648
2765
  children: /* @__PURE__ */ jsx(WrapperProvider, {
2649
2766
  value: { Link },
@@ -2653,38 +2770,6 @@ const VHSProvider = ({ children, theme = DEFAULT_THEME, globalStylesIncluded = t
2653
2770
  });
2654
2771
  };
2655
2772
  //#endregion
2656
- //#region src/components/ScreenReaderOnly/ScreenReaderOnly.tsx
2657
- const screenReaderOnlyStyle = css`
2658
- border: 0;
2659
- clip-path: inset(50%);
2660
- height: 1px;
2661
- overflow: hidden;
2662
- padding: 0;
2663
- position: absolute;
2664
- white-space: nowrap;
2665
- width: 1px;
2666
- `;
2667
- const VisuallyHidden = styled.div`
2668
- ${screenReaderOnlyStyle}
2669
- `;
2670
- const VisuallyHiddenButFocusable = styled.div`
2671
- &:not(:focus-within) {
2672
- ${screenReaderOnlyStyle}
2673
- }
2674
- `;
2675
- const ScreenReaderOnly = ({ text, children, focusable = false, ...otherProps }) => {
2676
- const accessibleText = isNotNil(text) ? text : children;
2677
- if (focusable) return /* @__PURE__ */ jsx(VisuallyHiddenButFocusable, {
2678
- ...otherProps,
2679
- children: accessibleText
2680
- });
2681
- return /* @__PURE__ */ jsx(VisuallyHidden, {
2682
- ...otherProps,
2683
- children: accessibleText
2684
- });
2685
- };
2686
- ScreenReaderOnly.displayName = "ScreenReaderOnly_VHS";
2687
- //#endregion
2688
2773
  //#region src/components/Truncate/Truncate.tsx
2689
2774
  const Truncate = ({ children, maxChars, terminator = "...", breakOnWords = false }) => {
2690
2775
  if (isNil(children)) return null;
@@ -3056,7 +3141,7 @@ const ModalCloseButton$1 = ({ onClick, closeIconColorOverride }) => /* @__PURE__
3056
3141
  zIndex: 1
3057
3142
  }
3058
3143
  });
3059
- ModalCloseButton$1.displayName = "ModalCloseButton";
3144
+ ModalCloseButton$1.displayName = "ModalCloseButton_VHS";
3060
3145
  //#endregion
3061
3146
  //#region src/private/helpers/mq/mq.ts
3062
3147
  const getMaxWidth = (breakpoint) => {
@@ -4697,7 +4782,7 @@ const FormFieldWrapper = ({ disabled = false, error = null, label = null, labelD
4697
4782
  ]
4698
4783
  });
4699
4784
  };
4700
- FormFieldWrapper.displayName = "FormFieldWrapper";
4785
+ FormFieldWrapper.displayName = "FormFieldWrapper_VHS";
4701
4786
  //#endregion
4702
4787
  //#region src/components/CheckboxGroup/CheckboxGroup.tsx
4703
4788
  const StyledOptionContainer$1 = styled.div`
@@ -5290,9 +5375,10 @@ const didValuesChange = (newValues, oldValues) => JSON.stringify(newValues) !==
5290
5375
  const handleInitialValues = (initialValues, validationSchema) => {
5291
5376
  const filteredInitialValues = {};
5292
5377
  Object.keys(initialValues).forEach((key) => {
5293
- if (initialValues[key] === null) if (isNotUndefined(validationSchema) && isNotUndefined(validationSchema.fields) && isNotUndefined(validationSchema.fields[key]) && validationSchema.fields[key]._type === "boolean") filteredInitialValues[key] = false;
5294
- else filteredInitialValues[key] = void 0;
5295
- else filteredInitialValues[key] = initialValues[key];
5378
+ if (initialValues[key] === null) {
5379
+ if (isNotUndefined(validationSchema) && isNotUndefined(validationSchema.fields) && isNotUndefined(validationSchema.fields[key]) && validationSchema.fields[key]._type === "boolean") filteredInitialValues[key] = false;
5380
+ else filteredInitialValues[key] = void 0;
5381
+ } else filteredInitialValues[key] = initialValues[key];
5296
5382
  });
5297
5383
  return filteredInitialValues;
5298
5384
  };
@@ -5387,7 +5473,7 @@ const FormConnectorButton = ({ type = "submit", isSubmitting = false, children,
5387
5473
  children
5388
5474
  });
5389
5475
  };
5390
- FormConnectorButton.displayName = "FormConnectorButton";
5476
+ FormConnectorButton.displayName = "FormConnectorButton_VHS";
5391
5477
  //#endregion
5392
5478
  //#region src/components/FormButtons/FormButtons.tsx
5393
5479
  const handleMouseDown = (event) => event.preventDefault();
@@ -5416,10 +5502,12 @@ const FormConnectorCheckboxGroup = ({ direction = "column", disabled = false, fi
5416
5502
  };
5417
5503
  const onChangeMultiple = (event, optionValue) => {
5418
5504
  const fieldValues = value;
5419
- if (isArray(fieldValues)) if (event.target.checked) fieldValues.push(optionValue);
5420
- else {
5421
- const index = fieldValues.indexOf(optionValue);
5422
- if (index !== -1) fieldValues.splice(index, 1);
5505
+ if (isArray(fieldValues)) {
5506
+ if (event.target.checked) fieldValues.push(optionValue);
5507
+ else {
5508
+ const index = fieldValues.indexOf(optionValue);
5509
+ if (index !== -1) fieldValues.splice(index, 1);
5510
+ }
5423
5511
  }
5424
5512
  setFieldValue(optionValue, fieldValues);
5425
5513
  };
@@ -5441,7 +5529,7 @@ const FormConnectorCheckboxGroup = ({ direction = "column", disabled = false, fi
5441
5529
  value
5442
5530
  });
5443
5531
  };
5444
- FormConnectorCheckboxGroup.displayName = "FormConnectorCheckboxGroup";
5532
+ FormConnectorCheckboxGroup.displayName = "FormConnectorCheckboxGroup_VHS";
5445
5533
  //#endregion
5446
5534
  //#region src/private/components/FormConnectorCustomField/FormConnectorCustomField.tsx
5447
5535
  const DEFAULT_LABEL_PROPS$5 = {};
@@ -5461,7 +5549,7 @@ const FormConnectorCustomField = ({ customComponent: Element, field, form, label
5461
5549
  })
5462
5550
  });
5463
5551
  };
5464
- FormConnectorCustomField.displayName = "FormConnectorCustomField";
5552
+ FormConnectorCustomField.displayName = "FormConnectorCustomField_VHS";
5465
5553
  //#endregion
5466
5554
  //#region src/private/helpers/coerceToString/coerceToString.ts
5467
5555
  /**
@@ -5865,7 +5953,7 @@ const FormConnectorHidden = ({ field: { name, value, onChange }, form: { setFiel
5865
5953
  ...otherProps
5866
5954
  });
5867
5955
  };
5868
- FormConnectorHidden.displayName = "FormConnectorHidden";
5956
+ FormConnectorHidden.displayName = "FormConnectorHidden_VHS";
5869
5957
  //#endregion
5870
5958
  //#region src/private/components/FormConnectorInput/FormConnectorInput.tsx
5871
5959
  const TRIMMABLE_INPUTS = /* @__PURE__ */ new Set([
@@ -5905,7 +5993,7 @@ const FormConnectorInput = ({ disabled, field: { name, value, onChange, onBlur }
5905
5993
  })
5906
5994
  });
5907
5995
  };
5908
- FormConnectorInput.displayName = "FormConnectorInput";
5996
+ FormConnectorInput.displayName = "FormConnectorInput_VHS";
5909
5997
  //#endregion
5910
5998
  //#region src/components/Radio/Radio.tsx
5911
5999
  const Radio = forwardRef(({ checked, direction = "column", disabled = false, forceState, hasError = false, id, label, labelDescription, name, onChange, value = "false", ...otherProps }, ref) => {
@@ -5995,7 +6083,7 @@ const FormConnectorRadioGroup = ({ direction = "column", disabled = false, field
5995
6083
  value: values[name]
5996
6084
  });
5997
6085
  };
5998
- FormConnectorRadioGroup.displayName = "FormConnectorRadioGroup";
6086
+ FormConnectorRadioGroup.displayName = "FormConnectorRadioGroup_VHS";
5999
6087
  //#endregion
6000
6088
  //#region src/private/components/Icon/iconMap.ts
6001
6089
  const iconMap = {
@@ -6155,7 +6243,7 @@ const Icon$1 = ({ color = "currentColor", size = "lg", style, type, ...otherProp
6155
6243
  ...otherProps
6156
6244
  });
6157
6245
  };
6158
- Icon$1.displayName = "Icon";
6246
+ Icon$1.displayName = "Icon_VHS";
6159
6247
  //#endregion
6160
6248
  //#region src/private/helpers/isUrl/isUrl.ts
6161
6249
  /**
@@ -6854,6 +6942,78 @@ const rteDeserializeHTML = (htmlString) => {
6854
6942
  return fragment;
6855
6943
  };
6856
6944
  //#endregion
6945
+ //#region src/components/RichTextEditor/utilities/useExternalValueSync.ts
6946
+ const defaultValue = [{
6947
+ type: "paragraph",
6948
+ children: [{ text: "" }]
6949
+ }];
6950
+ const MAX_PENDING_ECHOES = 50;
6951
+ const isTextValid = (rteValue) => {
6952
+ if (isNil(rteValue) || isNil(rteValue[0]) || isNil(rteValue[0].children)) return false;
6953
+ const { text } = rteValue[0].children[0];
6954
+ return isNonEmptyString(text);
6955
+ };
6956
+ /**
6957
+ * Keeps a Slate editor in sync with a controlled `value` prop without clobbering
6958
+ * in-progress typing.
6959
+ *
6960
+ * Controlled parents echo every `onChange` back as `value`. When that echo is
6961
+ * delayed (async store, debounced save, slow render), the prop can arrive
6962
+ * holding an *older* editor state than the one the user is typing into. The
6963
+ * previous implementation treated any mismatch as an external update, reset
6964
+ * `editor.children` to the stale value and nulled the selection — dropping
6965
+ * characters and sending the caret to the start of the document.
6966
+ *
6967
+ * Here, every state emitted through `onChange` is remembered until the parent
6968
+ * echoes it back. A `value` that matches one of those states is an echo (current
6969
+ * or stale) and is ignored. Anything else is a genuine external update and is
6970
+ * applied, as before.
6971
+ *
6972
+ * Returns the `onChange` handler to pass to `<Slate>`.
6973
+ *
6974
+ * This is directly from the Slate.js docs on how to update slate outside of onChange:
6975
+ * If you want to update the editor's content in response to events from outside of Slate, you
6976
+ * need to change the children property directly. The simplest way is to replace the value of
6977
+ * editor.children editor.children = newValue and trigger a re-rendering (e.g. by calling
6978
+ * editor.onChange()).
6979
+ * More info here: https://docs.slatejs.org/walkthroughs/06-saving-to-a-database
6980
+ */
6981
+ const useExternalValueSync = ({ editor, value, useExternalValue, onChange }) => {
6982
+ const lastSeenValueHtml = useRef(rteSerializeToHTML(value));
6983
+ const pendingEchoes = useRef([]);
6984
+ const handleChange = useCallback((nodes) => {
6985
+ const html = rteSerializeToHTML(nodes);
6986
+ const pending = pendingEchoes.current;
6987
+ if (pending.at(-1) !== html) {
6988
+ pending.push(html);
6989
+ if (pending.length > MAX_PENDING_ECHOES) pending.splice(0, pending.length - MAX_PENDING_ECHOES);
6990
+ }
6991
+ if (isNotNil(onChange)) onChange(nodes);
6992
+ }, [onChange]);
6993
+ useEffect(() => {
6994
+ const valueHtml = rteSerializeToHTML(value);
6995
+ if (valueHtml === lastSeenValueHtml.current) return;
6996
+ lastSeenValueHtml.current = valueHtml;
6997
+ const echoIndex = pendingEchoes.current.indexOf(valueHtml);
6998
+ if (echoIndex !== -1) {
6999
+ pendingEchoes.current.splice(0, echoIndex + 1);
7000
+ return;
7001
+ }
7002
+ /** if we have an external value and the text editor is not empty (and therefore valid), we can safely update the editor. */
7003
+ if (!(isEqual(value, defaultValue) || isTextValid(value) && useExternalValue)) return;
7004
+ if (valueHtml === rteSerializeToHTML(editor.children)) return;
7005
+ pendingEchoes.current = [];
7006
+ editor.children = value;
7007
+ editor.selection = null;
7008
+ editor.onChange();
7009
+ }, [
7010
+ value,
7011
+ editor,
7012
+ useExternalValue
7013
+ ]);
7014
+ return handleChange;
7015
+ };
7016
+ //#endregion
6857
7017
  //#region src/components/RichTextEditor/RichTextEditor.tsx
6858
7018
  const EditableWrapper = styled(Editable)`
6859
7019
  color: ${({ theme }) => theme.color.grey900};
@@ -6880,10 +7040,6 @@ const HOTKEYS = {
6880
7040
  "mod+i": "italic",
6881
7041
  "mod+u": "underline"
6882
7042
  };
6883
- const defaultValue = [{
6884
- type: "paragraph",
6885
- children: [{ text: "" }]
6886
- }];
6887
7043
  const RichTextEditor = ({ enabledFormats = Object.values(rteFormatTypes), value = defaultValue, onChange, onBlur, placeholder = "Enter some rich text...", disabled = false, ariaLabelledBy, useExternalValue, "data-testid": dataTestId = "vhs-rich-text-editor", height, ...otherProps }) => {
6888
7044
  const renderElement = useCallback((props) => /* @__PURE__ */ jsx(Element$1, { ...props }), []);
6889
7045
  const renderLeaf = useCallback((props) => /* @__PURE__ */ jsx(Leaf, { ...props }), []);
@@ -6891,34 +7047,12 @@ const RichTextEditor = ({ enabledFormats = Object.values(rteFormatTypes), value
6891
7047
  const baseEditor = withReact(createEditor());
6892
7048
  return withImages(withLinks(withHistory(baseEditor)));
6893
7049
  }, []);
6894
- /**
6895
- * This is directly from the Slate.js docs on how to update slate outside of onChange:
6896
- * If you want to update the editor's content in response to events from outside of Slate, you
6897
- * need to change the children property directly. The simplest way is to replace the value of
6898
- * editor.children editor.children = newValue and trigger a re-rendering (e.g. by calling
6899
- * editor.onChange() in the example above).
6900
- * More info here: https://docs.slatejs.org/walkthroughs/06-saving-to-a-database
6901
- */
6902
- const isTextValid = (rteValue) => {
6903
- if (isNil(rteValue) || isNil(rteValue[0]) || isNil(rteValue[0].children)) return false;
6904
- const { text } = rteValue[0].children[0];
6905
- return isNonEmptyString(text);
6906
- };
6907
- useEffect(() => {
6908
- const isDefaultValue = isEqual(value, defaultValue);
6909
- const valueString = rteSerializeToHTML(value);
6910
- const editorChildrenString = rteSerializeToHTML(editor.children);
6911
- /** if we have an external value and the text editor is not empty (and therefore valid) and the value string and children string is not equal to one another, we can safely update the editor. */
6912
- if (isDefaultValue || isTextValid(value) && useExternalValue && valueString !== editorChildrenString) {
6913
- editor.children = value;
6914
- editor.selection = null;
6915
- editor.onChange();
6916
- }
6917
- }, [
6918
- value,
7050
+ const handleChange = useExternalValueSync({
6919
7051
  editor,
6920
- useExternalValue
6921
- ]);
7052
+ value,
7053
+ useExternalValue,
7054
+ onChange
7055
+ });
6922
7056
  const handleEditorBlur = (_event) => {
6923
7057
  const updatedValue = editor.children;
6924
7058
  if (isNotNil(onBlur)) onBlur(updatedValue);
@@ -6949,7 +7083,7 @@ const RichTextEditor = ({ enabledFormats = Object.values(rteFormatTypes), value
6949
7083
  children: /* @__PURE__ */ jsxs(Slate, {
6950
7084
  editor,
6951
7085
  initialValue: value,
6952
- onChange,
7086
+ onChange: handleChange,
6953
7087
  ...otherProps,
6954
7088
  children: [/* @__PURE__ */ jsx(EditorButtons, {
6955
7089
  disabled,
@@ -7019,7 +7153,7 @@ const FormConnectorRichTextEditor = ({ field: { name, value, onChange }, form: {
7019
7153
  })
7020
7154
  });
7021
7155
  };
7022
- FormConnectorRichTextEditor.displayName = "FormConnectorRichTextEditor";
7156
+ FormConnectorRichTextEditor.displayName = "FormConnectorRichTextEditor_VHS";
7023
7157
  //#endregion
7024
7158
  //#region src/components/Select/SelectStyledComponent.tsx
7025
7159
  const focusStyle = css`
@@ -7195,7 +7329,7 @@ const FormConnectorSelect = ({ disabled = false, field: { name, value, onChange,
7195
7329
  })
7196
7330
  });
7197
7331
  };
7198
- FormConnectorSelect.displayName = "FormConnectorSelect";
7332
+ FormConnectorSelect.displayName = "FormConnectorSelect_VHS";
7199
7333
  //#endregion
7200
7334
  //#region src/components/FormField/inputTypeMap.ts
7201
7335
  const inputTypeMap = {
@@ -7779,6 +7913,7 @@ const StyledMenuItem = styled.div`
7779
7913
  ${({ $variant }) => isNotNil($variant) && getMenuItemStyles($variant)};
7780
7914
  }
7781
7915
  `;
7916
+ const PolymorphicStyledMenuItem = StyledMenuItem;
7782
7917
  const StyledMenuItemContent = styled.div`
7783
7918
  align-items: center;
7784
7919
  display: grid;
@@ -7817,7 +7952,7 @@ const MenuItem = ({ children, label, description, badge, icon, renderAs, href, t
7817
7952
  style: { outline: "none" },
7818
7953
  ...props,
7819
7954
  asChild: true,
7820
- children: /* @__PURE__ */ jsx(StyledMenuItem, {
7955
+ children: /* @__PURE__ */ jsx(PolymorphicStyledMenuItem, {
7821
7956
  $variant: variant,
7822
7957
  as,
7823
7958
  href,
@@ -8125,7 +8260,7 @@ const Menu$1 = forwardRef(({ items, menuHeader, width = "fullWidth", onClick, on
8125
8260
  children: [isNotNil(menuHeader) ? /* @__PURE__ */ jsxs(Fragment$1, { children: [menuHeader, /* @__PURE__ */ jsx(MenuItem$1, { children: /* @__PURE__ */ jsx(Divider, {}) })] }) : null, itemsToRender]
8126
8261
  });
8127
8262
  });
8128
- Menu$1.displayName = "Menu";
8263
+ Menu$1.displayName = "Menu_VHS";
8129
8264
  //#endregion
8130
8265
  //#region src/private/hooks/useBoolean/useBoolean.ts
8131
8266
  const useBoolean = (initialValue = false) => {
@@ -8353,8 +8488,7 @@ const scopeTab = (node, event) => {
8353
8488
  const target = tabbable[event.shiftKey ? tabbable.length - 1 : 0];
8354
8489
  if (target) target.focus();
8355
8490
  };
8356
- const createAriaHider = (containerNode, selector) => {
8357
- selector ??= "body > :not(script)";
8491
+ const createAriaHider = (containerNode, selector = "body > :not(script)") => {
8358
8492
  const rootNodes = [...document.querySelectorAll(selector)].map((node) => {
8359
8493
  if (node.contains(containerNode)) return;
8360
8494
  const ariaHidden = node.getAttribute("aria-hidden");
@@ -8392,8 +8526,10 @@ const useFocusTrap = (active = true, options = {}) => {
8392
8526
  const processNode = (node2) => {
8393
8527
  restoreAriaRef.current = !(options.disableAriaHider ?? false) ? createAriaHider(node2) : null;
8394
8528
  let focusElement = null;
8395
- if (isNotUndefined(options.focusSelector)) if (isRef(options.focusSelector)) focusElement = options.focusSelector.current;
8396
- else focusElement = typeof options.focusSelector === "string" ? node2.querySelector(options.focusSelector) : options.focusSelector;
8529
+ if (isNotUndefined(options.focusSelector)) {
8530
+ if (isRef(options.focusSelector)) focusElement = options.focusSelector.current;
8531
+ else focusElement = typeof options.focusSelector === "string" ? node2.querySelector(options.focusSelector) : options.focusSelector;
8532
+ }
8397
8533
  if (!focusElement) {
8398
8534
  const children = [...node2.querySelectorAll(FOCUSABLE_ELEMENT_SELECTORS)];
8399
8535
  focusElement = children.find((element) => isTabbableElement(element)) ?? children.find((element) => isFocusableElement(element)) ?? null;
@@ -8856,6 +8992,12 @@ const MonthButton = styled.button`
8856
8992
  }
8857
8993
  `;
8858
8994
  const Calendar = ({ displayDate, earliestDate, latestDate, onDisplayDateChange, onMouseLeave, shouldPreventFuture = false, renderDay }) => {
8995
+ const [today, setToday] = useState(() => /* @__PURE__ */ new Date());
8996
+ useEffect(() => {
8997
+ const nextMidnight = startOfDay(addDays(today, 1));
8998
+ const timeout = setTimeout(() => setToday(/* @__PURE__ */ new Date()), differenceInMilliseconds(nextMidnight, today));
8999
+ return () => clearTimeout(timeout);
9000
+ }, [today]);
8859
9001
  const month = monthLayout(daysOfMonth(displayDate));
8860
9002
  const nextMonth = startOfMonth(addMonths(displayDate, 1));
8861
9003
  const prevMonth = endOfMonth(addMonths(displayDate, -1));
@@ -8883,8 +9025,8 @@ const Calendar = ({ displayDate, earliestDate, latestDate, onDisplayDateChange,
8883
9025
  children: /* @__PURE__ */ jsx(DayNumber, { children: formatDay(day) })
8884
9026
  }, day);
8885
9027
  const possibleRange = {
8886
- start: earliestDate ?? addYears(/* @__PURE__ */ new Date(), -5),
8887
- end: shouldPreventFuture ? /* @__PURE__ */ new Date() : addYears(/* @__PURE__ */ new Date(), 5)
9028
+ start: earliestDate ?? addYears(today, -5),
9029
+ end: shouldPreventFuture ? today : addYears(today, 5)
8888
9030
  };
8889
9031
  const currentYear = displayDate.getFullYear();
8890
9032
  const getMonthOptions = () => {
@@ -8928,9 +9070,11 @@ const Calendar = ({ displayDate, earliestDate, latestDate, onDisplayDateChange,
8928
9070
  onChange: (event) => {
8929
9071
  const selectedMonth = event.target.value;
8930
9072
  const nextDate = new Date(currentYear, Number(selectedMonth));
8931
- if (onDisplayDateChange) if (isInFuture(nextDate)) onDisplayDateChange(/* @__PURE__ */ new Date());
8932
- else if (isBeforeEarliest(nextDate)) onDisplayDateChange(earliestDate);
8933
- else onDisplayDateChange(nextDate);
9073
+ if (onDisplayDateChange) {
9074
+ if (isInFuture(nextDate)) onDisplayDateChange(/* @__PURE__ */ new Date());
9075
+ else if (isBeforeEarliest(nextDate)) onDisplayDateChange(earliestDate);
9076
+ else onDisplayDateChange(nextDate);
9077
+ }
8934
9078
  },
8935
9079
  options: monthOptions,
8936
9080
  placeholder: null,
@@ -8944,9 +9088,11 @@ const Calendar = ({ displayDate, earliestDate, latestDate, onDisplayDateChange,
8944
9088
  const currentMonth = displayDate.getMonth();
8945
9089
  const selectedYear = event.target.value;
8946
9090
  const nextDate = new Date(Number(selectedYear), currentMonth);
8947
- if (onDisplayDateChange) if (isInFuture(nextDate)) onDisplayDateChange(/* @__PURE__ */ new Date());
8948
- else if (isBeforeEarliest(nextDate)) onDisplayDateChange(earliestDate);
8949
- else onDisplayDateChange(nextDate);
9091
+ if (onDisplayDateChange) {
9092
+ if (isInFuture(nextDate)) onDisplayDateChange(/* @__PURE__ */ new Date());
9093
+ else if (isBeforeEarliest(nextDate)) onDisplayDateChange(earliestDate);
9094
+ else onDisplayDateChange(nextDate);
9095
+ }
8950
9096
  },
8951
9097
  options: yearOptions,
8952
9098
  placeholder: null,
@@ -8974,7 +9120,7 @@ const Calendar = ({ displayDate, earliestDate, latestDate, onDisplayDateChange,
8974
9120
  })]
8975
9121
  });
8976
9122
  };
8977
- Calendar.displayName = "Calendar";
9123
+ Calendar.displayName = "Calendar_VHS";
8978
9124
  //#endregion
8979
9125
  //#region src/private/components/RangeSelectorCalendar/RangeSelectorCalendar.tsx
8980
9126
  const EnhancedDay = styled(Day)`
@@ -9046,7 +9192,7 @@ const EnhancedDay = styled(Day)`
9046
9192
  }
9047
9193
  `}
9048
9194
  `;
9049
- const isValidRange$1 = (range) => {
9195
+ const isValidRange = (range) => {
9050
9196
  if (isNil(range)) return false;
9051
9197
  const { start, end } = range;
9052
9198
  return start instanceof Date && end instanceof Date && isBefore(start, end);
@@ -9085,14 +9231,14 @@ const DEFAULT_RANGE$1 = {
9085
9231
  };
9086
9232
  const NOOP = () => {};
9087
9233
  const RangeSelectorCalendar = ({ range = DEFAULT_RANGE$1, rangePartToShow = "", onChange, onIsValidChange = NOOP, earliestDate, latestDate, shouldPreventFuture = false }) => {
9088
- const thisMonth = useMemo(() => startOfMonth(/* @__PURE__ */ new Date()), []);
9234
+ const [thisMonth] = useState(() => startOfMonth(/* @__PURE__ */ new Date()));
9089
9235
  const initialDisplayDate = isNotNil(range.end) ? range.end : thisMonth;
9090
9236
  const [displayDate, setDisplayDate] = useState(initialDisplayDate);
9091
9237
  const [{ firstDate, secondDate }, setDates] = useState({});
9092
9238
  const [hoveredDate, setHoveredDate] = useState();
9093
9239
  const internalRange = useRange(firstDate, secondDate);
9094
9240
  const priorInternalRange = usePreviousValue(internalRange);
9095
- const tempRange = useRange(!isValidRange$1(internalRange) && firstDate, hoveredDate);
9241
+ const tempRange = useRange(!isValidRange(internalRange) && firstDate, hoveredDate);
9096
9242
  const setDisplayDateDebounced = useMemo(() => debounce(0, setDisplayDate), []);
9097
9243
  useEffect(() => {
9098
9244
  setDisplayDateDebounced(range.end);
@@ -9111,13 +9257,13 @@ const RangeSelectorCalendar = ({ range = DEFAULT_RANGE$1, rangePartToShow = "",
9111
9257
  ]);
9112
9258
  useEffect(() => {
9113
9259
  const onIsValidChangeDebounced = debounce(100, onIsValidChange);
9114
- onIsValidChangeDebounced(isValidRange$1(internalRange));
9260
+ onIsValidChangeDebounced(isValidRange(internalRange));
9115
9261
  return () => {
9116
9262
  onIsValidChangeDebounced.cancel();
9117
9263
  };
9118
9264
  }, [internalRange, onIsValidChange]);
9119
9265
  useEffect(() => {
9120
- if (isValidRange$1(range)) {
9266
+ if (isValidRange(range)) {
9121
9267
  let date = void 0;
9122
9268
  if (priorInternalRange && !isEqual$1(range.start, priorInternalRange.start)) date = range.start;
9123
9269
  if (priorInternalRange && !isEqual$1(range.end, priorInternalRange.end)) date = range.end;
@@ -9176,7 +9322,7 @@ const RangeSelectorCalendar = ({ range = DEFAULT_RANGE$1, rangePartToShow = "",
9176
9322
  secondDate: nextSecond
9177
9323
  });
9178
9324
  const nextRange = makeRange(nextFirst, nextSecond);
9179
- if (isValidRange$1(nextRange) && onChange) onChange(nextRange);
9325
+ if (isValidRange(nextRange) && onChange) onChange(nextRange);
9180
9326
  setHoveredDate(void 0);
9181
9327
  },
9182
9328
  onMouseOver: () => {
@@ -9188,7 +9334,7 @@ const RangeSelectorCalendar = ({ range = DEFAULT_RANGE$1, rangePartToShow = "",
9188
9334
  shouldPreventFuture
9189
9335
  });
9190
9336
  };
9191
- RangeSelectorCalendar.displayName = "RangeSelectorCalendar";
9337
+ RangeSelectorCalendar.displayName = "RangeSelectorCalendar_VHS";
9192
9338
  //#endregion
9193
9339
  //#region src/private/components/RangeSelectorInput/constants.ts
9194
9340
  const DIVIDER_STRING = " - ";
@@ -9404,7 +9550,7 @@ const preventDoubleClick = (event) => {
9404
9550
  timeout = void 0;
9405
9551
  }, delay);
9406
9552
  };
9407
- const isValidRange = ({ start, end }) => isValid(start) && isValid(end);
9553
+ const hasValidDates = ({ start, end }) => isValid(start) && isValid(end);
9408
9554
  const getFieldId = ([start], positions) => {
9409
9555
  const currentPosition = positions.find((pos) => pos.start === start);
9410
9556
  return isNotNil(currentPosition) && isNotNil(currentPosition.id) ? currentPosition.id : "";
@@ -9592,7 +9738,7 @@ const RangeSelectorInput = ({ onChange, onSelectedRangePartChange, range, earlie
9592
9738
  }),
9593
9739
  minDate: earliestDate
9594
9740
  });
9595
- if (isValidRange(nextRange)) {
9741
+ if (hasValidDates(nextRange)) {
9596
9742
  setValue(rangeToString(nextRange));
9597
9743
  if (!isNonEmptyArray(errors) && isNotUndefined(onChange)) onChange(orderRange(nextRange));
9598
9744
  }
@@ -9687,7 +9833,7 @@ const RangeSelectorInput = ({ onChange, onSelectedRangePartChange, range, earlie
9687
9833
  value
9688
9834
  })] });
9689
9835
  };
9690
- RangeSelectorInput.displayName = "RangeSelectorInput";
9836
+ RangeSelectorInput.displayName = "RangeSelectorInput_VHS";
9691
9837
  //#endregion
9692
9838
  //#region src/components/RangeSelector/RangeSelector.tsx
9693
9839
  const TooltipWrapper = styled.div`