@mulmoclaude/collection-plugin 0.11.3 → 0.12.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/vue.cjs CHANGED
@@ -92,6 +92,13 @@ var i18n = (0, vue_i18n.createI18n)({
92
92
  deleteCollection: "Delete collection",
93
93
  confirmDeleteCollection: "Delete the entire \"{title}\" collection, including all its records? A restorable backup is archived first.",
94
94
  itemsEmpty: "No items yet. Click + to add one.",
95
+ readonlyChip: "Read-only",
96
+ itemsEmptyReadonly: "No rows in the data file yet. Add rows to the file and they appear here.",
97
+ filter: {
98
+ all: "All",
99
+ editable: "Editable",
100
+ data: "Data"
101
+ },
95
102
  notFound: "Collection not found",
96
103
  loadFailed: "Failed to load",
97
104
  requiredField: "This field is required",
@@ -228,6 +235,13 @@ var i18n = (0, vue_i18n.createI18n)({
228
235
  deleteCollection: "コレクションを削除",
229
236
  confirmDeleteCollection: "コレクション「{title}」とそのすべてのレコードを削除しますか?削除前に復元可能なバックアップが保存されます。",
230
237
  itemsEmpty: "まだ項目がありません。+ を押して追加してください。",
238
+ readonlyChip: "読み取り専用",
239
+ itemsEmptyReadonly: "データファイルにまだ行がありません。ファイルに行を追加するとここに表示されます。",
240
+ filter: {
241
+ all: "すべて",
242
+ editable: "編集可能",
243
+ data: "データ"
244
+ },
231
245
  notFound: "コレクションが見つかりません",
232
246
  loadFailed: "読み込みに失敗しました",
233
247
  requiredField: "この項目は必須です",
@@ -364,6 +378,13 @@ var i18n = (0, vue_i18n.createI18n)({
364
378
  deleteCollection: "删除集合",
365
379
  confirmDeleteCollection: "删除整个“{title}”集合及其所有记录?删除前会先归档一份可恢复的备份。",
366
380
  itemsEmpty: "暂无项目。点击 + 添加一个。",
381
+ readonlyChip: "只读",
382
+ itemsEmptyReadonly: "数据文件中还没有行。在文件中添加行后会显示在这里。",
383
+ filter: {
384
+ all: "全部",
385
+ editable: "可编辑",
386
+ data: "数据"
387
+ },
367
388
  notFound: "未找到集合",
368
389
  loadFailed: "加载失败",
369
390
  requiredField: "此字段为必填项",
@@ -500,6 +521,13 @@ var i18n = (0, vue_i18n.createI18n)({
500
521
  deleteCollection: "컬렉션 삭제",
501
522
  confirmDeleteCollection: "\"{title}\" 컬렉션과 모든 레코드를 삭제하시겠습니까? 삭제 전에 복원 가능한 백업이 보관됩니다.",
502
523
  itemsEmpty: "아직 항목이 없습니다. + 를 눌러 추가하세요.",
524
+ readonlyChip: "읽기 전용",
525
+ itemsEmptyReadonly: "데이터 파일에 아직 행이 없습니다. 파일에 행을 추가하면 여기에 표시됩니다.",
526
+ filter: {
527
+ all: "전체",
528
+ editable: "편집 가능",
529
+ data: "데이터"
530
+ },
503
531
  notFound: "컬렉션을 찾을 수 없습니다",
504
532
  loadFailed: "불러오기에 실패했습니다",
505
533
  requiredField: "이 필드는 필수입니다",
@@ -636,6 +664,13 @@ var i18n = (0, vue_i18n.createI18n)({
636
664
  deleteCollection: "Eliminar colección",
637
665
  confirmDeleteCollection: "¿Eliminar toda la colección \"{title}\", incluidos todos sus registros? Antes se archiva una copia de seguridad restaurable.",
638
666
  itemsEmpty: "Aún no hay elementos. Pulsa + para añadir uno.",
667
+ readonlyChip: "Solo lectura",
668
+ itemsEmptyReadonly: "El archivo de datos aún no tiene filas. Añádelas al archivo y aparecerán aquí.",
669
+ filter: {
670
+ all: "Todas",
671
+ editable: "Editables",
672
+ data: "Datos"
673
+ },
639
674
  notFound: "Colección no encontrada",
640
675
  loadFailed: "Error al cargar",
641
676
  requiredField: "Este campo es obligatorio",
@@ -772,6 +807,13 @@ var i18n = (0, vue_i18n.createI18n)({
772
807
  deleteCollection: "Excluir coleção",
773
808
  confirmDeleteCollection: "Excluir toda a coleção \"{title}\", incluindo todos os seus registros? Um backup restaurável é arquivado antes.",
774
809
  itemsEmpty: "Ainda não há itens. Clique em + para adicionar um.",
810
+ readonlyChip: "Somente leitura",
811
+ itemsEmptyReadonly: "O arquivo de dados ainda não tem linhas. Adicione linhas ao arquivo e elas aparecerão aqui.",
812
+ filter: {
813
+ all: "Todas",
814
+ editable: "Editáveis",
815
+ data: "Dados"
816
+ },
775
817
  notFound: "Coleção não encontrada",
776
818
  loadFailed: "Falha ao carregar",
777
819
  requiredField: "Este campo é obrigatório",
@@ -908,6 +950,13 @@ var i18n = (0, vue_i18n.createI18n)({
908
950
  deleteCollection: "Supprimer la collection",
909
951
  confirmDeleteCollection: "Supprimer toute la collection « {title} », y compris tous ses enregistrements ? Une sauvegarde restaurable est archivée au préalable.",
910
952
  itemsEmpty: "Aucun élément pour l'instant. Cliquez sur + pour en ajouter un.",
953
+ readonlyChip: "Lecture seule",
954
+ itemsEmptyReadonly: "Le fichier de données ne contient pas encore de lignes. Ajoutez-en au fichier et elles apparaîtront ici.",
955
+ filter: {
956
+ all: "Toutes",
957
+ editable: "Modifiables",
958
+ data: "Données"
959
+ },
911
960
  notFound: "Collection introuvable",
912
961
  loadFailed: "Échec du chargement",
913
962
  requiredField: "Ce champ est obligatoire",
@@ -1044,6 +1093,13 @@ var i18n = (0, vue_i18n.createI18n)({
1044
1093
  deleteCollection: "Sammlung löschen",
1045
1094
  confirmDeleteCollection: "Die gesamte Sammlung „{title}“ einschließlich aller Datensätze löschen? Zuvor wird eine wiederherstellbare Sicherung archiviert.",
1046
1095
  itemsEmpty: "Noch keine Einträge. Klicke auf +, um einen hinzuzufügen.",
1096
+ readonlyChip: "Schreibgeschützt",
1097
+ itemsEmptyReadonly: "Noch keine Zeilen in der Datendatei. Füge der Datei Zeilen hinzu, dann erscheinen sie hier.",
1098
+ filter: {
1099
+ all: "Alle",
1100
+ editable: "Bearbeitbar",
1101
+ data: "Daten"
1102
+ },
1047
1103
  notFound: "Sammlung nicht gefunden",
1048
1104
  loadFailed: "Laden fehlgeschlagen",
1049
1105
  requiredField: "Dieses Feld ist erforderlich",
@@ -2067,7 +2123,8 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2067
2123
  groupField: {},
2068
2124
  items: {},
2069
2125
  selected: {},
2070
- notified: {}
2126
+ notified: {},
2127
+ readonly: { type: Boolean }
2071
2128
  },
2072
2129
  emits: ["select", "move"],
2073
2130
  setup(__props, { emit: __emit }) {
@@ -2174,6 +2231,7 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2174
2231
  group: "collection-kanban-cards",
2175
2232
  class: "flex-1 overflow-y-auto p-2 space-y-2 min-h-[2rem]",
2176
2233
  animation: 150,
2234
+ disabled: __props.readonly,
2177
2235
  onChange: (e) => onDragChange(column.value, e)
2178
2236
  }, {
2179
2237
  item: (0, vue.withCtx)(({ element }) => [(0, vue.createElementVNode)("div", {
@@ -2184,7 +2242,7 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2184
2242
  class: (0, vue.normalizeClass)(["bg-white border border-slate-200 rounded shadow-sm p-2 cursor-grab hover:shadow active:cursor-grabbing focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-400", [itemId(element) === __props.selected ? "ring-2 ring-indigo-500 border-indigo-300" : "", notifyAccentClass(element)]]),
2185
2243
  onClick: ($event) => emit("select", itemId(element)),
2186
2244
  onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)((e) => !e.repeat && emit("select", itemId(element)), ["prevent", "self"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)((e) => !e.repeat && emit("select", itemId(element)), ["prevent", "self"]), ["space"])]
2187
- }, [(0, vue.createElementVNode)("div", _hoisted_9$8, [cardToggle.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
2245
+ }, [(0, vue.createElementVNode)("div", _hoisted_9$8, [cardToggle.value && !__props.readonly ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
2188
2246
  key: 0,
2189
2247
  type: "checkbox",
2190
2248
  checked: cardChecked(element),
@@ -2198,6 +2256,7 @@ var CollectionKanbanView_default = /* @__PURE__ */ (0, vue.defineComponent)({
2198
2256
  }, 8, [
2199
2257
  "model-value",
2200
2258
  "item-key",
2259
+ "disabled",
2201
2260
  "onChange"
2202
2261
  ])], 8, _hoisted_3$12);
2203
2262
  }), 128))])]);
@@ -2424,23 +2483,23 @@ var _hoisted_18$5 = [
2424
2483
  "placeholder",
2425
2484
  "data-testid"
2426
2485
  ];
2427
- var _hoisted_19$3 = {
2486
+ var _hoisted_19$4 = {
2428
2487
  key: 0,
2429
2488
  class: "inline-flex items-center gap-2.5 text-sm text-slate-700 cursor-pointer select-none"
2430
2489
  };
2431
- var _hoisted_20$3 = [
2490
+ var _hoisted_20$4 = [
2432
2491
  "id",
2433
2492
  "onUpdate:modelValue",
2434
2493
  "data-testid",
2435
2494
  "onChange"
2436
2495
  ];
2437
- var _hoisted_21$3 = [
2496
+ var _hoisted_21$4 = [
2438
2497
  "id",
2439
2498
  "onUpdate:modelValue",
2440
2499
  "required",
2441
2500
  "data-testid"
2442
2501
  ];
2443
- var _hoisted_22$3 = { value: "" };
2502
+ var _hoisted_22$4 = { value: "" };
2444
2503
  var _hoisted_23$3 = ["value"];
2445
2504
  var _hoisted_24$2 = [
2446
2505
  "id",
@@ -2624,6 +2683,7 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
2624
2683
  liveDerived: {},
2625
2684
  viewTitle: {},
2626
2685
  isSingleton: { type: Boolean },
2686
+ readonly: { type: Boolean },
2627
2687
  render: {},
2628
2688
  locale: {}
2629
2689
  }, {
@@ -2777,18 +2837,20 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
2777
2837
  onClick: ($event) => emit("runAction", action)
2778
2838
  }, [__props.runningActionIds.includes(action.id) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_8$6, "progress_activity")) : action.icon ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_9$6, (0, vue.toDisplayString)(action.icon), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(action.label), 1)], 8, _hoisted_7$6);
2779
2839
  }), 128)),
2780
- (0, vue.createElementVNode)("button", {
2840
+ !__props.readonly ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
2841
+ key: 0,
2781
2842
  type: "button",
2782
2843
  class: "h-8 px-2.5 rounded border border-slate-200 bg-white text-slate-700 hover:bg-slate-50 font-bold text-xs transition-all flex items-center gap-1",
2783
2844
  "data-testid": "collections-detail-edit",
2784
2845
  onClick: _cache[1] || (_cache[1] = ($event) => emit("edit"))
2785
- }, [_cache[6] || (_cache[6] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "edit", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.editItem")), 1)]),
2786
- (0, vue.createElementVNode)("button", {
2846
+ }, [_cache[6] || (_cache[6] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "edit", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.editItem")), 1)])) : (0, vue.createCommentVNode)("", true),
2847
+ !__props.readonly ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
2848
+ key: 1,
2787
2849
  type: "button",
2788
2850
  class: "h-8 px-2.5 rounded border border-rose-200 bg-white text-rose-600 hover:bg-rose-50 font-bold text-xs transition-all flex items-center gap-1",
2789
2851
  "data-testid": "collections-detail-remove",
2790
2852
  onClick: _cache[2] || (_cache[2] = ($event) => emit("delete"))
2791
- }, [_cache[7] || (_cache[7] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.remove")), 1)]),
2853
+ }, [_cache[7] || (_cache[7] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.remove")), 1)])) : (0, vue.createCommentVNode)("", true),
2792
2854
  (0, vue.createElementVNode)("button", {
2793
2855
  type: "button",
2794
2856
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-400 hover:bg-slate-100 hover:text-slate-600 transition-colors",
@@ -2826,26 +2888,26 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
2826
2888
  placeholder: (0, vue.unref)(t)("collectionsView.selectPlaceholder"),
2827
2889
  class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none font-medium text-slate-700 transition-all",
2828
2890
  "data-testid": `collections-input-${key}`
2829
- }, null, 8, _hoisted_18$5)), [[vue.vModelText, editing.value.text[field.idField]]]) : editing.value && isEditableType(field.type) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("label", _hoisted_19$3, [(0, vue.withDirectives)((0, vue.createElementVNode)("input", {
2891
+ }, null, 8, _hoisted_18$5)), [[vue.vModelText, editing.value.text[field.idField]]]) : editing.value && isEditableType(field.type) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("label", _hoisted_19$4, [(0, vue.withDirectives)((0, vue.createElementVNode)("input", {
2830
2892
  id: `collections-field-${key}`,
2831
2893
  "onUpdate:modelValue": ($event) => editing.value.bool[key] = $event,
2832
2894
  type: "checkbox",
2833
2895
  class: "h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500/20 cursor-pointer",
2834
2896
  "data-testid": `collections-input-${key}`,
2835
2897
  onChange: ($event) => markBoolTouched(String(key))
2836
- }, null, 40, _hoisted_20$3), [[vue.vModelCheckbox, editing.value.bool[key]]]), (0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["text-xs font-semibold", editing.value.bool[key] ? "text-indigo-600" : "text-slate-500"]) }, (0, vue.toDisplayString)(editing.value.bool[key] ? (0, vue.unref)(t)("common.yes") : (0, vue.unref)(t)("common.no")), 3)])) : field.type === "ref" && field.to && __props.render.refOptions(field.to).length > 0 ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
2898
+ }, null, 40, _hoisted_20$4), [[vue.vModelCheckbox, editing.value.bool[key]]]), (0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["text-xs font-semibold", editing.value.bool[key] ? "text-indigo-600" : "text-slate-500"]) }, (0, vue.toDisplayString)(editing.value.bool[key] ? (0, vue.unref)(t)("common.yes") : (0, vue.unref)(t)("common.no")), 3)])) : field.type === "ref" && field.to && __props.render.refOptions(field.to).length > 0 ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
2837
2899
  key: 1,
2838
2900
  id: `collections-field-${key}`,
2839
2901
  "onUpdate:modelValue": ($event) => editing.value.text[key] = $event,
2840
2902
  required: isFieldRequiredInUi(field),
2841
2903
  class: "w-full rounded-xl border border-slate-200 px-3 py-2 text-xs bg-slate-50 hover:bg-slate-50/50 focus:bg-white focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none transition-all cursor-pointer font-medium text-slate-700",
2842
2904
  "data-testid": `collections-input-${key}`
2843
- }, [(0, vue.createElementVNode)("option", _hoisted_22$3, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.refOptions(field.to), (opt) => {
2905
+ }, [(0, vue.createElementVNode)("option", _hoisted_22$4, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.refOptions(field.to), (opt) => {
2844
2906
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
2845
2907
  key: opt.slug,
2846
2908
  value: opt.slug
2847
2909
  }, (0, vue.toDisplayString)(opt.display), 9, _hoisted_23$3);
2848
- }), 128))], 8, _hoisted_21$3)), [[vue.vModelSelect, editing.value.text[key]]]) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
2910
+ }), 128))], 8, _hoisted_21$4)), [[vue.vModelSelect, editing.value.text[key]]]) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
2849
2911
  key: 2,
