@cocoar/vue-ui 3.1.0 → 3.2.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/dist/components/checkbox/CoarCheckbox.vue.d.ts +1 -1
  2. package/dist/components/checkbox/CoarCheckbox.vue.d.ts.map +1 -1
  3. package/dist/components/code-block/CoarCodeBlock.vue.d.ts +1 -1
  4. package/dist/components/code-block/CoarCodeBlock.vue.d.ts.map +1 -1
  5. package/dist/components/data-list/CoarDataList.vue.d.ts +158 -0
  6. package/dist/components/data-list/CoarDataList.vue.d.ts.map +1 -0
  7. package/dist/components/data-list/CoarDataListToolbar.vue.d.ts +30 -0
  8. package/dist/components/data-list/CoarDataListToolbar.vue.d.ts.map +1 -0
  9. package/dist/components/data-list/data-list-builder.d.ts +288 -0
  10. package/dist/components/data-list/data-list-builder.d.ts.map +1 -0
  11. package/dist/components/data-list/index.d.ts +12 -0
  12. package/dist/components/data-list/index.d.ts.map +1 -0
  13. package/dist/components/data-list/internal/compare.d.ts +14 -0
  14. package/dist/components/data-list/internal/compare.d.ts.map +1 -0
  15. package/dist/components/data-list/internal/reorder-core.d.ts +46 -0
  16. package/dist/components/data-list/internal/reorder-core.d.ts.map +1 -0
  17. package/dist/components/data-list/internal/search.d.ts +16 -0
  18. package/dist/components/data-list/internal/search.d.ts.map +1 -0
  19. package/dist/components/data-list/internal/useDataListLines.d.ts +92 -0
  20. package/dist/components/data-list/internal/useDataListLines.d.ts.map +1 -0
  21. package/dist/components/data-list/internal/useDataListReorder.d.ts +68 -0
  22. package/dist/components/data-list/internal/useDataListReorder.d.ts.map +1 -0
  23. package/dist/components/data-list/internal/useSearchHighlight.d.ts +19 -0
  24. package/dist/components/data-list/internal/useSearchHighlight.d.ts.map +1 -0
  25. package/dist/components/data-list/types.d.ts +185 -0
  26. package/dist/components/data-list/types.d.ts.map +1 -0
  27. package/dist/components/data-list/useDataListModel.d.ts +79 -0
  28. package/dist/components/data-list/useDataListModel.d.ts.map +1 -0
  29. package/dist/components/date-time/_shared/maskito-config.d.ts +7 -2
  30. package/dist/components/date-time/_shared/maskito-config.d.ts.map +1 -1
  31. package/dist/components/date-time/_shared/time-helpers.d.ts +11 -4
  32. package/dist/components/date-time/_shared/time-helpers.d.ts.map +1 -1
  33. package/dist/components/date-time/_shared/use-date-picker-base.d.ts +1 -1
  34. package/dist/components/date-time/plain-date-picker/CoarPlainDatePicker.vue.d.ts +1 -1
  35. package/dist/components/date-time/plain-date-picker/CoarPlainDatePicker.vue.d.ts.map +1 -1
  36. package/dist/components/date-time/plain-date-time-picker/CoarPlainDateTimePicker.vue.d.ts +1 -1
  37. package/dist/components/date-time/plain-date-time-picker/CoarPlainDateTimePicker.vue.d.ts.map +1 -1
  38. package/dist/components/date-time/zoned-date-time-picker/CoarZonedDateTimePicker.vue.d.ts +1 -1
  39. package/dist/components/date-time/zoned-date-time-picker/CoarZonedDateTimePicker.vue.d.ts.map +1 -1
  40. package/dist/components/dual-listbox/CoarDualListbox.vue.d.ts +3 -0
  41. package/dist/components/dual-listbox/CoarDualListbox.vue.d.ts.map +1 -1
  42. package/dist/components/form-field/CoarFormField.vue.d.ts +1 -1
  43. package/dist/components/form-field/CoarFormField.vue.d.ts.map +1 -1
  44. package/dist/components/icon/CoarIcon.vue.d.ts +2 -2
  45. package/dist/components/icon/CoarIcon.vue.d.ts.map +1 -1
  46. package/dist/components/listbox/CoarListbox.vue.d.ts +7 -0
  47. package/dist/components/listbox/CoarListbox.vue.d.ts.map +1 -1
  48. package/dist/components/number-input/CoarNumberInput.vue.d.ts +1 -1
  49. package/dist/components/number-input/CoarNumberInput.vue.d.ts.map +1 -1
  50. package/dist/components/otp-input/CoarOtpInput.vue.d.ts +1 -1
  51. package/dist/components/otp-input/CoarOtpInput.vue.d.ts.map +1 -1
  52. package/dist/components/password-input/CoarPasswordInput.vue.d.ts +1 -1
  53. package/dist/components/password-input/CoarPasswordInput.vue.d.ts.map +1 -1
  54. package/dist/components/switch/CoarSwitch.vue.d.ts +1 -1
  55. package/dist/components/switch/CoarSwitch.vue.d.ts.map +1 -1
  56. package/dist/components/text-input/CoarTextInput.vue.d.ts +1 -1
  57. package/dist/components/text-input/CoarTextInput.vue.d.ts.map +1 -1
  58. package/dist/composables/dragRegistry.d.ts +12 -0
  59. package/dist/composables/dragRegistry.d.ts.map +1 -1
  60. package/dist/composables/index.d.ts +2 -2
  61. package/dist/composables/index.d.ts.map +1 -1
  62. package/dist/composables/useDragDrop.d.ts +62 -6
  63. package/dist/composables/useDragDrop.d.ts.map +1 -1
  64. package/dist/composables/useVirtualList.d.ts +21 -1
  65. package/dist/composables/useVirtualList.d.ts.map +1 -1
  66. package/dist/index.css +1 -1
  67. package/dist/index.d.ts +4 -2
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +4508 -2039
  70. package/package.json +5 -3
  71. package/skills/cocoar-vue-ui/SKILL.md +244 -0
  72. package/skills/cocoar-vue-ui/references/components/avatar.md +178 -0
  73. package/skills/cocoar-vue-ui/references/components/badge.md +290 -0
  74. package/skills/cocoar-vue-ui/references/components/breadcrumb.md +238 -0
  75. package/skills/cocoar-vue-ui/references/components/button.md +252 -0
  76. package/skills/cocoar-vue-ui/references/components/calendar/agenda-view.md +353 -0
  77. package/skills/cocoar-vue-ui/references/components/calendar/coar-calendar.md +1645 -0
  78. package/skills/cocoar-vue-ui/references/components/calendar/day-view.md +361 -0
  79. package/skills/cocoar-vue-ui/references/components/calendar/index.md +312 -0
  80. package/skills/cocoar-vue-ui/references/components/calendar/month-view.md +475 -0
  81. package/skills/cocoar-vue-ui/references/components/calendar/performance.md +186 -0
  82. package/skills/cocoar-vue-ui/references/components/calendar/timeline-view.md +301 -0
  83. package/skills/cocoar-vue-ui/references/components/calendar/week-view.md +382 -0
  84. package/skills/cocoar-vue-ui/references/components/calendar/work-week-view.md +145 -0
  85. package/skills/cocoar-vue-ui/references/components/calendar/year-view.md +63 -0
  86. package/skills/cocoar-vue-ui/references/components/card.md +151 -0
  87. package/skills/cocoar-vue-ui/references/components/checkbox-group.md +103 -0
  88. package/skills/cocoar-vue-ui/references/components/checkbox.md +279 -0
  89. package/skills/cocoar-vue-ui/references/components/code-block.md +241 -0
  90. package/skills/cocoar-vue-ui/references/components/context-menu.md +355 -0
  91. package/skills/cocoar-vue-ui/references/components/data-grid/checkbox.md +213 -0
  92. package/skills/cocoar-vue-ui/references/components/data-grid/date-columns.md +272 -0
  93. package/skills/cocoar-vue-ui/references/components/data-grid/editing.md +236 -0
  94. package/skills/cocoar-vue-ui/references/components/data-grid/multi-select.md +193 -0
  95. package/skills/cocoar-vue-ui/references/components/data-grid/number.md +147 -0
  96. package/skills/cocoar-vue-ui/references/components/data-grid/select.md +202 -0
  97. package/skills/cocoar-vue-ui/references/components/data-grid/text.md +127 -0
  98. package/skills/cocoar-vue-ui/references/components/data-grid.md +1225 -0
  99. package/skills/cocoar-vue-ui/references/components/data-list.md +2121 -0
  100. package/skills/cocoar-vue-ui/references/components/date-or-time-picker.md +200 -0
  101. package/skills/cocoar-vue-ui/references/components/date-picker.md +203 -0
  102. package/skills/cocoar-vue-ui/references/components/date-time-picker.md +154 -0
  103. package/skills/cocoar-vue-ui/references/components/date-views.md +212 -0
  104. package/skills/cocoar-vue-ui/references/components/dialog.md +148 -0
  105. package/skills/cocoar-vue-ui/references/components/divider.md +157 -0
  106. package/skills/cocoar-vue-ui/references/components/document-viewer/annotations.md +400 -0
  107. package/skills/cocoar-vue-ui/references/components/document-viewer/coar-document-viewer.md +327 -0
  108. package/skills/cocoar-vue-ui/references/components/document-viewer/index.md +234 -0
  109. package/skills/cocoar-vue-ui/references/components/document-viewer/toolbar.md +221 -0
  110. package/skills/cocoar-vue-ui/references/components/drag-drop.md +267 -0
  111. package/skills/cocoar-vue-ui/references/components/dual-listbox.md +449 -0
  112. package/skills/cocoar-vue-ui/references/components/file-explorer/asset-store.md +327 -0
  113. package/skills/cocoar-vue-ui/references/components/file-explorer/in-memory-store.md +176 -0
  114. package/skills/cocoar-vue-ui/references/components/file-explorer/index.md +311 -0
  115. package/skills/cocoar-vue-ui/references/components/file-explorer/use-file-explorer.md +300 -0
  116. package/skills/cocoar-vue-ui/references/components/form-field.md +1025 -0
  117. package/skills/cocoar-vue-ui/references/components/fragment-parser.md +298 -0
  118. package/skills/cocoar-vue-ui/references/components/link.md +235 -0
  119. package/skills/cocoar-vue-ui/references/components/listbox.md +575 -0
  120. package/skills/cocoar-vue-ui/references/components/map/editor.md +448 -0
  121. package/skills/cocoar-vue-ui/references/components/map/index.md +351 -0
  122. package/skills/cocoar-vue-ui/references/components/markdown-diagrams.md +210 -0
  123. package/skills/cocoar-vue-ui/references/components/markdown-editor.md +1478 -0
  124. package/skills/cocoar-vue-ui/references/components/markdown-embeds.md +387 -0
  125. package/skills/cocoar-vue-ui/references/components/markdown-form.md +447 -0
  126. package/skills/cocoar-vue-ui/references/components/markdown.md +276 -0
  127. package/skills/cocoar-vue-ui/references/components/menu.md +380 -0
  128. package/skills/cocoar-vue-ui/references/components/mermaid.md +172 -0
  129. package/skills/cocoar-vue-ui/references/components/navbar.md +147 -0
  130. package/skills/cocoar-vue-ui/references/components/note.md +96 -0
  131. package/skills/cocoar-vue-ui/references/components/notice.md +131 -0
  132. package/skills/cocoar-vue-ui/references/components/number-input.md +215 -0
  133. package/skills/cocoar-vue-ui/references/components/otp-input.md +324 -0
  134. package/skills/cocoar-vue-ui/references/components/page-builder/authoring-contract.md +271 -0
  135. package/skills/cocoar-vue-ui/references/components/page-builder/coar-page-builder.md +476 -0
  136. package/skills/cocoar-vue-ui/references/components/page-builder/coar-page-renderer.md +677 -0
  137. package/skills/cocoar-vue-ui/references/components/page-builder/custom-elements.md +441 -0
  138. package/skills/cocoar-vue-ui/references/components/page-builder/idp-integration.md +122 -0
  139. package/skills/cocoar-vue-ui/references/components/page-builder/index.md +573 -0
  140. package/skills/cocoar-vue-ui/references/components/pagination.md +150 -0
  141. package/skills/cocoar-vue-ui/references/components/panel-layout.md +372 -0
  142. package/skills/cocoar-vue-ui/references/components/password-input.md +175 -0
  143. package/skills/cocoar-vue-ui/references/components/popconfirm.md +186 -0
  144. package/skills/cocoar-vue-ui/references/components/popover.md +173 -0
  145. package/skills/cocoar-vue-ui/references/components/progress-bar.md +178 -0
  146. package/skills/cocoar-vue-ui/references/components/radio-group.md +225 -0
  147. package/skills/cocoar-vue-ui/references/components/script-editor.md +1271 -0
  148. package/skills/cocoar-vue-ui/references/components/segmented-control.md +238 -0
  149. package/skills/cocoar-vue-ui/references/components/select.md +463 -0
  150. package/skills/cocoar-vue-ui/references/components/sidebar.md +421 -0
  151. package/skills/cocoar-vue-ui/references/components/spinner.md +132 -0
  152. package/skills/cocoar-vue-ui/references/components/switch.md +195 -0
  153. package/skills/cocoar-vue-ui/references/components/table.md +170 -0
  154. package/skills/cocoar-vue-ui/references/components/tabs.md +382 -0
  155. package/skills/cocoar-vue-ui/references/components/tag.md +178 -0
  156. package/skills/cocoar-vue-ui/references/components/text-input.md +256 -0
  157. package/skills/cocoar-vue-ui/references/components/toast.md +160 -0
  158. package/skills/cocoar-vue-ui/references/components/tooltip.md +121 -0
  159. package/skills/cocoar-vue-ui/references/components/transitions.md +193 -0
  160. package/skills/cocoar-vue-ui/references/components/tree.md +2388 -0
  161. package/skills/cocoar-vue-ui/references/components/virtual-list.md +212 -0
  162. package/skills/cocoar-vue-ui/references/components/wizard.md +251 -0
  163. package/skills/cocoar-vue-ui/references/components/zoned-date-time-picker.md +177 -0
  164. package/skills/cocoar-vue-ui/references/foundations/colors.md +708 -0
  165. package/skills/cocoar-vue-ui/references/foundations/design-principles.md +115 -0
  166. package/skills/cocoar-vue-ui/references/foundations/icons.md +381 -0
  167. package/skills/cocoar-vue-ui/references/foundations/localization/formatting.md +530 -0
  168. package/skills/cocoar-vue-ui/references/foundations/localization/setup.md +86 -0
  169. package/skills/cocoar-vue-ui/references/foundations/localization/timezones.md +182 -0
  170. package/skills/cocoar-vue-ui/references/foundations/localization/translations.md +305 -0
  171. package/skills/cocoar-vue-ui/references/foundations/motion.md +549 -0
  172. package/skills/cocoar-vue-ui/references/foundations/spacing.md +330 -0
  173. package/skills/cocoar-vue-ui/references/foundations/theming.md +140 -0
  174. package/skills/cocoar-vue-ui/references/foundations/typography.md +206 -0
  175. package/skills/cocoar-vue-ui/references/guide/error-handling.md +162 -0
  176. package/skills/cocoar-vue-ui/references/guide/getting-started.md +119 -0
  177. package/skills/cocoar-vue-ui/references/guide/migration-page-builder-3.md +207 -0
  178. package/skills/cocoar-vue-ui/references/guide/migration.md +140 -0
  179. package/skills/cocoar-vue-ui/references/guide/theming.md +98 -0
