@mulmoclaude/collection-plugin 0.12.0 → 0.13.1

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
@@ -114,6 +114,11 @@ var i18n = (0, vue_i18n.createI18n)({
114
114
  searchSummary: "Showing {shown} of {total}",
115
115
  noMatchingItems: "No matching items",
116
116
  clearSearch: "Clear search",
117
+ flagFilterButton: "Filters",
118
+ flagFilterAll: "Filter by {label}",
119
+ flagFilterHide: "Hiding {label}",
120
+ flagFilterOnly: "Only {label}",
121
+ flagDoneChip: "Done",
117
122
  sortBy: "Sort by {field}",
118
123
  openCollection: "Open {title}",
119
124
  createTitle: "Add new",
@@ -257,6 +262,11 @@ var i18n = (0, vue_i18n.createI18n)({
257
262
  searchSummary: "{total} 件中 {shown} 件を表示",
258
263
  noMatchingItems: "一致する項目がありません",
259
264
  clearSearch: "検索をクリア",
265
+ flagFilterButton: "絞り込み",
266
+ flagFilterAll: "{label} で絞り込む",
267
+ flagFilterHide: "{label} を非表示中",
268
+ flagFilterOnly: "{label} のみ表示中",
269
+ flagDoneChip: "完了",
260
270
  sortBy: "{field}で並べ替え",
261
271
  openCollection: "{title} を開く",
262
272
  createTitle: "新規追加",
@@ -400,6 +410,11 @@ var i18n = (0, vue_i18n.createI18n)({
400
410
  searchSummary: "显示 {total} 条中的 {shown} 条",
401
411
  noMatchingItems: "没有匹配的项目",
402
412
  clearSearch: "清除搜索",
413
+ flagFilterButton: "筛选",
414
+ flagFilterAll: "按{label}筛选",
415
+ flagFilterHide: "已隐藏{label}",
416
+ flagFilterOnly: "仅显示{label}",
417
+ flagDoneChip: "已完成",
403
418
  sortBy: "按{field}排序",
404
419
  openCollection: "打开 {title}",
405
420
  createTitle: "新增",
@@ -543,6 +558,11 @@ var i18n = (0, vue_i18n.createI18n)({
543
558
  searchSummary: "{total}개 중 {shown}개 표시",
544
559
  noMatchingItems: "일치하는 항목이 없습니다",
545
560
  clearSearch: "검색 지우기",
561
+ flagFilterButton: "필터",
562
+ flagFilterAll: "{label}(으)로 필터",
563
+ flagFilterHide: "{label} 숨김",
564
+ flagFilterOnly: "{label}만 표시",
565
+ flagDoneChip: "완료",
546
566
  sortBy: "{field} 기준 정렬",
547
567
  openCollection: "{title} 열기",
548
568
  createTitle: "새로 추가",
@@ -686,6 +706,11 @@ var i18n = (0, vue_i18n.createI18n)({
686
706
  searchSummary: "Mostrando {shown} de {total}",
687
707
  noMatchingItems: "No hay elementos coincidentes",
688
708
  clearSearch: "Borrar búsqueda",
709
+ flagFilterButton: "Filtros",
710
+ flagFilterAll: "Filtrar por {label}",
711
+ flagFilterHide: "Ocultando {label}",
712
+ flagFilterOnly: "Solo {label}",
713
+ flagDoneChip: "Hecho",
689
714
  sortBy: "Ordenar por {field}",
690
715
  openCollection: "Abrir {title}",
691
716
  createTitle: "Añadir nuevo",
@@ -829,6 +854,11 @@ var i18n = (0, vue_i18n.createI18n)({
829
854
  searchSummary: "Mostrando {shown} de {total}",
830
855
  noMatchingItems: "Nenhum item correspondente",
831
856
  clearSearch: "Limpar busca",
857
+ flagFilterButton: "Filtros",
858
+ flagFilterAll: "Filtrar por {label}",
859
+ flagFilterHide: "Ocultando {label}",
860
+ flagFilterOnly: "Somente {label}",
861
+ flagDoneChip: "Concluído",
832
862
  sortBy: "Ordenar por {field}",
833
863
  openCollection: "Abrir {title}",
834
864
  createTitle: "Adicionar novo",
@@ -972,6 +1002,11 @@ var i18n = (0, vue_i18n.createI18n)({
972
1002
  searchSummary: "Affichage de {shown} sur {total}",
973
1003
  noMatchingItems: "Aucun élément correspondant",
974
1004
  clearSearch: "Effacer la recherche",
1005
+ flagFilterButton: "Filtres",
1006
+ flagFilterAll: "Filtrer par {label}",
1007
+ flagFilterHide: "{label} masqué",
1008
+ flagFilterOnly: "Uniquement {label}",
1009
+ flagDoneChip: "Terminé",
975
1010
  sortBy: "Trier par {field}",
976
1011
  openCollection: "Ouvrir {title}",
977
1012
  createTitle: "Ajouter",
@@ -1115,6 +1150,11 @@ var i18n = (0, vue_i18n.createI18n)({
1115
1150
  searchSummary: "{shown} von {total} werden angezeigt",
1116
1151
  noMatchingItems: "Keine passenden Einträge",
1117
1152
  clearSearch: "Suche zurücksetzen",
1153
+ flagFilterButton: "Filter",
1154
+ flagFilterAll: "Nach {label} filtern",
1155
+ flagFilterHide: "{label} ausgeblendet",
1156
+ flagFilterOnly: "Nur {label}",
1157
+ flagDoneChip: "Erledigt",
1118
1158
  sortBy: "Nach {field} sortieren",
1119
1159
  openCollection: "{title} öffnen",
1120
1160
  createTitle: "Neu hinzufügen",
@@ -2595,77 +2635,79 @@ var _hoisted_57$1 = {
2595
2635
  key: 2,
2596
2636
  class: "text-slate-300"
2597
2637
  };
2598
- var _hoisted_58$1 = [
2638
+ var _hoisted_58$1 = ["data-testid"];
2639
+ var _hoisted_59$1 = ["data-testid"];
2640
+ var _hoisted_60$1 = [
2599
2641
  "href",
2600
2642
  "tabindex",
2601
2643
  "data-testid",
2602
2644
  "onClick",
2603
2645
  "onKeydown"
2604
2646
  ];
2605
- var _hoisted_59$1 = {
2606
- key: 3,
2647
+ var _hoisted_61$1 = {
2648
+ key: 4,
2607
2649
  class: "font-semibold text-slate-900 tabular-nums text-sm"
2608
2650
  };
2609
- var _hoisted_60$1 = {
2610
- key: 4,
2651
+ var _hoisted_62$1 = {
2652
+ key: 5,
2611
2653
  class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-2 py-0.5 rounded border border-indigo-100/50"
2612
2654
  };
2613
- var _hoisted_61$1 = ["data-testid"];
2614
- var _hoisted_62$1 = {
2615
- key: 6,
2655
+ var _hoisted_63$1 = ["data-testid"];
2656
+ var _hoisted_64$1 = {
2657
+ key: 7,
2616
2658
  class: "border border-slate-200/80 rounded-xl overflow-hidden shadow-sm mt-1"
2617
2659
  };
2618
- var _hoisted_63$1 = { class: "w-full text-[11px] text-slate-600 bg-white" };
2619
- var _hoisted_64$1 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
2620
- var _hoisted_65$1 = { class: "divide-y divide-slate-100" };
2621
- var _hoisted_66$1 = {
2660
+ var _hoisted_65$1 = { class: "w-full text-[11px] text-slate-600 bg-white" };
2661
+ var _hoisted_66$1 = { class: "bg-slate-50 border-b border-slate-200 text-slate-500 font-bold uppercase tracking-wider" };
2662
+ var _hoisted_67$1 = { class: "divide-y divide-slate-100" };
2663
+ var _hoisted_68$1 = {
2622
2664
  key: 0,
2623
2665
  class: "material-icons text-emerald-600 text-base"
2624
2666
  };
2625
- var _hoisted_67$1 = {
2667
+ var _hoisted_69$1 = {
2626
2668
  key: 1,
2627
2669
  class: "text-slate-300"
2628
2670
  };
2629
- var _hoisted_68$1 = {
2630
- key: 7,
2671
+ var _hoisted_70$1 = {
2672
+ key: 8,
2631
2673
  class: "text-slate-400 italic"
2632
2674
  };
2633
- var _hoisted_69$1 = {
2634
- key: 8,
2675
+ var _hoisted_71$1 = {
2676
+ key: 9,
2635
2677
  class: "bg-slate-50 rounded-xl p-4 border border-slate-200/60 text-slate-600 text-xs whitespace-pre-wrap leading-relaxed max-h-[30vh] overflow-y-auto"
2636
2678
  };
2637
- var _hoisted_70$1 = [
2679
+ var _hoisted_72$1 = [
2638
2680
  "src",
2639
2681
  "alt",
2640
2682
  "data-testid"
2641
2683
  ];
2642
- var _hoisted_71$1 = ["href", "data-testid"];
2643
- var _hoisted_72$1 = ["href", "data-testid"];
2644
- var _hoisted_73$1 = [
2684
+ var _hoisted_73$1 = ["href", "data-testid"];
2685
+ var _hoisted_74$1 = ["href", "data-testid"];
2686
+ var _hoisted_75$1 = [
2645
2687
  "href",
2646
2688
  "data-testid",
2647
2689
  "onClick"
2648
2690
  ];
2649
- var _hoisted_74$1 = {
2650
- key: 15,
2691
+ var _hoisted_76$1 = {
2692
+ key: 16,
2651
2693
  class: "text-slate-800 font-semibold"
2652
2694
  };
2653
- var _hoisted_75$1 = {
2695
+ var _hoisted_77$1 = {
2654
2696
  key: 0,
2655
2697
  class: "col-span-full text-xs font-semibold text-red-600 bg-red-50 border border-red-100 p-2.5 rounded-xl"
2656
2698
  };
2657
- var _hoisted_76$1 = {
2699
+ var _hoisted_78$1 = {
2658
2700
  key: 1,
2659
2701
  class: "mt-5 pt-4 border-t border-slate-200/60",
2660
2702
  "data-testid": "collections-detail-chat"
2661
2703
  };
2662
- var _hoisted_77$1 = {
2704
+ var _hoisted_79$1 = {
2663
2705
  class: "block text-[10px] font-bold text-slate-400 uppercase tracking-wider mb-1.5",
2664
2706
  for: "collections-detail-chat-input"
2665
2707
  };
2666
- var _hoisted_78$1 = { class: "flex items-end gap-2" };
2667
- var _hoisted_79$1 = ["placeholder", "onKeydown"];
2668
- var _hoisted_80$1 = ["disabled"];
2708
+ var _hoisted_80$1 = { class: "flex items-end gap-2" };
2709
+ var _hoisted_81$1 = ["placeholder", "onKeydown"];
2710
+ var _hoisted_82$1 = ["disabled"];
2669
2711
  //#endregion
2670
2712
  //#region src/vue/components/CollectionRecordPanel.vue
2671
2713
  var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
@@ -3027,8 +3069,16 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
3027
3069
  key: 3,
3028
3070
  class: "text-xs font-medium text-slate-700 break-words",
3029
3071
  "data-testid": `collections-detail-value-${key}`
3030
- }, [field.type === "toggle" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_53$1, [_cache[12] || (_cache[12] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_54$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1))], 64)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [detailRecord.value[key] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_55$1, [_cache[13] || (_cache[13] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : detailRecord.value[key] === false ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_56$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_57$1, "—"))], 64)) : field.type === "ref" && field.to && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3031
- key: 2,
3072
+ }, [field.type === "toggle" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [field.field !== void 0 && String(detailRecord.value[field.field] ?? "") === field.onValue ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_53$1, [_cache[12] || (_cache[12] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_54$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1))], 64)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [detailRecord.value[key] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_55$1, [_cache[13] || (_cache[13] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)])) : detailRecord.value[key] === false ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_56$1, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_57$1, "—"))], 64)) : field.type === "flag" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [__props.render.deriveRecord(detailRecord.value)[key] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3073
+ key: 0,
3074
+ class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-emerald-50 text-emerald-700 border border-emerald-200/40",
3075
+ "data-testid": `collections-detail-flag-${key}`
3076
+ }, [_cache[14] || (_cache[14] = (0, vue.createElementVNode)("span", { class: "h-1.5 w-1.5 rounded-full bg-emerald-500" }, null, -1)), (0, vue.createTextVNode)(" " + (0, vue.toDisplayString)((0, vue.unref)(t)("common.yes")), 1)], 8, _hoisted_58$1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3077
+ key: 1,
3078
+ class: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold bg-slate-50 text-slate-400 border border-slate-200/20",
3079
+ "data-testid": `collections-detail-flag-${key}`
3080
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)("common.no")), 9, _hoisted_59$1))], 64)) : field.type === "ref" && field.to && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3081
+ key: 3,
3032
3082
  href: (0, vue.unref)(cui).recordHref?.(field.to, String(detailRecord.value[key])),
3033
3083
  tabindex: (0, vue.unref)(cui).recordHref?.(field.to, String(detailRecord.value[key])) ? void 0 : 0,
3034
3084
  role: "link",
@@ -3036,16 +3086,16 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
3036
3086
  "data-testid": `collections-detail-ref-${key}`,
3037
3087
  onClick: ($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(detailRecord.value[key])),
3038
3088
  onKeydown: [(0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["enter"]), (0, vue.withKeys)(($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(detailRecord.value[key])), ["space"])]
3039
- }, (0, vue.toDisplayString)(__props.render.refDisplay(field.to, String(detailRecord.value[key]))), 41, _hoisted_58$1)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_59$1, (0, vue.toDisplayString)(__props.render.formatMoney(detailRecord.value[key], __props.render.resolveCurrency(field, detailRecord.value), __props.locale)), 1)) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_60$1, (0, vue.toDisplayString)(__props.render.derivedDisplay(field, __props.render.evaluateDerivedAgainstItem(field, String(key), detailRecord.value), detailRecord.value)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3040
- key: 5,
3089
+ }, (0, vue.toDisplayString)(__props.render.refDisplay(field.to, String(detailRecord.value[key]))), 41, _hoisted_60$1)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_61$1, (0, vue.toDisplayString)(__props.render.formatMoney(detailRecord.value[key], __props.render.resolveCurrency(field, detailRecord.value), __props.locale)), 1)) : field.type === "derived" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_62$1, (0, vue.toDisplayString)(__props.render.derivedDisplay(field, __props.render.evaluateDerivedAgainstItem(field, String(key), detailRecord.value), detailRecord.value)), 1)) : field.type === "rollup" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3090
+ key: 6,
3041
3091
  class: "inline-block truncate tabular-nums font-bold text-indigo-900 bg-indigo-50/50 px-2 py-0.5 rounded border border-indigo-100/50",
3042
3092
  "data-testid": `collections-detail-rollup-${key}`
3043
- }, (0, vue.toDisplayString)(__props.render.rollupDisplay(field, detailRecord.value)), 9, _hoisted_61$1)) : field.type === "table" && field.of && __props.render.hasTableRows(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_62$1, [(0, vue.createElementVNode)("table", _hoisted_63$1, [(0, vue.createElementVNode)("thead", _hoisted_64$1, [(0, vue.createElementVNode)("tr", null, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.of, (subField, subKey) => {
3093
+ }, (0, vue.toDisplayString)(__props.render.rollupDisplay(field, detailRecord.value)), 9, _hoisted_63$1)) : field.type === "table" && field.of && __props.render.hasTableRows(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_64$1, [(0, vue.createElementVNode)("table", _hoisted_65$1, [(0, vue.createElementVNode)("thead", _hoisted_66$1, [(0, vue.createElementVNode)("tr", null, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(field.of, (subField, subKey) => {
3044
3094
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
3045
3095
  key: subKey,
3046
3096
  class: "text-left px-4 py-2 font-bold"
3047
3097
  }, (0, vue.toDisplayString)(subField.label), 1);
3048
- }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_65$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.tableRows(detailRecord.value[key]), (row, rowIdx) => {
3098
+ }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_67$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(__props.render.tableRows(detailRecord.value[key]), (row, rowIdx) => {
3049
3099
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
3050
3100
  key: rowIdx,
3051
3101
  class: "hover:bg-slate-50/50"
@@ -3053,48 +3103,48 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
3053
3103
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("td", {
3054
3104
  key: subKey,
3055
3105
  class: "px-4 py-2 align-middle font-medium"
3056
- }, [subField.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [row[subKey] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_66$1, "check_circle")) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_67$1, "—"))], 64)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3106
+ }, [subField.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [row[subKey] === true ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_68$1, "check_circle")) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_69$1, "—"))], 64)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
3057
3107
  key: 1,
3058
3108
  class: (0, vue.normalizeClass)([subField.type === "money" ? "font-bold text-slate-800 tabular-nums" : ""])
3059
3109
  }, (0, vue.toDisplayString)(__props.render.formatSubCell(subField, row[subKey], detailRecord.value)), 3))]);
