diff --git a/apps/vue-storybook/.storybook/preview.ts b/apps/vue-storybook/.storybook/preview.ts index 263cf4ba..38593055 100644 --- a/apps/vue-storybook/.storybook/preview.ts +++ b/apps/vue-storybook/.storybook/preview.ts @@ -6,6 +6,7 @@ import { createRouter, createWebHashHistory, type RouterOptions } from 'vue-rout import { Swiper, SwiperSlide } from 'swiper/vue' import vClickOutside from 'click-outside-vue3' import VueCompareImage from 'vue3-compare-image' +import { BindOncePlugin } from 'vue-bind-once' import { createPinia } from 'pinia' import filters from '@explorer-1/vue/src/utils/filters' import '@explorer-1/common/src/scss/styles-with-fonts.scss' @@ -38,6 +39,7 @@ setup((app, _context) => { app.use(router) app.use(vClickOutside) app.use(VueCompareImage) + app.use(BindOncePlugin) app.component('Swiper', Swiper) app.component('SwiperSlide', SwiperSlide) app.config.globalProperties.$filters = filters diff --git a/apps/vue-storybook/package.json b/apps/vue-storybook/package.json index 4db6b08a..181fd941 100644 --- a/apps/vue-storybook/package.json +++ b/apps/vue-storybook/package.json @@ -44,6 +44,7 @@ "mitt": "^3.0.1", "swiper": "^11.1.3", "vue": "^3.2.47", + "vue-bind-once": "^0.2.1", "vue3-compare-image": "^1.2.5" }, "devDependencies": { diff --git a/packages/common/src/scss/_grid.scss b/packages/common/src/scss/_grid.scss index 6dc03422..c2084df6 100644 --- a/packages/common/src/scss/_grid.scss +++ b/packages/common/src/scss/_grid.scss @@ -6,27 +6,27 @@ .MixedBleedGrid { @screen sm { - grid-template-columns: [bleed-start] auto [container-start] 53.33px [indent-col-2] 53.33px [indent-col-3] 533.33px [container-end] auto [bleed-end]; + grid-template-columns: [bleed-start] 1fr [container-start] 53.33px [indent-col-2] 53.33px [indent-col-3] 533.33px [container-end] 1fr [bleed-end]; @apply grid gap-0; } @screen md { - grid-template-columns: [bleed-start] auto [container-start] 64px [indent-col-2] 64px [indent-col-3] 640px [container-end] auto [bleed-end]; + grid-template-columns: [bleed-start] 1fr [container-start] 64px [indent-col-2] 64px [indent-col-3] 640px [container-end] 1fr [bleed-end]; @apply grid; } @screen lg { - grid-template-columns: [bleed-start] auto [container-start] 85.33px [indent-col-2] 85.33px [indent-col-3] 853.33px [container-end] auto [bleed-end]; + grid-template-columns: [bleed-start] 1fr [container-start] 85.33px [indent-col-2] 85.33px [indent-col-3] 853.33px [container-end] 1fr [bleed-end]; @apply grid; } @screen xl { - grid-template-columns: [bleed-start] auto [container-start] 108px [indent-col-2] 108px [indent-col-3] 1088px [container-end] auto [bleed-end]; + grid-template-columns: [bleed-start] 1fr [container-start] 108px [indent-col-2] 108px [indent-col-3] 1088px [container-end] 1fr [bleed-end]; @apply grid; } @screen 2xl { - grid-template-columns: [bleed-start] auto [container-start] 110px [indent-col-2] 110px [indent-col-3] 1100px [container-end] auto [bleed-end]; + grid-template-columns: [bleed-start] 1fr [container-start] 110px [indent-col-2] 110px [indent-col-3] 1100px [container-end] 1fr [bleed-end]; @apply grid; } @@ -42,6 +42,10 @@ grid-column-start: container-start; } + .col-start-indent-col-1 { + grid-column-start: indent-col-1; + } + .col-start-indent-col-2 { grid-column-start: indent-col-2; } diff --git a/packages/vue/package.json b/packages/vue/package.json index 4276342e..c2f78e81 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -38,6 +38,7 @@ "tailwindcss": "^3.4.3", "twitter-widgets": "^2.0.0", "vue": "^3.4.21", + "vue-bind-once": "^0.2.1", "vue-observe-visibility": "^1.0.0", "vue3-compare-image": "^1.2.5" }, diff --git a/packages/vue/src/components/BaseAccordionItem/BaseAccordionItem.stories.js b/packages/vue/src/components/BaseAccordionItem/BaseAccordionItem.stories.js new file mode 100644 index 00000000..f3be33b0 --- /dev/null +++ b/packages/vue/src/components/BaseAccordionItem/BaseAccordionItem.stories.js @@ -0,0 +1,15 @@ +import BaseAccordionItem from './BaseAccordionItem.vue' +import { BlockStreamfieldTruncatedData } from '../BlockStreamfield/BlockStreamfield.stories' +export default { + title: 'Components/Base/BaseAccordionItem', + component: BaseAccordionItem +} + +// stories +export const BaseStory = { + name: 'BaseAccordionItem', + args: { + headingLevel: 'h3', + item: { title: 'Title for the accordion', body: BlockStreamfieldTruncatedData.body } + } +} diff --git a/packages/vue/src/components/BaseAccordionItem/BaseAccordionItem.vue b/packages/vue/src/components/BaseAccordionItem/BaseAccordionItem.vue new file mode 100644 index 00000000..5eb2951a --- /dev/null +++ b/packages/vue/src/components/BaseAccordionItem/BaseAccordionItem.vue @@ -0,0 +1,108 @@ + + + + + + + + + + + {{ item.title }} + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/vue/src/components/BaseButton/BaseButton.vue b/packages/vue/src/components/BaseButton/BaseButton.vue index def78f93..6b0fd495 100644 --- a/packages/vue/src/components/BaseButton/BaseButton.vue +++ b/packages/vue/src/components/BaseButton/BaseButton.vue @@ -2,7 +2,7 @@ import { defineComponent } from 'vue' interface Variants { - [name: string]: string + [key: string]: string } export const variants: Variants = { @@ -11,6 +11,11 @@ export const variants: Variants = { dark: '-dark', social: '-social' } +export const colors: Variants = { + primary: '-color-primary', + secondary: '-color-secondary', + action: '-color-action' +} export default defineComponent({ name: 'BaseButton', @@ -21,6 +26,12 @@ export default defineComponent({ default: 'primary', validator: (prop: string): boolean => Object.keys(variants).includes(prop) }, + color: { + type: String, + required: false, + default: 'primary', + validator: (prop: string): boolean => Object.keys(colors).includes(prop) + }, compact: { type: Boolean, default: false, diff --git a/packages/vue/src/components/BaseImage/BaseImage.vue b/packages/vue/src/components/BaseImage/BaseImage.vue index 7793a5c5..a0c9e8f0 100644 --- a/packages/vue/src/components/BaseImage/BaseImage.vue +++ b/packages/vue/src/components/BaseImage/BaseImage.vue @@ -5,7 +5,7 @@ import type { PropType } from 'vue' export type ImageLoader = 'lazy' | 'eager' | undefined interface ObjectFitClasses { - [name: string]: string + [key: string]: string } export const objectFitClasses: ObjectFitClasses = { diff --git a/packages/vue/src/components/BaseImagePlaceholder/BaseImagePlaceholder.vue b/packages/vue/src/components/BaseImagePlaceholder/BaseImagePlaceholder.vue index e8498acf..7bc19775 100644 --- a/packages/vue/src/components/BaseImagePlaceholder/BaseImagePlaceholder.vue +++ b/packages/vue/src/components/BaseImagePlaceholder/BaseImagePlaceholder.vue @@ -2,7 +2,7 @@ import { defineComponent } from 'vue' interface AspectRatios { - [name: string]: string + [key: string]: string } export const aspectRatios: AspectRatios = { diff --git a/packages/vue/src/components/BaseLink/BaseLink.vue b/packages/vue/src/components/BaseLink/BaseLink.vue index 74c2b37e..5d8fd291 100644 --- a/packages/vue/src/components/BaseLink/BaseLink.vue +++ b/packages/vue/src/components/BaseLink/BaseLink.vue @@ -4,7 +4,7 @@ import { eventBus } from './../../utils/eventBus' import MixinAnimationCaret from './../MixinAnimationCaret/MixinAnimationCaret.vue' interface Variants { - [name: string]: string + [key: string]: string } export const variants: Variants = { diff --git a/packages/vue/src/components/BlockAccordion/BlockAccordion.stories.js b/packages/vue/src/components/BlockAccordion/BlockAccordion.stories.js new file mode 100644 index 00000000..3a1239b8 --- /dev/null +++ b/packages/vue/src/components/BlockAccordion/BlockAccordion.stories.js @@ -0,0 +1,29 @@ +import BlockAccordion from './BlockAccordion.vue' +import { BlockStreamfieldTruncatedData } from '../BlockStreamfield/BlockStreamfield.stories' + +export default { + title: 'Components/Blocks/BlockAccordion', + component: BlockAccordion +} + +// stories +export const BaseStory = { + name: 'BlockAccordion', + args: { + headingLevel: 'h5', + items: [ + { + title: 'Title for the accordion', + body: BlockStreamfieldTruncatedData.body + }, + { + title: 'Another', + body: BlockStreamfieldTruncatedData.body + }, + { + title: 'Yet another', + body: BlockStreamfieldTruncatedData.body + } + ] + } +} diff --git a/packages/vue/src/components/BlockAccordion/BlockAccordion.vue b/packages/vue/src/components/BlockAccordion/BlockAccordion.vue new file mode 100644 index 00000000..666182e6 --- /dev/null +++ b/packages/vue/src/components/BlockAccordion/BlockAccordion.vue @@ -0,0 +1,32 @@ + + + + + + + + diff --git a/packages/vue/src/components/BlockHeading/BlockHeading.stories.js b/packages/vue/src/components/BlockHeading/BlockHeading.stories.js index fb04ae4f..a5da7129 100644 --- a/packages/vue/src/components/BlockHeading/BlockHeading.stories.js +++ b/packages/vue/src/components/BlockHeading/BlockHeading.stories.js @@ -1,5 +1,4 @@ import BlockHeading from './BlockHeading.vue' - export default { title: 'Components/Blocks/BlockHeading', component: BlockHeading, @@ -10,7 +9,8 @@ export const BlockHeadingData = { blockType: 'HeadingBlock', heading: 'Heading Text', level: 'h2', - size: 'h2' + size: 'h2', + blockId: `${Math.random().toString(36).slice(2)}` } // stories diff --git a/packages/vue/src/components/BlockHeading/BlockHeading.vue b/packages/vue/src/components/BlockHeading/BlockHeading.vue index c583a639..254d6682 100644 --- a/packages/vue/src/components/BlockHeading/BlockHeading.vue +++ b/packages/vue/src/components/BlockHeading/BlockHeading.vue @@ -11,10 +11,20 @@ + + + + + + + + + + + + + {{ buttonText }} + + + + + + + + + + + + + Standards + . + + + + + English Language Arts Standards + + . + + + + + Common Core State Standards For Math + + . + + + + + Next Generation Science Standards + + . + + + + + Technology Standards (ISTE) + + . + + + + + + + + + + + diff --git a/packages/vue/src/components/MetaPanelAccordion/MetaPanelAccordion.vue b/packages/vue/src/components/MetaPanelAccordion/MetaPanelAccordion.vue new file mode 100644 index 00000000..76c7e0be --- /dev/null +++ b/packages/vue/src/components/MetaPanelAccordion/MetaPanelAccordion.vue @@ -0,0 +1,64 @@ + + + + + + + + + {{ item.standard.domain?.domain }} + + + {{ item.standard.code }} + + + + + + {{ item.standard.definition }} + + + + + + diff --git a/packages/vue/src/components/MetaPanelItems/MetaPanelItems.stories.js b/packages/vue/src/components/MetaPanelItems/MetaPanelItems.stories.js new file mode 100644 index 00000000..13b276c6 --- /dev/null +++ b/packages/vue/src/components/MetaPanelItems/MetaPanelItems.stories.js @@ -0,0 +1,27 @@ +import MetaPanelItems from './MetaPanelItems.vue' + +export default { + title: 'Components/Utilities/MetaPanelItems', + component: MetaPanelItems, + tags: ['!autodocs'] +} + +// stories +export const BaseStory = { + name: 'MetaPanelItems', + args: { + primarySubject: { subject: 'Math' }, + additionalSubjects: [{ subject: 'Science' }], + time: { time: '30mins - hr' }, + gradeLevels: [ + { gradeLevel: 'All Ages' }, + { gradeLevel: 'K' }, + { gradeLevel: '1' }, + { gradeLevel: '2' }, + { gradeLevel: '5' }, + { gradeLevel: '6' }, + { gradeLevel: '7' }, + { gradeLevel: '8' } + ] + } +} diff --git a/packages/vue/src/components/MetaPanelItems/MetaPanelItems.vue b/packages/vue/src/components/MetaPanelItems/MetaPanelItems.vue new file mode 100644 index 00000000..5130de9f --- /dev/null +++ b/packages/vue/src/components/MetaPanelItems/MetaPanelItems.vue @@ -0,0 +1,186 @@ + + + + + + + + + + + Subjects + . + + + {{ subjects }} + + + + + + + + + + Grade Levels + . + + + {{ audience }} + + + + + + + + + + Time Required + . + + + {{ time.time }} + + + + + + diff --git a/packages/vue/src/components/MetadataEduResource/MetadataEduResource.stories.js b/packages/vue/src/components/MetadataEduResource/MetadataEduResource.stories.js index 91f5d69a..1a1045a5 100644 --- a/packages/vue/src/components/MetadataEduResource/MetadataEduResource.stories.js +++ b/packages/vue/src/components/MetadataEduResource/MetadataEduResource.stories.js @@ -7,10 +7,8 @@ export default { argTypes: { variant: { type: { name: 'string', required: false }, - control: { - type: 'select', - options: ['primary', 'secondary'] - } + control: { type: 'select' }, + options: ['primary', 'secondary'] } }, excludeStories: /.*Data$/ diff --git a/packages/vue/src/components/MixinCarousel/MixinCarousel.vue b/packages/vue/src/components/MixinCarousel/MixinCarousel.vue index efae2bad..b200c2ee 100644 --- a/packages/vue/src/components/MixinCarousel/MixinCarousel.vue +++ b/packages/vue/src/components/MixinCarousel/MixinCarousel.vue @@ -113,7 +113,7 @@ const MixinCarouselOptions = swiperOptions.MixinCarousel Swiper.use([Navigation, A11y]) interface Variants { - [name: string]: string + [key: string]: string } export const variants: Variants = { @@ -122,7 +122,7 @@ export const variants: Variants = { } interface Indents { - [name: string]: string + [key: string]: string } export const indents: Indents = { diff --git a/packages/vue/src/components/NavJumpMenu/NavJumpMenu.vue b/packages/vue/src/components/NavJumpMenu/NavJumpMenu.vue index abb51dfc..20c490a9 100644 --- a/packages/vue/src/components/NavJumpMenu/NavJumpMenu.vue +++ b/packages/vue/src/components/NavJumpMenu/NavJumpMenu.vue @@ -1,7 +1,7 @@ { return b.blockType === 'HeadingBlock' && b.level === props.headingLevel }) // map to the correct data shape - const links: BreadcrumbPathObject[] = filteredBlocks.map((l) => { + const links: BreadcrumbPathObject[] = filteredBlocks.map((h) => { return { // @ts-expect-error using parameter that was added to BlockData - path: '#' + getHeadingId(l.heading, l.index), - title: l.heading + path: '#' + getHeadingId(h.heading, h.blockId), + title: h.heading } as BreadcrumbPathObject }) return links @@ -95,11 +95,11 @@ const theBreadcrumbs = computed(() => { const rootItem = props.title ? { title: props.title, - path: '#JumpMenuTop' + path: '#siteTop' } : { title: 'Back to top', - path: '#JumpMenuTop' + path: '#siteTop' } const jumpMenu: BreadcrumbPathObject = { title: 'Jump to…', @@ -111,12 +111,14 @@ const theBreadcrumbs = computed(() => { } return breadcrumb as BreadcrumbPathObject[] | undefined }) + defineExpose({ NavJumpMenuRef }) onMounted(() => { mixinUpdateSecondary(theBreadcrumbs.value, true) }) + const route = useRoute() // repopulate the store with the jump links since the store is cleared on route changes @@ -131,10 +133,10 @@ watch(
{{ item.standard.definition }}