@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/json.js CHANGED
@@ -1,4 +1,4 @@
1
- import { G, J, a, b, c, g, d, e, f, v } from "./get-concept-e_HDPrW1.js";
1
+ import { G, J, a, b, c, g, d, e, f, v } from "./get-concept-DRFSt-XX.js";
2
2
  export {
3
3
  G as GET_CONCEPT_TOOL,
4
4
  J as JSON_GENERATE_FROM_OPENAPI_TOOL,
package/lib.js CHANGED
@@ -1,5 +1,5 @@
1
- import { G, J, a, b, c, g, d, e, f, v } from "./get-concept-e_HDPrW1.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-BlB_usDm.js";
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-e_HDPrW1.js";
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 }} @form-submit=${(e: CustomEvent) => { /* e.detail is the FormSubmitEvent; e.detail.data */ }}></gui-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('form-submit', (e) => { /* e.detail.data */ });`"
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
  },