3060
3110
  }), 128))]);
3061
- }), 128))])])])) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_68$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noRows")), 1)) : field.type === "markdown" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_69$1, (0, vue.toDisplayString)(__props.render.detailText(detailRecord.value[key])), 1)) : field.type === "embed" && embedViews.value[key] ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionEmbedView_default, {
3062
- key: 9,
3111
+ }), 128))])])])) : field.type === "table" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_70$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noRows")), 1)) : field.type === "markdown" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_71$1, (0, vue.toDisplayString)(__props.render.detailText(detailRecord.value[key])), 1)) : field.type === "embed" && embedViews.value[key] ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionEmbedView_default, {
3112
+ key: 10,
3063
3113
  view: embedViews.value[key],
3064
3114
  "field-key": String(key)
3065
3115
  }, null, 8, ["view", "field-key"])) : field.type === "backlinks" && backlinksViews.value[key] ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionBacklinksView_default, {
3066
- key: 10,
3116
+ key: 11,
3067
3117
  view: backlinksViews.value[key],
3068
3118
  "field-key": String(key)
3069
3119
  }, null, 8, ["view", "field-key"])) : field.type === "image" && typeof detailRecord.value[key] === "string" && detailRecord.value[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("img", {
3070
- key: 11,
3120
+ key: 12,
3071
3121
  src: (0, vue.unref)(resolveImageSrc)(String(detailRecord.value[key])),
3072
3122
  alt: field.label,
3073
3123
  class: "max-h-64 max-w-full object-contain rounded-lg border border-slate-200 bg-slate-50",
3074
3124
  "data-testid": `collections-detail-image-${key}`
3075
- }, null, 8, _hoisted_70$1)) : field.type !== "file" && __props.render.isExternalUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3076
- key: 12,
3125
+ }, null, 8, _hoisted_72$1)) : field.type !== "file" && __props.render.isExternalUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3126
+ key: 13,
3077
3127
  href: String(detailRecord.value[key]),
3078
3128
  target: "_blank",
3079
3129
  rel: "noopener noreferrer",
3080
3130
  class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
3081
3131
  "data-testid": `collections-detail-url-${key}`
