@univerjs/design 0.23.0 → 0.24.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/lib/cjs/index.js CHANGED
@@ -919,6 +919,7 @@ function Dialog(props) {
919
919
  * limitations under the License.
920
920
  */
921
921
  const hsvToRgb = (h, s, v) => {
922
+ h = h % 360;
922
923
  s = s / 100;
923
924
  v = v / 100;
924
925
  const c = v * s;
@@ -1029,6 +1030,7 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1029
1030
  const [isDragging, setIsDragging] = (0, react.useState)(false);
1030
1031
  const sliderRef = (0, react.useRef)(null);
1031
1032
  const thumbRef = (0, react.useRef)(null);
1033
+ const alphaRef = (0, react.useRef)(alpha);
1032
1034
  const calculateAlpha = (0, react.useCallback)((clientX) => {
1033
1035
  var _thumbRef$current$cli, _thumbRef$current;
1034
1036
  const slider = sliderRef.current;
@@ -1047,10 +1049,13 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1047
1049
  if (!isDragging) return;
1048
1050
  calculateAlpha(e.clientX);
1049
1051
  }, [isDragging, calculateAlpha]);
1052
+ (0, react.useEffect)(() => {
1053
+ alphaRef.current = alpha;
1054
+ }, [alpha]);
1050
1055
  const handlePointerUp = (0, react.useCallback)(() => {
1051
1056
  setIsDragging(false);
1052
- onChanged === null || onChanged === void 0 || onChanged(alpha);
1053
- }, [alpha]);
1057
+ onChanged === null || onChanged === void 0 || onChanged(alphaRef.current);
1058
+ }, [onChanged]);
1054
1059
  (0, react.useEffect)(() => {
1055
1060
  if (isDragging) {
1056
1061
  window.addEventListener("pointermove", handlePointerMove);
@@ -1077,6 +1082,7 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1077
1082
  };
1078
1083
  const color = hsvToRgb(...hsv);
1079
1084
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1085
+ "data-u-comp": "color-picker-alpha-slider",
1080
1086
  className: "univer-relative univer-w-full univer-select-none",
1081
1087
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1082
1088
  className: "univer-absolute univer-inset-0 univer-rounded-full",
@@ -1087,6 +1093,7 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1087
1093
  }
1088
1094
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1089
1095
  ref: sliderRef,
1096
+ "data-u-comp": "color-picker-alpha-slider-track",
1090
1097
  className: "univer-relative univer-h-2 univer-w-full univer-cursor-pointer univer-rounded-full univer-shadow-inner",
1091
1098
  style: { background: `linear-gradient(to right, transparent, rgb(${color.join(",")}))` },
1092
1099
  onPointerDown: (e) => {
@@ -1095,6 +1102,7 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1095
1102
  },
1096
1103
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1097
1104
  ref: thumbRef,
1105
+ "data-u-comp": "color-picker-alpha-slider-thumb",
1098
1106
  className: "univer-absolute univer-top-1/2 univer-box-border univer-size-2 univer-rounded-full univer-bg-transparent univer-shadow-md univer-ring-2 univer-ring-white univer-transition-transform univer-duration-75 univer-will-change-transform",
1099
1107
  style: {
1100
1108
  left: getThumbPosition(),
@@ -1374,7 +1382,7 @@ function ColorSpectrum({ hsv, onChange, onChanged }) {
1374
1382
  gradientV.addColorStop(1, "rgba(0, 0, 0, 1)");
1375
1383
  ctx.fillStyle = gradientV;
1376
1384
  ctx.fillRect(0, 0, canvas.width, canvas.height);
1377
- }, [hsv]);
1385
+ }, [hsv[0]]);
1378
1386
  const handlePointerEvent = (e) => {
1379
1387
  e.stopPropagation();
1380
1388
  const canvas = canvasRef.current;
@@ -1388,7 +1396,7 @@ function ColorSpectrum({ hsv, onChange, onChanged }) {
1388
1396
  };
1389
1397
  const handlePointerUp = (0, react.useCallback)(() => {
1390
1398
  setIsDragging(false);
1391
- }, [hsv]);
1399
+ }, []);
1392
1400
  function handleChange() {
1393
1401
  onChanged === null || onChanged === void 0 || onChanged(hsv[0], hsv[1], hsv[2]);
1394
1402
  }
