diff --git a/devui/steps-guide/hooks/index.ts b/devui/steps-guide/hooks/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..2cc49d128a46584ea6d750d4943fae3abe12d769 --- /dev/null +++ b/devui/steps-guide/hooks/index.ts @@ -0,0 +1,2 @@ +export * from './use-steps-guide-position' +export * from './use-steps-guide-ctrl' \ No newline at end of file diff --git a/devui/steps-guide/hooks/use-steps-guide-ctrl.ts b/devui/steps-guide/hooks/use-steps-guide-ctrl.ts new file mode 100644 index 0000000000000000000000000000000000000000..9c1b13a906e7d05082915e363a21dacddd82d9bc --- /dev/null +++ b/devui/steps-guide/hooks/use-steps-guide-ctrl.ts @@ -0,0 +1,25 @@ +import { ref, nextTick } from 'vue' + +export function useStepsGuideCtrl(stepsCount, stepIndex, updateGuidePosition) { + const showSteps = ref(true) + const closeSteps = ():void => { + showSteps.value = false + } + const setCurrentIndex = (index:number):void => { + if (index > stepsCount.value || index < 0) index = 0 + stepIndex.value = index + if (!showSteps.value) { + showSteps.value = true + nextTick(() => { + updateGuidePosition() + }) + } else { + updateGuidePosition() + } + } + return { + showSteps, + closeSteps, + setCurrentIndex + } +} \ No newline at end of file diff --git a/devui/steps-guide/hooks/use-steps-guide-position.ts b/devui/steps-guide/hooks/use-steps-guide-position.ts new file mode 100644 index 0000000000000000000000000000000000000000..4cfeff7496aee330566686bd77e728f55793970a --- /dev/null +++ b/devui/steps-guide/hooks/use-steps-guide-position.ts @@ -0,0 +1,74 @@ +import { Ref, ref, reactive, computed } from 'vue' +import { Step, positionConf } from '../src/steps-guide-types' + +export function useStepsGuideNav(steps: Step[], stepIndex:Ref) { + + const currentStep = computed(() => { + const _step = steps[stepIndex.value] + _step.position = _step.position || 'top' + return _step + }) + const guideClassList = ['d-steps-guide'] + const stepsRef = ref(null) + const guidePosition = reactive({ + left: '', + top: '', + zIndex: 1100 + }) + const updateGuidePosition = () => { + const baseTop = window.pageYOffset - document.documentElement.clientTop + const baseLeft = window.pageXOffset - document.documentElement.clientLeft + const currentStepPosition:positionConf = currentStep.value.position + let _left, _top + // 自定义 position位置 + if (typeof currentStepPosition !== 'string') { + const { top = 0, left = 0, type = 'top' } = currentStepPosition + guideClassList.splice(1, 1, type) + _left = left + _top = top + } else { + guideClassList.splice(1, 1, currentStepPosition) + const stepGuideElement = stepsRef.value + const triggerSelector = currentStep.value.target || currentStep.value.trigger + const triggerElement = document.querySelector(triggerSelector) + const targetRect = triggerElement.getBoundingClientRect() + _left = targetRect.left + triggerElement.clientWidth / 2 - stepGuideElement.clientWidth / 2 + baseLeft + _top = targetRect.top + triggerElement.clientHeight / 2 - stepGuideElement.clientHeight / 2 + baseTop + + const positionTypes = currentStepPosition.split('-') + switch (positionTypes[0]) { + case 'top': + _top += (-stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) + break + case 'bottom': + _top += (stepGuideElement.clientHeight / 2 + triggerElement.clientHeight) + break + case 'left': + _top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) + _left += (-stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2) + break + case 'right': + _top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) + _left += (stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2) + break + } + switch (positionTypes[1]) { + case 'left': + _left += (stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2) + break + case 'right': + _left += (-stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2) + break + } + } + guidePosition.left = _left + 'px' + guidePosition.top = _top + 'px' + } + return { + currentStep, + stepsRef, + guidePosition, + guideClassList, + updateGuidePosition + } +} \ No newline at end of file diff --git a/devui/steps-guide/src/steps-guide-types.ts b/devui/steps-guide/src/steps-guide-types.ts index c162691a8b5a76dcc0a54be49824e8a031313e57..6c712312b44318ff434c7a147053621fcb008516 100644 --- a/devui/steps-guide/src/steps-guide-types.ts +++ b/devui/steps-guide/src/steps-guide-types.ts @@ -4,16 +4,24 @@ export type positionConf = { left: number top: number type: string -} +} | positionType export type Step = { title: string content: string trigger: string target?: string - position?: positionType | positionConf + position?: positionConf } export const stepsGuideProps = { - steps: Array as PropType + steps: Array as PropType, + showClose: { + type: Boolean, + default: true + }, + showDots: { + type: Boolean, + default: true + } } as const export type StepsGuideProps = ExtractPropTypes diff --git a/devui/steps-guide/src/steps-guide.tsx b/devui/steps-guide/src/steps-guide.tsx index afaf90760176d1ccc7dbc46144b5014f455eeca6..93cf84bde5af5c8d04b8d810404c949f10fdd881 100644 --- a/devui/steps-guide/src/steps-guide.tsx +++ b/devui/steps-guide/src/steps-guide.tsx @@ -1,118 +1,81 @@ import './steps-guide.scss' -import { defineComponent, Teleport, ref, onMounted, reactive, computed } from 'vue' -import { stepsGuideProps, StepsGuideProps, Step, positionConf } from './steps-guide-types' - +import { defineComponent, Teleport, ref, onMounted, computed } from 'vue' +import { stepsGuideProps, StepsGuideProps } from './steps-guide-types' +import { useStepsGuideNav, useStepsGuideCtrl } from '../hooks' export default defineComponent({ name: 'DStepsGuide', props: stepsGuideProps, emits: [], setup(props: StepsGuideProps, ctx) { - const teleport = Teleport - const stepsRef = ref(null) const stepsCount = computed(() => props.steps.length - 1) - const stepIndex = ref(0), showSteps = ref(true) - const currentStep = computed(() => { - const _step = props.steps[stepIndex.value] - _step.position = _step.position || 'top' - return _step - }) - const guideClassName = ['d-steps-guide'] - const position = reactive({ - left: '', - top: '', - zIndex: 1100 - }) + const stepIndex = ref(0) + const { + currentStep, + stepsRef, + guidePosition, + guideClassList, + updateGuidePosition } = useStepsGuideNav(props.steps, stepIndex) + const { showSteps, + closeSteps, + setCurrentIndex } = useStepsGuideCtrl(stepsCount, stepIndex, updateGuidePosition) + onMounted(() => { updateGuidePosition() }) - function updateGuidePosition(){ - const baseTop = window.pageYOffset - document.documentElement.clientTop - const baseLeft = window.pageXOffset - document.documentElement.clientLeft - const currentStepPosition = currentStep.value.position - let left, top - // 自定义 position位置 - if(typeof currentStepPosition !== 'string'){ - guideClassName[1] = currentStepPosition.type - left = currentStepPosition.left - top = currentStepPosition.top - } else { - guideClassName[1] = currentStepPosition - const stepGuideElement = stepsRef.value - const triggerSelector = currentStep.value.target || currentStep.value.trigger - const triggerElement = document.querySelector(triggerSelector) - const targetRect = triggerElement.getBoundingClientRect() - left = targetRect.left + triggerElement.clientWidth / 2 - stepGuideElement.clientWidth / 2 + baseLeft - top = targetRect.top + triggerElement.clientHeight / 2 - stepGuideElement.clientHeight / 2 + baseTop - const positionTypes = currentStepPosition.split('-') - switch(positionTypes[0]){ - case 'top': - top += (-stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) - break - case 'bottom': - top += (stepGuideElement.clientHeight / 2 + triggerElement.clientHeight) - break - case 'left': - top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) - left += (-stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2) - break - case 'right': - top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) - left += (stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2) - break - } - switch(positionTypes[1]){ - case 'left': - left += (stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2) - break - case 'right': - left += (-stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2) - break - } - } - position.left = left + 'px' - position.top = top + 'px' + return { + stepsCount, + stepIndex, + showSteps, + guidePosition, + guideClassList, + stepsRef, + currentStep, + setCurrentIndex, + closeSteps } - function renderPrev(){ - return stepIndex.value > 0 ?
{ '上一步' }
: null - } - function renderNext(){ - return stepIndex.value === stepsCount.value ? -
{ '我知道啦' }
: -
{ '我知道啦,继续' }
- } - function prevStep(){ - stepIndex.value-- - updateGuidePosition() - } - function nextStep(){ - stepIndex.value++ - updateGuidePosition() - } - function closeSteps(){ - showSteps.value = false - } - return () => showSteps.value ? - ( -
+ }, + render(props) { + const { showSteps, + guidePosition, + guideClassList, + currentStep, + stepIndex, + stepsCount, + setCurrentIndex, + closeSteps, + showClose, + showDots } = props + + return showSteps ? + ( +
-

{ currentStep.value.title }

-
{ currentStep.value.content }
+

{currentStep.title}

+ {showClose ?
: null} +
{currentStep.content}
-
- -
+ { + showDots ? +
+ {props.steps.map((step, index) => { + return + })} +
: null + }
- { renderPrev() } - { renderNext() } + {stepIndex > 0 ?
setCurrentIndex(--props.stepIndex)}>{'上一步'}
: null} + {stepIndex === stepsCount ? +
{'我知道啦'}
: +
{ setCurrentIndex(++props.stepIndex) }}>{'我知道啦,继续'}
}
-
) : null + ) : null } }) diff --git a/docs/components/steps-guide/index.md b/docs/components/steps-guide/index.md index d62c463c692e0fccd1c73663a44e40c1d457306a..4744d655014125029c194ed6273c4848e6937098 100644 --- a/docs/components/steps-guide/index.md +++ b/docs/components/steps-guide/index.md @@ -14,10 +14,10 @@ Step 1 Step 2 Step 3 - +