@grampro/kit 2.7.1 → 2.7.3

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.
Files changed (80) hide show
  1. package/.gbs/skills/gbs-components/SKILL.md +233 -207
  2. package/.gbs/skills/gbs-components/references/data-grid.md +9 -0
  3. package/.gbs/skills/gbs-components/references/forms.md +12 -0
  4. package/.gbs/skills/gbs-components/references/install.md +42 -5
  5. package/CHANGELOG.md +963 -798
  6. package/README.md +13 -4
  7. package/index.cjs +250 -138
  8. package/package.json +1 -1
  9. package/source/components/accordion/passport.json +1 -1
  10. package/source/components/alert/passport.json +1 -1
  11. package/source/components/avatar/passport.json +1 -1
  12. package/source/components/badge/passport.json +1 -1
  13. package/source/components/breadcrumb/passport.json +1 -1
  14. package/source/components/button/passport.json +1 -1
  15. package/source/components/card/passport.json +1 -1
  16. package/source/components/checkbox/passport.json +2 -2
  17. package/source/components/checkbox/passport.manual.json +1 -1
  18. package/source/components/checkbox/react/Checkbox.tsx +14 -0
  19. package/source/components/combobox/passport.json +3 -2
  20. package/source/components/combobox/passport.manual.json +1 -1
  21. package/source/components/combobox/react/MultiSelect.tsx +13 -0
  22. package/source/components/combobox/react/Select.tsx +13 -0
  23. package/source/components/combobox/react/surface.ts +70 -0
  24. package/source/components/data-grid/passport.json +6 -6
  25. package/source/components/data-grid/react/DataGrid.tsx +353 -351
  26. package/source/components/date-picker/passport.json +3 -2
  27. package/source/components/date-picker/passport.manual.json +1 -1
  28. package/source/components/date-picker/react/DatePicker.tsx +16 -2
  29. package/source/components/date-picker/react/DateRangePicker.tsx +16 -2
  30. package/source/components/date-picker/react/surface.ts +68 -0
  31. package/source/components/dialog/passport.json +1 -1
  32. package/source/components/file-uploader/passport.json +1 -1
  33. package/source/components/input/passport.json +2 -2
  34. package/source/components/input/passport.manual.json +1 -1
  35. package/source/components/input/react/Input.tsx +21 -0
  36. package/source/components/menu/passport.json +1 -1
  37. package/source/components/modal/passport.json +1 -1
  38. package/source/components/number-input/passport.json +2 -2
  39. package/source/components/number-input/passport.manual.json +1 -1
  40. package/source/components/number-input/react/NumberInput.tsx +30 -0
  41. package/source/components/popover/passport.json +1 -1
  42. package/source/components/progress/passport.json +1 -1
  43. package/source/components/radio-group/passport.json +2 -2
  44. package/source/components/radio-group/passport.manual.json +1 -1
  45. package/source/components/radio-group/react/RadioGroup.tsx +33 -0
  46. package/source/components/shared/core/agent/field-executors.ts +173 -137
  47. package/source/components/shared/core/agent/index.ts +21 -0
  48. package/source/components/shared/core/agent/surface.ts +437 -0
  49. package/source/components/shared/core/agent/webmcp.ts +332 -328
  50. package/source/components/shared/core/agent/write.ts +62 -58
  51. package/source/components/shared/index.ts +7 -0
  52. package/source/components/shared/react/AgentSurface.tsx +145 -0
  53. package/source/components/shared/react/agentSurfaceContext.ts +92 -0
  54. package/source/components/shared/react/useFieldAgent.ts +62 -88
  55. package/source/components/shared/version.json +4 -4
  56. package/source/components/shared/version.ts +6 -6
  57. package/source/components/skeleton/passport.json +1 -1
  58. package/source/components/spinner/passport.json +1 -1
  59. package/source/components/switch/passport.json +2 -2
  60. package/source/components/switch/passport.manual.json +1 -1
  61. package/source/components/switch/react/Switch.tsx +16 -0
  62. package/source/components/tabs/passport.json +1 -1
  63. package/source/components/textarea/passport.json +2 -2
  64. package/source/components/textarea/passport.manual.json +1 -1
  65. package/source/components/textarea/react/Textarea.tsx +16 -0
  66. package/source/components/toaster/passport.json +1 -1
  67. package/source/components/tooltip/passport.json +1 -1
  68. package/tools/doctor/baseline.cjs +228 -0
  69. package/tools/doctor/contract.cjs +252 -0
  70. package/tools/doctor/format.cjs +160 -0
  71. package/tools/doctor/index.cjs +246 -0
  72. package/tools/doctor/usage.cjs +95 -0
  73. package/tools/jsx-tags.cjs +120 -0
  74. package/tools/mcp/server.cjs +60 -41
  75. package/tools/passport/extract.cjs +22 -40
  76. package/tools/passport/hash.cjs +56 -0
  77. package/tools/passport/index.cjs +4 -2
  78. package/tools/passport/typescript.cjs +220 -0
  79. package/tools/prompt.cjs +205 -0
  80. package/tools/ui.cjs +67 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grampro/kit",