@@ -1431,6 +1439,7 @@ function ColorSpectrum({ hsv, onChange, onChanged }) {
1431
1439
  className: "univer-relative univer-overflow-hidden",
1432
1440
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
1433
1441
  ref: canvasRef,
1442
+ "data-u-comp": "color-picker-spectrum-canvas",
1434
1443
  className: "univer-size-full univer-cursor-crosshair univer-rounded",
1435
1444
  onPointerDown: (e) => {
1436
1445
  setIsDragging(true);
@@ -1465,6 +1474,7 @@ function HueSlider({ hsv, onChange, onChanged }) {
1465
1474
  const [isDragging, setIsDragging] = (0, react.useState)(false);
1466
1475
  const sliderRef = (0, react.useRef)(null);
1467
1476
  const thumbRef = (0, react.useRef)(null);
1477
+ const hsvRef = (0, react.useRef)(hsv);
1468
1478
  const calculateHue = (0, react.useCallback)((clientX) => {
1469
1479
  var _thumbRef$current$cli, _thumbRef$current;
1470
1480
  const slider = sliderRef.current;
@@ -1484,10 +1494,14 @@ function HueSlider({ hsv, onChange, onChanged }) {
1484
1494
  if (!isDragging) return;
1485
1495
  calculateHue(e.clientX);
1486
1496
  }, [isDragging, calculateHue]);
1497
+ (0, react.useEffect)(() => {
1498
+ hsvRef.current = hsv;
1499
+ }, [hsv]);
1487
1500
  const handlePointerUp = (0, react.useCallback)(() => {
1488
1501
  setIsDragging(false);
1489
- onChanged === null || onChanged === void 0 || onChanged(hsv[0], hsv[1], hsv[2]);
1490
- }, [hsv, onChanged]);
1502
+ const [h, s, v] = hsvRef.current;
1503
+ onChanged === null || onChanged === void 0 || onChanged(h, s, v);
1504
+ }, [onChanged]);
1491
1505
  (0, react.useEffect)(() => {
1492
1506
  if (isDragging) {
1493
1507
  window.addEventListener("pointermove", handlePointerMove);
@@ -1532,6 +1546,7 @@ function HueSlider({ hsv, onChange, onChanged }) {
1532
1546
  },
1533
1547
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1534
1548
  ref: thumbRef,
1549
+ "data-u-comp": "color-picker-hue-slider-thumb",
1535
1550
  className: "univer-absolute univer-top-1/2 univer-box-border univer-size-2 univer-rounded-full univer-bg-transparent univer-shadow-md univer-ring-2 univer-ring-white univer-transition-transform univer-duration-75 univer-will-change-transform",
1536
1551
  style: {
1537
1552
  left: getThumbPosition(),
@@ -3062,6 +3077,19 @@ function GradientColorPicker(props) {
3062
3077
  const { locale } = (0, react.useContext)(ConfigContext);
3063
3078
  const [selectedIndex, setSelectedIndex] = (0, react.useState)(0);
3064
3079
  const barRef = (0, react.useRef)(null);
3080
+ const cleanupRef = (0, react.useRef)(null);
3081
+ (0, react.useEffect)(() => {
3082
+ setSelectedIndex((prev) => {
3083
+ if (prev >= value.stops.length) return Math.max(0, value.stops.length - 1);
3084
+ return prev;
3085
+ });
3086
+ }, [value.stops.length]);
3087
+ (0, react.useEffect)(() => {
3088
+ return () => {
3089
+ var _cleanupRef$current;
3090
+ (_cleanupRef$current = cleanupRef.current) === null || _cleanupRef$current === void 0 || _cleanupRef$current.call(cleanupRef);
3091
+ };
3092
+ }, []);
3065
3093
  const stops = (0, react.useMemo)(() => {
3066
3094
  return [...value.stops].sort((a, b) => a.offset - b.offset);
3067
3095
  }, [value.stops]);
@@ -3163,6 +3191,7 @@ function GradientColorPicker(props) {
3163
3191
  onChange: (v) => handleTypeChange(v)
3164
3192
  }),
3165
3193
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3194
+ "data-u-comp": "gradient-color-picker-preview",
3166
3195
  className: "univer-h-32 univer-w-full univer-rounded-md univer-border univer-border-gray-200 dark:!univer-border-gray-600",
3167
3196
  style: { background: mainPreview }
3168
3197
  }),
@@ -3170,10 +3199,13 @@ function GradientColorPicker(props) {
3170
3199
  className: "univer-relative univer-mt-4 univer-h-6",
3171
3200
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3172
3201
  ref: barRef,
3202
+ "data-u-comp": "gradient-color-picker-bar",
3173
3203
  className: "univer-absolute univer-inset-x-0 univer-top-1/2 univer-h-2 -univer-translate-y-1/2 univer-cursor-crosshair univer-rounded-full",
3174
3204
  style: { background: gradientPreview },
3175
3205
  onClick: handleAddStop
3176
3206
  }), value.stops.map((stop, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3207
+ "data-u-comp": "gradient-color-picker-stop",
3208
+ "data-selected": selectedIndex === index,
3177
3209
  className: clsx$1("univer-absolute univer-top-1/2 univer-size-4 -univer-translate-x-1/2 -univer-translate-y-1/2 univer-cursor-pointer univer-rounded-full univer-border-2 univer-border-white univer-shadow-md", selectedIndex === index ? "univer-z-10 univer-ring-2 univer-ring-primary-500" : "univer-z-0"),
3178
3210
  style: {
3179
3211
  left: `${stop.offset}%`,
@@ -3204,7 +3236,9 @@ function GradientColorPicker(props) {
3204
3236
  const handlePointerUp = () => {
3205
3237
  window.removeEventListener("pointermove", handlePointerMove);
3206
3238
  window.removeEventListener("pointerup", handlePointerUp);
3239
+ cleanupRef.current = null;
3207
3240
  };
3241
+ cleanupRef.current = handlePointerUp;
3208
3242
  window.addEventListener("pointermove", handlePointerMove);
3209
3243
  window.addEventListener("pointerup", handlePointerUp);
3210
3244
  }
@@ -3242,6 +3276,7 @@ function GradientColorPicker(props) {
3242
3276
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tooltip, {
3243
3277
  title: locale === null || locale === void 0 ? void 0 : locale.GradientColorPicker.delete,
3244
3278
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
3279
+ "data-u-comp": "gradient-color-picker-delete",
3245
3280
  variant: "danger",
3246
3281
  onClick: handleRemoveStop,
3247
3282
  disabled: value.stops.length <= 2,
@@ -3441,6 +3476,83 @@ const removeMessage = (id) => {
3441
3476
  activeMessageIds.clear();
3442
3477
  };
3443
3478
 
3479
+ //#endregion
3480
+ //#region src/components/panel/Panel.tsx
3481
+ function Panel(props) {
3482
+ const { children, className, style } = props;
3483
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3484
+ "data-u-comp": "panel",
3485
+ className: clsx$1("univer-flex univer-flex-col univer-gap-5 univer-py-2", className),
3486
+ style,
3487
+ children
3488
+ });
3489
+ }
3490
+ function PanelSection(props) {
3491
+ const { title, children, className, defaultExpanded = true, collapsible = true } = props;
3492
+ const [expanded, setExpanded] = (0, react.useState)(defaultExpanded);
3493
+ const contentId = (0, react.useId)();
3494
+ const headerId = (0, react.useId)();
3495
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3496
+ "data-u-comp": "panel-section",
3497
+ className: clsx$1("univer-flex univer-flex-col", className),
3498
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3499
+ id: headerId,
3500
+ type: "button",
3501
+ "aria-expanded": expanded,
3502
+ "aria-controls": contentId,
3503
+ disabled: !collapsible,
3504
+ className: clsx$1("univer-box-border univer-flex univer-w-full univer-items-center univer-gap-1.5 univer-border-none univer-bg-transparent univer-p-0 univer-pb-2.5 univer-text-left univer-text-sm univer-font-medium univer-text-gray-700 dark:!univer-text-gray-200", {
3505
+ "univer-cursor-pointer": collapsible,
3506
+ "univer-cursor-default": !collapsible
3507
+ }),
3508
+ onClick: () => collapsible && setExpanded((v) => !v),
3509
+ children: [collapsible && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.DownIcon, { className: clsx$1("univer-size-2.5 univer-flex-shrink-0 univer-transition-transform", {
3510
+ "-univer-rotate-90": !expanded,
3511
+ "univer-rotate-0": expanded
3512
+ }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: title })]
3513
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3514
+ id: contentId,
3515
+ role: "region",
3516
+ "aria-labelledby": headerId,
3517
+ className: clsx$1("univer-overflow-hidden univer-transition-[max-height,opacity] univer-duration-300 univer-ease-in-out", {
3518
+ "univer-max-h-[1000px] univer-opacity-100": expanded,
3519
+ "univer-max-h-0 univer-opacity-0": !expanded
3520
+ }),
3521
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3522
+ className: "univer-box-border univer-flex univer-flex-col univer-gap-3 univer-py-1",
3523
+ children
3524
+ })
3525
+ })]
3526
+ });
3527
+ }
3528
+ function PanelField(props) {
3529
+ const { label, children, className, required, error } = props;
3530
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3531
+ "data-u-comp": "panel-field",
3532
+ className: clsx$1("univer-flex univer-flex-col univer-gap-1.5", className),
3533
+ children: [
3534
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3535
+ className: "univer-flex univer-items-center univer-gap-1",
3536
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3537
+ className: "univer-text-xs univer-text-gray-600 dark:!univer-text-gray-300",
3538
+ children: label
3539
+ }), required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3540
+ className: "univer-text-xs univer-text-red-500",
3541
+ children: "*"
3542
+ })]
3543
+ }),
3544
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3545
+ className: "univer-w-full",
3546
+ children
3547
+ }),
3548
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3549
+ className: "univer-text-xs univer-text-red-500",
3550
+ children: error
3551
+ })
3552
+ ]
3553
+ });
3554
+ }
3555
+
3444
3556
  //#endregion