@@ -0,0 +1,355 @@
1
+ <!-- Generated from apps/docs/components/context-menu.md by apps/docs/scripts/sync-skill.mjs. Do not edit; edit the docs page. -->
2
+
3
+ # Context Menu
4
+
5
+ Open a menu at the pointer position on right-click. The `useContextMenu` composable manages open/close state and cursor coordinates, while `CoarContextMenu` renders the menu as a floating overlay with automatic viewport clamping.
6
+
7
+ ```ts
8
+ import { useContextMenu, CoarContextMenu } from '@cocoar/vue-ui';
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ Call `useContextMenu()` to get a controller, bind `menu.open` to `@contextmenu`, and place your menu items inside `<CoarContextMenu>`. The menu closes automatically when an item is clicked, when clicking outside, pressing Escape, or scrolling.
14
+
15
+ **Demo — `context-menu/demos/ContextMenuBasic.vue`**
16
+
17
+ ```vue
18
+ <template>
19
+ <div>
20
+ <div
21
+ class="target-area"
22
+ @contextmenu="menu.open"
23
+ >
24
+ Right-click anywhere in this area
25
+ </div>
26
+
27
+ <CoarContextMenu :menu="menu">
28
+ <CoarMenuItem icon="copy" label="Copy" @clicked="onAction('Copy')" />
29
+ <CoarMenuItem icon="clipboard" label="Paste" @clicked="onAction('Paste')" />
30
+ <CoarMenuDivider />
31
+ <CoarMenuItem icon="pencil" label="Rename" @clicked="onAction('Rename')" />
32
+ <CoarMenuItem icon="trash-2" label="Delete" @clicked="onAction('Delete')" />
33
+ </CoarContextMenu>
34
+
35
+ <p class="status">Last action: {{ lastAction || 'none' }}</p>
36
+ </div>
37
+ </template>
38
+
39
+ <script setup lang="ts">
40
+ import { ref } from 'vue';
41
+ import { useContextMenu, CoarContextMenu, CoarMenuItem, CoarMenuDivider } from '@cocoar/vue-ui';
42
+
43
+ const menu = useContextMenu();
44
+ const lastAction = ref('');
45
+
46
+ function onAction(action: string) {
47
+ lastAction.value = action;
48
+ }
49
+ </script>
50
+
51
+ <style scoped>
52
+ .target-area {
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: center;
56
+ height: 160px;
57
+ border: 2px dashed var(--coar-border-neutral-tertiary);
58
+ border-radius: var(--coar-radius-m);
59
+ color: var(--coar-text-neutral-secondary);
60
+ font-size: var(--coar-font-size-s);
61
+ user-select: none;
62
+ }
63
+
64
+ .status {
65
+ margin-top: 8px;
66
+ font-size: 13px;
67
+ color: var(--coar-text-neutral-secondary);
68
+ }
69
+ </style>
70
+ ```
71
+
72
+ ## With Headings & Submenus
73
+
74
+ All standard menu features work inside context menus — headings, dividers, icons, and inline submenus via `CoarSubExpand`.
75
+
76
+ **Demo — `context-menu/demos/ContextMenuSubmenus.vue`**
77
+
78
+ ```vue
79
+ <template>
80
+ <div>
81
+ <div
82
+ class="target-area"
83
+ @contextmenu="menu.open"
84
+ >
85
+ Right-click for a menu with headings and submenus
86
+ </div>
87
+
88
+ <CoarContextMenu :menu="menu">
89
+ <CoarMenuHeading label="Edit" />
90
+ <CoarMenuItem icon="scissors" label="Cut" @clicked="onAction('Cut')" />
91
+ <CoarMenuItem icon="copy" label="Copy" @clicked="onAction('Copy')" />
92
+ <CoarMenuItem icon="clipboard" label="Paste" @clicked="onAction('Paste')" />
93
+ <CoarMenuDivider />
94
+ <CoarSubExpand label="Sort by" icon="arrow-up-down">
95
+ <CoarMenuItem label="Name" @clicked="onAction('Sort by Name')" />
96
+ <CoarMenuItem label="Date" @clicked="onAction('Sort by Date')" />
97
+ <CoarMenuItem label="Size" @clicked="onAction('Sort by Size')" />
98
+ </CoarSubExpand>
99
+ <CoarMenuDivider />
100
+ <CoarMenuItem icon="settings" label="Preferences" @clicked="onAction('Preferences')" />
101
+ </CoarContextMenu>
102
+
103
+ <p class="status">Last action: {{ lastAction || 'none' }}</p>
104
+ </div>
105
+ </template>
106
+
107
+ <script setup lang="ts">
108
+ import { ref } from 'vue';
109
+ import {
110
+ useContextMenu,
111
+ CoarContextMenu,
112
+ CoarMenuItem,
113
+ CoarMenuDivider,
114
+ CoarMenuHeading,
115
+ CoarSubExpand,
116
+ } from '@cocoar/vue-ui';
117
+
118
+ const menu = useContextMenu();
119
+ const lastAction = ref('');
120
+
121
+ function onAction(action: string) {
122
+ lastAction.value = action;
123
+ }
124
+ </script>
125
+
126
+ <style scoped>
127
+ .target-area {
128
+ display: flex;
129
+ align-items: center;
130
+ justify-content: center;
131
+ height: 160px;
132
+ border: 2px dashed var(--coar-border-neutral-tertiary);
133
+ border-radius: var(--coar-radius-m);
134
+ color: var(--coar-text-neutral-secondary);
135
+ font-size: var(--coar-font-size-s);
136
+ user-select: none;
137
+ }
138
+
139
+ .status {
140
+ margin-top: 8px;
141
+ font-size: 13px;
142
+ color: var(--coar-text-neutral-secondary);
143
+ }
144
+ </style>
145
+ ```
146
+
147
+ ## Flyout Submenus
148
+
149
+ Use `CoarSubFlyout` inside a context menu for nested flyout panels — useful for status changes, priority selectors, etc.
150
+
151
+ **Demo — `context-menu/demos/ContextMenuFlyout.vue`**
152
+
153
+ ```vue
154
+ <template>
155
+ <div>
156
+ <div class="target-area" @contextmenu="menu.open">
157
+ Right-click for a menu with flyout submenus
158
+ </div>
159
+
160
+ <CoarContextMenu :menu="menu">
161
+ <CoarMenuItem icon="pencil" label="Edit" @clicked="onAction('Edit')" />
162
+ <CoarMenuDivider />
163
+ <CoarSubFlyout label="Set Status" icon="circle-alert">
164
+ <CoarMenu>
165
+ <CoarMenuItem label="New" @clicked="onAction('Status: New')" />
166
+ <CoarMenuItem label="In Progress" @clicked="onAction('Status: In Progress')" />
167
+ <CoarMenuItem label="Done" @clicked="onAction('Status: Done')" />
168
+ </CoarMenu>
169
+ </CoarSubFlyout>
170
+ <CoarSubFlyout label="Priority" icon="flag">
171
+ <CoarMenu>
172
+ <CoarMenuItem label="Low" @clicked="onAction('Priority: Low')" />
173
+ <CoarMenuItem label="Medium" @clicked="onAction('Priority: Medium')" />
174
+ <CoarMenuItem label="High" @clicked="onAction('Priority: High')" />
175
+ </CoarMenu>
176
+ </CoarSubFlyout>
177
+ <CoarMenuDivider />
178
+ <CoarMenuItem icon="trash-2" label="Delete" @clicked="onAction('Delete')" />
179
+ </CoarContextMenu>
180
+
181
+ <p class="status">Last action: {{ lastAction || 'none' }}</p>
182
+ </div>
183
+ </template>
184
+
185
+ <script setup lang="ts">
186
+ import { ref } from 'vue';
187
+ import {
188
+ useContextMenu,
189
+ CoarContextMenu,
190
+ CoarMenu,
191
+ CoarMenuItem,
192
+ CoarMenuDivider,
193
+ CoarSubFlyout,
194
+ } from '@cocoar/vue-ui';
195
+
196
+ const menu = useContextMenu();
197
+ const lastAction = ref('');
198
+
199
+ function onAction(action: string) {
200
+ lastAction.value = action;
201
+ }
202
+ </script>
203
+
204
+ <style scoped>
205
+ .target-area {
206
+ display: flex;
207
+ align-items: center;
208
+ justify-content: center;
209
+ height: 160px;
210
+ border: 2px dashed var(--coar-border-neutral-tertiary);
211
+ border-radius: var(--coar-radius-m);
212
+ color: var(--coar-text-neutral-secondary);
213
+ font-size: var(--coar-font-size-s);
214
+ user-select: none;
215
+ }
216
+
217
+ .status {
218
+ margin-top: 8px;
219
+ font-size: 13px;
220
+ color: var(--coar-text-neutral-secondary);
221
+ }
222
+ </style>
223
+ ```
224
+
225
+ ## Data Grid Integration
226
+
227
+ Use separate `useContextMenu()` instances for cell and viewport right-clicks. The data grid builder provides `onCellContextMenu` and `onViewportContextMenu` handlers that give you the mouse event to pass into `menu.open()`.
228
+
229
+ **Demo — `context-menu/demos/ContextMenuDataGrid.vue`**
230
+
231
+ ```vue
232
+ <template>
233
+ <div>
234
+ <div style="height: 300px;">
235
+ <CoarDataGrid :builder="builder" />
236
+ </div>
237
+
238
+ <!-- Cell context menu (right-click on a row) -->
239
+ <CoarContextMenu :menu="cellMenu">
240
+ <CoarMenuItem icon="pencil" label="Edit" @clicked="onCellAction('Edit', selectedUser)" />
241
+ <CoarMenuItem icon="copy" label="Duplicate" @clicked="onCellAction('Duplicate', selectedUser)" />
242
+ <CoarMenuDivider />
243
+ <CoarMenuItem icon="trash-2" label="Delete" @clicked="onCellAction('Delete', selectedUser)" />
244
+ </CoarContextMenu>
245
+
246
+ <!-- Viewport context menu (right-click on empty area) -->
247
+ <CoarContextMenu :menu="viewportMenu">
248
+ <CoarMenuItem icon="plus" label="Add user" @clicked="onViewportAction('Add user')" />
249
+ <CoarMenuItem icon="refresh-cw" label="Refresh" @clicked="onViewportAction('Refresh')" />
250
+ </CoarContextMenu>
251
+
252
+ <p class="status">Last action: {{ lastAction || 'none' }}</p>
253
+ </div>
254
+ </template>
255
+
256
+ <script setup lang="ts">
257
+ import { ref } from 'vue';
258
+ import { CoarDataGrid, CoarGridBuilder } from '@cocoar/vue-data-grid';
259
+ import type { CellContextMenuEvent } from '@cocoar/vue-data-grid';
260
+ import { useContextMenu, CoarContextMenu, CoarMenuItem, CoarMenuDivider } from '@cocoar/vue-ui';
261
+
262
+ interface User {
263
+ name: string;
264
+ email: string;
265
+ role: string;
266
+ }
267
+
268
+ const data: User[] = [
269
+ { name: 'Alice Johnson', email: 'alice@example.com', role: 'Engineer' },
270
+ { name: 'Bob Smith', email: 'bob@example.com', role: 'Designer' },
271
+ { name: 'Carol Williams', email: 'carol@example.com', role: 'Manager' },
272
+ { name: 'David Brown', email: 'david@example.com', role: 'Engineer' },
273
+ { name: 'Eve Davis', email: 'eve@example.com', role: 'Designer' },
274
+ ];
275
+
276
+ const cellMenu = useContextMenu();
277
+ const viewportMenu = useContextMenu();
278
+ const selectedUser = ref<User | null>(null);
279
+ const lastAction = ref('');
280
+
281
+ const builder = CoarGridBuilder.create<User>()
282
+ .columns([
283
+ (col) => col.field('name').header('Name').flex(1),
284
+ (col) => col.field('email').header('Email').flex(1),
285
+ (col) => col.field('role').header('Role').width(120),
286
+ ])
287
+ .rowData(data)
288
+ .onCellContextMenu((event: CellContextMenuEvent<User>) => {
289
+ selectedUser.value = event.data ?? null;
290
+ if (event.event) {
291
+ cellMenu.open(event.event as MouseEvent);
292
+ }
293
+ })
294
+ .onViewportContextMenu((event: MouseEvent) => {
295
+ viewportMenu.open(event);
296
+ });
297
+
298
+ function onCellAction(action: string, user: User | null) {
299
+ lastAction.value = `${action}: ${user?.name ?? 'unknown'}`;
300
+ }
301
+
302
+ function onViewportAction(action: string) {
303
+ lastAction.value = action;
304
+ }
305
+ </script>
306
+
307
+ <style scoped>
308
+ .status {
309
+ margin-top: 8px;
310
+ font-size: 13px;
311
+ color: var(--coar-text-neutral-secondary);
312
+ }
313
+ </style>
314
+ ```
315
+
316
+ ## Keeping the Menu Open
317
+
318
+ By default, clicking a `CoarMenuItem` closes the entire context menu. Call `keepMenuOpen()` on the click event to prevent this — useful for toggles or multi-select actions.
319
+
320
+ ```vue
321
+ <CoarMenuItem
322
+ label="Toggle dark mode"
323
+ icon="moon"
324
+ @clicked="(e) => { e.keepMenuOpen(); toggleDarkMode(); }"
325
+ />
326
+ ```
327
+
328
+ ## API
329
+
330
+ ### `useContextMenu()`
331
+
332
+ Returns a `ContextMenuContext` object:
333
+
334
+ | Property | Type | Description |
335
+ |------------|-------------------------------|------------------------------------------------|
336
+ | `isOpen` | `Readonly<Ref<boolean>>` | Whether the menu is currently visible |
337
+ | `position` | `Readonly<Ref<{x, y}>>` | Cursor position where the menu was opened |
338
+ | `open` | `(event: MouseEvent) => void` | Open at the event's cursor position |
339
+ | `close` | `() => void` | Close the menu |
340
+
341
+ ### `<CoarContextMenu>`
342
+
343
+ | Prop | Type | Required | Description |
344
+ |--------|----------------------|----------|------------------------------------------|
345
+ | `menu` | `ContextMenuContext` | Yes | Controller returned by `useContextMenu()` |
346
+
347
+ **Slot:** `default` — menu items (`CoarMenuItem`, `CoarMenuDivider`, `CoarMenuHeading`, `CoarSubExpand`, etc.)
348
+
349
+ ### Behavior
350
+
351
+ - **Viewport clamping** — the menu repositions to stay within the window
352
+ - **Click outside** — closes the menu
353
+ - **Escape** — closes the menu
354
+ - **Scroll** — closes the menu
355
+ - **Auto-close on item click** — unless `keepMenuOpen()` is called
@@ -0,0 +1,213 @@
1
+ <!-- Generated from apps/docs/components/data-grid/checkbox.md by apps/docs/scripts/sync-skill.mjs. Do not edit; edit the docs page. -->
2
+
3
+ # Checkbox Column
4
+
5
+ `col.checkbox(field, configurator?)` renders a `<CoarCheckbox>` in each cell — same visual language as forms, just sized to fit the row. The renderer is **always read-only**; interactivity comes from edit-mode, exactly like text/number/select columns.
6
+
7
+ ```ts
8
+ import { CoarGridBuilder } from '@cocoar/vue-data-grid';
9
+
10
+ CoarGridBuilder.create<Task>().columns([
11
+ (col) => col.checkbox('done').editable(true),
12
+ (col) => col.field('title').flex(1),
13
+ ])
14
+ ```
15
+
16
+ ## Edit-mode flow
17
+
18
+ Without `.editable()` the checkbox is a read-only indicator. Adding `.editable(true)` (or a row-predicate) opts the column into AG Grid's standard edit-mode flow:
19
+
20
+ | Action | Result |
21
+ |--------|--------|
22
+ | Double-click cell (or Enter / F2) | Opens `CoarCheckboxCellEditor` — interactive `<CoarCheckbox>` with focus on the input |
23
+ | Space | Toggles the checkbox |
24
+ | Tab | Commits + moves focus to the next editable cell, **opening its editor automatically** |
25
+ | Enter | Commits + stays |
26
+ | Escape | Cancels |
27
+
28
+ The Tab-through-edit-mode pattern is AG Grid's native data-entry workflow — keyboard users can fly through editable cells without ever touching the mouse. Pair with `gridBuilder.stopEditingWhenCellsLoseFocus()` so clicking outside also commits.
29
+
30
+ Toggles fire `cellValueChanged` like any other editor commit, so a single `gridBuilder.onCellValueChanged()` handler covers all column types — checkbox, text, number, custom editors.
31
+
32
+ ## Editable + per-row gating
33
+
34
+ Pass a row-predicate to `.editable()` to disable the editor for individual rows. Locked rows render a read-only checkbox and can't be entered.
35
+
36
+ **Demo — `data-grid/demos/GridCheckbox.vue`**
37
+
38
+ ```vue
39
+ <template>
40
+ <div>
41
+ <div style="height: 320px;">
42
+ <CoarDataGrid :builder="builder" />
43
+ </div>
44
+ <div style="margin-top: 12px; font-size: 13px; color: var(--coar-text-neutral-secondary);">
45
+ Double-click any "done" cell to enter edit mode. <strong>Space</strong> toggles, <strong>Tab</strong> commits and moves to the next editable cell, <strong>Escape</strong> cancels. Locked rows can't be entered.
46
+ </div>
47
+ <div
48
+ v-if="lastChange"
49
+ style="margin-top: 8px; padding: 8px 12px; border-radius: 6px; background: var(--coar-surface-neutral-subtle); font-size: 13px;"
50
+ >
51
+ Last change: <strong>{{ lastChange.task }}</strong> —
52
+ <code>done</code> →
53
+ <strong>{{ lastChange.value ? 'true' : 'false' }}</strong>
54
+ </div>
55
+ </div>
56
+ </template>
57
+
58
+ <script setup lang="ts">
59
+ import { ref, shallowRef } from 'vue';
60
+ import { CoarDataGrid, CoarGridBuilder } from '@cocoar/vue-data-grid';
61
+
62
+ interface Task {
63
+ id: number;
64
+ task: string;
65
+ done: boolean;
66
+ locked: boolean;
67
+ }
68
+
69
+ const data = ref<Task[]>([
70
+ { id: 1, task: 'Write specification', done: true, locked: false },
71
+ { id: 2, task: 'Implement renderer', done: false, locked: false },
72
+ { id: 3, task: 'Ship to production', done: false, locked: true },
73
+ { id: 4, task: 'Update changelog', done: true, locked: false },
74
+ { id: 5, task: 'Archive (legacy)', done: true, locked: true },
75
+ ]);
76
+
77
+ const lastChange = shallowRef<{ task: string; value: boolean } | null>(null);
78
+
79
+ const builder = CoarGridBuilder.create<Task>()
80
+ .columns([
81
+ (col) => col.checkbox('done').width(70).editable((row) => !row.locked),
82
+ (col) => col.field('task').header('Task').flex(1),
83
+ (col) => col.checkbox('locked').width(90),
84
+ ])
85
+ .rowDataRef(data)
86
+ .stopEditingWhenCellsLoseFocus()
87
+ .onCellValueChanged((event) => {
88
+ if (event.colDef.field !== 'done' || !event.data) return;
89
+ lastChange.value = { task: event.data.task, value: event.newValue };
90
+ });
91
+ </script>
92
+ ```
93
+
94
+ ```ts
95
+ CoarGridBuilder.create<Task>().columns([
96
+ (col) => col.checkbox('done').editable(row => !row.locked),
97
+ (col) => col.field('task').flex(1),
98
+ (col) => col.checkbox('locked'), // read-only indicator
99
+ ])
100
+ .stopEditingWhenCellsLoseFocus()
101
+ .onCellValueChanged((event) => {
102
+ if (event.colDef.field === 'done') save(event.data);
103
+ });
104
+ ```
105
+
106
+ ## States — read-only, editable, indeterminate
107
+
108
+ Three independent states, all using the same `col.checkbox()` shortcut:
109
+
110
+ - **Read-only:** omit `.editable()` — checkbox is rendered, edit-mode never opens.
111
+ - **Editable:** add `.editable(true)` or `.editable(row => …)`.
112
+ - **Indeterminate (tri-state):** pass `c.indeterminate(row => …)` in the configurator. Useful for "partial" or "in-progress" states where the row's value isn't a clean true/false. The indeterminate state is shown in both renderer and editor.
113
+
114
+ **Demo — `data-grid/demos/GridCheckboxStates.vue`**
115
+
116
+ ```vue
117
+ <template>
118
+ <div style="height: 320px;">
119
+ <CoarDataGrid :builder="builder" />
120
+ </div>
121
+ </template>
122
+
123
+ <script setup lang="ts">
124
+ import { ref } from 'vue';
125
+ import { CoarDataGrid, CoarGridBuilder } from '@cocoar/vue-data-grid';
126
+
127
+ interface Feature {
128
+ id: number;
129
+ name: string;
130
+ enabled: boolean;
131
+ rolloutComplete: boolean;
132
+ partial: boolean;
133
+ }
134
+
135
+ const data = ref<Feature[]>([
136
+ { id: 1, name: 'Dark mode', enabled: true, rolloutComplete: true, partial: false },
137
+ { id: 2, name: 'Calendar view', enabled: true, rolloutComplete: false, partial: true },
138
+ { id: 3, name: 'Bulk export', enabled: false, rolloutComplete: false, partial: false },
139
+ { id: 4, name: 'Beta dashboard', enabled: true, rolloutComplete: false, partial: true },
140
+ ]);
141
+
142
+ const builder = CoarGridBuilder.create<Feature>()
143
+ .columns([
144
+ (col) => col.field('name').header('Feature').flex(1),
145
+ // editable, no label
146
+ (col) =>
147
+ col
148
+ .checkbox('enabled')
149
+ .header('Enabled')
150
+ .width(110)
151
+ .editable(true),
152
+ // editable + tri-state indeterminate when partial rollout
153
+ (col) =>
154
+ col
155
+ .checkbox('rolloutComplete', (c) => c.indeterminate((row) => row.partial && !row.rolloutComplete))
156
+ .header('Rollout')
157
+ .width(110)
158
+ .editable(true),
159
+ // read-only indicator (no .editable())
160
+ (col) =>
161
+ col
162
+ .checkbox('partial')
163
+ .header('Partial')
164
+ .width(110),
165
+ ])
166
+ .rowDataRef(data)
167
+ .stopEditingWhenCellsLoseFocus();
168
+ </script>
169
+ ```
170
+
171
+ ```ts
172
+ col.checkbox('rolloutComplete', c => c
173
+ .indeterminate(row => row.partial && !row.rolloutComplete)
174
+ ).editable(true)
175
+ ```
176
+
177
+ ## Layered overrides
178
+
179
+ The shortcut bundles renderer + editor with the configurator's options. Subsequent calls on the chain override (last-write-wins):
180
+
181
+ ```ts
182
+ // Replace the renderer entirely (drops the configurator)
183
+ col.checkbox('done').cellRenderer(MyOwnCheckbox)
184
+
185
+ // Replace just the editor (e.g. a select-style "yes/no/maybe" widget)
186
+ col.checkbox('done').editable(true).cellEditorConfig(MyTriStateEditor, { ... })
187
+
188
+ // Keep the bundled renderer + editor, override editable
189
+ col.checkbox('done').editable(false)
190
+ ```
191
+
192
+ ## API
193
+
194
+ ### `col.checkbox(field, configurator?)`
195
+
196
+ | Configurator method | Type | Description |
197
+ |--------|------|-------------|
198
+ | `.label(value)` | `string \| (row) => string` | Optional label rendered next to the checkbox (in both renderer and editor) |
199
+ | `.indeterminate(predicate)` | `(row) => boolean` | Tri-state indicator per row |
200
+ | `.size(value)` | `'xs' \| 's' \| 'm' \| 'l'` | Checkbox size (default: `'s'`) |
201
+
202
+ The configurator config is passed identically to both `CoarCheckboxCellRenderer` and `CoarCheckboxCellEditor`, so display and edit look the same — only behavior changes.
203
+
204
+ Interactive state comes from the outer chain:
205
+
206
+ | Outer chain | Result |
207
+ |-------------|--------|
208
+ | no `.editable()` | Read-only — edit-mode never opens |
209
+ | `.editable(true)` | Edit-mode opens on double-click / Enter / F2 |
210
+ | `.editable(false)` | Read-only |
211
+ | `.editable(row => …)` | Per-row predicate — edit-mode opens only when `true` |
212
+
213
+ Commit behavior: the editor exposes `getValue()` per AG Grid's contract. Tab/Enter/Escape are handled by AG Grid's native edit-mode logic. Combine with `gridBuilder.stopEditingWhenCellsLoseFocus()` so clicking outside the editor also commits.