Skip to content

Commit

Permalink
Implement vue component factory (#8690)
Browse files Browse the repository at this point in the history
* Add serve example commands

* Implement SurveyComponent component

* Use SurveyVueComponent in in all components

* Do not register custom directive in global. Rename VueComponentFactory -> ComponentFactory and SurveyComponent -> SvComponent.

* Remove usage surveyPlugin from example

* Fix lint warnings

* Small refactor

* Fix lint command

* Register survey component in component factory

* Export PopupSurveyComponent

* Fix custom components in example

* Small refactor component factory

* Refactor to avoid breaking change

* Use global components if plugin is registered

* Refactor

* Fix popup survey component
  • Loading branch information
dk981234 authored Sep 11, 2024
1 parent 4107f8e commit fb3e4b6
Show file tree
Hide file tree
Showing 111 changed files with 1,248 additions and 687 deletions.
2 changes: 1 addition & 1 deletion packages/survey-vue3-ui/example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"dev": "vite --force",
"build": "run-p type-check build-only",
"preview": "vite preview --host 0.0.0.0 --port 8080",
"build-only": "vite build",
Expand Down
17 changes: 10 additions & 7 deletions packages/survey-vue3-ui/example/src/components/example/Example.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
<script setup lang="ts">
import { Model } from "survey-core";
import("survey-core/defaultV2.css");
import { SurveyComponent } from "survey-vue3-ui";
let survey = new Model({
elements: [
{
type: "text",
name: "q1"
}
]
})
elements: [
{
name: "name",
type: "file",
title: "Question title",
titleLocation: "hidden"
}
]
})
</script>

<template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { SurveyModel } from "survey-core";
import * as Survey from "survey-core"
import "survey-core/survey.i18n";
import { SurveyComponent, PopupSurveyComponent } from "survey-vue3-ui";
import { shallowRef } from "vue";
const survey = shallowRef();
const isPopup = shallowRef();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<template>
<div class="my-list-item" style="display:flex;" :title="item.hint">
<span>
<sv-svg-icon :iconName="item.iconName" :size="item.iconSize"></sv-svg-icon>
<SvComponent :is="'sv-svg-icon'" :iconName="item.iconName" :size="item.iconSize"></SvComponent>
</span>
<span :class="item.getActionBarItemTitleCss()">{{ item.title }}</span>
</div>
</template>
<script lang="ts" setup>
import { SvComponent } from 'survey-vue3-ui';
defineProps<{ item: any }>()
</script>
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<template>
<div class="sv-ranking-item__text" :style="{display: 'flex', alignItems: 'center', gap: '8px'}">
<sv-svg-icon iconName="icon-next_16x16" size = "16"></sv-svg-icon>
<survey-string :locString="item.locText" />
<SvComponent :is="'sv-svg-icon'" iconName="icon-next_16x16" size = "16"/>
<SvComponent :is="'survey-string'" :locString="item.locText" />
</div>
</template>
<script lang="ts" setup>
import { SvComponent } from 'survey-vue3-ui';
import type { ItemValue } from 'survey-core';
defineProps<{ item: ItemValue, cssClasses: any }>()
</script>
13 changes: 5 additions & 8 deletions packages/survey-vue3-ui/example/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { surveyPlugin } from "survey-vue3-ui";
import { ComponentFactory } from "survey-vue3-ui";

import { createApp } from 'vue'
import Action from "./components/test/test-custom-components/Action.vue"
Expand All @@ -7,14 +7,11 @@ import ItemContent from "./components/test/test-custom-components/ItemContent.vu
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(surveyPlugin);


app.component("svc-custom-action", Action);
app.component("new-item", Item);
app.component("new-item-content", ItemContent);
ComponentFactory.Instance.registerComponent("svc-custom-action", Action);
ComponentFactory.Instance.registerComponent("new-item", Item);
ComponentFactory.Instance.registerComponent("new-item-content", ItemContent);

const app = createApp(App)
app.use(router)

