dishui 0.0.78 → 0.0.80
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/components/Avatar/index.d.ts +6 -4
- package/dist/components/Avatar/index.js +39 -28
- package/dist/components/Avatar/index.js.map +1 -1
- package/dist/components/Card/index.d.ts +16 -8
- package/dist/components/Card/index.js +81 -99
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/DateTimeInput/index.js +3 -2
- package/dist/components/DateTimeInput/index.js.map +1 -1
- package/dist/components/GroupedTable/index.d.ts +2 -1
- package/dist/components/GroupedTable/index.js +96 -37
- package/dist/components/GroupedTable/index.js.map +1 -1
- package/dist/components/Input/index.d.ts +2 -2
- package/dist/components/Input/index.js +129 -111
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/Label/index.js +1 -1
- package/dist/components/Label/index.js.map +1 -1
- package/dist/components/NavigationList/index.js +55 -24
- package/dist/components/NavigationList/index.js.map +1 -1
- package/dist/components/Resizable/index.d.ts +28 -0
- package/dist/components/Resizable/index.js +128 -0
- package/dist/components/Resizable/index.js.map +1 -0
- package/dist/components/Resizable/useResize.d.ts +21 -0
- package/dist/components/Resizable/useResize.js +60 -0
- package/dist/components/Resizable/useResize.js.map +1 -0
- package/dist/components/SidebarToggleButton/index.js +51 -43
- package/dist/components/SidebarToggleButton/index.js.map +1 -1
- package/dist/components/Slider/index.d.ts +17 -3
- package/dist/components/Slider/index.js +131 -28
- package/dist/components/Slider/index.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js +62 -62
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/ResizableImage.d.ts +2 -0
- package/dist/components/pro/RichTextEditor/extensions/ResizableImage.js +94 -0
- package/dist/components/pro/RichTextEditor/extensions/ResizableImage.js.map +1 -0
- package/dist/components/pro/RichTextEditor/index.d.ts +1 -0
- package/dist/dishui.css +1 -1
- package/dist/index-nostyled.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +123 -121
- package/dist/layouts/Sidebar.js +34 -45
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/lite.d.ts +2 -0
- package/dist/lite.js +20 -18
- package/dist/utils/i18n.js +145 -75
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/menu.js +85 -8
- package/dist/utils/menu.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { cn as e } from "../../utils/cn.js";
|
|
2
|
-
|
|
3
|
-
import {
|
|
2
|
+
/* empty css */
|
|
3
|
+
import { useId as t, useRef as n, useState as r } from "react";
|
|
4
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
4
5
|
//#region src/components/Slider/index.tsx
|
|
5
|
-
var
|
|
6
|
+
var o = {
|
|
6
7
|
default: "",
|
|
7
8
|
primary: "range-primary",
|
|
8
9
|
secondary: "range-secondary",
|
|
@@ -11,42 +12,144 @@ var a = {
|
|
|
11
12
|
success: "range-success",
|
|
12
13
|
warning: "range-warning",
|
|
13
14
|
error: "range-error"
|
|
14
|
-
},
|
|
15
|
+
}, s = {
|
|
15
16
|
xs: "range-xs",
|
|
16
17
|
sm: "range-sm",
|
|
17
18
|
md: "range-md",
|
|
18
19
|
lg: "range-lg"
|
|
19
|
-
},
|
|
20
|
-
let
|
|
21
|
-
let t = Number(e.
|
|
22
|
-
|
|
23
|
-
}, [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
}, c = ({ value: c, defaultValue: u, min: d = 0, max: f, step: p, onChange: m, label: h, showValue: g = !1, variant: _ = "default", size: v = "sm", disabled: y = !1, name: b, className: x = "", style: S, mode: C = "linear", orientation: w = "horizontal", shape: T = "star", count: E = 5, allowHalf: D = !1, id: O, "aria-label": k, "aria-labelledby": A, "aria-describedby": j, "aria-valuetext": M }) => {
|
|
21
|
+
let N = t(), P = O ?? N, F = n(null), I = Number.isFinite(E) ? Math.max(1, Math.floor(E)) : 5, L = Math.max(d, f ?? (C === "discrete" ? d + I : 100)), R = C === "discrete" ? (L - d) / I / (D ? 2 : 1) || 1 : p !== void 0 && Number.isFinite(p) && p > 0 ? p : 1, z = (e) => {
|
|
22
|
+
let t = Math.min(Math.round((Math.min(L, Math.max(d, Number.isFinite(e) ? e : d)) - d) / R), Math.floor((L - d) / R + 1e-10));
|
|
23
|
+
return Number((d + t * R).toPrecision(15));
|
|
24
|
+
}, [B, V] = r(u ?? d), H = c !== void 0, U = z(H ? c : B), W = L > d ? (U - d) / (L - d) : 0, G = w === "vertical" && C !== "circular", K = C !== "linear", q = (e) => {
|
|
25
|
+
if (y) return;
|
|
26
|
+
let t = z(Number(e.target.value));
|
|
27
|
+
H || V(t), m?.(t, e);
|
|
28
|
+
}, J = (e) => {
|
|
29
|
+
let t = F.current;
|
|
30
|
+
if (y || !t || L === d) return;
|
|
31
|
+
let n = e.currentTarget.getBoundingClientRect(), r = G ? (n.bottom - e.clientY) / n.height : (e.clientX - n.left) / n.width;
|
|
32
|
+
if (C === "circular") {
|
|
33
|
+
let t = e.clientX - n.left - n.width / 2, i = e.clientY - n.top - n.height / 2;
|
|
34
|
+
if (Math.hypot(t, i) < n.width * .15) return;
|
|
35
|
+
r = (Math.atan2(t, -i) + Math.PI * 2) % (Math.PI * 2) / (Math.PI * 2), Math.abs(r - W) > .5 && e.type === "pointermove" && (r = +(W > .5));
|
|
36
|
+
}
|
|
37
|
+
let i = z(d + Math.min(1, Math.max(0, r)) * (L - d));
|
|
38
|
+
i !== U && (Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set?.call(t, String(i)), t.dispatchEvent(new Event("input", { bubbles: !0 })));
|
|
39
|
+
};
|
|
40
|
+
return /* @__PURE__ */ a("div", {
|
|
41
|
+
className: e("w-full dishui-slider", x),
|
|
42
|
+
style: S,
|
|
43
|
+
"data-mode": C,
|
|
44
|
+
"data-orientation": w,
|
|
45
|
+
"data-size": v,
|
|
46
|
+
"data-variant": _,
|
|
47
|
+
"data-disabled": y,
|
|
48
|
+
children: [(h !== void 0 || g) && /* @__PURE__ */ a("div", {
|
|
28
49
|
className: "mb-1 flex items-center justify-between",
|
|
29
|
-
children: [
|
|
50
|
+
children: [h !== void 0 && /* @__PURE__ */ i("label", {
|
|
51
|
+
htmlFor: P,
|
|
30
52
|
className: "label-text text-sm text-base-content/80",
|
|
31
|
-
children:
|
|
32
|
-
}),
|
|
53
|
+
children: h
|
|
54
|
+
}), g && /* @__PURE__ */ i("span", {
|
|
33
55
|
className: "text-xs font-mono text-base-content/60",
|
|
34
|
-
children:
|
|
56
|
+
children: U
|
|
35
57
|
})]
|
|
36
|
-
}), /* @__PURE__ */
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
58
|
+
}), /* @__PURE__ */ a("div", {
|
|
59
|
+
className: "dishui-slider-control",
|
|
60
|
+
onPointerDown: K ? (e) => {
|
|
61
|
+
y || e.button !== 0 || (e.preventDefault(), F.current?.focus(), e.currentTarget.setPointerCapture(e.pointerId), J(e));
|
|
62
|
+
} : void 0,
|
|
63
|
+
onPointerMove: K ? (e) => {
|
|
64
|
+
e.currentTarget.hasPointerCapture(e.pointerId) && J(e);
|
|
65
|
+
} : void 0,
|
|
66
|
+
onPointerUp: K ? (e) => {
|
|
67
|
+
e.currentTarget.hasPointerCapture(e.pointerId) && e.currentTarget.releasePointerCapture(e.pointerId);
|
|
68
|
+
} : void 0,
|
|
69
|
+
children: [
|
|
70
|
+
/* @__PURE__ */ i("input", {
|
|
71
|
+
ref: F,
|
|
72
|
+
id: P,
|
|
73
|
+
"aria-label": k,
|
|
74
|
+
"aria-labelledby": A,
|
|
75
|
+
"aria-describedby": j,
|
|
76
|
+
"aria-valuetext": M,
|
|
77
|
+
"aria-orientation": G ? "vertical" : "horizontal",
|
|
78
|
+
type: "range",
|
|
79
|
+
className: e("range", o[_], s[v]),
|
|
80
|
+
value: U,
|
|
81
|
+
min: d,
|
|
82
|
+
max: L,
|
|
83
|
+
step: R,
|
|
84
|
+
disabled: y,
|
|
85
|
+
name: b,
|
|
86
|
+
onChange: q
|
|
87
|
+
}),
|
|
88
|
+
C === "circular" && /* @__PURE__ */ a("svg", {
|
|
89
|
+
className: "dishui-slider-dial",
|
|
90
|
+
viewBox: "0 0 100 100",
|
|
91
|
+
"aria-hidden": "true",
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ i("circle", {
|
|
94
|
+
className: "dishui-slider-ring",
|
|
95
|
+
cx: "50",
|
|
96
|
+
cy: "50",
|
|
97
|
+
r: "40"
|
|
98
|
+
}),
|
|
99
|
+
/* @__PURE__ */ i("circle", {
|
|
100
|
+
className: "dishui-slider-progress",
|
|
101
|
+
cx: "50",
|
|
102
|
+
cy: "50",
|
|
103
|
+
r: "40",
|
|
104
|
+
pathLength: "100",
|
|
105
|
+
strokeDasharray: `${W * 100} 100`,
|
|
106
|
+
transform: "rotate(-90 50 50)"
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ i("circle", {
|
|
109
|
+
className: "dishui-slider-thumb",
|
|
110
|
+
cx: 50 + 40 * Math.sin(W * Math.PI * 2),
|
|
111
|
+
cy: 50 - 40 * Math.cos(W * Math.PI * 2),
|
|
112
|
+
r: "5"
|
|
113
|
+
}),
|
|
114
|
+
/* @__PURE__ */ i("text", {
|
|
115
|
+
x: "50",
|
|
116
|
+
y: "50",
|
|
117
|
+
dominantBaseline: "central",
|
|
118
|
+
textAnchor: "middle",
|
|
119
|
+
children: U
|
|
120
|
+
})
|
|
121
|
+
]
|
|
122
|
+
}),
|
|
123
|
+
C === "discrete" && /* @__PURE__ */ i("div", {
|
|
124
|
+
className: "dishui-slider-items",
|
|
125
|
+
"aria-hidden": "true",
|
|
126
|
+
children: Array.from({ length: I }, (e, t) => {
|
|
127
|
+
let n = Math.max(0, Math.min(1, W * I - t));
|
|
128
|
+
return /* @__PURE__ */ a("span", {
|
|
129
|
+
className: "dishui-slider-item",
|
|
130
|
+
children: [/* @__PURE__ */ i("svg", {
|
|
131
|
+
viewBox: "0 0 24 24",
|
|
132
|
+
children: /* @__PURE__ */ i("path", { d: l[T] })
|
|
133
|
+
}), /* @__PURE__ */ i("span", {
|
|
134
|
+
className: "dishui-slider-item-fill",
|
|
135
|
+
style: { clipPath: G ? `inset(${(1 - n) * 100}% 0 0 0)` : `inset(0 ${(1 - n) * 100}% 0 0)` },
|
|
136
|
+
children: /* @__PURE__ */ i("svg", {
|
|
137
|
+
viewBox: "0 0 24 24",
|
|
138
|
+
children: /* @__PURE__ */ i("path", { d: l[T] })
|
|
139
|
+
})
|
|
140
|
+
})]
|
|
141
|
+
}, t);
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
]
|
|
46
145
|
})]
|
|
47
146
|
});
|
|
147
|
+
}, l = {
|
|
148
|
+
square: "M3 3h18v18H3z",
|
|
149
|
+
star: "m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z",
|
|
150
|
+
heart: "M12 21 3.5 12.5C-3 6 6-2 12 5c6-7 15 1 8.5 7.5Z"
|
|
48
151
|
};
|
|
49
152
|
//#endregion
|
|
50
|
-
export {
|
|
153
|
+
export { c as default };
|
|
51
154
|
|
|
52
155
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Slider/index.tsx"],"sourcesContent":["import React, { useCallback, useState } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type SliderVariant =\n | 'default'\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'info'\n | 'success'\n | 'warning'\n | 'error';\n\nexport type SliderSize = 'xs' | 'sm' | 'md' | 'lg';\n\nexport type SliderProps = {\n /** Controlled value. */\n value?: number;\n /** Uncontrolled initial value. */\n defaultValue?: number;\n /** Minimum value. */\n min?: number;\n /** Maximum value. */\n max?: number;\n /** Step increment. */\n step?: number;\n /** Change handler with the numeric value. */\n onChange?: (value: number, e: React.ChangeEvent<HTMLInputElement>) => void;\n /** Optional label rendered above the track. */\n label?: React.ReactNode;\n /** Show the current value next to the label. */\n showValue?: boolean;\n /** Color variant (daisyUI). */\n variant?: SliderVariant;\n /** Size (daisyUI). */\n size?: SliderSize;\n /** Disabled state. */\n disabled?: boolean;\n /** Native name attribute. */\n name?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n /** Inline styles on the wrapper. */\n style?: React.CSSProperties;\n};\n\nconst VARIANT_CLASS: Record<SliderVariant, string> = {\n default: '',\n primary: 'range-primary',\n secondary: 'range-secondary',\n accent: 'range-accent',\n info: 'range-info',\n success: 'range-success',\n warning: 'range-warning',\n error: 'range-error',\n};\n\nconst SIZE_CLASS: Record<SliderSize, string> = {\n xs: 'range-xs',\n sm: 'range-sm',\n md: 'range-md',\n lg: 'range-lg',\n};\n\n/**\n * Slider —— A2UI 交互组件:滑动选择器(基于原生 range + daisyUI range)。\n * 支持受控 / 非受控、语义色、尺寸与当前值展示。\n */\nconst Slider: React.FC<SliderProps> = ({\n value,\n defaultValue,\n min = 0,\n max = 100,\n step = 1,\n onChange,\n label,\n showValue = false,\n variant = 'default',\n size = 'sm',\n disabled = false,\n name,\n className = '',\n style,\n}) => {\n const [internal, setInternal] = useState<number>(defaultValue ?? min);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const next = Number(e.target.value);\n if (!isControlled) setInternal(next);\n onChange?.(next, e);\n },\n [isControlled, onChange],\n );\n\n return (\n <div className={cn('w-full', className)} style={style}>\n {(label !== undefined || showValue) && (\n <div className=\"mb-1 flex items-center justify-between\">\n {label !== undefined && (\n <label className=\"label-text text-sm text-base-content/80\">{label}</label>\n )}\n {showValue && (\n <span className=\"text-xs font-mono text-base-content/60\">{current}</span>\n )}\n </div>\n )}\n <input\n type=\"range\"\n className={cn('range', VARIANT_CLASS[variant], SIZE_CLASS[size])}\n {...(isControlled\n ? { value: current }\n : { defaultValue: defaultValue ?? min })}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n name={name}\n onChange={handleChange}\n />\n </div>\n );\n};\n\nexport default Slider;\n"],"mappings":";;;;AA8CA,IAAM,IAA+C;CACnD,SAAS;CACT,SAAS;CACT,WAAW;CACX,QAAQ;CACR,MAAM;CACN,SAAS;CACT,SAAS;CACT,OAAO;AACT,GAEM,IAAyC;CAC7C,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAMM,KAAiC,EACrC,UACA,iBACA,SAAM,GACN,SAAM,KACN,UAAO,GACP,aACA,UACA,eAAY,IACZ,aAAU,WACV,UAAO,MACP,cAAW,IACX,SACA,eAAY,IACZ,eACI;CACJ,IAAM,CAAC,GAAU,KAAe,EAAiB,KAAgB,CAAG,GAC9D,IAAe,MAAU,KAAA,GACzB,IAAU,IAAe,IAAQ,GAEjC,IAAe,GAClB,MAA2C;EAC1C,IAAM,IAAO,OAAO,EAAE,OAAO,KAAK;EAElC,AADK,KAAc,EAAY,CAAI,GACnC,IAAW,GAAM,CAAC;CACpB,GACA,CAAC,GAAc,CAAQ,CACzB;CAEA,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,UAAU,CAAS;EAAU;EAAhD,UAAA,EACI,MAAU,KAAA,KAAa,MACvB,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,MAAU,KAAA,KACT,kBAAC,SAAD;IAAO,WAAU;IAA2C,UAAA;GAAa,CAAA,GAE1E,KACC,kBAAC,QAAD;IAAM,WAAU;IAA0C,UAAA;GAAc,CAAA,CAEvE;EAEP,CAAA,GAAA,kBAAC,SAAD;GACE,MAAK;GACL,WAAW,EAAG,SAAS,EAAc,IAAU,EAAW,EAAK;GAC/D,GAAK,IACD,EAAE,OAAO,EAAQ,IACjB,EAAE,cAAc,KAAgB,EAAI;GACnC;GACA;GACC;GACI;GACJ;GACN,UAAU;EACX,CAAA,CACE;;AAET"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Slider/index.tsx"],"sourcesContent":["import React, { useId, useRef, useState } from 'react';\nimport './Slider.css';\nimport { cn } from '../../utils/cn';\n\nexport type SliderVariant =\n | 'default'\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'info'\n | 'success'\n | 'warning'\n | 'error';\n\nexport type SliderSize = 'xs' | 'sm' | 'md' | 'lg';\n\nexport type SliderProps = {\n /** Linear remains the default. Circular starts at 12 o'clock, clockwise. */\n mode?: 'linear' | 'circular' | 'discrete';\n /** Applies to linear and discrete sliders. */\n orientation?: 'horizontal' | 'vertical';\n /** Discrete item shape and quantity (positive integer, defaults to 5). */\n shape?: 'square' | 'star' | 'heart';\n count?: number;\n /** Discrete increments: half an item instead of a whole item. */\n allowHalf?: boolean;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-valuetext'?: string;\n /** Controlled value. */\n value?: number;\n /** Uncontrolled initial value. */\n defaultValue?: number;\n /** Minimum value. */\n min?: number;\n /** Maximum value. */\n max?: number;\n /** Step increment for linear/circular modes; discrete derives it from count and allowHalf. */\n step?: number;\n /** Change handler with the numeric value. */\n onChange?: (value: number, e: React.ChangeEvent<HTMLInputElement>) => void;\n /** Optional label rendered above the track. */\n label?: React.ReactNode;\n /** Show the current value next to the label. */\n showValue?: boolean;\n /** Color variant (daisyUI). */\n variant?: SliderVariant;\n /** Size (daisyUI). */\n size?: SliderSize;\n /** Disabled state. */\n disabled?: boolean;\n /** Native name attribute. */\n name?: string;\n /** Extra class names on the wrapper. */\n className?: string;\n /** Inline styles on the wrapper. */\n style?: React.CSSProperties;\n};\n\nconst VARIANT_CLASS: Record<SliderVariant, string> = {\n default: '',\n primary: 'range-primary',\n secondary: 'range-secondary',\n accent: 'range-accent',\n info: 'range-info',\n success: 'range-success',\n warning: 'range-warning',\n error: 'range-error',\n};\n\nconst SIZE_CLASS: Record<SliderSize, string> = {\n xs: 'range-xs',\n sm: 'range-sm',\n md: 'range-md',\n lg: 'range-lg',\n};\n\n/**\n * Slider —— Native range semantics with linear, circular and discrete presentations.\n * Supports controlled/uncontrolled values, keyboard input and semantic colors.\n */\nconst Slider: React.FC<SliderProps> = ({\n value,\n defaultValue,\n min = 0,\n max: maxProp,\n step: stepProp,\n onChange,\n label,\n showValue = false,\n variant = 'default',\n size = 'sm',\n disabled = false,\n name,\n className = '',\n style,\n mode = 'linear',\n orientation = 'horizontal',\n shape = 'star',\n count = 5,\n allowHalf = false,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n 'aria-describedby': ariaDescribedby,\n 'aria-valuetext': ariaValueText,\n}) => {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const inputRef = useRef<HTMLInputElement>(null);\n const itemCount = Number.isFinite(count) ? Math.max(1, Math.floor(count)) : 5;\n const max = Math.max(min, maxProp ?? (mode === 'discrete' ? min + itemCount : 100));\n // Discrete steps are fractions of an item, even for a custom numeric range.\n const step = mode === 'discrete'\n ? (max - min) / itemCount / (allowHalf ? 2 : 1) || 1\n : stepProp !== undefined && Number.isFinite(stepProp) && stepProp > 0 ? stepProp : 1;\n const normalize = (n: number) => {\n const bounded = Math.min(max, Math.max(min, Number.isFinite(n) ? n : min));\n const ticks = Math.min(Math.round((bounded - min) / step), Math.floor((max - min) / step + 1e-10));\n return Number((min + ticks * step).toPrecision(15));\n };\n const [internal, setInternal] = useState<number>(defaultValue ?? min);\n const isControlled = value !== undefined;\n const current = normalize(isControlled ? value : internal);\n const ratio = max > min ? (current - min) / (max - min) : 0;\n const vertical = orientation === 'vertical' && mode !== 'circular';\n const custom = mode !== 'linear';\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (disabled) return;\n const next = normalize(Number(e.target.value));\n if (!isControlled) setInternal(next);\n onChange?.(next, e);\n };\n const updatePointer = (e: React.PointerEvent<HTMLDivElement>) => {\n const input = inputRef.current;\n if (disabled || !input || max === min) return;\n const rect = e.currentTarget.getBoundingClientRect();\n let fraction = vertical ? (rect.bottom - e.clientY) / rect.height : (e.clientX - rect.left) / rect.width;\n if (mode === 'circular') {\n const dx = e.clientX - rect.left - rect.width / 2;\n const dy = e.clientY - rect.top - rect.height / 2;\n if (Math.hypot(dx, dy) < rect.width * 0.15) return;\n fraction = (Math.atan2(dx, -dy) + Math.PI * 2) % (Math.PI * 2) / (Math.PI * 2);\n // Keep dragging across the seam at the nearest endpoint, not a full-range jump.\n if (Math.abs(fraction - ratio) > 0.5 && e.type === 'pointermove') fraction = ratio > 0.5 ? 1 : 0;\n }\n const next = normalize(min + Math.min(1, Math.max(0, fraction)) * (max - min));\n if (next === current) return;\n // Dispatch through the native input so consumers receive a real React change event.\n Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')?.set?.call(input, String(next));\n input.dispatchEvent(new Event('input', { bubbles: true }));\n };\n\n return (\n <div className={cn('w-full dishui-slider', className)} style={style} data-mode={mode} data-orientation={orientation} data-size={size} data-variant={variant} data-disabled={disabled}>\n {(label !== undefined || showValue) && (\n <div className=\"mb-1 flex items-center justify-between\">\n {label !== undefined && (\n <label htmlFor={inputId} className=\"label-text text-sm text-base-content/80\">{label}</label>\n )}\n {showValue && (\n <span className=\"text-xs font-mono text-base-content/60\">{current}</span>\n )}\n </div>\n )}\n <div className=\"dishui-slider-control\"\n onPointerDown={custom ? e => {\n if (disabled || e.button !== 0) return;\n e.preventDefault();\n inputRef.current?.focus();\n e.currentTarget.setPointerCapture(e.pointerId);\n updatePointer(e);\n } : undefined}\n onPointerMove={custom ? e => { if (e.currentTarget.hasPointerCapture(e.pointerId)) updatePointer(e); } : undefined}\n onPointerUp={custom ? e => { if (e.currentTarget.hasPointerCapture(e.pointerId)) e.currentTarget.releasePointerCapture(e.pointerId); } : undefined}\n >\n <input\n ref={inputRef}\n id={inputId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n aria-describedby={ariaDescribedby}\n aria-valuetext={ariaValueText}\n aria-orientation={vertical ? 'vertical' : 'horizontal'}\n type=\"range\"\n className={cn('range', VARIANT_CLASS[variant], SIZE_CLASS[size])}\n value={current}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n name={name}\n onChange={handleChange}\n />\n {mode === 'circular' && <svg className=\"dishui-slider-dial\" viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n <circle className=\"dishui-slider-ring\" cx=\"50\" cy=\"50\" r=\"40\" />\n <circle className=\"dishui-slider-progress\" cx=\"50\" cy=\"50\" r=\"40\" pathLength=\"100\" strokeDasharray={`${ratio * 100} 100`} transform=\"rotate(-90 50 50)\" />\n <circle className=\"dishui-slider-thumb\" cx={50 + 40 * Math.sin(ratio * Math.PI * 2)} cy={50 - 40 * Math.cos(ratio * Math.PI * 2)} r=\"5\" />\n <text x=\"50\" y=\"50\" dominantBaseline=\"central\" textAnchor=\"middle\">{current}</text>\n </svg>}\n {mode === 'discrete' && <div className=\"dishui-slider-items\" aria-hidden=\"true\">\n {Array.from({ length: itemCount }, (_, index) => {\n const fill = Math.max(0, Math.min(1, ratio * itemCount - index));\n return <span className=\"dishui-slider-item\" key={index}>\n <svg viewBox=\"0 0 24 24\"><path d={SHAPES[shape]} /></svg>\n <span className=\"dishui-slider-item-fill\" style={{ clipPath: vertical ? `inset(${(1 - fill) * 100}% 0 0 0)` : `inset(0 ${(1 - fill) * 100}% 0 0)` }}>\n <svg viewBox=\"0 0 24 24\"><path d={SHAPES[shape]} /></svg>\n </span>\n </span>;\n })}\n </div>}\n </div>\n </div>\n );\n};\n\nconst SHAPES = {\n square: 'M3 3h18v18H3z',\n star: 'm12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z',\n heart: 'M12 21 3.5 12.5C-3 6 6-2 12 5c6-7 15 1 8.5 7.5Z',\n};\n\nexport default Slider;\n"],"mappings":"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"}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import { cn as e } from "../../../utils/cn.js";
|
|
2
2
|
import { MarkdownBlockExtension as t } from "./extensions/MarkdownBlock.js";
|
|
3
3
|
import { FloatingDialogExtension as n } from "./extensions/FloatingDialog.js";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import { CodeBlockExtension as
|
|
14
|
-
import
|
|
4
|
+
import r from "./Toolbar/Toolbar.js";
|
|
5
|
+
import i from "./AIRewrite.js";
|
|
6
|
+
import a from "./ContextMenu.js";
|
|
7
|
+
import o from "./CommentPanel.js";
|
|
8
|
+
import s from "./CommentDialog.js";
|
|
9
|
+
import c from "./CommentPopover.js";
|
|
10
|
+
import l from "./SlashMenu.js";
|
|
11
|
+
import ee from "./BubbleToolbar.js";
|
|
12
|
+
import te from "./BlockHandle.js";
|
|
13
|
+
import { CodeBlockExtension as ne } from "./extensions/CodeBlockView.js";
|
|
14
|
+
import re from "./extensions/FontSize.js";
|
|
15
|
+
import { ResizableImage as ie } from "./extensions/ResizableImage.js";
|
|
15
16
|
import { CommentMark as ae } from "./extensions/CommentMark.js";
|
|
16
17
|
/* empty css */
|
|
17
|
-
import { useCallback as
|
|
18
|
-
import { jsx as
|
|
19
|
-
import { EditorContent as
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import { TextStyle as
|
|
23
|
-
import
|
|
24
|
-
import
|
|
25
|
-
import
|
|
26
|
-
import
|
|
27
|
-
import he from "@tiptap/extension-image";
|
|
18
|
+
import { useCallback as u, useEffect as d, useRef as oe, useState as f } from "react";
|
|
19
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
20
|
+
import { EditorContent as se, useEditor as ce } from "@tiptap/react";
|
|
21
|
+
import le from "@tiptap/starter-kit";
|
|
22
|
+
import ue from "@tiptap/extension-underline";
|
|
23
|
+
import { TextStyle as de } from "@tiptap/extension-text-style";
|
|
24
|
+
import fe from "@tiptap/extension-color";
|
|
25
|
+
import pe from "@tiptap/extension-highlight";
|
|
26
|
+
import me from "@tiptap/extension-text-align";
|
|
27
|
+
import he from "@tiptap/extension-link";
|
|
28
28
|
import { Table as ge } from "@tiptap/extension-table";
|
|
29
29
|
import _e from "@tiptap/extension-table-row";
|
|
30
30
|
import ve from "@tiptap/extension-table-cell";
|
|
@@ -41,15 +41,15 @@ function C() {
|
|
|
41
41
|
return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
42
42
|
}
|
|
43
43
|
var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O = "Start writing...", editable: k = !0, aiConfig: A, toolbarConfig: j, minHeight: M = "200px", maxHeight: N, className: P = "", autofocus: F = !1, labels: I, editorRef: L, notionMode: R = !1, showComments: ye = !1, commentThreads: be, onCommentThreadsChange: xe, currentUser: z }) => {
|
|
44
|
-
let [Se, Ce] =
|
|
44
|
+
let [Se, Ce] = f(!1), [we, B] = f(!1), [Te, Ee] = f(""), [De, Oe] = f({
|
|
45
45
|
from: 0,
|
|
46
46
|
to: 0
|
|
47
|
-
}), [V, H] =
|
|
47
|
+
}), [V, H] = f(R), [U, W] = f(ye), [ke, Ae] = f([]), [je, G] = f(!1), [K, Me] = f({
|
|
48
48
|
from: 0,
|
|
49
49
|
to: 0
|
|
50
|
-
}), q = oe(null), J = be ?? ke, Y = xe ?? Ae, X =
|
|
50
|
+
}), q = oe(null), J = be ?? ke, Y = xe ?? Ae, X = ce({
|
|
51
51
|
extensions: [
|
|
52
|
-
|
|
52
|
+
le.configure({
|
|
53
53
|
codeBlock: !1,
|
|
54
54
|
heading: { levels: [
|
|
55
55
|
1,
|
|
@@ -62,17 +62,17 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
|
|
|
62
62
|
link: !1,
|
|
63
63
|
underline: !1
|
|
64
64
|
}),
|
|
65
|
-
le,
|
|
66
65
|
ue,
|
|
67
66
|
de,
|
|
68
|
-
fe
|
|
69
|
-
pe.configure({
|
|
70
|
-
me.configure({
|
|
67
|
+
fe,
|
|
68
|
+
pe.configure({ multicolor: !0 }),
|
|
69
|
+
me.configure({ types: ["heading", "paragraph"] }),
|
|
70
|
+
he.configure({
|
|
71
71
|
openOnClick: !1,
|
|
72
72
|
autolink: !0,
|
|
73
73
|
HTMLAttributes: { class: "rte-link" }
|
|
74
74
|
}),
|
|
75
|
-
|
|
75
|
+
ie.configure({
|
|
76
76
|
inline: !1,
|
|
77
77
|
allowBase64: !0
|
|
78
78
|
}),
|
|
@@ -81,14 +81,14 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
|
|
|
81
81
|
ve,
|
|
82
82
|
h,
|
|
83
83
|
g.configure({ placeholder: O }),
|
|
84
|
-
|
|
84
|
+
ne,
|
|
85
85
|
_,
|
|
86
86
|
v.configure({ nested: !0 }),
|
|
87
87
|
y,
|
|
88
88
|
b,
|
|
89
89
|
x,
|
|
90
90
|
S,
|
|
91
|
-
|
|
91
|
+
re,
|
|
92
92
|
n,
|
|
93
93
|
t,
|
|
94
94
|
ae
|
|
@@ -100,28 +100,28 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
|
|
|
100
100
|
E?.(e.getHTML()), D?.(e.getJSON());
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
|
-
|
|
103
|
+
d(() => {
|
|
104
104
|
L && X && (L.current = X);
|
|
105
|
-
}, [X, L]),
|
|
105
|
+
}, [X, L]), d(() => {
|
|
106
106
|
X && T !== void 0 && T !== X.getHTML() && X.commands.setContent(T, { emitUpdate: !1 });
|
|
107
|
-
}, [X, T]),
|
|
107
|
+
}, [X, T]), d(() => {
|
|
108
108
|
X && X.setEditable(k);
|
|
109
109
|
}, [X, k]);
|
|
110
|
-
let Z =
|
|
110
|
+
let Z = u(() => {
|
|
111
111
|
if (!X) return;
|
|
112
112
|
let { from: e, to: t } = X.state.selection, n = e === t ? "" : X.state.doc.textBetween(e, t, " ");
|
|
113
113
|
Ee(n), Oe({
|
|
114
114
|
from: e,
|
|
115
115
|
to: t
|
|
116
116
|
}), B(!0);
|
|
117
|
-
}, [X]), Q =
|
|
117
|
+
}, [X]), Q = u(() => {
|
|
118
118
|
if (!X) return;
|
|
119
119
|
let { from: e, to: t } = X.state.selection;
|
|
120
120
|
e !== t && (Me({
|
|
121
121
|
from: e,
|
|
122
122
|
to: t
|
|
123
123
|
}), G(!0));
|
|
124
|
-
}, [X]), Ne =
|
|
124
|
+
}, [X]), Ne = u((e) => {
|
|
125
125
|
if (!X) return;
|
|
126
126
|
let t = C(), n = {
|
|
127
127
|
id: t,
|
|
@@ -141,40 +141,40 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
|
|
|
141
141
|
J,
|
|
142
142
|
Y,
|
|
143
143
|
z
|
|
144
|
-
]), Pe =
|
|
144
|
+
]), Pe = u((e) => {
|
|
145
145
|
q.current?.scrollToThread(e);
|
|
146
146
|
}, []);
|
|
147
147
|
if (!X) return null;
|
|
148
|
-
let Fe = typeof M == "number" ? `${M}px` : M, Ie = N ? typeof N == "number" ? `${N}px` : N : void 0, Le = e("rte-container", Se && "rte-container--format-painter", V && "rte-container--notion", P), Re = J.filter((e) => !e.resolved).length, $ = /* @__PURE__ */
|
|
148
|
+
let Fe = typeof M == "number" ? `${M}px` : M, Ie = N ? typeof N == "number" ? `${N}px` : N : void 0, Le = e("rte-container", Se && "rte-container--format-painter", V && "rte-container--notion", P), Re = J.filter((e) => !e.resolved).length, $ = /* @__PURE__ */ m("div", {
|
|
149
149
|
className: "rte-mode-toggle",
|
|
150
150
|
children: [
|
|
151
|
-
/* @__PURE__ */
|
|
151
|
+
/* @__PURE__ */ p("button", {
|
|
152
152
|
type: "button",
|
|
153
153
|
className: `rte-mode-toggle__btn ${V ? "" : "rte-mode-toggle__btn--active"}`,
|
|
154
154
|
onClick: () => H(!1),
|
|
155
155
|
title: "Classic mode",
|
|
156
156
|
children: "Classic"
|
|
157
157
|
}),
|
|
158
|
-
/* @__PURE__ */
|
|
158
|
+
/* @__PURE__ */ p("button", {
|
|
159
159
|
type: "button",
|
|
160
160
|
className: `rte-mode-toggle__btn ${V ? "rte-mode-toggle__btn--active" : ""}`,
|
|
161
161
|
onClick: () => H(!0),
|
|
162
162
|
title: "Notion-style mode",
|
|
163
163
|
children: "Notion"
|
|
164
164
|
}),
|
|
165
|
-
/* @__PURE__ */
|
|
165
|
+
/* @__PURE__ */ p("div", {
|
|
166
166
|
className: "rte-toolbar__divider",
|
|
167
167
|
style: {
|
|
168
168
|
height: 20,
|
|
169
169
|
margin: "0 4px"
|
|
170
170
|
}
|
|
171
171
|
}),
|
|
172
|
-
/* @__PURE__ */
|
|
172
|
+
/* @__PURE__ */ m("button", {
|
|
173
173
|
type: "button",
|
|
174
174
|
className: `rte-toolbar__btn rte-toolbar__comment-btn ${U ? "rte-toolbar__btn--active" : ""}`,
|
|
175
175
|
onClick: () => W(!U),
|
|
176
176
|
title: "Toggle comments",
|
|
177
|
-
children: [/* @__PURE__ */
|
|
177
|
+
children: [/* @__PURE__ */ p("svg", {
|
|
178
178
|
width: "16",
|
|
179
179
|
height: "16",
|
|
180
180
|
viewBox: "0 0 24 24",
|
|
@@ -183,19 +183,19 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
|
|
|
183
183
|
strokeWidth: "2",
|
|
184
184
|
strokeLinecap: "round",
|
|
185
185
|
strokeLinejoin: "round",
|
|
186
|
-
children: /* @__PURE__ */
|
|
187
|
-
}), Re > 0 && /* @__PURE__ */
|
|
186
|
+
children: /* @__PURE__ */ p("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" })
|
|
187
|
+
}), Re > 0 && /* @__PURE__ */ p("span", { className: "rte-toolbar__comment-badge" })]
|
|
188
188
|
})
|
|
189
189
|
]
|
|
190
190
|
});
|
|
191
|
-
return /* @__PURE__ */
|
|
191
|
+
return /* @__PURE__ */ m("div", {
|
|
192
192
|
className: Le,
|
|
193
193
|
style: {
|
|
194
194
|
minHeight: Fe,
|
|
195
195
|
maxHeight: Ie
|
|
196
196
|
},
|
|
197
197
|
children: [
|
|
198
|
-
k && !V && /* @__PURE__ */
|
|
198
|
+
k && !V && /* @__PURE__ */ p(r, {
|
|
199
199
|
editor: X,
|
|
200
200
|
config: j,
|
|
201
201
|
labels: I,
|
|
@@ -204,36 +204,36 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
|
|
|
204
204
|
onFormatPainterChange: Ce,
|
|
205
205
|
children: $
|
|
206
206
|
}),
|
|
207
|
-
k && V && /* @__PURE__ */
|
|
207
|
+
k && V && /* @__PURE__ */ p("div", {
|
|
208
208
|
className: "rte-notion-topbar",
|
|
209
209
|
children: $
|
|
210
210
|
}),
|
|
211
|
-
/* @__PURE__ */
|
|
211
|
+
/* @__PURE__ */ m("div", {
|
|
212
212
|
style: {
|
|
213
213
|
display: "flex",
|
|
214
214
|
flex: 1,
|
|
215
215
|
overflow: "hidden"
|
|
216
216
|
},
|
|
217
|
-
children: [/* @__PURE__ */
|
|
217
|
+
children: [/* @__PURE__ */ m("div", {
|
|
218
218
|
className: "rte-editor-wrapper",
|
|
219
219
|
style: { flex: 1 },
|
|
220
220
|
children: [
|
|
221
|
-
/* @__PURE__ */
|
|
221
|
+
/* @__PURE__ */ p(se, {
|
|
222
222
|
editor: X,
|
|
223
223
|
className: "rte-editor-content"
|
|
224
224
|
}),
|
|
225
|
-
k && /* @__PURE__ */
|
|
225
|
+
k && /* @__PURE__ */ p(a, {
|
|
226
226
|
editor: X,
|
|
227
227
|
labels: I,
|
|
228
228
|
onAIClick: A ? Z : void 0
|
|
229
229
|
}),
|
|
230
|
-
k && /* @__PURE__ */
|
|
231
|
-
k && V && /* @__PURE__ */
|
|
230
|
+
k && /* @__PURE__ */ p(l, { editor: X }),
|
|
231
|
+
k && V && /* @__PURE__ */ p(ee, {
|
|
232
232
|
editor: X,
|
|
233
233
|
onAddComment: Q
|
|
234
234
|
}),
|
|
235
|
-
k && V && /* @__PURE__ */
|
|
236
|
-
/* @__PURE__ */
|
|
235
|
+
k && V && /* @__PURE__ */ p(te, { editor: X }),
|
|
236
|
+
/* @__PURE__ */ p(c, {
|
|
237
237
|
editor: X,
|
|
238
238
|
threads: J,
|
|
239
239
|
onThreadsChange: Y,
|
|
@@ -243,7 +243,7 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
|
|
|
243
243
|
currentUser: z
|
|
244
244
|
})
|
|
245
245
|
]
|
|
246
|
-
}), U && /* @__PURE__ */
|
|
246
|
+
}), U && /* @__PURE__ */ p(o, {
|
|
247
247
|
ref: q,
|
|
248
248
|
editor: X,
|
|
249
249
|
threads: J,
|
|
@@ -252,7 +252,7 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
|
|
|
252
252
|
currentUser: z
|
|
253
253
|
})]
|
|
254
254
|
}),
|
|
255
|
-
A && we && /* @__PURE__ */
|
|
255
|
+
A && we && /* @__PURE__ */ p(i, {
|
|
256
256
|
editor: X,
|
|
257
257
|
aiConfig: A,
|
|
258
258
|
labels: I,
|
|
@@ -260,7 +260,7 @@ var w = ({ content: w, value: T, onChange: E, onChangeJSON: D, placeholder: O =
|
|
|
260
260
|
selectionRange: De,
|
|
261
261
|
onClose: () => B(!1)
|
|
262
262
|
}),
|
|
263
|
-
/* @__PURE__ */
|
|
263
|
+
/* @__PURE__ */ p(s, {
|
|
264
264
|
open: je,
|
|
265
265
|
onSubmit: Ne,
|
|
266
266
|
onClose: () => G(!1)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditor.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/RichTextEditor.tsx"],"sourcesContent":["import React, { useEffect, useCallback, useState, useRef } from 'react';\nimport { cn } from '../../../utils/cn';\nimport { useEditor, EditorContent } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport Underline from '@tiptap/extension-underline';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport Color from '@tiptap/extension-color';\nimport Highlight from '@tiptap/extension-highlight';\nimport TextAlign from '@tiptap/extension-text-align';\nimport Link from '@tiptap/extension-link';\nimport Image from '@tiptap/extension-image';\nimport { Table } from '@tiptap/extension-table';\nimport TableRow from '@tiptap/extension-table-row';\nimport TableCell from '@tiptap/extension-table-cell';\nimport TableHeader from '@tiptap/extension-table-header';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport TaskList from '@tiptap/extension-task-list';\nimport TaskItem from '@tiptap/extension-task-item';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport Typography from '@tiptap/extension-typography';\nimport FontFamily from '@tiptap/extension-font-family';\n\nimport Toolbar from './Toolbar';\nimport AIRewrite from './AIRewrite';\nimport ContextMenu from './ContextMenu';\nimport CommentPanel from './CommentPanel';\nimport type { CommentPanelHandle } from './CommentPanel';\nimport CommentDialog from './CommentDialog';\nimport CommentPopover from './CommentPopover';\nimport SlashMenu from './SlashMenu';\nimport BubbleToolbar from './BubbleToolbar';\nimport BlockHandle from './BlockHandle';\nimport { MarkdownBlockExtension } from './extensions/MarkdownBlock';\nimport { CodeBlockExtension } from './extensions/CodeBlockView';\nimport FontSize from './extensions/FontSize';\nimport { FloatingDialogExtension } from './extensions/FloatingDialog';\nimport { CommentMark } from './extensions/CommentMark';\nimport type { CommentThread } from './extensions/CommentMark';\nimport type { RichTextEditorProps } from './types';\nimport './styles.css';\n\nfunction generateId() {\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\nconst RichTextEditor: React.FC<RichTextEditorProps> = ({\n content,\n value,\n onChange,\n onChangeJSON,\n placeholder = 'Start writing...',\n editable = true,\n aiConfig,\n toolbarConfig,\n minHeight = '200px',\n maxHeight,\n className = '',\n autofocus = false,\n labels,\n editorRef,\n notionMode: initialNotionMode = false,\n showComments: initialShowComments = false,\n commentThreads: externalThreads,\n onCommentThreadsChange,\n currentUser,\n}) => {\n const [formatPainterActive, setFormatPainterActive] = useState(false);\n const [showAIPanel, setShowAIPanel] = useState(false);\n const [aiSelection, setAiSelection] = useState('');\n const [aiSelectionRange, setAiSelectionRange] = useState({ from: 0, to: 0 });\n const [notionMode, setNotionMode] = useState(initialNotionMode);\n const [showComments, setShowComments] = useState(initialShowComments);\n const [internalThreads, setInternalThreads] = useState<CommentThread[]>([]);\n const [commentDialogOpen, setCommentDialogOpen] = useState(false);\n const [commentSelectionRange, setCommentSelectionRange] = useState({ from: 0, to: 0 });\n const commentPanelRef = useRef<CommentPanelHandle>(null);\n\n const threads = externalThreads ?? internalThreads;\n const setThreads = onCommentThreadsChange ?? setInternalThreads;\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n codeBlock: false,\n heading: { levels: [1, 2, 3, 4, 5, 6] },\n // v3 StarterKit bundles these; explicit extensions below stay in charge.\n link: false,\n underline: false,\n }),\n Underline,\n TextStyle,\n Color,\n Highlight.configure({ multicolor: true }),\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Link.configure({\n openOnClick: false,\n autolink: true,\n HTMLAttributes: { class: 'rte-link' },\n }),\n Image.configure({ inline: false, allowBase64: true }),\n Table.configure({ resizable: true }),\n TableRow,\n TableCell,\n TableHeader,\n Placeholder.configure({ placeholder }),\n CodeBlockExtension,\n TaskList,\n TaskItem.configure({ nested: true }),\n Subscript,\n Superscript,\n Typography,\n FontFamily,\n FontSize,\n FloatingDialogExtension,\n MarkdownBlockExtension,\n CommentMark,\n ],\n content: value || content || '',\n editable,\n autofocus: autofocus ? 'end' : false,\n onUpdate: ({ editor: e }) => {\n onChange?.(e.getHTML());\n onChangeJSON?.(e.getJSON() as Record<string, unknown>);\n },\n });\n\n useEffect(() => {\n if (editorRef && editor) {\n editorRef.current = editor;\n }\n }, [editor, editorRef]);\n\n useEffect(() => {\n if (editor && value !== undefined) {\n const currentHTML = editor.getHTML();\n if (value !== currentHTML) {\n editor.commands.setContent(value, { emitUpdate: false });\n }\n }\n }, [editor, value]);\n\n useEffect(() => {\n if (editor) {\n editor.setEditable(editable);\n }\n }, [editor, editable]);\n\n const handleAIClick = useCallback(() => {\n if (!editor) return;\n const { from, to } = editor.state.selection;\n const text = from !== to\n ? editor.state.doc.textBetween(from, to, ' ')\n : '';\n setAiSelection(text);\n setAiSelectionRange({ from, to });\n setShowAIPanel(true);\n }, [editor]);\n\n const requestAddComment = useCallback(() => {\n if (!editor) return;\n const { from, to } = editor.state.selection;\n if (from === to) return;\n setCommentSelectionRange({ from, to });\n setCommentDialogOpen(true);\n }, [editor]);\n\n const handleCommentSubmit = useCallback((text: string) => {\n if (!editor) return;\n const id = generateId();\n const thread: CommentThread = {\n id,\n resolved: false,\n comments: [{\n id: generateId(),\n author: currentUser || 'User',\n text,\n createdAt: Date.now(),\n }],\n createdAt: Date.now(),\n };\n editor.chain()\n .focus()\n .setTextSelection(commentSelectionRange)\n .setComment(id)\n .run();\n setThreads([...threads, thread]);\n setCommentDialogOpen(false);\n }, [editor, commentSelectionRange, threads, setThreads, currentUser]);\n\n const handleScrollToThread = useCallback((id: string) => {\n commentPanelRef.current?.scrollToThread(id);\n }, []);\n\n if (!editor) return null;\n\n const minH = typeof minHeight === 'number' ? `${minHeight}px` : minHeight;\n const maxH = maxHeight ? (typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight) : undefined;\n\n const containerClass = cn(\n 'rte-container',\n formatPainterActive && 'rte-container--format-painter',\n notionMode && 'rte-container--notion',\n className,\n );\n\n const activeCommentCount = threads.filter((t) => !t.resolved).length;\n\n const modeToggle = (\n <div className=\"rte-mode-toggle\">\n <button\n type=\"button\"\n className={`rte-mode-toggle__btn ${!notionMode ? 'rte-mode-toggle__btn--active' : ''}`}\n onClick={() => setNotionMode(false)}\n title=\"Classic mode\"\n >\n Classic\n </button>\n <button\n type=\"button\"\n className={`rte-mode-toggle__btn ${notionMode ? 'rte-mode-toggle__btn--active' : ''}`}\n onClick={() => setNotionMode(true)}\n title=\"Notion-style mode\"\n >\n Notion\n </button>\n <div className=\"rte-toolbar__divider\" style={{ height: 20, margin: '0 4px' }} />\n <button\n type=\"button\"\n className={`rte-toolbar__btn rte-toolbar__comment-btn ${showComments ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setShowComments(!showComments)}\n title=\"Toggle comments\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" />\n </svg>\n {activeCommentCount > 0 && <span className=\"rte-toolbar__comment-badge\" />}\n </button>\n </div>\n );\n\n return (\n <div className={containerClass} style={{ minHeight: minH, maxHeight: maxH }}>\n {editable && !notionMode && (\n <Toolbar\n editor={editor}\n config={toolbarConfig}\n labels={labels}\n hasAI={!!aiConfig}\n onAIClick={handleAIClick}\n onFormatPainterChange={setFormatPainterActive}\n >\n {modeToggle}\n </Toolbar>\n )}\n\n {editable && notionMode && (\n <div className=\"rte-notion-topbar\">\n {modeToggle}\n </div>\n )}\n\n <div style={{ display: 'flex', flex: 1, overflow: 'hidden' }}>\n <div className=\"rte-editor-wrapper\" style={{ flex: 1 }}>\n <EditorContent editor={editor} className=\"rte-editor-content\" />\n {editable && <ContextMenu editor={editor} labels={labels} onAIClick={aiConfig ? handleAIClick : undefined} />}\n {editable && <SlashMenu editor={editor} />}\n {editable && notionMode && <BubbleToolbar editor={editor} onAddComment={requestAddComment} />}\n {editable && notionMode && <BlockHandle editor={editor} />}\n <CommentPopover\n editor={editor}\n threads={threads}\n onThreadsChange={setThreads}\n showPanel={showComments}\n onOpenPanel={() => setShowComments(true)}\n onScrollToThread={handleScrollToThread}\n currentUser={currentUser}\n />\n </div>\n\n {showComments && (\n <CommentPanel\n ref={commentPanelRef}\n editor={editor}\n threads={threads}\n onThreadsChange={setThreads}\n onRequestAddComment={requestAddComment}\n currentUser={currentUser}\n />\n )}\n </div>\n\n {aiConfig && showAIPanel && (\n <AIRewrite\n editor={editor}\n aiConfig={aiConfig}\n labels={labels}\n initialSelection={aiSelection}\n selectionRange={aiSelectionRange}\n onClose={() => setShowAIPanel(false)}\n />\n )}\n\n <CommentDialog\n open={commentDialogOpen}\n onSubmit={handleCommentSubmit}\n onClose={() => setCommentDialogOpen(false)}\n />\n </div>\n );\n};\n\nexport default RichTextEditor;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RichTextEditor.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/RichTextEditor.tsx"],"sourcesContent":["import React, { useEffect, useCallback, useState, useRef } from 'react';\nimport { cn } from '../../../utils/cn';\nimport { useEditor, EditorContent } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport Underline from '@tiptap/extension-underline';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport Color from '@tiptap/extension-color';\nimport Highlight from '@tiptap/extension-highlight';\nimport TextAlign from '@tiptap/extension-text-align';\nimport Link from '@tiptap/extension-link';\nimport { Table } from '@tiptap/extension-table';\nimport TableRow from '@tiptap/extension-table-row';\nimport TableCell from '@tiptap/extension-table-cell';\nimport TableHeader from '@tiptap/extension-table-header';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport TaskList from '@tiptap/extension-task-list';\nimport TaskItem from '@tiptap/extension-task-item';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport Typography from '@tiptap/extension-typography';\nimport FontFamily from '@tiptap/extension-font-family';\n\nimport Toolbar from './Toolbar';\nimport AIRewrite from './AIRewrite';\nimport ContextMenu from './ContextMenu';\nimport CommentPanel from './CommentPanel';\nimport type { CommentPanelHandle } from './CommentPanel';\nimport CommentDialog from './CommentDialog';\nimport CommentPopover from './CommentPopover';\nimport SlashMenu from './SlashMenu';\nimport BubbleToolbar from './BubbleToolbar';\nimport BlockHandle from './BlockHandle';\nimport { MarkdownBlockExtension } from './extensions/MarkdownBlock';\nimport { CodeBlockExtension } from './extensions/CodeBlockView';\nimport FontSize from './extensions/FontSize';\nimport { ResizableImage } from './extensions/ResizableImage';\nimport { FloatingDialogExtension } from './extensions/FloatingDialog';\nimport { CommentMark } from './extensions/CommentMark';\nimport type { CommentThread } from './extensions/CommentMark';\nimport type { RichTextEditorProps } from './types';\nimport './styles.css';\n\nfunction generateId() {\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\nconst RichTextEditor: React.FC<RichTextEditorProps> = ({\n content,\n value,\n onChange,\n onChangeJSON,\n placeholder = 'Start writing...',\n editable = true,\n aiConfig,\n toolbarConfig,\n minHeight = '200px',\n maxHeight,\n className = '',\n autofocus = false,\n labels,\n editorRef,\n notionMode: initialNotionMode = false,\n showComments: initialShowComments = false,\n commentThreads: externalThreads,\n onCommentThreadsChange,\n currentUser,\n}) => {\n const [formatPainterActive, setFormatPainterActive] = useState(false);\n const [showAIPanel, setShowAIPanel] = useState(false);\n const [aiSelection, setAiSelection] = useState('');\n const [aiSelectionRange, setAiSelectionRange] = useState({ from: 0, to: 0 });\n const [notionMode, setNotionMode] = useState(initialNotionMode);\n const [showComments, setShowComments] = useState(initialShowComments);\n const [internalThreads, setInternalThreads] = useState<CommentThread[]>([]);\n const [commentDialogOpen, setCommentDialogOpen] = useState(false);\n const [commentSelectionRange, setCommentSelectionRange] = useState({ from: 0, to: 0 });\n const commentPanelRef = useRef<CommentPanelHandle>(null);\n\n const threads = externalThreads ?? internalThreads;\n const setThreads = onCommentThreadsChange ?? setInternalThreads;\n\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n codeBlock: false,\n heading: { levels: [1, 2, 3, 4, 5, 6] },\n // v3 StarterKit bundles these; explicit extensions below stay in charge.\n link: false,\n underline: false,\n }),\n Underline,\n TextStyle,\n Color,\n Highlight.configure({ multicolor: true }),\n TextAlign.configure({\n types: ['heading', 'paragraph'],\n }),\n Link.configure({\n openOnClick: false,\n autolink: true,\n HTMLAttributes: { class: 'rte-link' },\n }),\n ResizableImage.configure({ inline: false, allowBase64: true }),\n Table.configure({ resizable: true }),\n TableRow,\n TableCell,\n TableHeader,\n Placeholder.configure({ placeholder }),\n CodeBlockExtension,\n TaskList,\n TaskItem.configure({ nested: true }),\n Subscript,\n Superscript,\n Typography,\n FontFamily,\n FontSize,\n FloatingDialogExtension,\n MarkdownBlockExtension,\n CommentMark,\n ],\n content: value || content || '',\n editable,\n autofocus: autofocus ? 'end' : false,\n onUpdate: ({ editor: e }) => {\n onChange?.(e.getHTML());\n onChangeJSON?.(e.getJSON() as Record<string, unknown>);\n },\n });\n\n useEffect(() => {\n if (editorRef && editor) {\n editorRef.current = editor;\n }\n }, [editor, editorRef]);\n\n useEffect(() => {\n if (editor && value !== undefined) {\n const currentHTML = editor.getHTML();\n if (value !== currentHTML) {\n editor.commands.setContent(value, { emitUpdate: false });\n }\n }\n }, [editor, value]);\n\n useEffect(() => {\n if (editor) {\n editor.setEditable(editable);\n }\n }, [editor, editable]);\n\n const handleAIClick = useCallback(() => {\n if (!editor) return;\n const { from, to } = editor.state.selection;\n const text = from !== to\n ? editor.state.doc.textBetween(from, to, ' ')\n : '';\n setAiSelection(text);\n setAiSelectionRange({ from, to });\n setShowAIPanel(true);\n }, [editor]);\n\n const requestAddComment = useCallback(() => {\n if (!editor) return;\n const { from, to } = editor.state.selection;\n if (from === to) return;\n setCommentSelectionRange({ from, to });\n setCommentDialogOpen(true);\n }, [editor]);\n\n const handleCommentSubmit = useCallback((text: string) => {\n if (!editor) return;\n const id = generateId();\n const thread: CommentThread = {\n id,\n resolved: false,\n comments: [{\n id: generateId(),\n author: currentUser || 'User',\n text,\n createdAt: Date.now(),\n }],\n createdAt: Date.now(),\n };\n editor.chain()\n .focus()\n .setTextSelection(commentSelectionRange)\n .setComment(id)\n .run();\n setThreads([...threads, thread]);\n setCommentDialogOpen(false);\n }, [editor, commentSelectionRange, threads, setThreads, currentUser]);\n\n const handleScrollToThread = useCallback((id: string) => {\n commentPanelRef.current?.scrollToThread(id);\n }, []);\n\n if (!editor) return null;\n\n const minH = typeof minHeight === 'number' ? `${minHeight}px` : minHeight;\n const maxH = maxHeight ? (typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight) : undefined;\n\n const containerClass = cn(\n 'rte-container',\n formatPainterActive && 'rte-container--format-painter',\n notionMode && 'rte-container--notion',\n className,\n );\n\n const activeCommentCount = threads.filter((t) => !t.resolved).length;\n\n const modeToggle = (\n <div className=\"rte-mode-toggle\">\n <button\n type=\"button\"\n className={`rte-mode-toggle__btn ${!notionMode ? 'rte-mode-toggle__btn--active' : ''}`}\n onClick={() => setNotionMode(false)}\n title=\"Classic mode\"\n >\n Classic\n </button>\n <button\n type=\"button\"\n className={`rte-mode-toggle__btn ${notionMode ? 'rte-mode-toggle__btn--active' : ''}`}\n onClick={() => setNotionMode(true)}\n title=\"Notion-style mode\"\n >\n Notion\n </button>\n <div className=\"rte-toolbar__divider\" style={{ height: 20, margin: '0 4px' }} />\n <button\n type=\"button\"\n className={`rte-toolbar__btn rte-toolbar__comment-btn ${showComments ? 'rte-toolbar__btn--active' : ''}`}\n onClick={() => setShowComments(!showComments)}\n title=\"Toggle comments\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" />\n </svg>\n {activeCommentCount > 0 && <span className=\"rte-toolbar__comment-badge\" />}\n </button>\n </div>\n );\n\n return (\n <div className={containerClass} style={{ minHeight: minH, maxHeight: maxH }}>\n {editable && !notionMode && (\n <Toolbar\n editor={editor}\n config={toolbarConfig}\n labels={labels}\n hasAI={!!aiConfig}\n onAIClick={handleAIClick}\n onFormatPainterChange={setFormatPainterActive}\n >\n {modeToggle}\n </Toolbar>\n )}\n\n {editable && notionMode && (\n <div className=\"rte-notion-topbar\">\n {modeToggle}\n </div>\n )}\n\n <div style={{ display: 'flex', flex: 1, overflow: 'hidden' }}>\n <div className=\"rte-editor-wrapper\" style={{ flex: 1 }}>\n <EditorContent editor={editor} className=\"rte-editor-content\" />\n {editable && <ContextMenu editor={editor} labels={labels} onAIClick={aiConfig ? handleAIClick : undefined} />}\n {editable && <SlashMenu editor={editor} />}\n {editable && notionMode && <BubbleToolbar editor={editor} onAddComment={requestAddComment} />}\n {editable && notionMode && <BlockHandle editor={editor} />}\n <CommentPopover\n editor={editor}\n threads={threads}\n onThreadsChange={setThreads}\n showPanel={showComments}\n onOpenPanel={() => setShowComments(true)}\n onScrollToThread={handleScrollToThread}\n currentUser={currentUser}\n />\n </div>\n\n {showComments && (\n <CommentPanel\n ref={commentPanelRef}\n editor={editor}\n threads={threads}\n onThreadsChange={setThreads}\n onRequestAddComment={requestAddComment}\n currentUser={currentUser}\n />\n )}\n </div>\n\n {aiConfig && showAIPanel && (\n <AIRewrite\n editor={editor}\n aiConfig={aiConfig}\n labels={labels}\n initialSelection={aiSelection}\n selectionRange={aiSelectionRange}\n onClose={() => setShowAIPanel(false)}\n />\n )}\n\n <CommentDialog\n open={commentDialogOpen}\n onSubmit={handleCommentSubmit}\n onClose={() => setCommentDialogOpen(false)}\n />\n </div>\n );\n};\n\nexport default RichTextEditor;\n"],"mappings":"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"}
|