@cosmicdrift/kumiko-renderer 0.386.0 → 0.387.0
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/LICENSE +21 -57
- package/dist/app/action-form-body.d.ts +2 -2
- package/dist/app/action-form-body.js +2 -2
- package/dist/app/action-form-shim.d.ts +8 -8
- package/dist/app/action-form-shim.js +20 -22
- package/dist/app/app-features-context.js +4 -4
- package/dist/app/column-renderers.d.ts +7 -9
- package/dist/app/column-renderers.js +15 -18
- package/dist/app/config-edit-body.js +1 -1
- package/dist/app/config-edit-shim.d.ts +7 -8
- package/dist/app/config-edit-shim.js +18 -20
- package/dist/app/custom-screens.d.ts +3 -3
- package/dist/app/custom-screens.js +8 -8
- package/dist/app/dashboard-body.d.ts +2 -2
- package/dist/app/dashboard-body.js +2 -2
- package/dist/app/entity-edit-prefill.js +9 -9
- package/dist/app/entity-edit-screen.js +4 -4
- package/dist/app/entity-list-screen.js +3 -3
- package/dist/app/extension-form-submit.d.ts +1 -1
- package/dist/app/extension-form-submit.js +14 -15
- package/dist/app/extension-sections.d.ts +24 -25
- package/dist/app/extension-sections.js +10 -10
- package/dist/app/feature-schema.js +11 -11
- package/dist/app/form-schema.js +1 -1
- package/dist/app/header-actions-bar.js +1 -1
- package/dist/app/kumiko-screen.js +8 -10
- package/dist/app/layout-fields.js +1 -1
- package/dist/app/list-facets.js +3 -3
- package/dist/app/nav.d.ts +10 -10
- package/dist/app/nav.js +13 -13
- package/dist/app/projection-detail-body.js +4 -4
- package/dist/app/projection-detail-shim.d.ts +6 -5
- package/dist/app/projection-detail-shim.js +23 -22
- package/dist/app/projection-list-body.js +10 -10
- package/dist/app/projection-list-shim.d.ts +5 -5
- package/dist/app/projection-list-shim.js +17 -18
- package/dist/app/qn.js +10 -12
- package/dist/app/qualify-screen-id.js +1 -1
- package/dist/app/screen-access.js +2 -2
- package/dist/app/screen-shared.js +1 -1
- package/dist/app/secret-mint-body.js +4 -4
- package/dist/app/write-failed-error.js +8 -7
- package/dist/components/embedded-list-field.js +4 -4
- package/dist/components/grid-cell-for-field.d.ts +1 -1
- package/dist/components/reference-create-dialog.js +3 -3
- package/dist/components/related-list-section.d.ts +1 -1
- package/dist/components/related-list-section.js +1 -1
- package/dist/components/render-edit-logic.js +1 -1
- package/dist/components/render-edit-types.d.ts +6 -6
- package/dist/components/render-edit.js +63 -65
- package/dist/components/render-field.d.ts +7 -7
- package/dist/components/render-field.js +57 -59
- package/dist/components/render-list.d.ts +42 -43
- package/dist/components/render-list.js +63 -67
- package/dist/components/use-wizard-form-draft.js +10 -10
- package/dist/context/dispatcher-context.js +5 -5
- package/dist/context/user-roles-context.js +2 -2
- package/dist/headless/apex/index.d.ts +1 -2
- package/dist/headless/apex/index.js +5 -6
- package/dist/headless/form/form-controller.js +6 -6
- package/dist/headless/form/zod-bridge.js +2 -2
- package/dist/headless/format/money.js +1 -1
- package/dist/headless/index.js +2 -2
- package/dist/headless/view-model/edit.js +2 -2
- package/dist/headless/view-model/list.js +3 -4
- package/dist/headless/view-model/types.d.ts +3 -3
- package/dist/hooks/reference-limits.js +11 -12
- package/dist/hooks/use-list-url-state.d.ts +13 -13
- package/dist/hooks/use-list-url-state.js +21 -22
- package/dist/hooks/use-query.js +3 -3
- package/dist/hooks/use-reference-lookup.js +16 -17
- package/dist/hooks/use-store.js +18 -22
- package/dist/hooks/use-stream-handler.js +4 -2
- package/dist/i18n-defaults.js +2 -8
- package/dist/i18n.d.ts +10 -10
- package/dist/i18n.js +25 -25
- package/dist/index.js +5 -4
- package/dist/live/dispatcher-live.js +2 -2
- package/dist/primitives.d.ts +225 -221
- package/dist/primitives.js +1 -1
- package/dist/sse/live-events.d.ts +5 -5
- package/dist/sse/live-events.js +17 -17
- package/dist/tokens.d.ts +8 -8
- package/dist/tokens.js +16 -17
- package/dist/web/app/browser-locale.d.ts +9 -9
- package/dist/web/app/browser-locale.js +19 -19
- package/dist/web/app/client-plugin.d.ts +44 -52
- package/dist/web/app/client-plugin.js +4 -5
- package/dist/web/app/create-app.d.ts +28 -31
- package/dist/web/app/create-app.js +21 -22
- package/dist/web/app/document-lang-sync.js +1 -1
- package/dist/web/app/draft-storage.js +1 -1
- package/dist/web/app/nav-providers-context.d.ts +3 -3
- package/dist/web/app/nav-providers-context.js +3 -3
- package/dist/web/app/nav.d.ts +18 -17
- package/dist/web/app/nav.js +66 -64
- package/dist/web/app/rich-content-editor.js +1 -1
- package/dist/web/components/config-cascade.js +17 -18
- package/dist/web/components/config-source-badge.js +4 -4
- package/dist/web/layout/app-layout.d.ts +9 -9
- package/dist/web/layout/app-layout.js +2 -2
- package/dist/web/layout/avatar.d.ts +4 -3
- package/dist/web/layout/avatar.js +15 -17
- package/dist/web/layout/default-app-shell.d.ts +22 -23
- package/dist/web/layout/editor-panel.js +3 -3
- package/dist/web/layout/nav-tree.js +86 -84
- package/dist/web/layout/profile-menu.d.ts +1 -1
- package/dist/web/layout/sidebar-brand.d.ts +7 -7
- package/dist/web/layout/sidebar-user.d.ts +1 -1
- package/dist/web/layout/sidebar-user.js +4 -4
- package/dist/web/layout/sidebar.d.ts +8 -8
- package/dist/web/layout/sidebar.js +7 -7
- package/dist/web/layout/target-resolver-stub.d.ts +5 -5
- package/dist/web/layout/target-resolver-stub.js +20 -20
- package/dist/web/layout/target-url.d.ts +7 -7
- package/dist/web/layout/target-url.js +22 -22
- package/dist/web/layout/theme-toggle.js +4 -5
- package/dist/web/layout/workspace-shell.d.ts +21 -21
- package/dist/web/layout/workspace-shell.js +29 -30
- package/dist/web/lib/cn.d.ts +4 -4
- package/dist/web/lib/cn.js +4 -4
- package/dist/web/primitives/action-menu.d.ts +8 -8
- package/dist/web/primitives/action-menu.js +14 -13
- package/dist/web/primitives/calendar-popover.d.ts +1 -1
- package/dist/web/primitives/calendar-popover.js +10 -10
- package/dist/web/primitives/card-styles.js +1 -1
- package/dist/web/primitives/card.js +2 -2
- package/dist/web/primitives/combobox.d.ts +12 -12
- package/dist/web/primitives/combobox.js +34 -35
- package/dist/web/primitives/data-table-cell.js +2 -2
- package/dist/web/primitives/data-table.js +2 -3
- package/dist/web/primitives/date-field.js +2 -2
- package/dist/web/primitives/date-input.js +4 -4
- package/dist/web/primitives/default-form.js +2 -2
- package/dist/web/primitives/dropdown-menu.js +14 -15
- package/dist/web/primitives/embedded-list-input.js +3 -3
- package/dist/web/primitives/facet-filter.js +1 -1
- package/dist/web/primitives/field.js +9 -8
- package/dist/web/primitives/form.d.ts +1 -1
- package/dist/web/primitives/form.js +6 -6
- package/dist/web/primitives/input.js +2 -2
- package/dist/web/primitives/layout-elements.js +1 -1
- package/dist/web/primitives/layout.js +2 -2
- package/dist/web/primitives/located-timestamp-input.js +4 -4
- package/dist/web/primitives/money-input.js +13 -17
- package/dist/web/primitives/pager.js +1 -1
- package/dist/web/primitives/row-actions.js +3 -4
- package/dist/web/primitives/secret-reveal.js +1 -1
- package/dist/web/primitives/timestamp-input.d.ts +9 -9
- package/dist/web/primitives/timestamp-input.js +21 -21
- package/dist/web/primitives/toast.js +12 -13
- package/dist/web/sse/live-events.d.ts +6 -6
- package/dist/web/sse/live-events.js +3 -3
- package/dist/web/tokens.d.ts +11 -12
- package/dist/web/tokens.js +35 -37
- package/dist/web/version/update-checker.js +14 -13
- package/dist/web/widgets/ai-text-field.js +1 -1
- package/dist/web/widgets/charts.d.ts +10 -10
- package/dist/web/widgets/charts.js +8 -8
- package/dist/web/widgets/collapsible-section.d.ts +3 -3
- package/dist/web/widgets/collapsible-section.js +6 -6
- package/dist/web/widgets/detail-list.d.ts +1 -3
- package/dist/web/widgets/detail-list.js +1 -3
- package/dist/web/widgets/feed-list.d.ts +2 -2
- package/dist/web/widgets/feed-list.js +2 -2
- package/dist/web/widgets/form-fields.d.ts +14 -14
- package/dist/web/widgets/form-fields.js +14 -13
- package/dist/web/widgets/index.js +4 -4
- package/dist/web/widgets/infinity-list.js +3 -3
- package/dist/web/widgets/mode-switch.d.ts +2 -2
- package/dist/web/widgets/mode-switch.js +2 -2
- package/dist/web/widgets/progress-list.d.ts +1 -2
- package/dist/web/widgets/progress-list.js +1 -2
- package/dist/web/widgets/query-table.d.ts +6 -6
- package/dist/web/widgets/result-panel.d.ts +16 -16
- package/dist/web/widgets/result-panel.js +10 -10
- package/dist/web/widgets/section-card.d.ts +3 -3
- package/dist/web/widgets/section-card.js +3 -3
- package/dist/web/widgets/stat.d.ts +4 -4
- package/dist/web/widgets/stat.js +6 -6
- package/dist/web/widgets/states.d.ts +4 -4
- package/dist/web/widgets/states.js +4 -4
- package/dist/web/widgets/use-draft.d.ts +7 -7
- package/dist/web/widgets/use-draft.js +7 -7
- package/package.json +6 -6
package/dist/primitives.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useContext, } from "react";
|
|
3
3
|
/** Structural marker a top-level `actions` node can carry so DefaultForm's
|
|
4
|
-
* sticky-footer split
|
|
4
|
+
* sticky-footer split treats it as the pinned primary action even
|
|
5
5
|
* though it isn't a `Button` with `type="submit"` — e.g. RenderEdit's
|
|
6
6
|
* footer-slot mount, whose actual rendered button is opaque app code the
|
|
7
7
|
* split can't inspect (see `ScreenSlots.footerPrimary`). */
|
|
@@ -14,15 +14,15 @@ export type LiveEvent = {
|
|
|
14
14
|
/** Synthetic eventType delivered to every subscribed entity after the stream
|
|
15
15
|
* reconnected: frames during the gap are lost, so consumers must refetch. */
|
|
16
16
|
export declare const LIVE_RESYNC_EVENT_TYPE = "live.resync";
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
/** Subscribes to live events for an entity (aggregateType) and returns the
|
|
18
|
+
* unsubscribe function. Multiple subscriptions to the same entity are
|
|
19
|
+
* allowed in parallel; each receives its own event. */
|
|
20
20
|
export type LiveEventSubscriber = (entityName: string, listener: (event: LiveEvent) => void) => () => void;
|
|
21
21
|
export type LiveEventsProviderProps = {
|
|
22
22
|
readonly children: ReactNode;
|
|
23
23
|
readonly value: LiveEventSubscriber;
|
|
24
24
|
};
|
|
25
25
|
export declare function LiveEventsProvider({ children, value }: LiveEventsProviderProps): ReactNode;
|
|
26
|
-
/** Hook
|
|
27
|
-
*
|
|
26
|
+
/** Hook for a useQuery-like consumer. Returns the subscription function
|
|
27
|
+
* from the context. Without a provider, it is a no-op. */
|
|
28
28
|
export declare function useLiveEvents(): LiveEventSubscriber;
|
package/dist/sse/live-events.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
//
|
|
3
|
-
// EventSource, Native
|
|
4
|
-
// via `<LiveEventsProvider value={...}>`;
|
|
5
|
-
//
|
|
2
|
+
// Platform-neutral live-events contract. The platform (Web with
|
|
3
|
+
// EventSource, Native with polyfill) supplies a `LiveEventSubscriber`
|
|
4
|
+
// via `<LiveEventsProvider value={...}>`; the shared layer consumes
|
|
5
|
+
// only the interface.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
7
|
+
// A Context is used instead of a module singleton as before the split:
|
|
8
|
+
// a module singleton couples the code to a global connection. Context
|
|
9
|
+
// lets the caller provide a different subscription source per tree,
|
|
10
|
+
// which is useful for tests (Fake-Feed), multi-tenant bridges, and
|
|
11
|
+
// the Native renderer, where connection lifecycle often differs from
|
|
12
|
+
// the app lifecycle.
|
|
13
13
|
import { createContext, useContext } from "react";
|
|
14
14
|
/** Synthetic eventType delivered to every subscribed entity after the stream
|
|
15
15
|
* reconnected: frames during the gap are lost, so consumers must refetch. */
|
|
16
16
|
export const LIVE_RESYNC_EVENT_TYPE = "live.resync";
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
17
|
+
// If no provider is present, return a no-op subscriber instead of
|
|
18
|
+
// throwing. This allows useQuery({ live: true }) to be optimistically
|
|
19
|
+
// disabled without tearing down the entire tree when the platform has
|
|
20
|
+
// temporarily disabled SSE. Error signals are silently swallowed; this
|
|
21
|
+
// is intentional and documented.
|
|
22
22
|
const noopSubscriber = () => () => { };
|
|
23
23
|
const LiveEventsContext = createContext(noopSubscriber);
|
|
24
24
|
export function LiveEventsProvider({ children, value }) {
|
|
25
25
|
return _jsx(LiveEventsContext.Provider, { value: value, children: children });
|
|
26
26
|
}
|
|
27
|
-
/** Hook
|
|
28
|
-
*
|
|
27
|
+
/** Hook for a useQuery-like consumer. Returns the subscription function
|
|
28
|
+
* from the context. Without a provider, it is a no-op. */
|
|
29
29
|
export function useLiveEvents() {
|
|
30
30
|
return useContext(LiveEventsContext);
|
|
31
31
|
}
|
package/dist/tokens.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export type CoreTokens = {
|
|
|
44
44
|
readonly shadow: ShadowTokens;
|
|
45
45
|
readonly spacing: SpacingTokens;
|
|
46
46
|
};
|
|
47
|
-
/**
|
|
47
|
+
/** Extension point for app-specific token categories. Augment it, for example:
|
|
48
48
|
*
|
|
49
49
|
* declare module "@cosmicdrift/kumiko-renderer" {
|
|
50
50
|
* interface AppTokens {
|
|
@@ -52,8 +52,8 @@ export type CoreTokens = {
|
|
|
52
52
|
* }
|
|
53
53
|
* }
|
|
54
54
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
55
|
+
* Then provide the matching `--chart-*` variables in the app's CSS.
|
|
56
|
+
* Kumiko's default primitives use only CoreTokens. */
|
|
57
57
|
export interface AppTokens {
|
|
58
58
|
}
|
|
59
59
|
export type Tokens = CoreTokens & AppTokens;
|
|
@@ -78,12 +78,12 @@ export type TokensProviderProps = {
|
|
|
78
78
|
readonly value: TokensApi;
|
|
79
79
|
};
|
|
80
80
|
export declare function TokensProvider({ children, value }: TokensProviderProps): ReactNode;
|
|
81
|
-
/** Read-only
|
|
82
|
-
* style
|
|
83
|
-
* `bg-[var(--color-primary)]` (
|
|
84
|
-
* `bg-primary`
|
|
81
|
+
/** Read-only tokens hook. Provides CSS variable strings for use in
|
|
82
|
+
* style props or Tailwind arbitrary values such as
|
|
83
|
+
* `bg-[var(--color-primary)]` (rarely needed; the shadcn Tailwind class
|
|
84
|
+
* `bg-primary` is more idiomatic). */
|
|
85
85
|
export declare function useTokens(): Tokens;
|
|
86
|
-
/**
|
|
86
|
+
/** Full API including theme toggling, for a dark/light switch button. */
|
|
87
87
|
export declare function useTokenController(): TokensApi;
|
|
88
88
|
/** Tokens with var-string values. Constant: the "values" are references,
|
|
89
89
|
* the real colors change via CSS without mutating the object. Platform
|
package/dist/tokens.js
CHANGED
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
// Design
|
|
3
|
-
//
|
|
4
|
-
// styles.css (Web)
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// ihn nicht.
|
|
2
|
+
// Design tokens using the shadcn naming scheme. Values are CSS variable
|
|
3
|
+
// references (`var(--color-primary)`); the actual values live in
|
|
4
|
+
// styles.css (Web) or a StyleSheet.create configuration (Native,
|
|
5
|
+
// later). The hook is mainly for custom components that need to pass a
|
|
6
|
+
// token value to a JS style prop; the default primitives use Tailwind
|
|
7
|
+
// classes directly and do not need it.
|
|
9
8
|
//
|
|
10
|
-
// Theme
|
|
11
|
-
//
|
|
12
|
-
//
|
|
9
|
+
// Theme toggling uses the `.dark` class on `<html>`, so no JS state is
|
|
10
|
+
// needed and CSS updates immediately. `useTokenController().toggleTheme()`
|
|
11
|
+
// is only a DOM wrapper, not separate React state.
|
|
13
12
|
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
13
|
+
// Extensible: augment the AppTokens interface as with primitives. Apps can
|
|
14
|
+
// declare custom token categories and populate them with var strings.
|
|
16
15
|
import { createContext, useContext } from "react";
|
|
17
16
|
// ---- Context + Provider + Hooks ----
|
|
18
17
|
const TokensContext = createContext(undefined);
|
|
19
18
|
export function TokensProvider({ children, value }) {
|
|
20
19
|
return _jsx(TokensContext.Provider, { value: value, children: children });
|
|
21
20
|
}
|
|
22
|
-
/** Read-only
|
|
23
|
-
* style
|
|
24
|
-
* `bg-[var(--color-primary)]` (
|
|
25
|
-
* `bg-primary`
|
|
21
|
+
/** Read-only tokens hook. Provides CSS variable strings for use in
|
|
22
|
+
* style props or Tailwind arbitrary values such as
|
|
23
|
+
* `bg-[var(--color-primary)]` (rarely needed; the shadcn Tailwind class
|
|
24
|
+
* `bg-primary` is more idiomatic). */
|
|
26
25
|
export function useTokens() {
|
|
27
26
|
return useTokenController().tokens;
|
|
28
27
|
}
|
|
29
|
-
/**
|
|
28
|
+
/** Full API including theme toggling, for a dark/light switch button. */
|
|
30
29
|
export function useTokenController() {
|
|
31
30
|
const api = useContext(TokensContext);
|
|
32
31
|
if (api === undefined) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type LocaleResolver } from "../../headless/index.ts";
|
|
2
2
|
export type CreateBrowserLocaleResolverOptions = {
|
|
3
|
-
/** localStorage
|
|
4
|
-
* Default: `"kumiko:locale"`. Apps
|
|
5
|
-
*
|
|
3
|
+
/** localStorage key used to persist the active locale.
|
|
4
|
+
* Default: `"kumiko:locale"`. Apps that mount multiple Kumiko instances on
|
|
5
|
+
* the same origin (rarely) should use different keys. */
|
|
6
6
|
readonly storageKey?: string;
|
|
7
|
-
/** Fallback
|
|
7
|
+
/** Fallback when neither localStorage nor navigator.language provides a locale.
|
|
8
8
|
* Default: `"en"`. */
|
|
9
9
|
readonly defaultLocale?: string;
|
|
10
10
|
/** Maps a stored or browser-reported tag onto one of the app's locales;
|
|
@@ -14,9 +14,9 @@ export type CreateBrowserLocaleResolverOptions = {
|
|
|
14
14
|
readonly normalizeLocale?: (tag: string) => string | undefined;
|
|
15
15
|
};
|
|
16
16
|
export declare const BROWSER_LOCALE_STORAGE_KEY = "kumiko:locale";
|
|
17
|
-
/** Default
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
/** Default resolver when createKumikoApp is booted without a `locale` option.
|
|
18
|
+
* Stateful: setLocale() persists to localStorage and notifies subscribed
|
|
19
|
+
* listeners. Apps with a full i18n layer (i18next, FormatJS, or a custom
|
|
20
|
+
* store) should instead pass their own resolver via
|
|
21
|
+
* `createKumikoApp({ locale })`. */
|
|
22
22
|
export declare function createBrowserLocaleResolver(options?: CreateBrowserLocaleResolverOptions): LocaleResolver;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
// Browser-
|
|
1
|
+
// Browser-specific LocaleResolver default for createKumikoApp.
|
|
2
2
|
//
|
|
3
|
-
// Stateful:
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// Stateful: stores the current locale in localStorage and notifies subscribed
|
|
4
|
+
// listeners when setLocale() is called. The initial value comes from
|
|
5
|
+
// localStorage when available, otherwise from navigator.language, and finally
|
|
6
|
+
// from defaultLocale.
|
|
6
7
|
//
|
|
7
|
-
// App
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// App-Code, nicht im Resolver).
|
|
8
|
+
// App code sets the locale programmatically via resolver.setLocale(), as the
|
|
9
|
+
// LanguageSwitcher component does. localStorage persistence preserves the
|
|
10
|
+
// language after a page reload without a server round trip. Cross-device
|
|
11
|
+
// persistence would additionally require a user:write:update for user.locale
|
|
12
|
+
// in separate app code, not in the resolver.
|
|
13
13
|
import { createStore } from "../../headless/index.js";
|
|
14
14
|
export const BROWSER_LOCALE_STORAGE_KEY = "kumiko:locale";
|
|
15
15
|
function detectInitialLocale(storageKey, fallback, normalizeLocale) {
|
|
@@ -23,8 +23,8 @@ function detectInitialLocale(storageKey, fallback, normalizeLocale) {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
catch {
|
|
26
|
-
// localStorage
|
|
27
|
-
//
|
|
26
|
+
// localStorage can throw (Safari private mode, disabled) —
|
|
27
|
+
// silently fall back to navigator.
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
if (typeof navigator !== "undefined" && navigator.language) {
|
|
@@ -42,11 +42,11 @@ function detectTimeZone() {
|
|
|
42
42
|
return "UTC";
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
/** Default
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
45
|
+
/** Default resolver when createKumikoApp is booted without a `locale` option.
|
|
46
|
+
* Stateful: setLocale() persists to localStorage and notifies subscribed
|
|
47
|
+
* listeners. Apps with a full i18n layer (i18next, FormatJS, or a custom
|
|
48
|
+
* store) should instead pass their own resolver via
|
|
49
|
+
* `createKumikoApp({ locale })`. */
|
|
50
50
|
export function createBrowserLocaleResolver(options = {}) {
|
|
51
51
|
const storageKey = options.storageKey ?? BROWSER_LOCALE_STORAGE_KEY;
|
|
52
52
|
const fallback = options.defaultLocale ?? "en";
|
|
@@ -69,8 +69,8 @@ export function createBrowserLocaleResolver(options = {}) {
|
|
|
69
69
|
localStorage.setItem(storageKey, next);
|
|
70
70
|
}
|
|
71
71
|
catch {
|
|
72
|
-
//
|
|
73
|
-
//
|
|
72
|
+
// Persistence failure is not fatal — the session locale remains set,
|
|
73
|
+
// but the next reload will lose it.
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
},
|
|
@@ -12,62 +12,57 @@ export type CollectionNavProviders = {
|
|
|
12
12
|
};
|
|
13
13
|
export type ClientFeatureDefinition = {
|
|
14
14
|
readonly name: string;
|
|
15
|
-
/** Context
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* jedes Screen-Child darauf Zugriff hat. */
|
|
15
|
+
/** Context providers wrapped around the complete renderer tree. The first
|
|
16
|
+
* array element is the outermost provider. All providers precede all gates
|
|
17
|
+
* in the tree so every gate and screen child can access them. */
|
|
19
18
|
readonly providers?: readonly ComponentType<{
|
|
20
19
|
children: ReactNode;
|
|
21
20
|
}>[];
|
|
22
|
-
/** Screen
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
21
|
+
/** Screen decorators placed between the provider stack and the shell or
|
|
22
|
+
* screen render. A typical pattern is AuthGate rendering LoginScreen
|
|
23
|
+
* instead of children while the user is not signed in. The first array
|
|
24
|
+
* element is the outermost gate. */
|
|
26
25
|
readonly gates?: readonly ComponentType<{
|
|
27
26
|
children: ReactNode;
|
|
28
27
|
}>[];
|
|
29
|
-
/** Default
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* komplett ausgetauscht werden müssen. */
|
|
28
|
+
/** Default translations supplied by the feature for its UI strings. They
|
|
29
|
+
* are added to the LocaleProvider as a fallback bundle; the app resolver
|
|
30
|
+
* (for example, i18next) takes precedence and can override individual keys
|
|
31
|
+
* without replacing the feature bundles entirely. */
|
|
34
32
|
readonly translations?: TranslationsByLocale;
|
|
35
|
-
/** Custom
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* `r.screen({ id, type: "custom", ... })` im server-side Feature. */
|
|
33
|
+
/** Custom screen components, mapped by screenId. When a schema screen has
|
|
34
|
+
* `type: "custom"`, KumikoScreen looks up and renders the matching component
|
|
35
|
+
* in this map, merged from all client features. This keeps routing out of
|
|
36
|
+
* the AppShell wrapper. The convention is that screenId matches the `id` in
|
|
37
|
+
* `r.screen({ id, type: "custom", ... })` in the server-side feature. */
|
|
41
38
|
readonly components?: Readonly<Record<string, ComponentType>>;
|
|
42
|
-
/** Column
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* Kollision über mehrere Features. */
|
|
39
|
+
/** Column renderer components, mapped by renderer name. A schema declares a
|
|
40
|
+
* column with `renderer: { react: { __component: "ColorSwatch" } }`; the
|
|
41
|
+
* client-side DataTable cell renderer looks up the component here. Schemas
|
|
42
|
+
* remain serializable because only a string key crosses the wire, while the
|
|
43
|
+
* actual JSX renderers live in the client bundle. Later features win on key
|
|
44
|
+
* collisions. */
|
|
49
45
|
readonly columnRenderers?: Readonly<Record<string, ColumnRendererComponent>>;
|
|
50
|
-
/** Extension-
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* bei Key-Kollision über mehrere Features. */
|
|
46
|
+
/** Extension-section components, mapped by `__component` name. A schema
|
|
47
|
+
* declares an entityEdit section with `kind: "extension"` and
|
|
48
|
+
* `component: { react: { __component: "X" } }`; RenderEdit looks up and
|
|
49
|
+
* mounts the component here with `{ entityName, entityId }`. As with
|
|
50
|
+
* columnRenderers, later features win on key collisions. */
|
|
56
51
|
readonly extensionSectionComponents?: Readonly<Record<string, ExtensionSectionComponent>>;
|
|
57
52
|
/** Handlers for RowAction `kind: "clientAction"`, keyed by the action name
|
|
58
53
|
* `<feature>:<kebab>`. Last-wins with a warning on key collisions, like
|
|
59
54
|
* columnRenderers. */
|
|
60
55
|
readonly clientActions?: Readonly<Record<string, ClientActionHandler>>;
|
|
61
|
-
/** Nav
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
56
|
+
/** Nav providers for the single nav visual-tree merge: they attach dynamic
|
|
57
|
+
* children to a static `r.nav({ provider: true })` node. Keys use the local
|
|
58
|
+
* nav ID; create-app qualifies it as `<feature>:nav:<id>`, while already
|
|
59
|
+
* qualified names pass through. Unlike `treeProvider`, which creates one
|
|
60
|
+
* top-level branch per feature, a navProvider attaches to a specific nav
|
|
61
|
+
* node—the idiomatic approach since the tree-to-nav merge. */
|
|
67
62
|
readonly navProviders?: Readonly<Record<string, TreeChildrenSubscribe>>;
|
|
68
|
-
/** SSE
|
|
69
|
-
*
|
|
70
|
-
*
|
|
63
|
+
/** SSE entity lists per nav ID for live refresh of navProviders, analogous
|
|
64
|
+
* to `treeEntities`. A live event for an entity re-invokes the node's
|
|
65
|
+
* provider so new children appear immediately. */
|
|
71
66
|
readonly navEntities?: Readonly<Record<string, readonly string[]>>;
|
|
72
67
|
/** Nav providers derived from the app schema — called with every
|
|
73
68
|
* `r.contentCollection()` the app declares. A feature that serves any
|
|
@@ -85,22 +80,19 @@ export type ClientFeatureDefinition = {
|
|
|
85
80
|
* format. Same last-wins semantics as columnRenderers. Public component
|
|
86
81
|
* contract: `{ value, onChange, variables, readOnly }`. */
|
|
87
82
|
readonly contentEditors?: Partial<Record<ContentEditorFormat, ContentEditorComponent>>;
|
|
88
|
-
/** Editor
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* zeigt der EditorPanel einen Info-Fallback.
|
|
93
|
-
* Siehe visual-tree.md V.1.2. */
|
|
83
|
+
/** Editor resolver components keyed by featureId:action. When a TreeNode
|
|
84
|
+
* with a target is clicked, EditorPanel looks up and renders the component
|
|
85
|
+
* here. Components receive target (with args) and an onClose callback. If
|
|
86
|
+
* no resolver is registered, EditorPanel shows an informational fallback. */
|
|
94
87
|
readonly resolvers?: Readonly<Record<string, ComponentType<{
|
|
95
88
|
readonly target: TargetRef;
|
|
96
89
|
readonly onClose: () => void;
|
|
97
90
|
}>>>;
|
|
98
91
|
};
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* ihre Reihenfolge nicht ändert. */
|
|
92
|
+
/** Wraps a ReactNode with a list of providers or gates from inside out; the
|
|
93
|
+
* first array element is the outermost wrapper. The key uses the component's
|
|
94
|
+
* display name, when available, plus its index, keeping mounts stable while
|
|
95
|
+
* the wrapper list's order does not change. */
|
|
104
96
|
export declare function stackWrappers(wrappers: readonly ComponentType<{
|
|
105
97
|
children: ReactNode;
|
|
106
98
|
}>[], inner: ReactNode): ReactNode;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* ihre Reihenfolge nicht ändert. */
|
|
2
|
+
/** Wraps a ReactNode with a list of providers or gates from inside out; the
|
|
3
|
+
* first array element is the outermost wrapper. The key uses the component's
|
|
4
|
+
* display name, when available, plus its index, keeping mounts stable while
|
|
5
|
+
* the wrapper list's order does not change. */
|
|
7
6
|
export function stackWrappers(wrappers, inner) {
|
|
8
7
|
return wrappers.reduceRight((acc, Wrapper, i) => {
|
|
9
8
|
const key = `${Wrapper.displayName ?? Wrapper.name ?? "wrapper"}-${i}`;
|
|
@@ -42,7 +42,7 @@ export type CreateKumikoAppOptions = {
|
|
|
42
42
|
* `createLiveDispatcher`); a cross-origin URL is fetched with
|
|
43
43
|
* `credentials: "include"`. */
|
|
44
44
|
readonly schemaUrl?: string;
|
|
45
|
-
/** RenderEdit's create-mode draftId storage
|
|
45
|
+
/** RenderEdit's create-mode draftId storage — where a
|
|
46
46
|
* same-tab reload finds which of several parallel create-sessions on a
|
|
47
47
|
* screen to resume. Default: `createBrowserDraftStorage()`
|
|
48
48
|
* (sessionStorage-backed). Apps that don't want any client-side draftId
|
|
@@ -52,51 +52,48 @@ export type CreateKumikoAppOptions = {
|
|
|
52
52
|
readonly screenQn?: string;
|
|
53
53
|
readonly translate?: Translate;
|
|
54
54
|
/** Row-click fallback for entities with no declared `detailFor` screen
|
|
55
|
-
*
|
|
55
|
+
* — a `detailFor` screen always wins over this option. */
|
|
56
56
|
readonly onRowClick?: (row: ListRowViewModel, entityName: string) => void;
|
|
57
|
-
/** App
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* greifen. */
|
|
57
|
+
/** App shell. Receives the resolved `schema` as a prop so AppShell
|
|
58
|
+
* components can pass it through to WorkspaceShell/DefaultAppShell
|
|
59
|
+
* without importing the schema themselves or accessing window globals. */
|
|
61
60
|
readonly shell?: (props: {
|
|
62
61
|
readonly children: ReactNode;
|
|
63
62
|
readonly schema: AppSchema;
|
|
64
63
|
}) => ReactNode;
|
|
65
64
|
readonly primitives?: Partial<PrimitivesRegistry>;
|
|
66
|
-
/**
|
|
67
|
-
*
|
|
68
|
-
* `clientFeatures: [emailPasswordClient()]`
|
|
65
|
+
/** Client extensions supplied by features. Each element provides a
|
|
66
|
+
* provider and gates; see ClientFeatureDefinition. Example:
|
|
67
|
+
* `clientFeatures: [emailPasswordClient()]` for session and login. */
|
|
69
68
|
readonly clientFeatures?: readonly ClientFeatureDefinition[];
|
|
70
|
-
/** App-level LocaleResolver.
|
|
71
|
-
*
|
|
72
|
-
* (`locale: "en"`, `translate: key → key`);
|
|
73
|
-
*
|
|
69
|
+
/** App-level LocaleResolver. Typically an adapter around i18next
|
|
70
|
+
* or a custom store. If unset, the static default is used
|
|
71
|
+
* (`locale: "en"`, `translate: key → key`); plugin translations then
|
|
72
|
+
* serve as fallbacks. */
|
|
74
73
|
readonly locale?: LocaleResolver;
|
|
75
|
-
/**
|
|
76
|
-
* (route + navigate + hrefFor). Default: `useBrowserNavApi`,
|
|
77
|
-
* window.history
|
|
78
|
-
*
|
|
79
|
-
*
|
|
74
|
+
/** Navigation adapter — a React hook that returns a NavApi instance
|
|
75
|
+
* (route + navigate + hrefFor). Default: `useBrowserNavApi`, which uses
|
|
76
|
+
* window.history as the source of truth. To integrate another router
|
|
77
|
+
* (TanStack Router, Expo Linking on mobile, or a memory router in tests),
|
|
78
|
+
* provide your own hook here.
|
|
80
79
|
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* ist das gängige Pattern.
|
|
80
|
+
* The hook is called ONCE in the component tree (see `BrowserNavBoot`),
|
|
81
|
+
* so it must follow the React Rules of Hooks — `useSyncExternalStore` on
|
|
82
|
+
* the underlying router state is the usual pattern.
|
|
85
83
|
*
|
|
86
|
-
*
|
|
87
|
-
* `{ hasWorkspaces: true }
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* dürfen sie ignorieren. */
|
|
84
|
+
* When the schema declares workspaces, the adapter is called with
|
|
85
|
+
* `{ hasWorkspaces: true }`; the default hook uses this to change the URL
|
|
86
|
+
* pattern to `/<workspace>/<screen>[/<entityId>]`. Custom adapters may
|
|
87
|
+
* ignore this option if their router handles it differently. `features` is
|
|
88
|
+
* `app.features`; the default hook needs it for resolveTarget()
|
|
89
|
+
* (ObjectTarget → ScreenTarget). Adapters that never receive an
|
|
90
|
+
* ObjectTarget may ignore it. */
|
|
94
91
|
readonly navAdapter?: (options?: {
|
|
95
92
|
readonly hasWorkspaces?: boolean;
|
|
96
93
|
readonly features?: readonly FeatureSchema[];
|
|
97
94
|
}) => NavApi;
|
|
98
95
|
/** App-wide default width for form/detail screens that don't set their
|
|
99
|
-
* own `layout.width
|
|
96
|
+
* own `layout.width`. Default "4xl" (unchanged behavior) — a
|
|
100
97
|
* consumer app that wants e.g. bundled-feature screens to match its own
|
|
101
98
|
* full-width lists passes `screenWidth: "full"` once here instead of
|
|
102
99
|
* forking every screen it doesn't own. Per-screen `layout.width` always
|