@jay-framework/design-system-validator 0.22.2 → 0.24.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.
@@ -0,0 +1,415 @@
1
+ <html>
2
+ <head>
3
+ <script type="application/jay-data">
4
+ data:
5
+ statusMessage: string
6
+ statusTone: string
7
+ showStatusMessage: boolean
8
+ catalogLoading: boolean
9
+ showNoCatalog: boolean
10
+ addMenuListRows:
11
+ - rowKey: string
12
+ itemId: string
13
+ title: string
14
+ subCategory: string
15
+ rowClass: string
16
+ showAddMenuEditor: boolean
17
+ editorTitle: string
18
+ editorSubCategory: string
19
+ editorTokenValue: string
20
+ editorFontSize: string
21
+ editorFontWeight: string
22
+ editorFontFamily: string
23
+ showTypographyFields: boolean
24
+ showTokenValueField: boolean
25
+ editorReadOnly: boolean
26
+ editorReadOnlyReason: string
27
+ unsavedChangeCount: number
28
+ saveButtonLabel: string
29
+ saveDisabled: boolean
30
+ discardDisabled: boolean
31
+ showAnalysisSection: boolean
32
+ showReport: boolean
33
+ reportSummary: string
34
+ reportBody: string
35
+ </script>
36
+ <style>
37
+ .ds-settings {
38
+ display: flex;
39
+ flex-direction: column;
40
+ height: 100vh;
41
+ max-height: 100vh;
42
+ margin: 0;
43
+ padding: 16px 20px;
44
+ box-sizing: border-box;
45
+ font-family: system-ui, sans-serif;
46
+ color: #162d3d;
47
+ background: #fff;
48
+ }
49
+ .ds-settings h1 {
50
+ margin: 0;
51
+ font-size: 18px;
52
+ font-weight: 600;
53
+ }
54
+ .ds-settings h2 {
55
+ margin: 0 0 8px;
56
+ font-size: 14px;
57
+ font-weight: 600;
58
+ }
59
+ .ds-settings .header {
60
+ flex-shrink: 0;
61
+ }
62
+ .ds-settings .header p {
63
+ margin: 4px 0 0;
64
+ font-size: 12px;
65
+ color: #5a6f82;
66
+ line-height: 1.45;
67
+ }
68
+ .ds-settings code {
69
+ font-size: 11px;
70
+ background: #f4f7f9;
71
+ padding: 1px 4px;
72
+ border-radius: 4px;
73
+ }
74
+ .ds-settings .toolbar {
75
+ display: flex;
76
+ gap: 8px;
77
+ flex-wrap: wrap;
78
+ margin-top: 12px;
79
+ align-items: center;
80
+ }
81
+ .ds-settings button {
82
+ padding: 7px 12px;
83
+ border: 1px solid #c5d0d8;
84
+ border-radius: 6px;
85
+ background: #fff;
86
+ font-size: 13px;
87
+ cursor: pointer;
88
+ }
89
+ .ds-settings button:disabled {
90
+ opacity: 0.45;
91
+ cursor: not-allowed;
92
+ }
93
+ .ds-settings button.primary {
94
+ background: #116dff;
95
+ border-color: #116dff;
96
+ color: #fff;
97
+ }
98
+ .ds-settings .operation-status {
99
+ flex-shrink: 0;
100
+ margin-top: 10px;
101
+ padding: 10px 12px;
102
+ border-radius: 8px;
103
+ border: 1px solid #d8e0e6;
104
+ font-size: 13px;
105
+ white-space: pre-wrap;
106
+ }
107
+ .ds-settings .operation-status.success {
108
+ background: #edf8f0;
109
+ border-color: #b9dfc4;
110
+ }
111
+ .ds-settings .operation-status.warning {
112
+ background: #fff8e8;
113
+ border-color: #efd9a2;
114
+ }
115
+ .ds-settings .operation-status.error {
116
+ background: #fff1f0;
117
+ border-color: #f5b5b0;
118
+ }
119
+ .ds-settings .operation-status.info {
120
+ background: #f4f7f9;
121
+ border-color: #d8e0e6;
122
+ }
123
+ .ds-settings .workspace {
124
+ flex: 1;
125
+ min-height: 0;
126
+ display: grid;
127
+ grid-template-columns: minmax(220px, 280px) minmax(0, 1fr);
128
+ gap: 16px;
129
+ margin-top: 14px;
130
+ }
131
+ .ds-settings .catalog-panel,
132
+ .ds-settings .editor-panel {
133
+ min-height: 0;
134
+ display: flex;
135
+ flex-direction: column;
136
+ border: 1px solid #d8e0e6;
137
+ border-radius: 10px;
138
+ background: #fafbfc;
139
+ }
140
+ .ds-settings .panel-head {
141
+ flex-shrink: 0;
142
+ padding: 10px 12px;
143
+ border-bottom: 1px solid #e8edf1;
144
+ font-size: 13px;
145
+ font-weight: 600;
146
+ color: #3d4f5f;
147
+ }
148
+ .ds-settings .catalog-list {
149
+ flex: 1;
150
+ min-height: 0;
151
+ overflow: auto;
152
+ padding: 6px;
153
+ }
154
+ .ds-settings .catalog-item {
155
+ display: block;
156
+ width: 100%;
157
+ text-align: left;
158
+ padding: 8px 10px;
159
+ margin: 0 0 4px;
160
+ border: 1px solid transparent;
161
+ border-radius: 8px;
162
+ background: transparent;
163
+ cursor: pointer;
164
+ }
165
+ .ds-settings .catalog-item:hover {
166
+ background: #eef3f8;
167
+ }
168
+ .ds-settings .catalog-item--selected {
169
+ background: #e8f1ff;
170
+ border-color: #b8d4ff;
171
+ }
172
+ .ds-settings .catalog-item-title {
173
+ display: block;
174
+ font-size: 13px;
175
+ font-weight: 500;
176
+ color: #162d3d;
177
+ }
178
+ .ds-settings .catalog-item-meta {
179
+ display: block;
180
+ margin-top: 2px;
181
+ font-size: 11px;
182
+ color: #6b7f92;
183
+ }
184
+ .ds-settings .editor-body {
185
+ flex: 1;
186
+ min-height: 0;
187
+ overflow: auto;
188
+ padding: 12px;
189
+ display: flex;
190
+ flex-direction: column;
191
+ gap: 12px;
192
+ }
193
+ .ds-settings .field {
194
+ display: flex;
195
+ flex-direction: column;
196
+ gap: 4px;
197
+ }
198
+ .ds-settings .field label {
199
+ font-size: 12px;
200
+ font-weight: 500;
201
+ color: #3d4f5f;
202
+ }
203
+ .ds-settings .field input {
204
+ padding: 7px 9px;
205
+ border: 1px solid #c5d0d8;
206
+ border-radius: 6px;
207
+ font-size: 13px;
208
+ font-family: inherit;
209
+ }
210
+ .ds-settings .field input:disabled {
211
+ background: #f0f3f6;
212
+ color: #6b7f92;
213
+ }
214
+ .ds-settings .read-only-note {
215
+ padding: 8px 10px;
216
+ border-radius: 6px;
217
+ background: #fff8e8;
218
+ border: 1px solid #efd9a2;
219
+ font-size: 12px;
220
+ color: #6b5a2e;
221
+ line-height: 1.45;
222
+ }
223
+ .ds-settings .preview-panel {
224
+ flex-shrink: 0;
225
+ border-top: 1px solid #e8edf1;
226
+ padding: 12px;
227
+ background: #fff;
228
+ }
229
+ .ds-settings .preview-label {
230
+ font-size: 12px;
231
+ font-weight: 600;
232
+ color: #3d4f5f;
233
+ margin-bottom: 8px;
234
+ }
235
+ .ds-settings .preview-host {
236
+ min-height: 72px;
237
+ padding: 12px;
238
+ border: 1px dashed #c5d0d8;
239
+ border-radius: 8px;
240
+ background: #f8fafc;
241
+ }
242
+ .ds-settings .empty-card {
243
+ padding: 16px;
244
+ font-size: 13px;
245
+ color: #5a6f82;
246
+ line-height: 1.5;
247
+ }
248
+ .ds-settings .analysis-section {
249
+ flex-shrink: 0;
250
+ margin-top: 12px;
251
+ padding-top: 12px;
252
+ border-top: 1px solid #e8edf1;
253
+ }
254
+ .ds-settings .report-panel {
255
+ margin-top: 10px;
256
+ padding: 10px 12px;
257
+ border: 1px solid #d8e0e6;
258
+ border-radius: 8px;
259
+ background: #fafbfc;
260
+ font-size: 11px;
261
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
262
+ white-space: pre-wrap;
263
+ max-height: 200px;
264
+ overflow: auto;
265
+ }
266
+ .ds-settings .report-summary {
267
+ font-size: 12px;
268
+ font-weight: 600;
269
+ margin-bottom: 6px;
270
+ color: #3d4f5f;
271
+ }
272
+ </style>
273
+ </head>
274
+ <body>
275
+ <div class="ds-settings">
276
+ <div class="header">
277
+ <h1>Design themes</h1>
278
+ <p>
279
+ Edit add-menu items below. Changes preview live — click <strong>Save and sync</strong> to
280
+ write <code>agent-kit/aiditor/add-menu/design-system.generated.yaml</code> and refresh the
281
+ Add Menu. Regenerating from <code>DESIGN.md</code> overwrites manual edits.
282
+ </p>
283
+ <div class="toolbar">
284
+ <button
285
+ type="button"
286
+ class="primary"
287
+ ref="saveCatalogBtn"
288
+ disabled="saveDisabled"
289
+ >
290
+ {saveButtonLabel}
291
+ </button>
292
+ <button type="button" ref="discardCatalogBtn" disabled="discardDisabled">
293
+ Discard changes
294
+ </button>
295
+ <button type="button" ref="regenerateCatalogBtn">Regenerate from DESIGN.md</button>
296
+ <button type="button" ref="toggleAnalysisBtn">Validation tools</button>
297
+ </div>
298
+ </div>
299
+
300
+ <div class="operation-status {statusTone}" if="showStatusMessage">{statusMessage}</div>
301
+
302
+ <div class="workspace" if="!catalogLoading">
303
+ <div class="catalog-panel">
304
+ <div class="panel-head">Add Menu items</div>
305
+ <div class="empty-card" if="showNoCatalog">
306
+ No add-menu catalog found. Run <strong>Regenerate from DESIGN.md</strong> or
307
+ <code>yarn agent-kit</code> after adding <code>DESIGN.md</code>.
308
+ </div>
309
+ <div class="catalog-list" ref="catalogList" if="!showNoCatalog">
310
+ <button
311
+ type="button"
312
+ class="{rowClass}"
313
+ forEach="addMenuListRows"
314
+ trackBy="rowKey"
315
+ data-catalog-item="{itemId}"
316
+ >
317
+ <span class="catalog-item-title">{title}</span>
318
+ <span class="catalog-item-meta">{subCategory}</span>
319
+ </button>
320
+ </div>
321
+ </div>
322
+
323
+ <div class="editor-panel">
324
+ <div class="panel-head">Editor</div>
325
+ <div class="empty-card" if="!showAddMenuEditor">
326
+ Select an add-menu item to edit and preview.
327
+ </div>
328
+ <div class="editor-body" if="showAddMenuEditor">
329
+ <div class="read-only-note" if="editorReadOnly">{editorReadOnlyReason}</div>
330
+
331
+ <div class="field">
332
+ <label for="editor-title">Title</label>
333
+ <input
334
+ id="editor-title"
335
+ type="text"
336
+ ref="editorTitleInput"
337
+ value="{editorTitle}"
338
+ disabled="editorReadOnly"
339
+ />
340
+ </div>
341
+
342
+ <div class="field">
343
+ <label>Category</label>
344
+ <input type="text" value="{editorSubCategory}" disabled />
345
+ </div>
346
+
347
+ <div class="field" if="showTokenValueField">
348
+ <label for="editor-token-value">Value</label>
349
+ <input
350
+ id="editor-token-value"
351
+ type="text"
352
+ ref="editorTokenValueInput"
353
+ value="{editorTokenValue}"
354
+ disabled="editorReadOnly"
355
+ />
356
+ </div>
357
+
358
+ <div class="field" if="showTypographyFields">
359
+ <label for="editor-font-family">Font family</label>
360
+ <input
361
+ id="editor-font-family"
362
+ type="text"
363
+ ref="editorFontFamilyInput"
364
+ value="{editorFontFamily}"
365
+ disabled="editorReadOnly"
366
+ />
367
+ </div>
368
+ <div class="field" if="showTypographyFields">
369
+ <label for="editor-font-size">Font size</label>
370
+ <input
371
+ id="editor-font-size"
372
+ type="text"
373
+ ref="editorFontSizeInput"
374
+ value="{editorFontSize}"
375
+ disabled="editorReadOnly"
376
+ />
377
+ </div>
378
+ <div class="field" if="showTypographyFields">
379
+ <label for="editor-font-weight">Font weight</label>
380
+ <input
381
+ id="editor-font-weight"
382
+ type="text"
383
+ ref="editorFontWeightInput"
384
+ value="{editorFontWeight}"
385
+ disabled="editorReadOnly"
386
+ />
387
+ </div>
388
+
389
+ <div class="preview-panel">
390
+ <div class="preview-label">Preview</div>
391
+ <div class="preview-host" ref="previewHost"></div>
392
+ </div>
393
+ </div>
394
+ </div>
395
+ </div>
396
+
397
+ <div class="empty-card" if="catalogLoading">Loading add-menu catalog…</div>
398
+
399
+ <div class="analysis-section" if="showAnalysisSection">
400
+ <h2>Validation</h2>
401
+ <p style="font-size: 12px; color: #5a6f82; margin: 0 0 8px;">
402
+ Runs design-tokens, design-components, design-structure, and design-contrast validators.
403
+ </p>
404
+ <div class="toolbar" style="margin-top: 0;">
405
+ <button type="button" class="primary" ref="runAnalysisBtn">Run analysis</button>
406
+ <button type="button" ref="sendToAgentBtn">Send to agent</button>
407
+ </div>
408
+ <div if="showReport">
409
+ <div class="report-summary">{reportSummary}</div>
410
+ <div class="report-panel">{reportBody}</div>
411
+ </div>
412
+ </div>
413
+ </div>
414
+ </body>
415
+ </html>
@@ -0,0 +1,74 @@
1
+ import {JayElement, RenderElement, HTMLElementProxy, RenderElementOptions, JayContract} from "@jay-framework/runtime";
2
+
3
+ import './page.css';
4
+
5
+ export interface AddMenuListRowOfPageViewState {
6
+ rowKey: string,
7
+ itemId: string,
8
+ title: string,
9
+ subCategory: string,
10
+ rowClass: string
11
+ }
12
+
13
+ export interface PageViewState {
14
+ statusMessage: string,
15
+ statusTone: string,
16
+ showStatusMessage: boolean,
17
+ catalogLoading: boolean,
18
+ showNoCatalog: boolean,
19
+ addMenuListRows: Array<AddMenuListRowOfPageViewState>,
20
+ showAddMenuEditor: boolean,
21
+ editorTitle: string,
22
+ editorSubCategory: string,
23
+ editorTokenValue: string,
24
+ editorFontSize: string,
25
+ editorFontWeight: string,
26
+ editorFontFamily: string,
27
+ showTypographyFields: boolean,
28
+ showTokenValueField: boolean,
29
+ editorReadOnly: boolean,
30
+ editorReadOnlyReason: string,
31
+ unsavedChangeCount: number,
32
+ saveButtonLabel: string,
33
+ saveDisabled: boolean,
34
+ discardDisabled: boolean,
35
+ showAnalysisSection: boolean,
36
+ showReport: boolean,
37
+ reportSummary: string,
38
+ reportBody: string
39
+ }
40
+
41
+
42
+ export interface PageElementRefs {
43
+ saveCatalogBtn: HTMLElementProxy<PageViewState, HTMLButtonElement>,
44
+ discardCatalogBtn: HTMLElementProxy<PageViewState, HTMLButtonElement>,
45
+ regenerateCatalogBtn: HTMLElementProxy<PageViewState, HTMLButtonElement>,
46
+ toggleAnalysisBtn: HTMLElementProxy<PageViewState, HTMLButtonElement>,
47
+ catalogList: HTMLElementProxy<PageViewState, HTMLDivElement>,
48
+ editorTitleInput: HTMLElementProxy<PageViewState, HTMLInputElement>,
49
+ editorTokenValueInput: HTMLElementProxy<PageViewState, HTMLInputElement>,
50
+ editorFontFamilyInput: HTMLElementProxy<PageViewState, HTMLInputElement>,
51
+ editorFontSizeInput: HTMLElementProxy<PageViewState, HTMLInputElement>,
52
+ editorFontWeightInput: HTMLElementProxy<PageViewState, HTMLInputElement>,
53
+ previewHost: HTMLElementProxy<PageViewState, HTMLDivElement>,
54
+ runAnalysisBtn: HTMLElementProxy<PageViewState, HTMLButtonElement>,
55
+ sendToAgentBtn: HTMLElementProxy<PageViewState, HTMLButtonElement>
56
+ }
57
+
58
+ export type PageSlowViewState = {};
59
+ export type PageFastViewState = PageViewState;
60
+ export type PageInteractiveViewState = PageViewState;
61
+
62
+ export type PageElement = JayElement<PageViewState, PageElementRefs>
63
+ export type PageElementRender = RenderElement<PageViewState, PageElementRefs, PageElement>
64
+ export type PageElementPreRender = [PageElementRefs, PageElementRender]
65
+ export type PageContract = JayContract<
66
+ PageViewState,
67
+ PageElementRefs,
68
+ PageSlowViewState,
69
+ PageFastViewState,
70
+ PageInteractiveViewState
71
+ >;
72
+
73
+
74
+ export declare function render(options?: RenderElementOptions): PageElementPreRender
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/design-system-validator",
3
- "version": "0.22.2",
3
+ "version": "0.24.0",
4
4
  "type": "module",
