@icij/murmur-next 4.0.1 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/AccordionStep.vue +53 -42
- package/lib/components/AccordionWrapper.vue +25 -24
- package/lib/components/ActiveTextTruncate.vue +44 -22
- package/lib/components/AdvancedLinkForm.vue +96 -46
- package/lib/components/Brand.vue +30 -23
- package/lib/components/BrandExpansion.vue +12 -3
- package/lib/components/ConfirmButton.vue +30 -26
- package/lib/components/ContentPlaceholder.vue +11 -7
- package/lib/components/CustomPagination.vue +50 -32
- package/lib/components/DigitsInput.vue +64 -60
- package/lib/components/DonateForm.vue +112 -83
- package/lib/components/EmbedForm.vue +37 -21
- package/lib/components/EmbeddableFooter.vue +14 -10
- package/lib/components/FollowUsPopover.vue +42 -40
- package/lib/components/GenericFooter.vue +98 -23
- package/lib/components/GenericHeader.vue +66 -29
- package/lib/components/HapticCopy.vue +41 -29
- package/lib/components/ImddbHeader.vue +113 -92
- package/lib/components/OrdinalLegend.vue +43 -20
- package/lib/components/RangePicker.vue +63 -42
- package/lib/components/ResponsiveIframe.vue +9 -2
- package/lib/components/ScaleLegend.vue +56 -18
- package/lib/components/SecretInput.vue +7 -8
- package/lib/components/SelectableDropdown.vue +120 -74
- package/lib/components/SharingOptions.vue +93 -36
- package/lib/components/SharingOptionsLink.vue +11 -5
- package/lib/components/SignUpForm.vue +44 -23
- package/lib/components/SlideUpDown.vue +7 -2
- package/lib/components/TexturedDeck.vue +24 -14
- package/lib/components/TinyPagination.vue +35 -22
- package/lib/composables/chart.ts +174 -157
- package/lib/composables/resizeObserver.ts +29 -29
- package/lib/composables/sendEmail.ts +53 -42
- package/lib/config.default.ts +17 -10
- package/lib/config.ts +34 -27
- package/lib/datavisualisations/BarChart.vue +48 -42
- package/lib/datavisualisations/ColumnChart.vue +133 -89
- package/lib/datavisualisations/LineChart.vue +79 -57
- package/lib/datavisualisations/StackedBarChart.vue +116 -68
- package/lib/datavisualisations/StackedColumnChart.vue +196 -115
- package/lib/enums.ts +25 -15
- package/lib/i18n.ts +3 -3
- package/lib/keys.ts +2 -2
- package/lib/main.ts +14 -10
- package/lib/maps/ChoroplethMap.vue +299 -160
- package/lib/maps/ChoroplethMapAnnotation.vue +29 -18
- package/lib/maps/SymbolMap.vue +194 -123
- package/lib/shims-bootstrap-vue.d.ts +1 -1
- package/lib/shims-vue.d.ts +3 -3
- package/lib/styles/functions.scss +10 -6
- package/lib/styles/lib.scss +2 -4
- package/lib/styles/mixins.scss +8 -8
- package/lib/styles/utilities.scss +1 -1
- package/lib/styles/variables.scss +24 -18
- package/lib/types.ts +26 -10
- package/lib/utils/animation.ts +4 -4
- package/lib/utils/assets.ts +31 -28
- package/lib/utils/clipboard.ts +16 -10
- package/lib/utils/iframe-resizer.ts +18 -13
- package/lib/utils/placeholder.ts +54 -23
- package/lib/utils/placeholderTypes.ts +3 -3
- package/package.json +7 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<b-card
|
|
3
|
-
|
|
3
|
+
:class="{
|
|
4
4
|
'accordion-wrapper__content__step--active': isActive,
|
|
5
5
|
'accordion-wrapper__content__step--previous': isPrevious
|
|
6
6
|
}"
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
class="accordion-wrapper__content__step"
|
|
8
|
+
no-body
|
|
9
9
|
>
|
|
10
10
|
<h4 class="card-body accordion-wrapper__content__step__heading m-0">
|
|
11
11
|
<!-- @slot Title of the step -->
|
|
@@ -13,85 +13,97 @@
|
|
|
13
13
|
{{ title }}
|
|
14
14
|
</slot>
|
|
15
15
|
</h4>
|
|
16
|
-
<
|
|
16
|
+
<slide-up-down :active="isActive">
|
|
17
17
|
<div class="accordion-wrapper__content__step__main card-body row g-0">
|
|
18
18
|
<!-- @slot Content of the step with props {isFirst:boolean, isLast:boolean, step:Step, nextStep:Function}-->
|
|
19
|
-
<slot
|
|
19
|
+
<slot
|
|
20
|
+
name="content"
|
|
21
|
+
v-bind="{ isFirst, isLast, step, previousStep, nextStep }"
|
|
22
|
+
>
|
|
20
23
|
{{ content }}
|
|
21
24
|
</slot>
|
|
22
25
|
</div>
|
|
23
26
|
<div class="card-footer">
|
|
24
27
|
<!-- @slot Previous step button with props {isFirst:boolean, isLast:boolean, step:Step, nextStep:Function} -->
|
|
25
|
-
<slot
|
|
28
|
+
<slot
|
|
29
|
+
name="previousStepButton"
|
|
30
|
+
v-bind="{ isFirst, isLast, step, previousStep }"
|
|
31
|
+
>
|
|
26
32
|
<b-button
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
v-if="!isFirst"
|
|
34
|
+
class="accordion-wrapper__content__step__back-button"
|
|
35
|
+
type="button"
|
|
36
|
+
variant="link"
|
|
37
|
+
@click="previousStep"
|
|
32
38
|
>
|
|
33
39
|
Back
|
|
34
40
|
</b-button>
|
|
35
41
|
</slot>
|
|
36
42
|
<!-- @slot Next step button with props {isFirst:boolean, isLast:boolean, step:Step, nextStep:Function} }-->
|
|
37
|
-
<slot
|
|
43
|
+
<slot
|
|
44
|
+
name="nextStepButton"
|
|
45
|
+
v-bind="{ isFirst, isLast, step, nextStep }"
|
|
46
|
+
>
|
|
38
47
|
<b-button
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
v-if="!isLast"
|
|
49
|
+
class="accordion-wrapper__content__step__continue-button"
|
|
50
|
+
type="button"
|
|
51
|
+
variant="primary"
|
|
52
|
+
@click="nextStep"
|
|
44
53
|
>
|
|
45
54
|
Continue
|
|
46
55
|
</b-button>
|
|
47
56
|
</slot>
|
|
48
57
|
</div>
|
|
49
|
-
</
|
|
58
|
+
</slide-up-down>
|
|
50
59
|
</b-card>
|
|
51
60
|
</template>
|
|
52
61
|
|
|
53
62
|
<script lang="ts">
|
|
54
|
-
import {computed, defineComponent, inject, PropType} from 'vue'
|
|
55
|
-
|
|
56
|
-
import
|
|
63
|
+
import { computed, defineComponent, inject, PropType } from 'vue'
|
|
64
|
+
|
|
65
|
+
import SlideUpDown from '@/components/SlideUpDown.vue'
|
|
66
|
+
import { AccordionKey } from '@/keys'
|
|
67
|
+
import { Accordion, Step } from '@/types'
|
|
57
68
|
|
|
58
69
|
export default defineComponent({
|
|
70
|
+
components: {
|
|
71
|
+
SlideUpDown
|
|
72
|
+
},
|
|
59
73
|
props: {
|
|
60
74
|
/**
|
|
61
75
|
* Step name
|
|
62
76
|
*/
|
|
63
|
-
step: {type: [String, Object as () => Step, Symbol], required: true},
|
|
77
|
+
step: { type: [String, Object as () => Step, Symbol], required: true },
|
|
64
78
|
/**
|
|
65
79
|
* Title of the step card
|
|
66
80
|
*/
|
|
67
|
-
title: {type: String, default:
|
|
81
|
+
title: { type: String, default: 'Step' },
|
|
68
82
|
|
|
69
83
|
/**
|
|
70
84
|
* Content of the step card
|
|
71
85
|
*/
|
|
72
|
-
content: {type: String, default:
|
|
86
|
+
content: { type: String, default: 'Step' },
|
|
73
87
|
/**
|
|
74
88
|
* Force card expansion/collapse
|
|
75
89
|
*/
|
|
76
|
-
active: {type: Boolean as PropType<boolean|undefined>, default: false}
|
|
90
|
+
active: { type: Boolean as PropType<boolean | undefined>, default: false }
|
|
77
91
|
},
|
|
78
92
|
emits: ['next-step', 'previous-step'],
|
|
79
|
-
setup(props: { step: Step
|
|
80
|
-
|
|
93
|
+
setup(props: { step: Step; active: boolean | undefined }, { emit }: any) {
|
|
81
94
|
const accordion = inject<Accordion>(AccordionKey)
|
|
82
95
|
const isActive = computed(() => {
|
|
83
|
-
const fromAccordion = !!accordion?.isActiveStep(props.step)
|
|
84
|
-
const fromSelf = props.active !== undefined ? props.active : false
|
|
85
|
-
return fromSelf || fromAccordion
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
const isPrevious = computed(() => !!accordion?.isPreviousStep(props.step));
|
|
89
|
-
const isFirst = computed(() => !!accordion?.isFirstStep(props.step));
|
|
90
|
-
const isLast = computed(() => !!accordion?.isLastStep(props.step));
|
|
96
|
+
const fromAccordion = !!accordion?.isActiveStep(props.step)
|
|
97
|
+
const fromSelf = props.active !== undefined ? props.active : false
|
|
98
|
+
return fromSelf || fromAccordion
|
|
99
|
+
})
|
|
91
100
|
|
|
101
|
+
const isPrevious = computed(() => !!accordion?.isPreviousStep(props.step))
|
|
102
|
+
const isFirst = computed(() => !!accordion?.isFirstStep(props.step))
|
|
103
|
+
const isLast = computed(() => !!accordion?.isLastStep(props.step))
|
|
92
104
|
|
|
93
105
|
const nextStep = () => {
|
|
94
|
-
accordion?.emitAccordionNextStepEvent()
|
|
106
|
+
accordion?.emitAccordionNextStepEvent()
|
|
95
107
|
/**
|
|
96
108
|
* Fired when the nextStep function is called
|
|
97
109
|
* either by clicking on the next button or in the next step slot
|
|
@@ -99,11 +111,11 @@ export default defineComponent({
|
|
|
99
111
|
* @event next-step
|
|
100
112
|
* @param Mixed New step value.
|
|
101
113
|
*/
|
|
102
|
-
emit('next-step')
|
|
103
|
-
}
|
|
114
|
+
emit('next-step')
|
|
115
|
+
}
|
|
104
116
|
|
|
105
117
|
const previousStep = () => {
|
|
106
|
-
accordion?.emitAccordionPreviousStepEvent()
|
|
118
|
+
accordion?.emitAccordionPreviousStepEvent()
|
|
107
119
|
/**
|
|
108
120
|
* Fired when the previousStep function is called
|
|
109
121
|
* either by clicking on the previous button or in the previous step slot
|
|
@@ -111,8 +123,8 @@ export default defineComponent({
|
|
|
111
123
|
* @event previous-step
|
|
112
124
|
* @param Mixed New step value.
|
|
113
125
|
*/
|
|
114
|
-
emit('previous-step')
|
|
115
|
-
}
|
|
126
|
+
emit('previous-step')
|
|
127
|
+
}
|
|
116
128
|
return {
|
|
117
129
|
isFirst,
|
|
118
130
|
isLast,
|
|
@@ -124,5 +136,4 @@ export default defineComponent({
|
|
|
124
136
|
}
|
|
125
137
|
}
|
|
126
138
|
})
|
|
127
|
-
|
|
128
139
|
</script>
|
|
@@ -8,40 +8,41 @@
|
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
10
|
<script lang="ts">
|
|
11
|
-
import {computed, PropType, provide, defineComponent} from 'vue'
|
|
12
|
-
import { AccordionKey } from '@/keys'
|
|
13
|
-
import {Accordion, Step} from '@/types'
|
|
11
|
+
import { computed, PropType, provide, defineComponent } from 'vue'
|
|
12
|
+
import { AccordionKey } from '@/keys'
|
|
13
|
+
import { Accordion, Step } from '@/types'
|
|
14
14
|
|
|
15
|
-
const STEP_CHANGE_EVENT: string = 'step-change'
|
|
15
|
+
const STEP_CHANGE_EVENT: string = 'step-change'
|
|
16
16
|
export default defineComponent({
|
|
17
|
-
props:{
|
|
17
|
+
props: {
|
|
18
18
|
step: {
|
|
19
19
|
type: [String, Symbol, Object as () => Step],
|
|
20
|
-
required: true
|
|
20
|
+
required: true
|
|
21
21
|
},
|
|
22
22
|
steps: {
|
|
23
23
|
type: Array as PropType<Step[]>,
|
|
24
|
-
required: true
|
|
25
|
-
}
|
|
24
|
+
required: true
|
|
25
|
+
}
|
|
26
26
|
},
|
|
27
|
-
emits:['step-change'],
|
|
28
|
-
setup(props,{emit}){
|
|
29
|
-
|
|
27
|
+
emits: ['step-change'],
|
|
28
|
+
setup(props, { emit }) {
|
|
30
29
|
const emitAccordionNextStepEvent = () => {
|
|
31
|
-
emit('step-change', props.steps[activeStepIndex.value + 1] || props.step)
|
|
32
|
-
}
|
|
30
|
+
emit('step-change', props.steps[activeStepIndex.value + 1] || props.step)
|
|
31
|
+
}
|
|
33
32
|
|
|
34
33
|
const emitAccordionPreviousStepEvent = () => {
|
|
35
|
-
emit('step-change', props.steps[activeStepIndex.value - 1] || props.step)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const activeStepIndex = computed(() => props.steps?.indexOf(props.step));
|
|
34
|
+
emit('step-change', props.steps[activeStepIndex.value - 1] || props.step)
|
|
35
|
+
}
|
|
39
36
|
|
|
40
|
-
const
|
|
41
|
-
const isLastStep = (step: Step): boolean => props.steps?.indexOf(step) === props.steps?.length - 1;
|
|
42
|
-
const isActiveStep = (step: Step): boolean => props.step === step;
|
|
43
|
-
const isPreviousStep = (step: Step): boolean => props.steps?.indexOf(step) < activeStepIndex.value;
|
|
37
|
+
const activeStepIndex = computed(() => props.steps?.indexOf(props.step))
|
|
44
38
|
|
|
39
|
+
const isFirstStep = (step: Step): boolean =>
|
|
40
|
+
props.steps?.indexOf(step) === 0
|
|
41
|
+
const isLastStep = (step: Step): boolean =>
|
|
42
|
+
props.steps?.indexOf(step) === props.steps?.length - 1
|
|
43
|
+
const isActiveStep = (step: Step): boolean => props.step === step
|
|
44
|
+
const isPreviousStep = (step: Step): boolean =>
|
|
45
|
+
props.steps?.indexOf(step) < activeStepIndex.value
|
|
45
46
|
|
|
46
47
|
provide<Accordion>(AccordionKey, {
|
|
47
48
|
emitAccordionNextStepEvent,
|
|
@@ -51,7 +52,7 @@ export default defineComponent({
|
|
|
51
52
|
isFirstStep,
|
|
52
53
|
isLastStep,
|
|
53
54
|
step: props.step,
|
|
54
|
-
steps: props.steps
|
|
55
|
+
steps: props.steps
|
|
55
56
|
})
|
|
56
57
|
return {
|
|
57
58
|
emitAccordionNextStepEvent,
|
|
@@ -65,7 +66,6 @@ export default defineComponent({
|
|
|
65
66
|
})
|
|
66
67
|
</script>
|
|
67
68
|
|
|
68
|
-
|
|
69
69
|
<style lang="scss" scoped>
|
|
70
70
|
@use 'sass:math';
|
|
71
71
|
@import '../styles/variables.scss';
|
|
@@ -83,7 +83,8 @@ export default defineComponent({
|
|
|
83
83
|
opacity: $btn-disabled-opacity;
|
|
84
84
|
transition: $transition-base;
|
|
85
85
|
|
|
86
|
-
&--active
|
|
86
|
+
&--active,
|
|
87
|
+
&--previous {
|
|
87
88
|
opacity: 1;
|
|
88
89
|
}
|
|
89
90
|
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {computed, defineComponent, ref, watch} from 'vue'
|
|
3
|
-
import useResizeObserver from
|
|
2
|
+
import { computed, defineComponent, ref, watch } from 'vue'
|
|
3
|
+
import useResizeObserver from '@/composables/resizeObserver'
|
|
4
4
|
import { RequestAnimationFrameWrapper } from '@/utils/animation'
|
|
5
5
|
|
|
6
|
-
type ActiveTextTruncateData = {
|
|
6
|
+
type ActiveTextTruncateData = {
|
|
7
|
+
textLivePosition: number
|
|
8
|
+
resizeObserverKey: string | null
|
|
9
|
+
}
|
|
7
10
|
|
|
8
11
|
export default defineComponent({
|
|
9
12
|
name: 'ActiveTextTruncate',
|
|
@@ -47,15 +50,15 @@ export default defineComponent({
|
|
|
47
50
|
validator: (value: string) => ['ltr', 'rtl'].indexOf(value) > -1
|
|
48
51
|
}
|
|
49
52
|
},
|
|
50
|
-
emits:['cancel','end','start'],
|
|
51
|
-
setup(props,{emit}){
|
|
52
|
-
const el
|
|
53
|
+
emits: ['cancel', 'end', 'start'],
|
|
54
|
+
setup(props, { emit }) {
|
|
55
|
+
const el = ref(null)
|
|
53
56
|
const textLivePosition = ref(0)
|
|
54
|
-
|
|
55
|
-
const {resizeRef,resizeState} = useResizeObserver(el)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
// This will hold a key generated every time the component is resized.
|
|
58
|
+
const { resizeRef, resizeState } = useResizeObserver(el)
|
|
59
|
+
watch(resizeState, () => {
|
|
60
|
+
onResized()
|
|
61
|
+
})
|
|
59
62
|
|
|
60
63
|
const wrapperElement = computed((): HTMLElement | null => {
|
|
61
64
|
const selector = '.active-text-truncate__wrapper'
|
|
@@ -75,7 +78,9 @@ export default defineComponent({
|
|
|
75
78
|
return `${props.delay}ms`
|
|
76
79
|
})
|
|
77
80
|
const textOffsetTransitionDuration = computed((): string => {
|
|
78
|
-
const offset = Math.abs(
|
|
81
|
+
const offset = Math.abs(
|
|
82
|
+
wrapperElementWidth.value - textElementWidth.value
|
|
83
|
+
)
|
|
79
84
|
const duration = offset / props.ppms
|
|
80
85
|
return `${duration}ms`
|
|
81
86
|
})
|
|
@@ -86,7 +91,7 @@ export default defineComponent({
|
|
|
86
91
|
const offset = wrapperElementWidth.value - textElementWidth.value
|
|
87
92
|
return `${offset}px`
|
|
88
93
|
})
|
|
89
|
-
const textOffsetValues = computed((): string
|
|
94
|
+
const textOffsetValues = computed((): string[] => {
|
|
90
95
|
if (props.direction === 'ltr') {
|
|
91
96
|
return [textInitialOffset.value, textFinalOffset.value]
|
|
92
97
|
}
|
|
@@ -103,20 +108,27 @@ export default defineComponent({
|
|
|
103
108
|
})
|
|
104
109
|
const fadingLeftWidth = computed((): string => {
|
|
105
110
|
const offset = textLivePosition.value
|
|
106
|
-
const width = Math.min(
|
|
111
|
+
const width = Math.min(
|
|
112
|
+
Math.max(props.fadingMinWidth, Math.abs(offset)),
|
|
113
|
+
props.fadingMaxWidth
|
|
114
|
+
)
|
|
107
115
|
return `${width}px`
|
|
108
116
|
})
|
|
109
117
|
const fadingRightWidth = computed((): string => {
|
|
110
118
|
const offset = parseInt(textFinalOffset.value) - textLivePosition.value
|
|
111
|
-
const width = Math.min(
|
|
119
|
+
const width = Math.min(
|
|
120
|
+
Math.max(props.fadingMinWidth, Math.abs(offset)),
|
|
121
|
+
props.fadingMaxWidth
|
|
122
|
+
)
|
|
112
123
|
return `${width}px`
|
|
113
124
|
})
|
|
114
|
-
const textLivePositionRequestAnimationFrame = computed(
|
|
115
|
-
|
|
116
|
-
|
|
125
|
+
const textLivePositionRequestAnimationFrame = computed(
|
|
126
|
+
(): RequestAnimationFrameWrapper => {
|
|
127
|
+
return new RequestAnimationFrameWrapper()
|
|
128
|
+
}
|
|
129
|
+
)
|
|
117
130
|
|
|
118
131
|
function onResized() {
|
|
119
|
-
|
|
120
132
|
textLivePosition.value = parseInt(textOffsetValues.value[0])
|
|
121
133
|
// Track transitions to update the text position in live using Request Animation Frame
|
|
122
134
|
listenOnTextElement('transitionstart', startTrackingTextLivePosition)
|
|
@@ -129,7 +141,9 @@ export default defineComponent({
|
|
|
129
141
|
}
|
|
130
142
|
function trackTextLivePosition(): void {
|
|
131
143
|
if (!textElement.value) return
|
|
132
|
-
const left = window
|
|
144
|
+
const left = window
|
|
145
|
+
.getComputedStyle(textElement.value, null)
|
|
146
|
+
.getPropertyValue('left')
|
|
133
147
|
textLivePosition.value = parseInt(left)
|
|
134
148
|
}
|
|
135
149
|
function startTrackingTextLivePosition(): void {
|
|
@@ -203,8 +217,16 @@ export default defineComponent({
|
|
|
203
217
|
.active-text-truncate {
|
|
204
218
|
--fading-left-width: 0;
|
|
205
219
|
--fading-right-width: 0;
|
|
206
|
-
--fading-left-gradient: linear-gradient(
|
|
207
|
-
|
|
220
|
+
--fading-left-gradient: linear-gradient(
|
|
221
|
+
to left,
|
|
222
|
+
black calc(100% - var(--fading-left-width)),
|
|
223
|
+
transparent 100%
|
|
224
|
+
);
|
|
225
|
+
--fading-right-gradient: linear-gradient(
|
|
226
|
+
to right,
|
|
227
|
+
black calc(100% - var(--fading-right-width)),
|
|
228
|
+
transparent 100%
|
|
229
|
+
);
|
|
208
230
|
--text-offset-transition-duration: 0ms;
|
|
209
231
|
--text-offset-transition-delay: 0ms;
|
|
210
232
|
--text-final-offset: 0;
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {computed, defineComponent, ref, Ref, toRef} from 'vue'
|
|
3
|
-
import {
|
|
2
|
+
import { computed, defineComponent, ref, Ref, toRef } from 'vue'
|
|
3
|
+
import {
|
|
4
|
+
BTabs,
|
|
5
|
+
BTab,
|
|
6
|
+
BInputGroup,
|
|
7
|
+
BInputGroupAppend,
|
|
8
|
+
BFormInput
|
|
9
|
+
} from 'bootstrap-vue-next'
|
|
4
10
|
|
|
5
11
|
import HapticCopy from './HapticCopy.vue'
|
|
6
12
|
|
|
7
|
-
import {useI18n} from
|
|
13
|
+
import { useI18n } from 'vue-i18n'
|
|
8
14
|
|
|
9
15
|
type AdvancedLinkedFormClassName = `${'advanced-link-form--'}${string}`
|
|
10
16
|
interface AdvancedLinkedFormClasses {
|
|
@@ -100,57 +106,65 @@ export default defineComponent({
|
|
|
100
106
|
type: Boolean
|
|
101
107
|
}
|
|
102
108
|
},
|
|
103
|
-
emits:[
|
|
104
|
-
setup(props,{emit}) {
|
|
109
|
+
emits: ['update:modelValue'],
|
|
110
|
+
setup(props, { emit }) {
|
|
105
111
|
const { t } = useI18n()
|
|
106
|
-
const rawInput = ref<HTMLTextAreaElement| null>(null)
|
|
107
|
-
const richInput = ref<HTMLElement|null>(null)
|
|
108
|
-
const markdownInput = ref<HTMLTextAreaElement| null>(null)
|
|
109
|
-
const htmlInput = ref<HTMLTextAreaElement| null>(null)
|
|
110
|
-
const titleOrLink = computed(() => props.title || props.link)
|
|
112
|
+
const rawInput = ref<HTMLTextAreaElement | null>(null)
|
|
113
|
+
const richInput = ref<HTMLElement | null>(null)
|
|
114
|
+
const markdownInput = ref<HTMLTextAreaElement | null>(null)
|
|
115
|
+
const htmlInput = ref<HTMLTextAreaElement | null>(null)
|
|
116
|
+
const titleOrLink = computed(() => props.title || props.link)
|
|
111
117
|
|
|
112
|
-
const linkAsMarkdown = computed(
|
|
118
|
+
const linkAsMarkdown = computed(
|
|
119
|
+
() => `[${titleOrLink.value}](${props.link})`
|
|
120
|
+
)
|
|
113
121
|
|
|
114
|
-
const linkAsHtml = computed(
|
|
122
|
+
const linkAsHtml = computed(
|
|
123
|
+
() => `<a href="${props.link}" target="_blank">${titleOrLink.value}</a>`
|
|
124
|
+
)
|
|
115
125
|
const formClasses = computed(() => {
|
|
116
|
-
const propsToCheck = ['card', 'pills', 'small', 'vertical']
|
|
126
|
+
const propsToCheck = ['card', 'pills', 'small', 'vertical']
|
|
117
127
|
return propsToCheck.reduce((classes, prop) => {
|
|
118
128
|
//@ts-ignore
|
|
119
|
-
classes[`advanced-link-form--${prop}`] = props[prop]
|
|
120
|
-
return classes
|
|
121
|
-
}, {})
|
|
122
|
-
})
|
|
129
|
+
classes[`advanced-link-form--${prop}`] = props[prop]
|
|
130
|
+
return classes
|
|
131
|
+
}, {})
|
|
132
|
+
})
|
|
123
133
|
|
|
124
|
-
const size = computed(() => props.small ? 'sm' : 'md')
|
|
134
|
+
const size = computed(() => (props.small ? 'sm' : 'md'))
|
|
125
135
|
|
|
126
|
-
const showForm
|
|
127
|
-
return (name:string) => props.forms.indexOf(name) > -1
|
|
136
|
+
const showForm = computed(() => {
|
|
137
|
+
return (name: string) => props.forms.indexOf(name) > -1
|
|
128
138
|
})
|
|
129
139
|
|
|
130
|
-
const selectInput = (target: Ref<HTMLElement|null>) => {
|
|
140
|
+
const selectInput = (target: Ref<HTMLElement | null>) => {
|
|
131
141
|
// if(!target.value){
|
|
132
142
|
// throw new Error("no target")
|
|
133
143
|
// }
|
|
134
144
|
if (target.value instanceof HTMLTextAreaElement) {
|
|
135
|
-
target.value.select()
|
|
145
|
+
target.value.select()
|
|
136
146
|
}
|
|
137
|
-
}
|
|
147
|
+
}
|
|
138
148
|
|
|
139
|
-
const selectRaw = () => selectInput(rawInput)
|
|
149
|
+
const selectRaw = () => selectInput(rawInput)
|
|
140
150
|
|
|
141
151
|
function selectRich() {
|
|
142
|
-
if (!richInput.value) return
|
|
152
|
+
if (!richInput.value) return
|
|
143
153
|
|
|
144
|
-
const selection = window.getSelection ? window.getSelection() : null
|
|
154
|
+
const selection = window.getSelection ? window.getSelection() : null
|
|
145
155
|
if (selection) {
|
|
146
|
-
const range = document.createRange()
|
|
147
|
-
range.selectNodeContents(richInput.value)
|
|
148
|
-
selection.removeAllRanges()
|
|
149
|
-
selection.addRange(range)
|
|
150
|
-
} else if (
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
range
|
|
156
|
+
const range = document.createRange()
|
|
157
|
+
range.selectNodeContents(richInput.value)
|
|
158
|
+
selection.removeAllRanges()
|
|
159
|
+
selection.addRange(range)
|
|
160
|
+
} else if (
|
|
161
|
+
(document.body as HTMLElementSupportingCreateRange).createTextRange
|
|
162
|
+
) {
|
|
163
|
+
const range = (
|
|
164
|
+
document.body as HTMLElementSupportingCreateRange
|
|
165
|
+
).createTextRange()
|
|
166
|
+
range.moveToElementText(richInput.value)
|
|
167
|
+
range.select()
|
|
154
168
|
}
|
|
155
169
|
}
|
|
156
170
|
function selectMarkdown() {
|
|
@@ -173,9 +187,8 @@ export default defineComponent({
|
|
|
173
187
|
selectRich,
|
|
174
188
|
selectMarkdown,
|
|
175
189
|
selectHtml
|
|
176
|
-
}
|
|
190
|
+
}
|
|
177
191
|
}
|
|
178
|
-
|
|
179
192
|
})
|
|
180
193
|
</script>
|
|
181
194
|
|
|
@@ -196,9 +209,19 @@ export default defineComponent({
|
|
|
196
209
|
<b-tab v-if="showForm('raw')" :title="t('advanced-link-form.raw.tab')">
|
|
197
210
|
<div class="advanced-link-form__raw" :class="{ small }">
|
|
198
211
|
<b-input-group :size="size">
|
|
199
|
-
<b-form-input
|
|
212
|
+
<b-form-input
|
|
213
|
+
ref="rawInput"
|
|
214
|
+
readonly
|
|
215
|
+
:model-value="link"
|
|
216
|
+
class="advanced-link-form__raw__input"
|
|
217
|
+
@click="selectRaw"
|
|
218
|
+
/>
|
|
200
219
|
<b-input-group-append>
|
|
201
|
-
<haptic-copy
|
|
220
|
+
<haptic-copy
|
|
221
|
+
class="btn-secondary"
|
|
222
|
+
:text="link"
|
|
223
|
+
@attempt="selectRaw"
|
|
224
|
+
/>
|
|
202
225
|
</b-input-group-append>
|
|
203
226
|
</b-input-group>
|
|
204
227
|
</div>
|
|
@@ -206,11 +229,21 @@ export default defineComponent({
|
|
|
206
229
|
<b-tab v-if="showForm('rich')" :title="t('advanced-link-form.rich.tab')">
|
|
207
230
|
<div class="advanced-link-form__rich" :class="{ small }">
|
|
208
231
|
<b-input-group :size="size">
|
|
209
|
-
<a
|
|
210
|
-
|
|
211
|
-
|
|
232
|
+
<a
|
|
233
|
+
ref="richInput"
|
|
234
|
+
:href="link"
|
|
235
|
+
class="form-control advanced-link-form__rich__input"
|
|
236
|
+
@click.prevent="selectRich"
|
|
237
|
+
>{{ titleOrLink }}</a
|
|
238
|
+
>
|
|
212
239
|
<b-input-group-append>
|
|
213
|
-
<haptic-copy
|
|
240
|
+
<haptic-copy
|
|
241
|
+
class="btn-secondary"
|
|
242
|
+
html
|
|
243
|
+
:text="linkAsHtml"
|
|
244
|
+
:plain="link"
|
|
245
|
+
@attempt="selectRich"
|
|
246
|
+
/>
|
|
214
247
|
</b-input-group-append>
|
|
215
248
|
</b-input-group>
|
|
216
249
|
<p class="text-muted mt-2 mb-0">
|
|
@@ -218,7 +251,10 @@ export default defineComponent({
|
|
|
218
251
|
</p>
|
|
219
252
|
</div>
|
|
220
253
|
</b-tab>
|
|
221
|
-
<b-tab
|
|
254
|
+
<b-tab
|
|
255
|
+
v-if="showForm('markdown')"
|
|
256
|
+
:title="t('advanced-link-form.markdown.tab')"
|
|
257
|
+
>
|
|
222
258
|
<div class="advanced-link-form__markdown" :class="{ small }">
|
|
223
259
|
<b-input-group :size="size">
|
|
224
260
|
<b-form-input
|
|
@@ -229,7 +265,11 @@ export default defineComponent({
|
|
|
229
265
|
@click="selectMarkdown"
|
|
230
266
|
/>
|
|
231
267
|
<b-input-group-append>
|
|
232
|
-
<haptic-copy
|
|
268
|
+
<haptic-copy
|
|
269
|
+
class="btn-secondary"
|
|
270
|
+
:text="linkAsMarkdown"
|
|
271
|
+
@attempt="selectMarkdown"
|
|
272
|
+
/>
|
|
233
273
|
</b-input-group-append>
|
|
234
274
|
</b-input-group>
|
|
235
275
|
<p class="text-muted mt-2 mb-0">
|
|
@@ -240,9 +280,19 @@ export default defineComponent({
|
|
|
240
280
|
<b-tab v-if="showForm('html')" :title="t('advanced-link-form.html.tab')">
|
|
241
281
|
<div class="advanced-link-form__html" :class="{ small }">
|
|
242
282
|
<b-input-group :size="size">
|
|
243
|
-
<b-form-input
|
|
283
|
+
<b-form-input
|
|
284
|
+
ref="htmlInput"
|
|
285
|
+
readonly
|
|
286
|
+
:modelValue="linkAsHtml"
|
|
287
|
+
class="advanced-link-form__html__input"
|
|
288
|
+
@click="selectHtml"
|
|
289
|
+
/>
|
|
244
290
|
<b-input-group-append>
|
|
245
|
-
<haptic-copy
|
|
291
|
+
<haptic-copy
|
|
292
|
+
class="btn-secondary"
|
|
293
|
+
:text="linkAsHtml"
|
|
294
|
+
@attempt="selectHtml"
|
|
295
|
+
/>
|
|
246
296
|
</b-input-group-append>
|
|
247
297
|
</b-input-group>
|
|
248
298
|
</div>
|