components/story_viewer.vue (107 lines of code) (raw):
<script>
import { camelCase } from 'lodash';
import { GlCard, GlIcon, GlLink } from '../helpers/gitlab_ui';
import StoryIframe from './story_iframe.vue';
const VIEW_MODE_STORY = 'story';
const VIEW_MODE_DOCS = 'docs';
export default {
components: {
GlCard,
GlIcon,
GlLink,
StoryIframe,
},
props: {
component: {
type: String,
required: true,
},
story: {
type: String,
required: false,
default: 'default',
},
title: {
type: String,
required: false,
default: null,
},
iframePadding: {
type: String,
required: false,
default: null,
},
viewMode: {
type: String,
required: false,
default: VIEW_MODE_STORY,
validator: (viewMode) => [VIEW_MODE_STORY, VIEW_MODE_DOCS].includes(viewMode),
},
},
computed: {
isDocsMode() {
return this.viewMode === VIEW_MODE_DOCS;
},
storyName() {
const suffix = this.isDocsMode ? 'docs' : this.story;
return `${this.component}--${suffix}`;
},
cardTitle() {
return this.title || this.storyName;
},
storyUrl() {
const url = new URL(this.$gitlabUiUrl);
url.searchParams.append('path', `/${this.viewMode}/${this.storyName}`);
if (this.storyBookArgs) {
url.searchParams.append('args', this.storyBookArgs);
}
return url.href;
},
storyBookArgs() {
return Object.entries(this.$attrs)
.flatMap(([key, value]) => {
if (!key.startsWith('args-')) {
return [];
}
return `${camelCase(key.substring(5))}:${value}`;
})
.join(';');
},
iFrameUrl() {
const url = new URL(`${this.$gitlabUiUrl}/iframe.html`);
url.searchParams.append('id', this.storyName);
url.searchParams.append('viewMode', this.viewMode);
if (this.storyBookArgs) {
url.searchParams.append('args', this.storyBookArgs);
}
return url.href;
},
},
};
</script>
<template>
<div class="gl-mb-5">
<story-iframe
v-if="isDocsMode"
:url="iFrameUrl"
:iframe-padding="iframePadding"
:title="cardTitle"
/>
<gl-card v-else>
<template #header>
<div class="gl-flex gl-gap-3">
<div>
<strong data-testid="story-title">{{ cardTitle }}</strong>
</div>
<div class="gl-ml-auto gl-text-right">
<gl-link :href="storyUrl" target="_blank" data-testid="story-link">
Open in Storybook
<gl-icon name="external-link" />
</gl-link>
</div>
</div>
</template>
<story-iframe :url="iFrameUrl" :iframe-padding="iframePadding" :title="cardTitle" />
</gl-card>
</div>
</template>