@object-ui/fields 17.7.0 → 18.0.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.
@@ -14,6 +14,17 @@ export interface FileValueView {
14
14
  url?: string;
15
15
  size?: number;
16
16
  mimeType?: string;
17
+ /**
18
+ * `true` when the value is the platform's refused marker
19
+ * `{ id, metadataRefused: true }` (`FileRefusedValueSchema`): the reader may
20
+ * read the record but not this file's `sys_file` metadata, so no name, size,
21
+ * MIME type or URL was served. The view still carries `id` and the
22
+ * id-derived `url` — the download endpoint judges its own access and may
23
+ * answer `403 FILE_DOWNLOAD_DENIED` — but a renderer draws a restricted
24
+ * state rather than a generic file chip, and never attempts a thumbnail
25
+ * (objectui#12339). Absent on every other form.
26
+ */
27
+ metadataRefused?: true;
17
28
  /** The value as it arrived, so callers can pass it through untouched. */
18
29
  raw: unknown;
19
30
  }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * The key a HOST writes onto a long-text widget's `field` carrier at runtime —
10
+ * wider than the shape an author may WRITE, on purpose (objectui#12242,
11
+ * maintainer ruling A, under AGENTS.md #0.1 and the objectui#6356 pattern).
12
+ *
13
+ * `mobile_fullscreen` is a projection of the FORM-level setting
14
+ * `ObjectFormSchema.mobile.fullscreenLongText`. Its one producer is
15
+ * `ObjectForm` (`@object-ui/plugin-form`), which stamps it onto the carrier
16
+ * the form renderer hands each long-text widget (`f.field || f`) while it
17
+ * builds the form. Its consumers are `TextAreaField` and `RichTextField` here,
18
+ * which read it off `field` and nowhere else (objectui#3245), and the form
19
+ * renderer's built-in `textarea` branch in `@object-ui/components`, which
20
+ * reads it off its own props. Nobody authors it: `@objectstack/spec`'s
21
+ * `FieldSchema` refuses the key by name, so no published object can carry it,
22
+ * and `@object-ui/types`' field metadata types no longer declare it.
23
+ *
24
+ * ⛔ Deliberately NOT exported from this package's index, and ⛔ never to be
25
+ * added back to `@object-ui/types`: the authoring face refuses the key, and a
26
+ * public type naming it would invite the spelling that face refuses.
27
+ */
28
+ export interface LongTextCarrierHandoff {
29
+ /**
30
+ * Draw the fullscreen-edit affordance (an "expand" button opening a
31
+ * full-height dialog) beside the inline editor. Absent when the form did
32
+ * not opt in.
33
+ */
34
+ mobile_fullscreen?: boolean;
35
+ }
@@ -23,7 +23,7 @@ export type SchemaOption = {
23
23
  /** Translate a schema field's options through the shared i18n option path. */
24
24
  export type OptionTranslator = (objectName: string, fieldName: string, options: SchemaOption[]) => SchemaOption[];
25
25
  /**
26
- * Normalise a lookup_columns entry (string | LookupColumnDef) into a
26
+ * Normalise a lookupColumns entry (string | LookupColumnDef) into a
27
27
  * concrete LookupColumnDef object.
28
28
  */
29
29
  export declare function normalizeColumn(col: string | LookupColumnDef): LookupColumnDef;
@@ -60,7 +60,7 @@ export declare function resolveSchemaOptions(meta: {
60
60
  * an unresolved foreign-key id resolves to a name (#5492).
61
61
  *
62
62
  * Columns whose def carries no `type` inherit the schema field's type, so
63
- * string-authored `lookup_columns` format identically to object-authored ones.
63
+ * string-authored `lookupColumns` format identically to object-authored ones.
64
64
  */
65
65
  export declare function buildLookupColumnDescriptors(columns: LookupColumnDef[], fieldsMeta: Record<string, any> | undefined, objectName: string, translateOptions: OptionTranslator): Record<string, any>;
66
66
  export interface LookupColumnRenderContext {
@@ -0,0 +1,16 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * An object's name as the `object-ref` picker spells it, `Label (name)`, or the
10
+ * bare name when the object has no label (objectui#12613). `ObjectRefField`
11
+ * labels each option with it, and the console's read face for the field
12
+ * (`@object-ui/app-shell`'s widget reference cells) uses it for its tooltip, so
13
+ * the two faces spell an object one way. Published from the package barrel for
14
+ * that reader. No React here.
15
+ */
16
+ export declare function objectRefOptionLabel(name: string, label: string | undefined): string;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * The recipient kinds a `recipient-picker` field stores, and where each kind's
10
+ * candidates and labels come from (objectui#12613).
11
+ *
12
+ * ONE table, two readers: `RecipientPickerField` (the edit widget) lists a
13
+ * kind's candidates from it, and the console's read face for the field
14
+ * (`@object-ui/app-shell`'s widget reference cells) names a stored recipient
15
+ * from it. They lived inside the widget until the face needed the same answer;
16
+ * a second copy beside the face is the drift this module exists to prevent, so
17
+ * a kind added here reaches both faces at once. Published from the package
18
+ * barrel for that reader. The picker's candidate query is not shared: it stops
19
+ * at 500 rows by name, and the face reads stored ids by exact id instead.
20
+ *
21
+ * No React here.
22
+ */
23
+ export interface RecipientMapping {
24
+ object: string;
25
+ /** Which record field to persist into recipient_id. */
26
+ storeField: 'id' | 'name';
27
+ /** Candidate display-label fields, in preference order. */
28
+ labelFields: string[];
29
+ /**
30
+ * i18n key for the "choose one" placeholder. Keyed per type rather than
31
+ * interpolating the enum value into an English sentence — "Select a
32
+ * business unit" and "选择业务单元" share no structure (objectstack#3821).
33
+ */
34
+ placeholderKey: string;
35
+ }
36
+ /**
37
+ * The recipient kinds whose candidates are RECORDS of one directory object,
38
+ * stored by the record field the evaluator matches on:
39
+ *
40
+ * user → sys_user, store `id`
41
+ * team → sys_team, store `id`
42
+ * business_unit → sys_business_unit, store `id`
43
+ * unit_and_subordinates → sys_business_unit, store `id`
44
+ */
45
+ export declare const RECIPIENT_RECORD_KINDS: Readonly<Record<string, RecipientMapping>>;
46
+ /** A recipient kind whose candidates are catalog items of one metadata type. */
47
+ export interface RegistryRecipientMapping {
48
+ /** The metadata type listed — the registry's `GET /api/v1/meta/<type>`. */
49
+ type: string;
50
+ /** Catalog items are referenced by machine name (ADR-0131 D4). */
51
+ storeField: 'name';
52
+ /** Candidate display-label keys, in preference order. */
53
+ labelFields: string[];
54
+ /** i18n key for the "choose one" placeholder (see {@link RecipientMapping}). */
55
+ placeholderKey: string;
56
+ }
57
+ /**
58
+ * The recipient kinds whose candidates come from the registry (objectui#7611).
59
+ *
60
+ * ADR-0131 D3 gives positions one home, the environment registry, and D7 says
61
+ * a picker LISTS that registry: one source, with no second list of
62
+ * `sys_position` rows merged in. The read goes through the console's metadata
63
+ * store (`useMetadata().ensureType`), the same reader that serves apps and
64
+ * objects, so the list is fetched once per session and shared with every
65
+ * other registry consumer.
66
+ */
67
+ export declare const RECIPIENT_REGISTRY_KINDS: Readonly<Record<string, RegistryRecipientMapping>>;
68
+ /**
69
+ * The RECORD-RELATIVE recipient kind (maintainer ruling objectstack#14103,
70
+ * executor objectstack#15072). It is deliberately absent from
71
+ * `RECIPIENT_RECORD_KINDS`: there is no target object to query and no record id to
72
+ * store. `recipient_id` holds the NAME of a user-valued column on the SHARED
73
+ * object, and the recipients are whoever that column names on each matched
74
+ * record — so this mode reads the object chosen in the sibling `object_name`
75
+ * field (the same dependency the `filter-condition` widget already reads) and
76
+ * offers that object's user-valued fields.
77
+ */
78
+ export declare const FIELD_RECIPIENT_TYPE = "field";
79
+ /**
80
+ * The display label of one candidate: the first non-empty member of the
81
+ * kind's `labelFields`, then the record id. The picker labels its options with
82
+ * it and the read cell names a stored recipient with it, so a recipient reads
83
+ * the same in the list and in the open picker.
84
+ */
85
+ export declare function recipientCandidateLabel(labelFields: readonly string[] | undefined, row: unknown): string;
@@ -86,23 +86,6 @@ export type RichTextFieldType = keyof typeof RICH_TEXT_CELL_RENDERERS;
86
86
  * `RichTextField` serves*.
87
87
  */
88
88
  export declare const RICH_TEXT_FIELD_TYPES: readonly RichTextFieldType[];
89
- /**
90
- * The SYNTAX a rich-content type stores, derived from the renderer that type
91
- * resolves to rather than declared a second time.
92
- *
93
- * This is what `RichTextField`'s editor header names ("Format: markdown"), and
94
- * deriving it from {@link RICH_TEXT_CELL_RENDERERS} is the point: the header
95
- * used to be computed as `field.format || 'markdown'`, and since `format` is
96
- * declared on no rich-content field type (only on `date`/`datetime`/`time`/
97
- * `phone`/`auto_number`), it read `undefined` for every real field and labelled
98
- * an `html` field "Format: markdown" — a label pointing at a pipeline the value
99
- * does not go through. Derived, the label cannot disagree with the renderer.
100
- *
101
- * `undefined` for a type with no pipeline, rather than a guessed default: the
102
- * caller has to say what it does with "not a rich-content type" instead of
103
- * silently getting the markdown answer, which is the bug this replaces.
104
- */
105
- export declare function richTextSyntax(fieldType: string): 'markdown' | 'html' | undefined;
106
89
  /**
107
90
  * The display pipeline a field type reads through, or `undefined` when the
108
91
  * type is not one of the three rich-content types.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ export declare function objectResolvesSearch(objectSchema: unknown): boolean | undefined;
@@ -93,8 +93,21 @@ declare const DOM_PASS_THROUGH_KEYS: readonly ["id", "name", "autoFocus", "tabIn
93
93
  * as a compile-time fact rather than as a comment.
94
94
  */
95
95
  export type DomPassThroughKey = (typeof DOM_PASS_THROUGH_KEYS)[number];
96
- /** The subset of `P` this helper forwards, with each key's declared type. */
97
- export type DomProps<P> = CoreDomProps<P, DomPassThroughKey>;
96
+ /**
97
+ * The subset of `P` this helper forwards, with each key's declared type.
98
+ *
99
+ * Not {@link FieldWidgetDomProps}: that is the contract's DOM block, the
100
+ * non-generic set of keys a widget may receive; this is the generic RESULT
101
+ * type of {@link toDomProps}, whatever `P` it is handed narrowed to this
102
+ * helper's key set.
103
+ *
104
+ * Not `DomProps`: `@object-ui/core` publishes that name for the general
105
+ * mechanism, whose default key set forwards `role` where this one forwards
106
+ * `name` and `disabled`. One exported name stood for both key sets until this
107
+ * declaration was renamed, the way `@object-ui/components` names its own
108
+ * specialisation `FormControlDomProps` (objectui#6349, batch 11).
109
+ */
110
+ export type FieldDomProps<P> = CoreDomProps<P, DomPassThroughKey>;
98
111
  /**
99
112
  * Keep only what may legitimately become a DOM attribute, and drop everything
100
113
  * else — renderer plumbing, and any extra key an author put on the field
@@ -116,5 +129,5 @@ export type DomProps<P> = CoreDomProps<P, DomPassThroughKey>;
116
129
  * `readonly`, `error`, …) are read from `props` as before; this function only
117
130
  * governs what gets spread.
118
131
  */
119
- export declare function toDomProps<P extends object>(props: P): DomProps<P>;
132
+ export declare function toDomProps<P extends object>(props: P): FieldDomProps<P>;
120
133
  export {};
@@ -78,6 +78,19 @@ export interface UseRecordQueryResult {
78
78
  totalPages: number;
79
79
  page: number;
80
80
  search: string;
81
+ /**
82
+ * The search term `records` answer: the term of the query that committed
83
+ * them, `''` before the first answer and after a reset. It is set in the same
84
+ * commit as `records`, so the two never disagree.
85
+ *
86
+ * `search` moves on every keystroke, and the query for it runs after the
87
+ * debounce, so for that window `records` still answer an earlier term. A
88
+ * consumer that acts on "the rows for what the user typed" compares this
89
+ * with `search` (objectui#13162): equal means the rows on screen answer the
90
+ * term in the box. A late answer to a superseded query commits nothing
91
+ * (objectui#10712), so it cannot set this either.
92
+ */
93
+ answeredSearch: string;
81
94
  sort: RecordQuerySort | null;
82
95
  /** Jump to a page (1-indexed). No-op unless `paginate` is set. */
83
96
  setPage: (page: number) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/fields",
3
- "version": "17.7.0",
3
+ "version": "18.0.0",
4
4
  "description": "Field renderers and registry for Object UI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,18 +23,18 @@
23
23
  "LICENSE"
24
24
  ],
25
25
  "dependencies": {
26
- "@objectstack/spec": "^17.6.0",
26
+ "@objectstack/spec": "^18.0.0",
27
27
  "lucide-react": "^1.43.0",
28
28
  "react-markdown": "^10.1.0",
29
29
  "rehype-sanitize": "^6.0.0",
30
30
  "remark-gfm": "^4.0.1",
31
- "@object-ui/components": "17.7.0",
32
- "@object-ui/core": "17.7.0",
33
- "@object-ui/permissions": "17.7.0",
34
- "@object-ui/i18n": "17.7.0",
35
- "@object-ui/providers": "17.7.0",
36
- "@object-ui/react": "17.7.0",
37
- "@object-ui/types": "17.7.0"
31
+ "@object-ui/components": "18.0.0",
32
+ "@object-ui/core": "18.0.0",
33
+ "@object-ui/i18n": "18.0.0",
34
+ "@object-ui/permissions": "18.0.0",
35
+ "@object-ui/providers": "18.0.0",
36
+ "@object-ui/react": "18.0.0",
37
+ "@object-ui/types": "18.0.0"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "react": "^18.0.0 || ^19.0.0",