5
5
  "description": "Design system validation plugin for Jay Framework — validates jay-html CSS against DESIGN.md tokens",
6
6
  "license": "Apache-2.0",
@@ -12,29 +12,45 @@
12
12
  ],
13
13
  "exports": {
14
14
  ".": "./dist/index.js",
15
- "./plugin.yaml": "./plugin.yaml"
15
+ "./client": "./dist/index.client.js",
16
+ "./plugin.yaml": "./plugin.yaml",
17
+ "./dist/pages/settings/page.jay-html": "./dist/pages/settings/page.jay-html",
18
+ "./font-fallback.jay-action": "./dist/actions/font-fallback.jay-action"
16
19
  },
17
20
  "scripts": {
18
- "build": "npm run clean && npm run build:server && npm run build:types && npm run validate",
21
+ "build": "npm run clean && npm run definitions && npm run build:copy-assets && npm run build:copy-actions && npm run build:client && npm run build:server && npm run build:types && npm run validate",
22
+ "definitions": "jay-cli definitions lib/pages/settings",
23
+ "build:copy-assets": "mkdir -p dist/pages/settings && cp lib/pages/settings/page.jay-html dist/pages/settings/ && cp lib/pages/settings/page.jay-html.d.ts dist/pages/settings/ 2>/dev/null || true",
24
+ "build:copy-actions": "mkdir -p dist/actions && cp lib/actions/*.jay-action dist/actions/",
25
+ "build:client": "vite build",
19
26
  "validate": "jay-stack-cli validate-plugin",
20
27
  "build:server": "vite build --ssr",
21
- "build:types": "tsup lib/index.ts --dts-only --format esm",
28
+ "build:types": "tsup lib/index.ts lib/index.client.ts --dts-only --format esm",
22
29
  "build:check-types": "tsc",
23
30
  "clean": "rimraf dist",
24
31
  "confirm": "npm run clean && npm run build && npm run test",
25
32
  "test": "vitest run"
26
33
  },