3082
- }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_71$1)) : field.type === "file" && __props.render.artifactUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3083
- key: 13,
3132
+ }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_73$1)) : field.type === "file" && __props.render.artifactUrl(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3133
+ key: 14,
3084
3134
  href: __props.render.artifactUrl(detailRecord.value[key]) ?? void 0,
3085
3135
  target: "_blank",
3086
3136
  rel: "noopener noreferrer",
3087
3137
  class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
3088
3138
  "data-testid": `collections-detail-file-${key}`
3089
- }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_72$1)) : field.type === "file" && __props.render.fileRoutePath(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3090
- key: 14,
3139
+ }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_74$1)) : field.type === "file" && __props.render.fileRoutePath(detailRecord.value[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
3140
+ key: 15,
3091
3141
  href: __props.render.fileRoutePath(detailRecord.value[key]) ?? void 0,
3092
3142
  class: "text-blue-600 hover:text-blue-800 font-semibold hover:underline break-all",
3093
3143
  "data-testid": `collections-detail-file-${key}`,
3094
3144
  onClick: ($event) => (0, vue.unref)(activatePathLink)($event, __props.render.fileRoutePath(detailRecord.value[key]) ?? "")
3095
- }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_73$1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_74$1, (0, vue.toDisplayString)(__props.render.formatCell(detailRecord.value[key], field.type)), 1))], 8, _hoisted_52$1))], 2)) : (0, vue.createCommentVNode)("", true)], 64);
3096
- }), 128)), editing.value && __props.saveError ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_75$1, (0, vue.toDisplayString)(__props.saveError), 1)) : (0, vue.createCommentVNode)("", true)]),
3097
- !editing.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_76$1, [(0, vue.createElementVNode)("label", _hoisted_77$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.itemChatLabel")), 1), (0, vue.createElementVNode)("div", _hoisted_78$1, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
3145
+ }, (0, vue.toDisplayString)(String(detailRecord.value[key])), 9, _hoisted_75$1)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_76$1, (0, vue.toDisplayString)(__props.render.formatCell(detailRecord.value[key], field.type)), 1))], 8, _hoisted_52$1))], 2)) : (0, vue.createCommentVNode)("", true)], 64);
3146
+ }), 128)), editing.value && __props.saveError ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_77$1, (0, vue.toDisplayString)(__props.saveError), 1)) : (0, vue.createCommentVNode)("", true)]),
3147
+ !editing.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_78$1, [(0, vue.createElementVNode)("label", _hoisted_79$1, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.itemChatLabel")), 1), (0, vue.createElementVNode)("div", _hoisted_80$1, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
3098
3148
  id: "collections-detail-chat-input",
3099
3149
  "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => chatMessage.value = $event),
3100
3150
  rows: "2",
@@ -3102,13 +3152,13 @@ var CollectionRecordPanel_default = /* @__PURE__ */ (0, vue.defineComponent)({
3102
3152
  class: "flex-1 bg-slate-50 border border-slate-200/80 rounded-xl px-3 py-2 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 resize-none",
3103
3153
  "data-testid": "collections-detail-chat-input",
3104
3154
  onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)(submitItemChat, ["meta"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)(submitItemChat, ["ctrl"]), ["enter"])]
3105
- }, null, 40, _hoisted_79$1), [[vue.vModelText, chatMessage.value]]), (0, vue.createElementVNode)("button", {
3155
+ }, null, 40, _hoisted_81$1), [[vue.vModelText, chatMessage.value]]), (0, vue.createElementVNode)("button", {
3106
3156
  type: "button",
3107
3157
  class: "h-8 px-2.5 rounded bg-indigo-600 text-white font-bold text-xs hover:bg-indigo-700 disabled:opacity-50 transition-all shadow-sm shadow-indigo-600/10 flex items-center gap-1 shrink-0",
3108
3158
  disabled: !chatMessage.value.trim(),
3109
3159
  "data-testid": "collections-detail-chat-send",
3110
3160
  onClick: submitItemChat
3111
- }, [_cache[14] || (_cache[14] = (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)], 8, _hoisted_80$1)])])) : (0, vue.createCommentVNode)("", true)
3161
+ }, [_cache[15] || (_cache[15] = (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)], 8, _hoisted_82$1)])])) : (0, vue.createCommentVNode)("", true)
3112
3162
  ]),
3113
3163
  _: 1
3114
3164
  }, 40, ["data-testid"]);
@@ -3903,6 +3953,38 @@ function writeCollectionSort(slug, sort) {
3903
3953
  localStorage.setItem(SORT_STORAGE_KEY, JSON.stringify(all));
3904
3954
  } catch {}
3905
3955
  }
3956
+ var FLAG_FILTER_STORAGE_KEY = "collection_flag_filters";
3957
+ function isFlagFilterState(value) {
3958
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
3959
+ return Object.values(value).every((mode) => mode === "hide" || mode === "only");
3960
+ }
3961
+ function readAllFlagFilters() {
3962
+ try {
3963
+ const raw = localStorage.getItem(FLAG_FILTER_STORAGE_KEY);
3964
+ if (!raw) return {};
3965
+ const parsed = JSON.parse(raw);
3966
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
3967
+ const out = {};
3968
+ for (const [slug, value] of Object.entries(parsed)) if (isFlagFilterState(value)) out[slug] = value;
3969
+ return out;
3970
+ } catch {
3971
+ return {};
3972
+ }
3973
+ }
3974
+ /** The slug's persisted chip states ({} when none). A key whose flag no
3975
+ * longer exists in the schema is harmless — the chip list is derived
3976
+ * from the live schema, so a stale entry just never renders/filters. */
3977
+ function readCollectionFlagFilters(slug) {
3978
+ return readAllFlagFilters()[slug] ?? {};
3979
+ }
3980
+ /** Persist the slug's chip states; an empty state clears the entry. */
3981
+ function writeCollectionFlagFilters(slug, filters) {
3982
+ try {
3983
+ const all = Object.fromEntries(Object.entries(readAllFlagFilters()).filter(([key]) => key !== slug));
3984
+ if (Object.keys(filters).length > 0) all[slug] = filters;
3985
+ localStorage.setItem(FLAG_FILTER_STORAGE_KEY, JSON.stringify(all));
3986
+ } catch {}
3987
+ }
3906
3988
  //#endregion
3907
3989
  //#region src/vue/components/CollectionView.vue?vue&type=script&setup=true&lang.ts
3908
3990
  var _hoisted_1$6 = { class: "h-full flex flex-col bg-slate-50/30" };
