@rokkit/forms 1.0.0-next.144 → 1.0.0-next.146

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.
@@ -5,7 +5,7 @@ export { default as FormRenderer } from "./FormRenderer.svelte";
5
5
  export { default as Input } from "./Input.svelte";
6
6
  export { default as InputField } from "./InputField.svelte";
7
7
  export { default as InfoField } from "./InfoField.svelte";
8
- export { default as ValidationReport } from "./ValidationReport.svelte";
8
+ export { default as StatusList } from "./StatusList.svelte";
9
9
  export * from "./display";
10
10
  export * from "./input";
11
11
  export { createLookup, createLookupManager, clearLookupCache } from "./lib/lookup.svelte.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/forms",
3
- "version": "1.0.0-next.144",
3
+ "version": "1.0.0-next.146",
4
4
  "description": "Form building components for Rokkit applications",
5
5
  "repository": {
6
6
  "type": "git",
@@ -39,10 +39,10 @@
39
39
  }
40
40
  },
41
41
  "dependencies": {
42
- "@rokkit/core": "workspace:latest",
43
- "@rokkit/data": "workspace:latest",
44
- "@rokkit/states": "workspace:latest",
45
- "@rokkit/ui": "workspace:latest",
42
+ "@rokkit/core": "latest",
43
+ "@rokkit/data": "latest",
44
+ "@rokkit/states": "latest",
45
+ "@rokkit/ui": "latest",
46
46
  "ramda": "^0.32.0"
47
47
  }
48
48
  }
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  /**
3
- * ValidationReport — grouped summary of validation messages
3
+ * StatusList — grouped summary of validation messages
4
4
  * Groups items by severity (error, warning, info, success) with count headers.
5
5
  * Supports click-to-focus via onclick callback.
6
6
  */
@@ -19,11 +19,11 @@
19
19
  </script>
20
20
 
