Skip to main content

Kandra.ClientLib.Common

Kandra.ClientLib.Common.ApiClients.IBlobsApiClient

Methods

MethodDescription
DownloadAsync(Guid, CancellationToken)undocumented

Kandra.ClientLib.Common.ApiClients.IConstantsApiClient

Methods

MethodDescription
AddAsync(String, SetConstantValueDto, CancellationToken)Adds a new value - always a create, never an edit-in-place (see IConstantsManageService.SetRawAsync's doc comment).
DeleteAsync(Guid, CancellationToken)Deletes by the row's own id rather than by its effective instant - see IConstantsManageService.DeleteAsync(Guid,...)'s doc comment for why (also sidesteps the DateTime-in-a-route-segment slash-encoding gotcha a date-keyed route hit here previously).
UpdateValueAsync(Guid, UpdateConstantValueDto, CancellationToken)Edits one existing row's value in place, by id - see IConstantsManageService.UpdateValueAsync's doc comment for why this never matches by date.

Kandra.ClientLib.Common.ApiClients.IDataProcessorApiClient<T0, T1>

Kandra.ClientLib.Common.ApiClients.IDictionaryApiClient<T0, T1, T2>

Kandra.ClientLib.Common.ApiClients.IDocumentApiClient<T0, T1, T2>

Methods

MethodDescription
PrintAsync(Guid, DocumentExportRequest, CancellationToken)undocumented

Kandra.ClientLib.Common.ApiClients.IEntityApiClient<T0, T1, T2>

Methods

MethodDescription
GetChangeStateAsync(Guid, CancellationToken)undocumented
GetHistoryAsync(Guid, ChangeHistoryQueryDto, CancellationToken)undocumented

Kandra.ClientLib.Common.ApiClients.IHandlerApiClient<T0, T1>

Generic Refit contract every handler's own hand-written closed client interface extends, e.g. [PathPrefix("/api/v1/handlers/PriceLookupForLine")] interface IPriceLookupForLineApiClient : IHandlerApiClient<WaybillPriceLookupRequestDto, WaybillPriceLookupResponseDto> — same hand-written-closed-interface-per-entity pattern as IDocumentApiClient/IDataProcessorApiClient (Refit's own generator can't see a source-generated interface, see ClientGenerator's doc comment). Kandra.Generators.ClientLib.Clients.ClientEmitter bridges every handler's closed client to this generic interface in DI (services.AddScoped<IHandlerApiClient<TIn,TOut>>(p => p.GetRequiredService<IFooApiClient>())) — no service-wrapper, unlike the entity kinds above, but enough for generated UI (Kandra.Generators.Ui.Blazor.DocumentUiEmitter) to [Inject] a handler's client purely from its (TIn,TOut) pair, without ever needing to know the closed interface's name/namespace. A handler's (TIn,TOut) pair isn't guaranteed unique across handlers (only the Name is, server-side), so two handlers sharing a pair share one DI registration/injected property — the same class of risk every other entity-kind bridge above already accepts for its Dto+Query pair, not a new one.

Kandra.ClientLib.Common.ApiClients.IHierarchicalDictionaryApiClient<T0, T1, T2>

Kandra.ClientLib.Common.ApiClients.IKandraApiClient

Kandra.ClientLib.Common.ApiClients.IKandraProtectedApiClient

Kandra.ClientLib.Common.ApiClients.IReportApiClient<T0, T1>

Kandra.ClientLib.Common.CultureHandler

Kandra.ClientLib.Common.DateTimeConversionOptions

Methods

MethodDescription
Override(Boolean)undocumented

Kandra.ClientLib.Common.Services.ClientTimeZoneService

Kandra.ClientLib.Common.Services.Crud.IDictionaryLookupService

Kandra.ClientLib.Common.Services.Crud.IDictionaryService<T0, T1>

Methods

MethodDescription
GetChangeState(Guid)undocumented
GetHistory(Guid, ChangeHistoryQueryDto)undocumented

Kandra.ClientLib.Common.Services.Crud.IDocumentLookupService<T0, T1>

Kandra.ClientLib.Common.Services.Crud.IDocumentService<T0, T1>

Methods

MethodDescription
GetChangeState(Guid)undocumented
GetHistory(Guid, ChangeHistoryQueryDto)undocumented

Kandra.ClientLib.Common.Services.Crud.IFlatDictionaryLookupService<T0, T1>

