@golemui/gui-mcp 1.1.0 → 1.1.1-rc.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.
- package/CHANGELOG.md +16 -0
- package/README.md +16 -0
- package/cli-commands.d.ts +18 -0
- package/cli.js +87 -2
- package/dx/dx-specs.d.ts +12 -0
- package/{get-concept-e_HDPrW1.js → get-concept-DRFSt-XX.js} +34 -34
- package/json.js +1 -1
- package/lib.js +2 -2
- package/{list-dx-factories-BlB_usDm.js → list-dx-factories-Dwy_BYZi.js} +291 -5
- package/package.json +5 -5
package/json.js
CHANGED
package/lib.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { G, J, a, b, c, g, d, e, f, v } from "./get-concept-
|
|
2
|
-
import { D, a as a2, b as b2, c as c2, d as d2, e as e2, g as g2, l, f as f2, t } from "./list-dx-factories-
|
|
1
|
+
import { G, J, a, b, c, g, d, e, f, v } from "./get-concept-DRFSt-XX.js";
|
|
2
|
+
import { D, a as a2, b as b2, c as c2, d as d2, e as e2, g as g2, l, f as f2, t } from "./list-dx-factories-Dwy_BYZi.js";
|
|
3
3
|
export {
|
|
4
4
|
D as DX_CHECK_CODE_TOOL,
|
|
5
5
|
a2 as DX_GET_SPEC_TOOL,
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { h as checkReactiveExpression } from "./get-concept-
|
|
1
|
+
import { h as checkReactiveExpression } from "./get-concept-DRFSt-XX.js";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { resolve, join, dirname } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { Decoder, err, ok, object, array, string, oneOf, boolean, optional, succeed, number, literal, lazy, discriminatedUnion, record } from "ts.data.json";
|
|
7
|
+
import "subscript/justin";
|
|
8
|
+
import { pipe, map, distinctUntilChanged, filter } from "rxjs";
|
|
6
9
|
const CONFIG_FIELDS = ["include", "exclude", "disabled", "readonly"];
|
|
7
10
|
function lintDxSnippet(ts, sourceText, lineOffset) {
|
|
8
11
|
const sf = ts.createSourceFile("__dx_lint__.ts", sourceText, ts.ScriptTarget.ES2020, true);
|
|
@@ -67,8 +70,7 @@ const GOLEMUI_TYPE_PACKAGES = [
|
|
|
67
70
|
{ spec: "@golemui/gui-shared", rel: "gui/shared/index.d.ts" },
|
|
68
71
|
{ spec: "@golemui/gui-shared/internals", rel: "gui/shared/internals.d.ts" },
|
|
69
72
|
{ spec: "@golemui/gui-validators", rel: "gui/validators/index.d.ts" },
|
|
70
|
-
{ spec: "@golemui/core", rel: "core/index.d.ts" }
|
|
71
|
-
{ spec: "@golemui/core/internals", rel: "core/internals.d.ts" }
|
|
73
|
+
{ spec: "@golemui/core", rel: "core/index.d.ts" }
|
|
72
74
|
];
|
|
73
75
|
const DIST_SEARCH_DEPTH = 8;
|
|
74
76
|
const SNIPPET_FILE = "__dx_snippet__.ts";
|
|
@@ -217,6 +219,249 @@ const DX_CHECK_CODE_TOOL = {
|
|
|
217
219
|
required: ["code"]
|
|
218
220
|
}
|
|
219
221
|
};
|
|
222
|
+
function objectWithSuffix(specs) {
|
|
223
|
+
return new Decoder((json) => {
|
|
224
|
+
if (typeof json !== "object" || json === null) {
|
|
225
|
+
return err([{ message: `Expected object literal, got "${typeof json}"`, path: [] }]);
|
|
226
|
+
}
|
|
227
|
+
const out = {};
|
|
228
|
+
for (const [specKey, spec] of Object.entries(specs)) {
|
|
229
|
+
const res = spec.decoder.decode(json[specKey]);
|
|
230
|
+
if (!res.isOk()) {
|
|
231
|
+
return err(
|
|
232
|
+
res.issues.map((issue) => ({
|
|
233
|
+
message: issue.message,
|
|
234
|
+
path: [specKey, ...issue.path]
|
|
235
|
+
}))
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
out[specKey] = res.value;
|
|
239
|
+
if (spec.suffixed) {
|
|
240
|
+
for (const [jsonKey, jsonValue] of Object.entries(json)) {
|
|
241
|
+
if (jsonKey.startsWith(specKey + ".")) {
|
|
242
|
+
const res2 = spec.decoder.decode(jsonValue);
|
|
243
|
+
if (!res2.isOk()) {
|
|
244
|
+
return err(
|
|
245
|
+
res2.issues.map((issue) => ({
|
|
246
|
+
message: issue.message,
|
|
247
|
+
path: [jsonKey, ...issue.path]
|
|
248
|
+
}))
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
out[jsonKey] = res2.value;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return ok(out);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
const shortUUID = () => crypto.randomUUID().slice(0, 8);
|
|
260
|
+
const isInputWidget = (widget) => typeof widget !== "function" && widget.kind === "input";
|
|
261
|
+
const isLayoutWidget = (widget) => typeof widget !== "function" && widget.kind === "layout";
|
|
262
|
+
const isFunctionWidget = (widget) => typeof widget === "function";
|
|
263
|
+
const inDecoder = object({ in: array(string()) });
|
|
264
|
+
const whenDecoder = object({ when: string() });
|
|
265
|
+
const includeDecoder = oneOf([inDecoder, whenDecoder]);
|
|
266
|
+
const fromDecoder = object({ from: array(string()) });
|
|
267
|
+
const excludeDecoder = oneOf([fromDecoder, whenDecoder]);
|
|
268
|
+
const boolWhenDecoder = oneOf([boolean(), whenDecoder]);
|
|
269
|
+
const widgetPropFnDecoder = new Decoder((json) => {
|
|
270
|
+
const jsonTypeof = typeof json;
|
|
271
|
+
if (jsonTypeof === "function") {
|
|
272
|
+
return ok(json);
|
|
273
|
+
} else {
|
|
274
|
+
return err([{ message: `Expected a function, got '${jsonTypeof}'`, path: [] }]);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
const decodeWidgetPropOrWidgetPropFn = (decoder) => oneOf([decoder, widgetPropFnDecoder]);
|
|
278
|
+
const onDecoder = objectWithSuffix({
|
|
279
|
+
load: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) },
|
|
280
|
+
click: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) },
|
|
281
|
+
change: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) },
|
|
282
|
+
filter: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) },
|
|
283
|
+
blur: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) }
|
|
284
|
+
});
|
|
285
|
+
const translationConfigDecoder = object({
|
|
286
|
+
key: string(),
|
|
287
|
+
default: optional(string()),
|
|
288
|
+
params: optional(succeed())
|
|
289
|
+
});
|
|
290
|
+
const localizableDecoder = oneOf([string(), translationConfigDecoder]);
|
|
291
|
+
const uidDecoder = optional(string());
|
|
292
|
+
const displayWidgetDecoder = objectWithSuffix({
|
|
293
|
+
kind: { decoder: literal("display") },
|
|
294
|
+
uid: { decoder: uidDecoder },
|
|
295
|
+
type: { decoder: string() },
|
|
296
|
+
size: { suffixed: true, decoder: optional(number()) },
|
|
297
|
+
include: { decoder: optional(includeDecoder) },
|
|
298
|
+
exclude: { decoder: optional(excludeDecoder) },
|
|
299
|
+
props: { decoder: optional(succeed()) }
|
|
300
|
+
});
|
|
301
|
+
const actionWidgetDecoder = objectWithSuffix({
|
|
302
|
+
kind: { decoder: literal("action") },
|
|
303
|
+
uid: { decoder: uidDecoder },
|
|
304
|
+
type: { decoder: string() },
|
|
305
|
+
actionType: {
|
|
306
|
+
decoder: optional(oneOf([literal("button"), literal("submit")]))
|
|
307
|
+
},
|
|
308
|
+
size: { suffixed: true, decoder: optional(number()) },
|
|
309
|
+
include: { decoder: optional(includeDecoder) },
|
|
310
|
+
exclude: { decoder: optional(excludeDecoder) },
|
|
311
|
+
label: {
|
|
312
|
+
suffixed: true,
|
|
313
|
+
decoder: decodeWidgetPropOrWidgetPropFn(optional(localizableDecoder))
|
|
314
|
+
},
|
|
315
|
+
disabled: { suffixed: true, decoder: optional(boolWhenDecoder) },
|
|
316
|
+
on: { decoder: optional(onDecoder) },
|
|
317
|
+
props: { decoder: optional(succeed()) }
|
|
318
|
+
});
|
|
319
|
+
const functionWidgetDecoder = new Decoder((json) => {
|
|
320
|
+
const jsonTypeof = typeof json;
|
|
321
|
+
if (jsonTypeof === "function") {
|
|
322
|
+
const fnWidget = json;
|
|
323
|
+
const widget = fnWidget({
|
|
324
|
+
$form: {},
|
|
325
|
+
errors: void 0,
|
|
326
|
+
touched: void 0,
|
|
327
|
+
translate: void 0
|
|
328
|
+
});
|
|
329
|
+
fnWidget.uid = fnWidget.uid || widget.uid || shortUUID();
|
|
330
|
+
fnWidget.type = widget.type;
|
|
331
|
+
fnWidget.path = widget.path;
|
|
332
|
+
return ok(fnWidget);
|
|
333
|
+
} else {
|
|
334
|
+
return err([{ message: `Expected a function, got '${jsonTypeof}'`, path: [] }]);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
const inputWidgetDecoder = objectWithSuffix({
|
|
338
|
+
kind: { decoder: literal("input") },
|
|
339
|
+
uid: { decoder: optional(string()) },
|
|
340
|
+
type: { decoder: string() },
|
|
341
|
+
size: { suffixed: true, decoder: optional(number()) },
|
|
342
|
+
include: { decoder: optional(includeDecoder) },
|
|
343
|
+
exclude: { decoder: optional(excludeDecoder) },
|
|
344
|
+
disabled: { suffixed: true, decoder: optional(boolWhenDecoder) },
|
|
345
|
+
readonly: { suffixed: true, decoder: optional(boolWhenDecoder) },
|
|
346
|
+
on: { decoder: optional(onDecoder) },
|
|
347
|
+
props: { decoder: optional(succeed()) },
|
|
348
|
+
label: {
|
|
349
|
+
suffixed: true,
|
|
350
|
+
decoder: decodeWidgetPropOrWidgetPropFn(optional(localizableDecoder))
|
|
351
|
+
},
|
|
352
|
+
path: { decoder: string() },
|
|
353
|
+
defaultValue: { decoder: optional(succeed()) },
|
|
354
|
+
validator: {
|
|
355
|
+
suffixed: true,
|
|
356
|
+
decoder: decodeWidgetPropOrWidgetPropFn(optional(succeed()))
|
|
357
|
+
}
|
|
358
|
+
}).map((ctrl) => {
|
|
359
|
+
const transformed = { ...ctrl };
|
|
360
|
+
if (!ctrl.uid) {
|
|
361
|
+
transformed.uid = `${ctrl.path}-${ctrl.type}`;
|
|
362
|
+
}
|
|
363
|
+
if (ctrl.type === "repeater") {
|
|
364
|
+
const props = ctrl["props"];
|
|
365
|
+
transformed.props = { ...props, template: layoutWidgetDecoder.parse(props["template"]) };
|
|
366
|
+
}
|
|
367
|
+
return transformed;
|
|
368
|
+
});
|
|
369
|
+
const formWidgetDecoder = lazy(() => {
|
|
370
|
+
const objectWidgetDecoder = discriminatedUnion("kind", {
|
|
371
|
+
input: inputWidgetDecoder,
|
|
372
|
+
layout: layoutWidgetDecoder,
|
|
373
|
+
display: displayWidgetDecoder,
|
|
374
|
+
action: actionWidgetDecoder
|
|
375
|
+
});
|
|
376
|
+
return new Decoder(
|
|
377
|
+
(json) => typeof json === "function" ? functionWidgetDecoder.decode(json) : objectWidgetDecoder.decode(json)
|
|
378
|
+
);
|
|
379
|
+
});
|
|
380
|
+
const layoutWidgetDecoder = objectWithSuffix({
|
|
381
|
+
kind: { decoder: literal("layout") },
|
|
382
|
+
uid: { decoder: uidDecoder },
|
|
383
|
+
type: { decoder: string() },
|
|
384
|
+
size: { suffixed: true, decoder: optional(number()) },
|
|
385
|
+
include: { decoder: optional(includeDecoder) },
|
|
386
|
+
exclude: { decoder: optional(excludeDecoder) },
|
|
387
|
+
props: { decoder: optional(succeed()) },
|
|
388
|
+
on: { decoder: optional(onDecoder) },
|
|
389
|
+
children: { decoder: array(formWidgetDecoder) }
|
|
390
|
+
});
|
|
391
|
+
function assignDeterministicUids(root) {
|
|
392
|
+
assignUidByPosition(root, "#0");
|
|
393
|
+
}
|
|
394
|
+
function assignUidByPosition(widget, positionUid) {
|
|
395
|
+
if (isFunctionWidget(widget)) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
if (!widget.uid) {
|
|
399
|
+
widget.uid = positionUid;
|
|
400
|
+
}
|
|
401
|
+
if (isLayoutWidget(widget)) {
|
|
402
|
+
widget.children.forEach((child, index) => {
|
|
403
|
+
assignUidByPosition(child, `${positionUid}.${index}`);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
if (isInputWidget(widget) && widget.type === "repeater") {
|
|
407
|
+
const template = widget.props?.["template"];
|
|
408
|
+
if (template) {
|
|
409
|
+
assignUidByPosition(template, `${positionUid}.t`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
object({
|
|
414
|
+
states: optional(record(string())),
|
|
415
|
+
form: lazy(() => layoutWidgetDecoder)
|
|
416
|
+
}).map((formDef) => {
|
|
417
|
+
assignDeterministicUids(formDef.form);
|
|
418
|
+
return formDef;
|
|
419
|
+
});
|
|
420
|
+
const formEventNames = {
|
|
421
|
+
submit: "formSubmit"
|
|
422
|
+
};
|
|
423
|
+
pipe(
|
|
424
|
+
map((store) => store.data),
|
|
425
|
+
distinctUntilChanged()
|
|
426
|
+
);
|
|
427
|
+
pipe(
|
|
428
|
+
filter((store) => store.touched === true),
|
|
429
|
+
map((store) => store.validations),
|
|
430
|
+
distinctUntilChanged()
|
|
431
|
+
);
|
|
432
|
+
pipe(
|
|
433
|
+
filter((store) => store.touched === true),
|
|
434
|
+
map((store) => store.injectedValidations),
|
|
435
|
+
distinctUntilChanged()
|
|
436
|
+
);
|
|
437
|
+
pipe(
|
|
438
|
+
map((store) => store.lang),
|
|
439
|
+
distinctUntilChanged()
|
|
440
|
+
);
|
|
441
|
+
pipe(
|
|
442
|
+
map((store) => store.calculatedWidgets),
|
|
443
|
+
distinctUntilChanged()
|
|
444
|
+
);
|
|
445
|
+
pipe(
|
|
446
|
+
map((store) => store.widgetFlags),
|
|
447
|
+
distinctUntilChanged()
|
|
448
|
+
);
|
|
449
|
+
pipe(
|
|
450
|
+
map((store) => store.touchedControls),
|
|
451
|
+
distinctUntilChanged()
|
|
452
|
+
);
|
|
453
|
+
pipe(
|
|
454
|
+
map((store) => store.formHealth),
|
|
455
|
+
distinctUntilChanged((prev, current) => {
|
|
456
|
+
if (prev.status !== current.status) {
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
if (prev.status === "errored" && current.status === "errored") {
|
|
460
|
+
return prev.message === current.message && prev.code === current.code;
|
|
461
|
+
}
|
|
462
|
+
return true;
|
|
463
|
+
})
|
|
464
|
+
);
|
|
220
465
|
const DX_FRAMEWORKS = ["react", "angular", "vue", "lit", "vanilla"];
|
|
221
466
|
function resolveDxFramework() {
|
|
222
467
|
const raw = typeof process !== "undefined" ? process.env?.["GOLEMUI_FRAMEWORK"]?.toLowerCase() : void 0;
|
|
@@ -226,8 +471,8 @@ const FRAMEWORK_SETUP = {
|
|
|
226
471
|
react: "RENDER (React) — `import { gui } from '@golemui/gui-shared'; import { GuiForm } from '@golemui/gui-react'; import type { FormSubmitEvent } from '@golemui/core';`, then render `<GuiForm config={{ formDef: form }} formSubmit={(e: FormSubmitEvent) => { /* e.data is the form data */ }} />`. A `gui.displays.display(() => <h2>…</h2>)` returns React JSX.",
|
|
227
472
|
angular: "RENDER (Angular) — `import { gui } from '@golemui/gui-shared'; import { FormComponent } from '@golemui/gui-angular';`, add `FormComponent` to the standalone component's `imports`, then in the template `<gui-form [config]=\"{ formDef: form }\" (formSubmit)=\"onSubmit($event)\"></gui-form>` — `$event` is a `FormSubmitEvent` (type from `@golemui/core`), `$event.data` is the form data.",
|
|
228
473
|
vue: "RENDER (Vue) — `import { gui } from '@golemui/gui-shared'; import { GuiForm } from '@golemui/gui-vue';`, then `<GuiForm :config=\"{ formDef: form }\" @form-submit=\"onSubmit\" />` — the handler receives a `FormSubmitEvent` (`.data` is the form data). The event is `form-submit` (kebab-case), not `formSubmit`.",
|
|
229
|
-
lit: "RENDER (Lit) — `import { gui } from '@golemui/gui-shared'; import '@golemui/gui-lit';` (registers the `<gui-form>` custom element), then `<gui-form .config=${{ formDef: form }} @
|
|
230
|
-
vanilla: "RENDER (vanilla JS) — `import { gui } from '@golemui/gui-shared'; import '@golemui/gui-lit';` (registers `<gui-form>`), then `const el = document.querySelector('gui-form'); el.config = { formDef: form }; el.addEventListener('
|
|
474
|
+
lit: "RENDER (Lit) — `import { gui } from '@golemui/gui-shared'; import '@golemui/gui-lit';` (registers the `<gui-form>` custom element), then `<gui-form .config=${{ formDef: form }} @" + formEventNames.submit + "=${(e: CustomEvent) => { /* e.detail is the FormSubmitEvent; e.detail.data */ }}></gui-form>`. The event name is `" + formEventNames.submit + "` (camelCase) — Lit dispatches a raw CustomEvent, so there is no kebab-case alias.",
|
|
475
|
+
vanilla: "RENDER (vanilla JS) — `import { gui } from '@golemui/gui-shared'; import '@golemui/gui-lit';` (registers `<gui-form>`), then `const el = document.querySelector('gui-form'); el.config = { formDef: form }; el.addEventListener('" + formEventNames.submit + "', (e) => { /* e.detail.data */ });`. In TypeScript, type the element — `import type { FormElement } from '@golemui/gui-lit'; const el = document.querySelector<FormElement>('gui-form');` — the published types do not register `gui-form` in `HTMLElementTagNameMap`, so an untyped `querySelector` yields `Element` and `el.config` fails to compile."
|
|
231
476
|
};
|
|
232
477
|
function commonNote(fw = "react") {
|
|
233
478
|
return "GolemUI builds FORMS — data collection and validation. It is NOT a general-purpose UI toolkit: it never renders documents, page content, or markdown for display. A form is just an array of these items: `export const form = [ /* items */ ];`. " + FRAMEWORK_SETUP[fw] + " Import the component stylesheet ONCE — `@golemui/gui-components/index.css` — or the form renders unstyled. To RECEIVE A SUBMIT: add a `gui.actions.button({ label, actionType: 'submit' })` to the form and listen for the submit on the host component (the RENDER line above shows how for your framework) — the handler gets a `FormSubmitEvent` whose `.data` is the collected form data. To DISABLE submit until the form is valid, add `disabled: { when: '$formIsInvalid' }` to that button (`$formIsInvalid` is a built-in validity flag) — see the conditional-and-state-props pattern. The SAME `formDef` renders in every framework (React/Angular/Vue/Lit/vanilla) — only the host wrapper changes. FORM-LEVEL CONFIG — `formDef` is ALWAYS the bare array. Anything form-wide (named `states`, `validateOn`) goes in a sibling `formConfig` on the config (`config={{ formDef: form, formConfig: { states, validateOn } }}`), NEVER inside `formDef`. Do NOT wrap the array as `{ states, form: [...] }` and pass THAT as `formDef` — `formDef` is typed `Record<string, any>` so it COMPILES, but the `gui.*` items are never resolved and the form renders BLANK with no error. See the form-level-states pattern. Common fields like `include`/`exclude` (conditional visibility) go INSIDE a factory’s config argument — never spread them onto the result (`{ ...gui.inputs.x(...), include }` compiles but silently does nothing). See the conditional-visibility pattern. STATIC CONTENT — a section heading or any non-input text/block is the HOST’s job, not GolemUI’s: use `gui.displays.display(() => <h2>…</h2>)` returning your framework’s own node (React JSX, Vue/Angular/Lit node) — it needs no dependency and always renders. MARKDOWN has exactly ONE use: `gui.inputs.markdown`, an INPUT where the user EDITS markdown (its value is their markdown string). There is NO markdown-for-display widget — never use markdown to render a heading or content; use `display` for that. VALIDATOR `type` — one rule, three cases (so you never have to guess): (1) choice widgets (`dropdown`, `radiogroup`, `select`) REQUIRE an explicit `type`: `validator: { type: 'string', required: true }`. (2) `repeater` (array) validators auto-supply `type: 'array'` — supply only the rules, e.g. `validator: { required: true, minItems: 1 }`, never `type`. (3) everything else (text, number, date) takes the loose validator with NO `type`: `validator: { required: true }`. EVENT HANDLERS — `onChange`/`onLoad`/`onFilter`/`onBlur` (inputs/layouts) and `onClick` (actions) are FUNCTIONS, never bare strings: return a string to dispatch a host event by that name (`onChange: () => 'languageChanged'`), or take the event to push live changes (`onChange: (event) => event.update({ path: 'city', options: [...] })`).";
|
|
@@ -268,6 +513,7 @@ const INPUTS = [
|
|
|
268
513
|
{
|
|
269
514
|
factory: "textInput",
|
|
270
515
|
namespace: "inputs",
|
|
516
|
+
docSlug: "textinput",
|
|
271
517
|
call: "gui.inputs.textInput(path, { label, placeholder?, defaultValue?, validator? })",
|
|
272
518
|
example: "gui.inputs.textInput('fullName', { label: 'Full name', validator: { required: true, minLength: 2 } })",
|
|
273
519
|
notes: [
|
|
@@ -278,6 +524,7 @@ const INPUTS = [
|
|
|
278
524
|
{
|
|
279
525
|
factory: "numberInput",
|
|
280
526
|
namespace: "inputs",
|
|
527
|
+
docSlug: "number",
|
|
281
528
|
call: "gui.inputs.numberInput(path, { label, defaultValue?, validator? })",
|
|
282
529
|
example: "gui.inputs.numberInput('age', { label: 'Age', validator: { required: true, minimum: 0, maximum: 120 } })",
|
|
283
530
|
notes: [
|
|
@@ -287,6 +534,7 @@ const INPUTS = [
|
|
|
287
534
|
{
|
|
288
535
|
factory: "booleanInput",
|
|
289
536
|
namespace: "inputs",
|
|
537
|
+
docSlug: "toggle",
|
|
290
538
|
call: "gui.inputs.booleanInput(path, { label, defaultValue? })",
|
|
291
539
|
example: "gui.inputs.booleanInput('newsletter', { label: 'Subscribe to newsletter', defaultValue: false })",
|
|
292
540
|
notes: ["The on/off toggle for a single boolean. Use `checkbox` for a checkbox presentation."]
|
|
@@ -294,6 +542,7 @@ const INPUTS = [
|
|
|
294
542
|
{
|
|
295
543
|
factory: "checkbox",
|
|
296
544
|
namespace: "inputs",
|
|
545
|
+
docSlug: "checkbox",
|
|
297
546
|
call: "gui.inputs.checkbox(path, { label, defaultValue? })",
|
|
298
547
|
example: "gui.inputs.checkbox('terms', { label: 'I accept the terms', defaultValue: false })",
|
|
299
548
|
notes: ["A single boolean rendered as a checkbox."]
|
|
@@ -301,6 +550,7 @@ const INPUTS = [
|
|
|
301
550
|
{
|
|
302
551
|
factory: "textarea",
|
|
303
552
|
namespace: "inputs",
|
|
553
|
+
docSlug: "textarea",
|
|
304
554
|
call: "gui.inputs.textarea(path, { label, placeholder?, validator? })",
|
|
305
555
|
example: "gui.inputs.textarea('bio', { label: 'Bio', validator: { maxLength: 500 } })",
|
|
306
556
|
notes: ["Multi-line text; same loose string validator as `textInput`."]
|
|
@@ -308,6 +558,7 @@ const INPUTS = [
|
|
|
308
558
|
{
|
|
309
559
|
factory: "password",
|
|
310
560
|
namespace: "inputs",
|
|
561
|
+
docSlug: "password",
|
|
311
562
|
call: "gui.inputs.password(path, { label, validator? })",
|
|
312
563
|
example: "gui.inputs.password('password', { label: 'Password', validator: { required: true, minLength: 8 } })",
|
|
313
564
|
notes: ["Masked text input; loose string validator."]
|
|
@@ -315,6 +566,7 @@ const INPUTS = [
|
|
|
315
566
|
{
|
|
316
567
|
factory: "dropdown",
|
|
317
568
|
namespace: "inputs",
|
|
569
|
+
docSlug: "dropdown",
|
|
318
570
|
call: "gui.inputs.dropdown(path, { label, items, validator? })",
|
|
319
571
|
example: "gui.inputs.dropdown('country', { label: 'Country', items: [{ value: 'us', label: 'United States' }, { value: 'ca', label: 'Canada' }], validator: { type: 'string', required: true } })",
|
|
320
572
|
notes: [
|
|
@@ -325,6 +577,7 @@ const INPUTS = [
|
|
|
325
577
|
{
|
|
326
578
|
factory: "radiogroup",
|
|
327
579
|
namespace: "inputs",
|
|
580
|
+
docSlug: "radiogroup",
|
|
328
581
|
call: "gui.inputs.radiogroup(path, { label, options, defaultValue?, validator? })",
|
|
329
582
|
example: "gui.inputs.radiogroup('accountType', { label: 'Account type', defaultValue: 'personal', options: [{ value: 'personal', label: 'Personal' }, { value: 'business', label: 'Business' }] })",
|
|
330
583
|
notes: [
|
|
@@ -335,6 +588,7 @@ const INPUTS = [
|
|
|
335
588
|
{
|
|
336
589
|
factory: "datePicker",
|
|
337
590
|
namespace: "inputs",
|
|
591
|
+
docSlug: "date-picker",
|
|
338
592
|
call: "gui.inputs.datePicker(path, { label, minDate?, maxDate?, validator? })",
|
|
339
593
|
example: "gui.inputs.datePicker('startDate', { label: 'Coverage start', minDate: '2025-01-01', validator: { required: true } })",
|
|
340
594
|
notes: [
|
|
@@ -345,6 +599,7 @@ const INPUTS = [
|
|
|
345
599
|
{
|
|
346
600
|
factory: "currency",
|
|
347
601
|
namespace: "inputs",
|
|
602
|
+
docSlug: "currency",
|
|
348
603
|
call: "gui.inputs.currency(path, { label, validator? })",
|
|
349
604
|
example: "gui.inputs.currency('price', { label: 'Price', validator: { required: true, minimum: 0 } })",
|
|
350
605
|
notes: ["Numeric money input; number-style validator."]
|
|
@@ -352,6 +607,7 @@ const INPUTS = [
|
|
|
352
607
|
{
|
|
353
608
|
factory: "select",
|
|
354
609
|
namespace: "inputs",
|
|
610
|
+
docSlug: "select",
|
|
355
611
|
call: "gui.inputs.select(path, { label, options, validator? })",
|
|
356
612
|
example: "gui.inputs.select('plan', { label: 'Plan', options: [{ value: 'free', label: 'Free' }, { value: 'pro', label: 'Pro' }], validator: { type: 'string', required: true } })",
|
|
357
613
|
notes: [
|
|
@@ -362,6 +618,7 @@ const INPUTS = [
|
|
|
362
618
|
{
|
|
363
619
|
factory: "dateInput",
|
|
364
620
|
namespace: "inputs",
|
|
621
|
+
docSlug: "dateinput",
|
|
365
622
|
call: "gui.inputs.dateInput(path, { label, minDate?, maxDate?, validator? })",
|
|
366
623
|
example: "gui.inputs.dateInput('startDate', { label: 'Start date', validator: { required: true } })",
|
|
367
624
|
notes: [
|
|
@@ -372,6 +629,7 @@ const INPUTS = [
|
|
|
372
629
|
{
|
|
373
630
|
factory: "timeInput",
|
|
374
631
|
namespace: "inputs",
|
|
632
|
+
docSlug: "timeinput",
|
|
375
633
|
call: "gui.inputs.timeInput(path, { label, hourFormat?, minuteStep?, validator? })",
|
|
376
634
|
example: "gui.inputs.timeInput('meetingTime', { label: 'Meeting time', minuteStep: 15 })",
|
|
377
635
|
notes: [
|
|
@@ -381,6 +639,7 @@ const INPUTS = [
|
|
|
381
639
|
{
|
|
382
640
|
factory: "timePicker",
|
|
383
641
|
namespace: "inputs",
|
|
642
|
+
docSlug: "timepicker",
|
|
384
643
|
call: "gui.inputs.timePicker(path, { label, minTime?, maxTime?, minuteStep?, disabledRanges?, allowCustomTime?, validator? })",
|
|
385
644
|
example: "gui.inputs.timePicker('meetingTime', { label: 'Meeting time', minTime: '09:00', maxTime: '18:00', minuteStep: 30 })",
|
|
386
645
|
notes: [
|
|
@@ -390,6 +649,7 @@ const INPUTS = [
|
|
|
390
649
|
{
|
|
391
650
|
factory: "dateTimeInput",
|
|
392
651
|
namespace: "inputs",
|
|
652
|
+
docSlug: "datetimeinput",
|
|
393
653
|
call: "gui.inputs.dateTimeInput(path, { label, hourFormat?, minuteStep?, validator? })",
|
|
394
654
|
example: "gui.inputs.dateTimeInput('meetingAt', { label: 'Meeting at' })",
|
|
395
655
|
notes: [
|
|
@@ -399,6 +659,7 @@ const INPUTS = [
|
|
|
399
659
|
{
|
|
400
660
|
factory: "calendar",
|
|
401
661
|
namespace: "inputs",
|
|
662
|
+
docSlug: "calendar",
|
|
402
663
|
call: "gui.inputs.calendar(path, { label, minDate?, maxDate? })",
|
|
403
664
|
example: "gui.inputs.calendar('day', { label: 'Pick a day', minDate: '2025-01-01' })",
|
|
404
665
|
notes: [
|
|
@@ -409,6 +670,7 @@ const INPUTS = [
|
|
|
409
670
|
{
|
|
410
671
|
factory: "dateTimeCalendar",
|
|
411
672
|
namespace: "inputs",
|
|
673
|
+
docSlug: "datetimecalendar",
|
|
412
674
|
call: "gui.inputs.dateTimeCalendar(path, { label, minDate?, maxDate?, minTime?, maxTime?, minuteStep?, disabledTimeRanges?, allowCustomTime? })",
|
|
413
675
|
example: "gui.inputs.dateTimeCalendar('appointmentAt', { label: 'Appointment', minTime: '09:00', maxTime: '18:00' })",
|
|
414
676
|
notes: [
|
|
@@ -420,6 +682,7 @@ const INPUTS = [
|
|
|
420
682
|
{
|
|
421
683
|
factory: "dateTimePicker",
|
|
422
684
|
namespace: "inputs",
|
|
685
|
+
docSlug: "datetimepicker",
|
|
423
686
|
call: "gui.inputs.dateTimePicker(path, { label, minDate?, maxDate?, minTime?, maxTime?, minuteStep?, disabledTimeRanges?, allowCustomTime? })",
|
|
424
687
|
example: "gui.inputs.dateTimePicker('appointmentAt', { label: 'Appointment', minTime: '09:00', maxTime: '18:00' })",
|
|
425
688
|
notes: [
|
|
@@ -431,6 +694,7 @@ const INPUTS = [
|
|
|
431
694
|
{
|
|
432
695
|
factory: "markdown",
|
|
433
696
|
namespace: "inputs",
|
|
697
|
+
docSlug: "markdown",
|
|
434
698
|
call: "gui.inputs.markdown(path, { label })",
|
|
435
699
|
example: "gui.inputs.markdown('notes', { label: 'Notes (markdown)' })",
|
|
436
700
|
notes: [
|
|
@@ -440,6 +704,7 @@ const INPUTS = [
|
|
|
440
704
|
{
|
|
441
705
|
factory: "tags",
|
|
442
706
|
namespace: "inputs",
|
|
707
|
+
docSlug: "tags",
|
|
443
708
|
call: "gui.inputs.tags(path, { label })",
|
|
444
709
|
example: "gui.inputs.tags('skills', { label: 'Skills' })",
|
|
445
710
|
notes: ["Free-form multi-value tag input; the value is a string array."]
|
|
@@ -447,6 +712,7 @@ const INPUTS = [
|
|
|
447
712
|
{
|
|
448
713
|
factory: "repeater",
|
|
449
714
|
namespace: "inputs",
|
|
715
|
+
docSlug: "repeater",
|
|
450
716
|
call: "gui.inputs.repeater(path, { label?, addLabel?, removeLabel?, limit?, template })",
|
|
451
717
|
example: "gui.inputs.repeater('attendees', { label: 'Attendees', addLabel: 'Add attendee', template: [ gui.inputs.textInput('attendees.items.name', { label: 'Name' }) ] })",
|
|
452
718
|
notes: [
|
|
@@ -458,6 +724,7 @@ const INPUTS = [
|
|
|
458
724
|
{
|
|
459
725
|
factory: "list",
|
|
460
726
|
namespace: "inputs",
|
|
727
|
+
docSlug: "list",
|
|
461
728
|
call: "gui.inputs.list(path, { label, items, height?, itemHeight? })",
|
|
462
729
|
example: "gui.inputs.list('selection', { label: 'Pick an option', items: ['Option 1', 'Option 2', 'Option 3'], height: 200, itemHeight: 40 })",
|
|
463
730
|
notes: [
|
|
@@ -468,6 +735,7 @@ const INPUTS = [
|
|
|
468
735
|
{
|
|
469
736
|
factory: "rangeCalendar",
|
|
470
737
|
namespace: "inputs",
|
|
738
|
+
docSlug: "range-calendar",
|
|
471
739
|
call: "gui.inputs.rangeCalendar(path, { label? })",
|
|
472
740
|
example: "gui.inputs.rangeCalendar('stayDates', { label: 'Stay dates' })",
|
|
473
741
|
notes: [
|
|
@@ -477,6 +745,7 @@ const INPUTS = [
|
|
|
477
745
|
{
|
|
478
746
|
factory: "rangeDateInput",
|
|
479
747
|
namespace: "inputs",
|
|
748
|
+
docSlug: "range-date-input",
|
|
480
749
|
call: "gui.inputs.rangeDateInput(path, { label? })",
|
|
481
750
|
example: "gui.inputs.rangeDateInput('stayDates', { label: 'Stay dates' })",
|
|
482
751
|
notes: ["Typed start–end date **range** entry (the range sibling of `dateInput`)."]
|
|
@@ -484,6 +753,7 @@ const INPUTS = [
|
|
|
484
753
|
{
|
|
485
754
|
factory: "rangeTimeInput",
|
|
486
755
|
namespace: "inputs",
|
|
756
|
+
docSlug: "range-time-input",
|
|
487
757
|
call: "gui.inputs.rangeTimeInput(path, { label?, minTime?, maxTime? })",
|
|
488
758
|
example: "gui.inputs.rangeTimeInput('shift', { label: 'Shift', minTime: '06:00:00', maxTime: '22:00:00' })",
|
|
489
759
|
notes: [
|
|
@@ -493,6 +763,7 @@ const INPUTS = [
|
|
|
493
763
|
{
|
|
494
764
|
factory: "rangeDateTimeInput",
|
|
495
765
|
namespace: "inputs",
|
|
766
|
+
docSlug: "range-datetime-input",
|
|
496
767
|
call: "gui.inputs.rangeDateTimeInput(path, { label?, minDateTime?, maxDateTime? })",
|
|
497
768
|
example: "gui.inputs.rangeDateTimeInput('window', { label: 'Window', minDateTime: '2026-03-01T06:00:00', maxDateTime: '2026-03-31T22:00:00' })",
|
|
498
769
|
notes: [
|
|
@@ -503,6 +774,7 @@ const INPUTS = [
|
|
|
503
774
|
{
|
|
504
775
|
factory: "rangeDateTimeCalendar",
|
|
505
776
|
namespace: "inputs",
|
|
777
|
+
docSlug: "range-datetime-calendar",
|
|
506
778
|
call: "gui.inputs.rangeDateTimeCalendar(path, { label?, minDateTime?, maxDateTime?, disabledRanges?, startTimeLabel?, endTimeLabel? })",
|
|
507
779
|
example: "gui.inputs.rangeDateTimeCalendar('stay', { label: 'Stay', startTimeLabel: 'Check-in', endTimeLabel: 'Check-out' })",
|
|
508
780
|
notes: [
|
|
@@ -513,6 +785,7 @@ const INPUTS = [
|
|
|
513
785
|
{
|
|
514
786
|
factory: "rangeDateTimePicker",
|
|
515
787
|
namespace: "inputs",
|
|
788
|
+
docSlug: "range-datetime-picker",
|
|
516
789
|
call: "gui.inputs.rangeDateTimePicker(path, { label?, minDateTime?, maxDateTime?, disabledRanges?, startTimeLabel?, endTimeLabel? })",
|
|
517
790
|
example: "gui.inputs.rangeDateTimePicker('stay', { label: 'Stay', startTimeLabel: 'Check-in', endTimeLabel: 'Check-out' })",
|
|
518
791
|
notes: [
|
|
@@ -523,6 +796,7 @@ const INPUTS = [
|
|
|
523
796
|
{
|
|
524
797
|
factory: "rangeDatePicker",
|
|
525
798
|
namespace: "inputs",
|
|
799
|
+
docSlug: "range-date-picker",
|
|
526
800
|
call: "gui.inputs.rangeDatePicker(path, { label? })",
|
|
527
801
|
example: "gui.inputs.rangeDatePicker('stayDates', { label: 'Stay dates' })",
|
|
528
802
|
notes: ["Popover calendar for a start–end date **range** (the range sibling of `datePicker`)."]
|
|
@@ -530,6 +804,7 @@ const INPUTS = [
|
|
|
530
804
|
{
|
|
531
805
|
factory: "rangeTimePicker",
|
|
532
806
|
namespace: "inputs",
|
|
807
|
+
docSlug: "range-time-picker",
|
|
533
808
|
call: "gui.inputs.rangeTimePicker(path, { label?, minTime?, maxTime? })",
|
|
534
809
|
example: "gui.inputs.rangeTimePicker('shift', { label: 'Shift', minTime: '06:00:00', maxTime: '22:00:00' })",
|
|
535
810
|
notes: [
|
|
@@ -541,6 +816,7 @@ const ACTIONS = [
|
|
|
541
816
|
{
|
|
542
817
|
factory: "button",
|
|
543
818
|
namespace: "actions",
|
|
819
|
+
docSlug: "button",
|
|
544
820
|
call: "gui.actions.button({ label, actionType?: 'submit', onClick? })",
|
|
545
821
|
example: "gui.actions.button({ label: 'Sign up', actionType: 'submit' })",
|
|
546
822
|
notes: [
|
|
@@ -554,6 +830,7 @@ const DISPLAYS = [
|
|
|
554
830
|
{
|
|
555
831
|
factory: "alert",
|
|
556
832
|
namespace: "displays",
|
|
833
|
+
docSlug: "alert",
|
|
557
834
|
call: "gui.displays.alert({ text })",
|
|
558
835
|
example: "gui.displays.alert({ text: 'Please review your details before submitting.' })",
|
|
559
836
|
notes: [
|
|
@@ -563,6 +840,7 @@ const DISPLAYS = [
|
|
|
563
840
|
{
|
|
564
841
|
factory: "display",
|
|
565
842
|
namespace: "displays",
|
|
843
|
+
docSlug: "renderer",
|
|
566
844
|
call: "gui.displays.display(render)",
|
|
567
845
|
example: "gui.displays.display(() => 'Order summary')",
|
|
568
846
|
notes: [
|
|
@@ -575,6 +853,7 @@ const LAYOUTS = [
|
|
|
575
853
|
{
|
|
576
854
|
factory: "flex",
|
|
577
855
|
namespace: "layouts",
|
|
856
|
+
docSlug: "flex",
|
|
578
857
|
call: "gui.layouts.flex(children, props?)",
|
|
579
858
|
example: "gui.layouts.flex([ gui.inputs.textInput('firstName', { label: 'First name' }), gui.inputs.textInput('lastName', { label: 'Last name' }) ])",
|
|
580
859
|
notes: [
|
|
@@ -585,6 +864,7 @@ const LAYOUTS = [
|
|
|
585
864
|
{
|
|
586
865
|
factory: "verticalFlex",
|
|
587
866
|
namespace: "layouts",
|
|
867
|
+
docSlug: "flex",
|
|
588
868
|
call: "gui.layouts.verticalFlex(children, props?)",
|
|
589
869
|
example: "gui.layouts.verticalFlex([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
|
|
590
870
|
notes: ["A `flex` with direction fixed to vertical."]
|
|
@@ -592,6 +872,7 @@ const LAYOUTS = [
|
|
|
592
872
|
{
|
|
593
873
|
factory: "horizontalFlex",
|
|
594
874
|
namespace: "layouts",
|
|
875
|
+
docSlug: "flex",
|
|
595
876
|
call: "gui.layouts.horizontalFlex(children, props?)",
|
|
596
877
|
example: "gui.layouts.horizontalFlex([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
|
|
597
878
|
notes: ["A `flex` with direction fixed to horizontal."]
|
|
@@ -599,6 +880,7 @@ const LAYOUTS = [
|
|
|
599
880
|
{
|
|
600
881
|
factory: "grid",
|
|
601
882
|
namespace: "layouts",
|
|
883
|
+
docSlug: "grid",
|
|
602
884
|
call: "gui.layouts.grid(children, props?)",
|
|
603
885
|
example: "gui.layouts.grid([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
|
|
604
886
|
notes: ["Grid layout; `horizontalGrid` / `verticalGrid` lock the direction."]
|
|
@@ -606,6 +888,7 @@ const LAYOUTS = [
|
|
|
606
888
|
{
|
|
607
889
|
factory: "verticalGrid",
|
|
608
890
|
namespace: "layouts",
|
|
891
|
+
docSlug: "grid",
|
|
609
892
|
call: "gui.layouts.verticalGrid(children, props?)",
|
|
610
893
|
example: "gui.layouts.verticalGrid([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
|
|
611
894
|
notes: ["A `grid` with direction fixed to vertical."]
|
|
@@ -613,6 +896,7 @@ const LAYOUTS = [
|
|
|
613
896
|
{
|
|
614
897
|
factory: "horizontalGrid",
|
|
615
898
|
namespace: "layouts",
|
|
899
|
+
docSlug: "grid",
|
|
616
900
|
call: "gui.layouts.horizontalGrid(children, props?)",
|
|
617
901
|
example: "gui.layouts.horizontalGrid([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
|
|
618
902
|
notes: ["A `grid` with direction fixed to horizontal."]
|
|
@@ -620,6 +904,7 @@ const LAYOUTS = [
|
|
|
620
904
|
{
|
|
621
905
|
factory: "tabs",
|
|
622
906
|
namespace: "layouts",
|
|
907
|
+
docSlug: "tabs",
|
|
623
908
|
call: "gui.layouts.tabs(sections)",
|
|
624
909
|
example: "gui.layouts.tabs([ { label: 'Account', children: [ gui.inputs.textInput('email', { label: 'Email' }) ] }, { label: 'Profile', children: [ gui.inputs.textInput('name', { label: 'Name' }) ] } ])",
|
|
625
910
|
notes: [
|
|
@@ -629,6 +914,7 @@ const LAYOUTS = [
|
|
|
629
914
|
{
|
|
630
915
|
factory: "accordion",
|
|
631
916
|
namespace: "layouts",
|
|
917
|
+
docSlug: "accordion",
|
|
632
918
|
call: "gui.layouts.accordion(sections)",
|
|
633
919
|
example: "gui.layouts.accordion([ { label: 'Billing', children: [ gui.inputs.textInput('card', { label: 'Card' }) ] } ])",
|
|
634
920
|
notes: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@golemui/gui-mcp",
|
|
3
|
-
"version": "1.1.0",
|
|
3
|
+
"version": "1.1.1-rc.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Model Context Protocol server for GolemUI — gives AI coding assistants deterministic schema validation and form generation for GolemUI form definitions.",
|
|
6
6
|
"type": "module",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"ajv": "^8.17.1",
|
|
41
41
|
"ajv-formats": "^3.0.1",
|
|
42
42
|
"typescript": "^5.9.2",
|
|
43
|
-
"@golemui/gui-schemas": "1.1.0",
|
|
44
|
-
"@golemui/gui-shared": "1.1.0",
|
|
45
|
-
"@golemui/gui-validators": "1.1.0",
|
|
46
|
-
"@golemui/core": "1.1.0",
|
|
43
|
+
"@golemui/gui-schemas": "1.1.1-rc.0",
|
|
44
|
+
"@golemui/gui-shared": "1.1.1-rc.0",
|
|
45
|
+
"@golemui/gui-validators": "1.1.1-rc.0",
|
|
46
|
+
"@golemui/core": "1.1.1-rc.0",
|
|
47
47
|
"zod": "^4.0.0",
|
|
48
48
|
"@standard-schema/spec": "^1.0.0"
|
|
49
49
|
},
|