pxd 0.0.61 → 0.0.63

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.
Files changed (223) hide show
  1. package/LICENSE +21 -0
  2. package/dist/components/_internal/dismiss-container.d.vue.ts +28 -0
  3. package/dist/components/_internal/dismiss-container.vue +162 -0
  4. package/dist/components/_internal/popover-arrow.d.vue.ts +9 -0
  5. package/dist/components/_internal/popover-arrow.vue +38 -0
  6. package/dist/components/active-graph/index.vue +4 -4
  7. package/dist/components/avatar/index.vue +5 -7
  8. package/dist/components/avatar-group/index.d.vue.ts +0 -1
  9. package/dist/components/avatar-group/index.vue +1 -1
  10. package/dist/components/backtop/index.vue +1 -1
  11. package/dist/components/badge/index.d.vue.ts +5 -1
  12. package/dist/components/badge/index.vue +18 -4
  13. package/dist/components/badge/types.d.ts +5 -0
  14. package/dist/components/book/index.vue +1 -1
  15. package/dist/components/browser/index.vue +1 -1
  16. package/dist/components/bubble/index.d.vue.ts +22 -0
  17. package/dist/components/bubble/index.vue +59 -0
  18. package/dist/components/bubble/types.d.ts +6 -0
  19. package/dist/components/button/index.d.vue.ts +0 -2
  20. package/dist/components/button/index.vue +30 -21
  21. package/dist/components/button/types.d.ts +3 -2
  22. package/dist/components/button-group/index.d.vue.ts +14 -0
  23. package/dist/components/button-group/index.vue +26 -0
  24. package/dist/components/button-group/types.d.ts +9 -0
  25. package/dist/components/carousel/index.d.vue.ts +3 -3
  26. package/dist/components/carousel/index.vue +146 -113
  27. package/dist/components/carousel/types.d.ts +1 -1
  28. package/dist/components/carousel-item/index.vue +22 -17
  29. package/dist/components/checkbox/index.vue +6 -6
  30. package/dist/components/checkbox-group/index.d.vue.ts +1 -1
  31. package/dist/components/chip/index.d.vue.ts +1 -5
  32. package/dist/components/chip/index.vue +4 -4
  33. package/dist/components/color-selector/index.d.vue.ts +12 -0
  34. package/dist/components/color-selector/index.vue +64 -0
  35. package/dist/components/color-selector/types.d.ts +12 -0
  36. package/dist/components/command-menu/index.d.vue.ts +6 -6
  37. package/dist/components/command-menu/index.vue +23 -32
  38. package/dist/components/command-menu/types.d.ts +1 -1
  39. package/dist/components/command-menu-group/index.vue +15 -6
  40. package/dist/components/command-menu-group/types.d.ts +1 -1
  41. package/dist/components/countdown/index.d.vue.ts +11 -11
  42. package/dist/components/drawer/index.d.vue.ts +8 -8
  43. package/dist/components/drawer/index.vue +13 -10
  44. package/dist/components/drawer/types.d.ts +4 -3
  45. package/dist/components/ellipsis-text/index.d.vue.ts +4 -1
  46. package/dist/components/ellipsis-text/index.vue +84 -107
  47. package/dist/components/ellipsis-text/types.d.ts +2 -1
  48. package/dist/components/error/index.vue +1 -1
  49. package/dist/components/fader/index.vue +5 -9
  50. package/dist/components/gauge/index.vue +34 -29
  51. package/dist/components/grid/index.vue +1 -1
  52. package/dist/components/grid-item/index.vue +1 -1
  53. package/dist/components/hold-button/index.d.vue.ts +8 -10
  54. package/dist/components/hold-button/index.vue +20 -29
  55. package/dist/components/hold-button/types.d.ts +5 -6
  56. package/dist/components/index.d.ts +7 -0
  57. package/dist/components/index.js +7 -0
  58. package/dist/components/input/index.d.vue.ts +8 -8
  59. package/dist/components/input/index.vue +5 -4
  60. package/dist/components/intersection-observer/index.vue +4 -4
  61. package/dist/components/kbd/index.vue +1 -1
  62. package/dist/components/link-button/index.d.vue.ts +4 -4
  63. package/dist/components/link-button/index.vue +9 -8
  64. package/dist/components/link-button/types.d.ts +0 -3
  65. package/dist/components/list/index.d.vue.ts +10 -15
  66. package/dist/components/list/index.vue +58 -131
  67. package/dist/components/list/types.d.ts +4 -4
  68. package/dist/components/list-item/index.d.vue.ts +2 -2
  69. package/dist/components/list-item/index.vue +44 -39
  70. package/dist/components/loading-bar/index.vue +8 -7
  71. package/dist/components/material/index.vue +24 -46
  72. package/dist/components/menu/index.d.vue.ts +6 -8
  73. package/dist/components/menu/index.vue +18 -24
  74. package/dist/components/menu/types.d.ts +1 -2
  75. package/dist/components/message/composables/use-group-expand.d.ts +13 -0
  76. package/dist/components/message/composables/use-group-expand.js +50 -0
  77. package/dist/components/message/composables/use-message-timer.d.ts +9 -0
  78. package/dist/components/message/composables/use-message-timer.js +61 -0
  79. package/dist/components/message/composables/use-promise-message.d.ts +4 -0
  80. package/dist/components/message/composables/use-promise-message.js +49 -0
  81. package/dist/components/message/index.d.vue.ts +6 -33
  82. package/dist/components/message/index.vue +33 -185
  83. package/dist/components/message/types.d.ts +2 -2
  84. package/dist/components/message-item/index.vue +26 -2
  85. package/dist/components/modal/index.d.vue.ts +7 -7
  86. package/dist/components/modal/index.vue +7 -3
  87. package/dist/components/modal/types.d.ts +7 -3
  88. package/dist/components/note/index.vue +2 -2
  89. package/dist/components/number-input/index.d.vue.ts +5 -4
  90. package/dist/components/number-input/index.vue +3 -0
  91. package/dist/components/number-input/types.d.ts +1 -0
  92. package/dist/components/overlay/index.d.vue.ts +6 -3
  93. package/dist/components/overlay/index.vue +63 -68
  94. package/dist/components/overlay/types.d.ts +5 -4
  95. package/dist/components/pagination/index.vue +2 -2
  96. package/dist/components/pin-input/index.d.vue.ts +1 -1
  97. package/dist/components/pin-input/index.vue +7 -6
  98. package/dist/components/placeholder/index.vue +1 -1
  99. package/dist/components/popover/index.d.vue.ts +7 -8
  100. package/dist/components/popover/index.vue +149 -239
  101. package/dist/components/popover/types.d.ts +5 -5
  102. package/dist/components/progress/index.vue +1 -1
  103. package/dist/components/radio/index.vue +2 -2
  104. package/dist/components/resizable/index.vue +43 -51
  105. package/dist/components/resizable/types.d.ts +1 -1
  106. package/dist/components/resizable-handle/index.d.vue.ts +4 -1
  107. package/dist/components/resizable-handle/index.vue +29 -3
  108. package/dist/components/resizable-panel/index.vue +3 -7
  109. package/dist/components/scalable-text/index.d.vue.ts +9 -0
  110. package/dist/components/scalable-text/index.vue +147 -0
  111. package/dist/components/scalable-text/types.d.ts +12 -0
  112. package/dist/components/scrollable/index.d.vue.ts +2 -2
  113. package/dist/components/scrollable/index.vue +4 -3
  114. package/dist/components/separator/index.d.vue.ts +6 -0
  115. package/dist/components/separator/index.vue +18 -0
  116. package/dist/components/separator/types.d.ts +5 -0
  117. package/dist/components/skeleton/index.d.vue.ts +1 -1
  118. package/dist/components/slider/index.d.vue.ts +1 -1
  119. package/dist/components/slider/index.vue +39 -7
  120. package/dist/components/snippet/index.vue +16 -13
  121. package/dist/components/spinner/index.vue +3 -1
  122. package/dist/components/stack/index.d.vue.ts +1 -1
  123. package/dist/components/stack/index.vue +1 -1
  124. package/dist/components/switch/index.d.vue.ts +1 -1
  125. package/dist/components/switch/index.vue +4 -3
  126. package/dist/components/switch-item/index.vue +1 -1
  127. package/dist/components/tabs/index.d.vue.ts +12 -0
  128. package/dist/components/tabs/index.vue +270 -0
  129. package/dist/components/tabs/types.d.ts +12 -0
  130. package/dist/components/tabs-item/index.d.vue.ts +4 -0
  131. package/dist/components/tabs-item/index.vue +16 -0
  132. package/dist/components/tabs-item/types.d.ts +10 -0
  133. package/dist/components/text/index.vue +1 -1
  134. package/dist/components/textarea/index.d.vue.ts +2 -2
  135. package/dist/components/textarea/index.vue +1 -1
  136. package/dist/components/time-picker/index.d.vue.ts +3 -5
  137. package/dist/components/time-picker/index.vue +53 -45
  138. package/dist/components/time-picker/types.d.ts +1 -2
  139. package/dist/components/toggle/index.d.vue.ts +0 -2
  140. package/dist/components/toggle/index.vue +6 -6
  141. package/dist/components/toggle-button/index.vue +8 -6
  142. package/dist/components/tooltip/index.d.vue.ts +1 -1
  143. package/dist/components/tooltip/index.vue +19 -11
  144. package/dist/components/tooltip/types.d.ts +2 -2
  145. package/dist/components/virtual-list/index.d.vue.ts +8 -8
  146. package/dist/components/virtual-list/index.vue +27 -5
  147. package/dist/components/virtual-list/types.d.ts +3 -0
  148. package/dist/composables/index.d.ts +4 -1
  149. package/dist/composables/index.js +4 -1
  150. package/dist/composables/use-browser-observer.js +2 -2
  151. package/dist/composables/use-client-online.js +2 -2
  152. package/dist/composables/use-color-scheme.js +2 -2
  153. package/dist/composables/use-countdown.js +3 -2
  154. package/dist/composables/use-deferred-value.js +2 -2
  155. package/dist/composables/use-delay-destroy.js +11 -6
  156. package/dist/composables/use-document-hidden.js +2 -2
  157. package/dist/composables/use-focus-trap.js +2 -2
  158. package/dist/composables/use-list-filter.d.ts +11 -0
  159. package/dist/composables/use-list-filter.js +56 -0
  160. package/dist/composables/use-list-navigation.d.ts +27 -0
  161. package/dist/composables/use-list-navigation.js +159 -0
  162. package/dist/composables/use-lock-scroll.js +12 -12
  163. package/dist/composables/use-media-query.js +2 -2
  164. package/dist/composables/use-outside-click.d.ts +1 -1
  165. package/dist/composables/use-outside-click.js +8 -11
  166. package/dist/composables/use-overlay-manager.d.ts +18 -0
  167. package/dist/composables/use-overlay-manager.js +80 -0
  168. package/dist/composables/use-popover-responsive.d.ts +6 -8
  169. package/dist/composables/use-popover-responsive.js +9 -12
  170. package/dist/composables/use-repeat-action.js +2 -2
  171. package/dist/composables/use-swipe-gesture.d.ts +65 -0
  172. package/dist/composables/use-swipe-gesture.js +99 -0
  173. package/dist/composables/use-virtual-list.d.ts +5 -3
  174. package/dist/composables/use-virtual-list.js +25 -14
  175. package/dist/composables/use-window-size.js +2 -2
  176. package/dist/constants/size.d.ts +12 -0
  177. package/dist/constants/size.js +12 -0
  178. package/dist/contexts/button.d.ts +5 -0
  179. package/dist/contexts/button.js +5 -0
  180. package/dist/contexts/carousel.d.ts +2 -1
  181. package/dist/contexts/list.d.ts +23 -3
  182. package/dist/contexts/list.js +6 -2
  183. package/dist/contexts/resizable.d.ts +3 -11
  184. package/dist/contexts/tabs.d.ts +15 -0
  185. package/dist/contexts/tabs.js +2 -0
  186. package/dist/locales/en-us.d.ts +4 -4
  187. package/dist/locales/en-us.js +4 -4
  188. package/dist/locales/zh-cn.d.ts +4 -4
  189. package/dist/locales/zh-cn.js +4 -4
  190. package/dist/plugins/dayjs-millisecond-token.js +1 -1
  191. package/dist/styles/source.css +133 -128
  192. package/dist/styles/styles.css +2 -2
  193. package/dist/styles/tw.css +133 -128
  194. package/dist/types/shared/props.d.ts +1 -0
  195. package/dist/types/shared/utils.d.ts +1 -4
  196. package/dist/utils/date.d.ts +3 -3
  197. package/dist/utils/dom.d.ts +1 -0
  198. package/dist/utils/dom.js +4 -0
  199. package/dist/utils/event.d.ts +2 -1
  200. package/dist/utils/event.js +7 -1
  201. package/dist/utils/format.d.ts +3 -3
  202. package/dist/utils/format.js +5 -4
  203. package/dist/utils/fuzzy-search.d.ts +7 -0
  204. package/dist/utils/fuzzy-search.js +61 -0
  205. package/dist/utils/get.d.ts +2 -0
  206. package/dist/utils/get.js +15 -1
  207. package/dist/utils/index.d.ts +10 -11
  208. package/dist/utils/index.js +2 -3
  209. package/dist/utils/ref.d.ts +2 -2
  210. package/dist/utils/{throttle.d.ts → timing.d.ts} +1 -0
  211. package/dist/utils/{throttle.js → timing.js} +4 -2
  212. package/package.json +40 -37
  213. package/volar.d.ts +7 -0
  214. package/dist/components/overlay/overlay-stack.d.ts +0 -3
  215. package/dist/components/overlay/overlay-stack.js +0 -17
  216. package/dist/composables/use-pointer-gesture.d.ts +0 -180
  217. package/dist/composables/use-pointer-gesture.js +0 -406
  218. package/dist/utils/debounce.d.ts +0 -1
  219. package/dist/utils/debounce.js +0 -1
  220. package/dist/utils/regexp.d.ts +0 -8
  221. package/dist/utils/regexp.js +0 -8
  222. package/dist/utils/responsive.d.ts +0 -3
  223. package/dist/utils/responsive.js +0 -14
