@explorer-1/vue 0.2.99 → 0.2.101

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @explorer-1/vue
2
2
 
3
+ ## 0.2.101
4
+
5
+ ### Patch Changes
6
+
7
+ - Adds Newsletter Signup Block
8
+ - Fixes captions in Video Embed block when used as a hero
9
+
10
+ ## 0.2.100
11
+
12
+ ### Patch Changes
13
+
14
+ - fb6ba35: Fixing height of HeroMedia
15
+ - Updated dependencies [fb6ba35]
16
+ - @explorer-1/common@1.1.24
17
+
3
18
  ## 0.2.99
4
19
 
5
20
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@explorer-1/vue",
3
- "version": "0.2.99",
3
+ "version": "0.2.101",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -30,7 +30,7 @@
30
30
  "vue-bind-once": "^0.2.1",
31
31
  "vue3-compare-image": "^1.2.5",
32
32
  "vue3-observe-visibility": "^1.0.1",
33
- "@explorer-1/common": "1.1.23"
33
+ "@explorer-1/common": "1.1.24"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@vitejs/plugin-vue": "^5.0.4",
@@ -43,7 +43,7 @@
43
43
  >
44
44
  <span
45
45
  v-if="option.title"
46
- class="font-semibold"
46
+ :class="option.text ? 'font-semibold' : ''"
47
47
  >{{ option.title }}</span
48
48
  >
49
49
  <span v-if="option.text"> - </span>
