@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,272 @@
1
+ <!-- Generated from apps/docs/components/data-grid/date-columns.md by apps/docs/scripts/sync-skill.mjs. Do not edit; edit the docs page. -->
2
+
3
+ # Date Columns (New in 2.0)
4
+
5
+ Three Temporal-typed column shortcuts for date / date-time / zoned-date-time cells. All three follow the same pattern: a renderer that formats locale-aware via `toLocaleString`, an editor that wraps the matching `<CoarPlainDatePicker>` / `<CoarPlainDateTimePicker>` / `<CoarZonedDateTimePicker>` component.
6
+
7
+ | | Cell value | Renderer format | Editor |
8
+ |--|--|--|--|
9
+ | **`col.plainDate()`** | `Temporal.PlainDate \| null` | `15. Mai 2026` (date-style: medium) | `CoarPlainDatePicker` |
10
+ | **`col.plainDateTime()`** | `Temporal.PlainDateTime \| null` | `15. Mai 2026, 14:30` (date-style: medium + time-style: short) | `CoarPlainDateTimePicker` |
11
+ | **`col.zonedDateTime()`** | `Temporal.ZonedDateTime \| null` | `15. Mai 2026, 14:30 GMT+2` (+ short zone-name suffix) | `CoarZonedDateTimePicker` |
12
+
13
+ ```ts
14
+ import { CoarGridBuilder } from '@cocoar/vue-data-grid';
15
+ import { Temporal } from '@js-temporal/polyfill';
16
+
17
+ CoarGridBuilder.create<Task>().columns([
18
+ (col) => col.plainDate('startsOn', d => d.highlightWeekends())
19
+ .editable(true),
20
+
21
+ (col) => col.plainDateTime('reminderAt')
22
+ .editable(true),
23
+
24
+ (col) => col.zonedDateTime('eventAt', d => d.timeZone('Europe/Vienna'))
25
+ .editable(true),
26
+ ])
27
+ ```
28
+
29
+ > **Info: Temporal-only contract**
30
+ >
31
+ > All three column shortcuts require the cell value to be the matching `Temporal` type (or `null`). ISO strings, native `Date`, floating `Temporal.PlainDateTime` in a `zonedDateTime` column — all rejected: the renderer shows empty, the editor falls back to `null`. Convert at the data layer (typically in the row mapper that turns API responses into grid rows). This matches `@cocoar/vue-calendar`'s Temporal-only contract — when a row's date round-trips between the grid and the calendar, both sides agree on the type.
32
+ >
33
+ > The legacy `col.date(field, config?)` shortcut (display-only, accepts `Date | string`) is unchanged for back-compat with existing consumer columns.
34
+
35
+ ## Edit-mode flow
36
+
37
+ | Action | Result |
38
+ |--------|--------|
39
+ | Double-click cell (or Enter / F2) | Opens the editor and focuses the picker's trigger. The picker handles its own open / navigate / select keystrokes. |
40
+ | Click outside / Tab / Enter (after selection) | AG Grid commits via `getValue()` — `Temporal.PlainDate` / `PlainDateTime` / `ZonedDateTime` (or `null` if cleared). |
41
+ | Escape | Cancels (no commit). |
42
+
43
+ Focus-preservation (capture-phase `mousedown` listener that `preventDefault`s on `.coar-overlay-host` targets) prevents AG Grid from committing prematurely while the user navigates the body-teleported picker panel.
44
+
45
+ ## `col.plainDate(field, configurator?)`
46
+
47
+ **Demo — `data-grid/demos/GridPlainDate.vue`**
48
+
49
+ ```vue
50
+ <template>
51
+ <div>
52
+ <div style="height: 320px;">
53
+ <CoarDataGrid :builder="builder" />
54
+ </div>
55
+ <div style="margin-top: 12px; font-size: 13px; color: var(--coar-text-neutral-secondary);">
56
+ Double-click any date cell. Cell value is <code>Temporal.PlainDate</code> — the renderer formats locale-aware, the editor opens <code>CoarPlainDatePicker</code>.
57
+ </div>
58
+ <div
59
+ v-if="lastChange"
60
+ style="margin-top: 8px; padding: 8px 12px; border-radius: 6px; background: var(--coar-surface-neutral-subtle); font-size: 13px;"
61
+ >
62
+ Last change: <strong>{{ lastChange.row }}</strong> —
63
+ <code>{{ lastChange.field }}</code> →
64
+ <strong>{{ lastChange.newValue }}</strong>
65
+ </div>
66
+ </div>
67
+ </template>
68
+
69
+ <script setup lang="ts">
70
+ import { ref, shallowRef } from 'vue';
71
+ import { Temporal } from '@js-temporal/polyfill';
72
+ import { CoarDataGrid, CoarGridBuilder } from '@cocoar/vue-data-grid';
73
+
74
+ interface Task {
75
+ id: number;
76
+ title: string;
77
+ startsOn: Temporal.PlainDate | null;
78
+ dueOn: Temporal.PlainDate | null;
79
+ }
80
+
81
+ const data = ref<Task[]>([
82
+ { id: 1, title: 'Write spec', startsOn: Temporal.PlainDate.from('2026-05-12'), dueOn: Temporal.PlainDate.from('2026-05-15') },
83
+ { id: 2, title: 'Implement', startsOn: Temporal.PlainDate.from('2026-05-16'), dueOn: Temporal.PlainDate.from('2026-05-22') },
84
+ { id: 3, title: 'Review', startsOn: null, dueOn: Temporal.PlainDate.from('2026-05-25') },
85
+ { id: 4, title: 'Deploy', startsOn: Temporal.PlainDate.from('2026-05-26'), dueOn: null },
86
+ ]);
87
+
88
+ const lastChange = shallowRef<{ row: string; field: string; newValue: string } | null>(null);
89
+
90
+ const builder = CoarGridBuilder.create<Task>()
91
+ .columns([
92
+ (col) => col.field('title').header('Title').flex(1),
93
+ (col) =>
94
+ col
95
+ .plainDate('startsOn', (d) => d.size('s').highlightWeekends())
96
+ .header('Starts')
97
+ .width(160)
98
+ .editable(true),
99
+ (col) =>
100
+ col
101
+ .plainDate('dueOn', (d) =>
102
+ d.size('s').showWeekNumbers().min(Temporal.PlainDate.from('2026-01-01')),
103
+ )
104
+ .header('Due')
105
+ .width(160)
106
+ .editable(true),
107
+ ])
108
+ .rowDataRef(data)
109
+ .stopEditingWhenCellsLoseFocus()
110
+ .onCellValueChanged((event) => {
111
+ if (!event.data || !event.colDef.field) return;
112
+ const v = event.newValue as Temporal.PlainDate | null;
113
+ lastChange.value = {
114
+ row: event.data.title,
115
+ field: event.colDef.field,
116
+ newValue: v?.toString() ?? '∅',
117
+ };
118
+ });
119
+ </script>
120
+ ```
121
+
122
+ | Configurator method | Type | Description |
123
+ |---|---|---|
124
+ | `.size(value)` | `'xs' \| 's' \| 'm' \| 'l'` | Trigger size (default: `'s'`) |
125
+ | `.clearable(value?)` | `boolean = true` | Show a clear button inside the picker (default: `true`) |
126
+ | `.min(value)` | `Temporal.PlainDate \| null` | Minimum selectable date |
127
+ | `.max(value)` | `Temporal.PlainDate \| null` | Maximum selectable date |
128
+ | `.showWeekNumbers(value?)` | `boolean = true` | Show ISO week numbers in the calendar panel |
129
+ | `.highlightWeekends(value?)` | `boolean = true` | Visually highlight Saturday + Sunday |
130
+ | `.markers(value)` | `CoarDateMarker[] \| (row) => CoarDateMarker[]` | Date markers (dot / ring / underline) |
131
+ | `.locale(value)` | `string` | Locale override (defaults to consumer-app locale via `useL10n()`) |
132
+
133
+ ## `col.plainDateTime(field, configurator?)`
134
+
135
+ **Demo — `data-grid/demos/GridPlainDateTime.vue`**
136
+
137
+ ```vue
138
+ <template>
139
+ <div>
140
+ <div style="height: 280px;">
141
+ <CoarDataGrid :builder="builder" />
142
+ </div>
143
+ <div style="margin-top: 12px; font-size: 13px; color: var(--coar-text-neutral-secondary);">
144
+ Double-click any cell. Cell value is <code>Temporal.PlainDateTime</code> — a floating wallclock (no zone).
145
+ </div>
146
+ </div>
147
+ </template>
148
+
149
+ <script setup lang="ts">
150
+ import { ref } from 'vue';
151
+ import { Temporal } from '@js-temporal/polyfill';
152
+ import { CoarDataGrid, CoarGridBuilder } from '@cocoar/vue-data-grid';
153
+
154
+ interface Reminder {
155
+ id: number;
156
+ title: string;
157
+ at: Temporal.PlainDateTime | null;
158
+ }
159
+
160
+ const data = ref<Reminder[]>([
161
+ { id: 1, title: 'Morning standup', at: Temporal.PlainDateTime.from('2026-05-13T09:00:00') },
162
+ { id: 2, title: 'Code review', at: Temporal.PlainDateTime.from('2026-05-13T14:30:00') },
163
+ { id: 3, title: 'No reminder yet', at: null },
164
+ ]);
165
+
166
+ const builder = CoarGridBuilder.create<Reminder>()
167
+ .columns([
168
+ (col) => col.field('title').header('Title').flex(1),
169
+ (col) =>
170
+ col
171
+ .plainDateTime('at', (d) => d.size('s'))
172
+ .header('When')
173
+ .width(220)
174
+ .editable(true),
175
+ ])
176
+ .rowDataRef(data)
177
+ .stopEditingWhenCellsLoseFocus();
178
+ </script>
179
+ ```
180
+
181
+ Same configurator surface as `col.plainDate()`, but `min` / `max` accept `Temporal.PlainDateTime`.
182
+
183
+ Use this when the time-of-day matters but the event has no fixed zone (calendar-local reminders, scheduled-locally tasks). For cross-zone events, use `col.zonedDateTime()`.
184
+
185
+ ## `col.zonedDateTime(field, configurator?)`
186
+
187
+ **Demo — `data-grid/demos/GridZonedDateTime.vue`**
188
+
189
+ ```vue
190
+ <template>
191
+ <div>
192
+ <div style="height: 320px;">
193
+ <CoarDataGrid :builder="builder" />
194
+ </div>
195
+ <div style="margin-top: 12px; font-size: 13px; color: var(--coar-text-neutral-secondary);">
196
+ Double-click <code>startsAt</code>. Cell value is <code>Temporal.ZonedDateTime</code> — same instant displayed in each event's own zone. Each row's zone is preserved through editing unless the user explicitly changes it via the picker.
197
+ </div>
198
+ </div>
199
+ </template>
200
+
201
+ <script setup lang="ts">
202
+ import { ref } from 'vue';
203
+ import { Temporal } from '@js-temporal/polyfill';
204
+ import { CoarDataGrid, CoarGridBuilder } from '@cocoar/vue-data-grid';
205
+
206
+ interface Meeting {
207
+ id: number;
208
+ title: string;
209
+ startsAt: Temporal.ZonedDateTime | null;
210
+ }
211
+
212
+ const data = ref<Meeting[]>([
213
+ { id: 1, title: 'EU sync', startsAt: Temporal.ZonedDateTime.from('2026-05-13T10:00:00[Europe/Vienna]') },
214
+ { id: 2, title: 'US sync', startsAt: Temporal.ZonedDateTime.from('2026-05-13T15:00:00[America/New_York]') },
215
+ { id: 3, title: 'AP sync', startsAt: Temporal.ZonedDateTime.from('2026-05-14T09:00:00[Asia/Tokyo]') },
216
+ { id: 4, title: 'No slot', startsAt: null },
217
+ ]);
218
+
219
+ const builder = CoarGridBuilder.create<Meeting>()
220
+ .columns([
221
+ (col) => col.field('title').header('Meeting').flex(1),
222
+ (col) =>
223
+ col
224
+ .zonedDateTime('startsAt', (d) =>
225
+ d.size('s').timeZone('Europe/Vienna').timezoneFilter(['Europe/*', 'America/*', 'Asia/*']),
226
+ )
227
+ .header('Starts at')
228
+ .width(280)
229
+ .editable(true),
230
+ ])
231
+ .rowDataRef(data)
232
+ .stopEditingWhenCellsLoseFocus();
233
+ </script>
234
+ ```
235
+
236
+ | Configurator method | Type | Description |
237
+ |---|---|---|
238
+ | `.size(value)` | `'xs' \| 's' \| 'm' \| 'l'` | Trigger size (default: `'s'`) |
239
+ | `.clearable(value?)` | `boolean = true` | Show a clear button inside the picker (default: `true`) |
240
+ | `.min(value)` | `Temporal.ZonedDateTime \| null` | Minimum selectable instant |
241
+ | `.max(value)` | `Temporal.ZonedDateTime \| null` | Maximum selectable instant |
242
+ | `.showWeekNumbers(value?)` | `boolean = true` | Show ISO week numbers |
243
+ | `.highlightWeekends(value?)` | `boolean = true` | Highlight Saturday + Sunday |
244
+ | `.markers(value)` | `CoarDateMarker[] \| (row) => CoarDateMarker[]` | Date markers |
245
+ | `.locale(value)` | `string` | Locale override |
246
+ | `.timeZone(value)` | `string` | **Default IANA zone** for newly-created values (cell was empty before the edit). Existing values keep their own zone. |
247
+ | `.timezoneFilter(value)` | `string[]` | Wildcard filter patterns for the zone selector (e.g. `['Europe/*', 'America/*']`) |
248
+ | `.displayTimeZone(value)` | `string` | **Renderer-only.** Project every row's instant into this zone for display (e.g. `'Europe/Vienna'` to render every event in Vienna time for cross-zone coordination views). When omitted, each row renders in its own value's zone. |
249
+
250
+ The renderer formats each cell in its own zone — a row whose value lives in `America/New_York` displays the New York wallclock + a `GMT-5` (or `GMT-4` in summer) suffix, regardless of the user's browser zone. Cross-zone columns stay unambiguous at a glance.
251
+
252
+ ## Row-aware markers
253
+
254
+ `markers` accepts a function for per-row decorations — useful when the calendar should highlight different dates depending on the row:
255
+
256
+ ```ts
257
+ col.plainDate('startsOn', d =>
258
+ d.markers(row => [
259
+ { date: row.deadline, variant: 'underline', color: 'var(--coar-color-warning-bold)' },
260
+ ])
261
+ ).editable(true)
262
+ ```
263
+
264
+ ## Layered overrides
265
+
266
+ Same escape-hatches as the other column shortcuts:
267
+
268
+ ```ts
269
+ col.plainDate('startsOn', d => d.size('s'))
270
+ .editable(true)
271
+ .cellEditorConfig(MyCustomDateEditor, { /* ... */ })
272
+ ```
@@ -0,0 +1,236 @@
1
+ <!-- Generated from apps/docs/components/data-grid/editing.md by apps/docs/scripts/sync-skill.mjs. Do not edit; edit the docs page. -->
2
+
3
+ # Editing
4
+
5
+ In-cell editing is exposed through three builder methods that map directly onto AG Grid's editor lifecycle:
6
+
7
+ | Method | Level | Purpose |
8
+ |--------|-------|---------|
9
+ | `column.editable(value)` | column | Enable editing — `boolean` or `(row) => boolean` predicate |
10
+ | `column.cellEditorConfig(component, config)` | column | Plug in a custom Vue editor component (mirrors `cellRendererConfig`) |
11
+ | `gridBuilder.onCellValueChanged(handler)` | grid | React to a committed cell edit |
12
+
13
+ `editable()` and `cellEditorConfig()` are **orthogonal** — set both, otherwise the editor never opens. If you only set `editable(true)`, the cell uses AG Grid's built-in text editor.
14
+
15
+ ## Default Editor
16
+
17
+ `.editable(true)` enables the default text editor. Editing starts on **double-click** (or pressing Enter / F2 with a cell focused). Enter commits, Escape cancels.
18
+
19
+ A row predicate gates editing per-row — locked items in the demo below skip the editor entirely:
20
+
21
+ ```ts
22
+ (col) => col.field('name').editable(row => !row.locked)
23
+ ```
24
+
25
+ `onCellValueChanged` fires once per committed edit and surfaces both the previous and new value. The demo updates a status line below the grid:
26
+
27
+ **Demo — `data-grid/demos/GridEditing.vue`**
28
+
29
+ ```vue
30
+ <template>
31
+ <div>
32
+ <div style="height: 320px;">
33
+ <CoarDataGrid :builder="builder" />
34
+ </div>
35
+ <div style="margin-top: 12px; font-size: 13px; color: var(--coar-text-neutral-secondary);">
36
+ Double-click any cell to edit. Enter commits, Escape cancels. Locked rows can't be edited.
37
+ </div>
38
+ <div
39
+ v-if="lastChange"
40
+ style="margin-top: 8px; padding: 8px 12px; border-radius: 6px; background: var(--coar-surface-neutral-subtle); font-size: 13px;"
41
+ >
42
+ Last change: <strong>{{ lastChange.name }}</strong>'s
43
+ <strong>{{ lastChange.field }}</strong> —
44
+ <code>{{ lastChange.oldValue }}</code> → <code>{{ lastChange.newValue }}</code>
45
+ </div>
46
+ </div>
47
+ </template>
48
+
49
+ <script setup lang="ts">
50
+ import { ref, shallowRef } from 'vue';
51
+ import { CoarDataGrid, CoarGridBuilder } from '@cocoar/vue-data-grid';
52
+
53
+ interface Person {
54
+ id: number;
55
+ name: string;
56
+ email: string;
57
+ amount: number;
58
+ locked: boolean;
59
+ }
60
+
61
+ const data = ref<Person[]>([
62
+ { id: 1, name: 'Alice Johnson', email: 'alice@example.com', amount: 1200, locked: false },
63
+ { id: 2, name: 'Bob Smith', email: 'bob@example.com', amount: 800, locked: true },
64
+ { id: 3, name: 'Carol Williams', email: 'carol@example.com', amount: 1750, locked: false },
65
+ { id: 4, name: 'David Brown', email: 'david@example.com', amount: 450, locked: false },
66
+ ]);
67
+
68
+ interface Change {
69
+ name: string;
70
+ field: string;
71
+ oldValue: unknown;
72
+ newValue: unknown;
73
+ }
74
+ const lastChange = shallowRef<Change | null>(null);
75
+
76
+ const builder = CoarGridBuilder.create<Person>()
77
+ .columns([
78
+ (col) => col.field('name').header('Name').flex(1).editable((row) => !row.locked),
79
+ (col) => col.field('email').header('Email').flex(1).editable((row) => !row.locked),
80
+ (col) => col.number('amount').header('Amount').width(120).editable((row) => !row.locked),
81
+ (col) => col.field('locked').header('Locked').width(100),
82
+ ])
83
+ .rowDataRef(data)
84
+ .onCellValueChanged((event) => {
85
+ if (!event.data || !event.colDef.field) return;
86
+ lastChange.value = {
87
+ name: event.data.name,
88
+ field: event.colDef.field,
89
+ oldValue: event.oldValue,
90
+ newValue: event.newValue,
91
+ };
92
+ });
93
+ </script>
94
+ ```
95
+
96
+ ```ts
97
+ CoarGridBuilder.create<Person>()
98
+ .columns([
99
+ (col) => col.field('name').editable(row => !row.locked),
100
+ (col) => col.number('amount').editable(row => !row.locked),
101
+ ])
102
+ .rowDataRef(data)
103
+ .onCellValueChanged((event) => {
104
+ saveField(event.data, event.colDef.field, event.newValue);
105
+ });
106
+ ```
107
+
108
+ ## Custom Cell Editor
109
+
110
+ `cellEditorConfig(component, config)` accepts any Vue component and wraps your `config` object under `params.config` — the exact same convention as `cellRendererConfig`.
111
+
112
+ The component must follow AG Grid's [editor contract](https://www.ag-grid.com/vue-data-grid/component-cell-editor/): receive a single `params` prop and expose a `getValue()` method via `defineExpose`. Cocoar does not ship editor wrappers — building them is consumer territory, since the appropriate input control (text, select, autocomplete, date picker, custom widget) is application-specific.
113
+
114
+ **Demo — `data-grid/demos/GridEditingCustom.vue`**
115
+
116
+ ```vue
117
+ <template>
118
+ <div>
119
+ <div style="height: 280px;">
120
+ <CoarDataGrid :builder="builder" />
121
+ </div>
122
+ <div style="margin-top: 12px; font-size: 13px; color: var(--coar-text-neutral-secondary);">
123
+ Double-click the <strong>Role</strong> cell to open a select-based editor. Other columns use the default text editor.
124
+ </div>
125
+ </div>
126
+ </template>
127
+
128
+ <script setup lang="ts">
129
+ import { ref } from 'vue';
130
+ import { CoarDataGrid, CoarGridBuilder } from '@cocoar/vue-data-grid';
131
+ import SelectCellEditor from './SelectCellEditor.vue';
132
+
133
+ interface User {
134
+ id: number;
135
+ name: string;
136
+ role: 'Engineer' | 'Designer' | 'Manager';
137
+ }
138
+
139
+ const data = ref<User[]>([
140
+ { id: 1, name: 'Alice Johnson', role: 'Engineer' },
141
+ { id: 2, name: 'Bob Smith', role: 'Designer' },
142
+ { id: 3, name: 'Carol Williams', role: 'Manager' },
143
+ { id: 4, name: 'David Brown', role: 'Engineer' },
144
+ ]);
145
+
146
+ const builder = CoarGridBuilder.create<User>()
147
+ .columns([
148
+ (col) => col.field('name').header('Name').flex(1).editable(true),
149
+ (col) =>
150
+ col
151
+ .field('role')
152
+ .header('Role')
153
+ .width(160)
154
+ .editable(true)
155
+ .cellEditorConfig(SelectCellEditor, {
156
+ options: ['Engineer', 'Designer', 'Manager'],
157
+ }),
158
+ ])
159
+ .rowDataRef(data);
160
+ </script>
161
+ ```
162
+
163
+ The minimal `SelectCellEditor.vue` used above:
164
+
165
+ ```vue
166
+ <template>
167
+ <select ref="selectRef" v-model="value" style="width:100%;height:100%;">
168
+ <option v-for="opt in options" :key="opt" :value="opt">{{ opt }}</option>
169
+ </select>
170
+ </template>
171
+
172
+ <script setup lang="ts">
173
+ import { ref, onMounted } from 'vue';
174
+ import type { ICellEditorParams } from 'ag-grid-community';
175
+
176
+ const props = defineProps<{
177
+ params: ICellEditorParams<unknown, string> & { config: { options: string[] } };
178
+ }>();
179
+
180
+ const selectRef = ref<HTMLSelectElement | null>(null);
181
+ const value = ref(props.params.value ?? '');
182
+ const options = props.params.config.options;
183
+
184
+ onMounted(() => selectRef.value?.focus());
185
+
186
+ defineExpose({ getValue: () => value.value });
187
+ </script>
188
+ ```
189
+
190
+ Wire it into a column:
191
+
192
+ ```ts
193
+ (col) =>
194
+ col.field('role')
195
+ .editable(true)
196
+ .cellEditorConfig(SelectCellEditor, {
197
+ options: ['Engineer', 'Designer', 'Manager'],
198
+ })
199
+ ```
200
+
201
+ ## Tips
202
+
203
+ **Single-click edit.** AG Grid's default is double-click. To enter edit on a single click, pass through the native option:
204
+
205
+ ```ts
206
+ gridBuilder.option('singleClickEdit', true);
207
+ ```
208
+
209
+ **Stop editing on focus loss.** Useful for forms where clicking outside should commit:
210
+
211
+ ```ts
212
+ gridBuilder.stopEditingWhenCellsLoseFocus();
213
+ ```
214
+
215
+ **Full-row editing.** Edit every cell in a row at once:
216
+
217
+ ```ts
218
+ gridBuilder.fullRowEdit();
219
+ ```
220
+
221
+ ## API
222
+
223
+ ### Column-level
224
+
225
+ | Method | Parameters | Description |
226
+ |--------|-----------|-------------|
227
+ | `.editable(value)` | `boolean \| (row: T) => boolean` | Enable editing statically or via row predicate. The predicate receives row data; rows without data (group rows etc.) return `false`. |
228
+ | `.cellEditorConfig(component, config)` | `Component, object` | Set custom cell editor. `config` is wrapped under `cellEditorParams.config`. |
229
+
230
+ ### Grid-level
231
+
232
+ | Method | Parameters | Description |
233
+ |--------|-----------|-------------|
234
+ | `.onCellValueChanged(handler)` | `(event: CellValueChangedEvent<T>) => void` | Fires once per committed cell edit. `event.oldValue`, `event.newValue`, `event.data`, `event.colDef.field`. |
235
+ | `.fullRowEdit(value?)` | `boolean` | Enable full-row editing mode. |
236
+ | `.stopEditingWhenCellsLoseFocus(value?)` | `boolean` | Commit the edit when focus leaves the cell. |