gbs-add-block 2.1.0 → 2.3.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 (129) hide show
  1. package/.gbs/skills/gbs-components/SKILL.md +190 -134
  2. package/.gbs/skills/gbs-components/references/install.md +25 -3
  3. package/.gbs/skills/gbs-components/references/styling.md +246 -207
  4. package/CHANGELOG.md +74 -0
  5. package/README.md +154 -23
  6. package/index.cjs +212 -3
  7. package/package.json +41 -10
  8. package/schema/passport-v1.schema.json +204 -0
  9. package/source/beta-components/accordion/passport.json +259 -0
  10. package/source/beta-components/accordion/styles.css +207 -208
  11. package/source/beta-components/alert/passport.json +250 -0
  12. package/source/beta-components/alert/styles.css +154 -155
  13. package/source/beta-components/avatar/passport.json +294 -0
  14. package/source/beta-components/avatar/styles.css +225 -226
  15. package/source/beta-components/badge/passport.json +332 -0
  16. package/source/beta-components/badge/styles.css +203 -204
  17. package/source/beta-components/breadcrumb/passport.json +243 -0
  18. package/source/beta-components/breadcrumb/styles.css +138 -140
  19. package/source/beta-components/button/passport.json +402 -0
  20. package/source/beta-components/button/passport.manual.json +31 -0
  21. package/source/beta-components/button/styles.css +232 -234
  22. package/source/beta-components/card/passport.json +337 -0
  23. package/source/beta-components/card/styles.css +230 -232
  24. package/source/beta-components/checkbox/passport.json +456 -0
  25. package/source/beta-components/checkbox/styles.css +211 -213
  26. package/source/beta-components/combobox/passport.json +456 -0
  27. package/source/beta-components/combobox/styles.css +419 -417
  28. package/source/beta-components/data-grid/agent/coerce.ts +368 -0
  29. package/source/beta-components/data-grid/agent/contract.ts +410 -0
  30. package/source/beta-components/data-grid/agent/dataset.ts +92 -0
  31. package/source/beta-components/data-grid/agent/engine.ts +470 -0
  32. package/source/beta-components/data-grid/agent/executors.ts +155 -0
  33. package/source/beta-components/data-grid/agent/index.ts +79 -0
  34. package/source/beta-components/data-grid/agent/intent.ts +324 -0
  35. package/source/beta-components/data-grid/agent/operations.ts +335 -0
  36. package/source/beta-components/data-grid/agent/validate.ts +630 -0
  37. package/source/beta-components/data-grid/agent/webmcp.ts +107 -0
  38. package/source/beta-components/data-grid/index.ts +14 -7
  39. package/source/beta-components/data-grid/passport.json +1051 -0
  40. package/source/beta-components/data-grid/passport.manual.json +255 -0
  41. package/source/beta-components/data-grid/react/AskGrid.tsx +164 -0
  42. package/source/beta-components/data-grid/react/DataGrid.tsx +39 -0
  43. package/source/beta-components/data-grid/styles.css +874 -716
  44. package/source/beta-components/date-picker/passport.json +407 -0
  45. package/source/beta-components/date-picker/styles.css +445 -446
  46. package/source/beta-components/dialog/passport.json +344 -0
  47. package/source/beta-components/dialog/styles.css +280 -279
  48. package/source/beta-components/file-uploader/passport.json +518 -0
  49. package/source/beta-components/file-uploader/styles.css +394 -396
  50. package/source/beta-components/input/passport.json +536 -0
  51. package/source/beta-components/input/styles.css +295 -297
  52. package/source/beta-components/menu/passport.json +322 -0
  53. package/source/beta-components/menu/styles.css +224 -223
  54. package/source/beta-components/modal/passport.json +289 -0
  55. package/source/beta-components/modal/styles.css +241 -240
  56. package/source/beta-components/number-input/passport.json +541 -0
  57. package/source/beta-components/number-input/styles.css +230 -231
  58. package/source/beta-components/popover/passport.json +238 -0
  59. package/source/beta-components/popover/styles.css +148 -147
  60. package/source/beta-components/progress/passport.json +270 -0
  61. package/source/beta-components/progress/styles.css +200 -201
  62. package/source/beta-components/radio-group/passport.json +477 -0
  63. package/source/beta-components/radio-group/styles.css +269 -270
  64. package/source/beta-components/shared/core/agent/adapter.ts +65 -0
  65. package/source/beta-components/shared/core/agent/history.ts +120 -0
  66. package/source/beta-components/shared/core/agent/index.ts +46 -0
  67. package/source/beta-components/shared/core/agent/numbers.ts +217 -0
  68. package/source/beta-components/shared/core/agent/schema.ts +180 -0
  69. package/source/beta-components/shared/core/agent/types.ts +169 -0
  70. package/source/beta-components/shared/core/agent/webmcp.ts +328 -0
  71. package/source/beta-components/shared/index.ts +9 -0
  72. package/source/beta-components/shared/react/GramproAIProvider.tsx +50 -0
  73. package/source/beta-components/shared/react/useAskAgent.ts +217 -0
  74. package/source/beta-components/shared/styles.css +79 -0
  75. package/source/beta-components/shared/version.json +4 -4
  76. package/source/beta-components/shared/version.ts +6 -6
  77. package/source/beta-components/skeleton/passport.json +251 -0
  78. package/source/beta-components/skeleton/styles.css +185 -187
  79. package/source/beta-components/spinner/passport.json +245 -0
  80. package/source/beta-components/spinner/styles.css +173 -174
  81. package/source/beta-components/switch/passport.json +421 -0
  82. package/source/beta-components/switch/styles.css +227 -229
  83. package/source/beta-components/tabs/passport.json +315 -0
  84. package/source/beta-components/tabs/styles.css +263 -264
  85. package/source/beta-components/textarea/passport.json +382 -0
  86. package/source/beta-components/textarea/styles.css +158 -160
  87. package/source/beta-components/toaster/passport.json +221 -0
  88. package/source/beta-components/toaster/styles.css +282 -282
  89. package/source/beta-components/tooltip/passport.json +170 -0
  90. package/source/beta-components/tooltip/styles.css +71 -73
  91. package/tools/env.cjs +61 -0
  92. package/tools/passport/cli.cjs +79 -0
  93. package/tools/passport/extract.cjs +493 -0
  94. package/tools/passport/index.cjs +185 -0
  95. package/tools/passport/merge.cjs +131 -0
  96. package/tools/passport/policy.cjs +65 -0
  97. package/tools/passport/validate.cjs +277 -0
  98. package/tools/ts-require.cjs +79 -0
  99. package/source/beta-components/accordion/__tests__/core.test.ts +0 -58
  100. package/source/beta-components/alert/__tests__/core.test.ts +0 -17
  101. package/source/beta-components/avatar/__tests__/core.test.ts +0 -88
  102. package/source/beta-components/badge/__tests__/core.test.ts +0 -46
  103. package/source/beta-components/breadcrumb/__tests__/core.test.ts +0 -58
  104. package/source/beta-components/button/__tests__/core.test.ts +0 -31
  105. package/source/beta-components/card/__tests__/core.test.ts +0 -57
  106. package/source/beta-components/checkbox/__tests__/core.test.ts +0 -40
  107. package/source/beta-components/combobox/__tests__/core.test.ts +0 -134
  108. package/source/beta-components/data-grid/__tests__/core.test.ts +0 -356
  109. package/source/beta-components/data-grid/__tests__/export.test.ts +0 -70
  110. package/source/beta-components/data-grid/__tests__/pdf.test.ts +0 -209
  111. package/source/beta-components/date-picker/__tests__/core.test.ts +0 -273
  112. package/source/beta-components/dialog/__tests__/core.test.ts +0 -86
  113. package/source/beta-components/file-uploader/__tests__/core.test.ts +0 -395
  114. package/source/beta-components/input/__tests__/core.test.ts +0 -75
  115. package/source/beta-components/menu/__tests__/core.test.ts +0 -120
  116. package/source/beta-components/modal/__tests__/core.test.ts +0 -55
  117. package/source/beta-components/number-input/__tests__/core.test.ts +0 -151
  118. package/source/beta-components/progress/__tests__/core.test.ts +0 -56
  119. package/source/beta-components/radio-group/__tests__/core.test.ts +0 -64
  120. package/source/beta-components/shared/__tests__/boundaries.test.ts +0 -95
  121. package/source/beta-components/shared/__tests__/core.test.ts +0 -55
  122. package/source/beta-components/shared/__tests__/position.test.ts +0 -143
  123. package/source/beta-components/skeleton/__tests__/core.test.ts +0 -41
  124. package/source/beta-components/spinner/__tests__/core.test.ts +0 -48
  125. package/source/beta-components/switch/__tests__/core.test.ts +0 -64
  126. package/source/beta-components/tabs/__tests__/core.test.ts +0 -51
  127. package/source/beta-components/textarea/__tests__/core.test.ts +0 -38
  128. package/source/beta-components/toaster/__tests__/core.test.ts +0 -256
  129. package/source/beta-components/tooltip/__tests__/core.test.ts +0 -42
