@contember/bindx-react 0.1.32 → 0.1.33

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/dist/index.d.ts CHANGED
@@ -7,11 +7,11 @@ export type { RelationType, ScalarFieldDef, HasOneRelationDef, HasManyRelationDe
7
7
  export { scalar, hasOne, hasMany, defineSchema, entityDef, roleEntityDef, DEFAULT_ROLE, SchemaRegistry, createFragment, buildQueryFromSelection, EntityHandle, HasOneHandle, HasManyListHandle, FieldHandle, FIELD_REF_META, MockAdapter, ContemberAdapter, createEntityLoader, resolveSelectionMeta, buildQuery, SnapshotStore, ActionDispatcher, isTempId, isPlaceholderId, isPersistedId, generatePlaceholderId, BatchPersister, ChangeRegistry, UndoManager, EventEmitter, __internal, } from '@contember/bindx';
8
8
  export type { BindxProviderProps, BindxContextValue, BindxGraphQlClient, UseEntityOptions, UseEntityListOptions, LoadingEntityResult, ErrorEntityResult, NotFoundEntityResult, ReadyEntityResult, UseEntityResult, LoadingEntityListResult, ErrorEntityListResult, ReadyEntityListResult, UseEntityListResult, PersistApi, EntityPersistApi, AnyRefWithMeta, PersistWithFeedbackApi, } from './hooks/index.js';
9
9
  export type { DirtyEntity, PersistScope, AllScope, EntityScope as EntityPersistScope, FieldsScope, RelationScope, CustomScope, EntityPersistResult, PersistenceResult, BatchPersistOptions, } from '@contember/bindx';
10
- export type { FieldProps, HasManyProps, HasOneProps, IfProps, EntityComponentProps, HasManyComponentOptions, ShowProps, SelectionPropMeta, SelectionProvider, EntityPropKeys, EntityFromProp, SelectionFromProp, ImplicitFragmentProperties, BindxComponentBase, BindxComponent, ComponentBuilder, ComponentBuilderState, CreateComponentOptions, InterfaceEntityPropConfig, ImplicitInterfaceEntityConfig, ExplicitInterfaceEntityConfig, AddInterfaces, InterfaceSelectorsMap, AnyEntityPropConfig, EntityPropConfig, ImplicitEntityConfig, ExplicitEntityConfig, AddImplicitEntity, AddExplicitEntity, AddImplicitInterfaceEntity, AddExplicitInterfaceEntity, SetScalarProps, BuildEntityProps, BuildProps, BuildFragmentProps, InitialBuilderState, } from './jsx/index.js';
10
+ export type { FieldProps, HasManyProps, HasOneProps, IfProps, EntityComponentProps, HasManyComponentOptions, ShowProps, SwitchProps, CaseProps, DefaultProps, SelectionPropMeta, SelectionProvider, EntityPropKeys, EntityFromProp, SelectionFromProp, ImplicitFragmentProperties, BindxComponentBase, BindxComponent, ComponentBuilder, ComponentBuilderState, CreateComponentOptions, InterfaceEntityPropConfig, ImplicitInterfaceEntityConfig, ExplicitInterfaceEntityConfig, AddInterfaces, InterfaceSelectorsMap, AnyEntityPropConfig, EntityPropConfig, ImplicitEntityConfig, ExplicitEntityConfig, AddImplicitEntity, AddExplicitEntity, AddImplicitInterfaceEntity, AddExplicitInterfaceEntity, SetScalarProps, BuildEntityProps, BuildProps, BuildFragmentProps, InitialBuilderState, } from './jsx/index.js';
11
11
  export { BindxProvider, useBackendAdapter, useSnapshotStore, useDispatcher, useBatchPersister, useBindxContext, useSchemaRegistry, useEntity, useEntityList, usePersist, usePersistEntity, useUndo, useOnEvent, useOnEntityEvent, useOnFieldEvent, useIntercept, useInterceptEntity, useInterceptField, useAccessor, useField, useHasMany, useHasOne, useNotificationStore, useNotifications, useShowNotification, useDismissNotification, usePersistWithFeedback, ContemberBindxProvider, schemaNamesToDef, } from './hooks/index.js';
12
12
  export { RoleProvider, useHasRole, type RoleProviderProps } from './roles/index.js';
13
13
  export type { UndoHookResult } from './hooks/useUndo.js';
14
- export { Attribute, type AttributeProps, Field, HasMany, HasOne, If, Show, Entity, type EntityProps, EntityList, type EntityListProps, HasRole, type HasRoleProps, BINDX_COMPONENT, SCOPE_REF, cond, type Condition, createComponent, withCollector, isBindxComponent, mergeFragments, COMPONENT_MARKER, COMPONENT_BRAND, COMPONENT_SELECTIONS, createComponentBuilder, getComponentBrand, setBrandValidation, validateBrand, } from './jsx/index.js';
14
+ export { Attribute, type AttributeProps, Field, HasMany, HasOne, If, Show, Switch, Case, Default, Entity, type EntityProps, EntityList, type EntityListProps, HasRole, type HasRoleProps, BINDX_COMPONENT, SCOPE_REF, cond, type Condition, createComponent, withCollector, isBindxComponent, mergeFragments, COMPONENT_MARKER, COMPONENT_BRAND, COMPONENT_SELECTIONS, createComponentBuilder, getComponentBrand, setBrandValidation, validateBrand, } from './jsx/index.js';
15
15
  export { EntityScope, useEntityScope, useOptionalEntityScope, type EntityScopeProps, } from './components/EntityScope.js';
16
16
  export { SelectionMetaCollector, mergeSelections, createEmptySelection, createCollectorProxy, analyzeJsx, collectSelection, convertToQuerySelection, debugSelection, } from './jsx/index.js';
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,YAAY,EAEX,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,cAAc,EAEd,mBAAmB,EACnB,SAAS,EACT,YAAY,EACZ,cAAc,EACd,aAAa,EACb,aAAa,EACb,WAAW,EAEX,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,cAAc,EACd,cAAc,EACd,SAAS,EACT,cAAc,EAEd,WAAW,EACX,aAAa,EACb,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,YAAY,EAEZ,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,UAAU,EACV,WAAW,EACX,UAAU,EACV,YAAY,EAEZ,QAAQ,EACR,UAAU,EACV,SAAS,EACT,SAAS,EAET,aAAa,EACb,eAAe,EACf,cAAc,EACd,cAAc,EAEd,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EAEd,cAAc,EACd,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,SAAS,EACT,WAAW,EACX,cAAc,EACd,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EAEvB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EAEjB,cAAc,EACd,aAAa,EACb,sBAAsB,EACtB,eAAe,EACf,WAAW,EACX,UAAU,EAEV,iBAAiB,EACjB,SAAS,EACT,SAAS,EAET,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,eAAe,GACf,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAEN,MAAM,EACN,MAAM,EACN,OAAO,EACP,YAAY,EACZ,SAAS,EACT,aAAa,EACb,YAAY,EACZ,cAAc,EAEd,cAAc,EACd,uBAAuB,EAEvB,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,WAAW,EAEX,cAAc,EAEd,WAAW,EACX,gBAAgB,EAEhB,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,EAEV,aAAa,EACb,gBAAgB,EAEhB,QAAQ,EACR,eAAe,EACf,aAAa,EACb,qBAAqB,EAErB,cAAc,EACd,cAAc,EAEd,WAAW,EAEX,YAAY,EAEZ,UAAU,GACV,MAAM,kBAAkB,CAAA;AAOzB,YAAY,EACX,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EAEnB,UAAU,EACV,gBAAgB,EAChB,cAAc,EAEd,sBAAsB,GACtB,MAAM,kBAAkB,CAAA;AAGzB,YAAY,EACX,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,WAAW,IAAI,kBAAkB,EACjC,WAAW,EACX,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,GACnB,MAAM,kBAAkB,CAAA;AAGzB,YAAY,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EACX,OAAO,EACP,oBAAoB,EACpB,uBAAuB,EACvB,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,0BAA0B,EAE1B,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EAEtB,yBAAyB,EACzB,6BAA6B,EAC7B,6BAA6B,EAC7B,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EAEnB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EAEpB,iBAAiB,EACjB,iBAAiB,EACjB,0BAA0B,EAC1B,0BAA0B,EAC1B,cAAc,EAEd,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,mBAAmB,GACnB,MAAM,gBAAgB,CAAA;AAOvB,OAAO,EACN,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EAEjB,SAAS,EACT,aAAa,EAEb,UAAU,EACV,gBAAgB,EAEhB,OAAO,EAEP,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EAEjB,WAAW,EACX,QAAQ,EACR,UAAU,EACV,SAAS,EAET,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,EAEtB,sBAAsB,EACtB,gBAAgB,GAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAGnF,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAIxD,OAAO,EACN,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,EACL,OAAO,EACP,MAAM,EACN,EAAE,EACF,IAAI,EACJ,MAAM,EACN,KAAK,WAAW,EAChB,UAAU,EACV,KAAK,eAAe,EACpB,OAAO,EACP,KAAK,YAAY,EACjB,eAAe,EACf,SAAS,EAET,IAAI,EACJ,KAAK,SAAS,EAEd,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,GACb,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACN,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,KAAK,gBAAgB,GACrB,MAAM,6BAA6B,CAAA;AAMpC,OAAO,EACN,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,UAAU,EACV,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,GACd,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ import { BINDX_COMPONENT } from '../types.js';
6
6
  */
7
7
  export interface ShowProps<T> {
8
8
  field: FieldRef<T>;
9
- children: (value: NonNullable<T>) => ReactNode;
9
+ children: ReactNode | ((value: NonNullable<T>) => ReactNode);
10
10
  fallback?: ReactNode;
11
11
  }
12
12
  /**
@@ -15,11 +15,17 @@ export interface ShowProps<T> {
15
15
  *
16
16
  * @example
17
17
  * ```tsx
18
- * <Show field={article.fields.publishedAt}>
18
+ * // Plain children - use when field value isn't needed
19
+ * <Show field={article.publishedAt}>
20
+ * <PublishedBadge />
21
+ * </Show>
22
+ *
23
+ * // Callback children - receive non-null field value
24
+ * <Show field={article.publishedAt}>
19
25
  * {value => <time>{value.toISOString()}</time>}
20
26
  * </Show>
21
27
  *
22
- * <Show field={author.fields.bio} fallback={<span>No bio</span>}>
28
+ * <Show field={author.bio} fallback={<span>No bio</span>}>
23
29
  * {bio => <p>{bio}</p>}
24
30
  * </Show>
25
31
  * ```
@@ -1 +1 @@
1
- {"version":3,"file":"Show.d.ts","sourceRoot":"","sources":["../../../src/jsx/components/Show.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAQ,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAoD,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAChH,OAAO,EAAkB,eAAe,EAAE,MAAM,aAAa,CAAA;AAG7D;;GAEG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC3B,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,SAAS,CAAA;IAC9C,QAAQ,CAAC,EAAE,SAAS,CAAA;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,iBAAS,QAAQ,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,YAAY,GAAG,IAAI,CASrF;AAED,eAAO,MAAM,IAAI,EAAqB,OAAO,QAAQ,CAAA;AAGrD,QAAA,MAAM,iBAAiB,EAAW,OAAO,IAAI,GAAG,iBAAiB,GAAG;IAAE,CAAC,eAAe,CAAC,EAAE,IAAI,CAAA;CAAE,CAAA;AAgB/F,OAAO,EAAE,iBAAiB,IAAI,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"Show.d.ts","sourceRoot":"","sources":["../../../src/jsx/components/Show.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAQ,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAoD,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAChH,OAAO,EAAkB,eAAe,EAAE,MAAM,aAAa,CAAA;AAG7D;;GAEG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC;IAC3B,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IAClB,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAA;IAC5D,QAAQ,CAAC,EAAE,SAAS,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,iBAAS,QAAQ,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,YAAY,GAAG,IAAI,CAarF;AAED,eAAO,MAAM,IAAI,EAAqB,OAAO,QAAQ,CAAA;AAGrD,QAAA,MAAM,iBAAiB,EAAW,OAAO,IAAI,GAAG,iBAAiB,GAAG;IAAE,CAAC,eAAe,CAAC,EAAE,IAAI,CAAA;CAAE,CAAA;AA6B/F,OAAO,EAAE,iBAAiB,IAAI,YAAY,EAAE,CAAA"}
@@ -0,0 +1,48 @@
1
+ import React, { type ReactElement, type ReactNode } from 'react';
2
+ import type { FieldRef, SelectionProvider } from '../types.js';
3
+ import { BINDX_COMPONENT } from '../types.js';
4
+ import { type Condition } from '../conditions.js';
5
+ /**
6
+ * Props for <Case>. Discriminated union: exactly one of `show` or `if` must be set.
7
+ *
8
+ * - `show={fieldRef}` matches when the field value is neither `null` nor `undefined`.
9
+ * Children may be a callback receiving the non-null value.
10
+ * - `if={cond}` accepts a boolean, a `FieldRef<boolean>`, or a `Condition` DSL object.
11
+ */
12
+ export type CaseProps<T = unknown> = {
13
+ show: FieldRef<T>;
14
+ if?: never;
15
+ children: ReactNode | ((value: NonNullable<T>) => ReactNode);
16
+ } | {
17
+ show?: never;
18
+ if: Condition | FieldRef<boolean> | boolean;
19
+ children: ReactNode;
20
+ };
21
+ export interface DefaultProps {
22
+ children: ReactNode;
23
+ }
24
+ export interface SwitchProps {
25
+ children: ReactNode;
26
+ }
27
+ /**
28
+ * Marker component for a case branch inside <Switch>. Never renders on its own —
29
+ * <Switch> reads its props to decide which branch to render.
30
+ */
31
+ export declare function Case<T>(_props: CaseProps<T>): null;
32
+ /**
33
+ * Marker component for the fallback branch inside <Switch>. At most one allowed.
34
+ */
35
+ export declare function Default(_props: DefaultProps): null;
36
+ declare function SwitchImpl({ children }: SwitchProps): ReactElement | null;
37
+ export declare const Switch: React.MemoExoticComponent<typeof SwitchImpl>;
38
+ declare const caseWithSelection: typeof Case & SelectionProvider & {
39
+ [BINDX_COMPONENT]: true;
40
+ };
41
+ declare const defaultWithSelection: typeof Default & SelectionProvider & {
42
+ [BINDX_COMPONENT]: true;
43
+ };
44
+ declare const switchWithSelection: typeof Switch & SelectionProvider & {
45
+ [BINDX_COMPONENT]: true;
46
+ };
47
+ export { switchWithSelection as SwitchWithMeta, caseWithSelection as CaseWithMeta, defaultWithSelection as DefaultWithMeta, };
48
+ //# sourceMappingURL=Switch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../../src/jsx/components/Switch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAKb,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EACX,QAAQ,EAGR,iBAAiB,EACjB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAkB,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7D,OAAO,EACN,KAAK,SAAS,EAId,MAAM,kBAAkB,CAAA;AAEzB;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG,OAAO,IAC9B;IACA,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IACjB,EAAE,CAAC,EAAE,KAAK,CAAA;IACV,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAA;CAC3D,GACD;IACA,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,EAAE,EAAE,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;IAC3C,QAAQ,EAAE,SAAS,CAAA;CAClB,CAAA;AAEJ,MAAM,WAAW,YAAY;IAC5B,QAAQ,EAAE,SAAS,CAAA;CACnB;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,EAAE,SAAS,CAAA;CACnB;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAElD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAElD;AA2ED,iBAAS,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW,GAAG,YAAY,GAAG,IAAI,CA4ClE;AAED,eAAO,MAAM,MAAM,8CAAmB,CAAA;AA0BtC,QAAA,MAAM,iBAAiB,EAAW,OAAO,IAAI,GAAG,iBAAiB,GAAG;IAAE,CAAC,eAAe,CAAC,EAAE,IAAI,CAAA;CAAE,CAAA;AAmC/F,QAAA,MAAM,oBAAoB,EAAc,OAAO,OAAO,GAAG,iBAAiB,GAAG;IAAE,CAAC,eAAe,CAAC,EAAE,IAAI,CAAA;CAAE,CAAA;AAaxG,QAAA,MAAM,mBAAmB,EAAa,OAAO,MAAM,GAAG,iBAAiB,GAAG;IAAE,CAAC,eAAe,CAAC,EAAE,IAAI,CAAA;CAAE,CAAA;AAarG,OAAO,EACN,mBAAmB,IAAI,cAAc,EACrC,iBAAiB,IAAI,YAAY,EACjC,oBAAoB,IAAI,eAAe,GACvC,CAAA"}
@@ -4,6 +4,7 @@ export { HasMany, HasManyWithMeta } from './HasMany.js';
4
4
  export { HasOne, HasOneWithMeta } from './HasOne.js';
5
5
  export { If, IfWithMeta } from './If.js';
6
6
  export { Show, ShowWithMeta, type ShowProps } from './Show.js';
7
+ export { Switch, Case, Default, SwitchWithMeta, CaseWithMeta, DefaultWithMeta, type SwitchProps, type CaseProps, type DefaultProps, } from './Switch.js';
7
8
  export { Entity, type EntityProps } from './Entity.js';
8
9
  export { EntityList, type EntityListProps } from './EntityList.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/jsx/components/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAGlF,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAGjD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAGvD,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGpD,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGxC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAA;AAG9D,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAGtD,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/jsx/components/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAGlF,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAGjD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAGvD,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGpD,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGxC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAA;AAG9D,OAAO,EACN,MAAM,EACN,IAAI,EACJ,OAAO,EACP,cAAc,EACd,YAAY,EACZ,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,YAAY,GACjB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAGtD,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA"}
@@ -8,6 +8,7 @@ export { HasMany, HasManyWithMeta } from './components/HasMany.js';
8
8
  export { HasOne, HasOneWithMeta } from './components/HasOne.js';
9
9
  export { If, IfWithMeta } from './components/If.js';
10
10
  export { Show, ShowWithMeta, type ShowProps } from './components/Show.js';
11
+ export { Switch, Case, Default, SwitchWithMeta, CaseWithMeta, DefaultWithMeta, type SwitchProps, type CaseProps, type DefaultProps, } from './components/Switch.js';
11
12
  export { Entity, type EntityProps } from './components/Entity.js';
12
13
  export { EntityList, type EntityListProps } from './components/EntityList.js';
13
14
  export { HasRole, type HasRoleProps } from './components/HasRole.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jsx/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,eAAe,EACf,cAAc,EACd,SAAS,EACT,KAAK,YAAY,EAEjB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EAEd,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EAEpB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,QAAQ,GACb,MAAM,YAAY,CAAA;AAGnB,OAAO,EACN,sBAAsB,EACtB,eAAe,EACf,oBAAoB,GACpB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EACN,oBAAoB,GACpB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACN,UAAU,EACV,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,GACd,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC7F,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACzE,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAGpE,OAAO,EACN,IAAI,EACJ,WAAW,EACX,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,EACd,KAAK,SAAS,EACd,KAAK,aAAa,GAClB,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,GACb,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAGhE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,YAAY,EACX,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EAEtB,yBAAyB,EACzB,6BAA6B,EAC7B,6BAA6B,EAC7B,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EAEnB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EAEpB,iBAAiB,EACjB,iBAAiB,EACjB,0BAA0B,EAC1B,0BAA0B,EAC1B,cAAc,EAEd,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAG7B,YAAY,EACX,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,0BAA0B,GAC1B,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jsx/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,eAAe,EACf,cAAc,EACd,SAAS,EACT,KAAK,YAAY,EAEjB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EAEd,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EAEpB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,QAAQ,GACb,MAAM,YAAY,CAAA;AAGnB,OAAO,EACN,sBAAsB,EACtB,eAAe,EACf,oBAAoB,GACpB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EACN,oBAAoB,GACpB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACN,UAAU,EACV,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,GACd,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC7F,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACzE,OAAO,EACN,MAAM,EACN,IAAI,EACJ,OAAO,EACP,cAAc,EACd,YAAY,EACZ,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,YAAY,GACjB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC7E,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAGpE,OAAO,EACN,IAAI,EACJ,WAAW,EACX,iBAAiB,EACjB,sBAAsB,EACtB,cAAc,EACd,KAAK,SAAS,EACd,KAAK,aAAa,GAClB,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACN,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,GACb,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAGhE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,YAAY,EACX,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EAEtB,yBAAyB,EACzB,6BAA6B,EAC7B,6BAA6B,EAC7B,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EAEnB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EAEpB,iBAAiB,EACjB,iBAAiB,EACjB,0BAA0B,EAC1B,0BAA0B,EAC1B,cAAc,EAEd,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,mBAAmB,GACnB,MAAM,sBAAsB,CAAA;AAG7B,YAAY,EACX,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,0BAA0B,GAC1B,MAAM,kBAAkB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contember/bindx-react",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "description": "Type-safe React data binding framework",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -15,8 +15,8 @@
15
15
  "react": ">=18.0.0"
16
16
  },
