diff --git a/.examples/_data/citiesByState.js b/.examples/_data/citiesByState.js new file mode 100644 index 00000000..55cb98c8 --- /dev/null +++ b/.examples/_data/citiesByState.js @@ -0,0 +1,630 @@ +export default [ + { + group: 'Alabama', + options: [ + { label: 'Birmingham', population: 209880, value: 'Birmingham, Alabama' }, + { label: 'Montgomery', population: 198218, value: 'Montgomery, Alabama' }, + { label: 'Mobile', population: 189572, value: 'Mobile, Alabama' }, + ], + }, + { + group: 'Alaska', + options: [ + { label: 'Anchorage', population: 291247, value: 'Anchorage, Alaska' }, + { label: 'Fairbanks', population: 31516, value: 'Fairbanks, Alaska' }, + { label: 'Juneau', population: 32113, value: 'Juneau, Alaska' }, + ], + }, + { + group: 'Arizona', + options: [ + { label: 'Phoenix', population: 1445632, value: 'Phoenix, Arizona' }, + { label: 'Tucson', population: 548073, value: 'Tucson, Arizona' }, + { label: 'Mesa', population: 518012, value: 'Mesa, Arizona' }, + ], + }, + { + group: 'Arkansas', + options: [ + { + label: 'Little Rock', + population: 197312, + value: 'Little Rock, Arkansas', + }, + { label: 'Fort Smith', population: 87818, value: 'Fort Smith, Arkansas' }, + { + label: 'Fayetteville', + population: 87016, + value: 'Fayetteville, Arkansas', + }, + ], + }, + { + group: 'California', + options: [ + { + label: 'Los Angeles', + population: 3976322, + value: 'Los Angeles, California', + }, + { + label: 'San Diego', + population: 1394928, + value: 'San Diego, California', + }, + { label: 'San Jose', population: 1026654, value: 'San Jose, California' }, + ], + }, + { + group: 'Colorado', + options: [ + { label: 'Denver', population: 693060, value: 'Denver, Colorado' }, + { + label: 'Colorado Springs', + population: 478221, + value: 'Colorado Springs, Colorado', + }, + { label: 'Aurora', population: 366623, value: 'Aurora, Colorado' }, + ], + }, + { + group: 'Connecticut', + options: [ + { + label: 'Bridgeport', + population: 148654, + value: 'Bridgeport, Connecticut', + }, + { + label: 'New Haven', + population: 130250, + value: 'New Haven, Connecticut', + }, + { label: 'Hartford', population: 123243, value: 'Hartford, Connecticut' }, + ], + }, + { + group: 'Delaware', + options: [ + { label: 'Wilmington', population: 70676, value: 'Wilmington, Delaware' }, + { label: 'Dover', population: 38458, value: 'Dover, Delaware' }, + { label: 'Newark', population: 33387, value: 'Newark, Delaware' }, + ], + }, + { + group: 'Florida', + options: [ + { + label: 'Jacksonville', + population: 892062, + value: 'Jacksonville, Florida', + }, + { label: 'Miami', population: 470914, value: 'Miami, Florida' }, + { label: 'Tampa', population: 399700, value: 'Tampa, Florida' }, + ], + }, + { + group: 'Georgia', + options: [ + { label: 'Atlanta', population: 498044, value: 'Atlanta, Georgia' }, + { label: 'Augusta', population: 197166, value: 'Augusta, Georgia' }, + { label: 'Columbus', population: 195769, value: 'Columbus, Georgia' }, + ], + }, + { + group: 'Hawaii', + options: [ + { label: 'Honolulu', population: 374658, value: 'Honolulu, Hawaii' }, + { + label: 'East Honolulu', + population: 49105, + value: 'East Honolulu, Hawaii', + }, + { label: 'Pearl City', population: 47698, value: 'Pearl City, Hawaii' }, + ], + }, + { + group: 'Idaho', + options: [ + { label: 'Boise', population: 228959, value: 'Boise, Idaho' }, + { label: 'Meridian', population: 106804, value: 'Meridian, Idaho' }, + { label: 'Nampa', population: 106475, value: 'Nampa, Idaho' }, + ], + }, + { + group: 'Illinois', + options: [ + { label: 'Chicago', population: 2705994, value: 'Chicago, Illinois' }, + { label: 'Aurora', population: 199602, value: 'Aurora, Illinois' }, + { label: 'Rockford', population: 147051, value: 'Rockford, Illinois' }, + ], + }, + { + group: 'Indiana', + options: [ + { + label: 'Indianapolis', + population: 867125, + value: 'Indianapolis, Indiana', + }, + { label: 'Fort Wayne', population: 270402, value: 'Fort Wayne, Indiana' }, + { label: 'Evansville', population: 118930, value: 'Evansville, Indiana' }, + ], + }, + { + group: 'Iowa', + options: [ + { label: 'Des Moines', population: 214778, value: 'Des Moines, Iowa' }, + { + label: 'Cedar Rapids', + population: 132228, + value: 'Cedar Rapids, Iowa', + }, + { label: 'Davenport', population: 101532, value: 'Davenport, Iowa' }, + ], + }, + { + group: 'Kansas', + options: [ + { label: 'Wichita', population: 389938, value: 'Wichita, Kansas' }, + { + label: 'Overland Park', + population: 195494, + value: 'Overland Park, Kansas', + }, + { + label: 'Kansas City', + population: 152960, + value: 'Kansas City, Kansas', + }, + ], + }, + { + group: 'Kentucky', + options: [ + { + label: 'Louisville', + population: 615366, + value: 'Louisville, Kentucky', + }, + { label: 'Lexington', population: 314488, value: 'Lexington, Kentucky' }, + { + label: 'Bowling Green', + population: 70846, + value: 'Bowling Green, Kentucky', + }, + ], + }, + { + group: 'Louisiana', + options: [ + { + label: 'New Orleans', + population: 393292, + value: 'New Orleans, Louisiana', + }, + { + label: 'Baton Rouge', + population: 227715, + value: 'Baton Rouge, Louisiana', + }, + { + label: 'Shreveport', + population: 194920, + value: 'Shreveport, Louisiana', + }, + ], + }, + { + group: 'Maine', + options: [ + { label: 'Portland', population: 66591, value: 'Portland, Maine' }, + { label: 'Lewiston', population: 36136, value: 'Lewiston, Maine' }, + { label: 'Bangor', population: 31666, value: 'Bangor, Maine' }, + ], + }, + { + group: 'Maryland', + options: [ + { label: 'Baltimore', population: 611648, value: 'Baltimore, Maryland' }, + { label: 'Columbia', population: 105162, value: 'Columbia, Maryland' }, + { label: 'Germantown', population: 90601, value: 'Germantown, Maryland' }, + ], + }, + { + group: 'Massachusetts', + options: [ + { label: 'Boston', population: 694583, value: 'Boston, Massachusetts' }, + { + label: 'Worcester', + population: 185877, + value: 'Worcester, Massachusetts', + }, + { + label: 'Springfield', + population: 154341, + value: 'Springfield, Massachusetts', + }, + ], + }, + { + group: 'Michigan', + options: [ + { label: 'Detroit', population: 673104, value: 'Detroit, Michigan' }, + { + label: 'Grand Rapids', + population: 200217, + value: 'Grand Rapids, Michigan', + }, + { label: 'Warren', population: 134587, value: 'Warren, Michigan' }, + ], + }, + { + group: 'Minnesota', + options: [ + { + label: 'Minneapolis', + population: 422331, + value: 'Minneapolis, Minnesota', + }, + { + label: 'Saint Paul', + population: 306621, + value: 'Saint Paul, Minnesota', + }, + { label: 'Rochester', population: 118935, value: 'Rochester, Minnesota' }, + ], + }, + { + group: 'Mississippi', + options: [ + { label: 'Jackson', population: 153701, value: 'Jackson, Mississippi' }, + { label: 'Gulfport', population: 71496, value: 'Gulfport, Mississippi' }, + { + label: 'Southaven', + population: 54418, + value: 'Southaven, Mississippi', + }, + ], + }, + { + group: 'Missouri', + options: [ + { + label: 'Kansas City', + population: 488943, + value: 'Kansas City, Missouri', + }, + { + label: 'Saint Louis', + population: 302838, + value: 'Saint Louis, Missouri', + }, + { + label: 'Springfield', + population: 167376, + value: 'Springfield, Missouri', + }, + ], + }, + { + group: 'Montana', + options: [ + { label: 'Billings', population: 110263, value: 'Billings, Montana' }, + { label: 'Missoula', population: 74727, value: 'Missoula, Montana' }, + { + label: 'Great Falls', + population: 58402, + value: 'Great Falls, Montana', + }, + ], + }, + { + group: 'Nebraska', + options: [ + { label: 'Omaha', population: 478192, value: 'Omaha, Nebraska' }, + { label: 'Lincoln', population: 287401, value: 'Lincoln, Nebraska' }, + { label: 'Bellevue', population: 54734, value: 'Bellevue, Nebraska' }, + ], + }, + { + group: 'Nevada', + options: [ + { label: 'Las Vegas', population: 635628, value: 'Las Vegas, Nevada' }, + { label: 'Henderson', population: 320189, value: 'Henderson, Nevada' }, + { label: 'Reno', population: 255601, value: 'Reno, Nevada' }, + ], + }, + { + group: 'New Hampshire', + options: [ + { + label: 'Manchester', + population: 112525, + value: 'Manchester, New Hampshire', + }, + { label: 'Nashua', population: 89536, value: 'Nashua, New Hampshire' }, + { label: 'Concord', population: 43172, value: 'Concord, New Hampshire' }, + ], + }, + { + group: 'New Jersey', + options: [ + { label: 'Newark', population: 282011, value: 'Newark, New Jersey' }, + { + label: 'Jersey City', + population: 265549, + value: 'Jersey City, New Jersey', + }, + { label: 'Paterson', population: 145948, value: 'Paterson, New Jersey' }, + ], + }, + { + group: 'New Mexico', + options: [ + { + label: 'Albuquerque', + population: 560218, + value: 'Albuquerque, New Mexico', + }, + { + label: 'Las Cruces', + population: 102512, + value: 'Las Cruces, New Mexico', + }, + { + label: 'Rio Rancho', + population: 99710, + value: 'Rio Rancho, New Mexico', + }, + ], + }, + { + group: 'New York', + options: [ + { + label: 'New York City', + population: 8175133, + value: 'New York City, New York', + }, + { label: 'Buffalo', population: 261310, value: 'Buffalo, New York' }, + { label: 'Rochester', population: 210565, value: 'Rochester, New York' }, + ], + }, + { + group: 'North Carolina', + options: [ + { + label: 'Charlotte', + population: 731424, + value: 'Charlotte, North Carolina', + }, + { + label: 'Raleigh', + population: 474069, + value: 'Raleigh, North Carolina', + }, + { + label: 'Greensboro', + population: 299035, + value: 'Greensboro, North Carolina', + }, + ], + }, + { + group: 'North Dakota', + options: [ + { label: 'Fargo', population: 113658, value: 'Fargo, North Dakota' }, + { label: 'Bismarck', population: 61272, value: 'Bismarck, North Dakota' }, + { + label: 'Grand Forks', + population: 56791, + value: 'Grand Forks, North Dakota', + }, + ], + }, + { + group: 'Ohio', + options: [ + { label: 'Columbus', population: 822553, value: 'Columbus, Ohio' }, + { label: 'Cleveland', population: 396815, value: 'Cleveland, Ohio' }, + { label: 'Cincinnati', population: 296943, value: 'Cincinnati, Ohio' }, + ], + }, + { + group: 'Oklahoma', + options: [ + { + label: 'Oklahoma City', + population: 649021, + value: 'Oklahoma City, Oklahoma', + }, + { label: 'Tulsa', population: 403505, value: 'Tulsa, Oklahoma' }, + { label: 'Norman', population: 110925, value: 'Norman, Oklahoma' }, + ], + }, + { + group: 'Oregon', + options: [ + { label: 'Portland', population: 647805, value: 'Portland, Oregon' }, + { label: 'Salem', population: 154637, value: 'Salem, Oregon' }, + { label: 'Eugene', population: 156185, value: 'Eugene, Oregon' }, + ], + }, + { + group: 'Pennsylvania', + options: [ + { + label: 'Philadelphia', + population: 1584138, + value: 'Philadelphia, Pennsylvania', + }, + { + label: 'Pittsburgh', + population: 303625, + value: 'Pittsburgh, Pennsylvania', + }, + { + label: 'Allentown', + population: 120207, + value: 'Allentown, Pennsylvania', + }, + ], + }, + { + group: 'Rhode Island', + options: [ + { + label: 'Providence', + population: 179883, + value: 'Providence, Rhode Island', + }, + { label: 'Warwick', population: 82039, value: 'Warwick, Rhode Island' }, + { label: 'Cranston', population: 80566, value: 'Cranston, Rhode Island' }, + ], + }, + { + group: 'South Carolina', + options: [ + { + label: 'Charleston', + population: 130113, + value: 'Charleston, South Carolina', + }, + { + label: 'Columbia', + population: 129272, + value: 'Columbia, South Carolina', + }, + { + label: 'North Charleston', + population: 115382, + value: 'North Charleston, South Carolina', + }, + ], + }, + { + group: 'South Dakota', + options: [ + { + label: 'Sioux Falls', + population: 153888, + value: 'Sioux Falls, South Dakota', + }, + { + label: 'Rapid City', + population: 69030, + value: 'Rapid City, South Dakota', + }, + { label: 'Aberdeen', population: 28489, value: 'Aberdeen, South Dakota' }, + ], + }, + { + group: 'Tennessee', + options: [ + { label: 'Nashville', population: 689447, value: 'Nashville, Tennessee' }, + { label: 'Memphis', population: 650618, value: 'Memphis, Tennessee' }, + { label: 'Knoxville', population: 186239, value: 'Knoxville, Tennessee' }, + ], + }, + { + group: 'Texas', + options: [ + { label: 'Houston', population: 2320268, value: 'Houston, Texas' }, + { + label: 'San Antonio', + population: 1547253, + value: 'San Antonio, Texas', + }, + { label: 'Dallas', population: 1317929, value: 'Dallas, Texas' }, + ], + }, + { + group: 'Utah', + options: [ + { + label: 'Salt Lake City', + population: 200567, + value: 'Salt Lake City, Utah', + }, + { + label: 'West Valley City', + population: 135248, + value: 'West Valley City, Utah', + }, + { label: 'Provo', population: 115264, value: 'Provo, Utah' }, + ], + }, + { + group: 'Vermont', + options: [ + { label: 'Burlington', population: 42284, value: 'Burlington, Vermont' }, + { + label: 'South Burlington', + population: 18998, + value: 'South Burlington, Vermont', + }, + { label: 'Essex', population: 21291, value: 'Essex, Vermont' }, + ], + }, + { + group: 'Virginia', + options: [ + { + label: 'Virginia Beach', + population: 450435, + value: 'Virginia Beach, Virginia', + }, + { label: 'Norfolk', population: 242742, value: 'Norfolk, Virginia' }, + { + label: 'Chesapeake', + population: 240397, + value: 'Chesapeake, Virginia', + }, + ], + }, + { + group: 'Washington', + options: [ + { label: 'Seattle', population: 744955, value: 'Seattle, Washington' }, + { label: 'Spokane', population: 219190, value: 'Spokane, Washington' }, + { label: 'Tacoma', population: 217827, value: 'Tacoma, Washington' }, + ], + }, + { + group: 'West Virginia', + options: [ + { + label: 'Charleston', + population: 51400, + value: 'Charleston, West Virginia', + }, + { + label: 'Huntington', + population: 46413, + value: 'Huntington, West Virginia', + }, + { + label: 'Morgantown', + population: 30505, + value: 'Morgantown, West Virginia', + }, + ], + }, + { + group: 'Wisconsin', + options: [ + { label: 'Milwaukee', population: 594833, value: 'Milwaukee, Wisconsin' }, + { label: 'Madison', population: 233209, value: 'Madison, Wisconsin' }, + { label: 'Green Bay', population: 104578, value: 'Green Bay, Wisconsin' }, + ], + }, + { + group: 'Wyoming', + options: [ + { label: 'Cheyenne', population: 59466, value: 'Cheyenne, Wyoming' }, + { label: 'Casper', population: 57913, value: 'Casper, Wyoming' }, + { label: 'Laramie', population: 32959, value: 'Laramie, Wyoming' }, + ], + }, +] diff --git a/.examples/autocomplete-pro/autocomplete-option-groups.vue b/.examples/autocomplete-pro/autocomplete-option-groups.vue new file mode 100644 index 00000000..e85eaa7b --- /dev/null +++ b/.examples/autocomplete-pro/autocomplete-option-groups.vue @@ -0,0 +1,20 @@ + + + + + diff --git a/.examples/colorpicker/alpha.vue b/.examples/colorpicker/alpha.vue new file mode 100644 index 00000000..059777cb --- /dev/null +++ b/.examples/colorpicker/alpha.vue @@ -0,0 +1,16 @@ + diff --git a/.examples/currency/currency-default.vue b/.examples/currency/currency-default.vue new file mode 100644 index 00000000..f960ada3 --- /dev/null +++ b/.examples/currency/currency-default.vue @@ -0,0 +1,21 @@ + + + diff --git a/.examples/currency/currency-props-explore.vue b/.examples/currency/currency-props-explore.vue new file mode 100644 index 00000000..02923306 --- /dev/null +++ b/.examples/currency/currency-props-explore.vue @@ -0,0 +1,28 @@ + + + diff --git a/.examples/currency/currency-simple-locale.vue b/.examples/currency/currency-simple-locale.vue new file mode 100644 index 00000000..15fecbe3 --- /dev/null +++ b/.examples/currency/currency-simple-locale.vue @@ -0,0 +1,47 @@ + + + diff --git a/.examples/dropdown/dropdown-option-groups.vue b/.examples/dropdown/dropdown-option-groups.vue new file mode 100644 index 00000000..0eee1743 --- /dev/null +++ b/.examples/dropdown/dropdown-option-groups.vue @@ -0,0 +1,20 @@ + + + + + diff --git a/.examples/taglist/taglist-option-groups.vue b/.examples/taglist/taglist-option-groups.vue new file mode 100644 index 00000000..fa9fd6c6 --- /dev/null +++ b/.examples/taglist/taglist-option-groups.vue @@ -0,0 +1,19 @@ + + + + + diff --git a/.examples/typebox/errors.vue b/.examples/typebox/errors.vue new file mode 100644 index 00000000..60dedcab --- /dev/null +++ b/.examples/typebox/errors.vue @@ -0,0 +1,50 @@ + + + diff --git a/.examples/typebox/importMap.json b/.examples/typebox/importMap.json new file mode 100644 index 00000000..04cf4d8a --- /dev/null +++ b/.examples/typebox/importMap.json @@ -0,0 +1,3 @@ +{ + "typebox": "https://cdn.jsdelivr.net/npm/@sinclair/typebox@0.32.30/build/cjs/index.min.js" +} diff --git a/.examples/typebox/validation.vue b/.examples/typebox/validation.vue new file mode 100644 index 00000000..2b8eea33 --- /dev/null +++ b/.examples/typebox/validation.vue @@ -0,0 +1,51 @@ + + + diff --git a/.examples/typebox/with-formkit-validation.vue b/.examples/typebox/with-formkit-validation.vue new file mode 100644 index 00000000..617817e6 --- /dev/null +++ b/.examples/typebox/with-formkit-validation.vue @@ -0,0 +1,63 @@ + + + diff --git a/.examples/unit/unit-default.vue b/.examples/unit/unit-default.vue new file mode 100644 index 00000000..bb1de13e --- /dev/null +++ b/.examples/unit/unit-default.vue @@ -0,0 +1,25 @@ + + + diff --git a/.examples/unit/unit-type-switcher.vue b/.examples/unit/unit-type-switcher.vue new file mode 100644 index 00000000..0286715e --- /dev/null +++ b/.examples/unit/unit-type-switcher.vue @@ -0,0 +1,38 @@ + + + diff --git a/api-reference/context.md b/api-reference/context.md index 255ab776..2fb1ea38 100644 --- a/api-reference/context.md +++ b/api-reference/context.md @@ -175,11 +175,26 @@ Current state of the input: * list, or form, this is true if any children have errors on them. */ errors: boolean + /** + * Determines if the input should be considered "invalid" β€” note that this + * is not the opposite of the valid state. A valid input is one where the + * input is not loading, not pending validation, not unsettled, and + * passes all validation rules. An invalid input is one whose validation + * rules are not explicitly not passing, and those rules are visible to the user. + */ + invalid: boolean | undefined /** * The loading state of the input or form. This property is only added while * the input is loading and is removed when loading is complete. */ loading: true | undefined + /** + * If the input is passing all validation rules. This state will remain + * in its current state until validation has completed, so if the input + * is not passing, and you have a long running validation rule this will + * remaining not passing until that rule has resolved. + */ + passing?: boolean /** * Indicates if the input is has the "required" validation rule. */ diff --git a/api-reference/formkit-typebox.md b/api-reference/formkit-typebox.md new file mode 100644 index 00000000..37d10ab9 --- /dev/null +++ b/api-reference/formkit-typebox.md @@ -0,0 +1,36 @@ +--- +title: formkit/typebox +--- + +# @formkit/typebox + + + +## Introduction + +The first-party typebox package/plugin for FormKit. Read the [documentation](https://formkit.com/essentials/typebox) for usage instructions. + +## Functions + +### createTypeboxPlugin() + +Creates a new Typebox schema plugin for form validation. + +#### Signature + + + +```typescript +createTypeboxPlugin(typeboxSchema: T, submitCallback: (payload: Static, node: FormKitNode | undefined) => void | Promise): [FormKitPlugin, (payload: any, node: FormKitNode | undefined) => void]; +``` + + + +#### Parameters + +- `typeboxSchema` β€” A Typebox schema to validate the form against. +- `submitCallback` β€” A callback to run when the form is submitted and it passes validation. + +#### Returns + + A tuple of a [FormKitPlugin](/api-reference/formkit-core#formkitplugin) and a submit handler. diff --git a/changelog-pro/63.v.0.122.17.md b/changelog-pro/63.v.0.122.17.md index 802dfd94..b779c62c 100644 --- a/changelog-pro/63.v.0.122.17.md +++ b/changelog-pro/63.v.0.122.17.md @@ -2,6 +2,6 @@ ### April 22, 2024 -### πŸ› Features +### πŸ’ͺ New Features - Makes `optionsLoader` function available as a prop for dropdown family inputs. \ No newline at end of file diff --git a/changelog-pro/68.v.0.123.0.md b/changelog-pro/68.v.0.123.0.md index 7c1bd9e8..ed04db22 100644 --- a/changelog-pro/68.v.0.123.0.md +++ b/changelog-pro/68.v.0.123.0.md @@ -2,9 +2,15 @@ ### April 25, 2024 -### ⚠️ Breaking Changes +::Callout +--- +type: "warning" +name: "Breaking Changes" +--- -- The rating input has been rewritten to be based on a radio group to provide better accessibility. While the API remains the same, be sure to update your theme at `themes.formkit.com`. +The rating input has been rewritten to be based on a radio group to provide better accessibility. While the API remains the same, be sure to update your theme at `themes.formkit.com`. + +:: ### πŸ’ͺ New Features diff --git a/changelog-pro/69.v.0.123.1.md b/changelog-pro/69.v.0.123.1.md new file mode 100644 index 00000000..11c23df5 --- /dev/null +++ b/changelog-pro/69.v.0.123.1.md @@ -0,0 +1,8 @@ +## 0.123.1 + +### April 25, 2024 + +### πŸ› Bug fixes + +- Fixes issue with `autocomplete` and `taglist` inputs where cloning during search prevented lookup of values with pojos. + diff --git a/changelog-pro/70.v.0.123.2.md b/changelog-pro/70.v.0.123.2.md new file mode 100644 index 00000000..14ee125a --- /dev/null +++ b/changelog-pro/70.v.0.123.2.md @@ -0,0 +1,7 @@ +## 0.123.2 + +### April 26, 2024 + +### πŸ› Bug fixes + +- Fixes issue [#1335](https://github.com/formkit/formkit/issues/1335) where the `options` prop typings for dropdown family inputs were incorrect. diff --git a/changelog-pro/71.v.0.123.3.md b/changelog-pro/71.v.0.123.3.md new file mode 100644 index 00000000..a91a05f9 --- /dev/null +++ b/changelog-pro/71.v.0.123.3.md @@ -0,0 +1,7 @@ +## 0.123.3 + +### April 26, 2024 + +### πŸ› Bug fixes + +- Fixes issue where filtering option groups were not being filtered down via search to individual listitem. diff --git a/changelog-pro/72.v.0.123.4.md b/changelog-pro/72.v.0.123.4.md new file mode 100644 index 00000000..9829a932 --- /dev/null +++ b/changelog-pro/72.v.0.123.4.md @@ -0,0 +1,7 @@ +## 0.123.4 + +### April 26, 2024 + +### πŸ› Bug fixes + +- Fixes issue where attempting to deselect a list item from the dropdown family inputs with a value of pojo was not working as expected. diff --git a/changelog-pro/73.v.0.123.5.md b/changelog-pro/73.v.0.123.5.md new file mode 100644 index 00000000..22beb265 --- /dev/null +++ b/changelog-pro/73.v.0.123.5.md @@ -0,0 +1,13 @@ +## 0.123.5 + +### April 26, 2024 + +### πŸ› Bug fixes + +- Fixes dropdown family issue where the loading state of all selections would end at the same time, even if their await times were different because the values were pojos. + +- Fixes dropdown family issue where value of pojo would sometimes cause issues with setting the active descendant. + +- Fixes dropdown family where active selection via. keyhandlers on taglist tags was not working properly. + +- Prevents focus state of tag via. keydown if text input is present. diff --git a/changelog-pro/74.v.0.123.6.md b/changelog-pro/74.v.0.123.6.md new file mode 100644 index 00000000..5d3d2566 --- /dev/null +++ b/changelog-pro/74.v.0.123.6.md @@ -0,0 +1,7 @@ +## 0.123.6 + +### April 27, 2024 + +### πŸ› Bug fixes + +- Fixes dropdown family issue where hydration mismatch occurs when loading option with value of pojo that can't be reduced to a string as temporary label. diff --git a/changelog-pro/75.v.0.124.0.md b/changelog-pro/75.v.0.124.0.md new file mode 100644 index 00000000..17e4d977 --- /dev/null +++ b/changelog-pro/75.v.0.124.0.md @@ -0,0 +1,7 @@ +## 0.124.0 + +### May 7, 2024 + +### πŸ’ͺ New features + +- Adds [`currency` input](/inputs/currency). diff --git a/changelog-pro/76.v.0.124.1.md b/changelog-pro/76.v.0.124.1.md new file mode 100644 index 00000000..a1d37b0e --- /dev/null +++ b/changelog-pro/76.v.0.124.1.md @@ -0,0 +1,7 @@ +## 0.124.1 + +### May 7, 2024 + +### πŸ› Bug fixes + +- Fixes max recursion bug in `currency` input in Safari. diff --git a/changelog-pro/77.v.0.124.2.md b/changelog-pro/77.v.0.124.2.md new file mode 100644 index 00000000..2f073a9e --- /dev/null +++ b/changelog-pro/77.v.0.124.2.md @@ -0,0 +1,7 @@ +## 0.124.2 + +### May 7, 2024 + +### πŸ› Bug fixes + +- Removes type `tel` from `currency` input. Now uses attr `inputmode` instead. diff --git a/changelog-pro/78.v.0.125.0.md b/changelog-pro/78.v.0.125.0.md new file mode 100644 index 00000000..9df7f2af --- /dev/null +++ b/changelog-pro/78.v.0.125.0.md @@ -0,0 +1,7 @@ +## 0.125.0 + +### May 8, 2024 + +### πŸ› Bug fixes + +- Fixes issue preventing tree shaking of FormKit Pro inputs. diff --git a/changelog-pro/79.v.0.125.1.md b/changelog-pro/79.v.0.125.1.md new file mode 100644 index 00000000..3bf4f57c --- /dev/null +++ b/changelog-pro/79.v.0.125.1.md @@ -0,0 +1,8 @@ +## 0.125.1 + +### May 9, 2024 + +### πŸ› Bug fixes + +- Fixes issues with dropdown family inputs introduced by 0.125.0 [#1346](https://github.com/formkit/formkit/issues/1346) and +[#1345](https://github.com/formkit/formkit/issues/1345) diff --git a/changelog-pro/80.v.0.125.2.md b/changelog-pro/80.v.0.125.2.md new file mode 100644 index 00000000..a8a9bee1 --- /dev/null +++ b/changelog-pro/80.v.0.125.2.md @@ -0,0 +1,7 @@ +## 0.125.2 + +### May 9, 2024 + +### πŸ› Bug fixes + +- Fixes issue where Slider input `min` and `max` values were not being applied reactively to associated inputs when `show-inputs` prop was enabled. [#1341](https://github.com/formkit/formkit/issues/1341) diff --git a/changelog-pro/81.v.0.125.3.md b/changelog-pro/81.v.0.125.3.md new file mode 100644 index 00000000..05c80485 --- /dev/null +++ b/changelog-pro/81.v.0.125.3.md @@ -0,0 +1,7 @@ +## 0.125.3 + +### May 10, 2024 + +### πŸ› Bug fixes + +- Fixes issue where Slider number inputs were unable to accept decimal input. [#1341](https://github.com/formkit/formkit/issues/1341) diff --git a/changelog-pro/82.v.0.125.4.md b/changelog-pro/82.v.0.125.4.md new file mode 100644 index 00000000..e7f920d8 --- /dev/null +++ b/changelog-pro/82.v.0.125.4.md @@ -0,0 +1,7 @@ +## 0.125.4 + +### May 10, 2024 + +### πŸ› Bug fixes + +- Fixes issue where `currency` input when using either the `max` or `min` prop did not allow the use of decimal points [#1344](https://github.com/formkit/formkit/issues/1344). diff --git a/changelog-pro/83.v.0.125.5.md b/changelog-pro/83.v.0.125.5.md new file mode 100644 index 00000000..1c9a28ff --- /dev/null +++ b/changelog-pro/83.v.0.125.5.md @@ -0,0 +1,13 @@ +## 0.125.5 + +### May 14, 2024 + +### πŸ’ͺ New Features + +- The `colorpicker` input now has an `alpha` prop which allows users to disable the alpha channel in the color picker [#1302](https://github.com/formkit/formkit/issues/1302) + +### πŸ› Bug fixes + +- Fixes issue where `dropdown` family inputs' listbox position would be incorrect when opened, inverted, and filtered while in `popover` mode. [#1310](https://github.com/formkit/formkit/issues/1310) +- Fixes issue where `dropdown` family inputs could trigger a javascript error due to having `id` attributes that were valid yet incompatible with `querySelector` syntax. [#1313](https://github.com/formkit/formkit/issues/1313) +- Fixes issue where linked inputs for the `slider` would not have reactive `min` and `max` properties. [#1341](https://github.com/formkit/formkit/issues/1341) diff --git a/changelog-pro/84.v.0.125.6.md b/changelog-pro/84.v.0.125.6.md new file mode 100644 index 00000000..6ad2dbff --- /dev/null +++ b/changelog-pro/84.v.0.125.6.md @@ -0,0 +1,7 @@ +## 0.125.5 + +### May 14, 2024 + +### πŸ› Bug fixes + +- Fixes issue where schema sections in Pro inputs with existing `meta` keys were not being assigned programmatic `meta` values. This was preventing the `eachSection` helper function from being able access some sections β€” which in turn was preventing the AutoAnimate plugin from being able to be applied to repeater items. Whew... this one was a doozy. πŸ˜… \ No newline at end of file diff --git a/changelog-pro/85.v.0.125.7.md b/changelog-pro/85.v.0.125.7.md new file mode 100644 index 00000000..518f85cc --- /dev/null +++ b/changelog-pro/85.v.0.125.7.md @@ -0,0 +1,7 @@ +## 0.125.7 + +### May 14, 2024 + +### πŸ› Bug fixes + +- Fixes issue where auto-animate plugin would conflict with drag and drop animations on repeater input. \ No newline at end of file diff --git a/changelog/32.v1.6.2.md b/changelog/32.v1.6.2.md deleted file mode 100644 index 198eb653..00000000 --- a/changelog/32.v1.6.2.md +++ /dev/null @@ -1,9 +0,0 @@ -## 1.6.2 - -### April 8, 2024 - -### πŸ› Bug fixes - -- Widens unocss compatibility for the `@formkit/themes` package ([#1281](https://github.com/formkit/formkit/issues/1281)). -- Small German translation fix ([#1293](https://github.com/formkit/formkit/issues/1293)). -- Adds additional dependencies to the `create-app` cli command ([#1233](https://github.com/formkit/formkit/issues/1233)). \ No newline at end of file diff --git a/changelog/33.v1.6.2.md b/changelog/33.v1.6.2.md new file mode 100644 index 00000000..479e1ca2 --- /dev/null +++ b/changelog/33.v1.6.2.md @@ -0,0 +1,12 @@ +## 1.6.3 + +### May 14, 2024 + +### πŸ’ͺ New Features +- New clear on submit option for local storage +- New `context.state.passing` property indicates whether or not a given input is passing all its validation rules. + +### πŸ› Bug fixes +- Fixes auto animate plugin for FormKit components ([#1354](https://github.com/formkit/formkit/issues/1354)). +- On multi-step inputs `beforeStepChange` is no longer called when the step cannot be advanced ([#1191](https://github.com/formkit/formkit/issues/1191)). +- Quickly typing into an input no longer causes an invalid state flicker ([#1324](https://github.com/formkit/formkit/issues/1324)). \ No newline at end of file diff --git a/essentials/examples.md b/essentials/examples.md index 67cb3923..3108381a 100644 --- a/essentials/examples.md +++ b/essentials/examples.md @@ -145,14 +145,6 @@ title: "Number input with custom step buttons" A custom input with +1 and -1 step buttons. Made using createInput(). :: -::ExampleCard ---- -href: "https://formkit.link/68e51abc7431687edc8f9ff008477b3d" -title: "A currency input with currency selector" ---- -A simple custom input that allows users to select a currency and enter a value. Made using createInput(). -:: - ::ExampleCard --- href: "https://formkit.link/de8e6530b80717f5229813258e739e7b" diff --git a/getting-started/community.md b/getting-started/community.md index 4f31b57b..5194bd87 100644 --- a/getting-started/community.md +++ b/getting-started/community.md @@ -39,25 +39,7 @@ Community involvement and contributions are one of the most important aspects of /> -### Silver sponsors - - - Peak Crypto logo - - - - SurveyJS logo - + ### Bronze sponsors @@ -79,6 +61,15 @@ Community involvement and contributions are one of the most important aspects of /> + + Wedgworth's Inc logo + + ### Backers [uscreen](https://uscreen.de), [gfenn08](https://github.com/gfenn08), [Ryan E](https://github.com/VikingDadMedic), [JoΓ£o Bondim](https://github.com/JesterIruka) diff --git a/inputs/autocomplete.md b/inputs/autocomplete.md index 771c9365..57616adb 100644 --- a/inputs/autocomplete.md +++ b/inputs/autocomplete.md @@ -353,6 +353,21 @@ file: [ --- :: +## Option groups + +If you would like the listitems in the listbox to be grouped, pass the `options` prop an array of objects and include the property `group`: + +::Example +--- +name: "Autocomplete" +min-height: 550 +file: [ + "_content/_examples/autocomplete-pro/autocomplete-option-groups.vue", + "_content/_examples/_data/citiesByState.js" +] +--- +:: + ## Full example @@ -838,14 +853,12 @@ schema: [ --- :: -### Inner listbox structure - -Below is the inner options list (`listbox`) structure from the diagrams above: +### Listbox structure ::FormKitInputDiagram --- hide-on-small: true -class: "input-diagram--autocomplete" +class: "input-diagram--dropdown" schema: [ { name: "dropdownWrapper", @@ -865,20 +878,108 @@ schema: [ ] }, { - name: "listitem", - class: "flex flex-grow", - position: "right", + name: "listitems", + children: [{ + name: 'listitem', + class: "flex flex-grow", + position: "right", + children: [ + { + name: "selectedIcon", + content: "βœ”οΈ" + }, + { + name: "option", + content: "Gray", + position: "right", + class: "flex flex-grow" + }, + ] + }] + }, + { + name: "loadMore", children: [ { - name: "selectedIcon", - content: "βœ”οΈ" + name: "loadMoreInner", + children: [ + { + name: "loaderIcon", + content: "⏳", + class: "text-center" + } + ] }, + ] + }, + ] + }, + ] + } +] +--- +:: + +### Grouped Listbox Structure + +::FormKitInputDiagram +--- +hide-on-small: true +class: "input-diagram--dropdown" +schema: [ + { + name: "dropdownWrapper", + position: "right", + children: [ + { + name: "listbox", + position: "right", + children: [ + { + name: "emptyMessage", + children: [ { - name: "option", - content: "Serena", - position: "right", - class: "flex flex-grow" - }, + name: "emptyMessageInner", + content: "No options to display.", + } + ] + }, + { + name: "listitems", + children: [ + { + name: 'listitemGroup', + children: [ + { + name: 'groupLabel' + }, + { + name: 'groupList', + children: [ + { + name: 'innerListitems', + children: [{ + name: 'listitem', + class: "flex flex-grow", + position: "right", + children: [ + { + name: "selectedIcon", + content: "βœ”οΈ" + }, + { + name: "option", + content: "Gray", + position: "right", + class: "flex flex-grow" + }, + ] + }] + } + ] + } + ] + } ] }, { diff --git a/inputs/colorpicker.md b/inputs/colorpicker.md index 92e06939..4805ef12 100644 --- a/inputs/colorpicker.md +++ b/inputs/colorpicker.md @@ -51,6 +51,18 @@ There may be times where you wish to show one format to users as a default but r --- :: +### Disabling the alpha channel + +You can disable the alpha channel in the `colorpicker` by setting the `alpha` prop to `false`. This will enforce full opacity on values. Any values with an alpha channel will be converted to full opacity. + +::Example +--- + name: "Color input" + file: "_content/_examples/colorpicker/alpha.vue" + minHeight: 400 +--- +:: + ## Swatches Swatches are provided using the `options` prop and use the same `options` API as the `select`, `dropdown`, `autocomplete` and `taglist` inputs from FormKit. @@ -138,6 +150,12 @@ data: [ default: "hex", description: "The format that the colorpicker input should show in the input preview and be the default setting for the picker panel input. Can be set to hex, hsla or rgba.", }, + { + prop: "alpha", + type: "boolean", + default: "true", + description: "When set to false the alpha channel will be disabled in the color picker.", + }, { prop: "value-format", type: "string", diff --git a/inputs/currency.md b/inputs/currency.md new file mode 100644 index 00000000..c9011c33 --- /dev/null +++ b/inputs/currency.md @@ -0,0 +1,155 @@ +--- +title: Currency +description: The currency input is used to create locale/currency specific parsed content +--- + +::InputPageHero +--- +type: "Currency" +--- +:: + +:PageToc + +:ProInstallSnippet + +## Basic example + +The `currency` input allows for restricted input of values based on the provided currency and locale. + +::Example +--- +name: "Currency input defaults" +file: "_content/_examples/currency/currency-default.vue" +--- +:: + +## Props + +### Currency + +The `currency` prop is the three letter currency code and sets the proper formatting for the specified currency. For a full list of supported currency types check: https://en.wikipedia.org/wiki/ISO_4217#List_of_ISO_4217_currency_codes + +### Locale + +By default, the locale used will be that of what is set in your `formkit.config.ts`. This can be overriden with the `display-locale` prop. For example, `en`, `de`, `en-IN`, `zh-CN`, etc, etc. + + +::Example +--- +name: "Currency and Locale settings" +file: "_content/_examples/currency/currency-simple-locale.vue" +--- +:: + +## Currency Additional Props + +### Decimals + +If you would like to prevent decimals from being displayed, set `decimals` to `false` or `0`. + +You can also choose to set a minimum number of decimals with the `min-decimals` prop. For example, setting the prop `min-decimals="2"` will always show 2 decimal points. + +### Minimum and Maximum Values + +Setting the props `min` or `max` will prevent entry of a higher or lower value. + +### Step + +Value scan be incremented and decremented by use of the up/down keys. The degree by which the value changes is determined by the `step` prop. + +::Example +--- +name: "Currecy Prop Exploration" +file: "_content/_examples/currency/currency-props-explore.vue" +--- +:: + +## Props & Attributes + +::ReferenceTable +--- +input: "currency" +data: [ + { + prop: "currency", + type: "string", + default: "USD", + description: "Set the specified currency to use for this input" + }, + { + prop: "displayLocale", + type: "string", + default: "en-US", + description: "Set the desired display locale to use for this input" + }, + { + prop: "decimals", + type: "boolean|number", + default: "null", + description: "Choose to either completely disallow decimals or override the maximum number of decimals for the input" + }, + { + prop: "minDecimals", + type: "number", + default: "null", + description: "Choose to show a minimum number of decimals should your input require this" + }, + { + prop: "min", + type: "number", + default: "null", + description: "Minimum numeric value allowed. If zero or above, negatives will not be allowed" + }, + { + prop: "max", + type: "number", + default: "null", + description: "Maximum numeric value allowed for this input" + }, + { + prop: "step", + type: "number", + default: "1", + description: "When using the up/down keys, how much to modify the current value." + }, + { + prop: "valueFormat", + type: "string", + default: "number", + description: "Choose between number and string whether you want a numeric value or a parsed string value" + }, +] +--- +:: + + +## Sections + +:SectionKeysIntro + +### Currency input diagram + +::FormKitInputDiagram +--- +prefix-icon-content: "" +suffix-icon-content: "" +label-content: "Currency Input" +input-content: "$1,234.56" +help-content: "How much do you want to donate?" +message-content: "That's a lot of money" +--- +:: +### Keyboard Interactions + +::KeyboardEventsTable +--- +data: [ + { + event: ["up", "down"], + separator: '', + description: "Increments through input value by current step amount.", + }, +] +--- +:: \ No newline at end of file diff --git a/inputs/dropdown.md b/inputs/dropdown.md index 53a92ea5..ebc026f2 100644 --- a/inputs/dropdown.md +++ b/inputs/dropdown.md @@ -306,6 +306,22 @@ file: [ --- :: +## Option groups + +If you would like the listitems in the listbox to be grouped, pass the `options` prop an array of objects and include the property `group`: + +::Example +--- +name: "Dropdown" +min-height: 550 +file: [ + "_content/_examples/dropdown/dropdown-option-groups.vue", + "_content/_examples/_data/citiesByState.js" +] +--- +:: + + ## Props & Attributes ::ReferenceTable @@ -538,20 +554,108 @@ schema: [ ] }, { - name: "listitem", - class: "flex flex-grow", - position: "right", + name: "listitems", + children: [{ + name: 'listitem', + class: "flex flex-grow", + position: "right", + children: [ + { + name: "selectedIcon", + content: "βœ”οΈ" + }, + { + name: "option", + content: "Gray", + position: "right", + class: "flex flex-grow" + }, + ] + }] + }, + { + name: "loadMore", children: [ { - name: "selectedIcon", - content: "βœ”οΈ" + name: "loadMoreInner", + children: [ + { + name: "loaderIcon", + content: "⏳", + class: "text-center" + } + ] }, + ] + }, + ] + }, + ] + } +] +--- +:: + +### Grouped Listbox Structure + +::FormKitInputDiagram +--- +hide-on-small: true +class: "input-diagram--dropdown" +schema: [ + { + name: "dropdownWrapper", + position: "right", + children: [ + { + name: "listbox", + position: "right", + children: [ + { + name: "emptyMessage", + children: [ { - name: "option", - content: "Gray", - position: "right", - class: "flex flex-grow" - }, + name: "emptyMessageInner", + content: "No options to display.", + } + ] + }, + { + name: "listitems", + children: [ + { + name: 'listitemGroup', + children: [ + { + name: 'groupLabel' + }, + { + name: 'groupList', + children: [ + { + name: 'innerListitems', + children: [{ + name: 'listitem', + class: "flex flex-grow", + position: "right", + children: [ + { + name: "selectedIcon", + content: "βœ”οΈ" + }, + { + name: "option", + content: "Gray", + position: "right", + class: "flex flex-grow" + }, + ] + }] + } + ] + } + ] + } ] }, { diff --git a/inputs/mask.md b/inputs/mask.md index 71fbee8b..fa1c433c 100644 --- a/inputs/mask.md +++ b/inputs/mask.md @@ -319,24 +319,6 @@ label: "Values can't match the mask" Your prefix and suffix content can't match the mask. For instance, if your mask has a digit token #, your prefix/suffix can't contain numbers. :: -## Running the mask in reverse - -In specific circumstances, you may want to run your mask in reverse. The mask will test if user input fulfills the mask from right to left. This is common in currency-type inputs and can be applied by adding the `reverse` prop: - -::Example ---- -name: "Mask input" -file: "_content/_examples/mask/reverse.vue" ---- -:: - -::Callout ---- -type: "warning" -label: "Shift mode requirement" ---- -Running a mask in reverse only works in shift mode. -:: ## Mask values diff --git a/inputs/taglist.md b/inputs/taglist.md index 1aa4afda..9cb4df61 100644 --- a/inputs/taglist.md +++ b/inputs/taglist.md @@ -266,6 +266,22 @@ file: [ --- :: +## Option groups + +If you would like the listitems in the listbox to be grouped, pass the `options` prop an array of objects and include the property `group`: + +::Example +--- +name: "Taglist" +min-height: 550 +file: [ + "_content/_examples/taglist/taglist-option-groups.vue", + "_content/_examples/_data/citiesByState.js" +] +--- +:: + + ## Full example @@ -469,6 +485,229 @@ data: [ --- :: +## Sections + +:SectionKeysIntro + +### Listbox structure + +::FormKitInputDiagram +--- +hide-on-small: true +class: "input-diagram--dropdown" +schema: [ + { + name: "dropdownWrapper", + position: "right", + children: [ + { + name: "listbox", + position: "right", + children: [ + { + name: "emptyMessage", + children: [ + { + name: "emptyMessageInner", + content: "No options to display.", + } + ] + }, + { + name: "listitems", + children: [{ + name: 'listitem', + class: "flex flex-grow", + position: "right", + children: [ + { + name: "selectedIcon", + content: "βœ”οΈ" + }, + { + name: "option", + content: "Gray", + position: "right", + class: "flex flex-grow" + }, + ] + }] + }, + { + name: "loadMore", + children: [ + { + name: "loadMoreInner", + children: [ + { + name: "loaderIcon", + content: "⏳", + class: "text-center" + } + ] + }, + ] + }, + ] + }, + ] + } +] +--- +:: + +### Grouped Listbox Structure + +::FormKitInputDiagram +--- +hide-on-small: true +class: "input-diagram--dropdown" +schema: [ + { + name: "dropdownWrapper", + position: "right", + children: [ + { + name: "listbox", + position: "right", + children: [ + { + name: "emptyMessage", + children: [ + { + name: "emptyMessageInner", + content: "No options to display.", + } + ] + }, + { + name: "listitems", + children: [ + { + name: 'listitemGroup', + children: [ + { + name: 'groupLabel' + }, + { + name: 'groupList', + children: [ + { + name: 'innerListitems', + children: [{ + name: 'listitem', + class: "flex flex-grow", + position: "right", + children: [ + { + name: "selectedIcon", + content: "βœ”οΈ" + }, + { + name: "option", + content: "Gray", + position: "right", + class: "flex flex-grow" + }, + ] + }] + } + ] + } + ] + } + ] + }, + { + name: "loadMore", + children: [ + { + name: "loadMoreInner", + children: [ + { + name: "loaderIcon", + content: "⏳", + class: "text-center" + } + ] + }, + ] + }, + ] + }, + ] + } +] +--- +:: + +#### Taglist selections + +::FormKitInputDiagram +--- +hide-on-small: true +class: "input-diagram--dropdown-outer" +schema: [ + { + name: "selector", + class: "flex flex-grow", + children: [ + { + name: "tagsWrapper", + class: "flex flex-grow", + children: [ + { + name: "tags", + class: "flex flex-grow border-solid", + children: [ + { + name: "tagWrapper", + children: [ + { + name: "tag", + class: 'flex', + children: [ + { + name: "tagLabel", + content: 'Gray' + }, + { + name: "removeSelection", + content: 'Γ—' + } + ] + }, + ] + }, + { + name: "tagWrapper", + children: [ + { + name: "tag", + class: 'flex', + children: [ + { + name: "tagLabel", + content: 'Blue' + }, + { + name: "removeSelection", + content: 'Γ—' + } + ] + }, + ] + } + ], + }, + ] + }, + ] + } +] +--- +:: + ## Accessibility All FormKit inputs are designed with the following accessibility considerations in mind. Help us continually improve accessibility for all by filing accessibility issues [here](https://github.com/formkit/formkit/issues/new?assignees=&labels=%F0%9F%90%9B+bug-report%2C%E2%9B%91+Needs+triage&projects=&template=bug-report.yml): diff --git a/plugins/typebox.md b/plugins/typebox.md new file mode 100644 index 00000000..5f159236 --- /dev/null +++ b/plugins/typebox.md @@ -0,0 +1,88 @@ +--- +title: Typebox Plugin +description: Use your Typebox schema to validate your FormKit forms. +--- + +# Typebox Plugin + +:PageToc + +With the `@formkit/typebox` package you can easily enable validation of your FormKit forms with your Typebox schema. This provides a convenient way to have isomorphic types and ensure that your front-end and back-end are using the same validation rules. + +When validating against a Typebox schema all validation errors will be mapped to their corresponding inputs, show or hide based on your form / input's `validation-visibility` prop, and prevent submission when form data does not pass validation with Typebox. + +## Installation + +To use this plugin with FormKit, install `@formkit/typebox`: + +```bash +yarn add @formkit/typebox +``` + +Once you've installed the `@formkit/typebox` package, you'll need to register the plugin on a per-form basis and each form that requires validation with a Typebox schema will create a new instance of the plugin using the `createTypeboxPlugin` function. + +## Usage + +To use the Typebox plugin we need to import the `createTypeboxPlugin` function from `@formkit/typebox`, call the `createTypeboxPlugin` function to create receive our `typeboxPlugin` and `submitHandler`, and then add them both to our FormKit form. + +The `createTypeboxPlugin` function takes two arguments: + +- `typeboxSchema`: The Typebox schema that you would like to use to validate against the form. +- `submitCallback`: a function you would like to run once validation has succeeded on your form β€”Β this is where you would handle posting your data to your backend or other submit-related tasks. You form data will be provided with full TypeScript support based on your Typebox schema. + +The `createTypeboxPlugin` will return a tuple of: + +- `typeboxPlugin`: The plugin that should be applied to your target form's `plugins` prop. +- `submitHandler`: The submit handler that should be attached to your form's `@submit` action. When the form data passes validation of your provided Typebox schema your `submitCallback` will fire. + +### For form validation + +Here is an example of using a Typebox schema to validate a FormKit form. It's important that your FormKit input `name`s match the expected values for your Typebox schema. + +::Example +--- +name: 'Typebox Validation' +file: [ +'/\_content/_examples/typebox/validation.vue', +] +import-map: '/\_content/_examples/typebox/importMap.json' +--- +:: + +Now your FormKit form will use your Typebox Schema for validation β€”Β and all messages will adjacent to each matching FormKit just live native FormKit validation! + +### In addition to FormKit validation + +Using Typebox to validate your form doesn't mean you have to forgo using FormKit's built-in validation messages. If you add FormKit validation to your FormKit inputs then Typebox validation errors will only show if all FormKit validations have been satisfied and there are remaining unsatisfied Typebox validations. + +This has a few benefits: + +- You can use FormKit's built-in rules such as `confirm` which don't have easy-to-use equivalents within Typebox. +- Your messages can be translated to one of the many existing languges in `@formkit/i18n` without any additional effort on your part. +- The built-in FormKit validation messages are written to be contextually aware of your input names and knowing that they will be attached directly to their corresponding inputs β€” so they are more precise and easier to understand than their generic Typebox counterparts. + +Here's the same form as before, but now using FormKit validation messages in addition to Typebox schema validation. + +::Example +--- +name: 'Typebox Validation with FormKit Validation' +file: [ +'/\_content/_examples/typebox/with-formkit-validation.vue', +] +import-map: '/\_content/_examples/typebox/importMap.json' +--- +:: + +### For setting form errors + +If you need to set errors on your form you can do so with the `node.setTypeboxErrors` function that is made available by the `typeboxPlugin`. The `node.setTypeboxErrors` function accepts a Typebox `ValueErrorIterator` and will map the errors to each input. Any non-matching errors will be shown as form-level errors. + +::Example +--- +name: 'Typebox Errors' +file: [ +'/\_content/_examples/typebox/errors.vue', +] +import-map: '/\_content/_examples/typebox/importMap.json' +--- +::