@finggujadhav/vue 0.9.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/package.json +32 -0
- package/src/Button.vue +74 -0
- package/src/Card.vue +56 -0
- package/src/Dropdown.vue +93 -0
- package/src/Input.vue +32 -0
- package/src/Modal.vue +79 -0
- package/src/Tabs.ts +87 -0
- package/src/composable.ts +44 -0
- package/src/index.ts +10 -0
- package/src/plugin.ts +42 -0
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@finggujadhav/vue",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Vue adapter for FingguFlux UI library",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "src/index.ts",
|
|
7
|
+
"types": "src/index.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "echo 'SFCs do not require pre-build for this release'"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"src"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./src/index.ts",
|
|
18
|
+
"import": "./src/index.ts"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@finggujadhav/core": "0.9.0",
|
|
23
|
+
"@finggujadhav/js-helper": "0.9.0"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"vue": ">=3.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"vue": "^3.0.0",
|
|
30
|
+
"typescript": "^5.0.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/Button.vue
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<button :class="ffClasses" v-bind="$attrs">
|
|
3
|
+
<slot />
|
|
4
|
+
</button>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { defineComponent, computed, PropType } from 'vue';
|
|
9
|
+
import { useFinggu } from './composable';
|
|
10
|
+
|
|
11
|
+
const VARIANTS = {
|
|
12
|
+
primary: 'ff-btn-primary',
|
|
13
|
+
secondary: 'ff-btn-secondary',
|
|
14
|
+
ghost: 'ff-btn-ghost',
|
|
15
|
+
outline: 'ff-btn-outline'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const SIZES = {
|
|
19
|
+
sm: 'ff-btn-sm',
|
|
20
|
+
md: 'ff-btn-md',
|
|
21
|
+
lg: 'ff-btn-lg'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const MOTIONS = {
|
|
25
|
+
fade: 'ff-fade-in',
|
|
26
|
+
'slide-up': 'ff-slide-up',
|
|
27
|
+
'scale-in': 'ff-scale-in',
|
|
28
|
+
lift: 'ff-hover-lift'
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const __ffClasses_Button = [
|
|
32
|
+
'ff-btn',
|
|
33
|
+
...Object.values(VARIANTS),
|
|
34
|
+
...Object.values(SIZES),
|
|
35
|
+
...Object.values(MOTIONS),
|
|
36
|
+
'ff-card-glass'
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
export default defineComponent({
|
|
40
|
+
name: 'FingguButton',
|
|
41
|
+
inheritAttrs: false,
|
|
42
|
+
props: {
|
|
43
|
+
variant: {
|
|
44
|
+
type: String as PropType<keyof typeof VARIANTS>,
|
|
45
|
+
default: 'primary'
|
|
46
|
+
},
|
|
47
|
+
size: {
|
|
48
|
+
type: String as PropType<keyof typeof SIZES>,
|
|
49
|
+
default: 'md'
|
|
50
|
+
},
|
|
51
|
+
motion: {
|
|
52
|
+
type: String as PropType<keyof typeof MOTIONS>,
|
|
53
|
+
default: undefined
|
|
54
|
+
},
|
|
55
|
+
glass: {
|
|
56
|
+
type: Boolean,
|
|
57
|
+
default: false
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
setup(props) {
|
|
61
|
+
const { resolveAll } = useFinggu();
|
|
62
|
+
|
|
63
|
+
const ffClasses = computed(() => resolveAll([
|
|
64
|
+
'ff-btn',
|
|
65
|
+
VARIANTS[props.variant],
|
|
66
|
+
SIZES[props.size],
|
|
67
|
+
props.glass && 'ff-card-glass',
|
|
68
|
+
props.motion && MOTIONS[props.motion]
|
|
69
|
+
]));
|
|
70
|
+
|
|
71
|
+
return { ffClasses };
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
</script>
|
package/src/Card.vue
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="ffClasses" v-bind="$attrs">
|
|
3
|
+
<slot />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { defineComponent, computed, PropType } from 'vue';
|
|
9
|
+
import { useFinggu } from './composable';
|
|
10
|
+
|
|
11
|
+
const VARIANTS = {
|
|
12
|
+
outline: 'ff-card-outline',
|
|
13
|
+
glass: 'ff-card-glass'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const PADDINGS = {
|
|
17
|
+
none: 'ff-p-0',
|
|
18
|
+
sm: 'ff-p-2',
|
|
19
|
+
md: 'ff-p-4',
|
|
20
|
+
lg: 'ff-p-8'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const __ffClasses_Card = [
|
|
24
|
+
'ff-card',
|
|
25
|
+
'ff-card-header',
|
|
26
|
+
'ff-card-body',
|
|
27
|
+
...Object.values(VARIANTS),
|
|
28
|
+
...Object.values(PADDINGS)
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export default defineComponent({
|
|
32
|
+
name: 'FingguCard',
|
|
33
|
+
inheritAttrs: false,
|
|
34
|
+
props: {
|
|
35
|
+
variant: {
|
|
36
|
+
type: String as PropType<keyof typeof VARIANTS>,
|
|
37
|
+
default: undefined
|
|
38
|
+
},
|
|
39
|
+
padding: {
|
|
40
|
+
type: String as PropType<keyof typeof PADDINGS>,
|
|
41
|
+
default: 'md'
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
setup(props) {
|
|
45
|
+
const { resolveAll } = useFinggu();
|
|
46
|
+
|
|
47
|
+
const ffClasses = computed(() => resolveAll([
|
|
48
|
+
'ff-card',
|
|
49
|
+
props.variant && VARIANTS[props.variant],
|
|
50
|
+
PADDINGS[props.padding]
|
|
51
|
+
]));
|
|
52
|
+
|
|
53
|
+
return { ffClasses };
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
</script>
|
package/src/Dropdown.vue
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :class="ffContainerClasses" ref="containerRef">
|
|
3
|
+
<button
|
|
4
|
+
type="button"
|
|
5
|
+
:class="ffTriggerClasses"
|
|
6
|
+
@click="toggle"
|
|
7
|
+
aria-haspopup="true"
|
|
8
|
+
:aria-expanded="isOpen"
|
|
9
|
+
>
|
|
10
|
+
<slot name="trigger" />
|
|
11
|
+
</button>
|
|
12
|
+
<div
|
|
13
|
+
:class="ffMenuClasses"
|
|
14
|
+
:data-ff-state="isOpen ? 'open' : 'closed'"
|
|
15
|
+
role="menu"
|
|
16
|
+
:aria-hidden="!isOpen"
|
|
17
|
+
>
|
|
18
|
+
<slot />
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script lang="ts">
|
|
24
|
+
import { defineComponent, ref, onMounted, onUnmounted, computed, PropType } from 'vue';
|
|
25
|
+
import { useFinggu } from './composable';
|
|
26
|
+
|
|
27
|
+
export const __ffClasses_Dropdown = [
|
|
28
|
+
'ff-dropdown',
|
|
29
|
+
'ff-dropdown-trigger',
|
|
30
|
+
'ff-dropdown-menu',
|
|
31
|
+
'ff-dropdown-menu-right',
|
|
32
|
+
'ff-dropdown-item'
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
export default defineComponent({
|
|
36
|
+
name: 'FingguDropdown',
|
|
37
|
+
props: {
|
|
38
|
+
align: {
|
|
39
|
+
type: String as PropType<'left' | 'right'>,
|
|
40
|
+
default: 'left'
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
setup(props) {
|
|
44
|
+
const { resolveAll } = useFinggu();
|
|
45
|
+
const isOpen = ref(false);
|
|
46
|
+
const containerRef = ref<HTMLElement | null>(null);
|
|
47
|
+
|
|
48
|
+
const toggle = () => { isOpen.value = !isOpen.value; };
|
|
49
|
+
const close = () => { isOpen.value = false; };
|
|
50
|
+
|
|
51
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
52
|
+
if (containerRef.value && !containerRef.value.contains(event.target as Node)) {
|
|
53
|
+
close();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
onMounted(() => {
|
|
58
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
onUnmounted(() => {
|
|
62
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const ffContainerClasses = computed(() => resolveAll(['ff-dropdown']));
|
|
66
|
+
const ffTriggerClasses = computed(() => resolveAll(['ff-dropdown-trigger']));
|
|
67
|
+
const ffMenuClasses = computed(() => resolveAll([
|
|
68
|
+
'ff-dropdown-menu',
|
|
69
|
+
props.align === 'right' && 'ff-dropdown-menu-right'
|
|
70
|
+
]));
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
isOpen,
|
|
74
|
+
containerRef,
|
|
75
|
+
toggle,
|
|
76
|
+
ffContainerClasses,
|
|
77
|
+
ffTriggerClasses,
|
|
78
|
+
ffMenuClasses
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// DropdownItem as a simple functional-like component
|
|
84
|
+
export const DropdownItem = defineComponent({
|
|
85
|
+
name: 'FingguDropdownItem',
|
|
86
|
+
setup(_, { slots, attrs }) {
|
|
87
|
+
const { resolveAll } = useFinggu();
|
|
88
|
+
const ffClasses = computed(() => resolveAll(['ff-dropdown-item', attrs.class as string]));
|
|
89
|
+
return () => h('div', { ...attrs, class: ffClasses.value }, slots.default?.());
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
import { h } from 'vue';
|
|
93
|
+
</script>
|
package/src/Input.vue
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<input :class="ffClasses" v-bind="$attrs" />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script lang="ts">
|
|
6
|
+
import { defineComponent, computed } from 'vue';
|
|
7
|
+
import { useFinggu } from './composable';
|
|
8
|
+
|
|
9
|
+
export const __ffClasses_Input = [
|
|
10
|
+
'ff-input',
|
|
11
|
+
'ff-input-error'
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export default defineComponent({
|
|
15
|
+
name: 'FingguInput',
|
|
16
|
+
inheritAttrs: false,
|
|
17
|
+
props: {
|
|
18
|
+
error: {
|
|
19
|
+
type: Boolean,
|
|
20
|
+
default: false
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
setup(props) {
|
|
24
|
+
const { resolveAll } = useFinggu();
|
|
25
|
+
const ffClasses = computed(() => resolveAll([
|
|
26
|
+
'ff-input',
|
|
27
|
+
props.error && 'ff-input-error'
|
|
28
|
+
]));
|
|
29
|
+
return { ffClasses };
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
</script>
|
package/src/Modal.vue
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<teleport to="body" v-if="mounted">
|
|
3
|
+
<div
|
|
4
|
+
v-show="isOpen || animating"
|
|
5
|
+
:class="ffContainerClasses"
|
|
6
|
+
aria-hidden="!isOpen"
|
|
7
|
+
>
|
|
8
|
+
<div class="ff-modal-overlay" @click="$emit('close')" />
|
|
9
|
+
<div :class="ffContentClasses">
|
|
10
|
+
<slot />
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</teleport>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script lang="ts">
|
|
17
|
+
import { defineComponent, ref, watch, onMounted, onUnmounted, computed } from 'vue';
|
|
18
|
+
import { useFinggu } from './composable';
|
|
19
|
+
|
|
20
|
+
export const __ffClasses_Modal = [
|
|
21
|
+
'ff-modal',
|
|
22
|
+
'ff-modal-open',
|
|
23
|
+
'ff-modal-closed',
|
|
24
|
+
'ff-modal-overlay',
|
|
25
|
+
'ff-modal-content'
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export default defineComponent({
|
|
29
|
+
name: 'FingguModal',
|
|
30
|
+
props: {
|
|
31
|
+
isOpen: {
|
|
32
|
+
type: Boolean,
|
|
33
|
+
required: true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
emits: ['close'],
|
|
37
|
+
setup(props) {
|
|
38
|
+
const { resolveAll } = useFinggu();
|
|
39
|
+
const mounted = ref(false);
|
|
40
|
+
const animating = ref(false);
|
|
41
|
+
|
|
42
|
+
onMounted(() => {
|
|
43
|
+
mounted.value = true;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
watch(() => props.isOpen, (val) => {
|
|
47
|
+
if (val) {
|
|
48
|
+
document.body.style.overflow = 'hidden';
|
|
49
|
+
animating.value = true;
|
|
50
|
+
} else {
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
animating.value = false;
|
|
53
|
+
document.body.style.overflow = '';
|
|
54
|
+
}, 300); // Exit animation duration
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
onUnmounted(() => {
|
|
59
|
+
document.body.style.overflow = '';
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const ffContainerClasses = computed(() => resolveAll([
|
|
63
|
+
'ff-modal',
|
|
64
|
+
props.isOpen ? 'ff-modal-open' : 'ff-modal-closed'
|
|
65
|
+
]));
|
|
66
|
+
|
|
67
|
+
const ffContentClasses = computed(() => resolveAll([
|
|
68
|
+
'ff-modal-content'
|
|
69
|
+
]));
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
mounted,
|
|
73
|
+
animating,
|
|
74
|
+
ffContainerClasses,
|
|
75
|
+
ffContentClasses
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
</script>
|
package/src/Tabs.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<script lang="ts" >
|
|
2
|
+
import { defineComponent, h, provide, ref, InjectionKey, Ref, PropType } from 'vue';
|
|
3
|
+
import { useFinggu } from './composable';
|
|
4
|
+
|
|
5
|
+
export const __ffClasses_Tabs = [
|
|
6
|
+
'ff-tabs',
|
|
7
|
+
'ff-tab-list',
|
|
8
|
+
'ff-tab',
|
|
9
|
+
'ff-tab-active',
|
|
10
|
+
'ff-tab-content'
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
interface TabsContext {
|
|
14
|
+
activeTab: Ref<string>;
|
|
15
|
+
setActiveTab: (value: string) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const TabsSymbol: InjectionKey<TabsContext> = Symbol('FingguTabs');
|
|
19
|
+
|
|
20
|
+
export const Tabs = defineComponent({
|
|
21
|
+
name: 'FingguTabs',
|
|
22
|
+
props: {
|
|
23
|
+
defaultValue: {
|
|
24
|
+
type: String,
|
|
25
|
+
required: true
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
setup(props, { slots }) {
|
|
29
|
+
const activeTab = ref(props.defaultValue);
|
|
30
|
+
const setActiveTab = (value: string) => { activeTab.value = value; };
|
|
31
|
+
|
|
32
|
+
provide(TabsSymbol, { activeTab, setActiveTab });
|
|
33
|
+
|
|
34
|
+
return () => h('div', { class: 'ff-tabs' }, slots.default?.());
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const TabList = defineComponent({
|
|
39
|
+
name: 'FingguTabList',
|
|
40
|
+
setup(_, { slots }) {
|
|
41
|
+
return () => h('div', { class: 'ff-tab-list', role: 'tablist' }, slots.default?.());
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export const TabTrigger = defineComponent({
|
|
46
|
+
name: 'FingguTabTrigger',
|
|
47
|
+
props: {
|
|
48
|
+
value: {
|
|
49
|
+
type: String,
|
|
50
|
+
required: true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
setup(props, { slots }) {
|
|
54
|
+
const context = inject(TabsSymbol);
|
|
55
|
+
const { resolveAll } = useFinggu();
|
|
56
|
+
|
|
57
|
+
return () => {
|
|
58
|
+
const isActive = context?.activeTab.value === props.value;
|
|
59
|
+
return h('button', {
|
|
60
|
+
role: 'tab',
|
|
61
|
+
'aria-selected': isActive,
|
|
62
|
+
class: resolveAll(['ff-tab', isActive && 'ff-tab-active']),
|
|
63
|
+
onClick: () => context?.setActiveTab(props.value)
|
|
64
|
+
}, slots.default?.());
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export const TabContent = defineComponent({
|
|
70
|
+
name: 'FingguTabContent',
|
|
71
|
+
props: {
|
|
72
|
+
value: {
|
|
73
|
+
type: String,
|
|
74
|
+
required: true
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
setup(props, { slots }) {
|
|
78
|
+
const context = inject(TabsSymbol);
|
|
79
|
+
return () => (context?.activeTab.value === props.value)
|
|
80
|
+
? h('div', { class: 'ff-tab-content' }, slots.default?.())
|
|
81
|
+
: null;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// For SFC imports
|
|
86
|
+
import { inject } from 'vue';
|
|
87
|
+
export default Tabs;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { inject } from 'vue';
|
|
2
|
+
import { FingguSymbol, FingguOptions } from './plugin';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* useFinggu composable to resolve FingguFlux classes.
|
|
6
|
+
*/
|
|
7
|
+
export function useFinggu() {
|
|
8
|
+
const finggu = inject<FingguOptions>(FingguSymbol, {
|
|
9
|
+
mapping: null,
|
|
10
|
+
mode: 'dev'
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const resolve = (className: string): string => {
|
|
14
|
+
const { mapping, mode } = finggu;
|
|
15
|
+
if (mode === 'dev' || !mapping) return className;
|
|
16
|
+
|
|
17
|
+
const mapped = mapping[className];
|
|
18
|
+
if (mode === 'ext' && !mapped && className.startsWith('ff-')) {
|
|
19
|
+
const errorMsg = `[FingguFlux] Critical: Class '${className}' not found in mapping.json in Extreme mode. This will cause broken styles in production.`;
|
|
20
|
+
// @ts-ignore - support vite/nuxt environments
|
|
21
|
+
const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV === 'development' : (import.meta as any).env?.DEV;
|
|
22
|
+
|
|
23
|
+
if (isDev) {
|
|
24
|
+
throw new Error(errorMsg);
|
|
25
|
+
} else {
|
|
26
|
+
console.error(errorMsg);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return mapped || className;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const resolveAll = (classes: (string | undefined | null | false)[]): string => {
|
|
33
|
+
return classes
|
|
34
|
+
.filter(Boolean)
|
|
35
|
+
.map(c => resolve(c as string))
|
|
36
|
+
.join(' ');
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
resolve,
|
|
41
|
+
resolveAll,
|
|
42
|
+
mode: finggu.mode
|
|
43
|
+
};
|
|
44
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './plugin';
|
|
2
|
+
export * from './composable';
|
|
3
|
+
|
|
4
|
+
// Components
|
|
5
|
+
export { default as Button, __ffClasses_Button } from './Button.vue';
|
|
6
|
+
export { default as Card, __ffClasses_Card } from './Card.vue';
|
|
7
|
+
export { default as Input, __ffClasses_Input } from './Input.vue';
|
|
8
|
+
export { default as Modal, __ffClasses_Modal } from './Modal.vue';
|
|
9
|
+
export { Tabs, TabList, TabTrigger, TabContent, __ffClasses_Tabs } from './Tabs';
|
|
10
|
+
export { default as Dropdown, __ffClasses_Dropdown, DropdownItem } from './Dropdown.vue';
|
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { InjectionKey, App, reactive, watch } from 'vue';
|
|
2
|
+
import { setTheme, FingguTheme } from '@finggujadhav/js-helper';
|
|
3
|
+
|
|
4
|
+
export interface FingguMapping {
|
|
5
|
+
_version?: string;
|
|
6
|
+
[key: string]: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface FingguOptions {
|
|
10
|
+
mapping?: FingguMapping;
|
|
11
|
+
mode?: 'dev' | 'opt' | 'ext';
|
|
12
|
+
version?: string;
|
|
13
|
+
theme?: FingguTheme;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const FingguSymbol: InjectionKey<FingguOptions> = Symbol('FingguFlux');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* FingguFlux Vue Plugin
|
|
20
|
+
* Installs mapping, mode, and theme via provide/inject.
|
|
21
|
+
*/
|
|
22
|
+
export const FingguPlugin = {
|
|
23
|
+
install(app: App, options: FingguOptions = {}) {
|
|
24
|
+
const state = reactive({
|
|
25
|
+
mapping: options.mapping || null,
|
|
26
|
+
mode: options.mode || 'dev',
|
|
27
|
+
version: options.version,
|
|
28
|
+
theme: options.theme || 'system'
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (state.mapping && state.version && state.mapping._version && state.mapping._version !== state.version) {
|
|
32
|
+
console.warn(`[FingguFlux] Version Mismatch: mapping.json (${state.mapping._version}) does not match expected CSS version (${state.version})`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Global theme application (optional, can be scoped)
|
|
36
|
+
watch(() => state.theme, (newTheme) => {
|
|
37
|
+
setTheme(newTheme as FingguTheme);
|
|
38
|
+
}, { immediate: true });
|
|
39
|
+
|
|
40
|
+
app.provide(FingguSymbol, state);
|
|
41
|
+
}
|
|
42
|
+
};
|