@chromvoid/headless-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +99 -0
  3. package/dist/a11y-contracts/index.d.ts +23 -0
  4. package/dist/a11y-contracts/index.js +1 -0
  5. package/dist/accordion/index.d.ts +78 -0
  6. package/dist/accordion/index.js +264 -0
  7. package/dist/adapters/index.d.ts +9 -0
  8. package/dist/adapters/index.js +1 -0
  9. package/dist/alert/index.d.ts +33 -0
  10. package/dist/alert/index.js +54 -0
  11. package/dist/alert-dialog/index.d.ts +69 -0
  12. package/dist/alert-dialog/index.js +94 -0
  13. package/dist/badge/index.d.ts +48 -0
  14. package/dist/badge/index.js +89 -0
  15. package/dist/breadcrumb/index.d.ts +55 -0
  16. package/dist/breadcrumb/index.js +77 -0
  17. package/dist/button/index.d.ts +46 -0
  18. package/dist/button/index.js +86 -0
  19. package/dist/callout/index.d.ts +41 -0
  20. package/dist/callout/index.js +63 -0
  21. package/dist/card/index.d.ts +54 -0
  22. package/dist/card/index.js +103 -0
  23. package/dist/carousel/index.d.ts +98 -0
  24. package/dist/carousel/index.js +243 -0
  25. package/dist/checkbox/index.d.ts +50 -0
  26. package/dist/checkbox/index.js +87 -0
  27. package/dist/combobox/index.d.ts +114 -0
  28. package/dist/combobox/index.js +431 -0
  29. package/dist/command-palette/index.d.ts +73 -0
  30. package/dist/command-palette/index.js +147 -0
  31. package/dist/context-menu/index.d.ts +111 -0
  32. package/dist/context-menu/index.js +372 -0
  33. package/dist/copy-button/index.d.ts +62 -0
  34. package/dist/copy-button/index.js +183 -0
  35. package/dist/core/index.d.ts +20 -0
  36. package/dist/core/index.js +2 -0
  37. package/dist/core/selection.d.ts +5 -0
  38. package/dist/core/selection.js +39 -0
  39. package/dist/core/value-range.d.ts +49 -0
  40. package/dist/core/value-range.js +134 -0
  41. package/dist/date-picker/index.d.ts +210 -0
  42. package/dist/date-picker/index.js +895 -0
  43. package/dist/dialog/index.d.ts +95 -0
  44. package/dist/dialog/index.js +153 -0
  45. package/dist/disclosure/index.d.ts +52 -0
  46. package/dist/disclosure/index.js +159 -0
  47. package/dist/drawer/index.d.ts +30 -0
  48. package/dist/drawer/index.js +39 -0
  49. package/dist/feed/index.d.ts +77 -0
  50. package/dist/feed/index.js +260 -0
  51. package/dist/grid/index.d.ts +103 -0
  52. package/dist/grid/index.js +415 -0
  53. package/dist/index.d.ts +51 -0
  54. package/dist/index.js +51 -0
  55. package/dist/input/index.d.ts +86 -0
  56. package/dist/input/index.js +156 -0
  57. package/dist/interactions/composite-navigation.d.ts +69 -0
  58. package/dist/interactions/composite-navigation.js +169 -0
  59. package/dist/interactions/index.d.ts +15 -0
  60. package/dist/interactions/index.js +4 -0
  61. package/dist/interactions/keyboard-intents.d.ts +16 -0
  62. package/dist/interactions/keyboard-intents.js +33 -0
  63. package/dist/interactions/overlay-focus.d.ts +40 -0
  64. package/dist/interactions/overlay-focus.js +93 -0
  65. package/dist/interactions/typeahead.d.ts +20 -0
  66. package/dist/interactions/typeahead.js +41 -0
  67. package/dist/landmarks/index.d.ts +39 -0
  68. package/dist/landmarks/index.js +58 -0
  69. package/dist/link/index.d.ts +34 -0
  70. package/dist/link/index.js +39 -0
  71. package/dist/listbox/index.d.ts +92 -0
  72. package/dist/listbox/index.js +337 -0
  73. package/dist/menu/index.d.ts +132 -0
  74. package/dist/menu/index.js +541 -0
  75. package/dist/menu-button/index.d.ts +71 -0
  76. package/dist/menu-button/index.js +121 -0
  77. package/dist/meter/index.d.ts +45 -0
  78. package/dist/meter/index.js +106 -0
  79. package/dist/number/index.d.ts +113 -0
  80. package/dist/number/index.js +252 -0
  81. package/dist/popover/index.d.ts +70 -0
  82. package/dist/popover/index.js +126 -0
  83. package/dist/progress/index.d.ts +49 -0
  84. package/dist/progress/index.js +79 -0
  85. package/dist/radio-group/index.d.ts +61 -0
  86. package/dist/radio-group/index.js +150 -0
  87. package/dist/select/index.d.ts +92 -0
  88. package/dist/select/index.js +239 -0
  89. package/dist/sidebar/index.d.ts +74 -0
  90. package/dist/sidebar/index.js +186 -0
  91. package/dist/slider/index.d.ts +61 -0
  92. package/dist/slider/index.js +150 -0
  93. package/dist/slider-multi-thumb/index.d.ts +70 -0
  94. package/dist/slider-multi-thumb/index.js +222 -0
  95. package/dist/spinbutton/index.d.ts +75 -0
  96. package/dist/spinbutton/index.js +214 -0
  97. package/dist/spinner/index.d.ts +1 -0
  98. package/dist/spinner/index.js +1 -0
  99. package/dist/spinner/spinner.d.ts +23 -0
  100. package/dist/spinner/spinner.js +25 -0
  101. package/dist/switch/index.d.ts +40 -0
  102. package/dist/switch/index.js +61 -0
  103. package/dist/table/index.d.ts +117 -0
  104. package/dist/table/index.js +377 -0
  105. package/dist/tabs/index.d.ts +63 -0
  106. package/dist/tabs/index.js +174 -0
  107. package/dist/textarea/index.d.ts +68 -0
  108. package/dist/textarea/index.js +137 -0
  109. package/dist/toast/index.d.ts +67 -0
  110. package/dist/toast/index.js +145 -0
  111. package/dist/toolbar/index.d.ts +59 -0
  112. package/dist/toolbar/index.js +139 -0
  113. package/dist/tooltip/index.d.ts +52 -0
  114. package/dist/tooltip/index.js +169 -0
  115. package/dist/treegrid/index.d.ts +101 -0
  116. package/dist/treegrid/index.js +463 -0
  117. package/dist/treeview/index.d.ts +68 -0
  118. package/dist/treeview/index.js +370 -0
  119. package/dist/window-splitter/index.d.ts +65 -0
  120. package/dist/window-splitter/index.js +204 -0
  121. package/package.json +92 -0
  122. package/specs/ADR-001-headless-architecture.md +461 -0
  123. package/specs/ADR-002-repo-release-model.md +108 -0
  124. package/specs/ADR-003-public-api-versioning.md +136 -0
  125. package/specs/ADR-004-focus-selection-policy.md +117 -0
  126. package/specs/IMPLEMENTATION-ROADMAP.md +237 -0
  127. package/specs/ISSUE-BACKLOG.md +681 -0
  128. package/specs/RELEASE-CANDIDATE.md +30 -0
  129. package/specs/components/accordion.md +130 -0
  130. package/specs/components/alert-dialog.md +72 -0
  131. package/specs/components/alert.md +65 -0
  132. package/specs/components/badge.md +220 -0
  133. package/specs/components/breadcrumb.md +74 -0
  134. package/specs/components/button.md +115 -0
  135. package/specs/components/callout.md +195 -0
  136. package/specs/components/card.md +280 -0
  137. package/specs/components/carousel.md +140 -0
  138. package/specs/components/checkbox.md +172 -0
  139. package/specs/components/combobox.md +423 -0
  140. package/specs/components/command-palette.md +92 -0
  141. package/specs/components/context-menu.md +556 -0
  142. package/specs/components/copy-button.md +293 -0
  143. package/specs/components/date-picker.md +400 -0
  144. package/specs/components/dialog.md +298 -0
  145. package/specs/components/disclosure.md +257 -0
  146. package/specs/components/drawer.md +353 -0
  147. package/specs/components/feed.md +265 -0
  148. package/specs/components/grid.md +186 -0
  149. package/specs/components/input.md +254 -0
  150. package/specs/components/landmarks.md +136 -0
  151. package/specs/components/link.md +134 -0
  152. package/specs/components/listbox.md +351 -0
  153. package/specs/components/menu-button.md +76 -0
  154. package/specs/components/menu.md +623 -0
  155. package/specs/components/meter.md +149 -0
  156. package/specs/components/number.md +393 -0
  157. package/specs/components/popover.md +252 -0
  158. package/specs/components/progress.md +188 -0
  159. package/specs/components/radio-group.md +151 -0
  160. package/specs/components/select.md +144 -0
  161. package/specs/components/sidebar.md +321 -0
  162. package/specs/components/slider-multi-thumb.md +78 -0
  163. package/specs/components/slider.md +84 -0
  164. package/specs/components/spinbutton.md +140 -0
  165. package/specs/components/spinner.md +132 -0
  166. package/specs/components/switch.md +175 -0
  167. package/specs/components/table.md +403 -0
  168. package/specs/components/tabs.md +265 -0
  169. package/specs/components/textarea.md +185 -0
  170. package/specs/components/toast.md +198 -0
  171. package/specs/components/toolbar.md +278 -0
  172. package/specs/components/tooltip.md +252 -0
  173. package/specs/components/treegrid.md +281 -0
  174. package/specs/components/treeview.md +91 -0
  175. package/specs/components/window-splitter.md +297 -0
  176. package/specs/ops/git-shard-sync.md +107 -0
  177. package/specs/ops/release-checklist.md +76 -0
  178. package/specs/release/GAP-TO-GREEN-ISSUES.md +88 -0
  179. package/specs/release/api-freeze-candidate.md +54 -0
  180. package/specs/release/changelog-automation.md +76 -0
  181. package/specs/release/changelog.generated.md +53 -0
  182. package/specs/release/changelog.patch.generated.md +46 -0
  183. package/specs/release/consumer-integration.md +53 -0
  184. package/specs/release/migration-notes-pre-v1.md +40 -0
  185. package/specs/release/mvp-changelog.md +57 -0
  186. package/specs/release/release-notes-template.md +61 -0
  187. package/specs/release/release-rehearsal.md +113 -0
  188. package/specs/release/semver-deprecation-dry-run.md +89 -0
  189. package/specs/release/shard-release-drill-report.md +50 -0
  190. package/specs/release/shard-release-follow-ups.md +31 -0
  191. package/specs/signals.md +208 -0