17
17
  "dependencies": {
18
- "@contember/bindx": "0.1.32",
19
- "@contember/bindx-client": "0.1.32",
18
+ "@contember/bindx": "0.1.33",
19
+ "@contember/bindx-client": "0.1.33",
20
20
  "@contember/graphql-client": "^2.1.0-beta.1",
21
21
  "@radix-ui/primitive": "^1.1.3",
22
22
  "@radix-ui/react-slot": "^1.2.4"
package/src/index.ts CHANGED
@@ -234,6 +234,9 @@ export type {
234
234
  EntityComponentProps,
235
235
  HasManyComponentOptions,
236
236
  ShowProps,
237
+ SwitchProps,
238
+ CaseProps,
239
+ DefaultProps,
237
240
  SelectionPropMeta,
238
241
  SelectionProvider,
239
242
  EntityPropKeys,
@@ -330,6 +333,9 @@ export {
330
333
  HasOne,
331
334
  If,
332
335
  Show,
336
+ Switch,
337
+ Case,
338
+ Default,
333
339
  Entity,
334
340
  type EntityProps,
335
341
  EntityList,
@@ -8,7 +8,7 @@ import { useField } from '../../hooks/useField.js'
8
8
  */
9
9
  export interface ShowProps<T> {
10
10
  field: FieldRef<T>
11
- children: (value: NonNullable<T>) => ReactNode
11
+ children: ReactNode | ((value: NonNullable<T>) => ReactNode)
12
12
  fallback?: ReactNode
13
13
  }
14
14
 
@@ -18,11 +18,17 @@ export interface ShowProps<T> {
18
18
  *
19
19
  * @example
20
20
  * ```tsx
21
- * <Show field={article.fields.publishedAt}>
21
+ * // Plain children - use when field value isn't needed
22
+ * <Show field={article.publishedAt}>
23
+ * <PublishedBadge />
24
+ * </Show>
25
+ *
26
+ * // Callback children - receive non-null field value
27
+ * <Show field={article.publishedAt}>
22
28
  * {value => <time>{value.toISOString()}</time>}
23
29
  * </Show>
24
30
  *
25
- * <Show field={author.fields.bio} fallback={<span>No bio</span>}>
31
+ * <Show field={author.bio} fallback={<span>No bio</span>}>
26
32
  * {bio => <p>{bio}</p>}
27
33
  * </Show>
28
34
  * ```
@@ -35,7 +41,11 @@ function ShowImpl<T>({ field, children, fallback }: ShowProps<T>): ReactElement
35
41
  return fallback ? <>{fallback}</> : null
36
42
  }
37
43
 
38
- return <>{children(accessor.value as NonNullable<T>)}</>
44
+ const rendered = typeof children === 'function'
45
+ ? children(accessor.value as NonNullable<T>)
46
+ : children
47
+
48
+ return <>{rendered}</>
39
49
  }
40
50
 
41
51
  export const Show = memo(ShowImpl) as typeof ShowImpl
@@ -43,16 +53,29 @@ export const Show = memo(ShowImpl) as typeof ShowImpl
43
53
  // Static method for selection extraction
44
54
  const showWithSelection = Show as typeof Show & SelectionProvider & { [BINDX_COMPONENT]: true }
45
55
 
46
- showWithSelection.getSelection = (props: ShowProps<unknown>): SelectionFieldMeta | null => {
56
+ showWithSelection.getSelection = (
57
+ props: ShowProps<unknown>,
58
+ collectNested: (children: ReactNode) => SelectionMeta,
59
+ ): SelectionFieldMeta[] | null => {
47
60
  const meta = props.field[FIELD_REF_META]
48
-
49
- return {
61
+ const result: SelectionFieldMeta[] = [{
50
62
  fieldName: meta.fieldName,
51
63
  alias: meta.fieldName,
52
64
  path: meta.path,
53
65
  isArray: false,
54
66
  isRelation: false,
67
+ }]
68
+
69
+ // Plain ReactNode children may contain nested <Field>/<HasOne>/etc.
70
+ // Callback children can't be analyzed statically (skipped).
71
+ if (typeof props.children !== 'function') {
72
+ const nested = collectNested(props.children)
73
+ for (const field of nested.fields.values()) {
74
+ result.push(field)
75
+ }
55
76
  }
77
+
78
+ return result
56
79
  }
57
80
 
58
81
  showWithSelection[BINDX_COMPONENT] = true
@@ -0,0 +1,276 @@
1
+ import React, {
2
+ Children,
3
+ Fragment,
4
+ isValidElement,
5
+ memo,
6
+ type ReactElement,
7
+ type ReactNode,
8
+ } from 'react'
9
+ import type {
10
+ FieldRef,
11
+ SelectionFieldMeta,
12
+ SelectionMeta,
13
+ SelectionProvider,
14
+ } from '../types.js'
15
+ import { FIELD_REF_META, BINDX_COMPONENT } from '../types.js'
16
+ import { useField } from '../../hooks/useField.js'
17
+ import {
18
+ type Condition,
19
+ isCondition,
20
+ evaluateCondition,
21
+ collectConditionFields,
22
+ } from '../conditions.js'
23
+
24
+ /**
25
+ * Props for <Case>. Discriminated union: exactly one of `show` or `if` must be set.
26
+ *
27
+ * - `show={fieldRef}` matches when the field value is neither `null` nor `undefined`.
28
+ * Children may be a callback receiving the non-null value.
29
+ * - `if={cond}` accepts a boolean, a `FieldRef<boolean>`, or a `Condition` DSL object.
30
+ */
31
+ export type CaseProps<T = unknown> =
32
+ | {
33
+ show: FieldRef<T>
34
+ if?: never
35
+ children: ReactNode | ((value: NonNullable<T>) => ReactNode)
36
+ }
37
+ | {
38
+ show?: never
39
+ if: Condition | FieldRef<boolean> | boolean
40
+ children: ReactNode
41
+ }
42
+
43
+ export interface DefaultProps {
44
+ children: ReactNode
45
+ }
46
+
47
+ export interface SwitchProps {
48
+ children: ReactNode
49
+ }
50
+
51
+ /**
52
+ * Marker component for a case branch inside <Switch>. Never renders on its own —
53
+ * <Switch> reads its props to decide which branch to render.
54
+ */
55
+ export function Case<T>(_props: CaseProps<T>): null {
56
+ return null
57
+ }
58
+
59
+ /**
60
+ * Marker component for the fallback branch inside <Switch>. At most one allowed.
61
+ */
62
+ export function Default(_props: DefaultProps): null {
63
+ return null
64
+ }
65
+
66
+ // =============================================================================
67
+ // Child extraction
68
+ // =============================================================================
69
+
70
+ interface CaseEntry {
71
+ readonly props: CaseProps<unknown>
72
+ }
73
+
74
+ interface DefaultEntry {
75
+ readonly props: DefaultProps
76
+ }
77
+
78
+ interface SwitchEntries {
79
+ readonly cases: readonly CaseEntry[]
80
+ readonly defaultEntry: DefaultEntry | null
81
+ }
82
+
83
+ function isFieldRef(value: unknown): value is FieldRef<unknown> {
84
+ return typeof value === 'object' && value !== null && FIELD_REF_META in value
85
+ }
86
+
87
+ function extractEntries(children: ReactNode): SwitchEntries {
88
+ const cases: CaseEntry[] = []
89
+ let defaultEntry: DefaultEntry | null = null
90
+
91
+ const visit = (node: ReactNode): void => {
92
+ if (node === null || node === undefined || typeof node === 'boolean') return
93
+ if (typeof node === 'string' || typeof node === 'number') return
94
+ if (Array.isArray(node)) {
95
+ for (const child of node) visit(child)
96
+ return
97
+ }
98
+ if (!isValidElement(node)) return
99
+ if (node.type === Fragment) {
100
+ visit((node.props as { children?: ReactNode }).children)
101
+ return
102
+ }
103
+ if (node.type === Case) {
104
+ cases.push({ props: node.props as CaseProps<unknown> })
105
+ return
106
+ }
107
+ if (node.type === Default) {
108
+ if (defaultEntry !== null) {
109
+ throw new Error('<Switch> allows at most one <Default>')
110
+ }
111
+ defaultEntry = { props: node.props as DefaultProps }
112
+ return
113
+ }
114
+ throw new Error('<Switch> children must be <Case> or <Default>')
115
+ }
116
+
117
+ Children.forEach(children, visit)
118
+
119
+ return { cases, defaultEntry }
120
+ }
121
+
122
+ function resolveTriggerField(props: CaseProps<unknown>): FieldRef<unknown> | null {
123
+ if ('show' in props && props.show !== undefined) {
124
+ return props.show
125
+ }
126
+ if ('if' in props && props.if !== undefined) {
127
+ const condition = props.if
128
+ if (typeof condition !== 'boolean' && !isCondition(condition)) {
129
+ return condition as FieldRef<unknown>
130
+ }
131
+ }
132
+ return null
133
+ }
134
+
135
+ // =============================================================================
136
+ // Runtime
137
+ // =============================================================================
138
+
139
+ function SwitchImpl({ children }: SwitchProps): ReactElement | null {
140
+ const entries = extractEntries(children)
141
+
142
+ // Subscribe to one field per case (stable count, stable order).
143
+ const accessors: Array<{ value: unknown } | null> = []
144
+ for (const entry of entries.cases) {
145
+ const ref = resolveTriggerField(entry.props)
146
+ // eslint-disable-next-line react-hooks/rules-of-hooks
147
+ accessors.push(useField(ref))
148
+ }
149
+
150
+ for (let i = 0; i < entries.cases.length; i++) {
151
+ const { props } = entries.cases[i]!
152
+ const accessor = accessors[i]!
153
+
154
+ if ('show' in props && props.show !== undefined) {
155
+ const value = accessor?.value
156
+ if (value !== null && value !== undefined) {
157
+ const rendered = typeof props.children === 'function'
158
+ ? props.children(value as NonNullable<unknown>)
159
+ : props.children
160
+ return <>{rendered}</>
161
+ }
162
+ continue
163
+ }
164
+
165
+ const condition = props.if
166
+ let matched: boolean
167
+ if (typeof condition === 'boolean') {
168
+ matched = condition
169
+ } else if (isCondition(condition)) {
170
+ matched = evaluateCondition(condition)
171
+ } else {
172
+ matched = Boolean(accessor?.value)
173
+ }
174
+ if (matched) {
175
+ return <>{props.children}</>
176
+ }
177
+ }
178
+
179
+ if (entries.defaultEntry !== null) {
180
+ return <>{entries.defaultEntry.props.children}</>
181
+ }
182
+ return null
183
+ }
184
+
185
+ export const Switch = memo(SwitchImpl)
186
+
187
+ // =============================================================================
188
+ // Selection analysis
189
+ // =============================================================================
190
+
191
+ function fieldRefToSelectionField(ref: FieldRef<unknown>): SelectionFieldMeta {
192
+ const meta = ref[FIELD_REF_META]
193
+ return {
194
+ fieldName: meta.fieldName,
195
+ alias: meta.fieldName,
196
+ path: meta.path,
197
+ isArray: meta.isArray ?? false,
198
+ isRelation: meta.isRelation ?? false,
199
+ }
200
+ }
201
+
202
+ function pushNestedFields(
203
+ target: SelectionFieldMeta[],
204
+ nested: SelectionMeta,
205
+ ): void {
206
+ for (const field of nested.fields.values()) {
207
+ target.push(field)
208
+ }
209
+ }
210
+
211
+ const caseWithSelection = Case as typeof Case & SelectionProvider & { [BINDX_COMPONENT]: true }
212
+
213
+ caseWithSelection.getSelection = (
214
+ props: CaseProps<unknown>,
215
+ collectNested: (children: ReactNode) => SelectionMeta,
216
+ ): SelectionFieldMeta[] | null => {
217
+ const result: SelectionFieldMeta[] = []
218
+
219
+ if ('show' in props && props.show !== undefined) {
220
+ result.push(fieldRefToSelectionField(props.show))
221
+ } else if ('if' in props && props.if !== undefined) {
222
+ const condition = props.if
223
+ if (typeof condition !== 'boolean') {
224
+ if (isCondition(condition)) {
225
+ for (const field of collectConditionFields(condition)) {
226
+ if (isFieldRef(field)) {
227
+ result.push(fieldRefToSelectionField(field))
228
+ }
229
+ }
230
+ } else if (isFieldRef(condition)) {
231
+ result.push(fieldRefToSelectionField(condition))
232
+ }
233
+ }
234
+ }
235
+
236
+ // Callback children can't be statically analyzed.
237
+ if (typeof props.children !== 'function') {
238
+ pushNestedFields(result, collectNested(props.children))
239
+ }
240
+
241
+ return result.length > 0 ? result : null
242
+ }
243
+
244
+ caseWithSelection[BINDX_COMPONENT] = true
245
+
246
+ const defaultWithSelection = Default as typeof Default & SelectionProvider & { [BINDX_COMPONENT]: true }
247
+
248
+ defaultWithSelection.getSelection = (
249
+ props: DefaultProps,
250
+ collectNested: (children: ReactNode) => SelectionMeta,
251
+ ): SelectionFieldMeta[] | null => {
252
+ const result: SelectionFieldMeta[] = []
253
+ pushNestedFields(result, collectNested(props.children))
254
+ return result.length > 0 ? result : null
255
+ }
256
+
257
+ defaultWithSelection[BINDX_COMPONENT] = true
258
+
259
+ const switchWithSelection = Switch as typeof Switch & SelectionProvider & { [BINDX_COMPONENT]: true }
260
+
261
+ switchWithSelection.getSelection = (
262
+ props: SwitchProps,
263
+ collectNested: (children: ReactNode) => SelectionMeta,
264
+ ): SelectionFieldMeta[] | null => {
265
+ const result: SelectionFieldMeta[] = []
266
+ pushNestedFields(result, collectNested(props.children))
267
+ return result.length > 0 ? result : null
268
+ }
269
+
270
+ switchWithSelection[BINDX_COMPONENT] = true
271
+
272
+ export {
273
+ switchWithSelection as SwitchWithMeta,
274
+ caseWithSelection as CaseWithMeta,
275
+ defaultWithSelection as DefaultWithMeta,
276
+ }
@@ -16,6 +16,19 @@ export { If, IfWithMeta } from './If.js'
16
16
  // Show component
17
17
  export { Show, ShowWithMeta, type ShowProps } from './Show.js'
18
18
 
19
+ // Switch / Case / Default components
20
+ export {
21
+ Switch,
22
+ Case,
23
+ Default,
24
+ SwitchWithMeta,
25
+ CaseWithMeta,
26
+ DefaultWithMeta,
27
+ type SwitchProps,
28
+ type CaseProps,
29
+ type DefaultProps,
30
+ } from './Switch.js'
31
+
19
32
  // Entity component
20
33
  export { Entity, type EntityProps } from './Entity.js'
21
34
 
package/src/jsx/index.ts CHANGED
@@ -58,6 +58,17 @@ export { HasMany, HasManyWithMeta } from './components/HasMany.js'
58
58
  export { HasOne, HasOneWithMeta } from './components/HasOne.js'
59
59
  export { If, IfWithMeta } from './components/If.js'
60
60
  export { Show, ShowWithMeta, type ShowProps } from './components/Show.js'
61
+ export {
62
+ Switch,
63
+ Case,
64
+ Default,
65
+ SwitchWithMeta,
66
+ CaseWithMeta,
67
+ DefaultWithMeta,
68
+ type SwitchProps,
69
+ type CaseProps,
70
+ type DefaultProps,
71
+ } from './components/Switch.js'
61
72
  export { Entity, type EntityProps } from './components/Entity.js'
62
73
  export { EntityList, type EntityListProps } from './components/EntityList.js'
63
74
  export { HasRole, type HasRoleProps } from './components/HasRole.js'