@@ -0,0 +1,21 @@
1
+ import BlockNewsletterSignup from './BlockNewsletterSignup.vue'
2
+
3
+ export default {
4
+ title: 'Components/Blocks/BlockNewsletterSignup',
5
+ component: BlockNewsletterSignup,
6
+ excludeStories: /.*Data$/
7
+ }
8
+
9
+ export const BlockNewsletterSignupData = {
10
+ blockType: 'NewsletterSignupBlock',
11
+ title: 'Get the JPL Newsletter',
12
+ description:
13
+ 'From Mars to the Milky Way—never miss a discovery! Delivered straight to your inbox.',
14
+ buttonText: 'Sign Up'
15
+ }
16
+
17
+ export const BaseStory = {
18
+ args: {
19
+ data: BlockNewsletterSignupData
20
+ }
21
+ }
@@ -0,0 +1,177 @@
1
+ <template>
2
+ <div
3
+ class="BlockNewsletterSignup bg-gray-light edu:bg-stars edu:bg-primary md:mx-0 sm:py-8 md:px-10 sm:mx-20 px-6 py-6 edu:text-white"
4
+ >
5
+ <div class="md:mx-16 xl:mx-24 text-center">
6
+ <p class="text-h6 edu:text-white edu:font-extrabold mb-3">{{ data.title }}</p>
7
+ <p>{{ data.description }}</p>
8
+ </div>
9
+ <hr class="text-gray-mid mt-6 mb-5" />
10
+
11
+ <div class="mb-3">
12
+ <form
13
+ id="ic_signupform"
14
+ target="_blank"
15
+ :captcha-key="captchaKey"
16
+ captcha-theme="light"
17
+ new-captcha="true"
18
+ method="POST"
19
+ :action="iContactForm"
20
+ >
21
+ <div
22
+ dataname="listGroups"
23
+ data-label="Which email groups would you like to join?"
24
+ >
25
+ <div>
26
+ <BaseRadioGroup
27
+ v-model="form.listgroups"
28
+ heading="Frequency:"
29
+ group="email"
30
+ title="Email Groups"
31
+ preselected="breaking"
32
+ :options="emailGroups"
33
+ />
34
+ </div>
35
+ </div>
36
+ <div class="flex flex-row flex-nowrap">
37
+ <TextInput
38
+ v-model="form.email"
39
+ class="email-container h-auto w-full"
40
+ input-name="data[email]"
41
+ label="Email"
42
+ type="email"
43
+ required
44
+ placeholder="Email address"
45
+ :show-label="false"
46
+ />
47
+ <div class="submit-container h-auto">
48
+ <BaseButton
49
+ class="text-nowrap"
50
+ variant="primary"
51
+ compact
52
+ >
53
+ {{ data.buttonText }}
54
+ </BaseButton>
55
+ </div>
56
+ </div>
57
+ </form>
58
+ </div>
59
+ </div>
60
+ </template>
61
+ <script lang="ts">
62
+ // @ts-nocheck
63
+ import { defineComponent } from 'vue'
64
+ import { mapStores } from 'pinia'
65
+ import { useThemeStore } from '../../store/theme'
66
+ import BaseButton from './../BaseButton/BaseButton.vue'
67
+ import BaseRadioGroup from './../BaseRadioGroup/BaseRadioGroup.vue'
68
+ import TextInput from './../TextInput/TextInput.vue'
69
+
70
+ const iContactForm =
71
+ 'https://app.icontact.com/icp/core/mycontacts/signup/designer/form/?id=5&cid=1389932&lid=11365'
72
+
73
+ const captchaKey = '6LeCZCcUAAAAALhxcQ5fN80W6Wa2K3GqRQK6WRjA'
74
+
75
+ const iContactTrackingGif =
76
+ 'https://app.icontact.com/icp/core/signup/tracking.gif?id=5&cid=1389932&lid=11365'
77
+
78
+ const emailGroups = [
79
+ {
80
+ id: 'breaking',
81
+ title: 'Latest News',
82
+ value: '41031',
83
+ alt: 'Lists',
84
+ name: 'data[listGroups][]'
85
+ },
86
+ {
87
+ id: 'daily',
88
+ title: 'Daily',
89
+ value: '41032',
90
+ alt: 'Lists',
91
+ name: 'data[listGroups][]'
92
+ },
93
+ {
94
+ id: 'weekly',
95
+ title: 'Weekly',
96
+ value: '41033',
97
+ alt: 'Lists',
98
+ name: 'data[listGroups][]'
99
+ },
100
+ {
101
+ id: 'monthly',
102
+ title: 'Monthly',
103
+ value: '41034',
104
+ alt: 'Lists',
105
+ name: 'data[listGroups][]'
106
+ }
107
+ ]
108
+
109
+ export default defineComponent({
110
+ name: 'BlockNewsletterSignup',
111
+ components: {
112
+ BaseButton,
113
+ BaseRadioGroup,
114
+ TextInput
115
+ },
116
+ props: {
117
+ data: {
118
+ type: Object,
119
+ required: true,
120
+ default: () => ({})
121
+ }
122
+ },
123
+ data() {
124
+ return {
125
+ submitted: false,
126
+ form: {
127
+ email: undefined,
128
+ listGroups: undefined
129
+ }
130
+ }
131
+ },
132
+ computed: {
133
+ ...mapStores(useThemeStore),
134
+ buttonVariant() {
135
+ return this.themeStore.theme === 'ThemeEdu' ? 'dark' : 'primary'
136
+ },
137
+ iContactForm() {
138
+ return iContactForm
139
+ },
140
+ iContactTrackingGif() {
141
+ return iContactTrackingGif
142
+ },
143
+ captchaKey() {
144
+ return captchaKey
145
+ },
146
+ emailGroups() {
147
+ return emailGroups
148
+ }
149
+ },
150
+ mounted() {
151
+ const validationScript = document.createElement('script')
152
+ validationScript.setAttribute(
153
+ 'src',
154
+ 'https://app.icontact.com/icp/static/form/javascripts/validation-captcha.js'
155
+ )
156
+ const trackingScript = document.createElement('script')
157
+ trackingScript.setAttribute(
158
+ 'src',
159
+ 'https://app.icontact.com/icp/static/form/javascripts/tracking.js'
160
+ )
161
+ document.head.appendChild(validationScript, trackingScript)
162
+ }
163
+ })
164
+ </script>
165
+ <style type="scss">
166
+ .BlockNewsletterSignup {
167
+ fieldset > div {
168
+ column-count: 2;
169
+ }
170
+ .email-container input {
171
+ @apply mt-0 -mr-1;
172
+ }
173
+ .BaseRadioGroup label {
174
+ @apply text-base text-left;
175
+ }
176
+ }
177
+ </style>
@@ -16,6 +16,7 @@ import { BlockTeaserData } from './../BlockTeaser/BlockTeaser.stories'
16
16
  import { BlockIframeEmbedData } from './../BlockIframeEmbed/BlockIframeEmbed.stories'
