@golemui/gui-mcp 1.1.0 → 1.1.1-rc.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/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-U8ZsqQy-.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,8 @@ 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/dx", rel: "dx/index.d.ts" },
74
+ { spec: "@golemui/core", rel: "core/index.d.ts" }
72
75
  ];
73
76
  const DIST_SEARCH_DEPTH = 8;
74
77
  const SNIPPET_FILE = "__dx_snippet__.ts";
@@ -217,6 +220,249 @@ const DX_CHECK_CODE_TOOL = {
217
220
  required: ["code"]
218
221
  }
219
222
  };
223
+ function objectWithSuffix(specs) {
224
+ return new Decoder((json) => {
225
+ if (typeof json !== "object" || json === null) {
226
+ return err([{ message: `Expected object literal, got "${typeof json}"`, path: [] }]);
227
+ }
228
+ const out = {};
229
+ for (const [specKey, spec] of Object.entries(specs)) {
230
+ const res = spec.decoder.decode(json[specKey]);
231
+ if (!res.isOk()) {
232
+ return err(
233
+ res.issues.map((issue) => ({
234
+ message: issue.message,
235
+ path: [specKey, ...issue.path]
236
+ }))
237
+ );
238
+ }
239
+ out[specKey] = res.value;
240
+ if (spec.suffixed) {
241
+ for (const [jsonKey, jsonValue] of Object.entries(json)) {
242
+ if (jsonKey.startsWith(specKey + ".")) {
243
+ const res2 = spec.decoder.decode(jsonValue);
244
+ if (!res2.isOk()) {
245
+ return err(
246
+ res2.issues.map((issue) => ({
247
+ message: issue.message,
248
+ path: [jsonKey, ...issue.path]
249
+ }))
250
+ );
251
+ }
252
+ out[jsonKey] = res2.value;
253
+ }
254
+ }
255
+ }
256
+ }
257
+ return ok(out);
258
+ });
259
+ }
260
+ const shortUUID = () => crypto.randomUUID().slice(0, 8);
261
+ const isInputWidget = (widget) => typeof widget !== "function" && widget.kind === "input";
262
+ const isLayoutWidget = (widget) => typeof widget !== "function" && widget.kind === "layout";
263
+ const isFunctionWidget = (widget) => typeof widget === "function";
264
+ const inDecoder = object({ in: array(string()) });
265
+ const whenDecoder = object({ when: string() });
266
+ const includeDecoder = oneOf([inDecoder, whenDecoder]);
267
+ const fromDecoder = object({ from: array(string()) });
268
+ const excludeDecoder = oneOf([fromDecoder, whenDecoder]);
269
+ const boolWhenDecoder = oneOf([boolean(), whenDecoder]);
270
+ const widgetPropFnDecoder = new Decoder((json) => {
271
+ const jsonTypeof = typeof json;
272
+ if (jsonTypeof === "function") {
273
+ return ok(json);
274
+ } else {
275
+ return err([{ message: `Expected a function, got '${jsonTypeof}'`, path: [] }]);
276
+ }
277
+ });
278
+ const decodeWidgetPropOrWidgetPropFn = (decoder) => oneOf([decoder, widgetPropFnDecoder]);
279
+ const onDecoder = objectWithSuffix({
280
+ load: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) },
281
+ click: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) },
282
+ change: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) },
283
+ filter: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) },
284
+ blur: { suffixed: true, decoder: decodeWidgetPropOrWidgetPropFn(optional(string())) }
285
+ });
286
+ const translationConfigDecoder = object({
287
+ key: string(),
288
+ default: optional(string()),
289
+ params: optional(succeed())
290
+ });
291
+ const localizableDecoder = oneOf([string(), translationConfigDecoder]);
292
+ const uidDecoder = optional(string());
293
+ const displayWidgetDecoder = objectWithSuffix({
294
+ kind: { decoder: literal("display") },
295
+ uid: { decoder: uidDecoder },
296
+ type: { decoder: string() },
297
+ size: { suffixed: true, decoder: optional(number()) },
298
+ include: { decoder: optional(includeDecoder) },
299
+ exclude: { decoder: optional(excludeDecoder) },
300
+ props: { decoder: optional(succeed()) }
301
+ });
302
+ const actionWidgetDecoder = objectWithSuffix({
303
+ kind: { decoder: literal("action") },
304
+ uid: { decoder: uidDecoder },
305
+ type: { decoder: string() },
306
+ actionType: {
307
+ decoder: optional(oneOf([literal("button"), literal("submit")]))
308
+ },
309
+ size: { suffixed: true, decoder: optional(number()) },
310
+ include: { decoder: optional(includeDecoder) },
311
+ exclude: { decoder: optional(excludeDecoder) },
312
+ label: {
313
+ suffixed: true,
314
+ decoder: decodeWidgetPropOrWidgetPropFn(optional(localizableDecoder))
315
+ },
316
+ disabled: { suffixed: true, decoder: optional(boolWhenDecoder) },
317
+ on: { decoder: optional(onDecoder) },
318
+ props: { decoder: optional(succeed()) }
319
+ });
320
+ const functionWidgetDecoder = new Decoder((json) => {
321
+ const jsonTypeof = typeof json;
322
+ if (jsonTypeof === "function") {
323
+ const fnWidget = json;
324
+ const widget = fnWidget({
325
+ $form: {},
326
+ errors: void 0,
327
+ touched: void 0,
328
+ translate: void 0
329
+ });
330
+ fnWidget.uid = fnWidget.uid || widget.uid || shortUUID();
331
+ fnWidget.type = widget.type;
332
+ fnWidget.path = widget.path;
333
+ return ok(fnWidget);
334
+ } else {
335
+ return err([{ message: `Expected a function, got '${jsonTypeof}'`, path: [] }]);
336
+ }
337
+ });
338
+ const inputWidgetDecoder = objectWithSuffix({
339
+ kind: { decoder: literal("input") },
340
+ uid: { decoder: optional(string()) },
341
+ type: { decoder: string() },
342
+ size: { suffixed: true, decoder: optional(number()) },
343
+ include: { decoder: optional(includeDecoder) },
344
+ exclude: { decoder: optional(excludeDecoder) },
345
+ disabled: { suffixed: true, decoder: optional(boolWhenDecoder) },
346
+ readonly: { suffixed: true, decoder: optional(boolWhenDecoder) },
347
+ on: { decoder: optional(onDecoder) },
348
+ props: { decoder: optional(succeed()) },
349
+ label: {
350
+ suffixed: true,
351
+ decoder: decodeWidgetPropOrWidgetPropFn(optional(localizableDecoder))
352
+ },
353
+ path: { decoder: string() },
354
+ defaultValue: { decoder: optional(succeed()) },
355
+ validator: {
356
+ suffixed: true,
357
+ decoder: decodeWidgetPropOrWidgetPropFn(optional(succeed()))
358
+ }
359
+ }).map((ctrl) => {
360
+ const transformed = { ...ctrl };
361
+ if (!ctrl.uid) {
362
+ transformed.uid = `${ctrl.path}-${ctrl.type}`;
363
+ }
364
+ if (ctrl.type === "repeater") {
365
+ const props = ctrl["props"];
366
+ transformed.props = { ...props, template: layoutWidgetDecoder.parse(props["template"]) };
367
+ }
368
+ return transformed;
369
+ });
370
+ const formWidgetDecoder = lazy(() => {
371
+ const objectWidgetDecoder = discriminatedUnion("kind", {
372
+ input: inputWidgetDecoder,
373
+ layout: layoutWidgetDecoder,
374
+ display: displayWidgetDecoder,
375
+ action: actionWidgetDecoder
376
+ });
377
+ return new Decoder(
378
+ (json) => typeof json === "function" ? functionWidgetDecoder.decode(json) : objectWidgetDecoder.decode(json)
379
+ );
380
+ });
381
+ const layoutWidgetDecoder = objectWithSuffix({
382
+ kind: { decoder: literal("layout") },
383
+ uid: { decoder: uidDecoder },
384
+ type: { decoder: string() },
385
+ size: { suffixed: true, decoder: optional(number()) },
386
+ include: { decoder: optional(includeDecoder) },
387
+ exclude: { decoder: optional(excludeDecoder) },
388
+ props: { decoder: optional(succeed()) },
389
+ on: { decoder: optional(onDecoder) },
390
+ children: { decoder: array(formWidgetDecoder) }
391
+ });
392
+ function assignDeterministicUids(root) {
393
+ assignUidByPosition(root, "#0");
394
+ }
395
+ function assignUidByPosition(widget, positionUid) {
396
+ if (isFunctionWidget(widget)) {
397
+ return;
398
+ }
399
+ if (!widget.uid) {
400
+ widget.uid = positionUid;
401
+ }
402
+ if (isLayoutWidget(widget)) {
403
+ widget.children.forEach((child, index) => {
404
+ assignUidByPosition(child, `${positionUid}.${index}`);
405
+ });
406
+ }
407
+ if (isInputWidget(widget) && widget.type === "repeater") {
408
+ const template = widget.props?.["template"];
409
+ if (template) {
410
+ assignUidByPosition(template, `${positionUid}.t`);
411
+ }
412
+ }
413
+ }
414
+ object({
415
+ states: optional(record(string())),
416
+ form: lazy(() => layoutWidgetDecoder)
417
+ }).map((formDef) => {
418
+ assignDeterministicUids(formDef.form);
419
+ return formDef;
420
+ });
421
+ const formEventNames = {
422
+ submit: "formSubmit"
423
+ };
424
+ pipe(
425
+ map((store) => store.data),
426
+ distinctUntilChanged()
427
+ );
428
+ pipe(
429
+ filter((store) => store.touched === true),
430
+ map((store) => store.validations),
431
+ distinctUntilChanged()
432
+ );
433
+ pipe(
434
+ filter((store) => store.touched === true),
435
+ map((store) => store.injectedValidations),
436
+ distinctUntilChanged()
437
+ );
438
+ pipe(
439
+ map((store) => store.lang),
440
+ distinctUntilChanged()
441
+ );
442
+ pipe(
443
+ map((store) => store.calculatedWidgets),
444
+ distinctUntilChanged()
445
+ );
446
+ pipe(
447
+ map((store) => store.widgetFlags),
448
+ distinctUntilChanged()
449
+ );
450
+ pipe(
451
+ map((store) => store.touchedControls),
452
+ distinctUntilChanged()
453
+ );
454
+ pipe(
455
+ map((store) => store.formHealth),
456
+ distinctUntilChanged((prev, current) => {
457
+ if (prev.status !== current.status) {
458
+ return false;
459
+ }
460
+ if (prev.status === "errored" && current.status === "errored") {
461
+ return prev.message === current.message && prev.code === current.code;
462
+ }
463
+ return true;
464
+ })
465
+ );
220
466
  const DX_FRAMEWORKS = ["react", "angular", "vue", "lit", "vanilla"];