@@ -0,0 +1,260 @@
1
+ import { action, atom, computed } from '@reatom/core';
2
+ const dedupe = (articles) => {
3
+ const seen = new Set();
4
+ const result = [];
5
+ for (const a of articles) {
6
+ if (seen.has(a.id))
7
+ continue;
8
+ seen.add(a.id);
9
+ result.push(a);
10
+ }
11
+ return result;
12
+ };
13
+ export function createFeed(options) {
14
+ const idBase = options.idBase ?? 'feed';
15
+ const articlesAtom = atom(dedupe(options.articles), `${idBase}.articles`);
16
+ const articleIdsAtom = computed(() => articlesAtom().map((a) => a.id), `${idBase}.articleIds`);
17
+ const articleByIdAtom = computed(() => new Map(articlesAtom().map((a, i) => [a.id, { article: a, index: i }])), `${idBase}.articleById`);
18
+ const enabledIdsAtom = computed(() => articlesAtom()
19
+ .filter((a) => !a.disabled)
20
+ .map((a) => a.id), `${idBase}.enabledIds`);
21
+ const isLoadingAtom = atom(false, `${idBase}.isLoading`);
22
+ const isBusyAtom = atom(false, `${idBase}.isBusy`);
23
+ const totalCountAtom = atom(options.totalCount ?? -1, `${idBase}.totalCount`);
24
+ const errorAtom = atom(null, `${idBase}.error`);
25
+ const isEmptyAtom = computed(() => articleIdsAtom().length === 0, `${idBase}.isEmpty`);
26
+ const hasErrorAtom = computed(() => errorAtom() !== null, `${idBase}.hasError`);
27
+ const canLoadMoreAtom = computed(() => options.onLoadMore != null && !isLoadingAtom(), `${idBase}.canLoadMore`);
28
+ const canLoadNewerAtom = computed(() => options.onLoadNewer != null && !isLoadingAtom(), `${idBase}.canLoadNewer`);
29
+ const resolveInitialActive = () => {
30
+ const initial = options.initialActiveArticleId;
31
+ if (initial != null) {
32
+ const info = articleByIdAtom().get(initial);
33
+ if (info && !info.article.disabled)
34
+ return initial;
35
+ }
36
+ return enabledIdsAtom()[0] ?? null;
37
+ };
38
+ const activeArticleIdAtom = atom(resolveInitialActive(), `${idBase}.activeArticleId`);
39
+ const ensureActiveInvariant = () => {
40
+ const active = activeArticleIdAtom();
41
+ const enabled = enabledIdsAtom();
42
+ if (enabled.length === 0) {
43
+ activeArticleIdAtom.set(null);
44
+ return;
45
+ }
46
+ if (active != null && enabled.includes(active))
47
+ return;
48
+ activeArticleIdAtom.set(enabled[0] ?? null);
49
+ };
50
+ const moveBy = (direction) => {
51
+ const enabled = enabledIdsAtom();
52
+ if (enabled.length === 0) {
53
+ activeArticleIdAtom.set(null);
54
+ return;
55
+ }
56
+ const active = activeArticleIdAtom();
57
+ if (active == null) {
58
+ activeArticleIdAtom.set(enabled[0] ?? null);
59
+ return;
60
+ }
61
+ const idx = enabled.indexOf(active);
62
+ if (idx < 0) {
63
+ activeArticleIdAtom.set(enabled[0] ?? null);
64
+ return;
65
+ }
66
+ const next = Math.min(Math.max(idx + direction, 0), enabled.length - 1);
67
+ activeArticleIdAtom.set(enabled[next] ?? null);
68
+ };
69
+ const focusNextArticle = action(() => {
70
+ moveBy(1);
71
+ }, `${idBase}.focusNextArticle`);
72
+ const focusPrevArticle = action(() => {
73
+ moveBy(-1);
74
+ }, `${idBase}.focusPrevArticle`);
75
+ const setArticles = action((articles) => {
76
+ articlesAtom.set(dedupe(articles));
77
+ ensureActiveInvariant();
78
+ }, `${idBase}.setArticles`);
79
+ const appendArticles = action((articles) => {
80
+ articlesAtom.set(dedupe([...articlesAtom(), ...articles]));
81
+ }, `${idBase}.appendArticles`);
82
+ const prependArticles = action((articles) => {
83
+ articlesAtom.set(dedupe([...articles, ...articlesAtom()]));
84
+ }, `${idBase}.prependArticles`);
85
+ const removeArticle = action((articleId) => {
86
+ const current = articlesAtom();
87
+ const idx = current.findIndex((a) => a.id === articleId);
88
+ if (idx < 0)
89
+ return;
90
+ const wasActive = activeArticleIdAtom() === articleId;
91
+ const next = current.filter((a) => a.id !== articleId);
92
+ articlesAtom.set(next);
93
+ if (wasActive) {
94
+ const enabled = enabledIdsAtom();
95
+ if (enabled.length === 0) {
96
+ activeArticleIdAtom.set(null);
97
+ return;
98
+ }
99
+ const allIds = articleIdsAtom();
100
+ let found = null;
101
+ for (let i = idx; i < allIds.length; i++) {
102
+ if (enabled.includes(allIds[i])) {
103
+ found = allIds[i];
104
+ break;
105
+ }
106
+ }
107
+ if (found == null) {
108
+ for (let i = Math.min(idx - 1, allIds.length - 1); i >= 0; i--) {
109
+ if (enabled.includes(allIds[i])) {
110
+ found = allIds[i];
111
+ break;
112
+ }
113
+ }
114
+ }
115
+ activeArticleIdAtom.set(found ?? enabled[0] ?? null);
116
+ }
117
+ }, `${idBase}.removeArticle`);
118
+ const setBusy = action((value) => {
119
+ isBusyAtom.set(value);
120
+ }, `${idBase}.setBusy`);
121
+ const setError = action((message) => {
122
+ errorAtom.set(message);
123
+ }, `${idBase}.setError`);
124
+ const clearError = action(() => {
125
+ errorAtom.set(null);
126
+ }, `${idBase}.clearError`);
127
+ const setTotalCount = action((count) => {
128
+ totalCountAtom.set(count);
129
+ }, `${idBase}.setTotalCount`);
130
+ const loadMore = action(async () => {
131
+ if (!options.onLoadMore)
132
+ return;
133
+ if (isLoadingAtom())
134
+ return;
135
+ isLoadingAtom.set(true);
136
+ isBusyAtom.set(true);
137
+ try {
138
+ const loaded = await options.onLoadMore();
139
+ articlesAtom.set(dedupe([...articlesAtom(), ...loaded]));
140
+ ensureActiveInvariant();
141
+ }
142
+ catch (e) {
143
+ errorAtom.set(e instanceof Error ? e.message : String(e));
144
+ }
145
+ finally {
146
+ isLoadingAtom.set(false);
147
+ isBusyAtom.set(false);
148
+ }
149
+ }, `${idBase}.loadMore`);
150
+ const loadNewer = action(async () => {
151
+ if (!options.onLoadNewer)
152
+ return;
153
+ if (isLoadingAtom())
154
+ return;
155
+ isLoadingAtom.set(true);
156
+ isBusyAtom.set(true);
157
+ try {
158
+ const loaded = await options.onLoadNewer();
159
+ articlesAtom.set(dedupe([...loaded, ...articlesAtom()]));
160
+ ensureActiveInvariant();
161
+ }
162
+ catch (e) {
163
+ errorAtom.set(e instanceof Error ? e.message : String(e));
164
+ }
165
+ finally {
166
+ isLoadingAtom.set(false);
167
+ isBusyAtom.set(false);
168
+ }
169
+ }, `${idBase}.loadNewer`);
170
+ const handleKeyDown = action((event) => {
171
+ const ctrlOrMeta = event.ctrlKey === true || event.metaKey === true;
172
+ if (event.key === 'PageDown') {
173
+ focusNextArticle();
174
+ return 'next';
175
+ }
176
+ if (event.key === 'PageUp') {
177
+ focusPrevArticle();
178
+ return 'prev';
179
+ }
180
+ if (event.key === 'End' && ctrlOrMeta) {
181
+ return 'exit-after';
182
+ }
183
+ if (event.key === 'Home' && ctrlOrMeta) {
184
+ return 'exit-before';
185
+ }
186
+ return null;
187
+ }, `${idBase}.handleKeyDown`);
188
+ const setActiveArticle = action((articleId) => {
189
+ const info = articleByIdAtom().get(articleId);
190
+ if (!info || info.article.disabled)
191
+ return;
192
+ activeArticleIdAtom.set(articleId);
193
+ }, `${idBase}.setActiveArticle`);
194
+ const contracts = {
195
+ getFeedProps() {
196
+ const props = {
197
+ id: `${idBase}-root`,
198
+ role: 'feed',
199
+ 'aria-busy': isBusyAtom() ? 'true' : 'false',
200
+ };
201
+ if (options.ariaLabel != null)
202
+ props['aria-label'] = options.ariaLabel;
203
+ if (options.ariaLabelledBy != null)
204
+ props['aria-labelledby'] = options.ariaLabelledBy;
205
+ return props;
206
+ },
207
+ getArticleProps(articleId) {
208
+ const info = articleByIdAtom().get(articleId);
209
+ if (!info) {
210
+ throw new Error(`Unknown feed article id: ${articleId}`);
211
+ }
212
+ const total = totalCountAtom();
213
+ const setSize = total >= 0 ? total : -1;
214
+ const posInSet = info.index + 1;
215
+ const isActive = activeArticleIdAtom() === articleId;
216
+ return {
217
+ id: `${idBase}-article-${articleId}`,
218
+ role: 'article',
219
+ tabindex: (isActive && !info.article.disabled ? '0' : '-1'),
220
+ 'aria-posinset': posInSet,
221
+ 'aria-setsize': setSize,
222
+ 'aria-disabled': info.article.disabled ? 'true' : undefined,
223
+ 'data-active': (isActive ? 'true' : 'false'),
224
+ onFocus: () => setActiveArticle(articleId),
225
+ };
226
+ },
227
+ };
228
+ const state = {
229
+ articleIds: articleIdsAtom,
230
+ activeArticleId: activeArticleIdAtom,
231
+ isLoading: isLoadingAtom,
232
+ isBusy: isBusyAtom,
233
+ totalCount: totalCountAtom,
234
+ isEmpty: isEmptyAtom,
235
+ hasError: hasErrorAtom,
236
+ error: errorAtom,
237
+ canLoadMore: canLoadMoreAtom,
238
+ canLoadNewer: canLoadNewerAtom,
239
+ };
240
+ const actions = {
241
+ focusNextArticle,
242
+ focusPrevArticle,
243
+ loadMore,
244
+ loadNewer,
245
+ setArticles,
246
+ appendArticles,
247
+ prependArticles,
248
+ removeArticle,
249
+ setBusy,
250
+ setError,
251
+ clearError,
252
+ setTotalCount,
253
+ handleKeyDown,
254
+ };
255
+ return {
256
+ state,
257
+ actions,
258
+ contracts,
259
+ };
260
+ }
@@ -0,0 +1,103 @@
1
+ import { type Atom, type Computed } from '@reatom/core';
2
+ export type GridFocusStrategy = 'roving-tabindex' | 'aria-activedescendant';
3
+ export type GridSelectionMode = 'single' | 'multiple';
4
+ export interface GridRow {
5
+ id: string;
6
+ index?: number;
7
+ disabled?: boolean;
8
+ }
9
+ export interface GridColumn {
10
+ id: string;
11
+ index?: number;
12
+ disabled?: boolean;
13
+ }
14
+ export interface GridCellId {
15
+ rowId: string;
16
+ colId: string;
17
+ }
18
+ export interface GridKeyboardEventLike {
19
+ key: string;
20
+ shiftKey?: boolean;
21
+ ctrlKey?: boolean;
22
+ metaKey?: boolean;
23
+ altKey?: boolean;
24
+ }
25
+ export interface CreateGridOptions {
26
+ rows: readonly GridRow[];
27
+ columns: readonly GridColumn[];
28
+ disabledCells?: readonly GridCellId[];
29
+ idBase?: string;
30
+ ariaLabel?: string;
31
+ ariaLabelledBy?: string;
32
+ focusStrategy?: GridFocusStrategy;
33
+ selectionMode?: GridSelectionMode;
34
+ selectionFollowsFocus?: boolean;
35
+ totalRowCount?: number;
36
+ totalColumnCount?: number;
37
+ pageSize?: number;
38
+ initialActiveCellId?: GridCellId | null;
39
+ initialSelectedCellIds?: readonly GridCellId[];
40
+ isReadOnly?: boolean;
41
+ }
42
+ export interface GridState {
43
+ activeCellId: Atom<GridCellId | null>;
44
+ selectedCellIds: Atom<Set<string>>;
45
+ rowCount: Computed<number>;
46
+ columnCount: Computed<number>;
47
+ }
48
+ export interface GridActions {
49
+ setActiveCell(cell: GridCellId): void;
50
+ moveUp(): void;
51
+ moveDown(): void;
52
+ moveLeft(): void;
53
+ moveRight(): void;
54
+ moveRowStart(): void;
55
+ moveRowEnd(): void;
56
+ moveGridStart(): void;
57
+ moveGridEnd(): void;
58
+ pageUp(): void;
59
+ pageDown(): void;
60
+ selectCell(cell: GridCellId): void;
61
+ toggleCellSelection(cell: GridCellId): void;
62
+ selectRow(rowId: string): void;
63
+ selectColumn(colId: string): void;
64
+ handleKeyDown(event: GridKeyboardEventLike): void;
65
+ }
66
+ export interface GridProps {
67
+ id: string;
68
+ role: 'grid';
69
+ tabindex: '0' | '-1';
70
+ 'aria-label'?: string;
71
+ 'aria-labelledby'?: string;
72
+ 'aria-multiselectable': 'true' | 'false';
73
+ 'aria-colcount': number;
74
+ 'aria-rowcount': number;
75
+ 'aria-activedescendant'?: string;
76
+ }
77
+ export interface GridRowProps {
78
+ id: string;
79
+ role: 'row';
80
+ 'aria-rowindex': number;
81
+ }
82
+ export interface GridCellProps {
83
+ id: string;
84
+ role: 'gridcell';
85
+ tabindex: '0' | '-1';
86
+ 'aria-colindex': number;
87
+ 'aria-selected': 'true' | 'false';
88
+ 'aria-readonly'?: 'true';
89
+ 'aria-disabled'?: 'true';
90
+ 'data-active': 'true' | 'false';
91
+ onFocus: () => void;
92
+ }
93
+ export interface GridContracts {
94
+ getGridProps(): GridProps;
95
+ getRowProps(rowId: string): GridRowProps;
96
+ getCellProps(rowId: string, colId: string): GridCellProps;
97
+ }
98
+ export interface GridModel {
99
+ readonly state: GridState;
100
+ readonly actions: GridActions;
101
+ readonly contracts: GridContracts;
102
+ }
103
+ export declare function createGrid(options: CreateGridOptions): GridModel;