@oddkin/workbench 0.0.0-stage → 1.0.0-beta.1
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.
- package/LICENSE +21 -0
- package/README.md +66 -2
- package/dist/app/card-previews.d.ts +14 -0
- package/dist/app/card-previews.d.ts.map +1 -0
- package/dist/app/card-previews.js +140 -0
- package/dist/app/card-previews.js.map +1 -0
- package/dist/app/copy.d.ts +48 -0
- package/dist/app/copy.d.ts.map +1 -0
- package/dist/app/copy.js +52 -0
- package/dist/app/copy.js.map +1 -0
- package/dist/app/define.d.ts +3 -0
- package/dist/app/define.d.ts.map +1 -0
- package/dist/app/define.js +10 -0
- package/dist/app/define.js.map +1 -0
- package/dist/app/details.d.ts +22 -0
- package/dist/app/details.d.ts.map +1 -0
- package/dist/app/details.js +17 -0
- package/dist/app/details.js.map +1 -0
- package/dist/app/index.d.ts +12 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +9 -0
- package/dist/app/index.js.map +1 -0
- package/dist/app/routes.d.ts +26 -0
- package/dist/app/routes.d.ts.map +1 -0
- package/dist/app/routes.js +96 -0
- package/dist/app/routes.js.map +1 -0
- package/dist/app/search.d.ts +17 -0
- package/dist/app/search.d.ts.map +1 -0
- package/dist/app/search.js +52 -0
- package/dist/app/search.js.map +1 -0
- package/dist/app/shell.d.ts +29 -0
- package/dist/app/shell.d.ts.map +1 -0
- package/dist/app/shell.js +478 -0
- package/dist/app/shell.js.map +1 -0
- package/dist/app/styles.d.ts +2 -0
- package/dist/app/styles.d.ts.map +1 -0
- package/dist/app/styles.js +356 -0
- package/dist/app/styles.js.map +1 -0
- package/dist/app/theme-studio.d.ts +12 -0
- package/dist/app/theme-studio.d.ts.map +1 -0
- package/dist/app/theme-studio.js +14 -0
- package/dist/app/theme-studio.js.map +1 -0
- package/dist/app/views.d.ts +38 -0
- package/dist/app/views.d.ts.map +1 -0
- package/dist/app/views.js +252 -0
- package/dist/app/views.js.map +1 -0
- package/dist/config/index.d.ts +170 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +148 -0
- package/dist/config/index.js.map +1 -0
- package/dist/conformance/button.d.ts +2 -0
- package/dist/conformance/button.d.ts.map +1 -0
- package/dist/conformance/button.js +233 -0
- package/dist/conformance/button.js.map +1 -0
- package/dist/conformance/index.d.ts +107 -0
- package/dist/conformance/index.d.ts.map +1 -0
- package/dist/conformance/index.js +60 -0
- package/dist/conformance/index.js.map +1 -0
- package/dist/data/build.d.ts +36 -0
- package/dist/data/build.d.ts.map +1 -0
- package/dist/data/build.js +260 -0
- package/dist/data/build.js.map +1 -0
- package/dist/data/import-map.d.ts +59 -0
- package/dist/data/import-map.d.ts.map +1 -0
- package/dist/data/import-map.js +195 -0
- package/dist/data/import-map.js.map +1 -0
- package/dist/data/index.d.ts +14 -0
- package/dist/data/index.d.ts.map +1 -0
- package/dist/data/index.js +10 -0
- package/dist/data/index.js.map +1 -0
- package/dist/data/theme-studio.d.ts +21 -0
- package/dist/data/theme-studio.d.ts.map +1 -0
- package/dist/data/theme-studio.js +112 -0
- package/dist/data/theme-studio.js.map +1 -0
- package/dist/data/types.d.ts +187 -0
- package/dist/data/types.d.ts.map +1 -0
- package/dist/data/types.js +4 -0
- package/dist/data/types.js.map +1 -0
- package/dist/examples/index.d.ts +101 -0
- package/dist/examples/index.d.ts.map +1 -0
- package/dist/examples/index.js +106 -0
- package/dist/examples/index.js.map +1 -0
- package/dist/frame/index.d.ts +9 -0
- package/dist/frame/index.d.ts.map +1 -0
- package/dist/frame/index.js +482 -0
- package/dist/frame/index.js.map +1 -0
- package/dist/internal/diagnostics.d.ts +17 -0
- package/dist/internal/diagnostics.d.ts.map +1 -0
- package/dist/internal/diagnostics.js +19 -0
- package/dist/internal/diagnostics.js.map +1 -0
- package/dist/node/bin.d.ts +3 -0
- package/dist/node/bin.d.ts.map +1 -0
- package/dist/node/bin.js +12 -0
- package/dist/node/bin.js.map +1 -0
- package/dist/node/cli.d.ts +17 -0
- package/dist/node/cli.d.ts.map +1 -0
- package/dist/node/cli.js +198 -0
- package/dist/node/cli.js.map +1 -0
- package/dist/node/config.d.ts +28 -0
- package/dist/node/config.d.ts.map +1 -0
- package/dist/node/config.js +80 -0
- package/dist/node/config.js.map +1 -0
- package/dist/node/example-modules.d.ts +8 -0
- package/dist/node/example-modules.d.ts.map +1 -0
- package/dist/node/example-modules.js +28 -0
- package/dist/node/example-modules.js.map +1 -0
- package/dist/node/generated.d.ts +19 -0
- package/dist/node/generated.d.ts.map +1 -0
- package/dist/node/generated.js +109 -0
- package/dist/node/generated.js.map +1 -0
- package/dist/node/html.d.ts +35 -0
- package/dist/node/html.d.ts.map +1 -0
- package/dist/node/html.js +51 -0
- package/dist/node/html.js.map +1 -0
- package/dist/node/index.d.ts +24 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +15 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/inputs.d.ts +26 -0
- package/dist/node/inputs.d.ts.map +1 -0
- package/dist/node/inputs.js +282 -0
- package/dist/node/inputs.js.map +1 -0
- package/dist/node/packages.d.ts +35 -0
- package/dist/node/packages.d.ts.map +1 -0
- package/dist/node/packages.js +87 -0
- package/dist/node/packages.js.map +1 -0
- package/dist/node/preload.d.ts +10 -0
- package/dist/node/preload.d.ts.map +1 -0
- package/dist/node/preload.js +61 -0
- package/dist/node/preload.js.map +1 -0
- package/dist/node/server.d.ts +42 -0
- package/dist/node/server.d.ts.map +1 -0
- package/dist/node/server.js +410 -0
- package/dist/node/server.js.map +1 -0
- package/dist/node/static.d.ts +43 -0
- package/dist/node/static.d.ts.map +1 -0
- package/dist/node/static.js +157 -0
- package/dist/node/static.js.map +1 -0
- package/dist/node/workbench.d.ts +43 -0
- package/dist/node/workbench.d.ts.map +1 -0
- package/dist/node/workbench.js +204 -0
- package/dist/node/workbench.js.map +1 -0
- package/dist/pages/build.d.ts +22 -0
- package/dist/pages/build.d.ts.map +1 -0
- package/dist/pages/build.js +363 -0
- package/dist/pages/build.js.map +1 -0
- package/dist/pages/defaults.d.ts +16 -0
- package/dist/pages/defaults.d.ts.map +1 -0
- package/dist/pages/defaults.js +88 -0
- package/dist/pages/defaults.js.map +1 -0
- package/dist/pages/index.d.ts +14 -0
- package/dist/pages/index.d.ts.map +1 -0
- package/dist/pages/index.js +10 -0
- package/dist/pages/index.js.map +1 -0
- package/dist/pages/navigation.d.ts +48 -0
- package/dist/pages/navigation.d.ts.map +1 -0
- package/dist/pages/navigation.js +83 -0
- package/dist/pages/navigation.js.map +1 -0
- package/dist/pages/types.d.ts +148 -0
- package/dist/pages/types.d.ts.map +1 -0
- package/dist/pages/types.js +3 -0
- package/dist/pages/types.js.map +1 -0
- package/dist/panels/catalog-define.d.ts +3 -0
- package/dist/panels/catalog-define.d.ts.map +1 -0
- package/dist/panels/catalog-define.js +7 -0
- package/dist/panels/catalog-define.js.map +1 -0
- package/dist/panels/catalog-layout-styles.d.ts +2 -0
- package/dist/panels/catalog-layout-styles.d.ts.map +1 -0
- package/dist/panels/catalog-layout-styles.js +54 -0
- package/dist/panels/catalog-layout-styles.js.map +1 -0
- package/dist/panels/catalog-styles.d.ts +2 -0
- package/dist/panels/catalog-styles.d.ts.map +1 -0
- package/dist/panels/catalog-styles.js +106 -0
- package/dist/panels/catalog-styles.js.map +1 -0
- package/dist/panels/catalog.d.ts +37 -0
- package/dist/panels/catalog.d.ts.map +1 -0
- package/dist/panels/catalog.js +74 -0
- package/dist/panels/catalog.js.map +1 -0
- package/dist/panels/component-define.d.ts +3 -0
- package/dist/panels/component-define.d.ts.map +1 -0
- package/dist/panels/component-define.js +6 -0
- package/dist/panels/component-define.js.map +1 -0
- package/dist/panels/component-detail.d.ts +49 -0
- package/dist/panels/component-detail.d.ts.map +1 -0
- package/dist/panels/component-detail.js +1352 -0
- package/dist/panels/component-detail.js.map +1 -0
- package/dist/panels/component.d.ts +17 -0
- package/dist/panels/component.d.ts.map +1 -0
- package/dist/panels/component.js +10 -0
- package/dist/panels/component.js.map +1 -0
- package/dist/panels/example-styles.d.ts +2 -0
- package/dist/panels/example-styles.d.ts.map +1 -0
- package/dist/panels/example-styles.js +343 -0
- package/dist/panels/example-styles.js.map +1 -0
- package/dist/panels/foundation-define.d.ts +3 -0
- package/dist/panels/foundation-define.d.ts.map +1 -0
- package/dist/panels/foundation-define.js +6 -0
- package/dist/panels/foundation-define.js.map +1 -0
- package/dist/panels/foundation-detail.d.ts +23 -0
- package/dist/panels/foundation-detail.d.ts.map +1 -0
- package/dist/panels/foundation-detail.js +216 -0
- package/dist/panels/foundation-detail.js.map +1 -0
- package/dist/panels/foundation.d.ts +15 -0
- package/dist/panels/foundation.d.ts.map +1 -0
- package/dist/panels/foundation.js +9 -0
- package/dist/panels/foundation.js.map +1 -0
- package/dist/panels/model.d.ts +184 -0
- package/dist/panels/model.d.ts.map +1 -0
- package/dist/panels/model.js +488 -0
- package/dist/panels/model.js.map +1 -0
- package/dist/panels/styles.d.ts +3 -0
- package/dist/panels/styles.d.ts.map +1 -0
- package/dist/panels/styles.js +265 -0
- package/dist/panels/styles.js.map +1 -0
- package/dist/panels/theme-model.d.ts +69 -0
- package/dist/panels/theme-model.d.ts.map +1 -0
- package/dist/panels/theme-model.js +166 -0
- package/dist/panels/theme-model.js.map +1 -0
- package/dist/panels/theme-studio.d.ts +32 -0
- package/dist/panels/theme-studio.d.ts.map +1 -0
- package/dist/panels/theme-studio.js +375 -0
- package/dist/panels/theme-studio.js.map +1 -0
- package/dist/preview/frame.d.ts +44 -0
- package/dist/preview/frame.d.ts.map +1 -0
- package/dist/preview/frame.js +260 -0
- package/dist/preview/frame.js.map +1 -0
- package/dist/preview/index.d.ts +26 -0
- package/dist/preview/index.d.ts.map +1 -0
- package/dist/preview/index.js +58 -0
- package/dist/preview/index.js.map +1 -0
- package/dist/preview/theme-generation.d.ts +33 -0
- package/dist/preview/theme-generation.d.ts.map +1 -0
- package/dist/preview/theme-generation.js +48 -0
- package/dist/preview/theme-generation.js.map +1 -0
- package/dist/protocol/index.d.ts +222 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +272 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/testing/index.d.ts +47 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +145 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +118 -4
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conformance suite for the `odd-button` foundation contract. Implementation-agnostic: it
|
|
3
|
+
* reaches the element only through its tag, public properties, native events, and the
|
|
4
|
+
* documented `control` anatomy role (a native, focusable `<button>`).
|
|
5
|
+
*/
|
|
6
|
+
import { defineConformance } from './index.js';
|
|
7
|
+
const control = (ctx, host) => {
|
|
8
|
+
const part = ctx.adapter.part(host, 'control');
|
|
9
|
+
ctx.expect(part !== null, 'the implementation exposes its control').toBe(true);
|
|
10
|
+
return part;
|
|
11
|
+
};
|
|
12
|
+
const countClicks = (host) => {
|
|
13
|
+
const counter = { count: 0 };
|
|
14
|
+
host.addEventListener('click', () => counter.count++);
|
|
15
|
+
return counter;
|
|
16
|
+
};
|
|
17
|
+
export const buttonConformance = defineConformance({
|
|
18
|
+
id: 'oddkin.button',
|
|
19
|
+
version: '0.1.0',
|
|
20
|
+
contract: { component: 'component:odd-button', versions: '0.x' },
|
|
21
|
+
description: 'Interaction contract shared by odd-button and its product implementations.',
|
|
22
|
+
requires: {
|
|
23
|
+
properties: [
|
|
24
|
+
'appearance',
|
|
25
|
+
'size',
|
|
26
|
+
'type',
|
|
27
|
+
'disabled',
|
|
28
|
+
'loading',
|
|
29
|
+
'fullWidth',
|
|
30
|
+
'name',
|
|
31
|
+
'value',
|
|
32
|
+
'label',
|
|
33
|
+
],
|
|
34
|
+
events: ['click'],
|
|
35
|
+
slots: ['', 'start', 'end'],
|
|
36
|
+
anatomy: ['control'],
|
|
37
|
+
},
|
|
38
|
+
cases: [
|
|
39
|
+
{
|
|
40
|
+
id: 'properties-attributes',
|
|
41
|
+
title: 'Attributes convert to properties; boolean and enum state reflects',
|
|
42
|
+
kind: 'assertion',
|
|
43
|
+
async run(ctx) {
|
|
44
|
+
const host = (await ctx.mount({
|
|
45
|
+
attributes: { appearance: 'primary', 'full-width': '' },
|
|
46
|
+
content: 'Go',
|
|
47
|
+
}));
|
|
48
|
+
ctx.expect(host['appearance']).toBe('primary');
|
|
49
|
+
ctx.expect(host['fullWidth']).toBe(true);
|
|
50
|
+
host['disabled'] = true;
|
|
51
|
+
host['size'] = 'lg';
|
|
52
|
+
await ctx.adapter.settle(host);
|
|
53
|
+
ctx.expect(host.hasAttribute('disabled')).toBe(true);
|
|
54
|
+
ctx.expect(host.getAttribute('size')).toBe('lg');
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'native-control',
|
|
59
|
+
title: 'The control is a native button and the default slot names it',
|
|
60
|
+
kind: 'assertion',
|
|
61
|
+
async run(ctx) {
|
|
62
|
+
const host = await ctx.mount({ content: 'Save' });
|
|
63
|
+
const part = control(ctx, host);
|
|
64
|
+
ctx.expect(part.localName).toBe('button');
|
|
65
|
+
ctx.expect(part.type).toBe('button');
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'keyboard-activation',
|
|
70
|
+
title: 'Click, Enter, and Space each dispatch one click at the host',
|
|
71
|
+
kind: 'assertion',
|
|
72
|
+
async run(ctx) {
|
|
73
|
+
const host = await ctx.mount({ content: 'Save' });
|
|
74
|
+
const clicks = countClicks(host);
|
|
75
|
+
await ctx.user.click(host);
|
|
76
|
+
host.focus();
|
|
77
|
+
await ctx.user.keyboard('{Enter}');
|
|
78
|
+
await ctx.user.keyboard(' ');
|
|
79
|
+
ctx.expect(clicks.count).toBe(3);
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: 'focus',
|
|
84
|
+
title: 'Focusing the host focuses the control',
|
|
85
|
+
kind: 'assertion',
|
|
86
|
+
async run(ctx) {
|
|
87
|
+
const host = await ctx.mount({ content: 'Save' });
|
|
88
|
+
host.focus();
|
|
89
|
+
const active = host.shadowRoot?.activeElement ?? document.activeElement;
|
|
90
|
+
ctx.expect(active).toBe(control(ctx, host));
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'disabled',
|
|
95
|
+
title: 'Disabled ignores activation and is not focusable',
|
|
96
|
+
kind: 'assertion',
|
|
97
|
+
async run(ctx) {
|
|
98
|
+
const host = await ctx.mount({ attributes: { disabled: '' }, content: 'Save' });
|
|
99
|
+
const clicks = countClicks(host);
|
|
100
|
+
host.click();
|
|
101
|
+
control(ctx, host).click();
|
|
102
|
+
host.focus();
|
|
103
|
+
ctx.expect(clicks.count).toBe(0);
|
|
104
|
+
ctx.expect(host.shadowRoot?.activeElement ?? null).toBe(null);
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: 'loading',
|
|
109
|
+
title: 'Loading ignores activation but stays focusable and exposes aria-disabled',
|
|
110
|
+
kind: 'assertion',
|
|
111
|
+
async run(ctx) {
|
|
112
|
+
const host = await ctx.mount({ attributes: { loading: '' }, content: 'Save' });
|
|
113
|
+
const clicks = countClicks(host);
|
|
114
|
+
host.focus();
|
|
115
|
+
await ctx.user.keyboard('{Enter}');
|
|
116
|
+
host.click();
|
|
117
|
+
ctx.expect(clicks.count).toBe(0);
|
|
118
|
+
ctx.expect(host.shadowRoot?.activeElement).toBe(control(ctx, host));
|
|
119
|
+
ctx.expect(control(ctx, host).getAttribute('aria-disabled')).toBe('true');
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: 'form-submission',
|
|
124
|
+
title: 'type="submit" submits its form once, including name and value',
|
|
125
|
+
kind: 'assertion',
|
|
126
|
+
async run(ctx) {
|
|
127
|
+
const host = await ctx.mount({
|
|
128
|
+
attributes: { type: 'submit', name: 'intent', value: 'save' },
|
|
129
|
+
content: 'Save',
|
|
130
|
+
within: '<form><input name="q" value="a">{{element}}</form>',
|
|
131
|
+
});
|
|
132
|
+
const form = host.closest('form');
|
|
133
|
+
const submitted = [];
|
|
134
|
+
form.addEventListener('submit', (event) => {
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
submitted.push([...new FormData(form, event.submitter)]);
|
|
137
|
+
});
|
|
138
|
+
await ctx.user.click(host);
|
|
139
|
+
await ctx.nextTask();
|
|
140
|
+
ctx.expect(submitted).toEqual([
|
|
141
|
+
[
|
|
142
|
+
['q', 'a'],
|
|
143
|
+
['intent', 'save'],
|
|
144
|
+
],
|
|
145
|
+
]);
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: 'cancelled-click',
|
|
150
|
+
title: 'A cancelled click does not submit',
|
|
151
|
+
kind: 'assertion',
|
|
152
|
+
async run(ctx) {
|
|
153
|
+
const host = await ctx.mount({
|
|
154
|
+
attributes: { type: 'submit' },
|
|
155
|
+
content: 'Save',
|
|
156
|
+
within: '<form>{{element}}</form>',
|
|
157
|
+
});
|
|
158
|
+
let submits = 0;
|
|
159
|
+
host.closest('form').addEventListener('submit', (event) => {
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
submits++;
|
|
162
|
+
});
|
|
163
|
+
host.addEventListener('click', (event) => event.preventDefault());
|
|
164
|
+
await ctx.user.click(host);
|
|
165
|
+
await ctx.nextTask();
|
|
166
|
+
ctx.expect(submits).toBe(0);
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: 'reconnect',
|
|
171
|
+
title: 'Reconnecting neither leaks owned work nor duplicates activation',
|
|
172
|
+
kind: 'invariant',
|
|
173
|
+
change: 'reconnect',
|
|
174
|
+
async run(ctx) {
|
|
175
|
+
const host = await ctx.mount({
|
|
176
|
+
attributes: { type: 'submit' },
|
|
177
|
+
content: 'Save',
|
|
178
|
+
within: '<form>{{element}}</form>',
|
|
179
|
+
});
|
|
180
|
+
const form = host.closest('form');
|
|
181
|
+
const parent = host.parentNode;
|
|
182
|
+
const before = ctx.ownedWork();
|
|
183
|
+
for (let i = 0; i < 5; i++) {
|
|
184
|
+
host.remove();
|
|
185
|
+
parent.append(host);
|
|
186
|
+
await ctx.adapter.settle(host);
|
|
187
|
+
}
|
|
188
|
+
ctx.expect(ctx.ownedWork()).toEqual(before);
|
|
189
|
+
let submits = 0;
|
|
190
|
+
form.addEventListener('submit', (event) => {
|
|
191
|
+
event.preventDefault();
|
|
192
|
+
submits++;
|
|
193
|
+
});
|
|
194
|
+
await ctx.user.click(host);
|
|
195
|
+
await ctx.nextTask();
|
|
196
|
+
ctx.expect(submits).toBe(1);
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
id: 'programmatic-updates',
|
|
201
|
+
title: 'Programmatic property changes dispatch no user-intent events',
|
|
202
|
+
kind: 'invariant',
|
|
203
|
+
change: 'programmatic',
|
|
204
|
+
async run(ctx) {
|
|
205
|
+
const host = (await ctx.mount({ content: 'Save' }));
|
|
206
|
+
const events = [];
|
|
207
|
+
for (const type of ['click', 'input', 'change'])
|
|
208
|
+
host.addEventListener(type, () => events.push(type));
|
|
209
|
+
host['appearance'] = 'ghost';
|
|
210
|
+
host['value'] = 'x';
|
|
211
|
+
host['loading'] = true;
|
|
212
|
+
host['disabled'] = true;
|
|
213
|
+
await ctx.adapter.settle(host);
|
|
214
|
+
ctx.expect(events).toEqual([]);
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
id: 'theme-value',
|
|
219
|
+
title: 'A theme-value change keeps the control node and applies',
|
|
220
|
+
kind: 'invariant',
|
|
221
|
+
change: 'theme-value',
|
|
222
|
+
async run(ctx) {
|
|
223
|
+
const host = await ctx.mount({ content: 'Save' });
|
|
224
|
+
const before = control(ctx, host);
|
|
225
|
+
host.parentElement.style.setProperty('--odd-button-radius', '0px');
|
|
226
|
+
await ctx.adapter.settle(host);
|
|
227
|
+
ctx.expect(control(ctx, host)).toBe(before);
|
|
228
|
+
ctx.expect(getComputedStyle(before).borderTopLeftRadius).toBe('0px');
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
],
|
|
232
|
+
});
|
|
233
|
+
//# sourceMappingURL=button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/conformance/button.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@oddkin/workbench/conformance` — portable conformance suites (conformance.v1). DOM-free at
|
|
3
|
+
* import: suites are data plus case functions that touch the DOM only when a runner calls them.
|
|
4
|
+
* Contract: docs/architecture/change-impact-and-verification.md §3; ADR 0034.
|
|
5
|
+
*/
|
|
6
|
+
import { type WorkbenchDiagnostic } from '../internal/diagnostics.js';
|
|
7
|
+
/** Declared changes an invariant is about. Identity invariants apply only to value changes. */
|
|
8
|
+
export type ChangeKind = 'theme-value' | 'density' | 'programmatic' | 'keyed-reorder' | 'reconnect' | 'invalid-draft';
|
|
9
|
+
/** The subset of a test runner's `expect` that suites use (Vitest and Jest compatible). */
|
|
10
|
+
export interface Matchers {
|
|
11
|
+
toBe(expected: unknown): void;
|
|
12
|
+
toEqual(expected: unknown): void;
|
|
13
|
+
toBeGreaterThan(expected: number): void;
|
|
14
|
+
toContain(expected: unknown): void;
|
|
15
|
+
}
|
|
16
|
+
export type Expect = (actual: unknown, message?: string) => Matchers;
|
|
17
|
+
/** Real user input from the project's browser runner (e.g. Vitest's `userEvent`). */
|
|
18
|
+
export interface UserInput {
|
|
19
|
+
click(element: Element): Promise<unknown>;
|
|
20
|
+
keyboard(text: string): Promise<unknown>;
|
|
21
|
+
}
|
|
22
|
+
/** Locates documented anatomy roles in an implementation. */
|
|
23
|
+
export interface Adapter {
|
|
24
|
+
/** The element that plays `role` (e.g. `control`), or null if absent. */
|
|
25
|
+
part(host: HTMLElement, role: string): HTMLElement | null;
|
|
26
|
+
/** Resolve once pending updates are committed. */
|
|
27
|
+
settle(host: HTMLElement): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export interface MountOptions {
|
|
30
|
+
readonly attributes?: Readonly<Record<string, string>>;
|
|
31
|
+
readonly content?: string;
|
|
32
|
+
/** Markup to place the element in; `{{element}}` marks its position, e.g. inside a form. */
|
|
33
|
+
readonly within?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ConformanceContext {
|
|
36
|
+
/** Tag name of the implementation under test. */
|
|
37
|
+
readonly tag: string;
|
|
38
|
+
readonly expect: Expect;
|
|
39
|
+
readonly user: UserInput;
|
|
40
|
+
readonly adapter: Adapter;
|
|
41
|
+
/** Mount the implementation in a fresh container owned by this case. */
|
|
42
|
+
mount(options?: MountOptions): Promise<HTMLElement>;
|
|
43
|
+
/** Live counts of owned work (`scopeStats()` from `@oddkin/core/scope`). */
|
|
44
|
+
ownedWork(): Readonly<Record<string, number>>;
|
|
45
|
+
/** Resolve after the current task, letting deferred default actions run. */
|
|
46
|
+
nextTask(): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
export interface ConformanceCase {
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly title: string;
|
|
51
|
+
readonly kind: 'assertion' | 'invariant';
|
|
52
|
+
/** For invariants: the declared change that must preserve the asserted relationship. */
|
|
53
|
+
readonly change?: ChangeKind;
|
|
54
|
+
readonly run: (context: ConformanceContext) => Promise<void> | void;
|
|
55
|
+
}
|
|
56
|
+
export interface ConformanceSuite {
|
|
57
|
+
/** Stable suite id, e.g. `oddkin.button`. */
|
|
58
|
+
readonly id: string;
|
|
59
|
+
/** Suite version (semver), tied to the contract version range below. */
|
|
60
|
+
readonly version: string;
|
|
61
|
+
/** The foundation contract verified: a component id and the versions it targets. */
|
|
62
|
+
readonly contract: {
|
|
63
|
+
readonly component: string;
|
|
64
|
+
readonly versions: string;
|
|
65
|
+
};
|
|
66
|
+
readonly description?: string;
|
|
67
|
+
/** Public capabilities an implementation must provide. */
|
|
68
|
+
readonly requires: {
|
|
69
|
+
readonly properties?: readonly string[];
|
|
70
|
+
readonly events?: readonly string[];
|
|
71
|
+
readonly slots?: readonly string[];
|
|
72
|
+
readonly anatomy?: readonly string[];
|
|
73
|
+
};
|
|
74
|
+
readonly cases: readonly ConformanceCase[];
|
|
75
|
+
}
|
|
76
|
+
/** Freeze a suite. Use `checkConformance` (or a test) to validate it. */
|
|
77
|
+
export declare function defineConformance(suite: ConformanceSuite): ConformanceSuite;
|
|
78
|
+
/** Structural problems in a suite, as diagnostics with JSON-pointer paths. */
|
|
79
|
+
export declare function checkConformance(suite: ConformanceSuite): WorkbenchDiagnostic[];
|
|
80
|
+
/** The serializable `conformance.v1` description of a suite (no functions). */
|
|
81
|
+
export declare function toConformanceJSON(suite: ConformanceSuite): Record<string, unknown>;
|
|
82
|
+
/** One case outcome. Untested cases are `not-executed`, never `passed`. */
|
|
83
|
+
export interface CaseResult {
|
|
84
|
+
readonly case: string;
|
|
85
|
+
readonly state: 'passed' | 'failed' | 'not-executed';
|
|
86
|
+
readonly message?: string;
|
|
87
|
+
}
|
|
88
|
+
/** A `conformance-result.v1` record: evidence for one implementation, configuration, and browser. */
|
|
89
|
+
export interface ConformanceResult {
|
|
90
|
+
readonly schema: 'https://oddkin.dev/schemas/conformance-result/v1.json';
|
|
91
|
+
readonly suite: {
|
|
92
|
+
readonly id: string;
|
|
93
|
+
readonly version: string;
|
|
94
|
+
};
|
|
95
|
+
readonly implementation: {
|
|
96
|
+
readonly tag: string;
|
|
97
|
+
readonly package?: string;
|
|
98
|
+
readonly definition?: string;
|
|
99
|
+
};
|
|
100
|
+
readonly configuration: Readonly<Record<string, string>>;
|
|
101
|
+
readonly environment: {
|
|
102
|
+
readonly userAgent: string;
|
|
103
|
+
};
|
|
104
|
+
readonly date: string;
|
|
105
|
+
readonly results: readonly CaseResult[];
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conformance/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@oddkin/workbench/conformance` — portable conformance suites (conformance.v1). DOM-free at
|
|
3
|
+
* import: suites are data plus case functions that touch the DOM only when a runner calls them.
|
|
4
|
+
* Contract: docs/architecture/change-impact-and-verification.md §3; ADR 0034.
|
|
5
|
+
*/
|
|
6
|
+
import { DiagnosticList } from '../internal/diagnostics.js';
|
|
7
|
+
const CHANGES = [
|
|
8
|
+
'theme-value',
|
|
9
|
+
'density',
|
|
10
|
+
'programmatic',
|
|
11
|
+
'keyed-reorder',
|
|
12
|
+
'reconnect',
|
|
13
|
+
'invalid-draft',
|
|
14
|
+
];
|
|
15
|
+
/** Freeze a suite. Use `checkConformance` (or a test) to validate it. */
|
|
16
|
+
export function defineConformance(suite) {
|
|
17
|
+
return Object.freeze({ ...suite, cases: Object.freeze([...suite.cases]) });
|
|
18
|
+
}
|
|
19
|
+
/** Structural problems in a suite, as diagnostics with JSON-pointer paths. */
|
|
20
|
+
export function checkConformance(suite) {
|
|
21
|
+
const out = new DiagnosticList();
|
|
22
|
+
if (!/^[a-z][\w.-]*$/.test(suite.id))
|
|
23
|
+
out.error('conformance.id.invalid', `Suite id "${suite.id}" must be a lowercase id.`, '/id');
|
|
24
|
+
if (!/^\d+\.\d+\.\d+/.test(suite.version))
|
|
25
|
+
out.error('conformance.version.invalid', 'Suite version must be semver.', '/version');
|
|
26
|
+
if (!/^component:[a-z][\w.]*-[\w.-]*$/.test(suite.contract.component))
|
|
27
|
+
out.error('conformance.contract.invalid', 'Use a component id such as "component:odd-button".', '/contract/component');
|
|
28
|
+
if (!suite.cases.length)
|
|
29
|
+
out.error('conformance.cases.empty', 'A suite needs cases.', '/cases');
|
|
30
|
+
const seen = new Set();
|
|
31
|
+
suite.cases.forEach((c, index) => {
|
|
32
|
+
const path = `/cases/${index}`;
|
|
33
|
+
if (seen.has(c.id))
|
|
34
|
+
out.error('conformance.case.duplicate', `Case "${c.id}" repeats.`, path);
|
|
35
|
+
seen.add(c.id);
|
|
36
|
+
if (c.kind === 'invariant' && !(c.change && CHANGES.includes(c.change)))
|
|
37
|
+
out.error('conformance.invariant.change', `Invariant "${c.id}" must name a change.`, path);
|
|
38
|
+
if (c.kind === 'assertion' && c.change)
|
|
39
|
+
out.error('conformance.assertion.change', `Assertion "${c.id}" names a change.`, path);
|
|
40
|
+
});
|
|
41
|
+
return out.items;
|
|
42
|
+
}
|
|
43
|
+
/** The serializable `conformance.v1` description of a suite (no functions). */
|
|
44
|
+
export function toConformanceJSON(suite) {
|
|
45
|
+
return {
|
|
46
|
+
schema: 'https://oddkin.dev/schemas/conformance/v1.json',
|
|
47
|
+
id: suite.id,
|
|
48
|
+
version: suite.version,
|
|
49
|
+
contract: { ...suite.contract },
|
|
50
|
+
...(suite.description ? { description: suite.description } : {}),
|
|
51
|
+
requires: { ...suite.requires },
|
|
52
|
+
cases: suite.cases.map((c) => ({
|
|
53
|
+
id: c.id,
|
|
54
|
+
title: c.title,
|
|
55
|
+
kind: c.kind,
|
|
56
|
+
...(c.change ? { change: c.change } : {}),
|
|
57
|
+
})),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/conformance/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAA4B,MAAM,4BAA4B,CAAC;AA6EtF,MAAM,OAAO,GAA0B;IACrC,aAAa;IACb,SAAS;IACT,cAAc;IACd,eAAe;IACf,WAAW;IACX,eAAe;CAChB,CAAC;AAEF,yEAAyE;AACzE,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,KAAuB;IACtD,MAAM,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;IACjC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,GAAG,CAAC,KAAK,CAAC,wBAAwB,EAAE,aAAa,KAAK,CAAC,EAAE,2BAA2B,EAAE,KAAK,CAAC,CAAC;IAC/F,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QACvC,GAAG,CAAC,KAAK,CAAC,6BAA6B,EAAE,+BAA+B,EAAE,UAAU,CAAC,CAAC;IACxF,IAAI,CAAC,iCAAiC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;QACnE,GAAG,CAAC,KAAK,CACP,8BAA8B,EAC9B,oDAAoD,EACpD,qBAAqB,CACtB,CAAC;IACJ,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM;QAAE,GAAG,CAAC,KAAK,CAAC,yBAAyB,EAAE,sBAAsB,EAAE,QAAQ,CAAC,CAAC;IAChG,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,UAAU,KAAK,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,GAAG,CAAC,KAAK,CAAC,4BAA4B,EAAE,SAAS,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;QAC7F,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACrE,GAAG,CAAC,KAAK,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC,EAAE,uBAAuB,EAAE,IAAI,CAAC,CAAC;QAC7F,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM;YACpC,GAAG,CAAC,KAAK,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC,EAAE,mBAAmB,EAAE,IAAI,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC,KAAK,CAAC;AACnB,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,OAAO;QACL,MAAM,EAAE,gDAAgD;QACxD,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE;QAC/B,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE;QAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the Workbench data files from analyzer outputs, configuration, authored content, and the
|
|
3
|
+
* token inspection the foundations reference (workbench.md §2.1). Pure and deterministic: the same
|
|
4
|
+
* inputs give the same files, and no build time enters them.
|
|
5
|
+
*/
|
|
6
|
+
import { type DocsContent, type ResolvedWorkbenchConfig, type WorkbenchConfig } from '../config/index.js';
|
|
7
|
+
import { type WorkbenchDiagnostic } from '../internal/diagnostics.js';
|
|
8
|
+
import { type ThemeStudioInput } from './theme-studio.js';
|
|
9
|
+
import { type LibraryInput, type PageData, type TokenInspectionLike, type WorkbenchData, type WorkbenchIndex } from './types.js';
|
|
10
|
+
export type { ThemeStudioInput } from './theme-studio.js';
|
|
11
|
+
export interface WorkbenchDataInput {
|
|
12
|
+
readonly config: WorkbenchConfig | ResolvedWorkbenchConfig;
|
|
13
|
+
/** The documented packages, in configuration order. */
|
|
14
|
+
readonly libraries: readonly LibraryInput[];
|
|
15
|
+
/** Authored content (`oddkin.docs.ts`). */
|
|
16
|
+
readonly docs?: DocsContent;
|
|
17
|
+
/** The token inspection the foundations reference (their `generation` source). */
|
|
18
|
+
readonly tokens?: TokenInspectionLike;
|
|
19
|
+
/** Theme Studio's baseline configuration and generator, loaded by dev tooling. */
|
|
20
|
+
readonly theme?: ThemeStudioInput;
|
|
21
|
+
/** Diagnostics from reading these inputs; reported first, with the data's own. */
|
|
22
|
+
readonly diagnostics?: readonly WorkbenchDiagnostic[];
|
|
23
|
+
}
|
|
24
|
+
/** The data file of a page, relative to the index: `pages/components/odd-button.json`. */
|
|
25
|
+
export declare function pageFile(id: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Build the index and the visible pages' data. `data` is undefined only when the configuration
|
|
28
|
+
* is invalid; every other problem is a diagnostic and leaves the affected value unknown.
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildWorkbenchData(input: WorkbenchDataInput): {
|
|
31
|
+
data: WorkbenchData | undefined;
|
|
32
|
+
diagnostics: WorkbenchDiagnostic[];
|
|
33
|
+
};
|
|
34
|
+
/** Serialize a data file: two-space JSON with a final newline, so output is byte-stable. */
|
|
35
|
+
export declare function serializeData(value: WorkbenchIndex | PageData): string;
|
|
36
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/data/build.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAA4B,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAIhG,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE3E,OAAO,EAQL,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,uBAAuB,CAAC;IAC3D,uDAAuD;IACvD,QAAQ,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC;IAC5B,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IACtC,kFAAkF;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAClC,kFAAkF;IAClF,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACvD;AAKD,0FAA0F;AAC1F,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE3C;AAkLD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,kBAAkB,GAAG;IAC7D,IAAI,EAAE,aAAa,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,mBAAmB,EAAE,CAAC;CACpC,CA2FA;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,QAAQ,GAAG,MAAM,CAEtE"}
|