@@ -3961,186 +4043,201 @@ var _hoisted_21$3 = {
3961
4043
  var _hoisted_22$3 = ["placeholder", "aria-label"];
3962
4044
  var _hoisted_23$2 = ["aria-label"];
3963
4045
  var _hoisted_24$1 = { class: "flex items-center gap-2" };
3964
- var _hoisted_25$1 = ["aria-label"];
3965
- var _hoisted_26$1 = ["aria-pressed"];
3966
- var _hoisted_27$1 = ["aria-pressed"];
3967
- var _hoisted_28 = ["aria-pressed"];
3968
- var _hoisted_29 = [
4046
+ var _hoisted_25$1 = ["aria-label", "aria-expanded"];
4047
+ var _hoisted_26$1 = {
4048
+ key: 0,
4049
+ class: "min-w-4 h-4 px-1 flex items-center justify-center rounded-full bg-indigo-600 text-white text-[10px] font-bold"
4050
+ };
4051
+ var _hoisted_27$1 = ["aria-label"];
4052
+ var _hoisted_28 = [
4053
+ "title",
4054
+ "aria-label",
3969
4055
  "aria-pressed",
3970
4056
  "data-testid",
3971
4057
  "onClick"
3972
4058
  ];
3973
- var _hoisted_30 = { class: "material-icons text-sm" };
3974
- var _hoisted_31 = [
4059
+ var _hoisted_29 = { class: "flex-1 text-left" };
4060
+ var _hoisted_30 = ["aria-label"];
4061
+ var _hoisted_31 = ["aria-pressed"];
4062
+ var _hoisted_32 = ["aria-pressed"];
4063
+ var _hoisted_33 = ["aria-pressed"];
4064
+ var _hoisted_34 = [
4065
+ "aria-pressed",
4066
+ "data-testid",
4067
+ "onClick"
4068
+ ];
4069
+ var _hoisted_35 = { class: "material-icons text-sm" };
4070
+ var _hoisted_36 = [
3975
4071
  "title",
3976
4072
  "aria-label",
3977
4073
  "aria-expanded"
3978
4074
  ];
3979
- var _hoisted_32 = {
4075
+ var _hoisted_37 = {
3980
4076
  key: 0,
3981
4077
  class: "absolute left-0 top-full mt-1 z-20 min-w-max rounded border border-slate-200 bg-white shadow-lg py-1",
3982
4078
  "data-testid": "collection-view-add-menu"
3983
4079
  };
3984
- var _hoisted_33 = ["title", "aria-label"];
3985
- var _hoisted_34 = ["value", "aria-label"];
3986
- var _hoisted_35 = ["value"];
3987
- var _hoisted_36 = ["value", "aria-label"];
3988
- var _hoisted_37 = ["value"];
3989
- var _hoisted_38 = {
3990
- key: 3,
4080
+ var _hoisted_38 = ["title", "aria-label"];
4081
+ var _hoisted_39 = ["value", "aria-label"];
4082
+ var _hoisted_40 = ["value"];
4083
+ var _hoisted_41 = ["value", "aria-label"];
4084
+ var _hoisted_42 = ["value"];
4085
+ var _hoisted_43 = {
4086
+ key: 4,
3991
4087
  class: "text-[10px] text-slate-400 font-bold uppercase tracking-wider select-none"
3992
4088
  };
3993
- var _hoisted_39 = {
4089
+ var _hoisted_44 = {
3994
4090
  key: 3,
3995
4091
  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",
3996
4092
  "data-testid": "collections-data-issues"
3997
4093
  };
3998
- var _hoisted_40 = { class: "flex-1" };
3999
- var _hoisted_41 = { class: "flex-1 overflow-auto" };
4000
- var _hoisted_42 = {
4094
+ var _hoisted_45 = { class: "flex-1" };
4095
+ var _hoisted_46 = { class: "flex-1 overflow-auto" };
4096
+ var _hoisted_47 = {
4001
4097
  key: 0,
4002
4098
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-500 gap-3"
4003
4099
  };
4004
- var _hoisted_43 = {
4100
+ var _hoisted_48 = {
4005
4101
  key: 1,
4006
4102
  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"
4007
4103
  };
4008
- var _hoisted_44 = { key: 2 };
4009
- var _hoisted_45 = {
4104
+ var _hoisted_49 = { key: 2 };
4105
+ var _hoisted_50 = {
4010
4106
  key: 3,
4011
4107
  class: "p-4"
4012
4108
  };
4013
- var _hoisted_46 = {
4109
+ var _hoisted_51 = {
4014
4110
  key: 4,
4015
4111
  class: "h-full flex flex-col"
4016
4112
  };
4017
- var _hoisted_47 = {
4113
+ var _hoisted_52 = {
4018
4114
  key: 0,
4019
4115
  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",
4020
4116
  "data-testid": "collections-inline-error"
4021
4117
  };
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 = {
4118
+ var _hoisted_53 = { class: "flex-1" };
4119
+ var _hoisted_54 = ["aria-label"];
4120
+ var _hoisted_55 = { class: "flex-1 min-h-0 px-3 py-2" };
4121
+ var _hoisted_56 = {
4026
4122
  key: 5,
4027
4123
  class: "h-full",
4028
4124
  "data-testid": "collection-custom-view-body"
4029
4125
  };
4030
- var _hoisted_52 = {
4126
+ var _hoisted_57 = {
4031
4127
  key: 6,
4032
4128
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
4033
4129
  };
4034
- var _hoisted_53 = { class: "font-semibold text-slate-600" };
4035
- var _hoisted_54 = {
4130
+ var _hoisted_58 = { class: "font-semibold text-slate-600" };
4131
+ var _hoisted_59 = {
4036
4132
  key: 7,
4037
4133
  class: "flex flex-col items-center justify-center py-20 text-sm text-slate-400 gap-2"
4038
4134
  };
4039
- var _hoisted_55 = { class: "font-semibold text-slate-600" };
4040
- var _hoisted_56 = {
4135
+ var _hoisted_60 = { class: "font-semibold text-slate-600" };
4136
+ var _hoisted_61 = {
4041
4137
  key: 8,
4042
4138
  class: "overflow-x-auto [container-type:inline-size]"
4043
4139
  };
4044
- var _hoisted_57 = {
4140
+ var _hoisted_62 = {
4045
4141
  key: 0,
4046
4142
  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",
4047
4143
  "data-testid": "collections-inline-error"
4048
4144
  };
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 = [
4145
+ var _hoisted_63 = { class: "flex-1" };
4146
+ var _hoisted_64 = ["aria-label"];
4147
+ var _hoisted_65 = { class: "min-w-full text-xs" };
4148
+ var _hoisted_66 = { class: "bg-slate-50 border-b border-slate-200" };
4149
+ var _hoisted_67 = ["aria-sort"];
4150
+ var _hoisted_68 = { class: "flex items-center gap-1" };
4151
+ var _hoisted_69 = ["title"];
4152
+ var _hoisted_70 = [
4057
4153
  "data-testid",
4058
4154
  "aria-label",
4059
4155
  "onClick",
4060
4156
  "onPointerenter"
4061
4157
  ];
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 = [
4158
+ var _hoisted_71 = { class: "material-icons text-base align-middle" };
4159
+ var _hoisted_72 = { class: "divide-y divide-slate-100 bg-white" };
4160
+ var _hoisted_73 = [
4065
4161
  "aria-label",
4066
4162
  "data-testid",
4067
4163
  "onClick",
4068
4164
  "onKeydown"
4069
4165
  ];
4070
- var _hoisted_69 = [
4166
+ var _hoisted_74 = [
4071
4167
  "checked",
4072
4168
  "disabled",
4073
4169
  "data-testid",
4074
4170
  "aria-label",
4075
4171
  "onChange"
4076
4172
  ];
4077
- var _hoisted_70 = [
4173
+ var _hoisted_75 = [
4078
4174
  "checked",
4079
4175
  "disabled",
4080
4176
  "data-testid",
4081
4177
  "aria-label",
4082
4178
  "onChange"
4083
4179
  ];
4084
- var _hoisted_71 = {
4085
- key: 2,
4180
+ var _hoisted_76 = ["data-testid", "aria-label"];
4181
+ var _hoisted_77 = {
4182
+ key: 3,
4086
4183
  class: "block truncate"
4087
4184
  };
4088
- var _hoisted_72 = [
4185
+ var _hoisted_78 = [
4089
4186
  "href",
4090
4187
  "tabindex",
4091
4188
  "data-testid",
4092
4189
  "onClick",
4093
4190
  "onKeydown"
4094
4191
  ];
4095
- var _hoisted_73 = [
4192
+ var _hoisted_79 = [
4096
4193
  "value",
4097
4194
  "disabled",
4098
4195
  "data-testid",
4099
4196
  "aria-label",
4100
4197
  "onChange"
4101
4198
  ];
4102
- var _hoisted_74 = {
4199
+ var _hoisted_80 = {
4103
4200
  key: 0,
4104
4201
  value: ""
4105
4202
  };
4106
- var _hoisted_75 = ["value"];
4107
- var _hoisted_76 = {
4108
- key: 4,
4203
+ var _hoisted_81 = ["value"];
4204
+ var _hoisted_82 = {
4205
+ key: 5,
4109
4206
  class: "block truncate tabular-nums font-semibold text-slate-900"
4110
4207
  };
4111
- var _hoisted_77 = {
4112
- key: 5,
4208
+ var _hoisted_83 = {
4209
+ key: 6,
4113
4210
  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"
4114
4211
  };
4115
- var _hoisted_78 = {
4116
- key: 6,
4212
+ var _hoisted_84 = {
4213
+ key: 7,
4117
4214
  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"
4118
4215
  };
4119
- var _hoisted_79 = ["data-testid"];
4120
- var _hoisted_80 = ["href", "data-testid"];
4121
- var _hoisted_81 = ["href", "data-testid"];
4122
- var _hoisted_82 = [
4216
+ var _hoisted_85 = ["data-testid"];
4217
+ var _hoisted_86 = ["href", "data-testid"];
4218
+ var _hoisted_87 = ["href", "data-testid"];
4219
+ var _hoisted_88 = [
4123
4220
  "href",
4124
4221
  "data-testid",
4125
4222
  "onClick"
4126
4223
  ];
4127
- var _hoisted_83 = {
4128
- key: 11,
4224
+ var _hoisted_89 = {
4225
+ key: 12,
4129
4226
  class: "block truncate text-slate-600"
4130
4227
  };
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 = {
4228
+ var _hoisted_90 = { class: "bg-white rounded-2xl shadow-2xl w-full max-w-xl flex flex-col border border-slate-200 overflow-hidden" };
4229
+ var _hoisted_91 = { class: "px-6 py-4 border-b border-slate-100 flex items-center gap-3 bg-slate-50/50" };
4230
+ var _hoisted_92 = { class: "flex-1" };
4231
+ var _hoisted_93 = {
4135
4232
  id: "collections-chat-title",
4136
4233
  class: "text-sm font-bold text-slate-800 uppercase tracking-wide"
4137
4234
  };
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"];
4235
+ var _hoisted_94 = { class: "text-xs text-slate-400 font-semibold" };
4236
+ var _hoisted_95 = ["aria-label"];
4237
+ var _hoisted_96 = { class: "px-6 py-5" };
4238
+ var _hoisted_97 = ["placeholder", "onKeydown"];
4239
+ var _hoisted_98 = { class: "px-6 py-3.5 border-t border-slate-100 flex items-center justify-end gap-2 bg-slate-50/50" };
4240
+ var _hoisted_99 = ["disabled"];
4144
4241
  /** `slug` / `selected` are supplied only in EMBEDDED mode (the
4145
4242
  * `presentCollection` chat card mounts this component and drives both
4146
4243
  * from the tool result). In standalone route mode (the
@@ -4151,6 +4248,11 @@ var _hoisted_93 = ["disabled"];
4151
4248
  * is our "rendered inside a chat" signal. When set, chat-triggering
4152
4249
  * actions send into the current session instead of spawning a new
4153
4250
  * chat (see `runAction` / `submitChat`). */
4251
+ var COMPLETION_CHIP_KEY = "__completion";
4252
+ /** The field types that earn a filter-menu entry: declared predicates
4253
+ * (`flag`) plus the fields that ARE a predicate already — a stored
4254
+ * `boolean` and a `toggle`'s projected on/off state. Enums stay out:
4255
+ * they need a value picker, and kanban already slices by enum. */
4154
4256
  var LIVE_REFRESH_DEBOUNCE_MS = 150;
4155
4257
  //#endregion
4156
4258
  //#region src/vue/components/CollectionView.vue
@@ -4277,6 +4379,125 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4277
4379
  if (!query) return items.value;
4278
4380
  return items.value.filter((item) => itemMatchesQuery(item, query));
4279
4381
  });
4382
+ /** Chip key (state/testid/localStorage) for the synthesized
4383
+ * legacy-completion chip. Field names are unrestricted strings, so a
4384
+ * schema COULD declare a field with this exact name — the chip list
4385
+ * below skips synthesizing in that case, and the predicate dispatch
4386
+ * keys off the structural `synthetic` marker, never this string. */
4387
+ function storedFlagFiltersFor(slug) {
4388
+ return slug ? readCollectionFlagFilters(slug) : {};
4389
+ }
4390
+ const flagFilters = (0, vue.ref)(storedFlagFiltersFor(activeSlug.value));
4391
+ const CHIP_FIELD_TYPES = /* @__PURE__ */ new Set([
4392
+ "flag",
4393
+ "boolean",
4394
+ "toggle"
4395
+ ]);
4396
+ /** True when an existing FIELD chip already expresses the legacy
4397
+ * completion predicate exactly, so a synthesized "done" chip would be a
4398
+ * duplicate: a boolean `completionField` (done ⇔ `"true"` ⇔ the
4399
+ * boolean's own chip), or a `toggle` projecting the `completionField`
4400
+ * whose `onValue` is the single done value (the todos-schema shape:
4401
+ * toggle "Done" on `status` + `completionDoneValues: ["done"]`). A
4402
+ * superset pair (extra done values) still synthesizes — no field chip
4403
+ * covers it. */
4404
+ function completionCoveredByFieldChip(schema) {
4405
+ const { completionField, completionDoneValues } = schema;
4406
+ if (completionDoneValues?.length !== 1) return false;
4407
+ const [doneValue] = completionDoneValues;
4408
+ if (schema.fields[completionField ?? ""]?.type === "boolean") return doneValue === "true";
4409
+ return Object.values(schema.fields).some((field) => field.type === "toggle" && field.field === completionField && field.onValue === doneValue);
4410
+ }
4411
+ const flagChips = (0, vue.computed)(() => {
4412
+ const schema = collection.value?.schema;
4413
+ if (!schema) return [];
4414
+ const chips = Object.entries(schema.fields).filter(([, field]) => CHIP_FIELD_TYPES.has(field.type)).map(([key, field]) => ({
4415
+ key,
4416
+ label: field.label ?? key
4417
+ }));
4418
+ if (schema.completionField && schema.completionDoneValues && schema.fields[schema.completionField]?.type !== "flag" && !completionCoveredByFieldChip(schema) && schema.fields[COMPLETION_CHIP_KEY] === void 0) chips.push({
4419
+ key: COMPLETION_CHIP_KEY,
4420
+ label: t("collectionsView.flagDoneChip"),
4421
+ synthetic: true
4422
+ });
4423
+ return chips;
4424
+ });
4425
+ /** Own-property read of a chip's active mode. Field names may shadow
4426
+ * `Object.prototype` members (`toString`, `valueOf`, …) — a plain
4427
+ * `filters[key]` on such a key reads the inherited function, which
4428
+ * renders as an "active" chip that can never cycle (Codex review on
4429
+ * PR #2176). Every chip-state read goes through here. */
4430
+ function flagFilterMode(key) {
4431
+ const filters = flagFilters.value;
4432
+ return Object.hasOwn(filters, key) ? filters[key] : void 0;
4433
+ }
4434
+ /** A flag FIELD's computed boolean for one row (list cells + sort):
4435
+ * the enriched record's value, so a flag over derived/rollup inputs
4436
+ * reads correctly. */
4437
+ function flagValueOf(key, item) {
4438
+ return render.deriveRecord(item)[key] === true;
4439
+ }
4440
+ /** The chip's boolean for one row — `itemIsDone` for the synthesized
4441
+ * completion chip, the stored/projected value for `boolean`/`toggle`
4442
+ * fields, the computed flag value otherwise. */
4443
+ function chipMatches(chip, item) {
4444
+ const schema = collection.value?.schema;
4445
+ if (!schema) return false;
4446
+ if (chip.synthetic) return (0, _mulmoclaude_core_collection.itemIsDone)(schema, item);
4447
+ const field = schema.fields[chip.key];
4448
+ if (field?.type === "toggle") return toggleChecked(item, field);
4449
+ if (field?.type === "boolean") return item[chip.key] === true;
4450
+ return flagValueOf(chip.key, item);
4451
+ }
4452
+ /** `filteredItems` further narrowed by every ACTIVE chip (AND). Consumed
4453
+ * only by the table (sortedItems / count summary / empty state). */
4454
+ const tableFilteredItems = (0, vue.computed)(() => {
4455
+ const active = flagChips.value.filter((chip) => flagFilterMode(chip.key) !== void 0);
4456
+ if (active.length === 0) return filteredItems.value;
4457
+ return filteredItems.value.filter((item) => active.every((chip) => chipMatches(chip, item) === (flagFilterMode(chip.key) === "only")));
4458
+ });
4459
+ /** Cycle a chip all → hide → only → all. */
4460
+ function cycleFlagFilter(key) {
4461
+ const current = flagFilterMode(key);
4462
+ const next = current === void 0 ? "hide" : current === "hide" ? "only" : void 0;
4463
+ const rest = Object.fromEntries(Object.entries(flagFilters.value).filter(([entry]) => entry !== key));
4464
+ flagFilters.value = next ? {
4465
+ ...rest,
4466
+ [key]: next
4467
+ } : rest;
4468
+ }
4469
+ function flagChipIcon(key) {
4470
+ return flagFilterMode(key) === "only" ? "check_box" : "check_box_outline_blank";
4471
+ }
4472
+ function flagChipIconClass(key) {
4473
+ const mode = flagFilterMode(key);
4474
+ if (mode === "hide") return "text-slate-600";
4475
+ if (mode === "only") return "text-indigo-600";
4476
+ return "text-slate-300";
4477
+ }
4478
+ function flagChipClass(key) {
4479
+ const mode = flagFilterMode(key);
4480
+ if (mode === "hide") return "bg-slate-100 text-slate-700";
4481
+ if (mode === "only") return "bg-indigo-50 text-indigo-700";
4482
+ return "text-slate-500";
4483
+ }
4484
+ /** How many chips currently filter (badge on the menu trigger). */
4485
+ const activeFlagFilterCount = (0, vue.computed)(() => flagChips.value.filter((chip) => flagFilterMode(chip.key) !== void 0).length);
4486
+ const filterMenuOpen = (0, vue.ref)(false);
4487
+ const filterMenuRef = (0, vue.ref)(null);
4488
+ function closeFilterMenuOnOutsideClick(event) {
4489
+ if (!filterMenuRef.value?.contains(event.target)) filterMenuOpen.value = false;
4490
+ }
4491
+ (0, vue.watch)(filterMenuOpen, (open) => {
4492
+ if (open) document.addEventListener("mousedown", closeFilterMenuOnOutsideClick);
4493
+ else document.removeEventListener("mousedown", closeFilterMenuOnOutsideClick);
4494
+ });
4495
+ function flagChipTitle(chip) {
4496
+ const mode = flagFilterMode(chip.key);
4497
+ if (mode === "hide") return t("collectionsView.flagFilterHide", { label: chip.label });
4498
+ if (mode === "only") return t("collectionsView.flagFilterOnly", { label: chip.label });
4499
+ return t("collectionsView.flagFilterAll", { label: chip.label });
4500
+ }
4280
4501
  function storedSortFor(slug) {
4281
4502
  return slug && readCollectionSort(slug) || null;
4282
4503
  }
@@ -4323,10 +4544,11 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4323
4544
  default: return (0, _mulmoclaude_core_collection.stringSortValue)(raw);
4324
4545
  }
4325
4546
  }
4326
- /** Comparable value for one row under the active field. Toggle and derived
4327
- * need the whole record; every other type keys off the raw cell. */
4547
+ /** Comparable value for one row under the active field. Toggle, flag, and
4548
+ * derived need the whole record; every other type keys off the raw cell. */
4328
4549
  function sortValueOf(field, key, item) {
4329
4550
  if (field.type === "toggle") return (0, _mulmoclaude_core_collection.boolSortValue)(toggleChecked(item, field));
4551
+ if (field.type === "flag") return (0, _mulmoclaude_core_collection.boolSortValue)(flagValueOf(key, item));
4330
4552
  if (field.type === "derived") return derivedSortValue(field, key, item);
4331
4553
  return scalarSortValue(field, item[key]);
4332
4554
  }
@@ -4342,8 +4564,8 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
4342
4564
  const sortedItems = (0, vue.computed)(() => {
4343
4565
  const state = sortState.value;
4344
4566
  const field = state ? collection.value?.schema.fields[state.field] : void 0;
4345
- if (!state || !field) return filteredItems.value;
4346
- return (0, _mulmoclaude_core_collection.sortItems)(filteredItems.value, state.direction, (item) => sortValueOf(field, state.field, item));
4567
+ if (!state || !field) return tableFilteredItems.value;
4568
+ return (0, _mulmoclaude_core_collection.sortItems)(tableFilteredItems.value, state.direction, (item) => sortValueOf(field, state.field, item));
4347
4569
  });
4348
4570
  /** Stringified primary-key value for a row (the row's stable identity). */
4349
4571
  function rowId(item) {
@@ -5288,7 +5510,9 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5288
5510
  anchorOverride.value = null;
5289
5511
  kanbanOverride.value = null;
5290
5512
  addMenuOpen.value = false;
5513
+ filterMenuOpen.value = false;
5291
5514
  sortState.value = storedSortFor(slug);
5515
+ flagFilters.value = storedFlagFiltersFor(slug);
5292
5516
  }
5293
5517
  if (slug) loadCollection(slug);
5294
5518
  else {
@@ -5337,12 +5561,14 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5337
5561
  clearLiveRefreshTimer();
5338
5562
  if (refreshNoteTimer !== void 0) clearTimeout(refreshNoteTimer);
5339
5563
  document.removeEventListener("mousedown", closeAddMenuOnOutsideClick);
5564
+ document.removeEventListener("mousedown", closeFilterMenuOnOutsideClick);
5340
5565
  });
5341
5566
  (0, vue.watch)([
5342
5567
  activeView,
5343
5568
  calendarAnchorField,
5344
5569
  kanbanGroupField,
5345
5570
  sortState,
5571
+ flagFilters,
5346
5572
  loading
5347
5573
  ], () => {
5348
5574
  if (embedded.value) emit("viewStateChange", {
@@ -5353,6 +5579,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5353
5579
  if (activeSlug.value && !loading.value && collection.value) {
5354
5580
  if (!embedded.value) writeCollectionViewMode(activeSlug.value, activeView.value);
5355
5581
  writeCollectionSort(activeSlug.value, sortState.value);
5582
+ writeCollectionFlagFilters(activeSlug.value, flagFilters.value);
5356
5583
  }
5357
5584
  });
5358
5585
  (0, vue.watch)(activeSelected, () => {
@@ -5371,9 +5598,9 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5371
5598
  "aria-label": (0, vue.unref)(t)("collectionsView.backToIndex"),
5372
5599
  "data-testid": "collections-back",
5373
5600
  onClick: goBack
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),
5601
+ }, [..._cache[28] || (_cache[28] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "arrow_back", -1)])], 8, _hoisted_3$5)) : (0, vue.createCommentVNode)("", true),
5375
5602
  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),
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", {
5603
+ (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[29] || (_cache[29] = (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
5604
  key: 0,
5378
5605
  href: dataSourceRoute.value ?? void 0,
5379
5606
  class: "ml-1 normal-case tracking-normal font-mono font-normal text-slate-500 hover:text-indigo-700 hover:underline",
@@ -5406,7 +5633,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5406
5633
  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",
5407
5634
  "data-testid": "collections-chat",
5408
5635
  onClick: openChat
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),
5636
+ }, [_cache[30] || (_cache[30] = (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),
5410
5637
  ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(collectionActions.value, (action) => {
5411
5638
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5412
5639
  key: action.id,
@@ -5423,7 +5650,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5423
5650
  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",
5424
5651
  "data-testid": "collections-add-item",
5425
5652
  onClick: openCreate
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),
5653
+ }, [_cache[31] || (_cache[31] = (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),
5427
5654
  canDeleteCollection.value && !embedded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5428
5655
  key: 6,
5429
5656
  type: "button",
@@ -5432,7 +5659,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5432
5659
  "aria-label": (0, vue.unref)(t)("collectionsView.deleteCollection"),
5433
5660
  "data-testid": "collections-delete",
5434
5661
  onClick: confirmCollectionDelete
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),
5662
+ }, [..._cache[32] || (_cache[32] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_16$4)) : (0, vue.createCommentVNode)("", true),
5436
5663
  canDeleteFeed.value && !embedded.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5437
5664
  key: 7,
5438
5665
  type: "button",
@@ -5441,11 +5668,11 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5441
5668
  "aria-label": (0, vue.unref)(t)("collectionsView.deleteFeed"),
5442
5669
  "data-testid": "feeds-delete",
5443
5670
  onClick: confirmFeedDelete
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)
5671
+ }, [..._cache[33] || (_cache[33] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "delete_forever", -1)])], 8, _hoisted_17$4)) : (0, vue.createCommentVNode)("", true)
5445
5672
  ])) : (0, vue.createCommentVNode)("", true),
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),
5673
+ refreshNote.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_18$4, [_cache[34] || (_cache[34] = (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
5674
  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)),
5675
+ _cache[36] || (_cache[36] = (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)),
5449
5676
  (0, vue.withDirectives)((0, vue.createElementVNode)("input", {
5450
5677
  "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => searchQuery.value = $event),
5451
5678
  type: "text",
@@ -5459,10 +5686,50 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5459
5686
  "aria-label": (0, vue.unref)(t)("collectionsView.clearSearch"),
5460
5687
  class: "absolute inset-y-0 right-0 flex items-center pr-2.5 text-slate-400 hover:text-slate-600",
5461
5688
  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)
5689
+ }, [..._cache[35] || (_cache[35] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "close", -1)])], 8, _hoisted_23$2)) : (0, vue.createCommentVNode)("", true)
5463
5690
  ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_24$1, [
5464
- !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5691
+ activeView.value === "table" && flagChips.value.length > 0 && items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5465
5692
  key: 0,
5693
+ ref_key: "filterMenuRef",
5694
+ ref: filterMenuRef,
5695
+ class: "relative"
5696
+ }, [(0, vue.createElementVNode)("button", {
5697
+ type: "button",
5698
+ class: (0, vue.normalizeClass)(["h-8 px-2.5 flex items-center gap-1 rounded-full text-xs font-medium transition-colors", activeFlagFilterCount.value > 0 ? "bg-indigo-50 text-indigo-700 border border-indigo-300" : "bg-transparent text-slate-500 border border-dashed border-slate-300 hover:bg-slate-50"]),
5699
+ "aria-label": (0, vue.unref)(t)("collectionsView.flagFilterButton"),
5700
+ "aria-expanded": filterMenuOpen.value,
5701
+ "data-testid": "collections-filter-menu",
5702
+ onClick: _cache[3] || (_cache[3] = ($event) => filterMenuOpen.value = !filterMenuOpen.value)
5703
+ }, [
5704
+ _cache[37] || (_cache[37] = (0, vue.createElementVNode)("span", {
5705
+ class: "material-icons text-sm",
5706
+ "aria-hidden": "true"
5707
+ }, "filter_alt", -1)),
5708
+ (0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.flagFilterButton")), 1),
5709
+ activeFlagFilterCount.value > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_26$1, (0, vue.toDisplayString)(activeFlagFilterCount.value), 1)) : (0, vue.createCommentVNode)("", true)
5710
+ ], 10, _hoisted_25$1), filterMenuOpen.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5711
+ key: 0,
5712
+ class: "absolute left-0 top-full mt-1 z-20 min-w-max rounded border border-slate-200 bg-white shadow-lg py-1",
5713
+ role: "group",
5714
+ "aria-label": (0, vue.unref)(t)("collectionsView.flagFilterButton"),
5715
+ "data-testid": "collections-filter-menu-panel"
5716
+ }, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(flagChips.value, (chip) => {
5717
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5718
+ key: chip.key,
5719
+ type: "button",
5720
+ class: (0, vue.normalizeClass)(["w-full h-8 px-3 flex items-center gap-2 text-xs font-medium transition-colors hover:bg-slate-50", flagChipClass(chip.key)]),
5721
+ title: flagChipTitle(chip),
5722
+ "aria-label": flagChipTitle(chip),
5723
+ "aria-pressed": flagFilterMode(chip.key) !== void 0,
5724
+ "data-testid": `collections-flag-chip-${chip.key}`,
5725
+ onClick: ($event) => cycleFlagFilter(chip.key)
5726
+ }, [(0, vue.createElementVNode)("span", {
5727
+ class: (0, vue.normalizeClass)(["material-icons text-sm", flagChipIconClass(chip.key)]),
5728
+ "aria-hidden": "true"
5729
+ }, (0, vue.toDisplayString)(flagChipIcon(chip.key)), 3), (0, vue.createElementVNode)("span", _hoisted_29, (0, vue.toDisplayString)(chip.label), 1)], 10, _hoisted_28);
5730
+ }), 128))], 8, _hoisted_27$1)) : (0, vue.createCommentVNode)("", true)], 512)) : (0, vue.createCommentVNode)("", true),
5731
+ !__props.hideViewToggle && (hasCalendar.value || hasKanban.value || hasCustomViews.value || canAddCustomView.value) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5732
+ key: 1,
5466
5733
  class: "flex gap-0.5",
5467
5734
  role: "group",
5468
5735
  "aria-label": (0, vue.unref)(t)("collectionsView.viewToggle")
@@ -5472,24 +5739,24 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5472
5739
  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"]),
5473
5740
  "aria-pressed": activeView.value === "table",
5474
5741
  "data-testid": "collection-view-toggle-table",
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),
5742
+ onClick: _cache[4] || (_cache[4] = ($event) => setView("table"))
5743
+ }, [_cache[38] || (_cache[38] = (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_31),
5477
5744
  hasCalendar.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5478
5745
  key: 0,
5479
5746
  type: "button",
5480
5747
  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"]),
5481
5748
  "aria-pressed": activeView.value === "calendar",
5482
5749
  "data-testid": "collection-view-toggle-calendar",
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),
5750
+ onClick: _cache[5] || (_cache[5] = ($event) => setView("calendar"))
5751
+ }, [_cache[39] || (_cache[39] = (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_32)) : (0, vue.createCommentVNode)("", true),
5485
5752
  hasKanban.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5486
5753
  key: 1,
5487
5754
  type: "button",
5488
5755
  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"]),
5489
5756
  "aria-pressed": activeView.value === "kanban",
5490
5757
  "data-testid": "collection-view-toggle-kanban",
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),
5758
+ onClick: _cache[6] || (_cache[6] = ($event) => setView("kanban"))
5759
+ }, [_cache[40] || (_cache[40] = (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_33)) : (0, vue.createCommentVNode)("", true),
5493
5760
  ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(customViews.value, (cv) => {
5494
5761
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5495
5762
  key: cv.id,
@@ -5498,7 +5765,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5498
5765
  "aria-pressed": activeView.value === (0, vue.unref)(customViewKey)(cv.id),
5499
5766
  "data-testid": `collection-view-custom-${cv.id}`,
5500
5767
  onClick: ($event) => setCustomView(cv.id)
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);
5768
+ }, [(0, vue.createElementVNode)("span", _hoisted_35, (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_34);
5502
5769
  }), 128)),
