@astrake/lumora-ui 0.2.0 → 0.2.2
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/CHANGELOG.md +44 -1
- package/dist/LuCodeBlock.vue_vue_type_script_setup_true_lang-BdXflBkJ.js +1672 -0
- package/dist/LuEmbeddedStatusBar.vue_vue_type_script_setup_true_lang-D4rqklgo.js +218 -0
- package/dist/LuOverlay.vue_vue_type_script_setup_true_lang-C5jhqCgy.js +221 -0
- package/dist/components/LuAlert.vue.d.ts +20 -0
- package/dist/components/LuAvatar.vue.d.ts +19 -0
- package/dist/components/LuBadge.vue.d.ts +16 -0
- package/dist/components/LuBreadcrumb.vue.d.ts +16 -0
- package/dist/components/LuButton.vue.d.ts +24 -0
- package/dist/components/LuCard.vue.d.ts +18 -0
- package/dist/components/LuCheckbox.vue.d.ts +27 -0
- package/dist/components/LuCodeBlock.vue.d.ts +26 -0
- package/dist/components/LuCollapsible.vue.d.ts +25 -0
- package/dist/components/LuDivider.vue.d.ts +8 -0
- package/dist/components/LuForm.types.d.ts +18 -0
- package/dist/components/LuForm.vue.d.ts +55 -0
- package/dist/components/LuIcon.vue.d.ts +18 -0
- package/dist/components/LuInput.vue.d.ts +26 -0
- package/dist/components/LuLink.vue.d.ts +23 -0
- package/dist/components/LuMenu.vue.d.ts +26 -0
- package/dist/components/LuMenuItem.vue.d.ts +20 -0
- package/dist/components/LuModal.vue.d.ts +32 -0
- package/dist/components/LuPageHeader.vue.d.ts +10 -0
- package/dist/components/LuPagination.vue.d.ts +18 -0
- package/dist/components/LuProgressBar.vue.d.ts +7 -0
- package/dist/components/LuRadio.vue.d.ts +18 -0
- package/dist/components/LuRadioGroup.types.d.ts +8 -0
- package/dist/components/LuRadioGroup.vue.d.ts +24 -0
- package/dist/components/LuSelect.vue.d.ts +18 -0
- package/dist/components/LuSkeleton.vue.d.ts +5 -0
- package/dist/components/LuSpinner.vue.d.ts +5 -0
- package/dist/components/LuSwitch.vue.d.ts +15 -0
- package/dist/components/LuTab.vue.d.ts +16 -0
- package/dist/components/LuTabList.vue.d.ts +15 -0
- package/dist/components/LuTabPanel.vue.d.ts +16 -0
- package/dist/components/LuTable.vue.d.ts +15 -0
- package/dist/components/LuTableBody.vue.d.ts +15 -0
- package/dist/components/LuTableCell.vue.d.ts +15 -0
- package/dist/components/LuTableHead.vue.d.ts +15 -0
- package/dist/components/LuTableHeadCell.vue.d.ts +15 -0
- package/dist/components/LuTableRow.vue.d.ts +15 -0
- package/dist/components/LuTabs.vue.d.ts +20 -0
- package/dist/components/LuTag.vue.d.ts +20 -0
- package/dist/components/LuText.vue.d.ts +16 -0
- package/dist/components/LuTextarea.vue.d.ts +14 -0
- package/dist/components/LuThemeSelect.vue.d.ts +2 -0
- package/dist/components/LuThemeSwitch.vue.d.ts +2 -0
- package/dist/components/LuToggleButton.vue.d.ts +16 -0
- package/dist/components/LuToggleGroup.vue.d.ts +20 -0
- package/dist/components/LuTooltip.vue.d.ts +19 -0
- package/dist/components/__tests__/LuForm.test.d.ts +1 -0
- package/dist/components/_all.d.ts +3 -0
- package/dist/components/index.js +47 -0
- package/{src/composables/index.ts → dist/composables/index.d.ts} +1 -1
- package/dist/composables/index.js +31 -0
- package/dist/composables/useRail.d.ts +6 -0
- package/dist/composables/useShiki.d.ts +2 -0
- package/dist/composables/useSplit.d.ts +4 -0
- package/dist/composables/useTheme.d.ts +7 -0
- package/dist/context-CGS7Ou_x.js +36 -0
- package/dist/context.d.ts +8 -0
- package/{src/index.ts → dist/index.d.ts} +0 -1
- package/dist/index.js +166 -0
- package/dist/layout/LuDock.vue.d.ts +9 -0
- package/dist/layout/LuDockItem.vue.d.ts +16 -0
- package/dist/layout/LuFill.vue.d.ts +18 -0
- package/dist/layout/LuFixed.vue.d.ts +18 -0
- package/dist/layout/LuGrid.vue.d.ts +22 -0
- package/dist/layout/LuOverlay.vue.d.ts +15 -0
- package/dist/layout/LuScroll.vue.d.ts +15 -0
- package/dist/layout/LuSplit.vue.d.ts +16 -0
- package/dist/layout/LuSplitPane.vue.d.ts +18 -0
- package/dist/layout/LuSplitResizer.vue.d.ts +5 -0
- package/dist/layout/LuStack.vue.d.ts +25 -0
- package/{src/layout/index.ts → dist/layout/index.d.ts} +1 -14
- package/dist/layout/index.js +14 -0
- package/dist/plugin.d.ts +6 -0
- package/dist/shell/desktop/LuDesktopRailBar.vue.d.ts +17 -0
- package/dist/shell/desktop/LuDesktopRailItem.vue.d.ts +18 -0
- package/dist/shell/desktop/LuDesktopShell.vue.d.ts +23 -0
- package/dist/shell/desktop/LuDesktopSidebar.vue.d.ts +21 -0
- package/dist/shell/desktop/LuDesktopStatusBar.vue.d.ts +15 -0
- package/dist/shell/desktop/LuDesktopTopBar.vue.d.ts +15 -0
- package/dist/shell/embedded/LuEmbeddedShell.vue.d.ts +19 -0
- package/dist/shell/embedded/LuEmbeddedStatusBar.vue.d.ts +17 -0
- package/dist/shell/embedded/LuEmbeddedTopBar.vue.d.ts +19 -0
- package/{src/shell/index.ts → dist/shell/index.d.ts} +0 -1
- package/dist/shell/index.js +15 -0
- package/dist/shell/mobile/LuMobileHeader.vue.d.ts +19 -0
- package/dist/shell/mobile/LuMobileNavBar.vue.d.ts +15 -0
- package/dist/shell/mobile/LuMobileShell.vue.d.ts +21 -0
- package/dist/skins/components.d.ts +2 -0
- package/dist/skins/default.d.ts +2 -0
- package/dist/skins/index.js +446 -0
- package/dist/skins/layout.d.ts +2 -0
- package/dist/skins/shell/desktop.d.ts +2 -0
- package/dist/skins/shell/embedded.d.ts +2 -0
- package/dist/skins/shell/mobile.d.ts +2 -0
- package/dist/tailwind.d.ts +1 -0
- package/dist/tailwind.js +13 -0
- package/dist/types.d.ts +15 -0
- package/dist/useShiki-DPOJfneq.js +30 -0
- package/dist/utils.d.ts +10 -0
- package/package.json +37 -12
- package/src/lumora.css +32 -0
- package/src/components/LuAlert.vue +0 -33
- package/src/components/LuAvatar.vue +0 -22
- package/src/components/LuBadge.vue +0 -15
- package/src/components/LuBreadcrumb.vue +0 -63
- package/src/components/LuButton.vue +0 -58
- package/src/components/LuCard.vue +0 -27
- package/src/components/LuCheckbox.vue +0 -94
- package/src/components/LuCodeBlock.vue +0 -168
- package/src/components/LuCollapsible.vue +0 -34
- package/src/components/LuDivider.vue +0 -18
- package/src/components/LuForm.types.ts +0 -24
- package/src/components/LuForm.vue +0 -121
- package/src/components/LuIcon.vue +0 -39
- package/src/components/LuInput.vue +0 -82
- package/src/components/LuLink.vue +0 -47
- package/src/components/LuMenu.vue +0 -86
- package/src/components/LuMenuItem.vue +0 -37
- package/src/components/LuModal.vue +0 -115
- package/src/components/LuPageHeader.vue +0 -24
- package/src/components/LuPagination.vue +0 -118
- package/src/components/LuProgressBar.vue +0 -21
- package/src/components/LuRadio.vue +0 -55
- package/src/components/LuRadioGroup.types.ts +0 -10
- package/src/components/LuRadioGroup.vue +0 -66
- package/src/components/LuSelect.vue +0 -67
- package/src/components/LuSkeleton.vue +0 -15
- package/src/components/LuSpinner.vue +0 -36
- package/src/components/LuSwitch.vue +0 -76
- package/src/components/LuTab.vue +0 -26
- package/src/components/LuTabList.vue +0 -15
- package/src/components/LuTabPanel.vue +0 -19
- package/src/components/LuTable.vue +0 -15
- package/src/components/LuTableBody.vue +0 -15
- package/src/components/LuTableCell.vue +0 -15
- package/src/components/LuTableHead.vue +0 -15
- package/src/components/LuTableHeadCell.vue +0 -15
- package/src/components/LuTableRow.vue +0 -15
- package/src/components/LuTabs.vue +0 -30
- package/src/components/LuTag.vue +0 -35
- package/src/components/LuText.vue +0 -18
- package/src/components/LuTextarea.vue +0 -62
- package/src/components/LuThemeSelect.vue +0 -26
- package/src/components/LuThemeSwitch.vue +0 -22
- package/src/components/LuToggleButton.vue +0 -35
- package/src/components/LuToggleGroup.vue +0 -27
- package/src/components/LuTooltip.vue +0 -36
- package/src/components/__tests__/LuForm.test.ts +0 -206
- package/src/composables/useRail.ts +0 -24
- package/src/composables/useSplit.ts +0 -17
- package/src/composables/useTheme.ts +0 -36
- package/src/context.ts +0 -39
- package/src/layout/LuDock.vue +0 -56
- package/src/layout/LuDockItem.vue +0 -20
- package/src/layout/LuFill.vue +0 -27
- package/src/layout/LuFixed.vue +0 -27
- package/src/layout/LuGrid.vue +0 -45
- package/src/layout/LuOverlay.vue +0 -17
- package/src/layout/LuScroll.vue +0 -19
- package/src/layout/LuSplit.vue +0 -23
- package/src/layout/LuSplitPane.vue +0 -32
- package/src/layout/LuSplitResizer.vue +0 -19
- package/src/layout/LuStack.vue +0 -29
- package/src/plugin.ts +0 -28
- package/src/shell/desktop/LuDesktopRailBar.vue +0 -23
- package/src/shell/desktop/LuDesktopRailItem.vue +0 -23
- package/src/shell/desktop/LuDesktopShell.vue +0 -25
- package/src/shell/desktop/LuDesktopSidebar.vue +0 -36
- package/src/shell/desktop/LuDesktopStatusBar.vue +0 -15
- package/src/shell/desktop/LuDesktopTopBar.vue +0 -15
- package/src/shell/embedded/LuEmbeddedShell.vue +0 -20
- package/src/shell/embedded/LuEmbeddedStatusBar.vue +0 -16
- package/src/shell/embedded/LuEmbeddedTopBar.vue +0 -17
- package/src/shell/mobile/LuMobileHeader.vue +0 -17
- package/src/shell/mobile/LuMobileNavBar.vue +0 -15
- package/src/shell/mobile/LuMobileShell.vue +0 -21
- package/src/skins/default.ts +0 -426
- package/src/tailwind.ts +0 -25
- package/src/types.ts +0 -18
- package/src/utils.ts +0 -95
- package/tsconfig.json +0 -10
- /package/{src/components/index.ts → dist/components/index.d.ts} +0 -0
- /package/{src/skins/index.ts → dist/skins/index.d.ts} +0 -0
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<table v-bind="$attrs" :class="resolvedSkin">
|
|
3
|
-
<slot />
|
|
4
|
-
</table>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue";
|
|
9
|
-
import { useLumoraConfig } from "../context";
|
|
10
|
-
|
|
11
|
-
const props = defineProps<{ variant?: string }>();
|
|
12
|
-
|
|
13
|
-
const { resolveSkin } = useLumoraConfig();
|
|
14
|
-
const resolvedSkin = computed(() => resolveSkin("LuTable", props.variant));
|
|
15
|
-
</script>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<tbody v-bind="$attrs" :class="resolvedSkin">
|
|
3
|
-
<slot />
|
|
4
|
-
</tbody>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue";
|
|
9
|
-
import { useLumoraConfig } from "../context";
|
|
10
|
-
|
|
11
|
-
const props = defineProps<{ variant?: string }>();
|
|
12
|
-
|
|
13
|
-
const { resolveSkin } = useLumoraConfig();
|
|
14
|
-
const resolvedSkin = computed(() => resolveSkin("LuTableBody", props.variant));
|
|
15
|
-
</script>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<td v-bind="$attrs" :class="resolvedSkin">
|
|
3
|
-
<slot />
|
|
4
|
-
</td>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue";
|
|
9
|
-
import { useLumoraConfig } from "../context";
|
|
10
|
-
|
|
11
|
-
const props = defineProps<{ variant?: string }>();
|
|
12
|
-
|
|
13
|
-
const { resolveSkin } = useLumoraConfig();
|
|
14
|
-
const resolvedSkin = computed(() => resolveSkin("LuTableCell", props.variant));
|
|
15
|
-
</script>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<thead v-bind="$attrs" :class="resolvedSkin">
|
|
3
|
-
<slot />
|
|
4
|
-
</thead>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue";
|
|
9
|
-
import { useLumoraConfig } from "../context";
|
|
10
|
-
|
|
11
|
-
const props = defineProps<{ variant?: string }>();
|
|
12
|
-
|
|
13
|
-
const { resolveSkin } = useLumoraConfig();
|
|
14
|
-
const resolvedSkin = computed(() => resolveSkin("LuTableHead", props.variant));
|
|
15
|
-
</script>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<th v-bind="$attrs" :class="resolvedSkin">
|
|
3
|
-
<slot />
|
|
4
|
-
</th>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue";
|
|
9
|
-
import { useLumoraConfig } from "../context";
|
|
10
|
-
|
|
11
|
-
const props = defineProps<{ variant?: string }>();
|
|
12
|
-
|
|
13
|
-
const { resolveSkin } = useLumoraConfig();
|
|
14
|
-
const resolvedSkin = computed(() => resolveSkin("LuTableHeadCell", props.variant));
|
|
15
|
-
</script>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<tr v-bind="$attrs" :class="resolvedSkin">
|
|
3
|
-
<slot />
|
|
4
|
-
</tr>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue";
|
|
9
|
-
import { useLumoraConfig } from "../context";
|
|
10
|
-
|
|
11
|
-
const props = defineProps<{ variant?: string }>();
|
|
12
|
-
|
|
13
|
-
const { resolveSkin } = useLumoraConfig();
|
|
14
|
-
const resolvedSkin = computed(() => resolveSkin("LuTableRow", props.variant));
|
|
15
|
-
</script>
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div v-bind="$attrs" :class="resolvedSkin">
|
|
3
|
-
<slot />
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed, provide, ref, watch } from "vue";
|
|
9
|
-
import { useLumoraConfig } from "../context";
|
|
10
|
-
|
|
11
|
-
const props = defineProps<{
|
|
12
|
-
variant?: string;
|
|
13
|
-
modelValue?: string | number;
|
|
14
|
-
}>();
|
|
15
|
-
|
|
16
|
-
const emit = defineEmits<{
|
|
17
|
-
(e: "update:modelValue", value: string | number): void;
|
|
18
|
-
}>();
|
|
19
|
-
|
|
20
|
-
const activeTab = ref(props.modelValue);
|
|
21
|
-
watch(() => props.modelValue, (val) => activeTab.value = val);
|
|
22
|
-
watch(activeTab, (val) => {
|
|
23
|
-
if (val !== undefined) emit("update:modelValue", val);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
provide("lu-tabs-active", activeTab);
|
|
27
|
-
|
|
28
|
-
const { resolveSkin } = useLumoraConfig();
|
|
29
|
-
const resolvedSkin = computed(() => resolveSkin("LuTabs", props.variant));
|
|
30
|
-
</script>
|
package/src/components/LuTag.vue
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<span :class="resolvedSkin">
|
|
3
|
-
<slot />
|
|
4
|
-
<button
|
|
5
|
-
v-if="closable"
|
|
6
|
-
type="button"
|
|
7
|
-
:class="resolvedCloseButtonSkin"
|
|
8
|
-
@click.stop="emit('close')"
|
|
9
|
-
aria-label="Remove"
|
|
10
|
-
>
|
|
11
|
-
<LuIcon name="x" :class="resolvedIconSkin" />
|
|
12
|
-
</button>
|
|
13
|
-
</span>
|
|
14
|
-
</template>
|
|
15
|
-
|
|
16
|
-
<script setup lang="ts">
|
|
17
|
-
import { computed } from "vue";
|
|
18
|
-
import { useLumoraConfig } from "../context";
|
|
19
|
-
import LuIcon from "./LuIcon.vue";
|
|
20
|
-
|
|
21
|
-
const props = defineProps<{
|
|
22
|
-
variant?: string;
|
|
23
|
-
closable?: boolean;
|
|
24
|
-
}>();
|
|
25
|
-
|
|
26
|
-
const emit = defineEmits<{
|
|
27
|
-
(e: "close"): void;
|
|
28
|
-
}>();
|
|
29
|
-
|
|
30
|
-
const { resolveSkin } = useLumoraConfig();
|
|
31
|
-
|
|
32
|
-
const resolvedSkin = computed(() => resolveSkin("LuTag", props.variant));
|
|
33
|
-
const resolvedCloseButtonSkin = computed(() => resolveSkin("LuTagCloseButton", props.variant));
|
|
34
|
-
const resolvedIconSkin = computed(() => resolveSkin("LuTagIcon", props.variant));
|
|
35
|
-
</script>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<component :is="as ?? 'span'" v-bind="$attrs" :class="resolvedSkin">
|
|
3
|
-
<slot />
|
|
4
|
-
</component>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue";
|
|
9
|
-
import { useLumoraConfig } from "../context";
|
|
10
|
-
|
|
11
|
-
const props = defineProps<{
|
|
12
|
-
variant?: string;
|
|
13
|
-
as?: string;
|
|
14
|
-
}>();
|
|
15
|
-
|
|
16
|
-
const { resolveSkin } = useLumoraConfig();
|
|
17
|
-
const resolvedSkin = computed(() => resolveSkin("LuText", props.variant));
|
|
18
|
-
</script>
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<textarea
|
|
3
|
-
v-bind="$attrs"
|
|
4
|
-
:class="resolvedSkin"
|
|
5
|
-
:value="modelValue"
|
|
6
|
-
:name="name"
|
|
7
|
-
:disabled="formContext?.disabled.value"
|
|
8
|
-
@input="onInput"
|
|
9
|
-
@blur="onBlur"
|
|
10
|
-
/>
|
|
11
|
-
</template>
|
|
12
|
-
|
|
13
|
-
<script setup lang="ts">
|
|
14
|
-
import { computed, inject, onMounted, onUnmounted, ref } from "vue";
|
|
15
|
-
import { useLumoraConfig } from "../context";
|
|
16
|
-
import { LuFormContextKey } from "./LuForm.types";
|
|
17
|
-
|
|
18
|
-
const props = defineProps<{
|
|
19
|
-
modelValue?: string | number;
|
|
20
|
-
variant?: string;
|
|
21
|
-
name?: string;
|
|
22
|
-
error?: string | null;
|
|
23
|
-
}>();
|
|
24
|
-
|
|
25
|
-
const emit = defineEmits<{
|
|
26
|
-
(e: "update:modelValue", value: string): void;
|
|
27
|
-
(e: "blur"): void;
|
|
28
|
-
}>();
|
|
29
|
-
|
|
30
|
-
const { resolveSkin } = useLumoraConfig();
|
|
31
|
-
const resolvedSkin = computed(() => resolveSkin("LuTextarea", props.variant));
|
|
32
|
-
|
|
33
|
-
const formContext = inject(LuFormContextKey, null);
|
|
34
|
-
const internalValue = ref<string | number | undefined>(props.modelValue);
|
|
35
|
-
|
|
36
|
-
const onInput = (event: Event) => {
|
|
37
|
-
const value = (event.target as HTMLTextAreaElement).value;
|
|
38
|
-
internalValue.value = value;
|
|
39
|
-
emit("update:modelValue", value);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const onBlur = () => {
|
|
43
|
-
if (props.name && formContext && (formContext.validateOn.value === "blur" || formContext.validateOn.value === "both")) {
|
|
44
|
-
// trigger single-field validation — handled by parent LuForm
|
|
45
|
-
}
|
|
46
|
-
emit("blur");
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
onMounted(() => {
|
|
50
|
-
if (!props.name || !formContext) return;
|
|
51
|
-
formContext.register({
|
|
52
|
-
name: props.name,
|
|
53
|
-
getValue: () => internalValue.value,
|
|
54
|
-
setValue: (v) => { internalValue.value = v as string; },
|
|
55
|
-
setError: (_msg) => { /* error display handled via formContext.getError in template if desired */ },
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
onUnmounted(() => {
|
|
60
|
-
if (props.name && formContext) formContext.unregister(props.name);
|
|
61
|
-
});
|
|
62
|
-
</script>
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<LuSelect
|
|
3
|
-
:model-value="mode"
|
|
4
|
-
variant="theme"
|
|
5
|
-
:options="options"
|
|
6
|
-
v-bind="$attrs"
|
|
7
|
-
@update:model-value="onChange"
|
|
8
|
-
/>
|
|
9
|
-
</template>
|
|
10
|
-
|
|
11
|
-
<script setup lang="ts">
|
|
12
|
-
import LuSelect from "./LuSelect.vue";
|
|
13
|
-
import { useTheme, type ThemeMode } from "../composables/useTheme";
|
|
14
|
-
|
|
15
|
-
const { mode, setMode } = useTheme();
|
|
16
|
-
|
|
17
|
-
const options = [
|
|
18
|
-
{ value: "system", label: "System" },
|
|
19
|
-
{ value: "light", label: "Light" },
|
|
20
|
-
{ value: "dark", label: "Dark" },
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
const onChange = (val: string | number) => {
|
|
24
|
-
setMode(val as ThemeMode);
|
|
25
|
-
};
|
|
26
|
-
</script>
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<LuSwitch
|
|
3
|
-
:model-value="isDark"
|
|
4
|
-
variant="theme"
|
|
5
|
-
v-bind="$attrs"
|
|
6
|
-
@update:model-value="onToggle"
|
|
7
|
-
/>
|
|
8
|
-
</template>
|
|
9
|
-
|
|
10
|
-
<script setup lang="ts">
|
|
11
|
-
import { computed } from "vue";
|
|
12
|
-
import LuSwitch from "./LuSwitch.vue";
|
|
13
|
-
import { useTheme } from "../composables/useTheme";
|
|
14
|
-
|
|
15
|
-
const { resolved, setMode } = useTheme();
|
|
16
|
-
|
|
17
|
-
const isDark = computed(() => resolved.value === "dark");
|
|
18
|
-
|
|
19
|
-
const onToggle = (val: boolean) => {
|
|
20
|
-
setMode(val ? "dark" : "light");
|
|
21
|
-
};
|
|
22
|
-
</script>
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<button
|
|
3
|
-
v-bind="$attrs"
|
|
4
|
-
:class="[resolvedSkin, isActive ? activeSkin : '']"
|
|
5
|
-
@click="onClick"
|
|
6
|
-
:aria-pressed="isActive"
|
|
7
|
-
>
|
|
8
|
-
<slot />
|
|
9
|
-
</button>
|
|
10
|
-
</template>
|
|
11
|
-
|
|
12
|
-
<script setup lang="ts">
|
|
13
|
-
import { computed, inject, type Ref } from "vue";
|
|
14
|
-
import { useLumoraConfig } from "../context";
|
|
15
|
-
|
|
16
|
-
const props = defineProps<{
|
|
17
|
-
value: string | number | boolean;
|
|
18
|
-
variant?: string;
|
|
19
|
-
}>();
|
|
20
|
-
|
|
21
|
-
const groupValue = inject<Ref<string | number | boolean | undefined>>("lu-toggle-value");
|
|
22
|
-
const setGroupValue = inject<(value: string | number | boolean) => void>("lu-toggle-set");
|
|
23
|
-
|
|
24
|
-
const isActive = computed(() => groupValue?.value === props.value);
|
|
25
|
-
|
|
26
|
-
const onClick = () => {
|
|
27
|
-
if (setGroupValue) {
|
|
28
|
-
setGroupValue(props.value);
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const { resolveSkin } = useLumoraConfig();
|
|
33
|
-
const resolvedSkin = computed(() => resolveSkin("LuToggleButton", props.variant));
|
|
34
|
-
const activeSkin = computed(() => resolveSkin("LuToggleButton", "active"));
|
|
35
|
-
</script>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div v-bind="$attrs" :class="resolvedSkin" role="group">
|
|
3
|
-
<slot />
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed, provide, type Ref } from "vue";
|
|
9
|
-
import { useLumoraConfig } from "../context";
|
|
10
|
-
|
|
11
|
-
const props = defineProps<{
|
|
12
|
-
modelValue?: string | number | boolean;
|
|
13
|
-
variant?: string;
|
|
14
|
-
}>();
|
|
15
|
-
|
|
16
|
-
const emit = defineEmits<{
|
|
17
|
-
(e: "update:modelValue", value: string | number | boolean): void;
|
|
18
|
-
}>();
|
|
19
|
-
|
|
20
|
-
provide("lu-toggle-value", computed(() => props.modelValue));
|
|
21
|
-
provide("lu-toggle-set", (value: string | number | boolean) => {
|
|
22
|
-
emit("update:modelValue", value);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const { resolveSkin } = useLumoraConfig();
|
|
26
|
-
const resolvedSkin = computed(() => resolveSkin("LuToggleGroup", props.variant));
|
|
27
|
-
</script>
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div v-bind="$attrs" :class="containerSkin" @mouseenter="onEnter" @mouseleave="onLeave">
|
|
3
|
-
<slot name="trigger" />
|
|
4
|
-
<div v-if="isVisible" :class="contentSkin">
|
|
5
|
-
<slot name="content" />
|
|
6
|
-
</div>
|
|
7
|
-
</div>
|
|
8
|
-
</template>
|
|
9
|
-
|
|
10
|
-
<script setup lang="ts">
|
|
11
|
-
import { computed, ref } from "vue";
|
|
12
|
-
import { useLumoraConfig } from "../context";
|
|
13
|
-
|
|
14
|
-
const props = defineProps<{ variant?: string; position?: "top" | "bottom" | "left" | "right"; delay?: number }>();
|
|
15
|
-
|
|
16
|
-
const isVisible = ref(false);
|
|
17
|
-
let timeout: ReturnType<typeof setTimeout> | null = null;
|
|
18
|
-
|
|
19
|
-
const onEnter = () => {
|
|
20
|
-
if (timeout) clearTimeout(timeout);
|
|
21
|
-
if (props.delay) {
|
|
22
|
-
timeout = setTimeout(() => isVisible.value = true, props.delay);
|
|
23
|
-
} else {
|
|
24
|
-
isVisible.value = true;
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const onLeave = () => {
|
|
29
|
-
if (timeout) clearTimeout(timeout);
|
|
30
|
-
isVisible.value = false;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const { resolveSkin } = useLumoraConfig();
|
|
34
|
-
const containerSkin = computed(() => resolveSkin("LuTooltip", props.variant));
|
|
35
|
-
const contentSkin = computed(() => resolveSkin("LuTooltipContent", props.position ?? props.variant));
|
|
36
|
-
</script>
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { mount } from "@vue/test-utils";
|
|
3
|
-
import LuForm from "../LuForm.vue";
|
|
4
|
-
import LuInput from "../LuInput.vue";
|
|
5
|
-
import { ref, defineComponent } from "vue";
|
|
6
|
-
|
|
7
|
-
describe("LuForm", () => {
|
|
8
|
-
it("emits submit event with values when validation passes", async () => {
|
|
9
|
-
const Wrapper = defineComponent({
|
|
10
|
-
components: { LuForm, LuInput },
|
|
11
|
-
template: `
|
|
12
|
-
<LuForm>
|
|
13
|
-
<LuInput name="email" modelValue="test@example.com" />
|
|
14
|
-
</LuForm>
|
|
15
|
-
`
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const wrapper = mount(Wrapper);
|
|
19
|
-
await wrapper.find("form").trigger("submit");
|
|
20
|
-
|
|
21
|
-
const form = wrapper.findComponent(LuForm);
|
|
22
|
-
expect(form.emitted("submit")).toBeTruthy();
|
|
23
|
-
expect(form.emitted("submit")?.[0][0]).toEqual({ email: "test@example.com" });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("emits error event and blocks submit when validation fails", async () => {
|
|
27
|
-
const rules = {
|
|
28
|
-
email: (v: unknown) => !v ? "Required" : null,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const Wrapper = defineComponent({
|
|
32
|
-
components: { LuForm, LuInput },
|
|
33
|
-
data() { return { rules }; },
|
|
34
|
-
template: `
|
|
35
|
-
<LuForm :rules="rules">
|
|
36
|
-
<LuInput name="email" modelValue="" />
|
|
37
|
-
</LuForm>
|
|
38
|
-
`
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const wrapper = mount(Wrapper);
|
|
42
|
-
await wrapper.find("form").trigger("submit");
|
|
43
|
-
|
|
44
|
-
const form = wrapper.findComponent(LuForm);
|
|
45
|
-
expect(form.emitted("submit")).toBeFalsy();
|
|
46
|
-
expect(form.emitted("error")).toBeTruthy();
|
|
47
|
-
expect(form.emitted("error")?.[0][0]).toEqual({ email: "Required" });
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("clears errors and emits submit when validation passes", async () => {
|
|
51
|
-
const Wrapper = defineComponent({
|
|
52
|
-
components: { LuForm, LuInput },
|
|
53
|
-
template: `
|
|
54
|
-
<LuForm>
|
|
55
|
-
<LuInput name="email" modelValue="hello" />
|
|
56
|
-
</LuForm>
|
|
57
|
-
`
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const wrapper = mount(Wrapper);
|
|
61
|
-
await wrapper.find("form").trigger("submit");
|
|
62
|
-
|
|
63
|
-
const form = wrapper.findComponent(LuForm);
|
|
64
|
-
expect(form.emitted("submit")).toBeTruthy();
|
|
65
|
-
expect(form.vm.errors).toEqual({});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it("evaluates multiple validators on one field and stops at first error", async () => {
|
|
69
|
-
const rules = {
|
|
70
|
-
code: [
|
|
71
|
-
(v: unknown) => !v ? "Required" : null,
|
|
72
|
-
(v: unknown) => String(v).length < 3 ? "Min 3 chars" : null,
|
|
73
|
-
],
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const Wrapper = defineComponent({
|
|
77
|
-
components: { LuForm, LuInput },
|
|
78
|
-
data() { return { rules }; },
|
|
79
|
-
template: `
|
|
80
|
-
<LuForm :rules="rules">
|
|
81
|
-
<LuInput name="code" modelValue="ab" />
|
|
82
|
-
</LuForm>
|
|
83
|
-
`
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
const wrapper = mount(Wrapper);
|
|
87
|
-
await wrapper.find("form").trigger("submit");
|
|
88
|
-
|
|
89
|
-
const form = wrapper.findComponent(LuForm);
|
|
90
|
-
expect(form.vm.errors).toEqual({ code: "Min 3 chars" });
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("handles programmatic reset", async () => {
|
|
94
|
-
const Wrapper = defineComponent({
|
|
95
|
-
components: { LuForm, LuInput },
|
|
96
|
-
template: `
|
|
97
|
-
<LuForm>
|
|
98
|
-
<LuInput name="email" modelValue="test" />
|
|
99
|
-
</LuForm>
|
|
100
|
-
`
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const wrapper = mount(Wrapper);
|
|
104
|
-
const form = wrapper.findComponent(LuForm);
|
|
105
|
-
await wrapper.find("form").trigger("reset");
|
|
106
|
-
|
|
107
|
-
expect(form.emitted("reset")).toBeTruthy();
|
|
108
|
-
|
|
109
|
-
// Check that values are cleared by submitting again
|
|
110
|
-
await wrapper.find("form").trigger("submit");
|
|
111
|
-
expect(form.emitted("submit")?.[0][0]).toEqual({ email: undefined });
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("clears values after successful submit when resetOnSubmit is true", async () => {
|
|
115
|
-
const Wrapper = defineComponent({
|
|
116
|
-
components: { LuForm, LuInput },
|
|
117
|
-
template: `
|
|
118
|
-
<LuForm :resetOnSubmit="true">
|
|
119
|
-
<LuInput name="email" modelValue="test" />
|
|
120
|
-
</LuForm>
|
|
121
|
-
`
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
const wrapper = mount(Wrapper);
|
|
125
|
-
await wrapper.find("form").trigger("submit");
|
|
126
|
-
|
|
127
|
-
const form = wrapper.findComponent(LuForm);
|
|
128
|
-
expect(form.emitted("submit")).toBeTruthy();
|
|
129
|
-
|
|
130
|
-
// Check that values are cleared by submitting again
|
|
131
|
-
await wrapper.find("form").trigger("submit");
|
|
132
|
-
// Second submit is at index 1
|
|
133
|
-
expect(form.emitted("submit")?.[1][0]).toEqual({ email: undefined });
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it("updates errors on blur when validateOn is both", async () => {
|
|
137
|
-
const rules = {
|
|
138
|
-
email: (v: unknown) => !v ? "Required" : null,
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const Wrapper = defineComponent({
|
|
142
|
-
components: { LuForm, LuInput },
|
|
143
|
-
data() { return { rules }; },
|
|
144
|
-
template: `
|
|
145
|
-
<LuForm ref="form" :rules="rules" validateOn="both">
|
|
146
|
-
<LuInput name="email" modelValue="" />
|
|
147
|
-
</LuForm>
|
|
148
|
-
`
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const wrapper = mount(Wrapper);
|
|
152
|
-
const form = wrapper.findComponent(LuForm);
|
|
153
|
-
|
|
154
|
-
// We trigger the validate method manually to simulate it since single-field
|
|
155
|
-
// validation logic is handled by parent LuForm in the plan
|
|
156
|
-
await form.vm.submit();
|
|
157
|
-
expect(form.vm.errors).toEqual({ email: "Required" });
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it("supports programmatic submit and reset via defineExpose", async () => {
|
|
161
|
-
const Wrapper = defineComponent({
|
|
162
|
-
components: { LuForm, LuInput },
|
|
163
|
-
template: `
|
|
164
|
-
<LuForm ref="form" @submit="onSubmit" @reset="onReset">
|
|
165
|
-
<LuInput name="email" modelValue="test" />
|
|
166
|
-
</LuForm>
|
|
167
|
-
`,
|
|
168
|
-
methods: {
|
|
169
|
-
onSubmit() { this.$emit("submit"); },
|
|
170
|
-
onReset() { this.$emit("reset"); }
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
const wrapper = mount(Wrapper);
|
|
175
|
-
const form = wrapper.findComponent(LuForm);
|
|
176
|
-
|
|
177
|
-
await form.vm.submit();
|
|
178
|
-
expect(wrapper.emitted("submit")).toBeTruthy();
|
|
179
|
-
|
|
180
|
-
form.vm.reset();
|
|
181
|
-
expect(wrapper.emitted("reset")).toBeTruthy();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it("allows inputs to work standalone without a LuForm parent", async () => {
|
|
185
|
-
const wrapper = mount(LuInput, {
|
|
186
|
-
props: { name: "email", modelValue: "test" },
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
expect(wrapper.exists()).toBe(true);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("passes disabled context down to registered inputs", async () => {
|
|
193
|
-
const Wrapper = defineComponent({
|
|
194
|
-
components: { LuForm, LuInput },
|
|
195
|
-
template: `
|
|
196
|
-
<LuForm :disabled="true">
|
|
197
|
-
<LuInput name="email" modelValue="test" />
|
|
198
|
-
</LuForm>
|
|
199
|
-
`
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
const wrapper = mount(Wrapper);
|
|
203
|
-
const input = wrapper.find("input");
|
|
204
|
-
expect(input.attributes("disabled")).toBeDefined();
|
|
205
|
-
});
|
|
206
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { ref, readonly } from "vue";
|
|
2
|
-
|
|
3
|
-
export function useRail(defaultExpanded = false) {
|
|
4
|
-
const isExpanded = ref(defaultExpanded);
|
|
5
|
-
|
|
6
|
-
function toggle() {
|
|
7
|
-
isExpanded.value = !isExpanded.value;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function expand() {
|
|
11
|
-
isExpanded.value = true;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function collapse() {
|
|
15
|
-
isExpanded.value = false;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
isExpanded: readonly(isExpanded),
|
|
20
|
-
toggle,
|
|
21
|
-
expand,
|
|
22
|
-
collapse,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ref, type Ref } from "vue";
|
|
2
|
-
|
|
3
|
-
export function useSplit(
|
|
4
|
-
containerRef: Ref<HTMLElement | null>,
|
|
5
|
-
direction: "horizontal" | "vertical" = "horizontal",
|
|
6
|
-
onResize?: (sizes: number[]) => void
|
|
7
|
-
) {
|
|
8
|
-
const isDragging = ref(false);
|
|
9
|
-
|
|
10
|
-
// Simplified split drag logic hook.
|
|
11
|
-
// In a real implementation, this would attach mousedown to resizers,
|
|
12
|
-
// and mousemove/mouseup to the window, updating the size of adjacent panes.
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
isDragging,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { ref, computed, watchEffect } from "vue";
|
|
2
|
-
|
|
3
|
-
export type ThemeMode = "system" | "light" | "dark";
|
|
4
|
-
export type ResolvedTheme = "light" | "dark";
|
|
5
|
-
|
|
6
|
-
// Global state for the theme
|
|
7
|
-
const mode = ref<ThemeMode>("system");
|
|
8
|
-
const systemPrefersDark = ref(false);
|
|
9
|
-
|
|
10
|
-
// Update system preference when window matches change
|
|
11
|
-
if (typeof window !== "undefined") {
|
|
12
|
-
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
13
|
-
systemPrefersDark.value = mediaQuery.matches;
|
|
14
|
-
mediaQuery.addEventListener("change", (e) => {
|
|
15
|
-
systemPrefersDark.value = e.matches;
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const resolved = computed<ResolvedTheme>(() => {
|
|
20
|
-
if (mode.value === "system") {
|
|
21
|
-
return systemPrefersDark.value ? "dark" : "light";
|
|
22
|
-
}
|
|
23
|
-
return mode.value;
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
export function useTheme() {
|
|
27
|
-
const setMode = (newMode: ThemeMode) => {
|
|
28
|
-
mode.value = newMode;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
mode,
|
|
33
|
-
resolved,
|
|
34
|
-
setMode,
|
|
35
|
-
};
|
|
36
|
-
}
|