kayforms 0.1.1

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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +337 -0
  3. package/examples/react-demo/README.md +337 -0
  4. package/examples/react-demo/eslint.config.js +22 -0
  5. package/examples/react-demo/index.html +13 -0
  6. package/examples/react-demo/package.json +33 -0
  7. package/examples/react-demo/public/apple-touch-icon.png +0 -0
  8. package/examples/react-demo/public/favicon-96x96.png +0 -0
  9. package/examples/react-demo/public/favicon.ico +0 -0
  10. package/examples/react-demo/public/favicon.svg +17 -0
  11. package/examples/react-demo/public/icons.svg +24 -0
  12. package/examples/react-demo/public/site.webmanifest +21 -0
  13. package/examples/react-demo/public/web-app-manifest-192x192.png +0 -0
  14. package/examples/react-demo/public/web-app-manifest-512x512.png +0 -0
  15. package/examples/react-demo/src/App.css +184 -0
  16. package/examples/react-demo/src/App.tsx +825 -0
  17. package/examples/react-demo/src/assets/hero.png +0 -0
  18. package/examples/react-demo/src/assets/react.svg +1 -0
  19. package/examples/react-demo/src/assets/vite.svg +1 -0
  20. package/examples/react-demo/src/index.css +627 -0
  21. package/examples/react-demo/src/main.tsx +10 -0
  22. package/examples/react-demo/tsconfig.app.json +25 -0
  23. package/examples/react-demo/tsconfig.json +7 -0
  24. package/examples/react-demo/tsconfig.node.json +24 -0
  25. package/examples/react-demo/vite.config.ts +7 -0
  26. package/kayforms.jpg +0 -0
  27. package/package.json +26 -0
  28. package/packages/angular/package.json +43 -0
  29. package/packages/angular/src/index.ts +198 -0
  30. package/packages/angular/tsconfig.json +8 -0
  31. package/packages/angular/tsup.config.ts +17 -0
  32. package/packages/core/README.md +337 -0
  33. package/packages/core/package.json +37 -0
  34. package/packages/core/src/batch.ts +106 -0
  35. package/packages/core/src/devtools.ts +329 -0
  36. package/packages/core/src/field.ts +167 -0
  37. package/packages/core/src/form.ts +448 -0
  38. package/packages/core/src/index.ts +71 -0
  39. package/packages/core/src/registry.ts +126 -0
  40. package/packages/core/src/signal.ts +399 -0
  41. package/packages/core/src/time-travel.ts +275 -0
  42. package/packages/core/src/validation.ts +243 -0
  43. package/packages/core/tsconfig.json +8 -0
  44. package/packages/core/tsup.config.ts +16 -0
  45. package/packages/devtools/extension/background.js +35 -0
  46. package/packages/devtools/extension/content-script.js +10 -0
  47. package/packages/devtools/extension/devtools.html +9 -0
  48. package/packages/devtools/extension/devtools.js +8 -0
  49. package/packages/devtools/extension/manifest.json +19 -0
  50. package/packages/devtools/extension/panel.css +505 -0
  51. package/packages/devtools/extension/panel.html +108 -0
  52. package/packages/devtools/extension/panel.js +354 -0
  53. package/packages/devtools/package.json +38 -0
  54. package/packages/devtools/src/index.ts +95 -0
  55. package/packages/devtools/src/panel.ts +226 -0
  56. package/packages/devtools/src/styles.ts +422 -0
  57. package/packages/devtools/src/timeline.ts +283 -0
  58. package/packages/devtools/tsconfig.json +8 -0
  59. package/packages/devtools/tsup.config.ts +17 -0
  60. package/packages/react/package.json +46 -0
  61. package/packages/react/src/index.ts +279 -0
  62. package/packages/react/tsconfig.json +8 -0
  63. package/packages/react/tsup.config.ts +17 -0
  64. package/packages/solid/package.json +42 -0
  65. package/packages/solid/src/index.ts +206 -0
  66. package/packages/solid/tsconfig.json +8 -0
  67. package/packages/solid/tsup.config.ts +17 -0
  68. package/packages/svelte/package.json +42 -0
  69. package/packages/svelte/src/index.ts +199 -0
  70. package/packages/svelte/tsconfig.json +8 -0
  71. package/packages/svelte/tsup.config.ts +17 -0
  72. package/packages/vanilla/package.json +38 -0
  73. package/packages/vanilla/src/index.ts +254 -0
  74. package/packages/vanilla/tsconfig.json +8 -0
  75. package/packages/vanilla/tsup.config.ts +17 -0
  76. package/packages/vue/package.json +42 -0
  77. package/packages/vue/src/index.ts +217 -0
  78. package/packages/vue/tsconfig.json +8 -0
  79. package/packages/vue/tsup.config.ts +17 -0
  80. package/pnpm-workspace.yaml +3 -0
  81. package/tsconfig.base.json +21 -0
