├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode └── extensions.json ├── CHANGELOG.md ├── CONTRIBUTION.md ├── README.md ├── apps └── formula-app │ ├── .eslintrc.json │ ├── jest.config.js │ ├── package.json │ ├── public │ ├── favicon.png │ ├── global.css │ └── index.html │ ├── rollup.config.js │ ├── src │ ├── App.svelte │ ├── main.ts │ └── pages │ │ ├── App2.svelte │ │ ├── Home.svelte │ │ ├── SignupForm.svelte │ │ ├── Table.svelte │ │ └── WeePage.svelte │ ├── tsconfig.app.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── assets └── logo.png ├── babel.config.json ├── docs ├── 1.23afa72b.js ├── 17896441.f9a33f88.js ├── 2.215e07fe.js ├── 2.215e07fe.js.LICENSE.txt ├── 27.e7fa62ba.js ├── 28.1be0f6ce.js ├── 40370821.3f878b17.js ├── 404.html ├── 41b8b04a.1fa08bb7.js ├── 5b8e8dbb.7997005f.js ├── 71eaf432.28e1d60c.js ├── 935f2afb.19677f49.js ├── 94d81bc1.9b5ae040.js ├── 95487a17.76aea661.js ├── CNAME ├── a3b85b22.dc69a3a0.js ├── abd305bb.2462f6f3.js ├── aebba8f7.37199675.js ├── b5f6d7ef.27541933.js ├── b8066252.66c747a8.js ├── bad4e641.93d08170.js ├── blog │ ├── atom.xml │ └── rss.xml ├── c4f5d8e4.f1743761.js ├── c9862f47.46757e4a.js ├── d0cdf717.ec9f3058.js ├── db915915.90407040.js ├── docs │ ├── attributes │ │ └── index.html │ ├── examples │ │ ├── custom-event │ │ │ └── index.html │ │ ├── customer-rows │ │ │ └── index.html │ │ └── signup │ │ │ └── index.html │ ├── formula │ │ └── index.html │ ├── groups │ │ ├── beaker │ │ │ └── index.html │ │ └── data │ │ │ └── index.html │ ├── lifecycle │ │ └── index.html │ ├── options │ │ └── index.html │ └── stores │ │ ├── stores-dirty │ │ └── index.html │ │ ├── stores-enrichment │ │ └── index.html │ │ ├── stores-form-valid │ │ └── index.html │ │ ├── stores-form-validity │ │ └── index.html │ │ ├── stores-form-values │ │ └── index.html │ │ ├── stores-initial-values │ │ └── index.html │ │ ├── stores-submit-values │ │ └── index.html │ │ ├── stores-touched │ │ └── index.html │ │ ├── stores-validity │ │ └── index.html │ │ └── stores │ │ └── index.html ├── f09413f6.7f430def.js ├── f3437f8c.45755d72.js ├── f5547967.fe5f509f.js ├── fb696b7f.c01b6e9a.js ├── img │ ├── atom.png │ ├── atom_256.png │ ├── beaker-large.png │ ├── beaker-small.png │ ├── beaker_256.png │ ├── favicon.ico │ ├── formula-small.png │ ├── logo-small.png │ ├── logo.png │ ├── logo.svg │ ├── logo_256.png │ ├── molecular-structure.png │ ├── molecular-structure_256.png │ ├── svelte-logo.svg │ ├── svelte-vertical.svg │ ├── undraw_apps.svg │ ├── undraw_docusaurus_mountain.svg │ ├── undraw_docusaurus_react.svg │ ├── undraw_docusaurus_tree.svg │ └── undraw_form.svg ├── index.html ├── main.64739da4.js ├── main.64739da4.js.LICENSE.txt ├── runtime~main.0404ab80.js ├── sitemap.xml ├── styles.92ad7215.js └── styles.c39ff6cc.css ├── jest.config.js ├── jest.preset.js ├── nx.json ├── package-lock.json ├── package.json ├── packages ├── .gitkeep ├── docs-site │ ├── babel.config.js │ ├── docs │ │ ├── attributes.md │ │ ├── examples │ │ │ ├── custom-event.md │ │ │ ├── customer-rows.md │ │ │ └── signup.md │ │ ├── formula.md │ │ ├── groups │ │ │ ├── data.md │ │ │ └── groups.md │ │ ├── lifecycle.md │ │ ├── options.md │ │ └── stores │ │ │ ├── dirty.mdx │ │ │ ├── enrichment.mdx │ │ │ ├── form-validity.mdx │ │ │ ├── form-values.mdx │ │ │ ├── initial-values.mdx │ │ │ ├── is-form-valid.mdx │ │ │ ├── stores.md │ │ │ ├── submit-values.md │ │ │ ├── touched.mdx │ │ │ └── validity.mdx │ ├── docusaurus.config.js │ ├── sidebars.js │ ├── src │ │ ├── css │ │ │ └── custom.css │ │ ├── pages │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ └── theme │ │ │ └── prism-include-languages.js │ └── static │ │ ├── CNAME │ │ └── img │ │ ├── atom.png │ │ ├── atom_256.png │ │ ├── beaker-large.png │ │ ├── beaker-small.png │ │ ├── beaker_256.png │ │ ├── favicon.ico │ │ ├── formula-small.png │ │ ├── logo-small.png │ │ ├── logo.png │ │ ├── logo.svg │ │ ├── logo_256.png │ │ ├── molecular-structure.png │ │ ├── molecular-structure_256.png │ │ ├── svelte-logo.svg │ │ ├── svelte-vertical.svg │ │ ├── undraw_apps.svg │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ ├── undraw_docusaurus_tree.svg │ │ └── undraw_form.svg ├── formula-app-e2e │ ├── .eslintrc.json │ ├── cypress.json │ ├── src │ │ ├── fixtures │ │ │ └── example.json │ │ ├── integration │ │ │ └── app.spec.ts │ │ ├── plugins │ │ │ └── index.js │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── index.ts │ ├── tsconfig.e2e.json │ └── tsconfig.json └── svelte │ └── formula │ ├── .babelrc │ ├── .eslintrc.json │ ├── jest.config.js │ ├── package.json │ ├── src │ ├── index.ts │ ├── lib │ │ ├── form │ │ │ ├── aria.spec.ts │ │ │ ├── aria.ts │ │ │ ├── dirty.spec.ts │ │ │ ├── dirty.ts │ │ │ ├── enrichment.spec.ts │ │ │ ├── enrichment.ts │ │ │ ├── errors.spec.ts │ │ │ ├── errors.ts │ │ │ ├── event.spec.ts │ │ │ ├── event.ts │ │ │ ├── extract.ts │ │ │ ├── form.ts │ │ │ ├── init.ts │ │ │ ├── touch.spec.ts │ │ │ └── touch.ts │ │ ├── group │ │ │ └── group.ts │ │ └── shared │ │ │ ├── fields.spec.ts │ │ │ ├── fields.ts │ │ │ ├── stores.spec.ts │ │ │ └── stores.ts │ └── types │ │ ├── enrich.ts │ │ ├── forms.ts │ │ ├── formula.ts │ │ ├── groups.ts │ │ ├── index.ts │ │ ├── options.ts │ │ └── validation.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── tools ├── generators │ └── .gitkeep └── tsconfig.tools.json ├── tsconfig.base.json ├── workspace.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = 120 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nrwl/nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nrwl/nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "*", 17 | "onlyDependOnLibsWithTags": ["*"] 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx"], 26 | "extends": ["plugin:@nrwl/nx/typescript"], 27 | "rules": {} 28 | }, 29 | { 30 | "files": ["*.js", "*.jsx"], 31 | "extends": ["plugin:@nrwl/nx/javascript"], 32 | "rules": {} 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | /docs/ 41 | 42 | # Generated Docusaurus files 43 | .docusaurus/ 44 | .cache-loader/ 45 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | .docusaurus/ 6 | docs/ 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "printWidth": 120, 4 | "semi": true, 5 | "trailingComma": "all" 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-vscode.vscode-typescript-tslint-plugin", 4 | "esbenp.prettier-vscode", 5 | "firsttris.vscode-jest-runner" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /CONTRIBUTION.md: -------------------------------------------------------------------------------- 1 | # This is an ad-hoc contribution guide. 2 | 3 | The purpose of this document is to describe steps required to get the repo working, as well as the common command used for testing before submitting a pull request. 4 | 5 | ## Setup 6 | 7 | - The repo uses NX and Yarn. You can install Yarn with `npm install --global yarn` 8 | - You can install NX and other packages with `yarn` 9 | 10 | ## Once set up, there's a couple of commands: 11 | 12 | - `npm run start formula-app --rollupConfig=apps/formula-app/rollup.config.js` - this starts the small testing app I use running, it's not very pretty but it lets me test thing (I already have a branch investigating using this app for Cypress e2e testing as well but there is an issue with the internal lib resolving) 13 | 14 | - `npm run start svelte-formula --skip-nx-cache --watch` If you run that with the above, you get hot-reloading when you change the lib` 15 | 16 | - `npm run build svelte-formula --skip-nx-cache` Runs build 17 | 18 | - `npm run lint svelte-formula` Runs linter 19 | 20 | - `npm run start docs-site` Runs the docosaurus site under packages/doc-site 21 | 22 | - `npm run nx test svelte-formula` - Runs the unit test suite 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # Formula + Beaker Δ→ 4 | 5 | **Reactive Forms for Svelte** 6 | 7 | ![The Svelte Formula Logo](https://raw.githubusercontent.com/tanepiper/svelte-formula/main/docs/img/logo_256.png) 8 | 9 |
10 | 11 | [![svelte-formula](https://img.shields.io/npm/v/svelte-formula?label=svelte-formula)](https://www.npmjs.com/package/svelte-formula) 12 | 13 | - [Documentation](https://tanepiper.github.io/svelte-formula) 14 | - [Changelog](https://github.com/tanepiper/svelte-formula/blob/main/CHANGELOG.md) 15 | 16 | `svelte-formula` is a Library for use with [Svelte](https://svelte.dev) that super-charges your ability to create rich 17 | data-driven for applications. 18 | 19 | ## Install Instructions 20 | 21 | `npm i svelte-formula` 22 | 23 | ## Usage 24 | 25 | All you need is an element container with the Svelte [use](https://svelte.dev/docs#use_action) directive and form input 26 | fields with their `name` property set. 27 | 28 | Visit the [documentation](https://tanepiper.github.io/svelte-formula) for more details API instructions. 29 | 30 | ## Formula 31 | 32 | [Demo](https://svelte.dev/repl/dda29ae516284147871b58a4f1966315) 33 | 34 |
35 | 36 | ![The Svelte Formula Logo](https://raw.githubusercontent.com/tanepiper/svelte-formula/main/docs/img/formula-small.png) 37 | 38 |
39 | 40 | **Formula** is a library for creating _Zero Configuration_ reactive form components, and fully data-driven applications. 41 | 42 | **Zero-Configuration** means you need nothing more than a well-defined HTML5 form element to have fully reactive stores 43 | of data and form states. 44 | 45 | Accessing the input requires only setting the `name` property, and for validation providing attributes like `require` 46 | or `minlength`. Formula supports single and multi-value inputs across all widely supported HTML inputs and extends them 47 | with checkbox groups and radio groups, and composite fields of values like text or number. 48 | 49 | Formula creates a form instance that contains Svelte [stores](https://tanepiper.github.io/svelte-formula/docs/stores/stores) that 50 | contain value and validation information, and some 51 | additional [lifecycle methods](https://tanepiper.github.io/svelte-formula/docs/lifecycle) that allow your to dynamically add and 52 | remove customisations, and reset or destroy the form. It also attempts to apply ARIA attributes to help with 53 | accessibility. 54 | 55 | ### Extending Formula 56 | 57 | Formula also supports a bunch of [powerful options](https://tanepiper.github.io/svelte-formula/docs/options) that provide additional 58 | validation, enrichment and custom messages. 59 | 60 | For example with the `enrich` [option](https://tanepiper.github.io/svelte-formula/docs/options#enrich) 61 | and `enrichment` [store](https://tanepiper.github.io/svelte-formula/docs/stores/stores-enrichment) you can provide functions that 62 | calculate additional computed values based on user input - for example calculating a password strength, or the length of 63 | text a user has entered. These are useful. 64 | 65 | Validations can be provided at the form and field level, and integrate with in-built browser validations to provide 66 | native messages, which can be customised for localisation. 67 | 68 | ### Beaker 69 | 70 | [Demo](https://svelte.dev/repl/c146c7976360405cba9a696e3fee853b) 71 | 72 |
73 | 74 | ![The Svelte Formula Logo](https://raw.githubusercontent.com/tanepiper/svelte-formula/main/docs/img/beaker-small.png) 75 | 76 |
77 | 78 | **Beaker** take Formula and adds another layer for working with collections of data. 79 | 80 | Using row-based input you can create full form instances per row that are also fully reactive and feed into Beaker's 81 | collection store. 82 | 83 | Beaker also provides methods for setting, adding and removing items from the in-built stores, when can be used with 84 | Svelte's `{#each}{/each}` blocks to create a re-usable template in the component 85 | 86 | With this you can build applications such as multi-row editable tables or lists. See 87 | the [documentation](https://tanepiper.github.io/svelte-formula/docs/groups/beaker) for more details and examples. 88 | -------------------------------------------------------------------------------- /apps/formula-app/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "env": { 5 | "browser": true, 6 | "commonjs": true, 7 | "es6": true, 8 | "jest": true, 9 | "node": true 10 | }, 11 | "plugins": ["import", "jsx-a11y", "react", "react-hooks"], 12 | "overrides": [ 13 | { 14 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 15 | "parserOptions": { 16 | "project": ["apps/formula-app/tsconfig.*?.json"] 17 | }, 18 | "rules": {} 19 | }, 20 | { 21 | "files": ["*.ts", "*.tsx"], 22 | "rules": {} 23 | }, 24 | { 25 | "files": ["*.js", "*.jsx"], 26 | "rules": {} 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /apps/formula-app/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'formula-app', 3 | preset: '../../jest.preset.js', 4 | globals: { 5 | 'ts-jest': { 6 | tsconfig: '/tsconfig.spec.json', 7 | }, 8 | }, 9 | transform: { 10 | '^.+\\.svelte$': 'svelte-jester', 11 | '^.+\\.[tj]s$': 'ts-jest', 12 | }, 13 | moduleFileExtensions: ['ts', 'js', 'html', 'svelte'], 14 | coverageDirectory: '../../coverage/apps/formula-app', 15 | }; 16 | -------------------------------------------------------------------------------- /apps/formula-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formula-app", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "svelte": ">= 3.0.0", 6 | "svelte-formula": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/formula-app/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanepiper/svelte-formula/bb09898fb2c852914c70208d2d0a992434ac857f/apps/formula-app/public/favicon.png -------------------------------------------------------------------------------- /apps/formula-app/public/global.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | position: relative; 4 | width: 100%; 5 | height: 100%; 6 | } 7 | 8 | body { 9 | color: #333; 10 | margin: 0; 11 | padding: 8px; 12 | box-sizing: border-box; 13 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', 14 | sans-serif; 15 | } 16 | 17 | a { 18 | color: rgb(0, 100, 200); 19 | text-decoration: none; 20 | } 21 | 22 | a:hover { 23 | text-decoration: underline; 24 | } 25 | 26 | a:visited { 27 | color: rgb(0, 80, 160); 28 | } 29 | 30 | label { 31 | display: block; 32 | } 33 | 34 | input, 35 | button, 36 | select, 37 | textarea { 38 | font-family: inherit; 39 | font-size: inherit; 40 | -webkit-padding: 0.4em 0; 41 | padding: 0.4em; 42 | margin: 0 0 0.5em 0; 43 | box-sizing: border-box; 44 | border: 1px solid #ccc; 45 | border-radius: 2px; 46 | } 47 | 48 | input:disabled { 49 | color: #ccc; 50 | } 51 | 52 | button { 53 | color: #333; 54 | background-color: #f4f4f4; 55 | outline: none; 56 | } 57 | 58 | button:disabled { 59 | color: #999; 60 | } 61 | 62 | button:not(:disabled):active { 63 | background-color: #ddd; 64 | } 65 | 66 | button:focus { 67 | border-color: #666; 68 | } 69 | -------------------------------------------------------------------------------- /apps/formula-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Svelte app 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /apps/formula-app/rollup.config.js: -------------------------------------------------------------------------------- 1 | module.exports = (config) => { 2 | const { output, external, ...rest } = config; 3 | 4 | const updatedOutput = { 5 | ...output, 6 | globals: [ 7 | { 8 | moduleId: 'svelte-formula', 9 | global: 'SvelteFormula', 10 | }, 11 | ], 12 | }; 13 | const updatedExternal = [...[external || []], 'svelte-formula']; 14 | const result = { 15 | ...rest, 16 | output: { ...updatedOutput }, 17 | external: [...updatedExternal], 18 | }; 19 | return result; 20 | }; 21 | -------------------------------------------------------------------------------- /apps/formula-app/src/App.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /apps/formula-app/src/main.ts: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | props: { 6 | name: 'formula-app', 7 | }, 8 | }); 9 | 10 | export default app; 11 | -------------------------------------------------------------------------------- /apps/formula-app/src/pages/Home.svelte: -------------------------------------------------------------------------------- 1 | 5 | 19 | -------------------------------------------------------------------------------- /apps/formula-app/src/pages/WeePage.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 |
17 |
18 | 19 | {$validity?.zzz?.message} 20 |
21 | 22 |
23 | 24 | 27 | -------------------------------------------------------------------------------- /apps/formula-app/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src/**/*"], 4 | "exclude": ["__sapper__/*", "public/*"] 5 | } 6 | -------------------------------------------------------------------------------- /apps/formula-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | 4 | "compilerOptions": { 5 | "moduleResolution": "node", 6 | "target": "es2017", 7 | /** 8 | Svelte Preprocess cannot figure out whether you have a value or a type, so tell TypeScript 9 | to enforce using `import type` instead of `import` for Types. 10 | */ 11 | "importsNotUsedAsValues": "error", 12 | "isolatedModules": true, 13 | /** 14 | To have warnings/errors of the Svelte compiler at the correct position, 15 | enable source maps by default. 16 | */ 17 | "sourceMap": true, 18 | /** Requests the runtime types from the svelte modules by default. Needed for TS files or else you get errors. */ 19 | "types": ["svelte"], 20 | 21 | "strict": false, 22 | "esModuleInterop": true, 23 | "skipLibCheck": true, 24 | "forceConsistentCasingInFileNames": true 25 | }, 26 | "files": [], 27 | "include": [], 28 | "references": [ 29 | { 30 | "path": "./tsconfig.app.json" 31 | }, 32 | { 33 | "path": "./tsconfig.spec.json" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /apps/formula-app/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["**/*.spec.ts", "**/*.spec.tsx", "**/*.spec.js", "**/*.spec.jsx", "**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanepiper/svelte-formula/bb09898fb2c852914c70208d2d0a992434ac857f/assets/logo.png -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@nrwl/web/babel"], 3 | "babelrcRoots": ["*"] 4 | } 5 | -------------------------------------------------------------------------------- /docs/2.215e07fe.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | Copyright (c) 2017 Jed Watson. 3 | Licensed under the MIT License (MIT), see 4 | http://jedwatson.github.io/classnames 5 | */ 6 | -------------------------------------------------------------------------------- /docs/28.1be0f6ce.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[28],{108:function(e,t,a){"use strict";a.r(t);var n=a(0),o=a.n(n),l=a(106);t.default=function(){return o.a.createElement(l.a,{title:"Page Not Found"},o.a.createElement("main",{className:"container margin-vert--xl"},o.a.createElement("div",{className:"row"},o.a.createElement("div",{className:"col col--6 col--offset-3"},o.a.createElement("h1",{className:"hero__title"},"Page Not Found"),o.a.createElement("p",null,"We could not find what you were looking for."),o.a.createElement("p",null,"Please contact the owner of the site that linked you to the original URL and let them know their link is broken.")))))}}}]); -------------------------------------------------------------------------------- /docs/40370821.3f878b17.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[4],{73:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return l})),n.d(t,"metadata",(function(){return o})),n.d(t,"toc",(function(){return u})),n.d(t,"default",(function(){return c}));var r=n(3),a=n(7),i=(n(0),n(97)),l={id:"stores-initial-values",title:"initialValues",sidebar_label:"initialValues"},o={unversionedId:"stores/stores-initial-values",id:"stores/stores-initial-values",isDocsHomePage:!1,title:"initialValues",description:"Description",source:"@site/docs/stores/initial-values.mdx",slug:"/stores/stores-initial-values",permalink:"/svelte-formula/docs/stores/stores-initial-values",version:"current",sidebar_label:"initialValues",sidebar:"someSidebar",previous:{title:"formValues",permalink:"/svelte-formula/docs/stores/stores-form-values"},next:{title:"isFormValid",permalink:"/svelte-formula/docs/stores/stores-form-valid"}},u=[{value:"Description",id:"description",children:[]},{value:"Example",id:"example",children:[]}],s={toc:u};function c(e){var t=e.components,n=Object(a.a)(e,["components"]);return Object(i.b)("wrapper",Object(r.a)({},s,n,{components:t,mdxType:"MDXLayout"}),Object(i.b)("h2",{id:"description"},"Description"),Object(i.b)("p",null,"This store contains all the form values at the time the form was initialised - this may include ",Object(i.b)("inlineCode",{parentName:"p"},"defaultValues")," and any values\nbound on the form at configuration. This store will never change during the lifecycle of the form The values are an ",Object(i.b)("inlineCode",{parentName:"p"},"Object")," with the\nkey per group ",Object(i.b)("inlineCode",{parentName:"p"},"name")," and it's value."),Object(i.b)("p",null,"The value can be a single value, or an array or values depending on there being fields with the same ",Object(i.b)("inlineCode",{parentName:"p"},"name")," (e.g. multiple checkboxes), or a ",Object(i.b)("inlineCode",{parentName:"p"}," 32 | 33 | 39 | 40 | ``` 41 | 42 | ## Component Use 43 | 44 | ```svelte 45 | 46 | 74 | 75 |
76 | 77 | 78 | 81 | 82 | 83 | 88 | 89 | ``` 90 | -------------------------------------------------------------------------------- /packages/docs-site/docs/examples/customer-rows.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: customer-rows 3 | 4 | title: Example - Customer Rows 5 | 6 | sidebar_label: Row Data 7 | --- 8 | 9 | ```svelte 10 | 65 | 66 | 67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | {#each $customersValues as row, i} 87 | 88 | 92 | 96 | 100 | 121 | 122 | 123 | 126 | 129 | 132 | 135 | 136 | {/each} 137 | 138 |
Customer DataSubscription LevelSubscriptions
89 | 90 | 91 | 93 | 94 | 95 | 97 | 98 | 99 | 101 | 102 | 107 | 108 | 113 | 114 | 119 | 120 | 133 | 134 |
139 |
140 | ``` 141 | -------------------------------------------------------------------------------- /packages/docs-site/docs/examples/signup.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: signup 3 | 4 | title: Example - Signup Form 5 | 6 | sidebar_label: Complex Form 7 | --- 8 | 9 | ```svelte 10 | 54 | {passwordStrength} 55 |
56 | 59 | 60 |
61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | 71 |
72 |
73 | 74 | 76 | 77 |
78 |
79 | 80 | 81 | 82 |
83 | 84 | 85 |
86 | 87 | 92 | 93 | ``` 94 | -------------------------------------------------------------------------------- /packages/docs-site/docs/formula.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: formula 3 | 4 | title: Formula API 5 | 6 | sidebar_label: Formula API 7 | --- 8 | 9 | [![svelte-formula](https://img.shields.io/npm/v/svelte-formula?label=svelte-formula)](https://www.npmjs.com/package/svelte-formula) 10 | 11 | ## What is Formula? 12 | 13 | > **Formula is still in active development - as such there may still be API changes** 14 | 15 | Formula is a library for [Svelte](https://svelte.dev) with features for creating **Zero Configuration** reactive forms 16 | and fully data-driven applications. 17 | 18 | Out-of-the box it's designed to work with HTML5 forms. Using the `name` attribute of your HTML elements, Formula builds 19 | a set of state objects using Svelte's subscribable [stores](stores/stores.md), making them available for you subscribe 20 | to in your application. These stores contain values and validation states, which are configured as easily as setting 21 | supported attributes, and doesn't get in the way of things like Accessibility. 22 | 23 | > Want to make a field required? Just add the `` attribute, or add `` to set a minimum length on the fields. 24 | 25 | Validation is enhanced via custom field and form level validation functions passed in the [options](options.md) - you 26 | can also pass default values, or override default HTML5 validation text with your own versions (such as localised text). 27 | 28 | You can also enrich you fields with computed values (such as a password strength derived from the users input). 29 | 30 | ### Working with Data Collections 31 | 32 | Formula also provides an API for working with collections of data - [beaker](groups/groups.md) allows you to use Formula to 33 | create rich row-level forms for applications such as data grids. 34 | 35 | ## Installation 36 | 37 | Formula is available on NPM, with the source available on GitHub. To install in your project type: 38 | 39 | > `npm i svelte-formula` 40 | 41 | ## Basic Form Example 42 | 43 | To use in your project all you need is an element container binding the form with 44 | Svelte [use](https://svelte.dev/docs#use_action) 45 | directive, and form input fields with their `name` property set. 46 | 47 | ```svelte 48 | 58 | 59 |
60 | 61 | 62 | 63 | 64 |
65 | ``` 66 | -------------------------------------------------------------------------------- /packages/docs-site/docs/groups/data.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: data 3 | 4 | title: Data API 5 | 6 | sidebar_label: Data API 7 | --- 8 | 9 | Like Formula, `beaker` returns an instance of the Beaker stores which are have the same name as 10 | the [Formula store](../stores/stores.md), but container Array of form data as rows. The exceptions are 11 | `isFormReady` and `isFormValid` which are for the entire group and still a single value. 12 | 13 | It also contains some additional properties and methods. The methods listed below allow for data to be added or removed 14 | from the groups `formValue` store - this store can also be used with a `{#each}` block to render the rows in the 15 | template. 16 | 17 | ## `init` 18 | 19 | Pass initial data into the form group, or reset the form to initial data - this will the form store data with the 20 | current items to render. Each key and value should match the fields in the group template (the exception 21 | is [radio fields](./groups.md) which should be based on the `data-formula-name` attribute passed). 22 | 23 | ```svelte 24 | 25 | 35 |
36 | {#each items as item, i} 37 | 38 | {/each} 39 |
40 | ``` 41 | 42 | ## `add` 43 | 44 | Add a row item to the store - this item should be a single object with the same key/value type for the form. 45 | 46 | ```svelte 47 | 48 | 58 | 59 | 60 |
61 | {#each items as item, i} 62 | 63 | {/each} 64 |
65 | ``` 66 | 67 | ## `set` 68 | 69 | Update an existing row in the store at the passed index. 70 | 71 | ```svelte 72 | 73 | 83 | 84 |
85 | {#each items as item, i} 86 | ... 87 | 88 | 89 | ... 90 | {/each} 91 |
92 | ``` 93 | 94 | ## `delete` 95 | 96 | Deletes a row from the form - this method takes the index of the row to remove. 97 | 98 | ```svelte 99 | 100 | 110 | 111 |
112 | {#each items as item, i} 113 | 114 | {/each} 115 |
116 | ``` 117 | 118 | ## `clear` 119 | 120 | Calling this will empty the group of all rows of data. 121 | 122 | ## `forms` 123 | 124 | An `Map` of all the underlying [Formula](../formula.md) instances that allows for finer control, or access to the form 125 | stores 126 | -------------------------------------------------------------------------------- /packages/docs-site/docs/lifecycle.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: lifecycle 3 | 4 | title: Formula Lifecycle 5 | 6 | sidebar_label: Formula Lifecycle 7 | --- 8 | 9 | ## Create 10 | 11 | To create your form instance call the `formula()` method, this creates a `form` instance that can be attached to any 12 | element with the [use](https://svelte.dev/docs#use_action) directive. 13 | 14 | When using like this, on component destruction the form will automatically unbind 15 | 16 | ```svelte 17 | 22 | 23 | 24 |
25 | 26 | 27 |
28 | ``` 29 | 30 | ## Update 31 | 32 | Any Formula instance can be updated using the `updateForm` method, which accepts a new `FormulaOptions` object. When 33 | using `update` all existing handlers will be removed and rebound. 34 | 35 | ```svelte 36 | 48 | 49 |
50 | 51 | 52 | 53 |
54 | 55 |
56 | 57 |
58 | ``` 59 | 60 | ## Reset 61 | 62 | The `resetForm` can be called at any time during the life of the form, it will reset the form to it's initial state after 63 | `defaultValues` and element values have been applied, also `touched` and `dirty` stores are reset. 64 | 65 | ```svelte 66 | 74 |
75 | 76 | 77 | 78 | 79 | 80 |
{$initialTotal?.value1} + {$initialTotal?.value2} = {initialTotal}
81 |
{$formValues?.value1} + {$formValues?.value2} = {total}
82 | 83 | 84 |
85 | ``` 86 | 87 | ## Destroy 88 | 89 | The `destroyForm` method allows the form to be destroyed early, which removes all handlers and removes the stores from the 90 | global store. 91 | -------------------------------------------------------------------------------- /packages/docs-site/docs/options.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: options 3 | 4 | title: Formula Options 5 | 6 | sidebar_label: Formula Options 7 | --- 8 | 9 | Formula is zero-configuration - Out-of-the-box - using standard HTML5 validation properties to build up its validation 10 | rules - however it is also possible to pass custom validation rules via the `formula()` options object. 11 | 12 | ## `defaultValues` 13 | 14 | The `defaultValues` option allows an initial set of values to be passed to the form. 15 | 16 | Form values can also be set with defaults using ``, if no value it set it will fall back to 17 | this value. If there is no default value, then it will be an empty string or array value. 18 | 19 | ```svelte 20 | 29 | 30 |
31 | 32 |
33 | ``` 34 | 35 | ## `enrich` 36 | 37 | The `enrich` object is used to pass methods to the Formula instance that allow the generation of computed values for 38 | current form values - these are added at the field level, and each field can have multiple. All the calculated values 39 | are available via the [enrichment store](stores/enrichment.mdx). 40 | 41 | ```svelte 42 | 53 | 54 |
55 | 56 | Length ${$enrichment?.content?.contentLength} 57 |
58 | ``` 59 | 60 | ## `messages` 61 | 62 | Used for localisation and custom messages, this is a `Object` containing a key that is the field `name` to apply the 63 | messages to. The value is another `Object` that contains the key for each error (e.g. `valueMissing`) and the value is 64 | the replacement string. 65 | 66 | ```svelte 67 | 68 | 79 | ``` 80 | 81 | ## `validators` 82 | 83 | An `Object` containing a key that is the field `name` to apply the validation to, the value is another object that 84 | contains each named validation function. The result are made available in the `validity` store. 85 | 86 | ```svelte 87 | 88 | 99 | ``` 100 | 101 | ## `formValidators` 102 | 103 | An `Object` containing a key that is the name of the validation rule, and the function that returns the validation 104 | result. The results are available in the `formValidity` store 105 | 106 | ```svelte 107 | 108 | 119 | 120 | 123 | ``` 124 | 125 | ## `preChanges` 126 | 127 | A `Function` that is called before any values are read from the DOM changes and the store updates. This can be used to 128 | carry out additional changes to the form. 129 | 130 | ```svelte 131 | 132 | 141 | 142 | 143 | ``` 144 | 145 | ## `postChanges` 146 | 147 | A `Function` that is called after all the values have been read and stores updated. This function receives the latest 148 | values and is functionaly the same as subscribing to the `form.formValues` store. 149 | 150 | ```svelte 151 | 152 | 159 | ``` 160 | -------------------------------------------------------------------------------- /packages/docs-site/docs/stores/dirty.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: stores-dirty 3 | 4 | title: dirty 5 | 6 | sidebar_label: dirty 7 | --- 8 | 9 | ## Description 10 | 11 | This store provides the dirty status of a field, or group of fields under a single `name` property. 12 | 13 | On form creation every form field is assigned a `blur` handler, and it reads the current value of the field. The dirty status for the group `name` is also set to `false`. 14 | 15 | When the user exits the field with a `blur` event the value is checked, and if changed the store is updated to reflect the `name` as `true`. 16 | All of the `blur` handlers for the group and then immediately removed, so this group will no longer update the status. 17 | 18 | ## Example 19 | 20 | ```svelte 21 | 25 |
26 | 27 | 28 | 29 |
30 | ``` 31 | -------------------------------------------------------------------------------- /packages/docs-site/docs/stores/enrichment.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: stores-enrichment 3 | 4 | title: enrichment 5 | 6 | sidebar_label: enrichment 7 | --- 8 | 9 | ## Description 10 | 11 | This store provides the results of any method passed to the `enrich` object for a group `name`. Each group contains a key and value based on the available methods. 12 | 13 | It emits on every value change, where the value group has available methods 14 | 15 | ## Example 16 | 17 | ```svelte 18 | 30 | 31 | 32 | 33 | 34 | ``` 35 | -------------------------------------------------------------------------------- /packages/docs-site/docs/stores/form-validity.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: stores-form-validity 3 | 4 | title: formValidity 5 | 6 | sidebar_label: formValidity 7 | --- 8 | 9 | ## Description 10 | 11 | This store provides the overall form status when using custom form validations, provided in the `formValidation` options object. If none are provided this store will not update. 12 | 13 | The store contains a `Object` that can contains the key of any validations that have failed, and a string value of the error message. 14 | 15 | Every time there is a value update the store is reset and any custom validations called, they should return `null` for a valid result, 16 | or a string for an invalid result, which can be used to display error messages. 17 | 18 | ## Example 19 | 20 | ```svelte 21 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 | ``` 38 | -------------------------------------------------------------------------------- /packages/docs-site/docs/stores/form-values.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: stores-form-values 3 | 4 | title: formValues 5 | 6 | sidebar_label: formValues 7 | --- 8 | 9 | ## Description 10 | 11 | This store contains all the current form values at the time any value changes on a bound element. The values are an `Object` with the 12 | key per group `name` and it's value. 13 | 14 | The value can be a single value, or an array or values depending on there being fields with the same `name` (e.g. multiple checkboxes), or a ` 30 | 31 | 32 | 33 |
{$formValues?.value1} + {$formValues?.value2} = {total}
34 | 35 | ``` 36 | -------------------------------------------------------------------------------- /packages/docs-site/docs/stores/initial-values.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: stores-initial-values 3 | 4 | title: initialValues 5 | 6 | sidebar_label: initialValues 7 | --- 8 | 9 | ## Description 10 | 11 | This store contains all the form values at the time the form was initialised - this may include `defaultValues` and any values 12 | bound on the form at configuration. This store will never change during the lifecycle of the form The values are an `Object` with the 13 | key per group `name` and it's value. 14 | 15 | The value can be a single value, or an array or values depending on there being fields with the same `name` (e.g. multiple checkboxes), or a ` 32 | 33 | 34 | 35 |
{$initialTotal?.value1} + {$initialTotal?.value2} = {initialTotal}
36 |
{$formValues?.value1} + {$formValues?.value2} = {total}
37 | 38 | 39 | 40 | ``` 41 | -------------------------------------------------------------------------------- /packages/docs-site/docs/stores/is-form-valid.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: stores-form-valid 3 | 4 | title: isFormValid 5 | 6 | sidebar_label: isFormValid 7 | --- 8 | 9 | ## Description 10 | 11 | This store emits a single boolean value any time the form validity changes. The state is checked on every value change, 12 | and if there are no invalid fields it's set to `true`, otherwise `false` (which is the default). 13 | 14 | ## Example 15 | 16 | ```svelte 17 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | ``` 30 | -------------------------------------------------------------------------------- /packages/docs-site/docs/stores/stores.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: stores 3 | 4 | title: Formula Stores 5 | 6 | sidebar_label: Formula Stores 7 | --- 8 | 9 | ## Accessing Stores 10 | 11 | Formula and Beaker provides a set of Svelte [stores](https://svelte.dev/docs#svelte_store) as part of each instance 12 | created. These stores provide different types of values at different lifecycles of your application. 13 | 14 | All the stores are listed in the sidebar. 15 | 16 | * When using Formula, the stores contain a single `Object` instance of the form 17 | * When using Beaker, the stores contain an `Array` of `Object` values for each row instance 18 | 19 | ```javascript 20 | const { form, enrichement, formValdity, formValues, isFormValid, submitValues, touched, validity } = formula(); 21 | ``` 22 | 23 | If you have multiple forms on the page you can also access stores via `form.stores` 24 | 25 | ```svelte 26 | 27 | 35 |
36 | 37 |
38 | 39 | ``` 40 | 41 | ## Global Store 42 | 43 | When attaching a form to an element, if you provide an `id` property the stores will be added to a global `Map` that can 44 | be accessed from anywhere else in your application from via `formulaStores` or `beakerStores` 45 | 46 | ```svelte 47 | 48 | 60 | 61 |
62 | 63 |
64 | ``` 65 | -------------------------------------------------------------------------------- /packages/docs-site/docs/stores/submit-values.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: stores-submit-values 3 | 4 | title: submitValues 5 | 6 | sidebar_label: submitValues 7 | --- 8 | 9 | ## Description 10 | 11 | This store contains all the form values at submit time, only if the bound element is a `form` element. The values are 12 | an `Object` with the key per group `name` and it's value. 13 | 14 | The value can be a single value, or an array or values depending on there being fields with the same `name` (e.g. 15 | multiple checkboxes), or a ` 34 | 35 | 36 | 37 |