@fangxinyan/lumina 0.6.4 → 0.6.6

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.
@@ -5,6 +5,8 @@
5
5
  align-self: flex-start;
6
6
  }
7
7
  .tip {
8
+ display: block;
9
+ box-sizing: border-box;
8
10
  background: var(--bg-sunken);
9
11
  color: var(--fg);
10
12
  padding: 6px 10px;
@@ -13,7 +15,7 @@
13
15
  font-weight: 500;
14
16
  white-space: nowrap;
15
17
  box-shadow: var(--neu-shadow-control);
16
- pointer-events: none;
18
+ pointer-events: auto;
17
19
  animation: fadeIn var(--dur) var(--ease);
18
20
  z-index: 1000;
19
21
  }
package/dist/Tooltip.cjs CHANGED
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var chunkF3LHLYX6_cjs = require('./chunk-F3LHLYX6.cjs');
3
+ var chunkRIUDYPRB_cjs = require('./chunk-RIUDYPRB.cjs');
4
4
  require('./chunk-YB3IWIOJ.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "Tooltip", {
9
9
  enumerable: true,
10
- get: function () { return chunkF3LHLYX6_cjs.Tooltip; }
10
+ get: function () { return chunkRIUDYPRB_cjs.Tooltip; }
11
11
  });
@@ -15,6 +15,8 @@ interface TooltipProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "chil
15
15
  /** Controlled visibility alias. */
16
16
  visible?: boolean;
17
17
  onVisibleChange?: (visible: boolean) => void;
18
+ /** Delay before closing after leaving trigger / bubble. */
19
+ closeDelay?: number;
18
20
  /** Class for the popped-out bubble. */
19
21
  overlayClassName?: string;
20
22
  /** Alias used by some popup APIs. */
package/dist/Tooltip.d.ts CHANGED
@@ -15,6 +15,8 @@ interface TooltipProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "chil
15
15
  /** Controlled visibility alias. */
16
16
  visible?: boolean;
17
17
  onVisibleChange?: (visible: boolean) => void;
18
+ /** Delay before closing after leaving trigger / bubble. */
19
+ closeDelay?: number;
18
20
  /** Class for the popped-out bubble. */
19
21
  overlayClassName?: string;
20
22
  /** Alias used by some popup APIs. */
package/dist/Tooltip.js CHANGED
@@ -1,2 +1,2 @@
1
- export { Tooltip } from './chunk-XHQGMMH7.js';
1
+ export { Tooltip } from './chunk-SFAGHPBT.js';
2
2
  import './chunk-DUFRASGO.js';
@@ -115,7 +115,7 @@
115
115
  .typo-link.disabled {
116
116
  color: var(--fg-subtle);
117
117
  cursor: not-allowed;
118
- pointer-events: none;
118
+ pointer-events: auto;
119
119
  text-decoration: none;
120
120
  }
121
121
  .typo-link-ext {
@@ -132,16 +132,21 @@
132
132
  display: inline-flex;
133
133
  align-items: center;
134
134
  justify-content: center;
135
- width: 22px;
136
- height: 22px;
137
- margin-left: 6px;
138
- border-radius: 7px;
135
+ width: 20px;
136
+ height: 20px;
137
+ margin-left: 5px;
138
+ border-radius: 6px;
139
139
  cursor: pointer;
140
140
  color: var(--fg-subtle);
141
+ line-height: 1;
141
142
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
142
- vertical-align: middle;
143
+ vertical-align: -0.18em;
143
144
  user-select: none;
144
145
  }
146
+ .typo-action > svg {
147
+ display: block;
148
+ flex-shrink: 0;
149
+ }
145
150
  .typo-action:hover {
146
151
  color: var(--accent-ink);
147
152
  background: var(--bg);
@@ -228,6 +233,31 @@
228
233
  }
229
234
  .typo-expand:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
230
235
 
236
+ .typo-ellipsis-tooltip {
237
+ display: block;
238
+ box-sizing: border-box;
239
+ max-width: min(520px, calc(100vw - 32px));
240
+ padding: 7px 10px;
241
+ border-radius: var(--r-sm);
242
+ background: var(--bg-sunken);
243
+ color: var(--fg);
244
+ box-shadow: var(--neu-shadow-control);
245
+ font-size: 12px;
246
+ font-weight: 500;
247
+ line-height: 1.55;
248
+ white-space: normal;
249
+ line-break: auto;
250
+ text-wrap: wrap;
251
+ text-align: justify;
252
+ text-align-last: left;
253
+ text-justify: inter-character;
254
+ word-break: normal;
255
+ overflow-wrap: anywhere;
256
+ pointer-events: auto;
257
+ animation: fadeIn var(--dur) var(--ease);
258
+ z-index: 1000;
259
+ }
260
+
231
261
  /* In dark mode, mark needs slightly higher contrast */
