pxd 0.0.39 → 0.0.41

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 (240) hide show
  1. package/README.md +9 -3
  2. package/dist/components/active-graph/index.vue +10 -5
  3. package/dist/components/backtop/index.vue +75 -0
  4. package/dist/components/badge/index.vue +9 -7
  5. package/dist/components/book/index.vue +3 -3
  6. package/dist/components/browser/index.vue +2 -2
  7. package/dist/components/checkbox/index.vue +4 -3
  8. package/dist/components/checkbox-group/index.vue +1 -1
  9. package/dist/components/choicebox-group/index.vue +1 -1
  10. package/dist/components/command-menu/index.vue +124 -0
  11. package/dist/components/command-menu-group/index.vue +18 -0
  12. package/dist/components/command-menu-item/index.vue +13 -0
  13. package/dist/components/countdown/index.vue +2 -1
  14. package/dist/components/drawer/index.vue +26 -26
  15. package/dist/components/error/index.vue +2 -2
  16. package/dist/components/fader/index.vue +31 -17
  17. package/dist/components/grid/index.vue +2 -2
  18. package/dist/components/grid-item/index.vue +2 -2
  19. package/dist/components/hold-button/index.vue +1 -1
  20. package/dist/components/index.d.ts +7 -0
  21. package/dist/components/index.js +7 -0
  22. package/dist/components/input/index.vue +18 -10
  23. package/dist/components/intersection-observer/index.vue +5 -5
  24. package/dist/components/kbd/index.vue +21 -8
  25. package/dist/components/{intersection-observer/content.vue → keep-alive-container/index.vue} +3 -1
  26. package/dist/components/list/index.vue +100 -92
  27. package/dist/components/list-item/index.vue +35 -33
  28. package/dist/components/loading-bar/index.vue +149 -0
  29. package/dist/components/material/index.vue +8 -8
  30. package/dist/components/menu/index.vue +26 -16
  31. package/dist/components/message/index.vue +28 -18
  32. package/dist/components/modal/index.vue +32 -36
  33. package/dist/components/note/index.vue +1 -1
  34. package/dist/components/overlay/index.vue +77 -24
  35. package/dist/components/pagination/index.vue +2 -2
  36. package/dist/components/placeholder/index.vue +13 -6
  37. package/dist/components/popover/index.vue +97 -87
  38. package/dist/components/progress/index.vue +1 -1
  39. package/dist/components/radio/index.vue +4 -3
  40. package/dist/components/radio-group/index.vue +1 -1
  41. package/dist/components/scrollable/index.vue +161 -94
  42. package/dist/components/slider/index.vue +7 -7
  43. package/dist/components/stack/index.vue +4 -4
  44. package/dist/components/switch/index.vue +1 -1
  45. package/dist/components/text/index.vue +1 -1
  46. package/dist/components/theme-switcher/index.vue +6 -2
  47. package/dist/components/time-picker/index.vue +281 -0
  48. package/dist/components/tooltip/index.vue +7 -7
  49. package/dist/composables/index.d.ts +1 -0
  50. package/dist/composables/index.js +1 -0
  51. package/dist/composables/use-browser-observer.d.ts +5 -5
  52. package/dist/composables/use-color-scheme.d.ts +5 -1
  53. package/dist/composables/use-color-scheme.js +20 -1
  54. package/dist/composables/use-config-provider-context.d.ts +1 -1
  55. package/dist/composables/use-countdown.d.ts +6 -0
  56. package/dist/composables/use-countdown.js +21 -7
  57. package/dist/composables/use-delay-destroy.d.ts +4 -4
  58. package/dist/composables/use-delay-destroy.js +15 -11
  59. package/dist/composables/use-focus-trap.d.ts +2 -2
  60. package/dist/composables/use-focus-trap.js +6 -6
  61. package/dist/composables/use-loading-bar.d.ts +25 -0
  62. package/dist/composables/use-loading-bar.js +27 -0
  63. package/dist/composables/use-media-query.js +1 -1
  64. package/dist/composables/use-message.d.ts +4 -1
  65. package/dist/composables/use-message.js +18 -0
  66. package/dist/composables/use-pointer-gesture.d.ts +2 -2
  67. package/dist/composables/use-pointer-gesture.js +3 -3
  68. package/dist/composables/use-repeat-action.d.ts +2 -2
  69. package/dist/composables/use-repeat-action.js +5 -5
  70. package/dist/composables/use-virtual-list.d.ts +1 -1
  71. package/dist/contexts/avatar.d.ts +1 -1
  72. package/dist/contexts/carousel.d.ts +1 -1
  73. package/dist/contexts/checkbox.d.ts +1 -1
  74. package/dist/contexts/choicebox.d.ts +2 -2
  75. package/dist/contexts/collapse.d.ts +1 -1
  76. package/dist/contexts/list.d.ts +5 -6
  77. package/dist/contexts/list.js +3 -3
  78. package/dist/contexts/radio.d.ts +1 -1
  79. package/dist/contexts/resizable.d.ts +1 -1
  80. package/dist/contexts/switch.d.ts +2 -2
  81. package/dist/{components/carousel → dist/components/keep-alive-container}/index.vue.d.ts +1 -1
  82. package/dist/index.d.ts +1 -1
  83. package/dist/index.js +1 -1
  84. package/dist/locales/en-us.d.ts +15 -7
  85. package/dist/locales/en-us.js +17 -9
  86. package/dist/locales/zh-cn.d.ts +15 -7
  87. package/dist/locales/zh-cn.js +17 -9
  88. package/dist/{components → src/components}/active-graph/index.vue.d.ts +7 -5
  89. package/dist/{components → src/components}/avatar-group/index.vue.d.ts +1 -1
  90. package/dist/src/components/backtop/index.vue.d.ts +20 -0
  91. package/dist/{components → src/components}/badge/index.vue.d.ts +2 -1
  92. package/dist/{components → src/components}/book/index.vue.d.ts +1 -1
  93. package/dist/{components → src/components}/browser/index.vue.d.ts +1 -1
  94. package/dist/{components → src/components}/button/index.vue.d.ts +1 -1
  95. package/dist/{components/intersection-observer/content.vue.d.ts → src/components/carousel/index.vue.d.ts} +1 -1
  96. package/dist/{components → src/components}/carousel-group/index.vue.d.ts +1 -1
  97. package/dist/{components → src/components}/chip/index.vue.d.ts +1 -1
  98. package/dist/{components → src/components}/choicebox/index.vue.d.ts +1 -1
  99. package/dist/{components → src/components}/choicebox-group/index.vue.d.ts +1 -1
  100. package/dist/{components → src/components}/collapse/index.vue.d.ts +1 -1
  101. package/dist/{components → src/components}/collapse-group/index.vue.d.ts +1 -1
  102. package/dist/src/components/command-menu/index.vue.d.ts +39 -0
  103. package/dist/src/components/command-menu-group/index.vue.d.ts +16 -0
  104. package/dist/src/components/command-menu-item/index.vue.d.ts +12 -0
  105. package/dist/{components → src/components}/config-provider/index.vue.d.ts +1 -1
  106. package/dist/{components → src/components}/description/index.vue.d.ts +1 -1
  107. package/dist/{components → src/components}/drawer/index.vue.d.ts +19 -14
  108. package/dist/{components → src/components}/empty-state/index.vue.d.ts +1 -1
  109. package/dist/{components → src/components}/error/index.vue.d.ts +1 -1
  110. package/dist/src/components/fader/index.vue.d.ts +11 -0
  111. package/dist/{components → src/components}/gauge/index.vue.d.ts +1 -1
  112. package/dist/{components → src/components}/grid/index.vue.d.ts +1 -1
  113. package/dist/{components → src/components}/grid-item/index.vue.d.ts +1 -1
  114. package/dist/{components → src/components}/hold-button/index.vue.d.ts +1 -1
  115. package/dist/{components → src/components}/input/index.vue.d.ts +9 -4
  116. package/dist/{components → src/components}/intersection-observer/index.vue.d.ts +3 -3
  117. package/dist/{components → src/components}/kbd/index.vue.d.ts +8 -5
  118. package/dist/src/components/keep-alive-container/index.vue.d.ts +12 -0
  119. package/dist/{components → src/components}/link-button/index.vue.d.ts +1 -1
  120. package/dist/src/components/list/index.vue.d.ts +40 -0
  121. package/dist/{components → src/components}/list-item/index.vue.d.ts +4 -4
  122. package/dist/src/components/loading-bar/index.vue.d.ts +14 -0
  123. package/dist/{components → src/components}/loading-dots/index.vue.d.ts +1 -1
  124. package/dist/{components → src/components}/material/index.vue.d.ts +1 -1
  125. package/dist/{components → src/components}/menu/index.vue.d.ts +11 -7
  126. package/dist/{components → src/components}/message/index.vue.d.ts +13 -13
  127. package/dist/{components → src/components}/modal/index.vue.d.ts +19 -14
  128. package/dist/{components → src/components}/more-button/index.vue.d.ts +1 -1
  129. package/dist/{components → src/components}/note/index.vue.d.ts +1 -1
  130. package/dist/{components → src/components}/number-input/index.vue.d.ts +1 -1
  131. package/dist/{components → src/components}/overlay/index.vue.d.ts +3 -4
  132. package/dist/{components → src/components}/pagination/index.vue.d.ts +1 -1
  133. package/dist/{components → src/components}/pin-input/index.vue.d.ts +1 -1
  134. package/dist/src/components/placeholder/index.vue.d.ts +9 -0
  135. package/dist/{components → src/components}/popover/index.vue.d.ts +10 -8
  136. package/dist/{components → src/components}/progress/index.vue.d.ts +1 -1
  137. package/dist/{components → src/components}/radio/index.vue.d.ts +1 -1
  138. package/dist/{components → src/components}/radio-group/index.vue.d.ts +1 -1
  139. package/dist/{components → src/components}/resizable/index.vue.d.ts +1 -1
  140. package/dist/src/components/resizable-handle/index.vue.d.ts +2 -0
  141. package/dist/{components → src/components}/resizable-panel/index.vue.d.ts +1 -1
  142. package/dist/{components → src/components}/skeleton/index.vue.d.ts +1 -1
  143. package/dist/{components → src/components}/slider/index.vue.d.ts +1 -1
  144. package/dist/{components → src/components}/snippet/index.vue.d.ts +1 -1
  145. package/dist/src/components/spinner/index.vue.d.ts +2 -0
  146. package/dist/{components → src/components}/stack/index.vue.d.ts +1 -1
  147. package/dist/{components → src/components}/status-dot/index.vue.d.ts +1 -1
  148. package/dist/{components → src/components}/switch/index.vue.d.ts +1 -1
  149. package/dist/{components → src/components}/switch-group/index.vue.d.ts +1 -1
  150. package/dist/{components → src/components}/teleport/index.vue.d.ts +1 -1
  151. package/dist/{components → src/components}/text/index.vue.d.ts +1 -1
  152. package/dist/{components → src/components}/textarea/index.vue.d.ts +1 -1
  153. package/dist/{components → src/components}/theme-switcher/index.vue.d.ts +1 -1
  154. package/dist/src/components/time-picker/index.vue.d.ts +25 -0
  155. package/dist/{components → src/components}/toggle/index.vue.d.ts +1 -1
  156. package/dist/{components → src/components}/tooltip/index.vue.d.ts +3 -5
  157. package/dist/{components → src/components}/virtual-list/index.vue.d.ts +1 -1
  158. package/dist/src/composables/use-browser-observer.d.ts +12 -0
  159. package/dist/src/composables/use-color-scheme.d.ts +11 -0
  160. package/dist/src/composables/use-config-provider-context.d.ts +7 -0
  161. package/dist/src/composables/use-copy-click.d.ts +4 -0
  162. package/dist/src/composables/use-countdown.d.ts +60 -0
  163. package/dist/src/composables/use-delay-change.d.ts +7 -0
  164. package/dist/src/composables/use-delay-destroy.d.ts +13 -0
  165. package/dist/src/composables/use-focus-trap.d.ts +4 -0
  166. package/dist/src/composables/use-loading-bar.d.ts +25 -0
  167. package/dist/src/composables/use-media-query.d.ts +15 -0
  168. package/dist/src/composables/use-message.d.ts +33 -0
  169. package/dist/src/composables/use-model-value.d.ts +11 -0
  170. package/dist/src/composables/use-pointer-gesture.d.ts +180 -0
  171. package/dist/src/composables/use-repeat-action.d.ts +16 -0
  172. package/dist/src/composables/use-unique-id-context.d.ts +2 -0
  173. package/dist/src/composables/use-virtual-list.d.ts +16 -0
  174. package/dist/src/contexts/avatar.d.ts +2 -0
  175. package/dist/src/contexts/carousel.d.ts +13 -0
  176. package/dist/src/contexts/checkbox.d.ts +2 -0
  177. package/dist/src/contexts/choicebox.d.ts +4 -0
  178. package/dist/src/contexts/collapse.d.ts +8 -0
  179. package/dist/src/contexts/list.d.ts +8 -0
  180. package/dist/src/contexts/radio.d.ts +2 -0
  181. package/dist/src/contexts/resizable.d.ts +35 -0
  182. package/dist/src/contexts/switch.d.ts +4 -0
  183. package/dist/src/locales/en-us.d.ts +42 -0
  184. package/dist/src/plugins/dayjs-millisecond-token.d.ts +3 -0
  185. package/dist/src/types/components/time-picker.d.ts +4 -0
  186. package/dist/src/utils/context.d.ts +17 -0
  187. package/dist/src/utils/date.d.ts +26 -0
  188. package/dist/src/utils/debounce/index.d.ts +73 -0
  189. package/dist/src/utils/debounce.d.ts +1 -0
  190. package/dist/src/utils/dom.d.ts +40 -0
  191. package/dist/{utils/events.d.ts → src/utils/event.d.ts} +1 -0
  192. package/dist/src/utils/format.d.ts +25 -0
  193. package/dist/src/utils/get.d.ts +11 -0
  194. package/dist/src/utils/is.d.ts +4 -0
  195. package/dist/src/utils/ref.d.ts +5 -0
  196. package/dist/src/utils/regexp.d.ts +8 -0
  197. package/dist/src/utils/responsive.d.ts +3 -0
  198. package/dist/src/utils/throttle/index.d.ts +53 -0
  199. package/dist/src/utils/throttle.d.ts +1 -0
  200. package/dist/src/utils/uid.d.ts +1 -0
  201. package/dist/styles/styles.css +2 -2
  202. package/dist/styles/tw.css +18 -1
  203. package/dist/types/components/list.d.ts +4 -3
  204. package/dist/types/components/time-picker.d.ts +4 -0
  205. package/dist/types/components/time-picker.js +0 -0
  206. package/dist/types/shared/utils.d.ts +5 -2
  207. package/dist/utils/date.d.ts +3 -3
  208. package/dist/utils/debounce/compat.d.ts +143 -0
  209. package/dist/utils/debounce/compat.js +47 -0
  210. package/dist/utils/debounce/index.d.ts +73 -0
  211. package/dist/utils/debounce/index.js +60 -0
  212. package/dist/utils/debounce.d.ts +1 -73
  213. package/dist/utils/debounce.js +1 -60
  214. package/dist/utils/event.d.ts +9 -0
  215. package/dist/utils/{events.js → event.js} +3 -0
  216. package/dist/utils/format.d.ts +4 -1
  217. package/dist/utils/format.js +6 -0
  218. package/dist/utils/ref.d.ts +2 -5
  219. package/dist/utils/regexp.d.ts +4 -0
  220. package/dist/utils/regexp.js +4 -0
  221. package/dist/utils/responsive.d.ts +2 -1
  222. package/dist/utils/responsive.js +4 -1
  223. package/dist/utils/throttle/compat.d.ts +79 -0
  224. package/dist/utils/throttle/compat.js +9 -0
  225. package/dist/utils/throttle/index.d.ts +53 -0
  226. package/dist/utils/throttle/index.js +34 -0
  227. package/dist/utils/throttle.d.ts +1 -53
  228. package/dist/utils/throttle.js +1 -34
  229. package/dist/utils/uid.js +1 -1
  230. package/package.json +11 -11
  231. package/volar.d.ts +7 -0
  232. package/dist/components/fader/index.vue.d.ts +0 -11
  233. package/dist/components/list/index.vue.d.ts +0 -29
  234. package/dist/components/placeholder/index.vue.d.ts +0 -8
  235. package/dist/components/resizable-handle/index.vue.d.ts +0 -2
  236. package/dist/components/spinner/index.vue.d.ts +0 -2
  237. /package/dist/{components → src/components}/avatar/index.vue.d.ts +0 -0
  238. /package/dist/{components → src/components}/checkbox/index.vue.d.ts +0 -0
  239. /package/dist/{components → src/components}/checkbox-group/index.vue.d.ts +0 -0
  240. /package/dist/{components → src/components}/countdown/index.vue.d.ts +0 -0