5503
5770
  canAddCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
5504
5771
  key: 2,
@@ -5513,17 +5780,17 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5513
5780
  "aria-expanded": addMenuOpen.value,
5514
5781
  "data-testid": "collection-view-add",
5515
5782
  onClick: onAddViewClick
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", {
5783
+ }, [..._cache[41] || (_cache[41] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "add", -1)])], 8, _hoisted_36), addMenuOpen.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_37, [(0, vue.createElementVNode)("button", {
5517
5784
  type: "button",
5518
5785
  class: "w-full h-8 px-3 flex items-center gap-2 text-xs font-bold text-slate-600 hover:bg-slate-50",
5519
5786
  "data-testid": "collection-view-add-desktop",
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", {
5787
+ onClick: _cache[7] || (_cache[7] = ($event) => addCustomView("desktop"))
5788
+ }, [_cache[42] || (_cache[42] = (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", {
5522
5789
  type: "button",
5523
5790
  class: "w-full h-8 px-3 flex items-center gap-2 text-xs font-bold text-slate-600 hover:bg-slate-50",
5524
5791
  "data-testid": "collection-view-add-mobile",
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),
5792
+ onClick: _cache[8] || (_cache[8] = ($event) => addCustomView("mobile"))
5793
+ }, [_cache[43] || (_cache[43] = (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),
5527
5794
  canConfigureViews.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5528
5795
  key: 3,
5529
5796
  type: "button",
@@ -5531,51 +5798,51 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5531
5798
  title: (0, vue.unref)(t)("collectionsView.config.open"),
5532
5799
  "aria-label": (0, vue.unref)(t)("collectionsView.config.open"),
5533
5800
  "data-testid": "collection-config-open",
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),
5801
+ onClick: _cache[9] || (_cache[9] = ($event) => configOpen.value = true)
5802
+ }, [..._cache[44] || (_cache[44] = [(0, vue.createElementVNode)("span", { class: "material-icons text-sm" }, "settings", -1)])], 8, _hoisted_38)) : (0, vue.createCommentVNode)("", true)
5803
+ ], 8, _hoisted_30)) : (0, vue.createCommentVNode)("", true),
5537
5804
  calendarActive.value && dateFields.value.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5538
