@mulmoclaude/collection-plugin 0.7.5 → 0.7.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"CollectionKanbanView.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/CollectionKanbanView.vue"],"names":[],"mappings":"AA2NA,OAAO,KAAK,EAAE,wBAAwB,IAAI,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAYnI,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,gBAAgB,CAAC;IACzB,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;gFAC4E;IAC5E,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC1C,CAAC;AA+UF,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"CollectionKanbanView.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/CollectionKanbanView.vue"],"names":[],"mappings":"AAoOA,OAAO,KAAK,EAAE,wBAAwB,IAAI,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAYnI,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,gBAAgB,CAAC;IACzB,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;gFAC4E;IAC5E,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC1C,CAAC;AAwVF,QAAA,MAAM,YAAY;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -29,7 +29,18 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
29
29
  submit: () => any;
30
30
  cancel: () => any;
31
31
  edit: () => any;
32
- runAction: (action: CollectionAction) => any;
32
+ runAction: (action: {
33
+ id: string;
34
+ label: string;
35
+ kind: "chat";
36
+ role: string;
37
+ template: string;
38
+ icon?: string | undefined;
39
+ when?: {
40
+ field: string;
41
+ in: string[];
42
+ } | undefined;
43
+ }) => any;
33
44
  itemChat: (message: string) => any;
34
45
  "update:editing": (value: EditState | null) => any;
35
46
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
@@ -38,7 +49,18 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
38
49
  onSubmit?: (() => any) | undefined;
39
50
  onCancel?: (() => any) | undefined;
40
51
  onEdit?: (() => any) | undefined;
41
- onRunAction?: ((action: CollectionAction) => any) | undefined;
52
+ onRunAction?: ((action: {
53
+ id: string;
54
+ label: string;
55
+ kind: "chat";
56
+ role: string;
57
+ template: string;
58
+ icon?: string | undefined;
59
+ when?: {
60
+ field: string;
61
+ in: string[];
62
+ } | undefined;
63
+ }) => any) | undefined;
42
64
  onItemChat?: ((message: string) => any) | undefined;
43
65
  "onUpdate:editing"?: ((value: EditState | null) => any) | undefined;
44
66
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -1 +1 @@
1
- {"version":3,"file":"CollectionRecordPanel.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/CollectionRecordPanel.vue"],"names":[],"mappings":"AAmsBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EAEd,SAAS,EAEV,MAAM,8BAA8B,CAAC;AAQtC,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,8CAA8C;IAC9C,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,gBAAgB,EAAE,CAAC;IACnC,qEAAqE;IACrE,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC;IAClC,gDAAgD;IAChD,WAAW,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,8DAA8D;IAC9D,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA8JF,KAAK,gBAAgB,GAAG;IACxB,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;CAC3B,CAAC;AAKF,KAAK,iBAAiB,GAAG,WAAW,GAAG,gBAAgB,CAAC;AA27CxD,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"CollectionRecordPanel.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/CollectionRecordPanel.vue"],"names":[],"mappings":"AAosBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EAEd,SAAS,EAEV,MAAM,8BAA8B,CAAC;AAQtC,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,8CAA8C;IAC9C,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,gBAAgB,EAAE,CAAC;IACnC,qEAAqE;IACrE,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC;IAClC,gDAAgD;IAChD,WAAW,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,8DAA8D;IAC9D,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA+JF,KAAK,gBAAgB,GAAG;IACxB,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;CAC3B,CAAC;AAKF,KAAK,iBAAiB,GAAG,WAAW,GAAG,gBAAgB,CAAC;AA27CxD,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1 +1 @@
1
- {"version":3,"file":"CollectionView.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/CollectionView.vue"],"names":[],"mappings":"AA20EA,OAAO,EAML,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAqC/B;;;;;;;;;6CAS6C;AAC7C,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C;;;;;uBAKmB;IACnB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;4EAGwE;IACxE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;wDAGoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;4EACwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAqzHF,QAAA,MAAM,YAAY;;;cA1yHiB,eAAe;qBAAe,MAAM;oBAAc,MAAM;;;;;cAAxD,eAAe;qBAAe,MAAM;oBAAc,MAAM;;kFA6yHzF,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"CollectionView.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/CollectionView.vue"],"names":[],"mappings":"AA00EA,OAAO,EAML,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAqC/B;;;;;;;;;6CAS6C;AAC7C,KAAK,WAAW,GAAG;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C;;;;;uBAKmB;IACnB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;4EAGwE;IACxE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;wDAGoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;4EACwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAozHF,QAAA,MAAM,YAAY;;;cAzyHiB,eAAe;qBAAe,MAAM;oBAAc,MAAM;;;;;cAAxD,eAAe;qBAAe,MAAM;oBAAc,MAAM;;kFA4yHzF,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -1,4 +1,4 @@
1
- import { type Ref } from "vue";
1
+ import type { Ref } from "vue";
2
2
  import type { CollectionDetail, CollectionItem, CollectionSchema, CollectionFieldSpec as FieldSpec, CollectionFieldType as FieldType, EmbedCache, EmbedView, RefCache, RefOption, RefRecordCache } from "@mulmoclaude/core/collection";