@@ -1,106 +1,86 @@
1
1
  <script setup>
2
- import { computed, onBeforeUnmount, onMounted, shallowRef } from "vue";
3
- import { provideListContext, provideListItemIndexContext } from "../../contexts/list";
4
- import { off, on } from "../../utils/events";
2
+ import { nextTick, onBeforeUnmount, onMounted, shallowRef } from "vue";
3
+ import { provideListContext } from "../../contexts/list";
4
+ import { optimizedOff, optimizedOn } from "../../utils/event";
5
5
  import { getCssUnitValue } from "../../utils/format";
6
6
  import { isServer } from "../../utils/is";
7
7
  import { throttle } from "../../utils/throttle";
8
8
  import PListItem from "../list-item/index.vue";
9
9
  import PScrollable from "../scrollable/index.vue";
10
10
  defineOptions({
11
- name: "PList"
11
+ name: "PList",
12
+ inheritAttrs: false
12
13
  });
13
14
  const props = defineProps({
15
+ loop: { type: Boolean, required: false, default: true },
14
16
  width: { type: [String, Number], required: false },
15
17
  options: { type: Array, required: false, default: () => [] },
16
- closeOnPressEscape: { type: Boolean, required: false, default: true }
18
+ keyListener: { type: Boolean, required: false, default: true },
19
+ itemTransition: { type: Boolean, required: false, default: true }
17
20
  });
