Skip to content

Commit

Permalink
feat(vue3): auto generate story from component
Browse files Browse the repository at this point in the history
  • Loading branch information
Akryum committed Feb 10, 2023
1 parent c161d15 commit 162d05f
Show file tree
Hide file tree
Showing 61 changed files with 1,189 additions and 187 deletions.
3 changes: 2 additions & 1 deletion examples/vue3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.1",
"private": true,
"scripts": {
"dev:hst": "HISTOIRE_DEV=true histoire dev",
"dev:hst": "nodemon --watch ../../packages/histoire/dist --watch ../../packages/histoire-plugin-vue/dist --exec \"rm -rf ./node_modules/.hst* && HISTOIRE_DEV=true histoire dev\"",
"story:dev": "histoire dev",
"story:build": "histoire build",
"story:preview": "histoire preview --port 4567",
Expand All @@ -24,6 +24,7 @@
"@vitejs/plugin-vue": "^4.0.0",
"cypress": "^9.5.3",
"histoire": "workspace:*",
"nodemon": "^2.0.20",
"sass": "^1.50.0",
"start-server-and-test": "^1.14.0",
"vite": "^4.1.0"
Expand Down
20 changes: 20 additions & 0 deletions examples/vue3/public/vue-amsterdam.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions examples/vue3/src/components/Amsterdam.story.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup>
import Amsterdam from './Amsterdam.vue'
</script>

<template>
<Story>
<Variant title="Default">
<Amsterdam />
</Variant>
</Story>
</template>
6 changes: 6 additions & 0 deletions examples/vue3/src/components/Amsterdam.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<template>
<img
src="/vue-amsterdam.svg"
alt="Vue Amsterdam"
>
</template>
11 changes: 10 additions & 1 deletion packages/histoire-app/src/app/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export default {
</script>

<script lang="ts" setup>
// @ts-expect-error virtual module
import { files as rawFiles, tree as rawTree, onUpdate } from 'virtual:$histoire-stories'
import StoryList from './components/tree/StoryList.vue'
import BaseSplitPane from './components/base/BaseSplitPane.vue'
Expand All @@ -18,8 +17,10 @@ import { useTitle } from '@vueuse/core'
import { histoireConfig } from './util/config'
import { onKeyboardShortcut } from './util/keyboard'
import { isMobile } from './util/responsive'
import { useCommandStore } from './stores/command'
import Breadcrumb from './components/app/Breadcrumb.vue'
import SearchModal from './components/search/SearchModal.vue'
import CommandPromptsModal from './components/command/CommandPromptsModal.vue'
import InitialLoading from './components/app/InitialLoading.vue'
import GenericMountStory from './components/story/GenericMountStory.vue'
Expand Down Expand Up @@ -89,6 +90,8 @@ const mounted = ref(false)
onMounted(() => {
mounted.value = true
})
const commandStore = useCommandStore()
</script>

<template>
Expand Down Expand Up @@ -153,6 +156,12 @@ onMounted(() => {
:shown="isSearchOpen"
@close="isSearchOpen = false"
/>

<CommandPromptsModal
v-if="__HISTOIRE_DEV__"
:shown="commandStore.showPromptsModal"
@close="commandStore.showPromptsModal = false"
/>
</div>

<transition name="__histoire-fade">
Expand Down
33 changes: 33 additions & 0 deletions packages/histoire-app/src/app/components/base/BaseButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { RouterLink } from 'vue-router'
const props = defineProps<{
to?: any
href?: string
color?: string
}>()
const comp = computed(() => {
if (props.to) {
return RouterLink
}
if (props.href) {
return 'a'
}
return 'button'
})
</script>

<template>
<component
:is="comp"
class="histoire-base-button htw-rounded htw-cursor-pointer"
:class="{
'htw-bg-primary-200 dark:htw-bg-primary-800 hover:htw-bg-primary-300 dark:hover:htw-bg-primary-700': color === 'primary' || !color,
'htw-bg-grey-100 dark:htw-bg-grey-900 hover:htw-bg-grey-200 dark:hover:htw-bg-grey-800': color === 'grey',
}"
>
<slot />
</component>
</template>
31 changes: 31 additions & 0 deletions packages/histoire-app/src/app/components/base/BaseIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script lang="ts" setup>
import { Icon } from '@iconify/vue'
import { computed } from 'vue'
const props = defineProps<{
icon: string
}>()
const isUrl = computed(() => props.icon.startsWith('http') || props.icon.startsWith('data:image') ||
props.icon.startsWith('.') || props.icon.startsWith('/'))
</script>

<template>
<img
v-if="isUrl"
:src="icon"
:alt="icon"
class="histoire-base-icon"
>
<Icon
v-else
:icon="icon"
class="histoire-base-icon"
/>
</template>

<style scoped>
img.colorize-black {
filter: grayscale(100) brightness(0);
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script lang="ts" setup>
import { formatKey } from '../../util/keyboard.js'
import { computed } from 'vue'
const props = defineProps<{
shortcut: string
}>()
const formatted = computed(() => props.shortcut.split('+').map(k => formatKey(k.trim())).join(' '))
</script>

<template>
<span class="histoire-base-keyboard-shortcut htw-border htw-border-current htw-opacity-50 htw-px-1 htw-rounded-sm">
{{ formatted }}
</span>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script lang="ts" setup>
import { reactive, ref, nextTick, onMounted } from 'vue'
import type { ClientCommand } from '@histoire/shared'
import { getCommandContext, executeCommand } from '../../util/commands.js'
import BaseButton from '../base/BaseButton.vue'
import BaseKeyboardShortcut from '../base/BaseKeyboardShortcut.vue'
import PromptText from './PromptText.vue'
import PromptSelect from './PromptSelect.vue'
const props = defineProps<{
command: ClientCommand
}>()
const emit = defineEmits<{
(e: 'close'): void
}>()
const promptTypes = {
text: PromptText,
select: PromptSelect,
}
const answers = reactive<Record<string, any>>({})
// Initial default values
for (const prompt of props.command.prompts) {
let defaultValue
if (typeof prompt.defaultValue === 'function') {
defaultValue = prompt.defaultValue(answers)
} else {
defaultValue = prompt.defaultValue
}
answers[prompt.field] = defaultValue
}
function submit () {
const params = props.command.getParams
? props.command.getParams({
...getCommandContext(),
answers,
})
: answers
executeCommand(props.command, params)
emit('close')
}
// Autofocus
const promptComps = ref<any[]>([])
function focusPrompt (index: number) {
nextTick(() => {
promptComps.value[index]?.focus?.()
})
}
onMounted(() => {
focusPrompt(0)
})
</script>

<template>
<form
class="histoire-command-prompts htw-flex htw-flex-col"
@submit.prevent="submit()"
@keyup.escape="$emit('close')"
>
<div class="htw-p-4 htw-opacity-70">
{{ command.label }}
</div>

<component
:is="promptTypes[prompt.type]"
v-for="(prompt, index) of command.prompts"
:key="prompt.field"
ref="promptComps"
v-model="answers[prompt.field]"
:prompt="prompt"
:answers="answers"
:index="index"
class="hover:htw-bg-gray-500/10 focus-within:htw-bg-gray-500/5"
@next="focusPrompt(index + 1)"
/>

<div class="htw-flex htw-justify-end htw-gap-2 htw-p-2">
<BaseButton
type="submit"
class="htw-px-4 htw-py-2 htw-flex htw-items-start htw-gap-2"
>
<BaseKeyboardShortcut
shortcut="Enter"
/>
<span>Submit</span>
</BaseButton>
</div>
</form>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { useCommandStore } from '../../stores/command.js'
const CommandPrompts = defineAsyncComponent(() => import('./CommandPrompts.vue'))
defineProps({
shown: {
type: Boolean,
default: false,
},
})
const emit = defineEmits({
close: () => true,
})
function close () {
emit('close')
}
const commandStore = useCommandStore()
</script>

<template>
<div
v-if="shown"
class="histoire-command-prompts-modal htw-fixed htw-inset-0 htw-bg-white/80 dark:htw-bg-gray-900/80 htw-z-20"
>
<div
class="htw-absolute htw-inset-0"
@click="close()"
/>
<div class="htw-bg-white dark:htw-bg-gray-900 md:htw-mt-16 md:htw-mx-auto htw-w-screen htw-max-w-[512px] htw-max-h-[80vh] htw-overflow-y-auto htw-scroll-smooth htw-shadow-xl htw-border htw-border-gray-200 dark:htw-border-gray-750 htw-rounded-lg htw-relative htw-divide-y htw-divide-gray-200 dark:htw-divide-gray-850">
<CommandPrompts
:command="commandStore.selectedCommand"
@close="close()"
/>
</div>
</div>
</template>

0 comments on commit 162d05f

Please sign in to comment.