2850
2912
  id: `collections-field-${key}`,
2851
2913
  "onUpdate:modelValue": ($event) => editing.value.text[key] = $event,
@@ -3858,222 +3920,227 @@ var _hoisted_6$4 = { class: "flex-1 min-w-0" };
3858
3920
  var _hoisted_7$4 = { class: "text-base font-bold text-slate-800 truncate" };
3859
3921
  var _hoisted_8$4 = {
3860
3922
  key: 0,
3861
- class: "block text-[10px] text-slate-400 font-bold uppercase tracking-wider"
3923
+ class: "block text-[10px] text-slate-400 font-bold uppercase tracking-wider truncate"
3862
3924
  };
3863
- var _hoisted_9$4 = ["disabled"];
3864
- var _hoisted_10$4 = { class: "material-icons text-sm" };
3865
- var _hoisted_11$4 = [
3925
+ var _hoisted_9$4 = {
3926
+ class: "inline-flex items-center gap-0.5 ml-1.5 px-1.5 py-px rounded bg-amber-50 text-amber-700 border border-amber-200 normal-case tracking-normal",
3927
+ "data-testid": "collections-readonly-chip"
3928
+ };
3929
+ var _hoisted_10$4 = ["href"];
3930
+ var _hoisted_11$4 = ["disabled"];
3931
+ var _hoisted_12$4 = { class: "material-icons text-sm" };
3932
+ var _hoisted_13$4 = [
3866
3933
  "disabled",
3867
3934
  "data-testid",
3868
3935
  "onClick"
3869
3936
  ];
3870
- var _hoisted_12$4 = {
3937
+ var _hoisted_14$4 = {
3871
3938
  key: 0,
3872
3939
  class: "material-icons text-sm animate-spin"
3873
3940
  };
3874
- var _hoisted_13$4 = {
3941
+ var _hoisted_15$4 = {
3875
3942
  key: 1,
3876
3943
  class: "material-icons text-sm"
3877
3944
  };
3878
- var _hoisted_14$4 = ["title", "aria-label"];
3879
- var _hoisted_15$4 = ["title", "aria-label"];
3880
- var _hoisted_16$4 = {
3945
+ var _hoisted_16$4 = ["title", "aria-label"];
3946
+ var _hoisted_17$4 = ["title", "aria-label"];
3947
+ var _hoisted_18$4 = {
3881
3948
  key: 1,
3882
3949
  class: "mx-6 mt-2 rounded-lg border border-indigo-200 bg-indigo-50/60 px-4 py-2 text-sm text-indigo-800 flex items-center gap-2",
3883
3950
  "data-testid": "collections-refresh-note"
3884
3951
  };
3885
- var _hoisted_17$4 = { class: "flex-1" };
3886
- var _hoisted_18$4 = {
3952
+ var _hoisted_19$3 = { class: "flex-1" };
3953
+ var _hoisted_20$3 = {
3887
3954
  key: 2,
3888
3955
  class: "px-6 py-3 bg-white border-b border-slate-100 flex items-center justify-between gap-4"
3889
3956
  };
3890
- var _hoisted_19$2 = {
3957
+ var _hoisted_21$3 = {
3891
3958
  key: 0,
3892
3959
  class: "relative flex-1 max-w-md"
3893
3960
  };
3894
- var _hoisted_20$2 = ["placeholder", "aria-label"];
3895
- var _hoisted_21$2 = ["aria-label"];
3896
- var _hoisted_22$2 = { class: "flex items-center gap-2" };
3961
+ var _hoisted_22$3 = ["placeholder", "aria-label"];
3897
3962
  var _hoisted_23$2 = ["aria-label"];
3898
- var _hoisted_24$1 = ["aria-pressed"];
3899
- var _hoisted_25$1 = ["aria-pressed"];
3963
+ var _hoisted_24$1 = { class: "flex items-center gap-2" };
3964
+ var _hoisted_25$1 = ["aria-label"];
3900
3965
  var _hoisted_26$1 = ["aria-pressed"];
3901
- var _hoisted_27$1 = [
3966
+ var _hoisted_27$1 = ["aria-pressed"];
3967
+ var _hoisted_28 = ["aria-pressed"];
3968
+ var _hoisted_29 = [
3902
3969
  "aria-pressed",
3903
3970
  "data-testid",
3904
3971
  "onClick"
3905
3972
  ];
3906
- var _hoisted_28 = { class: "material-icons text-sm" };
3907
- var _hoisted_29 = [
3973
+ var _hoisted_30 = { class: "material-icons text-sm" };
3974
+ var _hoisted_31 = [
3908
3975
  "title",
3909
3976
  "aria-label",
3910
3977
  "aria-expanded"
3911
3978
  ];
3912
- var _hoisted_30 = {
3979
+ var _hoisted_32 = {
3913
3980
  key: 0,
3914
3981
  class: "absolute left-0 top-full mt-1 z-20 min-w-max rounded border border-slate-200 bg-white shadow-lg py-1",
3915
3982
  "data-testid": "collection-view-add-menu"
3916
3983
  };
3917
- var _hoisted_31 = ["title", "aria-label"];
3918
- var _hoisted_32 = ["value", "aria-label"];
3919
- var _hoisted_33 = ["value"];
3984
+ var _hoisted_33 = ["title", "aria-label"];
3920
3985
  var _hoisted_34 = ["value", "aria-label"];
3921
3986
  var _hoisted_35 = ["value"];
3922
- var _hoisted_36 = {
3987
+ var _hoisted_36 = ["value", "aria-label"];
3988
+ var _hoisted_37 = ["value"];
3989
+ var _hoisted_38 = {
3923
3990
  key: 3,
3924
3991
  class: "text-[10px] text-slate-400 font-bold uppercase tracking-wider select-none"
3925
3992
  };
3926
- var _hoisted_37 = {
3993
+ var _hoisted_39 = {
3927
3994
  key: 3,
3928
3995
  class: "mx-6 mt-4 rounded-xl border border-amber-200 bg-amber-50/60 p-4 text-sm text-amber-900 shadow-sm flex items-center gap-3",
3929
3996
  "data-testid": "collections-data-issues"
3930
3997
  };
3931
- var _hoisted_38 = { class: "flex-1" };
3932
- var _hoisted_39 = { class: "flex-1 overflow-auto" };
3933
- var _hoisted_40 = {
3998
+ var _hoisted_40 = { class: "flex-1" };
3999
+ var _hoisted_41 = { class: "flex-1 overflow-auto" };
4000
+ var _hoisted_42 = {
3934
4001
  key: 0,
3935
4002
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-500 gap-3"
3936
4003
  };
3937
- var _hoisted_41 = {
4004
+ var _hoisted_43 = {
3938
4005
  key: 1,
3939
4006
  class: "m-6 rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3"
3940
4007
  };
3941
- var _hoisted_42 = { key: 2 };
3942
- var _hoisted_43 = {
4008
+ var _hoisted_44 = { key: 2 };
4009
+ var _hoisted_45 = {
3943
4010
  key: 3,
3944
4011
  class: "p-4"
3945
4012
  };
3946
- var _hoisted_44 = {
4013
+ var _hoisted_46 = {
3947
4014
  key: 4,
3948
4015
  class: "h-full flex flex-col"
3949
4016
  };
3950
- var _hoisted_45 = {
4017
+ var _hoisted_47 = {
3951
4018
  key: 0,
3952
4019
  class: "m-3 mb-0 rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3",
3953
4020
  "data-testid": "collections-inline-error"
3954
4021
  };
3955
- var _hoisted_46 = { class: "flex-1" };
3956
- var _hoisted_47 = ["aria-label"];
3957
- var _hoisted_48 = { class: "flex-1 min-h-0 px-3 py-2" };
3958
- var _hoisted_49 = {
4022
+ var _hoisted_48 = { class: "flex-1" };
4023
+ var _hoisted_49 = ["aria-label"];
4024
+ var _hoisted_50 = { class: "flex-1 min-h-0 px-3 py-2" };
4025
+ var _hoisted_51 = {
3959
4026
  key: 5,
3960
4027
  class: "h-full",
3961
4028
  "data-testid": "collection-custom-view-body"
3962
4029
  };
3963
- var _hoisted_50 = {
4030
+ var _hoisted_52 = {
3964
4031
  key: 6,
3965
4032
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
3966
4033
  };
3967
- var _hoisted_51 = { class: "font-semibold text-slate-600" };
3968
- var _hoisted_52 = {
4034
+ var _hoisted_53 = { class: "font-semibold text-slate-600" };
4035
+ var _hoisted_54 = {
3969
4036
  key: 7,
3970
4037
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
3971
4038
  };
3972
- var _hoisted_53 = { class: "font-semibold text-slate-600" };
3973
- var _hoisted_54 = {
4039
+ var _hoisted_55 = { class: "font-semibold text-slate-600" };
4040
+ var _hoisted_56 = {
3974
4041
  key: 8,
3975
4042
  class: "overflow-x-auto [container-type:inline-size]"
3976
4043
  };
3977
- var _hoisted_55 = {
4044
+ var _hoisted_57 = {
3978
4045
  key: 0,
3979
4046
  class: "m-4 rounded-xl border border-red-200 bg-red-50/50 p-4 text-sm text-red-800 shadow-sm flex items-center gap-3",
3980
4047
  "data-testid": "collections-inline-error"
3981
4048
  };
3982
- var _hoisted_56 = { class: "flex-1" };
3983
- var _hoisted_57 = ["aria-label"];
3984
- var _hoisted_58 = { class: "min-w-full text-xs" };
3985
- var _hoisted_59 = { class: "bg-slate-50 border-b border-slate-200" };
3986
- var _hoisted_60 = ["aria-sort"];
3987
- var _hoisted_61 = { class: "flex items-center gap-1" };
3988
- var _hoisted_62 = ["title"];
3989
- var _hoisted_63 = [
4049
+ var _hoisted_58 = { class: "flex-1" };
4050
+ var _hoisted_59 = ["aria-label"];
4051
+ var _hoisted_60 = { class: "min-w-full text-xs" };
4052
+ var _hoisted_61 = { class: "bg-slate-50 border-b border-slate-200" };
4053
+ var _hoisted_62 = ["aria-sort"];
4054
+ var _hoisted_63 = { class: "flex items-center gap-1" };
4055
+ var _hoisted_64 = ["title"];
4056
+ var _hoisted_65 = [
3990
4057
  "data-testid",
3991
4058
  "aria-label",
3992
4059
  "onClick",
3993
4060
  "onPointerenter"
3994
4061
  ];
3995
- var _hoisted_64 = { class: "material-icons text-base align-middle" };
3996
- var _hoisted_65 = { class: "divide-y divide-slate-100 bg-white" };
3997
- var _hoisted_66 = [
4062
+ var _hoisted_66 = { class: "material-icons text-base align-middle" };
4063
+ var _hoisted_67 = { class: "divide-y divide-slate-100 bg-white" };
4064
+ var _hoisted_68 = [
3998
4065
  "aria-label",
3999
4066
  "data-testid",
4000
4067
  "onClick",
4001
4068
  "onKeydown"
4002
4069
  ];
4003
- var _hoisted_67 = [
4070
+ var _hoisted_69 = [
4004
4071
  "checked",
4005
4072
  "disabled",
4006
4073
  "data-testid",
4007
4074
  "aria-label",
4008
4075
  "onChange"
4009
4076
  ];
4010
- var _hoisted_68 = [
4077
+ var _hoisted_70 = [
4011
4078
  "checked",
4012
4079
  "disabled",
4013
4080
  "data-testid",
4014
4081
  "aria-label",
4015
4082
  "onChange"
4016
4083
  ];
4017
- var _hoisted_69 = {
4084
+ var _hoisted_71 = {
4018
4085
  key: 2,
4019
4086
  class: "block truncate"
4020
4087
  };
4021
- var _hoisted_70 = [
4088
+ var _hoisted_72 = [
4022
4089
  "href",
4023
4090
  "tabindex",
4024
4091
  "data-testid",
4025
4092
  "onClick",
4026
4093
  "onKeydown"
4027
4094
  ];
4028
- var _hoisted_71 = [
4095
+ var _hoisted_73 = [
4029
4096
  "value",
4030
4097
  "disabled",
4031
4098
  "data-testid",
4032
4099
  "aria-label",
4033
4100
  "onChange"
4034
4101
  ];
4035
- var _hoisted_72 = {
4102
+ var _hoisted_74 = {
4036
4103
  key: 0,
4037
4104
  value: ""
4038
4105
  };
4039
- var _hoisted_73 = ["value"];
4040
- var _hoisted_74 = {
4106
+ var _hoisted_75 = ["value"];
4107
+ var _hoisted_76 = {
4041
4108
  key: 4,
4042
4109
  class: "block truncate tabular-nums font-semibold text-slate-900"
4043
4110
  };
4044
- var _hoisted_75 = {
4111
+ var _hoisted_77 = {
4045
4112
  key: 5,
4046
4113
  class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-lg text-[10px] font-bold bg-slate-100 text-slate-600 border border-slate-200/40"
4047
4114
  };
4048
- var _hoisted_76 = {
4115
+ var _hoisted_78 = {
4049
4116
  key: 6,
4050
4117
  class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-1.5 py-0.5 rounded border border-indigo-100/50"
4051
4118
  };
4052
- var _hoisted_77 = ["data-testid"];
4053
- var _hoisted_78 = ["href", "data-testid"];
4054
- var _hoisted_79 = ["href", "data-testid"];
4055
- var _hoisted_80 = [
4119
+ var _hoisted_79 = ["data-testid"];
4120
+ var _hoisted_80 = ["href", "data-testid"];
4121
+ var _hoisted_81 = ["href", "data-testid"];
4122
+ var _hoisted_82 = [
4056
4123
  "href",
4057
4124
  "data-testid",
4058
4125
  "onClick"
4059
4126
  ];
4060
- var _hoisted_81 = {
4127
+ var _hoisted_83 = {
4061
4128
  key: 11,
4062
4129
  class: "block truncate text-slate-600"
4063
4130
  };
4064
- var _hoisted_82 = { class: "bg-white rounded-2xl shadow-2xl w-full max-w-xl flex flex-col border border-slate-200 overflow-hidden" };
4065
- var _hoisted_83 = { class: "px-6 py-4 border-b border-slate-100 flex items-center gap-3 bg-slate-50/50" };
4066
- var _hoisted_84 = { class: "flex-1" };
4067
- var _hoisted_85 = {
4131
+ var _hoisted_84 = { class: "bg-white rounded-2xl shadow-2xl w-full max-w-xl flex flex-col border border-slate-200 overflow-hidden" };
4132
+ var _hoisted_85 = { class: "px-6 py-4 border-b border-slate-100 flex items-center gap-3 bg-slate-50/50" };
4133
+ var _hoisted_86 = { class: "flex-1" };
4134
+ var _hoisted_87 = {
4068
4135
  id: "collections-chat-title",
4069
4136
  class: "text-sm font-bold text-slate-800 uppercase tracking-wide"
4070
4137
  };
4071
- var _hoisted_86 = { class: "text-xs text-slate-400 font-semibold" };
4072
- var _hoisted_87 = ["aria-label"];
4073
- var _hoisted_88 = { class: "px-6 py-5" };
4074
- var _hoisted_89 = ["placeholder", "onKeydown"];
4075
- var _hoisted_90 = { class: "px-6 py-3.5 border-t border-slate-100 flex items-center justify-end gap-2 bg-slate-50/50" };
4076
- var _hoisted_91 = ["disabled"];
4138
+ var _hoisted_88 = { class: "text-xs text-slate-400 font-semibold" };
4139
+ var _hoisted_89 = ["aria-label"];
4140
+ var _hoisted_90 = { class: "px-6 py-5" };
4141
+ var _hoisted_91 = ["placeholder", "onKeydown"];
4142
+ var _hoisted_92 = { class: "px-6 py-3.5 border-t border-slate-100 flex items-center justify-end gap-2 bg-slate-50/50" };
4143
+ var _hoisted_93 = ["disabled"];
4077
4144
  /** `slug` / `selected` are supplied only in EMBEDDED mode (the
4078
4145
  * `presentCollection` chat card mounts this component and drives both
4079
4146
  * from the tool result). In standalone route mode (the
@@ -4627,10 +4694,22 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4627
4694
  /** True when the current collection declares `schema.singleton` —
4628
4695
  * exactly one record, its primary key fixed to the declared value. */
4629
4696
  const isSingleton = (0, vue.computed)(() => Boolean(collection.value?.schema.singleton));
4697
+ /** True when the collection is backed by an external `dataSource` (CSV) —
4698
+ * read-only in every write surface here; the server enforces the same
4699
+ * rule with 405s, this just keeps dead controls off the screen. */
4700
+ const isReadOnly = (0, vue.computed)(() => collection.value?.schema.dataSource !== void 0);
4701
+ /** File-explorer route for the dataSource file (the one editable thing
4702
+ * about a read-only collection), or null on a router-less host. */
4703
+ const dataSourceRoute = (0, vue.computed)(() => {
4704
+ const sourcePath = collection.value?.schema.dataSource?.path;
4705
+ return sourcePath ? fileRoutePath(sourcePath) : null;
4706
+ });
4630
4707
  /** Whether the Add button should show. Always for a normal collection;
4631
- * for a singleton only until its one record exists. */
4708
+ * for a singleton only until its one record exists; never for a
4709
+ * read-only (dataSource) collection. */
4632
4710
  const canCreate = (0, vue.computed)(() => {
4633
4711
  if (!collection.value) return false;
4712
+ if (isReadOnly.value) return false;
4634
4713
  return !(isSingleton.value && items.value.length > 0);
4635
4714
  });
4636
4715
  const canDeleteCollection = (0, vue.computed)(() => {
@@ -5022,7 +5101,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5022
5101
  * race the in-flight one. On failure, roll the cell back and surface the
5023
5102
  * error. Bypasses the detail/edit panel entirely. */
5024
5103
  async function commitInlineEdit(item, key, field, raw) {
5025
- if (!collection.value) return;
5104
+ if (!collection.value || isReadOnly.value) return;
5026
5105
  const { slug } = collection.value;
5027
5106
  const itemId = rowId(item);
5028
5107
  if (!itemId || inlineSavingRows.value.has(itemId)) return;
@@ -5292,9 +5371,15 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5292
5371
  "aria-label": (0, vue.unref)(t)("collectionsView.backToIndex"),
5293
5372
  "data-testid": "collections-back",
5294
5373
  onClick: goBack
5295
- }, [..._cache[26] || (_cache[26] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "arrow_back", -1)])], 8, _hoisted_3$5)) : (0, vue.createCommentVNode)("", true),
5374
+ }, [..._cache[27] || (_cache[27] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "arrow_back", -1)])], 8, _hoisted_3$5)) : (0, vue.createCommentVNode)("", true),
5296
5375
  collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$5, [(0, vue.createElementVNode)("span", _hoisted_5$5, (0, vue.toDisplayString)(collection.value.icon), 1)])) : (0, vue.createCommentVNode)("", true),
5297
- (0, vue.createElementVNode)("div", _hoisted_6$4, [(0, vue.createElementVNode)("h1", _hoisted_7$4, (0, vue.toDisplayString)(collection.value?.title ?? (0, vue.unref)(t)("collectionsView.title")), 1), collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_8$4, (0, vue.toDisplayString)(collection.value.slug), 1)) : (0, vue.createCommentVNode)("", true)]),
5376
+ (0, vue.createElementVNode)("div", _hoisted_6$4, [(0, vue.createElementVNode)("h1", _hoisted_7$4, (0, vue.toDisplayString)(collection.value?.title ?? (0, vue.unref)(t)("collectionsView.title")), 1), collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_8$4, [(0, vue.createTextVNode)((0, vue.toDisplayString)(collection.value.slug) + " ", 1), isReadOnly.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [(0, vue.createElementVNode)("span", _hoisted_9$4, [_cache[28] || (_cache[28] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "lock", -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.readonlyChip")), 1)]), dataSourceRoute.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5377
+ key: 0,
5378
+ href: dataSourceRoute.value ?? void 0,
5379
+ class: "ml-1 normal-case tracking-normal font-mono font-normal text-slate-500 hover:text-indigo-700 hover:underline",
5380
+ "data-testid": "collections-readonly-source",
5381
+ onClick: _cache[0] || (_cache[0] = ($event) => (0, vue.unref)(activatePathLink)($event, dataSourceRoute.value ?? "", true))
5382
+ }, (0, vue.toDisplayString)(collection.value.schema.dataSource?.path), 9, _hoisted_10$4)) : (0, vue.createCommentVNode)("", true)], 64)) : (0, vue.createCommentVNode)("", true)])) : (0, vue.createCommentVNode)("", true)]),
5298
5383
  collection.value && !embedded.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(pinToggle)), {
5299
5384
  key: 2,
5300
5385
  kind: isFeedRoute.value ? "feed" : "collection",
@@ -5314,14 +5399,14 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5314
5399
  disabled: refreshing.value,
5315
5400
  "data-testid": "collections-refresh-feed",
5316
5401
  onClick: refreshFeed
5317
- }, [(0, vue.createElementVNode)("span", _hoisted_10$4, (0, vue.toDisplayString)(refreshing.value ? "hourglass_empty" : "refresh"), 1), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.refreshFeed")), 1)], 8, _hoisted_9$4)) : (0, vue.createCommentVNode)("", true),
5402
+ }, [(0, vue.createElementVNode)("span", _hoisted_12$4, (0, vue.toDisplayString)(refreshing.value ? "hourglass_empty" : "refresh"), 1), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.refreshFeed")), 1)], 8, _hoisted_11$4)) : (0, vue.createCommentVNode)("", true),
5318
5403
  collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5319
5404
  key: 4,
5320
5405
  type: "button",
5321
5406
  class: "h-8 px-2.5 flex items-center gap-1 rounded border border-indigo-200 bg-white hover:bg-indigo-50 text-indigo-600 font-bold text-xs transition-colors",
5322
5407
  "data-testid": "collections-chat",
5323
5408
  onClick: openChat
5324
- }, [_cache[27] || (_cache[27] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "forum", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chat")), 1)])) : (0, vue.createCommentVNode)("", true),
5409
+ }, [_cache[29] || (_cache[29] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "forum", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chat")), 1)])) : (0, vue.createCommentVNode)("", true),
5325
5410
  ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(collectionActions.value, (action) => {
5326
5411
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5327
5412
  key: action.id,
@@ -5330,7 +5415,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5330
5415
  disabled: collectionActionPending.value || isActionRunning(action.id),
5331
5416
  "data-testid": `collections-action-${action.id}`,
5332
5417
  onClick: ($event) => runCollectionAction(action)
5333
- }, [isActionRunning(action.id) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_12$4, "progress_activity")) : action.icon ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_13$4, (0, vue.toDisplayString)(action.icon), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(action.label), 1)], 8, _hoisted_11$4);
5418
+ }, [isActionRunning(action.id) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_14$4, "progress_activity")) : action.icon ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_15$4, (0, vue.toDisplayString)(action.icon), 1)) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(action.label), 1)], 8, _hoisted_13$4);
5334
5419
  }), 128)),
5335
5420
  canCreate.value && !calendarActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5336
5421
  key: 5,
@@ -5338,7 +5423,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5338
5423
  class: "h-8 px-2.5 flex items-center gap-1 rounded bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-xs transition-colors shadow-sm",
5339
5424
  "data-testid": "collections-add-item",
5340
5425
  onClick: openCreate
5341
- }, [_cache[28] || (_cache[28] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.add")), 1)])) : (0, vue.createCommentVNode)("", true),
5426
+ }, [_cache[30] || (_cache[30] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.add")), 1)])) : (0, vue.createCommentVNode)("", true),
5342
5427
  canDeleteCollection.value && !embedded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5343
5428
  key: 6,
5344
5429
  type: "button",
@@ -5347,7 +5432,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5347
5432
  "aria-label": (0, vue.unref)(t)("collectionsView.deleteCollection"),
5348
5433
  "data-testid": "collections-delete",
5349
5434
  onClick: confirmCollectionDelete
5350
- }, [..._cache[29] || (_cache[29] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_14$4)) : (0, vue.createCommentVNode)("", true),
5435
+ }, [..._cache[31] || (_cache[31] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_16$4)) : (0, vue.createCommentVNode)("", true),
5351
5436
  canDeleteFeed.value && !embedded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5352
5437
  key: 7,
5353
5438
  type: "button",
@@ -5356,26 +5441,26 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5356
5441
  "aria-label": (0, vue.unref)(t)("collectionsView.deleteFeed"),
5357
5442
  "data-testid": "feeds-delete",
5358
5443
  onClick: confirmFeedDelete
5359
- }, [..._cache[30] || (_cache[30] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_15$4)) : (0, vue.createCommentVNode)("", true)
5444
+ }, [..._cache[32] || (_cache[32] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_17$4)) : (0, vue.createCommentVNode)("", true)
5360
5445
  ])) : (0, vue.createCommentVNode)("", true),
5361
- refreshNote.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_16$4, [_cache[31] || (_cache[31] = (0, vue.createElementVNode)("span", { class: "material-icons text-base text-indigo-600" }, "hourglass_top", -1)), (0, vue.createElementVNode)("span", _hoisted_17$4, (0, vue.toDisplayString)(refreshNote.value), 1)])) : (0, vue.createCommentVNode)("", true),
5362
- collection.value && (!__props.hideSearch && items.value.length > 0 || !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_18$4, [!__props.hideSearch && items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_19$2, [
5363
- _cache[33] || (_cache[33] = (0, vue.createElementVNode)("span", { class: "absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400 pointer-events-none" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "search")], -1)),
5446
+ refreshNote.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_18$4, [_cache[33] || (_cache[33] = (0, vue.createElementVNode)("span", { class: "material-icons text-base text-indigo-600" }, "hourglass_top", -1)), (0, vue.createElementVNode)("span", _hoisted_19$3, (0, vue.toDisplayString)(refreshNote.value), 1)])) : (0, vue.createCommentVNode)("", true),
5447
+ collection.value && (!__props.hideSearch && items.value.length > 0 || !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_20$3, [!__props.hideSearch && items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_21$3, [
5448
+ _cache[35] || (_cache[35] = (0, vue.createElementVNode)("span", { class: "absolute inset-y-0 left-0 flex items-center pl-3 text-slate-400 pointer-events-none" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "search")], -1)),
5364
5449
  (0, vue.withDirectives)((0, vue.createElementVNode)("input", {
5365
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchQuery.value = $event),
5450
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => searchQuery.value = $event),
5366
5451
  type: "text",
5367
5452
  placeholder: (0, vue.unref)(t)("collectionsView.searchPlaceholder"),
5368
5453
  "aria-label": (0, vue.unref)(t)("collectionsView.searchPlaceholder"),
5369
5454
  class: "w-full bg-slate-50 border border-slate-200/80 rounded-xl pl-9 pr-8 py-1.5 text-xs placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:bg-white transition-all font-medium"
5370
- }, null, 8, _hoisted_20$2), [[vue.vModelText, searchQuery.value]]),
5455
+ }, null, 8, _hoisted_22$3), [[vue.vModelText, searchQuery.value]]),
5371
5456
  searchQuery.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5372
