@icij/murmur-next 4.0.0
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/.github/workflows/deploy-github-pages.yaml +50 -0
- package/.storybook/app.scss +14 -0
- package/.storybook/doc_variables.scss +20 -0
- package/.storybook/main.ts +35 -0
- package/.storybook/preview-head.html +2 -0
- package/.storybook/preview.ts +32 -0
- package/README.md +71 -0
- package/deploy.js +15 -0
- package/docs/components/ApiTable.vue +171 -0
- package/docs/components/App.vue +146 -0
- package/docs/components/CollapsibleBlock.vue +122 -0
- package/docs/components/DocsHeader.vue +68 -0
- package/docs/components/DocsMenu.vue +201 -0
- package/docs/components/DocsMenuSection.vue +109 -0
- package/docs/components/EditLink.vue +49 -0
- package/docs/components/OutboundLink.vue +13 -0
- package/docs/components/PalettePresenter.vue +96 -0
- package/docs/components/RepositoryLink.vue +28 -0
- package/docs/components/SampleCard.vue +119 -0
- package/docs/main.js +42 -0
- package/docs/pages/components/accordion/doc.md +96 -0
- package/docs/pages/components/active-text-truncate/doc.md +44 -0
- package/docs/pages/components/advanced-link-form/doc.md +105 -0
- package/docs/pages/components/brand/doc.md +30 -0
- package/docs/pages/components/brand-expansion/doc.md +70 -0
- package/docs/pages/components/confirm-button/doc.md +91 -0
- package/docs/pages/components/content-placeholder/doc.md +16 -0
- package/docs/pages/components/custom-pagination/doc.md +61 -0
- package/docs/pages/components/digits-input/doc.md +28 -0
- package/docs/pages/components/donate-form/doc.md +20 -0
- package/docs/pages/components/embed-form/doc.md +22 -0
- package/docs/pages/components/embeddable-footer/doc.md +60 -0
- package/docs/pages/components/follow-us-popover/doc.md +5 -0
- package/docs/pages/components/generic-footer/doc.md +21 -0
- package/docs/pages/components/generic-header/doc.md +24 -0
- package/docs/pages/components/haptic-copy/doc.md +27 -0
- package/docs/pages/components/imddb-header/doc.md +23 -0
- package/docs/pages/components/ordinal-legend/doc.md +44 -0
- package/docs/pages/components/range-picker/doc.md +86 -0
- package/docs/pages/components/responsive-iframe/doc.md +13 -0
- package/docs/pages/components/scale-legend/doc.md +65 -0
- package/docs/pages/components/secret-input/doc.md +12 -0
- package/docs/pages/components/selectable-dropdown/doc.md +156 -0
- package/docs/pages/components/sharing-options/doc.md +13 -0
- package/docs/pages/components/sharing-options-link/doc.md +36 -0
- package/docs/pages/components/sign-up-form/doc.md +13 -0
- package/docs/pages/components/slide-up-down/doc.md +28 -0
- package/docs/pages/components/textured-deck/doc.md +78 -0
- package/docs/pages/components/tiny-pagination/doc.md +92 -0
- package/docs/pages/datavisualisation/bars/doc.md +110 -0
- package/docs/pages/datavisualisation/columns/doc.md +165 -0
- package/docs/pages/datavisualisation/lines/doc.md +139 -0
- package/docs/pages/datavisualisation/stacked-bar/doc.md +160 -0
- package/docs/pages/datavisualisation/stacked-column/doc.md +191 -0
- package/docs/pages/getting-started/about-icij/doc.md +13 -0
- package/docs/pages/getting-started/custom-bootstrap/doc.md +36 -0
- package/docs/pages/getting-started/installation-guide/doc.md +59 -0
- package/docs/pages/getting-started/internationalization/doc.md +74 -0
- package/docs/pages/maps/choropleth-map/doc.md +420 -0
- package/docs/pages/maps/choropleth-map-annotation/doc.md +373 -0
- package/docs/pages/maps/symbol-map/doc.md +203 -0
- package/docs/pages/structure/breakpoints/doc.md +3 -0
- package/docs/pages/structure/grid/doc.md +3 -0
- package/docs/pages/utilities/assets/doc.md +138 -0
- package/docs/pages/utilities/config/doc.md +52 -0
- package/docs/pages/utilities/iframes/doc.md +3 -0
- package/docs/pages/visual/colors/doc.md +31 -0
- package/docs/pages/visual/iconography/doc.md +56 -0
- package/docs/pages/visual/states/doc.md +77 -0
- package/docs/pages/visual/themes/doc.md +3 -0
- package/docs/pages/visual/typography/doc.md +71 -0
- package/docs/routes.js +25 -0
- package/docs/store/index.js +21 -0
- package/docs/styles/app.scss +36 -0
- package/docs/styles/variables.scss +20 -0
- package/lib/assets/images/icij-full-white.svg +6 -0
- package/lib/assets/images/icij-full.svg +6 -0
- package/lib/assets/images/icij.png +0 -0
- package/lib/assets/images/icij.svg +46 -0
- package/lib/assets/images/icij@2x.png +0 -0
- package/lib/assets/images/murmur-dark.png +0 -0
- package/lib/assets/images/murmur-dark.svg +79 -0
- package/lib/assets/images/murmur-white.png +0 -0
- package/lib/assets/images/murmur-white.svg +68 -0
- package/lib/components/AccordionStep.vue +128 -0
- package/lib/components/AccordionWrapper.vue +138 -0
- package/lib/components/ActiveTextTruncate.vue +258 -0
- package/lib/components/AdvancedLinkForm.vue +273 -0
- package/lib/components/Brand.vue +150 -0
- package/lib/components/BrandExpansion.vue +237 -0
- package/lib/components/ConfirmButton.vue +204 -0
- package/lib/components/ContentPlaceholder.vue +100 -0
- package/lib/components/CustomPagination.vue +225 -0
- package/lib/components/DigitsInput.vue +180 -0
- package/lib/components/DonateForm.vue +367 -0
- package/lib/components/EmbedForm.vue +173 -0
- package/lib/components/EmbeddableFooter.vue +201 -0
- package/lib/components/Fa.js +3 -0
- package/lib/components/FollowUsPopover.vue +117 -0
- package/lib/components/GenericFooter.vue +218 -0
- package/lib/components/GenericHeader.vue +259 -0
- package/lib/components/HapticCopy.vue +256 -0
- package/lib/components/ImddbHeader.vue +336 -0
- package/lib/components/OrdinalLegend.vue +164 -0
- package/lib/components/RangePicker.vue +430 -0
- package/lib/components/ResponsiveIframe.vue +48 -0
- package/lib/components/ScaleLegend.vue +230 -0
- package/lib/components/SecretInput.vue +132 -0
- package/lib/components/SelectableDropdown.vue +368 -0
- package/lib/components/SharingOptions.vue +230 -0
- package/lib/components/SharingOptionsLink.vue +259 -0
- package/lib/components/SignUpForm.vue +181 -0
- package/lib/components/SlideUpDown.vue +131 -0
- package/lib/components/TexturedDeck.vue +101 -0
- package/lib/components/TinyPagination.vue +268 -0
- package/lib/components/index.js +31 -0
- package/lib/composables/chart.ts +182 -0
- package/lib/composables/resizeObserver.ts +37 -0
- package/lib/composables/sendEmail.ts +50 -0
- package/lib/config.default.ts +33 -0
- package/lib/config.ts +70 -0
- package/lib/d3-geo-projection.d.ts +1 -0
- package/lib/datavisualisations/BarChart.vue +275 -0
- package/lib/datavisualisations/ColumnChart.vue +527 -0
- package/lib/datavisualisations/LineChart.vue +274 -0
- package/lib/datavisualisations/StackedBarChart.vue +614 -0
- package/lib/datavisualisations/StackedColumnChart.vue +640 -0
- package/lib/datavisualisations/index.js +5 -0
- package/lib/enums.ts +25 -0
- package/lib/i18n.ts +16 -0
- package/lib/keys.ts +2 -0
- package/lib/locales/en.json +140 -0
- package/lib/locales/fr.json +117 -0
- package/lib/locales/locales/en.json +140 -0
- package/lib/locales/locales/fr.json +117 -0
- package/lib/main.ts +87 -0
- package/lib/maps/ChoroplethMap.vue +825 -0
- package/lib/maps/ChoroplethMapAnnotation.vue +336 -0
- package/lib/maps/SymbolMap.vue +628 -0
- package/lib/maps/index.js +3 -0
- package/lib/querystring-es3.d.ts +1 -0
- package/lib/shims-bootstrap-vue.d.ts +5 -0
- package/lib/shims-tsx.d.ts +11 -0
- package/lib/shims-vue.d.ts +14 -0
- package/lib/styles/functions.scss +20 -0
- package/lib/styles/lib.scss +19 -0
- package/lib/styles/mixins.scss +37 -0
- package/lib/styles/utilities.scss +18 -0
- package/lib/styles/variables.scss +94 -0
- package/lib/styles/variables_dark.scss +1 -0
- package/lib/types.ts +46 -0
- package/lib/utils/animation.ts +24 -0
- package/lib/utils/assets.ts +46 -0
- package/lib/utils/clipboard.ts +41 -0
- package/lib/utils/iframe-resizer.ts +49 -0
- package/lib/utils/placeholder.ts +66 -0
- package/lib/utils/placeholderTypes.ts +21 -0
- package/lib/utils/strings.ts +8 -0
- package/loaders/highlight-loader.js +13 -0
- package/loaders/markdown-loader.js +91 -0
- package/loaders/metadata-loader.js +18 -0
- package/loaders/sass-extract-loader.js +14 -0
- package/loaders/vue-docgen-loader.js +14 -0
- package/package.json +96 -0
- package/plugins/MdPluginTypes.ts +10 -0
- package/plugins/docs.ts +50 -0
- package/plugins/front-matter.ts +36 -0
- package/plugins/highlight.ts +27 -0
- package/plugins/markdown-it/api-table.ts +25 -0
- package/plugins/markdown-it/sample-card.ts +31 -0
- package/plugins/plugin-delete.ts +47 -0
- package/plugins/plugin-docgen.ts +23 -0
- package/plugins/sass-vars.ts +25 -0
- package/plugins/vue-docgen.ts +29 -0
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/assets/img/arrow-bottom.svg +3 -0
- package/public/assets/img/texture-brick-black.jpg +0 -0
- package/public/assets/img/texture-brick.jpg +0 -0
- package/public/assets/img/texture-carbon-black.jpg +0 -0
- package/public/assets/img/texture-carbon.jpg +0 -0
- package/public/assets/img/texture-crack-black.jpg +0 -0
- package/public/assets/img/texture-crack.jpg +0 -0
- package/public/assets/img/texture-rock-black.jpg +0 -0
- package/public/assets/img/texture-rock.jpg +0 -0
- package/public/assets/img/texture-sand-black.jpg +0 -0
- package/public/assets/img/texture-sand.jpg +0 -0
- package/public/assets/img/texture-silk-black.jpg +0 -0
- package/public/assets/img/texture-silk.jpg +0 -0
- package/public/assets/topojson/france-departments.json +1 -0
- package/public/assets/topojson/paris-arrondissements.json +1 -0
- package/public/assets/topojson/world-countries-sans-antarctica.json +1 -0
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/site.webmanifest +1 -0
- package/stories/assets/code-brackets.svg +1 -0
- package/stories/assets/colors.svg +1 -0
- package/stories/assets/comments.svg +1 -0
- package/stories/assets/direction.svg +1 -0
- package/stories/assets/flow.svg +1 -0
- package/stories/assets/plugin.svg +1 -0
- package/stories/assets/repo.svg +1 -0
- package/stories/assets/stackalt.svg +1 -0
- package/stories/getting-started/about-icij.mdx +14 -0
- package/stories/getting-started/custom-bootstrap.mdx +23 -0
- package/stories/getting-started/installation-guide.mdx +62 -0
- package/stories/getting-started/internationalization.mdx +63 -0
- package/stories/murmur/components/AccordionStep.stories.ts +33 -0
- package/stories/murmur/components/AccordionWrapper.stories.ts +69 -0
- package/stories/murmur/components/ActiveTextTruncate.stories.ts +32 -0
- package/stories/murmur/components/AdvancedLinkForm.stories.ts +77 -0
- package/stories/murmur/components/Brand.stories.ts +30 -0
- package/stories/murmur/components/BrandExpansion.stories.ts +41 -0
- package/stories/murmur/components/ConfirmButton.stories.ts +40 -0
- package/stories/murmur/components/ContentPlaceholder.stories.ts +41 -0
- package/stories/murmur/components/CustomPagination.stories.ts +42 -0
- package/stories/murmur/components/DigitsInput.stories.ts +29 -0
- package/stories/murmur/components/DonateForm.stories.ts +29 -0
- package/stories/murmur/components/EmbedForm.stories.ts +35 -0
- package/stories/murmur/components/EmbeddableFooter.stories.ts +59 -0
- package/stories/murmur/components/FollowUsPopover.stories.ts +24 -0
- package/stories/murmur/components/GenericFooter.stories.ts +27 -0
- package/stories/murmur/components/GenericHeader.stories.ts +27 -0
- package/stories/murmur/components/HapticCopy.stories.ts +40 -0
- package/stories/murmur/components/ImddbHeader.stories.ts +27 -0
- package/stories/murmur/components/OrdinalLegend.stories.ts +49 -0
- package/stories/murmur/components/RangePicker.stories.ts +98 -0
- package/stories/murmur/components/ResponsiveIframe.stories.ts +24 -0
- package/stories/murmur/components/ScaleLegend.stories.ts +65 -0
- package/stories/murmur/components/SecretInput.stories.ts +60 -0
- package/stories/murmur/components/SelectableDropdown.stories.ts +143 -0
- package/stories/murmur/components/SharingOptions.stories.ts +32 -0
- package/stories/murmur/components/SharingOptionsLink.stories.ts +53 -0
- package/stories/murmur/components/SignUpForm.stories.ts +51 -0
- package/stories/murmur/components/SlideUpDown.stories.ts +32 -0
- package/stories/murmur/components/TexturedDeck.stories.ts +83 -0
- package/stories/murmur/components/TinyPagination.stories.ts +65 -0
- package/stories/murmur/datavisualisations/BarChart.stories.ts +54 -0
- package/stories/murmur/datavisualisations/ColumnChart.stories.ts +88 -0
- package/stories/murmur/datavisualisations/LineChart.stories.ts +139 -0
- package/stories/murmur/datavisualisations/StackedBarChart.stories.ts +199 -0
- package/stories/murmur/datavisualisations/StackedColumnChart.stories.ts +136 -0
- package/stories/murmur/decorators.ts +108 -0
- package/stories/murmur/maps/ChoroplethMap.stories.ts +440 -0
- package/stories/murmur/maps/ChoroplethMapAnnotation.stories.ts +26 -0
- package/stories/murmur/maps/SymbolMap.stories.ts +24 -0
- package/stories/murmur/utils.ts +7 -0
- package/tests/unit/components/AccordionStep.spec.ts +157 -0
- package/tests/unit/components/AccordionWrapper.spec.ts +57 -0
- package/tests/unit/components/ActiveTextTruncate.spec.js +30 -0
- package/tests/unit/components/AdvancedLinkForm.spec.js +124 -0
- package/tests/unit/components/Brand.spec.js +50 -0
- package/tests/unit/components/ContentPlaceholder.spec.js +29 -0
- package/tests/unit/components/CustomPagination.spec.js +72 -0
- package/tests/unit/components/DigitsInput.spec.ts +157 -0
- package/tests/unit/components/DonateForm.spec.js +149 -0
- package/tests/unit/components/EmbedForm.spec.js +108 -0
- package/tests/unit/components/EmbeddableFooter.spec.js +11 -0
- package/tests/unit/components/Fa.spec.js +18 -0
- package/tests/unit/components/FollowUsPopover.spec.js +29 -0
- package/tests/unit/components/GenericFooter.spec.js +29 -0
- package/tests/unit/components/GenericHeader.spec.js +104 -0
- package/tests/unit/components/HapticCopy.spec.js +123 -0
- package/tests/unit/components/ImddbHeader.spec.js +96 -0
- package/tests/unit/components/OrdinalLegend.spec.js +120 -0
- package/tests/unit/components/RangePicker.spec.ts +87 -0
- package/tests/unit/components/ResponsiveIframe.spec.js +20 -0
- package/tests/unit/components/ScaleLegend.spec.js +139 -0
- package/tests/unit/components/SecretInput.spec.js +81 -0
- package/tests/unit/components/SelectableDropdown.spec.js +160 -0
- package/tests/unit/components/SharingOptions.spec.js +125 -0
- package/tests/unit/components/SharingOptionsLink.spec.js +184 -0
- package/tests/unit/components/SignUpForm.spec.js +145 -0
- package/tests/unit/components/SlideUpDown.spec.js +59 -0
- package/tests/unit/components/TinyPagination.spec.js +46 -0
- package/tests/unit/config.spec.js +136 -0
- package/tests/unit/datavisualisations/BarChart.spec.js +63 -0
- package/tests/unit/datavisualisations/ColumnChart.spec.js +344 -0
- package/tests/unit/datavisualisations/LineChart.spec.js +155 -0
- package/tests/unit/datavisualisations/StackedBarChart.spec.js +294 -0
- package/tests/unit/datavisualisations/StackedColumnChart.spec.js +443 -0
- package/tests/unit/i18n.spec.ts +19 -0
- package/tests/unit/main.spec.js +82 -0
- package/tests/unit/maps/ChoroplethMap.spec.js +214 -0
- package/tests/unit/maps/ChoroplethMapAnnotation.spec.ts +186 -0
- package/tests/unit/maps/SymbolMap.spec.js +92 -0
- package/tests/unit/require.spec.js +22 -0
- package/tests/unit/setup.js +13 -0
- package/tests/unit/utils/assets.spec.js +61 -0
- package/tests/unit/utils/clipboard.spec.js +18 -0
- package/tests/unit/utils/iframe-resizer.spec.js +71 -0
- package/tsconfig.json +35 -0
- package/vite.config.ts +79 -0
- package/vitest.config.ts +19 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { defineComponent } from 'vue'
|
|
3
|
+
import type { CSSProperties } from 'vue'
|
|
4
|
+
|
|
5
|
+
type StyleTransition = Pick<CSSProperties, 'overflow' | 'transition-property' | 'transition-duration' | 'height'>
|
|
6
|
+
const STATE = {
|
|
7
|
+
PRE: 'pre',
|
|
8
|
+
ACTIVE: 'active',
|
|
9
|
+
POST: 'post'
|
|
10
|
+
}
|
|
11
|
+
interface SlideUpDownData {
|
|
12
|
+
state: string
|
|
13
|
+
mounted: boolean
|
|
14
|
+
scrollHeight: number
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* SlideUpDown
|
|
18
|
+
*/
|
|
19
|
+
export default defineComponent({
|
|
20
|
+
name: 'SlideUpDown',
|
|
21
|
+
props: {
|
|
22
|
+
/**
|
|
23
|
+
* Toggler property. Set to <em>false</em> to hide the component.
|
|
24
|
+
*/
|
|
25
|
+
active: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: false
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* Duration of the animation.
|
|
31
|
+
*/
|
|
32
|
+
duration: {
|
|
33
|
+
type: Number,
|
|
34
|
+
default: 200
|
|
35
|
+
},
|
|
36
|
+
/**
|
|
37
|
+
* HTML tag to render this component to.
|
|
38
|
+
*/
|
|
39
|
+
tag: {
|
|
40
|
+
type: String,
|
|
41
|
+
default: 'div'
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
data(): SlideUpDownData {
|
|
45
|
+
return {
|
|
46
|
+
state: STATE.POST,
|
|
47
|
+
mounted: false,
|
|
48
|
+
scrollHeight: 0
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
computed: {
|
|
52
|
+
stylePreTransition(): StyleTransition {
|
|
53
|
+
return {
|
|
54
|
+
overflow: 'hidden',
|
|
55
|
+
'transition-property': 'height',
|
|
56
|
+
'transition-duration': `${this.duration}ms`,
|
|
57
|
+
height: this.mounted ? `${this.containerScrollHeight}px` : 0
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
styleActiveTransition(): StyleTransition {
|
|
61
|
+
return {
|
|
62
|
+
overflow: 'hidden',
|
|
63
|
+
'transition-property': 'height',
|
|
64
|
+
'transition-duration': `${this.duration}ms`,
|
|
65
|
+
height: this.mounted ? `${this.activeHeight}px` : 'auto'
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
stylePostTransition(): StyleTransition {
|
|
69
|
+
// Reset style when the element is active
|
|
70
|
+
return this.active ? {} : this.styleActiveTransition
|
|
71
|
+
},
|
|
72
|
+
style(): StyleTransition {
|
|
73
|
+
switch (this.state) {
|
|
74
|
+
case STATE.PRE:
|
|
75
|
+
return this.stylePreTransition
|
|
76
|
+
case STATE.ACTIVE:
|
|
77
|
+
return this.styleActiveTransition
|
|
78
|
+
default:
|
|
79
|
+
return this.stylePostTransition
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
activeHeight(): number {
|
|
83
|
+
return this.active ? this.containerScrollHeight : 0
|
|
84
|
+
},
|
|
85
|
+
containerScrollHeight(): number {
|
|
86
|
+
return this.$container?.scrollHeight ?? 0
|
|
87
|
+
},
|
|
88
|
+
$container(): HTMLElement | undefined {
|
|
89
|
+
return this.$refs.container as HTMLElement | undefined
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
watch: {
|
|
93
|
+
active(): Promise<void> {
|
|
94
|
+
return this.triggerSlide()
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
async mounted() {
|
|
98
|
+
await this.deferredNextTick()
|
|
99
|
+
this.mounted = true
|
|
100
|
+
await this.cleanLayout(null)
|
|
101
|
+
this.$container?.addEventListener('transitionend', (e) => this.cleanLayout(e))
|
|
102
|
+
},
|
|
103
|
+
methods: {
|
|
104
|
+
async triggerSlide(): Promise<void> {
|
|
105
|
+
this.state = STATE.PRE
|
|
106
|
+
this.scrollHeight = this.containerScrollHeight
|
|
107
|
+
// Deferred next tick to let the component render once
|
|
108
|
+
await this.deferredNextTick()
|
|
109
|
+
this.state = STATE.ACTIVE
|
|
110
|
+
},
|
|
111
|
+
cleanLayout(e: Event | null) {
|
|
112
|
+
// This method can be triggered by animated child elements in
|
|
113
|
+
// which case, we should do anything
|
|
114
|
+
if (!e || e.target === this.$container) {
|
|
115
|
+
this.state = STATE.POST
|
|
116
|
+
return this.deferredNextTick()
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
async deferredNextTick() {
|
|
120
|
+
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
121
|
+
await this.$nextTick()
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
</script>
|
|
126
|
+
|
|
127
|
+
<template>
|
|
128
|
+
<component :is="tag" ref="container" :style="style">
|
|
129
|
+
<slot />
|
|
130
|
+
</component>
|
|
131
|
+
</template>
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { clamp } from 'lodash'
|
|
3
|
+
import {computed, defineComponent, PropType} from 'vue'
|
|
4
|
+
|
|
5
|
+
import { DeckTexture } from '@/enums'
|
|
6
|
+
import config from '@/config'
|
|
7
|
+
|
|
8
|
+
type TexturedDeckValue = DeckTexture | number
|
|
9
|
+
|
|
10
|
+
export default defineComponent({
|
|
11
|
+
name: 'TexturedDeck',
|
|
12
|
+
props: {
|
|
13
|
+
/**
|
|
14
|
+
* Name of the texture file ('silk', 'brick', 'rock', 'sand', 'crack', 'carbon')
|
|
15
|
+
*/
|
|
16
|
+
modelValue: {
|
|
17
|
+
type: String as PropType<TexturedDeckValue>,
|
|
18
|
+
default: DeckTexture.Brick
|
|
19
|
+
},
|
|
20
|
+
/**
|
|
21
|
+
* CSS background-size property (cover, contain, auto, 50%, 50% auto, ...)
|
|
22
|
+
*/
|
|
23
|
+
size: {
|
|
24
|
+
type: String,
|
|
25
|
+
default: 'cover'
|
|
26
|
+
},
|
|
27
|
+
/**
|
|
28
|
+
* Tag/Component to use as root tag.
|
|
29
|
+
*/
|
|
30
|
+
tag: {
|
|
31
|
+
type: [String, Object],
|
|
32
|
+
default: 'div'
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Either or note we should use the black version of the texture
|
|
36
|
+
*/
|
|
37
|
+
black: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default:false
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* Host where to find the textures (without tailing slash)
|
|
43
|
+
*/
|
|
44
|
+
backgroundBaseUrl: {
|
|
45
|
+
type: String,
|
|
46
|
+
default: () => config.get('textured-deck.background-base-url', window.location.origin)
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
setup(props, {attrs}) {
|
|
50
|
+
const names = computed((): DeckTexture[] =>{
|
|
51
|
+
return Object.values(DeckTexture)
|
|
52
|
+
})
|
|
53
|
+
const textureIndex = computed((): number =>{
|
|
54
|
+
if (typeof props.modelValue !== 'number') {
|
|
55
|
+
return clamp(names.value.indexOf(props.modelValue), 0, names.value.length - 1)
|
|
56
|
+
}
|
|
57
|
+
return props.modelValue
|
|
58
|
+
})
|
|
59
|
+
const textureName = computed((): string =>{
|
|
60
|
+
return names.value[textureIndex.value]
|
|
61
|
+
})
|
|
62
|
+
const filename = computed((): string =>{
|
|
63
|
+
if (props.black) {
|
|
64
|
+
return `texture-${textureName.value}-black.jpg`
|
|
65
|
+
}
|
|
66
|
+
return `texture-${textureName.value}.jpg`
|
|
67
|
+
})
|
|
68
|
+
const backgroundUrl = computed((): string =>{
|
|
69
|
+
return `${props.backgroundBaseUrl}/assets/img/${filename.value}`
|
|
70
|
+
})
|
|
71
|
+
const backgroundSize = computed((): string =>{
|
|
72
|
+
return props.size
|
|
73
|
+
})
|
|
74
|
+
const backgroundImage = computed((): string =>{
|
|
75
|
+
return `url("${backgroundUrl.value}")`
|
|
76
|
+
})
|
|
77
|
+
const inheritedProps = computed((): object =>{
|
|
78
|
+
return { ...attrs, ...props, tag: undefined }
|
|
79
|
+
})
|
|
80
|
+
return {
|
|
81
|
+
backgroundSize,
|
|
82
|
+
backgroundImage,
|
|
83
|
+
inheritedProps
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
</script>
|
|
88
|
+
|
|
89
|
+
<template>
|
|
90
|
+
<component :is="tag" :style="{ backgroundSize, backgroundImage }" v-bind="inheritedProps" class="textured-deck">
|
|
91
|
+
<slot />
|
|
92
|
+
</component>
|
|
93
|
+
</template>
|
|
94
|
+
|
|
95
|
+
<style lang="scss" scoped>
|
|
96
|
+
.textured-deck {
|
|
97
|
+
background: #000 no-repeat center center;
|
|
98
|
+
background-size: cover;
|
|
99
|
+
color: #fff;
|
|
100
|
+
}
|
|
101
|
+
</style>
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="tiny-pagination" :class="paginationClassList">
|
|
3
|
+
<b-button
|
|
4
|
+
class="tiny-pagination__nav"
|
|
5
|
+
:size="size"
|
|
6
|
+
:disabled="!hasPrevious"
|
|
7
|
+
:variant="navVariant"
|
|
8
|
+
@click="applyPreviousPage"
|
|
9
|
+
>
|
|
10
|
+
<!-- @slot Previous button content -->
|
|
11
|
+
<slot name="previous" v-bind="{ modelValue, numberOfPages, hasPrevious, hasNext }">
|
|
12
|
+
<fa :icon="previousPageIcon" />
|
|
13
|
+
<span class="sr-only">{{ t('tiny-pagination.previous') }}</span>
|
|
14
|
+
</slot>
|
|
15
|
+
</b-button>
|
|
16
|
+
<form class="tiny-pagination__form form-inline" @submit.prevent="applyPageForm">
|
|
17
|
+
<label v-show="!compact" class="tiny-pagination__form__label me-1 mb-0">
|
|
18
|
+
<!-- @slot Display page label -->
|
|
19
|
+
<slot name="page" v-bind="{ modelValue, numberOfPages }">
|
|
20
|
+
{{ t('tiny-pagination.page') }}
|
|
21
|
+
</slot>
|
|
22
|
+
</label>
|
|
23
|
+
<b-form-input
|
|
24
|
+
v-model="currentPageInput"
|
|
25
|
+
:size="size"
|
|
26
|
+
class="tiny-pagination__form__input me-1"
|
|
27
|
+
type="number"
|
|
28
|
+
step="1"
|
|
29
|
+
:min="1"
|
|
30
|
+
:max="numberOfPages"
|
|
31
|
+
:aria-label="t('tiny-pagination.aria')"
|
|
32
|
+
/>
|
|
33
|
+
<!-- @slot Display number of pages -->
|
|
34
|
+
<slot name="number-of-pages" v-bind="{ modelValue, numberOfPages }">
|
|
35
|
+
{{ t('tiny-pagination.total', { numberOfPages }) }}
|
|
36
|
+
</slot>
|
|
37
|
+
</form>
|
|
38
|
+
<b-button
|
|
39
|
+
class="tiny-pagination__nav"
|
|
40
|
+
:size="size"
|
|
41
|
+
:disabled="!hasNext"
|
|
42
|
+
:variant="navVariant"
|
|
43
|
+
@click="applyNextPage"
|
|
44
|
+
>
|
|
45
|
+
<!-- @slot Next button content -->
|
|
46
|
+
<slot name="next" v-bind="{ modelValue, numberOfPages, hasPrevious, hasNext }">
|
|
47
|
+
<fa :icon="nextPageIcon" />
|
|
48
|
+
<span class="sr-only">{{ t('tiny-pagination.next') }}</span>
|
|
49
|
+
</slot>
|
|
50
|
+
</b-button>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script lang="ts">
|
|
55
|
+
import { faAngleLeft, faAngleRight } from '@fortawesome/free-solid-svg-icons'
|
|
56
|
+
import { defineComponent, PropType, ref, computed, watch, onBeforeMount } from 'vue'
|
|
57
|
+
import {useI18n} from "vue-i18n";
|
|
58
|
+
|
|
59
|
+
import { library, default as Fa } from './Fa'
|
|
60
|
+
|
|
61
|
+
import { Size } from '@/enums'
|
|
62
|
+
import { ButtonVariant, BFormInput, BButton } from 'bootstrap-vue-next'
|
|
63
|
+
|
|
64
|
+
export default defineComponent({
|
|
65
|
+
name: 'TinyPagination',
|
|
66
|
+
components: {
|
|
67
|
+
Fa,
|
|
68
|
+
BFormInput,
|
|
69
|
+
BButton
|
|
70
|
+
},
|
|
71
|
+
props: {
|
|
72
|
+
/**
|
|
73
|
+
* Total items to be stored in pages
|
|
74
|
+
*/
|
|
75
|
+
totalRows: {
|
|
76
|
+
type: Number,
|
|
77
|
+
default: 0
|
|
78
|
+
},
|
|
79
|
+
/**
|
|
80
|
+
* Sets the quantity of items per page
|
|
81
|
+
*/
|
|
82
|
+
perPage: {
|
|
83
|
+
type: Number,
|
|
84
|
+
default: 20
|
|
85
|
+
},
|
|
86
|
+
/**
|
|
87
|
+
* Grabs and syncs the currentPage variable passed down from the parent in v-model
|
|
88
|
+
*/
|
|
89
|
+
modelValue: {
|
|
90
|
+
type: [Number, String],
|
|
91
|
+
default: 1
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* Set the size of the input: 'sm', 'md' (default), or 'lg'.
|
|
95
|
+
*/
|
|
96
|
+
size: {
|
|
97
|
+
type: String as PropType<Size>,
|
|
98
|
+
default: Size.md,
|
|
99
|
+
validator: (value: Size) => Object.values(Size).includes(value)
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* (Optional) Number of page. Property `size` is required for this to work
|
|
103
|
+
* properly. If `pages` is empty, it will be calculated using the size.
|
|
104
|
+
*/
|
|
105
|
+
pages: {
|
|
106
|
+
type: [Number, String],
|
|
107
|
+
default: null
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* Hide navigation buttons (next and previous)
|
|
111
|
+
*/
|
|
112
|
+
noNav: {
|
|
113
|
+
type: Boolean
|
|
114
|
+
},
|
|
115
|
+
/**
|
|
116
|
+
* FontAwesome icon of the previous page button
|
|
117
|
+
*/
|
|
118
|
+
previousPageIcon: {
|
|
119
|
+
type: [String, Array, Object],
|
|
120
|
+
default: 'angle-left'
|
|
121
|
+
},
|
|
122
|
+
/**
|
|
123
|
+
* FontAwesome icon of the next page button
|
|
124
|
+
*/
|
|
125
|
+
nextPageIcon: {
|
|
126
|
+
type: [String, Array, Object],
|
|
127
|
+
default: 'angle-right'
|
|
128
|
+
},
|
|
129
|
+
/**
|
|
130
|
+
* Navigation button variants
|
|
131
|
+
*/
|
|
132
|
+
navVariant: {
|
|
133
|
+
type: String as PropType<ButtonVariant>,
|
|
134
|
+
default: 'link'
|
|
135
|
+
},
|
|
136
|
+
/**
|
|
137
|
+
* Display pagination as a block (full width)
|
|
138
|
+
*/
|
|
139
|
+
block: {
|
|
140
|
+
type: Boolean
|
|
141
|
+
},
|
|
142
|
+
/**
|
|
143
|
+
* Compact mode with a grouped nav
|
|
144
|
+
*/
|
|
145
|
+
compact: {
|
|
146
|
+
type: Boolean
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
emits:['update:modelValue'],
|
|
150
|
+
setup(props,{emit}) {
|
|
151
|
+
|
|
152
|
+
onBeforeMount(()=> {
|
|
153
|
+
library.add(faAngleLeft, faAngleRight)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
const { t } = useI18n()
|
|
157
|
+
const pageValue = computed(()=>{return +props.modelValue})
|
|
158
|
+
const currentPageInput = ref<number|string>(pageValue.value)
|
|
159
|
+
const numberOfPages = computed((): number =>{
|
|
160
|
+
if (props.pages === null) {
|
|
161
|
+
return Math.ceil(props.totalRows / props.perPage)
|
|
162
|
+
}
|
|
163
|
+
return Number(props.pages)
|
|
164
|
+
})
|
|
165
|
+
const paginationClassList = computed((): object =>{
|
|
166
|
+
return {
|
|
167
|
+
[`tiny-pagination--${props.size}`]: true,
|
|
168
|
+
[`tiny-pagination--no-nav`]: props.noNav,
|
|
169
|
+
[`tiny-pagination--block`]: props.block,
|
|
170
|
+
[`tiny-pagination--compact`]: props.compact
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
const hasPrevious = computed((): boolean =>{
|
|
174
|
+
return pageValue.value > 1
|
|
175
|
+
})
|
|
176
|
+
const hasNext = computed((): boolean =>{
|
|
177
|
+
return pageValue.value < numberOfPages.value
|
|
178
|
+
})
|
|
179
|
+
function applyPageForm(): void {
|
|
180
|
+
if (!isNaN(currentPageInput.value as number)) {
|
|
181
|
+
emit('update:modelValue', +currentPageInput.value)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function applyNextPage(): void {
|
|
186
|
+
emit('update:modelValue', pageValue.value - 1)
|
|
187
|
+
}
|
|
188
|
+
function applyPreviousPage(): void {
|
|
189
|
+
emit('update:modelValue', pageValue.value + 1)
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
t,
|
|
193
|
+
currentPageInput,
|
|
194
|
+
paginationClassList,
|
|
195
|
+
numberOfPages,
|
|
196
|
+
hasPrevious,
|
|
197
|
+
hasNext,
|
|
198
|
+
applyPreviousPage,
|
|
199
|
+
applyNextPage,
|
|
200
|
+
applyPageForm
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
</script>
|
|
205
|
+
|
|
206
|
+
<style lang="scss" scoped>
|
|
207
|
+
@import '../styles/lib';
|
|
208
|
+
|
|
209
|
+
.tiny-pagination {
|
|
210
|
+
display: inline-flex;
|
|
211
|
+
align-items: center;
|
|
212
|
+
justify-content: center;
|
|
213
|
+
text-align: center;
|
|
214
|
+
|
|
215
|
+
&--block {
|
|
216
|
+
display: flex;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
&--sm {
|
|
220
|
+
font-size: $font-size-sm;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
&--lg {
|
|
224
|
+
font-size: $font-size-lg;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
&--no-nav &__nav {
|
|
228
|
+
display: none;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
&--no-nav &__form {
|
|
232
|
+
margin: 0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
&--compact &__nav {
|
|
236
|
+
order: 0;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
&--compact &__form {
|
|
240
|
+
order: 10;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
&__form {
|
|
244
|
+
margin: 0 $spacer * 0.25;
|
|
245
|
+
width: 100%;
|
|
246
|
+
display: flex;
|
|
247
|
+
align-items: center;
|
|
248
|
+
justify-content: center;
|
|
249
|
+
|
|
250
|
+
&__input {
|
|
251
|
+
max-width: 2.5rem;
|
|
252
|
+
padding-left: 0.2rem;
|
|
253
|
+
padding-right: 0.2rem;
|
|
254
|
+
text-align: center;
|
|
255
|
+
|
|
256
|
+
&[type='number'] {
|
|
257
|
+
-moz-appearance: textfield;
|
|
258
|
+
|
|
259
|
+
&::-webkit-outer-spin-button,
|
|
260
|
+
&::-webkit-inner-spin-button {
|
|
261
|
+
-webkit-appearance: none;
|
|
262
|
+
margin: 0;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export { default as AccordionWrapper } from './AccordionWrapper.vue'
|
|
2
|
+
export { default as AccordionStep } from './AccordionStep.vue'
|
|
3
|
+
export { default as ActiveTextTruncate } from './ActiveTextTruncate.vue'
|
|
4
|
+
export { default as AdvancedLinkForm } from './AdvancedLinkForm.vue'
|
|
5
|
+
export { default as BrandExpansion } from './BrandExpansion.vue'
|
|
6
|
+
export { default as Brand } from './Brand.vue'
|
|
7
|
+
export { default as ConfirmButton } from './ConfirmButton.vue'
|
|
8
|
+
export { default as ContentPlaceholder } from './ContentPlaceholder.vue'
|
|
9
|
+
export { default as CustomPagination } from './CustomPagination.vue'
|
|
10
|
+
export { default as DigitsInput } from './DigitsInput.vue'
|
|
11
|
+
export { default as DonateForm } from './DonateForm.vue'
|
|
12
|
+
export { default as EmbeddableFooter } from './EmbeddableFooter.vue'
|
|
13
|
+
export { default as EmbedForm } from './EmbedForm.vue'
|
|
14
|
+
export { default as FollowUsPopover } from './FollowUsPopover.vue'
|
|
15
|
+
export { default as Fa } from './Fa'
|
|
16
|
+
export { default as GenericFooter } from './GenericFooter.vue'
|
|
17
|
+
export { default as GenericHeader } from './GenericHeader.vue'
|
|
18
|
+
export { default as HapticCopy } from './HapticCopy.vue'
|
|
19
|
+
export { default as ImddbHeader } from './ImddbHeader.vue'
|
|
20
|
+
export { default as OrdinalLegend } from './OrdinalLegend.vue'
|
|
21
|
+
export { default as RangePicker } from './RangePicker.vue'
|
|
22
|
+
export { default as ResponsiveIframe } from './ResponsiveIframe.vue'
|
|
23
|
+
export { default as ScaleLegend } from './ScaleLegend.vue'
|
|
24
|
+
export { default as SelectableDropdown } from './SelectableDropdown.vue'
|
|
25
|
+
export { default as SecretInput } from './SecretInput.vue'
|
|
26
|
+
export { default as SharingOptions } from './SharingOptions.vue'
|
|
27
|
+
export { default as SharingOptionsLink } from './SharingOptionsLink.vue'
|
|
28
|
+
export { default as SignUpForm } from './SignUpForm.vue'
|
|
29
|
+
export { default as SlideUpDown } from './SlideUpDown.vue'
|
|
30
|
+
export { default as TexturedDeck } from './TexturedDeck.vue'
|
|
31
|
+
export { default as TinyPagination } from './TinyPagination.vue'
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import * as d3 from 'd3'
|
|
2
|
+
import isFunction from 'lodash/isFunction'
|
|
3
|
+
import isObject from 'lodash/isObject'
|
|
4
|
+
import isString from 'lodash/isString'
|
|
5
|
+
import max from 'lodash/max'
|
|
6
|
+
import some from 'lodash/some'
|
|
7
|
+
import {ComponentPublicInstance, computed, onMounted, ref, watch} from 'vue'
|
|
8
|
+
import {isUrl} from '@/utils/strings'
|
|
9
|
+
import { Ref, SetupContext} from "@vue/runtime-core";
|
|
10
|
+
import useResizeObserver from "@/composables/resizeObserver";
|
|
11
|
+
import { watchEffect } from 'vue'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
type ChartContext<T extends string[]> = SetupContext<[...T, ...string[]]>;
|
|
15
|
+
type ChartEmit = Pick<ChartContext<["resized", "loaded"]>, 'emit'>
|
|
16
|
+
type ChartProps = {
|
|
17
|
+
chartHeightRatio: { type: NumberConstructor },
|
|
18
|
+
data: {
|
|
19
|
+
default: () => any[] | string,
|
|
20
|
+
validator(value: string): boolean,
|
|
21
|
+
type: (ArrayConstructor | StringConstructor | ObjectConstructor)[]
|
|
22
|
+
},
|
|
23
|
+
dataUrlType: { default: string, validator(value: string): boolean, type: StringConstructor },
|
|
24
|
+
socialMode: { type: BooleanConstructor },
|
|
25
|
+
socialModeRatio:
|
|
26
|
+
{ default: number, type: NumberConstructor }
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function getChartProps(props: any): ChartProps {
|
|
30
|
+
return {
|
|
31
|
+
chartHeightRatio: props.chartHeightRatio,
|
|
32
|
+
data: props.data,
|
|
33
|
+
dataUrlType: props.dataUrlType,
|
|
34
|
+
socialMode: props.socialMode,
|
|
35
|
+
socialModeRatio: props.socialModeRatio,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const chartProps = (): ChartProps => ({
|
|
40
|
+
data: {
|
|
41
|
+
type: [Array, String, Object],
|
|
42
|
+
default: () => [],
|
|
43
|
+
validator(value: string) {
|
|
44
|
+
return isObject(value) || (isString(value) && isUrl(value))
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* Format of the data to load.
|
|
49
|
+
*/
|
|
50
|
+
dataUrlType: {
|
|
51
|
+
type: String,
|
|
52
|
+
default: 'json',
|
|
53
|
+
validator(value: string) {
|
|
54
|
+
return ['json', 'csv', 'tsv'].indexOf(value) > -1
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
* When applicable, default chart's height ratio
|
|
59
|
+
*/
|
|
60
|
+
chartHeightRatio: {
|
|
61
|
+
type: Number
|
|
62
|
+
},
|
|
63
|
+
/**
|
|
64
|
+
* If true, the chart will be display on social mode
|
|
65
|
+
*/
|
|
66
|
+
socialMode: {
|
|
67
|
+
type: Boolean
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* Ratio to use in social mode
|
|
71
|
+
*/
|
|
72
|
+
socialModeRatio: {
|
|
73
|
+
type: Number,
|
|
74
|
+
default: 5 / 4
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
export const chartEmits = ["resized", "loaded"]
|
|
78
|
+
type Chart = {
|
|
79
|
+
dataHasHighlights: any;
|
|
80
|
+
loadedData: any;
|
|
81
|
+
xAxisYearFormat: (year: (number | string)) => number | string;
|
|
82
|
+
elementsMaxBBox: ({selector, defaultWidth, defaultHeight}?: {
|
|
83
|
+
selector?: any;
|
|
84
|
+
defaultWidth?: any;
|
|
85
|
+
defaultHeight?: any
|
|
86
|
+
}) => ({ width: any; height: any });
|
|
87
|
+
d3Formatter: any;
|
|
88
|
+
baseHeightRatio: any
|
|
89
|
+
}
|
|
90
|
+
export function useChart(resizableRef: Ref<ComponentPublicInstance<HTMLElement> | null>, props: ChartProps, {emit}: ChartEmit, isLoaded:Ref<boolean>, onResized?:Function, afterLoaded?:()=>Promise<any>): Chart {
|
|
91
|
+
const { resizeRef , resizeState } = useResizeObserver(resizableRef)
|
|
92
|
+
const loadedData = ref([])
|
|
93
|
+
|
|
94
|
+
onMounted(async () => {
|
|
95
|
+
await document.fonts?.ready
|
|
96
|
+
|
|
97
|
+
watchEffect(async ()=>{
|
|
98
|
+
if(!isLoaded.value){
|
|
99
|
+
|
|
100
|
+
if (isString(props.data)) {
|
|
101
|
+
// @ts-ignore
|
|
102
|
+
loadedData.value = await d3[props.dataUrlType](props.data)
|
|
103
|
+
} else {
|
|
104
|
+
loadedData.value = props.data as unknown as []
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if(afterLoaded){
|
|
108
|
+
await afterLoaded()
|
|
109
|
+
}
|
|
110
|
+
isLoaded.value = true
|
|
111
|
+
emit('loaded')
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if(isLoaded.value && onResized){
|
|
115
|
+
onResized()
|
|
116
|
+
emit('resized')
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
})
|
|
122
|
+
function elementsMaxBBox({selector = 'text', defaultWidth = null, defaultHeight = null} = {}) {
|
|
123
|
+
|
|
124
|
+
const elements = isLoaded.value? resizeRef.value?.querySelectorAll(selector) : []
|
|
125
|
+
if (elements.length == 0) {
|
|
126
|
+
return {width: defaultWidth, height: defaultHeight}
|
|
127
|
+
}
|
|
128
|
+
const width = max(
|
|
129
|
+
[...elements].map((l) => {
|
|
130
|
+
return l.getBBox ? l.getBBox().width : defaultWidth
|
|
131
|
+
})
|
|
132
|
+
)
|
|
133
|
+
const height = max(
|
|
134
|
+
[...elements].map((l) => {
|
|
135
|
+
return l.getBBox ? l.getBBox().height : defaultHeight
|
|
136
|
+
})
|
|
137
|
+
)
|
|
138
|
+
return {width, height}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function xAxisYearFormat(year: number | string) {
|
|
142
|
+
// previously using narrowWidth but it is automatically updated through resizeObserver state reactivity
|
|
143
|
+
return resizeState.narrowWidth ? '’' + String(year).slice(2, 4) : year
|
|
144
|
+
}
|
|
145
|
+
function highlighted(datum: { highlight: boolean }) {
|
|
146
|
+
return datum.highlight
|
|
147
|
+
}
|
|
148
|
+
function d3Formatter(value:any,formatter:any) {
|
|
149
|
+
if (isFunction(formatter)) {
|
|
150
|
+
return formatter(value)
|
|
151
|
+
} else if (isString(formatter)) {
|
|
152
|
+
return d3.format(formatter)(value)
|
|
153
|
+
}
|
|
154
|
+
return value
|
|
155
|
+
}
|
|
156
|
+
const baseHeightRatio = computed(() => {
|
|
157
|
+
return props.chartHeightRatio || (props.socialMode ? props.socialModeRatio : 9 / 16)
|
|
158
|
+
})
|
|
159
|
+
const dataHasHighlights = computed(() => {
|
|
160
|
+
if (Array.isArray(props.data)) {
|
|
161
|
+
return some(props.data, highlighted)
|
|
162
|
+
}
|
|
163
|
+
return false
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
watch(resizeState.dimensions, () => {
|
|
167
|
+
if(isLoaded.value && onResized){
|
|
168
|
+
onResized()
|
|
169
|
+
emit('resized')
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
loadedData,
|
|
176
|
+
elementsMaxBBox,
|
|
177
|
+
xAxisYearFormat,
|
|
178
|
+
d3Formatter,
|
|
179
|
+
baseHeightRatio,
|
|
180
|
+
dataHasHighlights,
|
|
181
|
+
}
|
|
182
|
+
}
|