fix type errors of components/form
This commit is contained in:
parent
3abe6a0dfe
commit
bfffd94ae5
13 changed files with 90 additions and 70 deletions
|
@ -14,6 +14,7 @@
|
|||
"caughtErrorsIgnorePattern": "^_",
|
||||
"destructuredArrayIgnorePattern": "^_"
|
||||
}
|
||||
]
|
||||
],
|
||||
"vue/no-setup-props-destructure": "off"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ const props = defineProps<{
|
|||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: "update:modelValue", v: boolean): void;
|
||||
"update:modelValue": [v: boolean];
|
||||
}>();
|
||||
|
||||
const button = ref<HTMLElement>();
|
||||
|
@ -46,9 +46,9 @@ const toggle = () => {
|
|||
emit("update:modelValue", !checked.value);
|
||||
|
||||
if (!checked.value) {
|
||||
const rect = button.value.getBoundingClientRect();
|
||||
const x = rect.left + button.value.offsetWidth / 2;
|
||||
const y = rect.top + button.value.offsetHeight / 2;
|
||||
const rect = button.value!.getBoundingClientRect();
|
||||
const x = rect.left + button.value!.offsetWidth / 2;
|
||||
const y = rect.top + button.value!.offsetHeight / 2;
|
||||
os.popup(Ripple, { x, y, particle: false }, {}, "end");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
@input="onInput"
|
||||
/>
|
||||
<datalist v-if="datalist" :id="id">
|
||||
<option v-for="data in datalist" :value="data" />
|
||||
<option v-for="data in datalist" :key="data" :value="data" />
|
||||
</datalist>
|
||||
<div ref="suffixEl" class="suffix">
|
||||
<slot name="suffix"></slot>
|
||||
|
@ -47,7 +47,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, onMounted, ref, toRefs, watch } from "vue";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import { debounce as Debounce } from "throttle-debounce";
|
||||
import MkButton from "@/components/MkButton.vue";
|
||||
import { useInterval } from "@/scripts/use-interval";
|
||||
import { i18n } from "@/i18n";
|
||||
|
@ -72,7 +72,7 @@ const props = defineProps<{
|
|||
autofocus?: boolean;
|
||||
autocomplete?: string;
|
||||
spellcheck?: boolean;
|
||||
step?: any;
|
||||
step?: number | string;
|
||||
datalist?: string[];
|
||||
inline?: boolean;
|
||||
debounce?: boolean;
|
||||
|
@ -82,10 +82,10 @@ const props = defineProps<{
|
|||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: "change", _ev: KeyboardEvent): void;
|
||||
(ev: "change", _ev: Event): void;
|
||||
(ev: "keydown", _ev: KeyboardEvent): void;
|
||||
(ev: "enter"): void;
|
||||
(ev: "update:modelValue", value: string | number): void;
|
||||
(ev: "update:modelValue", value: string | number | null): void;
|
||||
}>();
|
||||
|
||||
const { modelValue, type, autofocus } = toRefs(props);
|
||||
|
@ -94,14 +94,15 @@ const id = Math.random().toString(); // TODO: uuid?
|
|||
const focused = ref(false);
|
||||
const changed = ref(false);
|
||||
const invalid = ref(false);
|
||||
const inputEl = ref<HTMLElement>();
|
||||
const inputEl = ref<HTMLInputElement>();
|
||||
const prefixEl = ref<HTMLElement>();
|
||||
const suffixEl = ref<HTMLElement>();
|
||||
const height = props.small ? 36 : props.large ? 40 : 38;
|
||||
|
||||
const focus = () => inputEl.value.focus();
|
||||
const selectRange = (start, end) => inputEl.value.setSelectionRange(start, end);
|
||||
const onInput = (ev: KeyboardEvent) => {
|
||||
const focus = () => inputEl.value!.focus();
|
||||
const selectRange = (start, end) =>
|
||||
inputEl.value!.setSelectionRange(start, end);
|
||||
const onInput = (ev: Event) => {
|
||||
changed.value = true;
|
||||
emit("change", ev);
|
||||
};
|
||||
|
@ -116,13 +117,13 @@ const onKeydown = (ev: KeyboardEvent) => {
|
|||
const updated = () => {
|
||||
changed.value = false;
|
||||
if (type.value === "number") {
|
||||
emit("update:modelValue", parseFloat(v.value));
|
||||
emit("update:modelValue", Number.parseFloat(v.value as string));
|
||||
} else {
|
||||
emit("update:modelValue", v.value);
|
||||
}
|
||||
};
|
||||
|
||||
const debouncedUpdated = debounce(1000, updated);
|
||||
const debouncedUpdated = Debounce(1000, updated);
|
||||
|
||||
watch(modelValue, (newValue) => {
|
||||
v.value = newValue;
|
||||
|
@ -137,7 +138,7 @@ watch(v, (_) => {
|
|||
}
|
||||
}
|
||||
|
||||
invalid.value = inputEl.value.validity.badInput;
|
||||
invalid.value = inputEl.value!.validity.badInput;
|
||||
});
|
||||
|
||||
// このコンポーネントが作成された時、非表示状態である場合がある
|
||||
|
@ -146,12 +147,12 @@ useInterval(
|
|||
() => {
|
||||
if (prefixEl.value) {
|
||||
if (prefixEl.value.offsetWidth) {
|
||||
inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + "px";
|
||||
inputEl.value!.style.paddingLeft = `${prefixEl.value.offsetWidth}px`;
|
||||
}
|
||||
}
|
||||
if (suffixEl.value) {
|
||||
if (suffixEl.value.offsetWidth) {
|
||||
inputEl.value.style.paddingRight = suffixEl.value.offsetWidth + "px";
|
||||
inputEl.value!.style.paddingRight = `${suffixEl.value.offsetWidth}px`;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -16,19 +16,22 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny:
|
||||
type ValueType = any;
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: any;
|
||||
value: any;
|
||||
modelValue: ValueType;
|
||||
value: ValueType;
|
||||
disabled: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: "update:modelValue", value: any): void;
|
||||
"update:modelValue": [value: ValueType];
|
||||
}>();
|
||||
|
||||
const checked = computed(() => props.modelValue === props.value);
|
||||
|
||||
function toggle(x) {
|
||||
function toggle(_ev: Event) {
|
||||
if (props.disabled) return;
|
||||
emit("update:modelValue", props.value);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent, h } from "vue";
|
||||
import { type VNode, defineComponent, h } from "vue";
|
||||
import MkRadio from "./radio.vue";
|
||||
|
||||
export default defineComponent({
|
||||
|
@ -22,13 +22,17 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
render() {
|
||||
let options = this.$slots.default();
|
||||
const label = this.$slots.label && this.$slots.label();
|
||||
const caption = this.$slots.caption && this.$slots.caption();
|
||||
let options = this.$slots.default!();
|
||||
const label = this.$slots.label && this.$slots.label!();
|
||||
const caption = this.$slots.caption && this.$slots.caption!();
|
||||
|
||||
// なぜかFragmentになることがあるため
|
||||
if (options.length === 1 && options[0].props == null)
|
||||
options = options[0].children;
|
||||
if (
|
||||
options.length === 1 &&
|
||||
options[0].props == null &&
|
||||
Array.isArray(options[0].children)
|
||||
)
|
||||
options = options[0].children as VNode[];
|
||||
|
||||
return h(
|
||||
"fieldset",
|
||||
|
@ -60,7 +64,10 @@ export default defineComponent({
|
|||
value: option.props?.value,
|
||||
disabled: option.props?.disabled,
|
||||
modelValue: this.value,
|
||||
"onUpdate:modelValue": (value) => (this.value = value),
|
||||
"onUpdate:modelValue": (value) => {
|
||||
this.value = value;
|
||||
return value;
|
||||
},
|
||||
},
|
||||
option.children,
|
||||
),
|
||||
|
@ -83,7 +90,7 @@ export default defineComponent({
|
|||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.novjtcto {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
@mouseleave="tooltipHide"
|
||||
@input="
|
||||
(x) => {
|
||||
inputVal = x.target.value;
|
||||
inputVal = Number((x.target as HTMLInputElement).value);
|
||||
if (instant) onChange(x);
|
||||
}
|
||||
"
|
||||
|
@ -29,6 +29,7 @@
|
|||
<datalist v-if="showTicks && steps" :id="id">
|
||||
<option
|
||||
v-for="i in steps"
|
||||
:key="`step-${i}`"
|
||||
:value="i + min"
|
||||
:label="(i + min).toString()"
|
||||
></option>
|
||||
|
@ -69,11 +70,11 @@ const props = withDefaults(
|
|||
},
|
||||
);
|
||||
|
||||
const inputEl = ref<HTMLElement>();
|
||||
const inputEl = ref<HTMLInputElement>();
|
||||
const inputVal = ref(props.modelValue);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: "update:modelValue", value: number): void;
|
||||
"update:modelValue": [value: number];
|
||||
}>();
|
||||
|
||||
const steps = computed(() => {
|
||||
|
@ -84,7 +85,7 @@ const steps = computed(() => {
|
|||
}
|
||||
});
|
||||
|
||||
function onChange(x) {
|
||||
function onChange(_x) {
|
||||
emit("update:modelValue", inputVal.value);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ import * as os from "@/os";
|
|||
import { useInterval } from "@/scripts/use-interval";
|
||||
import { i18n } from "@/i18n";
|
||||
import icon from "@/scripts/icon";
|
||||
import type { MenuItem } from "@/types/menu";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: string | null;
|
||||
|
@ -85,13 +86,13 @@ const focused = ref(false);
|
|||
const opening = ref(false);
|
||||
const changed = ref(false);
|
||||
const invalid = ref(false);
|
||||
const inputEl = ref(null);
|
||||
const prefixEl = ref(null);
|
||||
const suffixEl = ref(null);
|
||||
const container = ref(null);
|
||||
const inputEl = ref<HTMLInputElement | null>(null);
|
||||
const prefixEl = ref<HTMLElement | null>(null);
|
||||
const suffixEl = ref<HTMLElement | null>(null);
|
||||
const container = ref<HTMLElement | null>(null);
|
||||
const height = props.small ? 33 : props.large ? 39 : 36;
|
||||
|
||||
const focus = () => inputEl.value.focus();
|
||||
const focus = () => inputEl.value!.focus();
|
||||
const onInput = (ev) => {
|
||||
changed.value = true;
|
||||
emit("change", ev);
|
||||
|
@ -106,26 +107,27 @@ watch(modelValue, (newValue) => {
|
|||
v.value = newValue;
|
||||
});
|
||||
|
||||
watch(v, (newValue) => {
|
||||
watch(v, (_newValue) => {
|
||||
if (!props.manualSave) {
|
||||
updated();
|
||||
}
|
||||
|
||||
invalid.value = inputEl.value.validity.badInput;
|
||||
invalid.value = inputEl.value!.validity.badInput;
|
||||
});
|
||||
|
||||
// このコンポーネントが作成された時、非表示状態である場合がある
|
||||
// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する
|
||||
useInterval(
|
||||
() => {
|
||||
if (inputEl.value == null) return;
|
||||
if (prefixEl.value) {
|
||||
if (prefixEl.value.offsetWidth) {
|
||||
inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + "px";
|
||||
inputEl.value.style.paddingLeft = `${prefixEl.value.offsetWidth}px`;
|
||||
}
|
||||
}
|
||||
if (suffixEl.value) {
|
||||
if (suffixEl.value.offsetWidth) {
|
||||
inputEl.value.style.paddingRight = suffixEl.value.offsetWidth + "px";
|
||||
inputEl.value.style.paddingRight = `${suffixEl.value.offsetWidth}px`;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -144,19 +146,19 @@ onMounted(() => {
|
|||
});
|
||||
});
|
||||
|
||||
function show(ev: MouseEvent) {
|
||||
function show(_ev: MouseEvent) {
|
||||
focused.value = true;
|
||||
opening.value = true;
|
||||
|
||||
const menu = [];
|
||||
const menu: MenuItem[] = [];
|
||||
const options = slots.default!();
|
||||
|
||||
const pushOption = (option: VNode) => {
|
||||
menu.push({
|
||||
text: option.children,
|
||||
active: computed(() => v.value === option.props.value),
|
||||
text: option.children as string,
|
||||
active: computed(() => v.value === option.props?.value).value,
|
||||
action: () => {
|
||||
v.value = option.props.value;
|
||||
v.value = option.props?.value;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -167,13 +169,13 @@ function show(ev: MouseEvent) {
|
|||
const optgroup = vnode;
|
||||
menu.push({
|
||||
type: "label",
|
||||
text: optgroup.props.label,
|
||||
text: optgroup.props?.label,
|
||||
});
|
||||
scanOptions(optgroup.children);
|
||||
scanOptions(optgroup.children as VNode[]);
|
||||
} else if (Array.isArray(vnode.children)) {
|
||||
// 何故かフラグメントになってくることがある
|
||||
const fragment = vnode;
|
||||
scanOptions(fragment.children);
|
||||
scanOptions(fragment.children as VNode[]);
|
||||
} else if (vnode.props == null) {
|
||||
// v-if で条件が false のときにこうなる
|
||||
// nop?
|
||||
|
@ -186,12 +188,13 @@ function show(ev: MouseEvent) {
|
|||
|
||||
scanOptions(options);
|
||||
|
||||
os.popupMenu(menu, container.value, {
|
||||
width: container.value.offsetWidth,
|
||||
onClosing: () => {
|
||||
opening.value = false;
|
||||
},
|
||||
os.popupMenu(menu, container.value!, {
|
||||
width: container.value!.offsetWidth,
|
||||
// onClosing: () => {
|
||||
// opening.value = false;
|
||||
// },
|
||||
}).then(() => {
|
||||
opening.value = false;
|
||||
focused.value = false;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ const props = withDefaults(
|
|||
},
|
||||
);
|
||||
|
||||
const minWidth = props.minWidth + "px";
|
||||
const minWidth = `${props.minWidth}px`;
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -39,12 +39,13 @@ export default defineComponent({
|
|||
|
||||
props: {
|
||||
p: {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||
type: Function as PropType<() => Promise<any>>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
setup(props, context) {
|
||||
setup(props, _context) {
|
||||
const pending = ref(true);
|
||||
const resolved = ref(false);
|
||||
const rejected = ref(false);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<label class="ziffeomt">
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="modelValue"
|
||||
:checked="toValue(modelValue)"
|
||||
:disabled="disabled"
|
||||
@change="(x) => toggle(x)"
|
||||
/>
|
||||
|
@ -18,7 +18,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { Ref } from "vue";
|
||||
import { type Ref, toValue } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean | Ref<boolean>;
|
||||
|
@ -26,12 +26,12 @@ const props = defineProps<{
|
|||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: "update:modelValue", v: boolean): void;
|
||||
"update:modelValue": [v: boolean];
|
||||
}>();
|
||||
|
||||
function toggle(x) {
|
||||
function toggle(x: Event) {
|
||||
if (props.disabled) return;
|
||||
emit("update:modelValue", x.target.checked);
|
||||
emit("update:modelValue", (x.target as HTMLInputElement).checked);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ export default defineComponent({
|
|||
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
|
@ -92,9 +93,11 @@ export default defineComponent({
|
|||
default: false,
|
||||
},
|
||||
autocomplete: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
spellcheck: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
},
|
||||
code: {
|
||||
|
@ -132,9 +135,9 @@ export default defineComponent({
|
|||
const changed = ref(false);
|
||||
const invalid = ref(false);
|
||||
const filled = computed(() => v.value !== "" && v.value != null);
|
||||
const inputEl = ref(null);
|
||||
const inputEl = ref<HTMLTextAreaElement | null>(null);
|
||||
|
||||
const focus = () => inputEl.value.focus();
|
||||
const focus = () => inputEl.value!.focus();
|
||||
const onInput = (ev) => {
|
||||
changed.value = true;
|
||||
context.emit("change", ev);
|
||||
|
@ -167,7 +170,7 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
|
||||
invalid.value = inputEl.value.validity.badInput;
|
||||
invalid.value = inputEl.value!.validity.badInput;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
|
|
|
@ -27,7 +27,7 @@ const props = withDefaults(
|
|||
|
||||
const _time =
|
||||
props.time == null
|
||||
? NaN
|
||||
? Number.NaN
|
||||
: typeof props.time === "number"
|
||||
? props.time
|
||||
: (props.time instanceof Date
|
||||
|
|
|
@ -855,8 +855,8 @@ export function popupMenu(
|
|||
noReturnFocus?: boolean;
|
||||
},
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let dispose;
|
||||
return new Promise<void>((resolve, _reject) => {
|
||||
let dispose: () => void;
|
||||
popup(
|
||||
defineAsyncComponent({
|
||||
loader: () => import("@/components/MkPopupMenu.vue"),
|
||||
|
|
Loading…
Reference in a new issue