@@ -1,273 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from "vitest";
2
- import {
3
- addDays,
4
- addMonths,
5
- buildMonth,
6
- buildMonths,
7
- clampDate,
8
- compareDay,
9
- getISOWeek,
10
- isInRange,
11
- isSameDay,
12
- moveByKey,
13
- moveInGrid,
14
- normalizeRange,
15
- parseISODate,
16
- toDate,
17
- toISODate,
18
- yearPage,
19
- } from "../core/calendar";
20
- import { getServerToday, getToday, subscribeToToday } from "../core/today";
21
- import {
22
- fieldOrder,
23
- inputPlaceholder,
24
- monthNames,
25
- parseDate,
26
- weekdayNames,
27
- } from "../core/format";
28
-
29
- const iso = (date: Date | null) => (date ? toISODate(date) : null);
30
-
31
- describe("date normalization", () => {
32
- it("reads ISO strings as local days, never shifted by the time zone", () => {
33
- expect(iso(toDate("2026-03-12"))).toBe("2026-03-12");
34
- expect(iso(toDate(new Date(2026, 2, 12, 23, 59)))).toBe("2026-03-12");
35
- expect(toDate(null)).toBeNull();
36
- expect(toDate("not a date")).toBeNull();
37
- expect(parseISODate("2026-02-31")).toBeNull();
38
- });
39
-
40
- it("compares and matches days regardless of the time", () => {
41
- expect(compareDay(new Date(2026, 0, 1, 23), new Date(2026, 0, 2, 0))).toBeLessThan(0);
42
- expect(isSameDay(new Date(2026, 0, 1, 23), new Date(2026, 0, 1))).toBe(true);
43
- expect(isSameDay(null, new Date(2026, 0, 1))).toBe(false);
44
- });
45
-
46
- it("keeps the day of the month when a month is too short", () => {
47
- expect(iso(addMonths(new Date(2026, 0, 31), 1))).toBe("2026-02-28");
48
- expect(iso(addMonths(new Date(2024, 0, 31), 1))).toBe("2024-02-29");
49
- expect(iso(addDays(new Date(2026, 11, 31), 1))).toBe("2027-01-01");
50
- });
51
-
52
- it("clamps to the limits", () => {
53
- const min = new Date(2026, 0, 10);
54
- const max = new Date(2026, 0, 20);
55
- expect(iso(clampDate(new Date(2026, 0, 1), min, max))).toBe("2026-01-10");
56
- expect(iso(clampDate(new Date(2026, 0, 31), min, max))).toBe("2026-01-20");
57
- expect(iso(clampDate(new Date(2026, 0, 15), min, max))).toBe("2026-01-15");
58
- });
59
- });
60
-
61
- describe("month building", () => {
62
- const today = new Date(2026, 1, 10);
63
-
64
- it("returns six aligned weeks with the leading days of the previous month", () => {
65
- const february = buildMonth(2026, 1, { weekStartsOn: 1, today });
66
- expect(february.weeks).toHaveLength(6);
67
- expect(february.weeks[0].days).toHaveLength(7);
68
- // February 2026 starts on a Sunday, so a Monday-first grid opens on 26 January.
69
- expect(february.weeks[0].days[0].key).toBe("2026-01-26");
70
- expect(february.weeks[0].days[0].outside).toBe(true);
71
- expect(february.weeks[0].days[6].key).toBe("2026-02-01");
72
- expect(february.weeks[0].days[6].outside).toBe(false);
73
- });
74
-
75
- it("starts the week where the caller asks", () => {
76
- const sundayFirst = buildMonth(2026, 1, { weekStartsOn: 0, today });
77
- expect(sundayFirst.weeks[0].days[0].key).toBe("2026-02-01");
78
- });
79
-
80
- it("marks today, weekends and days outside the limits", () => {
81
- const february = buildMonth(2026, 1, {
82
- weekStartsOn: 1,
83
- today,
84
- min: new Date(2026, 1, 5),
85
- isDateDisabled: (date) => date.getDate() === 20,
86
- });
87
- const days = february.weeks.flatMap((week) => week.days);
88
- const byKey = (key: string) => days.find((day) => day.key === key);
89
-
90
- expect(byKey("2026-02-10")?.today).toBe(true);
91
- expect(byKey("2026-02-09")?.today).toBe(false);
92
- expect(byKey("2026-02-07")?.weekend).toBe(true);
93
- expect(byKey("2026-02-04")?.disabled).toBe(true);
94
- expect(byKey("2026-02-05")?.disabled).toBe(false);
95
- expect(byKey("2026-02-20")?.disabled).toBe(true);
96
- });
97
-
98
- it("builds consecutive months for a range view", () => {
99
- const months = buildMonths(new Date(2026, 10, 20), 2, { today });
100
- expect(months.map((month) => `${month.year}-${month.month}`)).toEqual(["2026-10", "2026-11"]);
101
- });
102
-
103
- it("numbers ISO weeks, including the ones spanning a year end", () => {
104
- expect(getISOWeek(new Date(2024, 0, 1))).toBe(1);
105
- expect(getISOWeek(new Date(2026, 0, 1))).toBe(1);
106
- expect(getISOWeek(new Date(2021, 0, 1))).toBe(53);
107
- });
108
- });
109
-
110
- describe("ranges", () => {
111
- it("puts a backwards range the right way round", () => {
112
- const start = new Date(2026, 0, 20);
113
- const end = new Date(2026, 0, 10);
114
- expect(iso(normalizeRange({ start, end }).start)).toBe("2026-01-10");
115
- expect(iso(normalizeRange({ start, end }).end)).toBe("2026-01-20");
116
- expect(normalizeRange({ start, end: null }).end).toBeNull();
117
- });
118
-
119
- it("includes both ends", () => {
120
- const start = new Date(2026, 0, 10);
121
- const end = new Date(2026, 0, 20);
122
- expect(isInRange(new Date(2026, 0, 10), start, end)).toBe(true);
123
- expect(isInRange(new Date(2026, 0, 20), start, end)).toBe(true);
124
- expect(isInRange(new Date(2026, 0, 21), start, end)).toBe(false);
125
- expect(isInRange(new Date(2026, 0, 15), start, null)).toBe(false);
126
- });
127
- });
128
-
129
- describe("keyboard movement", () => {
130
- const wednesday = new Date(2026, 1, 11);
131
-
132
- it("moves by day, week and month", () => {
133
- expect(iso(moveByKey(wednesday, "ArrowLeft"))).toBe("2026-02-10");
134
- expect(iso(moveByKey(wednesday, "ArrowRight"))).toBe("2026-02-12");
135
- expect(iso(moveByKey(wednesday, "ArrowUp"))).toBe("2026-02-04");
136
- expect(iso(moveByKey(wednesday, "ArrowDown"))).toBe("2026-02-18");
137
- expect(iso(moveByKey(wednesday, "PageUp"))).toBe("2026-01-11");
138
- expect(iso(moveByKey(wednesday, "PageDown"))).toBe("2026-03-11");
139
- expect(iso(moveByKey(wednesday, "PageUp", { shiftKey: true }))).toBe("2025-02-11");
140
- expect(iso(moveByKey(wednesday, "PageDown", { shiftKey: true }))).toBe("2027-02-11");
141
- expect(moveByKey(wednesday, "a")).toBeNull();
142
- });
143
-
144
- it("takes Home and End to the ends of the displayed week", () => {
145
- expect(iso(moveByKey(wednesday, "Home", { weekStartsOn: 1 }))).toBe("2026-02-09");
146
- expect(iso(moveByKey(wednesday, "End", { weekStartsOn: 1 }))).toBe("2026-02-15");
147
- expect(iso(moveByKey(wednesday, "Home", { weekStartsOn: 0 }))).toBe("2026-02-08");
148
- expect(iso(moveByKey(wednesday, "End", { weekStartsOn: 0 }))).toBe("2026-02-14");
149
- });
150
-
151
- it("swaps the arrows in right-to-left layouts", () => {
152
- expect(iso(moveByKey(wednesday, "ArrowRight", { rtl: true }))).toBe("2026-02-10");
153
- expect(iso(moveByKey(wednesday, "ArrowLeft", { rtl: true }))).toBe("2026-02-12");
154
- });
155
-
156
- it("moves inside the month and year panels without leaving the grid", () => {
157
- expect(moveInGrid(4, "ArrowDown", 3, 12)).toBe(7);
158
- expect(moveInGrid(10, "ArrowDown", 3, 12)).toBe(11);
159
- expect(moveInGrid(1, "ArrowUp", 3, 12)).toBe(0);
160
- expect(moveInGrid(5, "Home", 3, 12)).toBe(0);
161
- expect(moveInGrid(5, "End", 3, 12)).toBe(11);
162
- expect(moveInGrid(5, "Enter", 3, 12)).toBeNull();
163
- });
164
-
165
- it("pages years in steady blocks", () => {
166
- expect(yearPage(2026, 12)[0]).toBe(2016);
167
- expect(yearPage(2026, 12)).toHaveLength(12);
168
- expect(yearPage(2016, 12)[0]).toBe(2016);
169
- });
170
- });
171
-
172
- describe("locale formatting", () => {
173
- it("reports the field order and a matching placeholder", () => {
174
- expect(fieldOrder("en-GB")).toEqual(["day", "month", "year"]);
175
- expect(fieldOrder("en-US")).toEqual(["month", "day", "year"]);
176
- expect(inputPlaceholder("en-GB")).toBe("dd/mm/yyyy");
177
- expect(inputPlaceholder("en-US")).toBe("mm/dd/yyyy");
178
- });
179
-
180
- it("orders weekday names from the first day of the week", () => {
181
- expect(weekdayNames("en-GB", 1)[0].short).toBe("Mon");
182
- expect(weekdayNames("en-US", 0)[0].short).toBe("Sun");
183
- expect(weekdayNames("en-GB", 1)[0].long).toBe("Monday");
184
- expect(monthNames("en-GB")[0]).toBe("January");
185
- });
186
- });
187
-
188
- describe("typed input", () => {
189
- const reference = new Date(2026, 4, 20);
190
-
191
- it("accepts ISO whatever the locale", () => {
192
- expect(iso(parseDate("2026-03-12", "en-US", reference))).toBe("2026-03-12");
193
- });
194
-
195
- it("reads numbers in the locale's own order", () => {
196
- expect(iso(parseDate("3/4/2026", "en-GB", reference))).toBe("2026-04-03");
197
- expect(iso(parseDate("3/4/2026", "en-US", reference))).toBe("2026-03-04");
198
- expect(iso(parseDate("15.8.2026", "de-DE", reference))).toBe("2026-08-15");
199
- });
200
-
201
- it("fills in what was left out", () => {
202
- expect(iso(parseDate("15/8", "en-GB", reference))).toBe("2026-08-15");
203
- expect(iso(parseDate("5", "en-GB", reference))).toBe("2026-05-05");
204
- expect(iso(parseDate("15/8/26", "en-GB", reference))).toBe("2026-08-15");
205
- expect(iso(parseDate("15/8/95", "en-GB", reference))).toBe("1995-08-15");
206
- });
207
-
208
- it("understands written month names", () => {
209
- expect(iso(parseDate("12 Mar 2026", "en-GB", reference))).toBe("2026-03-12");
210
- expect(iso(parseDate("March 12, 2026", "en-US", reference))).toBe("2026-03-12");
211
- expect(iso(parseDate("7 September", "en-GB", reference))).toBe("2026-09-07");
212
- });
213
-
214
- it("rejects anything that isn't a date", () => {
215
- expect(parseDate("", "en-GB", reference)).toBeNull();
216
- expect(parseDate("hello", "en-GB", reference)).toBeNull();
217
- expect(parseDate("31/2/2026", "en-GB", reference)).toBeNull();
218
- expect(parseDate("2026-02-31", "en-GB", reference)).toBeNull();
219
- expect(parseDate("45/45/2026", "en-GB", reference)).toBeNull();
220
- });
221
- });
222
-
223
-
224
- describe("today", () => {
225
- afterEach(() => {
226
- vi.useRealTimers();
227
- });
228
-
229
- it("marks no day at all when the calendar is built without one", () => {
230
- // What a server render and the hydrating render pass, so the markup carries
231
- // no date the browser might disagree with.
232
- const month = buildMonth(2026, 8, { today: null });
233
- const marked = month.weeks.flatMap((week) => week.days).filter((day) => day.today);
234
- expect(marked).toHaveLength(0);
235
- });
236
-
237
- it("serves the same day object until the day changes", () => {
238
- expect(getToday()).toBe(getToday());
239
- expect(getServerToday()).toBeNull();
240
- });
241
-
242
- it("rolls over at the next local midnight and tells its subscribers", () => {
243
- vi.useFakeTimers();
244
- vi.setSystemTime(new Date(2026, 8, 18, 23, 30));
245
-
246
- const seen: string[] = [];
247
- const unsubscribe = subscribeToToday(() => seen.push(toISODate(getToday())));
248
- expect(toISODate(getToday())).toBe("2026-09-18");
249
-
250
- vi.advanceTimersByTime(29 * 60 * 1000);
251
- expect(seen).toEqual([]);
252
-
253
- vi.advanceTimersByTime(60 * 1000);
254
- expect(seen).toEqual(["2026-09-19"]);
255
- expect(toISODate(getToday())).toBe("2026-09-19");
256
-
257
- unsubscribe();
258
- });
259
-
260
- it("catches up after a machine sleeps through midnight", () => {
261
- vi.useFakeTimers();
262
- vi.setSystemTime(new Date(2026, 8, 18, 23, 59));
263
-
264
- const seen: string[] = [];
265
- const unsubscribe = subscribeToToday(() => seen.push(toISODate(getToday())));
266
- // The clock jumps two days while the timer never gets to run.
267
- vi.setSystemTime(new Date(2026, 8, 20, 9, 0));
268
- vi.advanceTimersByTime(60 * 1000);
269
-
270
- expect(seen).toEqual(["2026-09-20"]);
271
- unsubscribe();
272
- });
273
- });
@@ -1,86 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { createDialogApi } from "../core/api";
3
- import { dialog, dialogStore } from "../core/dialog";
4
- import { createDialogStore, resultFor } from "../core/store";
5
-
6
- describe("results", () => {
7
- it("maps an answer to each kind's value", () => {
8
- expect(resultFor("confirm", true)).toBe(true);
9
- expect(resultFor("confirm", false)).toBe(false);
10
- expect(resultFor("prompt", true, "Ada")).toBe("Ada");
11
- expect(resultFor("prompt", true)).toBe("");
12
- expect(resultFor("prompt", false, "ignored")).toBeNull();
13
- expect(resultFor("alert", true)).toBeUndefined();
14
- });
15
- });
16
-
17
- describe("queue", () => {
18
- it("shows one dialog at a time, in order", async () => {
19
- const store = createDialogStore();
20
- const api = createDialogApi(store);
21
-
22
- const first = api.confirm("Delete the file?");
23
- const second = api.prompt({ title: "Rename", defaultValue: "report.pdf" });
24
- const [a, b] = store.getSnapshot().queue;
25
- expect(a).toMatchObject({ kind: "confirm", options: { title: "Delete the file?" } });
26
- expect(b).toMatchObject({ kind: "prompt", options: { defaultValue: "report.pdf" } });
27
-
28
- store.resolve(a.id, true);
29
- expect(await first).toBe(true);
30
- expect(store.getSnapshot().queue.map((item) => item.id)).toEqual([b.id]);
31
-
32
- store.resolve(b.id, true, "summary.pdf");
33
- expect(await second).toBe("summary.pdf");
34
- expect(store.getSnapshot().queue).toHaveLength(0);
35
- });
36
-
37
- it("notifies subscribers and ignores unknown or repeated answers", async () => {
38
- const store = createDialogStore();
39
- const listener = vi.fn();
40
- store.subscribe(listener);
41
-
42
- const answer = store.open("alert", { title: "Saved" });
43
- const [request] = store.getSnapshot().queue;
44
- store.resolve("dialog-404", true);
45
- store.resolve(request.id, true);
46
- store.resolve(request.id, false);
47
-
48
- expect(await answer).toBeUndefined();
49
- expect(listener).toHaveBeenCalledTimes(2);
50
- });
51
-
52
- it("cancels everything with dismissAll", async () => {
53
- const store = createDialogStore();
54
- const api = createDialogApi(store);
55
- const results = Promise.all([api.confirm("One?"), api.prompt("Two?"), api.alert("Three")]);
56
-
57
- api.dismissAll();
58
- expect(await results).toEqual([false, null, undefined]);
59
- expect(store.getSnapshot().queue).toHaveLength(0);
60
- });
61
-
62
- it("keeps the snapshot object until something changes", () => {
63
- const store = createDialogStore();
64
- const before = store.getSnapshot();
65
- expect(store.getSnapshot()).toBe(before);
66
- void store.open("alert", { title: "Hi" });
67
- expect(store.getSnapshot()).not.toBe(before);
68
- });
69
- });
70
-
71
- describe("where nothing can be shown", () => {
72
- it("answers as a cancel at once", async () => {
73
- const store = createDialogStore();
74
- const api = createDialogApi(store, () => false);
75
- expect(await api.confirm("Sure?")).toBe(false);
76
- expect(await api.prompt("Name?")).toBeNull();
77
- expect(await api.alert("Hi")).toBeUndefined();
78
- expect(store.getSnapshot().queue).toHaveLength(0);
79
- });
80
-
81
- it("does so for the default dialog on a server, where there is no document", async () => {
82
- expect(typeof document).toBe("undefined");
83
- expect(await dialog.confirm("Rendered on the server")).toBe(false);
84
- expect(dialogStore.getSnapshot().queue).toHaveLength(0);
85
- });
86
- });