221
467
  function resolveDxFramework() {
222
468
  const raw = typeof process !== "undefined" ? process.env?.["GOLEMUI_FRAMEWORK"]?.toLowerCase() : void 0;
@@ -226,8 +472,8 @@ const FRAMEWORK_SETUP = {
226
472
  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
473
  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
474
  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 */ });`"
475
+ 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.",
476
+ 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
477
  };
232
478
  function commonNote(fw = "react") {
233
479
  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 +514,7 @@ const INPUTS = [
268
514
  {
269
515
  factory: "textInput",
270
516
  namespace: "inputs",
517
+ docSlug: "textinput",
271
518
  call: "gui.inputs.textInput(path, { label, placeholder?, defaultValue?, validator? })",
272
519
  example: "gui.inputs.textInput('fullName', { label: 'Full name', validator: { required: true, minLength: 2 } })",
273
520
  notes: [
@@ -278,6 +525,7 @@ const INPUTS = [
278
525
  {
279
526
  factory: "numberInput",
280
527
  namespace: "inputs",
528
+ docSlug: "number",
281
529
  call: "gui.inputs.numberInput(path, { label, defaultValue?, validator? })",
282
530
  example: "gui.inputs.numberInput('age', { label: 'Age', validator: { required: true, minimum: 0, maximum: 120 } })",
283
531
  notes: [
@@ -287,6 +535,7 @@ const INPUTS = [
287
535
  {
288
536
  factory: "booleanInput",
289
537
  namespace: "inputs",
538
+ docSlug: "toggle",
290
539
  call: "gui.inputs.booleanInput(path, { label, defaultValue? })",
291
540
  example: "gui.inputs.booleanInput('newsletter', { label: 'Subscribe to newsletter', defaultValue: false })",
292
541
  notes: ["The on/off toggle for a single boolean. Use `checkbox` for a checkbox presentation."]
@@ -294,6 +543,7 @@ const INPUTS = [
294
543
  {
295
544
  factory: "checkbox",
296
545
  namespace: "inputs",
546
+ docSlug: "checkbox",
297
547
  call: "gui.inputs.checkbox(path, { label, defaultValue? })",
298
548
  example: "gui.inputs.checkbox('terms', { label: 'I accept the terms', defaultValue: false })",
299
549
  notes: ["A single boolean rendered as a checkbox."]
@@ -301,6 +551,7 @@ const INPUTS = [
301
551
  {
302
552
  factory: "textarea",
303
553
  namespace: "inputs",
554
+ docSlug: "textarea",
304
555
  call: "gui.inputs.textarea(path, { label, placeholder?, validator? })",
305
556
  example: "gui.inputs.textarea('bio', { label: 'Bio', validator: { maxLength: 500 } })",
306
557
  notes: ["Multi-line text; same loose string validator as `textInput`."]
@@ -308,6 +559,7 @@ const INPUTS = [
308
559
  {
309
560
  factory: "password",
310
561
  namespace: "inputs",
562
+ docSlug: "password",
311
563
  call: "gui.inputs.password(path, { label, validator? })",
312
564
  example: "gui.inputs.password('password', { label: 'Password', validator: { required: true, minLength: 8 } })",
313
565
  notes: ["Masked text input; loose string validator."]
@@ -315,6 +567,7 @@ const INPUTS = [
315
567
  {
316
568
  factory: "dropdown",
317
569
  namespace: "inputs",
570
+ docSlug: "dropdown",
318
571
  call: "gui.inputs.dropdown(path, { label, items, validator? })",
319
572
  example: "gui.inputs.dropdown('country', { label: 'Country', items: [{ value: 'us', label: 'United States' }, { value: 'ca', label: 'Canada' }], validator: { type: 'string', required: true } })",
320
573
  notes: [
@@ -325,6 +578,7 @@ const INPUTS = [
325
578
  {
326
579
  factory: "radiogroup",
327
580
  namespace: "inputs",
581
+ docSlug: "radiogroup",
328
582
  call: "gui.inputs.radiogroup(path, { label, options, defaultValue?, validator? })",
329
583
  example: "gui.inputs.radiogroup('accountType', { label: 'Account type', defaultValue: 'personal', options: [{ value: 'personal', label: 'Personal' }, { value: 'business', label: 'Business' }] })",
330
584
  notes: [
@@ -335,6 +589,7 @@ const INPUTS = [
335
589
  {
336
590
  factory: "datePicker",
337
591
  namespace: "inputs",
592
+ docSlug: "date-picker",
338
593
  call: "gui.inputs.datePicker(path, { label, minDate?, maxDate?, validator? })",
339
594
  example: "gui.inputs.datePicker('startDate', { label: 'Coverage start', minDate: '2025-01-01', validator: { required: true } })",
340
595
  notes: [
@@ -345,6 +600,7 @@ const INPUTS = [
345
600
  {
346
601
  factory: "currency",
347
602
  namespace: "inputs",
603
+ docSlug: "currency",
348
604
  call: "gui.inputs.currency(path, { label, validator? })",
349
605
  example: "gui.inputs.currency('price', { label: 'Price', validator: { required: true, minimum: 0 } })",
350
606
  notes: ["Numeric money input; number-style validator."]
@@ -352,6 +608,7 @@ const INPUTS = [
352
608
  {
353
609
  factory: "select",
354
610
  namespace: "inputs",
611
+ docSlug: "select",
355
612
  call: "gui.inputs.select(path, { label, options, validator? })",
356
613
  example: "gui.inputs.select('plan', { label: 'Plan', options: [{ value: 'free', label: 'Free' }, { value: 'pro', label: 'Pro' }], validator: { type: 'string', required: true } })",
357
614
  notes: [
@@ -362,6 +619,7 @@ const INPUTS = [
362
619
  {
363
620
  factory: "dateInput",
364
621
  namespace: "inputs",
622
+ docSlug: "dateinput",
365
623
  call: "gui.inputs.dateInput(path, { label, minDate?, maxDate?, validator? })",
366
624
  example: "gui.inputs.dateInput('startDate', { label: 'Start date', validator: { required: true } })",
367
625
  notes: [
@@ -372,6 +630,7 @@ const INPUTS = [
372
630
  {
373
631
  factory: "timeInput",
374
632
  namespace: "inputs",
633
+ docSlug: "timeinput",
375
634
  call: "gui.inputs.timeInput(path, { label, hourFormat?, minuteStep?, validator? })",
376
635
  example: "gui.inputs.timeInput('meetingTime', { label: 'Meeting time', minuteStep: 15 })",
377
636
  notes: [
@@ -381,6 +640,7 @@ const INPUTS = [
381
640
  {
382
641
  factory: "timePicker",
383
642
  namespace: "inputs",
643
+ docSlug: "timepicker",
384
644
  call: "gui.inputs.timePicker(path, { label, minTime?, maxTime?, minuteStep?, disabledRanges?, allowCustomTime?, validator? })",
385
645
  example: "gui.inputs.timePicker('meetingTime', { label: 'Meeting time', minTime: '09:00', maxTime: '18:00', minuteStep: 30 })",
386
646
  notes: [
@@ -390,6 +650,7 @@ const INPUTS = [
390
650
  {
391
651
  factory: "dateTimeInput",
392
652
  namespace: "inputs",
653
+ docSlug: "datetimeinput",
393
654
  call: "gui.inputs.dateTimeInput(path, { label, hourFormat?, minuteStep?, validator? })",
394
655
  example: "gui.inputs.dateTimeInput('meetingAt', { label: 'Meeting at' })",
395
656
  notes: [
@@ -399,6 +660,7 @@ const INPUTS = [
399
660
  {
400
661
  factory: "calendar",
401
662
  namespace: "inputs",
663
+ docSlug: "calendar",
402
664
  call: "gui.inputs.calendar(path, { label, minDate?, maxDate? })",
403
665
  example: "gui.inputs.calendar('day', { label: 'Pick a day', minDate: '2025-01-01' })",
404
666
  notes: [
@@ -409,6 +671,7 @@ const INPUTS = [
409
671
  {
410
672
  factory: "dateTimeCalendar",
411
673
  namespace: "inputs",
674
+ docSlug: "datetimecalendar",
412
675
  call: "gui.inputs.dateTimeCalendar(path, { label, minDate?, maxDate?, minTime?, maxTime?, minuteStep?, disabledTimeRanges?, allowCustomTime? })",
413
676
  example: "gui.inputs.dateTimeCalendar('appointmentAt', { label: 'Appointment', minTime: '09:00', maxTime: '18:00' })",
414
677
  notes: [
@@ -420,6 +683,7 @@ const INPUTS = [
420
683
  {
421
684
  factory: "dateTimePicker",
422
685
  namespace: "inputs",
686
+ docSlug: "datetimepicker",
423
687
  call: "gui.inputs.dateTimePicker(path, { label, minDate?, maxDate?, minTime?, maxTime?, minuteStep?, disabledTimeRanges?, allowCustomTime? })",
424
688
  example: "gui.inputs.dateTimePicker('appointmentAt', { label: 'Appointment', minTime: '09:00', maxTime: '18:00' })",
425
689
  notes: [
@@ -431,6 +695,7 @@ const INPUTS = [
431
695
  {
432
696
  factory: "markdown",
433
697
  namespace: "inputs",
698
+ docSlug: "markdown",
434
699
  call: "gui.inputs.markdown(path, { label })",
435
700
  example: "gui.inputs.markdown('notes', { label: 'Notes (markdown)' })",
436
701
  notes: [
@@ -440,6 +705,7 @@ const INPUTS = [
440
705
  {
441
706
  factory: "tags",
442
707
  namespace: "inputs",
708
+ docSlug: "tags",
443
709
  call: "gui.inputs.tags(path, { label })",
444
710
  example: "gui.inputs.tags('skills', { label: 'Skills' })",
445
711
  notes: ["Free-form multi-value tag input; the value is a string array."]
@@ -447,6 +713,7 @@ const INPUTS = [
447
713
  {
448
714
  factory: "repeater",
449
715
  namespace: "inputs",
716
+ docSlug: "repeater",
450
717
  call: "gui.inputs.repeater(path, { label?, addLabel?, removeLabel?, limit?, template })",
451
718
  example: "gui.inputs.repeater('attendees', { label: 'Attendees', addLabel: 'Add attendee', template: [ gui.inputs.textInput('attendees.items.name', { label: 'Name' }) ] })",
452
719
  notes: [
@@ -458,6 +725,7 @@ const INPUTS = [
458
725
  {
459
726
  factory: "list",
460
727
  namespace: "inputs",
728
+ docSlug: "list",
461
729
  call: "gui.inputs.list(path, { label, items, height?, itemHeight? })",
462
730
  example: "gui.inputs.list('selection', { label: 'Pick an option', items: ['Option 1', 'Option 2', 'Option 3'], height: 200, itemHeight: 40 })",
463
731
  notes: [
@@ -468,6 +736,7 @@ const INPUTS = [
468
736
  {
469
737
  factory: "rangeCalendar",
470
738
  namespace: "inputs",
739
+ docSlug: "range-calendar",
471
740
  call: "gui.inputs.rangeCalendar(path, { label? })",
472
741
  example: "gui.inputs.rangeCalendar('stayDates', { label: 'Stay dates' })",
473
742
  notes: [
@@ -477,6 +746,7 @@ const INPUTS = [
477
746
  {
478
747
  factory: "rangeDateInput",
479
748
  namespace: "inputs",
749
+ docSlug: "range-date-input",
480
750
  call: "gui.inputs.rangeDateInput(path, { label? })",
481
751
  example: "gui.inputs.rangeDateInput('stayDates', { label: 'Stay dates' })",
482
752
  notes: ["Typed start–end date **range** entry (the range sibling of `dateInput`)."]
@@ -484,6 +754,7 @@ const INPUTS = [
484
754
  {
485
755
  factory: "rangeTimeInput",
486
756
  namespace: "inputs",
757
+ docSlug: "range-time-input",
487
758
  call: "gui.inputs.rangeTimeInput(path, { label?, minTime?, maxTime? })",
488
759
  example: "gui.inputs.rangeTimeInput('shift', { label: 'Shift', minTime: '06:00:00', maxTime: '22:00:00' })",
489
760
  notes: [
@@ -493,6 +764,7 @@ const INPUTS = [
493
764
  {
494
765
  factory: "rangeDateTimeInput",
495
766
  namespace: "inputs",
767
+ docSlug: "range-datetime-input",
496
768
  call: "gui.inputs.rangeDateTimeInput(path, { label?, minDateTime?, maxDateTime? })",
497
769
  example: "gui.inputs.rangeDateTimeInput('window', { label: 'Window', minDateTime: '2026-03-01T06:00:00', maxDateTime: '2026-03-31T22:00:00' })",
498
770
  notes: [
@@ -503,6 +775,7 @@ const INPUTS = [
503
775
  {
504
776
  factory: "rangeDateTimeCalendar",
505
777
  namespace: "inputs",
778
+ docSlug: "range-datetime-calendar",
506
779
  call: "gui.inputs.rangeDateTimeCalendar(path, { label?, minDateTime?, maxDateTime?, disabledRanges?, startTimeLabel?, endTimeLabel? })",
507
780
  example: "gui.inputs.rangeDateTimeCalendar('stay', { label: 'Stay', startTimeLabel: 'Check-in', endTimeLabel: 'Check-out' })",
508
781
  notes: [
@@ -513,6 +786,7 @@ const INPUTS = [
513
786
  {
514
787
  factory: "rangeDateTimePicker",
515
788
  namespace: "inputs",
789
+ docSlug: "range-datetime-picker",
516
790
  call: "gui.inputs.rangeDateTimePicker(path, { label?, minDateTime?, maxDateTime?, disabledRanges?, startTimeLabel?, endTimeLabel? })",
517
791
  example: "gui.inputs.rangeDateTimePicker('stay', { label: 'Stay', startTimeLabel: 'Check-in', endTimeLabel: 'Check-out' })",
518
792
  notes: [
@@ -523,6 +797,7 @@ const INPUTS = [
523
797
  {
524
798
  factory: "rangeDatePicker",
525
799
  namespace: "inputs",
800
+ docSlug: "range-date-picker",
526
801
  call: "gui.inputs.rangeDatePicker(path, { label? })",
527
802
  example: "gui.inputs.rangeDatePicker('stayDates', { label: 'Stay dates' })",
528
803
  notes: ["Popover calendar for a start–end date **range** (the range sibling of `datePicker`)."]
@@ -530,6 +805,7 @@ const INPUTS = [
530
805
  {
531
806
  factory: "rangeTimePicker",
532
807
  namespace: "inputs",
808
+ docSlug: "range-time-picker",
533
809
  call: "gui.inputs.rangeTimePicker(path, { label?, minTime?, maxTime? })",
534
810
  example: "gui.inputs.rangeTimePicker('shift', { label: 'Shift', minTime: '06:00:00', maxTime: '22:00:00' })",
535
811
  notes: [
@@ -541,6 +817,7 @@ const ACTIONS = [
541
817
  {
542
818
  factory: "button",
543
819
  namespace: "actions",
820
+ docSlug: "button",
544
821
  call: "gui.actions.button({ label, actionType?: 'submit', onClick? })",
545
822
  example: "gui.actions.button({ label: 'Sign up', actionType: 'submit' })",
546
823
  notes: [
@@ -554,6 +831,7 @@ const DISPLAYS = [
554
831
  {
555
832
  factory: "alert",
556
833
  namespace: "displays",
834
+ docSlug: "alert",
557
835
  call: "gui.displays.alert({ text })",
558
836
  example: "gui.displays.alert({ text: 'Please review your details before submitting.' })",
559
837
  notes: [
@@ -563,6 +841,7 @@ const DISPLAYS = [
563
841
  {
564
842
  factory: "display",
565
843
  namespace: "displays",
844
+ docSlug: "renderer",
566
845
  call: "gui.displays.display(render)",
567
846
  example: "gui.displays.display(() => 'Order summary')",
568
847
  notes: [
@@ -575,6 +854,7 @@ const LAYOUTS = [
575
854
  {
576
855
  factory: "flex",
577
856
  namespace: "layouts",
857
+ docSlug: "flex",
578
858
  call: "gui.layouts.flex(children, props?)",
579
859
  example: "gui.layouts.flex([ gui.inputs.textInput('firstName', { label: 'First name' }), gui.inputs.textInput('lastName', { label: 'Last name' }) ])",
580
860
  notes: [
@@ -585,6 +865,7 @@ const LAYOUTS = [
585
865
  {
586
866
  factory: "verticalFlex",
587
867
  namespace: "layouts",
868
+ docSlug: "flex",
588
869
  call: "gui.layouts.verticalFlex(children, props?)",
589
870
  example: "gui.layouts.verticalFlex([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
590
871
  notes: ["A `flex` with direction fixed to vertical."]
@@ -592,6 +873,7 @@ const LAYOUTS = [
592
873
  {
593
874
  factory: "horizontalFlex",
594
875
  namespace: "layouts",
876
+ docSlug: "flex",
595
877
  call: "gui.layouts.horizontalFlex(children, props?)",
596
878
  example: "gui.layouts.horizontalFlex([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
597
879
  notes: ["A `flex` with direction fixed to horizontal."]
@@ -599,6 +881,7 @@ const LAYOUTS = [
599
881
  {
600
882
  factory: "grid",
601
883
  namespace: "layouts",
884
+ docSlug: "grid",
602
885
  call: "gui.layouts.grid(children, props?)",
603
886
  example: "gui.layouts.grid([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
604
887
  notes: ["Grid layout; `horizontalGrid` / `verticalGrid` lock the direction."]
@@ -606,6 +889,7 @@ const LAYOUTS = [
606
889
  {
607
890
  factory: "verticalGrid",
608
891
  namespace: "layouts",
892
+ docSlug: "grid",
609
893
  call: "gui.layouts.verticalGrid(children, props?)",
610
894
  example: "gui.layouts.verticalGrid([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
611
895
  notes: ["A `grid` with direction fixed to vertical."]
@@ -613,6 +897,7 @@ const LAYOUTS = [
613
897
  {
614
898
  factory: "horizontalGrid",
615
899
  namespace: "layouts",
900
+ docSlug: "grid",
616
901
  call: "gui.layouts.horizontalGrid(children, props?)",
617
902
  example: "gui.layouts.horizontalGrid([ gui.inputs.textInput('a', { label: 'A' }), gui.inputs.textInput('b', { label: 'B' }) ])",
618
903
  notes: ["A `grid` with direction fixed to horizontal."]
@@ -620,6 +905,7 @@ const LAYOUTS = [
620
905
  {
621
906
  factory: "tabs",
622
907
  namespace: "layouts",
908
+ docSlug: "tabs",
623
909
  call: "gui.layouts.tabs(sections)",
624
910
  example: "gui.layouts.tabs([ { label: 'Account', children: [ gui.inputs.textInput('email', { label: 'Email' }) ] }, { label: 'Profile', children: [ gui.inputs.textInput('name', { label: 'Name' }) ] } ])",
625
911
  notes: [
@@ -629,6 +915,7 @@ const LAYOUTS = [
629
915
  {
630
916
  factory: "accordion",
631
917
  namespace: "layouts",
918
+ docSlug: "accordion",
632
919
  call: "gui.layouts.accordion(sections)",
633
920
  example: "gui.layouts.accordion([ { label: 'Billing', children: [ gui.inputs.textInput('card', { label: 'Card' }) ] } ])",
634
921
  notes: [
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "@golemui/gui-mcp",
3
- "version": "1.1.0",
3
+ "version": "1.1.1-rc.1",
4
4
  "license": "MIT",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
5
8
  "description": "Model Context Protocol server for GolemUI — gives AI coding assistants deterministic schema validation and form generation for GolemUI form definitions.",
6
9
  "type": "module",
7
10
  "main": "./lib.js",
@@ -40,10 +43,10 @@
40
43
  "ajv": "^8.17.1",
41
44
  "ajv-formats": "^3.0.1",
42
45
  "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",
46
+ "@golemui/gui-schemas": "1.1.1-rc.1",
47
+ "@golemui/gui-shared": "1.1.1-rc.1",
48
+ "@golemui/gui-validators": "1.1.1-rc.1",
49
+ "@golemui/core": "1.1.1-rc.1",
47
50
  "zod": "^4.0.0",
48
51
  "@standard-schema/spec": "^1.0.0"
49
52
  },