@tekkare/romulus 0.1.0 → 0.1.5
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/dist/module.json +1 -1
- package/dist/module.mjs +2 -1
- package/dist/runtime/assets/styles/tokens.css +1 -1
- package/dist/runtime/assets/styles/utilities.css +1 -0
- package/dist/runtime/components/ActionBar.vue +95 -0
- package/dist/runtime/components/AdvancedSearch.vue +110 -0
- package/dist/runtime/components/Breadcrumb.vue +46 -0
- package/dist/runtime/components/Button.vue +17 -9
- package/dist/runtime/components/Drawer.vue +79 -0
- package/dist/runtime/components/FilterCheckbox.vue +26 -0
- package/dist/runtime/components/FilterComplex.vue +205 -0
- package/dist/runtime/components/FilterDropdown.vue +119 -0
- package/dist/runtime/components/Icon.vue +43 -0
- package/dist/runtime/components/NavLink.vue +60 -0
- package/dist/runtime/components/Pill.vue +37 -0
- package/dist/runtime/components/PillTabs.vue +34 -0
- package/dist/runtime/components/SearchBar.vue +38 -0
- package/dist/runtime/components/Sidebar.vue +143 -0
- package/dist/runtime/components/Tabs.vue +105 -0
- package/dist/runtime/components/ToolbarFilter.vue +134 -0
- package/package.json +4 -3
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -10,13 +10,14 @@ const module = defineNuxtModule({
|
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
defaults: {
|
|
13
|
-
prefix: "
|
|
13
|
+
prefix: "Rm"
|
|
14
14
|
},
|
|
15
15
|
async setup(options, nuxt) {
|
|
16
16
|
const { resolve } = createResolver(import.meta.url);
|
|
17
17
|
const runtimeDir = fileURLToPath(new URL("./runtime", import.meta.url));
|
|
18
18
|
nuxt.options.css.push(resolve(runtimeDir, "assets/styles/tokens.css"));
|
|
19
19
|
nuxt.options.css.push(resolve(runtimeDir, "assets/styles/base.css"));
|
|
20
|
+
nuxt.options.css.push(resolve(runtimeDir, "assets/styles/utilities.css"));
|
|
20
21
|
await addComponentsDir({
|
|
21
22
|
path: resolve(runtimeDir, "components"),
|
|
22
23
|
prefix: options.prefix
|
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--r-color-primary-50:#
|
|
1
|
+
:root{--r-color-primary-50:#f0f4ff;--r-color-primary-100:#dce5fd;--r-color-primary-200:#b9cbfb;--r-color-primary-300:#96b0f9;--r-color-primary-400:#7395f5;--r-color-primary-500:#5a7ef2;--r-color-primary-600:#4164ee;--r-color-primary-700:#3451d4;--r-color-primary-800:#283fb0;--r-color-primary-900:#1c2d8a;--r-color-gray-50:#f9fafb;--r-color-gray-100:#f3f4f6;--r-color-gray-200:#e5e7eb;--r-color-gray-300:#d1d5db;--r-color-gray-400:#9ca3af;--r-color-gray-500:#6b7280;--r-color-gray-600:#4b5563;--r-color-gray-700:#374151;--r-color-gray-800:#1f2937;--r-color-gray-900:#111827;--r-color-gray-950:#030712;--r-color-success-500:#22c55e;--r-color-success-600:#16a34a;--r-color-warning-500:#f59e0b;--r-color-warning-600:#d97706;--r-color-danger-500:#ef4444;--r-color-danger-600:#dc2626;--r-color-white:#fff;--r-color-black:#000;--r-font-family:"Figtree",ui-sans-serif,system-ui,-apple-system,sans-serif;--r-font-mono:"JetBrains Mono",ui-monospace,"Cascadia Code",monospace;--r-text-xs:0.75rem;--r-text-sm:0.875rem;--r-text-base:1rem;--r-text-lg:1.125rem;--r-text-xl:1.25rem;--r-text-2xl:1.5rem;--r-text-3xl:1.875rem;--r-text-4xl:2.25rem;--r-font-weight-normal:400;--r-font-weight-medium:500;--r-font-weight-semibold:600;--r-font-weight-bold:700;--r-leading-tight:1.25;--r-leading-normal:1.5;--r-leading-relaxed:1.75;--r-space-0:0;--r-space-1:0.25rem;--r-space-2:0.5rem;--r-space-3:0.75rem;--r-space-4:1rem;--r-space-5:1.25rem;--r-space-6:1.5rem;--r-space-8:2rem;--r-space-10:2.5rem;--r-space-12:3rem;--r-space-16:4rem;--r-space-20:5rem;--r-radius-none:0;--r-radius-sm:0.25rem;--r-radius-md:0.375rem;--r-radius-lg:0.5rem;--r-radius-xl:0.75rem;--r-radius-2xl:1rem;--r-radius-full:9999px;--r-shadow-xs:0 1px 2px 0 rgba(0,0,0,.05);--r-shadow-sm:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--r-shadow-md:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--r-shadow-lg:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--r-shadow-xl:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--r-transition-fast:150ms cubic-bezier(0.4,0,0.2,1);--r-transition-base:200ms cubic-bezier(0.4,0,0.2,1);--r-transition-slow:300ms cubic-bezier(0.4,0,0.2,1)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.row{display:flex;flex-direction:row}.column{display:flex;flex-direction:column}.row-reverse{display:flex;flex-direction:row-reverse}.column-reverse{display:flex;flex-direction:column-reverse}.x-start{justify-content:flex-start}.x-center{justify-content:center}.x-end{justify-content:flex-end}.x-between{justify-content:space-between}.x-around{justify-content:space-around}.x-evenly{justify-content:space-evenly}.y-start{align-items:flex-start}.y-center{align-items:center}.y-end{align-items:flex-end}.y-between{align-content:space-between}.y-stretch{align-items:stretch}.y-baseline{align-items:baseline}.wrap{flex-wrap:wrap}.nowrap{flex-wrap:nowrap}.grow{flex-grow:1}.grow-0{flex-grow:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-1{flex:1}.flex-auto{flex:auto}.flex-none{flex:none}.self-start{align-self:flex-start}.self-center{align-self:center}.self-end{align-self:flex-end}.self-stretch{align-self:stretch}.w-full{width:100%}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.min-w-0{min-width:0}.h-full{height:100%}.h-auto{height:auto}.h-screen{height:100vh}.min-h-0{min-height:0}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.overflow-auto{overflow:auto}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}.sticky{position:sticky}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.block{display:block}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-14{gap:14px}.gap-16{gap:16px}.gap-18{gap:18px}.gap-20{gap:20px}.gap-22{gap:22px}.gap-24{gap:24px}.gap-26{gap:26px}.gap-28{gap:28px}.gap-30{gap:30px}.gap-32{gap:32px}.gap-34{gap:34px}.gap-36{gap:36px}.gap-38{gap:38px}.gap-40{gap:40px}.gap-42{gap:42px}.gap-44{gap:44px}.gap-46{gap:46px}.gap-48{gap:48px}.gap-50{gap:50px}.gap-52{gap:52px}.gap-54{gap:54px}.gap-56{gap:56px}.gap-58{gap:58px}.gap-60{gap:60px}.gap-62{gap:62px}.gap-64{gap:64px}.gap-66{gap:66px}.gap-68{gap:68px}.gap-70{gap:70px}.gap-72{gap:72px}.gap-74{gap:74px}.gap-76{gap:76px}.gap-78{gap:78px}.gap-80{gap:80px}.p-0{padding:0}.p-4{padding:4px}.p-8{padding:8px}.p-12{padding:12px}.p-16{padding:16px}.p-20{padding:20px}.p-24{padding:24px}.p-32{padding:32px}.p-40{padding:40px}.p-48{padding:48px}.px-4{padding-left:4px;padding-right:4px}.px-8{padding-left:8px;padding-right:8px}.px-12{padding-left:12px;padding-right:12px}.px-16{padding-left:16px;padding-right:16px}.px-20{padding-left:20px;padding-right:20px}.px-24{padding-left:24px;padding-right:24px}.px-32{padding-left:32px;padding-right:32px}.py-4{padding-bottom:4px;padding-top:4px}.py-8{padding-bottom:8px;padding-top:8px}.py-12{padding-bottom:12px;padding-top:12px}.py-16{padding-bottom:16px;padding-top:16px}.py-20{padding-bottom:20px;padding-top:20px}.py-24{padding-bottom:24px;padding-top:24px}.py-32{padding-bottom:32px;padding-top:32px}.m-0{margin:0}.m-auto{margin:auto}.mx-auto{margin-right:auto}.ml-auto,.mx-auto{margin-left:auto}.mr-auto{margin-right:auto}.mt-auto{margin-top:auto}.mb-auto{margin-bottom:auto}.border{border:1px solid var(--r-color-gray-200)}.border-t{border-top:1px solid var(--r-color-gray-200)}.border-b{border-bottom:1px solid var(--r-color-gray-200)}.border-l{border-left:1px solid var(--r-color-gray-200)}.border-r{border-right:1px solid var(--r-color-gray-200)}.border-none{border:none}.rounded-sm{border-radius:var(--r-radius-sm)}.rounded-md{border-radius:var(--r-radius-md)}.rounded-lg{border-radius:var(--r-radius-lg)}.rounded-xl{border-radius:var(--r-radius-xl)}.rounded-full{border-radius:var(--r-radius-full)}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
export interface RmActionBarProps {
|
|
3
|
+
/** Width of the action panel in px */
|
|
4
|
+
panelWidth?: number
|
|
5
|
+
/** Width of the drawer when open in px */
|
|
6
|
+
drawerWidth?: number
|
|
7
|
+
/** Whether the drawer is open */
|
|
8
|
+
drawerOpen?: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(defineProps<RmActionBarProps>(), {
|
|
12
|
+
panelWidth: 280,
|
|
13
|
+
drawerWidth: 640,
|
|
14
|
+
drawerOpen: false,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const emit = defineEmits<{
|
|
18
|
+
'update:drawerOpen': [value: boolean]
|
|
19
|
+
'closeDrawer': []
|
|
20
|
+
}>()
|
|
21
|
+
|
|
22
|
+
const totalWidth = computed(() => {
|
|
23
|
+
return props.drawerOpen
|
|
24
|
+
? props.panelWidth + props.drawerWidth
|
|
25
|
+
: props.panelWidth
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
function closeDrawer() {
|
|
29
|
+
emit('update:drawerOpen', false)
|
|
30
|
+
emit('closeDrawer')
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<div
|
|
37
|
+
class="rm-action-bar"
|
|
38
|
+
:style="{ width: totalWidth + 'px' }"
|
|
39
|
+
>
|
|
40
|
+
<!-- Panel -->
|
|
41
|
+
<div class="rm-action-bar__panel" :style="{ width: panelWidth + 'px' }">
|
|
42
|
+
<div class="rm-action-bar__header">
|
|
43
|
+
<slot name="header" />
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div v-if="$slots.tabs" class="rm-action-bar__tabs">
|
|
47
|
+
<slot name="tabs" />
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div class="rm-action-bar__content">
|
|
51
|
+
<slot name="actions" />
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div v-if="$slots.footer" class="rm-action-bar__footer">
|
|
55
|
+
<slot name="footer" />
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<!-- Overlay -->
|
|
60
|
+
<Teleport to="body">
|
|
61
|
+
<Transition name="rm-action-bar-overlay">
|
|
62
|
+
<div
|
|
63
|
+
v-if="drawerOpen"
|
|
64
|
+
class="rm-action-bar__overlay"
|
|
65
|
+
@click="closeDrawer"
|
|
66
|
+
/>
|
|
67
|
+
</Transition>
|
|
68
|
+
</Teleport>
|
|
69
|
+
|
|
70
|
+
<!-- Drawer -->
|
|
71
|
+
<Transition name="rm-action-bar-drawer">
|
|
72
|
+
<div
|
|
73
|
+
v-if="drawerOpen"
|
|
74
|
+
class="rm-action-bar__drawer"
|
|
75
|
+
>
|
|
76
|
+
<div class="rm-action-bar__drawer-header">
|
|
77
|
+
<slot name="drawer-header" />
|
|
78
|
+
<button class="rm-action-bar__drawer-close" @click="closeDrawer">
|
|
79
|
+
<RmIcon name="X" :size="20" />
|
|
80
|
+
</button>
|
|
81
|
+
</div>
|
|
82
|
+
<div class="rm-action-bar__drawer-body">
|
|
83
|
+
<slot name="drawer" />
|
|
84
|
+
</div>
|
|
85
|
+
<div v-if="$slots['drawer-footer']" class="rm-action-bar__drawer-footer">
|
|
86
|
+
<slot name="drawer-footer" />
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</Transition>
|
|
90
|
+
</div>
|
|
91
|
+
</template>
|
|
92
|
+
|
|
93
|
+
<style scoped>
|
|
94
|
+
.rm-action-bar{bottom:0;display:flex;position:fixed;right:0;top:0;transition:width .3s cubic-bezier(.4,0,.2,1);z-index:61}.rm-action-bar__panel{background-color:var(--r-color-white);border-left:1px solid var(--r-color-gray-200);display:flex;flex-direction:column;flex-shrink:0;height:100%}.rm-action-bar__header{align-items:center;display:flex;gap:12px;justify-content:space-between;min-height:64px;padding:0 16px}.rm-action-bar__tabs{border-bottom:1px solid var(--r-color-gray-200);padding:8px 16px 12px}.rm-action-bar__content{display:flex;flex:1;flex-direction:column;overflow-y:auto}.rm-action-bar__footer{border-top:1px solid var(--r-color-gray-200);padding:16px}.rm-action-bar__overlay{backdrop-filter:blur(2px);background-color:rgba(0,0,0,.2);inset:0;position:fixed;z-index:60}.rm-action-bar-overlay-enter-active,.rm-action-bar-overlay-leave-active{transition:opacity .25s ease}.rm-action-bar-overlay-enter-from,.rm-action-bar-overlay-leave-to{opacity:0}.rm-action-bar__drawer{background-color:var(--r-color-white);border-left:1px solid var(--r-color-gray-200);display:flex;flex:1;flex-direction:column;min-width:0;overflow:hidden}.rm-action-bar__drawer-header{align-items:center;border-bottom:1px solid var(--r-color-gray-200);display:flex;justify-content:space-between;min-height:64px;padding:0 24px}.rm-action-bar__drawer-close{align-items:center;background:none;border:none;border-radius:var(--r-radius-md);color:var(--r-color-gray-500);cursor:pointer;display:flex;flex-shrink:0;height:32px;justify-content:center;transition:all var(--r-transition-fast);width:32px}.rm-action-bar__drawer-close:hover{background-color:var(--r-color-gray-100);color:var(--r-color-gray-700)}.rm-action-bar__drawer-body{flex:1;overflow-y:auto;padding:24px}.rm-action-bar__drawer-footer{border-top:1px solid var(--r-color-gray-200);padding:16px 24px}.rm-action-bar-drawer-enter-active,.rm-action-bar-drawer-leave-active{transition:opacity .25s ease}.rm-action-bar-drawer-enter-from,.rm-action-bar-drawer-leave-to{opacity:0}
|
|
95
|
+
</style>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
PhTrash,
|
|
4
|
+
PhPlus,
|
|
5
|
+
PhLineVertical,
|
|
6
|
+
PhMinus,
|
|
7
|
+
} from '@phosphor-icons/vue'
|
|
8
|
+
|
|
9
|
+
interface SearchRow {
|
|
10
|
+
id: number
|
|
11
|
+
type: 'and' | 'or' | 'not'
|
|
12
|
+
value: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
defineProps<{
|
|
16
|
+
visible: boolean
|
|
17
|
+
}>()
|
|
18
|
+
|
|
19
|
+
defineEmits<{
|
|
20
|
+
close: []
|
|
21
|
+
saveSearch: []
|
|
22
|
+
}>()
|
|
23
|
+
|
|
24
|
+
let nextId = 1
|
|
25
|
+
|
|
26
|
+
const rows = ref<SearchRow[]>([
|
|
27
|
+
{ id: nextId++, type: 'and', value: '' },
|
|
28
|
+
])
|
|
29
|
+
|
|
30
|
+
function addRow(type: 'and' | 'or' | 'not') {
|
|
31
|
+
rows.value.push({ id: nextId++, type, value: '' })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function removeRow(id: number) {
|
|
35
|
+
rows.value = rows.value.filter(r => r.id !== id)
|
|
36
|
+
if (rows.value.length === 0) {
|
|
37
|
+
rows.value.push({ id: nextId++, type: 'and', value: '' })
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function clearAll() {
|
|
42
|
+
rows.value = [{ id: nextId++, type: 'and', value: '' }]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const typeColors: Record<string, string> = {
|
|
46
|
+
and: '#4164EE',
|
|
47
|
+
or: '#07816F',
|
|
48
|
+
not: '#F7520E',
|
|
49
|
+
}
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<template>
|
|
53
|
+
<div v-if="visible" class="advanced-search">
|
|
54
|
+
<div class="advanced-search__header">
|
|
55
|
+
<h2 class="advanced-search__title">Advanced search</h2>
|
|
56
|
+
<RmButton variant="outline" size="sm" @click="$emit('saveSearch')">
|
|
57
|
+
Save search
|
|
58
|
+
<PhLineVertical :size="14" />
|
|
59
|
+
</RmButton>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div class="advanced-search__rows">
|
|
63
|
+
<div
|
|
64
|
+
v-for="row in rows"
|
|
65
|
+
:key="row.id"
|
|
66
|
+
class="advanced-search__row"
|
|
67
|
+
>
|
|
68
|
+
<span
|
|
69
|
+
class="advanced-search__type"
|
|
70
|
+
:style="{ color: typeColors[row.type] }"
|
|
71
|
+
>
|
|
72
|
+
{{ row.type.charAt(0).toUpperCase() + row.type.slice(1) }}
|
|
73
|
+
</span>
|
|
74
|
+
<input
|
|
75
|
+
v-model="row.value"
|
|
76
|
+
type="text"
|
|
77
|
+
:placeholder="row.value ? '' : 'Add a keyword'"
|
|
78
|
+
class="advanced-search__input"
|
|
79
|
+
:class="{ 'advanced-search__input--not': row.type === 'not' }"
|
|
80
|
+
>
|
|
81
|
+
<button class="advanced-search__delete" @click="removeRow(row.id)">
|
|
82
|
+
<PhTrash :size="16" />
|
|
83
|
+
</button>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div class="advanced-search__actions">
|
|
88
|
+
<button class="advanced-search__add" @click="addRow('and')">
|
|
89
|
+
<PhPlus :size="12" />
|
|
90
|
+
and
|
|
91
|
+
</button>
|
|
92
|
+
<button class="advanced-search__add" @click="addRow('or')">
|
|
93
|
+
<PhLineVertical :size="12" />
|
|
94
|
+
or
|
|
95
|
+
</button>
|
|
96
|
+
<button class="advanced-search__add" @click="addRow('not')">
|
|
97
|
+
<PhMinus :size="12" />
|
|
98
|
+
not
|
|
99
|
+
</button>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<button class="advanced-search__clear" @click="clearAll">
|
|
103
|
+
Clear All
|
|
104
|
+
</button>
|
|
105
|
+
</div>
|
|
106
|
+
</template>
|
|
107
|
+
|
|
108
|
+
<style scoped>
|
|
109
|
+
.advanced-search{background-color:var(--r-color-white);border-bottom:1px solid var(--r-color-gray-200);padding:20px 24px}.advanced-search__header{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.advanced-search__title{color:var(--r-color-gray-900);font-family:var(--r-font-family);font-size:16px;font-weight:700;margin:0}.advanced-search__rows{display:flex;flex-direction:column;gap:12px;margin-bottom:16px}.advanced-search__row{align-items:center;display:flex;gap:12px}.advanced-search__type{flex-shrink:0;font-weight:600;min-width:32px}.advanced-search__input,.advanced-search__type{font-family:var(--r-font-family);font-size:var(--r-text-sm)}.advanced-search__input{background:#fff;border:1px solid #dbdef0;border-radius:6px;color:var(--r-color-gray-900);flex:1;height:36px;outline:none;padding:0 12px;transition:border-color var(--r-transition-fast)}.advanced-search__input:focus{border-color:#4164ee}.advanced-search__input--not,.advanced-search__input--not:focus{border-color:#f7520e}.advanced-search__input::-moz-placeholder{color:var(--r-color-gray-400)}.advanced-search__input::placeholder{color:var(--r-color-gray-400)}.advanced-search__delete{align-items:center;background:none;border:none;border-radius:4px;color:var(--r-color-gray-400);cursor:pointer;display:flex;justify-content:center;padding:4px;transition:color var(--r-transition-fast)}.advanced-search__delete:hover{color:var(--r-color-danger-500)}.advanced-search__actions{display:flex;gap:8px;margin-bottom:16px}.advanced-search__add{align-items:center;background:#fff;border:1px solid #dbdef0;border-radius:6px;color:var(--r-color-gray-600);cursor:pointer;display:inline-flex;font-family:var(--r-font-family);font-size:var(--r-text-sm);font-weight:var(--r-font-weight-medium);gap:4px;height:32px;padding:4px 12px;transition:all var(--r-transition-fast)}.advanced-search__add:hover{border-color:var(--r-color-gray-300);box-shadow:0 1px 2px 0 rgba(30,41,59,.1)}.advanced-search__clear{background:none;border:1px solid var(--r-color-danger-500);border-radius:6px;color:var(--r-color-danger-500);cursor:pointer;font-family:var(--r-font-family);font-size:var(--r-text-sm);font-weight:var(--r-font-weight-medium);padding:4px 12px;transition:all var(--r-transition-fast)}.advanced-search__clear:hover{background-color:var(--r-color-danger-500);color:#fff}
|
|
110
|
+
</style>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
export interface RmBreadcrumbItem {
|
|
3
|
+
/** Display label */
|
|
4
|
+
label: string
|
|
5
|
+
/** Optional icon name (Phosphor) — only shown on first item by default */
|
|
6
|
+
icon?: string
|
|
7
|
+
/** Navigation path */
|
|
8
|
+
to?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RmBreadcrumbProps {
|
|
12
|
+
/** Breadcrumb items */
|
|
13
|
+
items: RmBreadcrumbItem[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
defineProps<RmBreadcrumbProps>()
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<nav class="rm-breadcrumb">
|
|
21
|
+
<template v-for="(item, idx) in items" :key="idx">
|
|
22
|
+
<span v-if="idx > 0" class="rm-breadcrumb__sep">/</span>
|
|
23
|
+
<NuxtLink
|
|
24
|
+
v-if="item.to"
|
|
25
|
+
:to="item.to"
|
|
26
|
+
class="rm-breadcrumb__item"
|
|
27
|
+
:class="{ 'rm-breadcrumb__item--first': idx === 0 }"
|
|
28
|
+
>
|
|
29
|
+
<RmIcon v-if="item.icon" :name="item.icon" :size="16" weight="duotone" class="rm-breadcrumb__icon" />
|
|
30
|
+
{{ item.label }}
|
|
31
|
+
</NuxtLink>
|
|
32
|
+
<span
|
|
33
|
+
v-else
|
|
34
|
+
class="rm-breadcrumb__item"
|
|
35
|
+
:class="{ 'rm-breadcrumb__item--first': idx === 0 }"
|
|
36
|
+
>
|
|
37
|
+
<RmIcon v-if="item.icon" :name="item.icon" :size="16" weight="duotone" class="rm-breadcrumb__icon" />
|
|
38
|
+
{{ item.label }}
|
|
39
|
+
</span>
|
|
40
|
+
</template>
|
|
41
|
+
</nav>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<style scoped>
|
|
45
|
+
.rm-breadcrumb{align-items:center;color:var(--r-color-gray-400);display:flex;font-family:var(--r-font-family);font-size:14px;gap:8px}.rm-breadcrumb__sep{color:var(--r-color-gray-300)}.rm-breadcrumb__item{align-items:center;color:var(--r-color-gray-400);display:inline-flex;gap:6px;text-decoration:none;transition:color var(--r-transition-fast)}.rm-breadcrumb__item--first{color:var(--r-color-gray-700);font-weight:500}a.rm-breadcrumb__item:hover{color:var(--r-color-primary-600)}.rm-breadcrumb__icon{color:var(--r-color-primary-500)}
|
|
46
|
+
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
export interface
|
|
2
|
+
export interface RmButtonProps {
|
|
3
3
|
/** Visual style variant */
|
|
4
|
-
variant?: 'primary' | 'secondary' | 'outline' | 'ghost'
|
|
4
|
+
variant?: 'primary-fill' | 'primary-stroke' | 'discovery-fill' | 'discovery-stroke' | 'databank-fill' | 'databank-stroke' | 'pharma-fill' | 'pharma-stroke' | 'secondary' | 'outline' | 'ghost'
|
|
5
5
|
/** Size of the button */
|
|
6
6
|
size?: 'sm' | 'md' | 'lg'
|
|
7
7
|
/** Whether the button is disabled */
|
|
@@ -10,14 +10,20 @@ export interface RButtonProps {
|
|
|
10
10
|
block?: boolean
|
|
11
11
|
/** HTML button type attribute */
|
|
12
12
|
type?: 'button' | 'submit' | 'reset'
|
|
13
|
+
/** Phosphor icon name before the label */
|
|
14
|
+
prefixIcon?: string
|
|
15
|
+
/** Phosphor icon name after the label */
|
|
16
|
+
suffixIcon?: string
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
withDefaults(defineProps<
|
|
16
|
-
variant: 'primary',
|
|
19
|
+
withDefaults(defineProps<RmButtonProps>(), {
|
|
20
|
+
variant: 'primary-fill',
|
|
17
21
|
size: 'md',
|
|
18
22
|
disabled: false,
|
|
19
23
|
block: false,
|
|
20
24
|
type: 'button',
|
|
25
|
+
prefixIcon: undefined,
|
|
26
|
+
suffixIcon: undefined,
|
|
21
27
|
})
|
|
22
28
|
|
|
23
29
|
defineEmits<{
|
|
@@ -30,17 +36,19 @@ defineEmits<{
|
|
|
30
36
|
:type="type"
|
|
31
37
|
:disabled="disabled"
|
|
32
38
|
:class="[
|
|
33
|
-
'
|
|
34
|
-
`
|
|
35
|
-
`
|
|
36
|
-
{ '
|
|
39
|
+
'rm-button',
|
|
40
|
+
`rm-button--${variant}`,
|
|
41
|
+
`rm-button--${size}`,
|
|
42
|
+
{ 'rm-button--block': block },
|
|
37
43
|
]"
|
|
38
44
|
@click="$emit('click', $event)"
|
|
39
45
|
>
|
|
46
|
+
<RmIcon v-if="prefixIcon" :name="prefixIcon" :size="size === 'sm' ? 14 : 16" />
|
|
40
47
|
<slot />
|
|
48
|
+
<RmIcon v-if="suffixIcon" :name="suffixIcon" :size="size === 'sm' ? 14 : 16" />
|
|
41
49
|
</button>
|
|
42
50
|
</template>
|
|
43
51
|
|
|
44
52
|
<style scoped>
|
|
45
|
-
.
|
|
53
|
+
.rm-button{align-items:center;border:1px solid transparent;border-radius:6px;cursor:pointer;display:inline-flex;font-family:var(--r-font-family);font-weight:500;gap:8px;justify-content:center;transition:all var(--r-transition-fast);-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap}.rm-button:focus-visible{outline:2px solid var(--r-color-primary-500);outline-offset:2px}.rm-button:disabled{cursor:not-allowed;opacity:.5}.rm-button--sm{font-size:13px;height:32px;padding:6px 16px}.rm-button--md{font-size:14px;height:40px;padding:10px 24px}.rm-button--lg{font-size:15px;height:48px;padding:12px 28px}.rm-button--primary-fill{background:linear-gradient(180deg,rgba(65,100,238,.8),rgba(65,100,238,.9));border-color:#4164ee;box-shadow:0 2px 3px 0 rgba(65,100,238,.5);color:var(--r-color-white)}.rm-button--primary-fill:hover:not(:disabled){background:linear-gradient(180deg,#4164ee,#4164ee);box-shadow:0 2px 4px 0 rgba(65,100,238,.6)}.rm-button--primary-fill:active:not(:disabled){background:#3451d4;box-shadow:0 1px 2px 0 rgba(65,100,238,.4)}.rm-button--primary-stroke{box-shadow:0 2px 3px 0 rgba(65,100,238,.5);color:#4164ee}.rm-button--primary-stroke,.rm-button--primary-stroke:hover:not(:disabled){background:linear-gradient(180deg,hsla(0,0%,100%,.5),hsla(0,0%,100%,.9));border-color:#4164ee}.rm-button--primary-stroke:hover:not(:disabled){box-shadow:none}.rm-button--primary-stroke:active:not(:disabled){background:var(--r-color-primary-50);box-shadow:none}.rm-button--discovery-fill{background:linear-gradient(180deg,rgba(7,129,111,.8),rgba(7,129,111,.9));border-color:#07816f;box-shadow:0 2px 3px 0 rgba(7,129,111,.5);color:var(--r-color-white)}.rm-button--discovery-fill:hover:not(:disabled){background:linear-gradient(180deg,#07816f,#07816f);border-color:#07816f;box-shadow:none}.rm-button--discovery-fill:active:not(:disabled){background:linear-gradient(180deg,#066b5c,#066b5c);box-shadow:none}.rm-button--discovery-stroke{box-shadow:0 2px 3px 0 rgba(7,129,111,.5);color:#07816f}.rm-button--discovery-stroke,.rm-button--discovery-stroke:hover:not(:disabled){background:linear-gradient(180deg,hsla(0,0%,100%,.5),hsla(0,0%,100%,.9));border-color:#07816f}.rm-button--discovery-stroke:hover:not(:disabled){box-shadow:none}.rm-button--discovery-stroke:active:not(:disabled){background:rgba(7,129,111,.05);box-shadow:none}.rm-button--databank-fill{background:linear-gradient(180deg,rgba(224,67,128,.8),rgba(224,67,128,.9));border-color:#e04380;box-shadow:0 2px 3px 0 rgba(224,67,128,.5);color:var(--r-color-white)}.rm-button--databank-fill:hover:not(:disabled){background:linear-gradient(180deg,#e04380,#e04380);border-color:#e04380;box-shadow:none}.rm-button--databank-fill:active:not(:disabled){background:linear-gradient(180deg,#c73a6f,#c73a6f);box-shadow:none}.rm-button--databank-stroke{box-shadow:0 2px 3px 0 rgba(224,67,128,.5);color:#e04380}.rm-button--databank-stroke,.rm-button--databank-stroke:hover:not(:disabled){background:linear-gradient(180deg,hsla(0,0%,100%,.5),hsla(0,0%,100%,.9));border-color:#e04380}.rm-button--databank-stroke:hover:not(:disabled){box-shadow:none}.rm-button--databank-stroke:active:not(:disabled){background:rgba(224,67,128,.05);box-shadow:none}.rm-button--pharma-fill{background:linear-gradient(180deg,#ff7942,#f7520e);border-color:#f7520e;box-shadow:0 2px 3px 0 rgba(247,82,14,.5);color:var(--r-color-white)}.rm-button--pharma-fill:hover:not(:disabled){background:linear-gradient(180deg,#f7520e,#f7520e);border-color:#f7520e;box-shadow:none}.rm-button--pharma-fill:active:not(:disabled){background:linear-gradient(180deg,#d9470c,#d9470c);box-shadow:none}.rm-button--pharma-stroke{box-shadow:0 2px 3px 0 rgba(247,82,14,.5);color:#f7520e}.rm-button--pharma-stroke,.rm-button--pharma-stroke:hover:not(:disabled){background:linear-gradient(180deg,hsla(0,0%,100%,.5),hsla(0,0%,100%,.9));border-color:#f7520e}.rm-button--pharma-stroke:hover:not(:disabled){box-shadow:none}.rm-button--pharma-stroke:active:not(:disabled){background:rgba(247,82,14,.05);box-shadow:none}.rm-button--secondary{background-color:var(--r-color-gray-100);color:var(--r-color-gray-800)}.rm-button--secondary:hover:not(:disabled){background-color:var(--r-color-gray-200)}.rm-button--secondary:active:not(:disabled){background-color:var(--r-color-gray-300)}.rm-button--outline{background-color:transparent;border-color:var(--r-color-gray-300);color:var(--r-color-gray-700)}.rm-button--outline:hover:not(:disabled){background-color:var(--r-color-gray-50);border-color:var(--r-color-gray-400)}.rm-button--outline:active:not(:disabled){background-color:var(--r-color-gray-100)}.rm-button--ghost{background-color:transparent;color:var(--r-color-gray-700)}.rm-button--ghost:hover:not(:disabled){background-color:var(--r-color-gray-100)}.rm-button--ghost:active:not(:disabled){background-color:var(--r-color-gray-200)}.rm-button--block{width:100%}
|
|
46
54
|
</style>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
export interface RmDrawerProps {
|
|
3
|
+
/** Whether the drawer is open */
|
|
4
|
+
modelValue: boolean
|
|
5
|
+
/** Drawer size */
|
|
6
|
+
size?: 'sm' | 'md' | 'lg' | 'xl' | 'full'
|
|
7
|
+
/** Position */
|
|
8
|
+
side?: 'right' | 'left'
|
|
9
|
+
/** Show overlay behind the drawer */
|
|
10
|
+
overlay?: boolean
|
|
11
|
+
/** Offset from the edge (e.g. '280px' to keep a panel visible) */
|
|
12
|
+
offset?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const props = withDefaults(defineProps<RmDrawerProps>(), {
|
|
16
|
+
size: 'lg',
|
|
17
|
+
side: 'right',
|
|
18
|
+
overlay: true,
|
|
19
|
+
offset: '0px',
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const emit = defineEmits<{
|
|
23
|
+
'update:modelValue': [value: boolean]
|
|
24
|
+
}>()
|
|
25
|
+
|
|
26
|
+
function close() {
|
|
27
|
+
emit('update:modelValue', false)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const sizeMap: Record<string, string> = {
|
|
31
|
+
sm: '360px',
|
|
32
|
+
md: '480px',
|
|
33
|
+
lg: '640px',
|
|
34
|
+
xl: '860px',
|
|
35
|
+
full: '100%',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const drawerWidth = computed(() => sizeMap[props.size] || props.size)
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<Teleport to="body">
|
|
43
|
+
<Transition name="rm-drawer-overlay">
|
|
44
|
+
<div
|
|
45
|
+
v-if="modelValue && overlay"
|
|
46
|
+
class="rm-drawer-overlay"
|
|
47
|
+
@click="close"
|
|
48
|
+
/>
|
|
49
|
+
</Transition>
|
|
50
|
+
|
|
51
|
+
<Transition :name="`rm-drawer-slide-${side}`">
|
|
52
|
+
<div
|
|
53
|
+
v-if="modelValue"
|
|
54
|
+
class="rm-drawer"
|
|
55
|
+
:class="[`rm-drawer--${side}`]"
|
|
56
|
+
:style="{ width: drawerWidth, [side]: offset }"
|
|
57
|
+
>
|
|
58
|
+
<div class="rm-drawer__header">
|
|
59
|
+
<slot name="header" />
|
|
60
|
+
<button class="rm-drawer__close" @click="close">
|
|
61
|
+
<RmIcon name="X" :size="20" />
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="rm-drawer__body">
|
|
66
|
+
<slot />
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<div v-if="$slots.footer" class="rm-drawer__footer">
|
|
70
|
+
<slot name="footer" />
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</Transition>
|
|
74
|
+
</Teleport>
|
|
75
|
+
</template>
|
|
76
|
+
|
|
77
|
+
<style scoped>
|
|
78
|
+
.rm-drawer-overlay{backdrop-filter:blur(2px);background-color:rgba(0,0,0,.2);inset:0;position:fixed;z-index:90}.rm-drawer{background-color:var(--r-color-white);bottom:0;box-shadow:var(--r-shadow-xl);display:flex;flex-direction:column;max-width:100%;position:fixed;top:0;z-index:91}.rm-drawer--right{border-left:1px solid var(--r-color-gray-200)}.rm-drawer--left{border-right:1px solid var(--r-color-gray-200)}.rm-drawer__header{align-items:center;border-bottom:1px solid var(--r-color-gray-200);display:flex;justify-content:space-between;min-height:64px;padding:16px 24px}.rm-drawer__close{align-items:center;background:none;border:none;border-radius:var(--r-radius-md);color:var(--r-color-gray-500);cursor:pointer;display:flex;flex-shrink:0;height:32px;justify-content:center;transition:all var(--r-transition-fast);width:32px}.rm-drawer__close:hover{background-color:var(--r-color-gray-100);color:var(--r-color-gray-700)}.rm-drawer__body{flex:1;overflow-y:auto;padding:24px}.rm-drawer__footer{border-top:1px solid var(--r-color-gray-200);padding:16px 24px}.rm-drawer-overlay-enter-active,.rm-drawer-overlay-leave-active{transition:opacity .25s ease}.rm-drawer-overlay-enter-from,.rm-drawer-overlay-leave-to{opacity:0}.rm-drawer-slide-right-enter-active,.rm-drawer-slide-right-leave-active{transition:transform .3s cubic-bezier(.4,0,.2,1)}.rm-drawer-slide-right-enter-from,.rm-drawer-slide-right-leave-to{transform:translateX(100%)}.rm-drawer-slide-left-enter-active,.rm-drawer-slide-left-leave-active{transition:transform .3s cubic-bezier(.4,0,.2,1)}.rm-drawer-slide-left-enter-from,.rm-drawer-slide-left-leave-to{transform:translateX(-100%)}
|
|
79
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { PhCheck } from '@phosphor-icons/vue'
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
label: string
|
|
6
|
+
}>()
|
|
7
|
+
|
|
8
|
+
const checked = defineModel<boolean>({ default: false })
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<button
|
|
13
|
+
class="filter-checkbox"
|
|
14
|
+
:class="{ 'filter-checkbox--active': checked }"
|
|
15
|
+
@click="checked = !checked"
|
|
16
|
+
>
|
|
17
|
+
<span class="filter-checkbox__box" :class="{ 'filter-checkbox__box--checked': checked }">
|
|
18
|
+
<PhCheck v-if="checked" :size="10" weight="bold" />
|
|
19
|
+
</span>
|
|
20
|
+
<span>{{ label }}</span>
|
|
21
|
+
</button>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<style scoped>
|
|
25
|
+
.filter-checkbox{align-items:center;background:#fff;border:1px solid #dbdef0;border-radius:6px;box-sizing:border-box;color:var(--r-color-gray-600);cursor:pointer;display:flex;font-family:var(--r-font-family);font-size:var(--r-text-sm);font-weight:var(--r-font-weight-medium);gap:8px;height:32px;padding:8px;transition:all var(--r-transition-fast);white-space:nowrap;width:193px}.filter-checkbox:hover{border-color:var(--r-color-gray-300)}.filter-checkbox--active{border-color:#4164ee;box-shadow:0 0 8px 0 rgba(65,100,238,.1)}.filter-checkbox__box{align-items:center;border:1.5px solid var(--r-color-gray-300);border-radius:3px;display:flex;flex-shrink:0;height:16px;justify-content:center;transition:all var(--r-transition-fast);width:16px}.filter-checkbox__box--checked{background-color:#4164ee;border-color:#4164ee;color:#fff}
|
|
26
|
+
</style>
|