3
- "version": "2.7.1",
3
+ "version": "2.7.3",
4
4
  "description": "GramproKit — an agent-native UI runtime for React. Copy-in components you own, each publishing a contract that software can read.",
5
5
  "type": "module",
6
6
  "files": [
@@ -10,7 +10,7 @@
10
10
  ]
11
11
  },
12
12
  "source": {
13
- "libraryVersion": "2.7.1",
13
+ "libraryVersion": "2.7.3",
14
14
  "files": [
15
15
  "core/index.ts",
16
16
  "core/open.ts",
@@ -8,7 +8,7 @@
8
8
  ]
9
9
  },
10
10
  "source": {
11
- "libraryVersion": "2.7.1",
11
+ "libraryVersion": "2.7.3",
12
12
  "files": [
13
13
  "core/index.ts",
14
14
  "core/live.ts",
@@ -9,7 +9,7 @@
9
9
  ]
10
10
  },
11
11
  "source": {
12
- "libraryVersion": "2.7.1",
12
+ "libraryVersion": "2.7.3",
13
13
  "files": [
14
14
  "core/identity.ts",
15
15
  "core/index.ts",
@@ -9,7 +9,7 @@
9
9
  ]
10
10
  },
11
11
  "source": {
12
- "libraryVersion": "2.7.1",
12
+ "libraryVersion": "2.7.3",
13
13
  "files": [
14
14
  "core/count.ts",
15
15
  "core/index.ts",
@@ -8,7 +8,7 @@
8
8
  ]
9
9
  },
10
10
  "source": {
11
- "libraryVersion": "2.7.1",
11
+ "libraryVersion": "2.7.3",
12
12
  "files": [
13
13
  "core/index.ts",
14
14
  "core/trail.ts",
@@ -8,7 +8,7 @@
8
8
  ]
9
9
  },
10
10
  "source": {
11
- "libraryVersion": "2.7.1",
11
+ "libraryVersion": "2.7.3",
12
12
  "files": [
13
13
  "core/index.ts",
14
14
  "core/state.ts",
@@ -12,7 +12,7 @@
12
12
  ]
13
13
  },
14
14
  "source": {
15
- "libraryVersion": "2.7.1",
15
+ "libraryVersion": "2.7.3",
16
16
  "files": [
17
17
  "core/index.ts",
18
18
  "core/trend.ts",
@@ -10,7 +10,7 @@
10
10
  ]
11
11
  },
12
12
  "source": {
13
- "libraryVersion": "2.7.1",
13
+ "libraryVersion": "2.7.3",
14
14
  "files": [
15
15
  "core/agent.ts",
16
16
  "core/group.ts",
@@ -23,7 +23,7 @@
23
23
  "react/locale.ts",
24
24
  "react/props.ts"
25
25
  ],
26
- "sourceHash": "sha256:864a782462120954cea168efe6df111474541556f8518107677c1098cceaa035"
26
+ "sourceHash": "sha256:3bb3c0d76ef4b8d42f6b3bc0a3cdd203a90a1662175ec62ae40eba49ce7ad423"
27
27
  },
28
28
  "purpose": "A single native checkbox, and CheckboxGroup for several that share a name, with mixed state, a select-all and group-level validation.",