5457
  key: 0,
5373
5458
  type: "button",
5374
5459
  "aria-label": (0, vue.unref)(t)("collectionsView.clearSearch"),
5375
5460
  class: "absolute inset-y-0 right-0 flex items-center pr-2.5 text-slate-400 hover:text-slate-600",
5376
- onClick: _cache[1] || (_cache[1] = ($event) => searchQuery.value = "")
5377
- }, [..._cache[32] || (_cache[32] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_21$2)) : (0, vue.createCommentVNode)("", true)
5378
- ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_22$2, [
5461
+ onClick: _cache[2] || (_cache[2] = ($event) => searchQuery.value = "")
5462
+ }, [..._cache[34] || (_cache[34] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_23$2)) : (0, vue.createCommentVNode)("", true)
5463
+ ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_24$1, [
5379
5464
  !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5380
5465
  key: 0,
5381
5466
  class: "flex gap-0.5",
@@ -5387,24 +5472,24 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5387
5472
  class: (0, vue.normalizeClass)(["h-8 px-2.5 flex items-center gap-1 rounded text-xs font-bold transition-colors", activeView.value === "table" ? "bg-indigo-600 text-white" : "bg-white text-slate-500 border border-slate-200 hover:bg-slate-50"]),
5388
5473
  "aria-pressed": activeView.value === "table",
5389
5474
  "data-testid": "collection-view-toggle-table",
5390
- onClick: _cache[2] || (_cache[2] = ($event) => setView("table"))
5391
- }, [_cache[34] || (_cache[34] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "table_rows", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewTable")), 1)], 10, _hoisted_24$1),
5475
+ onClick: _cache[3] || (_cache[3] = ($event) => setView("table"))
5476
+ }, [_cache[36] || (_cache[36] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "table_rows", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewTable")), 1)], 10, _hoisted_26$1),
5392
5477
  hasCalendar.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5393
5478
  key: 0,
5394
5479
  type: "button",
5395
5480
  class: (0, vue.normalizeClass)(["h-8 px-2.5 flex items-center gap-1 rounded text-xs font-bold transition-colors", activeView.value === "calendar" ? "bg-indigo-600 text-white" : "bg-white text-slate-500 border border-slate-200 hover:bg-slate-50"]),
5396
5481
  "aria-pressed": activeView.value === "calendar",
5397
5482
  "data-testid": "collection-view-toggle-calendar",
5398
- onClick: _cache[3] || (_cache[3] = ($event) => setView("calendar"))
5399
- }, [_cache[35] || (_cache[35] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "calendar_month", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewCalendar")), 1)], 10, _hoisted_25$1)) : (0, vue.createCommentVNode)("", true),
5483
+ onClick: _cache[4] || (_cache[4] = ($event) => setView("calendar"))
5484
+ }, [_cache[37] || (_cache[37] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "calendar_month", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewCalendar")), 1)], 10, _hoisted_27$1)) : (0, vue.createCommentVNode)("", true),
5400
5485
  hasKanban.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5401
5486
  key: 1,
5402
5487
  type: "button",
5403
5488
  class: (0, vue.normalizeClass)(["h-8 px-2.5 flex items-center gap-1 rounded text-xs font-bold transition-colors", activeView.value === "kanban" ? "bg-indigo-600 text-white" : "bg-white text-slate-500 border border-slate-200 hover:bg-slate-50"]),
5404
5489
  "aria-pressed": activeView.value === "kanban",
5405
5490
  "data-testid": "collection-view-toggle-kanban",
5406
- onClick: _cache[4] || (_cache[4] = ($event) => setView("kanban"))
5407
- }, [_cache[36] || (_cache[36] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "view_kanban", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewKanban")), 1)], 10, _hoisted_26$1)) : (0, vue.createCommentVNode)("", true),
5491
+ onClick: _cache[5] || (_cache[5] = ($event) => setView("kanban"))
5492
+ }, [_cache[38] || (_cache[38] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "view_kanban", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.viewKanban")), 1)], 10, _hoisted_28)) : (0, vue.createCommentVNode)("", true),
5408
5493
  ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(customViews.value, (cv) => {
5409
5494
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5410
5495
  key: cv.id,
@@ -5413,7 +5498,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5413
5498
  "aria-pressed": activeView.value === (0, vue.unref)(customViewKey)(cv.id),
5414
5499
  "data-testid": `collection-view-custom-${cv.id}`,
5415
5500
  onClick: ($event) => setCustomView(cv.id)
5416
- }, [(0, vue.createElementVNode)("span", _hoisted_28, (0, vue.toDisplayString)(cv.icon || (cv.target === "mobile" ? "smartphone" : "dashboard_customize")), 1), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(cv.label), 1)], 10, _hoisted_27$1);
5501
+ }, [(0, vue.createElementVNode)("span", _hoisted_30, (0, vue.toDisplayString)(cv.icon || (cv.target === "mobile" ? "smartphone" : "dashboard_customize")), 1), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(cv.label), 1)], 10, _hoisted_29);
5417
5502
  }), 128)),
