foldkit 0.43.2 → 0.45.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 (59) hide show
  1. package/dist/index.d.ts +2 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -1
  4. package/dist/test/apps/counter.d.ts +38 -0
  5. package/dist/test/apps/counter.d.ts.map +1 -0
  6. package/dist/test/apps/counter.js +25 -0
  7. package/dist/test/apps/formChild.d.ts +69 -0
  8. package/dist/test/apps/formChild.d.ts.map +1 -0
  9. package/dist/test/apps/formChild.js +84 -0
  10. package/dist/test/apps/keypress.d.ts +23 -0
  11. package/dist/test/apps/keypress.d.ts.map +1 -0
  12. package/dist/test/apps/keypress.js +39 -0
  13. package/dist/test/apps/login.d.ts +46 -0
  14. package/dist/test/apps/login.d.ts.map +1 -0
  15. package/dist/test/apps/login.js +83 -0
  16. package/dist/test/apps/logoutButton.d.ts +17 -0
  17. package/dist/test/apps/logoutButton.d.ts.map +1 -0
  18. package/dist/test/apps/logoutButton.js +22 -0
  19. package/dist/test/internal.d.ts +25 -0
  20. package/dist/test/internal.d.ts.map +1 -0
  21. package/dist/test/internal.js +39 -0
  22. package/dist/test/matchers.d.ts +94 -0
  23. package/dist/test/matchers.d.ts.map +1 -0
  24. package/dist/test/matchers.js +283 -0
  25. package/dist/test/public.d.ts +2 -2
  26. package/dist/test/public.d.ts.map +1 -1
  27. package/dist/test/public.js +2 -1
  28. package/dist/test/query.d.ts +88 -0
  29. package/dist/test/query.d.ts.map +1 -0
  30. package/dist/test/query.js +227 -0
  31. package/dist/test/scene.d.ts +106 -0
  32. package/dist/test/scene.d.ts.map +1 -0
  33. package/dist/test/scene.js +373 -0
  34. package/dist/test/{index.d.ts → story.d.ts} +13 -17
  35. package/dist/test/story.d.ts.map +1 -0
  36. package/dist/test/{index.js → story.js} +8 -36
  37. package/dist/test/vitest-setup.d.ts +19 -0
  38. package/dist/test/vitest-setup.d.ts.map +1 -0
  39. package/dist/test/vitest-setup.js +3 -0
  40. package/dist/ui/input/index.d.ts +0 -2
  41. package/dist/ui/input/index.d.ts.map +1 -1
  42. package/dist/ui/input/index.js +2 -5
  43. package/dist/ui/input/public.d.ts +1 -1
  44. package/dist/ui/input/public.d.ts.map +1 -1
  45. package/dist/ui/input/public.js +1 -1
  46. package/dist/ui/select/index.d.ts +0 -2
  47. package/dist/ui/select/index.d.ts.map +1 -1
  48. package/dist/ui/select/index.js +2 -5
  49. package/dist/ui/select/public.d.ts +1 -1
  50. package/dist/ui/select/public.d.ts.map +1 -1
  51. package/dist/ui/select/public.js +1 -1
  52. package/dist/ui/textarea/index.d.ts +0 -2
  53. package/dist/ui/textarea/index.d.ts.map +1 -1
  54. package/dist/ui/textarea/index.js +2 -5
  55. package/dist/ui/textarea/public.d.ts +1 -1
  56. package/dist/ui/textarea/public.d.ts.map +1 -1
  57. package/dist/ui/textarea/public.js +1 -1
  58. package/package.json +5 -5
  59. package/dist/test/index.d.ts.map +0 -1
