@asteby/metacore-runtime-react 23.9.0 → 23.9.2
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/CHANGELOG.md +22 -0
- package/dist/dynamic-form-schema.d.ts +18 -1
- package/dist/dynamic-form-schema.d.ts.map +1 -1
- package/dist/dynamic-form-schema.js +43 -0
- package/dist/dynamic-form.d.ts.map +1 -1
- package/dist/dynamic-form.js +30 -9
- package/dist/dynamic-kanban.d.ts +8 -0
- package/dist/dynamic-kanban.d.ts.map +1 -1
- package/dist/dynamic-kanban.js +25 -4
- package/dist/dynamic-line-items.d.ts.map +1 -1
- package/dist/dynamic-line-items.js +24 -3
- package/dist/dynamic-table.d.ts.map +1 -1
- package/dist/dynamic-table.js +49 -26
- package/dist/types.d.ts +33 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/use-infinite-scroll.d.ts.map +1 -1
- package/dist/use-infinite-scroll.js +12 -0
- package/package.json +3 -3
- package/src/__tests__/dependent-enum-form.test.tsx +84 -0
- package/src/__tests__/dependent-enum-options.test.ts +67 -0
- package/src/dynamic-form-schema.ts +44 -1
- package/src/dynamic-form.tsx +76 -28
- package/src/dynamic-kanban.tsx +26 -5
- package/src/dynamic-line-items.tsx +26 -2
- package/src/dynamic-table.tsx +41 -36
- package/src/types.ts +35 -1
- package/src/use-infinite-scroll.ts +12 -0
package/src/types.ts
CHANGED
|
@@ -335,12 +335,46 @@ export type FieldWidget =
|
|
|
335
335
|
| 'switch'
|
|
336
336
|
| 'upload'
|
|
337
337
|
|
|
338
|
+
/**
|
|
339
|
+
* Per-option visibility gate for a STATIC enum (`options[]`). The option is only
|
|
340
|
+
* offered when the value of a sibling field (`field`, defaulting to the
|
|
341
|
+
* containing field's `dependsOn`) passes: value ∈ `in` and value ∉ `notIn`.
|
|
342
|
+
* Comparison is by string. Mirrors the kernel v3 `option.when` block; the SDK
|
|
343
|
+
* tolerates both the snake_case (`not_in`) the kernel serves and camelCase.
|
|
344
|
+
* An option WITHOUT a `when` always applies (retrocompat).
|
|
345
|
+
*/
|
|
346
|
+
export interface OptionWhen {
|
|
347
|
+
/** Sibling field whose value gates this option. Falls back to `dependsOn`. */
|
|
348
|
+
field?: string
|
|
349
|
+
/** The option applies when the gating field's value is in this list. */
|
|
350
|
+
in?: string[]
|
|
351
|
+
/** The option applies when the gating field's value is NOT in this list. */
|
|
352
|
+
notIn?: string[]
|
|
353
|
+
/** snake_case alias served by the kernel manifest for `notIn`. */
|
|
354
|
+
not_in?: string[]
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* A single static enum option. `value`/`label` are the core pair; `icon`,
|
|
359
|
+
* `color` and `image` drive the option's leading visual where the renderer
|
|
360
|
+
* supports it. `when` gates the option's visibility by a sibling field's value
|
|
361
|
+
* (see {@link OptionWhen}) — used for dependent/cascading STATIC enums.
|
|
362
|
+
*/
|
|
363
|
+
export interface OptionDef {
|
|
364
|
+
value: string
|
|
365
|
+
label: string
|
|
366
|
+
icon?: string
|
|
367
|
+
color?: string
|
|
368
|
+
image?: string
|
|
369
|
+
when?: OptionWhen
|
|
370
|
+
}
|
|
371
|
+
|
|
338
372
|
export interface ActionFieldDef {
|
|
339
373
|
key: string
|
|
340
374
|
label: string
|
|
341
375
|
type: string
|
|
342
376
|
required?: boolean
|
|
343
|
-
options?:
|
|
377
|
+
options?: OptionDef[]
|
|
344
378
|
defaultValue?: any
|
|
345
379
|
placeholder?: string
|
|
346
380
|
searchEndpoint?: string
|
|
@@ -64,6 +64,7 @@ export function useInfiniteScrollSentinel<
|
|
|
64
64
|
const sentinelRef = useRef<S | null>(null)
|
|
65
65
|
const cb = useRef(onLoadMore)
|
|
66
66
|
const disabledRef = useRef(disabled)
|
|
67
|
+
const intersectingRef = useRef(false)
|
|
67
68
|
cb.current = onLoadMore
|
|
68
69
|
disabledRef.current = disabled
|
|
69
70
|
|
|
@@ -78,6 +79,7 @@ export function useInfiniteScrollSentinel<
|
|
|
78
79
|
const observer = new IntersectionObserver(
|
|
79
80
|
(entries) => {
|
|
80
81
|
for (const entry of entries) {
|
|
82
|
+
intersectingRef.current = entry.isIntersecting
|
|
81
83
|
if (entry.isIntersecting && !disabledRef.current) {
|
|
82
84
|
cb.current()
|
|
83
85
|
}
|
|
@@ -90,5 +92,15 @@ export function useInfiniteScrollSentinel<
|
|
|
90
92
|
// Re-create only when the margin changes; onLoadMore/disabled are read live.
|
|
91
93
|
}, [rootMargin])
|
|
92
94
|
|
|
95
|
+
// IntersectionObserver only fires on intersection CHANGES. If a loaded page
|
|
96
|
+
// is too short to push the sentinel out of view (small screens, short
|
|
97
|
+
// lanes), the sentinel stays intersecting and no further event ever comes —
|
|
98
|
+
// the list stalls until the user jiggles the scroll. When a load finishes
|
|
99
|
+
// (disabled flips back to false) and the sentinel is still in view, chain
|
|
100
|
+
// the next page.
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (!disabled && intersectingRef.current) cb.current()
|
|
103
|
+
}, [disabled])
|
|
104
|
+
|
|
93
105
|
return { rootRef, sentinelRef }
|
|
94
106
|
}
|