18
- const emits = defineEmits(["close", "toggle", "selected"]);
21
+ const emits = defineEmits(["toggle", "select"]);
22
+ const activeValue = shallowRef("");
23
+ const containerRef = shallowRef();
19
24
  const ITEM_CLASS = "pxd-list-item";
20
- const ITEM_SELECTOR = `.${ITEM_CLASS}`;
21
- const initialIndex = Number.NaN;
22
- const activeIndex = shallowRef(initialIndex);
23
- const increaseIndex = shallowRef(0);
24
- const allItems = shallowRef([]);
25
- const computedStyle = computed(() => {
26
- return {
27
- width: getCssUnitValue(props.width)
28
- };
29
- });
30
- function registerListItem(el) {
31
- if (!allItems.value.includes(el)) {
32
- allItems.value.push(el);
33
- }
34
- }
35
- function unregisterListItem(el) {
36
- const index = allItems.value.indexOf(el);
37
- if (index >= 0) {
38
- allItems.value.splice(index, 1);
39
- }
40
- }
41
- function getItemData(index) {
42
- const element = allItems.value[index];
43
- if (!element) {
44
- return null;
45
- }
46
- const { disabled, type = "default" } = element.dataset;
47
- return {
48
- disabled: disabled === "true",
49
- type
50
- };
51
- }
52
- function getCorrectIndex(dir, index) {
53
- const nextIndex = dir === "prev" ? index - 1 : index + 1;
54
- const length = allItems.value.length;
55
- if (nextIndex < 0) {
56
- return length - 1;
57
- }
58
- if (nextIndex >= length) {
59
- return 0;
60
- }
61
- const item = getItemData(nextIndex);
62
- if (item?.disabled) {
63
- return getCorrectIndex(dir, nextIndex);
64
- }
65
- return nextIndex;
66
- }
25
+ const itemSelector = `.${ITEM_CLASS}:not([data-disabled="true"])`;
67
26
  const PREV_KEYS = ["ArrowUp", "ArrowLeft"];