27
34
  "dependencies": {
35
+ "@capsizecss/core": "^4.1.3",
36
+ "@capsizecss/metrics": "^4.2.0",
37
+ "@capsizecss/unpack": "^4.0.1",
28
38
  "@csstools/selector-specificity": "^5.0.0",
29
- "@jay-framework/compiler-shared": "^0.22.2",
30
- "@jay-framework/stack-server-runtime": "^0.22.2",
39
+ "@jay-framework/compiler-jay-html": "^0.24.0",
40
+ "@jay-framework/compiler-shared": "^0.24.0",
41
+ "@jay-framework/component": "^0.24.0",
42
+ "@jay-framework/fullstack-component": "^0.24.0",
43
+ "@jay-framework/plugin-validator": "^0.24.0",
44
+ "@jay-framework/stack-server-runtime": "^0.24.0",
31
45
  "js-yaml": "^4.1.0",
32
46
  "postcss": "^8.5.6",
33
47
  "postcss-selector-parser": "^7.1.0"
34
48
  },
35
49
  "devDependencies": {
36
- "@jay-framework/dev-environment": "^0.22.2",
37
- "@jay-framework/jay-stack-cli": "^0.22.2",
50
+ "@jay-framework/compiler-jay-stack": "^0.24.0",
51
+ "@jay-framework/dev-environment": "^0.24.0",
52
+ "@jay-framework/jay-cli": "^0.24.0",
53
+ "@jay-framework/jay-stack-cli": "^0.24.0",
38
54
  "@types/js-yaml": "^4.0.9",
39
55
  "@types/node": "^22.15.21",
40
56
  "node-html-parser": "^6.1.0",
package/plugin.yaml CHANGED
@@ -3,6 +3,22 @@ name: design-system-validator
3
3
  agentkit: generateDesignSystemAgentKit
4
4
  description: Generate AIditor add-menu entries from DESIGN.md tokens
5
5
 
6
+ actions:
7
+ - getDesignSystemSettingsStatus
8
+ - runDesignSystemAnalysis
9
+ - loadDesignSystemAddMenuCatalog
10
+ - saveDesignSystemAddMenuCatalog
11
+ - regenerateDesignSystemAddMenu
12
+ - name: fontFallback
13
+ action: font-fallback.jay-action
14
+
15
+ routes:
16
+ - path: /design-system/settings
17
+ jayHtml: ./dist/pages/settings/page.jay-html
18
+ component: designSystemSettingsPage
19
+ description: Design system project settings — token overview, analysis report, add-menu regeneration
20
+ devOnly: true
21
+
6
22
  validators:
7
23
  - name: design-tokens
8
24
  handler: validateTokens
@@ -19,3 +35,11 @@ validators:
19
35
  - name: design-contrast
20
36
  handler: validateContrast
21
37
  description: Checks WCAG AA color contrast compliance on statically determinable color pairs
38
+
39
+ - name: font-fallbacks
40
+ handler: validateFontFallbacks
41
+ description: Detects web fonts loaded via @font-face URL without a metric-matched local fallback (causes CLS)
42
+
43
+ - name: undefined-vars
44
+ handler: validateUndefinedVars
45
+ description: Flags CSS var(--name) references that are never defined as custom properties