orio-ui 0.1.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.
- package/LICENSE +21 -0
- package/README.md +237 -0
- package/dist/module.cjs +5 -0
- package/dist/module.d.mts +3 -0
- package/dist/module.d.ts +3 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +16 -0
- package/dist/runtime/assets/css/animation.css +1 -0
- package/dist/runtime/assets/css/colors.css +1 -0
- package/dist/runtime/assets/css/cool-gradient-hover.css +23 -0
- package/dist/runtime/assets/css/main.css +1 -0
- package/dist/runtime/assets/css/scroll.css +1 -0
- package/dist/runtime/components/Button.vue +102 -0
- package/dist/runtime/components/CheckBox.vue +93 -0
- package/dist/runtime/components/ControlElement.vue +39 -0
- package/dist/runtime/components/DashedContainer.vue +59 -0
- package/dist/runtime/components/DatePicker.vue +30 -0
- package/dist/runtime/components/DateRangePicker.vue +73 -0
- package/dist/runtime/components/EmptyState.vue +81 -0
- package/dist/runtime/components/Icon.vue +40 -0
- package/dist/runtime/components/Input.vue +48 -0
- package/dist/runtime/components/LoadingSpinner.vue +6 -0
- package/dist/runtime/components/Modal.vue +69 -0
- package/dist/runtime/components/Popover.vue +249 -0
- package/dist/runtime/components/Selector.vue +208 -0
- package/dist/runtime/components/Tag.vue +21 -0
- package/dist/runtime/components/Textarea.vue +53 -0
- package/dist/runtime/components/view/Dates.vue +59 -0
- package/dist/runtime/components/view/Separator.vue +26 -0
- package/dist/runtime/components/view/Text.vue +79 -0
- package/dist/runtime/composables/index.d.ts +4 -0
- package/dist/runtime/composables/index.js +4 -0
- package/dist/runtime/composables/useApi.d.ts +10 -0
- package/dist/runtime/composables/useApi.js +9 -0
- package/dist/runtime/composables/useFuzzySearch.d.ts +10 -0
- package/dist/runtime/composables/useFuzzySearch.js +22 -0
- package/dist/runtime/composables/useModal.d.ts +15 -0
- package/dist/runtime/composables/useModal.js +28 -0
- package/dist/runtime/composables/useTheme.d.ts +6 -0
- package/dist/runtime/composables/useTheme.js +23 -0
- package/dist/runtime/index.d.ts +20 -0
- package/dist/runtime/index.js +20 -0
- package/dist/runtime/utils/icon-registry.d.ts +2 -0
- package/dist/runtime/utils/icon-registry.js +26 -0
- package/dist/types.d.mts +7 -0
- package/dist/types.d.ts +7 -0
- package/nuxt.config.ts +38 -0
- package/package.json +99 -0
- package/src/module.ts +16 -0
- package/src/runtime/assets/css/animation.css +88 -0
- package/src/runtime/assets/css/colors.css +142 -0
- package/src/runtime/assets/css/cool-gradient-hover.scss +33 -0
- package/src/runtime/assets/css/main.css +11 -0
- package/src/runtime/assets/css/scroll.css +46 -0
- package/src/runtime/components/Button.vue +110 -0
- package/src/runtime/components/CheckBox.vue +103 -0
- package/src/runtime/components/ControlElement.vue +42 -0
- package/src/runtime/components/DashedContainer.vue +60 -0
- package/src/runtime/components/DatePicker.vue +84 -0
- package/src/runtime/components/DateRangePicker.vue +74 -0
- package/src/runtime/components/EmptyState.vue +87 -0
- package/src/runtime/components/Icon.vue +51 -0
- package/src/runtime/components/Input.vue +54 -0
- package/src/runtime/components/LoadingSpinner.vue +6 -0
- package/src/runtime/components/Modal.vue +111 -0
- package/src/runtime/components/Popover.vue +249 -0
- package/src/runtime/components/Selector.vue +224 -0
- package/src/runtime/components/Tag.vue +45 -0
- package/src/runtime/components/Textarea.vue +59 -0
- package/src/runtime/components/view/Dates.vue +61 -0
- package/src/runtime/components/view/Separator.vue +30 -0
- package/src/runtime/components/view/Text.vue +83 -0
- package/src/runtime/composables/index.ts +4 -0
- package/src/runtime/composables/useApi.ts +26 -0
- package/src/runtime/composables/useFuzzySearch.ts +51 -0
- package/src/runtime/composables/useModal.ts +47 -0
- package/src/runtime/composables/useTheme.ts +31 -0
- package/src/runtime/index.ts +25 -0
- package/src/runtime/utils/icon-registry.ts +41 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const iconRegistry = {
|
|
2
|
+
// Loading spinner (line-md:loading-loop)
|
|
3
|
+
"loading-loop": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><circle cx="12" cy="2" r="0"><animate attributeName="r" begin="0" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(45 12 12)"><animate attributeName="r" begin="0.125s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(90 12 12)"><animate attributeName="r" begin="0.25s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(135 12 12)"><animate attributeName="r" begin="0.375s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(180 12 12)"><animate attributeName="r" begin="0.5s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(225 12 12)"><animate attributeName="r" begin="0.625s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(270 12 12)"><animate attributeName="r" begin="0.75s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle><circle cx="12" cy="2" r="0" transform="rotate(315 12 12)"><animate attributeName="r" begin="0.875s" calcMode="spline" dur="1s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" repeatCount="indefinite" values="0;2;0;0"/></circle></svg>`,
|
|
4
|
+
// Chevron down (mdi-light:chevron-down)
|
|
5
|
+
"chevron-down": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6l-6-6z"/></svg>`,
|
|
6
|
+
// Chevron up
|
|
7
|
+
"chevron-up": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6l-6 6z"/></svg>`,
|
|
8
|
+
// Edit (material-symbols:edit-sharp)
|
|
9
|
+
"edit": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M3 21v-4.25L16.2 3.575q.3-.275.663-.425t.762-.15t.775.15t.65.45L20.425 5q.3.275.438.65T21 6.4q0 .4-.137.763t-.438.662L7.25 21zM17.6 7.8L19 6.4L17.6 5l-1.4 1.4z"/></svg>`,
|
|
10
|
+
// Check / Checkmark
|
|
11
|
+
"check": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16.17L4.83 12l-1.42 1.41L9 19L21 7l-1.41-1.41z"/></svg>`,
|
|
12
|
+
// Plus / Add
|
|
13
|
+
"plus": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>`,
|
|
14
|
+
// Calendar
|
|
15
|
+
"calendar": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 4h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2m0 16H5V10h14zm0-12H5V6h14zM7 12h5v5H7z"/></svg>`,
|
|
16
|
+
// Close / X
|
|
17
|
+
"close": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12z"/></svg>`,
|
|
18
|
+
// Search / Magnifying glass
|
|
19
|
+
"search": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M15.5 14h-.79l-.28-.27A6.47 6.47 0 0 0 16 9.5A6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5S14 7.01 14 9.5S11.99 14 9.5 14"/></svg>`,
|
|
20
|
+
// Upload
|
|
21
|
+
"upload": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M9 16h6v-6h4l-7-7l-7 7h4zm-4 2h14v2H5z"/></svg>`,
|
|
22
|
+
// Download
|
|
23
|
+
"download": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 9h-4V3H9v6H5l7 7zM5 18v2h14v-2z"/></svg>`,
|
|
24
|
+
// Delete / Trash
|
|
25
|
+
"delete": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12l1.41 1.41L13.41 14l2.12 2.12l-1.41 1.41L12 15.41l-2.12 2.12l-1.41-1.41L10.59 14zM15.5 4l-1-1h-5l-1 1H5v2h14V4z"/></svg>`
|
|
26
|
+
};
|
package/dist/types.d.mts
ADDED
package/dist/types.d.ts
ADDED
package/nuxt.config.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|
2
|
+
export default defineNuxtConfig({
|
|
3
|
+
// Makes this a Nuxt Layer
|
|
4
|
+
extends: [],
|
|
5
|
+
|
|
6
|
+
css: ['./src/runtime/assets/css/main.css'],
|
|
7
|
+
|
|
8
|
+
// Auto-import components with Orio prefix
|
|
9
|
+
components: {
|
|
10
|
+
dirs: [
|
|
11
|
+
{
|
|
12
|
+
path: './src/runtime/components',
|
|
13
|
+
prefix: 'Orio',
|
|
14
|
+
pathPrefix: false
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
// Auto-import composables
|
|
20
|
+
imports: {
|
|
21
|
+
dirs: ['./src/runtime/composables']
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
typescript: {
|
|
25
|
+
strict: true,
|
|
26
|
+
typeCheck: true
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
vite: {
|
|
30
|
+
css: {
|
|
31
|
+
preprocessorOptions: {
|
|
32
|
+
scss: {}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
compatibilityDate: '2025-01-15'
|
|
38
|
+
})
|
package/package.json
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "orio-ui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Modern Nuxt component library with theme support",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/runtime/index.js",
|
|
7
|
+
"types": "./dist/runtime/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/runtime/index.d.ts",
|
|
11
|
+
"import": "./dist/runtime/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./nuxt": {
|
|
14
|
+
"types": "./dist/module.d.ts",
|
|
15
|
+
"import": "./dist/module.mjs"
|
|
16
|
+
},
|
|
17
|
+
"./composables": {
|
|
18
|
+
"types": "./dist/runtime/composables/index.d.ts",
|
|
19
|
+
"import": "./dist/runtime/composables/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./styles": "./dist/runtime/assets/css/main.css",
|
|
22
|
+
"./theme": "./dist/runtime/assets/css/colors.css"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"nuxt.config.ts",
|
|
27
|
+
"src"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"dev": "vitepress dev docs",
|
|
31
|
+
"build": "nuxt-module-build build",
|
|
32
|
+
"prepack": "npm run build",
|
|
33
|
+
"test": "vitest",
|
|
34
|
+
"test:unit": "vitest run",
|
|
35
|
+
"test:watch": "vitest watch",
|
|
36
|
+
"docs:dev": "vitepress dev docs",
|
|
37
|
+
"docs:build": "vitepress build docs",
|
|
38
|
+
"docs:preview": "vitepress preview docs",
|
|
39
|
+
"lint": "eslint .",
|
|
40
|
+
"typecheck": "nuxt typecheck"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@nuxt/kit": "^3.15.3",
|
|
44
|
+
"@vueuse/core": "^11.0.0",
|
|
45
|
+
"@vueuse/integrations": "^11.0.0",
|
|
46
|
+
"fuse.js": "^7.0.0",
|
|
47
|
+
"nanoid": "^5.0.0",
|
|
48
|
+
"ofetch": "^1.5.1"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@eslint/js": "^9.39.2",
|
|
52
|
+
"@nuxt/eslint": "^1.12.1",
|
|
53
|
+
"@nuxt/module-builder": "^0.8.0",
|
|
54
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
55
|
+
"@vitest/ui": "^2.1.8",
|
|
56
|
+
"@vue/eslint-config-prettier": "^10.2.0",
|
|
57
|
+
"@vue/eslint-config-typescript": "^14.6.0",
|
|
58
|
+
"@vue/test-utils": "^2.4.6",
|
|
59
|
+
"eslint": "^9.39.2",
|
|
60
|
+
"eslint-config-prettier": "^10.1.8",
|
|
61
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
62
|
+
"eslint-plugin-vue": "^10.6.2",
|
|
63
|
+
"globals": "^17.0.0",
|
|
64
|
+
"jsdom": "^25.0.1",
|
|
65
|
+
"nuxt": "^4.2.2",
|
|
66
|
+
"prettier": "^3.7.4",
|
|
67
|
+
"sass": "^1.70.0",
|
|
68
|
+
"typescript": "^5.9.3",
|
|
69
|
+
"typescript-eslint": "^8.52.0",
|
|
70
|
+
"vitepress": "^1.6.4",
|
|
71
|
+
"vitepress-sidebar": "^1.33.1",
|
|
72
|
+
"vitest": "^2.1.8",
|
|
73
|
+
"vue": "^3.5.13",
|
|
74
|
+
"vue-tsc": "^3.2.1"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"nuxt": "^3.0.0 || ^4.0.0",
|
|
78
|
+
"vue": "^3.3.0"
|
|
79
|
+
},
|
|
80
|
+
"keywords": [
|
|
81
|
+
"nuxt",
|
|
82
|
+
"nuxt-layer",
|
|
83
|
+
"vue",
|
|
84
|
+
"components",
|
|
85
|
+
"ui-library",
|
|
86
|
+
"theme",
|
|
87
|
+
"orio-ui"
|
|
88
|
+
],
|
|
89
|
+
"author": "oriondor",
|
|
90
|
+
"license": "MIT",
|
|
91
|
+
"repository": {
|
|
92
|
+
"type": "git",
|
|
93
|
+
"url": "https://github.com/oriondor/orio-ui.git"
|
|
94
|
+
},
|
|
95
|
+
"homepage": "https://github.com/oriondor/orio-ui#readme",
|
|
96
|
+
"bugs": {
|
|
97
|
+
"url": "https://github.com/oriondor/orio-ui/issues"
|
|
98
|
+
}
|
|
99
|
+
}
|
package/src/module.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineNuxtModule } from '@nuxt/kit'
|
|
2
|
+
|
|
3
|
+
export default defineNuxtModule({
|
|
4
|
+
meta: {
|
|
5
|
+
name: 'orio-ui',
|
|
6
|
+
configKey: 'orioUi',
|
|
7
|
+
compatibility: {
|
|
8
|
+
nuxt: '^3.0.0 || ^4.0.0'
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
defaults: {},
|
|
12
|
+
setup() {
|
|
13
|
+
// Module setup is handled by the layer (nuxt.config.ts)
|
|
14
|
+
// This module entry is required for the build process
|
|
15
|
+
}
|
|
16
|
+
})
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
/* --- motion tokens --- */
|
|
3
|
+
--motion-duration-short: 0.05s;
|
|
4
|
+
--motion-duration-medium: 0.15s;
|
|
5
|
+
--motion-distance-small: 0.15rem;
|
|
6
|
+
--motion-distance-medium: 2rem;
|
|
7
|
+
--motion-distance-large: 1rem;
|
|
8
|
+
--motion-ease-default: ease-in;
|
|
9
|
+
--motion-ease-smooth: cubic-bezier(0.22, 1, 0.36, 1);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* fade */
|
|
13
|
+
.animate-fade-enter-active,
|
|
14
|
+
.animate-fade-leave-active {
|
|
15
|
+
transition:
|
|
16
|
+
opacity var(--motion-duration-short) var(--motion-ease-default),
|
|
17
|
+
transform var(--motion-duration-short) var(--motion-ease-default);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.animate-fade-enter-from,
|
|
21
|
+
.animate-fade-leave-to {
|
|
22
|
+
opacity: 0;
|
|
23
|
+
transform: translateY(calc(-1 * var(--motion-distance-small)));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* fade-slide */
|
|
27
|
+
.animate-fade-slide-enter-active,
|
|
28
|
+
.animate-fade-slide-leave-active,
|
|
29
|
+
.animate-fade-slide-appear-active {
|
|
30
|
+
transition:
|
|
31
|
+
opacity var(--motion-duration-medium) var(--motion-ease-smooth),
|
|
32
|
+
transform var(--motion-duration-medium) var(--motion-ease-smooth);
|
|
33
|
+
transition-delay: calc(var(--index, 0) * 0.08s);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.animate-fade-slide-enter-from,
|
|
37
|
+
.animate-fade-slide-appear-from {
|
|
38
|
+
opacity: 0;
|
|
39
|
+
transform: translateY(var(--motion-distance-medium));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.animate-fade-slide-leave-to {
|
|
43
|
+
opacity: 0;
|
|
44
|
+
transform: translateY(calc(-1 * var(--motion-distance-large)));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.animate-fade-slide-move {
|
|
48
|
+
transition: transform var(--motion-duration-medium) ease;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* fade-reverse */
|
|
52
|
+
.animate-fade-reverse-enter-active,
|
|
53
|
+
.animate-fade-reverse-leave-active {
|
|
54
|
+
transition:
|
|
55
|
+
opacity var(--motion-duration-short) var(--motion-ease-default),
|
|
56
|
+
transform var(--motion-duration-short) var(--motion-ease-default);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.animate-fade-reverse-enter-from,
|
|
60
|
+
.animate-fade-reverse-leave-to {
|
|
61
|
+
opacity: 0;
|
|
62
|
+
transform: translateY(var(--motion-distance-small));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* fade-slide-reverse */
|
|
66
|
+
.animate-fade-slide-reverse-enter-active,
|
|
67
|
+
.animate-fade-slide-reverse-leave-active,
|
|
68
|
+
.animate-fade-slide-reverse-appear-active {
|
|
69
|
+
transition:
|
|
70
|
+
opacity var(--motion-duration-medium) var(--motion-ease-smooth),
|
|
71
|
+
transform var(--motion-duration-medium) var(--motion-ease-smooth);
|
|
72
|
+
transition-delay: calc(var(--index, 0) * 0.08s);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.animate-fade-slide-reverse-enter-from,
|
|
76
|
+
.animate-fade-slide-reverse-appear-from {
|
|
77
|
+
opacity: 0;
|
|
78
|
+
transform: translateY(calc(-1 * var(--motion-distance-medium)));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.animate-fade-slide-reverse-leave-to {
|
|
82
|
+
opacity: 0;
|
|
83
|
+
transform: translateY(var(--motion-distance-large));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.animate-fade-slide-reverse-move {
|
|
87
|
+
transition: transform var(--motion-duration-medium) ease;
|
|
88
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/* 1) Role-based tokens (don’t change these names in CSS) */
|
|
2
|
+
:root {
|
|
3
|
+
--color-bg: #ffffff;
|
|
4
|
+
--color-surface: #f7f8fa;
|
|
5
|
+
--color-text: #0e1116;
|
|
6
|
+
--color-muted: #626a78;
|
|
7
|
+
--color-border: #bfbfc2;
|
|
8
|
+
|
|
9
|
+
/* Accent family */
|
|
10
|
+
--color-accent: #1f3a8a;
|
|
11
|
+
--color-accent-ink: #ffffff;
|
|
12
|
+
--color-accent-soft: #eef2ff;
|
|
13
|
+
--color-accent-border: #c7d2fe;
|
|
14
|
+
--color-accent-hover: color-mix(in srgb, var(--color-accent) 85%, black 15%);
|
|
15
|
+
--color-accent-active: color-mix(in srgb, var(--color-accent) 75%, black 25%);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* 2) Category themes (light vs dark) */
|
|
19
|
+
|
|
20
|
+
/* Light (default, already matches your root) */
|
|
21
|
+
:root[data-mode="light"] {
|
|
22
|
+
--color-bg: #ffffff;
|
|
23
|
+
--color-surface: #f7f8fa;
|
|
24
|
+
--color-text: #0e1116;
|
|
25
|
+
--color-muted: #626a78;
|
|
26
|
+
--color-border: #bfbfc2;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Dark */
|
|
30
|
+
:root[data-mode="dark"] {
|
|
31
|
+
--color-bg: #0e1116;
|
|
32
|
+
--color-surface: #1a1d23;
|
|
33
|
+
--color-text: #ffffff;
|
|
34
|
+
--color-muted: #a0a7b5;
|
|
35
|
+
--color-border: #2e333d;
|
|
36
|
+
|
|
37
|
+
--color-accent-ink: #ffffff;
|
|
38
|
+
--color-accent-soft: color-mix(in srgb, var(--color-accent) 12%, #0e1116);
|
|
39
|
+
--color-accent-border: color-mix(in srgb, var(--color-accent) 40%, #0e1116);
|
|
40
|
+
|
|
41
|
+
--color-accent-hover: color-mix(in srgb, var(--color-accent) 30%, white 70%);
|
|
42
|
+
--color-accent-active: color-mix(in srgb, var(--color-accent) 80%, white 25%);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* 3) Accent themes (just accents, independent of light/dark) */
|
|
46
|
+
|
|
47
|
+
:root[data-theme="navy"] {
|
|
48
|
+
--color-accent: hsl(219 20% 25%);
|
|
49
|
+
--color-accent-soft: hsl(221 100% 97%);
|
|
50
|
+
--color-accent-border: hsl(221 61% 84%);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:root[data-theme="teal"] {
|
|
54
|
+
--color-accent: hsl(174 72% 28%);
|
|
55
|
+
--color-accent-soft: hsl(174 55% 94%);
|
|
56
|
+
--color-accent-border: hsl(174 40% 75%);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:root[data-theme="forest"] {
|
|
60
|
+
--color-accent: hsl(152 45% 25%);
|
|
61
|
+
--color-accent-soft: hsl(152 45% 94%);
|
|
62
|
+
--color-accent-border: hsl(152 30% 72%);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
:root[data-theme="wine"] {
|
|
66
|
+
--color-accent: hsl(350 55% 34%);
|
|
67
|
+
--color-accent-soft: hsl(350 60% 96%);
|
|
68
|
+
--color-accent-border: hsl(350 35% 78%);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
:root[data-theme="royal"] {
|
|
72
|
+
--color-accent: hsl(230 60% 40%);
|
|
73
|
+
--color-accent-soft: hsl(230 65% 96%);
|
|
74
|
+
--color-accent-border: hsl(230 35% 78%);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Extra colors */
|
|
78
|
+
:root {
|
|
79
|
+
/* 🔴 Red */
|
|
80
|
+
--color-red: #dc2626;
|
|
81
|
+
--color-red-ink: #ffffff;
|
|
82
|
+
--color-red-soft: #fef2f2;
|
|
83
|
+
--color-red-border: #fecaca;
|
|
84
|
+
--color-red-hover: color-mix(in srgb, var(--color-red) 85%, black 15%);
|
|
85
|
+
--color-red-active: color-mix(in srgb, var(--color-red) 75%, black 25%);
|
|
86
|
+
|
|
87
|
+
/* 🟠 Orange */
|
|
88
|
+
--color-orange: #ea580c;
|
|
89
|
+
--color-orange-ink: #ffffff;
|
|
90
|
+
--color-orange-soft: #fff7ed;
|
|
91
|
+
--color-orange-border: #fed7aa;
|
|
92
|
+
--color-orange-hover: color-mix(in srgb, var(--color-orange) 85%, black 15%);
|
|
93
|
+
--color-orange-active: color-mix(in srgb, var(--color-orange) 75%, black 25%);
|
|
94
|
+
|
|
95
|
+
/* 🟡 Yellow */
|
|
96
|
+
--color-yellow: #ca8a04;
|
|
97
|
+
--color-yellow-ink: #ffffff;
|
|
98
|
+
--color-yellow-soft: #fefce8;
|
|
99
|
+
--color-yellow-border: #fef08a;
|
|
100
|
+
--color-yellow-hover: color-mix(in srgb, var(--color-yellow) 85%, black 15%);
|
|
101
|
+
--color-yellow-active: color-mix(in srgb, var(--color-yellow) 75%, black 25%);
|
|
102
|
+
|
|
103
|
+
/* 🟢 Green */
|
|
104
|
+
--color-green: #15803d;
|
|
105
|
+
--color-green-ink: #ffffff;
|
|
106
|
+
--color-green-soft: #f0fdf4;
|
|
107
|
+
--color-green-border: #bbf7d0;
|
|
108
|
+
--color-green-hover: color-mix(in srgb, var(--color-green) 85%, black 15%);
|
|
109
|
+
--color-green-active: color-mix(in srgb, var(--color-green) 75%, black 25%);
|
|
110
|
+
|
|
111
|
+
/* 🩵 Teal / Cyan */
|
|
112
|
+
--color-teal: #0d9488;
|
|
113
|
+
--color-teal-ink: #ffffff;
|
|
114
|
+
--color-teal-soft: #f0fdfa;
|
|
115
|
+
--color-teal-border: #99f6e4;
|
|
116
|
+
--color-teal-hover: color-mix(in srgb, var(--color-teal) 85%, black 15%);
|
|
117
|
+
--color-teal-active: color-mix(in srgb, var(--color-teal) 75%, black 25%);
|
|
118
|
+
|
|
119
|
+
/* 🔵 Blue */
|
|
120
|
+
--color-blue: #2563eb;
|
|
121
|
+
--color-blue-ink: #ffffff;
|
|
122
|
+
--color-blue-soft: #eff6ff;
|
|
123
|
+
--color-blue-border: #bfdbfe;
|
|
124
|
+
--color-blue-hover: color-mix(in srgb, var(--color-blue) 85%, black 15%);
|
|
125
|
+
--color-blue-active: color-mix(in srgb, var(--color-blue) 75%, black 25%);
|
|
126
|
+
|
|
127
|
+
/* 🟣 Purple */
|
|
128
|
+
--color-purple: #7e22ce;
|
|
129
|
+
--color-purple-ink: #ffffff;
|
|
130
|
+
--color-purple-soft: #faf5ff;
|
|
131
|
+
--color-purple-border: #e9d5ff;
|
|
132
|
+
--color-purple-hover: color-mix(in srgb, var(--color-purple) 85%, black 15%);
|
|
133
|
+
--color-purple-active: color-mix(in srgb, var(--color-purple) 75%, black 25%);
|
|
134
|
+
|
|
135
|
+
/* 💗 Pink */
|
|
136
|
+
--color-pink: #db2777;
|
|
137
|
+
--color-pink-ink: #ffffff;
|
|
138
|
+
--color-pink-soft: #fdf2f8;
|
|
139
|
+
--color-pink-border: #fbcfe8;
|
|
140
|
+
--color-pink-hover: color-mix(in srgb, var(--color-pink) 85%, black 15%);
|
|
141
|
+
--color-pink-active: color-mix(in srgb, var(--color-pink) 75%, black 25%);
|
|
142
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
.gradient-hover {
|
|
2
|
+
--gh-color: #fff;
|
|
3
|
+
--gh-angle: 120deg;
|
|
4
|
+
--gh-peek-x: 95%;
|
|
5
|
+
--gh-mix-base: black;
|
|
6
|
+
|
|
7
|
+
background-image: linear-gradient(
|
|
8
|
+
var(--gh-angle),
|
|
9
|
+
color-mix(in srgb, var(--gh-color) 90%, var(--gh-mix-base)) 0%,
|
|
10
|
+
var(--gh-color) 40%,
|
|
11
|
+
color-mix(in srgb, var(--gh-color) 90%, var(--gh-mix-base)) 80%
|
|
12
|
+
);
|
|
13
|
+
background-repeat: no-repeat;
|
|
14
|
+
|
|
15
|
+
background-size: 0% 0%;
|
|
16
|
+
background-position: 0% 0%;
|
|
17
|
+
|
|
18
|
+
transition:
|
|
19
|
+
background-position 0.8s ease,
|
|
20
|
+
border-color 0.2s ease;
|
|
21
|
+
will-change: background-size, background-position;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.gradient-hover:hover {
|
|
25
|
+
background-size: 200% 100%;
|
|
26
|
+
background-position: var(--gh-peek-x) 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Dark mode: now theme-aware */
|
|
30
|
+
:root[data-mode="dark"] .gradient-hover {
|
|
31
|
+
--gh-color: var(--color-accent); /* switch from static white to theme accent */
|
|
32
|
+
--gh-mix-base: var(--color-bg); /* blend into dark background */
|
|
33
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* ===== Scrollbar (WebKit) ===== */
|
|
2
|
+
::-webkit-scrollbar {
|
|
3
|
+
width: 12px;
|
|
4
|
+
height: 12px;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
::-webkit-scrollbar-track {
|
|
8
|
+
background: var(--color-surface);
|
|
9
|
+
border-left: 1px solid var(--color-border);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
::-webkit-scrollbar-thumb {
|
|
13
|
+
background-color: var(--color-accent-border);
|
|
14
|
+
border-radius: 8px;
|
|
15
|
+
border: 3px solid var(--color-surface);
|
|
16
|
+
transition: background-color 0.2s ease;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
::-webkit-scrollbar-thumb:hover {
|
|
20
|
+
background-color: var(--color-accent);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
::-webkit-scrollbar-corner {
|
|
24
|
+
background: var(--color-surface);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* ===== Scrollbar (Firefox) ===== */
|
|
28
|
+
* {
|
|
29
|
+
scrollbar-width: thin;
|
|
30
|
+
scrollbar-color: var(--color-accent-border) var(--color-surface);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* ===== Dark mode adjustments ===== */
|
|
34
|
+
:root[data-mode="dark"] ::-webkit-scrollbar-track {
|
|
35
|
+
background: var(--color-bg);
|
|
36
|
+
border-left: 1px solid var(--color-border);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:root[data-mode="dark"] ::-webkit-scrollbar-thumb {
|
|
40
|
+
background-color: var(--color-accent-border);
|
|
41
|
+
border: 3px solid var(--color-bg);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
:root[data-mode="dark"] * {
|
|
45
|
+
scrollbar-color: var(--color-accent-border) var(--color-bg);
|
|
46
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, toRefs, useAttrs, useSlots } from 'vue';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
type?: 'primary' | 'secondary' | 'subdued';
|
|
6
|
+
icon?: string;
|
|
7
|
+
loading?: boolean;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
12
|
+
type: 'primary',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const { loading, disabled } = toRefs(props);
|
|
16
|
+
|
|
17
|
+
const attrs = useAttrs();
|
|
18
|
+
const slots = useSlots();
|
|
19
|
+
|
|
20
|
+
const isIconOnly = computed(() => {
|
|
21
|
+
const hasIcon = !!props.icon || !!slots.icon;
|
|
22
|
+
const hasDefault = !!slots.default;
|
|
23
|
+
return hasIcon && !hasDefault;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const emit = defineEmits<{
|
|
27
|
+
(e: 'click', event: PointerEvent): void;
|
|
28
|
+
}>();
|
|
29
|
+
|
|
30
|
+
function click(event: PointerEvent) {
|
|
31
|
+
if (loading.value || disabled.value) return;
|
|
32
|
+
emit('click', event);
|
|
33
|
+
}
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<template>
|
|
37
|
+
<orio-control-element>
|
|
38
|
+
<button
|
|
39
|
+
v-bind="attrs"
|
|
40
|
+
:class="[type, 'gradient-hover', { 'icon-only': isIconOnly }]"
|
|
41
|
+
@click="click"
|
|
42
|
+
>
|
|
43
|
+
<orio-loading-spinner v-if="loading" />
|
|
44
|
+
<slot v-else name="icon">
|
|
45
|
+
<orio-icon v-if="icon" :name="icon" />
|
|
46
|
+
</slot>
|
|
47
|
+
<slot />
|
|
48
|
+
</button>
|
|
49
|
+
</orio-control-element>
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<style lang="scss" scoped>
|
|
53
|
+
button {
|
|
54
|
+
background-color: var(--color-accent);
|
|
55
|
+
color: var(--color-accent-ink);
|
|
56
|
+
border: 1px solid transparent;
|
|
57
|
+
border-radius: 4px;
|
|
58
|
+
padding: 8px 16px;
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
display: inline-flex;
|
|
61
|
+
align-items: center;
|
|
62
|
+
gap: 0.5rem;
|
|
63
|
+
user-select: none;
|
|
64
|
+
|
|
65
|
+
&.icon-only {
|
|
66
|
+
padding: 0;
|
|
67
|
+
border-radius: 50%;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
&:disabled {
|
|
71
|
+
background-color: var(--color-accent-soft);
|
|
72
|
+
color: var(--color-muted);
|
|
73
|
+
border-color: var(--color-accent-border);
|
|
74
|
+
cursor: not-allowed;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&:active {
|
|
78
|
+
border: 1px solid var(--color-accent-border);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&.primary {
|
|
82
|
+
--gh-color: var(--color-accent);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
&.secondary {
|
|
86
|
+
background-color: transparent;
|
|
87
|
+
border: 1px solid var(--color-accent);
|
|
88
|
+
color: var(--color-accent);
|
|
89
|
+
&:hover {
|
|
90
|
+
color: var(--color-accent-hover);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&.subdued {
|
|
95
|
+
background-color: transparent;
|
|
96
|
+
color: var(--color-accent);
|
|
97
|
+
&:hover {
|
|
98
|
+
color: var(--color-accent-hover);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&:active {
|
|
103
|
+
border-color: var(--color-accent-border) !important;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&:hover {
|
|
107
|
+
color: var(--color-accent-ink);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
</style>
|