@@ -0,0 +1,254 @@
1
+ // ============================================================================
2
+ // @kayforms/vanilla — Vanilla JS Adapter
3
+ // ============================================================================
4
+ // Binds Kayforms signal-based forms to plain DOM elements.
5
+ // Supports both programmatic binding and declarative data-attribute binding.
6
+ // ============================================================================
7
+
8
+ import {
9
+ createEffect,
10
+ type FormStore,
11
+ type FieldNode,
12
+ } from "@kayforms/core";
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Types
16
+ // ---------------------------------------------------------------------------
17
+
18
+ export interface BindFieldOptions {
19
+ /** Custom value extractor (default: el.value) */
20
+ getValue?: (el: HTMLElement) => unknown;
21
+ /** Custom value setter (default: el.value = ...) */
22
+ setValue?: (el: HTMLElement, value: unknown) => void;
23
+ /** CSS class to add when field has error */
24
+ errorClass?: string;
25
+ /** Element to display error message (created automatically if not provided) */
26
+ errorElement?: HTMLElement;
27
+ }
28
+
29
+ export interface BindFormOptions extends BindFieldOptions {
30
+ /** CSS class for error messages (default: 'kayform-error') */
31
+ errorClass?: string;
32
+ /** Whether to prevent default form submit (default: true) */
33
+ preventDefault?: boolean;
34
+ }
35
+
36
+ // ---------------------------------------------------------------------------
37
+ // bindField — Bind a single input to a FieldNode
38
+ // ---------------------------------------------------------------------------
39
+
40
+ /**
41
+ * Bind a DOM input element to a Kayforms FieldNode.
42
+ * Automatically syncs value, error state, and touched state.
43
+ * Returns an unbind function.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const form = createForm({ initialValues: { email: '' } });
48
+ * const emailInput = document.querySelector('#email');
49
+ * const unbind = bindField(emailInput, form.getField('email'));
50
+ * // Later: unbind();
51
+ * ```
52
+ */
53
+ export function bindField(
54
+ element: HTMLElement,
55
+ field: FieldNode,
56
+ options: BindFieldOptions = {}
57
+ ): () => void {
58
+ const {
59
+ getValue = (el) => (el as HTMLInputElement).value,
60
+ setValue = (el, v) => {
61
+ (el as HTMLInputElement).value = String(v ?? "");
62
+ },
63
+ errorClass = "kayform-error",
64
+ } = options;
65
+
66
+ const cleanups: (() => void)[] = [];
67
+
68
+ // --- Sync value: signal → DOM ---
69
+ const disposeValueEffect = createEffect(() => {
70
+ const val = field.value.value;
71
+ setValue(element, val);
72
+ });
73
+ cleanups.push(disposeValueEffect);
74
+
75
+ // --- Sync value: DOM → signal ---
76
+ const handleInput = () => {
77
+ const domValue = getValue(element);
78
+ field.onChange(domValue);
79
+ };
80
+ element.addEventListener("input", handleInput);
81
+ cleanups.push(() => element.removeEventListener("input", handleInput));
82
+
83
+ // For select, radio, checkbox
84
+ const handleChange = () => {
85
+ const el = element as HTMLInputElement;
86
+ if (el.type === "checkbox") {
87
+ field.onChange(el.checked);
88
+ } else if (el.type === "radio") {
89
+ if (el.checked) field.onChange(el.value);
90
+ } else {
91
+ field.onChange(getValue(element));
92
+ }
93
+ };
94
+ element.addEventListener("change", handleChange);
95
+ cleanups.push(() => element.removeEventListener("change", handleChange));
96
+
97
+ // --- Blur → touched ---
98
+ const handleBlur = () => field.onBlur();
99
+ element.addEventListener("blur", handleBlur);
100
+ cleanups.push(() => element.removeEventListener("blur", handleBlur));
101
+
102
+ // --- Error display ---
103
+ let errorEl = options.errorElement;
104
+ if (!errorEl) {
105
+ errorEl = document.createElement("span");
106
+ errorEl.className = errorClass;
107
+ errorEl.setAttribute("role", "alert");
108
+ errorEl.setAttribute("aria-live", "polite");
109
+ element.parentNode?.insertBefore(errorEl, element.nextSibling);
110
+ cleanups.push(() => errorEl?.remove());
111
+ }
112
+
113
+ const disposeErrorEffect = createEffect(() => {
114
+ const err = field.error.value;
115
+ const isTouched = field.touched.value;
116
+ if (errorEl) {
117
+ errorEl.textContent = isTouched && err ? err : "";
118
+ errorEl.style.display = isTouched && err ? "" : "none";
119
+ }
120
+ if (isTouched && err) {
121
+ element.classList.add(errorClass);
122
+ element.setAttribute("aria-invalid", "true");
123
+ } else {
124
+ element.classList.remove(errorClass);
125
+ element.removeAttribute("aria-invalid");
126
+ }
127
+ });
128
+ cleanups.push(disposeErrorEffect);
129
+
130
+ // Return unbind function
131
+ return () => {
132
+ for (const cleanup of cleanups) {
133
+ cleanup();
134
+ }
135
+ };
136
+ }
137
+
138
+ // ---------------------------------------------------------------------------
139
+ // bindForm — Bind an entire form element
140
+ // ---------------------------------------------------------------------------
141
+
142
+ /**
143
+ * Bind a form element to a Kayforms FormStore.
144
+ * Automatically binds all child inputs with `name` attributes.
145
+ * Returns an unbind function.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * const form = createForm({
150
+ * initialValues: { email: '', password: '' },
151
+ * onSubmit: (values) => console.log(values),
152
+ * });
153
+ * const unbind = bindForm(document.querySelector('form'), form);
154
+ * ```
155
+ */
156
+ export function bindForm(
157
+ formElement: HTMLFormElement,
158
+ store: FormStore,
159
+ options: BindFormOptions = {}
160
+ ): () => void {
161
+ const { preventDefault = true, ...fieldOptions } = options;
162
+ const cleanups: (() => void)[] = [];
163
+
164
+ // Find all named inputs
165
+ const inputs = formElement.querySelectorAll<HTMLElement>(
166
+ "input[name], select[name], textarea[name]"
167
+ );
168
+
169
+ for (const input of inputs) {
170
+ const name = input.getAttribute("name");
171
+ if (!name) continue;
172
+
173
+ const field = store.getField(name);
174
+ const unbind = bindField(input, field, fieldOptions);
175
+ cleanups.push(unbind);
176
+ }
177
+
178
+ // Handle form submit
179
+ const handleSubmit = (e: Event) => {
180
+ if (preventDefault) {
181
+ e.preventDefault();
182
+ }
183
+ store.submit();
184
+ };
185
+ formElement.addEventListener("submit", handleSubmit);
186
+ cleanups.push(() =>
187
+ formElement.removeEventListener("submit", handleSubmit)
188
+ );
189
+
190
+ return () => {
191
+ for (const cleanup of cleanups) {
192
+ cleanup();
193
+ }
194
+ };
195
+ }
196
+
197
+ // ---------------------------------------------------------------------------
198
+ // autoBindForm — Data-attribute-based declarative binding
199
+ // ---------------------------------------------------------------------------
200
+
201
+ /**
202
+ * Automatically bind form elements using `data-kayform` attributes.
203
+ *
204
+ * @example
205
+ * ```html
206
+ * <form id="login">
207
+ * <input data-kayform="email" type="email" />
208
+ * <input data-kayform="password" type="password" />
209
+ * <button type="submit">Login</button>
210
+ * </form>
211
+ * ```
212
+ * ```ts
213
+ * const form = createForm({ initialValues: { email: '', password: '' } });
214
+ * const unbind = autoBindForm(document.querySelector('#login'), form);
215
+ * ```
216
+ */
217
+ export function autoBindForm(
218
+ formElement: HTMLFormElement,
219
+ store: FormStore,
220
+ options: BindFormOptions = {}
221
+ ): () => void {
222
+ const { preventDefault = true, ...fieldOptions } = options;
223
+ const cleanups: (() => void)[] = [];
224
+
225
+ // Find all elements with data-kayform attribute
226
+ const elements = formElement.querySelectorAll<HTMLElement>("[data-kayform]");
227
+
228
+ for (const el of elements) {
229
+ const path = el.getAttribute("data-kayform");
230
+ if (!path) continue;
231
+
232
+ const field = store.getField(path);
233
+ const unbind = bindField(el, field, fieldOptions);
234
+ cleanups.push(unbind);
235
+ }
236
+
237
+ // Handle form submit
238
+ const handleSubmit = (e: Event) => {
239
+ if (preventDefault) {
240
+ e.preventDefault();
241
+ }
242
+ store.submit();
243
+ };
244
+ formElement.addEventListener("submit", handleSubmit);
245
+ cleanups.push(() =>
246
+ formElement.removeEventListener("submit", handleSubmit)
247
+ );
248
+
249
+ return () => {
250
+ for (const cleanup of cleanups) {
251
+ cleanup();
252
+ }
253
+ };
254
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src"]
8
+ }
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig({
4
+ entry: ["src/index.ts"],
5
+ format: ["esm", "cjs"],
6
+ dts: true,
7
+ clean: true,
8
+ sourcemap: true,
9
+ minify: false,
10
+ treeshake: true,
11
+ external: ["@kayforms/core"],
12
+ outExtension({ format }) {
13
+ return {
14
+ js: format === "cjs" ? ".cjs" : ".js",
15
+ };
16
+ },
17
+ });
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@kayforms/vue",
3
+ "version": "0.1.0",
4
+ "description": "Vue 3 adapter for Kayforms reactive form library",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": ["dist"],
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "dev": "tsup --watch",
25
+ "clean": "rimraf dist",
26
+ "typecheck": "tsc --noEmit"
27
+ },
28
+ "dependencies": {
29
+ "@kayforms/core": "workspace:*"
30
+ },
31
+ "peerDependencies": {
32
+ "vue": "^3.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "vue": "^3.4.0",
36
+ "tsup": "^8.0.0",
37
+ "typescript": "^5.5.0",
38
+ "rimraf": "^5.0.0"
39
+ },
40
+ "sideEffects": false,
41
+ "license": "MIT"
42
+ }
@@ -0,0 +1,217 @@
1
+ // ============================================================================
2
+ // @kayforms/vue — Vue 3 Adapter
3
+ // ============================================================================
4
+ // Bridges Kayforms reactive signals to Vue's reactive ref system.
5
+ // Each useField() injects the parent form context and resolves field states.
6
+ // ============================================================================
7
+
8
+ import {
9
+ inject,
10
+ provide,
11
+ shallowRef,
12
+ onUnmounted,
13
+ defineComponent,
14
+ type InjectionKey,
15
+ type ShallowRef,
16
+ } from "vue";
17
+ import {
18
+ createForm,
19
+ createEffect,
20
+ type FormConfig,
21
+ type FormStore,
22
+ type FormErrors,
23
+ type FieldNode,
24
+ type Signal,
25
+ type Computed,
26
+ } from "@kayforms/core";
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Signal → Vue Ref bridge
30
+ // ---------------------------------------------------------------------------
31
+
32
+ /**
33
+ * Hook to convert a Kayforms Signal or Computed to a Vue Ref.
34
+ * Subscribes to the signal and updates the ref value, cleaning up on unmount.
35
+ */
36
+ export function useSignalValue<T>(signal: Signal<T> | Computed<T>): ShallowRef<T> {
37
+ const r = shallowRef<T>(signal.peek());
38
+ const dispose = createEffect(() => {
39
+ r.value = signal.value;
40
+ });
41
+ onUnmounted(dispose);
42
+ return r;
43
+ }
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // Injection Context
47
+ // ---------------------------------------------------------------------------
48
+
49
+ const FORM_KEY: InjectionKey<FormStore> = Symbol("kayforms");
50
+
51
+ /** Provide form context in a parent component */
52
+ export function provideForm(store: FormStore) {
53
+ provide(FORM_KEY, store);
54
+ }
55
+
56
+ /** Inject form context in a child component */
57
+ export function useFormContext(): FormStore {
58
+ const store = inject(FORM_KEY);
59
+ if (!store) {
60
+ throw new Error(
61
+ "[kayforms/vue] useField must be used inside a form context. " +
62
+ "Wrap your form with <FormProvider :form=\"...\"> or call provideForm(form.store)."
63
+ );
64
+ }
65
+ return store;
66
+ }
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // useForm
70
+ // ---------------------------------------------------------------------------
71
+
72
+ export interface UseFormReturn<T extends Record<string, unknown>> {
73
+ /** The reactive form store */
74
+ store: FormStore<T>;
75
+ /** Current values (reactive) */
76
+ values: ShallowRef<T>;
77
+ /** Current errors (reactive) */
78
+ errors: ShallowRef<FormErrors<T>>;
79
+ /** Whether the form is dirty */
80
+ dirty: ShallowRef<boolean>;
81
+ /** Whether the form is valid */
82
+ valid: ShallowRef<boolean>;
83
+ /** Whether the form is submitting */
84
+ submitting: ShallowRef<boolean>;
85
+ /** Whether any async validation is running */
86
+ validating: ShallowRef<boolean>;
87
+ /** Handle form submission */
88
+ handleSubmit: (e?: Event) => void;
89
+ /** Reset the form */
90
+ reset: (values?: Partial<T>) => void;
91
+ /** Get a field node by path */
92
+ getField: <V = unknown>(path: string) => FieldNode<V>;
93
+ }
94
+
95
+ /**
96
+ * Create and manage a Kayforms form in a Vue component.
97
+ */
98
+ export function useForm<T extends Record<string, unknown>>(
99
+ config: FormConfig<T>
100
+ ): UseFormReturn<T> {
101
+ const store = createForm(config);
102
+
103
+ onUnmounted(() => {
104
+ store.dispose();
105
+ });
106
+
107
+ const values = useSignalValue(store.values);
108
+ const errors = useSignalValue(store.errors);
109
+ const dirty = useSignalValue(store.dirty);
110
+ const valid = useSignalValue(store.valid);
111
+ const submitting = useSignalValue(store.submitting);
112
+ const validating = useSignalValue(store.validating);
113
+
114
+ const handleSubmit = (e?: Event) => {
115
+ e?.preventDefault();
116
+ store.submit();
117
+ };
118
+
119
+ const reset = (newValues?: Partial<T>) => {
120
+ store.reset(newValues);
121
+ };
122
+
123
+ return {
124
+ store,
125
+ values,
126
+ errors,
127
+ dirty,
128
+ valid,
129
+ submitting,
130
+ validating,
131
+ handleSubmit,
132
+ reset,
133
+ getField: store.getField,
134
+ };
135
+ }
136
+
137
+ // ---------------------------------------------------------------------------
138
+ // useField
139
+ // ---------------------------------------------------------------------------
140
+
141
+ export interface UseFieldReturn<V = unknown> {
142
+ /** Current field value */
143
+ value: ShallowRef<V>;
144
+ /** Current error message (undefined = valid) */
145
+ error: ShallowRef<string | undefined>;
146
+ /** Whether the field has been touched */
147
+ touched: ShallowRef<boolean>;
148
+ /** Whether the field value differs from initial */
149
+ dirty: ShallowRef<boolean>;
150
+ /** Whether async validation is in progress */
151
+ validating: ShallowRef<boolean>;
152
+ /** Update the field value */
153
+ onChange: (value: V) => void;
154
+ /** Mark as touched */
155
+ onBlur: () => void;
156
+ /** Input props for binding */
157
+ inputProps: {
158
+ value: V;
159
+ onInput: (e: Event) => void;
160
+ onBlur: () => void;
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Subscribe to a single field's reactive state in a Vue component.
166
+ */
167
+ export function useField<V = unknown>(path: string): UseFieldReturn<V> {
168
+ const store = useFormContext();
169
+ const field = store.getField<V>(path);
170
+
171
+ const value = useSignalValue(field.value);
172
+ const error = useSignalValue(field.error);
173
+ const touched = useSignalValue(field.touched);
174
+ const dirty = useSignalValue(field.dirty);
175
+ const validating = useSignalValue(field.validating);
176
+
177
+ const onChange = (v: V) => field.onChange(v);
178
+ const onBlur = () => field.onBlur();
179
+
180
+ const handleInput = (e: Event) => {
181
+ const val = (e.target as HTMLInputElement).value;
182
+ field.onChange(val as unknown as V);
183
+ };
184
+
185
+ return {
186
+ value,
187
+ error,
188
+ touched,
189
+ dirty,
190
+ validating,
191
+ onChange,
192
+ onBlur,
193
+ inputProps: {
194
+ value: value.value,
195
+ onInput: handleInput,
196
+ onBlur,
197
+ },
198
+ };
199
+ }
200
+
201
+ // ---------------------------------------------------------------------------
202
+ // FormProvider
203
+ // ---------------------------------------------------------------------------
204
+
205
+ export const FormProvider = defineComponent({
206
+ name: "FormProvider",
207
+ props: {
208
+ form: {
209
+ type: Object as () => FormStore<any>,
210
+ required: true,
211
+ },
212
+ },
213
+ setup(props, { slots }) {
214
+ provideForm(props.form);
215
+ return () => slots.default?.();
216
+ },
217
+ });
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src"]
8
+ }
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig({
4
+ entry: ["src/index.ts"],
5
+ format: ["esm", "cjs"],
6
+ dts: true,
7
+ clean: true,
8
+ sourcemap: true,
9
+ minify: false,
10
+ treeshake: true,
11
+ external: ["vue", "@kayforms/core"],
12
+ outExtension({ format }) {
13
+ return {
14
+ js: format === "cjs" ? ".cjs" : ".js",
15
+ };
16
+ },
17
+ });
@@ -0,0 +1,3 @@
1
+ packages:
2
+ - "packages/*"
3
+ - "examples/*"
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "noUnusedLocals": true,
17
+ "noUnusedParameters": true,
18
+ "noFallthroughCasesInSwitch": true,
19
+ "jsx": "react-jsx"
20
+ }
21
+ }