@featherk/ui 0.9.0

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 ADDED
@@ -0,0 +1,73 @@
1
+ # @featherk/ui
2
+
3
+ Vue UI component package for FeatherK.
4
+
5
+ ## Components Overview
6
+
7
+ - **Address**: `USAddress` - Complete US address form component with delayed validation orchestration and normalized submit payloads.
8
+ - Guide: [docs/address/USAddress.md](https://github.com/NantHealth/featherk/blob/integration/packages/ui/docs/address/USAddress.md)
9
+
10
+ ## Importing Components
11
+
12
+ ```ts
13
+ import { USAddress } from "@featherk/ui";
14
+ import type { USAddressSubmitPayload } from "@featherk/composables/address";
15
+ ```
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 { USAddress } from "@featherk/ui";
24
+ import type { USAddressSubmitPayload } from "@featherk/composables/address";
25
+
26
+ function onValidSubmit(payload: USAddressSubmitPayload) {
27
+ console.log(payload);
28
+ }
29
+
30
+ function onInvalidSubmit() {
31
+ console.log("invalid");
32
+ }
33
+ </script>
34
+
35
+ <template>
36
+ <USAddress @valid-submit="onValidSubmit" @invalid-submit="onInvalidSubmit" />
37
+ </template>
38
+ ```
39
+
40
+ ## Events
41
+
42
+ - `valid-submit`: emits normalized `USAddressSubmitPayload`
43
+ - `invalid-submit`: emits when submission fails validation
44
+ - `reset`: emits after component reset
45
+
46
+ USAddress internally uses composables from `@featherk/composables/address`,
47
+ including delayed fieldset validation orchestration via `useFieldsetValidationKit`.
48
+
49
+ ## Peer Dependencies
50
+
51
+ - Required: `vue`
52
+ - Required for `USAddress`: `@progress/kendo-vue-buttons`, `@progress/kendo-vue-dropdowns`, `@progress/kendo-vue-inputs`, `@progress/kendo-vue-labels`
53
+
54
+ ## Build
55
+
56
+ Run from repository root:
57
+
58
+ ```bash
59
+ npm run build -- --filter=@featherk/ui
60
+ ```
61
+
62
+ Or run package-local:
63
+
64
+ ```bash
65
+ npm run build
66
+ ```
67
+
68
+ ## Maintainer Notes
69
+
70
+ - The build runs a first-party script that ensures `dist/featherk-ui.es.js` imports `./ui.css`.
71
+ - New component scoped styles are included automatically when the component is exported through the root package entry.
72
+ - If runtime subpath entries are added later (for example `@featherk/ui/address` as a JS entry), each runtime entry must also import CSS to preserve zero-effort DX.
73
+ - For new component documentation, follow the docs authoring template in `docs/README.md`.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import { type USAddressSubmitPayload } from "@featherk/composables/address";
2
+ type __VLS_Props = {
3
+ showAddress2?: boolean;
4
+ submitLabel?: string;
5
+ resetLabel?: string;
6
+ address1Placeholder?: string;
7
+ address2Placeholder?: string;
8
+ cityPlaceholder?: string;
9
+ zipPlaceholder?: string;
10
+ };
11
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ "valid-submit": (payload: USAddressSubmitPayload) => any;
13
+ "invalid-submit": () => any;
14
+ reset: () => any;
15
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
16
+ "onValid-submit"?: (payload: USAddressSubmitPayload) => any;
17
+ "onInvalid-submit"?: () => any;
18
+ onReset?: () => any;
19
+ }>, {
20
+ showAddress2: boolean;
21
+ submitLabel: string;
22
+ resetLabel: string;
23
+ address1Placeholder: string;
24
+ address2Placeholder: string;
25
+ cityPlaceholder: string;
26
+ zipPlaceholder: string;
27
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
28
+ export default _default;
@@ -0,0 +1 @@
1
+ export { default as USAddress } from "./USAddress.vue";
@@ -0,0 +1,196 @@
1
+ import "./ui.css";
2
+ import { defineComponent as z, ref as I, openBlock as i, createElementBlock as k, withModifiers as g, createElementVNode as u, unref as e, createVNode as r, createBlock as o, withCtx as l, createTextVNode as d, createCommentVNode as b, toDisplayString as S } from "vue";
3
+ import { Error as v, Hint as m } from "@progress/kendo-vue-labels";
4
+ import { TextBox as y } from "@progress/kendo-vue-inputs";
5
+ import { DropDownList as w } from "@progress/kendo-vue-dropdowns";
6
+ import { Button as h } from "@progress/kendo-vue-buttons";
7
+ import { useUSAddress as D } from "@featherk/composables/address";
8
+ const A = { class: "address1" }, E = {
9
+ key: 0,
10
+ class: "address2"
11
+ }, F = { class: "city" }, B = { class: "state" }, R = { class: "zip" }, L = { class: "messages" }, q = { class: "demo-actions" }, N = /* @__PURE__ */ z({
12
+ __name: "USAddress",
13
+ props: {
14
+ showAddress2: { type: Boolean, default: !0 },
15
+ submitLabel: { default: "Submit" },
16
+ resetLabel: { default: "Reset" },
17
+ address1Placeholder: { default: "Enter street address" },
18
+ address2Placeholder: { default: "Enter address line 2 (Optional)" },
19
+ cityPlaceholder: { default: "Enter city" },
20
+ zipPlaceholder: { default: "00000-0000" }
21
+ },
22
+ emits: ["valid-submit", "invalid-submit", "reset"],
23
+ setup(c, { emit: V }) {
24
+ const n = V, p = I(null), f = I(null), t = D({
25
+ formRef: p,
26
+ fieldsetRef: f
27
+ }), C = async () => {
28
+ const s = await t.submit();
29
+ if (s.isValid) {
30
+ n("valid-submit", s.payload);
31
+ return;
32
+ }
33
+ n("invalid-submit");
34
+ }, _ = () => {
35
+ t.reset(), n("reset");
36
+ };
37
+ return (s, a) => (i(), k("form", {
38
+ ref_key: "formRef",
39
+ ref: p,
40
+ novalidate: "",
41
+ onSubmit: g(C, ["prevent"])
42
+ }, [
43
+ u("fieldset", {
44
+ ref_key: "fieldsetRef",
45
+ ref: f,
46
+ class: "fkui-us-address",
47
+ onFocusout: a[0] || (a[0] = //@ts-ignore
48
+ (...P) => e(t).onFieldsetFocusout && e(t).onFieldsetFocusout(...P))
49
+ }, [
50
+ u("div", A, [
51
+ r(e(y), {
52
+ id: "address1",
53
+ placeholder: s.address1Placeholder,
54
+ value: e(t).formData.address1,
55
+ valid: e(t).address1Valid.value,
56
+ validate: e(t).addressValidate.value,
57
+ validityStyles: e(t).addressValidate.value,
58
+ onInput: e(t).onAddress1Input
59
+ }, null, 8, ["placeholder", "value", "valid", "validate", "validityStyles", "onInput"]),
60
+ e(t).address1Valid.value ? (i(), o(e(m), { key: 1 }, {
61
+ default: l(() => [...a[2] || (a[2] = [
62
+ d("Enter the street address including number.", -1)
63
+ ])]),
64
+ _: 1
65
+ })) : (i(), o(e(v), { key: 0 }, {
66
+ default: l(() => [...a[1] || (a[1] = [
67
+ d("Address 1 is required.", -1)
68
+ ])]),
69
+ _: 1
70
+ }))
71
+ ]),
72
+ s.showAddress2 ? (i(), k("div", E, [
73
+ r(e(y), {
74
+ id: "address2",
75
+ placeholder: s.address2Placeholder,
76
+ value: e(t).formData.address2,
77
+ onInput: e(t).onAddress2Input
78
+ }, null, 8, ["placeholder", "value", "onInput"]),
79
+ r(e(m), null, {
80
+ default: l(() => [...a[3] || (a[3] = [
81
+ d("This field is optional.", -1)
82
+ ])]),
83
+ _: 1
84
+ })
85
+ ])) : b("", !0),
86
+ u("div", F, [
87
+ r(e(y), {
88
+ id: "city",
89
+ placeholder: s.cityPlaceholder,
90
+ value: e(t).formData.city,
91
+ valid: e(t).cityValid.value,
92
+ validate: e(t).addressValidate.value,
93
+ validityStyles: e(t).addressValidate.value,
94
+ onInput: e(t).onCityInput
95
+ }, null, 8, ["placeholder", "value", "valid", "validate", "validityStyles", "onInput"]),
96
+ e(t).cityValid.value ? b("", !0) : (i(), o(e(v), { key: 0 }, {
97
+ default: l(() => [...a[4] || (a[4] = [
98
+ d("City is required.", -1)
99
+ ])]),
100
+ _: 1
101
+ }))
102
+ ]),
103
+ u("div", B, [
104
+ r(e(w), {
105
+ id: "state",
106
+ value: e(t).formData.state,
107
+ onChange: e(t).onStateChange,
108
+ defaultItem: e(t).stateDefaultItem,
109
+ dataItems: e(t).stateOptions,
110
+ textField: "label",
111
+ valueField: "value",
112
+ dataItemKey: "value",
113
+ valuePrimitive: !0,
114
+ valid: e(t).stateValid.value,
115
+ validate: e(t).addressValidate.value,
116
+ validityStyles: e(t).addressValidate.value
117
+ }, null, 8, ["value", "onChange", "defaultItem", "dataItems", "valid", "validate", "validityStyles"]),
118
+ e(t).stateValid.value ? b("", !0) : (i(), o(e(v), { key: 0 }, {
119
+ default: l(() => [...a[5] || (a[5] = [
120
+ d("State is required.", -1)
121
+ ])]),
122
+ _: 1
123
+ }))
124
+ ]),
125
+ u("div", R, [
126
+ r(e(y), {
127
+ id: "zip",
128
+ placeholder: s.zipPlaceholder,
129
+ wrapperClass: e(t).zipWrapperClass,
130
+ value: e(t).zipDisplay.value,
131
+ onInput: e(t).onZipInput,
132
+ valid: e(t).zipValid.value,
133
+ validate: e(t).addressValidate.value,
134
+ validityStyles: e(t).addressValidate.value,
135
+ style: { width: "100%" }
136
+ }, null, 8, ["placeholder", "wrapperClass", "value", "onInput", "valid", "validate", "validityStyles"]),
137
+ e(t).zipValid.value ? (i(), o(e(m), { key: 1 }, {
138
+ default: l(() => [...a[7] || (a[7] = [
139
+ d("Please enter a 5 or 9 digit zip code.", -1)
140
+ ])]),
141
+ _: 1
142
+ })) : (i(), o(e(v), { key: 0 }, {
143
+ default: l(() => [...a[6] || (a[6] = [
144
+ d("Please enter a 5 or 9 digit zip code.", -1)
145
+ ])]),
146
+ _: 1
147
+ }))
148
+ ]),
149
+ u("div", L, [
150
+ e(t).addressValid.value ? (i(), o(e(m), { key: 1 }, {
151
+ default: l(() => [...a[9] || (a[9] = [
152
+ d("Please enter address information.", -1)
153
+ ])]),
154
+ _: 1
155
+ })) : (i(), o(e(v), { key: 0 }, {
156
+ default: l(() => [...a[8] || (a[8] = [
157
+ d(" Please fill out all required address fields. ", -1)
158
+ ])]),
159
+ _: 1
160
+ }))
161
+ ])
162
+ ], 544),
163
+ u("div", q, [
164
+ r(e(h), {
165
+ type: "submit",
166
+ fillMode: "solid",
167
+ themeColor: "primary"
168
+ }, {
169
+ default: l(() => [
170
+ d(S(s.submitLabel), 1)
171
+ ]),
172
+ _: 1
173
+ }),
174
+ r(e(h), {
175
+ type: "button",
176
+ fillMode: "outline",
177
+ themeColor: "primary",
178
+ onClick: _
179
+ }, {
180
+ default: l(() => [
181
+ d(S(s.resetLabel), 1)
182
+ ]),
183
+ _: 1
184
+ })
185
+ ])
186
+ ], 544));
187
+ }
188
+ }), M = (c, V) => {
189
+ const n = c.__vccOpts || c;
190
+ for (const [p, f] of V)
191
+ n[p] = f;
192
+ return n;
193
+ }, W = /* @__PURE__ */ M(N, [["__scopeId", "data-v-14bc6580"]]);
194
+ export {
195
+ W as USAddress
196
+ };
@@ -0,0 +1 @@
1
+ (function(d,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"),require("@progress/kendo-vue-buttons"),require("@featherk/composables/address")):typeof define=="function"&&define.amd?define(["exports","vue","@progress/kendo-vue-labels","@progress/kendo-vue-inputs","@progress/kendo-vue-dropdowns","@progress/kendo-vue-buttons","@featherk/composables/address"],e):(d=typeof globalThis<"u"?globalThis:d||self,e(d.FeatherKUi={},d.Vue,d.KendoVueLabels,d.KendoVueInputs,d.KendoVueDropdowns,d.KendoVueButtons,d.FeatherKComposablesAddress))})(this,(function(d,e,s,o,u,c,m){"use strict";const y={class:"address1"},V={key:0,class:"address2"},h={class:"city"},k={class:"state"},x={class:"zip"},N={class:"messages"},B={class:"demo-actions"},C=((f,p)=>{const l=f.__vccOpts||f;for(const[i,n]of p)l[i]=n;return l})(e.defineComponent({__name:"USAddress",props:{showAddress2:{type:Boolean,default:!0},submitLabel:{default:"Submit"},resetLabel:{default:"Reset"},address1Placeholder:{default:"Enter street address"},address2Placeholder:{default:"Enter address line 2 (Optional)"},cityPlaceholder:{default:"Enter city"},zipPlaceholder:{default:"00000-0000"}},emits:["valid-submit","invalid-submit","reset"],setup(f,{emit:p}){const l=p,i=e.ref(null),n=e.ref(null),t=m.useUSAddress({formRef:i,fieldsetRef:n}),w=async()=>{const a=await t.submit();if(a.isValid){l("valid-submit",a.payload);return}l("invalid-submit")},S=()=>{t.reset(),l("reset")};return(a,r)=>(e.openBlock(),e.createElementBlock("form",{ref_key:"formRef",ref:i,novalidate:"",onSubmit:e.withModifiers(w,["prevent"])},[e.createElementVNode("fieldset",{ref_key:"fieldsetRef",ref:n,class:"fkui-us-address",onFocusout:r[0]||(r[0]=(...T)=>e.unref(t).onFieldsetFocusout&&e.unref(t).onFieldsetFocusout(...T))},[e.createElementVNode("div",y,[e.createVNode(e.unref(o.TextBox),{id:"address1",placeholder:a.address1Placeholder,value:e.unref(t).formData.address1,valid:e.unref(t).address1Valid.value,validate:e.unref(t).addressValidate.value,validityStyles:e.unref(t).addressValidate.value,onInput:e.unref(t).onAddress1Input},null,8,["placeholder","value","valid","validate","validityStyles","onInput"]),e.unref(t).address1Valid.value?(e.openBlock(),e.createBlock(e.unref(s.Hint),{key:1},{default:e.withCtx(()=>[...r[2]||(r[2]=[e.createTextVNode("Enter the street address including number.",-1)])]),_:1})):(e.openBlock(),e.createBlock(e.unref(s.Error),{key:0},{default:e.withCtx(()=>[...r[1]||(r[1]=[e.createTextVNode("Address 1 is required.",-1)])]),_:1}))]),a.showAddress2?(e.openBlock(),e.createElementBlock("div",V,[e.createVNode(e.unref(o.TextBox),{id:"address2",placeholder:a.address2Placeholder,value:e.unref(t).formData.address2,onInput:e.unref(t).onAddress2Input},null,8,["placeholder","value","onInput"]),e.createVNode(e.unref(s.Hint),null,{default:e.withCtx(()=>[...r[3]||(r[3]=[e.createTextVNode("This field is optional.",-1)])]),_:1})])):e.createCommentVNode("",!0),e.createElementVNode("div",h,[e.createVNode(e.unref(o.TextBox),{id:"city",placeholder:a.cityPlaceholder,value:e.unref(t).formData.city,valid:e.unref(t).cityValid.value,validate:e.unref(t).addressValidate.value,validityStyles:e.unref(t).addressValidate.value,onInput:e.unref(t).onCityInput},null,8,["placeholder","value","valid","validate","validityStyles","onInput"]),e.unref(t).cityValid.value?e.createCommentVNode("",!0):(e.openBlock(),e.createBlock(e.unref(s.Error),{key:0},{default:e.withCtx(()=>[...r[4]||(r[4]=[e.createTextVNode("City is required.",-1)])]),_:1}))]),e.createElementVNode("div",k,[e.createVNode(e.unref(u.DropDownList),{id:"state",value:e.unref(t).formData.state,onChange:e.unref(t).onStateChange,defaultItem:e.unref(t).stateDefaultItem,dataItems:e.unref(t).stateOptions,textField:"label",valueField:"value",dataItemKey:"value",valuePrimitive:!0,valid:e.unref(t).stateValid.value,validate:e.unref(t).addressValidate.value,validityStyles:e.unref(t).addressValidate.value},null,8,["value","onChange","defaultItem","dataItems","valid","validate","validityStyles"]),e.unref(t).stateValid.value?e.createCommentVNode("",!0):(e.openBlock(),e.createBlock(e.unref(s.Error),{key:0},{default:e.withCtx(()=>[...r[5]||(r[5]=[e.createTextVNode("State is required.",-1)])]),_:1}))]),e.createElementVNode("div",x,[e.createVNode(e.unref(o.TextBox),{id:"zip",placeholder:a.zipPlaceholder,wrapperClass:e.unref(t).zipWrapperClass,value:e.unref(t).zipDisplay.value,onInput:e.unref(t).onZipInput,valid:e.unref(t).zipValid.value,validate:e.unref(t).addressValidate.value,validityStyles:e.unref(t).addressValidate.value,style:{width:"100%"}},null,8,["placeholder","wrapperClass","value","onInput","valid","validate","validityStyles"]),e.unref(t).zipValid.value?(e.openBlock(),e.createBlock(e.unref(s.Hint),{key:1},{default:e.withCtx(()=>[...r[7]||(r[7]=[e.createTextVNode("Please enter a 5 or 9 digit zip code.",-1)])]),_:1})):(e.openBlock(),e.createBlock(e.unref(s.Error),{key:0},{default:e.withCtx(()=>[...r[6]||(r[6]=[e.createTextVNode("Please enter a 5 or 9 digit zip code.",-1)])]),_:1}))]),e.createElementVNode("div",N,[e.unref(t).addressValid.value?(e.openBlock(),e.createBlock(e.unref(s.Hint),{key:1},{default:e.withCtx(()=>[...r[9]||(r[9]=[e.createTextVNode("Please enter address information.",-1)])]),_:1})):(e.openBlock(),e.createBlock(e.unref(s.Error),{key:0},{default:e.withCtx(()=>[...r[8]||(r[8]=[e.createTextVNode(" Please fill out all required address fields. ",-1)])]),_:1}))])],544),e.createElementVNode("div",B,[e.createVNode(e.unref(c.Button),{type:"submit",fillMode:"solid",themeColor:"primary"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(a.submitLabel),1)]),_:1}),e.createVNode(e.unref(c.Button),{type:"button",fillMode:"outline",themeColor:"primary",onClick:S},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(a.resetLabel),1)]),_:1})])],544))}}),[["__scopeId","data-v-14bc6580"]]);d.USAddress=C,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}));
@@ -0,0 +1 @@
1
+ export * from "./address";
package/dist/ui.css ADDED
@@ -0,0 +1 @@
1
+ .fkui-us-address[data-v-14bc6580]{display:grid;grid-template-columns:2fr 1fr 1fr;grid-template-areas:"address1 address1 address1" "address2 address2 address2" "city state zip" "messages messages messages";gap:.75rem;padding:1rem}.fkui-us-address .address1[data-v-14bc6580]{grid-area:address1}.fkui-us-address .address2[data-v-14bc6580]{grid-area:address2}.fkui-us-address .city[data-v-14bc6580]{grid-area:city}.fkui-us-address .state[data-v-14bc6580]{grid-area:state}.fkui-us-address .zip[data-v-14bc6580]{grid-area:zip}.fkui-us-address .messages[data-v-14bc6580]{grid-area:messages}.fkui-us-address [data-v-14bc6580] .fk-zip-textbox{min-width:100%}[data-v-14bc6580] .demo-actions{min-height:4rem;align-items:center;flex:1 0 2rem}
package/docs/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @featherk/ui Docs Authoring
2
+
3
+ Use this structure when adding docs for a new UI component.
4
+
5
+ ## Folder Layout
6
+
7
+ - Place docs under `docs/<domain>/<ComponentName>.md`
8
+ - Example: `docs/address/USAddress.md`
9
+
10
+ ## Component Doc Template
11
+
12
+ Copy this template for each new component guide.
13
+
14
+ ```md
15
+ # `<ComponentName>`
16
+
17
+ `<ComponentName>` is a short one-sentence description.
18
+
19
+ ## Import
20
+
21
+ ```ts
22
+ import { <ComponentName> } from "@featherk/ui";
23
+ ```
24
+
25
+ ## Basic Usage
26
+
27
+ ```vue
28
+ <script setup lang="ts">
29
+ import { <ComponentName> } from "@featherk/ui";
30
+ </script>
31
+
32
+ <template>
33
+ <<ComponentName> />
34
+ </template>
35
+ ```
36
+
37
+ ## Props
38
+
39
+ - `<propName>?: <type>` (default: `<value>`)
40
+
41
+ ## Events
42
+
43
+ - `<event-name>`: what it emits and when
44
+
45
+ ## Notes
46
+
47
+ - Any runtime requirements
48
+ - Any accessibility behavior
49
+ - Any styling behavior
50
+ ```
51
+
52
+ ## Checklist for New Components
53
+
54
+ - Add component guide at `docs/<domain>/<ComponentName>.md`
55
+ - Add guide link under Components Overview in `packages/ui/README.md`
56
+ - Ensure component is exported from `packages/ui/src/index.ts`
57
+ - Keep runtime entry at root (`@featherk/ui`) unless subpath runtime entrypoints are intentionally added
58
+ - Run `npx turbo build --filter=@featherk/ui`
@@ -0,0 +1,68 @@
1
+ # `USAddress`
2
+
3
+ `USAddress` is a ready-to-use US address form component for Vue 3 and Kendo UI for Vue.
4
+
5
+ It is powered by `useUSAddress` from `@featherk/composables/address` and includes:
6
+
7
+ - Required field validation for Address 1, City, State, and ZIP
8
+ - Optional Address 2
9
+ - ZIP formatting/validation behavior via `useZipTextBox`
10
+ - Delayed fieldset validation orchestration via `useFieldsetValidationKit`
11
+ - Normalized submit payloads via `valid-submit`
12
+
13
+ ## Import
14
+
15
+ ```ts
16
+ import { USAddress } from "@featherk/ui";
17
+ import type { USAddressSubmitPayload } from "@featherk/composables/address";
18
+ ```
19
+
20
+ ## Basic Usage
21
+
22
+ ```vue
23
+ <script setup lang="ts">
24
+ import { USAddress } from "@featherk/ui";
25
+ import type { USAddressSubmitPayload } from "@featherk/composables/address";
26
+
27
+ function onValidSubmit(payload: USAddressSubmitPayload) {
28
+ console.log("valid", payload);
29
+ }
30
+
31
+ function onInvalidSubmit() {
32
+ console.log("invalid");
33
+ }
34
+
35
+ function onReset() {
36
+ console.log("reset");
37
+ }
38
+ </script>
39
+
40
+ <template>
41
+ <USAddress
42
+ @valid-submit="onValidSubmit"
43
+ @invalid-submit="onInvalidSubmit"
44
+ @reset="onReset"
45
+ />
46
+ </template>
47
+ ```
48
+
49
+ ## Props
50
+
51
+ - `showAddress2?: boolean` (default: `true`)
52
+ - `submitLabel?: string` (default: `"Submit"`)
53
+ - `resetLabel?: string` (default: `"Reset"`)
54
+ - `address1Placeholder?: string` (default: `"Enter street address"`)
55
+ - `address2Placeholder?: string` (default: `"Enter address line 2 (Optional)"`)
56
+ - `cityPlaceholder?: string` (default: `"Enter city"`)
57
+ - `zipPlaceholder?: string` (default: `"00000-0000"`)
58
+
59
+ ## Events
60
+
61
+ - `valid-submit`: emits `USAddressSubmitPayload` when submit succeeds
62
+ - `invalid-submit`: emits when submit fails validation
63
+ - `reset`: emits after reset action
64
+
65
+ ## Notes
66
+
67
+ - Component styles are delivered automatically from the package ESM entry.
68
+ - `USAddress` uses Kendo UI inputs/buttons/labels/dropdowns as peer dependencies of `@featherk/ui`.
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@featherk/ui",
3
+ "version": "0.9.0",
4
+ "main": "dist/featherk-ui.umd.js",
5
+ "module": "dist/featherk-ui.es.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "docs"
10
+ ],
11
+ "scripts": {
12
+ "build": "vite build && node ./scripts/inject-css-into-esm.mjs && npm run build:types",
13
+ "build:types": "vue-tsc --emitDeclarationOnly --declaration --declarationDir dist",
14
+ "test": "vitest --config vitest.config.ts",
15
+ "test:unit": "vitest run --config vitest.config.ts",
16
+ "test:coverage": "vitest run --config vitest.config.ts --coverage",
17
+ "clean": "rm -rf dist",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "peerDependencies": {
21
+ "vue": ">=3.0.0",
22
+ "@featherk/composables": ">=0.8.2",
23
+ "@progress/kendo-vue-buttons": "^6.4.1",
24
+ "@progress/kendo-vue-dropdowns": "^6.4.1",
25
+ "@progress/kendo-vue-inputs": "^6.4.1",
26
+ "@progress/kendo-vue-labels": "^6.4.1"
27
+ },
28
+ "devDependencies": {
29
+ "@featherk/composables": "file:../composables",
30
+ "@types/node": "^24.5.2",
31
+ "@vitejs/plugin-vue": "^6.0.1",
32
+ "@vue/test-utils": "^2.4.6",
33
+ "typescript": "~5.8.3",
34
+ "vite": "^7.1.7",
35
+ "vitest": "^4.1.10",
36
+ "vue-tsc": "^3.0.7"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "keywords": [
42
+ "vue",
43
+ "kendo",
44
+ "components",
45
+ "ui",
46
+ "address"
47
+ ],
48
+ "license": "MIT"
49
+ }