Kandra.ClientLib.Common.Services.Crud.IHierarchicalDictionaryLookupService<T0, T1>

Methods

MethodDescription
LookupBreadcrumbs(Nullable<Guid>, CancellationToken)undocumented

Kandra.ClientLib.Common.Services.Crud.IHierarchicalDictionaryService<T0, T1>

Methods

MethodDescription
GetChangeState(Guid)undocumented
GetHistory(Guid, ChangeHistoryQueryDto)undocumented

Kandra.ClientLib.Common.Services.Crud.PrintedFile

Kandra.ClientLib.Common.Services.Errors.ApiProblemDetails

Minimal client-side mirror of ASP.NET Core's ProblemDetails wire shape - deliberately not a reference to the server-side Microsoft.AspNetCore.Mvc.ProblemDetails type, since this is a Blazor WASM client project and shouldn't pull in ASP.NET Core MVC abstractions just to read four JSON fields back out of an error response.

Kandra.ClientLib.Common.Services.Errors.ApiProblemDetailsReader

Extracts the server's real ApiProblemDetails (including its extension fields) out of a caught Refit ApiException - today, nothing in the client parses this; every catch site just shows ex.Message, which for an ApiException is Refit's own generic "Response status code does not indicate success..." text, not the server's actual detail. Used specifically to detect a license-limit response (see LicenseLimitDialog) without hand-rolling JSON parsing at every call site.

Methods

MethodDescription
GetExtensionLong(ApiProblemDetails, String)Reads a numeric extension value (e.g. "limit"/"current") off problem, or null if absent.
GetExtensionString(ApiProblemDetails, String)Reads a string-typed extension value (e.g. "limitKind") off problem, or null if absent.
TryRead(Exception)Tries to read exception's response body as ApiProblemDetails. Returns null if the exception isn't an ApiException, has no content, or the content isn't valid ProblemDetails JSON - callers should fall back to the plain ex.Message alert in that case.

Kandra.ClientLib.Common.Services.IBlobsClientService

Kandra.ClientLib.Common.Services.IClientTimeZoneService

Kandra.ClientLib.Common.Services.IInterfacesService

Client-side wrapper around IInterfacesApiClient plus "which Interface is currently selected" - persisted via ILocalStorageService (not raw JS interop, unlike the culture switcher), and falls back to the first (default) visible Interface when nothing is stored yet or the stored one is no longer visible to the current user.

Events

EventDescription
ChangedRaised after SetCurrentInterfaceAsync - NavMenu/UserNav re-render without a full page reload (switching Interfaces only changes which nav links are shown, unlike a culture switch, which needs one).

Kandra.ClientLib.Common.Services.Security.JwtFeatureDefinitionProvider

Reads enabled features from the logged-in user's JWT claims (stamped server-side by Kandra.Api.Lib.Services.LoginService) instead of a client-side config file - the client has no appsettings-equivalent of its own, the server's Microsoft.FeatureManagement evaluation is the single source of truth.

Constructors

ConstructorDescription
JwtFeatureDefinitionProvider(IAuthenticationContext)Reads enabled features from the logged-in user's JWT claims (stamped server-side by Kandra.Api.Lib.Services.LoginService) instead of a client-side config file - the client has no appsettings-equivalent of its own, the server's Microsoft.FeatureManagement evaluation is the single source of truth.

Kandra.ClientLib.Common.TimeZoneHandler

Constructors

ConstructorDescription
TimeZoneHandler(IClientTimeZoneService)undocumented

Kandra.ClientLib.Common.TypeRegistry.ITypeRegistry