3445
3557
  //#region src/components/popup/Popup.tsx
3446
3558
  const POPUP_POINTER_OFFSET = 2;
@@ -4253,6 +4365,9 @@ exports.MessageType = MessageType;
4253
4365
  exports.Messager = Messager;
4254
4366
  exports.MultipleSelect = MultipleSelect;
4255
4367
  exports.Pager = Pager;
4368
+ exports.Panel = Panel;
4369
+ exports.PanelField = PanelField;
4370
+ exports.PanelSection = PanelSection;
4256
4371
  exports.Popup = Popup;
4257
4372
  exports.Radio = Radio;
4258
4373
  exports.RadioGroup = RadioGroup;
package/lib/es/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CalendarIcon, CheckMarkIcon, ClockIcon, CloseIcon, DeleteIcon, DownIcon, DropdownIcon, ErrorIcon, InfoIcon, LoadingMultiIcon, MoreDownIcon, MoreLeftIcon, MoreRightIcon, MoreUpIcon, OneToOneIcon, SuccessIcon, WarningIcon, ZoomInIcon, ZoomOutIcon } from "@univerjs/icons";
2
- import { Children, cloneElement, createContext, forwardRef, isValidElement, memo, useCallback, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
2
+ import { Children, cloneElement, createContext, forwardRef, isValidElement, memo, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
3
3
  import { clsx as clsx$1 } from "clsx";
4
4
  import { twMerge } from "tailwind-merge";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -918,6 +918,7 @@ function Dialog(props) {
918
918
  * limitations under the License.
919
919
  */
920
920
  const hsvToRgb = (h, s, v) => {
921
+ h = h % 360;
921
922
  s = s / 100;
922
923
  v = v / 100;
923
924
  const c = v * s;
@@ -1028,6 +1029,7 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1028
1029
  const [isDragging, setIsDragging] = useState(false);
1029
1030
  const sliderRef = useRef(null);
1030
1031
  const thumbRef = useRef(null);
1032
+ const alphaRef = useRef(alpha);
1031
1033
  const calculateAlpha = useCallback((clientX) => {
1032
1034
  var _thumbRef$current$cli, _thumbRef$current;
1033
1035
  const slider = sliderRef.current;
@@ -1046,10 +1048,13 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1046
1048
  if (!isDragging) return;
1047
1049
  calculateAlpha(e.clientX);
1048
1050
  }, [isDragging, calculateAlpha]);
1051
+ useEffect(() => {
1052
+ alphaRef.current = alpha;
1053
+ }, [alpha]);
1049
1054
  const handlePointerUp = useCallback(() => {
1050
1055
  setIsDragging(false);
1051
- onChanged === null || onChanged === void 0 || onChanged(alpha);
1052
- }, [alpha]);
1056
+ onChanged === null || onChanged === void 0 || onChanged(alphaRef.current);
1057
+ }, [onChanged]);
1053
1058
  useEffect(() => {
1054
1059
  if (isDragging) {
1055
1060
  window.addEventListener("pointermove", handlePointerMove);
@@ -1076,6 +1081,7 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1076
1081
  };
1077
1082
  const color = hsvToRgb(...hsv);
1078
1083
  return /* @__PURE__ */ jsxs("div", {
1084
+ "data-u-comp": "color-picker-alpha-slider",
1079
1085
  className: "univer-relative univer-w-full univer-select-none",
1080
1086
  children: [/* @__PURE__ */ jsx("div", {
1081
1087
  className: "univer-absolute univer-inset-0 univer-rounded-full",
@@ -1086,6 +1092,7 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1086
1092
  }
1087
1093
  }), /* @__PURE__ */ jsx("div", {
1088
1094
  ref: sliderRef,
1095
+ "data-u-comp": "color-picker-alpha-slider-track",
1089
1096
  className: "univer-relative univer-h-2 univer-w-full univer-cursor-pointer univer-rounded-full univer-shadow-inner",
1090
1097
  style: { background: `linear-gradient(to right, transparent, rgb(${color.join(",")}))` },
1091
1098
  onPointerDown: (e) => {
@@ -1094,6 +1101,7 @@ function AlphaSlider({ hsv, alpha, onChange, onChanged }) {
1094
1101
  },
1095
1102
  children: /* @__PURE__ */ jsx("div", {
1096
1103
  ref: thumbRef,
1104
+ "data-u-comp": "color-picker-alpha-slider-thumb",
1097
1105
  className: "univer-absolute univer-top-1/2 univer-box-border univer-size-2 univer-rounded-full univer-bg-transparent univer-shadow-md univer-ring-2 univer-ring-white univer-transition-transform univer-duration-75 univer-will-change-transform",
1098
1106
  style: {
1099
1107
  left: getThumbPosition(),
@@ -1373,7 +1381,7 @@ function ColorSpectrum({ hsv, onChange, onChanged }) {
1373
1381
  gradientV.addColorStop(1, "rgba(0, 0, 0, 1)");
1374
1382
  ctx.fillStyle = gradientV;
1375
1383
  ctx.fillRect(0, 0, canvas.width, canvas.height);
1376
- }, [hsv]);
1384
+ }, [hsv[0]]);
1377
1385
  const handlePointerEvent = (e) => {
1378
1386
  e.stopPropagation();
1379
1387
  const canvas = canvasRef.current;
@@ -1387,7 +1395,7 @@ function ColorSpectrum({ hsv, onChange, onChanged }) {
1387
1395
  };
1388
1396
  const handlePointerUp = useCallback(() => {
1389
1397
  setIsDragging(false);
1390
- }, [hsv]);
1398
+ }, []);
1391
1399
  function handleChange() {
1392
1400
  onChanged === null || onChanged === void 0 || onChanged(hsv[0], hsv[1], hsv[2]);
1393
1401
  }
@@ -1430,6 +1438,7 @@ function ColorSpectrum({ hsv, onChange, onChanged }) {
1430
1438
  className: "univer-relative univer-overflow-hidden",
1431
1439
  children: [/* @__PURE__ */ jsx("canvas", {
1432
1440
  ref: canvasRef,
1441
+ "data-u-comp": "color-picker-spectrum-canvas",
1433
1442
  className: "univer-size-full univer-cursor-crosshair univer-rounded",
1434
1443
  onPointerDown: (e) => {
1435
1444
  setIsDragging(true);
@@ -1464,6 +1473,7 @@ function HueSlider({ hsv, onChange, onChanged }) {
1464
1473
  const [isDragging, setIsDragging] = useState(false);
1465
1474
  const sliderRef = useRef(null);
1466
1475
  const thumbRef = useRef(null);
1476
+ const hsvRef = useRef(hsv);
1467
1477
  const calculateHue = useCallback((clientX) => {
1468
1478
  var _thumbRef$current$cli, _thumbRef$current;
1469
1479
  const slider = sliderRef.current;
@@ -1483,10 +1493,14 @@ function HueSlider({ hsv, onChange, onChanged }) {
1483
1493
  if (!isDragging) return;
1484
1494
  calculateHue(e.clientX);
1485
1495
  }, [isDragging, calculateHue]);
1496
+ useEffect(() => {
1497
+ hsvRef.current = hsv;
1498
+ }, [hsv]);
1486
1499
  const handlePointerUp = useCallback(() => {
1487
1500
  setIsDragging(false);
1488
- onChanged === null || onChanged === void 0 || onChanged(hsv[0], hsv[1], hsv[2]);
1489
- }, [hsv, onChanged]);
1501
+ const [h, s, v] = hsvRef.current;
1502
+ onChanged === null || onChanged === void 0 || onChanged(h, s, v);
1503
+ }, [onChanged]);
1490
1504
  useEffect(() => {
1491
1505
  if (isDragging) {
1492
1506
  window.addEventListener("pointermove", handlePointerMove);
@@ -1531,6 +1545,7 @@ function HueSlider({ hsv, onChange, onChanged }) {
1531
1545
  },
1532
1546
  children: /* @__PURE__ */ jsx("div", {
1533
1547
  ref: thumbRef,
1548
+ "data-u-comp": "color-picker-hue-slider-thumb",
1534
1549
  className: "univer-absolute univer-top-1/2 univer-box-border univer-size-2 univer-rounded-full univer-bg-transparent univer-shadow-md univer-ring-2 univer-ring-white univer-transition-transform univer-duration-75 univer-will-change-transform",
1535
1550
  style: {
1536
1551
  left: getThumbPosition(),
@@ -3061,6 +3076,19 @@ function GradientColorPicker(props) {
3061
3076
  const { locale } = useContext(ConfigContext);
3062
3077
  const [selectedIndex, setSelectedIndex] = useState(0);
3063
3078
  const barRef = useRef(null);
3079
+ const cleanupRef = useRef(null);
3080
+ useEffect(() => {
3081
+ setSelectedIndex((prev) => {
3082
+ if (prev >= value.stops.length) return Math.max(0, value.stops.length - 1);
3083
+ return prev;
3084
+ });
3085
+ }, [value.stops.length]);
3086
+ useEffect(() => {
3087
+ return () => {
3088
+ var _cleanupRef$current;
3089
+ (_cleanupRef$current = cleanupRef.current) === null || _cleanupRef$current === void 0 || _cleanupRef$current.call(cleanupRef);
3090
+ };
3091
+ }, []);
3064
3092
  const stops = useMemo(() => {
3065
3093
  return [...value.stops].sort((a, b) => a.offset - b.offset);
3066
3094
  }, [value.stops]);
@@ -3162,6 +3190,7 @@ function GradientColorPicker(props) {
3162
3190
  onChange: (v) => handleTypeChange(v)
3163
3191
  }),
3164
3192
  /* @__PURE__ */ jsx("div", {
3193
+ "data-u-comp": "gradient-color-picker-preview",
3165
3194
  className: "univer-h-32 univer-w-full univer-rounded-md univer-border univer-border-gray-200 dark:!univer-border-gray-600",
3166
3195
  style: { background: mainPreview }
3167
3196
  }),
@@ -3169,10 +3198,13 @@ function GradientColorPicker(props) {
3169
3198
  className: "univer-relative univer-mt-4 univer-h-6",
3170
3199
  children: [/* @__PURE__ */ jsx("div", {
3171
3200
  ref: barRef,
3201
+ "data-u-comp": "gradient-color-picker-bar",
3172
3202
  className: "univer-absolute univer-inset-x-0 univer-top-1/2 univer-h-2 -univer-translate-y-1/2 univer-cursor-crosshair univer-rounded-full",
3173
3203
  style: { background: gradientPreview },
3174
3204
  onClick: handleAddStop
3175
3205
  }), value.stops.map((stop, index) => /* @__PURE__ */ jsx("div", {
3206
+ "data-u-comp": "gradient-color-picker-stop",
3207
+ "data-selected": selectedIndex === index,
3176
3208
  className: clsx("univer-absolute univer-top-1/2 univer-size-4 -univer-translate-x-1/2 -univer-translate-y-1/2 univer-cursor-pointer univer-rounded-full univer-border-2 univer-border-white univer-shadow-md", selectedIndex === index ? "univer-z-10 univer-ring-2 univer-ring-primary-500" : "univer-z-0"),
3177
3209
  style: {
3178
3210
  left: `${stop.offset}%`,
@@ -3203,7 +3235,9 @@ function GradientColorPicker(props) {
3203
3235
  const handlePointerUp = () => {
3204
3236
  window.removeEventListener("pointermove", handlePointerMove);
3205
3237
  window.removeEventListener("pointerup", handlePointerUp);
3238
+ cleanupRef.current = null;
3206
3239
  };
3240
+ cleanupRef.current = handlePointerUp;
3207
3241
  window.addEventListener("pointermove", handlePointerMove);
3208
3242
  window.addEventListener("pointerup", handlePointerUp);
3209
3243
  }
@@ -3241,6 +3275,7 @@ function GradientColorPicker(props) {
3241
3275
  children: /* @__PURE__ */ jsx(Tooltip, {
3242
3276
  title: locale === null || locale === void 0 ? void 0 : locale.GradientColorPicker.delete,
3243
3277
  children: /* @__PURE__ */ jsx(Button, {
3278
+ "data-u-comp": "gradient-color-picker-delete",
3244
3279
  variant: "danger",
3245
3280
  onClick: handleRemoveStop,
3246
3281
  disabled: value.stops.length <= 2,
@@ -3440,6 +3475,83 @@ const removeMessage = (id) => {
3440
3475
  activeMessageIds.clear();
3441
3476
  };
3442
3477
 
3478
+ //#endregion
3479
+ //#region src/components/panel/Panel.tsx
3480
+ function Panel(props) {
3481
+ const { children, className, style } = props;
3482
+ return /* @__PURE__ */ jsx("div", {
3483
+ "data-u-comp": "panel",
3484
+ className: clsx("univer-flex univer-flex-col univer-gap-5 univer-py-2", className),
3485
+ style,
3486
+ children
3487
+ });
3488
+ }
3489
+ function PanelSection(props) {
3490
+ const { title, children, className, defaultExpanded = true, collapsible = true } = props;
3491
+ const [expanded, setExpanded] = useState(defaultExpanded);
3492
+ const contentId = useId();
3493
+ const headerId = useId();
3494
+ return /* @__PURE__ */ jsxs("div", {
3495
+ "data-u-comp": "panel-section",
3496
+ className: clsx("univer-flex univer-flex-col", className),
3497
+ children: [/* @__PURE__ */ jsxs("button", {
3498
+ id: headerId,
3499
+ type: "button",
3500
+ "aria-expanded": expanded,
3501
+ "aria-controls": contentId,
3502
+ disabled: !collapsible,
3503
+ className: clsx("univer-box-border univer-flex univer-w-full univer-items-center univer-gap-1.5 univer-border-none univer-bg-transparent univer-p-0 univer-pb-2.5 univer-text-left univer-text-sm univer-font-medium univer-text-gray-700 dark:!univer-text-gray-200", {
3504
+ "univer-cursor-pointer": collapsible,
3505
+ "univer-cursor-default": !collapsible
3506
+ }),
3507
+ onClick: () => collapsible && setExpanded((v) => !v),
3508
+ children: [collapsible && /* @__PURE__ */ jsx(DownIcon, { className: clsx("univer-size-2.5 univer-flex-shrink-0 univer-transition-transform", {
3509
+ "-univer-rotate-90": !expanded,
3510
+ "univer-rotate-0": expanded
3511
+ }) }), /* @__PURE__ */ jsx("span", { children: title })]
3512
+ }), /* @__PURE__ */ jsx("div", {
3513
+ id: contentId,
3514
+ role: "region",
3515
+ "aria-labelledby": headerId,
3516
+ className: clsx("univer-overflow-hidden univer-transition-[max-height,opacity] univer-duration-300 univer-ease-in-out", {
3517
+ "univer-max-h-[1000px] univer-opacity-100": expanded,
3518
+ "univer-max-h-0 univer-opacity-0": !expanded
3519
+ }),
3520
+ children: /* @__PURE__ */ jsx("div", {
3521
+ className: "univer-box-border univer-flex univer-flex-col univer-gap-3 univer-py-1",
3522
+ children
3523
+ })
3524
+ })]
3525
+ });
3526
+ }
3527
+ function PanelField(props) {
3528
+ const { label, children, className, required, error } = props;
3529
+ return /* @__PURE__ */ jsxs("div", {
3530
+ "data-u-comp": "panel-field",
3531
+ className: clsx("univer-flex univer-flex-col univer-gap-1.5", className),
3532
+ children: [
3533
+ /* @__PURE__ */ jsxs("div", {
3534
+ className: "univer-flex univer-items-center univer-gap-1",
3535
+ children: [/* @__PURE__ */ jsx("span", {
3536
+ className: "univer-text-xs univer-text-gray-600 dark:!univer-text-gray-300",
3537
+ children: label
3538
+ }), required && /* @__PURE__ */ jsx("span", {
3539
+ className: "univer-text-xs univer-text-red-500",
3540
+ children: "*"
3541
+ })]
3542
+ }),
3543
+ /* @__PURE__ */ jsx("div", {
3544
+ className: "univer-w-full",
3545
+ children
3546
+ }),
3547
+ error && /* @__PURE__ */ jsx("span", {
3548
+ className: "univer-text-xs univer-text-red-500",
3549
+ children: error
3550
+ })
3551
+ ]
3552
+ });
3553
+ }
3554
+
3443
3555
  //#endregion
3444
3556
  //#region src/components/popup/Popup.tsx
3445
3557
  const POPUP_POINTER_OFFSET = 2;
@@ -4221,4 +4333,4 @@ function resizeObserverCtor(callback) {
4221
4333
  }
4222
4334
 
4223
4335
  //#endregion
4224
- export { Accordion, Avatar, Badge, Button, ButtonGroup, Calendar, CascaderList, Checkbox, CheckboxGroup, ColorPicker, ConfigContext, ConfigProvider, Confirm, DatePicker, DateRangePicker, Dialog, DraggableList, Dropdown, DropdownMenu, FormDualColumnLayout, FormLayout, Gallery, GradientColorPicker, HoverCard, Input, InputNumber, KBD, MessageType, Messager, MultipleSelect, Pager, Popup, Radio, RadioGroup, Segmented, Select, SelectList, Separator, Switch, Textarea, TimeInput, Toaster, Tooltip, Tree, TreeSelectionMode, borderBottomClassName, borderClassName, borderLeftBottomClassName, borderLeftClassName, borderRightClassName, borderTopClassName, clsx, divideXClassName, divideYClassName, filterLeafNode, findNodePathFromTree, findSubTreeFromPath, isBrowser, mergeTreeSelected, message, removeMessage, render, resizeObserverCtor, scrollbarClassName, toast, unmount };
4336
+ export { Accordion, Avatar, Badge, Button, ButtonGroup, Calendar, CascaderList, Checkbox, CheckboxGroup, ColorPicker, ConfigContext, ConfigProvider, Confirm, DatePicker, DateRangePicker, Dialog, DraggableList, Dropdown, DropdownMenu, FormDualColumnLayout, FormLayout, Gallery, GradientColorPicker, HoverCard, Input, InputNumber, KBD, MessageType, Messager, MultipleSelect, Pager, Panel, PanelField, PanelSection, Popup, Radio, RadioGroup, Segmented, Select, SelectList, Separator, Switch, Textarea, TimeInput, Toaster, Tooltip, Tree, TreeSelectionMode, borderBottomClassName, borderClassName, borderLeftBottomClassName, borderLeftClassName, borderRightClassName, borderTopClassName, clsx, divideXClassName, divideYClassName, filterLeafNode, findNodePathFromTree, findSubTreeFromPath, isBrowser, mergeTreeSelected, message, removeMessage, render, resizeObserverCtor, scrollbarClassName, toast, unmount };
package/lib/index.css CHANGED
@@ -418,6 +418,10 @@
418
418
  max-height: var(--radix-popper-available-height);
419
419
  }
420
420
 
421
+ .univer-max-h-\[1000px\] {
422
+ max-height: 1000px;
423
+ }
424
+
421
425
  .univer-max-h-\[40vh\] {
422
426
  max-height: 40vh;
423
427
  }
@@ -733,6 +737,10 @@
733
737
  gap: 1rem;
734
738
  }
735
739
 
740
+ .univer-gap-5 {
741
+ gap: 1.25rem;
742
+ }
743
+
736
744
  .univer-space-y-1\.5 > :not([hidden]) ~ :not([hidden]) {
737
745
  --univer-tw-space-y-reverse: 0;
738
746
  margin-top: .375rem;
@@ -976,6 +984,10 @@
976
984
  border-color: var(--univer-primary-600);
977
985
  }
978
986
 
987
+ .univer-border-red-300 {
988
+ border-color: var(--univer-red-300);
989
+ }
990
+
979
991
  .univer-border-red-500 {
980
992
  border-color: var(--univer-red-500);
981
993
  }
@@ -1193,6 +1205,10 @@
1193
1205
  padding-left: 1rem !important;
1194
1206
  }
1195
1207
 
1208
+ .univer-pb-2\.5 {
1209
+ padding-bottom: .625rem;
1210
+ }
1211
+
1196
1212
  .univer-pl-2 {
1197
1213
  padding-left: .5rem;
1198
1214
  }
@@ -1454,6 +1470,10 @@
1454
1470
  opacity: 0;
1455
1471
  }
1456
1472
 
1473
+ .univer-opacity-100 {
1474
+ opacity: 1;
1475
+ }
1476
+
1457
1477
  .univer-opacity-40 {
1458
1478
  opacity: .4;
1459
1479
  }