@@ -1,4 +1,6 @@
1
1
  <script setup>
2
+ import { prepareWithSegments, layoutWithLines } from "@chenglou/pretext";
3
+ import { prepareRichInline, measureRichInlineStats } from "@chenglou/pretext/rich-inline";
2
4
  import { twMerge } from "tailwind-merge";
3
5
  import { shallowRef, computed, nextTick, watch } from "vue";
4
6
  import { useResizeObserver } from "../../composables/use-browser-observer";
@@ -16,15 +18,16 @@ const props = defineProps({
16
18
  position: { type: String, required: false, default: "end" },
17
19
  moreText: { type: String, required: false, default: "Expand" },
18
20
  lessText: { type: String, required: false, default: "Collapse" },
19
- actionClass: { type: String, required: false }
21
+ moreActionClass: { type: String, required: false },
22
+ lessActionClass: { type: String, required: false }
20
23
  });
21
24
  const emits = defineEmits(["toggle"]);
22
25
  const isExpanded = shallowRef(false);
23
- const isTruncated = shallowRef(false);
26
+ const isOverflow = shallowRef(false);
24
27
  const ellipsisText = shallowRef(props.text);
25
- const containerRef = shallowRef();
26
28
  const textRef = shallowRef();
27
29
  const actionRef = shallowRef();
