mirror of
https://github.com/mashirozx/sakura.git
synced 2024-12-12 09:54:35 +08:00
Add admin page component
This commit is contained in:
parent
edeab203e0
commit
4f0c68a46b
@ -79,6 +79,8 @@ class AdminPageHelper extends ViteHelper
|
|||||||
|
|
||||||
public function enqueue_common_scripts()
|
public function enqueue_common_scripts()
|
||||||
{
|
{
|
||||||
|
wp_enqueue_media();
|
||||||
|
|
||||||
wp_enqueue_style('style.css', get_template_directory_uri() . '/style.css');
|
wp_enqueue_style('style.css', get_template_directory_uri() . '/style.css');
|
||||||
|
|
||||||
wp_enqueue_style('fontawesome-free', 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css');
|
wp_enqueue_style('fontawesome-free', 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css');
|
||||||
|
@ -30,12 +30,16 @@
|
|||||||
"@formatjs/intl": "^1.13.2",
|
"@formatjs/intl": "^1.13.2",
|
||||||
"@material/button": "^12.0.0-canary.068fd5028.0",
|
"@material/button": "^12.0.0-canary.068fd5028.0",
|
||||||
"@material/card": "^12.0.0-canary.068fd5028.0",
|
"@material/card": "^12.0.0-canary.068fd5028.0",
|
||||||
|
"@material/checkbox": "^12.0.0-canary.e1703bed9.0",
|
||||||
"@material/chips": "^12.0.0-canary.068fd5028.0",
|
"@material/chips": "^12.0.0-canary.068fd5028.0",
|
||||||
"@material/dialog": "^12.0.0-canary.068fd5028.0",
|
"@material/dialog": "^12.0.0-canary.068fd5028.0",
|
||||||
"@material/elevation": "^12.0.0-canary.068fd5028.0",
|
"@material/elevation": "^12.0.0-canary.068fd5028.0",
|
||||||
|
"@material/form-field": "^12.0.0-canary.e1703bed9.0",
|
||||||
"@material/list": "^12.0.0-canary.068fd5028.0",
|
"@material/list": "^12.0.0-canary.068fd5028.0",
|
||||||
"@material/menu": "^12.0.0-canary.068fd5028.0",
|
"@material/menu": "^12.0.0-canary.068fd5028.0",
|
||||||
|
"@material/radio": "^12.0.0-canary.9f68a932e.0",
|
||||||
"@material/ripple": "^12.0.0-canary.068fd5028.0",
|
"@material/ripple": "^12.0.0-canary.068fd5028.0",
|
||||||
|
"@material/switch": "^12.0.0-canary.9f68a932e.0",
|
||||||
"@material/tab-bar": "^12.0.0-canary.22d29cbb4.0",
|
"@material/tab-bar": "^12.0.0-canary.22d29cbb4.0",
|
||||||
"@material/textfield": "^12.0.0-canary.068fd5028.0",
|
"@material/textfield": "^12.0.0-canary.068fd5028.0",
|
||||||
"@material/theme": "^12.0.0-canary.068fd5028.0",
|
"@material/theme": "^12.0.0-canary.068fd5028.0",
|
||||||
@ -95,7 +99,8 @@
|
|||||||
"vite": "^2.4.2",
|
"vite": "^2.4.2",
|
||||||
"vite-plugin-svgicon": "^1.0.0-alpha.0",
|
"vite-plugin-svgicon": "^1.0.0-alpha.0",
|
||||||
"vue-jest": "^5.0.0-alpha.10",
|
"vue-jest": "^5.0.0-alpha.10",
|
||||||
"vue-tsc": "^0.2.0"
|
"vue-tsc": "^0.2.0",
|
||||||
|
"wp-types": "^2.10.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"npm": "please-use-yarn",
|
"npm": "please-use-yarn",
|
||||||
|
@ -16,32 +16,49 @@
|
|||||||
v-for="(tabKey, tabKeyIndex) in tabKeys"
|
v-for="(tabKey, tabKeyIndex) in tabKeys"
|
||||||
:key="tabKeyIndex"
|
:key="tabKeyIndex"
|
||||||
>
|
>
|
||||||
<div class="tab-page__content mdc-typography">
|
<div class="tab-page__content">
|
||||||
<h1 class="mdc-typography--headline5">{{ options[tabKey].title }}</h1>
|
<h1 class="row__wrapper--title">{{ options[tabKey].title }}</h1>
|
||||||
|
<p class="row__wrapper--desc" v-if="options[tabKey].desc"> {{ options[tabKey].desc }} </p>
|
||||||
<div
|
<div
|
||||||
class="row__wrapper--options"
|
class="row__wrapper--options"
|
||||||
v-for="(option, optionIndex) in options[tabKey].options"
|
v-for="(option, optionIndex) in options[tabKey].options"
|
||||||
:key="optionIndex"
|
:key="optionIndex"
|
||||||
>
|
>
|
||||||
{{ option.namespace }}
|
<OptionItem :option="option"></OptionItem>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
</Swiper>
|
</Swiper>
|
||||||
|
<div class="buttons__wrapper">
|
||||||
|
<NormalButton icon="fas fa-save" context="Save" :contained="true"></NormalButton>
|
||||||
|
<NormalButton icon="fas fa-upload" context="Import" :contained="true"></NormalButton>
|
||||||
|
<NormalButton icon="fas fa-download" context="Export" :contained="true"></NormalButton>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, Ref, watch, nextTick } from 'vue'
|
import {
|
||||||
|
defineComponent,
|
||||||
|
ref,
|
||||||
|
Ref,
|
||||||
|
watch,
|
||||||
|
nextTick,
|
||||||
|
watchEffect,
|
||||||
|
onMounted,
|
||||||
|
onBeforeUnmount,
|
||||||
|
} from 'vue'
|
||||||
import { Swiper, SwiperSlide } from 'swiper/vue'
|
import { Swiper, SwiperSlide } from 'swiper/vue'
|
||||||
import { Swiper as SwiperInterface } from 'swiper'
|
import { Swiper as SwiperInterface } from 'swiper'
|
||||||
import { useInjector } from '@/hooks'
|
import { useInjector } from '@/hooks'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
import options from '@/admin/options'
|
import options from '@/admin/options'
|
||||||
import TabBar from '@/components/tabBar/TabBar.vue'
|
import TabBar from '@/components/tabBar/TabBar.vue'
|
||||||
|
import OptionItem from './OptionItem.vue'
|
||||||
|
import NormalButton from '@/components/buttons/NormalButton.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { TabBar, Swiper, SwiperSlide },
|
components: { TabBar, Swiper, SwiperSlide, OptionItem, NormalButton },
|
||||||
setup() {
|
setup() {
|
||||||
// UI controllers
|
// UI controllers
|
||||||
const currentTabIndex: Ref<number> = ref(0)
|
const currentTabIndex: Ref<number> = ref(0)
|
||||||
@ -55,7 +72,16 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(currentTabIndex, (current) => swiperRef.value?.slideTo(current))
|
watch(currentTabIndex, (current) => swiperRef.value?.slideTo(current))
|
||||||
nextTick(() => swiperRef.value?.updateAutoHeight(100))
|
|
||||||
|
const updateAutoHeight = () => swiperRef.value?.updateAutoHeight(0)
|
||||||
|
|
||||||
|
// nextTick(() => updateAutoHeight())
|
||||||
|
// watchEffect(() => updateAutoHeight())
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const timer = setInterval(() => updateAutoHeight(), 100)
|
||||||
|
onBeforeUnmount(() => clearInterval(timer))
|
||||||
|
})
|
||||||
|
|
||||||
// data controllers
|
// data controllers
|
||||||
const { config, setConfig } = useInjector(store)
|
const { config, setConfig } = useInjector(store)
|
||||||
@ -87,5 +113,14 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
> .buttons__wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
width: calc(100% - 24px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,24 +1,168 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="option__container">
|
<div class="option__container">
|
||||||
<h1 class="mdc-typography--headline6">{{ $props.namespace }}</h1>
|
<h3 class="column__wrapper--label"> {{ title }} </h3>
|
||||||
|
<div class="column__wrapper--main">
|
||||||
|
<div class="row__wrapper--option">
|
||||||
|
<OutlinedInput
|
||||||
|
v-if="type === 'string'"
|
||||||
|
v-model:content="optionResultRef"
|
||||||
|
v-bind="binds"
|
||||||
|
></OutlinedInput>
|
||||||
|
<OutlinedTextarea
|
||||||
|
v-else-if="type === 'longString'"
|
||||||
|
v-model:content="optionResultRef"
|
||||||
|
v-bind="binds"
|
||||||
|
></OutlinedTextarea>
|
||||||
|
<Selection
|
||||||
|
v-else-if="type === 'selection'"
|
||||||
|
v-model:result="optionResultRef"
|
||||||
|
v-bind="binds"
|
||||||
|
></Selection>
|
||||||
|
<Choose
|
||||||
|
v-else-if="type === 'choose'"
|
||||||
|
v-model:result="optionResultRef"
|
||||||
|
v-bind="binds"
|
||||||
|
></Choose>
|
||||||
|
<MediaPicker
|
||||||
|
v-else-if="type === 'mediaPicker'"
|
||||||
|
v-model:selection="optionResultRef"
|
||||||
|
v-bind="binds"
|
||||||
|
></MediaPicker>
|
||||||
|
<Switcher
|
||||||
|
v-else-if="type === 'switcher'"
|
||||||
|
v-model:checked="optionResultRef"
|
||||||
|
v-bind="binds"
|
||||||
|
></Switcher>
|
||||||
|
</div>
|
||||||
|
<p class="row__wrapper--desc" v-if="desc">
|
||||||
|
<i class="fas fa-info-circle"></i> <span v-html="desc"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue'
|
import { defineComponent, ref, watch } from 'vue'
|
||||||
import { useInjector } from '@/hooks'
|
import { useInjector } from '@/hooks'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
|
import validator from './validator'
|
||||||
const defaultOption = {}
|
import OutlinedInput from '@/components/inputs/OutlinedInput.vue'
|
||||||
|
import OutlinedTextarea from '@/components/inputs/OutlinedTextarea.vue'
|
||||||
|
import Selection from '@/components/checkbox/Selection.vue'
|
||||||
|
import MediaPicker from '@/admin/components/MediaPicker.vue'
|
||||||
|
import Choose from '@/components/radio/Choose.vue'
|
||||||
|
import Switcher from '@/components/switcher/Switcher.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
components: { OutlinedInput, OutlinedTextarea, Selection, MediaPicker, Choose, Switcher },
|
||||||
props: {
|
props: {
|
||||||
options: { type: Object, default: () => defaultOption },
|
option: { type: Object, required: true },
|
||||||
},
|
},
|
||||||
emits: [],
|
emits: [],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const { config, setConfig } = useInjector(store)
|
const { namespace, type, title, desc, binds } = props.option
|
||||||
return {}
|
const { config, updateOption } = useInjector(store)
|
||||||
|
const optionResultRef = ref(config.value[namespace] ?? props.option.default)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
optionResultRef,
|
||||||
|
(result) => {
|
||||||
|
if (validator(result, type).pass) {
|
||||||
|
updateOption(config, namespace, result)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
return { config, optionResultRef, type, title, desc, binds }
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.option__container {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
align-items: space-between;
|
||||||
|
justify-content: flex-start;
|
||||||
|
> .column__wrapper {
|
||||||
|
&--label {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 200px;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
&--main {
|
||||||
|
width: 100%;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
align-items: space-between;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding-top: 12px;
|
||||||
|
> .row__wrapper {
|
||||||
|
&--option {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
&--desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #646970;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom
|
||||||
|
// ::v-deep() {
|
||||||
|
// .mdc-checkbox {
|
||||||
|
// transform: translateX(-13px);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Polyfill WP default styles
|
||||||
|
::v-deep() {
|
||||||
|
input.disabled,
|
||||||
|
input:disabled,
|
||||||
|
select.disabled,
|
||||||
|
select:disabled,
|
||||||
|
textarea.disabled,
|
||||||
|
textarea:disabled {
|
||||||
|
background: unset;
|
||||||
|
border-color: unset;
|
||||||
|
box-shadow: unset;
|
||||||
|
color: unset;
|
||||||
|
}
|
||||||
|
input[type='checkbox'],
|
||||||
|
input[type='radio'] {
|
||||||
|
border: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='checkbox']:focus,
|
||||||
|
input[type='color']:focus,
|
||||||
|
input[type='date']:focus,
|
||||||
|
input[type='datetime-local']:focus,
|
||||||
|
input[type='datetime']:focus,
|
||||||
|
input[type='email']:focus,
|
||||||
|
input[type='month']:focus,
|
||||||
|
input[type='number']:focus,
|
||||||
|
input[type='password']:focus,
|
||||||
|
input[type='radio']:focus,
|
||||||
|
input[type='search']:focus,
|
||||||
|
input[type='tel']:focus,
|
||||||
|
input[type='text']:focus,
|
||||||
|
input[type='time']:focus,
|
||||||
|
input[type='url']:focus,
|
||||||
|
input[type='week']:focus,
|
||||||
|
select:focus,
|
||||||
|
textarea:focus {
|
||||||
|
border-color: unset;
|
||||||
|
box-shadow: unset;
|
||||||
|
outline: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-error,
|
||||||
|
div.error {
|
||||||
|
border-left-color: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1 +0,0 @@
|
|||||||
# The admin's panel sub-project
|
|
194
src/admin/components/MediaPicker.vue
Normal file
194
src/admin/components/MediaPicker.vue
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
<template>
|
||||||
|
<div class="picker__container">
|
||||||
|
<div class="row__wrapper--input">
|
||||||
|
<div class="input__wrapper">
|
||||||
|
<OutlinedInput v-model:content="userInput" label="Input remote URL here"></OutlinedInput>
|
||||||
|
</div>
|
||||||
|
<div class="button__wrapper" @click="add">
|
||||||
|
<NormalButton icon="fas fas fa-link" context="Add" :contained="true"></NormalButton>
|
||||||
|
</div>
|
||||||
|
<div class="button__wrapper" @click="open">
|
||||||
|
<NormalButton icon="fas fa-box-open" context="Pick" :contained="true"></NormalButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row__wrapper--preview">
|
||||||
|
<div class="image__box" v-for="(item, index) in selection" :key="index">
|
||||||
|
<div class="image__wrapper">
|
||||||
|
<Image :src="item.url" :avatar="false" :draggable="false"></Image>
|
||||||
|
</div>
|
||||||
|
<div class="delete__button" @click="del(index)">
|
||||||
|
<span><i class="fas fa-trash-alt"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, watch, Ref } from 'vue'
|
||||||
|
import { cloneDeep, remove } from 'lodash'
|
||||||
|
import uniqueHash from '@/utils/uniqueHash'
|
||||||
|
import { isUrl } from '@/utils/urlHelper'
|
||||||
|
import NormalButton from '@/components/buttons/NormalButton.vue'
|
||||||
|
import OutlinedInput from '@/components/inputs/OutlinedInput.vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { NormalButton, OutlinedInput },
|
||||||
|
props: {
|
||||||
|
title: { type: String, default: 'Select Media' },
|
||||||
|
button: { type: String, default: 'Use this media' },
|
||||||
|
type: { type: String, default: 'image' }, // video
|
||||||
|
multiple: { type: Boolean, default: true },
|
||||||
|
selection: { type: Array, default: () => [] }, // [{url,id}]
|
||||||
|
},
|
||||||
|
emits: ['update:selection'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const selection: Ref<{ id: number; url: string }[]> = ref(
|
||||||
|
props.selection as { id: number; url: string }[]
|
||||||
|
)
|
||||||
|
|
||||||
|
const userInput = ref('')
|
||||||
|
|
||||||
|
const frame = (window as any).wp.media({
|
||||||
|
id: `media-frame-${uniqueHash()}`,
|
||||||
|
title: props.title,
|
||||||
|
multiple: props.multiple ? 'add' : false,
|
||||||
|
allowLocalEdits: true,
|
||||||
|
displaySettings: true,
|
||||||
|
displayUserSettings: true,
|
||||||
|
library: {
|
||||||
|
// author: uid, // specific user-posted attachment
|
||||||
|
type: props.type,
|
||||||
|
},
|
||||||
|
button: { text: props.button },
|
||||||
|
})
|
||||||
|
|
||||||
|
frame.on('select', () => {
|
||||||
|
const result = (frame.state().get('selection') as any[]).map((item) => {
|
||||||
|
const { id, url } = item.attributes
|
||||||
|
return { id: id as number, url: url as string }
|
||||||
|
})
|
||||||
|
|
||||||
|
const selected = cloneDeep(selection.value)
|
||||||
|
|
||||||
|
// Delete unchecked items
|
||||||
|
remove(selected, (item) => item.id > 0 && result.map((i) => i.id).indexOf(item.id) < 0)
|
||||||
|
|
||||||
|
// Delete existing items
|
||||||
|
remove(result, (item) => selected.map((i) => i.id).indexOf(item.id) >= 0)
|
||||||
|
|
||||||
|
selection.value = [...selected, ...result]
|
||||||
|
})
|
||||||
|
|
||||||
|
// frame.on('close', () => {
|
||||||
|
// console.log(frame.state().get('selection').toJSON())
|
||||||
|
// })
|
||||||
|
|
||||||
|
frame.on('open', () => {
|
||||||
|
const result = frame.state().get('selection')
|
||||||
|
const preSelectIds = selection.value
|
||||||
|
.map((item) => (item.id ? (window as any).wp.media.attachment(item.id) : NaN))
|
||||||
|
.filter((attachment) => attachment)
|
||||||
|
result.add(preSelectIds)
|
||||||
|
})
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
frame.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
const add = () => {
|
||||||
|
const url = userInput.value
|
||||||
|
if (isUrl(url).state) {
|
||||||
|
if (selection.value.map((item) => item.url).indexOf(url) < 0) {
|
||||||
|
selection.value.push({ id: 0, url })
|
||||||
|
userInput.value = ''
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
console.warn('Duplicate URLs')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
console.warn('Invalid URL')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const del = (index: number) => {
|
||||||
|
remove(selection.value, (item, itemIndex) => index === itemIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(selection, (value) => emit('update:selection', value), { deep: true })
|
||||||
|
|
||||||
|
return { open, add, del, userInput, selection }
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.picker__container {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
> * {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
> .row__wrapper {
|
||||||
|
&--input {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
> .input__wrapper {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
> .button__wrapper {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&--preview {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
> .image__box {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
> .image__wrapper {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
border: 1px solid #bdbdbd;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
> .delete__button {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
background: #757575;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 0 5px 0 5px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
.delete__button {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -2,13 +2,18 @@
|
|||||||
@use '@material/elevation/mdc-elevation';
|
@use '@material/elevation/mdc-elevation';
|
||||||
@use '@material/button/mdc-button';
|
@use '@material/button/mdc-button';
|
||||||
@use "@material/textfield/mdc-text-field";
|
@use "@material/textfield/mdc-text-field";
|
||||||
@use '@material/chips/deprecated/mdc-chips';
|
// @use '@material/chips/deprecated/mdc-chips';
|
||||||
@use '@material/list/mdc-list';
|
// @use '@material/list/mdc-list';
|
||||||
@use '@material/card/mdc-card';
|
@use '@material/card/mdc-card';
|
||||||
|
|
||||||
// local only
|
|
||||||
@use "@material/tab-bar/mdc-tab-bar";
|
@use "@material/tab-bar/mdc-tab-bar";
|
||||||
@use "@material/tab-scroller/mdc-tab-scroller";
|
@use "@material/tab-scroller/mdc-tab-scroller";
|
||||||
@use "@material/tab-indicator/mdc-tab-indicator";
|
@use "@material/tab-indicator/mdc-tab-indicator";
|
||||||
@use "@material/tab/mdc-tab";
|
@use "@material/tab/mdc-tab";
|
||||||
@use '@material/typography/mdc-typography';
|
// @use '@material/typography/mdc-typography';
|
||||||
|
|
||||||
|
@use "@material/checkbox/mdc-checkbox";
|
||||||
|
// @use "@material/form-field/mdc-form-field";
|
||||||
|
@use "@material/radio/mdc-radio";
|
||||||
|
// @use "@material/switch/deprecated/mdc-switch";
|
||||||
|
@use '@material/switch/styles';
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
export interface Options {
|
export interface Options {
|
||||||
[tag: string]: {
|
[tag: string]: {
|
||||||
title: string
|
title: string
|
||||||
|
desc?: string
|
||||||
icon: string
|
icon: string
|
||||||
options: Array<{
|
options: Array<{
|
||||||
namespace: string
|
namespace: string
|
||||||
|
title: string
|
||||||
|
desc?: string
|
||||||
type: string
|
type: string
|
||||||
default: any
|
default: any
|
||||||
|
binds?: { [key: string]: any }
|
||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13,17 +17,87 @@ export interface Options {
|
|||||||
const options: Options = {
|
const options: Options = {
|
||||||
basic: {
|
basic: {
|
||||||
title: 'Basic',
|
title: 'Basic',
|
||||||
|
desc: 'The basic options',
|
||||||
icon: 'fas fa-address-card',
|
icon: 'fas fa-address-card',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
namespace: 'basic.siteTitle',
|
namespace: 'basic.siteTitle',
|
||||||
|
title: 'Site title',
|
||||||
|
desc: 'The site title',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: 'Opps',
|
default: 'Opps',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
namespace: 'basic.userName',
|
namespace: 'basic.switcher',
|
||||||
type: 'string',
|
title: 'Switcher',
|
||||||
default: 'Mashiro',
|
type: 'switcher',
|
||||||
|
default: true,
|
||||||
|
binds: {
|
||||||
|
positiveLabel: 'current on',
|
||||||
|
negativeLabel: 'current off',
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
namespace: 'basic.chooseTest',
|
||||||
|
title: 'Choose Test',
|
||||||
|
desc: 'wooooo',
|
||||||
|
type: 'choose',
|
||||||
|
default: NaN,
|
||||||
|
binds: {
|
||||||
|
options: [
|
||||||
|
{ label: 'op 1', disabled: false },
|
||||||
|
{ label: 'op 2', disabled: false },
|
||||||
|
{ label: 'op 3', disabled: false },
|
||||||
|
{ label: 'op 4', disabled: true },
|
||||||
|
],
|
||||||
|
max: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
namespace: 'basic.optionsTest',
|
||||||
|
title: 'Option Test',
|
||||||
|
desc: 'wooooo',
|
||||||
|
type: 'selection',
|
||||||
|
default: [true, false, true],
|
||||||
|
binds: {
|
||||||
|
options: [
|
||||||
|
{ label: 'op 1', disabled: false },
|
||||||
|
{ label: 'op 2', disabled: false },
|
||||||
|
{ label: 'op 3', disabled: false },
|
||||||
|
{ label: 'op 4', disabled: true },
|
||||||
|
],
|
||||||
|
max: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
namespace: 'basic.longString',
|
||||||
|
title: 'Long string',
|
||||||
|
desc: 'A long string',
|
||||||
|
type: 'longString',
|
||||||
|
default: 'Opps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
namespace: 'basic.mediaPicker',
|
||||||
|
title: 'Image picker',
|
||||||
|
desc: 'Media picker',
|
||||||
|
type: 'mediaPicker',
|
||||||
|
default: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
url: 'https://view.moezx.cc/images/2021/07/02/d5ab73174d18652d890e2f4d1b9bef8f.gif',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
url: 'https://view.moezx.cc/images/2021/07/02/a90553bf5b67770e87a89b2ce204eaa7.gif',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
binds: {
|
||||||
|
title: 'Select Media',
|
||||||
|
button: 'Use this media',
|
||||||
|
type: 'image',
|
||||||
|
multiple: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -31,8 +105,14 @@ const options: Options = {
|
|||||||
title: 'Social',
|
title: 'Social',
|
||||||
icon: 'fas fa-users',
|
icon: 'fas fa-users',
|
||||||
options: [
|
options: [
|
||||||
{ namespace: 'social.github', type: 'string', default: 'mashirozx' },
|
{
|
||||||
{ namespace: 'social.weibo', type: 'string', default: 'mashirozx' },
|
namespace: 'social.github',
|
||||||
|
title: 'Github username',
|
||||||
|
desc: 'Your <a href="https://github.com" target="_blank">Github</a> username',
|
||||||
|
type: 'string',
|
||||||
|
default: 'mashirozx',
|
||||||
|
},
|
||||||
|
{ namespace: 'social.weibo', title: 'Weibo username', type: 'string', default: 'mashirozx' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
other: {
|
other: {
|
||||||
@ -41,6 +121,7 @@ const options: Options = {
|
|||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
namespace: 'other.hello',
|
namespace: 'other.hello',
|
||||||
|
title: 'Hello world',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
default: 'world',
|
default: 'world',
|
||||||
},
|
},
|
||||||
|
@ -35,5 +35,5 @@ export default function auth(): object {
|
|||||||
// return data
|
// return data
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return { config, setConfig }
|
return { config, updateOption }
|
||||||
}
|
}
|
||||||
|
20
src/admin/validator.ts
Normal file
20
src/admin/validator.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import logger from '@/utils/logger'
|
||||||
|
export default function validator<T>(value: T, type: string): { pass: boolean; msg?: string } {
|
||||||
|
switch (type) {
|
||||||
|
case 'string':
|
||||||
|
case 'longString':
|
||||||
|
return { pass: typeof value === 'string' }
|
||||||
|
case 'choose':
|
||||||
|
return { pass: typeof value === 'number' }
|
||||||
|
case 'switcher':
|
||||||
|
return { pass: typeof value === 'boolean' }
|
||||||
|
case 'selection':
|
||||||
|
return { pass: value instanceof Array }
|
||||||
|
case 'mediaPicker':
|
||||||
|
return { pass: value instanceof Array }
|
||||||
|
default:
|
||||||
|
const msg = `No such type ${type}`
|
||||||
|
logger('error', msg)
|
||||||
|
return { pass: false, msg }
|
||||||
|
}
|
||||||
|
}
|
93
src/components/checkbox/Checkbox.vue
Normal file
93
src/components/checkbox/Checkbox.vue
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<div class="checkbox__container">
|
||||||
|
<div class="mdc-checkbox mdc-checkbox--touch" :ref="setElRef" @change="handleChange">
|
||||||
|
<input type="checkbox" class="mdc-checkbox__native-control" :id="`checkbox-${id}`" />
|
||||||
|
<div class="mdc-checkbox__background">
|
||||||
|
<svg class="mdc-checkbox__checkmark" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
class="mdc-checkbox__checkmark-path"
|
||||||
|
fill="none"
|
||||||
|
d="M1.73,12.91 8.1,19.28 22.79,4.59"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div class="mdc-checkbox__mixedmark"></div>
|
||||||
|
</div>
|
||||||
|
<div class="mdc-checkbox__ripple"></div>
|
||||||
|
</div>
|
||||||
|
<label class="label" :for="`checkbox-${id}`" :id="`checkbox-label-${id}`">
|
||||||
|
{{ $props.label }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, watch, ref } from 'vue'
|
||||||
|
import { useElementRef } from '@/hooks'
|
||||||
|
import useMDCCheckbox from '@/hooks/mdc/useMDCCheckbox'
|
||||||
|
import uniqueHash from '@/utils/uniqueHash'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
label: { type: String, default: 'This is the label' },
|
||||||
|
checked: { type: Boolean, default: false },
|
||||||
|
disabled: { type: Boolean, default: false },
|
||||||
|
},
|
||||||
|
emits: ['update:checked'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const id = uniqueHash()
|
||||||
|
|
||||||
|
const [elRef, setElRef] = useElementRef()
|
||||||
|
const MDCCheckboxRef = useMDCCheckbox(elRef)
|
||||||
|
|
||||||
|
const checked = ref(props.checked)
|
||||||
|
|
||||||
|
const handleChange = () => {
|
||||||
|
if (MDCCheckboxRef.value) {
|
||||||
|
checked.value = MDCCheckboxRef.value.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.checked,
|
||||||
|
(value) => {
|
||||||
|
checked.value = value
|
||||||
|
if (MDCCheckboxRef.value) MDCCheckboxRef.value.checked = value
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.disabled,
|
||||||
|
(value) => {
|
||||||
|
if (MDCCheckboxRef.value) {
|
||||||
|
MDCCheckboxRef.value.disabled = value
|
||||||
|
// MDCCheckboxRef.value.indeterminate = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(MDCCheckboxRef, (MDCCheckbox) => {
|
||||||
|
if (MDCCheckbox) {
|
||||||
|
MDCCheckbox.checked = checked.value
|
||||||
|
MDCCheckbox.disabled = props.disabled
|
||||||
|
// MDCCheckbox.indeterminate = props.disabled
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(checked, (value) => emit('update:checked', value))
|
||||||
|
|
||||||
|
return { checked, id, setElRef, handleChange }
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.checkbox__container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
.label {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
52
src/components/checkbox/Selection.vue
Normal file
52
src/components/checkbox/Selection.vue
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<section class="selection__container">
|
||||||
|
<div class="checkbox__wrapper" v-for="(option, index) in $props.options" :key="index">
|
||||||
|
<Checkbox
|
||||||
|
v-model:checked="resultRef[index]"
|
||||||
|
:label="option.label"
|
||||||
|
:disabled="(isMax && !resultRef[index]) || option.disabled"
|
||||||
|
></Checkbox>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, watch, computed } from 'vue'
|
||||||
|
import Checkbox from './Checkbox.vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { Checkbox },
|
||||||
|
props: {
|
||||||
|
max: { type: Number, default: -1 },
|
||||||
|
result: { type: Array, default: () => [true, false, true] },
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [
|
||||||
|
{ label: 'op 1', disabled: false },
|
||||||
|
{ label: 'op 2', disabled: false },
|
||||||
|
{ label: 'op 3', disabled: false },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['update:result'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const resultRef = ref(props.result)
|
||||||
|
|
||||||
|
const isMax = computed(() => {
|
||||||
|
const { max } = props
|
||||||
|
if (max < 0) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
const count = resultRef.value.filter((x) => x).length
|
||||||
|
return count >= max
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// watch(resultRef,result=>{
|
||||||
|
// if()
|
||||||
|
// })
|
||||||
|
|
||||||
|
return { resultRef, isMax }
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
@ -3,6 +3,7 @@
|
|||||||
:class="[
|
:class="[
|
||||||
'mdc-text-field',
|
'mdc-text-field',
|
||||||
'mdc-text-field--outlined',
|
'mdc-text-field--outlined',
|
||||||
|
{ 'mdc-text-field--no-label': !$props.label },
|
||||||
{ 'mdc-text-field--with-leading-icon': $props.leadingIcon },
|
{ 'mdc-text-field--with-leading-icon': $props.leadingIcon },
|
||||||
{ 'mdc-text-field--with-trailing-icon': $props.trailingIcon },
|
{ 'mdc-text-field--with-trailing-icon': $props.trailingIcon },
|
||||||
]"
|
]"
|
||||||
@ -10,7 +11,7 @@
|
|||||||
>
|
>
|
||||||
<span class="mdc-notched-outline">
|
<span class="mdc-notched-outline">
|
||||||
<span class="mdc-notched-outline__leading"></span>
|
<span class="mdc-notched-outline__leading"></span>
|
||||||
<span class="mdc-notched-outline__notch">
|
<span class="mdc-notched-outline__notch" v-if="$props.label">
|
||||||
<span class="mdc-floating-label" :id="id">{{ $props.label }}</span>
|
<span class="mdc-floating-label" :id="id">{{ $props.label }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="mdc-notched-outline__trailing"></span>
|
<span class="mdc-notched-outline__trailing"></span>
|
||||||
@ -37,8 +38,9 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, watch } from 'vue'
|
import { defineComponent, ref, watch } from 'vue'
|
||||||
import { MD5 } from 'crypto-js'
|
import uniqueHash from '@/utils/uniqueHash'
|
||||||
import { useElementRef, useMDCTextField } from '@/hooks'
|
import { useElementRef } from '@/hooks'
|
||||||
|
import useMDCTextField from '@/hooks/mdc/useMDCTextField'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
@ -51,7 +53,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
emits: ['update:content', 'blur'],
|
emits: ['update:content', 'blur'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const id = MD5(Math.random().toString()).toString().slice(0, 8)
|
const id = uniqueHash()
|
||||||
const [textareaRef, setTextareaRef] = useElementRef()
|
const [textareaRef, setTextareaRef] = useElementRef()
|
||||||
useMDCTextField(textareaRef)
|
useMDCTextField(textareaRef)
|
||||||
|
|
||||||
|
@ -4,13 +4,14 @@
|
|||||||
'mdc-text-field',
|
'mdc-text-field',
|
||||||
'mdc-text-field--outlined',
|
'mdc-text-field--outlined',
|
||||||
'mdc-text-field--textarea',
|
'mdc-text-field--textarea',
|
||||||
|
{ 'mdc-text-field--no-label': !$props.label },
|
||||||
{ 'mdc-text-field--with-internal-counter': showCounter },
|
{ 'mdc-text-field--with-internal-counter': showCounter },
|
||||||
]"
|
]"
|
||||||
:ref="setTextareaRef"
|
:ref="setTextareaRef"
|
||||||
>
|
>
|
||||||
<span class="mdc-notched-outline">
|
<span class="mdc-notched-outline">
|
||||||
<span class="mdc-notched-outline__leading"></span>
|
<span class="mdc-notched-outline__leading"></span>
|
||||||
<span class="mdc-notched-outline__notch">
|
<span class="mdc-notched-outline__notch" v-if="$props.label">
|
||||||
<span class="mdc-floating-label" :id="id">{{ label }}</span>
|
<span class="mdc-floating-label" :id="id">{{ label }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="mdc-notched-outline__trailing"></span>
|
<span class="mdc-notched-outline__trailing"></span>
|
||||||
@ -31,8 +32,9 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, computed, ref, watch } from 'vue'
|
import { defineComponent, computed, ref, watch } from 'vue'
|
||||||
import { MD5 } from 'crypto-js'
|
import uniqueHash from '@/utils/uniqueHash'
|
||||||
import { useElementRef, useMDCTextField } from '@/hooks'
|
import { useElementRef } from '@/hooks'
|
||||||
|
import useMDCTextField from '@/hooks/mdc/useMDCTextField'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
@ -47,7 +49,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
emits: ['update:content'],
|
emits: ['update:content'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const id = MD5(Math.random().toString()).toString().slice(0, 8)
|
const id = uniqueHash()
|
||||||
|
|
||||||
const [textareaRef, setTextareaRef] = useElementRef()
|
const [textareaRef, setTextareaRef] = useElementRef()
|
||||||
useMDCTextField(textareaRef)
|
useMDCTextField(textareaRef)
|
||||||
|
82
src/components/radio/Choose.vue
Normal file
82
src/components/radio/Choose.vue
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<template>
|
||||||
|
<section class="selection__container">
|
||||||
|
<div class="checkbox__wrapper" v-for="(option, index) in $props.options" :key="index">
|
||||||
|
<RadioButton
|
||||||
|
v-model:checked="arrayRef[index]"
|
||||||
|
:label="option.label"
|
||||||
|
:disabled="option.disabled"
|
||||||
|
></RadioButton>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, watch, computed, Ref } from 'vue'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
import RadioButton from './RadioButton.vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: { RadioButton },
|
||||||
|
props: {
|
||||||
|
result: { type: Number, default: () => NaN },
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [
|
||||||
|
{ label: 'op 1', disabled: false },
|
||||||
|
{ label: 'op 2', disabled: false },
|
||||||
|
{ label: 'op 3', disabled: false },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['update:result'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const arrayRef: Ref<boolean[]> = ref(
|
||||||
|
Array(props.options.length)
|
||||||
|
.fill(false)
|
||||||
|
.map((item, index) => index === props.result)
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO: watcher's bug on deep mode: https://github.com/vuejs/vue/issues/2164
|
||||||
|
const cacheArrayRef = computed(() => cloneDeep(arrayRef.value))
|
||||||
|
|
||||||
|
watch(
|
||||||
|
cacheArrayRef,
|
||||||
|
(n, o) => {
|
||||||
|
if (n.indexOf(true) < 0) return
|
||||||
|
n.forEach((_n, index) => {
|
||||||
|
if (_n && _n !== o[index]) {
|
||||||
|
const a = cloneDeep(arrayRef.value)
|
||||||
|
a.fill(false)
|
||||||
|
a[index] = true
|
||||||
|
arrayRef.value = a
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
arrayRef,
|
||||||
|
(arr) => {
|
||||||
|
const value = arr.indexOf(true)
|
||||||
|
if (value > -1) {
|
||||||
|
emit('update:result', value)
|
||||||
|
} else {
|
||||||
|
emit('update:result', NaN)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.options,
|
||||||
|
(options) =>
|
||||||
|
(arrayRef.value = Array(options.length)
|
||||||
|
.fill(false)
|
||||||
|
.map((item, index) => index === props.result))
|
||||||
|
)
|
||||||
|
|
||||||
|
return { arrayRef }
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
91
src/components/radio/RadioButton.vue
Normal file
91
src/components/radio/RadioButton.vue
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<div class="radio__container">
|
||||||
|
<div class="mdc-radio" :ref="setElRef">
|
||||||
|
<input
|
||||||
|
class="mdc-radio__native-control"
|
||||||
|
type="checkbox"
|
||||||
|
:id="`radio-${id}`"
|
||||||
|
:name="`radio-${id}`"
|
||||||
|
@change="handleChange"
|
||||||
|
/>
|
||||||
|
<div class="mdc-radio__background">
|
||||||
|
<div class="mdc-radio__outer-circle"></div>
|
||||||
|
<div class="mdc-radio__inner-circle"></div>
|
||||||
|
</div>
|
||||||
|
<div class="mdc-radio__ripple"></div>
|
||||||
|
</div>
|
||||||
|
<label class="label" :for="`radio-${id}`">{{ $props.label }}</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, watch, ref } from 'vue'
|
||||||
|
import { useElementRef } from '@/hooks'
|
||||||
|
import uniqueHash from '@/utils/uniqueHash'
|
||||||
|
import useMDCRadio from '@/hooks/mdc/useMDCRadio'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
label: { type: String, default: 'This is the label' },
|
||||||
|
checked: { type: Boolean, default: false },
|
||||||
|
disabled: { type: Boolean, default: false },
|
||||||
|
},
|
||||||
|
emits: ['update:checked'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const id = uniqueHash()
|
||||||
|
|
||||||
|
const [elRef, setElRef] = useElementRef()
|
||||||
|
|
||||||
|
const MDCRadioRef = useMDCRadio(elRef)
|
||||||
|
|
||||||
|
const checked = ref(props.checked)
|
||||||
|
|
||||||
|
const handleChange = (event: Event) => {
|
||||||
|
if (!props.disabled) checked.value = !checked.value
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.checked,
|
||||||
|
(value) => {
|
||||||
|
checked.value = value
|
||||||
|
if (MDCRadioRef.value) MDCRadioRef.value.checked = value
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.disabled,
|
||||||
|
(value) => {
|
||||||
|
if (MDCRadioRef.value) {
|
||||||
|
MDCRadioRef.value.disabled = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(MDCRadioRef, (MDCCheckbox) => {
|
||||||
|
if (MDCCheckbox) {
|
||||||
|
MDCCheckbox.checked = checked.value
|
||||||
|
MDCCheckbox.disabled = props.disabled
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(checked, (value) => {
|
||||||
|
if (MDCRadioRef.value) MDCRadioRef.value.checked = value
|
||||||
|
emit('update:checked', value)
|
||||||
|
})
|
||||||
|
|
||||||
|
return { checked, id, setElRef, handleChange }
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.radio__container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
.label {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
106
src/components/switcher/Switcher.vue
Normal file
106
src/components/switcher/Switcher.vue
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<div class="switcher__container">
|
||||||
|
<button
|
||||||
|
:id="`switch-${id}`"
|
||||||
|
class="mdc-switch mdc-switch--unselected"
|
||||||
|
role="switch"
|
||||||
|
:aria-checked="checked"
|
||||||
|
:ref="setElRef"
|
||||||
|
@click="handleChange"
|
||||||
|
>
|
||||||
|
<div class="mdc-switch__track"></div>
|
||||||
|
<div class="mdc-switch__handle-track">
|
||||||
|
<div class="mdc-switch__handle">
|
||||||
|
<div class="mdc-switch__shadow">
|
||||||
|
<div class="mdc-elevation-overlay"></div>
|
||||||
|
</div>
|
||||||
|
<div class="mdc-switch__ripple"></div>
|
||||||
|
<div class="mdc-switch__icons">
|
||||||
|
<svg class="mdc-switch__icon mdc-switch__icon--on" viewBox="0 0 24 24">
|
||||||
|
<path d="M19.69,5.23L8.96,15.96l-4.23-4.23L2.96,13.5l6,6L21.46,7L19.69,5.23z" />
|
||||||
|
</svg>
|
||||||
|
<svg class="mdc-switch__icon mdc-switch__icon--off" viewBox="0 0 24 24">
|
||||||
|
<path d="M20 13H4v-2h16v2z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<label class="label" :for="`switch-${id}`">
|
||||||
|
{{ checked ? $props.positiveLabel : $props.negativeLabel }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, watch } from 'vue'
|
||||||
|
import uniqueHash from '@/utils/uniqueHash'
|
||||||
|
import { useElementRef } from '@/hooks'
|
||||||
|
import useMDCSwitch from '@/hooks/mdc/useMDCSwitch'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
positiveLabel: { type: String, default: 'current on' },
|
||||||
|
negativeLabel: { type: String, default: 'current off' },
|
||||||
|
checked: { type: Boolean, default: true },
|
||||||
|
disabled: { type: Boolean, default: false },
|
||||||
|
},
|
||||||
|
emits: ['update:checked'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const id = uniqueHash()
|
||||||
|
|
||||||
|
const [elRef, setElRef] = useElementRef()
|
||||||
|
const MDCSwitchRef = useMDCSwitch(elRef)
|
||||||
|
|
||||||
|
const checked = ref(props.checked)
|
||||||
|
|
||||||
|
const handleChange = () => {
|
||||||
|
if (MDCSwitchRef.value) {
|
||||||
|
checked.value = !MDCSwitchRef.value.selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.checked,
|
||||||
|
(value) => {
|
||||||
|
checked.value = value
|
||||||
|
if (MDCSwitchRef.value) MDCSwitchRef.value.selected = !value
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.disabled,
|
||||||
|
(value) => {
|
||||||
|
if (MDCSwitchRef.value) {
|
||||||
|
MDCSwitchRef.value.disabled = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(MDCSwitchRef, (MDCCheckbox) => {
|
||||||
|
if (MDCCheckbox) {
|
||||||
|
MDCCheckbox.selected = checked.value
|
||||||
|
MDCCheckbox.disabled = props.disabled
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(checked, (value) => emit('update:checked', value))
|
||||||
|
|
||||||
|
return { id, setElRef, handleChange, checked }
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.switcher__container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
.label {
|
||||||
|
user-select: none;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -33,7 +33,8 @@
|
|||||||
import { defineComponent, onMounted, watch } from 'vue'
|
import { defineComponent, onMounted, watch } from 'vue'
|
||||||
import { useState } from '@/hooks'
|
import { useState } from '@/hooks'
|
||||||
import { MD5 } from 'crypto-js'
|
import { MD5 } from 'crypto-js'
|
||||||
import { useElementRef, useMDCTabBar } from '@/hooks'
|
import { useElementRef } from '@/hooks'
|
||||||
|
import useMDCTabBar from '@/hooks/mdc/useMDCTabBar'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
|
@ -7,7 +7,7 @@ import useResizeObserver from './useResizeObserver'
|
|||||||
import useReachElementSide from './useReachElementSide'
|
import useReachElementSide from './useReachElementSide'
|
||||||
import { useElementRef, useElementRefs } from './useElementRef'
|
import { useElementRef, useElementRefs } from './useElementRef'
|
||||||
import useOffsetDistance from './useOffsetDistance'
|
import useOffsetDistance from './useOffsetDistance'
|
||||||
import { useMDCRipple, useMDCDialog, useMDCTextField, useMDCTabBar } from './mdc'
|
import useMDCRipple from './mdc/useMDCRipple'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
useState,
|
useState,
|
||||||
@ -22,9 +22,6 @@ export {
|
|||||||
useWindowResize,
|
useWindowResize,
|
||||||
useResizeObserver,
|
useResizeObserver,
|
||||||
useMDCRipple,
|
useMDCRipple,
|
||||||
useMDCDialog,
|
|
||||||
useMDCTextField,
|
|
||||||
useMDCTabBar,
|
|
||||||
useReachElementSide,
|
useReachElementSide,
|
||||||
useElementRef,
|
useElementRef,
|
||||||
useElementRefs,
|
useElementRefs,
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
import { ref, Ref, watch, onBeforeUnmount } from 'vue'
|
|
||||||
import { MDCRipple } from '@material/ripple'
|
|
||||||
import { MDCDialog } from '@material/dialog'
|
|
||||||
import { MDCTextField } from '@material/textfield'
|
|
||||||
import { MDCTabBar } from '@material/tab-bar'
|
|
||||||
|
|
||||||
export const useMDCRipple = <El>(
|
|
||||||
elementRef: El extends Element ? Element : Ref<Element | null>,
|
|
||||||
unbounded = false
|
|
||||||
) => {
|
|
||||||
const rippleRef: Ref<MDCRipple | null> = ref(null)
|
|
||||||
|
|
||||||
if (elementRef instanceof Element) {
|
|
||||||
rippleRef.value = new MDCRipple(elementRef)
|
|
||||||
} else {
|
|
||||||
watch(elementRef, (element) => {
|
|
||||||
if (element) {
|
|
||||||
rippleRef.value = new MDCRipple(element)
|
|
||||||
if (unbounded) rippleRef.value.unbounded = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
rippleRef.value?.destroy()
|
|
||||||
})
|
|
||||||
|
|
||||||
return rippleRef
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useMDCDialog = <El>(
|
|
||||||
elementRef: El extends Element ? Element : Ref<Element | null>
|
|
||||||
) => {
|
|
||||||
const dialogRef: Ref<MDCDialog | null> = ref(null)
|
|
||||||
|
|
||||||
if (elementRef instanceof Element) {
|
|
||||||
dialogRef.value = new MDCDialog(elementRef)
|
|
||||||
} else {
|
|
||||||
watch(elementRef, (element) => {
|
|
||||||
if (element) {
|
|
||||||
dialogRef.value = new MDCDialog(element)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
dialogRef.value?.destroy()
|
|
||||||
})
|
|
||||||
|
|
||||||
return dialogRef
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useMDCTextField = <El>(
|
|
||||||
elementRef: El extends Element ? Element : Ref<Element | null>
|
|
||||||
) => {
|
|
||||||
const textFieldRef: Ref<MDCTextField | null> = ref(null)
|
|
||||||
|
|
||||||
if (elementRef instanceof Element) {
|
|
||||||
textFieldRef.value = new MDCTextField(elementRef)
|
|
||||||
} else {
|
|
||||||
watch(elementRef, (element) => {
|
|
||||||
if (element) {
|
|
||||||
textFieldRef.value = new MDCTextField(element)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
textFieldRef.value?.destroy()
|
|
||||||
})
|
|
||||||
|
|
||||||
return textFieldRef
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useMDCTabBar = <El>(
|
|
||||||
elementRef: El extends Element ? Element : Ref<Element | null>
|
|
||||||
) => {
|
|
||||||
const tabBarRef: Ref<MDCTabBar | null> = ref(null)
|
|
||||||
|
|
||||||
if (elementRef instanceof Element) {
|
|
||||||
tabBarRef.value = new MDCTabBar(elementRef)
|
|
||||||
} else {
|
|
||||||
watch(elementRef, (element) => {
|
|
||||||
if (element) {
|
|
||||||
tabBarRef.value = new MDCTabBar(element)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
tabBarRef.value?.destroy()
|
|
||||||
})
|
|
||||||
|
|
||||||
return tabBarRef
|
|
||||||
}
|
|
24
src/hooks/mdc/useMDCCheckbox.ts
Normal file
24
src/hooks/mdc/useMDCCheckbox.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { ref, Ref, watch, onBeforeUnmount } from 'vue'
|
||||||
|
import { MDCCheckbox } from '@material/checkbox'
|
||||||
|
|
||||||
|
const useMDCCheckbox = <El>(elementRef: El extends Element ? Element : Ref<Element | null>) => {
|
||||||
|
const mdcRef: Ref<MDCCheckbox | null> = ref(null)
|
||||||
|
|
||||||
|
if (elementRef instanceof Element) {
|
||||||
|
mdcRef.value = new MDCCheckbox(elementRef)
|
||||||
|
} else {
|
||||||
|
watch(elementRef, (element) => {
|
||||||
|
if (element) {
|
||||||
|
mdcRef.value = new MDCCheckbox(element)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
mdcRef.value?.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
|
return mdcRef
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMDCCheckbox
|
24
src/hooks/mdc/useMDCDialog.ts
Normal file
24
src/hooks/mdc/useMDCDialog.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { ref, Ref, watch, onBeforeUnmount } from 'vue'
|
||||||
|
import { MDCDialog } from '@material/dialog'
|
||||||
|
|
||||||
|
const useMDCDialog = <El>(elementRef: El extends Element ? Element : Ref<Element | null>) => {
|
||||||
|
const mdcRef: Ref<MDCDialog | null> = ref(null)
|
||||||
|
|
||||||
|
if (elementRef instanceof Element) {
|
||||||
|
mdcRef.value = new MDCDialog(elementRef)
|
||||||
|
} else {
|
||||||
|
watch(elementRef, (element) => {
|
||||||
|
if (element) {
|
||||||
|
mdcRef.value = new MDCDialog(element)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
mdcRef.value?.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
|
return mdcRef
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMDCDialog
|
24
src/hooks/mdc/useMDCRadio.ts
Normal file
24
src/hooks/mdc/useMDCRadio.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { ref, Ref, watch, onBeforeUnmount } from 'vue'
|
||||||
|
import { MDCRadio } from '@material/radio'
|
||||||
|
|
||||||
|
const useMDCRadio = <El>(elementRef: El extends Element ? Element : Ref<Element | null>) => {
|
||||||
|
const mdcRef: Ref<MDCRadio | null> = ref(null)
|
||||||
|
|
||||||
|
if (elementRef instanceof Element) {
|
||||||
|
mdcRef.value = new MDCRadio(elementRef)
|
||||||
|
} else {
|
||||||
|
watch(elementRef, (element) => {
|
||||||
|
if (element) {
|
||||||
|
mdcRef.value = new MDCRadio(element)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
mdcRef.value?.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
|
return mdcRef
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMDCRadio
|
28
src/hooks/mdc/useMDCRipple.ts
Normal file
28
src/hooks/mdc/useMDCRipple.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { ref, Ref, watch, onBeforeUnmount } from 'vue'
|
||||||
|
import { MDCRipple } from '@material/ripple'
|
||||||
|
|
||||||
|
const useMDCRipple = <El>(
|
||||||
|
elementRef: El extends Element ? Element : Ref<Element | null>,
|
||||||
|
unbounded = false
|
||||||
|
) => {
|
||||||
|
const rippleRef: Ref<MDCRipple | null> = ref(null)
|
||||||
|
|
||||||
|
if (elementRef instanceof Element) {
|
||||||
|
rippleRef.value = new MDCRipple(elementRef)
|
||||||
|
} else {
|
||||||
|
watch(elementRef, (element) => {
|
||||||
|
if (element) {
|
||||||
|
rippleRef.value = new MDCRipple(element)
|
||||||
|
if (unbounded) rippleRef.value.unbounded = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
rippleRef.value?.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
|
return rippleRef
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMDCRipple
|
24
src/hooks/mdc/useMDCSwitch.ts
Normal file
24
src/hooks/mdc/useMDCSwitch.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { ref, Ref, watch, onBeforeUnmount } from 'vue'
|
||||||
|
import { MDCSwitch } from '@material/switch'
|
||||||
|
|
||||||
|
const useMDCSwitch = <El>(elementRef: El extends Element ? Element : Ref<Element | null>) => {
|
||||||
|
const mdcRef: Ref<MDCSwitch | null> = ref(null)
|
||||||
|
|
||||||
|
if (elementRef instanceof Element) {
|
||||||
|
mdcRef.value = new MDCSwitch(elementRef as HTMLButtonElement)
|
||||||
|
} else {
|
||||||
|
watch(elementRef, (element) => {
|
||||||
|
if (element) {
|
||||||
|
mdcRef.value = new MDCSwitch(element as HTMLButtonElement)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
mdcRef.value?.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
|
return mdcRef
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMDCSwitch
|
24
src/hooks/mdc/useMDCTabBar.ts
Normal file
24
src/hooks/mdc/useMDCTabBar.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { ref, Ref, watch, onBeforeUnmount } from 'vue'
|
||||||
|
import { MDCTabBar } from '@material/tab-bar'
|
||||||
|
|
||||||
|
const useMDCTabBar = <El>(elementRef: El extends Element ? Element : Ref<Element | null>) => {
|
||||||
|
const tabBarRef: Ref<MDCTabBar | null> = ref(null)
|
||||||
|
|
||||||
|
if (elementRef instanceof Element) {
|
||||||
|
tabBarRef.value = new MDCTabBar(elementRef)
|
||||||
|
} else {
|
||||||
|
watch(elementRef, (element) => {
|
||||||
|
if (element) {
|
||||||
|
tabBarRef.value = new MDCTabBar(element)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
tabBarRef.value?.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
|
return tabBarRef
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMDCTabBar
|
24
src/hooks/mdc/useMDCTextField.ts
Normal file
24
src/hooks/mdc/useMDCTextField.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { ref, Ref, watch, onBeforeUnmount } from 'vue'
|
||||||
|
import { MDCTextField } from '@material/textfield'
|
||||||
|
|
||||||
|
const useMDCTextField = <El>(elementRef: El extends Element ? Element : Ref<Element | null>) => {
|
||||||
|
const textFieldRef: Ref<MDCTextField | null> = ref(null)
|
||||||
|
|
||||||
|
if (elementRef instanceof Element) {
|
||||||
|
textFieldRef.value = new MDCTextField(elementRef)
|
||||||
|
} else {
|
||||||
|
watch(elementRef, (element) => {
|
||||||
|
if (element) {
|
||||||
|
textFieldRef.value = new MDCTextField(element)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
textFieldRef.value?.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
|
return textFieldRef
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMDCTextField
|
5
src/utils/uniqueHash.ts
Normal file
5
src/utils/uniqueHash.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { MD5 } from 'crypto-js'
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
return MD5(Math.random().toString()).toString().slice(0, 8)
|
||||||
|
}
|
13
src/utils/urlHelper.ts
Normal file
13
src/utils/urlHelper.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export const isUrl = (url: string): { state: boolean; msg?: any } => {
|
||||||
|
try {
|
||||||
|
new URL(url)
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
state: false,
|
||||||
|
msg: error,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
state: true,
|
||||||
|
}
|
||||||
|
}
|
253
yarn.lock
253
yarn.lock
@ -685,6 +685,20 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/animation@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/animation/download/@material/animation-12.0.0-canary.9f68a932e.0.tgz#8deafa2e91db38d4f4ec4303c1eeba8a7e6b1586"
|
||||||
|
integrity sha1-jer6LpHbONT07EMDwe66in5rFYY=
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/animation@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/animation/download/@material/animation-12.0.0-canary.e1703bed9.0.tgz#d3f758c0ae65223b9459cfc3c35cd1313bb377bc"
|
||||||
|
integrity sha1-0/dYwK5lIjuUWc/Dw1zRMTuzd7w=
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/base@12.0.0-canary.068fd5028.0":
|
"@material/base@12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/base/download/@material/base-12.0.0-canary.068fd5028.0.tgz#ba4403e153550bfd44c6f4d74af27c43be94b23b"
|
resolved "https://registry.nlark.com/@material/base/download/@material/base-12.0.0-canary.068fd5028.0.tgz#ba4403e153550bfd44c6f4d74af27c43be94b23b"
|
||||||
@ -699,6 +713,20 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/base@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/base/download/@material/base-12.0.0-canary.9f68a932e.0.tgz#416b1ea1646de2585b9f6334b721eb32f27e1b62"
|
||||||
|
integrity sha1-QWseoWRt4lhbn2M0tyHrMvJ+G2I=
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/base@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/base/download/@material/base-12.0.0-canary.e1703bed9.0.tgz#b516620d7217a18955e694589c230d536ec04acd"
|
||||||
|
integrity sha1-tRZiDXIXoYlV5pRYnCMNU27ASs0=
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/button@12.0.0-canary.068fd5028.0", "@material/button@^12.0.0-canary.068fd5028.0":
|
"@material/button@12.0.0-canary.068fd5028.0", "@material/button@^12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/button/download/@material/button-12.0.0-canary.068fd5028.0.tgz#dea53b2914e4bd48c94fd8d6c3915c377ff6a326"
|
resolved "https://registry.nlark.com/@material/button/download/@material/button-12.0.0-canary.068fd5028.0.tgz#dea53b2914e4bd48c94fd8d6c3915c377ff6a326"
|
||||||
@ -745,6 +773,21 @@
|
|||||||
"@material/touch-target" "12.0.0-canary.068fd5028.0"
|
"@material/touch-target" "12.0.0-canary.068fd5028.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/checkbox@^12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/checkbox/download/@material/checkbox-12.0.0-canary.e1703bed9.0.tgz#97956408491070c2ffdf1bb718af23a35b5370c0"
|
||||||
|
integrity sha1-l5VkCEkQcML/3xu3GK8jo1tTcMA=
|
||||||
|
dependencies:
|
||||||
|
"@material/animation" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/base" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/density" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/dom" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/ripple" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/theme" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/touch-target" "12.0.0-canary.e1703bed9.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/chips@^12.0.0-canary.068fd5028.0":
|
"@material/chips@^12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/chips/download/@material/chips-12.0.0-canary.068fd5028.0.tgz#92f1f6fa3aef8906a34b3fe9e3f351861d0ab6df"
|
resolved "https://registry.nlark.com/@material/chips/download/@material/chips-12.0.0-canary.068fd5028.0.tgz#92f1f6fa3aef8906a34b3fe9e3f351861d0ab6df"
|
||||||
@ -779,6 +822,20 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/density@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/density/download/@material/density-12.0.0-canary.9f68a932e.0.tgz#e1aba9fb3242c3e94223700da4cbf6178bfe3170"
|
||||||
|
integrity sha1-4aup+zJCw+lCI3ANpMv2F4v+MXA=
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/density@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/density/download/@material/density-12.0.0-canary.e1703bed9.0.tgz#6f73f9a73dbc607c20f06a4dfa69bc041fac9a31"
|
||||||
|
integrity sha1-b3P5pz28YHwg8GpN+mm8BB+smjE=
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/dialog@^12.0.0-canary.068fd5028.0":
|
"@material/dialog@^12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/dialog/download/@material/dialog-12.0.0-canary.068fd5028.0.tgz#ad0990c32b4c3538ce469297ca2b7f1f71abc84a"
|
resolved "https://registry.nlark.com/@material/dialog/download/@material/dialog-12.0.0-canary.068fd5028.0.tgz#ad0990c32b4c3538ce469297ca2b7f1f71abc84a"
|
||||||
@ -815,6 +872,22 @@
|
|||||||
"@material/feature-targeting" "12.0.0-canary.22d29cbb4.0"
|
"@material/feature-targeting" "12.0.0-canary.22d29cbb4.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/dom@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/dom/download/@material/dom-12.0.0-canary.9f68a932e.0.tgz#e9baf1e7622cad75689245a703165e7d3c3eb16b"
|
||||||
|
integrity sha1-6brx52IsrXVokkWnAxZefTw+sWs=
|
||||||
|
dependencies:
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.9f68a932e.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/dom@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/dom/download/@material/dom-12.0.0-canary.e1703bed9.0.tgz#46fddbf9a0171409f144d5df618a4fc3887cc432"
|
||||||
|
integrity sha1-Rv3b+aAXFAnxRNXfYYpPw4h8xDI=
|
||||||
|
dependencies:
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.e1703bed9.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/elevation@12.0.0-canary.068fd5028.0", "@material/elevation@^12.0.0-canary.068fd5028.0":
|
"@material/elevation@12.0.0-canary.068fd5028.0", "@material/elevation@^12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/elevation/download/@material/elevation-12.0.0-canary.068fd5028.0.tgz#0c670ae52c8f83491b06e31c95917c7ea37ca9ea"
|
resolved "https://registry.nlark.com/@material/elevation/download/@material/elevation-12.0.0-canary.068fd5028.0.tgz#0c670ae52c8f83491b06e31c95917c7ea37ca9ea"
|
||||||
@ -837,6 +910,17 @@
|
|||||||
"@material/theme" "12.0.0-canary.22d29cbb4.0"
|
"@material/theme" "12.0.0-canary.22d29cbb4.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/elevation@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/elevation/download/@material/elevation-12.0.0-canary.9f68a932e.0.tgz#3bd2d5b30b27e43f5f4d822abe0693e52c6ce297"
|
||||||
|
integrity sha1-O9LVswsn5D9fTYIqvgaT5Sxs4pc=
|
||||||
|
dependencies:
|
||||||
|
"@material/animation" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/base" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/theme" "12.0.0-canary.9f68a932e.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/feature-targeting@12.0.0-canary.068fd5028.0":
|
"@material/feature-targeting@12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/feature-targeting/download/@material/feature-targeting-12.0.0-canary.068fd5028.0.tgz#e043d1f549bfd1a6e647486a354dcb7b04c7afb3"
|
resolved "https://registry.nlark.com/@material/feature-targeting/download/@material/feature-targeting-12.0.0-canary.068fd5028.0.tgz#e043d1f549bfd1a6e647486a354dcb7b04c7afb3"
|
||||||
@ -851,6 +935,20 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/feature-targeting@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/feature-targeting/download/@material/feature-targeting-12.0.0-canary.9f68a932e.0.tgz#8ec6b30b59558f8a84f63aa00dd2ce870ff6844c"
|
||||||
|
integrity sha1-jsazC1lVj4qE9jqgDdLOhw/2hEw=
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/feature-targeting@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/feature-targeting/download/@material/feature-targeting-12.0.0-canary.e1703bed9.0.tgz#ce6d8a3111c1b20ecaab13c73c975fa8bd9d59b6"
|
||||||
|
integrity sha1-zm2KMRHBsg7KqxPHPJdfqL2dWbY=
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/floating-label@12.0.0-canary.068fd5028.0":
|
"@material/floating-label@12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/floating-label/download/@material/floating-label-12.0.0-canary.068fd5028.0.tgz#db76cda2d1de4482ddca5df854e1c1e5efe73ac5"
|
resolved "https://registry.nlark.com/@material/floating-label/download/@material/floating-label-12.0.0-canary.068fd5028.0.tgz#db76cda2d1de4482ddca5df854e1c1e5efe73ac5"
|
||||||
@ -865,6 +963,19 @@
|
|||||||
"@material/typography" "12.0.0-canary.068fd5028.0"
|
"@material/typography" "12.0.0-canary.068fd5028.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/form-field@^12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/form-field/download/@material/form-field-12.0.0-canary.e1703bed9.0.tgz#82788ff08eeed0494598bde00b73992f14c7a585"
|
||||||
|
integrity sha1-gniP8I7u0ElFmL3gC3OZLxTHpYU=
|
||||||
|
dependencies:
|
||||||
|
"@material/base" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/ripple" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/rtl" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/theme" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/typography" "12.0.0-canary.e1703bed9.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/icon-button@12.0.0-canary.068fd5028.0":
|
"@material/icon-button@12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/icon-button/download/@material/icon-button-12.0.0-canary.068fd5028.0.tgz#eccd2bc14fd984817ae090e9c09433b1e94e1f46"
|
resolved "https://registry.nlark.com/@material/icon-button/download/@material/icon-button-12.0.0-canary.068fd5028.0.tgz#eccd2bc14fd984817ae090e9c09433b1e94e1f46"
|
||||||
@ -949,6 +1060,21 @@
|
|||||||
"@material/theme" "12.0.0-canary.068fd5028.0"
|
"@material/theme" "12.0.0-canary.068fd5028.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/radio@^12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/radio/download/@material/radio-12.0.0-canary.9f68a932e.0.tgz#8c329ccb1057aafff079cf28a2efeb01d341d156"
|
||||||
|
integrity sha1-jDKcyxBXqv/wec8oou/rAdNB0VY=
|
||||||
|
dependencies:
|
||||||
|
"@material/animation" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/base" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/density" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/dom" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/ripple" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/theme" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/touch-target" "12.0.0-canary.9f68a932e.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/ripple@12.0.0-canary.068fd5028.0", "@material/ripple@^12.0.0-canary.068fd5028.0":
|
"@material/ripple@12.0.0-canary.068fd5028.0", "@material/ripple@^12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/ripple/download/@material/ripple-12.0.0-canary.068fd5028.0.tgz#e1570b1e45b47bdb6166198abb47236bce3be689"
|
resolved "https://registry.nlark.com/@material/ripple/download/@material/ripple-12.0.0-canary.068fd5028.0.tgz#e1570b1e45b47bdb6166198abb47236bce3be689"
|
||||||
@ -973,6 +1099,30 @@
|
|||||||
"@material/theme" "12.0.0-canary.22d29cbb4.0"
|
"@material/theme" "12.0.0-canary.22d29cbb4.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/ripple@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/ripple/download/@material/ripple-12.0.0-canary.9f68a932e.0.tgz#cd923b2560250698215775cd67bd446b6a5e5e9b"
|
||||||
|
integrity sha1-zZI7JWAlBpghV3XNZ71Ea2peXps=
|
||||||
|
dependencies:
|
||||||
|
"@material/animation" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/base" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/dom" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/theme" "12.0.0-canary.9f68a932e.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/ripple@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/ripple/download/@material/ripple-12.0.0-canary.e1703bed9.0.tgz#2fc99d599b4d4fc67834e62e3abc06719a561652"
|
||||||
|
integrity sha1-L8mdWZtNT8Z4NOYuOrwGcZpWFlI=
|
||||||
|
dependencies:
|
||||||
|
"@material/animation" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/base" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/dom" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/theme" "12.0.0-canary.e1703bed9.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/rtl@12.0.0-canary.068fd5028.0":
|
"@material/rtl@12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/rtl/download/@material/rtl-12.0.0-canary.068fd5028.0.tgz#e7a24ffdc7ef2419433a29c9fed4a0bd79e9086b"
|
resolved "https://registry.nlark.com/@material/rtl/download/@material/rtl-12.0.0-canary.068fd5028.0.tgz#e7a24ffdc7ef2419433a29c9fed4a0bd79e9086b"
|
||||||
@ -989,6 +1139,22 @@
|
|||||||
"@material/theme" "12.0.0-canary.22d29cbb4.0"
|
"@material/theme" "12.0.0-canary.22d29cbb4.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/rtl@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/rtl/download/@material/rtl-12.0.0-canary.9f68a932e.0.tgz#268bff8f0d9d6eb43803269ecd401b5a7e69c909"
|
||||||
|
integrity sha1-Jov/jw2dbrQ4AyaezUAbWn5pyQk=
|
||||||
|
dependencies:
|
||||||
|
"@material/theme" "12.0.0-canary.9f68a932e.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/rtl@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/rtl/download/@material/rtl-12.0.0-canary.e1703bed9.0.tgz#52c0a7b09ce2dc52cac5df126e56be36ef8557fa"
|
||||||
|
integrity sha1-UsCnsJzi3FLKxd8Sbla+Nu+FV/o=
|
||||||
|
dependencies:
|
||||||
|
"@material/theme" "12.0.0-canary.e1703bed9.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/shape@12.0.0-canary.068fd5028.0":
|
"@material/shape@12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/shape/download/@material/shape-12.0.0-canary.068fd5028.0.tgz#e68f58979314a23a3486105a8f91482b8c8e9130"
|
resolved "https://registry.nlark.com/@material/shape/download/@material/shape-12.0.0-canary.068fd5028.0.tgz#e68f58979314a23a3486105a8f91482b8c8e9130"
|
||||||
@ -999,6 +1165,34 @@
|
|||||||
"@material/theme" "12.0.0-canary.068fd5028.0"
|
"@material/theme" "12.0.0-canary.068fd5028.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/shape@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/shape/download/@material/shape-12.0.0-canary.9f68a932e.0.tgz#cb0466b1e8409c3c9e6143fe6d28d6d97d9ee11a"
|
||||||
|
integrity sha1-ywRmsehAnDyeYUP+bSjW2X2e4Ro=
|
||||||
|
dependencies:
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/rtl" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/theme" "12.0.0-canary.9f68a932e.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/switch@^12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/switch/download/@material/switch-12.0.0-canary.9f68a932e.0.tgz#2089bcad64039c7d93917faa321392f5dd7dc5cd"
|
||||||
|
integrity sha1-IIm8rWQDnH2TkX+qMhOS9d19xc0=
|
||||||
|
dependencies:
|
||||||
|
"@material/animation" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/base" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/density" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/dom" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/elevation" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/ripple" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/rtl" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/shape" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/theme" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/tokens" "12.0.0-canary.9f68a932e.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/tab-bar@^12.0.0-canary.22d29cbb4.0":
|
"@material/tab-bar@^12.0.0-canary.22d29cbb4.0":
|
||||||
version "12.0.0-canary.22d29cbb4.0"
|
version "12.0.0-canary.22d29cbb4.0"
|
||||||
resolved "https://registry.nlark.com/@material/tab-bar/download/@material/tab-bar-12.0.0-canary.22d29cbb4.0.tgz#294a67f387e80cccade1700ab15ae79d9faee394"
|
resolved "https://registry.nlark.com/@material/tab-bar/download/@material/tab-bar-12.0.0-canary.22d29cbb4.0.tgz#294a67f387e80cccade1700ab15ae79d9faee394"
|
||||||
@ -1090,6 +1284,29 @@
|
|||||||
"@material/feature-targeting" "12.0.0-canary.22d29cbb4.0"
|
"@material/feature-targeting" "12.0.0-canary.22d29cbb4.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/theme@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/theme/download/@material/theme-12.0.0-canary.9f68a932e.0.tgz#58cc520689b3c3c3a2852c42117376b0c363cf75"
|
||||||
|
integrity sha1-WMxSBomzw8OihSxCEXN2sMNjz3U=
|
||||||
|
dependencies:
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.9f68a932e.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/theme@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/theme/download/@material/theme-12.0.0-canary.e1703bed9.0.tgz#f898b0ba756c183219750776b3e13b91e5ed1de8"
|
||||||
|
integrity sha1-+JiwunVsGDIZdQd2s+E7keXtHeg=
|
||||||
|
dependencies:
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.e1703bed9.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/tokens@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/tokens/download/@material/tokens-12.0.0-canary.9f68a932e.0.tgz#3e3b906ad0145c80fdca5b8e362939f177866b29"
|
||||||
|
integrity sha1-PjuQatAUXID9yluONik58XeGayk=
|
||||||
|
dependencies:
|
||||||
|
"@material/elevation" "12.0.0-canary.9f68a932e.0"
|
||||||
|
|
||||||
"@material/touch-target@12.0.0-canary.068fd5028.0":
|
"@material/touch-target@12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/touch-target/download/@material/touch-target-12.0.0-canary.068fd5028.0.tgz#542c3fa5e729fe542c21a8668a5fdd820b05e415"
|
resolved "https://registry.nlark.com/@material/touch-target/download/@material/touch-target-12.0.0-canary.068fd5028.0.tgz#542c3fa5e729fe542c21a8668a5fdd820b05e415"
|
||||||
@ -1099,6 +1316,24 @@
|
|||||||
"@material/feature-targeting" "12.0.0-canary.068fd5028.0"
|
"@material/feature-targeting" "12.0.0-canary.068fd5028.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/touch-target@12.0.0-canary.9f68a932e.0":
|
||||||
|
version "12.0.0-canary.9f68a932e.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/touch-target/download/@material/touch-target-12.0.0-canary.9f68a932e.0.tgz#c8d4a5c292fbf0d6442fd31e4b6eb77915f94087"
|
||||||
|
integrity sha1-yNSlwpL78NZEL9MeS263eRX5QIc=
|
||||||
|
dependencies:
|
||||||
|
"@material/base" "12.0.0-canary.9f68a932e.0"
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.9f68a932e.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/touch-target@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/touch-target/download/@material/touch-target-12.0.0-canary.e1703bed9.0.tgz#2df8ab02cfe7cd5ddf951338c77ae5a890c78c8b"
|
||||||
|
integrity sha1-LfirAs/nzV3flRM4x3rlqJDHjIs=
|
||||||
|
dependencies:
|
||||||
|
"@material/base" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.e1703bed9.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@material/typography@12.0.0-canary.068fd5028.0", "@material/typography@^12.0.0-canary.068fd5028.0":
|
"@material/typography@12.0.0-canary.068fd5028.0", "@material/typography@^12.0.0-canary.068fd5028.0":
|
||||||
version "12.0.0-canary.068fd5028.0"
|
version "12.0.0-canary.068fd5028.0"
|
||||||
resolved "https://registry.nlark.com/@material/typography/download/@material/typography-12.0.0-canary.068fd5028.0.tgz#3a3e536239cd1e55eec9921229877ef9cde4f288"
|
resolved "https://registry.nlark.com/@material/typography/download/@material/typography-12.0.0-canary.068fd5028.0.tgz#3a3e536239cd1e55eec9921229877ef9cde4f288"
|
||||||
@ -1117,6 +1352,15 @@
|
|||||||
"@material/theme" "12.0.0-canary.22d29cbb4.0"
|
"@material/theme" "12.0.0-canary.22d29cbb4.0"
|
||||||
tslib "^2.1.0"
|
tslib "^2.1.0"
|
||||||
|
|
||||||
|
"@material/typography@12.0.0-canary.e1703bed9.0":
|
||||||
|
version "12.0.0-canary.e1703bed9.0"
|
||||||
|
resolved "https://registry.nlark.com/@material/typography/download/@material/typography-12.0.0-canary.e1703bed9.0.tgz#f82960566f8afc7eafce0c60eda6fc60ef5e4839"
|
||||||
|
integrity sha1-+ClgVm+K/H6vzgxg7ab8YO9eSDk=
|
||||||
|
dependencies:
|
||||||
|
"@material/feature-targeting" "12.0.0-canary.e1703bed9.0"
|
||||||
|
"@material/theme" "12.0.0-canary.e1703bed9.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@nodelib/fs.scandir@2.1.4":
|
"@nodelib/fs.scandir@2.1.4":
|
||||||
version "2.1.4"
|
version "2.1.4"
|
||||||
resolved "https://registry.npm.taobao.org/@nodelib/fs.scandir/download/@nodelib/fs.scandir-2.1.4.tgz?cache=0&sync_timestamp=1609074618762&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40nodelib%2Ffs.scandir%2Fdownload%2F%40nodelib%2Ffs.scandir-2.1.4.tgz"
|
resolved "https://registry.npm.taobao.org/@nodelib/fs.scandir/download/@nodelib/fs.scandir-2.1.4.tgz?cache=0&sync_timestamp=1609074618762&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40nodelib%2Ffs.scandir%2Fdownload%2F%40nodelib%2Ffs.scandir-2.1.4.tgz"
|
||||||
@ -6699,7 +6943,7 @@ typescript-vscode-sh-plugin@^0.6.14:
|
|||||||
resolved "https://registry.nlark.com/typescript-vscode-sh-plugin/download/typescript-vscode-sh-plugin-0.6.14.tgz#a81031b502f6346a26ea49ce082438c3e353bb38"
|
resolved "https://registry.nlark.com/typescript-vscode-sh-plugin/download/typescript-vscode-sh-plugin-0.6.14.tgz#a81031b502f6346a26ea49ce082438c3e353bb38"
|
||||||
integrity sha1-qBAxtQL2NGom6knOCCQ4w+NTuzg=
|
integrity sha1-qBAxtQL2NGom6knOCCQ4w+NTuzg=
|
||||||
|
|
||||||
typescript@^4.0, typescript@^4.3.5:
|
typescript@>=3, typescript@^4.0, typescript@^4.3.5:
|
||||||
version "4.3.5"
|
version "4.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4"
|
||||||
integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==
|
integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==
|
||||||
@ -7392,6 +7636,13 @@ word-wrap@^1.2.3, word-wrap@~1.2.3:
|
|||||||
resolved "https://registry.npm.taobao.org/word-wrap/download/word-wrap-1.2.3.tgz?cache=0&sync_timestamp=1589683603678&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fword-wrap%2Fdownload%2Fword-wrap-1.2.3.tgz"
|
resolved "https://registry.npm.taobao.org/word-wrap/download/word-wrap-1.2.3.tgz?cache=0&sync_timestamp=1589683603678&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fword-wrap%2Fdownload%2Fword-wrap-1.2.3.tgz"
|
||||||
integrity sha1-YQY29rH3A4kb00dxzLF/uTtHB5w=
|
integrity sha1-YQY29rH3A4kb00dxzLF/uTtHB5w=
|
||||||
|
|
||||||
|
wp-types@^2.10.0:
|
||||||
|
version "2.10.0"
|
||||||
|
resolved "https://registry.nlark.com/wp-types/download/wp-types-2.10.0.tgz#f816346d37026563fe97bf502d4a5da3397c60f9"
|
||||||
|
integrity sha1-+BY0bTcCZWP+l79QLUpdozl8YPk=
|
||||||
|
dependencies:
|
||||||
|
typescript ">=3"
|
||||||
|
|
||||||
wrap-ansi@^7.0.0:
|
wrap-ansi@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
|
Loading…
Reference in New Issue
Block a user