@@ -0,0 +1,94 @@
1
+ import { Option } from 'effect';
2
+ import type { VNode } from '../vdom';
3
+ /** Custom Vitest matchers for scene testing. Register with `expect.extend(Scene.sceneMatchers)`. */
4
+ export declare const sceneMatchers: {
5
+ toHaveText(received: Option.Option<VNode>, expected: string): {
6
+ pass: boolean;
7
+ message: () => string;
8
+ } | {
9
+ pass: boolean;
10
+ message: () => string;
11
+ };
12
+ toContainText(received: Option.Option<VNode>, expected: string): {
13
+ pass: boolean;
14
+ message: () => string;
15
+ } | {
16
+ pass: boolean;
17
+ message: () => string;
18
+ };
19
+ toHaveClass(received: Option.Option<VNode>, expected: string): {
20
+ pass: boolean;
21
+ message: () => string;
22
+ } | {
23
+ pass: boolean;
24
+ message: () => string;
25
+ };
26
+ toHaveAttr(received: Option.Option<VNode>, name: string, expectedValue?: string): {
27
+ pass: boolean;
28
+ message: () => string;
29
+ } | {
30
+ pass: boolean;
31
+ message: () => string;
32
+ };
33
+ toExist(received: Option.Option<VNode>): {
34
+ pass: boolean;
35
+ message: () => "Expected element not to exist but it does." | "Expected element to exist but it does not.";
36
+ };
37
+ toBeAbsent(received: Option.Option<VNode>): {
38
+ pass: boolean;
39
+ message: () => "Expected element not to be absent but it is." | "Expected element to be absent but it exists.";
40
+ };
41
+ toHaveStyle(received: Option.Option<VNode>, name: string, expectedValue?: string): {
42
+ pass: boolean;
43
+ message: () => string;
44
+ } | {
45
+ pass: boolean;
46
+ message: () => string;
47
+ };
48
+ toHaveHook(received: Option.Option<VNode>, name: string): {
49
+ pass: boolean;
50
+ message: () => string;
51
+ } | {
52
+ pass: boolean;
53
+ message: () => string;
54
+ };
55
+ toHaveHandler(received: Option.Option<VNode>, name: string): {
56
+ pass: boolean;
57
+ message: () => string;
58
+ } | {
59
+ pass: boolean;
60
+ message: () => string;
61
+ };
62
+ toHaveValue(received: Option.Option<VNode>, expected: string): {
63
+ pass: boolean;
64
+ message: () => string;
65
+ } | {
66
+ pass: false;
67
+ message: () => string;
68
+ } | {
69
+ pass: boolean;
70
+ message: () => string;
71
+ };
72
+ toBeDisabled(received: Option.Option<VNode>): {
73
+ pass: boolean;
74
+ message: () => "Expected element to be disabled but the element does not exist.";
75
+ } | {
76
+ pass: boolean;
77
+ message: () => "Expected element not to be disabled but it is." | "Expected element to be disabled but it is not.";
78
+ };
79
+ toBeEnabled(received: Option.Option<VNode>): {
80
+ pass: boolean;
81
+ message: () => "Expected element to be enabled but the element does not exist.";
82
+ } | {
83
+ pass: boolean;
84
+ message: () => "Expected element not to be enabled but it is." | "Expected element to be enabled but it is disabled.";
85
+ };
86
+ toBeChecked(received: Option.Option<VNode>): {
87
+ pass: boolean;
88
+ message: () => "Expected element to be checked but the element does not exist.";
89
+ } | {
90
+ pass: boolean;
91
+ message: () => "Expected element not to be checked but it is." | "Expected element to be checked but it is not.";
92
+ };
93
+ };
94
+ //# sourceMappingURL=matchers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/test/matchers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAKpC,oGAAoG;AACpG,eAAO,MAAM,aAAa;yBACH,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM;;;;;;;4BAqBnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM;;;;;;;0BAqBxC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM;;;;;;;yBAmBhD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QACxB,MAAM,kBACI,MAAM;;;;;;;sBA2CN,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;yBAWjB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;0BAY7B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QACxB,MAAM,kBACI,MAAM;;;;;;;yBA8CH,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,MAAM;;;;;;;4BAsB/B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,MAAM;;;;;;;0BAkBpC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM;;;;;;;;;;2BA4BrC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;0BAyBrB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;0BAyBpB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;;;;;;;CAwB3C,CAAA"}
@@ -0,0 +1,283 @@
1
+ import { Option } from 'effect';
2
+ import { attr, textContent } from './query';
3
+ /** Custom Vitest matchers for scene testing. Register with `expect.extend(Scene.sceneMatchers)`. */
4
+ export const sceneMatchers = {
5
+ toHaveText(received, expected) {
6
+ return Option.match(received, {
7
+ onNone: () => ({
8
+ pass: false,
9
+ message: () => `Expected element to have text "${expected}" but the element does not exist.`,
10
+ }),
11
+ onSome: vnode => {
12
+ const actualText = textContent(vnode);
13
+ return {
14
+ pass: actualText === expected,
15
+ message: () =>
16
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
17
+ this.isNot
18
+ ? `Expected element not to have text "${expected}" but it does.`
19
+ : `Expected element to have text "${expected}" but received "${actualText}".`,
20
+ };
21
+ },
22
+ });
23
+ },
24
+ toContainText(received, expected) {
25
+ return Option.match(received, {
26
+ onNone: () => ({
27
+ pass: false,
28
+ message: () => `Expected element to contain text "${expected}" but the element does not exist.`,
29
+ }),
30
+ onSome: vnode => {
31
+ const actualText = textContent(vnode);
32
+ return {
33
+ pass: actualText.includes(expected),
34
+ message: () =>
35
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
36
+ this.isNot
37
+ ? `Expected element not to contain text "${expected}" but it does.`
38
+ : `Expected element to contain text "${expected}" but received "${actualText}".`,
39
+ };
40
+ },
41
+ });
42
+ },
43
+ toHaveClass(received, expected) {
44
+ return Option.match(received, {
45
+ onNone: () => ({
46
+ pass: false,
47
+ message: () => `Expected element to have class "${expected}" but the element does not exist.`,
48
+ }),
49
+ onSome: vnode => ({
50
+ pass: vnode.data?.class?.[expected] === true,
51
+ message: () =>
52
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
53
+ this.isNot
54
+ ? `Expected element not to have class "${expected}" but it does.`
55
+ : `Expected element to have class "${expected}" but it does not.`,
56
+ }),
57
+ });
58
+ },
59
+ toHaveAttr(received, name, expectedValue) {
60
+ return Option.match(received, {
61
+ onNone: () => ({
62
+ pass: false,
63
+ message: () => expectedValue === undefined
64
+ ? `Expected element to have attribute "${name}" but the element does not exist.`
65
+ : `Expected element to have attribute ${name}="${expectedValue}" but the element does not exist.`,
66
+ }),
67
+ onSome: vnode => {
68
+ const actualValue = attr(vnode, name);
69
+ if (expectedValue === undefined) {
70
+ return {
71
+ pass: Option.isSome(actualValue),
72
+ message: () =>
73
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
74
+ this.isNot
75
+ ? `Expected element not to have attribute "${name}" but it does.`
76
+ : `Expected element to have attribute "${name}" but it is not present.`,
77
+ };
78
+ }
79
+ return Option.match(actualValue, {
80
+ onNone: () => ({
81
+ pass: false,
82
+ message: () => `Expected element to have attribute ${name}="${expectedValue}" but the attribute is not present.`,
83
+ }),
84
+ onSome: actual => ({
85
+ pass: actual === expectedValue,
86
+ message: () =>
87
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
88
+ this.isNot
89
+ ? `Expected element not to have attribute ${name}="${expectedValue}" but it does.`
90
+ : `Expected element to have attribute ${name}="${expectedValue}" but received "${actual}".`,
91
+ }),
92
+ });
93
+ },
94
+ });
95
+ },
96
+ toExist(received) {
97
+ return {
98
+ pass: Option.isSome(received),
99
+ message: () =>
100
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
101
+ this.isNot
102
+ ? 'Expected element not to exist but it does.'
103
+ : 'Expected element to exist but it does not.',
104
+ };
105
+ },
106
+ toBeAbsent(received) {
107
+ return {
108
+ pass: Option.isNone(received),
109
+ message: () =>
110
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
111
+ this.isNot
112
+ ? 'Expected element not to be absent but it is.'
113
+ : 'Expected element to be absent but it exists.',
114
+ };
115
+ },
116
+ toHaveStyle(received, name, expectedValue) {
117
+ return Option.match(received, {
118
+ onNone: () => ({
119
+ pass: false,
120
+ message: () => expectedValue === undefined
121
+ ? `Expected element to have style "${name}" but the element does not exist.`
122
+ : `Expected element to have style ${name}="${expectedValue}" but the element does not exist.`,
123
+ }),
124
+ onSome: vnode => {
125
+ const maybeActualValue = Option.fromNullable(vnode.data?.style?.[name]);
126
+ if (expectedValue === undefined) {
127
+ return {
128
+ pass: Option.isSome(maybeActualValue),
129
+ message: () =>
130
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
131
+ this.isNot
132
+ ? `Expected element not to have style "${name}" but it does.`
133
+ : `Expected element to have style "${name}" but it is not present.`,
134
+ };
135
+ }
136
+ return Option.match(maybeActualValue, {
137
+ onNone: () => ({
138
+ pass: false,
139
+ message: () => `Expected element to have style ${name}="${expectedValue}" but the style is not present.`,
140
+ }),
141
+ onSome: actualValue => {
142
+ const actual = String(actualValue);
143
+ return {
144
+ pass: actual === expectedValue,
145
+ message: () =>
146
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
147
+ this.isNot
148
+ ? `Expected element not to have style ${name}="${expectedValue}" but it does.`
149
+ : `Expected element to have style ${name}="${expectedValue}" but received "${actual}".`,
150
+ };
151
+ },
152
+ });
153
+ },
154
+ });
155
+ },
156
+ toHaveHook(received, name) {
157
+ return Option.match(received, {
158
+ onNone: () => ({
159
+ pass: false,
160
+ message: () => `Expected element to have hook "${name}" but the element does not exist.`,
161
+ }),
162
+ onSome: vnode => {
163
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
164
+ const hooks = vnode.data?.hook;
165
+ return {
166
+ pass: typeof hooks?.[name] === 'function',
167
+ message: () =>
168
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
169
+ this.isNot
170
+ ? `Expected element not to have hook "${name}" but it does.`
171
+ : `Expected element to have hook "${name}" but it is not present.`,
172
+ };
173
+ },
174
+ });
175
+ },
176
+ toHaveHandler(received, name) {
177
+ return Option.match(received, {
178
+ onNone: () => ({
179
+ pass: false,
180
+ message: () => `Expected element to have handler "${name}" but the element does not exist.`,
181
+ }),
182
+ onSome: vnode => ({
183
+ pass: vnode.data?.on?.[name] !== undefined,
184
+ message: () =>
185
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
186
+ this.isNot
187
+ ? `Expected element not to have handler "${name}" but it does.`
188
+ : `Expected element to have handler "${name}" but it is not present.`,
189
+ }),
190
+ });
191
+ },
192
+ toHaveValue(received, expected) {
193
+ return Option.match(received, {
194
+ onNone: () => ({
195
+ pass: false,
196
+ message: () => `Expected element to have value "${expected}" but the element does not exist.`,
197
+ }),
198
+ onSome: vnode => {
199
+ const actualValue = attr(vnode, 'value');
200
+ return Option.match(actualValue, {
201
+ onNone: () => ({
202
+ pass: false,
203
+ message: () => `Expected element to have value "${expected}" but the element has no value.`,
204
+ }),
205
+ onSome: actual => ({
206
+ pass: actual === expected,
207
+ message: () =>
208
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
209
+ this.isNot
210
+ ? `Expected element not to have value "${expected}" but it does.`
211
+ : `Expected element to have value "${expected}" but received "${actual}".`,
212
+ }),
213
+ });
214
+ },
215
+ });
216
+ },
217
+ toBeDisabled(received) {
218
+ return Option.match(received, {
219
+ onNone: () => ({
220
+ pass: false,
221
+ message: () => 'Expected element to be disabled but the element does not exist.',
222
+ }),
223
+ onSome: vnode => {
224
+ const disabled = attr(vnode, 'disabled');
225
+ const ariaDisabled = attr(vnode, 'aria-disabled');
226
+ const pass = (Option.isSome(disabled) && disabled.value !== 'false') ||
227
+ (Option.isSome(ariaDisabled) && ariaDisabled.value === 'true');
228
+ return {
229
+ pass,
230
+ message: () =>
231
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
232
+ this.isNot
233
+ ? 'Expected element not to be disabled but it is.'
234
+ : 'Expected element to be disabled but it is not.',
235
+ };
236
+ },
237
+ });
238
+ },
239
+ toBeEnabled(received) {
240
+ return Option.match(received, {
241
+ onNone: () => ({
242
+ pass: false,
243
+ message: () => 'Expected element to be enabled but the element does not exist.',
244
+ }),
245
+ onSome: vnode => {
246
+ const disabled = attr(vnode, 'disabled');
247
+ const ariaDisabled = attr(vnode, 'aria-disabled');
248
+ const isDisabled = (Option.isSome(disabled) && disabled.value !== 'false') ||
249
+ (Option.isSome(ariaDisabled) && ariaDisabled.value === 'true');
250
+ return {
251
+ pass: !isDisabled,
252
+ message: () =>
253
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
254
+ this.isNot
255
+ ? 'Expected element not to be enabled but it is.'
256
+ : 'Expected element to be enabled but it is disabled.',
257
+ };
258
+ },
259
+ });
260
+ },
261
+ toBeChecked(received) {
262
+ return Option.match(received, {
263
+ onNone: () => ({
264
+ pass: false,
265
+ message: () => 'Expected element to be checked but the element does not exist.',
266
+ }),
267
+ onSome: vnode => {
268
+ const checked = attr(vnode, 'checked');
269
+ const ariaChecked = attr(vnode, 'aria-checked');
270
+ const pass = (Option.isSome(checked) && checked.value !== 'false') ||
271
+ (Option.isSome(ariaChecked) && ariaChecked.value === 'true');
272
+ return {
273
+ pass,
274
+ message: () =>
275
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
276
+ this.isNot
277
+ ? 'Expected element not to be checked but it is.'
278
+ : 'Expected element to be checked but it is not.',
279
+ };
280
+ },
281
+ });
282
+ },
283
+ };
@@ -1,3 +1,3 @@
1
- export type { AnyCommand, ResolverPair, Simulation, StoryStep, WithStep, } from './index';
2
- export { message, resolve, resolveAll, story, tap, with } from './index';
1
+ export * as Story from './story';
2
+ export * as Scene from './scene';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/test/public.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,UAAU,EACV,YAAY,EACZ,UAAU,EACV,SAAS,EACT,QAAQ,GACT,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/test/public.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA;AAChC,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA"}
@@ -1 +1,2 @@
1
- export { message, resolve, resolveAll, story, tap, with } from './index';
1
+ export * as Story from './story';
2
+ export * as Scene from './scene';
@@ -0,0 +1,88 @@
1
+ import { Option } from 'effect';
2
+ import type { VNode } from '../vdom';
3
+ type MatchMode = 'Exact' | 'StartsWith';
4
+ type AttributeMatcher = Readonly<{
5
+ name: string;
6
+ value: Option.Option<string>;
7
+ mode: MatchMode;
8
+ }>;
9
+ type SimpleSelector = Readonly<{
10
+ tag: Option.Option<string>;
11
+ id: Option.Option<string>;
12
+ classes: ReadonlyArray<string>;
13
+ attributes: ReadonlyArray<AttributeMatcher>;
14
+ }>;
15
+ type Selector = ReadonlyArray<SimpleSelector>;
16
+ export declare const parseSelector: (input: string) => Selector;
17
+ /** Finds the first VNode matching the CSS selector. */
18
+ export declare const find: {
19
+ (html: VNode, selectorString: string): Option.Option<VNode>;
20
+ (selectorString: string): (html: VNode) => Option.Option<VNode>;
21
+ };
22
+ /** Finds all VNodes matching the CSS selector. */
23
+ export declare const findAll: {
24
+ (html: VNode, selectorString: string): ReadonlyArray<VNode>;
25
+ (selectorString: string): (html: VNode) => ReadonlyArray<VNode>;
26
+ };
27
+ /** Extracts all text content from a VNode tree, depth-first. */
28
+ export declare const textContent: (vnode: VNode) => string;
29
+ /** Reads an attribute or prop value from a VNode. */
30
+ export declare const attr: {
31
+ (vnode: VNode, name: string): Option.Option<string>;
32
+ (name: string): (vnode: VNode) => Option.Option<string>;
33
+ };
34
+ /** Finds the first element with the given ARIA role and optional accessible name. */
35
+ export declare const getByRole: (role: string, options?: Readonly<{
36
+ name?: string;
37
+ }>) => (html: VNode) => Option.Option<VNode>;
38
+ /** Finds all elements with the given ARIA role and optional accessible name. */
39
+ export declare const getAllByRole: (html: VNode, role: string, options?: Readonly<{
40
+ name?: string;
41
+ }>) => ReadonlyArray<VNode>;
42
+ /** Finds the most specific element matching the given text content.
43
+ * Skips text VNodes (sel undefined) — only returns actual DOM elements. */
44
+ export declare const getByText: (target: string, options?: Readonly<{
45
+ exact?: boolean;
46
+ }>) => (html: VNode) => Option.Option<VNode>;
47
+ /** Finds the first element with the given placeholder attribute. */
48
+ export declare const getByPlaceholder: (placeholderValue: string) => (html: VNode) => Option.Option<VNode>;
49
+ /** Finds the first element with the given label text. Checks `aria-label`
50
+ * first, then `<label for="id">` association, then `<label>` nesting,
51
+ * then `aria-labelledby` reverse lookup. */
52
+ export declare const getByLabel: (labelValue: string) => (html: VNode) => Option.Option<VNode>;
53
+ /** A deferred element query that resolves against a VNode tree. Callable as a
54
+ * function (`locator(html)`) so it composes directly in `flow` and `pipe` chains.
55
+ * Used by interaction steps (`click`, `type`, `submit`, `keydown`) to
56
+ * target elements by accessible attributes instead of CSS selectors. */
57
+ export type Locator = ((html: VNode) => Option.Option<VNode>) & Readonly<{
58
+ description: string;
59
+ }>;
60
+ /** Creates a Locator that finds an element by ARIA role and optional accessible name. */
61
+ export declare const role: (roleValue: string, options?: Readonly<{
62
+ name?: string;
63
+ }>) => Locator;
64
+ /** Creates a Locator that finds an element by placeholder attribute. */
65
+ export declare const placeholder: (placeholderValue: string) => Locator;
66
+ /** Creates a Locator that finds an element by aria-label. */
67
+ export declare const label: (labelValue: string) => Locator;
68
+ /** Creates a Locator that finds the most specific element matching the given text content. */
69
+ export declare const text: (target: string, options?: Readonly<{
70
+ exact?: boolean;
71
+ }>) => Locator;
72
+ /** Creates a Locator that wraps a CSS selector. Escape hatch for cases
73
+ * where no accessible attribute is available. */
74
+ export declare const selector: (css: string) => Locator;
75
+ /** Creates a scoped Locator that finds the child within the parent.
76
+ * Composes via `Option.flatMap` — the parent is resolved first, then
77
+ * the child is searched within the parent's subtree. */
78
+ export declare const within: {
79
+ (parent: Locator, child: Locator): Locator;
80
+ (child: Locator): (parent: Locator) => Locator;
81
+ };
82
+ /** Resolves a target (CSS selector string or Locator) against a VNode tree. */
83
+ export declare const resolveTarget: (html: VNode, target: string | Locator) => Readonly<{
84
+ maybeElement: Option.Option<VNode>;
85
+ description: string;
86
+ }>;
87
+ export {};
88
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/test/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,MAAM,EAMP,MAAM,QAAQ,CAAA;AAIf,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAIpC,KAAK,SAAS,GAAG,OAAO,GAAG,YAAY,CAAA;AAEvC,KAAK,gBAAgB,GAAG,QAAQ,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC5B,IAAI,EAAE,SAAS,CAAA;CAChB,CAAC,CAAA;AAEF,KAAK,cAAc,GAAG,QAAQ,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC1B,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACzB,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC9B,UAAU,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAA;CAC5C,CAAC,CAAA;AAEF,KAAK,QAAQ,GAAG,aAAa,CAAC,cAAc,CAAC,CAAA;AAmI7C,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,KAAG,QAc7C,CAAA;AA+QD,uDAAuD;AACvD,eAAO,MAAM,IAAI,EAAE;IACjB,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAC3D,CAAC,cAAc,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;CAKhE,CAAA;AAED,kDAAkD;AAClD,eAAO,MAAM,OAAO,EAAE;IACpB,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;IAC3D,CAAC,cAAc,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,KAAK,KAAK,aAAa,CAAC,KAAK,CAAC,CAAA;CAGhE,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,WAAW,GAAI,OAAO,KAAK,KAAG,MAU1C,CAAA;AAsBD,qDAAqD;AACrD,eAAO,MAAM,IAAI,EAAE;IACjB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACnD,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;CACpC,CAAA;AAIrB,qFAAqF;AACrF,eAAO,MAAM,SAAS,GACnB,MAAM,MAAM,EAAE,UAAU,QAAQ,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,MACnD,MAAM,KAAK,KAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAYjC,CAAA;AAEH,gFAAgF;AAChF,eAAO,MAAM,YAAY,GACvB,MAAM,KAAK,EACX,MAAM,MAAM,EACZ,UAAU,QAAQ,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,KACpC,aAAa,CAAC,KAAK,CAYrB,CAAA;AAED;4EAC4E;AAC5E,eAAO,MAAM,SAAS,GACnB,QAAQ,MAAM,EAAE,UAAU,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,MACvD,MAAM,KAAK,KAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAmBjC,CAAA;AAEH,oEAAoE;AACpE,eAAO,MAAM,gBAAgB,GAC1B,kBAAkB,MAAM,MACxB,MAAM,KAAK,KAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAO/B,CAAA;AAEL;;6CAE6C;AAC7C,eAAO,MAAM,UAAU,GACpB,YAAY,MAAM,MAClB,MAAM,KAAK,KAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAuCjC,CAAA;AAIH;;;yEAGyE;AACzE,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAC3D,QAAQ,CAAC;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAOnC,yFAAyF;AACzF,eAAO,MAAM,IAAI,GACf,WAAW,MAAM,EACjB,UAAU,QAAQ,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,KACpC,OAOA,CAAA;AAEH,wEAAwE;AACxE,eAAO,MAAM,WAAW,GAAI,kBAAkB,MAAM,KAAG,OAIpD,CAAA;AAEH,6DAA6D;AAC7D,eAAO,MAAM,KAAK,GAAI,YAAY,MAAM,KAAG,OACmB,CAAA;AAE9D,8FAA8F;AAC9F,eAAO,MAAM,IAAI,GACf,QAAQ,MAAM,EACd,UAAU,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,KACtC,OAAsE,CAAA;AAEzE;kDACkD;AAClD,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,KAAG,OACsB,CAAA;AAE7D;;yDAEyD;AACzD,eAAO,MAAM,MAAM,EAAE;IACnB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAA;IAC1C,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAA;CAQ/C,CAAA;AAED,+EAA+E;AAC/E,eAAO,MAAM,aAAa,GACxB,MAAM,KAAK,EACX,QAAQ,MAAM,GAAG,OAAO,KACvB,QAAQ,CAAC;IAAE,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAQtE,CAAA"}