orio-ui 1.0.1 → 1.0.3
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 +9 -7
- 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 +24 -0
- package/dist/runtime/assets/css/animation.css +1 -0
- package/dist/runtime/assets/css/colors.css +1 -0
- package/{src/runtime/assets/css/cool-gradient-hover.scss → dist/runtime/assets/css/cool-gradient-hover.css} +4 -14
- package/dist/runtime/assets/css/main.css +1 -0
- package/dist/runtime/assets/css/scroll.css +1 -0
- package/{src → dist}/runtime/components/Button.vue +38 -46
- package/dist/runtime/components/CheckBox.vue +93 -0
- package/{src → dist}/runtime/components/ControlElement.vue +13 -16
- package/{src → dist}/runtime/components/DashedContainer.vue +6 -7
- package/dist/runtime/components/DatePicker.vue +30 -0
- package/{src → dist}/runtime/components/DateRangePicker.vue +14 -15
- package/{src → dist}/runtime/components/EmptyState.vue +22 -28
- package/{src → dist}/runtime/components/Icon.vue +1 -12
- package/{src → dist}/runtime/components/Input.vue +18 -24
- package/{src → dist}/runtime/components/Modal.vue +1 -43
- package/{src → dist}/runtime/components/Popover.vue +1 -1
- package/{src → dist}/runtime/components/Selector.vue +36 -52
- package/dist/runtime/components/Tag.vue +21 -0
- package/{src → dist}/runtime/components/Textarea.vue +18 -24
- package/{src → dist}/runtime/components/view/Dates.vue +1 -3
- package/{src → dist}/runtime/components/view/Separator.vue +1 -5
- package/{src → dist}/runtime/components/view/Text.vue +38 -42
- package/dist/runtime/composables/index.d.ts +4 -0
- package/dist/runtime/composables/index.js +6 -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/{src/runtime/utils/icon-registry.ts → dist/runtime/utils/icon-registry.js} +5 -20
- package/dist/types.d.mts +7 -0
- package/dist/types.d.ts +7 -0
- package/package.json +11 -15
- package/nuxt.config.ts +0 -38
- package/src/module.ts +0 -16
- package/src/runtime/assets/css/animation.css +0 -88
- package/src/runtime/assets/css/colors.css +0 -142
- package/src/runtime/assets/css/main.css +0 -11
- package/src/runtime/assets/css/scroll.css +0 -46
- package/src/runtime/components/CheckBox.vue +0 -103
- package/src/runtime/components/DatePicker.vue +0 -84
- package/src/runtime/components/Tag.vue +0 -49
- package/src/runtime/composables/index.ts +0 -9
- package/src/runtime/composables/useApi.ts +0 -32
- package/src/runtime/composables/useFuzzySearch.ts +0 -51
- package/src/runtime/composables/useModal.ts +0 -47
- package/src/runtime/composables/useTheme.ts +0 -31
- package/src/runtime/index.ts +0 -25
- /package/{src → dist}/runtime/components/LoadingSpinner.vue +0 -0
package/nuxt.config.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
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/src/module.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
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
|
-
});
|
|
@@ -1,88 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,142 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
const modelValue = defineModel<boolean>({ required: false });
|
|
3
|
-
|
|
4
|
-
defineProps<{
|
|
5
|
-
checkedIcon?: string; // optional: pass icon name for checked state
|
|
6
|
-
uncheckedIcon?: string; // optional: pass icon name for unchecked state
|
|
7
|
-
}>();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<orio-control-element class="checkbox">
|
|
12
|
-
<label class="checkbox-label">
|
|
13
|
-
<input
|
|
14
|
-
v-model="modelValue"
|
|
15
|
-
type="checkbox"
|
|
16
|
-
class="checkbox-input"
|
|
17
|
-
tabindex="-1"
|
|
18
|
-
/>
|
|
19
|
-
<span
|
|
20
|
-
class="checkbox-box"
|
|
21
|
-
:class="{
|
|
22
|
-
defaultChecked: !checkedIcon,
|
|
23
|
-
defaultUnchecked: !uncheckedIcon,
|
|
24
|
-
}"
|
|
25
|
-
>
|
|
26
|
-
<slot name="icon" :checked="modelValue">
|
|
27
|
-
<orio-icon v-if="modelValue && checkedIcon" :name="checkedIcon" />
|
|
28
|
-
<orio-icon
|
|
29
|
-
v-else-if="!modelValue && uncheckedIcon"
|
|
30
|
-
:name="uncheckedIcon"
|
|
31
|
-
/>
|
|
32
|
-
</slot>
|
|
33
|
-
</span>
|
|
34
|
-
<slot />
|
|
35
|
-
</label>
|
|
36
|
-
</orio-control-element>
|
|
37
|
-
</template>
|
|
38
|
-
|
|
39
|
-
<style lang="scss" scoped>
|
|
40
|
-
.checkbox {
|
|
41
|
-
--box-size: 1rem;
|
|
42
|
-
|
|
43
|
-
&-label {
|
|
44
|
-
position: relative;
|
|
45
|
-
user-select: none;
|
|
46
|
-
display: inline-flex;
|
|
47
|
-
align-items: center;
|
|
48
|
-
gap: 0.4rem;
|
|
49
|
-
cursor: pointer;
|
|
50
|
-
font-size: 0.9rem;
|
|
51
|
-
color: var(--color-text);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
&-input {
|
|
55
|
-
position: absolute;
|
|
56
|
-
inset: 0;
|
|
57
|
-
width: var(--box-size);
|
|
58
|
-
height: 1rem;
|
|
59
|
-
margin: 0;
|
|
60
|
-
opacity: 0;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
&-box {
|
|
64
|
-
width: var(--box-size);
|
|
65
|
-
height: var(--box-size);
|
|
66
|
-
border: 2px solid var(--color-border);
|
|
67
|
-
border-radius: 4px;
|
|
68
|
-
background-color: var(--color-bg);
|
|
69
|
-
display: inline-flex;
|
|
70
|
-
align-items: center;
|
|
71
|
-
justify-content: center;
|
|
72
|
-
transition:
|
|
73
|
-
background-color 0.2s ease,
|
|
74
|
-
border-color 0.2s ease;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.checkbox-input:checked + .checkbox-box {
|
|
78
|
-
background-color: var(--color-accent);
|
|
79
|
-
border-color: var(--color-accent);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.checkbox-input:checked + .checkbox-box.defaultChecked {
|
|
83
|
-
&::after {
|
|
84
|
-
content: '';
|
|
85
|
-
width: 0.3rem;
|
|
86
|
-
height: 0.6rem;
|
|
87
|
-
position: relative;
|
|
88
|
-
bottom: 0.1rem;
|
|
89
|
-
border: solid var(--color-accent-ink);
|
|
90
|
-
border-width: 0 2px 2px 0;
|
|
91
|
-
transform: rotate(45deg);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
&-label:hover .checkbox-box {
|
|
96
|
-
border-color: var(--color-accent);
|
|
97
|
-
}
|
|
98
|
-
.checkbox-input:focus-visible + .checkbox-box {
|
|
99
|
-
outline: 2px solid var(--color-accent);
|
|
100
|
-
outline-offset: 2px;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
</style>
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue';
|
|
3
|
-
import { nanoid } from 'nanoid';
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
month?: boolean;
|
|
7
|
-
}
|
|
8
|
-
defineProps<Props>();
|
|
9
|
-
|
|
10
|
-
const date = defineModel<string | null | undefined>('date', {
|
|
11
|
-
required: true,
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
const randomName = computed(() => `date-${nanoid(8)}`);
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<template>
|
|
18
|
-
<orio-control-element class="date-picker" v-bind="$attrs">
|
|
19
|
-
<input
|
|
20
|
-
v-model="date"
|
|
21
|
-
:type="month ? 'month' : 'date'"
|
|
22
|
-
class="date-input"
|
|
23
|
-
:name="randomName"
|
|
24
|
-
/>
|
|
25
|
-
</orio-control-element>
|
|
26
|
-
</template>
|
|
27
|
-
|
|
28
|
-
<style scoped>
|
|
29
|
-
.date-picker * {
|
|
30
|
-
width: 100%;
|
|
31
|
-
cursor: pointer;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.date-picker-label {
|
|
35
|
-
display: inline-flex;
|
|
36
|
-
flex-direction: column;
|
|
37
|
-
gap: 0.25rem;
|
|
38
|
-
font-size: 0.9rem;
|
|
39
|
-
color: var(--color-text);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.date-input {
|
|
43
|
-
/* border-box allows correct sizing for input */
|
|
44
|
-
box-sizing: border-box;
|
|
45
|
-
appearance: none;
|
|
46
|
-
background-color: var(--color-bg);
|
|
47
|
-
border: 1px solid var(--color-border);
|
|
48
|
-
border-radius: 4px;
|
|
49
|
-
padding: 0.4rem 0.6rem;
|
|
50
|
-
color: var(--color-text);
|
|
51
|
-
font-size: 0.95rem;
|
|
52
|
-
transition:
|
|
53
|
-
border-color 0.2s ease,
|
|
54
|
-
box-shadow 0.2s ease;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/* Hover + focus */
|
|
58
|
-
.date-input:hover {
|
|
59
|
-
border-color: var(--color-accent);
|
|
60
|
-
}
|
|
61
|
-
.date-input:focus {
|
|
62
|
-
border-color: var(--color-accent);
|
|
63
|
-
box-shadow: 0 0 0 2px var(--color-accent-soft);
|
|
64
|
-
outline: none;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/* Disabled */
|
|
68
|
-
.date-input:disabled {
|
|
69
|
-
background-color: var(--color-surface);
|
|
70
|
-
color: var(--color-muted);
|
|
71
|
-
cursor: not-allowed;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/* Calendar icon (WebKit browsers like Chrome/Safari) */
|
|
75
|
-
.date-input::-webkit-calendar-picker-indicator {
|
|
76
|
-
cursor: pointer;
|
|
77
|
-
filter: invert(36%) sepia(65%) saturate(325%) hue-rotate(180deg);
|
|
78
|
-
opacity: 0.7;
|
|
79
|
-
transition: opacity 0.2s ease;
|
|
80
|
-
}
|
|
81
|
-
.date-input::-webkit-calendar-picker-indicator:hover {
|
|
82
|
-
opacity: 1;
|
|
83
|
-
}
|
|
84
|
-
</style>
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
export type TagStyle = 'neutral' | 'accent';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
text: string;
|
|
6
|
-
variant?: TagStyle;
|
|
7
|
-
}
|
|
8
|
-
withDefaults(defineProps<Props>(), {
|
|
9
|
-
variant: 'neutral',
|
|
10
|
-
});
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<template>
|
|
14
|
-
<span class="tag" :class="`tag--${variant}`">
|
|
15
|
-
{{ text }}
|
|
16
|
-
</span>
|
|
17
|
-
</template>
|
|
18
|
-
|
|
19
|
-
<style scoped>
|
|
20
|
-
.tag {
|
|
21
|
-
max-height: 1rem;
|
|
22
|
-
display: inline-block;
|
|
23
|
-
padding: 0.25rem 0.6rem;
|
|
24
|
-
border-radius: 1rem;
|
|
25
|
-
font-size: 0.8rem;
|
|
26
|
-
font-weight: 500;
|
|
27
|
-
line-height: 1;
|
|
28
|
-
border: 1px solid transparent;
|
|
29
|
-
user-select: none;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/* Neutral (gray chip) */
|
|
33
|
-
.tag--neutral {
|
|
34
|
-
background-color: var(--color-surface);
|
|
35
|
-
border-color: color-mix(
|
|
36
|
-
in srgb,
|
|
37
|
-
var(--color-border) 80%,
|
|
38
|
-
var(--color-accent) 20%
|
|
39
|
-
);
|
|
40
|
-
color: var(--color-muted);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/* Accent (themed chip) */
|
|
44
|
-
.tag--accent {
|
|
45
|
-
background-color: var(--color-accent-soft);
|
|
46
|
-
border-color: var(--color-accent-border);
|
|
47
|
-
color: var(--color-accent);
|
|
48
|
-
}
|
|
49
|
-
</style>
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
useApi,
|
|
3
|
-
type ApiOptions,
|
|
4
|
-
type RequestBody,
|
|
5
|
-
type RequestMethod,
|
|
6
|
-
} from './useApi';
|
|
7
|
-
export { useFuzzySearch } from './useFuzzySearch';
|
|
8
|
-
export { useModal, type ModalProps, type OriginRect } from './useModal';
|
|
9
|
-
export { useTheme } from './useTheme';
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { $fetch } from 'ofetch';
|
|
2
|
-
|
|
3
|
-
export type RequestBody = Record<string, unknown>;
|
|
4
|
-
export type RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
5
|
-
|
|
6
|
-
export interface ApiOptions {
|
|
7
|
-
method?: RequestMethod;
|
|
8
|
-
body?: RequestBody;
|
|
9
|
-
signal?: AbortSignal;
|
|
10
|
-
query?: Record<string, unknown>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Overload 1: Just URL (GET request)
|
|
14
|
-
export async function useApi<T = unknown>(url: string): Promise<T>;
|
|
15
|
-
|
|
16
|
-
// Overload 2: URL + options
|
|
17
|
-
export async function useApi<T = unknown>(
|
|
18
|
-
url: string,
|
|
19
|
-
options: ApiOptions,
|
|
20
|
-
): Promise<T>;
|
|
21
|
-
|
|
22
|
-
export async function useApi<T = unknown>(
|
|
23
|
-
url: string,
|
|
24
|
-
options?: ApiOptions,
|
|
25
|
-
): Promise<T> {
|
|
26
|
-
return (await $fetch(url, {
|
|
27
|
-
method: options?.method || 'GET',
|
|
28
|
-
body: options?.body,
|
|
29
|
-
signal: options?.signal,
|
|
30
|
-
query: options?.query,
|
|
31
|
-
})) as T;
|
|
32
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { computed, unref, type MaybeRef } from 'vue';
|
|
2
|
-
import { useFuse, type FuseOptions } from '@vueuse/integrations/useFuse';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Search using Fuse.js fuzzy search
|
|
6
|
-
* @param dataSource - Array of strings or objects to search
|
|
7
|
-
* @param search - Search query string
|
|
8
|
-
* @param options - Fuse.js options (e.g., { keys: ['name'] })
|
|
9
|
-
*/
|
|
10
|
-
export function useFuzzySearch(
|
|
11
|
-
dataSource: MaybeRef<string[]>,
|
|
12
|
-
search: MaybeRef<string>,
|
|
13
|
-
): ReturnType<typeof useFuse>;
|
|
14
|
-
|
|
15
|
-
export function useFuzzySearch<T extends object>(
|
|
16
|
-
dataSource: MaybeRef<T[]>,
|
|
17
|
-
search: MaybeRef<string>,
|
|
18
|
-
options: FuseOptions<T>,
|
|
19
|
-
): ReturnType<typeof useFuse>;
|
|
20
|
-
|
|
21
|
-
export function useFuzzySearch<T extends object>(
|
|
22
|
-
dataSource: MaybeRef<string[] | T[]>,
|
|
23
|
-
search: MaybeRef<string>,
|
|
24
|
-
options?: FuseOptions<T>,
|
|
25
|
-
) {
|
|
26
|
-
// If options are provided, treat as object array; otherwise string array
|
|
27
|
-
const isObjectArray = !!options;
|
|
28
|
-
|
|
29
|
-
if (!isObjectArray) {
|
|
30
|
-
// String array handling
|
|
31
|
-
const wrappedData = computed(() => {
|
|
32
|
-
const data = unref(dataSource) as string[];
|
|
33
|
-
return data.map((str) => ({ value: str }));
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const { results } = useFuse(search, wrappedData, {
|
|
37
|
-
fuseOptions: { keys: ['value'] },
|
|
38
|
-
matchAllWhenSearchEmpty: true,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
return computed(() => results.value.map(({ item }) => item.value));
|
|
42
|
-
} else {
|
|
43
|
-
// Object array handling
|
|
44
|
-
const { results } = useFuse(search, dataSource as MaybeRef<T[]>, {
|
|
45
|
-
fuseOptions: options,
|
|
46
|
-
matchAllWhenSearchEmpty: true,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
return computed(() => results.value.map(({ item }) => item));
|
|
50
|
-
}
|
|
51
|
-
}
|