29
29
  "props": [
@@ -5,7 +5,7 @@
5
5
  "intentDomains": [
6
6
  "ActionIntent"
7
7
  ],
8
- "$operationsNote": "Mirrors shared/core/agent/field.ts, which is what the runtime dispatches on. source/components/shared/core/agent/__tests__/field-passport.test.ts fails if the two drift. No `apiMethod`: a field is written through its ref — the element for most of these, a handle for Combobox and DatePicker — and that is a normal case, not a gap.",
8
+ "$operationsNote": "Mirrors shared/core/agent/field.ts, which is what the runtime dispatches on. source/components/shared/core/agent/__tests__/field-passport.test.ts fails if the two drift. No `apiMethod`: a field is written through its ref — the element for most of these, a handle for Combobox and DatePicker — and that is a normal case, not a gap. Inside an <AgentSurface> the component registers itself with these operations; NumberInput and RadioGroup are then written through their own commit path rather than the element.",
9
9
  "operations": {
10
10
  "setValue": {
11
11
  "summary": "Write a value into the field, as though a person had entered it.",
@@ -14,6 +14,7 @@ import {
14
14
  } from "react";
15
15
  import { useControllableState } from "../../shared/react/useControllableState";
16
16
  import { describeField } from "../../shared/core/field";
17
+ import { labelText, useAgentSurfaceField } from "../../shared/react/agentSurfaceContext";
17
18
  import type { CheckboxSize, CheckedState } from "../core/types";
18
19
  import { CheckboxGroupContext } from "./context";
19
20
  import { cx, type CheckboxSlot } from "./props";
@@ -107,6 +108,19 @@ export function Checkbox(props: CheckboxProps) {
107
108
  onCheckedChange?.(next);
108
109
  };
109
110
 
111
+ // Inside an <AgentSurface>, offered to an agent as a yes/no it can set.
112
+ useAgentSurfaceField(() => ({
113
+ contract: {
114
+ component: "Checkbox",
115
+ kind: "boolean",
116
+ label: labelText(label, inputProps["aria-label"], name, value),
117
+ disabled: disabled || group?.disabled,
118
+ required,
119
+ operations: ["setValue", "clear", "focus"],
120
+ },
121
+ target: () => inputRef.current,
122
+ }));
123
+
110
124
  const invalid = Boolean(error) || (group?.invalid ?? false);
111
125
  const describedBy = describeField(id, { extra: describedByProp, description, error });
112
126
 
@@ -9,7 +9,7 @@
9
9
  ]
10
10
  },
11
11
  "source": {
12
- "libraryVersion": "2.7.1",
12
+ "libraryVersion": "2.7.3",
13
13
  "files": [
14
14
  "core/agent.ts",
15
15
  "core/filter.ts",
@@ -24,9 +24,10 @@
24
24
  "react/icons.tsx",
25
25
  "react/locale.ts",
26
26
  "react/props.ts",
27
+ "react/surface.ts",
27
28
  "react/useCombobox.ts"
28
29
  ],
29
- "sourceHash": "sha256:5243c2cc6863f8c2dcd248c2fd46417390fec66a8d5b0d405177a372e9c0566f"
30
+ "sourceHash": "sha256:c8001ea7c65beeed1b50d9f35cb0fcc447d01cea88128dda3d8b3584bd542496"
30
31
  },
31
32
  "purpose": "Select and MultiSelect: a searchable combobox for one or many values, with options in the browser's top layer, optional virtualisation and create-on-type.",
32
33
  "props": [
@@ -7,7 +7,7 @@
7
7
  "Recommendation",
8
8
  "Classification"
9
9
  ],
10
- "$operationsNote": "Mirrors shared/core/agent/field.ts, which is what the runtime dispatches on. source/components/shared/core/agent/__tests__/field-passport.test.ts fails if the two drift. No `apiMethod`: a field is written through its ref — the element for most of these, a handle for Combobox and DatePicker — and that is a normal case, not a gap.",
10
+ "$operationsNote": "Mirrors shared/core/agent/field.ts, which is what the runtime dispatches on. source/components/shared/core/agent/__tests__/field-passport.test.ts fails if the two drift. No `apiMethod`: a field is written through its ref — the element for most of these, a handle for Combobox and DatePicker — and that is a normal case, not a gap. Inside an <AgentSurface> the component registers itself with these operations; NumberInput and RadioGroup are then written through their own commit path rather than the element.",
11
11
  "operations": {
12
12
  "setValue": {
13
13
  "summary": "Write a value into the field, as though a person had entered it.",
@@ -8,6 +8,7 @@ import { Listbox } from "./Listbox";
8
8
  import { defaultComboboxText } from "./locale";
9
9
  import { ComboboxPopover } from "./Popover";
10
10
  import { cx, type ComboboxHandle, type ComboboxSharedProps } from "./props";
11
+ import { useComboboxSurface } from "./surface";
11
12
  import { useCombobox } from "./useCombobox";
12
13
 
13
14
  export interface MultiSelectProps<V extends OptionValue = string> extends ComboboxSharedProps<V> {
@@ -89,6 +90,18 @@ export function MultiSelect<V extends OptionValue = string>(props: MultiSelectPr
89
90
  const visibleTags = hidden > 0 ? selectedOptions.slice(0, maxVisibleTags) : selectedOptions;
90
91
 
91
92
  useImperativeHandle(ref, () => combobox.handle, [combobox.handle]);
93
+ useComboboxSurface({
94
+ component: "MultiSelect",
95
+ label,
96
+ ariaLabel: props["aria-label"],
97
+ name,
98
+ required,
99
+ disabled,
100
+ options,
101
+ mode: props.mode,
102
+ max: max,
103
+ handle: combobox.handle,
104
+ });
92
105
 
93
106
  const selectableVisible = combobox.entries.filter(
94
107
  (entry) => !entry.option.disabled && !combobox.isSelected(entry.option.value),
@@ -8,6 +8,7 @@ import { ChevronIcon, XIcon } from "./icons";
8
8
  import { Listbox } from "./Listbox";
9
9
  import { ComboboxPopover } from "./Popover";
10
10
  import { cx, type ComboboxHandle, type ComboboxSharedProps } from "./props";
11
+ import { useComboboxSurface } from "./surface";
11
12
  import { useCombobox } from "./useCombobox";
12
13
 
13
14
  export interface SelectProps<V extends OptionValue = string> extends ComboboxSharedProps<V> {
@@ -83,6 +84,18 @@ export function Select<V extends OptionValue = string>(props: SelectProps<V>) {
83
84
  const selected = combobox.selectedOptions[0];
84
85
 
85
86
  useImperativeHandle(ref, () => combobox.handle, [combobox.handle]);
87
+ useComboboxSurface({
88
+ component: "Select",
89
+ label,
90
+ ariaLabel: props["aria-label"],
91
+ name,
92
+ required,
93
+ disabled,
94
+ options,
95
+ mode: props.mode,
96
+ max: undefined,
97
+ handle: combobox.handle,
98
+ });
86
99
 
87
100
  return (
88
101
  <div
@@ -0,0 +1,70 @@
1
+ "use client";
2
+
3
+ import { labelText, useAgentSurfaceField } from "../../shared/react/agentSurfaceContext";
4
+ import type { ComboboxOption, OptionValue } from "../core/types";
5
+ import type { ComboboxHandle } from "./props";
6
+
7
+ interface ComboboxSurfaceParams<V extends OptionValue> {
8
+ component: "Select" | "MultiSelect";
9
+ label: unknown;
10
+ ariaLabel: unknown;
11
+ name?: string;
12
+ required: boolean;
13
+ disabled: boolean;
14
+ options: readonly ComboboxOption<V>[];
15
+ mode?: "client" | "server";
16
+ max?: number;
17
+ handle: ComboboxHandle<V>;
18
+ }
19
+
20
+ /**
21
+ * Inside an <AgentSurface>, offer a Select or MultiSelect with its options.
22
+ *
23
+ * An agent speaks in strings and an option's value may be a number, so values
24
+ * are offered as text and mapped back to the option they came from before the
25
+ * write. In server mode the options are only the current results, so none are
26
+ * enumerated: the set is the server's, not the component's.
27
+ */
28
+ export function useComboboxSurface<V extends OptionValue>(params: ComboboxSurfaceParams<V>): void {
29
+ useAgentSurfaceField(() => {
30
+ const { component, options, handle } = params;
31
+ const multiple = component === "MultiSelect";
32
+ const enumerate = params.mode !== "server";
33
+ const back = (value: unknown): V => {
34
+ const text = String(value);
35
+ return (options.find((option) => String(option.value) === text)?.value ?? text) as V;
36
+ };
37
+ return {
38
+ contract: {
39
+ component,
40
+ kind: multiple ? "multiChoice" : "choice",
41
+ label: labelText(params.label, params.ariaLabel, params.name),
42
+ disabled: params.disabled,
43
+ required: params.required,
44
+ ...(enumerate
45
+ ? {
46
+ options: options.map((option) => ({
47
+ value: String(option.value),
48
+ label: option.label,
49
+ ...(option.disabled ? { disabled: true } : {}),
50
+ })),
51
+ }
52
+ : {}),
53
+ ...(multiple && params.max !== undefined ? { maxSelected: params.max } : {}),
54
+ operations: ["setValue", "clear", "focus", "open", "close"],
55
+ },
56
+ target: () => ({
57
+ setValue: (next) =>
58
+ handle.setValue(
59
+ (next == null ? null : Array.isArray(next) ? next.map(back) : back(next)) as Parameters<
60
+ ComboboxHandle<V>["setValue"]
61
+ >[0],
62
+ ),
63
+ clear: handle.clear,
64
+ focus: handle.focus,
65
+ open: handle.open,
66
+ close: handle.close,
67
+ }),
68
+ };
69
+ });
70
+ }
@@ -14,7 +14,7 @@
14
14
  ]
15
15
  },
16
16
  "source": {
17
- "libraryVersion": "2.7.1",
17
+ "libraryVersion": "2.7.3",
18
18
  "files": [
19
19
  "agent/coerce.ts",
20
20
  "agent/contract.ts",
@@ -64,7 +64,7 @@
64
64
  "react/keyboard.ts",
65
65
  "react/locale.ts"
66
66
  ],
67
- "sourceHash": "sha256:66dfc75f60791c6e4397d3438ec3ad19ce47f9e5ea51677024200d1f75bd5d44"
67
+ "sourceHash": "sha256:1047a3723ee462533fa5b82741d89309723cecedc71ea4b1339176a50ced0545"
68
68
  },
69
69
  "purpose": "Display and operate on tabular data. Virtualized; holds its own sort, filter, search, selection, column and pagination state in an external store exposed through GridApi.",
70
70
  "props": [
@@ -93,7 +93,7 @@
93
93
  "required": false,
94
94
  "default": false,
95
95
  "origin": "derived",
96
- "description": "Render a natural-language box above the grid.\r\n\r\nNeeds a `<GramproAIProvider>` above it supplying an adapter; without one\r\nthis renders nothing and the grid is unchanged. No model is bundled or\r\ndownloaded — the application brings its own.",
96
+ "description": "Render a natural-language box above the grid.\n\nNeeds a `<GramproAIProvider>` above it supplying an adapter; without one\nthis renders nothing and the grid is unchanged. No model is bundled or\ndownloaded — the application brings its own.",
97
97
  "descriptionOrigin": "jsdoc"
98
98
  },
99
99
  {
@@ -152,7 +152,7 @@
152
152
  "typeText": "ReactNode",
153
153
  "required": false,
154
154
  "origin": "derived",
155
- "description": "Shown in place of rows when there are none. Worth distinguishing \"nothing\r\nhere yet\" from \"nothing matched your filters\", which the default does not.",
155
+ "description": "Shown in place of rows when there are none. Worth distinguishing \"nothing\nhere yet\" from \"nothing matched your filters\", which the default does not.",
156
156
  "descriptionOrigin": "jsdoc"
157
157
  },
158
158
  {
@@ -306,7 +306,7 @@
306
306
  "required": false,
307
307
  "default": false,
308
308
  "origin": "derived",
309
- "description": "Show the loading treatment over the grid. The existing rows stay in place\r\nunderneath, so a refresh does not empty the screen.",
309
+ "description": "Show the loading treatment over the grid. The existing rows stay in place\nunderneath, so a refresh does not empty the screen.",
310
310
  "descriptionOrigin": "jsdoc"
311
311
  },
312
312
  {
@@ -483,7 +483,7 @@
483
483
  "required": false,
484
484
  "default": true,
485
485
  "origin": "derived",
486
- "description": "The toolbar above the grid. `true` for all of it, `false` for none, or an\r\nobject to choose parts — `{ search: true, export: false }` — and to put\r\nyour own controls at its `start` or `end`.",
486
+ "description": "The toolbar above the grid. `true` for all of it, `false` for none, or an\nobject to choose parts — `{ search: true, export: false }` — and to put\nyour own controls at its `start` or `end`.",
487
487
  "descriptionOrigin": "jsdoc"
488
488
  }
489
489
  ],