jcicl 1.0.28 → 1.0.30
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/FormContext/createFormContext.d.ts +32 -0
- package/FormContext/createFormContext.js +74 -0
- package/FormContext/index.d.ts +2 -0
- package/FormContext/index.js +5 -0
- package/FormContext/types.d.ts +53 -0
- package/FormContext/types.js +1 -0
- package/FormFields/FormFields.js +40 -40
- package/LabeledDropdown/LabeledDropdown.js +2 -2
- package/Toast/index.d.ts +1 -0
- package/Toast/index.js +8 -6
- package/Toast/useToast.d.ts +23 -0
- package/Toast/useToast.js +10 -0
- package/index.d.ts +1 -0
- package/index.js +41 -38
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FormContextOptions, FormContextResult, InputChangeExtension } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Factory function to create a typed form context with shared functionality.
|
|
4
|
+
* Fixes the stale closure bug by computing all values inside the functional update.
|
|
5
|
+
*
|
|
6
|
+
* @template T - The type of form data this context will manage
|
|
7
|
+
* @param options - Configuration options for the form context
|
|
8
|
+
* @returns Object containing the Context and Provider
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* interface MyFormData {
|
|
13
|
+
* name: string;
|
|
14
|
+
* email: string;
|
|
15
|
+
* [key: string]: unknown; // Required for FormFields compatibility
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* const { Context: MyFormContext, Provider: MyFormProvider } = createFormContext<MyFormData>({
|
|
19
|
+
* name: 'MyForm',
|
|
20
|
+
* defaultValues: { name: '', email: '' },
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function createFormContext<T extends Record<string, unknown>>(options: FormContextOptions<T>): FormContextResult<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a DOB → Age autofill extension.
|
|
27
|
+
* When dateOfBirth field changes, automatically calculates and sets age.
|
|
28
|
+
*
|
|
29
|
+
* @param dobKey - The form field key for date of birth (default: 'dateOfBirth')
|
|
30
|
+
* @param ageKey - The form field key for age (default: 'age')
|
|
31
|
+
*/
|
|
32
|
+
export declare function createDobToAgeExtension<T extends Record<string, unknown>>(dobKey?: keyof T & string, ageKey?: keyof T & string): InputChangeExtension<T>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as N } from "react/jsx-runtime";
|
|
2
|
+
import { createContext as w, useState as E, useEffect as P, useMemo as $ } from "react";
|
|
3
|
+
import { formatPhoneNumber as C } from "../utils.js";
|
|
4
|
+
function I(b) {
|
|
5
|
+
const { name: n, defaultValues: s = {}, onInputChangeExtensions: u = [], submit: m, debug: a = !1 } = b, i = w({
|
|
6
|
+
onFormInputChange: () => console.error(`Failed to update form input. ${n}FormContext not initialized`),
|
|
7
|
+
formData: s,
|
|
8
|
+
setFormData: () => console.error(`Failed to set form data. ${n}FormContext not initialized`),
|
|
9
|
+
resetForm: () => console.error(`Failed to reset form. ${n}FormContext not initialized`)
|
|
10
|
+
});
|
|
11
|
+
return { Context: i, Provider: ({ children: x }) => {
|
|
12
|
+
const [e, r] = E(s), d = (g, t, c) => {
|
|
13
|
+
r((l) => {
|
|
14
|
+
let o;
|
|
15
|
+
if (c === "checkbox")
|
|
16
|
+
o = t.target.checked;
|
|
17
|
+
else if (c === "multiDropdown") {
|
|
18
|
+
const h = t.target.value;
|
|
19
|
+
Array.isArray(h) ? o = h.map((D) => D.value) : o = [];
|
|
20
|
+
} else if (c === "phone") {
|
|
21
|
+
const [, h] = C(t.target.value);
|
|
22
|
+
o = h;
|
|
23
|
+
} else
|
|
24
|
+
o = t.target.value;
|
|
25
|
+
return o === "undefined" && (o = void 0), { ...l, [g]: o };
|
|
26
|
+
});
|
|
27
|
+
let p;
|
|
28
|
+
if (c === "checkbox")
|
|
29
|
+
p = t.target.checked;
|
|
30
|
+
else if (c === "phone") {
|
|
31
|
+
const [, l] = C(t.target.value);
|
|
32
|
+
p = l;
|
|
33
|
+
} else
|
|
34
|
+
p = t.target.value === "undefined" ? void 0 : t.target.value;
|
|
35
|
+
u.forEach((l) => {
|
|
36
|
+
l(g, p, r);
|
|
37
|
+
});
|
|
38
|
+
}, v = () => r(s);
|
|
39
|
+
P(() => {
|
|
40
|
+
a && console.log(`[${n}Form] Updated form data:`, e);
|
|
41
|
+
}, [e]);
|
|
42
|
+
const f = $(
|
|
43
|
+
() => ({
|
|
44
|
+
onFormInputChange: d,
|
|
45
|
+
formData: e,
|
|
46
|
+
setFormData: r,
|
|
47
|
+
resetForm: v,
|
|
48
|
+
...m ? { submit: () => m(e) } : {}
|
|
49
|
+
}),
|
|
50
|
+
[e]
|
|
51
|
+
);
|
|
52
|
+
return /* @__PURE__ */ N(i.Provider, { value: f, children: x });
|
|
53
|
+
} };
|
|
54
|
+
}
|
|
55
|
+
function M(b = "dateOfBirth", n = "age") {
|
|
56
|
+
return (s, u, m) => {
|
|
57
|
+
if (s === b && u && typeof u == "string") {
|
|
58
|
+
const a = u.split("-");
|
|
59
|
+
if (a.length !== 3) return;
|
|
60
|
+
const i = Number(a[0]), F = Number(a[1]), x = Number(a[2]), e = /* @__PURE__ */ new Date(), r = e.getFullYear(), d = e.getMonth() + 1, v = e.getDate();
|
|
61
|
+
if (i > r || i < 1900)
|
|
62
|
+
return;
|
|
63
|
+
let f = r - i;
|
|
64
|
+
(F > d || F === d && x > v) && (f -= 1), m((g) => ({
|
|
65
|
+
...g,
|
|
66
|
+
[n]: String(f)
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
M as createDobToAgeExtension,
|
|
73
|
+
I as createFormContext
|
|
74
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Base form context properties that all form contexts share.
|
|
4
|
+
* @template T - The type of form data this context manages
|
|
5
|
+
*/
|
|
6
|
+
export interface FormContextProps<T extends Record<string, unknown>> {
|
|
7
|
+
/**
|
|
8
|
+
* Handler for form input changes - supports text, checkbox, multiDropdown, and phone types.
|
|
9
|
+
* Accepts any string key to maintain compatibility with FormFields component,
|
|
10
|
+
* but typed form data provides compile-time safety for direct property access.
|
|
11
|
+
*/
|
|
12
|
+
onFormInputChange: (key: string, e: React.ChangeEvent<HTMLInputElement>, type?: string) => void;
|
|
13
|
+
/** Current form data state */
|
|
14
|
+
formData: T;
|
|
15
|
+
/** Direct setter for form data (use sparingly - prefer onFormInputChange) */
|
|
16
|
+
setFormData: React.Dispatch<React.SetStateAction<T>>;
|
|
17
|
+
/** Reset form to initial/empty state */
|
|
18
|
+
resetForm: () => void;
|
|
19
|
+
/** Optional submit handler (if configured in factory) */
|
|
20
|
+
submit?: () => void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Extension function called after each input change.
|
|
24
|
+
* Use for side effects like auto-filling related fields (e.g., DOB → Age).
|
|
25
|
+
* @template T - The type of form data
|
|
26
|
+
*/
|
|
27
|
+
export type InputChangeExtension<T extends Record<string, unknown>> = (key: string, value: unknown, setFormData: React.Dispatch<React.SetStateAction<T>>) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Configuration options for creating a form context.
|
|
30
|
+
* @template T - The type of form data this context will manage
|
|
31
|
+
*/
|
|
32
|
+
export interface FormContextOptions<T extends Record<string, unknown>> {
|
|
33
|
+
/** Name for the context (used in error messages) */
|
|
34
|
+
name: string;
|
|
35
|
+
/** Default/initial values for the form */
|
|
36
|
+
defaultValues?: Partial<T>;
|
|
37
|
+
/** Extensions called after each input change (e.g., DOB→Age autofill) */
|
|
38
|
+
onInputChangeExtensions?: InputChangeExtension<T>[];
|
|
39
|
+
/** Custom submit function */
|
|
40
|
+
submit?: (formData: T) => void;
|
|
41
|
+
/** Enable debug logging of form data changes */
|
|
42
|
+
debug?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Return type from createFormContext factory.
|
|
46
|
+
* @template T - The type of form data
|
|
47
|
+
*/
|
|
48
|
+
export interface FormContextResult<T extends Record<string, unknown>> {
|
|
49
|
+
/** The React Context object */
|
|
50
|
+
Context: React.Context<FormContextProps<T>>;
|
|
51
|
+
/** Provider component that wraps children with form state */
|
|
52
|
+
Provider: React.FC<PropsWithChildren>;
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
package/FormFields/FormFields.js
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { FormInput as
|
|
3
|
-
import { FormSectionTitle as
|
|
4
|
-
import
|
|
5
|
-
import { u as
|
|
6
|
-
const
|
|
7
|
-
title:
|
|
8
|
-
fields:
|
|
9
|
-
columns:
|
|
10
|
-
columnsOverride:
|
|
11
|
-
gap:
|
|
12
|
-
noLabel:
|
|
13
|
-
checkboxContainer:
|
|
14
|
-
formDefaults:
|
|
15
|
-
onChange:
|
|
16
|
-
}) => /* @__PURE__ */
|
|
17
|
-
|
|
18
|
-
!
|
|
19
|
-
const
|
|
20
|
-
return /* @__PURE__ */
|
|
21
|
-
|
|
1
|
+
import { jsxs as f, Fragment as D, jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import { FormInput as p } from "../FormInput/FormInput.js";
|
|
3
|
+
import { FormSectionTitle as g, FormFieldGrid as j, FormFieldCheckboxContainer as C } from "../FormComponents/FormComponents.js";
|
|
4
|
+
import S from "../theme.js";
|
|
5
|
+
import { u as z } from "../.chunks/useMediaQuery.js";
|
|
6
|
+
const V = ({
|
|
7
|
+
title: a,
|
|
8
|
+
fields: h,
|
|
9
|
+
columns: v = z(`(max-width: ${S.screenSizes.tablet})`) ? 2 : 3,
|
|
10
|
+
columnsOverride: w,
|
|
11
|
+
gap: b = 21,
|
|
12
|
+
noLabel: s = !1,
|
|
13
|
+
checkboxContainer: F = !1,
|
|
14
|
+
formDefaults: c,
|
|
15
|
+
onChange: x
|
|
16
|
+
}) => /* @__PURE__ */ f(D, { children: [
|
|
17
|
+
a && /* @__PURE__ */ n(g, { children: a }),
|
|
18
|
+
!F && /* @__PURE__ */ n(j, { columns: v, columnsOverride: w, gap: b, children: h.map(({ key: r, label: e, type: o, limit: d, options: l, defaultValue: i, ...u }) => {
|
|
19
|
+
const m = c[r] !== void 0 ? c[r] : i !== void 0 ? i : o === "multiDropdown" ? [] : o === "checkbox" ? !1 : "";
|
|
20
|
+
return /* @__PURE__ */ n(
|
|
21
|
+
p,
|
|
22
22
|
{
|
|
23
|
-
onChange: (
|
|
24
|
-
label:
|
|
23
|
+
onChange: (t) => x(r, t, o),
|
|
24
|
+
label: e,
|
|
25
25
|
type: o,
|
|
26
|
-
limit:
|
|
27
|
-
value:
|
|
28
|
-
noLabel:
|
|
29
|
-
options:
|
|
26
|
+
limit: d,
|
|
27
|
+
...o === "checkbox" ? { checked: !!m } : { value: m },
|
|
28
|
+
noLabel: s,
|
|
29
|
+
options: l,
|
|
30
30
|
multiple: o === "multiDropdown",
|
|
31
|
-
...
|
|
31
|
+
...u
|
|
32
32
|
},
|
|
33
33
|
r
|
|
34
34
|
);
|
|
35
35
|
}) }),
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
return /* @__PURE__ */
|
|
39
|
-
|
|
36
|
+
F && /* @__PURE__ */ n(C, { children: h.map(({ key: r, label: e, type: o, limit: d, options: l, defaultValue: i, ...u }) => {
|
|
37
|
+
const m = c[r] !== void 0 ? c[r] : i !== void 0 ? i : o === "multiDropdown" ? [] : o === "checkbox" ? !1 : "";
|
|
38
|
+
return /* @__PURE__ */ n(
|
|
39
|
+
p,
|
|
40
40
|
{
|
|
41
|
-
onChange: (
|
|
42
|
-
label:
|
|
41
|
+
onChange: (t) => x(r, t, o),
|
|
42
|
+
label: e,
|
|
43
43
|
type: o,
|
|
44
|
-
limit:
|
|
45
|
-
defaultValue:
|
|
46
|
-
noLabel:
|
|
47
|
-
options:
|
|
44
|
+
limit: d,
|
|
45
|
+
...o === "checkbox" ? { checked: !!m } : { defaultValue: m },
|
|
46
|
+
noLabel: s,
|
|
47
|
+
options: l,
|
|
48
48
|
multiple: o === "multiDropdown",
|
|
49
|
-
...
|
|
49
|
+
...u
|
|
50
50
|
},
|
|
51
51
|
r
|
|
52
52
|
);
|
|
53
53
|
}) })
|
|
54
54
|
] });
|
|
55
55
|
export {
|
|
56
|
-
|
|
56
|
+
V as default
|
|
57
57
|
};
|
|
@@ -2694,8 +2694,8 @@ const Et = ["colon", "borderFocusColor", "minWidth", "noLabel"], zt = Yo("div",
|
|
|
2694
2694
|
{
|
|
2695
2695
|
options: a,
|
|
2696
2696
|
onChange: (m, w) => (
|
|
2697
|
-
// @ts-ignore
|
|
2698
|
-
h && h({ ...m, target: { ...m.target, value:
|
|
2697
|
+
// @ts-ignore - Fix: Use nullish coalescing to avoid "undefined" string
|
|
2698
|
+
h && h({ ...m, target: { ...m.target, value: (w == null ? void 0 : w.value) ?? "" } })
|
|
2699
2699
|
),
|
|
2700
2700
|
...P,
|
|
2701
2701
|
renderInput: (m) => /* @__PURE__ */ T(zo, { ...m })
|
package/Toast/index.d.ts
CHANGED
package/Toast/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { default as e } from "./Toast.js";
|
|
2
|
-
import { Toaster as
|
|
3
|
-
import { handleDismissToast as T, saveToastForRedirect as
|
|
2
|
+
import { Toaster as r } from "./Toaster.js";
|
|
3
|
+
import { handleDismissToast as T, saveToastForRedirect as f, showSavedToast as m, showToast as d } from "./ToastHelpers.js";
|
|
4
|
+
import { useToast as x } from "./useToast.js";
|
|
4
5
|
export {
|
|
5
|
-
|
|
6
|
+
r as Toaster,
|
|
6
7
|
e as default,
|
|
7
8
|
T as handleDismissToast,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
f as saveToastForRedirect,
|
|
10
|
+
m as showSavedToast,
|
|
11
|
+
d as showToast,
|
|
12
|
+
x as useToast
|
|
11
13
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ToastProps } from './Toast';
|
|
2
|
+
import { ToastItem } from './Toaster';
|
|
3
|
+
/**
|
|
4
|
+
* Hook for managing toast notifications.
|
|
5
|
+
* Encapsulates toast state management and provides a simple API.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* const { toasts, toast, dismissToast } = useToast();
|
|
10
|
+
*
|
|
11
|
+
* // Show a toast
|
|
12
|
+
* toast({ type: 'success', message: 'Saved!', duration: 3000 });
|
|
13
|
+
*
|
|
14
|
+
* // In render
|
|
15
|
+
* <Toaster toastQueue={toasts} onDismiss={dismissToast} />
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare const useToast: () => {
|
|
19
|
+
toasts: ToastItem[];
|
|
20
|
+
toast: (toastProps: ToastProps) => void;
|
|
21
|
+
dismissToast: (id: number) => void;
|
|
22
|
+
};
|
|
23
|
+
export default useToast;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useState as a } from "react";
|
|
2
|
+
import { handleDismissToast as e, showToast as i } from "./ToastHelpers.js";
|
|
3
|
+
const c = () => {
|
|
4
|
+
const [o, t] = a([]);
|
|
5
|
+
return { toasts: o, toast: (s) => i(s, t), dismissToast: (s) => e(s, t) };
|
|
6
|
+
};
|
|
7
|
+
export {
|
|
8
|
+
c as default,
|
|
9
|
+
c as useToast
|
|
10
|
+
};
|
package/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { default as LabeledValue } from './LabeledValue';
|
|
|
9
9
|
export { default as ListButton } from './ListButton';
|
|
10
10
|
export { default as Loading } from './Loading';
|
|
11
11
|
export { default as ScrollContainer } from './ScrollContainer';
|
|
12
|
+
export * from './FormContext';
|
|
12
13
|
export { default as Accordion } from './Accordion';
|
|
13
14
|
export { default as ErrorBoundary } from './ErrorBoundary';
|
|
14
15
|
export { default as InfoCard } from './InfoCard';
|
package/index.js
CHANGED
|
@@ -1,52 +1,55 @@
|
|
|
1
|
-
import { AvatarWithImage as
|
|
1
|
+
import { AvatarWithImage as e } from "./AvatarWithImage/AvatarWithImage.js";
|
|
2
2
|
import { Button as a } from "./Button/Button.js";
|
|
3
3
|
import { Divider as p } from "./Divider/Divider.js";
|
|
4
|
-
import { Flex as
|
|
5
|
-
import { Grid as
|
|
4
|
+
import { Flex as m } from "./Flex/Flex.js";
|
|
5
|
+
import { Grid as n } from "./Grid/Grid.js";
|
|
6
6
|
import { default as i } from "./Icon/Icon.js";
|
|
7
7
|
import { Input as s } from "./Input/Input.js";
|
|
8
|
-
import { LabeledValue as
|
|
9
|
-
import { default as
|
|
8
|
+
import { LabeledValue as c } from "./LabeledValue/LabeledValue.js";
|
|
9
|
+
import { default as I } from "./ListButton/ListButton.js";
|
|
10
10
|
import { default as g } from "./Loading/Loading.js";
|
|
11
|
-
import { default as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
11
|
+
import { default as B } from "./ScrollContainer/ScrollContainer.js";
|
|
12
|
+
import { createDobToAgeExtension as v, createFormContext as E } from "./FormContext/createFormContext.js";
|
|
13
|
+
import { Accordion as D } from "./Accordion/Accordion.js";
|
|
14
|
+
import { default as S } from "./ErrorBoundary/ErrorBoundary.js";
|
|
14
15
|
import { InfoCard as y } from "./InfoCard/InfoCard.js";
|
|
15
|
-
import { LabeledInput as
|
|
16
|
-
import { default as
|
|
17
|
-
import { default as
|
|
18
|
-
import { SiteBanner as
|
|
19
|
-
import { Tooltip as
|
|
20
|
-
import { default as
|
|
21
|
-
import { default as
|
|
22
|
-
import { A as
|
|
23
|
-
import { EditableInfoCard as
|
|
24
|
-
import { Nav as
|
|
25
|
-
import { default as
|
|
16
|
+
import { LabeledInput as H } from "./LabeledInput/LabeledInput.js";
|
|
17
|
+
import { default as V } from "./List/List.js";
|
|
18
|
+
import { default as k } from "./LogoLoop/LogoLoop.js";
|
|
19
|
+
import { SiteBanner as w } from "./SiteBanner/SiteBanner.js";
|
|
20
|
+
import { Tooltip as J } from "./Tooltip/Tooltip.js";
|
|
21
|
+
import { default as M } from "./WithLabel/WithLabel.js";
|
|
22
|
+
import { default as P } from "./WithLoading/WithLoading.js";
|
|
23
|
+
import { A as R } from "./.chunks/AppHeader.js";
|
|
24
|
+
import { EditableInfoCard as X } from "./EditableInfoCard/EditableInfoCard.js";
|
|
25
|
+
import { Nav as Z } from "./Nav/Nav.js";
|
|
26
|
+
import { default as $ } from "./AppContainer/AppContainer.js";
|
|
26
27
|
export {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
D as Accordion,
|
|
29
|
+
$ as AppContainer,
|
|
30
|
+
R as AppHeader,
|
|
31
|
+
e as AvatarWithImage,
|
|
31
32
|
a as Button,
|
|
32
33
|
p as Divider,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
X as EditableInfoCard,
|
|
35
|
+
S as ErrorBoundary,
|
|
36
|
+
m as Flex,
|
|
37
|
+
n as Grid,
|
|
37
38
|
i as Icon,
|
|
38
39
|
y as InfoCard,
|
|
39
40
|
s as Input,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
H as LabeledInput,
|
|
42
|
+
c as LabeledValue,
|
|
43
|
+
V as List,
|
|
44
|
+
I as ListButton,
|
|
44
45
|
g as Loading,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
k as LogoLoop,
|
|
47
|
+
Z as Nav,
|
|
48
|
+
B as ScrollContainer,
|
|
49
|
+
w as SiteBanner,
|
|
50
|
+
J as Tooltip,
|
|
51
|
+
M as WithLabel,
|
|
52
|
+
P as WithLoading,
|
|
53
|
+
v as createDobToAgeExtension,
|
|
54
|
+
E as createFormContext
|
|
52
55
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jcicl",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.30",
|
|
5
5
|
"description": "Component library for the websites of Johnson County Iowa",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://devops.jc.net/JCIT/Business%20Solutions%20Delivery/_git/JCComponentLibrary?path=%2FREADME.md&version=GBmaster",
|