app.mount('#app')
32 changes: 23 additions & 9 deletions packages/survey-vue3-ui/example/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,29 @@ import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
],
resolve: {
preserveSymlinks: true,
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
"survey-core": fileURLToPath(new URL('./node_modules/survey-core', import.meta.url)),
export default defineConfig(({ command }) => {
return {
plugins: [
vue(),
],
server: {
watch: {
ignored: ["survey-vue3-ui"].map((m) => `!**/node_modules/${m}/**`)
}
},
build: {
commonjsOptions: { exclude: ["survey-core"] },
},
optimizeDeps: {
exclude: ["survey-vue3-ui"],
include: ["survey-core", "survey-core/survey.i18n", "survey-core/plugins/bootstrap-integration", "survey-core/plugins/bootstrap-material-integration" ]
},
resolve: {
preserveSymlinks: command == "serve" ? false : true,
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
"survey-core": fileURLToPath(new URL('./node_modules/survey-core', import.meta.url)),
}
}
}
})
7 changes: 5 additions & 2 deletions packages/survey-vue3-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
"build": "vite build && npm run build:types",
"build:dev": "vite build --mode development",
"build:types": "vue-tsc --project tsconfig.types.json --emitDeclarationOnly",
"serve:example:dev": "npm run dev --prefix ./example",
"serve:example:prod": "npm run preview --prefix ./example",
"build:example:prod": "npm run build --prefix ./example",
"type-check": "vue-tsc --project tsconfig.types.json --noEmit",
"test": "vitest --no-threads tests/*.spec.ts",
"test:single": "vitest --no-watch --no-threads tests/*.spec.ts",
"release": "commit-and-tag-version --message \"Release: %s [azurepipelines skip]\" ",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
"lint": "eslint ./src ./tests --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
},
"devDependencies": {
"@babel/types": "^7.20.2",
Expand All @@ -40,4 +43,4 @@
"vue": "3.4.19",
"vue-tsc": "^1.0.8"
}
}
}
16 changes: 11 additions & 5 deletions packages/survey-vue3-ui/src/BooleanCheckbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,35 @@
:id="question.labelRenderedAriaID"
:class="question.cssClasses.checkboxControlLabel"
>
<survey-element-title-content
<SvComponent
:is="'survey-element-title-content'"
v-if="!question.hasTitleActions"
:element="question"
:css="css"
></survey-element-title-content>
<sv-title-actions
></SvComponent>
<SvComponent
:is="'sv-title-actions'"
v-if="question.hasTitleActions"
:element="question"
:css="css"
></sv-title-actions>
></SvComponent>
</span>
</label>
<div
v-if="question.canRenderLabelDescription"
:class="question.cssDescription"
:id="question.ariaDescriptionId"
>
<survey-string :locString="question.locDescription" />
<SvComponent
:is="'survey-string'"
:locString="question.locDescription"
/>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import SvComponent from "@/SvComponent.vue";
import { RendererFactory } from "survey-core";
import type { IBooleanProps } from "./boolean";
import { ref } from "vue";
Expand Down
22 changes: 13 additions & 9 deletions packages/survey-vue3-ui/src/BooleanRadio.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
<template>
<div :class="question.cssClasses.rootRadio" ref="root">
<fieldset role="presentation" :class="question.cssClasses.radioFieldset">
<sv-boolean-radio-item
<SvComponent
:is="'sv-boolean-radio-item'"
v-if="question.swapOrder"
:key="true"
:key="'true'"
:question="question"
:locText="question.locLabelTrue"
:value="true"
></sv-boolean-radio-item>
<sv-boolean-radio-item
:key="false"
></SvComponent>
<SvComponent
:is="'sv-boolean-radio-item'"
:key="'false'"
:question="question"
:locText="question.locLabelFalse"
:value="false"
></sv-boolean-radio-item>
<sv-boolean-radio-item
></SvComponent>
<SvComponent
:is="'sv-boolean-radio-item'"
v-if="!question.swapOrder"
:key="true"
:key="'true'"
:question="question"
:locText="question.locLabelTrue"
:value="true"
></sv-boolean-radio-item>
></SvComponent>
</fieldset>
</div>
</template>

<script lang="ts" setup>
import SvComponent from "@/SvComponent.vue";
import { RendererFactory } from "survey-core";
import { ref } from "vue";
import { useQuestion } from "./base";
Expand Down
3 changes: 2 additions & 1 deletion packages/survey-vue3-ui/src/BooleanRadioItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@
</svg>
</span>
<span :class="question.cssClasses.radioControlLabel">
<survey-string :locString="locText" />
<SvComponent :is="'survey-string'" :locString="locText" />
</span>
</label>
</div>
</template>