- key: 1,
5805
+ key: 2,
5539
5806
  value: calendarAnchorField.value,
5540
5807
  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",
5541
5808
  "aria-label": (0, vue.unref)(t)("collectionsView.calendarFieldLabel"),
5542
5809
  "data-testid": "collection-calendar-field",
5543
- onChange: _cache[9] || (_cache[9] = ($event) => anchorOverride.value = $event.target.value)
5810
+ onChange: _cache[10] || (_cache[10] = ($event) => anchorOverride.value = $event.target.value)
5544
5811
  }, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(dateFields.value, (key) => {
5545
5812
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
5546
5813
  key,
5547
5814
  value: key
5548
- }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_35);
5549
- }), 128))], 40, _hoisted_34)) : (0, vue.createCommentVNode)("", true),
5815
+ }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_40);
5816
+ }), 128))], 40, _hoisted_39)) : (0, vue.createCommentVNode)("", true),
5550
5817
  kanbanActive.value && enumFields.value.length > 1 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
5551
- key: 2,
5818
+ key: 3,
5552
5819
  value: kanbanGroupField.value,
5553
5820
  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",
5554
5821
  "aria-label": (0, vue.unref)(t)("collectionsView.kanbanFieldLabel"),
5555
5822
  "data-testid": "collection-kanban-field",
5556
- onChange: _cache[10] || (_cache[10] = ($event) => kanbanOverride.value = $event.target.value)
5823
+ onChange: _cache[11] || (_cache[11] = ($event) => kanbanOverride.value = $event.target.value)
5557
5824
  }, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(enumFields.value, (key) => {
5558
5825
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
5559
5826
  key,
5560
5827
  value: key
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", {
5564
- shown: filteredItems.value.length,
5828
+ }, (0, vue.toDisplayString)(collection.value?.schema.fields[key]?.label ?? key), 9, _hoisted_42);
5829
+ }), 128))], 40, _hoisted_41)) : (0, vue.createCommentVNode)("", true),
5830
+ items.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_43, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.searchSummary", {
5831
+ shown: activeView.value === "table" ? tableFilteredItems.value.length : filteredItems.value.length,
5565
5832
  total: items.value.length
5566
5833
  })), 1)) : (0, vue.createCommentVNode)("", true)