5418
5503
  canAddCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5419
5504
  key: 2,
@@ -5428,17 +5513,17 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5428
5513
  "aria-expanded": addMenuOpen.value,
5429
5514
  "data-testid": "collection-view-add",
5430
5515
  onClick: onAddViewClick
5431
- }, [..._cache[37] || (_cache[37] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)])], 8, _hoisted_29), addMenuOpen.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_30, [(0, vue.createElementVNode)("button", {
5516
+ }, [..._cache[39] || (_cache[39] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)])], 8, _hoisted_31), addMenuOpen.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_32, [(0, vue.createElementVNode)("button", {
5432
5517
  type: "button",
5433
5518
  class: "w-full h-8 px-3 flex items-center gap-2 text-xs font-bold text-slate-600 hover:bg-slate-50",
5434
5519
  "data-testid": "collection-view-add-desktop",
5435
- onClick: _cache[5] || (_cache[5] = ($event) => addCustomView("desktop"))
5436
- }, [_cache[38] || (_cache[38] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "dashboard_customize", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addViewDesktop")), 1)]), (0, vue.createElementVNode)("button", {
5520
+ onClick: _cache[6] || (_cache[6] = ($event) => addCustomView("desktop"))
5521
+ }, [_cache[40] || (_cache[40] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "dashboard_customize", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addViewDesktop")), 1)]), (0, vue.createElementVNode)("button", {
5437
5522
  type: "button",
5438
5523
  class: "w-full h-8 px-3 flex items-center gap-2 text-xs font-bold text-slate-600 hover:bg-slate-50",
5439
5524
  "data-testid": "collection-view-add-mobile",
5440
- onClick: _cache[6] || (_cache[6] = ($event) => addCustomView("mobile"))
5441
- }, [_cache[39] || (_cache[39] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "smartphone", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addViewMobile")), 1)])])) : (0, vue.createCommentVNode)("", true)], 512)) : (0, vue.createCommentVNode)("", true),
5525
+ onClick: _cache[7] || (_cache[7] = ($event) => addCustomView("mobile"))
5526
+ }, [_cache[41] || (_cache[41] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "smartphone", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.addViewMobile")), 1)])])) : (0, vue.createCommentVNode)("", true)], 512)) : (0, vue.createCommentVNode)("", true),
5442
5527
  canConfigureViews.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5443
5528
  key: 3,
5444
5529
  type: "button",
@@ -5446,51 +5531,51 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5446
5531
  title: (0, vue.unref)(t)("collectionsView.config.open"),
5447
5532
  "aria-label": (0, vue.unref)(t)("collectionsView.config.open"),
5448
5533
  "data-testid": "collection-config-open",
5449
- onClick: _cache[7] || (_cache[7] = ($event) => configOpen.value = true)
5450
- }, [..._cache[40] || (_cache[40] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "settings", -1)])], 8, _hoisted_31)) : (0, vue.createCommentVNode)("", true)
5451
- ], 8, _hoisted_23$2)) : (0, vue.createCommentVNode)("", true),
5534
+ onClick: _cache[8] || (_cache[8] = ($event) => configOpen.value = true)
5535
+ }, [..._cache[42] || (_cache[42] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "settings", -1)])], 8, _hoisted_33)) : (0, vue.createCommentVNode)("", true)
5536
+ ], 8, _hoisted_25$1)) : (0, vue.createCommentVNode)("", true),
5452
5537
  calendarActive.value && dateFields.value.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5453
