Skip to content

Commit

Permalink
Merge pull request #22 from formsible/feat/typing
Browse files Browse the repository at this point in the history
  • Loading branch information
tewnut authored Oct 28, 2024
2 parents b459cd7 + 140dedf commit 672728b
Show file tree
Hide file tree
Showing 29 changed files with 434 additions and 573 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,4 @@ dist
#vite config timestamp
/vite.config.ts.timestamp-*.mjs

pnpm-lock.yaml

components.d.ts
/components.d.ts
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default [
languageOptions: { parserOptions: { parser: tseslint.parser } },
},
{
files: ['**/*.{js,ts,vue}'],
files: ['**/*.{js,ts,vue,cjs}'],
rules: {
// Disable the rule that forbids require imports
'@typescript-eslint/no-require-imports': 'off',
Expand Down
3 changes: 1 addition & 2 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@
"label": "List",
"component": "list",
"description": "A sortable list of items.",
"placeholder": "Add an item",
"props": {
"items": ["First item", "Second item"]
}
Expand Down Expand Up @@ -729,7 +728,7 @@
"properties": {
"display": {
"component": "html_block_list",
"tag": "ordered",
"type": "ordered",
"items": ["First item", "Second item", "Third item"]
}
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"module": "dist/element.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/element.js",
"require": "./dist/element.umd.js"
},
Expand Down
32 changes: 20 additions & 12 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -181,18 +181,26 @@ onMounted(async () => {
return comp.meta?.enabled
})
formComponents.value = availableComponents.value.map((comp) => {
return {
name: comp.meta?.name || 'Unnamed Component',
component:
comp.init?.properties.input?.component ||
comp.init?.properties.display?.component,
inputProps: {
...comp.init?.properties.input,
...comp.init?.properties.display,
},
}
})
formComponents.value = availableComponents.value
.filter(
(components) =>
!!components.init.properties.display.component ||
!!components.init.properties.input.component,
)
.map((comp) => {
const displayComponent = comp.init?.properties.display.component
const inputComponent = comp.init?.properties.input.component
const component = inputComponent || displayComponent
return {
name: comp.meta?.name || 'Unnamed Component',
component: component as string | Component, // Ensure the type matches
inputProps: {
...comp.init.properties.input,
...comp.init.properties.display,
},
}
})
for (const comp of formComponents.value) {
const module = await import(`./components/${comp.component}/index.vue`)
Expand Down
3 changes: 1 addition & 2 deletions src/components/address/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ const isRequired = computed(() =>
:input-id="props.input.key"
:class="props.theme.input"
rows="4"
:placeholder="props.input?.placeholder || 'Enter your address'"
v-bind="{ ...$attrs, ...props.input.props }"
v-bind="props.input.props"
/>
<!-- if error -->
<small
Expand Down
45 changes: 13 additions & 32 deletions src/components/checkboxes/index.vue
Original file line number Diff line number Diff line change
@@ -1,47 +1,30 @@
<script setup lang="ts">
import { defineModel, computed, defineProps, type PropType } from 'vue'
import type { InputProperties } from '~/types'
import type { InputChoiceProperties } from '~/types'
import Checkbox from 'primevue/checkbox'
import { computed } from 'vue'
const props = defineProps({
input: {
type: Object as PropType<InputProperties>,
required: true,
},
theme: {
type: Object,
default: () => ({
container: '',
label: 'w-full text-black dark:text-white', // Added text color for label
input: 'flex flex-col gap-2', // Layout for checkboxes
description: 'text-sm text-slate-700 dark:text-slate-300', // Description text for both modes
checkbox: 'mr-2', // Margin for checkbox alignment
checkboxLabel: 'text-black dark:text-white', // Added text color for checkbox labels
error: 'text-red-600 dark:text-red-400', // Added dark mode color for error
}),
},
error: {
type: String,
default: '',
},
})
interface Props {
input: InputChoiceProperties
error?: string
}
const props = defineProps<Props>()
const model = defineModel<string[]>()
const isRequired = computed(() =>
props.input.validations?.map((v) => v.rule).includes('required'),
)
</script>

<template>
<div :class="theme.container">
<label :class="theme.label" :for="input.key">
<div>
<label :for="input.key">
{{ input.label }}
<span v-if="isRequired" class="text-red-600 dark:text-red-400"
>*</span
>
<!-- Adjusted for dark mode -->
</label>
<p :class="theme.description">{{ input.description }}</p>
<div :class="theme.input">
<p>{{ input.description }}</p>
<div>
<div
v-for="option in input.choices"
:key="option.value"
Expand All @@ -54,13 +37,11 @@ const isRequired = computed(() =>
:input-id="option.value"
v-bind="{ ...$attrs, ...props.input.props }"
/>
<label :for="option.value" :class="theme.checkboxLabel">{{
option.label
}}</label>
<label :for="option.value">{{ option.label }}</label>
<!-- Applied label styling -->
</div>
</div>
<small v-if="error" :id="`${input.key}-help`" :class="theme.error">
<small v-if="error" :id="`${input.key}-help`">
{{ error }}
</small>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/code_json/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ const handleReady = (payload: { view: EditorView }) => {
<Codemirror
v-model="code"
:disabled="readonly"
:placeholder="input.placeholder || 'Enter your code'"
:style="{ height: '400px' }"
:autofocus="true"
:indent-with-tab="true"
:v-bind="input.props"
:tab-size="2"
:extensions="extensions"
@ready="handleReady"
Expand Down
4 changes: 2 additions & 2 deletions src/components/dropdown/index.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script setup lang="ts">
import { computed, defineModel, defineProps } from 'vue'
import type { InputProperties } from '~/types'
import type { InputChoiceProperties } from '~/types'
import Select from 'primevue/select'
interface Props {
input: InputProperties
input: InputChoiceProperties
error?: string
readonly?: boolean
}
Expand Down
3 changes: 1 addition & 2 deletions src/components/email/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ const isRequired = computed(() =>
:input-id="input.key"
:class="theme.input"
type="email"
:placeholder="input?.placeholder || 'Enter your email'"
v-bind="{ ...$attrs, ...input.props }"
v-bind="input.props"
/>
<!-- if error -->
<small v-if="error" :id="`${input.key}-help`" :class="theme.error">{{
Expand Down
65 changes: 19 additions & 46 deletions src/components/image_choice/index.vue
Original file line number Diff line number Diff line change
@@ -1,33 +1,12 @@
<script setup lang="ts">
import { ref, computed, defineModel, defineProps, type PropType } from 'vue'
import type { InputProperties } from '~/types'
import { ref, computed } from 'vue'
import type { InputChoiceProperties } from '~/types'
const props = defineProps({
input: {
type: Object as PropType<InputProperties>,
required: true,
},
theme: {
type: Object,
default: () => ({
container: '',
label: 'w-full text-lg font-semibold text-gray-900 dark:text-gray-100',
input: 'w-full flex flex-wrap gap-2',
description: 'text-sm text-gray-700 dark:text-gray-300',
error: 'text-red-600 dark:text-red-400',
imageOption:
'relative flex flex-col items-center p-2 cursor-pointer transition-transform duration-300 ease-in-out transform hover:scale-105',
image: 'w-24 h-24 object-cover border-2 border-transparent rounded-lg',
imageSelected: 'border-blue-500 dark:border-blue-300',
selectedOverlay:
'absolute inset-0 border-4 border-blue-500 dark:border-blue-300 rounded-lg pointer-events-none',
}),
},
error: {
type: String,
default: '',
},
})
interface Props {
input: InputChoiceProperties
error?: string
}
const props = defineProps<Props>()
const model = defineModel<string>({ default: '' })
Expand All @@ -42,35 +21,38 @@ const isRequired = computed(() =>
</script>

<template>
<div :class="theme.container">
<label :class="theme.label" :for="input.key">
<div>
<label :for="input.key">
{{ input.label }}
<span v-if="isRequired" class="text-red-600 dark:text-red-400"
>*</span
>
</label>
<p :class="theme.description">{{ input.description }}</p>
<p>{{ input.description }}</p>
<!-- input section -->
<div :class="theme.input">
<div>
<div
v-for="option in input.choices"
:key="option.value"
:class="theme.imageOption"
class="relative flex flex-col items-center p-2 cursor-pointer transition-transform duration-300 ease-in-out transform hover:scale-105"
@click="selectImage(option.value)"
>
<div
:class="[
'relative',
{ [theme.selectedOverlay]: selected === option.value },
{
'absolute inset-0 border-4 border-blue-500 dark:border-blue-300 rounded-lg pointer-events-none':
selected === option.value,
},
]"
>
<img
:src="option.value"
:alt="option.label"
:class="[
theme.image,
'w-24 h-24 object-cover border-2 border-transparent rounded-lg',
{
[theme.imageSelected]:
['border-blue-500 dark:border-blue-300']:
selected === option.value,
},
]"
Expand All @@ -82,17 +64,8 @@ const isRequired = computed(() =>
</div>
</div>
<!-- if error -->
<small v-if="error" :id="`${input.key}-help`" :class="theme.error">{{
<small v-if="error" :id="`${input.key}-help`" class="text-red-500">{{
error
}}</small>
</div>
</template>

<style scoped>
.imageOption {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
</style>
38 changes: 12 additions & 26 deletions src/components/likert_scale/index.vue
Original file line number Diff line number Diff line change
@@ -1,36 +1,23 @@
<script setup lang="ts">
import { defineModel, computed, defineProps, type PropType } from 'vue'
import type { InputProperties } from '~/types'
import { computed } from 'vue'
import type { InputChoiceProperties } from '~/types'
import RadioButton from 'primevue/radiobutton'
const props = defineProps({
input: {
type: Object as PropType<InputProperties>,
required: true,
},
theme: {
type: Object,
default: () => ({
container: '',
label: 'w-full text-black dark:text-white', // Label colors for dark and light mode
input: 'flex items-center text-black dark:text-white', // Ensure RadioButton and label text colors adapt
description: 'text-sm text-slate-700 dark:text-slate-300', // Description text for both modes
error: 'text-red-600 dark:text-red-400', // Error colors for dark and light mode
}),
},
error: {
type: String,
default: '',
},
})
interface Props {
input: InputChoiceProperties
error?: string
}
const props = defineProps<Props>()
const model = defineModel<string>({ default: '' })
const isRequired = computed(() =>
props.input.validations?.map((v) => v.rule).includes('required'),
)
</script>

<template>
<div :class="theme.container">
<div>
<p class="font-medium">
{{ props.input.label }}
<span v-if="isRequired" class="text-red-500">*</span>
Expand All @@ -48,8 +35,7 @@ const isRequired = computed(() =>
v-model="model"
:value="option.value"
:input-id="`${input.key}-${option.value}`"
:class="theme.input"
v-bind="{ ...$attrs, ...input.props }"
v-bind="input.props"
/>
<label
:for="`${input.key}-${option.value}`"
Expand All @@ -59,7 +45,7 @@ const isRequired = computed(() =>
</label>
</div>
</div>
<small v-if="error" :id="`${input.key}-help`" :class="theme.error">
<small v-if="error" :id="`${input.key}-help`" class="text-red-500">
{{ error }}
</small>
</div>
Expand Down
Loading

0 comments on commit 672728b

Please sign in to comment.