30
+ const containerRef = shallowRef();
28
31
  const maxRows = computed(() => {
29
32
  const rows = Number(props.rows ?? 1);
30
33
  return Number.isFinite(rows) && rows > 0 ? Math.floor(rows) : 1;
@@ -32,7 +35,7 @@ const maxRows = computed(() => {
32
35
  const computedActionClass = computed(() => {
33
36
  return twMerge(
34
37
  "pxd-ellipsis-text--action cursor-pointer whitespace-nowrap text-blue-900",
35
- props.actionClass
38
+ isExpanded.value ? props.lessActionClass : props.moreActionClass
36
39
  );
37
40
  });
38
41
  const displayText = computed(() => {
@@ -55,18 +58,6 @@ function toggleAction() {
55
58
  emits("toggle", isExpanded.value);
56
59
  updateEllipsis();
57
60
  }
58
- const TEXT_STYLE_KEYS = [
59
- "fontFamily",
60
- "fontSize",
61
- "fontWeight",
62
- "fontStyle",
63
- "fontVariant",
64
- "letterSpacing",
65
- "lineHeight",
66
- "textTransform",
67
- "textRendering",
68
- "wordSpacing"
69
- ];
70
61
  function parseSize(value) {
71
62
  const parsed = Number.parseFloat(value);
72
63
  return Number.isFinite(parsed) ? parsed : 0;
@@ -83,74 +74,39 @@ function getLineHeightPx(style) {
83
74
  }
84
75
  return parsed;
85
76
  }
86
- function applyTextStyles(style, target) {
87
- TEXT_STYLE_KEYS.forEach((key) => {
88
- target.style.setProperty(
89
- key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`),
90
- style[key]
91
- );
92
- });
93
- target.style.display = "inline";
94
- target.style.whiteSpace = "pre-wrap";
95
- target.style.wordBreak = "break-word";
77
+ function getFontShorthand(style) {
78
+ const fontStyle = style.fontStyle || "normal";
79
+ const fontWeight = style.fontWeight || "400";
80
+ const fontSize = style.fontSize || "16px";
81
+ const fontFamily = style.fontFamily || "sans-serif";
82
+ return `${fontStyle} ${fontWeight} ${fontSize} ${fontFamily}`;
83
+ }
84
+ function getAvailableWidth(container) {
85
+ const containerStyle = getStyle(container);
86
+ const paddingLeft = parseSize(containerStyle.paddingLeft);
87
+ const paddingRight = parseSize(containerStyle.paddingRight);
88
+ return Math.max(0, container.clientWidth - paddingLeft - paddingRight);
89
+ }
90
+ function measureLineCount(text, textFont, maxWidth, actionText, actionFont) {
91
+ const items = [{ text, font: textFont }];
92
+ if (actionText) {
93
+ items.push({ text: actionText, font: actionFont || textFont, break: "never" });
94
+ }
95
+ return measureRichInlineStats(prepareRichInline(items), maxWidth).lineCount;
96
+ }
97
+ function joinChars(chars, start, end) {
98
+ return chars.slice(start, end).join("");
96
99
  }
97
100
  function buildCandidate(chars, keep, dots, position) {
98
101
  if (keep <= 0) {
99
102
  return dots;
100
103
  }
101
104
  if (position === "start") {
102
- return `${dots}${chars.slice(chars.length - keep).join("")}`;
105
+ return `${dots}${joinChars(chars, chars.length - keep, chars.length)}`;
103
106
  }
104
- if (position === "middle") {
105
- const headLen = Math.ceil(keep / 2);
106
- const tailLen = keep - headLen;
107
- const head = chars.slice(0, headLen).join("");
108
- const tail = chars.slice(chars.length - tailLen).join("");
109
- return `${head}${dots}${tail}`;
110
- }
111
- return `${chars.slice(0, keep).join("")}${dots}`;
112
- }
113
- function createMeasureElements(parent) {
114
- const mc = document.createElement("span");
115
- const mt = document.createElement("span");
116
- const ma = document.createElement("span");
117
- mc.append(mt, ma);
118
- mc.style.position = "absolute";
119
- mc.style.visibility = "hidden";
120
- mc.style.pointerEvents = "none";
121
- mc.style.zIndex = "-1";
122
- mc.style.left = "0";
123
- mc.style.top = "0";
124
- mc.style.overflow = "visible";
125
- mc.style.whiteSpace = "pre-wrap";
126
- mc.style.wordBreak = "break-word";
127
- mc.style.display = "block";
128
- mc.style.boxSizing = "border-box";
129
- parent.appendChild(mc);
130
- return { container: mc, text: mt, action: ma };
131
- }
132
- function syncMeasureStyles(elements, container, textEl, actionEl) {
133
- const containerStyle = getStyle(container);
134
- const paddingLeft = parseSize(containerStyle.paddingLeft);
135
- const paddingRight = parseSize(containerStyle.paddingRight);
136
- const availableWidth = Math.max(0, container.clientWidth - paddingLeft - paddingRight);
137
- elements.container.style.width = `${availableWidth}px`;
138
- const textStyle = getStyle(textEl ?? container);
139
- applyTextStyles(textStyle, elements.text);
140
- const actionStyle = actionEl ? getStyle(actionEl) : textStyle;
141
- applyTextStyles(actionStyle, elements.action);
142
- }
143
- function fits(elements, text, actionText, maxHeight) {
144
- elements.text.textContent = text;
145
- if (actionText) {
146
- elements.action.textContent = actionText;
147
- elements.action.style.display = "inline";
148
- } else {
149
- elements.action.textContent = "";
150
- elements.action.style.display = "none";
151
- }
152
- const height = elements.container.getBoundingClientRect().height;
153
- return height <= maxHeight + 0.5;
107
+ const headLen = Math.ceil(keep / 2);
108
+ const tailLen = keep - headLen;
109
+ return `${joinChars(chars, 0, headLen)}${dots}${joinChars(chars, chars.length - tailLen, chars.length)}`;
154
110
  }
155
111
  async function updateEllipsis() {
156
112
  if (isServer()) {
@@ -164,7 +120,7 @@ async function updateEllipsis() {
164
120
  const sourceText = props.text ?? "";
165
121
  if (container.clientWidth <= 0) {
166
122
  ellipsisText.value = sourceText;
167
- isTruncated.value = false;
123
+ isOverflow.value = false;
168
124
  return;
169
125
  }
170
126
  if (isExpanded.value || !sourceText) {
@@ -173,41 +129,58 @@ async function updateEllipsis() {
173
129
  }
174
130
  const style = getStyle(textRef.value ?? container);
175
131
  const lineHeight = getLineHeightPx(style);
176
- const maxHeight = lineHeight * maxRows.value;
177
- if (maxHeight <= 0) {
132
+ if (lineHeight <= 0) {
178
133
  ellipsisText.value = sourceText;
179
- isTruncated.value = false;
134
+ isOverflow.value = false;
180
135
  return;
181
136
  }
182
- const elements = createMeasureElements(container);
183
- try {
184
- syncMeasureStyles(elements, container, textRef.value, actionRef.value);
185
- if (fits(elements, sourceText, "", maxHeight)) {
186
- ellipsisText.value = sourceText;
187
- isTruncated.value = false;
188
- return;
189
- }
190
- isTruncated.value = true;
191
- const actionText = props.action ? props.moreText : "";
192
- const chars = [...sourceText];
193
- const dots = props.dots ?? "";
194
- let low = 0;
195
- let high = chars.length;
196
- let best = "";
197
- while (low <= high) {
198
- const mid = Math.floor((low + high) / 2);
199
- const candidate = buildCandidate(chars, mid, dots, props.position);
200
- if (fits(elements, candidate, actionText, maxHeight)) {
201
- best = candidate;
202
- low = mid + 1;
137
+ const availableWidth = getAvailableWidth(container);
138
+ const textFont = getFontShorthand(style);
139
+ if (measureLineCount(sourceText, textFont, availableWidth) <= maxRows.value) {
140
+ ellipsisText.value = sourceText;
141
+ isOverflow.value = false;
142
+ return;
143
+ }
144
+ isOverflow.value = true;
145
+ const actionText = props.action ? props.moreText : "";
146
+ const actionFont = actionRef.value ? getFontShorthand(getStyle(actionRef.value)) : textFont;
147
+ const dots = props.dots ?? "";
148
+ if (props.position === "end") {
149
+ const prepared = prepareWithSegments(sourceText, textFont);
150
+ const { lines } = layoutWithLines(prepared, availableWidth, lineHeight);
151
+ const baseText = lines.slice(0, maxRows.value).map((l) => l.text).join("");
152
+ const baseChars = [...baseText];
153
+ let low2 = 0;
154
+ let high2 = baseChars.length;
155
+ let best2 = "";
156
+ while (low2 <= high2) {
157
+ const mid = Math.floor((low2 + high2) / 2);
158
+ const candidate = `${joinChars(baseChars, 0, mid)}${dots}`;
159
+ if (measureLineCount(candidate, textFont, availableWidth, actionText, actionFont) <= maxRows.value) {
160
+ best2 = candidate;
161
+ low2 = mid + 1;
203
162
  } else {
204
- high = mid - 1;
163
+ high2 = mid - 1;
205
164
  }
206
165
  }
207
- ellipsisText.value = best || dots;
208
- } finally {
209
- elements.container.remove();
166
+ ellipsisText.value = best2 || dots;
167
+ return;
168
+ }
169
+ const chars = [...sourceText];
170
+ let low = 0;
171
+ let high = chars.length;
172
+ let best = "";
173
+ while (low <= high) {
174
+ const mid = Math.floor((low + high) / 2);
175
+ const candidate = buildCandidate(chars, mid, dots, props.position);
176
+ if (measureLineCount(candidate, textFont, availableWidth, actionText, actionFont) <= maxRows.value) {
177
+ best = candidate;
178
+ low = mid + 1;
179
+ } else {
180
+ high = mid - 1;
181
+ }
210
182
  }
183
+ ellipsisText.value = best || dots;
211
184
  }
212
185
  watch(
213
186
  () => props,
@@ -224,6 +197,10 @@ watch(
224
197
  }
225
198
  );
226
199
  useResizeObserver(containerRef, updateEllipsis);
200
+ defineExpose({
201
+ isExpanded,
202
+ isOverflow
203
+ });
227
204
  </script>
228
205
 
229
206
  <template>
@@ -231,7 +208,7 @@ useResizeObserver(containerRef, updateEllipsis);
231
208
  <span ref="textRef" class="pxd-ellipsis-text--text">{{ displayText.content }}</span>
232
209
 
233
210
  <span
234
- v-if="action && (isTruncated || isExpanded)"
211
+ v-if="action && (isOverflow || isExpanded)"
235
212
  ref="actionRef"
236
213
  :class="computedActionClass"
237
214
  @click="toggleAction"
@@ -6,7 +6,8 @@ export interface EllipsisTextProps {
6
6
  position?: 'start' | 'middle' | 'end'
7
7
  moreText?: string
8
8
  lessText?: string
9
- actionClass?: string
9
+ moreActionClass?: string
10
+ lessActionClass?: string
10
11
  }
11
12
 
12
13
  export interface EllipsisTextEmits {
@@ -19,7 +19,7 @@ const errorVariant = tv({
19
19
  variants: {
20
20
  size: {
21
21
  xs: "text-xs [--mt:0.125rem]",
22
- sm: "text-13px [--mt:0.125rem]",
22
+ sm: "text-13 [--mt:0.125rem]",
23
23
  md: "text-sm [--mt:0.125rem]",
24
24
  lg: "text-base [--mt:0.25rem]"
25
25
  }
@@ -4,7 +4,7 @@ import { useResizeObserver } from "../../composables/use-browser-observer";
4
4
  import { cachedOff, cachedOn } from "../../utils/event";
5
5
  import { getCssUnitValue } from "../../utils/format";
6
6
  import { unrefElement } from "../../utils/ref";
7
- import { throttleByRaf } from "../../utils/throttle";
7
+ import { throttleByRaf } from "../../utils/timing";
8
8
  defineOptions({
9
9
  name: "PFader",
10
10
  inheritAttrs: false
@@ -95,12 +95,8 @@ onBeforeUnmount(() => {
95
95
  content: '';
96
96
  position: absolute;
97
97
  border-radius: inherit;
98
- background: linear-gradient(var(--dir), transparent, var(--fader-color, var(--color-gray-100)));
99
- mask-image: linear-gradient(
100
- var(--dir-revert),
101
- var(--fader-color, var(--color-gray-100)) 50%,
102
- transparent
103
- );
98
+ background: linear-gradient(var(--dir), transparent, var(--fader-color));
99
+ mask-image: linear-gradient(var(--dir-revert), var(--fader-color) 50%, transparent);
104
100
  transition-property: opacity;
105
101
  opacity: 0;
106
102
  }
@@ -116,7 +112,7 @@ onBeforeUnmount(() => {
116
112
  &::before,
117
113
  &::after {
118
114
  top: 0;
119
- width: var(--fader-size, 16px);
115
+ width: var(--fader-size);
120
116
  height: 100%;
121
117
  }
122
118
 
@@ -138,7 +134,7 @@ onBeforeUnmount(() => {
138
134
  &::after {
139
135
  left: 0;
140
136
  width: 100%;
141
- height: var(--fader-size, 16px);
137
+ height: var(--fader-size);
142
138
  }
143
139
 
144
140
  &::before {
@@ -27,6 +27,7 @@ const SIZES = {
27
27
  const PROGRESS_BAR_GAP = 5;
28
28
  const MIN_VISIBLE_TRACK = PROGRESS_BAR_GAP * 2;
29
29
  const RADIUS = 42;
30
+ const STROKE_WIDTH = 10;
30
31
  const CIRCUMFERENCE = 2 * Math.PI * RADIUS;
31
32
  const GAP_LENGTH = PROGRESS_BAR_GAP / 100 * CIRCUMFERENCE;
32
33
  const defaultColors = {
@@ -47,8 +48,8 @@ const progressArc = computed(() => {
47
48
  return progress.value / 100 * CIRCUMFERENCE;
48
49
  }
49
50
  const baseArc = progress.value / 100 * CIRCUMFERENCE;
50
- const visualCorrection = 8;
51
- return Math.max(0, baseArc - visualCorrection);
51
+ const roundCapTrim = STROKE_WIDTH;
52
+ return Math.max(0, baseArc - roundCapTrim);
52
53
  });
53
54
  const progressStatus = computed(() => {
54
55
  const _progress = progress.value;
@@ -106,38 +107,42 @@ const progressColors = computed(() => {
106
107
  v-bind="$attrs"
107
108
  >
108
109
  <svg
109
- class="pxd-gauge--svg block size-(--gauge-size) -rotate-85 overflow-visible"
110
+ class="pxd-gauge--svg block size-(--gauge-size) overflow-visible"
110
111
  aria-hidden="true"
111
112
  fill="none"
112
113
  viewBox="0 0 100 100"
113
114
  >
114
- <circle
115
- v-if="progressStatus.hasProgress"
116
- cx="50"
117
- cy="50"
118
- fill="none"
119
- :r="RADIUS"
120
- stroke-width="10"
121
- stroke-dashoffset="0"
122
- stroke-linecap="round"
123
- :stroke="progressColors.primary"
124
- class="pxd-gauge--bar motion-safe:transition-all"
125
- :stroke-dasharray="`${progressArc} ${CIRCUMFERENCE}`"
126
- />
115
+ <g transform="rotate(-83 50 50)">
116
+ <circle
117
+ v-if="shouldShowTrack"
118
+ cx="50"
119
+ cy="50"
120
+ fill="none"
121
+ :r="RADIUS"
122
+ :stroke-width="STROKE_WIDTH"
123
+ stroke-linecap="round"
124
+ :stroke-dashoffset="trackOffset"
125
+ :stroke="progressColors.secondary"
126
+ class="pxd-gauge--track motion-safe:transition-appearance"
127
+ :stroke-dasharray="
128
+ progressStatus.hasProgress ? `${trackArc} ${CIRCUMFERENCE}` : void 0
129
+ "
130
+ />
127
131
 
128
- <circle
129
- v-if="shouldShowTrack"
130
- cx="50"
131
- cy="50"
132
- fill="none"
133
- :r="RADIUS"
134
- stroke-width="10"
135
- stroke-linecap="round"
136
- :stroke-dashoffset="trackOffset"
137
- :stroke="progressColors.secondary"
138
- class="pxd-gauge--track motion-safe:transition-all"
139
- :stroke-dasharray="progressStatus.hasProgress ? `${trackArc} ${CIRCUMFERENCE}` : void 0"
140
- />
132
+ <circle
133
+ v-if="progressStatus.hasProgress || progressStatus.isComplete"
134
+ cx="50"
135
+ cy="50"
136
+ fill="none"
137
+ :r="RADIUS"
138
+ :stroke-width="STROKE_WIDTH"
139
+ stroke-dashoffset="0"
140
+ stroke-linecap="round"
141
+ :stroke="progressColors.primary"
142
+ class="pxd-gauge--bar motion-safe:transition-appearance"
143
+ :stroke-dasharray="`${progressArc} ${CIRCUMFERENCE}`"
144
+ />
145
+ </g>
141
146
  </svg>
142
147
 
143
148
  <div
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import { computed } from "vue";
3
- import { getResponsiveValue } from "../../utils/responsive";
3
+ import { getResponsiveValue } from "../../utils/get";
4
4
  defineOptions({
5
5
  name: "PGrid",
6
6
  inheritAttrs: false
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import { computed } from "vue";
3
- import { getResponsiveValue } from "../../utils/responsive";
3
+ import { getResponsiveValue } from "../../utils/get";
4
4
  defineOptions({
5
5
  name: "PGridItem",
6
6
  inheritAttrs: false
@@ -8,22 +8,20 @@ type __VLS_Slots = {} & {
8
8
  suffix?: (props: typeof __VLS_18) => any;
9
9
  };
10
10
  declare const __VLS_base: import("vue").DefineComponent<HoldButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
- pointerdown: (args_0: PointerEvent) => any;
12
- pointerup: (args_0: PointerEvent) => any;
13
- finished: (args_0: boolean) => any;
11
+ cancel: () => any;
14
12
  confirm: () => any;
15
- canceled: () => any;
13
+ release: (confirmed: boolean) => any;
14
+ pointerup: (args_0: PointerEvent) => any;
15
+ pointerdown: (args_0: PointerEvent) => any;
16
16
  }, string, import("vue").PublicProps, Readonly<HoldButtonProps> & Readonly<{
17
- onPointerdown?: ((args_0: PointerEvent) => any) | undefined;
18
- onPointerup?: ((args_0: PointerEvent) => any) | undefined;
19
- onFinished?: ((args_0: boolean) => any) | undefined;
17
+ onCancel?: (() => any) | undefined;
20
18
  onConfirm?: (() => any) | undefined;
21
- onCanceled?: (() => any) | undefined;
19
+ onRelease?: ((confirmed: boolean) => any) | undefined;
20
+ onPointerup?: ((args_0: PointerEvent) => any) | undefined;
21
+ onPointerdown?: ((args_0: PointerEvent) => any) | undefined;
22
22
  }>, {
23
- durations: number | string;
24
23
  vibrate: boolean;
25
24
  scalable: boolean;
26
- maskColor: string;
27
25
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
26
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
29
27
  declare const _default: typeof __VLS_export;
@@ -1,51 +1,44 @@
1
1
  <script setup>
2
- import { computed, onBeforeUnmount, shallowRef } from "vue";
2
+ import { computed, onBeforeUnmount, shallowRef, useAttrs } from "vue";
3
3
  import { getStyle } from "../../utils/dom";
4
4
  import { off, once } from "../../utils/event";
5
5
  import PButton from "../button/index.vue";
6
6
  defineOptions({
7
- name: "PHoldButton"
7
+ name: "PHoldButton",
8
+ inheritAttrs: false
8
9
  });
9
10
  const props = defineProps({
10
11
  vibrate: { type: Boolean, required: false, default: true },
12
+ disabled: { type: Boolean, required: false },
11
13
  scalable: { type: Boolean, required: false, default: true },
12
- durations: { type: [Number, String], required: false, default: 2e3 },
13
- maskColor: { type: String, required: false, default: "var(--color-gray-alpha-600)" },
14
+ durations: { type: [Number, String], required: false },
14
15
  cancelable: { type: Boolean, required: false },
15
- variant: { type: String, required: false },
16
- size: { type: String, required: false },
17
- shape: { type: String, required: false },
18
- align: { type: String, required: false },
19
- icon: { type: Boolean, required: false },
20
- loading: { type: Boolean, required: false },
21
- disabled: { type: Boolean, required: false },
22
- fullWidth: { type: Boolean, required: false }
16
+ progressColor: { type: String, required: false }
23
17
  });
24
- const emits = defineEmits(["confirm", "canceled", "finished", "pointerup", "pointerdown"]);
18
+ const emits = defineEmits(["cancel", "confirm", "release", "pointerup", "pointerdown"]);
19
+ const attrs = useAttrs();
25
20
  const status = shallowRef("idle");
26
21
  const computedAttrs = computed(() => {
27
- const { scalable, durations, maskColor, cancelable, ...rest } = props;
28
22
  return {
29
23
  class: [
30
- "pxd-hold-button relative motion-safe:transition-all",
24
+ "pxd-hold-button relative motion-safe:transition-appearance",
31
25
  {
32
- scalable,
26
+ scalable: props.scalable,
33
27
  effective: status.value !== "canceled"
34
28
  }
35
29
  ],
36
- ...rest
30
+ ...attrs
37
31
  };
38
32
  });
39
33
  const computedStyle = computed(() => {
40
- const { durations, maskColor } = props;
34
+ const { durations, progressColor } = props;
41
35
  let _durations = Number(durations);
42
36
  if (Number.isNaN(_durations) || _durations < 0) {
43
- console.warn("Invalid durations value provided to PHoldButton, defaulting to 2000");
44
37
  _durations = 2e3;
45
38
  }
46
39
  return {
47
40
  "--hold-button-durations": `${_durations}ms`,
48
- "--hold-button-mask-color": maskColor
41
+ "--hold-button-progress-color": progressColor
49
42
  };
50
43
  });
51
44
  function onTriggerVibrate() {
@@ -75,7 +68,7 @@ function onPointerLeave(e) {
75
68
  }
76
69
  if (status.value === "loading" || status.value === "confirmed") {
77
70
  status.value = "canceled";
78
- emits("canceled");
71
+ emits("cancel");
79
72
  }
80
73
  }
81
74
  function onPointerDown(event) {
@@ -93,7 +86,7 @@ function onPointerUp(event) {
93
86
  }
94
87
  const isConfirmed = status.value === "confirmed";
95
88
  status.value = "idle";
96
- emits("finished", isConfirmed);
89
+ emits("release", isConfirmed);
97
90
  emits("pointerup", event);
98
91
  onTriggerVibrate();
99
92
  cleanPointerReleaseEvents();
@@ -139,8 +132,8 @@ onBeforeUnmount(() => {
139
132
  <template #suffix>
140
133
  <slot name="suffix" />
141
134
  <div
142
- class="pxd-hold-button--overlay pointer-events-none absolute -inset-px rounded-inherit bg-(--hold-button-mask-color) default-transition-timing-function!"
143
- :class="{ finished: status === 'confirmed' }"
135
+ class="pxd-hold-button--overlay pointer-events-none absolute -inset-px rounded-inherit bg-(--hold-button-progress-color) default-transition-timing-function!"
136
+ :class="{ confirmed: status === 'confirmed' }"
144
137
  :style="computedStyle"
145
138
  @transitionend="onTransitionEnd"
146
139
  />
@@ -154,10 +147,8 @@ onBeforeUnmount(() => {
154
147
  transform: scale(0.97);
155
148
  }
156
149
 
157
- &:hover {
158
- .pxd-hold-button--overlay {
159
- will-change: clip-path;
160
- }
150
+ &:hover .pxd-hold-button--overlay {
151
+ will-change: clip-path;
161
152
  }
162
153
 
163
154
  .pxd-hold-button--overlay {
@@ -168,7 +159,7 @@ onBeforeUnmount(() => {
168
159
  clip-path 0.1s,
169
160
  opacity 0s;
170
161
 
171
- &.finished {
162
+ &.confirmed {
172
163
  --opacity: 0.68;
173
164
  }
174
165
  }
@@ -1,19 +1,18 @@
1
- import type { ButtonProps } from '../button/types'
2
-
3
1
  export type HoldButtonStatus = 'idle' | 'loading' | 'canceled' | 'confirmed'
4
2
 
5
- export interface HoldButtonProps extends Omit<ButtonProps, 'as'> {
3
+ export interface HoldButtonProps {
6
4
  vibrate?: boolean
5
+ disabled?: boolean
7
6
  scalable?: boolean
8
7
  durations?: number | string
9
- maskColor?: string
10
8
  cancelable?: boolean
9
+ progressColor?: string
11
10
  }
12
11
 
13
12
  export interface HoldButtonEmits {
13
+ cancel: []
14
14
  confirm: []
15
- canceled: []
16
- finished: [boolean]
15
+ release: [confirmed: boolean]
17
16
  pointerup: [PointerEvent]
18
17
  pointerdown: [PointerEvent]
19
18
  }
@@ -5,7 +5,9 @@ export { default as Backtop } from './backtop/index.vue';
5
5
  export { default as Badge } from './badge/index.vue';
6
6
  export { default as Book } from './book/index.vue';
7
7
  export { default as Browser } from './browser/index.vue';
8
+ export { default as Bubble } from './bubble/index.vue';
8
9
  export { default as Button } from './button/index.vue';
10
+ export { default as ButtonGroup } from './button-group/index.vue';
9
11
  export { default as Carousel } from './carousel/index.vue';
10
12
  export { default as CarouselItem } from './carousel-item/index.vue';
11
13
  export { default as Checkbox } from './checkbox/index.vue';
@@ -15,6 +17,7 @@ export { default as Choicebox } from './choicebox/index.vue';
15
17
  export { default as ChoiceboxItem } from './choicebox-item/index.vue';
16
18
  export { default as Collapse } from './collapse/index.vue';
17
19
  export { default as CollapseGroup } from './collapse-group/index.vue';
20
+ export { default as ColorSelector } from './color-selector/index.vue';
18
21
  export { default as CommandMenu } from './command-menu/index.vue';
19
22
  export { default as CommandMenuGroup } from './command-menu-group/index.vue';
20
23
  export { default as ConfigProvider } from './config-provider/index.vue';
@@ -60,7 +63,9 @@ export { default as RadioGroup } from './radio-group/index.vue';
60
63
  export { default as Resizable } from './resizable/index.vue';
61
64
  export { default as ResizableHandle } from './resizable-handle/index.vue';
62
65
  export { default as ResizablePanel } from './resizable-panel/index.vue';
66
+ export { default as ScalableText } from './scalable-text/index.vue';
63
67
  export { default as Scrollable } from './scrollable/index.vue';
68
+ export { default as Separator } from './separator/index.vue';
64
69
  export { default as Skeleton } from './skeleton/index.vue';
65
70
  export { default as Slider } from './slider/index.vue';
66
71
  export { default as Snippet } from './snippet/index.vue';
@@ -69,6 +74,8 @@ export { default as Stack } from './stack/index.vue';
69
74
  export { default as StatusDot } from './status-dot/index.vue';
70
75
  export { default as Switch } from './switch/index.vue';
71
76
  export { default as SwitchItem } from './switch-item/index.vue';
77
+ export { default as Tabs } from './tabs/index.vue';
78
+ export { default as TabsItem } from './tabs-item/index.vue';
72
79
  export { default as Teleport } from './teleport/index.vue';
73
80
  export { default as Text } from './text/index.vue';
74
81
  export { default as Textarea } from './textarea/index.vue';