@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 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
- - Guide: [docs/address/USAddress.md](https://github.com/NantHealth/featherk/blob/integration/packages/ui/docs/address/USAddress.md)
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
- ## Usage
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:
@@ -169,3 +169,4 @@ const N = { class: "address1" }, b = {
169
169
  export {
170
170
  X as USAddress
171
171
  };
172
+ //# sourceMappingURL=featherk-ui.es.js.map
@@ -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":";;;;;;;;;;GA0JMA,IAAmB,kCACnBC,IACJ;;;;;;;;;;;;;;AAzBF,UAAMC,IAAQC,GA6BRC,IAAaC,EAAS,MACnBH,EAAM,iBAAiB,OAC/B,GAEKI,IAAgBD,EAAS,MACtBH,EAAM,iBAAiB,UAC/B,GAEKK,IAAaF,EAAS,MAAMH,EAAM,QAAQ,GAE1CM,IAAaH,EAAS,MAAME,EAAW,KAAK,GAE5CE,IAAWJ,EAAS,OAAO;AAAA,MAC/B,UAAU,GAAGH,EAAM,EAAE;AAAA,MACrB,UAAU,GAAGA,EAAM,EAAE;AAAA,MACrB,MAAM,GAAGA,EAAM,EAAE;AAAA,MACjB,OAAO,GAAGA,EAAM,EAAE;AAAA,MAClB,KAAK,GAAGA,EAAM,EAAE;AAAA,IAAA,EAChB,GAEIQ,IAAUL,EAAS,MAAMH,EAAM,OAAO,GAEtCS,IAA4BN,EAAS,MAEvCK,EAAQ,MAAM,cAAc,SAC5BA,EAAQ,MAAM,UAAU,SACxBA,EAAQ,MAAM,WAAW,KAE5B,GAEKE,IAAsBP,EAAS,MAEjCK,EAAQ,MAAM,SAAS,SAAS,KAAA,MAAW,MAC3CA,EAAQ,MAAM,SAAS,SAAS,KAAA,MAAW,MAC3CA,EAAQ,MAAM,SAAS,KAAK,KAAA,MAAW,OACtCA,EAAQ,MAAM,SAAS,SAAS,IAAI,KAAA,MAAW,MAChDA,EAAQ,MAAM,SAAS,IAAI,QAAQ,OAAO,EAAE,MAAM,EAErD,GAEKG,IAAqBR,EAAS,MAAM;AACxC,UAAIK,EAAQ,MAAM;AAChB,eAAOA,EAAQ,MAAM,mBAAmB;AAG1C,YAAMI,IAAYJ,EAAQ,MAAM,SAAS,IAAI,QAAQ,OAAO,EAAE;AAC9D,aACE,CAACH,EAAW,SACZK,EAAoB,SACpBE,EAAU,WAAW,KACrBA,EAAU,WAAW;AAAA,IAEzB,CAAC,GAEKC,IAAyBV,EAAS,MAClCK,EAAQ,MAAM,yBACTA,EAAQ,MAAM,uBAAuB,QAI5C,CAACH,EAAW,SACZK,EAAoB,SACpB,CAACF,EAAQ,MAAM,aAAa,KAE/B,GAEKM,IAAuBX,EAAS,MAChCE,EAAW,SAAS,CAACQ,EAAuB,QACvC,KAGLL,EAAQ,MAAM,yBACTA,EAAQ,MAAM,uBAAuB,QAGvC,EACR,GAEKO,IAAoBZ,EAAS,MAE9BG,EAAW,SAAS,CAACE,EAAQ,MAAM,cAAc,SACjDM,EAAqB,SACpBN,EAAQ,MAAM,SAAS,SAAS,WAAW,EAEhD,GAEKQ,IAAgBb,EAAS,MAE1BG,EAAW,SAAS,CAACE,EAAQ,MAAM,UAAU,SAC7CM,EAAqB,SAASN,EAAQ,MAAM,SAAS,KAAK,WAAW,EAEzE,GAEKS,IAAiBd,EAAS,MAE3BG,EAAW,SAAS,CAACE,EAAQ,MAAM,WAAW,SAC9CM,EAAqB,UACnBN,EAAQ,MAAM,SAAS,SAAS,IAAI,WAAW,EAErD,GAEKU,IAAef,EAAS,MAEzBG,EAAW,SAAS,CAACE,EAAQ,MAAM,SAAS,SAC5CM,EAAqB,SAASH,EAAmB,KAErD,GAEKQ,IAA6BhB,EAAS,MACtCC,EAAc,SAASC,EAAW,QAC7B,GAAGL,EAAM,mBAAmB,gBAE9BA,EAAM,mBACd;2BAhRCoB,EA4FM,OAAA;AAAA,MA3FJ,OAAKC,EAAA,CAAC,mBAAiB,EAAA,mCACsBjB,EAAA,OAAa,CAAA;AAAA,IAAA;MAE1DkB,EAcM,OAdNC,GAcM;AAAA,QAbJC,EAQEC,EAAAC,CAAA,GAAA;AAAA,UAPC,IAAInB,EAAA,MAAS;AAAA,UACb,aAAaoB,EAAAA;AAAAA,UACb,OAAOnB,EAAA,MAAQ,SAAS;AAAA,UACxB,OAAOH,EAAA,QAAaG,QAAQ,cAAc,QAAK;AAAA,UAC/C,UAAUH,EAAA,QAAaG,QAAQ,gBAAgB,QAAK;AAAA,UACpD,gBAAgBH,EAAA,QAAaG,QAAQ,gBAAgB,QAAK;AAAA,UAC1D,SAAOA,EAAA,MAAQ;AAAA,QAAA;QAEFN,EAAA,cAAhBkB,EAGWQ,GAAA,EAAA,KAAA,KAAA;AAAA,UAFIb,EAAA,cAAbc,EAAmDJ,EAAAK,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,uBAAnB,MAAW,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAAX,eAAW,EAAA;AAAA,YAAA;;sBAC3CF,EAAyCJ,EAAAO,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,uBAA5B,MAAqB,CAAA,GAAAD,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAArB,yBAAqB,EAAA;AAAA,YAAA;;;;;MAI3BE,EAAAA,gBAAXC,EAAA,GAAAd,EAQM,OARNe,GAQM;AAAA,QAPJX,EAKEC,EAAAC,CAAA,GAAA;AAAA,UAJC,IAAInB,EAAA,MAAS;AAAA,UACb,aAAaY,EAAA;AAAA,UACb,OAAOX,EAAA,MAAQ,SAAS;AAAA,UACxB,SAAOA,EAAA,MAAQ;AAAA,QAAA;QAENN,EAAA,cAAZ2B,EAAwCJ,EAAAO,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,qBAAhB,MAAS,CAAA,GAAAD,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAAT,aAAS,EAAA;AAAA,UAAA;;;;MAGnCT,EAWM,OAXNc,GAWM;AAAA,QAVJZ,EAQEC,EAAAC,CAAA,GAAA;AAAA,UAPC,IAAInB,EAAA,MAAS;AAAA,UACb,aAAa8B,EAAAA;AAAAA,UACb,OAAO7B,EAAA,MAAQ,SAAS;AAAA,UACxB,OAAOH,EAAA,QAAaG,QAAQ,UAAU,QAAK;AAAA,UAC3C,UAAUH,EAAA,QAAaG,QAAQ,gBAAgB,QAAK;AAAA,UACpD,gBAAgBH,EAAA,QAAaG,QAAQ,gBAAgB,QAAK;AAAA,UAC1D,SAAOA,EAAA,MAAQ;AAAA,QAAA;QAELN,EAAA,SAAcc,EAAA,cAA3Ba,EAA6DJ,EAAAK,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,qBAAnB,MAAW,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAAX,eAAW,EAAA;AAAA,UAAA;;;;MAGvDT,EAgBM,OAhBNgB,GAgBM;AAAA,QAfJd,EAaEC,EAAAc,CAAA,GAAA;AAAA,UAZC,IAAIhC,EAAA,MAAS;AAAA,UACb,OAAOC,EAAA,MAAQ,SAAS;AAAA,UACxB,UAAQA,EAAA,MAAQ;AAAA,UAChB,aAAaA,EAAA,MAAQ;AAAA,UACrB,WAAWA,EAAA,MAAQ;AAAA,UACpB,WAAU;AAAA,UACV,YAAW;AAAA,UACX,aAAY;AAAA,UACX,gBAAgB;AAAA,UAChB,OAAOH,EAAA,QAAaG,QAAQ,WAAW,QAAK;AAAA,UAC5C,UAAUH,EAAA,QAAaG,QAAQ,gBAAgB,QAAK;AAAA,UACpD,gBAAgBH,EAAA,QAAaG,QAAQ,gBAAgB,QAAK;AAAA,QAAA;QAEhDN,EAAA,SAAce,EAAA,cAA3BY,EAA8DJ,EAAAK,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,qBAAnB,MAAW,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAAX,eAAW,EAAA;AAAA,UAAA;;;;MAGxDT,EAkBM,OAlBNkB,GAkBM;AAAA,QAjBJhB,EAUEC,EAAAC,CAAA,GAAA;AAAA,UATC,IAAInB,EAAA,MAAS;AAAA,UACb,aAAakC,EAAAA;AAAAA,UACb,cAAcjC,EAAA,MAAQ;AAAA,UACtB,OAAOA,EAAA,MAAQ,WAAW;AAAA,UAC1B,SAAOA,EAAA,MAAQ;AAAA,UACf,OAAOH,EAAA,QAAaG,QAAQ,SAAS,QAAK;AAAA,UAC1C,UAAUH,EAAA,QAAaG,QAAQ,gBAAgB,QAAK;AAAA,UACpD,gBAAgBH,EAAA,QAAaG,QAAQ,gBAAgB,QAAK;AAAA,UAC1D,OAAO,EAAA,OAAA,OAAA;AAAA,QAAA;QAEGN,EAAA,SAAcgB,EAAA,cAA3BW,EAEQJ,EAAAK,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,qBADN,MAAsB;AAAA,gBAAnBhC,CAAgB,CAAA;AAAA,UAAA;;;QAETI,EAAA,UAAegB,EAAA,cAA3BW,EAEOJ,EAAAO,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,qBADL,MAAsB;AAAA,gBAAnBlC,CAAgB,CAAA;AAAA,UAAA;;;;MAIZM,EAAA,SAAX8B,EAAA,GAAAd,EAUM,OAVNsB,GAUM;AAAA,QATSpC,EAAA,SAAU,CAAKE,EAAA,MAAQ,aAAa,cAAjDqB,EAGQJ,EAAAK,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,qBAFN,MAAqE;AAAA,gBAAlErB,EAAA,QAAyB,KAAA,8BAAA,IAAyC,MACrEkC,EAAGnC,EAAA,MAAQ,SAAS,QAAK,KAAQV,CAAgB,GAAA,CAAA;AAAA,UAAA;;cAEjCgB,EAAA,cAAlBe,EAGQJ,EAAAK,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,qBAFN,MAA6B;AAAA,YAA1Bc,EAAAD,EAAA5C,CAAuB,IAAG,MAC7B4C,EAAGhC,EAAA,QAAqBb,IAAgB,EAAA,GAAA,CAAA;AAAA,UAAA;;oBAE1C+B,EAA8CJ,EAAAO,CAAA,GAAA,EAAA,KAAA,KAAA;AAAA,qBAAjC,MAA0B,CAAA,GAAAD,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAA1B,8BAA0B,EAAA;AAAA,UAAA;;;;;;;;;;;;"}
@@ -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, toRef } from "vue";
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: toRef(() => shippingFieldsetRef.value),
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
- <USAddress id="shipping-address" :address="shippingAddress" />
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>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@featherk/ui",
3
- "version": "0.9.4",
3
+ "version": "0.9.6",
4
4
  "main": "dist/featherk-ui.umd.js",
5
5
  "module": "dist/featherk-ui.es.js",
6
6
  "types": "dist/index.d.ts",