5567
5834
  ])])) : (0, vue.createCommentVNode)("", true),
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),
5835
+ collection.value && dataIssues.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_44, [
5836
+ _cache[46] || (_cache[46] = (0, vue.createElementVNode)("span", { class: "material-icons text-amber-600" }, "warning", -1)),
5837
+ (0, vue.createElementVNode)("span", _hoisted_45, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.dataIssuesDetected", { count: dataIssues.value.length })), 1),
5571
5838
  (0, vue.createElementVNode)("button", {
5572
5839
  type: "button",
5573
5840
  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",
5574
5841
  "data-testid": "collections-repair",
5575
5842
  onClick: repairCollection
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)])
5843
+ }, [_cache[45] || (_cache[45] = (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)])
5577
5844
  ])) : (0, vue.createCommentVNode)("", true),
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, {
5845
+ (0, vue.createElementVNode)("div", _hoisted_46, [loading.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_47, [_cache[47] || (_cache[47] = (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_48, [_cache[48] || (_cache[48] = (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_49)) : calendarActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_50, [(0, vue.createVNode)(CollectionCalendarView_default, {
5579
5846
  schema: collection.value.schema,
5580
5847
  items: filteredItems.value,
5581
5848
  "anchor-field": calendarAnchorField.value,
@@ -5611,7 +5878,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5611
5878
  }, {
5612
5879
  detail: (0, vue.withCtx)(() => [(0, vue.createVNode)(CollectionRecordPanel_default, {
5613
5880
  editing: editing.value,
5614
- "onUpdate:editing": _cache[11] || (_cache[11] = ($event) => editing.value = $event),
5881
+ "onUpdate:editing": _cache[12] || (_cache[12] = ($event) => editing.value = $event),
5615
5882
  collection: collection.value,
5616
5883
  viewing: viewing.value,
5617
5884
  saving: saving.value,
@@ -5631,7 +5898,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5631
5898
  onCancel: cancelEditor,
5632
5899
  onEdit: editFromView,
5633
5900
  onClose: onDayClose,
5634
- onDelete: _cache[12] || (_cache[12] = ($event) => viewing.value && confirmDelete(viewing.value)),
5901
+ onDelete: _cache[13] || (_cache[13] = ($event) => viewing.value && confirmDelete(viewing.value)),
5635
5902
  onRunAction: runAction,
5636
5903
  onItemChat
5637
5904
  }, null, 8, [
@@ -5664,16 +5931,16 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5664
5931
  "selected",
5665
5932
  "can-create",
5666
5933
  "show-detail"
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),
5934
+ ])) : (0, vue.createCommentVNode)("", true)])) : kanbanActive.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_51, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_52, [
5935
+ _cache[50] || (_cache[50] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
5936
+ (0, vue.createElementVNode)("span", _hoisted_53, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5670
5937
  (0, vue.createElementVNode)("button", {
5671
5938
  type: "button",
5672
5939
  class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
5673
5940
  "aria-label": (0, vue.unref)(t)("common.close"),
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, {
5941
+ onClick: _cache[14] || (_cache[14] = ($event) => inlineError.value = null)
5942
+ }, [..._cache[49] || (_cache[49] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_54)
5943
+ ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("div", _hoisted_55, [(0, vue.createVNode)(CollectionKanbanView_default, {
5677
5944
  schema: collection.value.schema,
5678
5945
  items: filteredItems.value,
5679
5946
  "group-field": kanbanGroupField.value,
@@ -5689,7 +5956,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5689
5956
  "selected",
5690
5957
  "notified",
5691
5958
  "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, {
5959
+ ])])])) : activeCustomView.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_56, [activeCustomView.value.target === "mobile" ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRemoteViewPreview_default, {
5693
5960
  key: 0,
5694
5961
  slug: collection.value.slug,
5695
5962
  view: activeCustomView.value,
@@ -5700,32 +5967,32 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5700
5967
  view: activeCustomView.value,
5701
5968
  onOpenItem: onCustomViewOpenItem,
5702
5969
  onStartChat: onCustomViewStartChat
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),
5970
+ }, null, 8, ["slug", "view"]))])) : items.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_57, [_cache[51] || (_cache[51] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "folder_open", -1)), (0, vue.createElementVNode)("p", _hoisted_58, (0, vue.toDisplayString)((0, vue.unref)(t)(isReadOnly.value ? "collectionsView.itemsEmptyReadonly" : "collectionsView.itemsEmpty")), 1)])) : tableFilteredItems.value.length === 0 && editing.value?.mode !== "create" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_59, [
5971
+ _cache[52] || (_cache[52] = (0, vue.createElementVNode)("span", { class: "material-icons text-4xl text-slate-300" }, "search_off", -1)),
5972
+ (0, vue.createElementVNode)("p", _hoisted_60, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.noMatchingItems")), 1),
5706
5973
  (0, vue.createElementVNode)("button", {
5707
5974
  type: "button",
5708
5975
  class: "text-xs text-indigo-600 font-semibold hover:underline",
5709
- onClick: _cache[14] || (_cache[14] = ($event) => searchQuery.value = "")
5976
+ onClick: _cache[15] || (_cache[15] = ($event) => (searchQuery.value = "", flagFilters.value = {}))
5710
5977
  }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.clearSearch")), 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),
5978
+ ])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_61, [inlineError.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_62, [
5979
+ _cache[54] || (_cache[54] = (0, vue.createElementVNode)("span", { class: "material-icons text-red-600" }, "error", -1)),
5980
+ (0, vue.createElementVNode)("span", _hoisted_63, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.inlineSaveFailed", { error: inlineError.value })), 1),
5714
5981
  (0, vue.createElementVNode)("button", {
5715
5982
  type: "button",
5716
5983
  class: "h-8 w-8 flex items-center justify-center rounded text-red-600 hover:bg-red-100",
5717
5984
  "aria-label": (0, vue.unref)(t)("common.close"),
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]) => {
5985
+ onClick: _cache[16] || (_cache[16] = ($event) => inlineError.value = null)
5986
+ }, [..._cache[53] || (_cache[53] = [(0, vue.createElementVNode)("span", { class: "material-icons text-base" }, "close", -1)])], 8, _hoisted_64)
5987
+ ])) : (0, vue.createCommentVNode)("", true), (0, vue.createElementVNode)("table", _hoisted_65, [(0, vue.createElementVNode)("thead", null, [(0, vue.createElementVNode)("tr", _hoisted_66, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(listColumnFields.value, ([key, field]) => {
5721
5988
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("th", {
5722
5989
  key,
5723
5990
  "aria-sort": (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? sortAriaValue(key) : void 0,
5724
5991
  class: "px-5 py-3 font-bold text-slate-500 text-left uppercase tracking-wider whitespace-nowrap"
5725
- }, [(0, vue.createElementVNode)("div", _hoisted_63, [(0, vue.createElementVNode)("span", {
5992
+ }, [(0, vue.createElementVNode)("div", _hoisted_68, [(0, vue.createElementVNode)("span", {
5726
5993
  class: "truncate max-w-[14rem]",
5727
5994
  title: field.label
5728
- }, (0, vue.toDisplayString)(field.label), 9, _hoisted_64), (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5995
+ }, (0, vue.toDisplayString)(field.label), 9, _hoisted_69), (0, vue.unref)(_mulmoclaude_core_collection.isSortableField)(field) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
5729
5996
  key: 0,
5730
5997
  type: "button",
5731
5998
  class: (0, vue.normalizeClass)(["inline-flex items-center justify-center rounded p-0.5 -my-1 leading-none transition-colors", sortButtonClass(key)]),
@@ -5733,9 +6000,9 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5733
6000
  "aria-label": (0, vue.unref)(t)("collectionsView.sortBy", { field: field.label }),
5734
6001
  onClick: (0, vue.withModifiers)(($event) => cycleSort(key), ["stop"]),
5735
6002
  onPointerenter: ($event) => hoveredSortKey.value = key,
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) => {
6003
+ onPointerleave: _cache[17] || (_cache[17] = ($event) => hoveredSortKey.value = null)
6004
+ }, [(0, vue.createElementVNode)("span", _hoisted_71, (0, vue.toDisplayString)(sortIconName(key)), 1)], 42, _hoisted_70)) : (0, vue.createCommentVNode)("", true)])], 8, _hoisted_67);
6005
+ }), 128))])]), (0, vue.createElementVNode)("tbody", _hoisted_72, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(sortedItems.value, (item) => {
5739
6006
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("tr", {
5740
6007
  key: String(item[collection.value.schema.primaryKey] ?? ""),
5741
6008
  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" : ""]),
@@ -5757,9 +6024,9 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5757
6024
  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",
5758
6025
  "data-testid": `collections-inline-toggle-${key}-${item[collection.value.schema.primaryKey]}`,
5759
6026
  "aria-label": field.label,
5760
- onClick: _cache[17] || (_cache[17] = (0, vue.withModifiers)(() => {}, ["stop"])),
6027
+ onClick: _cache[18] || (_cache[18] = (0, vue.withModifiers)(() => {}, ["stop"])),
5761
6028
  onChange: ($event) => commitToggle(item, field)
5762
- }, null, 40, _hoisted_69)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
6029
+ }, null, 40, _hoisted_74)) : field.type === "boolean" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("input", {
5763
6030
  key: 1,
5764
6031
  type: "checkbox",
5765
6032
  checked: item[key] === true,
@@ -5767,9 +6034,15 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5767
6034
  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",
5768
6035
  "data-testid": `collections-inline-bool-${key}-${item[collection.value.schema.primaryKey]}`,
5769
6036
  "aria-label": field.label,
5770
- onClick: _cache[18] || (_cache[18] = (0, vue.withModifiers)(() => {}, ["stop"])),
6037
+ onClick: _cache[19] || (_cache[19] = (0, vue.withModifiers)(() => {}, ["stop"])),
5771
6038
  onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.checked)
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", {
6039
+ }, null, 40, _hoisted_75)) : field.type === "flag" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
6040
+ key: 2,
6041
+ class: (0, vue.normalizeClass)(["material-icons text-lg align-middle", flagValueOf(String(key), item) ? "text-emerald-600" : "text-slate-300"]),
6042
+ "data-testid": `collections-flag-${key}-${item[collection.value.schema.primaryKey]}`,
6043
+ "aria-label": `${field.label}: ${(0, vue.unref)(t)(flagValueOf(String(key), item) ? "common.yes" : "common.no")}`,
6044
+ role: "img"
6045
+ }, (0, vue.toDisplayString)(flagValueOf(String(key), item) ? "check_circle" : "radio_button_unchecked"), 11, _hoisted_76)) : field.type === "ref" && field.to && typeof item[key] === "string" && item[key] ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_77, [(0, vue.createElementVNode)("a", {
5773
6046
  href: (0, vue.unref)(cui).recordHref?.(field.to, String(item[key])),
5774
6047
  tabindex: (0, vue.unref)(cui).recordHref?.(field.to, String(item[key])) ? void 0 : 0,
5775
6048
  role: "link",
@@ -5777,48 +6050,48 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5777
6050
  "data-testid": `collections-ref-link-${key}-${item[key]}`,
5778
6051
  onClick: ($event) => (0, vue.unref)(activateRefLink)($event, field.to, String(item[key]), true),
5779
6052
  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"])]
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", {
5781
- key: 3,
6053
+ }, (0, vue.toDisplayString)((0, vue.unref)(refDisplay)(field.to, String(item[key]))), 41, _hoisted_78)])) : field.type === "enum" && Array.isArray(field.values) && field.values.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("select", {
6054
+ key: 4,
5782
6055
  value: item[key] == null ? "" : String(item[key]),
5783
6056
  disabled: isReadOnly.value || isRowInlineSaving(item),
5784
6057
  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])]),
