@liftkit-vue/core 0.1.0 → 0.2.1
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/package.json +11 -7
- package/src/components/LkBadge.vue +64 -0
- package/src/components/LkButton.vue +102 -0
- package/src/components/LkCard.vue +85 -0
- package/src/components/LkColumn.vue +40 -0
- package/src/components/LkContainer.vue +26 -0
- package/src/components/LkDropdown/LkDropdown.vue +14 -0
- package/src/components/LkDropdown/LkDropdownMenu.vue +99 -0
- package/src/components/LkDropdown/LkDropdownTrigger.vue +39 -0
- package/src/components/LkDropdown/index.ts +3 -0
- package/src/components/LkGrid.vue +58 -0
- package/src/components/LkHeading.vue +43 -0
- package/src/components/LkIcon.vue +56 -0
- package/src/components/LkIconButton.vue +78 -0
- package/src/components/LkImage.vue +62 -0
- package/src/components/LkMaterialLayer.vue +147 -0
- package/src/components/LkMenuItem.vue +51 -0
- package/src/components/LkNavbar.vue +113 -0
- package/src/components/LkPlaceholderBlock.vue +9 -0
- package/src/components/LkRow.vue +40 -0
- package/src/components/LkSection.vue +45 -0
- package/src/components/LkSelect.vue +167 -0
- package/src/components/LkSelectMenu.vue +67 -0
- package/src/components/LkSelectOption.vue +56 -0
- package/src/components/LkSelectTrigger.vue +43 -0
- package/src/components/LkSnackbar.vue +127 -0
- package/src/components/LkStateLayer.vue +33 -0
- package/src/components/LkSticker.vue +42 -0
- package/src/components/LkSwitch.vue +90 -0
- package/src/components/LkTabContent.vue +33 -0
- package/src/components/LkTabLink.vue +50 -0
- package/src/components/LkTabMenu.vue +59 -0
- package/src/components/LkTabs.vue +65 -0
- package/src/components/LkText.vue +37 -0
- package/src/components/LkTextInput.vue +105 -0
- package/src/components/LkTheme.vue +49 -0
- package/src/components/LkThemeController.vue +396 -0
- package/src/css/index.css +3 -1
- package/src/css/liftkit-core.css +5 -464
- package/src/css/liftkit-reset.css +74 -0
- package/src/css/liftkit-tokens.css +375 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { propsToDataAttrs } from '../utils/utilities'
|
|
4
|
+
import LkText from './LkText.vue'
|
|
5
|
+
|
|
6
|
+
export interface LkTabLinkProps {
|
|
7
|
+
selected?: boolean
|
|
8
|
+
fontClass?: LkFontClass
|
|
9
|
+
indicatorClass?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const props = withDefaults(defineProps<LkTabLinkProps>(), {
|
|
13
|
+
selected: false,
|
|
14
|
+
fontClass: 'body',
|
|
15
|
+
indicatorClass: 'lk-indicator',
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
defineOptions({
|
|
19
|
+
inheritAttrs: false,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const dataAttrs = computed(() =>
|
|
23
|
+
propsToDataAttrs(
|
|
24
|
+
{
|
|
25
|
+
selected: props.selected,
|
|
26
|
+
fontClass: props.fontClass,
|
|
27
|
+
indicatorClass: props.indicatorClass,
|
|
28
|
+
},
|
|
29
|
+
'tab-link',
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
const textStyle = computed(() =>
|
|
34
|
+
props.selected ? { fontWeight: 700 } : {},
|
|
35
|
+
)
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<div
|
|
40
|
+
data-lk-component="tab-link"
|
|
41
|
+
v-bind="{ ...$attrs, ...dataAttrs }"
|
|
42
|
+
>
|
|
43
|
+
<div data-lk-slot="child">
|
|
44
|
+
<LkText :font-class="fontClass" :style="textStyle">
|
|
45
|
+
<slot />
|
|
46
|
+
</LkText>
|
|
47
|
+
</div>
|
|
48
|
+
<div :class="indicatorClass" />
|
|
49
|
+
</div>
|
|
50
|
+
</template>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { propsToDataAttrs } from '../utils/utilities'
|
|
4
|
+
import LkRow from './LkRow.vue'
|
|
5
|
+
import LkTabLink from './LkTabLink.vue'
|
|
6
|
+
|
|
7
|
+
export interface LkTabMenuProps {
|
|
8
|
+
tabLinks?: string[]
|
|
9
|
+
alignItems?: 'start' | 'center' | 'end' | 'stretch'
|
|
10
|
+
justifyContent?: 'start' | 'center' | 'end' | 'space-between' | 'space-around'
|
|
11
|
+
activeTab?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const props = withDefaults(defineProps<LkTabMenuProps>(), {
|
|
15
|
+
tabLinks: () => ['Tab Link 1', 'Tab Link 2', 'Tab Link 3'],
|
|
16
|
+
activeTab: 0,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const emit = defineEmits<{
|
|
20
|
+
'update:activeTab': [index: number]
|
|
21
|
+
}>()
|
|
22
|
+
|
|
23
|
+
defineOptions({
|
|
24
|
+
inheritAttrs: false,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const dataAttrs = computed(() =>
|
|
28
|
+
propsToDataAttrs(
|
|
29
|
+
{
|
|
30
|
+
alignItems: props.alignItems,
|
|
31
|
+
justifyContent: props.justifyContent,
|
|
32
|
+
activeTab: props.activeTab,
|
|
33
|
+
},
|
|
34
|
+
'tab-menu',
|
|
35
|
+
),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
function handleTabClick(index: number) {
|
|
39
|
+
emit('update:activeTab', index)
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<div
|
|
45
|
+
data-lk-component="tab-menu"
|
|
46
|
+
v-bind="{ ...$attrs, ...dataAttrs }"
|
|
47
|
+
>
|
|
48
|
+
<LkRow :align-items="alignItems" :justify-content="justifyContent">
|
|
49
|
+
<LkTabLink
|
|
50
|
+
v-for="(label, index) in tabLinks"
|
|
51
|
+
:key="index"
|
|
52
|
+
:selected="index === activeTab"
|
|
53
|
+
@click="handleTabClick(index)"
|
|
54
|
+
>
|
|
55
|
+
<div>{{ label ?? 'Tab Link' }}</div>
|
|
56
|
+
</LkTabLink>
|
|
57
|
+
</LkRow>
|
|
58
|
+
</div>
|
|
59
|
+
</template>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, computed, watch, provide } from 'vue'
|
|
3
|
+
import { propsToDataAttrs } from '../utils/utilities'
|
|
4
|
+
import LkTabMenu from './LkTabMenu.vue'
|
|
5
|
+
|
|
6
|
+
export interface LkTabsProps {
|
|
7
|
+
tabLinks: string[]
|
|
8
|
+
scrollableContent?: boolean
|
|
9
|
+
defaultTab?: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const props = withDefaults(defineProps<LkTabsProps>(), {
|
|
13
|
+
scrollableContent: false,
|
|
14
|
+
defaultTab: 0,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const emit = defineEmits<{
|
|
18
|
+
'activeTabChange': [index: number]
|
|
19
|
+
}>()
|
|
20
|
+
|
|
21
|
+
defineOptions({
|
|
22
|
+
inheritAttrs: false,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const activeTab = ref(props.defaultTab)
|
|
26
|
+
|
|
27
|
+
function setActiveTab(index: number) {
|
|
28
|
+
activeTab.value = index
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
watch(activeTab, (newVal) => {
|
|
32
|
+
emit('activeTabChange', newVal)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
provide('lk-tabs', {
|
|
36
|
+
activeTab,
|
|
37
|
+
setActiveTab,
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const dataAttrs = computed(() =>
|
|
41
|
+
propsToDataAttrs({ activeTab: activeTab.value }, 'tabs'),
|
|
42
|
+
)
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<div
|
|
47
|
+
data-lk-component="tabs"
|
|
48
|
+
:data-lk-tabs-content-scrollable="scrollableContent || undefined"
|
|
49
|
+
v-bind="{ ...$attrs, ...dataAttrs }"
|
|
50
|
+
>
|
|
51
|
+
<LkTabMenu
|
|
52
|
+
:tab-links="tabLinks"
|
|
53
|
+
justify-content="start"
|
|
54
|
+
align-items="stretch"
|
|
55
|
+
:active-tab="activeTab"
|
|
56
|
+
@update:active-tab="setActiveTab"
|
|
57
|
+
/>
|
|
58
|
+
<div
|
|
59
|
+
data-lk-tabs-el="tab-content"
|
|
60
|
+
:data-lk-tabs-content-scrollable="scrollableContent || undefined"
|
|
61
|
+
>
|
|
62
|
+
<slot :active-tab="activeTab" />
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</template>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
|
|
4
|
+
interface LkTextProps {
|
|
5
|
+
tag?: string
|
|
6
|
+
fontClass?: LkFontClass
|
|
7
|
+
color?: LkColor
|
|
8
|
+
class?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(defineProps<LkTextProps>(), {
|
|
12
|
+
tag: 'div',
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
defineOptions({
|
|
16
|
+
inheritAttrs: false,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const textClass = computed(() => {
|
|
20
|
+
const classes: string[] = []
|
|
21
|
+
if (props.fontClass) classes.push(props.fontClass)
|
|
22
|
+
if (props.color) classes.push(`color-${props.color}`)
|
|
23
|
+
if (props.class) classes.push(props.class)
|
|
24
|
+
return classes.join(' ')
|
|
25
|
+
})
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<template>
|
|
29
|
+
<component
|
|
30
|
+
:is="props.tag"
|
|
31
|
+
data-lk-component="text"
|
|
32
|
+
:class="textClass"
|
|
33
|
+
v-bind="$attrs"
|
|
34
|
+
>
|
|
35
|
+
<slot />
|
|
36
|
+
</component>
|
|
37
|
+
</template>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { propsToDataAttrs } from '../utils/utilities'
|
|
4
|
+
import LkIcon from './LkIcon.vue'
|
|
5
|
+
import LkStateLayer from './LkStateLayer.vue'
|
|
6
|
+
import LkRow from './LkRow.vue'
|
|
7
|
+
import LkText from './LkText.vue'
|
|
8
|
+
|
|
9
|
+
export interface LkTextInputProps {
|
|
10
|
+
modelValue?: string
|
|
11
|
+
labelPosition?: 'default' | 'on-input'
|
|
12
|
+
helpText?: string
|
|
13
|
+
placeholder?: string
|
|
14
|
+
name?: string
|
|
15
|
+
endIcon?: string
|
|
16
|
+
labelBackgroundColor?: LkColor
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const props = withDefaults(defineProps<LkTextInputProps>(), {
|
|
20
|
+
modelValue: '',
|
|
21
|
+
labelPosition: 'default',
|
|
22
|
+
placeholder: 'Placeholder',
|
|
23
|
+
name: 'Label',
|
|
24
|
+
endIcon: 'search',
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const emit = defineEmits<{
|
|
28
|
+
'update:modelValue': [value: string]
|
|
29
|
+
}>()
|
|
30
|
+
|
|
31
|
+
defineOptions({
|
|
32
|
+
inheritAttrs: false,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const textInputAttrs = computed(() =>
|
|
36
|
+
propsToDataAttrs({ labelPosition: props.labelPosition }, 'text-input'),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
function onInput(event: Event) {
|
|
40
|
+
const target = event.target as HTMLInputElement
|
|
41
|
+
emit('update:modelValue', target.value)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const onInputLabelClass = computed(() => {
|
|
45
|
+
let cls = 'body'
|
|
46
|
+
if (props.labelBackgroundColor) {
|
|
47
|
+
cls += ` bg-${props.labelBackgroundColor}`
|
|
48
|
+
}
|
|
49
|
+
if (props.modelValue) {
|
|
50
|
+
cls += ' on-field-with-value-set'
|
|
51
|
+
}
|
|
52
|
+
return cls
|
|
53
|
+
})
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<template>
|
|
57
|
+
<div
|
|
58
|
+
data-lk-component="text-input"
|
|
59
|
+
v-bind="{ ...$attrs, ...textInputAttrs }"
|
|
60
|
+
>
|
|
61
|
+
<label
|
|
62
|
+
v-if="labelPosition === 'default'"
|
|
63
|
+
:for="name"
|
|
64
|
+
class="label"
|
|
65
|
+
>
|
|
66
|
+
{{ name }}
|
|
67
|
+
</label>
|
|
68
|
+
|
|
69
|
+
<div
|
|
70
|
+
data-lk-text-input-el="input-wrap"
|
|
71
|
+
:data-lk-input-help-text="helpText ? 'true' : 'false'"
|
|
72
|
+
:data-help-text="helpText"
|
|
73
|
+
>
|
|
74
|
+
<label
|
|
75
|
+
v-if="labelPosition === 'on-input'"
|
|
76
|
+
:for="name"
|
|
77
|
+
:class="onInputLabelClass"
|
|
78
|
+
>
|
|
79
|
+
{{ name }}
|
|
80
|
+
</label>
|
|
81
|
+
<input
|
|
82
|
+
type="text"
|
|
83
|
+
:name="name"
|
|
84
|
+
:id="name"
|
|
85
|
+
:placeholder="labelPosition !== 'on-input' ? placeholder : ''"
|
|
86
|
+
:value="modelValue"
|
|
87
|
+
@input="onInput"
|
|
88
|
+
/>
|
|
89
|
+
<LkStateLayer />
|
|
90
|
+
<LkIcon :name="endIcon" />
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<LkRow v-if="helpText" align-items="center">
|
|
94
|
+
<LkIcon
|
|
95
|
+
name="info"
|
|
96
|
+
font-class="capline"
|
|
97
|
+
color="outline"
|
|
98
|
+
:optic-shift="true"
|
|
99
|
+
/>
|
|
100
|
+
<LkText color="outline" font-class="caption" class="m-left-2xs">
|
|
101
|
+
Help text goes here
|
|
102
|
+
</LkText>
|
|
103
|
+
</LkRow>
|
|
104
|
+
</div>
|
|
105
|
+
</template>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { provideTheme, type PaletteState, type ColorModePreference } from '../composables'
|
|
4
|
+
|
|
5
|
+
export interface LkThemeProps {
|
|
6
|
+
/** Source/seed color to generate theme from (hex) */
|
|
7
|
+
sourceColor?: string
|
|
8
|
+
/** Color mode - 'auto' follows OS setting, 'light'/'dark' forces mode */
|
|
9
|
+
colorMode?: ColorModePreference
|
|
10
|
+
/** Custom initial palette overrides */
|
|
11
|
+
palette?: Partial<PaletteState>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const props = withDefaults(defineProps<LkThemeProps>(), {
|
|
15
|
+
sourceColor: undefined,
|
|
16
|
+
colorMode: 'auto',
|
|
17
|
+
palette: undefined,
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
// Build the initial palette from props
|
|
21
|
+
const initialPalette = computed<Partial<PaletteState>>(() => {
|
|
22
|
+
const pal: Partial<PaletteState> = {}
|
|
23
|
+
if (props.palette) {
|
|
24
|
+
Object.assign(pal, props.palette)
|
|
25
|
+
}
|
|
26
|
+
return pal
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
// Provide theme context to all children
|
|
30
|
+
const theme = provideTheme(initialPalette.value)
|
|
31
|
+
|
|
32
|
+
// Set the initial color mode preference
|
|
33
|
+
theme.setColorMode(props.colorMode)
|
|
34
|
+
|
|
35
|
+
// If sourceColor is provided, generate theme from it
|
|
36
|
+
if (props.sourceColor) {
|
|
37
|
+
theme.updateThemeFromMaster(props.sourceColor)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
defineExpose({
|
|
41
|
+
theme,
|
|
42
|
+
})
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<div class="lk-theme" v-bind="$attrs">
|
|
47
|
+
<slot />
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|