<script lang="ts" setup>
import SvComponent from "@/SvComponent.vue";
import type { LocalizableString, QuestionBooleanModel } from "survey-core";
const props = defineProps<{
Expand Down
19 changes: 13 additions & 6 deletions packages/survey-vue3-ui/src/BooleanSwitch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@
v-on:click="onLabelClick($event, question.swapOrder)"
>
<span :class="question.getLabelCss(question.swapOrder)"
><survey-string :locString="question.locLabelLeft"></survey-string
></span>
><SvComponent
:is="'survey-string'"
:locString="question.locLabelLeft"
/>
</span>
</div>
<div
:class="question.cssClasses.switch"
Expand All @@ -40,9 +43,10 @@
v-if="question.cssClasses.sliderText && question.isDeterminated"
:class="question.cssClasses.sliderText"
>
<survey-string
<SvComponent
:is="'survey-string'"
:locString="question.getCheckedLabel()"
></survey-string>
></SvComponent>
</span>
</span>
</div>
Expand All @@ -51,14 +55,17 @@
v-on:click="onLabelClick($event, !question.swapOrder)"
>
<span :class="question.getLabelCss(!question.swapOrder)"
><survey-string :locString="question.locLabelRight"></survey-string
></span>
><SvComponent
:is="'survey-string'"
:locString="question.locLabelRight"
/></span>
</div>
</label>
</div>
</template>
<script lang="ts" setup>
import SvComponent from "@/SvComponent.vue";
import { useQuestion } from "./base";
import { ref } from "vue";
import type { IBooleanProps } from "./boolean";
Expand Down
3 changes: 2 additions & 1 deletion packages/survey-vue3-ui/src/CheckboxItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@
<use :xlink:href="question.itemSvgIcon"></use>
</svg> </span
><span v-if="!hideLabel" :class="question.cssClasses.controlLabel">
<survey-string :locString="item.locText" />
<SvComponent :is="'survey-string'" :locString="item.locText" />
</span>
</label>
</div>
</template>

<script lang="ts" setup>
import SvComponent from "@/SvComponent.vue";
import type { ItemValue, QuestionCheckboxModel } from "survey-core";
import { ref } from "vue";
import { useSelectBaseItem } from "./selectbase-item";
Expand Down
21 changes: 15 additions & 6 deletions packages/survey-vue3-ui/src/Comment.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
<template>
<div ref="root" v-if="!question.isReadOnlyRenderDiv() && question.getMaxLength()">
<sv-text-area :model="question.textAreaModel"></sv-text-area>
<sv-character-counter
<div
ref="root"
v-if="!question.isReadOnlyRenderDiv() && question.getMaxLength()"
>
<SvComponent
:is="'sv-text-area'"
:model="question.textAreaModel"
></SvComponent>
<SvComponent
:is="'sv-character-counter'"
:counter="question.characterCounter"
:remainingCharacterCounter="question.cssClasses.remainingCharacterCounter"
></sv-character-counter>
></SvComponent>
</div>
<sv-text-area
<SvComponent
:is="'sv-text-area'"
ref="root"
v-else-if="!question.isReadOnlyRenderDiv() && !question.getMaxLength()"
:model="question.textAreaModel"
></sv-text-area>
></SvComponent>
<div ref="root" v-else>{{ question.value }}</div>
</template>

<script lang="ts" setup>
import SvComponent from "@/SvComponent.vue";
import type { QuestionCommentModel } from "survey-core";
import { useQuestion } from "./base";
import { ref } from "vue";
Expand Down
8 changes: 7 additions & 1 deletion packages/survey-vue3-ui/src/Composite.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
<template>
<survey-panel ref="root" :element="contentPanel" :css="css" />
<SvComponent
:is="'survey-panel'"
ref="root"
:element="contentPanel"
:css="css"
/>
</template>

<script lang="ts" setup>
import SvComponent from "@/SvComponent.vue";
import { computed, ref } from "vue";
import type { QuestionCompositeModel } from "survey-core";
import { useQuestion } from "./base";
Expand Down
3 changes: 2 additions & 1 deletion packages/survey-vue3-ui/src/Custom.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<component
<SvComponent
:ref="root"
:is="getComponentName(contentQuestion)"
:question="contentQuestion"
Expand All @@ -8,6 +8,7 @@
</template>

<script lang="ts" setup>
import SvComponent from "@/SvComponent.vue";
import { computed, ref } from "vue";
import type { QuestionCustomModel, Question } from "survey-core";
import { getComponentName as getComponent, useQuestion } from "./base";
Expand Down
Loading

0 comments on commit fb3e4b6

Please sign in to comment.