68
27
  const NEXT_KEYS = ["ArrowDown", "ArrowRight"];
69
- const FUNCTION_KEYS = ["Enter", "Escape", "Tab"];
28
+ const FUNCTION_KEYS = ["Enter", "Tab", "Home", "End"];
70
29
  const PREVENT_DEFAULT_KEYS = [...FUNCTION_KEYS, ...PREV_KEYS, ...NEXT_KEYS];
71
- const THROTTLE_INTERVALS = 255;
30
+ const listItemKeys = [];
31
+ const listItemsMap = /* @__PURE__ */ new Map();
72
32
  const containerKeydownThrottled = throttle((ev) => {
73
- const count = allItems.value.length;
74
- if (count === 0) {
75
- return;
76
- }
77
33
  const { key } = ev;
78
34
  if (key === "Tab") {
79
35
  return;
80
36
  }
81
37
  if (key === "Enter") {
82
- allItems.value[activeIndex.value]?.click();
83
- return;
84
- }
85
- if (key === "Escape" && props.closeOnPressEscape) {
86
- emits("close");
38
+ listItemsMap.get(activeValue.value)?.click();
87
39
  return;
88
40
  }
41
+ let newActiveValue = "";
89
42
  if (PREV_KEYS.includes(key)) {
90
- activeIndex.value = Object.is(activeIndex.value, initialIndex) ? count - 1 : getCorrectIndex("prev", activeIndex.value);
91
- emits("toggle", activeIndex.value);
43
+ if (activeValue.value) {
44
+ const index = listItemKeys.indexOf(activeValue.value);
45
+ if (props.loop) {
46
+ const prevIndex = (index - 1 + listItemKeys.length) % listItemKeys.length;
47
+ newActiveValue = listItemKeys[prevIndex];
48
+ } else if (index > 0) {
49
+ newActiveValue = listItemKeys[index - 1];
50
+ }
51
+ } else {
52
+ newActiveValue = listItemKeys.at(-1);
53
+ }
92
54
  } else if (NEXT_KEYS.includes(key)) {
93
- activeIndex.value = Object.is(activeIndex.value, initialIndex) ? 0 : getCorrectIndex("next", activeIndex.value);
94
- emits("toggle", activeIndex.value);
55
+ if (activeValue.value) {
56
+ const index = listItemKeys.indexOf(activeValue.value);
57
+ if (props.loop) {
58
+ const nextIndex = (index + 1) % listItemKeys.length;
59
+ newActiveValue = listItemKeys[nextIndex];
60
+ } else if (index < listItemKeys.length - 1) {
61
+ newActiveValue = listItemKeys[index + 1];
62
+ }
63
+ } else {
64
+ newActiveValue = listItemKeys.at(0);
65
+ }
66
+ } else if (key === "Home") {
67
+ newActiveValue = listItemKeys.at(0);
68
+ } else if (key === "End") {
69
+ newActiveValue = listItemKeys.at(-1);
95
70
  }
96
- if (allItems.value.length <= 0 || activeIndex.value < 0) {
71
+ if (!newActiveValue) {
97
72
  return;
98
73
  }
99
- allItems.value[activeIndex.value].scrollIntoView({
100
- block: "nearest"
101
- });
102
- }, THROTTLE_INTERVALS, { edges: ["leading"] });
74
+ if (activeValue.value !== newActiveValue) {
75
+ emits("toggle");
76
+ activeValue.value = newActiveValue;
77
+ }
78
+ listItemsMap.get(activeValue.value)?.scrollIntoView({ block: "nearest" });
79
+ }, 100, { edges: ["leading"] });
103
80
  function onContainerKeydown(ev) {
81
+ if (!props.keyListener || listItemKeys.length === 0) {
82
+ return;
83
+ }
104
84
  if (PREVENT_DEFAULT_KEYS.includes(ev.key)) {
105
85
  ev.preventDefault();
106
86
  }
@@ -109,45 +89,73 @@ function onContainerKeydown(ev) {
109
89
  }
110
90
  function onPointerOver(ev) {
111
91
  const target = ev.target;
112
- const listItem = target.closest(ITEM_SELECTOR);
113
- if (!listItem || listItem.dataset.index === void 0) {
92
+ const listItem = target.closest(`.${ITEM_CLASS}`);
93
+ const itemValue = listItem?.dataset.value;
94
+ if (!listItem || itemValue === void 0) {
114
95
  return;
115
96
  }
116
- activeIndex.value = Number(listItem.dataset.index);
97
+ activeValue.value = itemValue;
117
98
  }
118
- function onOptionClick(ev, index) {
119
- activeIndex.value = index;
120
- emits("selected", ev, index);
121
- emits("close");
99
+ function onOptionClick(ev, item) {
100
+ const { as, onClick, ...option } = item;
101
+ activeValue.value = "";
102
+ emits("select", ev, option);
103
+ }
104
+ function updateListItem() {
105
+ listItemsMap.clear();
106
+ listItemKeys.splice(0);
107
+ Array.from(containerRef.value.querySelectorAll(itemSelector)).forEach((el) => {
108
+ const key = el.dataset.value;
109
+ listItemsMap.set(key, el);
110
+ listItemKeys.push(key);
111
+ });
112
+ }
113
+ function isNoVisibleItem() {
114
+ return listItemsMap.size === 0;
115
+ }
116
+ function setActiveValue(newValue = "") {
117
+ activeValue.value = newValue;
118
+ }
119
+ function setActiveValueToFirst() {
120
+ setActiveValue(listItemKeys[0]);
122
121
  }
123
- provideListItemIndexContext(increaseIndex);
124
122
  provideListContext({
125
- activeIndex,
126
- onOptionClick,
127
- registerListItem,
128
- unregisterListItem
123
+ activeValue,
124
+ onOptionClick
129
125
  });
130
- onMounted(() => {
126
+ onMounted(async () => {
131
127
  if (isServer) {
132
128
  return;
133
129
  }
134
- on(document, "keydown", onContainerKeydown);
130
+ await nextTick();
131
+ updateListItem();
132
+ optimizedOn(document, "keydown", onContainerKeydown);
135
133
  });
136
134
  onBeforeUnmount(() => {
137
- off(document, "keydown", onContainerKeydown);
138
- allItems.value = [];
135
+ listItemsMap.clear();
136
+ listItemKeys.splice(0);
137
+ optimizedOff(document, "keydown", onContainerKeydown);
138
+ });
139
+ defineExpose({
140
+ setActiveValue,
141
+ updateListItem,
142
+ isNoVisibleItem,
143
+ setActiveValueToFirst
139
144
  });
140
145
  </script>
141
146
 
142
147
  <template>
143
148
  <ul
149
+ ref="containerRef"
144
150
  role="list"
145
151
  tabindex="-1"
146
- class="pxd-list max-w-full"
147
- :style="computedStyle"
152
+ :data-transition="itemTransition"
153
+ class="pxd-list group/list max-w-full list-none bg-background-100 outline-none"
154
+ :style="{ width: getCssUnitValue(width) }"
155
+ v-bind="$attrs"
148
156
  @pointerover="onPointerOver"
149
157
  >
150
- <PScrollable class="max-h-68" content-class="pr-2">
158
+ <PScrollable class="p-2 h-full max-h-inherit rounded-inherit" fader-direction="vertical">
151
159
  <slot>
152
160
  <PListItem
153
161
  v-for="(option, index) in options"
@@ -1,6 +1,8 @@
1
1
  <script setup>
2
- import { computed, onMounted, onUnmounted, shallowRef, useAttrs } from "vue";
3
- import { useListContext, useListItemIndexContext } from "../../contexts/list";
2
+ import { computed, nextTick, onMounted, shallowRef } from "vue";
3
+ import { useListContext, useListFilterValue } from "../../contexts/list";
4
+ import { unrefElement } from "../../utils/ref";
5
+ import { getUniqueId } from "../../utils/uid";
4
6
  defineOptions({
5
7
  name: "PListItem"
6
8
  });
@@ -13,40 +15,40 @@ const props = defineProps({
13
15
  });
14
16
  const emits = defineEmits(["click"]);
15
17
  const {
16
- activeIndex,
17
- onOptionClick,
18
- registerListItem,
19
- unregisterListItem
18
+ activeValue,
19
+ onOptionClick
20
20
  } = useListContext();
21
- const listItemIndex = useListItemIndexContext();
22
- const attrs = useAttrs();
21
+ const uniqueId = getUniqueId();
22
+ const filterValue = useListFilterValue();
23
23
  const itemRef = shallowRef();
24
- const currentIndex = shallowRef(listItemIndex.value++);
24
+ const currentValue = shallowRef("");
25
25
  const itemTypeMap = {
26
- error: "text-red-900 data-[selected=true]:bg-red-100",
27
- warning: "text-amber-900 data-[selected=true]:bg-amber-100",
28
- default: "text-foreground data-[selected=true]:bg-gray-alpha-100"
26
+ error: "text-red-900 pointer-coarse:active:bg-red-100 pointer-fine:data-[selected=true]:bg-red-100",
27
+ warning: "text-amber-900 pointer-coarse:active:bg-amber-100 pointer-fine:data-[selected=true]:bg-amber-100",
28
+ default: "text-foreground pointer-coarse:active:bg-gray-alpha-100 pointer-fine:data-[selected=true]:bg-gray-alpha-100",
29
+ separator: "!h-0 !w-auto px-0 m-1.5 border-b"
29
30
  };
30
- const isSelected = computed(() => activeIndex.value === currentIndex.value);
31
+ const isVisible = computed(() => filterValue?.value ? currentValue.value.includes(filterValue.value) : true);
32
+ const isSelected = computed(() => activeValue.value === uniqueId);
33
+ const isDisabled = computed(() => props.disabled || props.type === "separator");
31
34
  const computedClass = computed(() => {
32
- const classes = ["cursor-pointer data-[disabled=true]:pointer-events-none data-[disabled=true]:text-gray-700", attrs.class];
33
- if (props.type) {
34
- classes.push(itemTypeMap[props.type]);
35
+ const { type = "default" } = props;
36
+ const classes = ["pxd-list-item h-10 gap-3 px-2 text-sm flex w-full cursor-pointer items-center rounded-md outline-none data-[disabled=true]:pointer-events-none data-[disabled=true]:text-gray-700 group-data-[transition=true]/list:motion-safe:transition-colors"];
37
+ if (type in itemTypeMap) {
38
+ classes.push(itemTypeMap[type]);
35
39
  }
36
40
  return classes.join(" ");
37
41
  });
38
42
  function onItemClick(ev) {
39
- emits("click", ev, currentIndex.value);
40
- onOptionClick?.(ev, currentIndex.value);
43
+ emits("click", ev, props);
44
+ onOptionClick?.(ev, props);
41
45
  }
42
- onMounted(() => {
43
- if (registerListItem) {
44
- registerListItem(itemRef.value);
45
- }
46
- });
47
- onUnmounted(() => {
48
- if (unregisterListItem) {
49
- unregisterListItem(itemRef.value);
46
+ onMounted(async () => {
47
+ await nextTick();
48
+ if (props.label) {
49
+ currentValue.value = `${String(props.label || "")}${props.description || ""}`.toLowerCase().replace(/\s/g, "");
50
+ } else {
51
+ currentValue.value = (unrefElement(itemRef.value)?.textContent || "").toLowerCase().replace(/\s/g, "");
50
52
  }
51
53
  });
52
54
  </script>
@@ -54,20 +56,20 @@ onUnmounted(() => {
54
56
  <template>
55
57
  <Component
56
58
  :is="as"
59
+ v-if="isVisible"
57
60
  ref="itemRef"
58
61
  tabindex="-1"
59
62
  role="listitem"
60
63
  :data-type="type"
61
- :data-index="currentIndex"
62
- :data-disabled="disabled"
64
+ :data-value="uniqueId"
63
65
  :data-selected="isSelected"
64
- class="pxd-list-item h-10 gap-1 px-2 text-sm flex w-full items-center rounded-md outline-none motion-safe:transition-colors"
66
+ :data-disabled="isDisabled"
65
67
  :class="computedClass"
66
- @click="onItemClick"
68
+ @click.prevent.stop="onItemClick"
67
69
  >
68
- <slot>
69
- <span class="gap-2 flex items-center">{{ label }}</span>
70
- <span v-if="description" class="text-sm text-foreground-secondary">{{ description }}</span>
70
+ <slot v-if="type !== 'separator'">
71
+ <span>{{ label }}</span>
72
+ <span v-if="description" class="text-foreground-secondary">{{ description }}</span>
71
73
  </slot>
72
74
  </component>
73
75
  </template>
@@ -0,0 +1,149 @@
1
+ <script setup>
2
+ import { computed, onBeforeUnmount, onMounted, shallowRef } from "vue";
3
+ import {
4
+ ERROR_LOADING_BAR_EVENT_NAME,
5
+ FINISH_LOADING_BAR_EVENT_NAME,
6
+ INCREASE_LOADING_BAR_EVENT_NAME,
7
+ START_LOADING_BAR_EVENT_NAME
8
+ } from "../../composables/use-loading-bar";
9
+ import { optimizedOff, optimizedOn } from "../../utils/event";
10
+ import { clampValue } from "../../utils/format";
11
+ import { isServer } from "../../utils/is";
12
+ import PTeleport from "../teleport/index.vue";
13
+ defineOptions({
14
+ name: "PLoadingBar",
15
+ inheritAttrs: false
16
+ });
17
+ const props = defineProps({
18
+ to: { type: null, required: false },
19
+ group: { type: String, required: false, default: "default" },
20
+ minimum: { type: Number, required: false, default: 0.08 },
21
+ trickle: { type: Boolean, required: false, default: true },
22
+ trickleThreshold: { type: Number, required: false, default: 300 }
23
+ });
24
+ let hideTimerId;
25
+ let prevTimestamp = 0;
26
+ let prevAnimationKey = 0;
27
+ const status = shallowRef("finish");
28
+ const hidden = shallowRef(false);
29
+ const progress = shallowRef(0);
30
+ const computedClass = computed(() => {
31
+ const _status = status.value;
32
+ return {
33
+ "opacity-0": hidden.value,
34
+ "bg-primary": _status === "running" || _status === "finish",
35
+ "bg-red-900": _status === "error"
36
+ };
37
+ });
38
+ function getIncreaseDelta(n) {
39
+ if (n >= 0 && n < 0.2) {
40
+ return 0.1;
41
+ } else if (n >= 0.2 && n < 0.5) {
42
+ return 0.04;
43
+ } else if (n >= 0.5 && n < 0.8) {
44
+ return 0.02;
45
+ } else if (n >= 0.8 && n < 0.98) {
46
+ return 5e-3;
47
+ } else {
48
+ return 0;
49
+ }
50
+ }
51
+ function increaseProgress(n) {
52
+ if (progress.value >= 1) {
53
+ cancelAnimationFrame(prevAnimationKey);
54
+ return;
55
+ }
56
+ const now = performance.now();
57
+ const delta = now - prevTimestamp;
58
+ const threshold = props.trickleThreshold || 200;
59
+ if (delta < threshold && props.trickle) {
60
+ prevAnimationKey = requestAnimationFrame(() => increaseProgress());
61
+ return;
62
+ }
63
+ prevTimestamp = now;
64
+ const amount = n || getIncreaseDelta(progress.value);
65
+ progress.value = clampValue(progress.value + amount, 0, 0.994);
66
+ if (amount === 0 || !props.trickle) {
67
+ return;
68
+ }
69
+ prevAnimationKey = requestAnimationFrame(() => increaseProgress());
70
+ }
71
+ function onStartProgress({ detail }) {
72
+ if (detail.group !== props.group) {
73
+ return;
74
+ }
75
+ hidden.value = false;
76
+ status.value = "running";
77
+ clearTimeout(hideTimerId);
78
+ progress.value = props.minimum;
79
+ if (!props.trickle) {
80
+ return;
81
+ }
82
+ prevTimestamp = 0;
83
+ requestAnimationFrame(() => increaseProgress());
84
+ }
85
+ function onErrorProgress({ detail }) {
86
+ if (detail.group !== props.group) {
87
+ return;
88
+ }
89
+ cancelAnimationFrame(prevAnimationKey);
90
+ clearTimeout(hideTimerId);
91
+ status.value = "error";
92
+ hidden.value = false;
93
+ progress.value = 1;
94
+ hideTimerId = setTimeout(() => {
95
+ hidden.value = true;
96
+ }, 300);
97
+ }
98
+ function onFinishProgress({ detail }) {
99
+ if (detail.group !== props.group) {
100
+ return;
101
+ }
102
+ cancelAnimationFrame(prevAnimationKey);
103
+ clearTimeout(hideTimerId);
104
+ status.value = "finish";
105
+ hidden.value = false;
106
+ progress.value = 1;
107
+ hideTimerId = setTimeout(() => {
108
+ hidden.value = true;
109
+ }, 300);
110
+ }
111
+ function onIncreaseProgress({ detail }) {
112
+ if (detail.group !== props.group) {
113
+ return;
114
+ }
115
+ increaseProgress(detail.value);
116
+ }
117
+ onMounted(() => {
118
+ if (isServer) {
119
+ return;
120
+ }
121
+ optimizedOn(window, START_LOADING_BAR_EVENT_NAME, onStartProgress);
122
+ optimizedOn(window, ERROR_LOADING_BAR_EVENT_NAME, onErrorProgress);
123
+ optimizedOn(window, FINISH_LOADING_BAR_EVENT_NAME, onFinishProgress);
124
+ optimizedOn(window, INCREASE_LOADING_BAR_EVENT_NAME, onIncreaseProgress);
125
+ });
126
+ onBeforeUnmount(() => {
127
+ optimizedOff(window, START_LOADING_BAR_EVENT_NAME, onStartProgress);
128
+ optimizedOff(window, ERROR_LOADING_BAR_EVENT_NAME, onErrorProgress);
129
+ optimizedOff(window, FINISH_LOADING_BAR_EVENT_NAME, onFinishProgress);
130
+ optimizedOff(window, INCREASE_LOADING_BAR_EVENT_NAME, onIncreaseProgress);
131
+ });
132
+ </script>
133
+
134
+ <template>
135
+ <PTeleport :to="to">
136
+ <div
137
+ aria-hidden="true"
138
+ class="pxd-loading-bar top-0 left-0 right-0 h-0.5 pointer-events-none z-10 max-w-full overflow-hidden"
139
+ :class="to ? 'absolute' : 'fixed'"
140
+ v-bind="$attrs"
141
+ >
142
+ <div
143
+ class="pxd-loading-bar--inner size-full origin-left rounded-r-full motion-safe:transition-all"
144
+ :class="computedClass"
145
+ :style="{ transform: `scaleX(${progress})` }"
146
+ />
147
+ </div>
148
+ </PTeleport>
149
+ </template>
@@ -18,35 +18,35 @@ defineProps({
18
18
  <style lang="postcss">
19
19
  .pxd-material {
20
20
  &.default {
21
- border-radius: 6px;
21
+ border-radius: calc(var(--radius) - 2px);
22
22
  box-shadow: var(--shadow-border-default);
23
23
  }
24
24
  &.small {
25
- border-radius: 6px;
25
+ border-radius: calc(var(--radius) - 2px);
26
26
  box-shadow: var(--shadow-border-small);
27
27
  }
28
28
  &.medium {
29
- border-radius: 12px;
29
+ border-radius: calc(var(--radius) + 6px);
30
30
  box-shadow: var(--shadow-border-medium);
31
31
  }
32
32
  &.large {
33
- border-radius: 12px;
33
+ border-radius: calc(var(--radius) + 6px);
34
34
  box-shadow: var(--shadow-border-large);
35
35
  }
36
36
  &.tooltip {
37
- border-radius: 6px;
37
+ border-radius: calc(var(--radius) - 2px);
38
38
  box-shadow: var(--shadow-border-tooltip);
39
39
  }
40
40
  &.menu {
41
- border-radius: 12px;
41
+ border-radius: calc(var(--radius) + 6px);
42
42
  box-shadow: var(--shadow-border-menu);
43
43
  }
44
44
  &.modal {
45
- border-radius: 12px;
45
+ border-radius: calc(var(--radius) + 6px);
46
46
  box-shadow: var(--shadow-border-modal);
47
47
  }
48
48
  &.fullscreen {
49
- border-radius: 16px;
49
+ border-radius: calc(var(--radius) + 8px);
50
50
  box-shadow: var(--shadow-border-fullscreen);
51
51
  }
52
52
  }
@@ -3,34 +3,44 @@ import { shallowRef } from "vue";
3
3
  import PList from "../list/index.vue";
4
4
  import PPopover from "../popover/index.vue";
5
5
  defineOptions({
6
- name: "PMenu"
6
+ name: "PMenu",
7
+ inheritAttrs: false
7
8
  });
8
9
  defineProps({
9
10
  width: { type: [String, Number], required: false },
10
11
  options: { type: Array, required: false, default: () => [] },
11
- position: { type: null, required: false, default: "bottom-start" }
12
+ position: { type: null, required: false, default: "bottom-start" },
13
+ closeOnPressEscape: { type: Boolean, required: false, default: true }
12
14
  });
13
- const emits = defineEmits(["selected"]);
14
- const popoverRef = shallowRef();
15
- function closePopover() {
16
- popoverRef.value?.hide();
15
+ const emits = defineEmits(["change", "select"]);
16
+ const popoverVisible = shallowRef(false);
17
+ function showPopover() {
18
+ popoverVisible.value = true;
17
19
  }
18
- function onOptionClick(ev, index) {
19
- emits("selected", ev, index);
20
+ function hidePopover() {
21
+ popoverVisible.value = false;
22
+ }
23
+ function onOptionClick(ev, item) {
24
+ emits("select", ev, item);
25
+ hidePopover();
20
26
  }
21
27
  </script>
22
28
 
23
29
  <template>
24
30
  <PPopover
25
- ref="popoverRef"
26
- trigger="click"
27
- class="pxd-menu"
31
+ enterable
28
32
  scroll-hidden
33
+ class="pxd-menu"
34
+ trigger="manual"
29
35
  :show-delay="0"
30
36
  :hide-delay="100"
31
37
  :position="position"
32
- :show-transition="false"
33
- enterable
38
+ disabled-show-transition
39
+ :visible="popoverVisible"
40
+ :close-on-press-escape="closeOnPressEscape"
41
+ v-bind="$attrs"
42
+ @outside-click="hidePopover"
43
+ @trigger-click="showPopover"
34
44
  >
35
45
  <slot />
36
46
 
@@ -38,9 +48,9 @@ function onOptionClick(ev, index) {
38
48
  <PList
39
49
  :width="width"
40
50
  :options="options"
41
- class="p-2 pr-0 list-none rounded-xl bg-background-100 shadow-border-menu outline-none"
42
- @close="closePopover"
43
- @selected="onOptionClick"
51
+ :key-listener="popoverVisible"
52
+ class="max-h-68 rounded-xl bg-background-100 shadow-border-menu"
53
+ @select="onOptionClick"
44
54
  >
45
55
  <slot name="items" />
46
56
  </PList>