@cosmicdrift/kumiko-headless 0.333.0 → 0.334.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/index.d.ts CHANGED
@@ -11,4 +11,4 @@ export { resolveNavigation } from "./nav/index.js";
11
11
  export type { Store, WritableStore } from "./store/index.js";
12
12
  export { createStore, shallowEqual } from "./store/index.js";
13
13
  export type { ComputeEditViewModelInput, ComputeListViewModelInput, DerivedCellRoundingTarget, EditExtensionSectionViewModel, EditFieldSpec, EditFieldsSectionViewModel, EditFieldViewModel, EditRelatedListSectionViewModel, EditSectionSpec, EditSectionViewModel, EditViewModel, EditWriteFormSectionViewModel, EmbeddedDerivedOp, EmbeddedListCellViewModel, EmbeddedListIssueGroups, FieldConditionCtx, FieldRenderer, ListColumnSpec, ListColumnViewModel, ListRowViewModel, ListViewModel, RuntimeRenderer, ScreenSlots, Translate, } from "./view-model/index.js";
14
- export { computeDerivedCellValue, computeEditViewModel, computeListViewModel, computeRelatedListSectionViewModel, embeddedCellLabelKey, embeddedCellOptionLabelKey, fieldLabelKey, fieldOptionLabelKey, fieldOptionLabelKeyPrefix, groupEmbeddedListIssues, roundDerivedCellValue, sumEmbeddedListColumn, } from "./view-model/index.js";
14
+ export { buildOptionLabels, computeDerivedCellValue, computeEditViewModel, computeListViewModel, computeRelatedListSectionViewModel, embeddedCellLabelKey, embeddedCellOptionLabelKey, fieldLabelKey, fieldOptionLabelKey, fieldOptionLabelKeyPrefix, groupEmbeddedListIssues, roundDerivedCellValue, sumEmbeddedListColumn, } from "./view-model/index.js";
package/dist/index.js CHANGED
@@ -6,4 +6,4 @@ export { createFormController, I18N_KEY_PARAM } from "./form/index.js";
6
6
  export { applyFormatSpec, currencyDecimals, escapeHtml, escapeHtmlAttr, escapeXml, html, isSafeHref, RawHtml, raw, stripControlChars, toInstant, } from "./format/index.js";
7
7
  export { resolveNavigation } from "./nav/index.js";
8
8
  export { createStore, shallowEqual } from "./store/index.js";
9
- export { computeDerivedCellValue, computeEditViewModel, computeListViewModel, computeRelatedListSectionViewModel, embeddedCellLabelKey, embeddedCellOptionLabelKey, fieldLabelKey, fieldOptionLabelKey, fieldOptionLabelKeyPrefix, groupEmbeddedListIssues, roundDerivedCellValue, sumEmbeddedListColumn, } from "./view-model/index.js";
9
+ export { buildOptionLabels, computeDerivedCellValue, computeEditViewModel, computeListViewModel, computeRelatedListSectionViewModel, embeddedCellLabelKey, embeddedCellOptionLabelKey, fieldLabelKey, fieldOptionLabelKey, fieldOptionLabelKeyPrefix, groupEmbeddedListIssues, roundDerivedCellValue, sumEmbeddedListColumn, } from "./view-model/index.js";
@@ -120,9 +120,11 @@ function deriveTextFieldHints(fieldDef) {
120
120
  const format = fieldDef.type === "text"
121
121
  ? fieldDef.format
122
122
  : undefined;
123
+ const writeOnly = fieldDef.type === "text" && fieldDef.writeOnly === true;
123
124
  return {
124
125
  ...(multiline !== undefined && { multiline }),
125
126
  ...(format !== undefined && { format }),
127
+ ...(writeOnly && { writeOnly: true }),
126
128
  };
127
129
  }
128
130
  function deriveDateFieldHints(fieldDef) {
@@ -3,5 +3,5 @@ export { computeEditViewModel, computeRelatedListSectionViewModel } from "./edit
3
3
  export type { DerivedCellRoundingTarget, EmbeddedDerivedOp, EmbeddedListIssueGroups, } from "./embedded-list.js";
4
4
  export { computeDerivedCellValue, groupEmbeddedListIssues, roundDerivedCellValue, sumEmbeddedListColumn, } from "./embedded-list.js";
5
5
  export type { ComputeListViewModelInput } from "./list.js";
6
- export { computeListViewModel, embeddedCellLabelKey, embeddedCellOptionLabelKey, fieldLabelKey, fieldOptionLabelKey, fieldOptionLabelKeyPrefix, } from "./list.js";
6
+ export { buildOptionLabels, computeListViewModel, embeddedCellLabelKey, embeddedCellOptionLabelKey, fieldLabelKey, fieldOptionLabelKey, fieldOptionLabelKeyPrefix, } from "./list.js";
7
7
  export type { EditExtensionSectionViewModel, EditFieldSpec, EditFieldsSectionViewModel, EditFieldViewModel, EditRelatedListSectionViewModel, EditSectionSpec, EditSectionViewModel, EditViewModel, EditWriteFormSectionViewModel, EmbeddedListCellViewModel, FieldConditionCtx, FieldRenderer, ListColumnSpec, ListColumnViewModel, ListRowViewModel, ListViewModel, RuntimeRenderer, ScreenSlots, Translate, } from "./types.js";
@@ -1,3 +1,3 @@
1
1
  export { computeEditViewModel, computeRelatedListSectionViewModel } from "./edit.js";
2
2
  export { computeDerivedCellValue, groupEmbeddedListIssues, roundDerivedCellValue, sumEmbeddedListColumn, } from "./embedded-list.js";
3
- export { computeListViewModel, embeddedCellLabelKey, embeddedCellOptionLabelKey, fieldLabelKey, fieldOptionLabelKey, fieldOptionLabelKeyPrefix, } from "./list.js";
3
+ export { buildOptionLabels, computeListViewModel, embeddedCellLabelKey, embeddedCellOptionLabelKey, fieldLabelKey, fieldOptionLabelKey, fieldOptionLabelKeyPrefix, } from "./list.js";
@@ -1,4 +1,5 @@
1
1
  import { LIST_ROW_META_COLUMNS, LIST_ROW_META_REFERENCES, normalizeListColumn, parseRefTarget, } from "@cosmicdrift/kumiko-framework/ui-types";
2
+ const WRITE_ONLY_SET_LABEL_KEY = "kumiko.field.writeOnly.set";
2
3
  // Pure transform: takes the declared screen + entity + incoming rows, spits
3
4
  // out the flat shape the renderer draws. No conditions, no access-checks —
4
5
  // those are list-level decisions that the caller makes BEFORE calling
@@ -136,9 +137,24 @@ export function computeListViewModel(input) {
136
137
  };
137
138
  columns.push(column);
138
139
  }