5538
  key: 1,
5454
5539
  value: calendarAnchorField.value,
5455
5540
  class: "h-8 px-2 rounded border border-slate-200 bg-white text-xs font-semibold text-slate-600 focus:outline-none focus:border-indigo-500 cursor-pointer",
5456
5541
  "aria-label": (0, vue.unref)(t)("collectionsView.calendarFieldLabel"),
5457
5542
  "data-testid": "collection-calendar-field",
5458
- onChange: _cache[8] || (_cache[8] = ($event) => anchorOverride.value = $event.target.value)
5543
+ onChange: _cache[9] || (_cache[9] = ($event) => anchorOverride.value = $event.target.value)
5459
5544
  }, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(dateFields.value, (key) => {
5460
5545
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
5461
5546
  key,
5462
5547
  value: key
5463
- }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_33);
5464
- }), 128))], 40, _hoisted_32)) : (0, vue.createCommentVNode)("", true),
5548
+ }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_35);
5549
+ }), 128))], 40, _hoisted_34)) : (0, vue.createCommentVNode)("", true),
5465
5550
  kanbanActive.value && enumFields.value.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5466
5551
  key: 2,
5467
5552
  value: kanbanGroupField.value,
5468
5553
  class: "h-8 px-2 rounded border border-slate-200 bg-white text-xs font-semibold text-slate-600 focus:outline-none focus:border-indigo-500 cursor-pointer",
5469
5554
  "aria-label": (0, vue.unref)(t)("collectionsView.kanbanFieldLabel"),
5470
5555
  "data-testid": "collection-kanban-field",
5471
- onChange: _cache[9] || (_cache[9] = ($event) => kanbanOverride.value = $event.target.value)
5556
+ onChange: _cache[10] || (_cache[10] = ($event) => kanbanOverride.value = $event.target.value)
5472
5557
  }, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(enumFields.value, (key) => {
5473
5558
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
5474
5559
  key,
5475
5560
  value: key
5476
- }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_35);
5477
- }), 128))], 40, _hoisted_34)) : (0, vue.createCommentVNode)("", true),
5478
- items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_36, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.searchSummary", {
5561
+ }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_37);
5562
+ }), 128))], 40, _hoisted_36)) : (0, vue.createCommentVNode)("", true),
5563
+ items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_38, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.searchSummary", {
5479
5564
  shown: filteredItems.value.length,
5480
5565
  total: items.value.length
5481
5566
  })), 1)) : (0, vue.createCommentVNode)("", true)
5482
5567
  ])])) : (0, vue.createCommentVNode)("", true),
