@object-ui/plugin-list 13.2.0 → 14.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,120 @@
1
1
  # @object-ui/plugin-list
2
2
 
3
+ ## 14.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - dea65f7: Unify the list-view conditional tier onto the canonical CEL engine (#1584).
8
+
9
+ Conditional formatting (list / grid / kanban) and row-action `visible` /
10
+ `disabled` predicates are now evaluated by `@objectstack/formula`'s
11
+ `ExpressionEngine` — the same engine the server uses — instead of the legacy
12
+ JS-dialect `ExpressionEvaluator`, matching how `@objectstack/spec` already types
13
+ these surfaces (`ExpressionInputSchema` / CEL). The whole platform now speaks one
14
+ expression dialect (framework ADR-0058).
15
+
16
+ - `@object-ui/core`: new `evalRowPredicate` + `resolveConditionalFormatting`
17
+ helpers (next to `evalFieldPredicate`). One implementation of all three
18
+ formatting rule shapes; dialect routing (a `{ dialect: 'cel' }` envelope is
19
+ always CEL; a bare string is CEL unless it carries legacy-only syntax
20
+ (`${…}` / `===` / `?.` / `.includes()`), which routes to the old engine with a
21
+ one-time deprecation warning); the native `{ field, operator, value }` form is
22
+ translated to CEL.
23
+ - `@object-ui/react`: new `useRowPredicate` hook (canonical CEL, ambient
24
+ predicate scope merged).
25
+ - Consumers converged: `ListView.evaluateConditionalFormatting` (thin wrapper,
26
+ export kept), `ObjectGrid` row styling (inline copy removed), kanban card
27
+ styles, and the grid / data-table row-action menus. `plugin-view`'s kanban
28
+ branch now forwards top-level `conditionalFormatting` (previously dropped).
29
+ - Row-action `visible` fails **closed** (broken predicate → hidden + warn);
30
+ `disabled` fails soft. The CEL `in` operator (and list membership) now work in
31
+ row predicates — the legacy engine could not parse them.
32
+ - The legacy `FormField.condition: { field, equals/notEquals/in }` is retired to
33
+ a CEL translation (back-compat preserved); `FieldDesigner` migrated to
34
+ `visibleWhen`.
35
+
36
+ Fully back-compat: existing conditional-formatting rules, row-action predicates,
37
+ and form `condition` metadata keep working (translated / routed as needed).
38
+
39
+ - f0f10f5: feat(kanban): default lane field honours the ADR-0085 `stageField` role
40
+
41
+ Kanban views without an explicit `groupByField`/`groupField` hard-coded their
42
+ lane field to the literal `'status'` (in both app-shell's ObjectView options
43
+ and plugin-list's ListView fallback) — ignoring the object's declared
44
+ lifecycle and even inventing a field the object doesn't have. The default now
45
+ resolves through the shared `stageField` detector:
46
+
47
+ 1. explicit view config (unchanged, always wins);
48
+ 2. the object's `stageField` semantic role;
49
+ 3. `stageField: false` → **no default lanes** (the status-shaped field is
50
+ declared non-linear; the board renders its empty state until the view
51
+ picks a lane field explicitly);
52
+ 4. else the shared name/type heuristic (status / stage / state / phase by
53
+ name, then status/stage by type) — never a nonexistent field.
54
+
55
+ `detectStatusField` moved from `@object-ui/plugin-detail` to
56
+ `@object-ui/types` (new export, with the `StatusFieldSource` input type) so
57
+ plugin-list and app-shell share the exact semantics; plugin-detail re-exports
58
+ it unchanged.
59
+
60
+ Also fixes ListView's pre-existing rules-of-hooks error while touching the
61
+ file: `useListFieldLabel` wrapped `useObjectLabel()` in try/catch (hook-order
62
+ desync risk; the hook is provider-safe) — same fix as objectui#2595's
63
+ `useFieldLabel`.
64
+
65
+ Behavior change is limited to kanban views with no explicit lane field on
66
+ objects that either declare `stageField` (now honoured), declare
67
+ `stageField: false` (now suppressed), or have no status-shaped field at all
68
+ (previously grouped by a nonexistent `status` into one "undefined" lane; now
69
+ an honest empty state). Objects with a real `status` field — the common case —
70
+ are unchanged.
71
+
72
+ ### Patch Changes
73
+
74
+ - 4b0aee6: Fix: a view declaring its `sort` in the `@objectstack/spec` bare-string
75
+ top-level form (`sort: "name desc"` — `ListViewSchema.sort` is
76
+ `string | Array<{field, order}>`) crashed ListView with
77
+ "schema.sort.map is not a function". Found by the spec/renderer
78
+ shape-mismatch audit that followed the dashboard filter-options crash.
79
+ Sort parsing is now a single normalized `parseSortConfig` (exported) that
80
+ accepts the bare string, legacy `"field desc"` array entries, and
81
+ `{ field, order }` objects, and returns `[]` for malformed entries instead
82
+ of throwing. The `@object-ui/types` declaration already carried the union —
83
+ only the implementation missed the string branch.
84
+
85
+ ## 14.0.0
86
+
87
+ ### Patch Changes
88
+
89
+ - 05e56ca: 导出/导入模板的下载文件名与内容本地化。
90
+
91
+ **导出文件名**:CSV/Excel/JSON 导出下载不再是 `<对象名>.<扩展名>`(如 `contracts.csv`),改为「对象显示名-视图名-时间戳.扩展名」(如 `任务-In Progress-20260714-153045.xlsx`);`exportOptions.fileNamePrefix` 配置仍优先(且作为完整前缀,不再追加视图名)。视图名与对象名重复时自动省略;`@object-ui/core` 新增 `buildExportFileName(ext, { prefix, label, objectName, viewLabel }, now?)` 与 `sanitizeFileNameBase(raw)`,ObjectGrid 与 ListView 的所有导出路径(服务端流式与前端兜底)统一走它。app-shell/plugin-view 的 ObjectView 现将当前视图的显示标签写进传给 ListView 的 schema(`label`),使导出文件名能区分同一对象的不同保存视图。
92
+
93
+ **导入模板**:「下载模板」修复两处英文漏出——示例行的 select/多选取值改为优先取选项**显示标签**(如 `准备中`)而非 ASCII slug(`prepare`,服务端导入两者都接受);模板文件名本地化为 `{{object}}-导入模板.csv`(新增 i18n key `grid.import.templateFileName`,英文回退 `{{object}}-import-template.csv`)。
94
+
95
+ - b66d8ee: The list toolbar search button now shows the active keyword inline (mirroring
96
+ the Sort button's count badge). Previously a search term restored from
97
+ localStorage after navigating away and back kept filtering the list while the
98
+ search popover stayed collapsed — the only cue was a slightly darker magnifier
99
+ icon, so users couldn't tell a keyword filter was still active. The keyword is
100
+ rendered (truncated at 8rem) next to the magnifier whenever a search is active,
101
+ and clicking it opens the popover pre-filled for editing or clearing.
102
+ - Updated dependencies [443360a]
103
+ - Updated dependencies [c70bca7]
104
+ - Updated dependencies [86c69c3]
105
+ - Updated dependencies [05e56ca]
106
+ - Updated dependencies [a44e7b6]
107
+ - Updated dependencies [5971cc4]
108
+ - Updated dependencies [6a74160]
109
+ - @object-ui/core@14.0.0
110
+ - @object-ui/i18n@14.0.0
111
+ - @object-ui/react@14.0.0
112
+ - @object-ui/types@14.0.0
113
+ - @object-ui/components@14.0.0
114
+ - @object-ui/fields@14.0.0
115
+ - @object-ui/mobile@14.0.0
116
+ - @object-ui/permissions@14.0.0
117
+
3
118
  ## 13.2.0
4
119
 
5
120
  ## 13.1.0
@@ -1,4 +1,4 @@
1
- import { FilterGroup } from '@object-ui/components';
1
+ import { SortItem, FilterGroup } from '@object-ui/components';
2
2
  import { ViewType } from './ViewSwitcher';
3
3
  import { ListViewSchema } from '@object-ui/types';
4
4
  /**
@@ -50,6 +50,19 @@ export interface ListViewProps {
50
50
  * E.g., ['status', 'in', ['a','b']] → ['or', ['status','=','a'], ['status','=','b']]
51
51
  */
52
52
  export declare function normalizeFilterCondition(condition: any[]): any[];
53
+ /**
54
+ * Format an action identifier string into a human-readable label.
55
+ * e.g., 'send_email' → 'Send Email'
56
+ */
57
+ /**
58
+ * Normalize a view's `sort` declaration to SortItem[]. @objectstack/spec
59
+ * ListViewSchema.sort is `string | Array<{ field, order }>` — the TOP-LEVEL
60
+ * value may be a bare string ("name desc"); array entries may be strings
61
+ * (legacy "field desc") or `{ field, order }` objects. Calling `.map` on the
62
+ * bare-string form threw "schema.sort.map is not a function" and crashed the
63
+ * list (spec/renderer shape-mismatch audit, objectui#2578 follow-up).
64
+ */
65
+ export declare function parseSortConfig(sort: unknown): SortItem[];
53
66
  /**
54
67
  * Normalize an array of filter conditions, expanding `in`/`not in` operators
55
68
  * and ensuring consistent AST structure.
@@ -59,12 +72,20 @@ export declare function convertFilterGroupToAST(group: FilterGroup): any[];
59
72
  /**
60
73
  * Evaluate conditional formatting rules against a record.
61
74
  * Returns a CSSProperties object for the first matching rule, or empty object.
62
- * Supports both field/operator/value rules and expression-based rules.
75
+ * Supports all three historical rule shapes (spec `{ condition, style }`,
76
+ * ObjectUI `{ expression, … }`, native `{ field, operator, value, … }`).
77
+ *
78
+ * Thin wrapper over `@object-ui/core`'s `resolveConditionalFormatting`, which
79
+ * evaluates every predicate on the canonical CEL engine (with a legacy-dialect
80
+ * fallback) so a list view speaks the same expression dialect the server does
81
+ * (issue #1584 / ADR-0058). Kept exported for back-compat with consumers that
82
+ * evaluate formatting outside the ListView component.
63
83
  *
64
- * Exported for use by child view renderers (e.g., ObjectGrid) and consumers
65
- * who need to evaluate formatting rules outside the ListView component.
84
+ * @param scope Extra top-level scope (the host predicate scope) bound
85
+ * alongside the row, so `features.*` / `current_user.*`
86
+ * conditions resolve as they do on grid rows / kanban cards.
66
87
  */
67
- export declare function evaluateConditionalFormatting(record: Record<string, unknown>, rules?: ListViewSchema['conditionalFormatting']): React.CSSProperties;
88
+ export declare function evaluateConditionalFormatting(record: Record<string, unknown>, rules?: ListViewSchema['conditionalFormatting'], scope?: Record<string, unknown>): React.CSSProperties;
68
89
  /**
69
90
  * Imperative handle exposed by ListView via React.forwardRef.
70
91
  * Allows parent components to trigger a data refresh programmatically.
@@ -1 +1 @@
1
- {"version":3,"file":"ListView.d.ts","sourceRoot":"","sources":["../src/ListView.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAwB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAKhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAMvD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACxC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAClD,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7F,uEAAuE;IACvE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACvD,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gGAAgG;IAChG,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IACxE,gFAAgF;IAChF,4BAA4B,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;IACtG;;;;;OAKG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,6FAA6F;IAC7F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAuBD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAyBhE;AAUD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAKtD;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,CA0BjE;AAED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,CAAC,EAAE,cAAc,CAAC,uBAAuB,CAAC,GAC9C,KAAK,CAAC,aAAa,CAoDrB;AAqGD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,eAAO,MAAM,QAAQ,mGAqpEnB,CAAC"}
1
+ {"version":3,"file":"ListView.d.ts","sourceRoot":"","sources":["../src/ListView.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAwB,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAKhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAOvD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACxC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAClD,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7F,uEAAuE;IACvE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACvD,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gGAAgG;IAChG,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IACxE,gFAAgF;IAChF,4BAA4B,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;IACtG;;;;;OAKG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,6FAA6F;IAC7F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAuBD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAyBhE;AAED;;;GAGG;AACH;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAE,CAqBzD;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,CAKtD;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,CA0BjE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,KAAK,CAAC,EAAE,cAAc,CAAC,uBAAuB,CAAC,EAC/C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,KAAK,CAAC,aAAa,CAErB;AA+FD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,eAAO,MAAM,QAAQ,mGAsrEnB,CAAC"}