vue-pane 0.0.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 +424 -0
- package/dist/src/components/PButton.vue.d.ts +11 -0
- package/dist/src/components/PCheckbox.vue.d.ts +15 -0
- package/dist/src/components/PColor.vue.d.ts +16 -0
- package/dist/src/components/PFolder.vue.d.ts +27 -0
- package/dist/src/components/PGraph.vue.d.ts +10 -0
- package/dist/src/components/PLabel.vue.d.ts +17 -0
- package/dist/src/components/PMonitor.vue.d.ts +8 -0
- package/dist/src/components/PMonitorMulti.vue.d.ts +8 -0
- package/dist/src/components/PNumber.vue.d.ts +18 -0
- package/dist/src/components/PPoint2d.vue.d.ts +26 -0
- package/dist/src/components/PSelect.vue.d.ts +19 -0
- package/dist/src/components/PSeparator.vue.d.ts +3 -0
- package/dist/src/components/PSlider.vue.d.ts +18 -0
- package/dist/src/components/PTab.vue.d.ts +25 -0
- package/dist/src/components/PText.vue.d.ts +15 -0
- package/dist/src/components/PTooltipIcon.vue.d.ts +3 -0
- package/dist/src/components/VPane.vue.d.ts +28 -0
- package/dist/src/composables/useFoldable.d.ts +5 -0
- package/dist/src/composables/usePaneConfig.d.ts +8 -0
- package/dist/src/composables/usePickerFold.d.ts +2 -0
- package/dist/src/composables/useTooltip.d.ts +19 -0
- package/dist/src/index.d.ts +19 -0
- package/dist/vue-pane.css +2 -0
- package/dist/vue-pane.js +3076 -0
- package/dist/vue-pane.umd.cjs +1 -0
- package/package.json +79 -0
- package/src/components/PButton.vue +53 -0
- package/src/components/PCheckbox.vue +37 -0
- package/src/components/PColor.vue +107 -0
- package/src/components/PConfig.vue +10 -0
- package/src/components/PFolder.vue +81 -0
- package/src/components/PGraph.vue +49 -0
- package/src/components/PLabel.vue +50 -0
- package/src/components/PMonitor.vue +28 -0
- package/src/components/PMonitorMulti.vue +30 -0
- package/src/components/PNumber.vue +162 -0
- package/src/components/PPoint2d.vue +191 -0
- package/src/components/PSelect.vue +44 -0
- package/src/components/PSeparator.vue +8 -0
- package/src/components/PSlider.vue +96 -0
- package/src/components/PTab.vue +73 -0
- package/src/components/PText.vue +30 -0
- package/src/components/PTooltipIcon.vue +30 -0
- package/src/components/VPane.vue +61 -0
- package/src/composables/useFoldable.ts +128 -0
- package/src/composables/usePaneConfig.ts +25 -0
- package/src/composables/usePickerFold.ts +46 -0
- package/src/composables/useTooltip.ts +27 -0
- package/src/index.ts +38 -0
- package/src/styles/_vp.scss +12 -0
- package/src/styles/common/_defs.scss +56 -0
- package/src/styles/index.scss +1 -0
- package/src/styles/view/_button.scss +12 -0
- package/src/styles/view/_checkbox.scss +54 -0
- package/src/styles/view/_color.scss +57 -0
- package/src/styles/view/_folder.scss +70 -0
- package/src/styles/view/_graph.scss +11 -0
- package/src/styles/view/_label.scss +37 -0
- package/src/styles/view/_list.scss +17 -0
- package/src/styles/view/_log.scss +13 -0
- package/src/styles/view/_monitor-multi.scss +18 -0
- package/src/styles/view/_number.scss +110 -0
- package/src/styles/view/_point-2d.scss +61 -0
- package/src/styles/view/_root.scss +126 -0
- package/src/styles/view/_separator.scss +15 -0
- package/src/styles/view/_slider.scss +32 -0
- package/src/styles/view/_tab.scss +139 -0
- package/src/styles/view/_text.scss +24 -0
- package/src/styles/view/_tooltip.scss +17 -0
- package/src/styles/view/_views.scss +2 -0
- package/src/styles/view/placeholder/_button.scss +28 -0
- package/src/styles/view/placeholder/_container.scss +80 -0
- package/src/styles/view/placeholder/_folder.scss +102 -0
- package/src/styles/view/placeholder/_input.scss +26 -0
- package/src/styles/view/placeholder/_list.scss +35 -0
- package/src/styles/view/placeholder/_monitor.scss +26 -0
- package/src/styles/view/placeholder/_texts.scss +11 -0
- package/src/styles/view/placeholder/_theme.scss +111 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref } from 'vue'
|
|
3
|
+
import { useFoldable } from '../composables/useFoldable'
|
|
4
|
+
import { type PaneConfig, providePaneConfig } from '../composables/usePaneConfig'
|
|
5
|
+
|
|
6
|
+
const expandedModel = defineModel<boolean>('expanded', { default: undefined })
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
title,
|
|
10
|
+
id,
|
|
11
|
+
disabled,
|
|
12
|
+
config,
|
|
13
|
+
} = defineProps<{
|
|
14
|
+
title?: string
|
|
15
|
+
id?: string
|
|
16
|
+
disabled?: boolean
|
|
17
|
+
config?: PaneConfig
|
|
18
|
+
}>()
|
|
19
|
+
|
|
20
|
+
if (config) {
|
|
21
|
+
providePaneConfig(config)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const key = id ?? title
|
|
25
|
+
const hasTitle = computed(() => !!title)
|
|
26
|
+
const containerRef = ref<HTMLElement | null>(null)
|
|
27
|
+
const { isExpanded, toggle } = useFoldable(
|
|
28
|
+
containerRef,
|
|
29
|
+
expandedModel,
|
|
30
|
+
key ? `vp-pane-${key}` : undefined,
|
|
31
|
+
)
|
|
32
|
+
</script>
|
|
33
|
+
<template>
|
|
34
|
+
<div
|
|
35
|
+
class="vp-pane"
|
|
36
|
+
:class="{
|
|
37
|
+
'vp-pane--expanded': isExpanded,
|
|
38
|
+
'vp-pane--no-title': !hasTitle,
|
|
39
|
+
'vp--disabled': disabled,
|
|
40
|
+
}"
|
|
41
|
+
>
|
|
42
|
+
<button
|
|
43
|
+
v-if="hasTitle"
|
|
44
|
+
class="vp-pane__title"
|
|
45
|
+
@click="toggle"
|
|
46
|
+
>
|
|
47
|
+
{{ title }}
|
|
48
|
+
<div class="vp-pane__chevron" />
|
|
49
|
+
</button>
|
|
50
|
+
<div
|
|
51
|
+
ref="containerRef"
|
|
52
|
+
class="vp-pane__content"
|
|
53
|
+
>
|
|
54
|
+
<slot />
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
<style lang="scss">
|
|
59
|
+
@use '../styles/view/root';
|
|
60
|
+
@use '../styles/view/tooltip';
|
|
61
|
+
</style>
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { Ref } from 'vue'
|
|
2
|
+
import { nextTick, onMounted, ref, watch } from 'vue'
|
|
3
|
+
import { usePaneConfig } from './usePaneConfig.ts'
|
|
4
|
+
|
|
5
|
+
function measureExpandedHeight(el: HTMLElement, expandedClass: string): number {
|
|
6
|
+
const parent = el.parentElement
|
|
7
|
+
if (!parent) return 0
|
|
8
|
+
|
|
9
|
+
const wasExpanded = parent.classList.contains(expandedClass)
|
|
10
|
+
|
|
11
|
+
// Temporarily disable transitions and apply expanded state to measure true height
|
|
12
|
+
el.style.transition = 'none'
|
|
13
|
+
if (!wasExpanded) {
|
|
14
|
+
parent.classList.add(expandedClass)
|
|
15
|
+
el.style.height = 'auto'
|
|
16
|
+
}
|
|
17
|
+
void el.offsetHeight
|
|
18
|
+
const height = el.clientHeight
|
|
19
|
+
|
|
20
|
+
if (!wasExpanded) {
|
|
21
|
+
parent.classList.remove(expandedClass)
|
|
22
|
+
el.style.height = ''
|
|
23
|
+
}
|
|
24
|
+
void el.offsetHeight
|
|
25
|
+
el.style.transition = ''
|
|
26
|
+
|
|
27
|
+
return height
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function useFoldable(
|
|
31
|
+
containerRef: Ref<HTMLElement | null>,
|
|
32
|
+
expandedRef: Ref<boolean>,
|
|
33
|
+
storageKey?: string,
|
|
34
|
+
expandedClass = 'vp-folder--expanded',
|
|
35
|
+
): {
|
|
36
|
+
isExpanded: Ref<boolean>
|
|
37
|
+
toggle: () => void
|
|
38
|
+
} {
|
|
39
|
+
let stored: string | null = null
|
|
40
|
+
if (storageKey) {
|
|
41
|
+
stored = localStorage?.getItem?.(storageKey) ?? null
|
|
42
|
+
}
|
|
43
|
+
const config = usePaneConfig()
|
|
44
|
+
const onToggle = (val: boolean) => expandedRef.value = val
|
|
45
|
+
const initialPropValue = expandedRef.value as boolean | undefined
|
|
46
|
+
const isExpanded = ref(
|
|
47
|
+
initialPropValue !== undefined
|
|
48
|
+
? initialPropValue
|
|
49
|
+
: stored !== null
|
|
50
|
+
? stored === 'true'
|
|
51
|
+
: config.expandedDefault ?? true,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
watch(isExpanded, (val) => {
|
|
55
|
+
if (storageKey && typeof localStorage !== 'undefined') {
|
|
56
|
+
localStorage.setItem(storageKey, String(val))
|
|
57
|
+
}
|
|
58
|
+
onToggle(val)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
onMounted(() => {
|
|
62
|
+
const el = containerRef.value
|
|
63
|
+
if (el && isExpanded.value) {
|
|
64
|
+
el.style.height = 'auto'
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
function animateExpand(el: HTMLElement) {
|
|
69
|
+
const targetHeight = measureExpandedHeight(el, expandedClass)
|
|
70
|
+
isExpanded.value = true
|
|
71
|
+
|
|
72
|
+
nextTick(() => {
|
|
73
|
+
if (targetHeight === 0) {
|
|
74
|
+
el.style.height = 'auto'
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
// Pin padding to 0 inline so both height and padding can animate from 0
|
|
78
|
+
el.style.paddingTop = '0'
|
|
79
|
+
el.style.paddingBottom = '0'
|
|
80
|
+
void el.offsetHeight
|
|
81
|
+
|
|
82
|
+
el.style.height = targetHeight + 'px'
|
|
83
|
+
el.style.paddingTop = ''
|
|
84
|
+
el.style.paddingBottom = ''
|
|
85
|
+
|
|
86
|
+
el.addEventListener('transitionend', (e: TransitionEvent) => {
|
|
87
|
+
if (e.propertyName === 'height' && isExpanded.value) {
|
|
88
|
+
el.style.height = 'auto'
|
|
89
|
+
}
|
|
90
|
+
}, { once: true })
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function animateCollapse(el: HTMLElement) {
|
|
95
|
+
// Lock to px so height: auto → 0 is animatable
|
|
96
|
+
el.style.transition = 'none'
|
|
97
|
+
el.style.height = el.clientHeight + 'px'
|
|
98
|
+
void el.offsetHeight
|
|
99
|
+
el.style.transition = ''
|
|
100
|
+
void el.offsetHeight
|
|
101
|
+
|
|
102
|
+
el.style.height = '0'
|
|
103
|
+
isExpanded.value = false
|
|
104
|
+
|
|
105
|
+
el.addEventListener('transitionend', (e: TransitionEvent) => {
|
|
106
|
+
if (e.propertyName === 'height') {
|
|
107
|
+
el.style.height = ''
|
|
108
|
+
}
|
|
109
|
+
}, { once: true })
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
watch(() => expandedRef.value as boolean | undefined, (val) => {
|
|
113
|
+
if (val === undefined || val === isExpanded.value) return
|
|
114
|
+
const el = containerRef.value
|
|
115
|
+
if (!el) return
|
|
116
|
+
if (val) animateExpand(el)
|
|
117
|
+
else animateCollapse(el)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
function toggle() {
|
|
121
|
+
const el = containerRef.value
|
|
122
|
+
if (!el) return
|
|
123
|
+
if (isExpanded.value) animateCollapse(el)
|
|
124
|
+
else animateExpand(el)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return { isExpanded, toggle }
|
|
128
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Component, inject, type InjectionKey, provide } from 'vue'
|
|
2
|
+
import PTooltipIcon from '../components/PTooltipIcon.vue'
|
|
3
|
+
|
|
4
|
+
export interface PaneConfig {
|
|
5
|
+
readonly tooltipIcon?: Component | null
|
|
6
|
+
readonly expandedDefault?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const DEFAULTS: PaneConfig = {
|
|
10
|
+
expandedDefault: true,
|
|
11
|
+
tooltipIcon: PTooltipIcon,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const PANE_CONFIG_KEY: InjectionKey<PaneConfig> = Symbol('vp-config')
|
|
15
|
+
|
|
16
|
+
export function usePaneConfig(): PaneConfig {
|
|
17
|
+
return inject(PANE_CONFIG_KEY, DEFAULTS)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function providePaneConfig(config: Partial<PaneConfig> | null = null): void {
|
|
21
|
+
provide(PANE_CONFIG_KEY, {
|
|
22
|
+
...usePaneConfig(),
|
|
23
|
+
...config,
|
|
24
|
+
} as PaneConfig)
|
|
25
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ref, watch } from 'vue'
|
|
2
|
+
import type { Ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
export function usePickerFold(
|
|
5
|
+
panelRef: Ref<HTMLElement | null>,
|
|
6
|
+
isOpen: Ref<boolean>,
|
|
7
|
+
): Ref<boolean> {
|
|
8
|
+
const isComplete = ref(false)
|
|
9
|
+
|
|
10
|
+
watch(isOpen, (open) => {
|
|
11
|
+
const el = panelRef.value
|
|
12
|
+
if (!el) return
|
|
13
|
+
|
|
14
|
+
isComplete.value = false
|
|
15
|
+
|
|
16
|
+
if (open) {
|
|
17
|
+
el.style.transition = 'none'
|
|
18
|
+
el.style.height = 'auto'
|
|
19
|
+
void el.offsetHeight
|
|
20
|
+
const h = el.clientHeight
|
|
21
|
+
el.style.height = '0'
|
|
22
|
+
void el.offsetHeight
|
|
23
|
+
el.style.transition = ''
|
|
24
|
+
void el.offsetHeight
|
|
25
|
+
el.style.height = h + 'px'
|
|
26
|
+
el.addEventListener('transitionend', (e: TransitionEvent) => {
|
|
27
|
+
if (e.propertyName === 'height') {
|
|
28
|
+
el.style.height = 'auto'
|
|
29
|
+
isComplete.value = true
|
|
30
|
+
}
|
|
31
|
+
}, { once: true })
|
|
32
|
+
} else {
|
|
33
|
+
el.style.transition = 'none'
|
|
34
|
+
el.style.height = el.clientHeight + 'px'
|
|
35
|
+
void el.offsetHeight
|
|
36
|
+
el.style.transition = ''
|
|
37
|
+
void el.offsetHeight
|
|
38
|
+
el.style.height = '0'
|
|
39
|
+
el.addEventListener('transitionend', (e: TransitionEvent) => {
|
|
40
|
+
if (e.propertyName === 'height') el.style.height = ''
|
|
41
|
+
}, { once: true })
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
return isComplete
|
|
46
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ref, useTemplateRef } from 'vue'
|
|
2
|
+
import { flip, offset, shift, useFloating } from '@floating-ui/vue'
|
|
3
|
+
|
|
4
|
+
export function useTooltip() {
|
|
5
|
+
const referenceEl = ref<HTMLElement | null>(null)
|
|
6
|
+
const floatingEl = useTemplateRef<HTMLElement>('floatingEl')
|
|
7
|
+
const visible = ref(false)
|
|
8
|
+
const activeText = ref<string | undefined>(undefined)
|
|
9
|
+
|
|
10
|
+
const { floatingStyles } = useFloating(referenceEl, floatingEl, {
|
|
11
|
+
placement: 'top-start',
|
|
12
|
+
strategy: 'fixed',
|
|
13
|
+
middleware: [offset(4), flip(), shift({ padding: 8 })],
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
function show(e: MouseEvent, text: string) {
|
|
17
|
+
referenceEl.value = e.currentTarget as HTMLElement
|
|
18
|
+
activeText.value = text
|
|
19
|
+
visible.value = true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function hide() {
|
|
23
|
+
visible.value = false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return { floatingStyles, visible, activeText, show, hide }
|
|
27
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import VPane from './components/VPane.vue'
|
|
2
|
+
import PFolder from './components/PFolder.vue'
|
|
3
|
+
import PLabel from './components/PLabel.vue'
|
|
4
|
+
import PText from './components/PText.vue'
|
|
5
|
+
import PNumber from './components/PNumber.vue'
|
|
6
|
+
import PButton from './components/PButton.vue'
|
|
7
|
+
import PSeparator from './components/PSeparator.vue'
|
|
8
|
+
import PCheckbox from './components/PCheckbox.vue'
|
|
9
|
+
import PSelect from './components/PSelect.vue'
|
|
10
|
+
import PMonitor from './components/PMonitor.vue'
|
|
11
|
+
import PMonitorMulti from './components/PMonitorMulti.vue'
|
|
12
|
+
import PSlider from './components/PSlider.vue'
|
|
13
|
+
import PTab from './components/PTab.vue'
|
|
14
|
+
import PColor from './components/PColor.vue'
|
|
15
|
+
import PGraph from './components/PGraph.vue'
|
|
16
|
+
import PPoint2d from './components/PPoint2d.vue'
|
|
17
|
+
|
|
18
|
+
export type { PaneConfig } from './composables/usePaneConfig'
|
|
19
|
+
export { usePaneConfig } from './composables/usePaneConfig'
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
VPane,
|
|
23
|
+
PFolder,
|
|
24
|
+
PLabel,
|
|
25
|
+
PText,
|
|
26
|
+
PNumber,
|
|
27
|
+
PButton,
|
|
28
|
+
PSeparator,
|
|
29
|
+
PCheckbox,
|
|
30
|
+
PSelect,
|
|
31
|
+
PMonitor,
|
|
32
|
+
PMonitorMulti,
|
|
33
|
+
PSlider,
|
|
34
|
+
PTab,
|
|
35
|
+
PColor,
|
|
36
|
+
PGraph,
|
|
37
|
+
PPoint2d,
|
|
38
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Entry point for plugins
|
|
2
|
+
|
|
3
|
+
@forward './common/defs';
|
|
4
|
+
|
|
5
|
+
@forward './view/placeholder/button';
|
|
6
|
+
@forward './view/placeholder/container';
|
|
7
|
+
@forward './view/placeholder/folder';
|
|
8
|
+
@forward './view/placeholder/input';
|
|
9
|
+
@forward './view/placeholder/list';
|
|
10
|
+
@forward './view/placeholder/monitor';
|
|
11
|
+
@forward './view/placeholder/texts';
|
|
12
|
+
@forward './view/placeholder/theme';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
@use 'sass:map';
|
|
2
|
+
@use 'sass:string';
|
|
3
|
+
|
|
4
|
+
$prefix: 'vp';
|
|
5
|
+
|
|
6
|
+
// Global state classes
|
|
7
|
+
$disabled: #{$prefix}--disabled;
|
|
8
|
+
|
|
9
|
+
// Common Sass variables
|
|
10
|
+
$fold-transition-duration: 0.2s;
|
|
11
|
+
$separator-width: 2px;
|
|
12
|
+
$slider-knob-size: 12px;
|
|
13
|
+
$z-index-picker: 1000;
|
|
14
|
+
|
|
15
|
+
// CSS variables — short names to reduce file size
|
|
16
|
+
$css-vars: (
|
|
17
|
+
'base-bg': 'bs-bg',
|
|
18
|
+
'base-border-radius': 'bs-br',
|
|
19
|
+
'base-font': 'bs-ff',
|
|
20
|
+
'base-shadow': 'bs-sh',
|
|
21
|
+
'blade-border-radius': 'bld-br',
|
|
22
|
+
'blade-h-padding': 'bld-hp',
|
|
23
|
+
'blade-value-width': 'bld-vw',
|
|
24
|
+
'button-bg': 'btn-bg',
|
|
25
|
+
'button-bg-active': 'btn-bg-a',
|
|
26
|
+
'button-bg-focus': 'btn-bg-f',
|
|
27
|
+
'button-bg-hover': 'btn-bg-h',
|
|
28
|
+
'button-fg': 'btn-fg',
|
|
29
|
+
'container-bg': 'cnt-bg',
|
|
30
|
+
'container-bg-active': 'cnt-bg-a',
|
|
31
|
+
'container-bg-focus': 'cnt-bg-f',
|
|
32
|
+
'container-bg-hover': 'cnt-bg-h',
|
|
33
|
+
'container-fg': 'cnt-fg',
|
|
34
|
+
'container-h-padding': 'cnt-hp',
|
|
35
|
+
'container-unit-size': 'cnt-usz',
|
|
36
|
+
'container-unit-spacing': 'cnt-usp',
|
|
37
|
+
'container-v-padding': 'cnt-vp',
|
|
38
|
+
'groove-fg': 'grv-fg',
|
|
39
|
+
'input-bg': 'in-bg',
|
|
40
|
+
'input-bg-active': 'in-bg-a',
|
|
41
|
+
'input-bg-focus': 'in-bg-f',
|
|
42
|
+
'input-bg-hover': 'in-bg-h',
|
|
43
|
+
'input-fg': 'in-fg',
|
|
44
|
+
'label-fg': 'lbl-fg',
|
|
45
|
+
'monitor-bg': 'mo-bg',
|
|
46
|
+
'monitor-fg': 'mo-fg',
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
@function cssVar($name) {
|
|
50
|
+
$short-name: map.get($css-vars, $name);
|
|
51
|
+
@if $short-name == null {
|
|
52
|
+
@error 'Short CSS variable for \'#{$name}\' not found.';
|
|
53
|
+
}
|
|
54
|
+
@return string.unquote('var(--' + $short-name + ')');
|
|
55
|
+
}
|
|
56
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@use './view/views';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
@use '../vp';
|
|
2
|
+
|
|
3
|
+
.vp-checkbox {
|
|
4
|
+
&__label {
|
|
5
|
+
display: block;
|
|
6
|
+
position: relative;
|
|
7
|
+
}
|
|
8
|
+
&__input {
|
|
9
|
+
left: 0;
|
|
10
|
+
opacity: 0;
|
|
11
|
+
position: absolute;
|
|
12
|
+
top: 0;
|
|
13
|
+
}
|
|
14
|
+
&__box {
|
|
15
|
+
background-color: vp.cssVar('input-bg');
|
|
16
|
+
border-radius: vp.cssVar('blade-border-radius');
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
display: block;
|
|
19
|
+
height: vp.cssVar('container-unit-size');
|
|
20
|
+
position: relative;
|
|
21
|
+
width: vp.cssVar('container-unit-size');
|
|
22
|
+
|
|
23
|
+
svg {
|
|
24
|
+
display: block;
|
|
25
|
+
height: 16px;
|
|
26
|
+
inset: 0;
|
|
27
|
+
margin: auto;
|
|
28
|
+
opacity: 0;
|
|
29
|
+
position: absolute;
|
|
30
|
+
width: 16px;
|
|
31
|
+
|
|
32
|
+
path {
|
|
33
|
+
fill: none;
|
|
34
|
+
stroke: vp.cssVar('input-fg');
|
|
35
|
+
stroke-width: 2;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
&__input:hover + &__box {
|
|
40
|
+
background-color: vp.cssVar('input-bg-hover');
|
|
41
|
+
}
|
|
42
|
+
&__input:focus + &__box {
|
|
43
|
+
background-color: vp.cssVar('input-bg-focus');
|
|
44
|
+
}
|
|
45
|
+
&__input:active + &__box {
|
|
46
|
+
background-color: vp.cssVar('input-bg-active');
|
|
47
|
+
}
|
|
48
|
+
&__input:checked + &__box svg {
|
|
49
|
+
opacity: 1;
|
|
50
|
+
}
|
|
51
|
+
&.#{vp.$disabled} &__box {
|
|
52
|
+
opacity: 0.5;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
@use '../vp';
|
|
2
|
+
|
|
3
|
+
.vp-color {
|
|
4
|
+
position: relative;
|
|
5
|
+
|
|
6
|
+
&__header { display: flex; }
|
|
7
|
+
&__swatch { flex-grow: 0; flex-shrink: 0; width: vp.cssVar('container-unit-size'); }
|
|
8
|
+
&__text { flex: 1; margin-left: 4px; }
|
|
9
|
+
|
|
10
|
+
&__swatch-btn {
|
|
11
|
+
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%),
|
|
12
|
+
linear-gradient(-45deg, #ccc 25%, transparent 25%),
|
|
13
|
+
linear-gradient(45deg, transparent 75%, #ccc 75%),
|
|
14
|
+
linear-gradient(-45deg, transparent 75%, #ccc 75%);
|
|
15
|
+
background-position: 0 0, 0 4px, 4px -4px, -4px 0px;
|
|
16
|
+
background-size: 8px 8px;
|
|
17
|
+
border-radius: vp.cssVar('blade-border-radius');
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
display: block;
|
|
20
|
+
height: vp.cssVar('container-unit-size');
|
|
21
|
+
overflow: hidden;
|
|
22
|
+
position: relative;
|
|
23
|
+
width: 100%;
|
|
24
|
+
|
|
25
|
+
&:focus::after {
|
|
26
|
+
border: rgba(white, 0.75) solid 2px;
|
|
27
|
+
border-radius: vp.cssVar('blade-border-radius');
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
content: '';
|
|
30
|
+
display: block;
|
|
31
|
+
inset: 0;
|
|
32
|
+
position: absolute;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&__color { inset: 0; position: absolute; }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&__popup {
|
|
39
|
+
z-index: vp.$z-index-picker;
|
|
40
|
+
|
|
41
|
+
// vue-color CSS variable overrides — maps to our design tokens
|
|
42
|
+
--vc-body-bg: #{vp.cssVar('base-bg')};
|
|
43
|
+
--vc-picker-bg: rgba(255, 255, 255, 0.85);
|
|
44
|
+
--vc-input-bg: #{vp.cssVar('input-bg')};
|
|
45
|
+
--vc-input-text: #{vp.cssVar('container-fg')};
|
|
46
|
+
--vc-input-label: #{vp.cssVar('label-fg')};
|
|
47
|
+
--vc-input-border: rgba(255, 255, 255, 0.15);
|
|
48
|
+
--vc-chrome-toggle-btn-highlighted: #{vp.cssVar('input-bg-hover')};
|
|
49
|
+
|
|
50
|
+
.vc-chrome-picker {
|
|
51
|
+
box-sizing: border-box;
|
|
52
|
+
font-family: #{vp.cssVar('base-font')};
|
|
53
|
+
font-size: 11px;
|
|
54
|
+
width: 220px;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
@use '../vp';
|
|
2
|
+
|
|
3
|
+
.vp-folder {
|
|
4
|
+
position: relative;
|
|
5
|
+
|
|
6
|
+
// Title button
|
|
7
|
+
&__title {
|
|
8
|
+
@extend %vp-folder_title;
|
|
9
|
+
}
|
|
10
|
+
// Title text inside button
|
|
11
|
+
&__title-text {
|
|
12
|
+
padding-left: 4px;
|
|
13
|
+
}
|
|
14
|
+
// Expand/collapse chevron
|
|
15
|
+
&__chevron {
|
|
16
|
+
@extend %vp-folder_mark;
|
|
17
|
+
}
|
|
18
|
+
&__title:disabled &__chevron {
|
|
19
|
+
display: none;
|
|
20
|
+
}
|
|
21
|
+
&#{&}--expanded > &__title > &__chevron {
|
|
22
|
+
@extend %vp-folder_mark-expanded;
|
|
23
|
+
}
|
|
24
|
+
// Children container
|
|
25
|
+
&__content {
|
|
26
|
+
@extend %vp-folder_container;
|
|
27
|
+
@extend %vp-container_children;
|
|
28
|
+
@extend %vp-container_subcontainers;
|
|
29
|
+
|
|
30
|
+
padding-left: 4px;
|
|
31
|
+
}
|
|
32
|
+
&#{&}--expanded > &__content {
|
|
33
|
+
@extend %vp-folder_container-expanded;
|
|
34
|
+
}
|
|
35
|
+
&#{&}--complete:not(#{&}--expanded) > &__content {
|
|
36
|
+
@extend %vp-folder_container-shrinkedCompletely;
|
|
37
|
+
}
|
|
38
|
+
// Indent line
|
|
39
|
+
&__indent {
|
|
40
|
+
bottom: 0;
|
|
41
|
+
color: vp.cssVar('container-bg');
|
|
42
|
+
left: 0;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
position: absolute;
|
|
45
|
+
top: calc(#{vp.cssVar('container-unit-size')} + 4px);
|
|
46
|
+
width: max(vp.cssVar('base-border-radius'), 4px);
|
|
47
|
+
|
|
48
|
+
&::before {
|
|
49
|
+
background-color: currentColor;
|
|
50
|
+
bottom: 0;
|
|
51
|
+
content: '';
|
|
52
|
+
left: 0;
|
|
53
|
+
position: absolute;
|
|
54
|
+
top: 0;
|
|
55
|
+
width: 4px;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
&__title:hover + &__indent {
|
|
59
|
+
color: vp.cssVar('container-bg-hover');
|
|
60
|
+
}
|
|
61
|
+
&__title:focus + &__indent {
|
|
62
|
+
color: vp.cssVar('container-bg-focus');
|
|
63
|
+
}
|
|
64
|
+
&__title:active + &__indent {
|
|
65
|
+
color: vp.cssVar('container-bg-active');
|
|
66
|
+
}
|
|
67
|
+
&.#{vp.$disabled} > &__indent {
|
|
68
|
+
opacity: 0.5;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
@use '../vp';
|
|
2
|
+
|
|
3
|
+
.vp-graph {
|
|
4
|
+
position: relative;
|
|
5
|
+
&__svg {
|
|
6
|
+
@extend %vp-monitor;
|
|
7
|
+
display: block; height: calc(vp.cssVar('container-unit-size') * 3);
|
|
8
|
+
polyline { fill: none; stroke: vp.cssVar('monitor-fg'); stroke-linejoin: round; }
|
|
9
|
+
}
|
|
10
|
+
&.vp--disabled &__svg { opacity: 0.5; }
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
@use '../vp';
|
|
2
|
+
|
|
3
|
+
.vp-label {
|
|
4
|
+
align-items: center;
|
|
5
|
+
display: flex;
|
|
6
|
+
line-height: 1.3;
|
|
7
|
+
padding-left: vp.cssVar('container-h-padding');
|
|
8
|
+
padding-right: vp.cssVar('container-h-padding');
|
|
9
|
+
|
|
10
|
+
&--no-label {
|
|
11
|
+
display: block;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&__text {
|
|
15
|
+
color: vp.cssVar('label-fg');
|
|
16
|
+
flex: 1;
|
|
17
|
+
hyphens: auto;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
padding-left: 4px;
|
|
20
|
+
padding-right: 16px;
|
|
21
|
+
}
|
|
22
|
+
&.#{vp.$disabled} &__text {
|
|
23
|
+
opacity: 0.5;
|
|
24
|
+
}
|
|
25
|
+
&--no-label &__text {
|
|
26
|
+
display: none;
|
|
27
|
+
}
|
|
28
|
+
&__value {
|
|
29
|
+
align-self: flex-start;
|
|
30
|
+
flex-grow: 0;
|
|
31
|
+
flex-shrink: 0;
|
|
32
|
+
width: vp.cssVar('blade-value-width');
|
|
33
|
+
}
|
|
34
|
+
&--no-label &__value {
|
|
35
|
+
width: 100%;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
@use '../vp';
|
|
2
|
+
|
|
3
|
+
.vp-select {
|
|
4
|
+
@extend %vp-list;
|
|
5
|
+
|
|
6
|
+
&__input {
|
|
7
|
+
@extend %vp-list_select;
|
|
8
|
+
|
|
9
|
+
padding: 0 (16px + 2px * 2) 0 vp.cssVar('blade-h-padding');
|
|
10
|
+
width: 100%;
|
|
11
|
+
}
|
|
12
|
+
&__arrow {
|
|
13
|
+
@extend %vp-list_arrow;
|
|
14
|
+
|
|
15
|
+
color: vp.cssVar('button-fg');
|
|
16
|
+
}
|
|
17
|
+
}
|