Skip to content

Commit

Permalink
feat: make former headless and remove formkit (#28)
Browse files Browse the repository at this point in the history
Co-authored-by: Tristan Stier <[email protected]>
Co-authored-by: mariusheine <[email protected]>
  • Loading branch information
3 people authored Oct 8, 2024
1 parent 1fc2a79 commit 2f52780
Show file tree
Hide file tree
Showing 74 changed files with 4,511 additions and 5,979 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Deploy
name: Deploy Playground

on:
pull_request:
Expand All @@ -21,11 +21,11 @@ jobs:
with:
version: 8
run_install: true
- run: pnpm build
- run: pnpm -r build:playground
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: playground/dist
path: packages/former/dist-playground

deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ on:
- main

jobs:
formart:
name: Check Formart
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand All @@ -18,10 +18,10 @@ jobs:
with:
version: 8
run_install: true
- run: pnpm format:check
- run: pnpm lint

lint:
name: Lint
typecheck:
name: Typecheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand All @@ -32,7 +32,7 @@ jobs:
with:
version: 8
run_install: true
# - run: pnpm lint # TODO: Uncomment this line after adding correct linting rules
- run: pnpm test

unit-test:
name: Unit Tests
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ lerna-debug.log*
node_modules
.DS_Store
dist
dist-playground
dist-ssr
coverage
*.local
Expand Down
6 changes: 6 additions & 0 deletions .gitpod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ tasks:
init: pnpm install && pnpm run build
command: pnpm run dev

vscode:
extensions:
- dbaeumer.vscode-eslint
- Vue.volar
- bradlc.vscode-tailwindcss
1 change: 0 additions & 1 deletion .prettierignore

This file was deleted.

8 changes: 0 additions & 8 deletions .prettierrc.cjs

This file was deleted.

40 changes: 38 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,42 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
// ########## START - eslint formatting options (https://github.com/antfu/eslint-config?tab=readme-ov-file#ide-support-auto-fix-on-save) ##############
// Disable the default formatter, use eslint instead
"prettier.enable": false,
"editor.formatOnSave": false,

// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},

// Enable eslint for all supported languages
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml",
"toml",
"xml",
"gql",
"graphql",
"astro",
"svelte",
"css",
"less",
"scss",
"pcss",
"postcss"
],
// ########## END - eslint formatting options ###############

