@featherk/ui 0.9.4 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -62
- package/dist/featherk-ui.es.js +1 -0
- package/dist/featherk-ui.es.js.map +1 -0
- package/dist/featherk-ui.umd.js +1 -0
- package/dist/featherk-ui.umd.js.map +1 -0
- package/docs/address/USAddress.md +31 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Vue UI component package for FeatherK.
|
|
|
5
5
|
## Components Overview
|
|
6
6
|
|
|
7
7
|
- **Address**: `USAddress` - Presentational US address renderer driven by a parent-owned `useUSAddress` view model.
|
|
8
|
-
|
|
8
|
+
- Component guide: [docs/address/USAddress.md](./docs/address/USAddress.md)
|
|
9
9
|
|
|
10
10
|
## Importing Components
|
|
11
11
|
|
|
@@ -14,73 +14,17 @@ import { USAddress } from "@featherk/ui";
|
|
|
14
14
|
import { useUSAddress } from "@featherk/composables/address";
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Component styles ship with `@featherk/ui` and are automatically loaded from the package ESM entry.
|
|
20
|
-
|
|
21
|
-
```vue
|
|
22
|
-
<script setup lang="ts">
|
|
23
|
-
import { ref, toRef } from "vue";
|
|
24
|
-
import { USAddress } from "@featherk/ui";
|
|
25
|
-
import { useUSAddress } from "@featherk/composables/address";
|
|
26
|
-
|
|
27
|
-
const billingFieldsetRef = ref<HTMLFieldSetElement | null>(null);
|
|
28
|
-
const isAddressRequired = ref(true);
|
|
29
|
-
|
|
30
|
-
const billingAddress = useUSAddress({
|
|
31
|
-
fieldsetRef: toRef(() => billingFieldsetRef.value),
|
|
32
|
-
addressId: "billing-address",
|
|
33
|
-
required: toRef(() => isAddressRequired.value),
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const onFieldsetFocusout = (event: FocusEvent) => {
|
|
37
|
-
billingAddress.onFieldsetFocusout(event);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
function onReset() {
|
|
41
|
-
billingAddress.reset();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async function onSubmit() {
|
|
45
|
-
const result = await billingAddress.validateForSubmit();
|
|
46
|
-
if (!result.isValid) return;
|
|
47
|
-
|
|
48
|
-
console.log(result.payload);
|
|
49
|
-
}
|
|
50
|
-
</script>
|
|
51
|
-
|
|
52
|
-
<template>
|
|
53
|
-
<form @submit.prevent="onSubmit">
|
|
54
|
-
<fieldset ref="billingFieldsetRef" @focusout="onFieldsetFocusout">
|
|
55
|
-
<USAddress
|
|
56
|
-
id="billing-address"
|
|
57
|
-
:address="billingAddress"
|
|
58
|
-
:required="isAddressRequired"
|
|
59
|
-
/>
|
|
60
|
-
|
|
61
|
-
<label for="billing-attn">Attention</label>
|
|
62
|
-
<input id="billing-attn" type="text" />
|
|
63
|
-
</fieldset>
|
|
64
|
-
|
|
65
|
-
<button type="submit">Submit</button>
|
|
66
|
-
<button type="button" @click="onReset">Reset</button>
|
|
67
|
-
</form>
|
|
68
|
-
</template>
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
`USAddress` is presentational. Parent components own composable orchestration.
|
|
72
|
-
|
|
73
|
-
Required prop:
|
|
74
|
-
- `address`: pass the object returned by `useUSAddress(...)`.
|
|
75
|
-
|
|
76
|
-
Submission ownership:
|
|
77
|
-
- Parent form components own submission orchestration, reset behavior, and payload handling.
|
|
17
|
+
For complete setup, behavior, and examples, use the component guide listed in Components Overview.
|
|
78
18
|
|
|
79
19
|
## Peer Dependencies
|
|
80
20
|
|
|
81
21
|
- Required: `vue`
|
|
82
22
|
- Required for `USAddress`: `@progress/kendo-vue-buttons`, `@progress/kendo-vue-dropdowns`, `@progress/kendo-vue-inputs`, `@progress/kendo-vue-labels`
|
|
83
23
|
|
|
24
|
+
## Styling
|
|
25
|
+
|
|
26
|
+
Component styles ship with `@featherk/ui` and are automatically loaded from the package ESM entry.
|
|
27
|
+
|
|
84
28
|
## Build
|
|
85
29
|
|
|
86
30
|
Run from repository root:
|
package/dist/featherk-ui.es.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"featherk-ui.es.js","sources":["../src/address/USAddress.vue"],"sourcesContent":["<template>\n <div\n class=\"fkui-us-address\"\n :class=\"{ 'fkui-us-address--fieldset-scope': fieldsetScope }\"\n >\n <div class=\"address1\">\n <TextBox\n :id=\"fieldIds.address1\"\n :placeholder=\"address1Placeholder\"\n :value=\"address.formData.address1\"\n :valid=\"isRequired ? address.address1Valid.value : true\"\n :validate=\"isRequired ? address.addressValidate.value : false\"\n :validityStyles=\"isRequired ? address.addressValidate.value : false\"\n @input=\"address.onAddress1Input\"\n />\n <template v-if=\"fieldScope\">\n <Error v-if=\"showAddress1Error\"> Required. </Error>\n <Hint v-else>Enter address line 1.</Hint>\n </template>\n </div>\n\n <div v-if=\"showAddress2\" class=\"address2\">\n <TextBox\n :id=\"fieldIds.address2\"\n :placeholder=\"address2PlaceholderDisplay\"\n :value=\"address.formData.address2\"\n @input=\"address.onAddress2Input\"\n />\n <Hint v-if=\"fieldScope\">Optional.</Hint>\n </div>\n\n <div class=\"city\">\n <TextBox\n :id=\"fieldIds.city\"\n :placeholder=\"cityPlaceholder\"\n :value=\"address.formData.city\"\n :valid=\"isRequired ? address.cityValid.value : true\"\n :validate=\"isRequired ? address.addressValidate.value : false\"\n :validityStyles=\"isRequired ? address.addressValidate.value : false\"\n @input=\"address.onCityInput\"\n />\n <Error v-if=\"fieldScope && showCityError\"> Required. </Error>\n </div>\n\n <div class=\"state\">\n <DropDownList\n :id=\"fieldIds.state\"\n :value=\"address.formData.state\"\n @change=\"address.onStateChange\"\n :defaultItem=\"address.stateDefaultItem\"\n :dataItems=\"address.stateOptions\"\n textField=\"label\"\n valueField=\"value\"\n dataItemKey=\"value\"\n :valuePrimitive=\"true\"\n :valid=\"isRequired ? address.stateValid.value : true\"\n :validate=\"isRequired ? address.addressValidate.value : false\"\n :validityStyles=\"isRequired ? address.addressValidate.value : false\"\n />\n <Error v-if=\"fieldScope && showStateError\"> Required. </Error>\n </div>\n\n <div class=\"zip\">\n <TextBox\n :id=\"fieldIds.zip\"\n :placeholder=\"zipPlaceholder\"\n :wrapperClass=\"address.zipWrapperClass\"\n :value=\"address.zipDisplay.value\"\n @input=\"address.onZipInput\"\n :valid=\"isRequired ? address.zipValid.value : true\"\n :validate=\"isRequired ? address.addressValidate.value : false\"\n :validityStyles=\"isRequired ? address.addressValidate.value : false\"\n :style=\"{ width: '100%' }\"\n />\n <Error v-if=\"fieldScope && showZipError\">\n {{ ZIP_CODE_MESSAGE }}\n </Error>\n <Hint v-if=\"fieldScope && !showZipError\">\n {{ ZIP_CODE_MESSAGE }}\n </Hint>\n </div>\n\n <div v-if=\"fieldsetScope\" class=\"messages\">\n <Error v-if=\"showErrors && !address.addressValid.value\">\n {{ nonZipRequiredFieldsValid ? \"\" : \"Required fields are missing.\" }}\n {{ address.zipValid.value ? \"\" : ZIP_CODE_MESSAGE }}\n </Error>\n <Error v-else-if=\"showOptionalFeedback\">\n {{ OPTIONAL_FIELDS_MESSAGE }}\n {{ optionalZipInvalid ? ZIP_CODE_MESSAGE : \"\" }}\n </Error>\n <Hint v-else>Enter address information.</Hint>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Error, Hint } from \"@progress/kendo-vue-labels\";\nimport { TextBox } from \"@progress/kendo-vue-inputs\";\nimport { DropDownList } from \"@progress/kendo-vue-dropdowns\";\n\ninterface USAddressViewModel {\n formData: {\n address1: string;\n address2: string;\n city: string;\n state: string | null;\n zip: string;\n };\n addressValidate: { value: boolean };\n address1Valid: { value: boolean };\n cityValid: { value: boolean };\n stateValid: { value: boolean };\n zipValid: { value: boolean };\n addressValid: { value: boolean };\n optionalFeedbackActive?: { value: boolean };\n optionalPartialInvalid?: { value: boolean };\n optionalMissingRequiredFields?: { value: boolean };\n optionalZipInvalid?: { value: boolean };\n stateDefaultItem: { label: string; value: string | null };\n stateOptions: Array<{ label: string; value: string }>;\n zipDisplay: { value: string };\n zipWrapperClass: string;\n onAddress1Input: (...args: unknown[]) => void;\n onAddress2Input: (...args: unknown[]) => void;\n onCityInput: (...args: unknown[]) => void;\n onStateChange: (event: { value: string | null }) => void;\n onZipInput: (...args: unknown[]) => void;\n}\n\nconst props = withDefaults(\n defineProps<{\n id: string;\n address: USAddressViewModel;\n required?: boolean;\n messageScope?: USAddressMessageScope;\n showAddress2?: boolean;\n address1Placeholder?: string;\n address2Placeholder?: string;\n cityPlaceholder?: string;\n zipPlaceholder?: string;\n }>(),\n {\n required: true,\n messageScope: \"fieldset\",\n showAddress2: true,\n address1Placeholder: \"Address Line 1\",\n address2Placeholder: \"Address Line 2\",\n cityPlaceholder: \"City\",\n zipPlaceholder: \"00000-0000\",\n },\n);\n\nconst ZIP_CODE_MESSAGE = \"Enter a 5 or 9 digit zip code.\";\nconst OPTIONAL_FIELDS_MESSAGE =\n \"Address is optional. Enter Address 1, City, State, and ZIP (Address Line 2 is optional), or clear the address.\";\n\ntype USAddressMessageScope = \"field\" | \"fieldset\";\n\nconst fieldScope = computed(() => {\n return props.messageScope === \"field\";\n});\n\nconst fieldsetScope = computed(() => {\n return props.messageScope === \"fieldset\";\n});\n\nconst isRequired = computed(() => props.required);\n\nconst showErrors = computed(() => isRequired.value);\n\nconst fieldIds = computed(() => ({\n address1: `${props.id}-address1`,\n address2: `${props.id}-address2`,\n city: `${props.id}-city`,\n state: `${props.id}-state`,\n zip: `${props.id}-zip`,\n}));\n\nconst address = computed(() => props.address);\n\nconst nonZipRequiredFieldsValid = computed(() => {\n return (\n address.value.address1Valid.value &&\n address.value.cityValid.value &&\n address.value.stateValid.value\n );\n});\n\nconst hasAnyOptionalInput = computed(() => {\n return (\n address.value.formData.address1.trim() !== \"\" ||\n address.value.formData.address2.trim() !== \"\" ||\n address.value.formData.city.trim() !== \"\" ||\n (address.value.formData.state ?? \"\").trim() !== \"\" ||\n address.value.formData.zip.replace(/\\D/g, \"\") !== \"\"\n );\n});\n\nconst optionalZipInvalid = computed(() => {\n if (address.value.optionalZipInvalid) {\n return address.value.optionalZipInvalid.value;\n }\n\n const zipDigits = address.value.formData.zip.replace(/\\D/g, \"\");\n return (\n !isRequired.value &&\n hasAnyOptionalInput.value &&\n zipDigits.length !== 5 &&\n zipDigits.length !== 9\n );\n});\n\nconst optionalPartialInvalid = computed(() => {\n if (address.value.optionalPartialInvalid) {\n return address.value.optionalPartialInvalid.value;\n }\n\n return (\n !isRequired.value &&\n hasAnyOptionalInput.value &&\n !address.value.addressValid.value\n );\n});\n\nconst showOptionalFeedback = computed(() => {\n if (isRequired.value || !optionalPartialInvalid.value) {\n return false;\n }\n\n if (address.value.optionalFeedbackActive) {\n return address.value.optionalFeedbackActive.value;\n }\n\n return false;\n});\n\nconst showAddress1Error = computed(() => {\n return (\n (showErrors.value && !address.value.address1Valid.value) ||\n (showOptionalFeedback.value &&\n address.value.formData.address1.trim() === \"\")\n );\n});\n\nconst showCityError = computed(() => {\n return (\n (showErrors.value && !address.value.cityValid.value) ||\n (showOptionalFeedback.value && address.value.formData.city.trim() === \"\")\n );\n});\n\nconst showStateError = computed(() => {\n return (\n (showErrors.value && !address.value.stateValid.value) ||\n (showOptionalFeedback.value &&\n (address.value.formData.state ?? \"\").trim() === \"\")\n );\n});\n\nconst showZipError = computed(() => {\n return (\n (showErrors.value && !address.value.zipValid.value) ||\n (showOptionalFeedback.value && optionalZipInvalid.value)\n );\n});\n\nconst address2PlaceholderDisplay = computed(() => {\n if (fieldsetScope.value && isRequired.value) {\n return `${props.address2Placeholder} (Optional)`;\n }\n return props.address2Placeholder;\n});\n</script>\n\n<style scoped>\n.fkui-us-address {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr;\n grid-template-areas:\n \"address1 address1 address1\"\n \"address2 address2 address2\"\n \"city state zip\"\n \"messages messages messages\";\n gap: 0.75rem;\n margin-bottom: 1rem;\n\n .address1 {\n grid-area: address1;\n }\n\n .address2 {\n grid-area: address2;\n }\n\n .city {\n grid-area: city;\n }\n\n .state {\n grid-area: state;\n }\n\n .zip {\n grid-area: zip;\n }\n\n .messages {\n grid-area: messages;\n }\n\n :deep(.fk-zip-textbox) {\n min-width: 100%;\n }\n}\n\n.fkui-us-address--fieldset-scope {\n row-gap: 0.5rem;\n\n .messages {\n margin-top: -0.375rem;\n }\n}\n</style>\n"],"names":["ZIP_CODE_MESSAGE","OPTIONAL_FIELDS_MESSAGE","props","__props","fieldScope","computed","fieldsetScope","isRequired","showErrors","fieldIds","address","nonZipRequiredFieldsValid","hasAnyOptionalInput","optionalZipInvalid","zipDigits","optionalPartialInvalid","showOptionalFeedback","showAddress1Error","showCityError","showStateError","showZipError","address2PlaceholderDisplay","_createElementBlock","_normalizeClass","_createElementVNode","_hoisted_1","_createVNode","_unref","TextBox","address1Placeholder","_Fragment","_createBlock","Error","_cache","Hint","showAddress2","_openBlock","_hoisted_2","_hoisted_3","cityPlaceholder","_hoisted_4","DropDownList","_hoisted_5","zipPlaceholder","_hoisted_6","_toDisplayString","_createTextVNode"],"mappings":"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"}
|
package/dist/featherk-ui.umd.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
1
|
(function(r,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue"),require("@progress/kendo-vue-labels"),require("@progress/kendo-vue-inputs"),require("@progress/kendo-vue-dropdowns")):typeof define=="function"&&define.amd?define(["exports","vue","@progress/kendo-vue-labels","@progress/kendo-vue-inputs","@progress/kendo-vue-dropdowns"],e):(r=typeof globalThis<"u"?globalThis:r||self,e(r.FeatherKUi={},r.Vue,r.KendoVueLabels,r.KendoVueInputs,r.KendoVueDropdowns))})(this,(function(r,e,o,f,k){"use strict";const B={class:"address1"},S={key:0,class:"address2"},C={class:"city"},x={class:"state"},D={class:"zip"},E={key:1,class:"messages"},v="Enter a 5 or 9 digit zip code.",I="Address is optional. Enter Address 1, City, State, and ZIP (Address Line 2 is optional), or clear the address.",N=((m,l)=>{const s=m.__vccOpts||m;for(const[n,t]of l)s[n]=t;return s})(e.defineComponent({__name:"USAddress",props:{id:{},address:{},required:{type:Boolean,default:!0},messageScope:{default:"fieldset"},showAddress2:{type:Boolean,default:!0},address1Placeholder:{default:"Address Line 1"},address2Placeholder:{default:"Address Line 2"},cityPlaceholder:{default:"City"},zipPlaceholder:{default:"00000-0000"}},setup(m){const l=m,s=e.computed(()=>l.messageScope==="field"),n=e.computed(()=>l.messageScope==="fieldset"),t=e.computed(()=>l.required),u=e.computed(()=>t.value),c=e.computed(()=>({address1:`${l.id}-address1`,address2:`${l.id}-address2`,city:`${l.id}-city`,state:`${l.id}-state`,zip:`${l.id}-zip`})),a=e.computed(()=>l.address),g=e.computed(()=>a.value.address1Valid.value&&a.value.cityValid.value&&a.value.stateValid.value),y=e.computed(()=>a.value.formData.address1.trim()!==""||a.value.formData.address2.trim()!==""||a.value.formData.city.trim()!==""||(a.value.formData.state??"").trim()!==""||a.value.formData.zip.replace(/\D/g,"")!==""),h=e.computed(()=>{if(a.value.optionalZipInvalid)return a.value.optionalZipInvalid.value;const i=a.value.formData.zip.replace(/\D/g,"");return!t.value&&y.value&&i.length!==5&&i.length!==9}),_=e.computed(()=>a.value.optionalPartialInvalid?a.value.optionalPartialInvalid.value:!t.value&&y.value&&!a.value.addressValid.value),p=e.computed(()=>t.value||!_.value?!1:a.value.optionalFeedbackActive?a.value.optionalFeedbackActive.value:!1),w=e.computed(()=>u.value&&!a.value.address1Valid.value||p.value&&a.value.formData.address1.trim()===""),A=e.computed(()=>u.value&&!a.value.cityValid.value||p.value&&a.value.formData.city.trim()===""),P=e.computed(()=>u.value&&!a.value.stateValid.value||p.value&&(a.value.formData.state??"").trim()===""),V=e.computed(()=>u.value&&!a.value.zipValid.value||p.value&&h.value),T=e.computed(()=>n.value&&t.value?`${l.address2Placeholder} (Optional)`:l.address2Placeholder);return(i,d)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["fkui-us-address",{"fkui-us-address--fieldset-scope":n.value}])},[e.createElementVNode("div",B,[e.createVNode(e.unref(f.TextBox),{id:c.value.address1,placeholder:i.address1Placeholder,value:a.value.formData.address1,valid:t.value?a.value.address1Valid.value:!0,validate:t.value?a.value.addressValidate.value:!1,validityStyles:t.value?a.value.addressValidate.value:!1,onInput:a.value.onAddress1Input},null,8,["id","placeholder","value","valid","validate","validityStyles","onInput"]),s.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[w.value?(e.openBlock(),e.createBlock(e.unref(o.Error),{key:0},{default:e.withCtx(()=>[...d[0]||(d[0]=[e.createTextVNode(" Required. ",-1)])]),_:1})):(e.openBlock(),e.createBlock(e.unref(o.Hint),{key:1},{default:e.withCtx(()=>[...d[1]||(d[1]=[e.createTextVNode("Enter address line 1.",-1)])]),_:1}))],64)):e.createCommentVNode("",!0)]),i.showAddress2?(e.openBlock(),e.createElementBlock("div",S,[e.createVNode(e.unref(f.TextBox),{id:c.value.address2,placeholder:T.value,value:a.value.formData.address2,onInput:a.value.onAddress2Input},null,8,["id","placeholder","value","onInput"]),s.value?(e.openBlock(),e.createBlock(e.unref(o.Hint),{key:0},{default:e.withCtx(()=>[...d[2]||(d[2]=[e.createTextVNode("Optional.",-1)])]),_:1})):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0),e.createElementVNode("div",C,[e.createVNode(e.unref(f.TextBox),{id:c.value.city,placeholder:i.cityPlaceholder,value:a.value.formData.city,valid:t.value?a.value.cityValid.value:!0,validate:t.value?a.value.addressValidate.value:!1,validityStyles:t.value?a.value.addressValidate.value:!1,onInput:a.value.onCityInput},null,8,["id","placeholder","value","valid","validate","validityStyles","onInput"]),s.value&&A.value?(e.openBlock(),e.createBlock(e.unref(o.Error),{key:0},{default:e.withCtx(()=>[...d[3]||(d[3]=[e.createTextVNode(" Required. ",-1)])]),_:1})):e.createCommentVNode("",!0)]),e.createElementVNode("div",x,[e.createVNode(e.unref(k.DropDownList),{id:c.value.state,value:a.value.formData.state,onChange:a.value.onStateChange,defaultItem:a.value.stateDefaultItem,dataItems:a.value.stateOptions,textField:"label",valueField:"value",dataItemKey:"value",valuePrimitive:!0,valid:t.value?a.value.stateValid.value:!0,validate:t.value?a.value.addressValidate.value:!1,validityStyles:t.value?a.value.addressValidate.value:!1},null,8,["id","value","onChange","defaultItem","dataItems","valid","validate","validityStyles"]),s.value&&P.value?(e.openBlock(),e.createBlock(e.unref(o.Error),{key:0},{default:e.withCtx(()=>[...d[4]||(d[4]=[e.createTextVNode(" Required. ",-1)])]),_:1})):e.createCommentVNode("",!0)]),e.createElementVNode("div",D,[e.createVNode(e.unref(f.TextBox),{id:c.value.zip,placeholder:i.zipPlaceholder,wrapperClass:a.value.zipWrapperClass,value:a.value.zipDisplay.value,onInput:a.value.onZipInput,valid:t.value?a.value.zipValid.value:!0,validate:t.value?a.value.addressValidate.value:!1,validityStyles:t.value?a.value.addressValidate.value:!1,style:{width:"100%"}},null,8,["id","placeholder","wrapperClass","value","onInput","valid","validate","validityStyles"]),s.value&&V.value?(e.openBlock(),e.createBlock(e.unref(o.Error),{key:0},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(v))]),_:1})):e.createCommentVNode("",!0),s.value&&!V.value?(e.openBlock(),e.createBlock(e.unref(o.Hint),{key:1},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(v))]),_:1})):e.createCommentVNode("",!0)]),n.value?(e.openBlock(),e.createElementBlock("div",E,[u.value&&!a.value.addressValid.value?(e.openBlock(),e.createBlock(e.unref(o.Error),{key:0},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(g.value?"":"Required fields are missing.")+" "+e.toDisplayString(a.value.zipValid.value?"":v),1)]),_:1})):p.value?(e.openBlock(),e.createBlock(e.unref(o.Error),{key:1},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(I)+" "+e.toDisplayString(h.value?v:""),1)]),_:1})):(e.openBlock(),e.createBlock(e.unref(o.Hint),{key:2},{default:e.withCtx(()=>[...d[5]||(d[5]=[e.createTextVNode("Enter address information.",-1)])]),_:1}))])):e.createCommentVNode("",!0)],2))}}),[["__scopeId","data-v-95d578ff"]]);r.USAddress=N,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})}));
|
|
2
|
+
//# sourceMappingURL=featherk-ui.umd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"featherk-ui.umd.js","sources":["../src/address/USAddress.vue"],"sourcesContent":["<template>\n <div\n class=\"fkui-us-address\"\n :class=\"{ 'fkui-us-address--fieldset-scope': fieldsetScope }\"\n >\n <div class=\"address1\">\n <TextBox\n :id=\"fieldIds.address1\"\n :placeholder=\"address1Placeholder\"\n :value=\"address.formData.address1\"\n :valid=\"isRequired ? address.address1Valid.value : true\"\n :validate=\"isRequired ? address.addressValidate.value : false\"\n :validityStyles=\"isRequired ? address.addressValidate.value : false\"\n @input=\"address.onAddress1Input\"\n />\n <template v-if=\"fieldScope\">\n <Error v-if=\"showAddress1Error\"> Required. </Error>\n <Hint v-else>Enter address line 1.</Hint>\n </template>\n </div>\n\n <div v-if=\"showAddress2\" class=\"address2\">\n <TextBox\n :id=\"fieldIds.address2\"\n :placeholder=\"address2PlaceholderDisplay\"\n :value=\"address.formData.address2\"\n @input=\"address.onAddress2Input\"\n />\n <Hint v-if=\"fieldScope\">Optional.</Hint>\n </div>\n\n <div class=\"city\">\n <TextBox\n :id=\"fieldIds.city\"\n :placeholder=\"cityPlaceholder\"\n :value=\"address.formData.city\"\n :valid=\"isRequired ? address.cityValid.value : true\"\n :validate=\"isRequired ? address.addressValidate.value : false\"\n :validityStyles=\"isRequired ? address.addressValidate.value : false\"\n @input=\"address.onCityInput\"\n />\n <Error v-if=\"fieldScope && showCityError\"> Required. </Error>\n </div>\n\n <div class=\"state\">\n <DropDownList\n :id=\"fieldIds.state\"\n :value=\"address.formData.state\"\n @change=\"address.onStateChange\"\n :defaultItem=\"address.stateDefaultItem\"\n :dataItems=\"address.stateOptions\"\n textField=\"label\"\n valueField=\"value\"\n dataItemKey=\"value\"\n :valuePrimitive=\"true\"\n :valid=\"isRequired ? address.stateValid.value : true\"\n :validate=\"isRequired ? address.addressValidate.value : false\"\n :validityStyles=\"isRequired ? address.addressValidate.value : false\"\n />\n <Error v-if=\"fieldScope && showStateError\"> Required. </Error>\n </div>\n\n <div class=\"zip\">\n <TextBox\n :id=\"fieldIds.zip\"\n :placeholder=\"zipPlaceholder\"\n :wrapperClass=\"address.zipWrapperClass\"\n :value=\"address.zipDisplay.value\"\n @input=\"address.onZipInput\"\n :valid=\"isRequired ? address.zipValid.value : true\"\n :validate=\"isRequired ? address.addressValidate.value : false\"\n :validityStyles=\"isRequired ? address.addressValidate.value : false\"\n :style=\"{ width: '100%' }\"\n />\n <Error v-if=\"fieldScope && showZipError\">\n {{ ZIP_CODE_MESSAGE }}\n </Error>\n <Hint v-if=\"fieldScope && !showZipError\">\n {{ ZIP_CODE_MESSAGE }}\n </Hint>\n </div>\n\n <div v-if=\"fieldsetScope\" class=\"messages\">\n <Error v-if=\"showErrors && !address.addressValid.value\">\n {{ nonZipRequiredFieldsValid ? \"\" : \"Required fields are missing.\" }}\n {{ address.zipValid.value ? \"\" : ZIP_CODE_MESSAGE }}\n </Error>\n <Error v-else-if=\"showOptionalFeedback\">\n {{ OPTIONAL_FIELDS_MESSAGE }}\n {{ optionalZipInvalid ? ZIP_CODE_MESSAGE : \"\" }}\n </Error>\n <Hint v-else>Enter address information.</Hint>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Error, Hint } from \"@progress/kendo-vue-labels\";\nimport { TextBox } from \"@progress/kendo-vue-inputs\";\nimport { DropDownList } from \"@progress/kendo-vue-dropdowns\";\n\ninterface USAddressViewModel {\n formData: {\n address1: string;\n address2: string;\n city: string;\n state: string | null;\n zip: string;\n };\n addressValidate: { value: boolean };\n address1Valid: { value: boolean };\n cityValid: { value: boolean };\n stateValid: { value: boolean };\n zipValid: { value: boolean };\n addressValid: { value: boolean };\n optionalFeedbackActive?: { value: boolean };\n optionalPartialInvalid?: { value: boolean };\n optionalMissingRequiredFields?: { value: boolean };\n optionalZipInvalid?: { value: boolean };\n stateDefaultItem: { label: string; value: string | null };\n stateOptions: Array<{ label: string; value: string }>;\n zipDisplay: { value: string };\n zipWrapperClass: string;\n onAddress1Input: (...args: unknown[]) => void;\n onAddress2Input: (...args: unknown[]) => void;\n onCityInput: (...args: unknown[]) => void;\n onStateChange: (event: { value: string | null }) => void;\n onZipInput: (...args: unknown[]) => void;\n}\n\nconst props = withDefaults(\n defineProps<{\n id: string;\n address: USAddressViewModel;\n required?: boolean;\n messageScope?: USAddressMessageScope;\n showAddress2?: boolean;\n address1Placeholder?: string;\n address2Placeholder?: string;\n cityPlaceholder?: string;\n zipPlaceholder?: string;\n }>(),\n {\n required: true,\n messageScope: \"fieldset\",\n showAddress2: true,\n address1Placeholder: \"Address Line 1\",\n address2Placeholder: \"Address Line 2\",\n cityPlaceholder: \"City\",\n zipPlaceholder: \"00000-0000\",\n },\n);\n\nconst ZIP_CODE_MESSAGE = \"Enter a 5 or 9 digit zip code.\";\nconst OPTIONAL_FIELDS_MESSAGE =\n \"Address is optional. Enter Address 1, City, State, and ZIP (Address Line 2 is optional), or clear the address.\";\n\ntype USAddressMessageScope = \"field\" | \"fieldset\";\n\nconst fieldScope = computed(() => {\n return props.messageScope === \"field\";\n});\n\nconst fieldsetScope = computed(() => {\n return props.messageScope === \"fieldset\";\n});\n\nconst isRequired = computed(() => props.required);\n\nconst showErrors = computed(() => isRequired.value);\n\nconst fieldIds = computed(() => ({\n address1: `${props.id}-address1`,\n address2: `${props.id}-address2`,\n city: `${props.id}-city`,\n state: `${props.id}-state`,\n zip: `${props.id}-zip`,\n}));\n\nconst address = computed(() => props.address);\n\nconst nonZipRequiredFieldsValid = computed(() => {\n return (\n address.value.address1Valid.value &&\n address.value.cityValid.value &&\n address.value.stateValid.value\n );\n});\n\nconst hasAnyOptionalInput = computed(() => {\n return (\n address.value.formData.address1.trim() !== \"\" ||\n address.value.formData.address2.trim() !== \"\" ||\n address.value.formData.city.trim() !== \"\" ||\n (address.value.formData.state ?? \"\").trim() !== \"\" ||\n address.value.formData.zip.replace(/\\D/g, \"\") !== \"\"\n );\n});\n\nconst optionalZipInvalid = computed(() => {\n if (address.value.optionalZipInvalid) {\n return address.value.optionalZipInvalid.value;\n }\n\n const zipDigits = address.value.formData.zip.replace(/\\D/g, \"\");\n return (\n !isRequired.value &&\n hasAnyOptionalInput.value &&\n zipDigits.length !== 5 &&\n zipDigits.length !== 9\n );\n});\n\nconst optionalPartialInvalid = computed(() => {\n if (address.value.optionalPartialInvalid) {\n return address.value.optionalPartialInvalid.value;\n }\n\n return (\n !isRequired.value &&\n hasAnyOptionalInput.value &&\n !address.value.addressValid.value\n );\n});\n\nconst showOptionalFeedback = computed(() => {\n if (isRequired.value || !optionalPartialInvalid.value) {\n return false;\n }\n\n if (address.value.optionalFeedbackActive) {\n return address.value.optionalFeedbackActive.value;\n }\n\n return false;\n});\n\nconst showAddress1Error = computed(() => {\n return (\n (showErrors.value && !address.value.address1Valid.value) ||\n (showOptionalFeedback.value &&\n address.value.formData.address1.trim() === \"\")\n );\n});\n\nconst showCityError = computed(() => {\n return (\n (showErrors.value && !address.value.cityValid.value) ||\n (showOptionalFeedback.value && address.value.formData.city.trim() === \"\")\n );\n});\n\nconst showStateError = computed(() => {\n return (\n (showErrors.value && !address.value.stateValid.value) ||\n (showOptionalFeedback.value &&\n (address.value.formData.state ?? \"\").trim() === \"\")\n );\n});\n\nconst showZipError = computed(() => {\n return (\n (showErrors.value && !address.value.zipValid.value) ||\n (showOptionalFeedback.value && optionalZipInvalid.value)\n );\n});\n\nconst address2PlaceholderDisplay = computed(() => {\n if (fieldsetScope.value && isRequired.value) {\n return `${props.address2Placeholder} (Optional)`;\n }\n return props.address2Placeholder;\n});\n</script>\n\n<style scoped>\n.fkui-us-address {\n display: grid;\n grid-template-columns: 2fr 1fr 1fr;\n grid-template-areas:\n \"address1 address1 address1\"\n \"address2 address2 address2\"\n \"city state zip\"\n \"messages messages messages\";\n gap: 0.75rem;\n margin-bottom: 1rem;\n\n .address1 {\n grid-area: address1;\n }\n\n .address2 {\n grid-area: address2;\n }\n\n .city {\n grid-area: city;\n }\n\n .state {\n grid-area: state;\n }\n\n .zip {\n grid-area: zip;\n }\n\n .messages {\n grid-area: messages;\n }\n\n :deep(.fk-zip-textbox) {\n min-width: 100%;\n }\n}\n\n.fkui-us-address--fieldset-scope {\n row-gap: 0.5rem;\n\n .messages {\n margin-top: -0.375rem;\n }\n}\n</style>\n"],"names":["ZIP_CODE_MESSAGE","OPTIONAL_FIELDS_MESSAGE","props","__props","fieldScope","computed","fieldsetScope","isRequired","showErrors","fieldIds","address","nonZipRequiredFieldsValid","hasAnyOptionalInput","optionalZipInvalid","zipDigits","optionalPartialInvalid","showOptionalFeedback","showAddress1Error","showCityError","showStateError","showZipError","address2PlaceholderDisplay","_createElementBlock","_normalizeClass","_createElementVNode","_hoisted_1","_createVNode","_unref","TextBox","address1Placeholder","_Fragment","_createBlock","Error","_cache","Hint","showAddress2","_openBlock","_hoisted_2","_hoisted_3","cityPlaceholder","_hoisted_4","DropDownList","_hoisted_5","zipPlaceholder","_hoisted_6","_toDisplayString","_createTextVNode"],"mappings":"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"}
|
|
@@ -18,29 +18,49 @@ import { USAddress } from "@featherk/ui";
|
|
|
18
18
|
import { useUSAddress } from "@featherk/composables/address";
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
1. Call `useUSAddress({ fieldsetRef, addressId, required })` to get the composable API.
|
|
24
|
+
2. Wrap `<USAddress>` inside a `<fieldset>` and bind its `ref` to `fieldsetRef`.
|
|
25
|
+
3. Wire the fieldset's `@focusout` to `onFieldsetFocusout` — this activates
|
|
26
|
+
delayed validation, which stays suspended until the fieldset loses focus
|
|
27
|
+
or the form is submitted.
|
|
28
|
+
4. On submit, call `await address.validateForSubmit()`. This sets internal
|
|
29
|
+
`submitted` state (activating error display) and returns
|
|
30
|
+
`{ isValid, payload }`, where `payload` is `null` when `isValid` is `false`.
|
|
31
|
+
5. On reset, call `address.reset()`. **Use `type="button"` on the Reset
|
|
32
|
+
control** — the HTML default is `type="submit"`, which would immediately
|
|
33
|
+
re-trigger form submission and re-raise the error you just cleared.
|
|
34
|
+
|
|
21
35
|
## Basic Usage
|
|
22
36
|
|
|
23
37
|
```vue
|
|
24
38
|
<script setup lang="ts">
|
|
25
|
-
import { ref
|
|
39
|
+
import { ref } from "vue";
|
|
26
40
|
import { USAddress } from "@featherk/ui";
|
|
27
41
|
import { useUSAddress } from "@featherk/composables/address";
|
|
28
42
|
|
|
29
43
|
const shippingFieldsetRef = ref<HTMLFieldSetElement | null>(null);
|
|
44
|
+
const isShippingAddressRequired = ref(true);
|
|
30
45
|
|
|
46
|
+
// Step 1: get the composable API; refs can be passed directly (no toRef needed)
|
|
31
47
|
const shippingAddress = useUSAddress({
|
|
32
|
-
fieldsetRef:
|
|
48
|
+
fieldsetRef: shippingFieldsetRef,
|
|
33
49
|
addressId: "shipping-address",
|
|
50
|
+
required: isShippingAddressRequired,
|
|
34
51
|
});
|
|
35
52
|
|
|
53
|
+
// Step 3: activates delayed validation on fieldset blur
|
|
36
54
|
const onFieldsetFocusout = (event: FocusEvent) => {
|
|
37
55
|
shippingAddress.onFieldsetFocusout(event);
|
|
38
56
|
};
|
|
39
57
|
|
|
58
|
+
// Step 5
|
|
40
59
|
function onReset() {
|
|
41
60
|
shippingAddress.reset();
|
|
42
61
|
}
|
|
43
62
|
|
|
63
|
+
// Step 4
|
|
44
64
|
async function onSubmit() {
|
|
45
65
|
const result = await shippingAddress.validateForSubmit();
|
|
46
66
|
if (!result.isValid) return;
|
|
@@ -51,14 +71,22 @@ async function onSubmit() {
|
|
|
51
71
|
|
|
52
72
|
<template>
|
|
53
73
|
<form @submit.prevent="onSubmit">
|
|
74
|
+
<!-- Step 2: fieldsetRef binds here -->
|
|
54
75
|
<fieldset ref="shippingFieldsetRef" @focusout="onFieldsetFocusout">
|
|
55
|
-
|
|
76
|
+
<!-- required must match the same source passed to useUSAddress; messageScope defaults to "fieldset" -->
|
|
77
|
+
<USAddress
|
|
78
|
+
id="shipping-address"
|
|
79
|
+
:address="shippingAddress"
|
|
80
|
+
:required="isShippingAddressRequired"
|
|
81
|
+
messageScope="fieldset"
|
|
82
|
+
/>
|
|
56
83
|
|
|
57
84
|
<label for="shipping-attn">Attention</label>
|
|
58
85
|
<input id="shipping-attn" type="text" />
|
|
59
86
|
</fieldset>
|
|
60
87
|
|
|
61
88
|
<button type="submit">Submit</button>
|
|
89
|
+
<!-- Step 5: type="button" required, see Quick Start -->
|
|
62
90
|
<button type="button" @click="onReset">Reset</button>
|
|
63
91
|
</form>
|
|
64
92
|
</template>
|