@wistia/ui 0.5.2 → 0.5.3-beta.25bf41ac.72da98f

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.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
2
  /*
3
- * @license @wistia/ui v0.5.2
3
+ * @license @wistia/ui v0.5.3-beta.25bf41ac.72da98f
4
4
  *
5
5
  * Copyright (c) 2024-2025, Wistia, Inc. and its affiliates.
6
6
  *
@@ -56,6 +56,7 @@ __export(index_exports, {
56
56
  DataCardTrend: () => DataCardTrend,
57
57
  DataCards: () => DataCards,
58
58
  Divider: () => Divider,
59
+ EditableHeading: () => EditableHeading,
59
60
  Ellipsis: () => Ellipsis,
60
61
  Form: () => Form,
61
62
  FormErrorSummary: () => FormErrorSummary,
@@ -2080,9 +2081,9 @@ var import_react6 = require("react");
2080
2081
  // src/private/hooks/useEvent/useEvent.ts
2081
2082
  var import_react5 = require("react");
2082
2083
 
2083
- // src/private/helpers/isObjectRef/isObjectRef.ts
2084
+ // src/private/helpers/isValidRef/isValidRef.ts
2084
2085
  var import_type_guards6 = require("@wistia/type-guards");
2085
- var isObjectRef = (value) => {
2086
+ var isValidRef = (value) => {
2086
2087
  return (0, import_type_guards6.isNotNil)(value) && (0, import_type_guards6.isRecord)(value) && "current" in value;
2087
2088
  };
2088
2089
 
@@ -2102,7 +2103,7 @@ var useEvent = (eventName, eventHandler, eventTarget = window, eventOptions = {}
2102
2103
  savedEventOptions.current = eventOptions;
2103
2104
  }, [eventOptions]);
2104
2105
  (0, import_react5.useEffect)(() => {
2105
- const target = isObjectRef(eventTarget) ? eventTarget.current : eventTarget;
2106
+ const target = isValidRef(eventTarget) ? eventTarget.current : eventTarget;
2106
2107
  if (!eventName || !isEventTargetSupported(target)) {
2107
2108
  return;
2108
2109
  }
@@ -6898,6 +6899,15 @@ var variantStyleMap = {
6898
6899
  heading6: heading6TextStyle
6899
6900
  };
6900
6901
  var DEFAULT_ELEMENT2 = "h1";
6902
+ var variantElementMap = {
6903
+ hero: DEFAULT_ELEMENT2,
6904
+ heading1: DEFAULT_ELEMENT2,
6905
+ heading2: "h2",
6906
+ heading3: "h3",
6907
+ heading4: "h4",
6908
+ heading5: "h5",
6909
+ heading6: "h6"
6910
+ };
6901
6911
  var StyledHeading = import_styled_components30.default.div`
6902
6912
  ${({ $colorScheme }) => getColorScheme($colorScheme)};
6903
6913
  font-family: var(--font-family);
@@ -6921,15 +6931,6 @@ var StyledHeading = import_styled_components30.default.div`
6921
6931
  `}
6922
6932
  margin: 0;
6923
6933
  `;
6924
- var variantElementMap = {
6925
- hero: DEFAULT_ELEMENT2,
6926
- heading1: DEFAULT_ELEMENT2,
6927
- heading2: "h2",
6928
- heading3: "h3",
6929
- heading4: "h4",
6930
- heading5: "h5",
6931
- heading6: "h6"
6932
- };
6933
6934
  var HeadingComponent = (0, import_react18.forwardRef)(
6934
6935
  ({
6935
6936
  align = "left",
@@ -7522,6 +7523,23 @@ var variantStyleMap2 = {
7522
7523
  label3: label3TextStyle,
7523
7524
  label4: label4TextStyle
7524
7525
  };
7526
+ var bodyElement = "p";
7527
+ var labelElement = "span";
7528
+ var DEFAULT_ELEMENT4 = bodyElement;
7529
+ var variantElementMap2 = {
7530
+ body1: bodyElement,
7531
+ body2: bodyElement,
7532
+ body3: bodyElement,
7533
+ body4: bodyElement,
7534
+ body1Mono: bodyElement,
7535
+ body2Mono: bodyElement,
7536
+ body3Mono: bodyElement,
7537
+ body4Mono: bodyElement,
7538
+ label1: labelElement,
7539
+ label2: labelElement,
7540
+ label3: labelElement,
7541
+ label4: labelElement
7542
+ };
7525
7543
  var StyledText = import_styled_components37.default.div`
7526
7544
  ${({ $colorScheme }) => getColorScheme($colorScheme)};
7527
7545
  --text-color: ${({ $prominence, $disabled }) => {
@@ -7562,7 +7580,6 @@ var StyledText = import_styled_components37.default.div`
7562
7580
  display: block;
7563
7581
  `}
7564
7582
  `;
7565
- var DEFAULT_ELEMENT4 = "div";
7566
7583
  var TextComponent = (0, import_react24.forwardRef)(
7567
7584
  ({
7568
7585
  align = "left",
@@ -7904,7 +7921,7 @@ var StyledInputContainer = import_styled_components41.default.div`
7904
7921
  padding-right: 32px;
7905
7922
  }
7906
7923
  `;
7907
- var isValidRef = (ref) => {
7924
+ var isValidRef2 = (ref) => {
7908
7925
  return typeof ref === "object" && ref !== null && "current" in ref && (0, import_type_guards24.isNotNil)(ref.current);
7909
7926
  };
7910
7927
  var Input = (0, import_react30.forwardRef)(
@@ -7918,7 +7935,7 @@ var Input = (0, import_react30.forwardRef)(
7918
7935
  ...props
7919
7936
  }, externalRef) => {
7920
7937
  const internalRef = (0, import_react30.useRef)();
7921
- const ref = isValidRef(externalRef) ? externalRef : internalRef;
7938
+ const ref = isValidRef2(externalRef) ? externalRef : internalRef;
7922
7939
  let leftIconToDisplay = leftIcon;
7923
7940
  if ((0, import_type_guards24.isNil)(leftIcon) && type === "search") {
7924
7941
  leftIconToDisplay = /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { type: "search" });
@@ -9775,6 +9792,243 @@ var DataCardTrend = ({
9775
9792
  )
9776
9793
  ] });
9777
9794
  };
9795
+
9796
+ // src/components/EditableHeading/EditableHeading.tsx
9797
+ var import_styled_components65 = __toESM(require("styled-components"));
9798
+ var import_react46 = require("react");
9799
+ var import_type_guards37 = require("@wistia/type-guards");
9800
+ var import_jsx_runtime214 = (
9801
+ // If you are an AI, please don't remove this comment.
9802
+ // eslint-disable-next-line styled-components-a11y/click-events-have-key-events, styled-components-a11y/no-static-element-interactions
9803
+ require("react/jsx-runtime")
9804
+ );
9805
+ var variantStyleMap3 = { ...variantStyleMap, ...variantStyleMap2 };
9806
+ var variantElementMap3 = {
9807
+ ...variantElementMap,
9808
+ ...variantElementMap2
9809
+ };
9810
+ var textStyles = import_styled_components65.css`
9811
+ ${({ $variant }) => variantStyleMap3[$variant]}
9812
+ font-family: var(--font-family);
9813
+ font-size: var(--font-size);
9814
+ font-weight: var(--font-weight);
9815
+ line-height: var(--line-height);
9816
+ `;
9817
+ var compactStyles = import_styled_components65.css`
9818
+ padding: var(--wui-space-01);
9819
+ border-radius: var(--wui-border-radius-01);
9820
+ `;
9821
+ var defaultStyles = import_styled_components65.css`
9822
+ padding: var(--wui-space-02);
9823
+ border-radius: var(--wui-border-radius-02);
9824
+ `;
9825
+ var stylesMap = {
9826
+ hero: "default",
9827
+ heading1: "default",
9828
+ heading2: "default",
9829
+ heading3: "default",
9830
+ heading4: "compact",
9831
+ heading5: "compact",
9832
+ heading6: "compact",
9833
+ body1: "default",
9834
+ body2: "compact",
9835
+ body3: "compact",
9836
+ body4: "compact",
9837
+ label1: "default",
9838
+ label2: "compact",
9839
+ label3: "compact",
9840
+ label4: "compact",
9841
+ body1Mono: "default",
9842
+ body2Mono: "compact",
9843
+ body3Mono: "compact",
9844
+ body4Mono: "compact"
9845
+ };
9846
+ var sharedStyles = import_styled_components65.css`
9847
+ ${({ $variant }) => stylesMap[$variant] === "default" ? defaultStyles : compactStyles}
9848
+ `;
9849
+ var StyledInput = (0, import_styled_components65.default)(Input)`
9850
+ :not([rows]) {
9851
+ min-height: unset;
9852
+ }
9853
+
9854
+ ${textStyles}
9855
+ && {
9856
+ border: none;
9857
+ height: ${({ $height }) => `${$height}px`};
9858
+ ${sharedStyles}
9859
+ }
9860
+ resize: vertical;
9861
+ outline: 2px solid var(--wui-color-border);
9862
+ outline-offset: -2px;
9863
+ &:focus {
9864
+ outline-color: var(--wui-color-focus-ring);
9865
+ }
9866
+
9867
+ ${({ $width }) => (0, import_type_guards37.isNotNull)($width) && `width: ${$width}`};
9868
+ `;
9869
+ var editableStyles = import_styled_components65.css`
9870
+ &:has(+ :focus-within) {
9871
+ background: var(--wui-color-bg-surface-hover);
9872
+ }
9873
+
9874
+ &:hover {
9875
+ background: var(--wui-color-bg-surface-hover);
9876
+ cursor: pointer;
9877
+ }
9878
+ `;
9879
+ var singleLineStyles = import_styled_components65.css`
9880
+ white-space: nowrap;
9881
+ overflow: hidden;
9882
+ text-overflow: ellipsis;
9883
+ `;
9884
+ var StyledHeading2 = import_styled_components65.default.span`
9885
+ ${textStyles}
9886
+ && {
9887
+ margin: 0;
9888
+ ${sharedStyles}
9889
+ width: ${({ $fullWidth }) => $fullWidth ? "100%" : "auto"};
9890
+ ${({ $singleLine }) => $singleLine && singleLineStyles}
9891
+ }
9892
+ display: block;
9893
+ overflow-wrap: ${({ $singleLine }) => $singleLine ? "normal" : "anywhere"};
9894
+ transition: all var(--wui-motion-duration-01) var(--wui-motion-ease);
9895
+ ${({ $isEditingControlled }) => !$isEditingControlled && editableStyles}
9896
+ `;
9897
+ var resolveFullWidth = (fullWidth) => ({
9898
+ heading: typeof fullWidth === "boolean" ? fullWidth : fullWidth.heading ?? true,
9899
+ input: typeof fullWidth === "boolean" ? fullWidth : fullWidth.input ?? true
9900
+ });
9901
+ var EditableHeading = ({
9902
+ value: controlledValue,
9903
+ onValueChange,
9904
+ onEditingChange,
9905
+ tooltipText,
9906
+ ariaLabel,
9907
+ isEditing: controlledIsEditing,
9908
+ renderTextAs: passedRenderTextAs,
9909
+ textVariant = "heading1",
9910
+ fullWidth = true,
9911
+ singleLine = false,
9912
+ disableOnBlur = false,
9913
+ editingDisabled = false
9914
+ }) => {
9915
+ const [internalIsEditing, setInternalIsEditing] = (0, import_react46.useState)(false);
9916
+ const [internalValue, setInternalValue] = (0, import_react46.useState)(controlledValue);
9917
+ const [previousValue, setPreviousValue] = (0, import_react46.useState)(controlledValue);
9918
+ const [headingHeight, setHeadingHeight] = (0, import_react46.useState)("60");
9919
+ const [headingWidth, setHeadingWidth] = (0, import_react46.useState)("auto");
9920
+ const headingRef = (0, import_react46.useRef)(null);
9921
+ const isValueControlled = (0, import_type_guards37.isNotNil)(onValueChange);
9922
+ const isEditingControlled = (0, import_type_guards37.isNotNil)(controlledIsEditing);
9923
+ const isEditing = isEditingControlled ? controlledIsEditing : internalIsEditing;
9924
+ const value = isValueControlled ? controlledValue : internalValue;
9925
+ (0, import_react46.useEffect)(() => {
9926
+ if (isValueControlled) {
9927
+ setInternalValue(controlledValue);
9928
+ setPreviousValue(controlledValue);
9929
+ }
9930
+ }, [controlledValue, isValueControlled]);
9931
+ const renderTextAs = passedRenderTextAs ?? variantElementMap3[textVariant];
9932
+ (0, import_react46.useEffect)(() => {
9933
+ if (headingRef.current) {
9934
+ setHeadingHeight(`${headingRef.current.offsetHeight}`);
9935
+ setHeadingWidth(`${headingRef.current.offsetWidth}`);
9936
+ }
9937
+ }, [isEditing]);
9938
+ const handleValueChange = (newValue) => {
9939
+ if (!isValueControlled) {
9940
+ setInternalValue(newValue);
9941
+ }
9942
+ onValueChange?.(newValue);
9943
+ };
9944
+ const handleSetEditing = (editing) => {
9945
+ if (editing) {
9946
+ setPreviousValue(value);
9947
+ }
9948
+ if (!isEditingControlled) {
9949
+ setInternalIsEditing(editing);
9950
+ }
9951
+ onEditingChange?.(editing);
9952
+ };
9953
+ const handleFinishEditing = () => {
9954
+ const trimmedValue = value.trim();
9955
+ if (trimmedValue === "" && !isValueControlled) {
9956
+ setInternalValue(previousValue);
9957
+ }
9958
+ if (trimmedValue !== previousValue) {
9959
+ handleValueChange(trimmedValue);
9960
+ }
9961
+ handleSetEditing(false);
9962
+ };
9963
+ const handleKeyDown = (event) => {
9964
+ if (event.key === "Enter" && !event.shiftKey) {
9965
+ event.preventDefault();
9966
+ handleFinishEditing();
9967
+ }
9968
+ if (event.key === "Escape") {
9969
+ if (!isValueControlled) {
9970
+ setInternalValue(previousValue);
9971
+ }
9972
+ handleSetEditing(false);
9973
+ }
9974
+ };
9975
+ const resolvedFullWidth = resolveFullWidth(fullWidth);
9976
+ const HeadingComponent2 = /* @__PURE__ */ (0, import_jsx_runtime214.jsx)(
9977
+ StyledHeading2,
9978
+ {
9979
+ ref: headingRef,
9980
+ $fullWidth: resolvedFullWidth.heading,
9981
+ $isEditingControlled: isEditingControlled || editingDisabled,
9982
+ $singleLine: singleLine,
9983
+ $variant: textVariant,
9984
+ as: renderTextAs,
9985
+ onClick: () => !editingDisabled && !isEditingControlled && !isEditing && handleSetEditing(true),
9986
+ children: value
9987
+ }
9988
+ );
9989
+ if (editingDisabled) {
9990
+ return HeadingComponent2;
9991
+ }
9992
+ if (isEditing) {
9993
+ return /* @__PURE__ */ (0, import_jsx_runtime214.jsx)(
9994
+ StyledInput,
9995
+ {
9996
+ $height: headingHeight,
9997
+ $variant: textVariant,
9998
+ $width: resolvedFullWidth.input ? headingWidth : null,
9999
+ autoFocus: true,
10000
+ fullWidth: resolvedFullWidth.input,
10001
+ onBlur: () => !disableOnBlur && handleFinishEditing(),
10002
+ onChange: (event) => handleValueChange(event.target.value),
10003
+ onFocus: (event) => {
10004
+ const { length } = event.currentTarget.value;
10005
+ event.currentTarget.setSelectionRange(length, length);
10006
+ },
10007
+ onKeyDown: handleKeyDown,
10008
+ type: singleLine ? "text" : "multiline",
10009
+ value
10010
+ }
10011
+ );
10012
+ }
10013
+ return /* @__PURE__ */ (0, import_jsx_runtime214.jsxs)(import_jsx_runtime214.Fragment, { children: [
10014
+ /* @__PURE__ */ (0, import_jsx_runtime214.jsx)(
10015
+ Tooltip,
10016
+ {
10017
+ compact: true,
10018
+ content: tooltipText ?? "",
10019
+ children: HeadingComponent2
10020
+ }
10021
+ ),
10022
+ !isEditingControlled && /* @__PURE__ */ (0, import_jsx_runtime214.jsx)(ScreenReaderOnly, { children: /* @__PURE__ */ (0, import_jsx_runtime214.jsx)(
10023
+ "button",
10024
+ {
10025
+ "aria-label": ariaLabel,
10026
+ onClick: () => handleSetEditing(true),
10027
+ type: "button"
10028
+ }
10029
+ ) })
10030
+ ] });
10031
+ };
9778
10032
  // Annotate the CommonJS export names for ESM import in node:
9779
10033
  0 && (module.exports = {
9780
10034
  ActionButton,
@@ -9794,6 +10048,7 @@ var DataCardTrend = ({
9794
10048
  DataCardTrend,
9795
10049
  DataCards,
9796
10050
  Divider,
10051
+ EditableHeading,
9797
10052
  Ellipsis,
9798
10053
  Form,
9799
10054
  FormErrorSummary,