232
262
  [data-theme="dark"] .typo mark {
233
263
  background: color-mix(in oklch, var(--warning) 30%, transparent);
@@ -1,27 +1,28 @@
1
1
  'use strict';
2
2
 
3
- var chunk5JPAUQ5H_cjs = require('./chunk-5JPAUQ5H.cjs');
3
+ var chunkYU5JK247_cjs = require('./chunk-YU5JK247.cjs');
4
+ require('./chunk-YB3IWIOJ.cjs');
4
5
  require('./chunk-6LARTGLP.cjs');
5
6
 
6
7
 
7
8
 
8
9
  Object.defineProperty(exports, "Link", {
9
10
  enumerable: true,
10
- get: function () { return chunk5JPAUQ5H_cjs.Link; }
11
+ get: function () { return chunkYU5JK247_cjs.Link; }
11
12
  });
12
13
  Object.defineProperty(exports, "Paragraph", {
13
14
  enumerable: true,
14
- get: function () { return chunk5JPAUQ5H_cjs.Paragraph; }
15
+ get: function () { return chunkYU5JK247_cjs.Paragraph; }
15
16
  });
16
17
  Object.defineProperty(exports, "Text", {
17
18
  enumerable: true,
18
- get: function () { return chunk5JPAUQ5H_cjs.Text; }
19
+ get: function () { return chunkYU5JK247_cjs.Text; }
19
20
  });
20
21
  Object.defineProperty(exports, "Title", {
21
22
  enumerable: true,
22
- get: function () { return chunk5JPAUQ5H_cjs.Title; }
23
+ get: function () { return chunkYU5JK247_cjs.Title; }
23
24
  });
24
25
  Object.defineProperty(exports, "Typography", {
25
26
  enumerable: true,
26
- get: function () { return chunk5JPAUQ5H_cjs.Typography; }
27
+ get: function () { return chunkYU5JK247_cjs.Typography; }
27
28
  });
@@ -53,7 +53,7 @@ interface EllipsisConfig {
53
53
  symbol?: React.ReactNode;
54
54
  /** Fired on expand. */
55
55
  onExpand?: (event: React.MouseEvent<HTMLElement>) => void;
56
- /** Show full text in a `title` attribute. */
56
+ /** Show full text in a tooltip when truncated. */
57
57
  tooltip?: boolean | React.ReactNode;
58
58
  /** Optional suffix that should always remain visible (e.g. an em-dash author). */
59
59
  suffix?: string;
@@ -53,7 +53,7 @@ interface EllipsisConfig {
53
53
  symbol?: React.ReactNode;
54
54
  /** Fired on expand. */
55
55
  onExpand?: (event: React.MouseEvent<HTMLElement>) => void;
56
- /** Show full text in a `title` attribute. */
56
+ /** Show full text in a tooltip when truncated. */
57
57
  tooltip?: boolean | React.ReactNode;
58
58
  /** Optional suffix that should always remain visible (e.g. an em-dash author). */
59
59
  suffix?: string;
@@ -1,2 +1,3 @@
1
- export { Link, Paragraph, Text, Title, Typography } from './chunk-BCFCSVGJ.js';
1
+ export { Link, Paragraph, Text, Title, Typography } from './chunk-5JNDDWFZ.js';
2
+ import './chunk-DUFRASGO.js';
2
3
  import './chunk-YT5NLCRC.js';
@@ -1,9 +1,11 @@
1
+ import { useFloating } from './chunk-DUFRASGO.js';
1
2
  import { Icon } from './chunk-YT5NLCRC.js';
2
3
  import './tokens-EF34LSWI.css';
3
4
  import './shared-NJHRNLRH.css';
4
- import './Typography-GQNIJ4XD.css';
5
+ import './Typography-32QQLD4F.css';
5
6
  import * as React from 'react';
6
- import { jsx, jsxs } from 'react/jsx-runtime';
7
+ import { createPortal } from 'react-dom';
8
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
7
9
 
8
10
  function toText(node) {
9
11
  if (node == null || node === false) return "";
@@ -31,6 +33,122 @@ function buildClass(props, base, extra) {
31
33
  props.className
32
34
  ].filter(Boolean).join(" ");
33
35
  }
36
+ function assignRef(ref, value) {
37
+ if (!ref) return;
38
+ if (typeof ref === "function") {
39
+ ref(value);
40
+ return;
41
+ }
42
+ ref.current = value;
43
+ }
44
+ var EllipsisTooltip = React.forwardRef(({ content, children }, forwardedRef) => {
45
+ const [open, setOpen] = React.useState(false);
46
+ const openTimerRef = React.useRef();
47
+ const closeTimerRef = React.useRef();
48
+ const childRef = children.ref;
49
+ const {
50
+ triggerRef,
51
+ floatingRef,
52
+ floatingStyle,
53
+ placement
54
+ } = useFloating({
55
+ open,
56
+ placement: "top",
57
+ panelWidth: 360,
58
+ panelHeight: 96,
59
+ alignCross: "center"
60
+ });
61
+ React.useEffect(() => {
62
+ return () => {
63
+ window.clearTimeout(openTimerRef.current);
64
+ window.clearTimeout(closeTimerRef.current);
65
+ };
66
+ }, []);
67
+ const show = React.useCallback(() => {
68
+ window.clearTimeout(closeTimerRef.current);
69
+ if (open || openTimerRef.current != null) return;
70
+ openTimerRef.current = window.setTimeout(() => {
71
+ openTimerRef.current = void 0;
72
+ setOpen(true);
73
+ }, 250);
74
+ }, [open]);
75
+ const hide = React.useCallback(() => {
76
+ window.clearTimeout(openTimerRef.current);
77
+ openTimerRef.current = void 0;
78
+ window.clearTimeout(closeTimerRef.current);
79
+ closeTimerRef.current = window.setTimeout(() => setOpen(false), 300);
80
+ }, []);
81
+ const setTriggerRef = React.useCallback(
82
+ (node) => {
83
+ triggerRef.current = node;
84
+ assignRef(forwardedRef, node);
85
+ assignRef(childRef, node);
86
+ },
87
+ [childRef, forwardedRef, triggerRef]
88
+ );
89
+ const childProps = children.props;
90
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
91
+ React.cloneElement(children, {
92
+ ref: setTriggerRef,
93
+ onMouseEnter: (event) => {
94
+ childProps.onMouseEnter?.(event);
95
+ show();
96
+ },
97
+ onMouseOver: (event) => {
98
+ childProps.onMouseOver?.(event);
99
+ show();
100
+ },
101
+ onMouseMove: (event) => {
102
+ childProps.onMouseMove?.(event);
103
+ show();
104
+ },
105
+ onMouseLeave: (event) => {
106
+ childProps.onMouseLeave?.(event);
107
+ hide();
108
+ },
109
+ onPointerEnter: (event) => {
110
+ childProps.onPointerEnter?.(event);
111
+ show();
112
+ },
113
+ onPointerMove: (event) => {
114
+ childProps.onPointerMove?.(event);
115
+ show();
116
+ },
117
+ onPointerLeave: (event) => {
118
+ childProps.onPointerLeave?.(event);
119
+ hide();
120
+ },
121
+ onFocus: (event) => {
122
+ childProps.onFocus?.(event);
123
+ show();
124
+ },
125
+ onBlur: (event) => {
126
+ childProps.onBlur?.(event);
127
+ hide();
128
+ }
129
+ }),
130
+ open && typeof document !== "undefined" && createPortal(
131
+ /* @__PURE__ */ jsx(
132
+ "div",
133
+ {
134
+ ref: floatingRef,
135
+ className: `typo-ellipsis-tooltip ${placement}`,
136
+ style: floatingStyle,
137
+ role: "tooltip",
138
+ onMouseEnter: show,
139
+ onMouseMove: show,
140
+ onMouseLeave: hide,
141
+ onPointerEnter: show,
142
+ onPointerMove: show,
143
+ onPointerLeave: hide,
144
+ children: content
145
+ }
146
+ ),
147
+ document.body
148
+ )
149
+ ] });
150
+ });
151
+ EllipsisTooltip.displayName = "Typography.EllipsisTooltip";
34
152
  var CopyAction = ({ config, fallbackText }) => {
35
153
  const [copied, setCopied] = React.useState(false);
36
154
  const timerRef = React.useRef(null);
@@ -230,7 +348,7 @@ function useTypographyBody(props) {
230
348
  }
231
349
  );