Resolves a runtime Guid TypeId to its CLR Type (Dto or enum) plus kind classification - the client-visible counterpart of IEntityWithTypeId/TypeIdResolver, built from what KandraWms.Forms/KandraWms.Enums can see (the client can't reference KandraWms.Domain). The implementation is generated - see Kandra.Generators.TypeRegistry.

Kandra.ClientLib.Common.TypeRegistry.TypeRegistryEntry

One [TypeId]-attributed CLR type (a Dictionary/Document Dto or a subconto-backing enum), as discovered from KandraWms.Forms/KandraWms.Enums. ClrType is exactly the [TypeId]-attributed type itself - for a hierarchical dictionary this is the concrete leaf Dto (e.g. CounterpartyDto, since [TypeId] sits on the leaf, see Kandra.Generators.TypeRegistry.TypeRegistryDiscovery's own doc comment), which is also what a resolved subconto value's entity row really is. DialogDtoType is what a selector control must actually be parameterized with to look the value up/pick a new one - the root Dto for a hierarchical dictionary (e.g. CounterpartyNodeDto, matching the "Search/Dropdown/Dialog must target the abstract root Dto" rule every other selector attribute already follows), otherwise identical to ClrType (flat dictionary, document, or the enum type itself for Enum). DialogQueryType is the paired QueryDto a dialog/search selector needs (null only for Enum, which has no server-side lookup at all). IsHierarchical picks between the flat and hierarchical selector component families at runtime - always false for Document/Enum kinds.

Constructors

ConstructorDescription
TypeRegistryEntry(Guid, Type, TypeKind, Type, Type, Boolean)One [TypeId]-attributed CLR type (a Dictionary/Document Dto or a subconto-backing enum), as discovered from KandraWms.Forms/KandraWms.Enums. ClrType is exactly the [TypeId]-attributed type itself - for a hierarchical dictionary this is the concrete leaf Dto (e.g. CounterpartyDto, since [TypeId] sits on the leaf, see Kandra.Generators.TypeRegistry.TypeRegistryDiscovery's own doc comment), which is also what a resolved subconto value's entity row really is. DialogDtoType is what a selector control must actually be parameterized with to look the value up/pick a new one - the root Dto for a hierarchical dictionary (e.g. CounterpartyNodeDto, matching the "Search/Dropdown/Dialog must target the abstract root Dto" rule every other selector attribute already follows), otherwise identical to ClrType (flat dictionary, document, or the enum type itself for Enum). DialogQueryType is the paired QueryDto a dialog/search selector needs (null only for Enum, which has no server-side lookup at all). IsHierarchical picks between the flat and hierarchical selector component families at runtime - always false for Document/Enum kinds.

Kandra.ClientLib.Common.Ui.IUiRenderer

UI-framework-agnostic rendering primitives for a generated Document/Dictionary/Report/DataProcessor form — the counterpart to Kandra.Printing's IPrintRenderTarget, and the reason this interface lives in Kandra.ClientLib.Common rather than alongside its one current implementation (Kandra.ClientLib.MudBlazor.Ui.BlazorUiRenderer, driven by Kandra.Generators.Ui.Blazor - a Blazor/MudBlazor- specific generator project despite its "Ui" folder name, see UiFormGenerator's doc comment). A generator emits a short, straight-line sequence of calls into this interface instead of hand-building framework-specific markup (RenderTreeBuilder calls for Blazor today; potentially native controls for a future Kandra.ClientLib.Avalonia host - with its own sibling generator project (Kandra.Generators.Ui.Avalonia) reusing the same Kandra.Generators.Shared discovery/model types - reading the same Form metadata, per docs/kandra-architecture.md §4.4 and §9 Phase 5, which named .NET MAUI as this second stack until v0.7) - all the "how do I actually build this control" knowledge lives in one real, compiled renderer implementation per framework instead of being re-derived correctly in every emitter call site's string template. Container-shaped members (Form and friends) are fluent: the method itself opens the surrounding context, invokes body with the renderer, and closes the context afterwards - there is no caller-visible Begin/End pair for generated code to get out of sync.

Methods

MethodDescription
AddAccountSelector(String, Func<String>, Action<String>, UiSelectorKind, UiNodeSelection, Boolean, Func<Task>)Account-code selector ([AccountSearch]/[AccountDialog]): binds a string? property directly (the account's Code, e.g. "68" or "28.1") - unlike AddDictionarySelector's Guid/Guid.Empty coalescing, no widening is needed here since the underlying component's own SelectedCode parameter is itself string?. No TDto/TQuery type parameters and no Dropdown case - there is exactly one chart of accounts per configuration, not a per-field choice of source Dto. No Expression<Func<...>> valueExpression, same reasoning as AddDictionaryMultiSelector - bound via SelectedCode, not the component's own MudBaseInput<string> Value, so there's no ambient "For"/validation wiring to feed.
AddAccountSubcontoEditor(String, Func<String>, Action<String>, UiSelectorKind, IReadOnlyList<Func<Nullable<Guid>>>, IReadOnlyList<Action<Nullable<Guid>>>, UiNodeSelection, Boolean)One [AccountSearch]/[AccountDialog] account-code field plus its 1-5 grouped [SubcontoEditor] slot fields (Kandra.Generators.Ui.Blazor.DocumentUiEmitter groups every field referencing the same account property into one call like this, instead of emitting the account field and each slot field independently). slotGets/slotSetters are ordered by slot index (0-4, validated contiguous at discovery time); the underlying component resolves each slot's allowed TypeId from the chosen account (via the client-side chart-of-accounts cache) and renders nothing for a slot the account doesn't declare - see Kandra.ClientLib.MudBlazor.Shared.Components.Selectors.AccountSubcontoEditor.
AddAccountSubcontoMultiSelectEditor(String, Func<String>, Action<String>, UiSelectorKind, IReadOnlyList<Func<IReadOnlyList<Guid>>>, IReadOnlyList<Action<IReadOnlyList<Guid>>>, UiNodeSelection, Boolean)Multi-select counterpart of AddAccountSubcontoEditor ([SubcontoMultiSelectEditor] slots) - each slot binds IReadOnlyList<Guid>? instead of Guid?.
AddButton(String, Func<Task>, Boolean)A single action button with an async click handler - the generic primitive behind a Report page's export buttons (one call per [SupportedExportFormats] flag actually set).
AddDateEditor(String, Func<Nullable<DateTime>>, Action<Nullable<DateTime>>, Boolean, Boolean, Func<Task>)timeOnly picks a time-only editor (MudTimePicker on the Blazor side) over a date-only one (MudDatePicker) - mirrors UiFieldModel.DateEditorKind's "Time" vs default distinction. No valueExpression parameter - matches the original codegen, which never attached a "ValueExpression"/"For" to date fields (so no validation-message routing for them today; not something this refactor should silently add).
AddDateRangeEditor(Func<DateRangeDto>, Action<DateRangeDto>, Func<Task>)Calendar range picker with quick-range presets ([DateRangeEditor], e.g. a Report's DateRange filter). The underlying component has no Label parameter of its own (its internal MudDateRangePicker always shows a fixed caption) - no caption here, unlike every other Add* method, for that reason.
AddDictionaryMultiSelector<T0, T1>(String, Func<IReadOnlyList<Guid>>, Action<IReadOnlyList<Guid>>, Boolean, Boolean, Func<Task>)Chip-based multi-value dictionary selector ([MultiSelect]): the collection analog of AddDictionarySelector. No UiSelectorKind parameter - unlike single-select, a multi-select only has one style (a dialog with a checkable list), so there's nothing to switch on. No Expression<Func<...>> valueExpression either - like AddFileEditor, this control isn't a MudBaseInput<T> (a collection doesn't fit that base cleanly), so there's no ambient "For"/validation wiring to feed.
AddDictionarySelector<T0, T1>(String, Func<Guid>, Action<Guid>, Expression<Func<Guid>>, UiSelectorKind, Boolean, UiNodeSelection, Boolean, Func<Task>)TDto/TQuery are the referenced dictionary's own Dto/query-result types - always known at the generator's compile time, so this stays fully typed with no reflection (matches the register engine's existing rejection of reflection-based construction, src/KandraCore/CLAUDE.md). Guid, not Guid? - matches the underlying MudBaseInput<Guid> selector components exactly (unselected is Guid.Empty, not null); the generator coalesces a nullable source property with ?? Guid.Empty when building get/valueExpression.
AddDocumentSelector<T0, T1>(String, Func<Guid>, Action<Guid>, Expression<Func<Guid>>, Boolean, Func<Task>)Document-reference counterpart of AddDictionarySelector - a [Search]/[Dropdown]/[Dialog] field whose SourceType resolved to a Document Dto instead of a Dictionary one. No UiSelectorKind/isHierarchical/nodeSelection parameters: a Document reference only ever renders as a modal dialog (DocumentDialogSelect), there is no dropdown/search style and no hierarchy to speak of. Same Guid/Guid.Empty-coalescing convention as AddDictionarySelector.
AddEnumGuidMultiSelect<T0>(String, Func<IReadOnlyList<Guid>>, Action<IReadOnlyList<Guid>>, Boolean, Func<Task>)Multi-value counterpart of AddEnumGuidSelect ([EnumGuidMultiSelect]) - binds IReadOnlyList<Guid>?. Unlike AddDictionaryMultiSelector, this doesn't need a dialog: the whole option set is compiled-in and small (a closed enum), so it renders as a native multi-select on the same MudSelect<Guid> shape AddEnumGuidSelect uses.
AddEnumGuidSelect<T0>(String, Func<Guid>, Action<Guid>, Expression<Func<Guid>>, Boolean, Func<Task>)Renders like AddEnumSelect (compiled-in options, no server round-trip, same [EnumCaption] item text) but binds the selected member's Guid [SubcontoId] (Kandra.Forms.Accounting.SubcontoEnumValues<TEnum>) instead of the enum value itself - for an [EnumGuidDropdown] field. Unlike AddEnumSelect, no localizer parameter - the underlying component (EnumGuidSelect<TEnum>) injects its own IStringLocalizer, since it's a real component rather than built inline. Guid, not Guid?, same Guid.Empty-coalescing convention as AddDictionarySelector.
AddEnumSelect<T0>(String, Func<T0>, Action<T0>, Expression<Func<T0>>, Boolean, Func<Task>)Opens EnumSelect<TEnum>, which captions each item via its own [EnumCaption] (Kandra.Localization.EnumLocalizationExtensions.GetCaption) using its own injected IStringLocalizer - no localizer parameter here, unlike this method's earlier inline-RenderTreeBuilder implementation, since the component resolves it itself.
AddExecuteButton(Boolean, String)Single full-width submit button for a DataProcessor's Execute action - no Cancel counterpart (unlike AddSaveCancelButtons's EditButtons-backed pair), since a generated DataProcessor page is a standalone single-purpose screen with nothing to navigate back to. Also ButtonType.Submit, routing through the enclosing Form's own submit pipeline exactly like AddSaveCancelButtons's Save button - no direct OnClick needed here either.
AddFileEditor(String, Func<Nullable<Guid>>, Action<Nullable<Guid>>, Expression<Func<Nullable<Guid>>>, String, Boolean, Func<Task>)Single-file attachment control ([FilePicker]): get/setter bind the nullable blob-reference id itself, unlike AddDictionarySelector - no Guid.Empty coalescing, since this field is genuinely Guid? (null = no file). Selecting a local file never uploads immediately; the concrete component registers a "flush" delegate with the ambient FormSaveContext (cascaded by Form/Form when the owning page provides one) so the upload happens, and setter fires with the resulting id, right before the page's own Save/Execute call - see Kandra.ClientLib.MudBlazor.Shared.FormSaveContext. extensions is the raw [FilePicker(Extensions=...)] value (e.g. "*.pdf"/"*.csv;*.xlsx") - null means any file type; parsing/formatting for the concrete UI framework happens in the renderer, not here.
AddPrintButton(Boolean, String, Func<Task>, Boolean)Full-width button (matches AddSaveCancelButtons/AddBackButton's own width, not the small icon-only button this replaces) for a Document's Print action - Update and View both place this via DocumentFormBase<TRecord,TValidator>, which is what keeps the position unified between them without either page needing its own opinion about it. trailingMargin should be true only when another button follows Print inside the same form (Update's Save/Submit/Cancel row) - View's Print is the form's last child (Back lives outside the tabs entirely, see EmitViewTabs), so it needs no bottom margin of its own there; passing true anyway would visibly stack on top of Back's own spacing instead of replacing it.
AddSaveCancelButtons(Boolean, String)Both buttons use ButtonType.Submit - Save routes through the enclosing EditForm's own submit pipeline (wired once when Form opens), matching plain HTML form-submit semantics rather than carrying its own click handler here.
AddSaveSubmitButtons(Boolean, String, String, Func<Boolean>, Action<Boolean>)Save-vs-Submit button pair for a Document form (matches the hand-written Waybill/Form.razor's own EditButtons ShowSubmit="true" usage) - both buttons are ButtonType.Submit exactly like AddSaveCancelButtons, but first record which one was clicked via getIntentSubmit/setIntentSubmit (a plain get/setter pair over a field the caller owns, same convention as every field editor above - a renderer instance is too short-lived, recreated on every render, to hold this itself). The actual "Save will unsubmit an active document" confirmation-dialog decision reads that flag back out from inside the enclosing Form's own onValidSubmit callback (needs IDialogService, so it lives on the calling component, not in this framework-agnostic interface).
AddTextEditor(String, Func<String>, Action<String>, Expression<Func<String>>, UiTextEditorMode, Int32, Boolean, Func<Task>)get/setter are the two-way binding pair a generator already builds today (() => Record.Prop / v => Record.Prop = v) - get is a plain compiled delegate, read directly on every render with no Expression.Compile() call (compiling an expression tree is comparatively expensive - orders of magnitude slower than invoking a delegate - and a fresh renderer is created on every BuildRenderTree, so paying that cost per field per render, e.g. on every keystroke for an Immediate text field, would be a real regression against the original hand-emitted codegen, which never compiled anything). valueExpression is the same binding as a genuine, uncompiled expression tree - needed separately because MudBlazor's "ValueExpression"/"For" parameters use it (via reflection over the expression's MemberExpression, not by executing it) to build a validation FieldIdentifier; the generator emits the identical () => Record.Prop lambda text for both arguments, so this costs it nothing extra to provide. onChanged carries a [HandlerTrigger] OnChange call (already resolved by UiFieldDiscovery at generator discovery time) - invoked after setter, before the implementation triggers its own re-render.
ButtonRow(Action<IUiRenderer>)Lays out body's buttons horizontally (a Row-oriented stack on the Blazor side) - wraps a sequence of AddButton calls exactly like a hand-written report page's own <MudStack Row="true"> today.
Form<T0>(T0, Boolean, Func<Task>, Action<IUiRenderer>)Opens the record-editing shell (an EditForm+MudCard, or a read-only MudForm when readOnly), invokes body to let the caller add field editors/buttons, then closes it. No client-side validator is attached. onValidSubmit is ignored when readOnly (a read-only MudForm never submits).
Form<T0, T1>(T0, Boolean, Func<Task>, Action<IUiRenderer>)Same as Form, additionally wrapping the shell in a FluentValidator<TValidator> (skipped entirely when readOnly, matching today's FlatDictionaryUiEmitter.EmitForm - a read-only MudForm never submits, so it never validates).
GridItem(Int32, Action<IUiRenderer>)A responsive column within a TablePart row - widthPercent (1-100; the emitter passes 100 for a field with no explicit [GridColumn(WidthPercent=...)], i.e. full row width) is converted to whatever column-count system the concrete framework uses (MudBlazor's MudItem: a 12-column grid, so 25% -> md="3"). Every field inside a TablePart row goes through this - never emitted bare - so they lay out as siblings in one responsive grid instead of each field silently claiming the full row width regardless of how many fields the row actually has.
TablePart<T0>(String, String, ICollection<T0>, Func<T0>, Action<IUiRenderer, T0>, Boolean, Func<T0, Task>)A Document's line-item (tabular section) editor - the counterpart to Form for the repeating Lines collection every Document (and no Dictionary today) carries. lines is the live, mutable collection the generator already binds two-way elsewhere (Record.Lines); newLine constructs a fresh row for the addCaption button (skipped when readOnly); rowBody is invoked once per row with the nested renderer and that row's own record so the caller can add per-line field editors, mirroring how Form's own body works one level up; onLineRemoved fires after a row is removed from lines (e.g. to recompute a document total), and is never invoked when readOnly (no delete button exists there).

Kandra.ClientLib.Common.Ui.UiNodeSelection

Which node types a hierarchical dictionary selector lets the user pick - mirrors Kandra.ClientLib.MudBlazor.Shared.Components.Selectors' own runtime enum of the same name/shape (that one lives in a Blazor-specific project this interface can't reference; the generator/renderer maps between the two at emit/render time, same reasoning as UiSelectorKind mirroring the analyzer-only UiEditorKind). Meaningless for a flat (non-hierarchical) selector - ignored in that case.

Fields

FieldDescription
Anyundocumented
Foldersundocumented
Leavesundocumented

Kandra.ClientLib.Common.Ui.UiSelectorKind

Dictionary-reference editor variants — mirrors the Dropdown/Search/Dialog subset of Kandra.Generators.Ui.Blazor's internal UiEditorKind (that enum lives in a netstandard2.0 analyzer-only project and can't be referenced from here; the generator maps between the two at emit time).

Kandra.ClientLib.Common.Ui.UiTextEditorMode

Text-field editor variants — one MudTextField shape covers all three (Kandra.Generators.Ui.Blazor's FieldEditorEmitter.EmitTextLike today), distinguished only by which extra attribute gets added.

Kandra.ClientLib.Common.UtcToLocalDateTimeJsonConverter

RefitInternalGenerated.Kandra_ClientLib_Common.PreserveAttribute

Identifies generated members that should be preserved by tools that honor this attribute.

Properties

PropertyDescription
AllMembersGets or sets a value indicating whether all members should be preserved.
ConditionalGets or sets a value indicating whether preservation should be conditional.