@cosmicdrift/kumiko-renderer 0.337.1 → 0.339.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/dist/app/kumiko-screen.js +28 -1
- package/dist/i18n-defaults.js +6 -0
- package/dist/index.d.ts +2 -2
- package/dist/primitives.d.ts +17 -5
- package/dist/tokens.d.ts +9 -0
- package/package.json +5 -5
- package/src/changes.json +12 -0
|
@@ -2386,6 +2386,23 @@ function mapFailedConfigCommandIssuesToField(error, failedIndex, commandFieldNam
|
|
|
2386
2386
|
},
|
|
2387
2387
|
};
|
|
2388
2388
|
}
|
|
2389
|
+
// A number/money field without a declared default starts empty: buildInitialValues
|
|
2390
|
+
// maps it to 0, which a save would persist as a deliberate "0" override.
|
|
2391
|
+
function buildConfigEditDefaults(fields) {
|
|
2392
|
+
const defaults = buildInitialValues(fields); // @cast-boundary render-helper
|
|
2393
|
+
for (const [shortName, fieldDef] of Object.entries(fields)) {
|
|
2394
|
+
const { type, default: fieldDefault } = fieldDef; // @cast-boundary schema-walk
|
|
2395
|
+
if ((type === "number" || type === "money") && fieldDefault === undefined) {
|
|
2396
|
+
defaults[shortName] = undefined;
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
return defaults;
|
|
2400
|
+
}
|
|
2401
|
+
function isEmptyNumericFormValue(value) {
|
|
2402
|
+
if (value === undefined || value === null || value === "")
|
|
2403
|
+
return true;
|
|
2404
|
+
return typeof value === "number" && !Number.isFinite(value);
|
|
2405
|
+
}
|
|
2389
2406
|
function ConfigEditBody({ schema, screen, translate, }) {
|
|
2390
2407
|
const { ConfigCascadeView } = usePrimitives();
|
|
2391
2408
|
const t = useTranslation();
|
|
@@ -2408,7 +2425,7 @@ function ConfigEditBody({ schema, screen, translate, }) {
|
|
|
2408
2425
|
if (valuesQuery.data === null)
|
|
2409
2426
|
return null;
|
|
2410
2427
|
const out = {};
|
|
2411
|
-
const defaults =
|
|
2428
|
+
const defaults = buildConfigEditDefaults(screen.fields);
|
|
2412
2429
|
for (const [shortName, fieldDef] of Object.entries(screen.fields)) {
|
|
2413
2430
|
const qualified = screen.configKeys[shortName];
|
|
2414
2431
|
if (qualified === undefined) {
|
|
@@ -2512,6 +2529,16 @@ function ConfigEditBody({ schema, screen, translate, }) {
|
|
|
2512
2529
|
});
|
|
2513
2530
|
continue;
|
|
2514
2531
|
}
|
|
2532
|
+
// Cleared number/money: drop this scope's override instead of storing an empty value.
|
|
2533
|
+
if ((ftype === "number" || ftype === "money") &&
|
|
2534
|
+
isEmptyNumericFormValue(ftype === "money" ? unwrapMoneyValue(value) : value)) {
|
|
2535
|
+
commandFieldNames.push(shortName);
|
|
2536
|
+
commands.push({
|
|
2537
|
+
type: "config:write:reset",
|
|
2538
|
+
payload: { key: qualified, scope: screen.scope },
|
|
2539
|
+
});
|
|
2540
|
+
continue;
|
|
2541
|
+
}
|
|
2515
2542
|
commandFieldNames.push(shortName);
|
|
2516
2543
|
commands.push({
|
|
2517
2544
|
type: "config:write:set",
|
package/dist/i18n-defaults.js
CHANGED
|
@@ -23,6 +23,8 @@ export const kumikoDefaultTranslations = {
|
|
|
23
23
|
"kumiko.actions.next": "Next",
|
|
24
24
|
"kumiko.actions.back": "Back",
|
|
25
25
|
"kumiko.actions.finish": "Finish",
|
|
26
|
+
"kumiko.boolean.no": "No",
|
|
27
|
+
"kumiko.boolean.yes": "Yes",
|
|
26
28
|
"kumiko.wizard.step": "Step {current} of {total}",
|
|
27
29
|
"kumiko.wizard.up-next": "Up next",
|
|
28
30
|
"kumiko.wizard.step-with-title": "Step {current} of {total} · {title}",
|
|
@@ -76,6 +78,7 @@ export const kumikoDefaultTranslations = {
|
|
|
76
78
|
"kumiko.list.count.other": "{count} entries",
|
|
77
79
|
"kumiko.list.row-actions.more": "More actions",
|
|
78
80
|
"kumiko.page-header.actions": "Page actions",
|
|
81
|
+
"kumiko.theme.auto": "Automatic theme",
|
|
79
82
|
"kumiko.theme.dark": "Dark theme",
|
|
80
83
|
"kumiko.theme.light": "Light theme",
|
|
81
84
|
"kumiko.list.row.collapse": "Collapse {title}",
|
|
@@ -136,6 +139,9 @@ export const kumikoDefaultTranslations = {
|
|
|
136
139
|
"kumiko.dialog.confirm": "Confirm",
|
|
137
140
|
"kumiko.dialog.cancel": "Cancel",
|
|
138
141
|
"kumiko.dialog.close": "Close",
|
|
142
|
+
"kumiko.lightbox.previous": "Previous image",
|
|
143
|
+
"kumiko.lightbox.next": "Next image",
|
|
144
|
+
"kumiko.lightbox.position": "{current} / {total}",
|
|
139
145
|
"kumiko.drawer.discard.title": "Discard changes?",
|
|
140
146
|
"kumiko.drawer.discard.body": "Your input in this form will be lost.",
|
|
141
147
|
"kumiko.drawer.discard.confirm": "Discard",
|
package/dist/index.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export { createStaticLocaleResolver, FormalityProvider, LocaleProvider, mergeTra
|
|
|
70
70
|
export { kumikoDefaultTranslations } from "./i18n-defaults.js";
|
|
71
71
|
export { InsideDrawerProvider, useInsideDrawer } from "./inside-drawer.js";
|
|
72
72
|
export { PageHeaderCompactProvider, PageHeaderSlotAvailableProvider, usePageHeaderCompact, usePageHeaderSlotAvailable, } from "./page-header-slot.js";
|
|
73
|
-
export type { ActionMenuItemSpec, ActionOverflowMenuProps, AppPrimitives, BannerProps, ButtonProps, CardOptions, CardProps, CardSlots, CopyButtonProps, CorePrimitives, DataTableDateRangeFacet, DataTableFacet, DataTableFacetChip, DataTableProps, DataTableRowAction, DataTableRowActionMode, DataTableRowGrouping, DataTableSort, DataTableSortDir, DialogProps, DrawerProps, EmbeddedListCellType, EmbeddedListColumn, EmbeddedListInputProps, EmbeddedListTotal, FieldCellWidth, FieldProps, FillContainerProps, FooterActionMarker, FooterActionRole, FormProps, FormSectionNavItem, FormWidth, GridCellProps, GridProps, HeadingProps, InputProps, JsonViewProps, LightboxProps, LinkProps, MetricBandProps, MetricProps, ModalProps, PageHeaderProps, PrimitivesProviderProps, PrimitivesRegistry, ProgressProps, ProgressTone, PromoPanelAction, PromoPanelProps, RuntimeRenderer, SecretRevealProps, SecretRevealValue, SectionProps, ShareButtonProps, StatusBadgeProps, StatusTone, StepBarProps, StickyActionBarProps, StickyPrimaryActionMarker, TabsProps, TextProps, TrailingInputAction, WizardStepGroupProps, } from "./primitives.js";
|
|
73
|
+
export type { ActionMenuItemSpec, ActionOverflowMenuProps, AppPrimitives, BannerProps, ButtonProps, CardOptions, CardProps, CardSlots, CopyButtonProps, CorePrimitives, DataTableDateRangeFacet, DataTableFacet, DataTableFacetChip, DataTableProps, DataTableRowAction, DataTableRowActionMode, DataTableRowGrouping, DataTableSort, DataTableSortDir, DialogProps, DrawerProps, EmbeddedListCellType, EmbeddedListColumn, EmbeddedListInputProps, EmbeddedListTotal, FieldCellWidth, FieldProps, FillContainerProps, FooterActionMarker, FooterActionRole, FormProps, FormSectionNavItem, FormWidth, GridCellProps, GridProps, HeadingProps, InputProps, JsonViewProps, LightboxImage, LightboxProps, LinkProps, MetricBandProps, MetricProps, ModalProps, PageHeaderProps, PrimitivesProviderProps, PrimitivesRegistry, ProgressProps, ProgressTone, PromoPanelAction, PromoPanelProps, RuntimeRenderer, SecretRevealProps, SecretRevealValue, SectionProps, ShareButtonProps, StatusBadgeProps, StatusTone, StepBarProps, StickyActionBarProps, StickyPrimaryActionMarker, TabsProps, TextProps, TrailingInputAction, WizardStepGroupProps, } from "./primitives.js";
|
|
74
74
|
export { FOOTER_ACTION_ROLE_PROP, NARROW_LABEL_PROP, PrimitivesProvider, STICKY_PRIMARY_ACTION_PROP, shouldRenderActionsIconOnly, statusToneForOptionTone, statusToneForValue, usePrimitives, } from "./primitives.js";
|
|
75
75
|
export type { SessionEndedSignal, SessionEndedSignalProviderProps, } from "./session/session-ended.js";
|
|
76
76
|
export { createSessionEndedSignal, isSessionEndedError, SESSION_ENDED_ERROR_CODES, SessionEndedSignalProvider, useSessionEndedSignal, withSessionEndedDetection, } from "./session/session-ended.js";
|
|
@@ -78,5 +78,5 @@ export { buildWhatsAppShareUrl } from "./share-links.js";
|
|
|
78
78
|
export { sortByAccessor } from "./sort-by-accessor.js";
|
|
79
79
|
export type { LiveEvent, LiveEventSubscriber, LiveEventsProviderProps } from "./sse/live-events.js";
|
|
80
80
|
export { LiveEventsProvider, useLiveEvents } from "./sse/live-events.js";
|
|
81
|
-
export type { AppTokens, ColorTokens, CoreTokens, FontTokens, RadiusTokens, ShadowTokens, SpacingTokens, ThemeMode, Tokens, TokensApi, TokensProviderProps, } from "./tokens.js";
|
|
81
|
+
export type { AppTokens, ColorTokens, CoreTokens, FontTokens, RadiusTokens, ShadowTokens, SpacingTokens, ThemeMode, ThemePreference, Tokens, TokensApi, TokensProviderProps, } from "./tokens.js";
|
|
82
82
|
export { cssVarTokens, TokensProvider, useTokenController, useTokens } from "./tokens.js";
|
package/dist/primitives.d.ts
CHANGED
|
@@ -1069,15 +1069,27 @@ export type DrawerProps = {
|
|
|
1069
1069
|
readonly children: ReactNode;
|
|
1070
1070
|
readonly testId?: string;
|
|
1071
1071
|
};
|
|
1072
|
-
|
|
1073
|
-
* trigger (thumbnail) and open state live in the app. */
|
|
1074
|
-
export type LightboxProps = {
|
|
1075
|
-
readonly open: boolean;
|
|
1076
|
-
readonly onOpenChange: (open: boolean) => void;
|
|
1072
|
+
export type LightboxImage = {
|
|
1077
1073
|
readonly src: string;
|
|
1078
1074
|
readonly alt: string;
|
|
1075
|
+
};
|
|
1076
|
+
type LightboxBaseProps = {
|
|
1077
|
+
readonly open: boolean;
|
|
1078
|
+
readonly onOpenChange: (open: boolean) => void;
|
|
1079
1079
|
readonly testId?: string;
|
|
1080
1080
|
};
|
|
1081
|
+
/** Image lightbox — full-size preview on click. Web renders Radix overlay;
|
|
1082
|
+
* trigger (thumbnail) and open state live in the app. Takes either one image
|
|
1083
|
+
* (`src`/`alt`) or a browsable set (`images` + controlled `index`);
|
|
1084
|
+
* navigation wraps around at both ends. */
|
|
1085
|
+
export type LightboxProps = LightboxBaseProps & ({
|
|
1086
|
+
readonly src: string;
|
|
1087
|
+
readonly alt: string;
|
|
1088
|
+
} | {
|
|
1089
|
+
readonly images: readonly LightboxImage[];
|
|
1090
|
+
readonly index: number;
|
|
1091
|
+
readonly onIndexChange: (index: number) => void;
|
|
1092
|
+
});
|
|
1081
1093
|
/** Source-badge for one cascade step (User / Tenant / System / …).
|
|
1082
1094
|
* Used inline next to a config value to indicate where it came from.
|
|
1083
1095
|
* Requires a LocaleProvider above it (labels run through useTranslation)
|
package/dist/tokens.d.ts
CHANGED
|
@@ -58,10 +58,19 @@ export interface AppTokens {
|
|
|
58
58
|
}
|
|
59
59
|
export type Tokens = CoreTokens & AppTokens;
|
|
60
60
|
export type ThemeMode = "light" | "dark";
|
|
61
|
+
/** "auto" follows the OS color scheme live; light/dark are explicit choices. */
|
|
62
|
+
export type ThemePreference = ThemeMode | "auto";
|
|
61
63
|
export type TokensApi = {
|
|
62
64
|
readonly tokens: Tokens;
|
|
65
|
+
/** The scheme currently applied (resolved from the preference when it is "auto"). */
|
|
63
66
|
readonly mode: ThemeMode;
|
|
67
|
+
/** Optional so hand-built TokensApi values (tests, custom providers) stay valid:
|
|
68
|
+
* absent means a plain light/dark implementation, read as `mode`. */
|
|
69
|
+
readonly preference?: ThemePreference;
|
|
70
|
+
readonly setPreference?: (preference: ThemePreference) => void;
|
|
71
|
+
/** Explicit choice: leaves "auto". */
|
|
64
72
|
readonly setMode: (mode: ThemeMode) => void;
|
|
73
|
+
/** Explicit flip of the resolved mode: leaves "auto". */
|
|
65
74
|
readonly toggleMode: () => void;
|
|
66
75
|
};
|
|
67
76
|
export type TokensProviderProps = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-renderer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.339.0",
|
|
4
4
|
"description": "Platform-agnostic React renderer for Kumiko screens. Contains the shared logic — primitives-contract, hooks, KumikoScreen, navigation & SSE abstractions — that any platform-specific renderer (web, native) composes. No DOM, no EventSource, no react-dom.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
19
|
-
"@cosmicdrift/kumiko-headless": "0.
|
|
20
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
18
|
+
"@cosmicdrift/kumiko-framework": "0.339.0",
|
|
19
|
+
"@cosmicdrift/kumiko-headless": "0.339.0",
|
|
20
|
+
"@cosmicdrift/kumiko-types": "0.339.0",
|
|
21
21
|
"react": "^19.2.6",
|
|
22
22
|
"temporal-polyfill": "^0.3.2",
|
|
23
23
|
"zod": "^4.4.3"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@types/react-dom": "^19.2.3",
|
|
29
29
|
"jsdom": "^29.1.1",
|
|
30
30
|
"react-dom": "^19.2.6",
|
|
31
|
-
"@cosmicdrift/kumiko-locale-de": "0.
|
|
31
|
+
"@cosmicdrift/kumiko-locale-de": "0.339.0"
|
|
32
32
|
},
|
|
33
33
|
"repository": {
|
|
34
34
|
"type": "git",
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.339.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "Lightbox pages through multiple images",
|
|
6
|
+
"detail": "`LightboxProps` is now a union: the existing `src`/`alt` form is unchanged, and the new `images` + `index` + `onIndexChange` form renders previous/next buttons, a position counter and ArrowLeft/ArrowRight navigation with wrap-around when more than one image is given. The Apex lightbox collects every `.shot-frame img` on open and gains previous/next buttons; its CSP script hash changed. New i18n keys: `kumiko.lightbox.previous`, `kumiko.lightbox.next`, `kumiko.lightbox.position`."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.338.0",
|
|
10
|
+
"type": "fix",
|
|
11
|
+
"title": "configEdit number and money fields start empty without a default",
|
|
12
|
+
"detail": "Number and money fields without a default no longer show 0, so saving does not write an unintended 0. Clearing a stored value resets this scope's override instead of sending an empty number."
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"version": "0.337.1",
|
|
4
16
|
"type": "improvement",
|