v-uixy 1.9.0 → 1.9.2

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.
@@ -1,10 +1,16 @@
1
1
  export type UixyPieChartData = {
2
2
  label: string;
3
3
  value: number;
4
- color: string;
4
+ color?: string;
5
5
  };
6
6
 
7
7
  export interface UixyPieChartProps {
8
8
  data: UixyPieChartData[];
9
+ resolution?: number;
9
10
  thickness?: number;
11
+ total?: string;
12
+ legend?: boolean;
13
+ animate?: boolean;
14
+ interactive?: boolean;
15
+ format?: (value: number) => string;
10
16
  }
@@ -11,7 +11,7 @@
11
11
  :style="{ zIndex }"
12
12
  data-uixy-overlay
13
13
  @click.self="handleClick"
14
- class="fixed left-0 top-0 size-full bg-white/5 backdrop-blur-[2px] dark:bg-gray-900/5"
14
+ class="fixed left-0 top-0 size-full bg-white/5 [html[data-uixy-gpu=on]_&]:backdrop-blur-[2px] dark:bg-gray-900/5"
15
15
  />
16
16
  <motion.div
17
17
  initial="initial"
@@ -37,7 +37,7 @@
37
37
  <script setup lang="ts">
38
38
  import { AnimatePresence, motion } from "motion-v";
39
39
  import { useScale } from "../Scale";
40
- import { useOverlayLayer } from "~/composables";
40
+ import { useOverlayLayer, useGpuAcceleration } from "~/composables";
41
41
  import type { UixySheetProps } from "./Sheet.types";
42
42
  import { sheetStyles } from "./Sheet.styles";
43
43
 
@@ -72,6 +72,8 @@
72
72
 
73
73
  const { zIndex, acquire, release } = useOverlayLayer();
74
74
 
75
+ useGpuAcceleration();
76
+
75
77
  const open = defineModel<boolean>();
76
78
 
77
79
  const handleClick = () => {
@@ -2,11 +2,17 @@ export * from "./Accordion";
2
2
  export * from "./Alert";
3
3
  export * from "./Avatar";
4
4
  export * from "./Badge";
5
+ export * from "./Breadcrumb";
5
6
  export * from "./Button";
6
7
  export * from "./Calendar";
7
8
  export * from "./Card";
9
+ export * from "./Chart";
8
10
  export * from "./Checkbox";
11
+ export * from "./ColorPicker";
9
12
  export * from "./Command";
13
+ export * from "./DatePicker";
14
+ export * from "./DateRangePicker";
15
+ export * from "./FileUpload";
10
16
  export * from "./Icon";
11
17
  export * from "./IconButton";
12
18
  export * from "./Input";
@@ -18,12 +24,14 @@ export * from "./PieChart";
18
24
  export * from "./Popover";
19
25
  export * from "./Radio";
20
26
  export * from "./Scale";
27
+ export * from "./SegmentedControl";
21
28
  export * from "./Select";
22
29
  export * from "./Separator";
23
30
  export * from "./Sheet";
24
31
  export * from "./Skeleton";
25
32
  export * from "./Slider";
26
33
  export * from "./Switch";
34
+ export * from "./Table";
27
35
  export * from "./TableOfContents";
28
36
  export * from "./Tabs";
29
37
  export * from "./Textarea";
@@ -32,4 +40,3 @@ export * from "./TimePicker";
32
40
  export * from "./Toast";
33
41
  export * from "./Toggle";
34
42
  export * from "./Tooltip";
35
- export * from "./ColorPicker";
@@ -130,12 +130,12 @@
130
130
  "name": "Modal",
131
131
  "related-components": [],
132
132
  "packages": ["motion-v"],
133
- "composables": ["useOverlayLayer"]
133
+ "composables": ["useOverlayLayer", "useGpuAcceleration"]
134
134
  },
135
135
  {
136
136
  "name": "PieChart",
137
137
  "related-components": [],
138
- "packages": ["motion-v"],
138
+ "packages": [],
139
139
  "composables": []
140
140
  },
141
141
  {
@@ -178,7 +178,7 @@
178
178
  "name": "Sheet",
179
179
  "related-components": ["Scale"],
180
180
  "packages": ["motion-v"],
181
- "composables": ["useOverlayLayer"]
181
+ "composables": ["useOverlayLayer", "useGpuAcceleration"]
182
182
  },