232
350
  }
233
- const titleAttr = wantClamp && ellConf.tooltip ? typeof ellConf.tooltip === "string" ? ellConf.tooltip : fallbackText : void 0;
351
+ const tooltipContent = wantClamp && !expanded && ellConf.tooltip ? ellConf.tooltip === true ? fallbackText : ellConf.tooltip : void 0;
234
352
  return {
235
353
  editing,
236
354
  editConf,
@@ -243,7 +361,7 @@ function useTypographyBody(props) {
243
361
  expandNode,
244
362
  style,
245
363
  extraCls,
246
- titleAttr
364
+ tooltipContent
247
365
  };
248
366
  }
249
367
  var Title = React.forwardRef((props, ref) => {
@@ -271,13 +389,12 @@ var Title = React.forwardRef((props, ref) => {
271
389
  }
272
390
  );
273
391
  }
274
- return /* @__PURE__ */ jsxs(
392
+ const element = /* @__PURE__ */ jsxs(
275
393
  Tag,
276
394
  {
277
395
  ref,
278
396
  className: buildClass(rest, `typo typo-title h${level}`, body.extraCls),
279
397
  style: body.style,
280
- title: body.titleAttr,
281
398
  children: [
282
399
  body.inner,
283
400
  body.expandNode,
@@ -286,6 +403,7 @@ var Title = React.forwardRef((props, ref) => {
286
403
  ]
287
404
  }
288
405
  );
406
+ return body.tooltipContent ? /* @__PURE__ */ jsx(EllipsisTooltip, { ref, content: body.tooltipContent, children: element }) : element;
289
407
  });
290
408
  Title.displayName = "Typography.Title";
291
409
  var Text = React.forwardRef((props, ref) => {
@@ -313,13 +431,12 @@ var Text = React.forwardRef((props, ref) => {
313
431
  }
314
432
  );
315
433
  }
316
- return /* @__PURE__ */ jsxs(
434
+ const element = /* @__PURE__ */ jsxs(
317
435
  Tag,
318
436
  {
319
437
  ref,
320
438
  className: buildClass(rest, "typo typo-text", body.extraCls),
321
439
  style: body.style,
322
- title: body.titleAttr,
323
440
  children: [
324
441
  body.inner,
325
442
  body.expandNode,
@@ -328,6 +445,7 @@ var Text = React.forwardRef((props, ref) => {
328
445
  ]
329
446
  }
330
447
  );
448
+ return body.tooltipContent ? /* @__PURE__ */ jsx(EllipsisTooltip, { ref, content: body.tooltipContent, children: element }) : element;
331
449
  });
332
450
  Text.displayName = "Typography.Text";
333
451
  var Paragraph = React.forwardRef(
@@ -354,13 +472,12 @@ var Paragraph = React.forwardRef(
354
472
  }
355
473
  );
356
474
  }
357
- return /* @__PURE__ */ jsxs(
475
+ const element = /* @__PURE__ */ jsxs(
358
476
  "p",
359
477
  {
360
478
  ref,
361
479
  className: buildClass(props, "typo typo-paragraph", body.extraCls),
362
480
  style: body.style,
363
- title: body.titleAttr,
364
481
  children: [
365
482
  body.inner,
366
483
  body.expandNode,
@@ -369,6 +486,7 @@ var Paragraph = React.forwardRef(
369
486
  ]
370
487
  }
371
488
  );
489
+ return body.tooltipContent ? /* @__PURE__ */ jsx(EllipsisTooltip, { ref, content: body.tooltipContent, children: element }) : element;
372
490
  }
373
491
  );
374
492
  Paragraph.displayName = "Typography.Paragraph";
@@ -431,13 +549,12 @@ var Link = React.forwardRef(
431
549
  }
432
550
  );
433
551
  }
434
- return /* @__PURE__ */ jsxs(
552
+ const element = /* @__PURE__ */ jsxs(
435
553
  "a",
436
554
  {
437
555
  ref,
438
556
  className: buildClass(props, "typo typo-link", body.extraCls),
439
557
  style: body.style,
440
- title: body.titleAttr,
441
558
  target,
442
559
  rel: safeRel,
443
560
  "aria-disabled": disabled || void 0,
@@ -458,6 +575,7 @@ var Link = React.forwardRef(
458
575
  ]
459
576
  }
460
577
  );
578
+ return body.tooltipContent ? /* @__PURE__ */ jsx(EllipsisTooltip, { ref, content: body.tooltipContent, children: element }) : element;
461
579
  }
462
580
  );
463
581
  Link.displayName = "Typography.Link";
@@ -3,7 +3,7 @@
3
3
  var chunkYB3IWIOJ_cjs = require('./chunk-YB3IWIOJ.cjs');
4
4
  require('./tokens-EF34LSWI.css');
5
5
  require('./shared-NJHRNLRH.css');
6
- require('./Tooltip-WI23DSRQ.css');
6
+ require('./Tooltip-5FSPJWLX.css');
7
7
  var React = require('react');
8
8
  var reactDom = require('react-dom');
9
9
  var jsxRuntime = require('react/jsx-runtime');