5483
- collection.value && dataIssues.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_37, [
5484
- _cache[42] || (_cache[42] = (0, vue.createElementVNode)("span", { class: "material-icons text-amber-600" }, "warning", -1)),
5485
- (0, vue.createElementVNode)("span", _hoisted_38, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.dataIssuesDetected", { count: dataIssues.value.length })), 1),
5568
+ collection.value && dataIssues.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_39, [
5569
+ _cache[44] || (_cache[44] = (0, vue.createElementVNode)("span", { class: "material-icons text-amber-600" }, "warning", -1)),
5570
+ (0, vue.createElementVNode)("span", _hoisted_40, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.dataIssuesDetected", { count: dataIssues.value.length })), 1),
5486
5571
  (0, vue.createElementVNode)("button", {
5487
5572
  type: "button",
5488
5573
  class: "h-8 px-2.5 flex items-center gap-1 rounded border border-amber-300 bg-white hover:bg-amber-100 text-amber-700 font-bold text-xs transition-colors",
5489
5574
  "data-testid": "collections-repair",
5490
5575
  onClick: repairCollection
5491
- }, [_cache[41] || (_cache[41] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "build", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.repair")), 1)])
5576
+ }, [_cache[43] || (_cache[43] = (0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "build", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.repair")), 1)])
5492
5577
  ])) : (0, vue.createCommentVNode)("", true),
5493
- (0, vue.createElementVNode)("div", _hoisted_39, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_40, [_cache[43] || (_cache[43] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_41, [_cache[44] || (_cache[44] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(loadError.value === "not-found" ? (0, vue.unref)(t)("collectionsView.notFound") : `${(0, vue.unref)(t)("collectionsView.loadFailed")}: ${loadError.value}`), 1)])) : !collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_42)) : calendarActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_43, [(0, vue.createVNode)(CollectionCalendarView_default, {
5578
+ (0, vue.createElementVNode)("div", _hoisted_41, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_42, [_cache[45] || (_cache[45] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_43, [_cache[46] || (_cache[46] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(loadError.value === "not-found" ? (0, vue.unref)(t)("collectionsView.notFound") : `${(0, vue.unref)(t)("collectionsView.loadFailed")}: ${loadError.value}`), 1)])) : !collection.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_44)) : calendarActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_45, [(0, vue.createVNode)(CollectionCalendarView_default, {
5494
5579
  schema: collection.value.schema,
5495
5580
  items: filteredItems.value,
5496
5581
  "anchor-field": calendarAnchorField.value,
@@ -5526,7 +5611,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5526
5611
  }, {
5527
5612
  detail: (0, vue.withCtx)(() => [(0, vue.createVNode)(CollectionRecordPanel_default, {
5528
5613
  editing: editing.value,
5529
- "onUpdate:editing": _cache[10] || (_cache[10] = ($event) => editing.value = $event),
5614
+ "onUpdate:editing": _cache[11] || (_cache[11] = ($event) => editing.value = $event),
5530
5615
  collection: collection.value,
5531
5616
  viewing: viewing.value,
5532
5617
  saving: saving.value,
@@ -5539,13 +5624,14 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5539
5624
  "live-derived": liveDerived.value,
5540
5625
  "view-title": viewTitle.value,
5541
5626
  "is-singleton": isSingleton.value,
5627
+ readonly: isReadOnly.value,
5542
5628
  render: (0, vue.unref)(render),
5543
5629
  locale: (0, vue.unref)(locale),
5544
5630
  onSubmit: saveEditor,
5545
5631
  onCancel: cancelEditor,
5546
5632
  onEdit: editFromView,
5547
5633
  onClose: onDayClose,
5548
- onDelete: _cache[11] || (_cache[11] = ($event) => viewing.value && confirmDelete(viewing.value)),
5634
+ onDelete: _cache[12] || (_cache[12] = ($event) => viewing.value && confirmDelete(viewing.value)),
5549
5635
  onRunAction: runAction,
5550
5636
  onItemChat
5551
5637
  }, null, 8, [
@@ -5562,6 +5648,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5562
5648
  "live-derived",
5563
5649
  "view-title",
5564
5650
  "is-singleton",
5651
+ "readonly",
5565
5652
  "render",
5566
5653
  "locale"
5567
5654
  ])]),
@@ -5577,21 +5664,22 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5577
5664
  "selected",
5578
5665
  "can-create",
5579
5666
  "show-detail"
5580
- ])) : (0, vue.createCommentVNode)("", true)])) : kanbanActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_44, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_45, [
5581
- _cache[46] || (_cache[46] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
5582
- (0, vue.createElementVNode)("span", _hoisted_46, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5667
+ ])) : (0, vue.createCommentVNode)("", true)])) : kanbanActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_46, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_47, [
5668
+ _cache[48] || (_cache[48] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
5669
+ (0, vue.createElementVNode)("span", _hoisted_48, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5583
5670
  (0, vue.createElementVNode)("button", {
5584
5671
  type: "button",
5585
5672
  class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
5586
5673
  "aria-label": (0, vue.unref)(t)("common.close"),
5587
- onClick: _cache[12] || (_cache[12] = ($event) => inlineError.value = null)
5588
- }, [..._cache[45] || (_cache[45] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_47)
5589
- ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_48, [(0, vue.createVNode)(CollectionKanbanView_default, {
5674
+ onClick: _cache[13] || (_cache[13] = ($event) => inlineError.value = null)
5675
+ }, [..._cache[47] || (_cache[47] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_49)
5676
+ ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_50, [(0, vue.createVNode)(CollectionKanbanView_default, {
5590
5677
  schema: collection.value.schema,
5591
5678
  items: filteredItems.value,
5592
5679
  "group-field": kanbanGroupField.value,
5593
5680
  selected: viewing.value ? String(viewing.value[collection.value.schema.primaryKey] ?? "") : void 0,
5594
5681
  notified: notifiedSeverities.value,
5682
+ readonly: isReadOnly.value,
5595
5683
  onSelect: onCalendarSelect,
5596
5684
  onMove: onKanbanMove
5597
5685
  }, null, 8, [
@@ -5599,8 +5687,9 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5599
5687
  "items",
5600
5688
  "group-field",
5601
5689
  "selected",
5602
- "notified"
5603
- ])])])) : activeCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_49, [activeCustomView.value.target === "mobile" ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRemoteViewPreview_default, {
5690
+ "notified",
5691
+ "readonly"
5692
+ ])])])) : activeCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_51, [activeCustomView.value.target === "mobile" ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRemoteViewPreview_default, {
5604
5693
  key: 0,
5605
5694
  slug: collection.value.slug,
5606
5695
  view: activeCustomView.value,
@@ -5611,32 +5700,32 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5611
5700
  view: activeCustomView.value,
5612
5701
  onOpenItem: onCustomViewOpenItem,
5613
5702
  onStartChat: onCustomViewStartChat
5614
- }, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_50, [_cache[47] || (_cache[47] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), (0, vue.createElementVNode)("p", _hoisted_51, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.itemsEmpty")), 1)])) : filteredItems.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_52, [
5615
- _cache[48] || (_cache[48] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
5616
- (0, vue.createElementVNode)("p", _hoisted_53, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noMatchingItems")), 1),
5703
+ }, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_52, [_cache[49] || (_cache[49] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), (0, vue.createElementVNode)("p", _hoisted_53, (0, vue.toDisplayString)((0, vue.unref)(t)(isReadOnly.value ? "collectionsView.itemsEmptyReadonly" : "collectionsView.itemsEmpty")), 1)])) : filteredItems.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_54, [
5704
+ _cache[50] || (_cache[50] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
5705
+ (0, vue.createElementVNode)("p", _hoisted_55, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noMatchingItems")), 1),
5617
5706
  (0, vue.createElementVNode)("button", {
5618
5707
  type: "button",
5619
5708
  class: "text-xs text-indigo-600 font-semibold hover:underline",
5620
- onClick: _cache[13] || (_cache[13] = ($event) => searchQuery.value = "")
5709
+ onClick: _cache[14] || (_cache[14] = ($event) => searchQuery.value = "")
5621
5710
  }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.clearSearch")), 1)
5622
- ])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_54, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_55, [
5623
- _cache[50] || (_cache[50] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
5624
- (0, vue.createElementVNode)("span", _hoisted_56, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5711
+ ])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_56, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_57, [
5712
+ _cache[52] || (_cache[52] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
5713
+ (0, vue.createElementVNode)("span", _hoisted_58, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5625
5714
  (0, vue.createElementVNode)("button", {
5626
5715
  type: "button",
5627
5716
  class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
5628
5717
  "aria-label": (0, vue.unref)(t)("common.close"),
5629
- onClick: _cache[14] || (_cache[14] = ($event) => inlineError.value = null)
5630
- }, [..._cache[49] || (_cache[49] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_57)
5631
- ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("table", _hoisted_58, [(0, vue.createElementVNode)("thead", null, [(0, vue.createElementVNode)("tr", _hoisted_59, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(listColumnFields.value, ([key, field]) => {
5718
+ onClick: _cache[15] || (_cache[15] = ($event) => inlineError.value = null)
5719
+ }, [..._cache[51] || (_cache[51] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_59)
5720
+ ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("table", _hoisted_60, [(0, vue.createElementVNode)("thead", null, [(0, vue.createElementVNode)("tr", _hoisted_61, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(listColumnFields.value, ([key, field]) => {
5632
5721
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
5633
5722
  key,
5634
5723
  "aria-sort": (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? sortAriaValue(key) : void 0,
5635
5724
  class: "px-5 py-3 font-bold text-slate-500 text-left uppercase tracking-wider whitespace-nowrap"
5636
- }, [(0, vue.createElementVNode)("div", _hoisted_61, [(0, vue.createElementVNode)("span", {
5725
+ }, [(0, vue.createElementVNode)("div", _hoisted_63, [(0, vue.createElementVNode)("span", {
5637
5726
  class: "truncate max-w-[14rem]",
5638
5727
  title: field.label
5639
- }, (0, vue.toDisplayString)(field.label), 9, _hoisted_62), (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5728
+ }, (0, vue.toDisplayString)(field.label), 9, _hoisted_64), (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5640
5729
  key: 0,
5641
5730
  type: "button",
5642
5731
  class: (0, vue.normalizeClass)(["inline-flex items-center justify-center rounded p-0.5 -my-1 leading-none transition-colors", sortButtonClass(key)]),
@@ -5644,9 +5733,9 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5644
5733
  "aria-label": (0, vue.unref)(t)("collectionsView.sortBy", { field: field.label }),
5645
5734
  onClick: (0, vue.withModifiers)(($event) => cycleSort(key), ["stop"]),
5646
5735
  onPointerenter: ($event) => hoveredSortKey.value = key,
5647
- onPointerleave: _cache[15] || (_cache[15] = ($event) => hoveredSortKey.value = null)
5648
- }, [(0, vue.createElementVNode)("span", _hoisted_64, (0, vue.toDisplayString)(sortIconName(key)), 1)], 42, _hoisted_63)) : (0, vue.createCommentVNode)("", true)])], 8, _hoisted_60);
5649
- }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_65, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(sortedItems.value, (item) => {
5736
+ onPointerleave: _cache[16] || (_cache[16] = ($event) => hoveredSortKey.value = null)
5737
+ }, [(0, vue.createElementVNode)("span", _hoisted_66, (0, vue.toDisplayString)(sortIconName(key)), 1)], 42, _hoisted_65)) : (0, vue.createCommentVNode)("", true)])], 8, _hoisted_62);
5738
+ }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_67, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(sortedItems.value, (item) => {
5650
5739
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
5651
5740
  key: String(item[collection.value.schema.primaryKey] ?? ""),
5652
5741
  class: (0, vue.normalizeClass)(["hover:bg-slate-50/70 cursor-pointer transition-colors focus:outline-none focus:bg-indigo-50/30", isRowOpen(item) || isEditingRow(item) ? "bg-indigo-50/40" : ""]),
@@ -5664,23 +5753,23 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5664
5753
  key: 0,
5665
5754
  type: "checkbox",
5666
5755
  checked: toggleChecked(item, field),
5667
- disabled: isRowInlineSaving(item),
5756
+ disabled: isReadOnly.value || isRowInlineSaving(item),
5668
5757
  class: "h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500/20 cursor-pointer align-middle disabled:opacity-50 disabled:cursor-not-allowed",
5669
5758
  "data-testid": `collections-inline-toggle-${key}-${item[collection.value.schema.primaryKey]}`,
5670
5759
  "aria-label": field.label,
5671
- onClick: _cache[16] || (_cache[16] = (0, vue.withModifiers)(() => {}, ["stop"])),
5760
+ onClick: _cache[17] || (_cache[17] = (0, vue.withModifiers)(() => {}, ["stop"])),
5672
5761
  onChange: ($event) => commitToggle(item, field)
5673
- }, null, 40, _hoisted_67)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
5762
+ }, null, 40, _hoisted_69)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
5674
5763
  key: 1,
5675
5764
  type: "checkbox",
5676
5765
  checked: item[key] === true,
5677
- disabled: isRowInlineSaving(item),
5766
+ disabled: isReadOnly.value || isRowInlineSaving(item),
5678
5767
  class: "h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500/20 cursor-pointer align-middle disabled:opacity-50 disabled:cursor-not-allowed",
5679
5768
  "data-testid": `collections-inline-bool-${key}-${item[collection.value.schema.primaryKey]}`,
5680
5769
  "aria-label": field.label,
5681
- onClick: _cache[17] || (_cache[17] = (0, vue.withModifiers)(() => {}, ["stop"])),
5770
+ onClick: _cache[18] || (_cache[18] = (0, vue.withModifiers)(() => {}, ["stop"])),
5682
5771
  onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.checked)
5683
- }, null, 40, _hoisted_68)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_69, [(0, vue.createElementVNode)("a", {
5772
+ }, null, 40, _hoisted_70)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_71, [(0, vue.createElementVNode)("a", {
5684
5773
  href: (0, vue.unref)(cui).recordHref?.(field.to, String(item[key])),
5685
5774
  tabindex: (0, vue.unref)(cui).recordHref?.(field.to, String(item[key])) ? void 0 : 0,
5686
5775
  role: "link",
@@ -5688,48 +5777,48 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5688
5777
  "data-testid": `collections-ref-link-${key}-${item[key]}`,
5689
5778
  onClick: ($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true),
5690
5779
  onKeydown: [(0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true), ["enter"]), (0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true), ["space"])]
5691
- }, (0, vue.toDisplayString)((0, vue.unref)(refDisplay)(field.to, String(item[key]))), 41, _hoisted_70)])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5780
+ }, (0, vue.toDisplayString)((0, vue.unref)(refDisplay)(field.to, String(item[key]))), 41, _hoisted_72)])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5692
5781
  key: 3,
5693
5782
  value: item[key] == null ? "" : String(item[key]),
5694
- disabled: isRowInlineSaving(item),
5783
+ disabled: isReadOnly.value || isRowInlineSaving(item),
5695
5784
  class: (0, vue.normalizeClass)(["rounded-lg border px-2 py-0.5 text-[11px] font-semibold focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20 focus:outline-none cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed", enumControlClass(String(key), item[key])]),
5696
5785
  "data-testid": `collections-inline-enum-${key}-${item[collection.value.schema.primaryKey]}`,
5697
5786
  "aria-label": field.label,
5698
- onClick: _cache[18] || (_cache[18] = (0, vue.withModifiers)(() => {}, ["stop"])),
5787
+ onClick: _cache[19] || (_cache[19] = (0, vue.withModifiers)(() => {}, ["stop"])),
5699
5788
  onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.value)
5700
- }, [showEnumPlaceholder(item, String(key)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("option", _hoisted_72, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1)) : (0, vue.createCommentVNode)("", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.values, (value) => {
5789
+ }, [showEnumPlaceholder(item, String(key)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("option", _hoisted_74, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.selectPlaceholder")), 1)) : (0, vue.createCommentVNode)("", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.values, (value) => {
5701
5790
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
5702
5791
  key: value,
5703
5792
  value
5704
- }, (0, vue.toDisplayString)(value), 9, _hoisted_73);
5705
- }), 128))], 42, _hoisted_71)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_74, (0, vue.toDisplayString)((0, vue.unref)(formatMoney)(item[key], (0, vue.unref)(resolveCurrency)(field, item), (0, vue.unref)(locale))), 1)) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_75, [_cache[51] || (_cache[51] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "list", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(tableSummary(item[key])), 1)])) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_76, (0, vue.toDisplayString)((0, vue.unref)(derivedDisplay)(field, (0, vue.unref)(evaluateDerivedAgainstItem)(field, String(key), item), item)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
5793
+ }, (0, vue.toDisplayString)(value), 9, _hoisted_75);
5794
+ }), 128))], 42, _hoisted_73)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_76, (0, vue.toDisplayString)((0, vue.unref)(formatMoney)(item[key], (0, vue.unref)(resolveCurrency)(field, item), (0, vue.unref)(locale))), 1)) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_77, [_cache[53] || (_cache[53] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "list", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)(tableSummary(item[key])), 1)])) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_78, (0, vue.toDisplayString)((0, vue.unref)(derivedDisplay)(field, (0, vue.unref)(evaluateDerivedAgainstItem)(field, String(key), item), item)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
5706
5795
  key: 7,
5707
5796
  class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-1.5 py-0.5 rounded border border-indigo-100/50",
5708
5797
  "data-testid": `collections-rollup-${key}-${item[collection.value.schema.primaryKey]}`
5709
- }, (0, vue.toDisplayString)((0, vue.unref)(render).rollupDisplay(field, item)), 9, _hoisted_77)) : field.type !== "file" && (0, vue.unref)(isExternalUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5798
+ }, (0, vue.toDisplayString)((0, vue.unref)(render).rollupDisplay(field, item)), 9, _hoisted_79)) : field.type !== "file" && (0, vue.unref)(isExternalUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5710
5799
  key: 8,
5711
5800
  href: String(item[key]),
5712
5801
  target: "_blank",
5713
5802
  rel: "noopener noreferrer",
5714
5803
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5715
5804
  "data-testid": `collections-url-link-${key}-${item[collection.value.schema.primaryKey]}`,
5716
- onClick: _cache[19] || (_cache[19] = (0, vue.withModifiers)(() => {}, ["stop"]))
5717
- }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_78)) : field.type === "file" && (0, vue.unref)(artifactUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5805
+ onClick: _cache[20] || (_cache[20] = (0, vue.withModifiers)(() => {}, ["stop"]))
5806
+ }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_80)) : field.type === "file" && (0, vue.unref)(artifactUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5718
5807
  key: 9,
5719
5808
  href: (0, vue.unref)(artifactUrl)(item[key]) ?? void 0,
5720
5809
  target: "_blank",
5721
5810
  rel: "noopener noreferrer",
5722
5811
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5723
5812
  "data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
5724
- onClick: _cache[20] || (_cache[20] = (0, vue.withModifiers)(() => {}, ["stop"]))
5725
- }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_79)) : field.type === "file" && (0, vue.unref)(fileRoutePath)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5813
+ onClick: _cache[21] || (_cache[21] = (0, vue.withModifiers)(() => {}, ["stop"]))
5814
+ }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_81)) : field.type === "file" && (0, vue.unref)(fileRoutePath)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
5726
5815
  key: 10,