183
183
  {
184
184
  "name": "Skeleton",
@@ -213,7 +213,7 @@
213
213
  {
214
214
  "name": "Tabs",
215
215
  "related-components": [],
216
- "packages": ["motion-v"],
216
+ "packages": ["motion-v", "uuid"],
217
217
  "composables": []
218
218
  },
219
219
  {
@@ -0,0 +1,79 @@
1
+ import { onMounted } from "vue";
2
+
3
+ const GPU_ATTRIBUTE = "data-uixy-gpu";
4
+ const IDLE_TIMEOUT_MS = 2000;
5
+ const FALLBACK_DELAY_MS = 200;
6
+
7
+ const SOFTWARE_RENDERER_PATTERN =
8
+ /swiftshader|llvmpipe|softpipe|software|basic render/i;
9
+
10
+ let cachedResult: boolean | null = null;
11
+ let isDetectionScheduled = false;
12
+
13
+ const createWebGlContext = (): WebGLRenderingContext | null => {
14
+ const canvas = document.createElement("canvas");
15
+ const options = { failIfMajorPerformanceCaveat: true };
16
+
17
+ return (canvas.getContext("webgl2", options) ??
18
+ canvas.getContext("webgl", options)) as WebGLRenderingContext | null;
19
+ };
20
+
21
+ const getRendererName = (gl: WebGLRenderingContext): string => {
22
+ const info = gl.getExtension("WEBGL_debug_renderer_info");
23
+
24
+ return info ? String(gl.getParameter(info.UNMASKED_RENDERER_WEBGL)) : "";
25
+ };
26
+
27
+ const checkGpuAcceleration = (): boolean => {
28
+ try {
29
+ const gl = createWebGlContext();
30
+
31
+ if (!gl) return false;
32
+
33
+ const isHardwareRenderer = !SOFTWARE_RENDERER_PATTERN.test(
34
+ getRendererName(gl),
35
+ );
36
+
37
+ gl.getExtension("WEBGL_lose_context")?.loseContext();
38
+
39
+ return isHardwareRenderer;
40
+ } catch {
41
+ return false;
42
+ }
43
+ };
44
+
45
+ export const detectGpuAcceleration = (): boolean => {
46
+ if (typeof document === "undefined") return false;
47
+
48
+ cachedResult ??= checkGpuAcceleration();
49
+
50
+ return cachedResult;
51
+ };
52
+
53
+ const applyGpuAttribute = () => {
54
+ const value = detectGpuAcceleration() ? "on" : "off";
55
+
56
+ document.documentElement.setAttribute(GPU_ATTRIBUTE, value);
57
+ };
58
+
59
+ const runWhenIdle = (callback: () => void) => {
60
+ if ("requestIdleCallback" in window) {
61
+ window.requestIdleCallback(callback, { timeout: IDLE_TIMEOUT_MS });
62
+ return;
63
+ }
64
+
65
+ setTimeout(callback, FALLBACK_DELAY_MS);
66
+ };
67
+
68
+ export function useGpuAcceleration() {
69
+ onMounted(() => {
70
+ if (
71
+ isDetectionScheduled ||
72
+ document.documentElement.hasAttribute(GPU_ATTRIBUTE)
73
+ )
74
+ return;
75
+
76
+ isDetectionScheduled = true;
77
+ runWhenIdle(applyGpuAttribute);
78
+ });
79
+ }
@@ -47,6 +47,7 @@ export function useOverlayLayer(): UseOverlayLayerReturn {
47
47
  const MANAGED_ATTR = "data-uixy-inert-managed";
48
48
  const OVERLAY_ATTR = "data-uixy-overlay";
49
49
  export const MODAL_ATTR = "data-uixy-modal";
50
+ export const MODAL_ID_ATTR = "data-uixy-modal-id";
50
51
 
51
52
  const modalStack = ref<number[]>([]);
52
53
 
@@ -60,7 +61,11 @@ export const getTopModalEl = (): HTMLElement | null => {
60
61
  if (typeof document === "undefined") return null;
61
62
  const els = Array.from(
62
63
  document.querySelectorAll<HTMLElement>(`[${MODAL_ATTR}]`),
63
- );
64
+ ).filter((el) => {
65
+ const raw = el.getAttribute(MODAL_ID_ATTR);
66
+ if (raw === null) return true;
67
+ return modalStack.value.includes(Number(raw));
68
+ });
64
69
  if (els.length === 0) return null;
65
70
  return els.reduce((a, b) => (zOf(b) >= zOf(a) ? b : a));
66
71
  };
@@ -92,6 +97,7 @@ function reconcileInert() {
92
97
  }
93
98
 
94
99
  export interface UseModalLayerReturn {
100
+ id: number;
95
101
  zIndex: ComputedRef<number>;
96
102
  isTopModal: ComputedRef<boolean>;
97
103
  open: () => void;
@@ -115,10 +121,11 @@ export function useModalLayer(): UseModalLayerReturn {
115
121
  const close = () => {
116
122
  layer.release();
117
123
  modalStack.value = modalStack.value.filter((x) => x !== layer.id);
124
+ reconcileInert();
118
125
  nextTick(reconcileInert);
119
126
  };
120
127
 
121
128
  onScopeDispose(close);
122
129
 
123
- return { zIndex: layer.zIndex, isTopModal, open, close };
130
+ return { id: layer.id, zIndex: layer.zIndex, isTopModal, open, close };
124
131
  }