@@ -45,16 +45,20 @@ var Tooltip = React__namespace.forwardRef(({
45
45
  onOpenChange,
46
46
  visible,
47
47
  onVisibleChange,
48
+ closeDelay = 300,
48
49
  overlayClassName = "",
49
50
  popupClassName = "",
50
51
  onMouseEnter,
51
52
  onMouseLeave,
53
+ onPointerEnter,
54
+ onPointerLeave,
52
55
  onFocus,
53
56
  onBlur,
54
57
  ...rest
55
58
  }, ref) => {
56
59
  const [innerShow, setInnerShow] = React__namespace.useState(defaultOpen);
57
- const t = React__namespace.useRef();
60
+ const openTimerRef = React__namespace.useRef();
61
+ const closeTimerRef = React__namespace.useRef();
58
62
  const controlledShow = openProp ?? visible;
59
63
  const show = controlledShow ?? innerShow;
60
64
  const resolvedContent = content ?? title;
@@ -64,17 +68,41 @@ var Tooltip = React__namespace.forwardRef(({
64
68
  onOpenChange?.(next);
65
69
  onVisibleChange?.(next);
66
70
  }, [controlledShow, onOpenChange, onVisibleChange]);
67
- const open = () => {
71
+ React__namespace.useEffect(() => {
72
+ return () => {
73
+ window.clearTimeout(openTimerRef.current);
74
+ window.clearTimeout(closeTimerRef.current);
75
+ };
76
+ }, []);
77
+ React__namespace.useEffect(() => {
78
+ if (disabledTooltip && show) setShow(false);
79
+ }, [disabledTooltip, setShow, show]);
80
+ const open = React__namespace.useCallback(() => {
68
81
  if (disabledTooltip) return;
69
- window.clearTimeout(t.current);
70
- t.current = window.setTimeout(() => setShow(true), delay);
71
- };
72
- const close = () => {
73
- window.clearTimeout(t.current);
74
- setShow(false);
75
- };
82
+ window.clearTimeout(closeTimerRef.current);
83
+ window.clearTimeout(openTimerRef.current);
84
+ if (delay <= 0) {
85
+ setShow(true);
86
+ return;
87
+ }
88
+ openTimerRef.current = window.setTimeout(() => setShow(true), delay);
89
+ }, [delay, disabledTooltip, setShow]);
90
+ const close = React__namespace.useCallback(() => {
91
+ window.clearTimeout(openTimerRef.current);
92
+ window.clearTimeout(closeTimerRef.current);
93
+ if (closeDelay <= 0) {
94
+ setShow(false);
95
+ return;
96
+ }
97
+ closeTimerRef.current = window.setTimeout(() => setShow(false), closeDelay);
98
+ }, [closeDelay, setShow]);
76
99
  const normalized = normalizePlacement(placement);
77
- const { triggerRef, floatingStyle, placement: resolved } = chunkYB3IWIOJ_cjs.useFloating({
100
+ const {
101
+ triggerRef,
102
+ floatingRef,
103
+ floatingStyle,
104
+ placement: resolved
105
+ } = chunkYB3IWIOJ_cjs.useFloating({
78
106
  open: show,
79
107
  placement: normalized.placement,
80
108
  panelWidth: 160,
@@ -103,6 +131,14 @@ var Tooltip = React__namespace.forwardRef(({
103
131
  onMouseLeave?.(e);
104
132
  close();
105
133
  },
134
+ onPointerEnter: (e) => {
135
+ onPointerEnter?.(e);
136
+ open();
137
+ },
138
+ onPointerLeave: (e) => {
139
+ onPointerLeave?.(e);
140
+ close();
141
+ },
106
142
  onFocus: (e) => {
107
143
  onFocus?.(e);
108
144
  open();
@@ -116,7 +152,20 @@ var Tooltip = React__namespace.forwardRef(({
116
152
  }
117
153
  ),
118
154
  show && typeof document !== "undefined" && reactDom.createPortal(
119
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `tip ${resolved} ${overlayClassName} ${popupClassName}`, style: floatingStyle, children: resolvedContent }),
155
+ /* @__PURE__ */ jsxRuntime.jsx(
156
+ "div",
157
+ {
158
+ ref: floatingRef,
159
+ className: `tip ${resolved} ${overlayClassName} ${popupClassName}`,
160
+ style: floatingStyle,
161
+ role: "tooltip",
162
+ onMouseEnter: open,
163
+ onMouseLeave: close,
164
+ onPointerEnter: open,
165
+ onPointerLeave: close,
166
+ children: resolvedContent
167
+ }
168
+ ),
120
169
  document.body
121
170
  )
122
171
  ] });
@@ -1,7 +1,7 @@
1
1
  import { useFloating } from './chunk-DUFRASGO.js';
2
2
  import './tokens-EF34LSWI.css';
3
3
  import './shared-NJHRNLRH.css';
4
- import './Tooltip-WI23DSRQ.css';
4
+ import './Tooltip-5FSPJWLX.css';
5
5
  import * as React from 'react';
6
6
  import { createPortal } from 'react-dom';
7
7
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
@@ -23,16 +23,20 @@ var Tooltip = React.forwardRef(({
23
23
  onOpenChange,
24
24
  visible,
25
25
  onVisibleChange,
26
+ closeDelay = 300,
26
27
  overlayClassName = "",
27
28
  popupClassName = "",
28
29
  onMouseEnter,
29
30
  onMouseLeave,
31
+ onPointerEnter,
32
+ onPointerLeave,
30
33
  onFocus,
31
34
  onBlur,
32
35
  ...rest
33
36
  }, ref) => {
34
37
  const [innerShow, setInnerShow] = React.useState(defaultOpen);
35
- const t = React.useRef();
38
+ const openTimerRef = React.useRef();
39
+ const closeTimerRef = React.useRef();
36
40
  const controlledShow = openProp ?? visible;
37
41
  const show = controlledShow ?? innerShow;
38
42
  const resolvedContent = content ?? title;
@@ -42,17 +46,41 @@ var Tooltip = React.forwardRef(({
42
46
  onOpenChange?.(next);
43
47
  onVisibleChange?.(next);
44
48
  }, [controlledShow, onOpenChange, onVisibleChange]);
45
- const open = () => {
49
+ React.useEffect(() => {
50
+ return () => {
51
+ window.clearTimeout(openTimerRef.current);
52
+ window.clearTimeout(closeTimerRef.current);
53
+ };
54
+ }, []);
55
+ React.useEffect(() => {
56
+ if (disabledTooltip && show) setShow(false);
57
+ }, [disabledTooltip, setShow, show]);
58
+ const open = React.useCallback(() => {
46
59
  if (disabledTooltip) return;
47
- window.clearTimeout(t.current);
48
- t.current = window.setTimeout(() => setShow(true), delay);
49
- };
50
- const close = () => {
51
- window.clearTimeout(t.current);
52
- setShow(false);
53
- };
60
+ window.clearTimeout(closeTimerRef.current);
61
+ window.clearTimeout(openTimerRef.current);
62
+ if (delay <= 0) {
63
+ setShow(true);
64
+ return;
65
+ }
66
+ openTimerRef.current = window.setTimeout(() => setShow(true), delay);
67
+ }, [delay, disabledTooltip, setShow]);
68
+ const close = React.useCallback(() => {
69
+ window.clearTimeout(openTimerRef.current);
70
+ window.clearTimeout(closeTimerRef.current);
71
+ if (closeDelay <= 0) {
72
+ setShow(false);
73
+ return;
74
+ }
75
+ closeTimerRef.current = window.setTimeout(() => setShow(false), closeDelay);
76
+ }, [closeDelay, setShow]);
54
77
  const normalized = normalizePlacement(placement);
55
- const { triggerRef, floatingStyle, placement: resolved } = useFloating({
78
+ const {
79
+ triggerRef,
80
+ floatingRef,
81
+ floatingStyle,
82
+ placement: resolved
83
+ } = useFloating({
56
84
  open: show,
57
85
  placement: normalized.placement,
58
86
  panelWidth: 160,
@@ -81,6 +109,14 @@ var Tooltip = React.forwardRef(({
81
109
  onMouseLeave?.(e);
82
110
  close();
83
111
  },
112
+ onPointerEnter: (e) => {
113
+ onPointerEnter?.(e);
114
+ open();
115
+ },
116
+ onPointerLeave: (e) => {
117
+ onPointerLeave?.(e);
118
+ close();
119
+ },
84
120
  onFocus: (e) => {
85
121
  onFocus?.(e);
86
122
  open();
@@ -94,7 +130,20 @@ var Tooltip = React.forwardRef(({
94
130
  }
95
131
  ),
96
132
  show && typeof document !== "undefined" && createPortal(
97
- /* @__PURE__ */ jsx("span", { className: `tip ${resolved} ${overlayClassName} ${popupClassName}`, style: floatingStyle, children: resolvedContent }),
133
+ /* @__PURE__ */ jsx(
134
+ "div",
135
+ {
136
+ ref: floatingRef,
137
+ className: `tip ${resolved} ${overlayClassName} ${popupClassName}`,
138
+ style: floatingStyle,
139
+ role: "tooltip",
140
+ onMouseEnter: open,
141
+ onMouseLeave: close,
142
+ onPointerEnter: open,
143
+ onPointerLeave: close,
144
+ children: resolvedContent
145
+ }
146
+ ),
98
147
  document.body
99
148
  )
100
149
  ] });
@@ -1,10 +1,12 @@
1
1
  'use strict';
2
2
 
3
+ var chunkYB3IWIOJ_cjs = require('./chunk-YB3IWIOJ.cjs');
3
4
  var chunk6LARTGLP_cjs = require('./chunk-6LARTGLP.cjs');
4
5
  require('./tokens-EF34LSWI.css');
5
6
  require('./shared-NJHRNLRH.css');
6
- require('./Typography-GQNIJ4XD.css');
7
+ require('./Typography-32QQLD4F.css');
7
8
  var React = require('react');
9
+ var reactDom = require('react-dom');
8
10
  var jsxRuntime = require('react/jsx-runtime');
9
11
 
10
12
  function _interopNamespace(e) {
@@ -53,6 +55,122 @@ function buildClass(props, base, extra) {
53
55
  props.className
54
56
  ].filter(Boolean).join(" ");
55
57
  }
58
+ function assignRef(ref, value) {
59
+ if (!ref) return;
60
+ if (typeof ref === "function") {
61
+ ref(value);
62
+ return;
63
+ }
64
+ ref.current = value;
65
+ }
66
+ var EllipsisTooltip = React__namespace.forwardRef(({ content, children }, forwardedRef) => {
67
+ const [open, setOpen] = React__namespace.useState(false);
68
+ const openTimerRef = React__namespace.useRef();
69
+ const closeTimerRef = React__namespace.useRef();
70
+ const childRef = children.ref;
71
+ const {
72
+ triggerRef,
73
+ floatingRef,
74
+ floatingStyle,
75
+ placement
76
+ } = chunkYB3IWIOJ_cjs.useFloating({
77
+ open,
78
+ placement: "top",
79
+ panelWidth: 360,
80
+ panelHeight: 96,
81
+ alignCross: "center"
82
+ });
83
+ React__namespace.useEffect(() => {
84
+ return () => {
85
+ window.clearTimeout(openTimerRef.current);
86
+ window.clearTimeout(closeTimerRef.current);
87
+ };
88
+ }, []);
89
+ const show = React__namespace.useCallback(() => {
90
+ window.clearTimeout(closeTimerRef.current);
91
+ if (open || openTimerRef.current != null) return;
92
+ openTimerRef.current = window.setTimeout(() => {
93
+ openTimerRef.current = void 0;
94
+ setOpen(true);
95
+ }, 250);
96
+ }, [open]);
97
+ const hide = React__namespace.useCallback(() => {
98
+ window.clearTimeout(openTimerRef.current);
99
+ openTimerRef.current = void 0;
100
+ window.clearTimeout(closeTimerRef.current);
101
+ closeTimerRef.current = window.setTimeout(() => setOpen(false), 300);
102
+ }, []);
103
+ const setTriggerRef = React__namespace.useCallback(
104
+ (node) => {
105
+ triggerRef.current = node;
106
+ assignRef(forwardedRef, node);
107
+ assignRef(childRef, node);
108
+ },
109
+ [childRef, forwardedRef, triggerRef]
110
+ );
111
+ const childProps = children.props;
112
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
113
+ React__namespace.cloneElement(children, {
114
+ ref: setTriggerRef,
115
+ onMouseEnter: (event) => {
116
+ childProps.onMouseEnter?.(event);
117
+ show();
118
+ },
119
+ onMouseOver: (event) => {
120
+ childProps.onMouseOver?.(event);
121
+ show();
122
+ },
123
+ onMouseMove: (event) => {
124
+ childProps.onMouseMove?.(event);
125
+ show();
126
+ },
127
+ onMouseLeave: (event) => {
128
+ childProps.onMouseLeave?.(event);
129
+ hide();
130
+ },
131
+ onPointerEnter: (event) => {
132
+ childProps.onPointerEnter?.(event);
133
+ show();
134
+ },
135
+ onPointerMove: (event) => {
136
+ childProps.onPointerMove?.(event);
137
+ show();
138
+ },
139
+ onPointerLeave: (event) => {
140
+ childProps.onPointerLeave?.(event);
141
+ hide();
142
+ },
143
+ onFocus: (event) => {
144
+ childProps.onFocus?.(event);
145
+ show();
146
+ },
147
+ onBlur: (event) => {
148
+ childProps.onBlur?.(event);
149
+ hide();
150
+ }
151
+ }),
152
+ open && typeof document !== "undefined" && reactDom.createPortal(
153
+ /* @__PURE__ */ jsxRuntime.jsx(
154
+ "div",
155
+ {
156
+ ref: floatingRef,
157
+ className: `typo-ellipsis-tooltip ${placement}`,
158
+ style: floatingStyle,
159
+ role: "tooltip",
160
+ onMouseEnter: show,
161
+ onMouseMove: show,
162
+ onMouseLeave: hide,
163
+ onPointerEnter: show,
164
+ onPointerMove: show,
165
+ onPointerLeave: hide,
166
+ children: content
167
+ }
168
+ ),
169
+ document.body
170
+ )
171
+ ] });
172
+ });
173
+ EllipsisTooltip.displayName = "Typography.EllipsisTooltip";
56
174
  var CopyAction = ({ config, fallbackText }) => {
57
175
  const [copied, setCopied] = React__namespace.useState(false);
58
176
  const timerRef = React__namespace.useRef(null);
@@ -252,7 +370,7 @@ function useTypographyBody(props) {
252
370
  }
253
371
  );
254
372
  }
255
- const titleAttr = wantClamp && ellConf.tooltip ? typeof ellConf.tooltip === "string" ? ellConf.tooltip : fallbackText : void 0;
373
+ const tooltipContent = wantClamp && !expanded && ellConf.tooltip ? ellConf.tooltip === true ? fallbackText : ellConf.tooltip : void 0;
256
374
  return {
257
375
  editing,
258
376
  editConf,
@@ -265,7 +383,7 @@ function useTypographyBody(props) {
265
383
  expandNode,
266
384
  style,
267
385
  extraCls,
268
- titleAttr
386
+ tooltipContent
269
387
  };
270
388
  }
271
389
  var Title = React__namespace.forwardRef((props, ref) => {
@@ -293,13 +411,12 @@ var Title = React__namespace.forwardRef((props, ref) => {
293
411
  }
294
412
  );
295
413
  }
296
- return /* @__PURE__ */ jsxRuntime.jsxs(
414
+ const element = /* @__PURE__ */ jsxRuntime.jsxs(
297
415
  Tag,
298
416
  {
299
417
  ref,
300
418
  className: buildClass(rest, `typo typo-title h${level}`, body.extraCls),
301
419
  style: body.style,
302
- title: body.titleAttr,
303
420
  children: [
304
421
  body.inner,
305
422
  body.expandNode,
@@ -308,6 +425,7 @@ var Title = React__namespace.forwardRef((props, ref) => {
308
425
  ]
309
426
  }
310
427
  );
428
+ return body.tooltipContent ? /* @__PURE__ */ jsxRuntime.jsx(EllipsisTooltip, { ref, content: body.tooltipContent, children: element }) : element;
311
429
  });
312
430
  Title.displayName = "Typography.Title";
313
431
  var Text = React__namespace.forwardRef((props, ref) => {
@@ -335,13 +453,12 @@ var Text = React__namespace.forwardRef((props, ref) => {
335
453
  }
336
454
  );
337
455
  }
338
- return /* @__PURE__ */ jsxRuntime.jsxs(
456
+ const element = /* @__PURE__ */ jsxRuntime.jsxs(
339
457
  Tag,
340
458
  {
341
459
  ref,
342
460
  className: buildClass(rest, "typo typo-text", body.extraCls),
343
461
  style: body.style,
344
- title: body.titleAttr,
345
462
  children: [
346
463
  body.inner,
347
464
  body.expandNode,
@@ -350,6 +467,7 @@ var Text = React__namespace.forwardRef((props, ref) => {
350
467
  ]
351
468
  }
352
469
  );
470
+ return body.tooltipContent ? /* @__PURE__ */ jsxRuntime.jsx(EllipsisTooltip, { ref, content: body.tooltipContent, children: element }) : element;
353
471
  });
354
472
  Text.displayName = "Typography.Text";
355
473
  var Paragraph = React__namespace.forwardRef(
@@ -376,13 +494,12 @@ var Paragraph = React__namespace.forwardRef(
376
494
  }
377
495
  );
378
496
  }
379
- return /* @__PURE__ */ jsxRuntime.jsxs(
497
+ const element = /* @__PURE__ */ jsxRuntime.jsxs(
380
498
  "p",
381
499
  {
382
500
  ref,
383
501
  className: buildClass(props, "typo typo-paragraph", body.extraCls),
384
502
  style: body.style,
385
- title: body.titleAttr,
386
503
  children: [
387
504
  body.inner,
388
505
  body.expandNode,
@@ -391,6 +508,7 @@ var Paragraph = React__namespace.forwardRef(
391
508
  ]
392
509
  }
393
510
  );
511
+ return body.tooltipContent ? /* @__PURE__ */ jsxRuntime.jsx(EllipsisTooltip, { ref, content: body.tooltipContent, children: element }) : element;
394
512
  }
395
513
  );
396
514
  Paragraph.displayName = "Typography.Paragraph";
@@ -453,13 +571,12 @@ var Link = React__namespace.forwardRef(
453
571
  }
454
572
  );
455
573
  }
456
- return /* @__PURE__ */ jsxRuntime.jsxs(
574
+ const element = /* @__PURE__ */ jsxRuntime.jsxs(
457
575
  "a",
458
576
  {
459
577
  ref,
460
578
  className: buildClass(props, "typo typo-link", body.extraCls),
461
579
  style: body.style,
462
- title: body.titleAttr,
463
580
  target,
464
581
  rel: safeRel,
465
582
  "aria-disabled": disabled || void 0,
@@ -480,6 +597,7 @@ var Link = React__namespace.forwardRef(
480
597
  ]
481
598
  }
482
599
  );
600
+ return body.tooltipContent ? /* @__PURE__ */ jsxRuntime.jsx(EllipsisTooltip, { ref, content: body.tooltipContent, children: element }) : element;
483
601
  }
484
602
  );
485
603
  Link.displayName = "Typography.Link";
package/dist/index.cjs CHANGED
@@ -3,8 +3,8 @@
3
3
  var chunkIHK2FRTS_cjs = require('./chunk-IHK2FRTS.cjs');
4
4
  var chunkLFTCK2VM_cjs = require('./chunk-LFTCK2VM.cjs');
5
5
  var chunkBJ6WUVEG_cjs = require('./chunk-BJ6WUVEG.cjs');
6
- var chunkF3LHLYX6_cjs = require('./chunk-F3LHLYX6.cjs');
7
- var chunk5JPAUQ5H_cjs = require('./chunk-5JPAUQ5H.cjs');
6
+ var chunkRIUDYPRB_cjs = require('./chunk-RIUDYPRB.cjs');
7
+ var chunkYU5JK247_cjs = require('./chunk-YU5JK247.cjs');
8
8
  var chunkZWCDB5PP_cjs = require('./chunk-ZWCDB5PP.cjs');
9
9
  var chunkSG42F5VB_cjs = require('./chunk-SG42F5VB.cjs');
10
10
  var chunkN3OLFKV5_cjs = require('./chunk-N3OLFKV5.cjs');
@@ -51,7 +51,7 @@ var chunkACQSRMLF_cjs = require('./chunk-ACQSRMLF.cjs');
51
51
  var chunk6LARTGLP_cjs = require('./chunk-6LARTGLP.cjs');
52
52
 
53
53
  // src/index.ts
54
- var VERSION = "0.6.4";
54
+ var VERSION = "0.6.6";
55
55
 
56
56
  Object.defineProperty(exports, "Tabs", {
57
57
  enumerable: true,
@@ -75,27 +75,27 @@ Object.defineProperty(exports, "Timeline", {
75
75
  });
76
76
  Object.defineProperty(exports, "Tooltip", {
77
77
  enumerable: true,
78
- get: function () { return chunkF3LHLYX6_cjs.Tooltip; }
78
+ get: function () { return chunkRIUDYPRB_cjs.Tooltip; }
79
79
  });
80
80
  Object.defineProperty(exports, "Link", {
81
81
  enumerable: true,
82
- get: function () { return chunk5JPAUQ5H_cjs.Link; }
82
+ get: function () { return chunkYU5JK247_cjs.Link; }
83
83
  });
84
84
  Object.defineProperty(exports, "Paragraph", {
85
85
  enumerable: true,
86
- get: function () { return chunk5JPAUQ5H_cjs.Paragraph; }
86
+ get: function () { return chunkYU5JK247_cjs.Paragraph; }
87
87
  });
88
88
  Object.defineProperty(exports, "Text", {
89
89
  enumerable: true,
90
- get: function () { return chunk5JPAUQ5H_cjs.Text; }
90
+ get: function () { return chunkYU5JK247_cjs.Text; }
91
91
  });
92
92
  Object.defineProperty(exports, "Title", {
93
93
  enumerable: true,
94
- get: function () { return chunk5JPAUQ5H_cjs.Title; }
94
+ get: function () { return chunkYU5JK247_cjs.Title; }
95
95
  });
96
96
  Object.defineProperty(exports, "Typography", {
97
97
  enumerable: true,
98
- get: function () { return chunk5JPAUQ5H_cjs.Typography; }
98
+ get: function () { return chunkYU5JK247_cjs.Typography; }
99
99
  });
100
100
  Object.defineProperty(exports, "Slider", {
101
101
  enumerable: true,
package/dist/index.d.cts CHANGED
@@ -49,6 +49,6 @@ import 'react/jsx-runtime';
49
49
  import 'react';
50
50
 
51
51
  /** Package version — bumped by release scripts. */
52
- declare const VERSION = "0.6.4";
52
+ declare const VERSION = "0.6.6";
53
53
 
54
54
  export { VERSION };
package/dist/index.d.ts CHANGED
@@ -49,6 +49,6 @@ import 'react/jsx-runtime';
49
49
  import 'react';
50
50
 
51
51
  /** Package version — bumped by release scripts. */
52
- declare const VERSION = "0.6.4";
52
+ declare const VERSION = "0.6.6";
53
53
 
54
54
  export { VERSION };
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  export { Tabs } from './chunk-TVUBGXWA.js';
2
2
  export { THEME_PANEL_DEFAULT_PRESET_OPTIONS, THEME_PANEL_DEFAULT_THEME_PRESETS, ThemePanel } from './chunk-NJCHFXGC.js';
3
3
  export { Timeline } from './chunk-OQU3TJCF.js';
4
- export { Tooltip } from './chunk-XHQGMMH7.js';
5
- export { Link, Paragraph, Text, Title, Typography } from './chunk-BCFCSVGJ.js';
4
+ export { Tooltip } from './chunk-SFAGHPBT.js';
5
+ export { Link, Paragraph, Text, Title, Typography } from './chunk-5JNDDWFZ.js';
6
6
  export { Slider } from './chunk-HU7T64Y3.js';
7
7
  export { Spin } from './chunk-Y5F7ZTBH.js';
8
8
  export { Splitter } from './chunk-7ZNGHWVS.js';
@@ -49,6 +49,6 @@ export { Calendar } from './chunk-CEZ2DR4R.js';
49
49
  export { AimOutlined, AppstoreOutlined, BarChartOutlined, BlockOutlined, BorderOutlined, CameraOutlined, CaretDownOutlined, CaretUpOutlined, CheckCircleFilled, CheckCircleOutlined, CheckOutlined, ClockCircleFilled, CloseCircleOutlined, CloseOutlined, CopyOutlined, DashboardOutlined, DeleteOutlined, DownOutlined, EnvironmentOutlined, ExclamationCircleOutlined, FolderOpenOutlined, ICON_NAMES, Icon, LeftOutlined, LoadingOutlined, MinusCircleOutlined, MinusOutlined, NAMED_ICON_MAP, PictureOutlined, PlusOutlined, QqOutlined, ReloadOutlined, RightOutlined, RobotOutlined, SearchOutlined, SettingOutlined, StarFilled, StarOutlined, SwapOutlined, SwapRightOutlined, SyncOutlined, ThunderboltOutlined, TranslationOutlined, UnorderedListOutlined, UserOutlined, isIconName, renderIconSlot, resolveIconName } from './chunk-YT5NLCRC.js';
50
50
 
51
51
  // src/index.ts
52
- var VERSION = "0.6.4";
52
+ var VERSION = "0.6.6";
53
53
 
54
54
  export { VERSION };
package/dist/styles.css CHANGED
@@ -1763,6 +1763,8 @@ input, textarea, select { font-family: inherit; color: inherit; }
1763
1763
  align-self: flex-start;
1764
1764
  }
1765
1765
  .tip {
1766
+ display: block;
1767
+ box-sizing: border-box;
1766
1768
  background: var(--bg-sunken);
1767
1769
  color: var(--fg);
1768
1770
  padding: 6px 10px;
@@ -1771,7 +1773,7 @@ input, textarea, select { font-family: inherit; color: inherit; }
1771
1773
  font-weight: 500;
1772
1774
  white-space: nowrap;
1773
1775
  box-shadow: var(--neu-shadow-control);
1774
- pointer-events: none;
1776
+ pointer-events: auto;
1775
1777
  animation: fadeIn var(--dur) var(--ease);
1776
1778
  z-index: 1000;
1777
1779
  }
@@ -2986,7 +2988,7 @@ input, textarea, select { font-family: inherit; color: inherit; }
2986
2988
  .typo-link.disabled {
2987
2989
  color: var(--fg-subtle);
2988
2990
  cursor: not-allowed;
2989
- pointer-events: none;
2991
+ pointer-events: auto;
2990
2992
  text-decoration: none;
2991
2993
  }
2992
2994
  .typo-link-ext {
@@ -3002,16 +3004,21 @@ input, textarea, select { font-family: inherit; color: inherit; }
3002
3004
  display: inline-flex;
3003
3005
  align-items: center;
3004
3006
  justify-content: center;
3005
- width: 22px;
3006
- height: 22px;
3007
- margin-left: 6px;
3008
- border-radius: 7px;
3007
+ width: 20px;
3008
+ height: 20px;
3009
+ margin-left: 5px;
3010
+ border-radius: 6px;
3009
3011
  cursor: pointer;
3010
3012
  color: var(--fg-subtle);
3013
+ line-height: 1;
3011
3014
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
3012
- vertical-align: middle;
3015
+ vertical-align: -0.18em;
3013
3016
  user-select: none;
3014
3017
  }
3018
+ .typo-action > svg {
3019
+ display: block;
3020
+ flex-shrink: 0;
3021
+ }
3015
3022
  .typo-action:hover {
3016
3023
  color: var(--accent-ink);
3017
3024
  background: var(--bg);
@@ -3092,6 +3099,30 @@ input, textarea, select { font-family: inherit; color: inherit; }
3092
3099
  user-select: none;
3093
3100
  }
3094
3101
  .typo-expand:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
3102
+ .typo-ellipsis-tooltip {
3103
+ display: block;
3104
+ box-sizing: border-box;
3105
+ max-width: min(520px, calc(100vw - 32px));
3106
+ padding: 7px 10px;
3107
+ border-radius: var(--r-sm);
3108
+ background: var(--bg-sunken);
3109
+ color: var(--fg);
3110
+ box-shadow: var(--neu-shadow-control);
3111
+ font-size: 12px;
3112
+ font-weight: 500;
3113
+ line-height: 1.55;
3114
+ white-space: normal;
3115
+ line-break: auto;
3116
+ text-wrap: wrap;
3117
+ text-align: justify;
3118
+ text-align-last: left;
3119
+ text-justify: inter-character;
3120
+ word-break: normal;
3121
+ overflow-wrap: anywhere;
3122
+ pointer-events: auto;
3123
+ animation: fadeIn var(--dur) var(--ease);
3124
+ z-index: 1000;
3125
+ }
3095
3126
  /* In dark mode, mark needs slightly higher contrast */
3096
3127
  [data-theme="dark"] .typo mark {
3097
3128
  background: color-mix(in oklch, var(--warning) 30%, transparent);
@@ -42,6 +42,7 @@ title 与 content 等价,也支持 bottomLeft 等细分位置。
42
42
  | title | `ReactNode` | — | content 的等价别名 |
43
43
  | placement | `"top" | "bottom" | "left" | "right" | ...` | `"top"` | 位置,支持 bottomLeft 等细分方向 |
44
44
  | delay | `number` | `250` | 悬浮延时 (ms) |
45
+ | closeDelay | `number` | `300` | 离开触发器或提示浮层后的关闭延时 (ms) |
45
46
  | disabled | `boolean` | `false` | 禁用提示 |
46
47
  | open / visible | `boolean` | — | 受控显示状态 |
47
48
  | overlayClassName / popupClassName | `string` | — | 浮层 className |
@@ -57,10 +57,10 @@ import { Typography } from "@fangxinyan/lumina";
57
57
 
58
58
  ### 省略截断
59
59
 
60
- 多行截断并支持「展开」。
60
+ 多行截断支持「展开」,悬停时可查看完整内容。
61
61
 
62
62
  ```tsx
63
- <Typography.Paragraph ellipsis={{ rows: 2, expandable: true }}>{long}</Typography.Paragraph>
63
+ <Typography.Paragraph ellipsis={{ rows: 2, expandable: true, tooltip: true }}>{long}</Typography.Paragraph>
64
64
  ```
65
65
 
66
66
  ### 链接
@@ -90,6 +90,16 @@ import { Typography } from "@fangxinyan/lumina";
90
90
  | ellipsis | `boolean | EllipsisConfig` | — | 截断省略 |
91
91
 
92
92
 
93
+ **EllipsisConfig**
94
+
95
+ | Prop | 类型 | 默认 | 说明 |
96
+ | --- | --- | --- | --- |
97
+ | rows | `number` | `1` | 截断行数 |
98
+ | expandable | `boolean` | `false` | 显示展开入口 |
99
+ | tooltip | `boolean | ReactNode` | `false` | 悬停显示完整内容 |
100
+ | symbol | `ReactNode` | `"展开"` | 自定义展开文案 |
101
+
102
+
93
103
  **Typography.Link**
94
104
 
95
105
  | Prop | 类型 | 默认 | 说明 |
package/docs/llms.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > 拟态风格的 React 18 组件库,目标是 Electron 桌面应用。**写给 AI 编程助手**的按需文档 —— 每个组件单独一个 `.md`,避免一次性读取全部。示例源自 playground 的 demo,可直接复制运行。
4
4
 
5
5
  - **包名**: `@fangxinyan/lumina`
6
- - **版本**: `0.6.4`
6
+ - **版本**: `0.6.6`
7
7
  - **React 最低版本**: 18
8
8
  - **环境**: 带打包器的 React 工程(Vite / Next.js / Webpack / Remix / Electron + Vite 等)
9
9
  - **零运行时依赖**: 只依赖 `react` / `react-dom` (peer deps)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fangxinyan/lumina",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
4
4
  "description": "Lumina — Neumorphic component library for Electron & React apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",