vitepress-plugin-toolkit 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,16 +37,42 @@ interface SizeOptions {
37
37
  type __VLS_Props$1 = {
38
38
  text: string;
39
39
  };
40
- declare const __VLS_export$1: import("vue").DefineComponent<__VLS_Props$1, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props$1> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
- declare const _default: typeof __VLS_export$1;
40
+ declare const __VLS_export$2: import("vue").DefineComponent<__VLS_Props$1, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props$1> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const _default: typeof __VLS_export$2;
42
42
  //#endregion
43
43
  //#region src/client/components/VPLoading.vue.d.ts
44
44
  type __VLS_Props = {
45
45
  absolute?: boolean;
46
46
  height?: string;
47
47
  };
48
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
- declare const _default$1: typeof __VLS_export;
48
+ declare const __VLS_export$1: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
+ declare const _default$1: typeof __VLS_export$1;
50
+ //#endregion
51
+ //#region src/client/components/VPTabSwitch.vue.d.ts
52
+ interface Item<T> {
53
+ value: T;
54
+ label: string;
55
+ }
56
+ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
57
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<({
58
+ items: Item<T>[];
59
+ } & {
60
+ modelValue?: T;
61
+ }) & {
62
+ onUpdate?: ((tab: T) => any) | undefined;
63
+ "onUpdate:modelValue"?: ((value: T | undefined) => any) | undefined;
64
+ }> & (typeof globalThis extends {
65
+ __VLS_PROPS_FALLBACK: infer P;
66
+ } ? P : {});
67
+ expose: (exposed: {}) => void;
68
+ attrs: any;
69
+ slots: {};
70
+ emit: ((evt: "update", tab: T) => void) & ((event: "update:modelValue", value: T | undefined) => void);
71
+ }>) => import("vue").VNode & {
72
+ __ctx?: Awaited<typeof __VLS_setup>;
73
+ };
74
+ declare const _default$2: typeof __VLS_export;
75
+ type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K] } : { [K in keyof T as K]: T[K] }) & {};
50
76
  //#endregion
51
77
  //#region src/client/composables/use-size.d.ts