5727
5816
  href: (0, vue.unref)(fileRoutePath)(item[key]) ?? void 0,
5728
5817
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5729
5818
  "data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
5730
5819
  onClick: ($event) => (0, vue.unref)(activatePathLink)($event, (0, vue.unref)(fileRoutePath)(item[key]) ?? "", true)
5731
- }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_80)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_81, (0, vue.toDisplayString)((0, vue.unref)(formatCell)(item[key], field.type)), 1))], 64)) : (0, vue.createCommentVNode)("", true)]);
5732
- }), 128))], 42, _hoisted_66);
5820
+ }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_82)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_83, (0, vue.toDisplayString)((0, vue.unref)(formatCell)(item[key], field.type)), 1))], 64)) : (0, vue.createCommentVNode)("", true)]);
5821
+ }), 128))], 42, _hoisted_68);
5733
5822
  }), 128))])])]))]),
5734
5823
  collection.value && (viewing.value || editing.value) && !(calendarActive.value && openDay.value) ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRecordModal_default, {
5735
5824
  key: 4,
@@ -5737,7 +5826,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5737
5826
  }, {
5738
5827
  default: (0, vue.withCtx)(() => [(0, vue.createVNode)(CollectionRecordPanel_default, {
5739
5828
  editing: editing.value,
5740
- "onUpdate:editing": _cache[21] || (_cache[21] = ($event) => editing.value = $event),
5829
+ "onUpdate:editing": _cache[22] || (_cache[22] = ($event) => editing.value = $event),
5741
5830
  collection: collection.value,
5742
5831
  viewing: viewing.value,
5743
5832
  saving: saving.value,
@@ -5750,13 +5839,14 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5750
5839
  "live-derived": liveDerived.value,
5751
5840
  "view-title": viewTitle.value,
5752
5841
  "is-singleton": isSingleton.value,
5842
+ readonly: isReadOnly.value,
5753
5843
  render: (0, vue.unref)(render),
5754
5844
  locale: (0, vue.unref)(locale),
5755
5845
  onSubmit: saveEditor,
5756
5846
  onCancel: cancelEditor,
5757
5847
  onEdit: editFromView,
5758
5848
  onClose: closeView,
5759
- onDelete: _cache[22] || (_cache[22] = ($event) => viewing.value && confirmDelete(viewing.value)),
5849
+ onDelete: _cache[23] || (_cache[23] = ($event) => viewing.value && confirmDelete(viewing.value)),
5760
5850
  onRunAction: runAction,
5761
5851
  onItemChat
5762
5852
  }, null, 8, [
@@ -5773,6 +5863,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5773
5863
  "live-derived",
5774
5864
  "view-title",
5775
5865
  "is-singleton",
5866
+ "readonly",
5776
5867
  "render",
5777
5868
  "locale"
5778
5869
  ])]),
@@ -5783,7 +5874,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5783
5874
  action: mutateModal.value.action,
5784
5875
  pending: mutatePending.value,
5785
5876
  error: mutateError.value,
5786
- onClose: _cache[23] || (_cache[23] = ($event) => mutateModal.value = null),
5877
+ onClose: _cache[24] || (_cache[24] = ($event) => mutateModal.value = null),
5787
5878
  onSubmit: submitMutateParams
5788
5879
  }, null, 8, [
5789
5880
  "action",
@@ -5796,7 +5887,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5796
5887
  title: collection.value.title,
5797
5888
  views: customViews.value,
5798
5889
  onChanged: onViewsChanged,
5799
- onClose: _cache[24] || (_cache[24] = ($event) => configOpen.value = false)
5890
+ onClose: _cache[25] || (_cache[25] = ($event) => configOpen.value = false)
5800
5891
  }, null, 8, [
5801
5892
  "slug",
5802
5893
  "title",
@@ -5811,29 +5902,29 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5811
5902
  "data-testid": "collections-chat-modal",
5812
5903
  onClick: (0, vue.withModifiers)(closeChat, ["self"]),
5813
5904
  onKeydown: (0, vue.withKeys)(closeChat, ["esc"])
5814
- }, [(0, vue.createElementVNode)("div", _hoisted_82, [
5815
- (0, vue.createElementVNode)("header", _hoisted_83, [
5816
- _cache[53] || (_cache[53] = (0, vue.createElementVNode)("div", { class: "h-9 w-9 flex items-center justify-center rounded-xl bg-indigo-50 text-indigo-600 border border-indigo-100/50" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "forum")], -1)),
5817
- (0, vue.createElementVNode)("div", _hoisted_84, [(0, vue.createElementVNode)("h2", _hoisted_85, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatTitle")), 1), (0, vue.createElementVNode)("span", _hoisted_86, (0, vue.toDisplayString)(collection.value.title), 1)]),
5905
+ }, [(0, vue.createElementVNode)("div", _hoisted_84, [
5906
+ (0, vue.createElementVNode)("header", _hoisted_85, [
5907
+ _cache[55] || (_cache[55] = (0, vue.createElementVNode)("div", { class: "h-9 w-9 flex items-center justify-center rounded-xl bg-indigo-50 text-indigo-600 border border-indigo-100/50" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "forum")], -1)),
5908
+ (0, vue.createElementVNode)("div", _hoisted_86, [(0, vue.createElementVNode)("h2", _hoisted_87, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatTitle")), 1), (0, vue.createElementVNode)("span", _hoisted_88, (0, vue.toDisplayString)(collection.value.title), 1)]),
5818
5909
  (0, vue.createElementVNode)("button", {
5819
5910
  type: "button",
5820
5911
  class: "h-8 w-8 flex items-center justify-center rounded text-slate-400 hover:bg-slate-200/50 hover:text-slate-600 transition-colors",
5821
5912
  "aria-label": (0, vue.unref)(t)("common.close"),
5822
5913
  "data-testid": "collections-chat-close",
5823
5914
  onClick: closeChat
5824
- }, [..._cache[52] || (_cache[52] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_87)
5915
+ }, [..._cache[54] || (_cache[54] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_89)
5825
5916
  ]),
5826
- (0, vue.createElementVNode)("div", _hoisted_88, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
5917
+ (0, vue.createElementVNode)("div", _hoisted_90, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
5827
5918
  ref_key: "chatInputEl",
5828
5919
  ref: chatInputEl,
5829
- "onUpdate:modelValue": _cache[25] || (_cache[25] = ($event) => chatMessage.value = $event),
5920
+ "onUpdate:modelValue": _cache[26] || (_cache[26] = ($event) => chatMessage.value = $event),
5830
5921
  rows: "4",
5831
5922
  placeholder: (0, vue.unref)(t)("collectionsView.chatPlaceholder"),
5832
5923
  class: "w-full bg-slate-50 border border-slate-200/80 rounded-xl px-3 py-2.5 text-sm placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500 focus:bg-white transition-all resize-none",
5833
5924
  "data-testid": "collections-chat-input",
5834
5925
  onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)(submitChat, ["meta"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)(submitChat, ["ctrl"]), ["enter"])]
5835
- }, null, 40, _hoisted_89), [[vue.vModelText, chatMessage.value]])]),
5836
- (0, vue.createElementVNode)("footer", _hoisted_90, [(0, vue.createElementVNode)("button", {
5926
+ }, null, 40, _hoisted_91), [[vue.vModelText, chatMessage.value]])]),
5927
+ (0, vue.createElementVNode)("footer", _hoisted_92, [(0, vue.createElementVNode)("button", {
5837
5928
  type: "button",
5838
5929
  class: "h-8 px-2.5 rounded text-xs font-bold text-slate-500 hover:bg-slate-200/50 transition-colors",
5839
5930
  "data-testid": "collections-chat-cancel",
@@ -5844,7 +5935,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5844
5935
  disabled: !chatMessage.value.trim(),
5845
5936
  "data-testid": "collections-chat-send",
5846
5937
  onClick: submitChat
5847
- }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatStart")), 9, _hoisted_91)])
5938
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatStart")), 9, _hoisted_93)])
5848
5939
  ])], 32)) : (0, vue.createCommentVNode)("", true)
5849
5940
  ]);
5850
5941
  };
@@ -5996,10 +6087,10 @@ var _hoisted_18$3 = {
5996
6087
  key: 0,
5997
6088
  class: "text-teal-600"
5998
6089
  };
5999
- var _hoisted_19$1 = { key: 1 };
6000
- var _hoisted_20$1 = { class: "flex items-center justify-between pt-1 border-t border-slate-100" };
6001
- var _hoisted_21$1 = { class: "text-[10px] text-slate-400 font-mono" };
6002
- var _hoisted_22$1 = { class: "flex items-center gap-2" };
6090
+ var _hoisted_19$2 = { key: 1 };
6091
+ var _hoisted_20$2 = { class: "flex items-center justify-between pt-1 border-t border-slate-100" };
6092
+ var _hoisted_21$2 = { class: "text-[10px] text-slate-400 font-mono" };
6093
+ var _hoisted_22$2 = { class: "flex items-center gap-2" };
6003
6094
  var _hoisted_23$1 = ["data-testid"];
6004
6095
  var _hoisted_24 = ["data-testid", "onClick"];
6005
6096
  var _hoisted_25 = [
@@ -6100,9 +6191,9 @@ var DiscoverPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
6100
6191
  (0, vue.createElementVNode)("div", _hoisted_17$3, [
6101
6192
  (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.fields", { count: entry.fieldCount })), 1),
6102
6193
  entry.views.length ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_18$3, "· " + (0, vue.toDisplayString)(entry.views.join(" · ")), 1)) : (0, vue.createCommentVNode)("", true),
6103
- entry.hasSeed ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_19$1, "· " + (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.samples", { count: entry.seedCount })), 1)) : (0, vue.createCommentVNode)("", true)
6194
+ entry.hasSeed ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_19$2, "· " + (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.discover.samples", { count: entry.seedCount })), 1)) : (0, vue.createCommentVNode)("", true)
6104
6195
  ]),
6105
- (0, vue.createElementVNode)("div", _hoisted_20$1, [(0, vue.createElementVNode)("span", _hoisted_21$1, "v" + (0, vue.toDisplayString)(entry.version), 1), (0, vue.createElementVNode)("div", _hoisted_22$1, [stateOf(entry).status === "error" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
6196
+ (0, vue.createElementVNode)("div", _hoisted_20$2, [(0, vue.createElementVNode)("span", _hoisted_21$2, "v" + (0, vue.toDisplayString)(entry.version), 1), (0, vue.createElementVNode)("div", _hoisted_22$2, [stateOf(entry).status === "error" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
6106
6197
  key: 0,
6107
6198
  class: "text-[11px] text-red-600",
6108
6199
  "data-testid": `discover-error-${entry.slug}`
@@ -6353,22 +6444,27 @@ var _hoisted_9$1 = {
6353
6444
  class: "rounded-xl border border-slate-200 bg-white px-6 py-12 text-center text-sm text-slate-500 shadow-sm"
6354
6445
  };
6355
6446
  var _hoisted_10$1 = { class: "font-medium text-slate-700" };
6356
- var _hoisted_11$1 = {
6357
- key: 3,
6358
- class: "grid gap-4 sm:grid-cols-2"
6447
+ var _hoisted_11$1 = { key: 3 };
6448
+ var _hoisted_12$1 = {
6449
+ key: 0,
6450
+ class: "flex items-center gap-1.5 mb-4",
6451
+ "data-testid": "collections-filter-chips"
6359
6452
  };
6360
- var _hoisted_12$1 = [
6453
+ var _hoisted_13$1 = ["data-testid", "onClick"];
6454
+ var _hoisted_14$1 = { class: "grid gap-4 sm:grid-cols-2" };
6455
+ var _hoisted_15$1 = [
6361
6456
  "aria-label",
6362
6457
  "data-testid",
6363
6458
  "onClick",
6364
6459
  "onKeydown"
6365
6460
  ];
6366
- var _hoisted_13$1 = { class: "material-symbols-outlined text-2xl" };
6367
- var _hoisted_14$1 = { class: "flex-1 min-w-0" };
6368
- var _hoisted_15$1 = { class: "block font-semibold text-slate-800 text-[15px] group-hover:text-indigo-950 transition-colors truncate" };
6369
- var _hoisted_16$1 = { class: "block text-[10px] text-slate-400 mt-1 tracking-wider font-semibold uppercase flex items-center gap-1.5" };
6370
- var _hoisted_17$1 = { class: "text-[10px] bg-slate-100 px-1 rounded lowercase text-slate-500 font-mono font-normal" };
6371
- var _hoisted_18$1 = [
6461
+ var _hoisted_16$1 = { class: "material-symbols-outlined text-2xl" };
6462
+ var _hoisted_17$1 = { class: "flex-1 min-w-0" };
6463
+ var _hoisted_18$1 = { class: "block font-semibold text-slate-800 text-[15px] group-hover:text-indigo-950 transition-colors truncate" };
6464
+ var _hoisted_19$1 = { class: "block text-[10px] text-slate-400 mt-1 tracking-wider font-semibold uppercase flex items-center gap-1.5" };
6465
+ var _hoisted_20$1 = { class: "text-[10px] bg-slate-100 px-1 rounded lowercase text-slate-500 font-mono font-normal" };
6466
+ var _hoisted_21$1 = ["data-testid"];
6467
+ var _hoisted_22$1 = [
6372
6468
  "title",
6373
6469
  "aria-label",
6374
6470
  "data-testid",
@@ -6387,6 +6483,18 @@ var CollectionsIndexView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6387
6483
  const collections = (0, vue.ref)([]);
6388
6484
  const loading = (0, vue.ref)(true);
6389
6485
  const loadError = (0, vue.ref)(null);
6486
+ const FILTER_CHIPS = [
6487
+ "all",
6488
+ "editable",
6489
+ "data"
6490
+ ];
6491
+ const filter = (0, vue.ref)("all");
6492
+ const hasReadonlyCollections = (0, vue.computed)(() => collections.value.some((collection) => collection.readonly === true));
6493
+ const filteredCollections = (0, vue.computed)(() => {
6494
+ if (filter.value === "editable") return collections.value.filter((collection) => collection.readonly !== true);
6495
+ if (filter.value === "data") return collections.value.filter((collection) => collection.readonly === true);
6496
+ return collections.value;
6497
+ });
6390
6498
  async function loadCollections() {
6391
6499
  loading.value = true;
6392
6500
  loadError.value = null;
@@ -6449,7 +6557,15 @@ var CollectionsIndexView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6449
6557
  tab.value === "discover" ? ((0, vue.openBlock)(), (0, vue.createBlock)(DiscoverPanel_default, {
6450
6558
  key: 1,
6451
6559
  onImported: loadCollections
6452
- })) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_7$1, [_cache[5] || (_cache[5] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_8$1, [_cache[6] || (_cache[6] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.loadFailed")) + ": " + (0, vue.toDisplayString)(loadError.value), 1)])) : collections.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_9$1, [_cache[7] || (_cache[7] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300 mb-2" }, "dashboard_customize", -1)), (0, vue.createElementVNode)("p", _hoisted_10$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.indexEmpty")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_11$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(collections.value, (collection) => {
6560
+ })) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_7$1, [_cache[5] || (_cache[5] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 border-2 border-indigo-600/20 border-t-indigo-600 rounded-full animate-spin" }, null, -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("common.loading")), 1)])) : loadError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_8$1, [_cache[6] || (_cache[6] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)), (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.loadFailed")) + ": " + (0, vue.toDisplayString)(loadError.value), 1)])) : collections.value.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_9$1, [_cache[7] || (_cache[7] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300 mb-2" }, "dashboard_customize", -1)), (0, vue.createElementVNode)("p", _hoisted_10$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.indexEmpty")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_11$1, [hasReadonlyCollections.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_12$1, [((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(FILTER_CHIPS, (chip) => {
6561
+ return (0, vue.createElementVNode)("button", {
6562
+ key: chip,
6563
+ type: "button",
6564
+ class: (0, vue.normalizeClass)(["px-3 h-7 rounded-full text-xs font-semibold border transition-colors", filter.value === chip ? "bg-indigo-600 border-indigo-600 text-white" : "bg-white border-slate-200 text-slate-500 hover:text-slate-700 hover:bg-slate-50"]),
6565
+ "data-testid": `collections-filter-${chip}`,
6566
+ onClick: ($event) => filter.value = chip
6567
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)(`collectionsView.filter.${chip}`)), 11, _hoisted_13$1);
6568
+ }), 64))])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_14$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(filteredCollections.value, (collection) => {
6453
6569
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
6454
6570
  key: collection.slug,
6455
6571
  class: "group relative rounded-xl border border-slate-200 bg-white p-5 shadow-sm hover:shadow-md hover:border-indigo-300 transition-all duration-300 cursor-pointer flex items-center gap-4 focus:outline-none focus:ring-2 focus:ring-indigo-500/20",
@@ -6461,11 +6577,16 @@ var CollectionsIndexView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6461
6577
  onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)(($event) => openCollection(collection.slug), ["self"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)(($event) => openCollection(collection.slug), ["self", "prevent"]), ["space"])]
6462
6578
  }, [
6463
6579
  (0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)(["absolute left-0 top-0 bottom-0 w-1 rounded-l-xl transition-all duration-300 group-hover:w-1.5", collection.source === "project" ? "bg-indigo-600" : "bg-violet-600"]) }, null, 2),
6464
- (0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)(["h-12 w-12 flex items-center justify-center rounded-xl transition-all duration-300 group-hover:scale-105 shadow-sm", collection.source === "project" ? "bg-indigo-50 text-indigo-600 group-hover:bg-indigo-100/80 border border-indigo-100/50" : "bg-violet-50 text-violet-600 group-hover:bg-violet-100/80 border border-violet-100/50"]) }, [(0, vue.createElementVNode)("span", _hoisted_13$1, (0, vue.toDisplayString)(collection.icon), 1)], 2),
6465
- (0, vue.createElementVNode)("div", _hoisted_14$1, [(0, vue.createElementVNode)("span", _hoisted_15$1, (0, vue.toDisplayString)(collection.title), 1), (0, vue.createElementVNode)("span", _hoisted_16$1, [
6580
+ (0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)(["h-12 w-12 flex items-center justify-center rounded-xl transition-all duration-300 group-hover:scale-105 shadow-sm", collection.source === "project" ? "bg-indigo-50 text-indigo-600 group-hover:bg-indigo-100/80 border border-indigo-100/50" : "bg-violet-50 text-violet-600 group-hover:bg-violet-100/80 border border-violet-100/50"]) }, [(0, vue.createElementVNode)("span", _hoisted_16$1, (0, vue.toDisplayString)(collection.icon), 1)], 2),
6581
+ (0, vue.createElementVNode)("div", _hoisted_17$1, [(0, vue.createElementVNode)("span", _hoisted_18$1, (0, vue.toDisplayString)(collection.title), 1), (0, vue.createElementVNode)("span", _hoisted_19$1, [
6466
6582
  (0, vue.createElementVNode)("span", { class: (0, vue.normalizeClass)(["h-1.5 w-1.5 rounded-full", collection.source === "project" ? "bg-indigo-500" : "bg-violet-500"]) }, null, 2),
6467
6583
  (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)(`collectionsView.source.${collection.source}`)) + " · ", 1),
6468
- (0, vue.createElementVNode)("code", _hoisted_17$1, (0, vue.toDisplayString)(collection.slug), 1)
6584
+ (0, vue.createElementVNode)("code", _hoisted_20$1, (0, vue.toDisplayString)(collection.slug), 1),
6585
+ collection.readonly ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
6586
+ key: 0,
6587
+ class: "inline-flex items-center gap-0.5 px-1.5 py-px rounded bg-amber-50 text-amber-700 border border-amber-200 normal-case tracking-normal",
6588
+ "data-testid": `collections-readonly-badge-${collection.slug}`
6589
+ }, [_cache[8] || (_cache[8] = (0, vue.createElementVNode)("span", { class: "material-icons text-[11px]" }, "lock", -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.readonlyChip")), 1)], 8, _hoisted_21$1)) : (0, vue.createCommentVNode)("", true)
6469
6590
  ])]),
6470
6591
  ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(pinToggle)), {
6471
6592
  kind: "collection",
@@ -6477,17 +6598,18 @@ var CollectionsIndexView_default = /* @__PURE__ */ (0, vue.defineComponent)({
6477
6598
  "title",
6478
6599
  "icon"
6479
6600
  ])),
6480
- (0, vue.createElementVNode)("button", {
6601
+ !collection.readonly ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
6602
+ key: 0,
6481
6603
  type: "button",
6482
6604
  class: "h-8 w-8 flex items-center justify-center rounded-lg bg-slate-50 text-slate-400 hover:bg-teal-50 hover:text-teal-600 transition-all duration-300",
6483
6605
  title: (0, vue.unref)(t)("collectionsView.contribute"),
6484
6606
  "aria-label": (0, vue.unref)(t)("collectionsView.contribute"),
6485
6607
  "data-testid": `collections-contribute-${collection.slug}`,
6486
6608
  onClick: (0, vue.withModifiers)(($event) => startContributeChat(collection), ["stop"])
6487
- }, [..._cache[8] || (_cache[8] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "ios_share", -1)])], 8, _hoisted_18$1),
6488
- _cache[9] || (_cache[9] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 flex items-center justify-center rounded-lg bg-slate-50 group-hover:bg-indigo-50 text-slate-400 group-hover:text-indigo-600 transition-all duration-300" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg transition-transform duration-300 group-hover:translate-x-0.5" }, "chevron_right")], -1))
6489
- ], 40, _hoisted_12$1);
6490
- }), 128))]))], 64))
6609
+ }, [..._cache[9] || (_cache[9] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "ios_share", -1)])], 8, _hoisted_22$1)) : (0, vue.createCommentVNode)("", true),
6610
+ _cache[10] || (_cache[10] = (0, vue.createElementVNode)("div", { class: "h-8 w-8 flex items-center justify-center rounded-lg bg-slate-50 group-hover:bg-indigo-50 text-slate-400 group-hover:text-indigo-600 transition-all duration-300" }, [(0, vue.createElementVNode)("span", { class: "material-icons text-lg transition-transform duration-300 group-hover:translate-x-0.5" }, "chevron_right")], -1))
6611
+ ], 40, _hoisted_15$1);
6612
+ }), 128))])]))], 64))
6491
6613
  ])]);
6492
6614
  };
6493
6615
  }