// further configs
"editor.inlineSuggest.enabled": true,
"files.associations": {
"*.css": "tailwindcss"
Expand Down
171 changes: 136 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# 👩🏾‍🌾 Former

Former is a library to create [FormKit](https://formkit.com/) forms using an UI.
Former is a headless library for building and handlings forms for Vue using an UI. The available components must be configured externally so that it is highly customizable per use case.

It includes further headless features like

- conditional showing elements
- validation

## Playground

Expand All @@ -22,64 +27,160 @@ yarn add former-ui

## Usage

Just configure your form layout, define the components and let former do the rest.

```vue
<template>
<FormBuilder v-model:schema="schema" :mode="mode" v-model:data="data">
<main id="form-panel">
<div>
<label>Former mode:</label>
<select v-model="mode">
<option value="build">
build
</option>
<option value="edit">
edit
</option>
<option value="read">
read
</option>
</select>
</div>
<Former v-slot="{ selectedNode }" v-model:schema="schema" v-model:data="data" :mode :components>
<main>
<h1>My Form</h1>
<FormContent />
</main>
<aside id="form-field-options">
<FormFieldOptions />
<aside>
<h2>Form Config</h2>
<template v-if="mode === 'build'">
<FormNodeProps v-if="selectedNode" />
<FormAdd v-else />
</template>
<pre>{{ data }}</pre>
</aside>
</FormBuilder>
</Former>
</template>
<script setup lang="ts">
import type { FormKitSchemaNode } from '@formkit/core';
import { FormBuilder, FormBuilderOptions } from 'former-ui';
import { FormAdd, type FormData, Former, type FormFieldType, FormNodeProps, Mode, type SchemaNode } from 'former-ui';
import { markRaw, ref } from 'vue';
import TextInput from './TextInput.vue';
const schema = ref<FormKitSchemaNode[]>([
const schema = ref<SchemaNode[]>([
{
$el: 'h1',
children: 'Register',
attrs: {
class: 'text-2xl font-bold mb-4',
type: 'text',
name: 'name',
props: {
label: 'Name',
placeholder: 'Enter your name',
},
},
{
$formkit: 'text',
name: 'username',
label: 'Username',
help: 'This is your username.',
},
{
$formkit: 'text',
type: 'text',
name: 'email',
label: 'Email',
help: 'This is your email.',
props: {
label: 'Email',
placeholder: 'Enter your e-mail',
type: 'email'
},
},
{
$formkit: 'password',
type: 'text',
name: 'password',
label: 'Password',
help: 'This is your password.',
},
{
$formkit: 'checkbox',
name: 'terms',
label: 'I agree to the terms and conditions.',
props: {
label: 'Password',
placeholder: 'Enter your password',
type: 'password'
},
},
]);
const mode = ref<'edit' | 'preview'>('edit');
const components: { [k: string]: FormFieldType } = {
text: {
label: 'Text',
component: markRaw(TextInput),
propsSchema: [
{
type: 'text',
name: '$name',
props: {
label: 'Name',
placeholder: 'Enter the name of the data field',
},
},
{
type: 'text',
name: 'label',
props: {
label: 'Label',
placeholder: 'Enter a label',
},
},
{
type: 'text',
name: 'placeholder',
props: {
label: 'Placeholder',
placeholder: 'Enter a placeholder',
},
},
{
type: 'text',
name: 'type',
props: {
label: 'Text input type',
placeholder: 'Specify the text input type e.g. "text", "password", "email", ...'
}
}
],
},
};
const data = ref<Record<string, any>>({});
const mode = ref<Mode>('edit');
const data = ref<FormData>({});
</script>
```

## Credits
Of course you need to provide the relevant component implementations.
Here is a sample text input implementation that is suitable for the above sample

```vue
<template>
<div>
<label v-if="label">{{ label }}</label>
<div>
<input v-model="modelValue" :disabled="mode === 'read'" :type :placeholder>
</div>
<div v-if="error">
{{ error }}
</div>
</div>
</template>
<script setup lang="ts">
import { toRef } from 'vue';
import type { Mode } from '~/types';
const props = withDefaults(
defineProps<{
label?: string;
type?: 'text' | 'password' | 'email';
placeholder?: string;
error?: string;
mode?: Mode;
}>(),
{
type: 'text',
mode: 'edit',
},
);
const mode = toRef(props, 'mode');
const modelValue = defineModel<string>();
</script>
```

- https://github.com/formkit/formkit
For more detailed usage example check out the playground.
27 changes: 24 additions & 3 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,30 @@ import antfu from '@antfu/eslint-config';
export default antfu({
vue: true,
typescript: true,
formatters: {
/**
* Format CSS, LESS, SCSS files, also the `<style>` blocks in Vue
* By default uses Prettier
*/
css: true,
/**
* Format HTML files
* By default uses Prettier
*/
html: true,
/**
* Format Markdown files
* Supports Prettier and dprint
* By default uses Prettier
*/
markdown: 'prettier',
},
rules: {
'unused-imports/no-unused-vars': 'off', // off for now
'@typescript-eslint/no-unused-vars': 'off', // off for now
'node/prefer-global/process': 'off', // off for now
'@typescript-eslint/consistent-type-definitions': 'off', // off for now
'style/member-delimiter-style': 'off', // off for now
'style/semi': ['error', 'always'],
'vue/block-order': ['error', {
order: [['template', 'script'], 'style'],
}],
},
});
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
"type": "module",
"version": "0.0.0",
"private": true,
"packageManager": "[email protected]",
"scripts": {
"dev": "pnpm -r --parallel dev",
"lint": "eslint .",
"test": "pnpm -r test",
"typecheck": "pnpm -r typecheck",
"release": "pnpm -r release && changeset publish",
"format:check": "prettier --check .",
"build": "pnpm -r build"
},
"devDependencies": {
"prettier": "^3.2.5"
"@antfu/eslint-config": "^3.6.2",
"eslint": "^9.9.1",
"eslint-plugin-format": "^0.1.2"
}
}
Loading

0 comments on commit 2f52780

Please sign in to comment.