3
3
  export interface CollectionRendering {
4
4
  refCache: Ref<RefCache>;
@@ -1 +1 @@
1
- {"version":3,"file":"useCollectionRendering.d.ts","sourceRoot":"","sources":["../../src/vue/useCollectionRendering.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useCollectionRendering.d.ts","sourceRoot":"","sources":["../../src/vue/useCollectionRendering.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,9 @@ export declare function detailText(value: unknown): string;
6
6
  export declare function formatCell(value: unknown, type: FieldType): string;
7
7
  /** Resolve the ISO 4217 code for a money field: a per-record
8
8
  * `currencyField` (when present and non-blank) wins over the field's
9
- * literal `currency`. */
9
+ * literal `currency`. Only `money` / `derived` variants carry currency
10
+ * keys; any other field resolves to undefined (the formatter's USD
11
+ * fallback), as before. */
10
12
  export declare function resolveCurrency(field: FieldSpec, record: CollectionItem | null | undefined): string | undefined;
11
13
  export declare function formatMoney(value: unknown, currency: string | undefined, displayLocale: string): string;
12
14
  export declare function currencySymbolForLocale(currency: string | undefined, locale: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"useCollectionRendering.helpers.d.ts","sourceRoot":"","sources":["../../src/vue/useCollectionRendering.helpers.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,wBAAwB,EACxB,cAAc,EACd,gBAAgB,EAChB,mBAAmB,IAAI,SAAS,EAChC,mBAAmB,IAAI,SAAS,EAChC,aAAa,EACb,SAAS,EACT,YAAY,EACb,MAAM,8BAA8B,CAAC;AAWtC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAIpE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAOpD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAErD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGjD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAOlE;AAED;;0BAE0B;AAC1B,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAM/G;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAUvG;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQ5F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAGnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpD;AAED;qEACqE;AACrE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAI7F;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAYnE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAQrE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,aAAa,CAWlF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,wBAAwB,GAAG,YAAY,CAQhF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,EAAE,CAIhE;AAED;;yEAEyE;AACzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,SAAS,EAAE,CAYhG"}
1
+ {"version":3,"file":"useCollectionRendering.helpers.d.ts","sourceRoot":"","sources":["../../src/vue/useCollectionRendering.helpers.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,wBAAwB,EACxB,cAAc,EACd,gBAAgB,EAChB,mBAAmB,IAAI,SAAS,EAChC,mBAAmB,IAAI,SAAS,EAChC,aAAa,EACb,SAAS,EACT,YAAY,EACb,MAAM,8BAA8B,CAAC;AAWtC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,CAIpE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAOpD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAErD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGjD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAOlE;AAED;;;;4BAI4B;AAC5B,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAO/G;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAUvG;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQ5F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAGnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpD;AAED;qEACqE;AACrE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAI7F;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAYnE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAQrE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,aAAa,CAWlF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,wBAAwB,GAAG,YAAY,CAQhF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,EAAE,CAIhE;AAED;;yEAEyE;AACzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,SAAS,EAAE,CAYhG"}
@@ -0,0 +1,22 @@
1
+ import type { CollectionItem, CollectionSchema, CollectionFieldSpec as FieldSpec, EmbedCache, EmbedView, RefCache, RefOption, RefRecordCache } from "@mulmoclaude/core/collection";
2
+ export declare function lookupRefDisplay(refCache: RefCache, targetSlug: string, itemSlug: string): string;
3
+ export declare function refOptionsFor(refCache: RefCache, targetSlug: string): RefOption[];
4
+ /** Dropdown options for an `embed` field's per-record picker (`idField`):
5
+ * every record in the target collection, labelled by its name/title (or
6
+ * primary key). Built from `embedCache` so it works for embed targets
7
+ * that aren't also `ref` targets (the profile collection, say). */
8
+ export declare function embedOptionsFor(embedCache: EmbedCache, targetSlug: string): RefOption[];
9
+ export declare function resolveEmbed(field: FieldSpec, record: CollectionItem | null, embedCache: EmbedCache): {
10
+ schema: CollectionSchema | null;
11
+ item: CollectionItem | null;
12
+ };
13
+ export declare function formatEmbedValue(field: FieldSpec, value: unknown, record: CollectionItem | null, locale: string): string;
14
+ /** Build the read-only embed view-models for one record. A function of the
15
+ * open record (not a bare computed) because a per-record `idField` embed
16
+ * resolves a different target per row. `schema` is the OPEN collection's
17
+ * schema (null when no collection is loaded → no views). */
18
+ export declare function buildEmbedViews(schema: CollectionSchema | null, embedCache: EmbedCache, record: CollectionItem | null, locale: string): Record<string, EmbedView>;
19
+ export declare function renderSubCell(subField: FieldSpec, value: unknown, record: CollectionItem | null, refCache: RefCache, locale: string): string;
20
+ export declare function evaluateDerived(field: FieldSpec, fieldKey: string, item: CollectionItem, schema: CollectionSchema | null, refRecords: RefRecordCache): number | null;
21
+ export declare function renderDerived(field: FieldSpec, computedValue: unknown, record: CollectionItem | null, locale: string): string;
22
+ //# sourceMappingURL=useCollectionRendering.renderers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCollectionRendering.renderers.d.ts","sourceRoot":"","sources":["../../src/vue/useCollectionRendering.renderers.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,mBAAmB,IAAI,SAAS,EAChC,UAAU,EAEV,SAAS,EACT,QAAQ,EACR,SAAS,EACT,cAAc,EACf,MAAM,8BAA8B,CAAC;AAGtC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGjG;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,CAGjF;AAED;;;oEAGoE;AACpE,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,CAGvF;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,EAChB,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,UAAU,EAAE,UAAU,GACrB;IAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAA;CAAE,CAOlE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGxH;AAED;;;6DAG6D;AAC7D,wBAAgB,eAAe,CAC7B,MAAM,EAAE,gBAAgB,GAAG,IAAI,EAC/B,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAmB3B;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAI5I;AAOD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,gBAAgB,GAAG,IAAI,EAC/B,UAAU,EAAE,cAAc,GACzB,MAAM,GAAG,IAAI,CAKf;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK7H"}
@@ -0,0 +1,33 @@
1
+ import { type Ref } from "vue";
2
+ import { type CollectionApiResult } from "./uiContext";
3
+ import type { CollectionDetail, CollectionDetailResponse, CollectionSchema, EmbedCache, RefCache, RefRecordCache } from "@mulmoclaude/core/collection";
4
+ export interface LinkedCollectionCaches {
5
+ refCache: Ref<RefCache>;
6
+ refRecordCache: Ref<RefRecordCache>;
7
+ embedCache: Ref<EmbedCache>;
8
+ resetLinkedCaches: () => void;
9
+ loadLinkedCollections: (schema: CollectionSchema, expectedSlug: string) => Promise<void>;
10
+ }
11
+ export interface LinkedTargets {
12
+ refTargets: Set<string>;
13
+ embedTargets: Set<string>;
14
+ allTargets: string[];
15
+ }
16
+ export interface LinkedCachesSnapshot {
17
+ refCache: RefCache;
18
+ refRecordCache: RefRecordCache;
19
+ embedCache: EmbedCache;
20
+ }
21
+ type FetchCollectionDetail = (slug: string) => Promise<CollectionApiResult<CollectionDetailResponse>>;
22
+ /** The de-duplicated ref + embed target slugs a schema links to. `allTargets`
23
+ * is the union (each target fetched once even when both ref'd and embedded). */
24
+ export declare function linkedTargets(schema: CollectionSchema): LinkedTargets;
25
+ /** Fan-out fetch that hydrates the linked-collection caches. Best-effort: a
26
+ * target whose fetch *rejects* (vs. resolving `{ ok: false }`) is coerced to a
27
+ * skip and must not abort the others. Returns null when a quicker subsequent
28
+ * load has already moved on (stale-write guard) so the caller drops the write.
29
+ * Pure + injectable (`fetchDetail`, `currentSlug`) so both paths are testable. */
30
+ export declare function fetchLinkedCaches(targets: LinkedTargets, fetchDetail: FetchCollectionDetail, currentSlug: () => string | undefined, expectedSlug: string): Promise<LinkedCachesSnapshot | null>;
31
+ export declare function useLinkedCollectionCaches(collection: Ref<CollectionDetail | null>): LinkedCollectionCaches;
32
+ export {};
33
+ //# sourceMappingURL=useLinkedCollectionCaches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLinkedCollectionCaches.d.ts","sourceRoot":"","sources":["../../src/vue/useLinkedCollectionCaches.ts"],"names":[],"mappings":"AAOA,OAAO,EAAO,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEvJ,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,cAAc,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IACpC,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IAC5B,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,qBAAqB,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1F;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,KAAK,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,wBAAwB,CAAC,CAAC,CAAC;AAEtG;iFACiF;AACjF,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAKrE;AAED;;;;mFAImF;AACnF,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,qBAAqB,EAClC,WAAW,EAAE,MAAM,MAAM,GAAG,SAAS,EACrC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CA2BtC;AAED,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,GAAG,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,sBAAsB,CA4B1G"}
package/dist/vue.cjs CHANGED
@@ -1741,7 +1741,10 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
1741
1741
  const emit = __emit;
1742
1742
  const { t } = useCollectionI18n();
1743
1743
  /** The Uncategorized column uses the empty string as its sentinel value. */
1744
- const groupSpec = (0, vue.computed)(() => props.schema.fields[props.groupField]);
1744
+ const groupSpec = (0, vue.computed)(() => {
1745
+ const spec = props.schema.fields[props.groupField];
1746
+ return spec?.type === "enum" ? spec : void 0;
1747
+ });
1745
1748
  /** Declared enum values become columns in order, with a trailing
1746
1749
  * Uncategorized column for empty/unknown values (also a drop target that
1747
1750
  * clears the field). The Uncategorized column is omitted when the group
@@ -1788,7 +1791,10 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
1788
1791
  const value = String(raw);
1789
1792
  return (groupSpec.value?.values ?? []).includes(value) ? value : UNCATEGORIZED;
1790
1793
  }
1791
- const visibleItems = (0, vue.computed)(() => groupSpec.value ? props.items.filter((item) => (0, _mulmoclaude_core_collection.fieldVisible)(groupSpec.value, item)) : []);
1794
+ const visibleItems = (0, vue.computed)(() => {
1795
+ const spec = groupSpec.value;
1796
+ return spec ? props.items.filter((item) => (0, _mulmoclaude_core_collection.fieldVisible)(spec, item)) : [];
1797
+ });
1792
1798
  const itemsByColumnMap = (0, vue.computed)(() => {
1793
1799
  const map = /* @__PURE__ */ new Map();
1794
1800
  for (const column of columns.value) map.set(column.value, []);
@@ -2315,7 +2321,8 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
2315
2321
  /** Required flag for an embed's per-record picker — read off the storage
2316
2322
  * field it writes (`idField`), since the embed itself stores nothing. */
2317
2323
  function embedPickerRequired(field) {
2318
- const target = field.idField ? props.collection.schema.fields[field.idField] : void 0;
2324
+ const idField = field.type === "embed" ? field.idField : void 0;
2325
+ const target = idField ? props.collection.schema.fields[idField] : void 0;
2319
2326
  return target ? isFieldRequiredInUi(target) : false;
2320
2327
  }
2321
2328
  /** Tailwind fill/text/border classes tinting an enum `<select>` by its current
@@ -3067,8 +3074,11 @@ function formatCell(value, type) {
3067
3074
  }
3068
3075
  /** Resolve the ISO 4217 code for a money field: a per-record
3069
3076
  * `currencyField` (when present and non-blank) wins over the field's
3070
- * literal `currency`. */
3077
+ * literal `currency`. Only `money` / `derived` variants carry currency
3078
+ * keys; any other field resolves to undefined (the formatter's USD
3079
+ * fallback), as before. */
3071
3080
  function resolveCurrency(field, record) {
3081
+ if (field.type !== "money" && field.type !== "derived") return void 0;
3072
3082
  if (field.currencyField && record) {
3073
3083
  const code = record[field.currencyField];
3074
3084
  if (typeof code === "string" && code.trim().length > 0) return code;
@@ -3173,8 +3183,60 @@ function buildEmbedOptions(schema, items) {
3173
3183
  }).filter((opt) => opt.slug.length > 0).sort((left, right) => left.display.localeCompare(right.display));
3174
3184
  }
3175
3185
  //#endregion
3176
- //#region src/vue/useCollectionRendering.ts
3177
- function useCollectionRendering(collection, locale) {
3186
+ //#region src/vue/useLinkedCollectionCaches.ts
3187
+ /** The de-duplicated ref + embed target slugs a schema links to. `allTargets`
3188
+ * is the union (each target fetched once even when both ref'd and embedded). */
3189
+ function linkedTargets(schema) {
3190
+ const refTargets = new Set(uniqueRefTargets(schema));
3191
+ const embedTargets = new Set(uniqueEmbedTargets(schema));
3192
+ return {
3193
+ refTargets,
3194
+ embedTargets,
3195
+ allTargets: [.../* @__PURE__ */ new Set([...refTargets, ...embedTargets])]
3196
+ };
3197
+ }
3198
+ /** Fan-out fetch that hydrates the linked-collection caches. Best-effort: a
3199
+ * target whose fetch *rejects* (vs. resolving `{ ok: false }`) is coerced to a
3200
+ * skip and must not abort the others. Returns null when a quicker subsequent
3201
+ * load has already moved on (stale-write guard) so the caller drops the write.
3202
+ * Pure + injectable (`fetchDetail`, `currentSlug`) so both paths are testable. */
3203
+ async function fetchLinkedCaches(targets, fetchDetail, currentSlug, expectedSlug) {
3204
+ const { refTargets, embedTargets, allTargets } = targets;
3205
+ const results = await Promise.all(allTargets.map(async (target) => {
3206
+ try {
3207
+ return {
3208
+ target,
3209
+ result: await fetchDetail(target)
3210
+ };
3211
+ } catch {
3212
+ return {
3213
+ target,
3214
+ result: { ok: false }
3215
+ };
3216
+ }
3217
+ }));
3218
+ if (currentSlug() !== expectedSlug) return null;
3219
+ const refCache = {};
3220
+ const refRecordCache = {};
3221
+ const embedCache = {};
3222
+ for (const { target, result } of results) {
3223
+ if (!result.ok) continue;
3224
+ if (refTargets.has(target)) {
3225
+ refCache[target] = buildRefDisplayMap(result.data);
3226
+ refRecordCache[target] = buildRefRecordMap(result.data);
3227
+ }
3228
+ if (embedTargets.has(target)) embedCache[target] = {
3229
+ schema: result.data.collection.schema,
3230
+ items: result.data.items
3231
+ };
3232
+ }
3233
+ return {
3234
+ refCache,
3235
+ refRecordCache,
3236
+ embedCache
3237
+ };
3238
+ }
3239
+ function useLinkedCollectionCaches(collection) {
3178
3240
  const refCache = (0, vue.ref)({});
3179
3241
  const refRecordCache = (0, vue.ref)({});
3180
3242
  const embedCache = (0, vue.ref)({});
@@ -3184,161 +3246,139 @@ function useCollectionRendering(collection, locale) {
3184
3246
  embedCache.value = {};
3185
3247
  }
3186
3248
  async function loadLinkedCollections(schema, expectedSlug) {
3187
- const refTargets = new Set(uniqueRefTargets(schema));
3188
- const embedTargets = new Set(uniqueEmbedTargets(schema));
3189
- const allTargets = [.../* @__PURE__ */ new Set([...refTargets, ...embedTargets])];
3190
- if (allTargets.length === 0) return;
3249
+ const targets = linkedTargets(schema);
3250
+ if (targets.allTargets.length === 0) return;
3191
3251
  const binding = collectionUi();
3192
- const results = await Promise.all(allTargets.map(async (target) => {
3193
- try {
3194
- return {
3195
- target,
3196
- result: await binding.fetchCollectionDetail(target)
3197
- };
3198
- } catch {
3199
- return {
3200
- target,
3201
- result: { ok: false }
3202
- };
3203
- }
3204
- }));
3205
- if (collection.value?.slug !== expectedSlug) return;
3206
- const nextRef = {};
3207
- const nextRefRecords = {};
3208
- const nextEmbed = {};
3209
- for (const { target, result } of results) {
3210
- if (!result.ok) continue;
3211
- if (refTargets.has(target)) {
3212
- nextRef[target] = buildRefDisplayMap(result.data);
3213
- nextRefRecords[target] = buildRefRecordMap(result.data);
3214
- }
3215
- if (embedTargets.has(target)) nextEmbed[target] = {
3216
- schema: result.data.collection.schema,
3217
- items: result.data.items
3218
- };
3219
- }
3220
- refCache.value = nextRef;
3221
- refRecordCache.value = nextRefRecords;
3222
- embedCache.value = nextEmbed;
3223
- }
3224
- function refDisplay(targetSlug, itemSlug) {
3225
- const map = refCache.value[targetSlug];
3226
- return map && map[itemSlug] || itemSlug;
3227
- }
3228
- function refOptions(targetSlug) {
3229
- const map = refCache.value[targetSlug];
3230
- return map ? sortedRefOptions(map) : [];
3231
- }
3232
- /** Dropdown options for an `embed` field's per-record picker (`idField`):
3233
- * every record in the target collection, labelled by its name/title (or
3234
- * primary key). Built from `embedCache` so it works for embed targets
3235
- * that aren't also `ref` targets (the profile collection, say). */
3236
- function embedOptions(targetSlug) {
3237
- const data = embedCache.value[targetSlug];
3238
- return data ? buildEmbedOptions(data.schema, data.items) : [];
3239
- }
3240
- function resolveEmbed(field, record) {
3241
- if (field.type !== "embed" || !field.to) return {
3242
- schema: null,
3243
- item: null
3244
- };
3245
- const targetId = (0, _mulmoclaude_core_collection.embedTargetId)(field, record);
3246
- const data = targetId ? embedCache.value[field.to] : void 0;
3247
- if (!data) return {
3248
- schema: null,
3249
- item: null
3250
- };
3251
- const item = data.items.find((entry) => String(entry[data.schema.primaryKey] ?? "") === targetId) ?? null;
3252
- return {
3253
- schema: data.schema,
3254
- item
3255
- };
3256
- }
3257
- function embedValue(field, value, record) {
3258
- if (field.type === "money") return formatMoney(value, resolveCurrency(field, record), locale.value);
3259
- return detailText(value);
3260
- }
3261
- /** Build the read-only embed view-models for one record. A function of
3262
- * the open record (not a bare computed) because a per-record `idField`
3263
- * embed resolves a different target per row. */
3264
- function embedViewsFor(record) {
3265
- const out = {};
3266
- if (!collection.value) return out;
3267
- for (const [key, field] of Object.entries(collection.value.schema.fields)) {
3268
- if (field.type !== "embed") continue;
3269
- const { schema, item } = resolveEmbed(field, record);
3270
- const rows = [];
3271
- if (schema && item) for (const [subKey, subField] of Object.entries(schema.fields)) {
3272
- const value = item[subKey];
3273
- if (value === void 0 || value === null || value === "") continue;
3274
- rows.push({
3275
- key: subKey,
3276
- label: subField.label,
3277
- type: subField.type,
3278
- value,
3279
- display: embedValue(subField, value, item)
3280
- });
3281
- }
3282
- out[key] = {
3283
- found: Boolean(item),
3284
- rows,
3285
- targetSlug: field.to ?? "",
3286
- recordId: (0, _mulmoclaude_core_collection.embedTargetId)(field, record)
3287
- };
3288
- }
3289
- return out;
3290
- }
3291
- function currencySymbol(currency) {
3292
- return currencySymbolForLocale(currency, locale.value);
3293
- }
3294
- function artifactUrl(value) {
3295
- return collectionUi().fileAssetUrl(value);
3296
- }
3297
- function fileRoutePath(value) {
3298
- return collectionUi().fileRoutePath(value);
3299
- }
3300
- function formatSubCell(subField, value, record) {
3301
- if (subField.type === "money") return formatMoney(value, resolveCurrency(subField, record), locale.value);
3302
- if (subField.type === "ref" && subField.to && typeof value === "string" && value.length > 0) return refDisplay(subField.to, value);
3303
- return formatCell(value, subField.type);
3304
- }
3305
- const stepFor = stepForFieldType;
3306
- function evaluateDerivedAgainstItem(field, fieldKey, item) {
3307
- if (!field.formula || !collection.value) return null;
3308
- const result = (0, _mulmoclaude_core_collection.deriveAll)(collection.value.schema, item, refRecordCache.value)[fieldKey];
3309
- return typeof result === "number" && Number.isFinite(result) ? result : null;
3310
- }
3311
- function derivedDisplay(field, computedValue, record) {
3312
- if (computedValue === null || computedValue === void 0) return "—";
3313
- if (field.display === "money") return formatMoney(computedValue, resolveCurrency(field, record), locale.value);
3314
- return formatCell(computedValue, field.display ?? "number");
3252
+ const snapshot = await fetchLinkedCaches(targets, (slug) => binding.fetchCollectionDetail(slug), () => collection.value?.slug, expectedSlug);
3253
+ if (!snapshot) return;
3254
+ refCache.value = snapshot.refCache;
3255
+ refRecordCache.value = snapshot.refRecordCache;
3256
+ embedCache.value = snapshot.embedCache;
3315
3257
  }
3316
3258
  return {
3317
3259
  refCache,
3318
3260
  refRecordCache,
3319
3261
  embedCache,
3320
3262
  resetLinkedCaches,
3321
- loadLinkedCollections,
3322
- refDisplay,
3323
- refOptions,
3324
- embedOptions,
3325
- embedViewsFor,
3326
- resolveCurrency,
3327
- currencySymbol,
3328
- formatMoney,
3329
- formatCell,
3330
- detailText,
3331
- isExternalUrl,
3332
- artifactUrl,
3333
- fileRoutePath,
3334
- tableRows,
3335
- hasTableRows,
3336
- formatSubCell,
3337
- inputTypeFor,
3338
- stepFor,
3339
- deriveAll: _mulmoclaude_core_collection.deriveAll,
3340
- evaluateDerivedAgainstItem,
3341
- derivedDisplay
3263
+ loadLinkedCollections
3264
+ };
3265
+ }
3266
+ //#endregion
3267
+ //#region src/vue/useCollectionRendering.renderers.ts
3268
+ function lookupRefDisplay(refCache, targetSlug, itemSlug) {
3269
+ const map = refCache[targetSlug];
3270
+ return map && map[itemSlug] || itemSlug;
3271
+ }
3272
+ function refOptionsFor(refCache, targetSlug) {
3273
+ const map = refCache[targetSlug];
3274
+ return map ? sortedRefOptions(map) : [];
3275
+ }
3276
+ /** Dropdown options for an `embed` field's per-record picker (`idField`):
3277
+ * every record in the target collection, labelled by its name/title (or
3278
+ * primary key). Built from `embedCache` so it works for embed targets
3279
+ * that aren't also `ref` targets (the profile collection, say). */
3280
+ function embedOptionsFor(embedCache, targetSlug) {
3281
+ const data = embedCache[targetSlug];
3282
+ return data ? buildEmbedOptions(data.schema, data.items) : [];
3283
+ }
3284
+ function resolveEmbed(field, record, embedCache) {
3285
+ if (field.type !== "embed" || !field.to) return {
3286
+ schema: null,
3287
+ item: null
3288
+ };
3289
+ const targetId = (0, _mulmoclaude_core_collection.embedTargetId)(field, record);
3290
+ const data = targetId ? embedCache[field.to] : void 0;
3291
+ if (!data) return {
3292
+ schema: null,
3293
+ item: null
3294
+ };
3295
+ const item = data.items.find((entry) => String(entry[data.schema.primaryKey] ?? "") === targetId) ?? null;
3296
+ return {
3297
+ schema: data.schema,
3298
+ item
3299
+ };
3300
+ }
3301
+ function formatEmbedValue(field, value, record, locale) {
3302
+ if (field.type === "money") return formatMoney(value, resolveCurrency(field, record), locale);
3303
+ return detailText(value);
3304
+ }
3305
+ /** Build the read-only embed view-models for one record. A function of the
3306
+ * open record (not a bare computed) because a per-record `idField` embed
3307
+ * resolves a different target per row. `schema` is the OPEN collection's
3308
+ * schema (null when no collection is loaded → no views). */
3309
+ function buildEmbedViews(schema, embedCache, record, locale) {
3310
+ const out = {};
3311
+ if (!schema) return out;
3312
+ for (const [key, field] of Object.entries(schema.fields)) {
3313
+ if (field.type !== "embed") continue;
3314
+ const { schema: targetSchema, item } = resolveEmbed(field, record, embedCache);
3315
+ const rows = [];
3316
+ if (targetSchema && item) for (const [subKey, subField] of Object.entries(targetSchema.fields)) {
3317
+ const value = item[subKey];
3318
+ if (value === void 0 || value === null || value === "") continue;
3319
+ rows.push({
3320
+ key: subKey,
3321
+ label: subField.label,
3322
+ type: subField.type,
3323
+ value,
3324
+ display: formatEmbedValue(subField, value, item, locale)
3325
+ });
3326
+ }
3327
+ out[key] = {
3328
+ found: Boolean(item),
3329
+ rows,
3330
+ targetSlug: field.to ?? "",
3331
+ recordId: (0, _mulmoclaude_core_collection.embedTargetId)(field, record)
3332
+ };
3333
+ }
3334
+ return out;
3335
+ }
3336
+ function renderSubCell(subField, value, record, refCache, locale) {
3337
+ if (subField.type === "money") return formatMoney(value, resolveCurrency(subField, record), locale);
3338
+ if (subField.type === "ref" && subField.to && typeof value === "string" && value.length > 0) return lookupRefDisplay(refCache, subField.to, value);
3339
+ return formatCell(value, subField.type);
3340
+ }
3341
+ function evaluateDerived(field, fieldKey, item, schema, refRecords) {
3342
+ if (field.type !== "derived" || !schema) return null;
3343
+ const result = (0, _mulmoclaude_core_collection.deriveAll)(schema, item, refRecords)[fieldKey];
3344
+ return typeof result === "number" && Number.isFinite(result) ? result : null;
3345
+ }
3346
+ function renderDerived(field, computedValue, record, locale) {
3347
+ if (computedValue === null || computedValue === void 0) return "—";
3348
+ const display = field.type === "derived" ? field.display : void 0;
3349
+ if (display === "money") return formatMoney(computedValue, resolveCurrency(field, record), locale);
3350
+ return formatCell(computedValue, display ?? "number");
3351
+ }
3352
+ //#endregion
3353
+ //#region src/vue/useCollectionRendering.ts
3354
+ var STATELESS_RENDERERS = {
3355
+ resolveCurrency,
3356
+ formatMoney,
3357
+ formatCell,
3358
+ detailText,
3359
+ isExternalUrl,
3360
+ tableRows,
3361
+ hasTableRows,
3362
+ inputTypeFor,
3363
+ stepFor: stepForFieldType,
3364
+ deriveAll: _mulmoclaude_core_collection.deriveAll
3365
+ };
3366
+ function useCollectionRendering(collection, locale) {
3367
+ const caches = useLinkedCollectionCaches(collection);
3368
+ const { refCache, refRecordCache, embedCache } = caches;
3369
+ return {
3370
+ ...caches,
3371
+ ...STATELESS_RENDERERS,
3372
+ refDisplay: (targetSlug, itemSlug) => lookupRefDisplay(refCache.value, targetSlug, itemSlug),
3373
+ refOptions: (targetSlug) => refOptionsFor(refCache.value, targetSlug),
3374
+ embedOptions: (targetSlug) => embedOptionsFor(embedCache.value, targetSlug),
3375
+ embedViewsFor: (record) => buildEmbedViews(collection.value?.schema ?? null, embedCache.value, record, locale.value),
3376
+ currencySymbol: (currency) => currencySymbolForLocale(currency, locale.value),
3377
+ artifactUrl: (value) => collectionUi().fileAssetUrl(value),
3378
+ fileRoutePath: (value) => collectionUi().fileRoutePath(value),
3379
+ formatSubCell: (subField, value, record) => renderSubCell(subField, value, record, refCache.value, locale.value),
3380
+ evaluateDerivedAgainstItem: (field, fieldKey, item) => evaluateDerived(field, fieldKey, item, collection.value?.schema ?? null, refRecordCache.value),
3381
+ derivedDisplay: (field, computedValue, record) => renderDerived(field, computedValue, record, locale.value)
3342
3382
  };
3343
3383
  }
3344
3384
  //#endregion
@@ -3829,12 +3869,12 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
3829
3869
  return scalarSortValue(field, item[key]);
3830
3870
  }
3831
3871
  /** Derived rows sort by their display type: money/number → numeric,
3832
- * date/datetime → epoch, anything else → the enriched value as a string. */
3872
+ * date → epoch, anything else → the enriched value as a string. */
3833
3873
  function derivedSortValue(field, key, item) {
3834
- const { display } = field;
3874
+ const display = field.type === "derived" ? field.display : void 0;
3835
3875
  if (display === void 0 || display === "number" || display === "money") return (0, _mulmoclaude_core_collection.numericSortValue)(evaluateDerivedAgainstItem(field, key, item));
3836
3876
  const enriched = collection.value ? render.deriveAll(collection.value.schema, item, render.refRecordCache.value) : item;
3837
- if (display === "date" || display === "datetime") return (0, _mulmoclaude_core_collection.dateSortValue)(enriched[key]);
3877
+ if (display === "date") return (0, _mulmoclaude_core_collection.dateSortValue)(enriched[key]);
3838
3878
  return (0, _mulmoclaude_core_collection.stringSortValue)(enriched[key]);
3839
3879
  }
3840
3880
  const sortedItems = (0, vue.computed)(() => {
@@ -4012,10 +4052,12 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4012
4052
  function buildChatSeed(slug, message, itemId) {
4013
4053
  const current = collection.value;
4014
4054
  if (current?.source !== "feed") return itemId ? `/${slug} id=${itemId} ${message}` : `/${slug} ${message}`;
4055
+ const dataPath = current.schema.dataPath ?? `data/feeds/${slug}`;
4056
+ const scoped = itemId ? `(for record \`${itemId}\`) ${message}` : message;
4015
4057
  return t("collectionsView.feedChatSeed", {
4016
4058
  slug,
4017
- dataPath: current.schema.dataPath ?? `data/feeds/${slug}`,
4018
- message: itemId ? `(for record \`${itemId}\`) ${message}` : message
4059
+ dataPath,
4060
+ message: scoped
4019
4061
  });
4020
4062
  }
4021
4063
  /** Start a new general-role chat seeded from the current view. */
@@ -4090,7 +4132,10 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4090
4132
  enumOriginallyEmpty.value = snapshotEmptyEnums(result.data.collection.schema, result.data.items);
4091
4133
  await render.loadLinkedCollections(result.data.collection.schema, slug);
4092
4134
  if (activeSlug.value !== slug) return;
4093
- if (viewing.value) viewing.value = findItemById(String(viewing.value[result.data.collection.schema.primaryKey] ?? "")) ?? null;
4135
+ if (viewing.value) {
4136
+ const openId = String(viewing.value[result.data.collection.schema.primaryKey] ?? "");
4137
+ viewing.value = findItemById(openId) ?? null;
4138
+ }
4094
4139
  }
4095
4140
  function maybeAutoRefreshFeed(slug) {
4096
4141
  if (embedded.value) return;
@@ -4268,7 +4313,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4268
4313
  }
4269
4314
  /** Select a custom view by id (builds the `custom:<id>` mode key). */
4270
4315
  function setCustomView(viewId) {
4271
- view.value = `custom:${viewId}`;
4316
+ const mode = `custom:${viewId}`;
4317
+ view.value = mode;
4272
4318
  }
4273
4319
  /** A short, slug-safe id not already used by a loaded record. Collisions
4274
4320
  * are astronomically unlikely (32 bits), but we still re-roll a few
@@ -4426,7 +4472,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4426
4472
  viewing.value = null;
4427
4473
  return;
4428
4474
  }
4429
- viewing.value = findItemById(selected) ?? null;
4475
+ const match = findItemById(selected) ?? null;
4476
+ viewing.value = match;
4430
4477
  }
4431
4478
  /** Title for the open-mode header: the record's primary-key value
4432
4479
  * (e.g. `INV-2026-0001`), falling back to the collection title.
@@ -4520,19 +4567,17 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4520
4567
  /** Whether a `toggle` field reads as checked: its projected enum field
4521
4568
  * currently equals `onValue`. The toggle stores nothing itself. */
4522
4569
  function toggleChecked(item, field) {
4523
- return field.field !== void 0 && String(item[field.field] ?? "") === field.onValue;
4570
+ return field.type === "toggle" && String(item[field.field] ?? "") === field.onValue;
4524
4571
  }
4525
4572
  /** Flip a `toggle`: write the projected enum field to `offValue` when
4526
4573
  * currently checked, else `onValue`. Reuses the inline-edit PUT path
4527
4574
  * (optimistic + rollback) — the toggle has no value of its own. */
4528
4575
  function commitToggle(item, field) {
4576
+ if (field.type !== "toggle" || !collection.value) return;
4529
4577
  const targetKey = field.field;
4530
- if (!targetKey || !collection.value) return;
4531
4578
  const enumField = collection.value.schema.fields[targetKey];
4532
4579
  if (!enumField) return;
4533
- const next = toggleChecked(item, field) ? field.offValue : field.onValue;
4534
- if (next === void 0) return;
4535
- commitInlineEdit(item, targetKey, enumField, next);
4580
+ commitInlineEdit(item, targetKey, enumField, toggleChecked(item, field) ? field.offValue : field.onValue);
4536
4581
  }
4537
4582
  async function confirmDelete(item) {
4538
4583
  if (!collection.value) return;