17
17
  import { BlockVideoData } from './../BlockVideo/BlockVideo.stories'
18
18
  import { BlockVideoEmbedData } from './../BlockVideoEmbed/BlockVideoEmbed.stories'
19
+ import { BlockNewsletterSignupData } from '../BlockNewsletterSignup/BlockNewsletterSignup.stories'
19
20
  import { MixedColumnWidths } from './../BlockRichTable/BlockRichTable.stories'
20
21
  import BlockStreamfield, { variants } from './BlockStreamfield.vue'
21
22
 
@@ -167,6 +168,7 @@ export const BlockStreamfieldData = {
167
168
  ]
168
169
  }
169
170
  },
171
+ BlockNewsletterSignupData,
170
172
  {
171
173
  blockType: 'ListBlock',
172
174
  field: 'card_grid',
@@ -75,6 +75,14 @@
75
75
  >
76
76
  <BlockCta :data="block" />
77
77
  </LayoutHelper>
78
+ <LayoutHelper
79
+ v-else-if="block.blockType == 'NewsletterSignupBlock'"
80
+ :key="`newsletterSignupBlock${index}`"
81
+ indent="col-4"
82
+ :class="marginBottom"
83
+ >
84
+ <BlockNewsletterSignup :data="block" />
85
+ </LayoutHelper>
78
86
 
79
87
  <LayoutHelper
80
88
  v-else-if="block.blockType == 'TeaserBlock'"
@@ -277,6 +285,7 @@ import BlockVideo from './../BlockVideo/BlockVideo.vue'
277
285
  import BlockVideoEmbed, {
278
286
  type BlockData as VideoBlockEmbedData
279
287
  } from './../BlockVideoEmbed/BlockVideoEmbed.vue'
288
+ import BlockNewsletterSignup from '../BlockNewsletterSignup/BlockNewsletterSignup.vue'
280
289
  import { mapStores } from 'pinia'
281
290
  import { useThemeStore } from '../../store/theme'
282
291
 
@@ -315,7 +324,8 @@ export default defineComponent({
315
324
  BlockIframeEmbed,
316
325
  BlockGist,
317
326
  BlockVideo,
318
- BlockVideoEmbed
327
+ BlockVideoEmbed,
328
+ BlockNewsletterSignup
319
329
  },
320
330
  props: {
321
331
  variant: {
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { reactive } from 'vue'
3
- import BaseImagePlaceholder from './../BaseImagePlaceholder/BaseImagePlaceholder.vue'
3
+ import BlockVideoEmbed from './../BlockVideoEmbed/BlockVideoEmbed.vue'
4
4
  import BlockIframeEmbed from './../BlockIframeEmbed/BlockIframeEmbed.vue'
5
5
  import BlockImageComparison from './../BlockImageComparison/BlockImageComparison.vue'
6
6
  import BlockImageCarousel from './../BlockImageCarousel/BlockImageCarousel.vue'
@@ -42,13 +42,10 @@ const { heroBlocks, constrain } = reactive(props)
42
42
  v-else-if="heroBlocks[0].blockType === 'VideoBlock'"
43
43
  :data="heroBlocks[0]"
44
44
  />
45
- <BaseImagePlaceholder
45
+ <BlockVideoEmbed
46
46
  v-else-if="heroBlocks[0].blockType === 'VideoEmbedBlock'"
47
- aspect-ratio="16:9"
48
- dark-mode
49
- >
50
- <div v-html="heroBlocks[0].embed?.embed"></div>
51
- </BaseImagePlaceholder>
47
+ :data="heroBlocks[0]"
48
+ />
52
49
  <BlockImageComparison
53
50
  v-else-if="heroBlocks[0].blockType === 'ImageComparisonBlock'"
54
51
  :data="heroBlocks[0]"
@@ -3,40 +3,42 @@
3
3
  v-if="image || video"
4
4
  class="HeroMedia"
5
5
  >
6
- <div class="vh-crop max-w-screen-3xl relative flex items-center mx-auto overflow-hidden">
7
- <div class="hero w-full">
8
- <template v-if="theImageData">
9
- <img
10
- v-if="theImageData.src"
11
- class="object-cover object-center w-full h-full"
12
- :srcset="theSrcSet"
13
- :src="theImageData.src.url"
14
- :width="theImageData.src.width"
15
- :height="theImageData.src.height"
16
- :alt="theImageData.alt"
17
- itemprop="image"
18
- data-chromatic="ignore"
19
- />
20
- </template>
21
- <template v-else-if="video">
22
- <MixinVideoBg :video="video" />
23
- </template>
24
- </div>
25
- <div
26
- v-if="hasCaptionArea"
27
- class="lg:hidden absolute bottom-0 left-0 w-full h-auto mx-auto print:hidden"
28
- >
29
- <button
30
- class="bg-opacity-90 text-gray-dark flex items-center justify-center w-12 h-12 ml-auto bg-white cursor-pointer"
31
- aria-label="Toggle caption"
32
- @click="toggleCaption"
6
+ <div>
7
+ <div class="vh-crop max-w-screen-3xl relative flex items-center mx-auto overflow-hidden">
8
+ <div class="hero w-full">
9
+ <template v-if="theImageData">
10
+ <img
11
+ v-if="theImageData.src"
12
+ class="object-cover object-center w-full h-full"
13
+ :srcset="theSrcSet"
14
+ :src="theImageData.src.url"
15
+ :width="theImageData.src.width"
16
+ :height="theImageData.src.height"
17
+ :alt="theImageData.alt"
18
+ itemprop="image"
19
+ data-chromatic="ignore"
20
+ />
21
+ </template>
22
+ <template v-else-if="video">
23
+ <MixinVideoBg :video="video" />
24
+ </template>
25
+ </div>
26
+ <div
27
+ v-if="hasCaptionArea"
28
+ class="lg:hidden absolute bottom-0 left-0 w-full h-auto mx-auto print:hidden"
33
29
  >
34
- <IconInfo
35
- v-show="!captionVisible"
36
- class="text-xl"
37
- />
38
- <IconClose v-show="captionVisible" />
39
- </button>
30
+ <button
31
+ class="bg-opacity-90 text-gray-dark flex items-center justify-center w-12 h-12 ml-auto bg-white cursor-pointer"
32
+ aria-label="Toggle caption"
33
+ @click="toggleCaption"
34
+ >
35
+ <IconInfo
36
+ v-show="!captionVisible"
37
+ class="text-xl"
38
+ />
39
+ <IconClose v-show="captionVisible" />
40
+ </button>
41
+ </div>
40
42
  </div>
41
43
  </div>
42
44
 
@@ -16,6 +16,7 @@ import BlockRelatedLinks from './../../components/BlockRelatedLinks/BlockRelated
16
16
  import FormContact from './../../components/FormContact/FormContact.vue'
17
17
  import FormNewsletterSignup from './../../components/FormNewsletterSignup/FormNewsletterSignup.vue'
18
18
  import BlockLinkCarousel from './../../components/BlockLinkCarousel/BlockLinkCarousel.vue'
19
+ import type { BlockData } from '../../interfaces'
19
20
 
20
21
  const route = useRoute()
21
22
 
@@ -71,6 +72,18 @@ export default defineComponent({
71
72
  return 'lg:mt-12 mt-5'
72
73
  }
73
74
  return 'lg:mt-12 lg:mb-18 edu:lg:mb-12 mt-5 mb-10 edu:mb-8'
75
+ },
76
+ hasNewsletterSignupBlock() {
77
+ let status = false
78
+ const blocks = this.data?.body
79
+ if (blocks?.length) {
80
+ blocks.forEach((block: BlockData) => {
81
+ if (block.blockType === `NewsletterSignupBlock`) {
82
+ status = true
83
+ }
84
+ })
85
+ }
86
+ return status
74
87
  }
75
88
  }
76
89
  })
@@ -168,7 +181,7 @@ export default defineComponent({
168
181
  </template>
169
182
 
170
183
  <!-- Newsletter Signup form for specific content page only -->
171
- <template v-if="data.slug === 'newsletter-signup'">
184
+ <template v-if="data.slug === 'newsletter-signup' && !hasNewsletterSignupBlock">
172
185
  <!-- Newsletter Signup Form -->
173
186
  <FormNewsletterSignup class="lg:mb-18 mb-10" />
174
187
  </template>
@@ -51,34 +51,10 @@
51
51
  indent="col-2"
52
52
  class="lg:mb-22 mt-10 mb-10"
53
53
  >
54
- <BlockImageStandard
55
- v-if="data.hero[0].blockType === 'HeroImageBlock'"
56
- :data="data.hero[0].imageInline"
57
- :display-caption="data.hero[0].displayCaption"
58
- :caption="data.hero[0].caption"
54
+ <HeroInlineMedia
55
+ :hero-blocks="data.hero"
59
56
  :constrain="data.heroConstrain"
60
57
  />
61
- <BlockImageCarousel
62
- v-else-if="data.hero[0].blockType === 'CarouselBlock'"
63
- :items="data.hero[0].blocks"
64
- :block-id="data.hero[0].id"
65
- />
66
- <BlockVideo
67
- v-else-if="data.hero[0].blockType === 'VideoBlock'"
68
- :data="data.hero[0]"
69
- autoplay
70
- />
71
- <BaseImagePlaceholder
72
- v-else-if="data.hero[0].blockType === 'VideoEmbedBlock'"
73
- aspect-ratio="16:9"
74
- dark-mode
75
- >
76
- <div v-html="data.hero[0].embed.embed"></div>
77
- </BaseImagePlaceholder>
78
- <BlockImageComparison
79
- v-else-if="data.hero[0].blockType === 'ImageComparisonBlock'"
80
- :data="data.hero[0]"
81
- />
82
58
  </LayoutHelper>
83
59
 
84
60
  <!-- share buttons -->
@@ -166,17 +142,13 @@ import { defineComponent } from 'vue'
166
142
  import LayoutHelper from './../../components/LayoutHelper/LayoutHelper.vue'
167
143
  import HeroMedia from './../../components/HeroMedia/HeroMedia.vue'
168
144
  import DetailHeadline from './../../components/DetailHeadline/DetailHeadline.vue'
169
- import BaseImagePlaceholder from './../../components/BaseImagePlaceholder/BaseImagePlaceholder.vue'
170
145
  import BlockStreamfield from './../../components/BlockStreamfield/BlockStreamfield.vue'
171
146
  import NewsDetailMediaContact from './../../components/NewsDetailMediaContact/NewsDetailMediaContact.vue'
172
147
  import BlockRelatedLinks from './../../components/BlockRelatedLinks/BlockRelatedLinks.vue'
173
- import BlockImageCarousel from './../../components/BlockImageCarousel/BlockImageCarousel.vue'
174
- import BlockImageComparison from './../../components/BlockImageComparison/BlockImageComparison.vue'
175
- import BlockImageStandard from './../../components/BlockImage/BlockImageStandard.vue'
148
+ import HeroInlineMedia from './../../components/HeroInlineMedia/HeroInlineMedia.vue'
176
149
  import BlockLinkCarousel from './../../components/BlockLinkCarousel/BlockLinkCarousel.vue'
177
150
  import ShareButtons from './../../components/ShareButtons/ShareButtons.vue'
178
151
  import BlockText from './../../components/BlockText/BlockText.vue'
179
- import BlockVideo from './../../components/BlockVideo/BlockVideo.vue'
180
152
 
181
153
  export default defineComponent({
182
154
  name: 'PageNewsDetail',
@@ -184,17 +156,13 @@ export default defineComponent({
184
156
  LayoutHelper,
185
157
  HeroMedia,
186
158
  DetailHeadline,
187
- BaseImagePlaceholder,
188
159
  BlockStreamfield,
189
160
  NewsDetailMediaContact,
190
161
  BlockRelatedLinks,
191
- BlockImageCarousel,
192
- BlockImageComparison,
193
- BlockImageStandard,
194
162
  BlockLinkCarousel,
195
163
  ShareButtons,
196
164
  BlockText,
197
- BlockVideo
165
+ HeroInlineMedia
198
166
  },
199
167
  props: {
200
168
  data: {