@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/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 };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Copyright 2023-present DreamNum Co., Ltd.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import type { CSSProperties, ReactNode } from 'react';
17
+ export interface IPanelProps {
18
+ children: ReactNode;
19
+ className?: string;
20
+ style?: CSSProperties;
21
+ }
22
+ export declare function Panel(props: IPanelProps): import("react/jsx-runtime").JSX.Element;
23
+ export interface IPanelSectionProps {
24
+ title: ReactNode;
25
+ children: ReactNode;
26
+ className?: string;
27
+ defaultExpanded?: boolean;
28
+ collapsible?: boolean;
29
+ }
30
+ export declare function PanelSection(props: IPanelSectionProps): import("react/jsx-runtime").JSX.Element;
31
+ export interface IPanelFieldProps {
32
+ label: ReactNode;
33
+ children: ReactNode;
34
+ className?: string;
35
+ required?: boolean;
36
+ error?: string;
37
+ }
38
+ export declare function PanelField(props: IPanelFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Copyright 2023-present DreamNum Co., Ltd.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import type { Meta } from '@storybook/react';
17
+ import { Panel } from './Panel';
18
+ declare const meta: Meta<typeof Panel>;
19
+ export default meta;
20
+ export declare const PanelBasic: {
21
+ render(): import("react/jsx-runtime").JSX.Element;
22
+ };
@@ -41,6 +41,7 @@ export { type IInputProps, Input } from './components/input/Input';
41
41
  export { type IKBDProps, KBD } from './components/kbd/Kbd';
42
42
  export { type IMessageProps, message, Messager, MessageType, removeMessage } from './components/message/Message';
43
43
  export { type IPagerProps, Pager } from './components/pager/Pager';
44
+ export { type IPanelFieldProps, type IPanelProps, type IPanelSectionProps, Panel, PanelField, PanelSection } from './components/panel/Panel';
44
45
  export { type IPopupProps, Popup } from './components/popup';
45
46
  export { type IRadioGroupProps, RadioGroup } from './components/radio-group/RadioGroup';
46
47
  export { type IRadioProps, Radio } from './components/radio/Radio';