pxd 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # PXD
2
2
  A universal UI component library for Vue2&3
3
3
 
4
+ > [!WARNING]
5
+ > The project is under active development and is not ready for production.
6
+
4
7
  ## Contribution
5
8
 
6
9
  ### Dev
@@ -9,8 +12,6 @@ A universal UI component library for Vue2&3
9
12
  pnpm install
10
13
 
11
14
  pnpm dev
12
-
13
- pnpm dev:docs
14
15
  ```
15
16
 
16
17
  ### Build
@@ -1,61 +1,69 @@
1
1
  <script setup>
2
+ import { twMerge } from "tailwind-merge";
2
3
  import { computed } from "vue";
3
4
  import { useConfigProvider } from "../../composables/useConfigProviderContext";
5
+ import Spinner from "../spinner/index.vue";
4
6
  defineOptions({
5
7
  name: "PButton"
6
8
  });
7
9
  const props = defineProps({
10
+ as: { type: null, required: false, default: "button" },
8
11
  variant: { type: null, required: false, default: "outline" },
9
12
  size: { type: null, required: false },
10
- disabled: { type: Boolean, required: false },
13
+ class: { type: [String, Object, Array], required: false },
14
+ shape: { type: String, required: false },
11
15
  block: { type: Boolean, required: false },
12
- href: { type: String, required: false },
13
- shape: { type: String, required: false }
16
+ loading: { type: Boolean, required: false },
17
+ disabled: { type: Boolean, required: false }
14
18
  });
15
19
  const config = useConfigProvider();
16
20
  const SIZES = {
17
- xs: "px-1 rounded-md h-6 text-sm ",
18
- sm: "px-1.5 rounded-md h-7 text-sm ",
19
- md: "px-2.5 rounded-md h-8 text-sm ",
20
- lg: "px-3.5 rounded-lg h-9 text-base "
21
+ xs: "px-1 rounded-md h-6 text-sm",
22
+ sm: "px-1.5 rounded-md h-7 text-sm",
23
+ md: "px-2.5 rounded-md h-8 text-sm",
24
+ lg: "px-3.5 rounded-lg h-9 text-base"
21
25
  };
22
26
  const VARIANTS = {
23
- outline: "bg-background text-foreground hover:bg-background-hover active:bg-background-active border-input ",
24
- ghost: "bg-transparent text-foreground hover:bg-gray-alpha-200 active:bg-gray-alpha-300 border-transparent ",
25
- primary: "bg-foreground text-background hover:bg-foreground/80 active:bg-foreground border-transparent ",
26
- error: "bg-red-800 text-white hover:bg-red-700 active:bg-red-800 border-transparent ",
27
- warning: "bg-amber-800 text-black hover:bg-amber-700 active:bg-amber-800 border-transparent ",
28
- success: "bg-green-800 text-white hover:bg-green-700 active:bg-green-800 border-transparent "
27
+ outline: "bg-background text-foreground hover:bg-background-hover active:bg-background-active border-input",
28
+ ghost: "bg-transparent text-foreground hover:bg-gray-alpha-200 active:bg-gray-alpha-300 border-transparent",
29
+ primary: "bg-foreground text-background hover:bg-foreground/80 active:bg-foreground border-transparent",
30
+ error: "bg-red-800 text-white hover:bg-red-700 active:bg-red-800 border-transparent",
31
+ warning: "bg-amber-800 text-black hover:bg-amber-700 active:bg-amber-800 border-transparent",
32
+ success: "bg-green-800 text-white hover:bg-green-700 active:bg-green-800 border-transparent"
29
33
  };
30
- const DISABLED_CLASS_NAMES = "disabled:bg-gray-100 !text-gray-700 border-none shadow-[0_0_0_1px_hsl(var(--gray-200-value))] !cursor-not-allowed ";
34
+ const DISABLED_CLASS_NAMES = "is-disabled bg-gray-100 hover:bg-gray-100 active:bg-gray-100 cursor-not-allowed text-gray-700 border-gray-300";
35
+ const computedDisabled = computed(() => {
36
+ return props.disabled || props.loading;
37
+ });
31
38
  const computedClassNames = computed(() => {
32
- let classNames = "";
33
- classNames += VARIANTS[props.variant] || VARIANTS.outline;
34
- classNames += SIZES[props.size || config.size];
35
- classNames += props.block ? "flex " : "inline-flex ";
36
- if (props.disabled) {
37
- classNames += DISABLED_CLASS_NAMES;
39
+ const classNames = ["pxd-button cursor-pointer motion-safe:transition-colors items-center justify-center border"];
40
+ classNames.push(VARIANTS[props.variant] || VARIANTS.outline);
41
+ classNames.push(SIZES[props.size || config.size]);
42
+ classNames.push(props.block ? "flex " : "inline-flex");
43
+ if (computedDisabled.value) {
44
+ classNames.push(DISABLED_CLASS_NAMES);
38
45
  }
39
- if (props.shape === "square") {
40
- classNames += "!rounded-none ";
41
- } else if (props.shape === "rounded") {
42
- classNames += "!rounded-full ";
46
+ if (props.shape) {
47
+ classNames.push(
48
+ props.shape === "square" ? "rounded-none" : "rounded-full"
49
+ );
43
50
  }
44
- return classNames;
51
+ return twMerge(classNames, props.class);
45
52
  });
46
53
  </script>
47
54
 
48
55
  <template>
49
56
  <Component
50
- :is="props.href ? 'router-link' : 'button'"
51
- class="pxd-button cursor-pointer transition-colors items-center justify-center border"
57
+ :is="as"
58
+ role="button"
52
59
  :class="computedClassNames"
53
- :disabled="disabled"
54
- :to="href"
60
+ :disabled="computedDisabled"
55
61
  >
62
+ <Spinner v-if="loading" />
63
+
56
64
  <slot name="prefix" />
57
65
 
58
- <span class="px-1 inline-flex truncate">
66
+ <span class="px-1.5 inline-flex truncate">
59
67
  <slot />
60
68
  </span>
61
69
 
@@ -0,0 +1,59 @@
1
+ <script setup>
2
+ import { MoonIcon, SunIcon } from "gdsi/vue";
3
+ import { customRef } from "vue";
4
+ import Button from "../button/index.vue";
5
+ const emits = defineEmits(["toggle"]);
6
+ const colorTransitions = {
7
+ dark: "light",
8
+ light: "dark"
9
+ };
10
+ const colorMode = customRef((track, trigger) => {
11
+ const storageKey = "fe.system.color-mode";
12
+ const rootClassList = document.documentElement.classList;
13
+ let curMode = rootClassList.contains("dark") ? "dark" : "light";
14
+ return {
15
+ get() {
16
+ track();
17
+ return curMode;
18
+ },
19
+ set(newMode) {
20
+ if (newMode === curMode)
21
+ return;
22
+ rootClassList.remove(curMode);
23
+ rootClassList.add(newMode);
24
+ localStorage.setItem(storageKey, newMode);
25
+ curMode = newMode;
26
+ trigger();
27
+ }
28
+ };
29
+ });
30
+ function toggleColorMode() {
31
+ colorMode.value = colorTransitions[colorMode.value];
32
+ emits("toggle", colorMode.value);
33
+ }
34
+ </script>
35
+
36
+ <template>
37
+ <Button aria-label="Toggle color mode" @click="toggleColorMode">
38
+ <Transition name="color-mode" mode="out-in">
39
+ <Component :is="colorMode === 'light' ? SunIcon : MoonIcon" class="size-[1em]" />
40
+ </Transition>
41
+ </Button>
42
+ </template>
43
+
44
+ <style>
45
+ @media (prefers-reduced-motion: no-preference) {
46
+ .color-mode-enter-active,
47
+ .color-mode-leave-active {
48
+ transition: transform 0.15s ease-out;
49
+ }
50
+
51
+ .color-mode-enter-from {
52
+ transform: rotate(-45deg) scale(0.68);
53
+ }
54
+
55
+ .color-mode-leave-to {
56
+ transform: rotate(45deg) scale(0.68);
57
+ }
58
+ }
59
+ </style>
@@ -1,12 +1,12 @@
1
1
  <script setup>
2
- import { defaultConfig, provideConfigProvider } from "../../composables/useConfigProviderContext";
2
+ import { provideConfigProvider } from "../../composables/useConfigProviderContext";
3
3
  defineOptions({
4
4
  name: "PConfigProvider"
5
5
  });
6
- const props = defineProps(/* @__PURE__ */ _mergeDefaults({
7
- as: { type: null, required: false },
8
- size: { type: String, required: false }
9
- }, { as: "div", ...defaultConfig }));
6
+ const props = defineProps({
7
+ as: { type: null, required: false, default: "div" },
8
+ size: { type: String, required: false, default: "md" }
9
+ });
10
10
  provideConfigProvider(props);
11
11
  </script>
12
12
 
@@ -1,36 +1,79 @@
1
1
  <script setup>
2
2
  import { shallowRef } from "vue";
3
3
  import Button from "../button/index.vue";
4
- defineProps({
4
+ defineOptions({
5
+ name: "PHoldButton"
6
+ });
7
+ const props = defineProps({
5
8
  scale: { type: Boolean, required: false, default: true },
9
+ disabled: { type: Boolean, required: false },
6
10
  durations: { type: [Number, String], required: false, default: 2 },
7
- maskColor: { type: String, required: false, default: "hsl(var(--red-600-value))" }
11
+ maskColor: { type: String, required: false, default: "hsl(var(--red-600-value))" },
12
+ cancelable: { type: Boolean, required: false }
8
13
  });
9
- const emits = defineEmits(["trigger", "confirm"]);
10
- let isPointerDown = true;
11
- const isConfirm = shallowRef(false);
12
- function onPointerDown() {
13
- isPointerDown = true;
14
- isConfirm.value = false;
14
+ const emits = defineEmits(["confirm", "canceled", "finished"]);
15
+ let isStarted = false;
16
+ const status = shallowRef("idle");
17
+ function onPointerEnter() {
18
+ if (props.disabled) {
19
+ return;
20
+ }
21
+ if (!isStarted) {
22
+ status.value = "idle";
23
+ return;
24
+ }
25
+ if (status.value === "canceled") {
26
+ status.value = "loading";
27
+ }
15
28
  }
16
- function onTransitionEnd(ev) {
17
- const targetElement = ev.target;
18
- const styleValue = getComputedStyle(targetElement).getPropertyValue(ev.propertyName);
19
- if (isPointerDown && styleValue === "inset(0px)") {
20
- emits("trigger");
21
- isPointerDown = false;
22
- isConfirm.value = true;
29
+ function onPointerLeave() {
30
+ if (props.disabled || !isStarted || !props.cancelable) {
31
+ return;
23
32
  }
33
+ status.value = "canceled";
34
+ emits("canceled");
35
+ }
36
+ function onPointerDown() {
37
+ if (props.disabled) {
38
+ return;
39
+ }
40
+ isStarted = true;
41
+ status.value = "loading";
24
42
  }
25
43
  function onPointerUp() {
26
- emits("confirm", isConfirm.value);
27
- isPointerDown = false;
28
- isConfirm.value = false;
44
+ if (props.disabled) {
45
+ return;
46
+ }
47
+ const isConfirmed = status.value === "confirmed";
48
+ isStarted = false;
49
+ status.value = "idle";
50
+ emits("finished", isConfirmed);
51
+ }
52
+ function onTransitionEnd({ target, propertyName }) {
53
+ if (status.value !== "loading") {
54
+ return;
55
+ }
56
+ const stylesValue = getComputedStyle(target).getPropertyValue(propertyName);
57
+ const isConfirmed = stylesValue === "inset(0px)";
58
+ if (isConfirmed) {
59
+ emits("confirm");
60
+ status.value = "confirmed";
61
+ return;
62
+ }
63
+ status.value = "loading";
29
64
  }
30
65
  </script>
31
66
 
32
67
  <template>
33
- <Button class="pxd-hold-button relative !transition-all" :class="{ scale }" @pointerdown="onPointerDown" @pointerup="onPointerUp">
68
+ <Button
69
+ class="pxd-hold-button relative motion-safe:transition-all"
70
+ :class="{ scale, effective: status !== 'canceled' }"
71
+ :disabled="disabled"
72
+ @pointerdown="onPointerDown"
73
+ @pointerup="onPointerUp"
74
+ @pointerenter="onPointerEnter"
75
+ @pointerleave="onPointerLeave"
76
+ >
34
77
  <template #prefix>
35
78
  <slot name="prefix" />
36
79
  </template>
@@ -41,7 +84,7 @@ function onPointerUp() {
41
84
  <slot name="suffix" />
42
85
  <div
43
86
  class="pxd-hold-button--overlay absolute -inset-px bg-(--mc) rounded-[inherit] pointer-events-none"
44
- :class="{ confirm: isConfirm }"
87
+ :class="{ finished: status === 'confirmed' }"
45
88
  :style="`--ds:${durations}s;--mc:${maskColor}`"
46
89
  @transitionend="onTransitionEnd"
47
90
  />
@@ -50,23 +93,23 @@ function onPointerUp() {
50
93
  </template>
51
94
 
52
95
  <style lang="postcss">
96
+ .pxd-hold-button.scale:active {
97
+ transform: scale(.97);
98
+ }
99
+
53
100
  .pxd-hold-button--overlay {
54
- --opacity: .48;
101
+ --opacity: .45;
55
102
  opacity: var(--opacity);
56
103
  clip-path: inset(0 100% 0 0);
57
104
  transition: clip-path .1s ease-out, opacity 0s linear;
58
105
 
59
- &.confirm {
60
- --opacity: .72;
106
+ &.finished {
107
+ --opacity: .68;
61
108
  }
62
109
  }
63
110
 
64
- .pxd-hold-button.scale:active {
65
- transform: scale(.97);
66
- }
67
-
68
- .pxd-hold-button:active .pxd-hold-button--overlay {
69
- clip-path: inset(0);
111
+ .pxd-hold-button.effective:not(.is-disabled):active .pxd-hold-button--overlay {
112
+ clip-path: inset(0px);
70
113
  transition: clip-path var(--ds) ease-out, opacity .2s ease-out;
71
114
  }
72
115
  </style>
@@ -1,3 +1,7 @@
1
1
  export { default as Button } from './button/index.vue';
2
+ export { default as ColorScheme } from './color-scheme/index.vue';
2
3
  export { default as ConfigProvider } from './config-provider/index.vue';
3
4
  export { default as HoldButton } from './hold-button/index.vue';
5
+ export { default as LinkButton } from './link-button/index.vue';
6
+ export { default as MoreButton } from './more-button/index.vue';
7
+ export { default as Spinner } from './spinner/index.vue';
@@ -1,3 +1,7 @@
1
1
  export { default as Button } from "./button/index.vue";
2
+ export { default as ColorScheme } from "./color-scheme/index.vue";
2
3
  export { default as ConfigProvider } from "./config-provider/index.vue";
3
4
  export { default as HoldButton } from "./hold-button/index.vue";
5
+ export { default as LinkButton } from "./link-button/index.vue";
6
+ export { default as MoreButton } from "./more-button/index.vue";
7
+ export { default as Spinner } from "./spinner/index.vue";
@@ -0,0 +1,56 @@
1
+ <script setup>
2
+ import { ExternalIcon } from "gdsi/vue";
3
+ import Button from "../button/index.vue";
4
+ defineOptions({
5
+ name: "PLinkButton"
6
+ });
7
+ const props = defineProps({
8
+ href: { type: String, required: true },
9
+ align: { type: String, required: false, default: "left" },
10
+ target: { type: String, required: false, default: "_self" },
11
+ externalIcon: { type: Boolean, required: false }
12
+ });
13
+ const alignClassName = {
14
+ left: "justify-start",
15
+ center: "justify-center",
16
+ right: "justify-end"
17
+ };
18
+ function linkAttrs() {
19
+ if (!props.href) {
20
+ return null;
21
+ }
22
+ const firstChar = props.href.slice(0, 1);
23
+ if (["#", "/"].includes(firstChar)) {
24
+ return {
25
+ as: "router-link",
26
+ to: props.href
27
+ };
28
+ }
29
+ return {
30
+ as: "a",
31
+ href: props.href,
32
+ target: props.target
33
+ };
34
+ }
35
+ </script>
36
+
37
+ <template>
38
+ <Button
39
+ v-bind="linkAttrs()"
40
+ role="link"
41
+ rel="noopener noreferrer"
42
+ class="pxd-link-button !no-underline"
43
+ :class="alignClassName[align]"
44
+ >
45
+ <template #prefix>
46
+ <slot name="prefix" />
47
+ </template>
48
+
49
+ <slot />
50
+
51
+ <template #suffix>
52
+ <slot name="suffix" />
53
+ <ExternalIcon v-if="externalIcon" class="opacity-50 scale-y-90" />
54
+ </template>
55
+ </Button>
56
+ </template>
@@ -0,0 +1,53 @@
1
+ <script setup>
2
+ import { ChevronDownIcon } from "gdsi/vue";
3
+ import { computed } from "vue";
4
+ import Button from "../button/index.vue";
5
+ defineOptions({
6
+ name: "PxdMoreButton",
7
+ model: {
8
+ prop: "modelValue",
9
+ event: "update:modelValue"
10
+ }
11
+ });
12
+ const props = defineProps({
13
+ moreText: { type: String, required: false, default: "Show More" },
14
+ lessText: { type: String, required: false, default: "Show Less" },
15
+ modelValue: { type: Boolean, required: false, default: false }
16
+ });
17
+ const emits = defineEmits(["update:modelValue"]);
18
+ const isExpanded = computed({
19
+ get() {
20
+ return props.modelValue;
21
+ },
22
+ set(value) {
23
+ emits("update:modelValue", value);
24
+ }
25
+ });
26
+ function onToggleExpand() {
27
+ isExpanded.value = !isExpanded.value;
28
+ }
29
+ </script>
30
+
31
+ <template>
32
+ <div class="pxd-more-button flex justify-center items-center relative px-4">
33
+ <Button variant="outline" shape="rounded" v-bind="$attrs" class="z-10" @click="onToggleExpand">
34
+ {{ isExpanded ? lessText : moreText }}
35
+
36
+ <template #suffix>
37
+ <ChevronDownIcon class="-ml-0.5 motion-safe:transition-transform motion-safe:duration-200" :class="{ 'rotate-180': isExpanded }" />
38
+ </template>
39
+ </Button>
40
+ </div>
41
+ </template>
42
+
43
+ <style>
44
+ .pxd-more-button::before {
45
+ content: '';
46
+ position: absolute;
47
+ top: 50%;
48
+ left: 0;
49
+ display: block;
50
+ width: 100%;
51
+ border-bottom: 1px solid var(--gray-alpha-300);
52
+ }
53
+ </style>
@@ -0,0 +1,18 @@
1
+ <script setup>
2
+ const ITEMS_COUNT = 12;
3
+ const ROTATE_STEP = 360 / ITEMS_COUNT;
4
+ const OPACITY_STEP = 1 / ITEMS_COUNT;
5
+ </script>
6
+
7
+ <template>
8
+ <div class="pxd-spinner relative text-gray-700 motion-safe:animate-spin overflow-hidden pointer-events-none size-[1em]">
9
+ <div class="absolute left-1/2 top-1/2 w-full h-full">
10
+ <div
11
+ v-for="i of ITEMS_COUNT"
12
+ :key="i"
13
+ class="pxd-spinner-item absolute rounded bg-current left-[-10%] top-[-3.9%] w-[24%] h-[8%]"
14
+ :style="{ opacity: i * OPACITY_STEP, transform: `rotate(${i * ROTATE_STEP}deg) translate(146%)` }"
15
+ />
16
+ </div>
17
+ </div>
18
+ </template>
@@ -0,0 +1,2 @@
1
+ export * from './useConfigProviderContext.js';
2
+ export * from './useMediaQuery.js';
@@ -0,0 +1,2 @@
1
+ export * from "./useConfigProviderContext.js";
2
+ export * from "./useMediaQuery.js";
@@ -3,6 +3,5 @@ export type ComponentSize = 'xs' | 'sm' | 'md' | 'lg';
3
3
  export interface ConfigProviderProps {
4
4
  size?: ComponentSize;
5
5
  }
6
- export declare const defaultConfig: Required<ConfigProviderProps>;
7
6
  export declare function provideConfigProvider(configProvider: ConfigProviderProps): void;
8
7
  export declare function useConfigProvider(): Required<ConfigProviderProps>;
@@ -1,11 +1,11 @@
1
1
  import { inject, provide } from "vue";
2
2
  export const injectionKey = "configProvider";
3
- export const defaultConfig = {
4
- size: "md"
5
- };
6
3
  export function provideConfigProvider(configProvider) {
7
4
  provide(injectionKey, configProvider);
8
5
  }
9
6
  export function useConfigProvider() {
7
+ const defaultConfig = {
8
+ size: "md"
9
+ };
10
10
  return inject(injectionKey, defaultConfig);
11
11
  }
@@ -0,0 +1,13 @@
1
+ export declare function useMediaQuery(query: string): import("vue").ShallowRef<boolean, boolean>;
2
+ export declare const MEDIA_QUERY: {
3
+ MOTION_REDUCE: string;
4
+ MOTION_NO_PREFERENCE: string;
5
+ MOTION_NO_REDUCE: string;
6
+ COLOR_SCHEME_LIGHT: string;
7
+ COLOR_SCHEME_DARK: string;
8
+ COLOR_SCHEME_NO_PREFERENCE: string;
9
+ SCROLLBAR_WIDTH: string;
10
+ SCROLLBAR_WIDTH_NONE: string;
11
+ SCROLLBAR_HEIGHT: string;
12
+ SCROLLBAR_HEIGHT_NONE: string;
13
+ };
@@ -0,0 +1,28 @@
1
+ import { onUnmounted, shallowRef } from "vue";
2
+ export function useMediaQuery(query) {
3
+ const matches = shallowRef(false);
4
+ if (typeof window !== "undefined" && window.matchMedia) {
5
+ matches.value = window.matchMedia(query).matches;
6
+ const mediaQuery = window.matchMedia(query);
7
+ const handler = (event) => {
8
+ matches.value = event.matches;
9
+ };
10
+ mediaQuery.addEventListener("change", handler, { passive: true });
11
+ onUnmounted(() => {
12
+ mediaQuery.removeEventListener("change", handler);
13
+ });
14
+ }
15
+ return matches;
16
+ }
17
+ export const MEDIA_QUERY = {
18
+ MOTION_REDUCE: "(prefers-reduced-motion: reduce)",
19
+ MOTION_NO_PREFERENCE: "(prefers-reduced-motion: no-preference)",
20
+ MOTION_NO_REDUCE: "(prefers-reduced-motion: no-reduce)",
21
+ COLOR_SCHEME_LIGHT: "(prefers-color-scheme: light)",
22
+ COLOR_SCHEME_DARK: "(prefers-color-scheme: dark)",
23
+ COLOR_SCHEME_NO_PREFERENCE: "(prefers-color-scheme: no-preference)",
24
+ SCROLLBAR_WIDTH: "(scrollbar-width: thin)",
25
+ SCROLLBAR_WIDTH_NONE: "(scrollbar-width: none)",
26
+ SCROLLBAR_HEIGHT: "(scrollbar-height: thin)",
27
+ SCROLLBAR_HEIGHT_NONE: "(scrollbar-height: none)"
28
+ };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import type { App } from 'vue';
2
2
  export * from './components/index';
3
- export default function install(app: App): void;
3
+ export default function install(app: App, prefix?: string): void;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as components from "./components/index.js";
2
2
  export * from "./components/index.js";
3
- export default function install(app) {
3
+ export default function install(app, prefix = "P") {
4
4
  Object.entries(components).forEach(([key, component]) => {
5
- app.component(key, component);
5
+ app.component(`${prefix}${key}`, component);
6
6
  });
7
7
  }
@@ -1,6 +1,5 @@
1
1
  import { addComponent, defineNuxtModule } from "@nuxt/kit";
2
- import * as components from "../index.js";
3
- import { name } from "../../package.json";
2
+ import * as components from "../components/index.js";
4
3
  export default defineNuxtModule({
5
4
  meta: {
6
5
  name: "pxd",
@@ -10,14 +9,14 @@ export default defineNuxtModule({
10
9
  }
11
10
  },
12
11
  defaults: {
13
- prefix: ""
12
+ prefix: "P"
14
13
  },
15
14
  async setup(options) {
16
15
  for (const component in components) {
17
16
  addComponent({
18
17
  name: `${options.prefix}${component}`,
19
18
  export: component,
20
- filePath: name
19
+ filePath: "pxd"
21
20
  });
22
21
  }
23
22
  }
@@ -0,0 +1,242 @@
1
+ :root {
2
+ --radius: 0.5rem;
3
+
4
+ --background-100: #fff;
5
+ --background-200: #f8f8f8;
6
+
7
+ /* --accents-1: #fafafa;
8
+ --accents-2: #eaeaea;
9
+ --accents-3: #999;
10
+ --accents-4: #888;
11
+ --accents-5: #666;
12
+ --accents-6: #444;
13
+ --accents-7: #333;
14
+ --accents-8: #111; */
15
+
16
+ --gray-alpha-100: hsla(0, 0%, 0%, 0.05);
17
+ --gray-alpha-200: hsla(0, 0%, 0%, 0.08);
18
+ --gray-alpha-300: hsla(0, 0%, 0%, 0.12);
19
+ --gray-alpha-400: hsla(0, 0%, 0%, 0.17);
20
+ --gray-alpha-500: hsla(0, 0%, 0%, 0.21);
21
+ --gray-alpha-600: hsla(0, 0%, 0%, 0.34);
22
+ --gray-alpha-700: hsla(0, 0%, 0%, 0.44);
23
+ --gray-alpha-800: hsla(0, 0%, 0%, 0.51);
24
+ --gray-alpha-900: hsla(0, 0%, 0%, 0.61);
25
+ --gray-alpha-1000: hsla(0, 0%, 0%, 0.91);
26
+
27
+ --gray-100-value: 0, 0%, 95%;
28
+ --gray-200-value: 0, 0%, 93%;
29
+ --gray-300-value: 0, 0%, 90%;
30
+ --gray-400-value: 0, 0%, 85%;
31
+ --gray-500-value: 0, 0%, 79%;
32
+ --gray-600-value: 0, 0%, 66%;
33
+ --gray-700-value: 0, 0%, 56%;
34
+ --gray-800-value: 0, 0%, 49%;
35
+ --gray-900-value: 0, 0%, 40%;
36
+ --gray-1000-value: 0, 0%, 9%;
37
+
38
+ --blue-100-value: 212, 100%, 97%;
39
+ --blue-200-value: 210, 100%, 96%;
40
+ --blue-300-value: 210, 100%, 94%;
41
+ --blue-400-value: 209, 100%, 90%;
42
+ --blue-500-value: 209, 100%, 80%;
43
+ --blue-600-value: 208, 100%, 66%;
44
+ --blue-700-value: 212, 100%, 48%;
45
+ --blue-800-value: 212, 100%, 41%;
46
+ --blue-900-value: 211, 100%, 42%;
47
+ --blue-1000-value: 211, 100%, 15%;
48
+
49
+ --red-100-value: 0, 100%, 97%;
50
+ --red-200-value: 0, 100%, 96%;
51
+ --red-300-value: 0, 100%, 95%;
52
+ --red-400-value: 0, 90%, 92%;
53
+ --red-500-value: 0, 82%, 85%;
54
+ --red-600-value: 359, 90%, 71%;
55
+ --red-700-value: 358, 75%, 59%;
56
+ --red-800-value: 358, 70%, 52%;
57
+ --red-900-value: 358, 66%, 48%;
58
+ --red-1000-value: 355, 49%, 15%;
59
+
60
+ --amber-100-value: 39, 100%, 95%;
61
+ --amber-200-value: 44, 100%, 92%;
62
+ --amber-300-value: 43, 96%, 90%;
63
+ --amber-400-value: 42, 100%, 78%;
64
+ --amber-500-value: 38, 100%, 71%;
65
+ --amber-600-value: 36, 90%, 62%;
66
+ --amber-700-value: 39, 100%, 57%;
67
+ --amber-800-value: 35, 100%, 52%;
68
+ --amber-900-value: 30, 100%, 32%;
69
+ --amber-1000-value: 20, 79%, 17%;
70
+
71
+ --green-100-value: 120, 60%, 96%;
72
+ --green-200-value: 120, 60%, 95%;
73
+ --green-300-value: 120, 60%, 91%;
74
+ --green-400-value: 122, 60%, 86%;
75
+ --green-500-value: 124, 60%, 75%;
76
+ --green-600-value: 125, 60%, 64%;
77
+ --green-700-value: 131, 41%, 46%;
78
+ --green-800-value: 132, 43%, 39%;
79
+ --green-900-value: 133, 50%, 32%;
80
+ --green-1000-value: 128, 29%, 15%;
81
+
82
+ --teal-100-value: 169, 70%, 96%;
83
+ --teal-200-value: 167, 70%, 94%;
84
+ --teal-300-value: 168, 70%, 90%;
85
+ --teal-400-value: 170, 70%, 85%;
86
+ --teal-500-value: 170, 70%, 72%;
87
+ --teal-600-value: 170, 70%, 57%;
88
+ --teal-700-value: 173, 80%, 36%;
89
+ --teal-800-value: 173, 83%, 30%;
90
+ --teal-900-value: 174, 91%, 25%;
91
+ --teal-1000-value: 171, 80%, 13%;
92
+
93
+ --purple-100-value: 276, 100%, 97%;
94
+ --purple-200-value: 277, 87%, 97%;
95
+ --purple-300-value: 274, 78%, 95%;
96
+ --purple-400-value: 276, 71%, 92%;
97
+ --purple-500-value: 274, 70%, 82%;
98
+ --purple-600-value: 273, 72%, 73%;
99
+ --purple-700-value: 272, 51%, 54%;
100
+ --purple-800-value: 272, 47%, 45%;
101
+ --purple-900-value: 274, 71%, 43%;
102
+ --purple-1000-value: 276, 100%, 15%;
103
+
104
+ --pink-100-value: 330, 100%, 96%;
105
+ --pink-200-value: 340, 90%, 96%;
106
+ --pink-300-value: 340, 82%, 94%;
107
+ --pink-400-value: 341, 76%, 91%;
108
+ --pink-500-value: 340, 75%, 84%;
109
+ --pink-600-value: 341, 75%, 73%;
110
+ --pink-700-value: 336, 80%, 58%;
111
+ --pink-800-value: 336, 74%, 51%;
112
+ --pink-900-value: 336, 65%, 45%;
113
+ --pink-1000-value: 333, 74%, 15%;
114
+
115
+ font-family: Inter, Geist, system-ui, Avenir, Helvetica, Arial, sans-serif;
116
+ line-height: 1.5;
117
+ font-weight: 400;
118
+ color-scheme: light dark;
119
+ background-color: var(--background-100);
120
+ color: hsl(var(--gray-1000-value));
121
+ }
122
+
123
+ :root.dark {
124
+ --background-100: #121212;
125
+ --background-200: #000;
126
+
127
+ /* --accents-1: #111;
128
+ --accents-2: #333;
129
+ --accents-3: #444;
130
+ --accents-4: #666;
131
+ --accents-5: #888;
132
+ --accents-6: #999;
133
+ --accents-7: #eaeaea;
134
+ --accents-8: #fafafa; */
135
+
136
+ --gray-100-value: 0, 0%, 10%;
137
+ --gray-200-value: 0, 0%, 12%;
138
+ --gray-300-value: 0, 0%, 16%;
139
+ --gray-400-value: 0, 0%, 18%;
140
+ --gray-500-value: 0, 0%, 27%;
141
+ --gray-600-value: 0, 0%, 53%;
142
+ --gray-700-value: 0, 0%, 56%;
143
+ --gray-800-value: 0, 0%, 49%;
144
+ --gray-900-value: 0, 0%, 63%;
145
+ --gray-1000-value: 0, 0%, 93%;
146
+
147
+ --blue-100-value: 216, 50%, 12%;
148
+ --blue-200-value: 214, 59%, 15%;
149
+ --blue-300-value: 213, 71%, 20%;
150
+ --blue-400-value: 212, 78%, 23%;
151
+ --blue-500-value: 211, 86%, 27%;
152
+ --blue-600-value: 206, 100%, 50%;
153
+ --blue-700-value: 212, 100%, 48%;
154
+ --blue-800-value: 212, 100%, 41%;
155
+ --blue-900-value: 210, 100%, 66%;
156
+ --blue-1000-value: 206, 100%, 96%;
157
+
158
+ --red-100-value: 357, 37%, 12%;
159
+ --red-200-value: 357, 46%, 16%;
160
+ --red-300-value: 356, 54%, 22%;
161
+ --red-400-value: 357, 55%, 26%;
162
+ --red-500-value: 357, 60%, 32%;
163
+ --red-600-value: 358, 75%, 59%;
164
+ --red-700-value: 358, 75%, 59%;
165
+ --red-800-value: 358, 69%, 52%;
166
+ --red-900-value: 358, 100%, 69%;
167
+ --red-1000-value: 353, 90%, 96%;
168
+
169
+ --amber-100-value: 35, 100%, 8%;
170
+ --amber-200-value: 32, 100%, 10%;
171
+ --amber-300-value: 33, 100%, 15%;
172
+ --amber-400-value: 35, 100%, 17%;
173
+ --amber-500-value: 35, 91%, 22%;
174
+ --amber-600-value: 39, 85%, 49%;
175
+ --amber-700-value: 39, 100%, 57%;
176
+ --amber-800-value: 35, 100%, 52%;
177
+ --amber-900-value: 39, 90%, 50%;
178
+ --amber-1000-value: 40, 94%, 93%;
179
+
180
+ --green-100-value: 136, 50%, 9%;
181
+ --green-200-value: 137, 50%, 12%;
182
+ --green-300-value: 136, 50%, 14%;
183
+ --green-400-value: 135, 70%, 16%;
184
+ --green-500-value: 135, 70%, 23%;
185
+ --green-600-value: 135, 70%, 34%;
186
+ --green-700-value: 131, 41%, 46%;
187
+ --green-800-value: 132, 43%, 39%;
188
+ --green-900-value: 131, 43%, 57%;
189
+ --green-1000-value: 136, 73%, 94%;
190
+
191
+ --teal-100-value: 169, 78%, 7%;
192
+ --teal-200-value: 170, 74%, 9%;
193
+ --teal-300-value: 171, 75%, 13%;
194
+ --teal-400-value: 171, 85%, 13%;
195
+ --teal-500-value: 172, 85%, 20%;
196
+ --teal-600-value: 172, 85%, 32%;
197
+ --teal-700-value: 173, 80%, 36%;
198
+ --teal-800-value: 173, 83%, 30%;
199
+ --teal-900-value: 174, 90%, 41%;
200
+ --teal-1000-value: 166, 71%, 93%;
201
+
202
+ --purple-100-value: 283, 30%, 12%;
203
+ --purple-200-value: 281, 38%, 16%;
204
+ --purple-300-value: 279, 44%, 23%;
205
+ --purple-400-value: 277, 46%, 28%;
206
+ --purple-500-value: 274, 49%, 35%;
207
+ --purple-600-value: 272, 51%, 54%;
208
+ --purple-700-value: 272, 51%, 54%;
209
+ --purple-800-value: 272, 47%, 45%;
210
+ --purple-900-value: 275, 80%, 71%;
211
+ --purple-1000-value: 281, 73%, 96%;
212
+
213
+ --pink-100-value: 335, 32%, 12%;
214
+ --pink-200-value: 335, 43%, 16%;
215
+ --pink-300-value: 335, 47%, 21%;
216
+ --pink-400-value: 335, 51%, 22%;
217
+ --pink-500-value: 335, 57%, 27%;
218
+ --pink-600-value: 336, 75%, 40%;
219
+ --pink-700-value: 336, 80%, 58%;
220
+ --pink-800-value: 336, 74%, 51%;
221
+ --pink-900-value: 341, 90%, 67%;
222
+ --pink-1000-value: 333, 90%, 96%;
223
+
224
+ --gray-alpha-100: hsla(0, 0%, 100%, .06);
225
+ --gray-alpha-200: hsla(0, 0%, 100%, .09);
226
+ --gray-alpha-300: hsla(0, 0%, 100%, .13);
227
+ --gray-alpha-400: hsla(0, 0%, 100%, .14);
228
+ --gray-alpha-500: hsla(0, 0%, 100%, .24);
229
+ --gray-alpha-600: hsla(0, 0%, 100%, .51);
230
+ --gray-alpha-700: hsla(0, 0%, 100%, .54);
231
+ --gray-alpha-800: hsla(0, 0%, 100%, .47);
232
+ --gray-alpha-900: hsla(0, 0%, 100%, .61);
233
+ --gray-alpha-1000: hsla(0, 0%, 100%, .92);
234
+ }
235
+
236
+ .scrollbar-hidden::-webkit-scrollbar {
237
+ display: none;
238
+ }
239
+
240
+ * {
241
+ border-color: hsl(var(--gray-300-value));
242
+ }
@@ -10,16 +10,16 @@
10
10
  --radius: 0.5rem;
11
11
 
12
12
  --background-100: #fff;
13
- --background-200: #fafafa;
13
+ --background-200: #f8f8f8;
14
14
 
15
- --accents-1: #fafafa;
15
+ /* --accents-1: #fafafa;
16
16
  --accents-2: #eaeaea;
17
17
  --accents-3: #999;
18
18
  --accents-4: #888;
19
19
  --accents-5: #666;
20
20
  --accents-6: #444;
21
21
  --accents-7: #333;
22
- --accents-8: #111;
22
+ --accents-8: #111; */
23
23
 
24
24
  --gray-alpha-100: hsla(0, 0%, 0%, 0.05);
25
25
  --gray-alpha-200: hsla(0, 0%, 0%, 0.08);
@@ -120,24 +120,26 @@
120
120
  --pink-900-value: 336, 65%, 45%;
121
121
  --pink-1000-value: 333, 74%, 15%;
122
122
 
123
- font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
123
+ font-family: Inter, Geist, system-ui, Avenir, Helvetica, Arial, sans-serif;
124
124
  line-height: 1.5;
125
125
  font-weight: 400;
126
126
  color-scheme: light dark;
127
+ background-color: var(--color-background);
128
+ color: var(--color-foreground);
127
129
  }
128
130
 
129
- .dark {
130
- --background-100: #0a0a0a;
131
+ :root.dark {
132
+ --background-100: #121212;
131
133
  --background-200: #000;
132
134
 
133
- --accents-1: #111;
135
+ /* --accents-1: #111;
134
136
  --accents-2: #333;
135
137
  --accents-3: #444;
136
138
  --accents-4: #666;
137
139
  --accents-5: #888;
138
140
  --accents-6: #999;
139
141
  --accents-7: #eaeaea;
140
- --accents-8: #fafafa;
142
+ --accents-8: #fafafa; */
141
143
 
142
144
  --gray-100-value: 0, 0%, 10%;
143
145
  --gray-200-value: 0, 0%, 12%;
@@ -370,9 +372,4 @@
370
372
  * {
371
373
  @apply border-border outline-ring/50;
372
374
  }
373
-
374
- body {
375
- background-color: var(--color-background);
376
- color: var(--color-foreground);
377
- }
378
375
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pxd",
3
3
  "type": "module",
4
- "version": "0.0.7",
4
+ "version": "0.0.9",
5
5
  "description": "A universal UI component library for Vue2&3.",
6
6
  "author": "libondev <bon.li@outlook.com>",
7
7
  "license": "MIT",
@@ -37,7 +37,12 @@
37
37
  "types": "./dist/components/index.d.ts",
38
38
  "default": "./dist/components/index.js"
39
39
  },
40
+ "./composables": {
41
+ "types": "./dist/composables/index.d.ts",
42
+ "default": "./dist/composables/index.js"
43
+ },
40
44
  "./tw.css": "./dist/styles/tw.css",
45
+ "./tokens.css": "./dist/styles/tokens.css",
41
46
  "./components/*": "./dist/components/*/index.vue"
42
47
  },
43
48
  "main": "./dist/index.js",
@@ -60,44 +65,52 @@
60
65
  "access": "public",
61
66
  "registry": "https://registry.npmjs.org/"
62
67
  },
68
+ "peerDependencies": {
69
+ "tailwind-merge": ">=3.0.0",
70
+ "vue": ">=2.7.0 || >=3.3.0"
71
+ },
72
+ "dependencies": {
73
+ "gdsi": "^1.2.1",
74
+ "tailwind-merge": "^3.2.0"
75
+ },
76
+ "devDependencies": {
77
+ "@antfu/eslint-config": "^4.12.0",
78
+ "@nuxt/kit": "^3.16.2",
79
+ "@nuxt/schema": "^3.16.2",
80
+ "@testing-library/vue": "^8.1.0",
81
+ "@tsconfig/node22": "^22.0.1",
82
+ "@types/node": "^22.14.1",
83
+ "@vitejs/plugin-vue": "^5.2.3",
84
+ "@vue/test-utils": "^2.4.6",
85
+ "@vue/tsconfig": "^0.7.0",
86
+ "eslint": "^9.25.1",
87
+ "jsdom": "^26.1.0",
88
+ "mkdist": "^2.3.0",
89
+ "npm-run-all2": "^7.0.2",
90
+ "tinyglobby": "^0.2.13",
91
+ "typescript": "^5.8.3",
92
+ "unbuild": "^3.5.0",
93
+ "unplugin-auto-import": "^19.1.2",
94
+ "unplugin-vue-components": "^28.5.0",
95
+ "vitest": "^3.1.2",
96
+ "vue": "^3.5.13",
97
+ "vue-sfc-transformer": "^0.1.13",
98
+ "vue-tsc": "^2.2.10"
99
+ },
63
100
  "scripts": {
64
- "dev": "unbuild --stub",
101
+ "dev": "run-s update-exports dev:lib dev:docs",
102
+ "dev:lib": "unbuild --stub",
65
103
  "dev:docs": "pnpm --filter docs dev",
66
- "build": "run-s typecheck update-exports build:lib",
104
+ "build": "run-s update-exports typecheck lint build:lib",
67
105
  "build:lib": "unbuild",
68
- "build:docs": "pnpm build && pnpm --filter docs build",
106
+ "build:docs": "pnpm --filter docs build",
69
107
  "preview:docs": "pnpm --filter docs preview",
70
108
  "update-exports": "node scripts/update-exports.js",
71
- "prepublishOnly": "pnpm build",
72
109
  "lint": "eslint .",
73
110
  "lint:fix": "eslint . --fix",
74
111
  "test": "vitest run",
75
112
  "test:watch": "vitest",
76
- "typecheck": "vue-tsc -p tsconfig.app.json --noEmit"
77
- },
78
- "devDependencies": {
79
- "@antfu/eslint-config": "catalog:",
80
- "@nuxt/kit": "catalog:",
81
- "@nuxt/schema": "catalog:",
82
- "@testing-library/vue": "catalog:",
83
- "@tsconfig/node22": "catalog:",
84
- "@types/node": "catalog:",
85
- "@vitejs/plugin-vue": "catalog:",
86
- "@vue/test-utils": "catalog:",
87
- "@vue/tsconfig": "catalog:",
88
- "eslint": "catalog:",
89
- "jsdom": "catalog:",
90
- "mkdist": "catalog:",
91
- "npm-run-all2": "catalog:",
92
- "tailwindcss": "catalog:",
93
- "tinyglobby": "catalog:",
94
- "typescript": "catalog:",
95
- "unbuild": "catalog:",
96
- "unplugin-auto-import": "catalog:",
97
- "unplugin-vue-components": "catalog:",
98
- "vitest": "catalog:",
99
- "vue": "catalog:",
100
- "vue-sfc-transformer": "catalog:",
101
- "vue-tsc": "catalog:"
113
+ "typecheck": "vue-tsc -p tsconfig.app.json --noEmit",
114
+ "bump": "pnpx bumpp"
102
115
  }
103
- }
116
+ }