140
+ const writeOnlyFieldNames = screen.columns
141
+ .map((spec) => normalizeListColumn(spec).field)
142
+ .filter((name) => {
143
+ const fieldDef = entity.fields[name];
144
+ return fieldDef?.type === "text" && fieldDef.writeOnly === true;
145
+ });
146
+ // The wire carries `true` (set) / `null` (empty) for writeOnly fields; the cell shows a word, not "true".
147
+ const showWriteOnlyAsWord = (row) => {
148
+ const shown = { ...row };
149
+ for (const name of writeOnlyFieldNames) {
150
+ if (row[name] === true)
151
+ shown[name] = translate(WRITE_ONLY_SET_LABEL_KEY);
152
+ }
153
+ return shown;
154
+ };
139
155
  const listRows = rows.map((row) => ({
140
156
  id: String(row["id"] ?? ""),
141
- values: row,
157
+ values: showWriteOnlyAsWord(row),
142
158
  }));
143
159
  return {
144
160
  screenId: screen.id,
@@ -1,4 +1,4 @@
1
- import type { EditFieldSpec, EditSectionSpec, FieldIconKey, FieldRenderer, IconKey, ListColumnSpec, ListFacetSpec, ListSortSpec, PlatformComponent, RelatedListGroupBy, RelatedListRowTone, RelatedListToolbarAction, RowAction, RowActionMode, ScreenSlots, SelectOptionTone } from "@cosmicdrift/kumiko-framework/ui-types";
1
+ import type { EditFieldSpec, EditSectionSpec, FieldIconKey, FieldRenderer, IconKey, ListColumnSpec, ListFacetSpec, ListSortSpec, OptionsQueryPayload, PlatformComponent, RelatedListGroupBy, RelatedListRowTone, RelatedListToolbarAction, RowAction, RowActionMode, ScreenSlots, SelectOptionTone } from "@cosmicdrift/kumiko-framework/ui-types";
2
2
  export type RuntimeRenderer = (value: unknown, row?: Readonly<Record<string, unknown>>) => string;
3
3
  export type ListColumnViewModel = {
4
4
  readonly field: string;
@@ -85,12 +85,13 @@ export type EditFieldViewModel = {
85
85
  * `<feature>:entity:<entity>:field:<field>:option:<value>`. */
86
86
  readonly optionLabels?: Readonly<Record<string, string>>;
87
87
  /** Set for `type: "select"` when SelectFieldDef.optionsQuery is set: the
88
- * renderer loads the options from this query (`{ rows: { value, label }[] }`,
89
- * labels verbatim) instead of `options`. `payload` is the static
90
- * optionsQueryPayload, `{}` when absent. */
88
+ * renderer loads the options from this query (`{ rows: { value, label,
89
+ * description?, group? }[] }`, labels verbatim) instead of `options`. `payload`
90
+ * is optionsQueryPayload (`{ field }` refs are resolved by the renderer against
91
+ * the live form values), `{}` when absent. */
91
92
  readonly selectOptionsQuery?: {
92
93
  readonly query: string;
93
- readonly payload: Readonly<Record<string, string | number | boolean>>;
94
+ readonly payload: OptionsQueryPayload;
94
95
  };
95
96
  /** Set for `type: "multiSelect"` when MultiSelectFieldDef.display is
96
97
  * "checkboxes" — the renderer shows a checkbox grid with a select-all
@@ -116,6 +117,8 @@ export type EditFieldViewModel = {
116
117
  };
117
118
  /** From TextFieldDef.format — `password` makes the renderer mask the input. */
118
119
  readonly format?: "email" | "url" | "phone" | "password";
120
+ /** From TextFieldDef.writeOnly — value is `true` (set) / `null` (empty), never plaintext. */
121
+ readonly writeOnly?: true;
119
122
  /** Nur bei `type: "timestamp"` gesetzt wenn TimestampFieldDef.locatedBy
120
123
  * existiert — Wall-Clock-Zeit ohne Offset. Der Renderer emittiert
121
124
  * dann lokale Zeit ohne `Z` statt eines UTC-Instants. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-headless",
3
- "version": "0.333.0",
3
+ "version": "0.334.0",
4
4
  "description": "Headless UI logic for Kumiko — Dispatcher contract, Form-Controller, View-Model, Nav-Resolver. Plattform- und React-frei; jeder Renderer (renderer, renderer-web, renderer-native, …) komponiert darauf.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -36,7 +36,7 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@cosmicdrift/kumiko-framework": "0.333.0",
39
+ "@cosmicdrift/kumiko-framework": "0.334.0",
40
40
  "temporal-polyfill": "^0.3.2",
41
41
  "zod": "^4.4.3"
42
42
  },