21
21
  {#if items.length > 0}
22
- <div data-validation-report class={className} role="status">
22
+ <div data-status-list class={className} role="status">
23
23
  {#each grouped as group (group.state)}
24
- <div data-validation-group data-severity={group.state}>
25
- <div data-validation-group-header>
26
- <span data-validation-count>{group.items.length}</span>
24
+ <div data-status-group data-severity={group.state}>
25
+ <div data-status-header>
26
+ <span data-status-count>{group.items.length}</span>
27
27
  <span
28
28
  >{group.items.length === 1
29
29
  ? SEVERITY_LABELS[group.state]
@@ -33,7 +33,7 @@
33
33
  {#each group.items as item (item.path)}
34
34
  {#if onclick}
35
35
  <button
36
- data-validation-item
36
+ data-status-item
37
37
  data-status={item.state}
38
38
  onclick={() => onclick(item.path)}
39
39
  type="button"
@@ -41,7 +41,7 @@
41
41
  {item.text}
42
42
  </button>
43
43
  {:else}
44
- <div data-validation-item data-status={item.state}>
44
+ <div data-status-item data-status={item.state}>
45
45
  {item.text}
46
46
  </div>
47
47
  {/if}
@@ -28,7 +28,8 @@
28
28
  }
29
29
 
30
30
  const formatters = {
31
- currency: (v) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(v),
31
+ currency: (v) =>
32
+ new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(v),
32
33
  datetime: (v) => new Date(v).toLocaleString(),
33
34
  duration: (v) => formatDuration(v),
34
35
  number: (v) => new Intl.NumberFormat().format(v),
@@ -21,7 +21,8 @@
21
21
  }
22
22
 
23
23
  const valueFormatters = {
24
- currency: (v) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(v),
24
+ currency: (v) =>
25
+ new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(v),
25
26
  datetime: (v) => new Date(v).toLocaleString(),
26
27
  duration: (v) => formatDuration(v),
27
28
  number: (v) => new Intl.NumberFormat().format(v),
package/src/index.js CHANGED
@@ -13,7 +13,7 @@ export { default as FormRenderer } from './FormRenderer.svelte'
13
13
  export { default as Input } from './Input.svelte'
14
14
  export { default as InputField } from './InputField.svelte'
15
15
  export { default as InfoField } from './InfoField.svelte'
16
- export { default as ValidationReport } from './ValidationReport.svelte'
16
+ export { default as StatusList } from './StatusList.svelte'
17
17
 
18
18
  // Display Components
19
19
  export * from './display'
@@ -658,7 +658,8 @@ export class FormBuilder {
658
658
  const value = this.getValue(fieldPath)
659
659
 
660
660
  if (element.elements) return this.#convertNestedElement(element, fieldPath, scope, value)
661
- if (element.props.readonly) return this.#convertReadonlyElement(element, fieldPath, scope, value)
661
+ if (element.props.readonly)
662
+ return this.#convertReadonlyElement(element, fieldPath, scope, value)
662
663
  return this.#buildStandardElement(element, fieldPath, scope, value)
663
664
  }
664
665
 
@@ -726,13 +727,9 @@ export class FormBuilder {
726
727
  */
727
728
  getVisibleData() {
728
729
  const visiblePaths = new SvelteSet(
729
- this.elements
730
- .filter((el) => el.scope)
731
- .map((el) => el.scope.replace(/^#\//, ''))
732
- )
733
- return Object.fromEntries(
734
- Object.entries(this.#data).filter(([key]) => visiblePaths.has(key))
730
+ this.elements.filter((el) => el.scope).map((el) => el.scope.replace(/^#\//, ''))
735
731
  )
732
+ return Object.fromEntries(Object.entries(this.#data).filter(([key]) => visiblePaths.has(key)))
736
733
  }
737
734
 
738
735
  /**
@@ -7,9 +7,9 @@
7
7
  * @returns {boolean}
8
8
  */
9
9
  export function evaluateCondition(condition, data) {
10
- if (!condition) return true
11
- const value = data[condition.field]
12
- if ('equals' in condition) return value === condition.equals
13
- if ('notEquals' in condition) return value !== condition.notEquals
14
- return true
10
+ if (!condition) return true
11
+ const value = data[condition.field]
12
+ if ('equals' in condition) return value === condition.equals
13
+ if ('notEquals' in condition) return value !== condition.notEquals
14
+ return true
15
15
  }
@@ -2,57 +2,57 @@ import { describe, it, expect } from 'vitest'
2
2
  import { evaluateCondition } from './conditions.js'
3
3
 
4
4
  describe('evaluateCondition', () => {
5
- it('returns true when condition is null', () => {
6
- expect(evaluateCondition(null, { accountType: 'personal' })).toBe(true)
7
- })
8
-
9
- it('returns true when condition is undefined', () => {
10
- expect(evaluateCondition(undefined, { accountType: 'personal' })).toBe(true)
11
- })
12
-
13
- it('returns true when neither operator is set', () => {
14
- expect(evaluateCondition({ field: 'accountType' }, { accountType: 'business' })).toBe(true)
15
- })
16
-
17
- describe('equals operator', () => {
18
- it('returns true when value matches', () => {
19
- expect(
20
- evaluateCondition({ field: 'accountType', equals: 'business' }, { accountType: 'business' })
21
- ).toBe(true)
22
- })
23
-
24
- it('returns false when value does not match', () => {
25
- expect(
26
- evaluateCondition({ field: 'accountType', equals: 'business' }, { accountType: 'personal' })
27
- ).toBe(false)
28
- })
29
-
30
- it('returns false when field is absent (undefined)', () => {
31
- expect(evaluateCondition({ field: 'accountType', equals: 'business' }, {})).toBe(false)
32
- })
33
- })
34
-
35
- describe('notEquals operator', () => {
36
- it('returns true when value does not match', () => {
37
- expect(
38
- evaluateCondition(
39
- { field: 'accountType', notEquals: 'business' },
40
- { accountType: 'personal' }
41
- )
42
- ).toBe(true)
43
- })
44
-
45
- it('returns false when value matches', () => {
46
- expect(
47
- evaluateCondition(
48
- { field: 'accountType', notEquals: 'business' },
49
- { accountType: 'business' }
50
- )
51
- ).toBe(false)
52
- })
53
-
54
- it('returns true when field is absent (undefined !== value)', () => {
55
- expect(evaluateCondition({ field: 'accountType', notEquals: 'business' }, {})).toBe(true)
56
- })
57
- })
5
+ it('returns true when condition is null', () => {
6
+ expect(evaluateCondition(null, { accountType: 'personal' })).toBe(true)
7
+ })
8
+
9
+ it('returns true when condition is undefined', () => {
10
+ expect(evaluateCondition(undefined, { accountType: 'personal' })).toBe(true)
11
+ })
12
+
13
+ it('returns true when neither operator is set', () => {
14
+ expect(evaluateCondition({ field: 'accountType' }, { accountType: 'business' })).toBe(true)
15
+ })
16
+
17
+ describe('equals operator', () => {
18
+ it('returns true when value matches', () => {
19
+ expect(
20
+ evaluateCondition({ field: 'accountType', equals: 'business' }, { accountType: 'business' })
21
+ ).toBe(true)
22
+ })
23
+
24
+ it('returns false when value does not match', () => {
25
+ expect(
26
+ evaluateCondition({ field: 'accountType', equals: 'business' }, { accountType: 'personal' })
27
+ ).toBe(false)
28
+ })
29
+
30
+ it('returns false when field is absent (undefined)', () => {
31
+ expect(evaluateCondition({ field: 'accountType', equals: 'business' }, {})).toBe(false)
32
+ })
33
+ })
34
+
35
+ describe('notEquals operator', () => {
36
+ it('returns true when value does not match', () => {
37
+ expect(
38
+ evaluateCondition(
39
+ { field: 'accountType', notEquals: 'business' },
40
+ { accountType: 'personal' }
41
+ )
42
+ ).toBe(true)
43
+ })
44
+
45
+ it('returns false when value matches', () => {
46
+ expect(
47
+ evaluateCondition(
48
+ { field: 'accountType', notEquals: 'business' },
49
+ { accountType: 'business' }
50
+ )
51
+ ).toBe(false)
52
+ })
53
+
54
+ it('returns true when field is absent (undefined !== value)', () => {
55
+ expect(evaluateCondition({ field: 'accountType', notEquals: 'business' }, {})).toBe(true)
56
+ })
57
+ })
58
58
  })
@@ -186,12 +186,24 @@ async function runWithLoadingState(asyncFn, state) {
186
186
  function buildLookupApi(ctx, fns) {
187
187
  const { state, meta } = ctx
188
188
  return {
189
- get options() { return state.options },
190
- get loading() { return state.loading },
191
- get error() { return state.error },
192
- get disabled() { return state.disabled },
193
- get dependsOn() { return meta.dependsOn },
194
- get fields() { return meta.fields },
189
+ get options() {
190
+ return state.options
191
+ },
192
+ get loading() {
193
+ return state.loading
194
+ },
195
+ get error() {
196
+ return state.error
197
+ },
198
+ get disabled() {
199
+ return state.disabled
200
+ },
201
+ get dependsOn() {
202
+ return meta.dependsOn
203
+ },
204
+ get fields() {
205
+ return meta.fields
206
+ },
195
207
  ...fns
196
208
  }
197
209
  }
@@ -241,7 +253,10 @@ function fetchDispatch(params, ctx) {
241
253
  }
242
254
 
243
255
  if (fetchHook) {
244
- return runWithLoadingState(() => fetchFromHook({ fetchHook, cacheKeyFn, cacheTime, transform }, params), state)
256
+ return runWithLoadingState(
257
+ () => fetchFromHook({ fetchHook, cacheKeyFn, cacheTime, transform }, params),
258
+ state
259
+ )
245
260
  }
246
261
 
247
262
  return runWithLoadingState(() => fetchFromUrl({ url, cacheTime, transform }, params), state)
@@ -253,8 +268,17 @@ function fetchDispatch(params, ctx) {
253
268
  * @returns {Object} Lookup provider with reactive state
254
269
  */
255
270
  export function createLookup(config) {
256
- const { url, fetch: fetchHook, source, filter, cacheKey: cacheKeyFn,
257
- dependsOn = [], fields = {}, cacheTime = DEFAULT_CACHE_TIME, transform } = config
271
+ const {
272
+ url,
273
+ fetch: fetchHook,
274
+ source,
275
+ filter,
276
+ cacheKey: cacheKeyFn,
277
+ dependsOn = [],
278
+ fields = {},
279
+ cacheTime = DEFAULT_CACHE_TIME,
280
+ transform
281
+ } = config
258
282
 
259
283
  let state = $state({ options: [], loading: false, error: null, disabled: false })
260
284
  const ctx = { state, dependsOn, source, filter, fetchHook, cacheKeyFn, cacheTime, transform, url }
@@ -319,8 +343,12 @@ export function createLookupManager(lookupConfigs) {
319
343
  handleFieldChange: (changedField, formData) =>
320
344
  triggerDependentLookups(lookups, changedField, formData),
321
345
  initialize: (formData) => initializeAllLookups(lookups, formData),
322
- clearAllCaches: () => { for (const lookup of lookups.values()) lookup.clearCache() },
323
- get lookups() { return lookups }
346
+ clearAllCaches: () => {
347
+ for (const lookup of lookups.values()) lookup.clearCache()
348
+ },
349
+ get lookups() {
350
+ return lookups
351
+ }
324
352
  }
325
353
  }
326
354