5785
6058
  "data-testid": `collections-inline-enum-${key}-${item[collection.value.schema.primaryKey]}`,
5786
6059
  "aria-label": field.label,
5787
- onClick: _cache[19] || (_cache[19] = (0, vue.withModifiers)(() => {}, ["stop"])),
6060
+ onClick: _cache[20] || (_cache[20] = (0, vue.withModifiers)(() => {}, ["stop"])),
5788
6061
  onChange: ($event) => commitInlineEdit(item, String(key), field, $event.target.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) => {
6062
+ }, [showEnumPlaceholder(item, String(key)) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("option", _hoisted_80, (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) => {
5790
6063
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("option", {
5791
6064
  key: value,
5792
6065
  value
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", {
5795
- key: 7,
6066
+ }, (0, vue.toDisplayString)(value), 9, _hoisted_81);
6067
+ }), 128))], 42, _hoisted_79)) : field.type === "money" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_82, (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_83, [_cache[55] || (_cache[55] = (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_84, (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", {
6068
+ key: 8,
5796
6069
  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",
5797
6070
  "data-testid": `collections-rollup-${key}-${item[collection.value.schema.primaryKey]}`
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", {
5799
- key: 8,
6071
+ }, (0, vue.toDisplayString)((0, vue.unref)(render).rollupDisplay(field, item)), 9, _hoisted_85)) : field.type !== "file" && (0, vue.unref)(isExternalUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
6072
+ key: 9,
5800
6073
  href: String(item[key]),
5801
6074
  target: "_blank",
5802
6075
  rel: "noopener noreferrer",
5803
6076
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5804
6077
  "data-testid": `collections-url-link-${key}-${item[collection.value.schema.primaryKey]}`,
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", {
5807
- key: 9,
6078
+ onClick: _cache[21] || (_cache[21] = (0, vue.withModifiers)(() => {}, ["stop"]))
6079
+ }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_86)) : field.type === "file" && (0, vue.unref)(artifactUrl)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
6080
+ key: 10,
5808
6081
  href: (0, vue.unref)(artifactUrl)(item[key]) ?? void 0,
5809
6082
  target: "_blank",
5810
6083
  rel: "noopener noreferrer",
5811
6084
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5812
6085
  "data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
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", {
5815
- key: 10,
6086
+ onClick: _cache[22] || (_cache[22] = (0, vue.withModifiers)(() => {}, ["stop"]))
6087
+ }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_87)) : field.type === "file" && (0, vue.unref)(fileRoutePath)(item[key]) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("a", {
6088
+ key: 11,
5816
6089
  href: (0, vue.unref)(fileRoutePath)(item[key]) ?? void 0,
5817
6090
  class: "block truncate text-blue-600 hover:text-blue-800 hover:underline font-semibold",
5818
6091
  "data-testid": `collections-file-link-${key}-${item[collection.value.schema.primaryKey]}`,
5819
6092
  onClick: ($event) => (0, vue.unref)(activatePathLink)($event, (0, vue.unref)(fileRoutePath)(item[key]) ?? "", true)
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);
6093
+ }, (0, vue.toDisplayString)(String(item[key])), 9, _hoisted_88)) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_89, (0, vue.toDisplayString)((0, vue.unref)(formatCell)(item[key], field.type)), 1))], 64)) : (0, vue.createCommentVNode)("", true)]);
6094
+ }), 128))], 42, _hoisted_73);
5822
6095
  }), 128))])])]))]),
5823
6096
  collection.value && (viewing.value || editing.value) && !(calendarActive.value && openDay.value) ? ((0, vue.openBlock)(), (0, vue.createBlock)(CollectionRecordModal_default, {
5824
6097
  key: 4,
@@ -5826,7 +6099,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5826
6099
  }, {
5827
6100
  default: (0, vue.withCtx)(() => [(0, vue.createVNode)(CollectionRecordPanel_default, {
5828
6101
  editing: editing.value,
5829
- "onUpdate:editing": _cache[22] || (_cache[22] = ($event) => editing.value = $event),
6102
+ "onUpdate:editing": _cache[23] || (_cache[23] = ($event) => editing.value = $event),
5830
6103
  collection: collection.value,
5831
6104
  viewing: viewing.value,
5832
6105
  saving: saving.value,
@@ -5846,7 +6119,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5846
6119
  onCancel: cancelEditor,
5847
6120
  onEdit: editFromView,
5848
6121
  onClose: closeView,
5849
- onDelete: _cache[23] || (_cache[23] = ($event) => viewing.value && confirmDelete(viewing.value)),
6122
+ onDelete: _cache[24] || (_cache[24] = ($event) => viewing.value && confirmDelete(viewing.value)),
5850
6123
  onRunAction: runAction,
5851
6124
  onItemChat
5852
6125
  }, null, 8, [
@@ -5874,7 +6147,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5874
6147
  action: mutateModal.value.action,
5875
6148
  pending: mutatePending.value,
5876
6149
  error: mutateError.value,
5877
- onClose: _cache[24] || (_cache[24] = ($event) => mutateModal.value = null),
6150
+ onClose: _cache[25] || (_cache[25] = ($event) => mutateModal.value = null),
5878
6151
  onSubmit: submitMutateParams
5879
6152
  }, null, 8, [
5880
6153
  "action",
@@ -5887,7 +6160,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5887
6160
  title: collection.value.title,
5888
6161
  views: customViews.value,
5889
6162
  onChanged: onViewsChanged,
5890
- onClose: _cache[25] || (_cache[25] = ($event) => configOpen.value = false)
6163
+ onClose: _cache[26] || (_cache[26] = ($event) => configOpen.value = false)
5891
6164
  }, null, 8, [
5892
6165
  "slug",
5893
6166
  "title",
@@ -5902,29 +6175,29 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5902
6175
  "data-testid": "collections-chat-modal",
5903
6176
  onClick: (0, vue.withModifiers)(closeChat, ["self"]),
5904
6177
  onKeydown: (0, vue.withKeys)(closeChat, ["esc"])
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)]),
6178
+ }, [(0, vue.createElementVNode)("div", _hoisted_90, [
6179
+ (0, vue.createElementVNode)("header", _hoisted_91, [
6180
+ _cache[57] || (_cache[57] = (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)),
6181
+ (0, vue.createElementVNode)("div", _hoisted_92, [(0, vue.createElementVNode)("h2", _hoisted_93, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatTitle")), 1), (0, vue.createElementVNode)("span", _hoisted_94, (0, vue.toDisplayString)(collection.value.title), 1)]),
5909
6182
  (0, vue.createElementVNode)("button", {
5910
6183
  type: "button",
5911
6184
  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",
5912
6185
  "aria-label": (0, vue.unref)(t)("common.close"),
5913
6186
  "data-testid": "collections-chat-close",
5914
6187
  onClick: closeChat
5915
- }, [..._cache[54] || (_cache[54] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_89)
6188
+ }, [..._cache[56] || (_cache[56] = [(0, vue.createElementVNode)("span", { class: "material-icons text-lg" }, "close", -1)])], 8, _hoisted_95)
5916
6189
  ]),
5917
- (0, vue.createElementVNode)("div", _hoisted_90, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
6190
+ (0, vue.createElementVNode)("div", _hoisted_96, [(0, vue.withDirectives)((0, vue.createElementVNode)("textarea", {
5918
6191
  ref_key: "chatInputEl",
5919
6192
  ref: chatInputEl,
5920
- "onUpdate:modelValue": _cache[26] || (_cache[26] = ($event) => chatMessage.value = $event),
6193
+ "onUpdate:modelValue": _cache[27] || (_cache[27] = ($event) => chatMessage.value = $event),
5921
6194
  rows: "4",
5922
6195
  placeholder: (0, vue.unref)(t)("collectionsView.chatPlaceholder"),
5923
6196
  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",
5924
6197
  "data-testid": "collections-chat-input",
5925
6198
  onKeydown: [(0, vue.withKeys)((0, vue.withModifiers)(submitChat, ["meta"]), ["enter"]), (0, vue.withKeys)((0, vue.withModifiers)(submitChat, ["ctrl"]), ["enter"])]
5926
- }, null, 40, _hoisted_91), [[vue.vModelText, chatMessage.value]])]),
5927
- (0, vue.createElementVNode)("footer", _hoisted_92, [(0, vue.createElementVNode)("button", {
6199
+ }, null, 40, _hoisted_97), [[vue.vModelText, chatMessage.value]])]),
6200
+ (0, vue.createElementVNode)("footer", _hoisted_98, [(0, vue.createElementVNode)("button", {
5928
6201
  type: "button",
5929
6202
  class: "h-8 px-2.5 rounded text-xs font-bold text-slate-500 hover:bg-slate-200/50 transition-colors",
5930
6203
  "data-testid": "collections-chat-cancel",
@@ -5935,7 +6208,7 @@ var CollectionView_default = /* @__PURE__ */ (0, vue.defineComponent)({
5935
6208
  disabled: !chatMessage.value.trim(),
5936
6209
  "data-testid": "collections-chat-send",
5937
6210
  onClick: submitChat
5938
- }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatStart")), 9, _hoisted_93)])
6211
+ }, (0, vue.toDisplayString)((0, vue.unref)(t)("collectionsView.chatStart")), 9, _hoisted_99)])
5939
6212
  ])], 32)) : (0, vue.createCommentVNode)("", true)
5940
6213
  ]);
5941
6214
  };
@@ -6839,9 +7112,11 @@ exports.collectionUi = collectionUi;
6839
7112
  exports.configureCollectionUi = configureCollectionUi;
6840
7113
  exports.customViewKey = customViewKey;
6841
7114
  exports.plugin = plugin;
7115
+ exports.readCollectionFlagFilters = readCollectionFlagFilters;
6842
7116
  exports.readCollectionSort = readCollectionSort;
6843
7117
  exports.readCollectionViewMode = readCollectionViewMode;
6844
7118
  exports.useCollectionRendering = useCollectionRendering;
7119
+ exports.writeCollectionFlagFilters = writeCollectionFlagFilters;
6845
7120
  exports.writeCollectionSort = writeCollectionSort;
6846
7121
  exports.writeCollectionViewMode = writeCollectionViewMode;
6847
7122