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.
- package/package.json +1 -1
- package/templates/components/Button/Button.component.vue +2 -2
- package/templates/components/Chart/Chart.component.vue +895 -222
- package/templates/components/Chart/Chart.types.ts +7 -0
- package/templates/components/DatePicker/DatePicker.component.vue +25 -5
- package/templates/components/DatePicker/DatePicker.types.ts +1 -0
- package/templates/components/Input/Input.styles.ts +4 -2
- package/templates/components/Modal/Modal.component.vue +10 -1
- package/templates/components/Modal/Modal.styles.ts +1 -1
- package/templates/components/PieChart/PieChart.component.vue +515 -152
- package/templates/components/PieChart/PieChart.types.ts +7 -1
- package/templates/components/Sheet/Sheet.component.vue +4 -2
- package/templates/components/index.ts +8 -1
- package/templates/components.json +4 -4
- package/templates/composables/useGpuAcceleration.ts +79 -0
- package/templates/composables/useOverlayLayer.ts +9 -2
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
export type UixyPieChartData = {
|
|
2
2
|
label: string;
|
|
3
3
|
value: number;
|
|
4
|
-
color
|
|
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": [
|
|
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
|
}
|