52
78
  interface SizeInfo {
@@ -56,6 +82,21 @@ interface SizeInfo {
56
82
  }
57
83
  declare function useSize<T extends HTMLElement>(el: TemplateRef<T>, options: ToRefs<SizeOptions>, extraHeight?: MaybeRef<number>): SizeInfo;
58
84
  //#endregion
85
+ //#region src/client/composables/use-zoom-and-drag.d.ts
86
+ declare function useZoomAndDrag(parentEl: TemplateRef<HTMLDivElement>): {
87
+ actorStyle: import("vue").ComputedRef<{
88
+ left: string;
89
+ top: string;
90
+ width: string | undefined;
91
+ height: string;
92
+ }>;
93
+ zoom: import("vue").ComputedRef<string>;
94
+ reset: (isFullscreen?: boolean) => void;
95
+ zoomIn: () => void;
96
+ zoomOut: () => void;
97
+ resetZoom: () => void;
98
+ };
99
+ //#endregion
59
100
  //#region src/client/utils/env.d.ts
60
101
  interface NavigatorUAData {
61
102
  platform?: string;
@@ -123,4 +164,4 @@ declare function isMobile(): boolean;
123
164
  */
124
165
  declare function isSafari(): boolean;
125
166
  //#endregion
126
- export { EXTERNAL_URL_RE, SizeInfo, SizeOptions, URL_PROTOCOL_RE, _default as VPCopyButton, _default$1 as VPLoading, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize };
167
+ export { EXTERNAL_URL_RE, SizeInfo, SizeOptions, URL_PROTOCOL_RE, _default as VPCopyButton, _default$1 as VPLoading, _default$2 as VPTabSwitch, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize, useZoomAndDrag };
@@ -1,5 +1,5 @@
1
- import { computed, createElementBlock, createElementVNode, defineComponent, isRef, normalizeClass, normalizeStyle, onMounted, openBlock, ref, toValue, unref, watch } from "vue";
2
- import { useClipboard, useEventListener } from "@vueuse/core";
1
+ import { Fragment, computed, createElementBlock, createElementVNode, defineComponent, isRef, mergeModels, nextTick, normalizeClass, normalizeStyle, onMounted, openBlock, ref, renderList, shallowRef, toDisplayString, toValue, unref, useModel, watch } from "vue";
2
+ import { useClipboard, useEventListener, useMediaQuery, useMutationObserver } from "@vueuse/core";
3
3
  //#region src/shared/link.ts
4
4
  const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
5
5
  function isExternal(path) {
@@ -11,7 +11,7 @@ function isLinkWithProtocol(link) {
11
11
  }
12
12
  //#endregion
13
13
  //#region src/client/components/VPCopyButton.vue
14
- const _sfc_main = /* @__PURE__ */ defineComponent({
14
+ const _sfc_main = /*@__PURE__*/ defineComponent({
15
15
  __name: "VPCopyButton",
16
16
  props: { text: {} },
17
17
  setup(__props) {
@@ -28,7 +28,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
28
28
  });
29
29
  //#endregion
30
30
  //#region src/client/components/VPLoading.vue
31
- const _sfc_main$1 = /* @__PURE__ */ defineComponent({
31
+ const _sfc_main$1 = /*@__PURE__*/ defineComponent({
32
32
  __name: "VPLoading",
33
33
  props: {
34
34
  absolute: { type: Boolean },
@@ -68,6 +68,38 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
68
68
  }
69
69
  });
70
70
  //#endregion
71
+ //#region src/client/components/VPTabSwitch.vue
72
+ const _hoisted_1 = { class: "vp-tab-switch-list" };
73
+ const _hoisted_2 = ["onClick"];
74
+ const _sfc_main$2 = /*@__PURE__*/ defineComponent({
75
+ __name: "VPTabSwitch",
76
+ props: /*@__PURE__*/ mergeModels({ items: {} }, {
77
+ "modelValue": {},
78
+ "modelModifiers": {}
79
+ }),
80
+ emits: /*@__PURE__*/ mergeModels(["update"], ["update:modelValue"]),
81
+ setup(__props, { emit: __emit }) {
82
+ const emit = __emit;
83
+ const tab = useModel(__props, "modelValue");
84
+ watch(() => __props.items, () => {
85
+ tab.value = __props.items[0].value;
86
+ });
87
+ function onClick(item) {
88
+ tab.value = item;
89
+ emit("update", item);
90
+ }
91
+ return (_ctx, _cache) => {
92
+ return openBlock(), createElementBlock("div", _hoisted_1, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item) => {
93
+ return openBlock(), createElementBlock("button", {
94
+ key: item.label,
95
+ class: normalizeClass({ active: tab.value === item.value }),
96
+ onClick: ($event) => onClick(item.value)
97
+ }, toDisplayString(item.label), 11, _hoisted_2);
98
+ }), 128))]);
99
+ };
100
+ }
101
+ });
102
+ //#endregion
71
103
  //#region src/client/composables/use-size.ts
72
104
  function useSize(el, options, extraHeight = 0) {
73
105
  const width = computed(() => toValue(options.width) || "100%");
@@ -101,6 +133,160 @@ function getRadio(ratio) {
101
133
  return typeof ratio === "number" ? ratio : 16 / 9;
102
134
  }
103
135
  //#endregion
136
+ //#region src/client/composables/use-zoom-and-drag.ts
137
+ function useZoomAndDrag(parentEl) {
138
+ const actorEl = shallowRef();
139
+ let ratio = 0;
140
+ const x = ref(0);
141
+ const y = ref(0);
142
+ const width = ref(void 0);
143
+ let originalWidth = 0;
144
+ let initialState = {
145
+ width: 0,
146
+ x: 0,
147
+ y: 0
148
+ };
149
+ const isDesktop = useMediaQuery("(min-width: 640px)");
150
+ useMutationObserver(actorEl, (mutationList) => {
151
+ if (mutationList.some((mutation) => mutation.type === "childList")) nextTick(initialize);
152
+ }, {
153
+ subtree: true,
154
+ childList: true,
155
+ attributes: false
156
+ });
157
+ onMounted(() => nextTick(initialize));
158
+ function initialize(isFullscreen = false) {
159
+ if (!parentEl.value) return;
160
+ const actor = parentEl.value.querySelector(".content");
161
+ actorEl.value = actor;
162
+ if (!actor) return;
163
+ actor.style.width = "max-content";
164
+ actor.style.height = "";
165
+ const stage = parentEl.value;
166
+ const clientHeight = document.documentElement.clientHeight;
167
+ const maxHeight = isFullscreen ? clientHeight : isDesktop.value ? clientHeight * .75 : clientHeight / 2;
168
+ const { offsetWidth: actorWidth, offsetHeight: actorHeight } = actor;
169
+ const stageWidth = stage.offsetWidth;
170
+ ratio = actorWidth / actorHeight;
171
+ let tryZoom = 1;
172
+ let stageHeight = isFullscreen ? clientHeight : actorHeight;
173
+ let newActorHeight = actorHeight;
174
+ if (actorWidth > stageWidth) {
175
+ tryZoom = stageWidth / actorWidth;
176
+ newActorHeight = actorHeight * tryZoom;
177
+ }
178
+ if (newActorHeight > maxHeight) {
179
+ tryZoom = maxHeight / actorHeight;
180
+ stageHeight = maxHeight;
181
+ }
182
+ stage.style.height = `${stageHeight + 24}px`;
183
+ if (tryZoom === 1) {
184
+ width.value = actorWidth;
185
+ x.value = (stageWidth - width.value) / 2;
186
+ y.value = (stageHeight - actorHeight) / 2;
187
+ } else {
188
+ width.value = actorWidth * tryZoom;
189
+ const zoomHeight = width.value / ratio;
190
+ x.value = (stageWidth - width.value) / 2;
191
+ y.value = Math.max(0, ((isFullscreen ? clientHeight : stage.offsetHeight) - zoomHeight) / 2);
192
+ }
193
+ originalWidth = actorWidth;
194
+ initialState = {
195
+ width: width.value,
196
+ x: x.value,
197
+ y: y.value
198
+ };
199
+ }
200
+ let isDragging = false;
201
+ let startX = 0;
202
+ let startY = 0;
203
+ useEventListener(parentEl, "mousedown", (e) => {
204
+ if (e.target.matches("button,[class^=\"vpi-\"]")) return;
205
+ e.preventDefault();
206
+ startX = e.clientX;
207
+ startY = e.clientY;
208
+ isDragging = true;
209
+ parentEl.value.style.cursor = "move";
210
+ });
211
+ useEventListener(parentEl, "mousemove", (e) => {
212
+ if (isDragging) {
213
+ e.preventDefault();
214
+ x.value += e.clientX - startX;
215
+ y.value += e.clientY - startY;
216
+ startX = e.clientX;
217
+ startY = e.clientY;
218
+ }
219
+ });
220
+ useEventListener(parentEl, "mouseup", () => {
221
+ isDragging = false;
222
+ parentEl.value.style.cursor = "";
223
+ });
224
+ let startGap = 0;
225
+ let currentWidth = 0;
226
+ useEventListener(parentEl, "touchstart", (e) => {
227
+ if (e.target.matches("button,[class^=\"vpi-\"]")) return;
228
+ e.preventDefault();
229
+ const touches = e.touches;
230
+ startX = touches[0].clientX;
231
+ startY = touches[0].clientY;
232
+ isDragging = true;
233
+ if (touches[1]) {
234
+ startGap = Math.abs(touches[1].clientX - touches[0].clientX);
235
+ currentWidth = width.value || originalWidth;
236
+ }
237
+ }, { passive: false });
238
+ useEventListener(parentEl, "touchmove", (e) => {
239
+ if (!isDragging) return;
240
+ const touches = e.touches;
241
+ e.preventDefault();
242
+ x.value += touches[0].clientX - startX;
243
+ y.value += touches[0].clientY - startY;
244
+ startX = touches[0].clientX;
245
+ startY = touches[0].clientY;
246
+ if (touches[1]) width.value = currentWidth + Math.abs(touches[1].clientX - touches[0].clientX) - startGap;
247
+ }, { passive: false });
248
+ useEventListener(parentEl, "touchend", () => {
249
+ isDragging = false;
250
+ }, { passive: false });
251
+ function zoom(type) {
252
+ if (typeof width.value === "undefined" || !actorEl.value) return;
253
+ if (type === 0) {
254
+ zooming();
255
+ x.value = initialState.x;
256
+ y.value = initialState.y;
257
+ width.value = initialState.width;
258
+ } else {
259
+ const steps = initialState.width / 10 * type;
260
+ if (width.value + steps <= 100) return;
261
+ zooming();
262
+ width.value += steps;
263
+ x.value -= steps / 2;
264
+ y.value -= steps / ratio / 2;
265
+ }
266
+ }
267
+ let zoomTimer;
268
+ function zooming() {
269
+ actorEl.value?.classList.add("zooming");
270
+ if (zoomTimer) clearTimeout(zoomTimer);
271
+ zoomTimer = setTimeout(() => {
272
+ actorEl.value.classList.remove("zooming");
273
+ }, 250);
274
+ }
275
+ return {
276
+ actorStyle: computed(() => ({
277
+ left: `${Math.ceil(x.value)}px`,
278
+ top: `${Math.ceil(y.value)}px`,
279
+ width: width.value ? `${Math.ceil(width.value)}px` : void 0,
280
+ height: `${width.value ? Math.ceil(width.value / ratio) : void 0}px`
281
+ })),
282
+ zoom: computed(() => `${Math.round((width.value || originalWidth) / originalWidth * 100)}%`),
283
+ reset: initialize,
284
+ zoomIn: () => zoom(1),
285
+ zoomOut: () => zoom(-1),
286
+ resetZoom: () => zoom(0)
287
+ };
288
+ }
289
+ //#endregion
104
290
  //#region src/client/utils/env.ts
105
291
  function getPlatform() {
106
292
  return navigator.userAgentData?.platform ?? navigator.platform;
@@ -178,4 +364,4 @@ function isSafari() {
178
364
  return /safari/iu.test(ua) && !/chrome|crios|fxios|edgios|edg|opr|opera|ucbrowser|qqbrowser|baidubrowser/iu.test(ua);
179
365
  }
180
366
  //#endregion
181
- export { EXTERNAL_URL_RE, URL_PROTOCOL_RE, _sfc_main as VPCopyButton, _sfc_main$1 as VPLoading, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize };
367
+ export { EXTERNAL_URL_RE, URL_PROTOCOL_RE, _sfc_main as VPCopyButton, _sfc_main$1 as VPLoading, _sfc_main$2 as VPTabSwitch, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize, useZoomAndDrag };
@@ -37,16 +37,42 @@ interface SizeOptions {
37
37
  type __VLS_Props$1 = {
38
38
  text: string;
39
39
  };
40
- declare const __VLS_export$1: import("vue").DefineComponent<__VLS_Props$1, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props$1> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
- declare const _default: typeof __VLS_export$1;
40
+ declare const __VLS_export$2: import("vue").DefineComponent<__VLS_Props$1, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props$1> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const _default: typeof __VLS_export$2;
42
42
  //#endregion
43
43
  //#region src/client/components/VPLoading.vue.d.ts
44
44
  type __VLS_Props = {
45
45
  absolute?: boolean;
46
46
  height?: string;
47
47
  };
48
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
- declare const _default$1: typeof __VLS_export;
48
+ declare const __VLS_export$1: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
+ declare const _default$1: typeof __VLS_export$1;
50
+ //#endregion
51
+ //#region src/client/components/VPTabSwitch.vue.d.ts
52
+ interface Item<T> {
53
+ value: T;
54
+ label: string;
55
+ }
56
+ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
57
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<({
58
+ items: Item<T>[];
59
+ } & {
60
+ modelValue?: T;
61
+ }) & {
62
+ onUpdate?: ((tab: T) => any) | undefined;
63
+ "onUpdate:modelValue"?: ((value: T | undefined) => any) | undefined;
64
+ }> & (typeof globalThis extends {
65
+ __VLS_PROPS_FALLBACK: infer P;
66
+ } ? P : {});
67
+ expose: (exposed: {}) => void;
68
+ attrs: any;
69
+ slots: {};
70
+ emit: ((evt: "update", tab: T) => void) & ((event: "update:modelValue", value: T | undefined) => void);
71
+ }>) => import("vue").VNode & {
72
+ __ctx?: Awaited<typeof __VLS_setup>;
73
+ };
74
+ declare const _default$2: typeof __VLS_export;
75
+ type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K] } : { [K in keyof T as K]: T[K] }) & {};
50
76
  //#endregion
51
77
  //#region src/client/composables/use-size.d.ts
52
78
  interface SizeInfo {
@@ -56,6 +82,21 @@ interface SizeInfo {
56
82
  }
57
83
  declare function useSize<T extends HTMLElement>(el: TemplateRef<T>, options: ToRefs<SizeOptions>, extraHeight?: MaybeRef<number>): SizeInfo;
58
84
  //#endregion
85
+ //#region src/client/composables/use-zoom-and-drag.d.ts
86
+ declare function useZoomAndDrag(parentEl: TemplateRef<HTMLDivElement>): {
87
+ actorStyle: import("vue").ComputedRef<{
88
+ left: string;
89
+ top: string;
90
+ width: string | undefined;
91
+ height: string;
92
+ }>;
93
+ zoom: import("vue").ComputedRef<string>;
94
+ reset: (isFullscreen?: boolean) => void;
95
+ zoomIn: () => void;
96
+ zoomOut: () => void;
97
+ resetZoom: () => void;
98
+ };
99
+ //#endregion
59
100
  //#region src/client/utils/env.d.ts
60
101
  interface NavigatorUAData {
61
102
  platform?: string;
@@ -123,4 +164,4 @@ declare function isMobile(): boolean;
123
164
  */
124
165
  declare function isSafari(): boolean;
125
166
  //#endregion
126
- export { EXTERNAL_URL_RE, SizeInfo, SizeOptions, URL_PROTOCOL_RE, _default as VPCopyButton, _default$1 as VPLoading, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize };
167
+ export { EXTERNAL_URL_RE, SizeInfo, SizeOptions, URL_PROTOCOL_RE, _default as VPCopyButton, _default$1 as VPLoading, _default$2 as VPTabSwitch, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize, useZoomAndDrag };
@@ -1,6 +1,6 @@
1
- import { computed, defineComponent, isRef, mergeProps, onMounted, ref, toValue, unref, useSSRContext, watch } from "vue";
2
- import { ssrRenderAttrs } from "vue/server-renderer";
3
- import { useClipboard, useEventListener } from "@vueuse/core";
1
+ import { computed, defineComponent, isRef, mergeModels, mergeProps, nextTick, onMounted, ref, shallowRef, toValue, unref, useModel, useSSRContext, watch } from "vue";
2
+ import { ssrInterpolate, ssrRenderAttrs, ssrRenderClass, ssrRenderList } from "vue/server-renderer";
3
+ import { useClipboard, useEventListener, useMediaQuery, useMutationObserver } from "@vueuse/core";
4
4
  //#region src/shared/link.ts
5
5
  const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
6
6
  function isExternal(path) {
@@ -12,7 +12,7 @@ function isLinkWithProtocol(link) {
12
12
  }
13
13
  //#endregion
14
14
  //#region src/client/components/VPCopyButton.vue
15
- const _sfc_main = /* @__PURE__ */ defineComponent({
15
+ const _sfc_main = /*@__PURE__*/ defineComponent({
16
16
  __name: "VPCopyButton",
17
17
  __ssrInlineRender: true,
18
18
  props: { text: {} },
@@ -27,15 +27,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
27
27
  };
28
28
  }
29
29
  });
30
- const _sfc_setup$1 = _sfc_main.setup;
30
+ const _sfc_setup$2 = _sfc_main.setup;
31
31
  _sfc_main.setup = (props, ctx) => {
32
32
  const ssrContext = useSSRContext();
33
33
  (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/client/components/VPCopyButton.vue");
34
- return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
34
+ return _sfc_setup$2 ? _sfc_setup$2(props, ctx) : void 0;
35
35
  };
36
36
  //#endregion
37
37
  //#region src/client/components/VPLoading.vue
38
- const _sfc_main$1 = /* @__PURE__ */ defineComponent({
38
+ const _sfc_main$1 = /*@__PURE__*/ defineComponent({
39
39
  __name: "VPLoading",
40
40
  __ssrInlineRender: true,
41
41
  props: {
@@ -51,10 +51,40 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
51
51
  };
52
52
  }
53
53
  });
54
- const _sfc_setup = _sfc_main$1.setup;
54
+ const _sfc_setup$1 = _sfc_main$1.setup;
55
55
  _sfc_main$1.setup = (props, ctx) => {
56
56
  const ssrContext = useSSRContext();
57
57
  (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/client/components/VPLoading.vue");
58
+ return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
59
+ };
60
+ //#endregion
61
+ //#region src/client/components/VPTabSwitch.vue
62
+ const _sfc_main$2 = /*@__PURE__*/ defineComponent({
63
+ __name: "VPTabSwitch",
64
+ __ssrInlineRender: true,
65
+ props: /*@__PURE__*/ mergeModels({ items: {} }, {
66
+ "modelValue": {},
67
+ "modelModifiers": {}
68
+ }),
69
+ emits: /*@__PURE__*/ mergeModels(["update"], ["update:modelValue"]),
70
+ setup(__props, { emit: __emit }) {
71
+ const tab = useModel(__props, "modelValue");
72
+ watch(() => __props.items, () => {
73
+ tab.value = __props.items[0].value;
74
+ });
75
+ return (_ctx, _push, _parent, _attrs) => {
76
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "vp-tab-switch-list" }, _attrs))}><!--[-->`);
77
+ ssrRenderList(__props.items, (item) => {
78
+ _push(`<button class="${ssrRenderClass({ active: tab.value === item.value })}">${ssrInterpolate(item.label)}</button>`);
79
+ });
80
+ _push(`<!--]--></div>`);
81
+ };
82
+ }
83
+ });
84
+ const _sfc_setup = _sfc_main$2.setup;
85
+ _sfc_main$2.setup = (props, ctx) => {
86
+ const ssrContext = useSSRContext();
87
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/client/components/VPTabSwitch.vue");
58
88
  return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
59
89
  };
60
90
  //#endregion
@@ -91,6 +121,160 @@ function getRadio(ratio) {
91
121
  return typeof ratio === "number" ? ratio : 16 / 9;
92
122
  }
93
123
  //#endregion
124
+ //#region src/client/composables/use-zoom-and-drag.ts
125
+ function useZoomAndDrag(parentEl) {
126
+ const actorEl = shallowRef();
127
+ let ratio = 0;
128
+ const x = ref(0);
129
+ const y = ref(0);
130
+ const width = ref(void 0);
131
+ let originalWidth = 0;
132
+ let initialState = {
133
+ width: 0,
134
+ x: 0,
135
+ y: 0
136
+ };
137
+ const isDesktop = useMediaQuery("(min-width: 640px)");
138
+ useMutationObserver(actorEl, (mutationList) => {
139
+ if (mutationList.some((mutation) => mutation.type === "childList")) nextTick(initialize);
140
+ }, {
141
+ subtree: true,
142
+ childList: true,
143
+ attributes: false
144
+ });
145
+ onMounted(() => nextTick(initialize));
146
+ function initialize(isFullscreen = false) {
147
+ if (!parentEl.value) return;
148
+ const actor = parentEl.value.querySelector(".content");
149
+ actorEl.value = actor;
150
+ if (!actor) return;
151
+ actor.style.width = "max-content";
152
+ actor.style.height = "";
153
+ const stage = parentEl.value;
154
+ const clientHeight = document.documentElement.clientHeight;
155
+ const maxHeight = isFullscreen ? clientHeight : isDesktop.value ? clientHeight * .75 : clientHeight / 2;
156
+ const { offsetWidth: actorWidth, offsetHeight: actorHeight } = actor;
157
+ const stageWidth = stage.offsetWidth;
158
+ ratio = actorWidth / actorHeight;
159
+ let tryZoom = 1;
160
+ let stageHeight = isFullscreen ? clientHeight : actorHeight;
161
+ let newActorHeight = actorHeight;
162
+ if (actorWidth > stageWidth) {
163
+ tryZoom = stageWidth / actorWidth;
164
+ newActorHeight = actorHeight * tryZoom;
165
+ }
166
+ if (newActorHeight > maxHeight) {
167
+ tryZoom = maxHeight / actorHeight;
168
+ stageHeight = maxHeight;
169
+ }
170
+ stage.style.height = `${stageHeight + 24}px`;
171
+ if (tryZoom === 1) {
172
+ width.value = actorWidth;
173
+ x.value = (stageWidth - width.value) / 2;
174
+ y.value = (stageHeight - actorHeight) / 2;
175
+ } else {
176
+ width.value = actorWidth * tryZoom;
177
+ const zoomHeight = width.value / ratio;
178
+ x.value = (stageWidth - width.value) / 2;
179
+ y.value = Math.max(0, ((isFullscreen ? clientHeight : stage.offsetHeight) - zoomHeight) / 2);
180
+ }
181
+ originalWidth = actorWidth;
182
+ initialState = {
183
+ width: width.value,
184
+ x: x.value,
185
+ y: y.value
186
+ };
187
+ }
188
+ let isDragging = false;
189
+ let startX = 0;
190
+ let startY = 0;
191
+ useEventListener(parentEl, "mousedown", (e) => {
192
+ if (e.target.matches("button,[class^=\"vpi-\"]")) return;
193
+ e.preventDefault();
194
+ startX = e.clientX;
195
+ startY = e.clientY;
196
+ isDragging = true;
197
+ parentEl.value.style.cursor = "move";
198
+ });
199
+ useEventListener(parentEl, "mousemove", (e) => {
200
+ if (isDragging) {
201
+ e.preventDefault();
202
+ x.value += e.clientX - startX;
203
+ y.value += e.clientY - startY;
204
+ startX = e.clientX;
205
+ startY = e.clientY;
206
+ }
207
+ });
208
+ useEventListener(parentEl, "mouseup", () => {
209
+ isDragging = false;
210
+ parentEl.value.style.cursor = "";
211
+ });
212
+ let startGap = 0;
213
+ let currentWidth = 0;
214
+ useEventListener(parentEl, "touchstart", (e) => {
215
+ if (e.target.matches("button,[class^=\"vpi-\"]")) return;
216
+ e.preventDefault();
217
+ const touches = e.touches;
218
+ startX = touches[0].clientX;
219
+ startY = touches[0].clientY;
220
+ isDragging = true;
221
+ if (touches[1]) {
222
+ startGap = Math.abs(touches[1].clientX - touches[0].clientX);
223
+ currentWidth = width.value || originalWidth;
224
+ }
225
+ }, { passive: false });
226
+ useEventListener(parentEl, "touchmove", (e) => {
227
+ if (!isDragging) return;
228
+ const touches = e.touches;
229
+ e.preventDefault();
230
+ x.value += touches[0].clientX - startX;
231
+ y.value += touches[0].clientY - startY;
232
+ startX = touches[0].clientX;
233
+ startY = touches[0].clientY;
234
+ if (touches[1]) width.value = currentWidth + Math.abs(touches[1].clientX - touches[0].clientX) - startGap;
235
+ }, { passive: false });
236
+ useEventListener(parentEl, "touchend", () => {
237
+ isDragging = false;
238
+ }, { passive: false });
239
+ function zoom(type) {
240
+ if (typeof width.value === "undefined" || !actorEl.value) return;
241
+ if (type === 0) {
242
+ zooming();
243
+ x.value = initialState.x;
244
+ y.value = initialState.y;
245
+ width.value = initialState.width;
246
+ } else {
247
+ const steps = initialState.width / 10 * type;
248
+ if (width.value + steps <= 100) return;
249
+ zooming();
250
+ width.value += steps;
251
+ x.value -= steps / 2;
252
+ y.value -= steps / ratio / 2;
253
+ }
254
+ }
255
+ let zoomTimer;
256
+ function zooming() {
257
+ actorEl.value?.classList.add("zooming");
258
+ if (zoomTimer) clearTimeout(zoomTimer);
259
+ zoomTimer = setTimeout(() => {
260
+ actorEl.value.classList.remove("zooming");
261
+ }, 250);
262
+ }
263
+ return {
264
+ actorStyle: computed(() => ({
265
+ left: `${Math.ceil(x.value)}px`,
266
+ top: `${Math.ceil(y.value)}px`,
267
+ width: width.value ? `${Math.ceil(width.value)}px` : void 0,
268
+ height: `${width.value ? Math.ceil(width.value / ratio) : void 0}px`
269
+ })),
270
+ zoom: computed(() => `${Math.round((width.value || originalWidth) / originalWidth * 100)}%`),
271
+ reset: initialize,
272
+ zoomIn: () => zoom(1),
273
+ zoomOut: () => zoom(-1),
274
+ resetZoom: () => zoom(0)
275
+ };
276
+ }
277
+ //#endregion
94
278
  //#region src/client/utils/env.ts
95
279
  function getPlatform() {
96
280
  return navigator.userAgentData?.platform ?? navigator.platform;
@@ -168,4 +352,4 @@ function isSafari() {
168
352
  return /safari/iu.test(ua) && !/chrome|crios|fxios|edgios|edg|opr|opera|ucbrowser|qqbrowser|baidubrowser/iu.test(ua);
169
353
  }
170
354
  //#endregion
171
- export { EXTERNAL_URL_RE, URL_PROTOCOL_RE, _sfc_main as VPCopyButton, _sfc_main$1 as VPLoading, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize };
355
+ export { EXTERNAL_URL_RE, URL_PROTOCOL_RE, _sfc_main as VPCopyButton, _sfc_main$1 as VPLoading, _sfc_main$2 as VPTabSwitch, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize, useZoomAndDrag };
@@ -0,0 +1,31 @@
1
+ .vp-tab-switch-list {
2
+ display: flex;
3
+ gap: 8px;
4
+ align-items: center;
5
+ justify-content: center;
6
+ padding-block: 2px;
7
+ padding-inline: 4px;
8
+ background-color: var(--vp-c-gray-soft);
9
+ border-radius: 6px;
10
+ }
11
+
12
+ .vp-tab-switch-list button {
13
+ display: inline-block;
14
+ padding-block: 2px;
15
+ padding-inline: 6px;
16
+ font-size: 14px;
17
+ font-weight: 500;
18
+ line-height: 18px;
19
+ color: var(--vp-c-text-3);
20
+ cursor: pointer;
21
+ user-select: none;
22
+ background-color: transparent;
23
+ border-radius: 6px;
24
+ transition: background-color 0.25s ease-in-out;
25
+ }
26
+
27
+ .vp-tab-switch-list button.active {
28
+ color: var(--vp-c-text-1);
29
+ background-color: var(--vp-c-bg);
30
+ box-shadow: var(--vp-shadow-1);
31
+ }
@@ -1,7 +1,7 @@
1
1
  import MarkdownIt from "markdown-it";
2
2
  import { RenderRule } from "markdown-it/lib/renderer.mjs";
3
3
  import { RuleOptions } from "markdown-it/lib/ruler.mjs";
4
- import { MarkdownEnv, SiteConfig } from "vitepress";
4
+ import { MarkdownEnv, Plugin, SiteConfig } from "vitepress";
5
5
 
6
6
  //#region src/shared/link.d.ts
7
7
  declare const EXTERNAL_URL_RE: RegExp;
@@ -184,19 +184,24 @@ declare function createEmbedRuleBlock<Meta extends Record<string, any> = Record<
184
184
  }: EmbedRuleBlockOptions<Meta>): void;
185
185
  //#endregion
186
186
  //#region src/node/utils/constants.d.ts
187
+ declare const isBuild: boolean;
188
+ declare const isDev: boolean;
187
189
  /**
188
- * 支持的视频文件名扩展名
190
+ * 浏览器支持的视频文件名扩展名
189
191
  */
190
192
  declare const EXTENSION_VIDEOS: string[];
191
193
  /**
192
- * 支持的图片文件名扩展名
194
+ * 浏览器支持的图片文件名扩展名
193
195
  */
194
196
  declare const EXTENSION_IMAGES: string[];
195
197
  /**
196
- * 支持的音频文件名扩展名
198
+ * 浏览器支持的音频文件名扩展名
197
199
  */
198
200
  declare const EXTENSION_AUDIOS: string[];
199
201
  //#endregion
202
+ //#region src/node/utils/hash.d.ts
203
+ declare function genHash(data: unknown, length?: number): string;
204
+ //#endregion
200
205
  //#region src/node/utils/logger.d.ts
201
206
  type LogType = 'info' | 'warn' | 'error' | 'debug';
202
207
  type LogLevel = LogType | 'silent';
@@ -305,6 +310,14 @@ declare function stringifyAttrs<T extends object = object>(attrs: T, withUndefin
305
310
  //#region src/node/utils/treat-as-html.d.ts
306
311
  declare function treatAsHtml(filename: string): boolean;
307
312
  //#endregion
313
+ //#region src/node/vite-plugins/iconPlugin.d.ts
314
+ interface Icon {
315
+ name: string;
316
+ svg: string;
317
+ classname?: string;
318
+ }
319
+ declare function iconPlugin(icons: Icon[]): Plugin;
320
+ //#endregion
308
321
  //#region src/node/vitepress/createLocales.d.ts
309
322
  type BuiltinLocale<LocaleData extends Record<string, unknown>> = [langCodes: string[], localeData: LocaleData];
310
323
  type BuiltinLocales<LocaleData extends Record<string, unknown>> = BuiltinLocale<LocaleData>[];
@@ -328,4 +341,4 @@ declare function getVitepressConfig(): SiteConfig;
328
341
  //#region src/node/vitepress/resolve-route-link.d.ts
329
342
  declare function resolveRouteLink(url: string, env: MarkdownEnv): string;
330
343
  //#endregion
331
- export { BuiltinLocale, BuiltinLocales, ContainerOptions, EXTENSION_AUDIOS, EXTENSION_IMAGES, EXTENSION_VIDEOS, EXTERNAL_URL_RE, EmbedRuleBlockOptions, LogLevel, LogType, Logger, SizeOptions, URL_PROTOCOL_RE, createContainerPlugin, createContainerSyntaxPlugin, createEmbedRuleBlock, createLocales, createLogger, getLocaleWithPath, getVitepressConfig, isExternal, isLinkWithProtocol, logLevels, parseRect, resolveAttr, resolveAttrs, resolveRouteLink, slugify, stringifyAttrs, treatAsHtml };
344
+ export { BuiltinLocale, BuiltinLocales, ContainerOptions, EXTENSION_AUDIOS, EXTENSION_IMAGES, EXTENSION_VIDEOS, EXTERNAL_URL_RE, EmbedRuleBlockOptions, LogLevel, LogType, Logger, SizeOptions, URL_PROTOCOL_RE, createContainerPlugin, createContainerSyntaxPlugin, createEmbedRuleBlock, createLocales, createLogger, genHash, getLocaleWithPath, getVitepressConfig, iconPlugin, isBuild, isDev, isExternal, isLinkWithProtocol, logLevels, parseRect, resolveAttr, resolveAttrs, resolveRouteLink, slugify, stringifyAttrs, treatAsHtml };
@@ -1,7 +1,8 @@
1
1
  import container from "markdown-it-container";
2
- import { camelCase, deepMerge, isBoolean, isNull, isNumber, isString, isUndefined, kebabCase, objectEntries, objectKeys, slash } from "@pengzhanbo/utils";
3
- import ansis from "ansis";
2
+ import { camelCase, deepMerge, isBoolean, isNull, isNumber, isPrimitive, isString, isUndefined, kebabCase, objectEntries, objectKeys, omit, slash } from "@pengzhanbo/utils";
4
3
  import process from "node:process";
4
+ import { createHash } from "node:crypto";
5
+ import ansis from "ansis";
5
6
  //#region src/shared/link.ts
6
7
  const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
7
8
  function isExternal(path) {
@@ -202,8 +203,10 @@ function createEmbedRuleBlock(md, { type, name = type, syntaxPattern, beforeName
202
203
  }
203
204
  //#endregion
204
205
  //#region src/node/utils/constants.ts
206
+ const isBuild = process.env.NODE_ENV === "production";
207
+ const isDev = process.env.NODE_ENV === "development";
205
208
  /**
206
- * 支持的视频文件名扩展名
209
+ * 浏览器支持的视频文件名扩展名
207
210
  */
208
211
  const EXTENSION_VIDEOS = [
209
212
  "mp4",
@@ -221,7 +224,7 @@ const EXTENSION_VIDEOS = [
221
224
  "ogv"
222
225
  ];
223
226
  /**
224
- * 支持的图片文件名扩展名
227
+ * 浏览器支持的图片文件名扩展名
225
228
  */
226
229
  const EXTENSION_IMAGES = [
227
230
  "jpg",
@@ -241,7 +244,7 @@ const EXTENSION_IMAGES = [
241
244
  "xbm"
242
245
  ];
243
246
  /**
244
- * 支持的音频文件名扩展名
247
+ * 浏览器支持的音频文件名扩展名
245
248
  */
246
249
  const EXTENSION_AUDIOS = [
247
250
  "mp3",
@@ -253,6 +256,13 @@ const EXTENSION_AUDIOS = [
253
256
  "acc"
254
257
  ];
255
258
  //#endregion
259
+ //#region src/node/utils/hash.ts
260
+ function genHash(data, length) {
261
+ const str = isPrimitive(data) ? String(data) : JSON.stringify(data);
262
+ const hash = createHash("sha256").update(str).digest("hex");
263
+ return length ? hash.slice(0, length) : hash;
264
+ }
265
+ //#endregion
256
266
  //#region src/node/utils/logger.ts
257
267
  /**
258
268
  * Log levels mapping
@@ -375,6 +385,44 @@ function treatAsHtml(filename) {
375
385
  return ext == null || !KNOWN_EXTENSIONS.has(ext.toLowerCase());
376
386
  }
377
387
  //#endregion
388
+ //#region src/node/vite-plugins/iconPlugin.ts
389
+ const name = "vitepress:tuck-icons";
390
+ const iconList = [];
391
+ let isProcessing = false;
392
+ function iconPlugin(icons) {
393
+ for (const icon of icons) {
394
+ const index = iconList.findIndex((item) => item.name === icon.name);
395
+ if (index === -1) iconList.push({
396
+ ...omit(icon, ["classname"]),
397
+ classname: new Set([icon.classname || icon.name])
398
+ });
399
+ else icon.classname && iconList[index].classname.add(icon.classname);
400
+ }
401
+ const moduleId = "virtual:tuck-icons.css";
402
+ const resolveId = `\0${moduleId}`;
403
+ return {
404
+ name,
405
+ enforce: "post",
406
+ resolveId(id) {
407
+ if (id === moduleId) {
408
+ isProcessing = true;
409
+ return resolveId;
410
+ }
411
+ },
412
+ load(id) {
413
+ if (id !== resolveId) return null;
414
+ if (!isProcessing) return null;
415
+ let css = "";
416
+ for (const icon of iconList) {
417
+ const classname = Array.from(icon.classname).map((name) => `.vpi-${name}`).join(",\n");
418
+ css += `${classname} {\n --icon: ${icon.svg};\n}\n`;
419
+ }
420
+ isProcessing = false;
421
+ return css;
422
+ }
423
+ };
424
+ }
425
+ //#endregion
378
426
  //#region src/node/vitepress/get-vitepress-config.ts
379
427
  function getVitepressConfig() {
380
428
  const config = globalThis.VITEPRESS_CONFIG;
@@ -444,4 +492,4 @@ function normalizeHash(str) {
444
492
  return str ? encodeURI(`#${slugify(decodeURI(str).slice(1))}`) : "";
445
493
  }
446
494
  //#endregion
447
- export { EXTENSION_AUDIOS, EXTENSION_IMAGES, EXTENSION_VIDEOS, EXTERNAL_URL_RE, URL_PROTOCOL_RE, createContainerPlugin, createContainerSyntaxPlugin, createEmbedRuleBlock, createLocales, createLogger, getLocaleWithPath, getVitepressConfig, isExternal, isLinkWithProtocol, logLevels, parseRect, resolveAttr, resolveAttrs, resolveRouteLink, slugify, stringifyAttrs, treatAsHtml };
495
+ export { EXTENSION_AUDIOS, EXTENSION_IMAGES, EXTENSION_VIDEOS, EXTERNAL_URL_RE, URL_PROTOCOL_RE, createContainerPlugin, createContainerSyntaxPlugin, createEmbedRuleBlock, createLocales, createLogger, genHash, getLocaleWithPath, getVitepressConfig, iconPlugin, isBuild, isDev, isExternal, isLinkWithProtocol, logLevels, parseRect, resolveAttr, resolveAttrs, resolveRouteLink, slugify, stringifyAttrs, treatAsHtml };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vitepress-plugin-toolkit",
3
3
  "type": "module",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "description": "Development toolkit for vitepress plugins",
6
6
  "author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)",
7
7
  "license": "MIT",