@seed-ship/mcp-ui-solid 6.23.0 → 6.25.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.
Files changed (172) hide show
  1. package/CHANGELOG.md +167 -0
  2. package/README.md +154 -2
  3. package/dist/components/ActionGroupRenderer.cjs +6 -6
  4. package/dist/components/ActionGroupRenderer.cjs.map +1 -1
  5. package/dist/components/ActionGroupRenderer.js +6 -6
  6. package/dist/components/ActionGroupRenderer.js.map +1 -1
  7. package/dist/components/AutocompleteDropdown.cjs +6 -6
  8. package/dist/components/AutocompleteDropdown.cjs.map +1 -1
  9. package/dist/components/AutocompleteDropdown.js +6 -6
  10. package/dist/components/AutocompleteDropdown.js.map +1 -1
  11. package/dist/components/AutocompleteFormField.cjs +6 -5
  12. package/dist/components/AutocompleteFormField.cjs.map +1 -1
  13. package/dist/components/AutocompleteFormField.d.ts.map +1 -1
  14. package/dist/components/AutocompleteFormField.js +6 -5
  15. package/dist/components/AutocompleteFormField.js.map +1 -1
  16. package/dist/components/ChartJSRenderer.cjs +406 -70
  17. package/dist/components/ChartJSRenderer.cjs.map +1 -1
  18. package/dist/components/ChartJSRenderer.d.ts.map +1 -1
  19. package/dist/components/ChartJSRenderer.js +407 -71
  20. package/dist/components/ChartJSRenderer.js.map +1 -1
  21. package/dist/components/ChatPrompt.cjs +5 -5
  22. package/dist/components/ChatPrompt.cjs.map +1 -1
  23. package/dist/components/ChatPrompt.js +5 -5
  24. package/dist/components/ChatPrompt.js.map +1 -1
  25. package/dist/components/ComponentToolbar.cjs +5 -5
  26. package/dist/components/ComponentToolbar.cjs.map +1 -1
  27. package/dist/components/ComponentToolbar.js +5 -5
  28. package/dist/components/ComponentToolbar.js.map +1 -1
  29. package/dist/components/DegradedFallback.cjs +35 -3
  30. package/dist/components/DegradedFallback.cjs.map +1 -1
  31. package/dist/components/DegradedFallback.d.ts +7 -0
  32. package/dist/components/DegradedFallback.d.ts.map +1 -1
  33. package/dist/components/DegradedFallback.js +35 -3
  34. package/dist/components/DegradedFallback.js.map +1 -1
  35. package/dist/components/ExpandableWrapper.cjs +10 -7
  36. package/dist/components/ExpandableWrapper.cjs.map +1 -1
  37. package/dist/components/ExpandableWrapper.d.ts.map +1 -1
  38. package/dist/components/ExpandableWrapper.js +10 -7
  39. package/dist/components/ExpandableWrapper.js.map +1 -1
  40. package/dist/components/FormFieldRenderer.cjs +13 -12
  41. package/dist/components/FormFieldRenderer.cjs.map +1 -1
  42. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  43. package/dist/components/FormFieldRenderer.js +13 -12
  44. package/dist/components/FormFieldRenderer.js.map +1 -1
  45. package/dist/components/FormRenderer.cjs +1 -1
  46. package/dist/components/FormRenderer.cjs.map +1 -1
  47. package/dist/components/FormRenderer.js +1 -1
  48. package/dist/components/FormRenderer.js.map +1 -1
  49. package/dist/components/GenerativeUIErrorBoundary.cjs +1 -1
  50. package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
  51. package/dist/components/GenerativeUIErrorBoundary.js +1 -1
  52. package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
  53. package/dist/components/GhostText.cjs +2 -2
  54. package/dist/components/GhostText.cjs.map +1 -1
  55. package/dist/components/GhostText.js +2 -2
  56. package/dist/components/GhostText.js.map +1 -1
  57. package/dist/components/GraphRenderer.cjs +100 -29
  58. package/dist/components/GraphRenderer.cjs.map +1 -1
  59. package/dist/components/GraphRenderer.d.ts +1 -1
  60. package/dist/components/GraphRenderer.d.ts.map +1 -1
  61. package/dist/components/GraphRenderer.js +100 -29
  62. package/dist/components/GraphRenderer.js.map +1 -1
  63. package/dist/components/MissingValue.cjs +43 -0
  64. package/dist/components/MissingValue.cjs.map +1 -0
  65. package/dist/components/MissingValue.d.ts +27 -0
  66. package/dist/components/MissingValue.d.ts.map +1 -0
  67. package/dist/components/MissingValue.js +43 -0
  68. package/dist/components/MissingValue.js.map +1 -0
  69. package/dist/components/ModalRenderer.cjs +39 -31
  70. package/dist/components/ModalRenderer.cjs.map +1 -1
  71. package/dist/components/ModalRenderer.d.ts.map +1 -1
  72. package/dist/components/ModalRenderer.js +40 -32
  73. package/dist/components/ModalRenderer.js.map +1 -1
  74. package/dist/components/PortalDropdownMenu.cjs +6 -3
  75. package/dist/components/PortalDropdownMenu.cjs.map +1 -1
  76. package/dist/components/PortalDropdownMenu.d.ts.map +1 -1
  77. package/dist/components/PortalDropdownMenu.js +7 -4
  78. package/dist/components/PortalDropdownMenu.js.map +1 -1
  79. package/dist/components/ScratchpadPanel.cjs +38 -44
  80. package/dist/components/ScratchpadPanel.cjs.map +1 -1
  81. package/dist/components/ScratchpadPanel.d.ts.map +1 -1
  82. package/dist/components/ScratchpadPanel.js +38 -44
  83. package/dist/components/ScratchpadPanel.js.map +1 -1
  84. package/dist/components/UIResourceRenderer.cjs +255 -217
  85. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  86. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  87. package/dist/components/UIResourceRenderer.js +255 -217
  88. package/dist/components/UIResourceRenderer.js.map +1 -1
  89. package/dist/components/chart-data-table.cjs +30 -5
  90. package/dist/components/chart-data-table.cjs.map +1 -1
  91. package/dist/components/chart-data-table.d.ts +18 -1
  92. package/dist/components/chart-data-table.d.ts.map +1 -1
  93. package/dist/components/chart-data-table.js +30 -5
  94. package/dist/components/chart-data-table.js.map +1 -1
  95. package/dist/components/chart-missing-plugin.cjs +194 -0
  96. package/dist/components/chart-missing-plugin.cjs.map +1 -0
  97. package/dist/components/chart-missing-plugin.d.ts +129 -0
  98. package/dist/components/chart-missing-plugin.d.ts.map +1 -0
  99. package/dist/components/chart-missing-plugin.js +194 -0
  100. package/dist/components/chart-missing-plugin.js.map +1 -0
  101. package/dist/context/MCPUIStringsContext.cjs +12 -1
  102. package/dist/context/MCPUIStringsContext.cjs.map +1 -1
  103. package/dist/context/MCPUIStringsContext.d.ts +62 -0
  104. package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
  105. package/dist/context/MCPUIStringsContext.js +12 -1
  106. package/dist/context/MCPUIStringsContext.js.map +1 -1
  107. package/dist/services/component-registry.cjs +9 -2
  108. package/dist/services/component-registry.cjs.map +1 -1
  109. package/dist/services/component-registry.d.ts.map +1 -1
  110. package/dist/services/component-registry.js +9 -2
  111. package/dist/services/component-registry.js.map +1 -1
  112. package/dist/services/validation.cjs +31 -8
  113. package/dist/services/validation.cjs.map +1 -1
  114. package/dist/services/validation.d.ts.map +1 -1
  115. package/dist/services/validation.js +31 -8
  116. package/dist/services/validation.js.map +1 -1
  117. package/dist/types/index.d.ts +14 -2
  118. package/dist/types/index.d.ts.map +1 -1
  119. package/dist/utils/degraded-projections.cjs +19 -3
  120. package/dist/utils/degraded-projections.cjs.map +1 -1
  121. package/dist/utils/degraded-projections.d.ts +22 -2
  122. package/dist/utils/degraded-projections.d.ts.map +1 -1
  123. package/dist/utils/degraded-projections.js +19 -3
  124. package/dist/utils/degraded-projections.js.map +1 -1
  125. package/dist/utils/math-markdown.cjs +1 -1
  126. package/dist/utils/math-markdown.cjs.map +1 -1
  127. package/dist/utils/math-markdown.js +1 -1
  128. package/dist/utils/math-markdown.js.map +1 -1
  129. package/dist/utils/missing-value.cjs +60 -0
  130. package/dist/utils/missing-value.cjs.map +1 -0
  131. package/dist/utils/missing-value.d.ts +79 -0
  132. package/dist/utils/missing-value.d.ts.map +1 -0
  133. package/dist/utils/missing-value.js +60 -0
  134. package/dist/utils/missing-value.js.map +1 -0
  135. package/dist/utils/theme.cjs +91 -0
  136. package/dist/utils/theme.cjs.map +1 -0
  137. package/dist/utils/theme.d.ts +11 -0
  138. package/dist/utils/theme.d.ts.map +1 -0
  139. package/dist/utils/theme.js +91 -0
  140. package/dist/utils/theme.js.map +1 -0
  141. package/docs/SECURITY-DEPENDENCIES.md +81 -0
  142. package/docs/THEMING.md +205 -0
  143. package/package.json +7 -5
  144. package/src/components/ActionGroupRenderer.tsx +6 -6
  145. package/src/components/AutocompleteDropdown.tsx +17 -17
  146. package/src/components/AutocompleteFormField.tsx +10 -9
  147. package/src/components/ChartJSRenderer.tsx +609 -212
  148. package/src/components/ChatPrompt.tsx +16 -16
  149. package/src/components/ComponentToolbar.tsx +5 -5
  150. package/src/components/DegradedFallback.tsx +33 -11
  151. package/src/components/ExpandableWrapper.tsx +15 -11
  152. package/src/components/FormFieldRenderer.tsx +52 -51
  153. package/src/components/FormRenderer.tsx +12 -12
  154. package/src/components/GenerativeUIErrorBoundary.tsx +6 -6
  155. package/src/components/GhostText.tsx +7 -7
  156. package/src/components/GraphRenderer.tsx +83 -67
  157. package/src/components/MissingValue.tsx +61 -0
  158. package/src/components/ModalRenderer.tsx +11 -5
  159. package/src/components/PortalDropdownMenu.tsx +6 -2
  160. package/src/components/ScratchpadPanel.tsx +144 -141
  161. package/src/components/UIResourceRenderer.tsx +143 -110
  162. package/src/components/chart-data-table.ts +50 -6
  163. package/src/components/chart-missing-plugin.ts +336 -0
  164. package/src/context/MCPUIStringsContext.tsx +76 -0
  165. package/src/services/component-registry.ts +10 -2
  166. package/src/services/validation.ts +44 -9
  167. package/src/styles/autocomplete.css +53 -53
  168. package/src/types/index.ts +13 -1
  169. package/src/utils/degraded-projections.ts +44 -4
  170. package/src/utils/math-markdown.ts +1 -1
  171. package/src/utils/missing-value.ts +127 -0
  172. package/src/utils/theme.ts +101 -0
@@ -1 +1 @@
1
- {"version":3,"file":"FormRenderer.js","sources":["../../src/components/FormRenderer.tsx"],"sourcesContent":["/**\n * FormRenderer - Main form component\n * Sprint 1: Form Foundation\n * Sprint 2: Conditional field visibility (showWhen)\n * Sprint 4: Form state persistence\n */\n\nimport { Component, createSignal, For, Show, onMount, createEffect, onCleanup } from 'solid-js'\nimport { FormFieldRenderer } from './FormFieldRenderer'\nimport type { UIComponent, FormComponentParams, FormFieldParams } from '../types'\nimport { useAction } from '../hooks/useAction'\nimport { validateFormData } from '../services/validation'\nimport { evaluateCondition } from '../hooks/useConditionalField'\nimport { useFormPersistence } from '../hooks/useFormPersistence'\nimport { useTelemetry } from '../context/MCPUITelemetryContext'\nimport { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nexport interface FormRendererProps {\n component: UIComponent\n onSubmit?: (data: Record<string, any>) => void\n onError?: (errors: Record<string, string>) => void\n}\n\n/**\n * Get default value for a field type\n */\nfunction getFieldDefault(type: FormFieldParams['type']): any {\n switch (type) {\n case 'checkbox':\n return false\n case 'number':\n return undefined\n case 'select':\n case 'radio':\n return ''\n default:\n return ''\n }\n}\n\nexport const FormRenderer: Component<FormRendererProps> = (props) => {\n const strings = useMCPUIStrings()\n /**\n * The end-user validation wording, read from the chrome strings and\n * injected into the pure validators (which cannot reach the context).\n */\n const validationMessages = () => ({\n required: strings.fieldRequired,\n mustBeChecked: strings.fieldMustBeChecked,\n minLength: strings.fieldMinLength,\n maxLength: strings.fieldMaxLength,\n invalidPattern: strings.fieldInvalidPattern,\n invalidEmail: strings.fieldInvalidEmail,\n invalidNumber: strings.fieldInvalidNumber,\n minValue: strings.fieldMinValue,\n maxValue: strings.fieldMaxValue,\n minDate: strings.fieldMinDate,\n maxDate: strings.fieldMaxDate,\n invalidOption: strings.fieldInvalidOption,\n invalidFormat: strings.fieldInvalidFormat,\n })\n const params = () => props.component.params as FormComponentParams\n const [formData, setFormData] = createSignal<Record<string, any>>({})\n const [errors, setErrors] = createSignal<Record<string, string>>({})\n const [isSubmitting, setIsSubmitting] = createSignal(false)\n const { execute } = useAction()\n const telemetry = useTelemetry()\n\n // Form persistence (Sprint 4)\n let clearPersisted: (() => void) | undefined\n\n /**\n * Get fields that are currently visible based on showWhen conditions\n */\n const getVisibleFields = (): FormFieldParams[] => {\n return params().fields.filter((field) => {\n if (!field.showWhen) return true\n return evaluateCondition(field.showWhen, formData())\n })\n }\n\n // Auto-submit countdown state (v4.2.0)\n const [countdown, setCountdown] = createSignal<number | null>(null)\n let countdownTimer: ReturnType<typeof setInterval> | null = null\n const [userInteracted, setUserInteracted] = createSignal(false)\n\n const cancelCountdown = () => {\n if (countdownTimer) {\n clearInterval(countdownTimer)\n countdownTimer = null\n }\n setCountdown(null)\n }\n\n const handleUserInteraction = () => {\n if (!userInteracted()) {\n setUserInteracted(true)\n cancelCountdown()\n }\n }\n\n onCleanup(() => cancelCountdown())\n\n /**\n * Check if all required fields have prefill values\n */\n const allRequiredPrefilled = (): boolean => {\n return params().fields\n .filter((f) => f.required)\n .every((f) => f.prefill != null)\n }\n\n // Initialize form data with default values, applying prefill (v4.2.0)\n const initializeForm = (clearStorage = false) => {\n const initial: Record<string, any> = {}\n for (const field of params().fields) {\n // prefill takes priority over defaultValue\n initial[field.name] = field.prefill ?? field.defaultValue ?? getFieldDefault(field.type)\n }\n setFormData(initial)\n setErrors({})\n\n // Clear persisted data if requested\n if (clearStorage && clearPersisted) {\n clearPersisted()\n }\n }\n\n // Initialize on mount\n onMount(() => {\n initializeForm()\n })\n\n // Setup persistence if persistKey is provided (Sprint 4)\n createEffect(() => {\n const persistKey = params().persistKey\n if (persistKey) {\n const persistence = useFormPersistence({\n persistKey,\n formData,\n setFormData,\n excludeFields: params().excludeFromPersistence,\n expiresIn: params().persistExpiresIn,\n })\n clearPersisted = persistence.clearPersisted\n }\n })\n\n // Auto-submit countdown (v4.2.0)\n createEffect(() => {\n const delay = params().autoSubmitDelay\n if (!delay || !allRequiredPrefilled() || userInteracted()) return\n\n let remaining = Math.ceil(delay / 1000)\n setCountdown(remaining)\n\n countdownTimer = setInterval(() => {\n remaining--\n if (remaining <= 0) {\n cancelCountdown()\n // Trigger submit programmatically\n const form = document.querySelector(`#form-${props.component.id}`) as HTMLFormElement | null\n if (form) form.requestSubmit()\n } else {\n setCountdown(remaining)\n }\n }, 1000)\n })\n\n const handleFieldChange = (name: string, value: any) => {\n handleUserInteraction()\n setFormData((prev) => ({ ...prev, [name]: value }))\n // Clear error on change\n if (errors()[name]) {\n setErrors((prev) => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { [name]: _removed, ...rest } = prev\n return rest\n })\n }\n }\n\n const handleSubmit = async (e: Event) => {\n e.preventDefault()\n setIsSubmitting(true)\n setErrors({})\n\n // Get only visible fields for validation and submission\n const visibleFields = getVisibleFields()\n const visibleFieldNames = new Set(visibleFields.map((f) => f.name))\n\n // Filter form data to only include visible fields\n const visibleFormData: Record<string, any> = {}\n for (const [key, value] of Object.entries(formData())) {\n if (visibleFieldNames.has(key)) {\n visibleFormData[key] = value\n }\n }\n\n // Validate only visible fields\n const validationResult = validateFormData(visibleFormData, visibleFields, validationMessages())\n if (!validationResult.valid) {\n setErrors(validationResult.errors)\n setIsSubmitting(false)\n props.onError?.(validationResult.errors)\n return\n }\n\n // Submit via tool call if specified\n if (params().submitAction?.toolName) {\n try {\n const result = await execute(params().submitAction!.toolName, {\n ...params().submitAction!.params,\n formData: visibleFormData,\n })\n if (!result.success) {\n setErrors({ _form: result.error || strings.formSubmissionFailed })\n setIsSubmitting(false)\n props.onError?.({ _form: result.error || strings.formSubmissionFailed })\n return\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : strings.formSubmissionFailed\n setErrors({ _form: errorMessage })\n setIsSubmitting(false)\n props.onError?.({ _form: errorMessage })\n return\n }\n }\n\n // Clear persisted data on successful submit\n if (clearPersisted) {\n clearPersisted()\n }\n\n // Telemetry: action:dispatched on successful submit (B.5 — v5.6.0).\n // Privacy: only the action name (toolName or 'submit'), NO form values.\n if (telemetry) {\n telemetry.dispatch({\n type: 'action:dispatched',\n id: props.component.id,\n componentType: 'form',\n actionName: params().submitAction?.toolName ?? 'submit',\n ts: Date.now(),\n })\n }\n\n props.onSubmit?.(visibleFormData)\n setIsSubmitting(false)\n }\n\n const layoutClass = () => {\n switch (params().layout) {\n case 'horizontal':\n return 'grid grid-cols-2 gap-4'\n case 'inline':\n return 'flex flex-wrap gap-4 items-end'\n default:\n return 'space-y-4'\n }\n }\n\n return (\n <div class=\"w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4\">\n <Show when={params().title}>\n <h3 class=\"text-lg font-semibold text-gray-900 dark:text-white mb-4\">\n {params().title}\n </h3>\n </Show>\n\n <form id={`form-${props.component.id}`} onSubmit={handleSubmit} noValidate>\n {/* Proposal 3: prefill summary */}\n <Show when={params().fields.some((f) => f.prefill != null)}>\n {(() => {\n const prefilled = params().fields.filter((f) => f.prefill != null).length\n const total = params().fields.length\n return (\n <p class=\"text-xs text-gray-500 dark:text-gray-400 mb-3\">\n {formatMCPUIString(\n prefilled === 1 ? strings.formPrefilledOne : strings.formPrefilledMany,\n { count: prefilled, total }\n )}\n </p>\n )\n })()}\n </Show>\n <div class={layoutClass()}>\n <For each={params().fields}>\n {(field) => (\n <FormFieldRenderer\n field={field}\n value={formData()[field.name]}\n error={errors()[field.name]}\n onChange={(value) => handleFieldChange(field.name, value)}\n disabled={isSubmitting() || field.disabled}\n formData={formData}\n />\n )}\n </For>\n </div>\n\n <Show when={errors()._form}>\n <div class=\"mt-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-md\">\n <p class=\"text-sm text-red-600 dark:text-red-400\" role=\"alert\">\n {errors()._form}\n </p>\n </div>\n </Show>\n\n {/* Auto-submit countdown (v4.2.0) */}\n <Show when={countdown() != null}>\n <div class=\"mt-4 flex items-center gap-3 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-md\">\n <span class=\"text-sm text-blue-700 dark:text-blue-300\">\n {formatMCPUIString(strings.formSubmitCountdown, {\n label: params().submitLabel || strings.submit,\n seconds: countdown()!,\n })}\n </span>\n <button\n type=\"button\"\n onClick={() => { cancelCountdown(); setUserInteracted(true) }}\n class=\"text-sm text-blue-600 dark:text-blue-400 underline hover:text-blue-800 dark:hover:text-blue-200\"\n >\n {strings.cancel}\n </button>\n </div>\n </Show>\n\n <div class=\"flex gap-2 pt-4 mt-4 border-t border-gray-200 dark:border-gray-700\">\n <button\n type=\"submit\"\n disabled={isSubmitting()}\n class=\"px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {isSubmitting() ? (\n <span class=\"flex items-center gap-2\">\n <span class=\"animate-spin h-4 w-4 border-2 border-white border-t-transparent rounded-full\" />\n {strings.formSubmitting}\n </span>\n ) : (\n params().submitLabel || strings.submit\n )}\n </button>\n <Show when={params().showReset}>\n <button\n type=\"button\"\n onClick={() => initializeForm(true)}\n disabled={isSubmitting()}\n class=\"px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-md hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {strings.formReset}\n </button>\n </Show>\n </div>\n </form>\n </div>\n )\n}\n"],"names":["getFieldDefault","type","undefined","FormRenderer","props","strings","useMCPUIStrings","validationMessages","required","fieldRequired","mustBeChecked","fieldMustBeChecked","minLength","fieldMinLength","maxLength","fieldMaxLength","invalidPattern","fieldInvalidPattern","invalidEmail","fieldInvalidEmail","invalidNumber","fieldInvalidNumber","minValue","fieldMinValue","maxValue","fieldMaxValue","minDate","fieldMinDate","maxDate","fieldMaxDate","invalidOption","fieldInvalidOption","invalidFormat","fieldInvalidFormat","params","component","formData","setFormData","createSignal","errors","setErrors","isSubmitting","setIsSubmitting","execute","useAction","telemetry","useTelemetry","clearPersisted","getVisibleFields","fields","filter","field","showWhen","evaluateCondition","countdown","setCountdown","countdownTimer","userInteracted","setUserInteracted","cancelCountdown","clearInterval","handleUserInteraction","onCleanup","allRequiredPrefilled","f","every","prefill","initializeForm","clearStorage","initial","name","defaultValue","onMount","createEffect","persistKey","persistence","useFormPersistence","excludeFields","excludeFromPersistence","expiresIn","persistExpiresIn","delay","autoSubmitDelay","remaining","Math","ceil","setInterval","form","document","querySelector","id","requestSubmit","handleFieldChange","value","prev","_removed","rest","handleSubmit","e","preventDefault","visibleFields","visibleFieldNames","Set","map","visibleFormData","key","Object","entries","has","validationResult","validateFormData","valid","onError","submitAction","toolName","result","success","_form","error","formSubmissionFailed","errorMessage","Error","message","dispatch","componentType","actionName","ts","Date","now","onSubmit","layoutClass","layout","_el$","_$getNextElement","_tmpl$5","_el$19","firstChild","_el$20","_co$5","_$getNextMarker","nextSibling","_el$3","_el$13","_el$14","_co$2","_el$4","_el$15","_el$16","_co$3","_el$17","_el$18","_co$4","_el$0","_el$1","_el$11","_el$12","_co$","_$insert","_$createComponent","Show","when","title","children","_el$2","_tmpl$","addEventListener","some","prefilled","length","total","_el$21","_tmpl$6","formatMCPUIString","formPrefilledOne","formPrefilledMany","count","For","each","FormFieldRenderer","onChange","disabled","_el$5","_tmpl$2","_el$6","_el$7","_tmpl$3","_el$8","_el$9","formSubmitCountdown","label","submitLabel","submit","seconds","$$click","cancel","_$runHydrationEvents","_c$","_$memo","_el$22","_tmpl$7","_el$23","_el$24","_el$25","_co$6","formSubmitting","showReset","_el$10","_tmpl$4","formReset","_$effect","_$setProperty","_p$","_v$","_v$2","_v$3","_$setAttribute","t","_$className","a","_$delegateEvents"],"mappings":"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"}
1
+ {"version":3,"file":"FormRenderer.js","sources":["../../src/components/FormRenderer.tsx"],"sourcesContent":["/**\n * FormRenderer - Main form component\n * Sprint 1: Form Foundation\n * Sprint 2: Conditional field visibility (showWhen)\n * Sprint 4: Form state persistence\n */\n\nimport { Component, createSignal, For, Show, onMount, createEffect, onCleanup } from 'solid-js'\nimport { FormFieldRenderer } from './FormFieldRenderer'\nimport type { UIComponent, FormComponentParams, FormFieldParams } from '../types'\nimport { useAction } from '../hooks/useAction'\nimport { validateFormData } from '../services/validation'\nimport { evaluateCondition } from '../hooks/useConditionalField'\nimport { useFormPersistence } from '../hooks/useFormPersistence'\nimport { useTelemetry } from '../context/MCPUITelemetryContext'\nimport { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nexport interface FormRendererProps {\n component: UIComponent\n onSubmit?: (data: Record<string, any>) => void\n onError?: (errors: Record<string, string>) => void\n}\n\n/**\n * Get default value for a field type\n */\nfunction getFieldDefault(type: FormFieldParams['type']): any {\n switch (type) {\n case 'checkbox':\n return false\n case 'number':\n return undefined\n case 'select':\n case 'radio':\n return ''\n default:\n return ''\n }\n}\n\nexport const FormRenderer: Component<FormRendererProps> = (props) => {\n const strings = useMCPUIStrings()\n /**\n * The end-user validation wording, read from the chrome strings and\n * injected into the pure validators (which cannot reach the context).\n */\n const validationMessages = () => ({\n required: strings.fieldRequired,\n mustBeChecked: strings.fieldMustBeChecked,\n minLength: strings.fieldMinLength,\n maxLength: strings.fieldMaxLength,\n invalidPattern: strings.fieldInvalidPattern,\n invalidEmail: strings.fieldInvalidEmail,\n invalidNumber: strings.fieldInvalidNumber,\n minValue: strings.fieldMinValue,\n maxValue: strings.fieldMaxValue,\n minDate: strings.fieldMinDate,\n maxDate: strings.fieldMaxDate,\n invalidOption: strings.fieldInvalidOption,\n invalidFormat: strings.fieldInvalidFormat,\n })\n const params = () => props.component.params as FormComponentParams\n const [formData, setFormData] = createSignal<Record<string, any>>({})\n const [errors, setErrors] = createSignal<Record<string, string>>({})\n const [isSubmitting, setIsSubmitting] = createSignal(false)\n const { execute } = useAction()\n const telemetry = useTelemetry()\n\n // Form persistence (Sprint 4)\n let clearPersisted: (() => void) | undefined\n\n /**\n * Get fields that are currently visible based on showWhen conditions\n */\n const getVisibleFields = (): FormFieldParams[] => {\n return params().fields.filter((field) => {\n if (!field.showWhen) return true\n return evaluateCondition(field.showWhen, formData())\n })\n }\n\n // Auto-submit countdown state (v4.2.0)\n const [countdown, setCountdown] = createSignal<number | null>(null)\n let countdownTimer: ReturnType<typeof setInterval> | null = null\n const [userInteracted, setUserInteracted] = createSignal(false)\n\n const cancelCountdown = () => {\n if (countdownTimer) {\n clearInterval(countdownTimer)\n countdownTimer = null\n }\n setCountdown(null)\n }\n\n const handleUserInteraction = () => {\n if (!userInteracted()) {\n setUserInteracted(true)\n cancelCountdown()\n }\n }\n\n onCleanup(() => cancelCountdown())\n\n /**\n * Check if all required fields have prefill values\n */\n const allRequiredPrefilled = (): boolean => {\n return params().fields\n .filter((f) => f.required)\n .every((f) => f.prefill != null)\n }\n\n // Initialize form data with default values, applying prefill (v4.2.0)\n const initializeForm = (clearStorage = false) => {\n const initial: Record<string, any> = {}\n for (const field of params().fields) {\n // prefill takes priority over defaultValue\n initial[field.name] = field.prefill ?? field.defaultValue ?? getFieldDefault(field.type)\n }\n setFormData(initial)\n setErrors({})\n\n // Clear persisted data if requested\n if (clearStorage && clearPersisted) {\n clearPersisted()\n }\n }\n\n // Initialize on mount\n onMount(() => {\n initializeForm()\n })\n\n // Setup persistence if persistKey is provided (Sprint 4)\n createEffect(() => {\n const persistKey = params().persistKey\n if (persistKey) {\n const persistence = useFormPersistence({\n persistKey,\n formData,\n setFormData,\n excludeFields: params().excludeFromPersistence,\n expiresIn: params().persistExpiresIn,\n })\n clearPersisted = persistence.clearPersisted\n }\n })\n\n // Auto-submit countdown (v4.2.0)\n createEffect(() => {\n const delay = params().autoSubmitDelay\n if (!delay || !allRequiredPrefilled() || userInteracted()) return\n\n let remaining = Math.ceil(delay / 1000)\n setCountdown(remaining)\n\n countdownTimer = setInterval(() => {\n remaining--\n if (remaining <= 0) {\n cancelCountdown()\n // Trigger submit programmatically\n const form = document.querySelector(`#form-${props.component.id}`) as HTMLFormElement | null\n if (form) form.requestSubmit()\n } else {\n setCountdown(remaining)\n }\n }, 1000)\n })\n\n const handleFieldChange = (name: string, value: any) => {\n handleUserInteraction()\n setFormData((prev) => ({ ...prev, [name]: value }))\n // Clear error on change\n if (errors()[name]) {\n setErrors((prev) => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { [name]: _removed, ...rest } = prev\n return rest\n })\n }\n }\n\n const handleSubmit = async (e: Event) => {\n e.preventDefault()\n setIsSubmitting(true)\n setErrors({})\n\n // Get only visible fields for validation and submission\n const visibleFields = getVisibleFields()\n const visibleFieldNames = new Set(visibleFields.map((f) => f.name))\n\n // Filter form data to only include visible fields\n const visibleFormData: Record<string, any> = {}\n for (const [key, value] of Object.entries(formData())) {\n if (visibleFieldNames.has(key)) {\n visibleFormData[key] = value\n }\n }\n\n // Validate only visible fields\n const validationResult = validateFormData(visibleFormData, visibleFields, validationMessages())\n if (!validationResult.valid) {\n setErrors(validationResult.errors)\n setIsSubmitting(false)\n props.onError?.(validationResult.errors)\n return\n }\n\n // Submit via tool call if specified\n if (params().submitAction?.toolName) {\n try {\n const result = await execute(params().submitAction!.toolName, {\n ...params().submitAction!.params,\n formData: visibleFormData,\n })\n if (!result.success) {\n setErrors({ _form: result.error || strings.formSubmissionFailed })\n setIsSubmitting(false)\n props.onError?.({ _form: result.error || strings.formSubmissionFailed })\n return\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : strings.formSubmissionFailed\n setErrors({ _form: errorMessage })\n setIsSubmitting(false)\n props.onError?.({ _form: errorMessage })\n return\n }\n }\n\n // Clear persisted data on successful submit\n if (clearPersisted) {\n clearPersisted()\n }\n\n // Telemetry: action:dispatched on successful submit (B.5 — v5.6.0).\n // Privacy: only the action name (toolName or 'submit'), NO form values.\n if (telemetry) {\n telemetry.dispatch({\n type: 'action:dispatched',\n id: props.component.id,\n componentType: 'form',\n actionName: params().submitAction?.toolName ?? 'submit',\n ts: Date.now(),\n })\n }\n\n props.onSubmit?.(visibleFormData)\n setIsSubmitting(false)\n }\n\n const layoutClass = () => {\n switch (params().layout) {\n case 'horizontal':\n return 'grid grid-cols-2 gap-4'\n case 'inline':\n return 'flex flex-wrap gap-4 items-end'\n default:\n return 'space-y-4'\n }\n }\n\n return (\n <div class=\"mcp-ui-root w-full bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] rounded-lg shadow-[var(--mcp-ui-shadow,var(--shadow-sm))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-700,#374151))] p-4\">\n <Show when={params().title}>\n <h3 class=\"text-lg font-semibold text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))] mb-4\">\n {params().title}\n </h3>\n </Show>\n\n <form id={`form-${props.component.id}`} onSubmit={handleSubmit} noValidate>\n {/* Proposal 3: prefill summary */}\n <Show when={params().fields.some((f) => f.prefill != null)}>\n {(() => {\n const prefilled = params().fields.filter((f) => f.prefill != null).length\n const total = params().fields.length\n return (\n <p class=\"text-xs text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))] mb-3\">\n {formatMCPUIString(\n prefilled === 1 ? strings.formPrefilledOne : strings.formPrefilledMany,\n { count: prefilled, total }\n )}\n </p>\n )\n })()}\n </Show>\n <div class={layoutClass()}>\n <For each={params().fields}>\n {(field) => (\n <FormFieldRenderer\n field={field}\n value={formData()[field.name]}\n error={errors()[field.name]}\n onChange={(value) => handleFieldChange(field.name, value)}\n disabled={isSubmitting() || field.disabled}\n formData={formData}\n />\n )}\n </For>\n </div>\n\n <Show when={errors()._form}>\n <div class=\"mt-4 p-3 bg-[color:var(--mcp-ui-danger-soft,var(--color-red-50))] dark:bg-[color:var(--mcp-ui-danger-soft,color-mix(in_oklab,var(--color-red-900)_20%,transparent))] border border-[color:var(--mcp-ui-danger-border,var(--color-red-200))] dark:border-[color:var(--mcp-ui-danger-border,var(--color-red-800))] rounded-md\">\n <p class=\"text-sm text-[color:var(--mcp-ui-danger,var(--color-red-600))] dark:text-[color:var(--mcp-ui-danger,var(--color-red-400))]\" role=\"alert\">\n {errors()._form}\n </p>\n </div>\n </Show>\n\n {/* Auto-submit countdown (v4.2.0) */}\n <Show when={countdown() != null}>\n <div class=\"mt-4 flex items-center gap-3 p-3 bg-[color:var(--mcp-ui-accent-soft,var(--color-blue-50))] dark:bg-[color:var(--mcp-ui-accent-soft,color-mix(in_oklab,var(--color-blue-900)_20%,transparent))] border border-[color:var(--mcp-ui-accent-border,var(--color-blue-200))] dark:border-[color:var(--mcp-ui-accent-border,var(--color-blue-800))] rounded-md\">\n <span class=\"text-sm text-[color:var(--mcp-ui-accent,var(--color-blue-700))] dark:text-[color:var(--mcp-ui-accent,var(--color-blue-300))]\">\n {formatMCPUIString(strings.formSubmitCountdown, {\n label: params().submitLabel || strings.submit,\n seconds: countdown()!,\n })}\n </span>\n <button\n type=\"button\"\n onClick={() => { cancelCountdown(); setUserInteracted(true) }}\n class=\"text-sm text-[color:var(--mcp-ui-accent,var(--color-blue-600))] dark:text-[color:var(--mcp-ui-accent,var(--color-blue-400))] underline hover:text-[color:var(--mcp-ui-accent,var(--color-blue-800))] dark:hover:text-[color:var(--mcp-ui-accent,var(--color-blue-200))]\"\n >\n {strings.cancel}\n </button>\n </div>\n </Show>\n\n <div class=\"flex gap-2 pt-4 mt-4 border-t border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-700,#374151))]\">\n <button\n type=\"submit\"\n disabled={isSubmitting()}\n class=\"px-4 py-2 bg-[color:var(--mcp-ui-accent,var(--color-blue-600))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] rounded-md hover:bg-[color:var(--mcp-ui-accent-hover,var(--color-blue-700))] focus:outline-none focus:ring-2 focus:ring-[color:var(--mcp-ui-focus,var(--color-blue-500))] focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {isSubmitting() ? (\n <span class=\"flex items-center gap-2\">\n <span class=\"animate-spin h-4 w-4 border-2 border-[color:var(--mcp-ui-border,var(--color-white,#fff))] border-t-transparent rounded-full\" />\n {strings.formSubmitting}\n </span>\n ) : (\n params().submitLabel || strings.submit\n )}\n </button>\n <Show when={params().showReset}>\n <button\n type=\"button\"\n onClick={() => initializeForm(true)}\n disabled={isSubmitting()}\n class=\"px-4 py-2 border border-[color:var(--mcp-ui-border,var(--color-gray-300,#d1d5db))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] rounded-md hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-50,#f9fafb))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] focus:outline-none focus:ring-2 focus:ring-[color:var(--mcp-ui-focus,var(--color-gray-500,#6b7280))] focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {strings.formReset}\n </button>\n </Show>\n </div>\n </form>\n </div>\n )\n}\n"],"names":["getFieldDefault","type","undefined","FormRenderer","props","strings","useMCPUIStrings","validationMessages","required","fieldRequired","mustBeChecked","fieldMustBeChecked","minLength","fieldMinLength","maxLength","fieldMaxLength","invalidPattern","fieldInvalidPattern","invalidEmail","fieldInvalidEmail","invalidNumber","fieldInvalidNumber","minValue","fieldMinValue","maxValue","fieldMaxValue","minDate","fieldMinDate","maxDate","fieldMaxDate","invalidOption","fieldInvalidOption","invalidFormat","fieldInvalidFormat","params","component","formData","setFormData","createSignal","errors","setErrors","isSubmitting","setIsSubmitting","execute","useAction","telemetry","useTelemetry","clearPersisted","getVisibleFields","fields","filter","field","showWhen","evaluateCondition","countdown","setCountdown","countdownTimer","userInteracted","setUserInteracted","cancelCountdown","clearInterval","handleUserInteraction","onCleanup","allRequiredPrefilled","f","every","prefill","initializeForm","clearStorage","initial","name","defaultValue","onMount","createEffect","persistKey","persistence","useFormPersistence","excludeFields","excludeFromPersistence","expiresIn","persistExpiresIn","delay","autoSubmitDelay","remaining","Math","ceil","setInterval","form","document","querySelector","id","requestSubmit","handleFieldChange","value","prev","_removed","rest","handleSubmit","e","preventDefault","visibleFields","visibleFieldNames","Set","map","visibleFormData","key","Object","entries","has","validationResult","validateFormData","valid","onError","submitAction","toolName","result","success","_form","error","formSubmissionFailed","errorMessage","Error","message","dispatch","componentType","actionName","ts","Date","now","onSubmit","layoutClass","layout","_el$","_$getNextElement","_tmpl$5","_el$19","firstChild","_el$20","_co$5","_$getNextMarker","nextSibling","_el$3","_el$13","_el$14","_co$2","_el$4","_el$15","_el$16","_co$3","_el$17","_el$18","_co$4","_el$0","_el$1","_el$11","_el$12","_co$","_$insert","_$createComponent","Show","when","title","children","_el$2","_tmpl$","addEventListener","some","prefilled","length","total","_el$21","_tmpl$6","formatMCPUIString","formPrefilledOne","formPrefilledMany","count","For","each","FormFieldRenderer","onChange","disabled","_el$5","_tmpl$2","_el$6","_el$7","_tmpl$3","_el$8","_el$9","formSubmitCountdown","label","submitLabel","submit","seconds","$$click","cancel","_$runHydrationEvents","_c$","_$memo","_el$22","_tmpl$7","_el$23","_el$24","_el$25","_co$6","formSubmitting","showReset","_el$10","_tmpl$4","formReset","_$effect","_$setProperty","_p$","_v$","_v$2","_v$3","_$setAttribute","t","_$className","a","_$delegateEvents"],"mappings":"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"}
@@ -6,7 +6,7 @@ const logger$1 = require("../utils/logger.cjs");
6
6
  const MCPUITelemetryContext = require("../context/MCPUITelemetryContext.cjs");
7
7
  const MCPUIStringsContext = require("../context/MCPUIStringsContext.cjs");
8
8
  const formatString = require("../utils/format-string.cjs");
9
- var _tmpl$ = /* @__PURE__ */ web.template(`<p class="text-xs text-yellow-600 dark:text-yellow-400 mt-2 font-mono">`), _tmpl$2 = /* @__PURE__ */ web.template(`<button class="mt-3 text-xs font-medium text-yellow-800 dark:text-yellow-200 hover:text-yellow-900 dark:hover:text-yellow-100 underline">`), _tmpl$3 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4"><div class="flex items-start gap-3"><div class=flex-shrink-0><svg class="w-5 h-5 text-yellow-600 dark:text-yellow-400"fill=none stroke=currentColor viewBox="0 0 24 24"><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><p class="text-sm font-medium text-yellow-900 dark:text-yellow-100"></p><p class="text-xs text-yellow-700 dark:text-yellow-300 mt-1"></p><!$><!/><!$><!/>`);
9
+ var _tmpl$ = /* @__PURE__ */ web.template(`<p class="text-xs text-[color:var(--mcp-ui-warning,var(--color-yellow-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))] mt-2 font-mono">`), _tmpl$2 = /* @__PURE__ */ web.template(`<button class="mt-3 text-xs font-medium text-[color:var(--mcp-ui-warning,var(--color-yellow-800))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-200))] hover:text-[color:var(--mcp-ui-warning,var(--color-yellow-900))] dark:hover:text-[color:var(--mcp-ui-warning,var(--color-yellow-100))] underline">`), _tmpl$3 = /* @__PURE__ */ web.template(`<div class="w-full h-full bg-[color:var(--mcp-ui-warning-soft,var(--color-yellow-50))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-yellow-900)_20%,transparent))] border border-[color:var(--mcp-ui-warning-border,var(--color-yellow-200))] dark:border-[color:var(--mcp-ui-warning-border,var(--color-yellow-800))] rounded-lg p-4"><div class="flex items-start gap-3"><div class=flex-shrink-0><svg class="w-5 h-5 text-[color:var(--mcp-ui-warning,var(--color-yellow-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))]"fill=none stroke=currentColor viewBox="0 0 24 24"><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><p class="text-sm font-medium text-[color:var(--mcp-ui-warning,var(--color-yellow-900))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-100))]"></p><p class="text-xs text-[color:var(--mcp-ui-warning,var(--color-yellow-700))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-300))] mt-1"></p><!$><!/><!$><!/>`);
10
10
  const logger = logger$1.createLogger("generative-ui");
11
11
  function DefaultErrorFallback(props) {
12
12
  const strings = MCPUIStringsContext.useMCPUIStrings();
@@ -1 +1 @@
1
- {"version":3,"file":"GenerativeUIErrorBoundary.cjs","sources":["../../src/components/GenerativeUIErrorBoundary.tsx"],"sourcesContent":["/**\n * Generative UI Error Boundary with Telemetry\n * Phase 0: Error isolation + structured logging\n *\n * Features:\n * - Component-level error isolation\n * - Structured logging with context\n * - Performance timing\n * - Retry mechanism\n * - User-friendly fallback UI\n */\n\nimport { Component, ErrorBoundary, createSignal, Show, onMount } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport { createLogger } from '../utils/logger'\nimport type { RendererError, ComponentType } from '../types'\nimport { useTelemetry } from '../context/MCPUITelemetryContext'\nimport { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nconst logger = createLogger('generative-ui')\n\n/**\n * Props for GenerativeUIErrorBoundary\n */\nexport interface GenerativeUIErrorBoundaryProps {\n /**\n * Component identifier for telemetry\n */\n componentId: string\n\n /**\n * Component type for context\n */\n componentType: string\n\n /**\n * Error callback\n */\n onError?: (error: RendererError) => void\n\n /**\n * Allow retry on error\n */\n allowRetry?: boolean\n\n /**\n * Child components to wrap\n */\n children: any\n\n /**\n * Custom fallback UI (optional)\n */\n fallback?: (error: Error, retry?: () => void) => any\n}\n\n/**\n * Default fallback UI for errors\n */\nfunction DefaultErrorFallback(props: {\n error: Error\n componentId: string\n componentType: string\n allowRetry?: boolean\n onRetry?: () => void\n}) {\n const strings = useMCPUIStrings()\n return (\n <div class=\"w-full h-full bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4\">\n <div class=\"flex items-start gap-3\">\n <div class=\"flex-shrink-0\">\n <svg\n class=\"w-5 h-5 text-yellow-600 dark:text-yellow-400\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-yellow-900 dark:text-yellow-100\">\n {strings.errorBoundaryTitle}\n </p>\n <p class=\"text-xs text-yellow-700 dark:text-yellow-300 mt-1\">\n {formatMCPUIString(strings.errorBoundaryMeta, {\n type: props.componentType || strings.unknown,\n id: props.componentId?.slice(0, 8) || strings.unknown,\n })}\n </p>\n <Show when={import.meta.env.DEV}>\n <p class=\"text-xs text-yellow-600 dark:text-yellow-400 mt-2 font-mono\">\n {props.error.message}\n </p>\n </Show>\n <Show when={props.allowRetry}>\n <button\n onClick={props.onRetry}\n class=\"mt-3 text-xs font-medium text-yellow-800 dark:text-yellow-200 hover:text-yellow-900 dark:hover:text-yellow-100 underline\"\n >\n {strings.errorBoundaryRetry}\n </button>\n </Show>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * Generative UI Error Boundary Component\n */\nexport const GenerativeUIErrorBoundary: Component<GenerativeUIErrorBoundaryProps> = (props) => {\n const [retryKey, setRetryKey] = createSignal(0)\n const [renderStartTime, setRenderStartTime] = createSignal(0)\n // Telemetry sink (B.5 — v5.6.0). Null when no Provider is mounted.\n const telemetry = useTelemetry()\n\n // SSR-safe: Initialize performance timing on client only\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setRenderStartTime(performance.now())\n }\n })\n\n // Handle error with telemetry\n const handleError = (error: Error) => {\n // SSR-safe: Calculate render duration\n const renderDuration = !isServer && typeof performance !== 'undefined'\n ? performance.now() - renderStartTime()\n : 0\n\n // SSR-safe: Get client-only context\n const userAgent = !isServer && typeof navigator !== 'undefined'\n ? navigator.userAgent\n : 'server'\n const viewport = !isServer && typeof window !== 'undefined'\n ? { width: window.innerWidth, height: window.innerHeight }\n : { width: 0, height: 0 }\n\n // Structure error context\n const errorContext = {\n componentId: props.componentId,\n componentType: props.componentType,\n errorMessage: error.message,\n errorStack: error.stack,\n renderDuration,\n retryCount: retryKey(),\n timestamp: new Date().toISOString(),\n userAgent,\n viewport,\n }\n\n // Log to structured logger\n logger.error(`Component render failed: ${props.componentType}`, errorContext)\n\n // Call error callback\n props.onError?.({\n type: 'render',\n message: error.message,\n componentId: props.componentId,\n details: errorContext,\n })\n\n // Dispatch render:error to telemetry sink (B.5 — v5.6.0). Only the\n // message (capped semantically by the consumer if desired) — NO stack\n // trace, NO component payload, per privacy hard rule (§M.6.2).\n if (telemetry) {\n telemetry.dispatch({\n type: 'render:error',\n id: props.componentId,\n componentType: props.componentType as ComponentType,\n errorMessage: error.message,\n ts: Date.now(),\n })\n }\n\n // In production, send to monitoring service\n if (import.meta.env.PROD) {\n // Future: Send to Sentry or other APM\n // Sentry.captureException(error, { contexts: { component: errorContext } })\n }\n }\n\n // Retry mechanism\n const handleRetry = () => {\n const newRetryCount = retryKey() + 1\n logger.info(`Retrying component render: ${props.componentType}`, {\n componentId: props.componentId,\n retryCount: newRetryCount,\n })\n setRetryKey(newRetryCount)\n }\n\n return (\n <ErrorBoundary\n fallback={(error) => {\n handleError(error)\n\n // Use custom fallback if provided\n if (props.fallback) {\n return props.fallback(error, props.allowRetry ? handleRetry : undefined)\n }\n\n // Default fallback\n return (\n <DefaultErrorFallback\n error={error}\n componentId={props.componentId}\n componentType={props.componentType}\n allowRetry={props.allowRetry}\n onRetry={handleRetry}\n />\n )\n }}\n >\n {/* Key prop for forcing remount on retry */}\n {(() => {\n void retryKey() // Access signal to track changes\n return <>{props.children}</>\n })()}\n </ErrorBoundary>\n )\n}\n\n/**\n * Performance monitoring wrapper\n * Logs render times for performance analysis\n */\nexport function withPerformanceMonitoring<P extends { componentId: string; componentType: string }>(\n WrappedComponent: Component<P>\n) {\n return (props: P) => {\n const [renderStart, setRenderStart] = createSignal(0)\n\n // Log render start\n logger.debug(`Component render start: ${props.componentType}`, {\n componentId: props.componentId,\n timestamp: new Date().toISOString(),\n })\n\n // SSR-safe: Measure on mount completion (client-side only)\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setRenderStart(performance.now())\n\n requestAnimationFrame(() => {\n const renderEnd = performance.now()\n const duration = renderEnd - renderStart()\n\n logger.info(`Component rendered: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n timestamp: new Date().toISOString(),\n })\n\n // Warn if render is slow (>50ms target)\n if (duration > 50) {\n logger.warn(`Slow component render: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n threshold: 50,\n })\n }\n })\n }\n })\n\n return <WrappedComponent {...props} />\n }\n}\n\n/**\n * Hook to track component lifecycle events\n */\nexport function useComponentTelemetry(componentId: string, componentType: string) {\n const [mountTime, setMountTime] = createSignal(0)\n\n // SSR-safe: Initialize mount time on client only\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setMountTime(performance.now())\n }\n\n // Log mount\n logger.debug(`Component mounted: ${componentType}`, {\n componentId,\n timestamp: new Date().toISOString(),\n })\n })\n\n // Return cleanup function for unmount\n return () => {\n const lifetime = !isServer && typeof performance !== 'undefined'\n ? performance.now() - mountTime()\n : 0\n logger.debug(`Component unmounted: ${componentType}`, {\n componentId,\n lifetime,\n timestamp: new Date().toISOString(),\n })\n }\n}\n"],"names":["logger","createLogger","DefaultErrorFallback","props","strings","useMCPUIStrings","_el$","_$getNextElement","_tmpl$3","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$9","_el$0","_co$","_$getNextMarker","_el$1","_el$10","_co$2","_$insert","errorBoundaryTitle","formatMCPUIString","errorBoundaryMeta","type","componentType","unknown","id","componentId","slice","_$createComponent","Show","when","import","children","_el$7","_tmpl$","error","message","allowRetry","_el$8","_tmpl$2","_$addEventListener","onRetry","errorBoundaryRetry","_$runHydrationEvents","GenerativeUIErrorBoundary","retryKey","setRetryKey","createSignal","renderStartTime","setRenderStartTime","telemetry","useTelemetry","onMount","performance","now","handleError","renderDuration","isServer","userAgent","navigator","viewport","window","width","innerWidth","height","innerHeight","errorContext","errorMessage","errorStack","stack","retryCount","timestamp","Date","toISOString","onError","details","dispatch","ts","handleRetry","newRetryCount","info","ErrorBoundary","fallback","undefined","_$memo","_$delegateEvents"],"mappings":"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"}
1
+ {"version":3,"file":"GenerativeUIErrorBoundary.cjs","sources":["../../src/components/GenerativeUIErrorBoundary.tsx"],"sourcesContent":["/**\n * Generative UI Error Boundary with Telemetry\n * Phase 0: Error isolation + structured logging\n *\n * Features:\n * - Component-level error isolation\n * - Structured logging with context\n * - Performance timing\n * - Retry mechanism\n * - User-friendly fallback UI\n */\n\nimport { Component, ErrorBoundary, createSignal, Show, onMount } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport { createLogger } from '../utils/logger'\nimport type { RendererError, ComponentType } from '../types'\nimport { useTelemetry } from '../context/MCPUITelemetryContext'\nimport { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nconst logger = createLogger('generative-ui')\n\n/**\n * Props for GenerativeUIErrorBoundary\n */\nexport interface GenerativeUIErrorBoundaryProps {\n /**\n * Component identifier for telemetry\n */\n componentId: string\n\n /**\n * Component type for context\n */\n componentType: string\n\n /**\n * Error callback\n */\n onError?: (error: RendererError) => void\n\n /**\n * Allow retry on error\n */\n allowRetry?: boolean\n\n /**\n * Child components to wrap\n */\n children: any\n\n /**\n * Custom fallback UI (optional)\n */\n fallback?: (error: Error, retry?: () => void) => any\n}\n\n/**\n * Default fallback UI for errors\n */\nfunction DefaultErrorFallback(props: {\n error: Error\n componentId: string\n componentType: string\n allowRetry?: boolean\n onRetry?: () => void\n}) {\n const strings = useMCPUIStrings()\n return (\n <div class=\"w-full h-full bg-[color:var(--mcp-ui-warning-soft,var(--color-yellow-50))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-yellow-900)_20%,transparent))] border border-[color:var(--mcp-ui-warning-border,var(--color-yellow-200))] dark:border-[color:var(--mcp-ui-warning-border,var(--color-yellow-800))] rounded-lg p-4\">\n <div class=\"flex items-start gap-3\">\n <div class=\"flex-shrink-0\">\n <svg\n class=\"w-5 h-5 text-[color:var(--mcp-ui-warning,var(--color-yellow-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))]\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-[color:var(--mcp-ui-warning,var(--color-yellow-900))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-100))]\">\n {strings.errorBoundaryTitle}\n </p>\n <p class=\"text-xs text-[color:var(--mcp-ui-warning,var(--color-yellow-700))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-300))] mt-1\">\n {formatMCPUIString(strings.errorBoundaryMeta, {\n type: props.componentType || strings.unknown,\n id: props.componentId?.slice(0, 8) || strings.unknown,\n })}\n </p>\n <Show when={import.meta.env.DEV}>\n <p class=\"text-xs text-[color:var(--mcp-ui-warning,var(--color-yellow-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))] mt-2 font-mono\">\n {props.error.message}\n </p>\n </Show>\n <Show when={props.allowRetry}>\n <button\n onClick={props.onRetry}\n class=\"mt-3 text-xs font-medium text-[color:var(--mcp-ui-warning,var(--color-yellow-800))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-200))] hover:text-[color:var(--mcp-ui-warning,var(--color-yellow-900))] dark:hover:text-[color:var(--mcp-ui-warning,var(--color-yellow-100))] underline\"\n >\n {strings.errorBoundaryRetry}\n </button>\n </Show>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * Generative UI Error Boundary Component\n */\nexport const GenerativeUIErrorBoundary: Component<GenerativeUIErrorBoundaryProps> = (props) => {\n const [retryKey, setRetryKey] = createSignal(0)\n const [renderStartTime, setRenderStartTime] = createSignal(0)\n // Telemetry sink (B.5 — v5.6.0). Null when no Provider is mounted.\n const telemetry = useTelemetry()\n\n // SSR-safe: Initialize performance timing on client only\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setRenderStartTime(performance.now())\n }\n })\n\n // Handle error with telemetry\n const handleError = (error: Error) => {\n // SSR-safe: Calculate render duration\n const renderDuration = !isServer && typeof performance !== 'undefined'\n ? performance.now() - renderStartTime()\n : 0\n\n // SSR-safe: Get client-only context\n const userAgent = !isServer && typeof navigator !== 'undefined'\n ? navigator.userAgent\n : 'server'\n const viewport = !isServer && typeof window !== 'undefined'\n ? { width: window.innerWidth, height: window.innerHeight }\n : { width: 0, height: 0 }\n\n // Structure error context\n const errorContext = {\n componentId: props.componentId,\n componentType: props.componentType,\n errorMessage: error.message,\n errorStack: error.stack,\n renderDuration,\n retryCount: retryKey(),\n timestamp: new Date().toISOString(),\n userAgent,\n viewport,\n }\n\n // Log to structured logger\n logger.error(`Component render failed: ${props.componentType}`, errorContext)\n\n // Call error callback\n props.onError?.({\n type: 'render',\n message: error.message,\n componentId: props.componentId,\n details: errorContext,\n })\n\n // Dispatch render:error to telemetry sink (B.5 — v5.6.0). Only the\n // message (capped semantically by the consumer if desired) — NO stack\n // trace, NO component payload, per privacy hard rule (§M.6.2).\n if (telemetry) {\n telemetry.dispatch({\n type: 'render:error',\n id: props.componentId,\n componentType: props.componentType as ComponentType,\n errorMessage: error.message,\n ts: Date.now(),\n })\n }\n\n // In production, send to monitoring service\n if (import.meta.env.PROD) {\n // Future: Send to Sentry or other APM\n // Sentry.captureException(error, { contexts: { component: errorContext } })\n }\n }\n\n // Retry mechanism\n const handleRetry = () => {\n const newRetryCount = retryKey() + 1\n logger.info(`Retrying component render: ${props.componentType}`, {\n componentId: props.componentId,\n retryCount: newRetryCount,\n })\n setRetryKey(newRetryCount)\n }\n\n return (\n <ErrorBoundary\n fallback={(error) => {\n handleError(error)\n\n // Use custom fallback if provided\n if (props.fallback) {\n return props.fallback(error, props.allowRetry ? handleRetry : undefined)\n }\n\n // Default fallback\n return (\n <DefaultErrorFallback\n error={error}\n componentId={props.componentId}\n componentType={props.componentType}\n allowRetry={props.allowRetry}\n onRetry={handleRetry}\n />\n )\n }}\n >\n {/* Key prop for forcing remount on retry */}\n {(() => {\n void retryKey() // Access signal to track changes\n return <>{props.children}</>\n })()}\n </ErrorBoundary>\n )\n}\n\n/**\n * Performance monitoring wrapper\n * Logs render times for performance analysis\n */\nexport function withPerformanceMonitoring<P extends { componentId: string; componentType: string }>(\n WrappedComponent: Component<P>\n) {\n return (props: P) => {\n const [renderStart, setRenderStart] = createSignal(0)\n\n // Log render start\n logger.debug(`Component render start: ${props.componentType}`, {\n componentId: props.componentId,\n timestamp: new Date().toISOString(),\n })\n\n // SSR-safe: Measure on mount completion (client-side only)\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setRenderStart(performance.now())\n\n requestAnimationFrame(() => {\n const renderEnd = performance.now()\n const duration = renderEnd - renderStart()\n\n logger.info(`Component rendered: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n timestamp: new Date().toISOString(),\n })\n\n // Warn if render is slow (>50ms target)\n if (duration > 50) {\n logger.warn(`Slow component render: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n threshold: 50,\n })\n }\n })\n }\n })\n\n return <WrappedComponent {...props} />\n }\n}\n\n/**\n * Hook to track component lifecycle events\n */\nexport function useComponentTelemetry(componentId: string, componentType: string) {\n const [mountTime, setMountTime] = createSignal(0)\n\n // SSR-safe: Initialize mount time on client only\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setMountTime(performance.now())\n }\n\n // Log mount\n logger.debug(`Component mounted: ${componentType}`, {\n componentId,\n timestamp: new Date().toISOString(),\n })\n })\n\n // Return cleanup function for unmount\n return () => {\n const lifetime = !isServer && typeof performance !== 'undefined'\n ? performance.now() - mountTime()\n : 0\n logger.debug(`Component unmounted: ${componentType}`, {\n componentId,\n lifetime,\n timestamp: new Date().toISOString(),\n })\n }\n}\n"],"names":["logger","createLogger","DefaultErrorFallback","props","strings","useMCPUIStrings","_el$","_$getNextElement","_tmpl$3","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$9","_el$0","_co$","_$getNextMarker","_el$1","_el$10","_co$2","_$insert","errorBoundaryTitle","formatMCPUIString","errorBoundaryMeta","type","componentType","unknown","id","componentId","slice","_$createComponent","Show","when","import","children","_el$7","_tmpl$","error","message","allowRetry","_el$8","_tmpl$2","_$addEventListener","onRetry","errorBoundaryRetry","_$runHydrationEvents","GenerativeUIErrorBoundary","retryKey","setRetryKey","createSignal","renderStartTime","setRenderStartTime","telemetry","useTelemetry","onMount","performance","now","handleError","renderDuration","isServer","userAgent","navigator","viewport","window","width","innerWidth","height","innerHeight","errorContext","errorMessage","errorStack","stack","retryCount","timestamp","Date","toISOString","onError","details","dispatch","ts","handleRetry","newRetryCount","info","ErrorBoundary","fallback","undefined","_$memo","_$delegateEvents"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { createLogger } from "../utils/logger.js";
4
4
  import { useTelemetry } from "../context/MCPUITelemetryContext.js";
5
5
  import { useMCPUIStrings } from "../context/MCPUIStringsContext.js";
6
6
  import { formatMCPUIString } from "../utils/format-string.js";
7
- var _tmpl$ = /* @__PURE__ */ template(`<p class="text-xs text-yellow-600 dark:text-yellow-400 mt-2 font-mono">`), _tmpl$2 = /* @__PURE__ */ template(`<button class="mt-3 text-xs font-medium text-yellow-800 dark:text-yellow-200 hover:text-yellow-900 dark:hover:text-yellow-100 underline">`), _tmpl$3 = /* @__PURE__ */ template(`<div class="w-full h-full bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4"><div class="flex items-start gap-3"><div class=flex-shrink-0><svg class="w-5 h-5 text-yellow-600 dark:text-yellow-400"fill=none stroke=currentColor viewBox="0 0 24 24"><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><p class="text-sm font-medium text-yellow-900 dark:text-yellow-100"></p><p class="text-xs text-yellow-700 dark:text-yellow-300 mt-1"></p><!$><!/><!$><!/>`);
7
+ var _tmpl$ = /* @__PURE__ */ template(`<p class="text-xs text-[color:var(--mcp-ui-warning,var(--color-yellow-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))] mt-2 font-mono">`), _tmpl$2 = /* @__PURE__ */ template(`<button class="mt-3 text-xs font-medium text-[color:var(--mcp-ui-warning,var(--color-yellow-800))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-200))] hover:text-[color:var(--mcp-ui-warning,var(--color-yellow-900))] dark:hover:text-[color:var(--mcp-ui-warning,var(--color-yellow-100))] underline">`), _tmpl$3 = /* @__PURE__ */ template(`<div class="w-full h-full bg-[color:var(--mcp-ui-warning-soft,var(--color-yellow-50))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-yellow-900)_20%,transparent))] border border-[color:var(--mcp-ui-warning-border,var(--color-yellow-200))] dark:border-[color:var(--mcp-ui-warning-border,var(--color-yellow-800))] rounded-lg p-4"><div class="flex items-start gap-3"><div class=flex-shrink-0><svg class="w-5 h-5 text-[color:var(--mcp-ui-warning,var(--color-yellow-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))]"fill=none stroke=currentColor viewBox="0 0 24 24"><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg></div><div class="flex-1 min-w-0"><p class="text-sm font-medium text-[color:var(--mcp-ui-warning,var(--color-yellow-900))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-100))]"></p><p class="text-xs text-[color:var(--mcp-ui-warning,var(--color-yellow-700))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-300))] mt-1"></p><!$><!/><!$><!/>`);
8
8
  const logger = createLogger("generative-ui");
9
9
  function DefaultErrorFallback(props) {
10
10
  const strings = useMCPUIStrings();
@@ -1 +1 @@
1
- {"version":3,"file":"GenerativeUIErrorBoundary.js","sources":["../../src/components/GenerativeUIErrorBoundary.tsx"],"sourcesContent":["/**\n * Generative UI Error Boundary with Telemetry\n * Phase 0: Error isolation + structured logging\n *\n * Features:\n * - Component-level error isolation\n * - Structured logging with context\n * - Performance timing\n * - Retry mechanism\n * - User-friendly fallback UI\n */\n\nimport { Component, ErrorBoundary, createSignal, Show, onMount } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport { createLogger } from '../utils/logger'\nimport type { RendererError, ComponentType } from '../types'\nimport { useTelemetry } from '../context/MCPUITelemetryContext'\nimport { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nconst logger = createLogger('generative-ui')\n\n/**\n * Props for GenerativeUIErrorBoundary\n */\nexport interface GenerativeUIErrorBoundaryProps {\n /**\n * Component identifier for telemetry\n */\n componentId: string\n\n /**\n * Component type for context\n */\n componentType: string\n\n /**\n * Error callback\n */\n onError?: (error: RendererError) => void\n\n /**\n * Allow retry on error\n */\n allowRetry?: boolean\n\n /**\n * Child components to wrap\n */\n children: any\n\n /**\n * Custom fallback UI (optional)\n */\n fallback?: (error: Error, retry?: () => void) => any\n}\n\n/**\n * Default fallback UI for errors\n */\nfunction DefaultErrorFallback(props: {\n error: Error\n componentId: string\n componentType: string\n allowRetry?: boolean\n onRetry?: () => void\n}) {\n const strings = useMCPUIStrings()\n return (\n <div class=\"w-full h-full bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4\">\n <div class=\"flex items-start gap-3\">\n <div class=\"flex-shrink-0\">\n <svg\n class=\"w-5 h-5 text-yellow-600 dark:text-yellow-400\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-yellow-900 dark:text-yellow-100\">\n {strings.errorBoundaryTitle}\n </p>\n <p class=\"text-xs text-yellow-700 dark:text-yellow-300 mt-1\">\n {formatMCPUIString(strings.errorBoundaryMeta, {\n type: props.componentType || strings.unknown,\n id: props.componentId?.slice(0, 8) || strings.unknown,\n })}\n </p>\n <Show when={import.meta.env.DEV}>\n <p class=\"text-xs text-yellow-600 dark:text-yellow-400 mt-2 font-mono\">\n {props.error.message}\n </p>\n </Show>\n <Show when={props.allowRetry}>\n <button\n onClick={props.onRetry}\n class=\"mt-3 text-xs font-medium text-yellow-800 dark:text-yellow-200 hover:text-yellow-900 dark:hover:text-yellow-100 underline\"\n >\n {strings.errorBoundaryRetry}\n </button>\n </Show>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * Generative UI Error Boundary Component\n */\nexport const GenerativeUIErrorBoundary: Component<GenerativeUIErrorBoundaryProps> = (props) => {\n const [retryKey, setRetryKey] = createSignal(0)\n const [renderStartTime, setRenderStartTime] = createSignal(0)\n // Telemetry sink (B.5 — v5.6.0). Null when no Provider is mounted.\n const telemetry = useTelemetry()\n\n // SSR-safe: Initialize performance timing on client only\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setRenderStartTime(performance.now())\n }\n })\n\n // Handle error with telemetry\n const handleError = (error: Error) => {\n // SSR-safe: Calculate render duration\n const renderDuration = !isServer && typeof performance !== 'undefined'\n ? performance.now() - renderStartTime()\n : 0\n\n // SSR-safe: Get client-only context\n const userAgent = !isServer && typeof navigator !== 'undefined'\n ? navigator.userAgent\n : 'server'\n const viewport = !isServer && typeof window !== 'undefined'\n ? { width: window.innerWidth, height: window.innerHeight }\n : { width: 0, height: 0 }\n\n // Structure error context\n const errorContext = {\n componentId: props.componentId,\n componentType: props.componentType,\n errorMessage: error.message,\n errorStack: error.stack,\n renderDuration,\n retryCount: retryKey(),\n timestamp: new Date().toISOString(),\n userAgent,\n viewport,\n }\n\n // Log to structured logger\n logger.error(`Component render failed: ${props.componentType}`, errorContext)\n\n // Call error callback\n props.onError?.({\n type: 'render',\n message: error.message,\n componentId: props.componentId,\n details: errorContext,\n })\n\n // Dispatch render:error to telemetry sink (B.5 — v5.6.0). Only the\n // message (capped semantically by the consumer if desired) — NO stack\n // trace, NO component payload, per privacy hard rule (§M.6.2).\n if (telemetry) {\n telemetry.dispatch({\n type: 'render:error',\n id: props.componentId,\n componentType: props.componentType as ComponentType,\n errorMessage: error.message,\n ts: Date.now(),\n })\n }\n\n // In production, send to monitoring service\n if (import.meta.env.PROD) {\n // Future: Send to Sentry or other APM\n // Sentry.captureException(error, { contexts: { component: errorContext } })\n }\n }\n\n // Retry mechanism\n const handleRetry = () => {\n const newRetryCount = retryKey() + 1\n logger.info(`Retrying component render: ${props.componentType}`, {\n componentId: props.componentId,\n retryCount: newRetryCount,\n })\n setRetryKey(newRetryCount)\n }\n\n return (\n <ErrorBoundary\n fallback={(error) => {\n handleError(error)\n\n // Use custom fallback if provided\n if (props.fallback) {\n return props.fallback(error, props.allowRetry ? handleRetry : undefined)\n }\n\n // Default fallback\n return (\n <DefaultErrorFallback\n error={error}\n componentId={props.componentId}\n componentType={props.componentType}\n allowRetry={props.allowRetry}\n onRetry={handleRetry}\n />\n )\n }}\n >\n {/* Key prop for forcing remount on retry */}\n {(() => {\n void retryKey() // Access signal to track changes\n return <>{props.children}</>\n })()}\n </ErrorBoundary>\n )\n}\n\n/**\n * Performance monitoring wrapper\n * Logs render times for performance analysis\n */\nexport function withPerformanceMonitoring<P extends { componentId: string; componentType: string }>(\n WrappedComponent: Component<P>\n) {\n return (props: P) => {\n const [renderStart, setRenderStart] = createSignal(0)\n\n // Log render start\n logger.debug(`Component render start: ${props.componentType}`, {\n componentId: props.componentId,\n timestamp: new Date().toISOString(),\n })\n\n // SSR-safe: Measure on mount completion (client-side only)\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setRenderStart(performance.now())\n\n requestAnimationFrame(() => {\n const renderEnd = performance.now()\n const duration = renderEnd - renderStart()\n\n logger.info(`Component rendered: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n timestamp: new Date().toISOString(),\n })\n\n // Warn if render is slow (>50ms target)\n if (duration > 50) {\n logger.warn(`Slow component render: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n threshold: 50,\n })\n }\n })\n }\n })\n\n return <WrappedComponent {...props} />\n }\n}\n\n/**\n * Hook to track component lifecycle events\n */\nexport function useComponentTelemetry(componentId: string, componentType: string) {\n const [mountTime, setMountTime] = createSignal(0)\n\n // SSR-safe: Initialize mount time on client only\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setMountTime(performance.now())\n }\n\n // Log mount\n logger.debug(`Component mounted: ${componentType}`, {\n componentId,\n timestamp: new Date().toISOString(),\n })\n })\n\n // Return cleanup function for unmount\n return () => {\n const lifetime = !isServer && typeof performance !== 'undefined'\n ? performance.now() - mountTime()\n : 0\n logger.debug(`Component unmounted: ${componentType}`, {\n componentId,\n lifetime,\n timestamp: new Date().toISOString(),\n })\n }\n}\n"],"names":["logger","createLogger","DefaultErrorFallback","props","strings","useMCPUIStrings","_el$","_$getNextElement","_tmpl$3","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$9","_el$0","_co$","_$getNextMarker","_el$1","_el$10","_co$2","_$insert","errorBoundaryTitle","formatMCPUIString","errorBoundaryMeta","type","componentType","unknown","id","componentId","slice","_$createComponent","Show","when","import","children","_el$7","_tmpl$","error","message","allowRetry","_el$8","_tmpl$2","_$addEventListener","onRetry","errorBoundaryRetry","_$runHydrationEvents","GenerativeUIErrorBoundary","retryKey","setRetryKey","createSignal","renderStartTime","setRenderStartTime","telemetry","useTelemetry","onMount","performance","now","handleError","renderDuration","isServer","userAgent","navigator","viewport","window","width","innerWidth","height","innerHeight","errorContext","errorMessage","errorStack","stack","retryCount","timestamp","Date","toISOString","onError","details","dispatch","ts","handleRetry","newRetryCount","info","ErrorBoundary","fallback","undefined","_$memo","_$delegateEvents"],"mappings":"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"}
1
+ {"version":3,"file":"GenerativeUIErrorBoundary.js","sources":["../../src/components/GenerativeUIErrorBoundary.tsx"],"sourcesContent":["/**\n * Generative UI Error Boundary with Telemetry\n * Phase 0: Error isolation + structured logging\n *\n * Features:\n * - Component-level error isolation\n * - Structured logging with context\n * - Performance timing\n * - Retry mechanism\n * - User-friendly fallback UI\n */\n\nimport { Component, ErrorBoundary, createSignal, Show, onMount } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport { createLogger } from '../utils/logger'\nimport type { RendererError, ComponentType } from '../types'\nimport { useTelemetry } from '../context/MCPUITelemetryContext'\nimport { formatMCPUIString, useMCPUIStrings } from '../context/MCPUIStringsContext'\n\nconst logger = createLogger('generative-ui')\n\n/**\n * Props for GenerativeUIErrorBoundary\n */\nexport interface GenerativeUIErrorBoundaryProps {\n /**\n * Component identifier for telemetry\n */\n componentId: string\n\n /**\n * Component type for context\n */\n componentType: string\n\n /**\n * Error callback\n */\n onError?: (error: RendererError) => void\n\n /**\n * Allow retry on error\n */\n allowRetry?: boolean\n\n /**\n * Child components to wrap\n */\n children: any\n\n /**\n * Custom fallback UI (optional)\n */\n fallback?: (error: Error, retry?: () => void) => any\n}\n\n/**\n * Default fallback UI for errors\n */\nfunction DefaultErrorFallback(props: {\n error: Error\n componentId: string\n componentType: string\n allowRetry?: boolean\n onRetry?: () => void\n}) {\n const strings = useMCPUIStrings()\n return (\n <div class=\"w-full h-full bg-[color:var(--mcp-ui-warning-soft,var(--color-yellow-50))] dark:bg-[color:var(--mcp-ui-warning-soft,color-mix(in_oklab,var(--color-yellow-900)_20%,transparent))] border border-[color:var(--mcp-ui-warning-border,var(--color-yellow-200))] dark:border-[color:var(--mcp-ui-warning-border,var(--color-yellow-800))] rounded-lg p-4\">\n <div class=\"flex items-start gap-3\">\n <div class=\"flex-shrink-0\">\n <svg\n class=\"w-5 h-5 text-[color:var(--mcp-ui-warning,var(--color-yellow-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))]\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-[color:var(--mcp-ui-warning,var(--color-yellow-900))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-100))]\">\n {strings.errorBoundaryTitle}\n </p>\n <p class=\"text-xs text-[color:var(--mcp-ui-warning,var(--color-yellow-700))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-300))] mt-1\">\n {formatMCPUIString(strings.errorBoundaryMeta, {\n type: props.componentType || strings.unknown,\n id: props.componentId?.slice(0, 8) || strings.unknown,\n })}\n </p>\n <Show when={import.meta.env.DEV}>\n <p class=\"text-xs text-[color:var(--mcp-ui-warning,var(--color-yellow-600))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-400))] mt-2 font-mono\">\n {props.error.message}\n </p>\n </Show>\n <Show when={props.allowRetry}>\n <button\n onClick={props.onRetry}\n class=\"mt-3 text-xs font-medium text-[color:var(--mcp-ui-warning,var(--color-yellow-800))] dark:text-[color:var(--mcp-ui-warning,var(--color-yellow-200))] hover:text-[color:var(--mcp-ui-warning,var(--color-yellow-900))] dark:hover:text-[color:var(--mcp-ui-warning,var(--color-yellow-100))] underline\"\n >\n {strings.errorBoundaryRetry}\n </button>\n </Show>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * Generative UI Error Boundary Component\n */\nexport const GenerativeUIErrorBoundary: Component<GenerativeUIErrorBoundaryProps> = (props) => {\n const [retryKey, setRetryKey] = createSignal(0)\n const [renderStartTime, setRenderStartTime] = createSignal(0)\n // Telemetry sink (B.5 — v5.6.0). Null when no Provider is mounted.\n const telemetry = useTelemetry()\n\n // SSR-safe: Initialize performance timing on client only\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setRenderStartTime(performance.now())\n }\n })\n\n // Handle error with telemetry\n const handleError = (error: Error) => {\n // SSR-safe: Calculate render duration\n const renderDuration = !isServer && typeof performance !== 'undefined'\n ? performance.now() - renderStartTime()\n : 0\n\n // SSR-safe: Get client-only context\n const userAgent = !isServer && typeof navigator !== 'undefined'\n ? navigator.userAgent\n : 'server'\n const viewport = !isServer && typeof window !== 'undefined'\n ? { width: window.innerWidth, height: window.innerHeight }\n : { width: 0, height: 0 }\n\n // Structure error context\n const errorContext = {\n componentId: props.componentId,\n componentType: props.componentType,\n errorMessage: error.message,\n errorStack: error.stack,\n renderDuration,\n retryCount: retryKey(),\n timestamp: new Date().toISOString(),\n userAgent,\n viewport,\n }\n\n // Log to structured logger\n logger.error(`Component render failed: ${props.componentType}`, errorContext)\n\n // Call error callback\n props.onError?.({\n type: 'render',\n message: error.message,\n componentId: props.componentId,\n details: errorContext,\n })\n\n // Dispatch render:error to telemetry sink (B.5 — v5.6.0). Only the\n // message (capped semantically by the consumer if desired) — NO stack\n // trace, NO component payload, per privacy hard rule (§M.6.2).\n if (telemetry) {\n telemetry.dispatch({\n type: 'render:error',\n id: props.componentId,\n componentType: props.componentType as ComponentType,\n errorMessage: error.message,\n ts: Date.now(),\n })\n }\n\n // In production, send to monitoring service\n if (import.meta.env.PROD) {\n // Future: Send to Sentry or other APM\n // Sentry.captureException(error, { contexts: { component: errorContext } })\n }\n }\n\n // Retry mechanism\n const handleRetry = () => {\n const newRetryCount = retryKey() + 1\n logger.info(`Retrying component render: ${props.componentType}`, {\n componentId: props.componentId,\n retryCount: newRetryCount,\n })\n setRetryKey(newRetryCount)\n }\n\n return (\n <ErrorBoundary\n fallback={(error) => {\n handleError(error)\n\n // Use custom fallback if provided\n if (props.fallback) {\n return props.fallback(error, props.allowRetry ? handleRetry : undefined)\n }\n\n // Default fallback\n return (\n <DefaultErrorFallback\n error={error}\n componentId={props.componentId}\n componentType={props.componentType}\n allowRetry={props.allowRetry}\n onRetry={handleRetry}\n />\n )\n }}\n >\n {/* Key prop for forcing remount on retry */}\n {(() => {\n void retryKey() // Access signal to track changes\n return <>{props.children}</>\n })()}\n </ErrorBoundary>\n )\n}\n\n/**\n * Performance monitoring wrapper\n * Logs render times for performance analysis\n */\nexport function withPerformanceMonitoring<P extends { componentId: string; componentType: string }>(\n WrappedComponent: Component<P>\n) {\n return (props: P) => {\n const [renderStart, setRenderStart] = createSignal(0)\n\n // Log render start\n logger.debug(`Component render start: ${props.componentType}`, {\n componentId: props.componentId,\n timestamp: new Date().toISOString(),\n })\n\n // SSR-safe: Measure on mount completion (client-side only)\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setRenderStart(performance.now())\n\n requestAnimationFrame(() => {\n const renderEnd = performance.now()\n const duration = renderEnd - renderStart()\n\n logger.info(`Component rendered: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n timestamp: new Date().toISOString(),\n })\n\n // Warn if render is slow (>50ms target)\n if (duration > 50) {\n logger.warn(`Slow component render: ${props.componentType}`, {\n componentId: props.componentId,\n renderDuration: duration,\n threshold: 50,\n })\n }\n })\n }\n })\n\n return <WrappedComponent {...props} />\n }\n}\n\n/**\n * Hook to track component lifecycle events\n */\nexport function useComponentTelemetry(componentId: string, componentType: string) {\n const [mountTime, setMountTime] = createSignal(0)\n\n // SSR-safe: Initialize mount time on client only\n onMount(() => {\n if (typeof performance !== 'undefined') {\n setMountTime(performance.now())\n }\n\n // Log mount\n logger.debug(`Component mounted: ${componentType}`, {\n componentId,\n timestamp: new Date().toISOString(),\n })\n })\n\n // Return cleanup function for unmount\n return () => {\n const lifetime = !isServer && typeof performance !== 'undefined'\n ? performance.now() - mountTime()\n : 0\n logger.debug(`Component unmounted: ${componentType}`, {\n componentId,\n lifetime,\n timestamp: new Date().toISOString(),\n })\n }\n}\n"],"names":["logger","createLogger","DefaultErrorFallback","props","strings","useMCPUIStrings","_el$","_$getNextElement","_tmpl$3","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$6","_el$9","_el$0","_co$","_$getNextMarker","_el$1","_el$10","_co$2","_$insert","errorBoundaryTitle","formatMCPUIString","errorBoundaryMeta","type","componentType","unknown","id","componentId","slice","_$createComponent","Show","when","import","children","_el$7","_tmpl$","error","message","allowRetry","_el$8","_tmpl$2","_$addEventListener","onRetry","errorBoundaryRetry","_$runHydrationEvents","GenerativeUIErrorBoundary","retryKey","setRetryKey","createSignal","renderStartTime","setRenderStartTime","telemetry","useTelemetry","onMount","performance","now","handleError","renderDuration","isServer","userAgent","navigator","viewport","window","width","innerWidth","height","innerHeight","errorContext","errorMessage","errorStack","stack","retryCount","timestamp","Date","toISOString","onError","details","dispatch","ts","handleRetry","newRetryCount","info","ErrorBoundary","fallback","undefined","_$memo","_$delegateEvents"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const web = require("solid-js/web");
4
4
  const solidJs = require("solid-js");
5
- var _tmpl$ = /* @__PURE__ */ web.template(`<div class=mcp-ghost-text-overlay aria-hidden=true style=position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;overflow:hidden;white-space:pre;padding:inherit;font:inherit;line-height:inherit;letter-spacing:inherit><span style=visibility:hidden></span><span style=color:#9ca3af;opacity:0.7>`), _tmpl$2 = /* @__PURE__ */ web.template(`<div class=mcp-ghost-text-hint style="position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:0.75rem;color:#6b7280;background-color:rgba(255, 255, 255, 0.9);padding:2px 6px;border-radius:4px;pointer-events:none">`), _tmpl$3 = /* @__PURE__ */ web.template(`<div class=mcp-ghost-text-loading style=position:absolute;right:8px;top:50%;transform:translateY(-50%)><span style="display:inline-block;width:12px;height:12px;border:2px solid #e5e7eb;border-top-color:#3b82f6;border-radius:50%;animation:mcp-spin 0.6s linear infinite">`), _tmpl$4 = /* @__PURE__ */ web.template(`<div style=position:relative;display:inline-block;width:100%><!$><!/><!$><!/><!$><!/>`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class=mcp-ghost-text-input-wrapper style=position:relative><!$><!/><input style=position:relative;background-color:transparent;caret-color:inherit>`);
5
+ var _tmpl$ = /* @__PURE__ */ web.template(`<div class=mcp-ghost-text-overlay aria-hidden=true style=position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;overflow:hidden;white-space:pre;padding:inherit;font:inherit;line-height:inherit;letter-spacing:inherit><span style=visibility:hidden></span><span style="color:var(--mcp-ui-fg-subtle, #9ca3af);opacity:0.7">`), _tmpl$2 = /* @__PURE__ */ web.template(`<div class=mcp-ghost-text-hint style="position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:0.75rem;color:var(--mcp-ui-fg-muted, #6b7280);background-color:var(--mcp-ui-surface, rgba(255, 255, 255, 0.9));padding:2px 6px;border-radius:4px;pointer-events:none">`), _tmpl$3 = /* @__PURE__ */ web.template(`<div class=mcp-ghost-text-loading style=position:absolute;right:8px;top:50%;transform:translateY(-50%)><span style="display:inline-block;width:12px;height:12px;border:2px solid var(--mcp-ui-border, #e5e7eb);border-top-color:var(--mcp-ui-accent, #3b82f6);border-radius:50%;animation:mcp-spin 0.6s linear infinite">`), _tmpl$4 = /* @__PURE__ */ web.template(`<div style=position:relative;display:inline-block;width:100%><!$><!/><!$><!/><!$><!/>`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class="mcp-ui-root mcp-ghost-text-input-wrapper"style=position:relative><!$><!/><input style=position:relative;background-color:transparent;caret-color:inherit>`);
6
6
  const GhostText = (props) => {
7
7
  const shouldShow = solidJs.createMemo(() => props.visible !== false && props.ghostText && props.ghostText.length > 0);
8
8
  return (() => {
@@ -39,7 +39,7 @@ const GhostText = (props) => {
39
39
  return _el$6;
40
40
  }
41
41
  }), _el$11, _co$3);
42
- web.effect(() => web.className(_el$, `mcp-ghost-text-container ${props.class || ""}`));
42
+ web.effect(() => web.className(_el$, `mcp-ui-root mcp-ghost-text-container ${props.class || ""}`));
43
43
  return _el$;
44
44
  })();
45
45
  };
@@ -1 +1 @@
1
- {"version":3,"file":"GhostText.cjs","sources":["../../src/components/GhostText.tsx"],"sourcesContent":["/**\n * GhostText Component\n * Displays LLM-style ghost text completion overlay\n *\n * Sprint Autocomplete Feature\n */\n\nimport { Component, Show, JSX, createMemo } from 'solid-js'\n\n/**\n * Props for GhostText component\n */\nexport interface GhostTextProps {\n /**\n * Current input value\n */\n inputValue: string\n\n /**\n * Ghost text to show (the completion after input)\n */\n ghostText: string\n\n /**\n * Whether ghost text is visible\n */\n visible?: boolean\n\n /**\n * Custom class for the container\n */\n class?: string\n\n /**\n * Custom class for the ghost text\n */\n ghostClass?: string\n\n /**\n * Accept hint text (e.g., \"Tab to accept\")\n */\n hintText?: string\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n}\n\n/**\n * GhostText Component\n * Overlays ghost text on an input field to show completion suggestions\n */\nexport const GhostText: Component<GhostTextProps> = (props) => {\n const shouldShow = createMemo(() =>\n props.visible !== false && props.ghostText && props.ghostText.length > 0\n )\n\n return (\n <div\n class={`mcp-ghost-text-container ${props.class || ''}`}\n style={{\n position: 'relative',\n display: 'inline-block',\n width: '100%'\n }}\n >\n {/* Ghost text overlay */}\n <Show when={shouldShow()}>\n <div\n class=\"mcp-ghost-text-overlay\"\n style={{\n position: 'absolute',\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n 'pointer-events': 'none',\n overflow: 'hidden',\n 'white-space': 'pre',\n padding: 'inherit',\n font: 'inherit',\n 'line-height': 'inherit',\n 'letter-spacing': 'inherit'\n }}\n aria-hidden=\"true\"\n >\n {/* Invisible placeholder for input text */}\n <span style={{ visibility: 'hidden' }}>{props.inputValue}</span>\n {/* Visible ghost text */}\n <span\n class={`mcp-ghost-text ${props.ghostClass || ''}`}\n style={{\n color: '#9ca3af',\n opacity: '0.7'\n }}\n >\n {props.ghostText}\n </span>\n </div>\n </Show>\n\n {/* Hint text */}\n <Show when={shouldShow() && props.hintText}>\n <div\n class=\"mcp-ghost-text-hint\"\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)',\n 'font-size': '0.75rem',\n color: '#6b7280',\n 'background-color': 'rgba(255, 255, 255, 0.9)',\n padding: '2px 6px',\n 'border-radius': '4px',\n 'pointer-events': 'none'\n }}\n >\n {props.hintText}\n </div>\n </Show>\n\n {/* Loading indicator */}\n <Show when={props.isLoading}>\n <div\n class=\"mcp-ghost-text-loading\"\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)'\n }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '12px',\n height: '12px',\n border: '2px solid #e5e7eb',\n 'border-top-color': '#3b82f6',\n 'border-radius': '50%',\n animation: 'mcp-spin 0.6s linear infinite'\n }}\n />\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Input wrapper that includes ghost text functionality\n */\nexport interface GhostTextInputProps {\n /**\n * Current input value\n */\n value: string\n\n /**\n * Ghost text to show\n */\n ghostText: string\n\n /**\n * onChange handler\n */\n onInput?: (value: string) => void\n\n /**\n * onKeyDown handler\n */\n onKeyDown?: (e: KeyboardEvent) => void\n\n /**\n * Placeholder text\n */\n placeholder?: string\n\n /**\n * Input type\n */\n type?: 'text' | 'email' | 'search'\n\n /**\n * Whether input is disabled\n */\n disabled?: boolean\n\n /**\n * Input name\n */\n name?: string\n\n /**\n * Input ID\n */\n id?: string\n\n /**\n * Custom class for input\n */\n class?: string\n\n /**\n * Accept hint\n */\n hintText?: string\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n\n /**\n * Whether ghost text is visible\n */\n showGhost?: boolean\n\n /**\n * Additional input attributes\n */\n inputProps?: JSX.InputHTMLAttributes<HTMLInputElement>\n}\n\n/**\n * GhostTextInput Component\n * Input field with integrated ghost text overlay\n */\nexport const GhostTextInput: Component<GhostTextInputProps> = (props) => {\n return (\n <div class=\"mcp-ghost-text-input-wrapper\" style={{ position: 'relative' }}>\n <GhostText\n inputValue={props.value}\n ghostText={props.ghostText}\n visible={props.showGhost}\n hintText={props.hintText}\n isLoading={props.isLoading}\n />\n <input\n type={props.type || 'text'}\n id={props.id}\n name={props.name}\n value={props.value}\n placeholder={props.placeholder}\n disabled={props.disabled}\n class={`mcp-ghost-text-input ${props.class || ''}`}\n style={{\n position: 'relative',\n 'background-color': 'transparent',\n 'caret-color': 'inherit'\n }}\n onInput={(e) => props.onInput?.(e.currentTarget.value)}\n onKeyDown={(e) => props.onKeyDown?.(e)}\n {...(props.inputProps || {})}\n />\n </div>\n )\n}\n\nexport default GhostText\n"],"names":["GhostText","props","shouldShow","createMemo","visible","ghostText","length","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$0","_el$1","_co$2","_el$10","_el$11","_co$3","_$insert","_$createComponent","Show","when","children","_el$2","_tmpl$","_el$3","_el$4","inputValue","_$effect","_$className","ghostClass","_$memo","hintText","_el$5","_tmpl$2","isLoading","_el$6","_tmpl$3","class","GhostTextInput","_el$12","_tmpl$5","_el$14","_el$15","_co$4","_el$13","value","showGhost","$$keydown","e","onKeyDown","$$input","onInput","currentTarget","_$spread","_$mergeProps","type","id","name","placeholder","disabled","inputProps","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}
1
+ {"version":3,"file":"GhostText.cjs","sources":["../../src/components/GhostText.tsx"],"sourcesContent":["/**\n * GhostText Component\n * Displays LLM-style ghost text completion overlay\n *\n * Sprint Autocomplete Feature\n */\n\nimport { Component, Show, JSX, createMemo } from 'solid-js'\n\n/**\n * Props for GhostText component\n */\nexport interface GhostTextProps {\n /**\n * Current input value\n */\n inputValue: string\n\n /**\n * Ghost text to show (the completion after input)\n */\n ghostText: string\n\n /**\n * Whether ghost text is visible\n */\n visible?: boolean\n\n /**\n * Custom class for the container\n */\n class?: string\n\n /**\n * Custom class for the ghost text\n */\n ghostClass?: string\n\n /**\n * Accept hint text (e.g., \"Tab to accept\")\n */\n hintText?: string\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n}\n\n/**\n * GhostText Component\n * Overlays ghost text on an input field to show completion suggestions\n */\nexport const GhostText: Component<GhostTextProps> = (props) => {\n const shouldShow = createMemo(() =>\n props.visible !== false && props.ghostText && props.ghostText.length > 0\n )\n\n return (\n <div\n class={`mcp-ui-root mcp-ghost-text-container ${props.class || ''}`}\n style={{\n position: 'relative',\n display: 'inline-block',\n width: '100%'\n }}\n >\n {/* Ghost text overlay */}\n <Show when={shouldShow()}>\n <div\n class=\"mcp-ghost-text-overlay\"\n style={{\n position: 'absolute',\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n 'pointer-events': 'none',\n overflow: 'hidden',\n 'white-space': 'pre',\n padding: 'inherit',\n font: 'inherit',\n 'line-height': 'inherit',\n 'letter-spacing': 'inherit'\n }}\n aria-hidden=\"true\"\n >\n {/* Invisible placeholder for input text */}\n <span style={{ visibility: 'hidden' }}>{props.inputValue}</span>\n {/* Visible ghost text */}\n <span\n class={`mcp-ghost-text ${props.ghostClass || ''}`}\n style={{\n color: 'var(--mcp-ui-fg-subtle, #9ca3af)',\n opacity: '0.7'\n }}\n >\n {props.ghostText}\n </span>\n </div>\n </Show>\n\n {/* Hint text */}\n <Show when={shouldShow() && props.hintText}>\n <div\n class=\"mcp-ghost-text-hint\"\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)',\n 'font-size': '0.75rem',\n color: 'var(--mcp-ui-fg-muted, #6b7280)',\n 'background-color': 'var(--mcp-ui-surface, rgba(255, 255, 255, 0.9))',\n padding: '2px 6px',\n 'border-radius': '4px',\n 'pointer-events': 'none'\n }}\n >\n {props.hintText}\n </div>\n </Show>\n\n {/* Loading indicator */}\n <Show when={props.isLoading}>\n <div\n class=\"mcp-ghost-text-loading\"\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)'\n }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '12px',\n height: '12px',\n border: '2px solid var(--mcp-ui-border, #e5e7eb)',\n 'border-top-color': 'var(--mcp-ui-accent, #3b82f6)',\n 'border-radius': '50%',\n animation: 'mcp-spin 0.6s linear infinite'\n }}\n />\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Input wrapper that includes ghost text functionality\n */\nexport interface GhostTextInputProps {\n /**\n * Current input value\n */\n value: string\n\n /**\n * Ghost text to show\n */\n ghostText: string\n\n /**\n * onChange handler\n */\n onInput?: (value: string) => void\n\n /**\n * onKeyDown handler\n */\n onKeyDown?: (e: KeyboardEvent) => void\n\n /**\n * Placeholder text\n */\n placeholder?: string\n\n /**\n * Input type\n */\n type?: 'text' | 'email' | 'search'\n\n /**\n * Whether input is disabled\n */\n disabled?: boolean\n\n /**\n * Input name\n */\n name?: string\n\n /**\n * Input ID\n */\n id?: string\n\n /**\n * Custom class for input\n */\n class?: string\n\n /**\n * Accept hint\n */\n hintText?: string\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n\n /**\n * Whether ghost text is visible\n */\n showGhost?: boolean\n\n /**\n * Additional input attributes\n */\n inputProps?: JSX.InputHTMLAttributes<HTMLInputElement>\n}\n\n/**\n * GhostTextInput Component\n * Input field with integrated ghost text overlay\n */\nexport const GhostTextInput: Component<GhostTextInputProps> = (props) => {\n return (\n <div class=\"mcp-ui-root mcp-ghost-text-input-wrapper\" style={{ position: 'relative' }}>\n <GhostText\n inputValue={props.value}\n ghostText={props.ghostText}\n visible={props.showGhost}\n hintText={props.hintText}\n isLoading={props.isLoading}\n />\n <input\n type={props.type || 'text'}\n id={props.id}\n name={props.name}\n value={props.value}\n placeholder={props.placeholder}\n disabled={props.disabled}\n class={`mcp-ghost-text-input ${props.class || ''}`}\n style={{\n position: 'relative',\n 'background-color': 'transparent',\n 'caret-color': 'inherit'\n }}\n onInput={(e) => props.onInput?.(e.currentTarget.value)}\n onKeyDown={(e) => props.onKeyDown?.(e)}\n {...(props.inputProps || {})}\n />\n </div>\n )\n}\n\nexport default GhostText\n"],"names":["GhostText","props","shouldShow","createMemo","visible","ghostText","length","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$0","_el$1","_co$2","_el$10","_el$11","_co$3","_$insert","_$createComponent","Show","when","children","_el$2","_tmpl$","_el$3","_el$4","inputValue","_$effect","_$className","ghostClass","_$memo","hintText","_el$5","_tmpl$2","isLoading","_el$6","_tmpl$3","class","GhostTextInput","_el$12","_tmpl$5","_el$14","_el$15","_co$4","_el$13","value","showGhost","$$keydown","e","onKeyDown","$$input","onInput","currentTarget","_$spread","_$mergeProps","type","id","name","placeholder","disabled","inputProps","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { getNextElement, getNextMarker, insert, createComponent, effect, className, memo, spread, mergeProps, runHydrationEvents, template, delegateEvents } from "solid-js/web";
2
2
  import { createMemo, Show } from "solid-js";
3
- var _tmpl$ = /* @__PURE__ */ template(`<div class=mcp-ghost-text-overlay aria-hidden=true style=position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;overflow:hidden;white-space:pre;padding:inherit;font:inherit;line-height:inherit;letter-spacing:inherit><span style=visibility:hidden></span><span style=color:#9ca3af;opacity:0.7>`), _tmpl$2 = /* @__PURE__ */ template(`<div class=mcp-ghost-text-hint style="position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:0.75rem;color:#6b7280;background-color:rgba(255, 255, 255, 0.9);padding:2px 6px;border-radius:4px;pointer-events:none">`), _tmpl$3 = /* @__PURE__ */ template(`<div class=mcp-ghost-text-loading style=position:absolute;right:8px;top:50%;transform:translateY(-50%)><span style="display:inline-block;width:12px;height:12px;border:2px solid #e5e7eb;border-top-color:#3b82f6;border-radius:50%;animation:mcp-spin 0.6s linear infinite">`), _tmpl$4 = /* @__PURE__ */ template(`<div style=position:relative;display:inline-block;width:100%><!$><!/><!$><!/><!$><!/>`), _tmpl$5 = /* @__PURE__ */ template(`<div class=mcp-ghost-text-input-wrapper style=position:relative><!$><!/><input style=position:relative;background-color:transparent;caret-color:inherit>`);
3
+ var _tmpl$ = /* @__PURE__ */ template(`<div class=mcp-ghost-text-overlay aria-hidden=true style=position:absolute;top:0;left:0;right:0;bottom:0;pointer-events:none;overflow:hidden;white-space:pre;padding:inherit;font:inherit;line-height:inherit;letter-spacing:inherit><span style=visibility:hidden></span><span style="color:var(--mcp-ui-fg-subtle, #9ca3af);opacity:0.7">`), _tmpl$2 = /* @__PURE__ */ template(`<div class=mcp-ghost-text-hint style="position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:0.75rem;color:var(--mcp-ui-fg-muted, #6b7280);background-color:var(--mcp-ui-surface, rgba(255, 255, 255, 0.9));padding:2px 6px;border-radius:4px;pointer-events:none">`), _tmpl$3 = /* @__PURE__ */ template(`<div class=mcp-ghost-text-loading style=position:absolute;right:8px;top:50%;transform:translateY(-50%)><span style="display:inline-block;width:12px;height:12px;border:2px solid var(--mcp-ui-border, #e5e7eb);border-top-color:var(--mcp-ui-accent, #3b82f6);border-radius:50%;animation:mcp-spin 0.6s linear infinite">`), _tmpl$4 = /* @__PURE__ */ template(`<div style=position:relative;display:inline-block;width:100%><!$><!/><!$><!/><!$><!/>`), _tmpl$5 = /* @__PURE__ */ template(`<div class="mcp-ui-root mcp-ghost-text-input-wrapper"style=position:relative><!$><!/><input style=position:relative;background-color:transparent;caret-color:inherit>`);
4
4
  const GhostText = (props) => {
5
5
  const shouldShow = createMemo(() => props.visible !== false && props.ghostText && props.ghostText.length > 0);
6
6
  return (() => {
@@ -37,7 +37,7 @@ const GhostText = (props) => {
37
37
  return _el$6;
38
38
  }
39
39
  }), _el$11, _co$3);
40
- effect(() => className(_el$, `mcp-ghost-text-container ${props.class || ""}`));
40
+ effect(() => className(_el$, `mcp-ui-root mcp-ghost-text-container ${props.class || ""}`));
41
41
  return _el$;
42
42
  })();
43
43
  };
@@ -1 +1 @@
1
- {"version":3,"file":"GhostText.js","sources":["../../src/components/GhostText.tsx"],"sourcesContent":["/**\n * GhostText Component\n * Displays LLM-style ghost text completion overlay\n *\n * Sprint Autocomplete Feature\n */\n\nimport { Component, Show, JSX, createMemo } from 'solid-js'\n\n/**\n * Props for GhostText component\n */\nexport interface GhostTextProps {\n /**\n * Current input value\n */\n inputValue: string\n\n /**\n * Ghost text to show (the completion after input)\n */\n ghostText: string\n\n /**\n * Whether ghost text is visible\n */\n visible?: boolean\n\n /**\n * Custom class for the container\n */\n class?: string\n\n /**\n * Custom class for the ghost text\n */\n ghostClass?: string\n\n /**\n * Accept hint text (e.g., \"Tab to accept\")\n */\n hintText?: string\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n}\n\n/**\n * GhostText Component\n * Overlays ghost text on an input field to show completion suggestions\n */\nexport const GhostText: Component<GhostTextProps> = (props) => {\n const shouldShow = createMemo(() =>\n props.visible !== false && props.ghostText && props.ghostText.length > 0\n )\n\n return (\n <div\n class={`mcp-ghost-text-container ${props.class || ''}`}\n style={{\n position: 'relative',\n display: 'inline-block',\n width: '100%'\n }}\n >\n {/* Ghost text overlay */}\n <Show when={shouldShow()}>\n <div\n class=\"mcp-ghost-text-overlay\"\n style={{\n position: 'absolute',\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n 'pointer-events': 'none',\n overflow: 'hidden',\n 'white-space': 'pre',\n padding: 'inherit',\n font: 'inherit',\n 'line-height': 'inherit',\n 'letter-spacing': 'inherit'\n }}\n aria-hidden=\"true\"\n >\n {/* Invisible placeholder for input text */}\n <span style={{ visibility: 'hidden' }}>{props.inputValue}</span>\n {/* Visible ghost text */}\n <span\n class={`mcp-ghost-text ${props.ghostClass || ''}`}\n style={{\n color: '#9ca3af',\n opacity: '0.7'\n }}\n >\n {props.ghostText}\n </span>\n </div>\n </Show>\n\n {/* Hint text */}\n <Show when={shouldShow() && props.hintText}>\n <div\n class=\"mcp-ghost-text-hint\"\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)',\n 'font-size': '0.75rem',\n color: '#6b7280',\n 'background-color': 'rgba(255, 255, 255, 0.9)',\n padding: '2px 6px',\n 'border-radius': '4px',\n 'pointer-events': 'none'\n }}\n >\n {props.hintText}\n </div>\n </Show>\n\n {/* Loading indicator */}\n <Show when={props.isLoading}>\n <div\n class=\"mcp-ghost-text-loading\"\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)'\n }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '12px',\n height: '12px',\n border: '2px solid #e5e7eb',\n 'border-top-color': '#3b82f6',\n 'border-radius': '50%',\n animation: 'mcp-spin 0.6s linear infinite'\n }}\n />\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Input wrapper that includes ghost text functionality\n */\nexport interface GhostTextInputProps {\n /**\n * Current input value\n */\n value: string\n\n /**\n * Ghost text to show\n */\n ghostText: string\n\n /**\n * onChange handler\n */\n onInput?: (value: string) => void\n\n /**\n * onKeyDown handler\n */\n onKeyDown?: (e: KeyboardEvent) => void\n\n /**\n * Placeholder text\n */\n placeholder?: string\n\n /**\n * Input type\n */\n type?: 'text' | 'email' | 'search'\n\n /**\n * Whether input is disabled\n */\n disabled?: boolean\n\n /**\n * Input name\n */\n name?: string\n\n /**\n * Input ID\n */\n id?: string\n\n /**\n * Custom class for input\n */\n class?: string\n\n /**\n * Accept hint\n */\n hintText?: string\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n\n /**\n * Whether ghost text is visible\n */\n showGhost?: boolean\n\n /**\n * Additional input attributes\n */\n inputProps?: JSX.InputHTMLAttributes<HTMLInputElement>\n}\n\n/**\n * GhostTextInput Component\n * Input field with integrated ghost text overlay\n */\nexport const GhostTextInput: Component<GhostTextInputProps> = (props) => {\n return (\n <div class=\"mcp-ghost-text-input-wrapper\" style={{ position: 'relative' }}>\n <GhostText\n inputValue={props.value}\n ghostText={props.ghostText}\n visible={props.showGhost}\n hintText={props.hintText}\n isLoading={props.isLoading}\n />\n <input\n type={props.type || 'text'}\n id={props.id}\n name={props.name}\n value={props.value}\n placeholder={props.placeholder}\n disabled={props.disabled}\n class={`mcp-ghost-text-input ${props.class || ''}`}\n style={{\n position: 'relative',\n 'background-color': 'transparent',\n 'caret-color': 'inherit'\n }}\n onInput={(e) => props.onInput?.(e.currentTarget.value)}\n onKeyDown={(e) => props.onKeyDown?.(e)}\n {...(props.inputProps || {})}\n />\n </div>\n )\n}\n\nexport default GhostText\n"],"names":["GhostText","props","shouldShow","createMemo","visible","ghostText","length","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$0","_el$1","_co$2","_el$10","_el$11","_co$3","_$insert","_$createComponent","Show","when","children","_el$2","_tmpl$","_el$3","_el$4","inputValue","_$effect","_$className","ghostClass","_$memo","hintText","_el$5","_tmpl$2","isLoading","_el$6","_tmpl$3","class","GhostTextInput","_el$12","_tmpl$5","_el$14","_el$15","_co$4","_el$13","value","showGhost","$$keydown","e","onKeyDown","$$input","onInput","currentTarget","_$spread","_$mergeProps","type","id","name","placeholder","disabled","inputProps","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}
1
+ {"version":3,"file":"GhostText.js","sources":["../../src/components/GhostText.tsx"],"sourcesContent":["/**\n * GhostText Component\n * Displays LLM-style ghost text completion overlay\n *\n * Sprint Autocomplete Feature\n */\n\nimport { Component, Show, JSX, createMemo } from 'solid-js'\n\n/**\n * Props for GhostText component\n */\nexport interface GhostTextProps {\n /**\n * Current input value\n */\n inputValue: string\n\n /**\n * Ghost text to show (the completion after input)\n */\n ghostText: string\n\n /**\n * Whether ghost text is visible\n */\n visible?: boolean\n\n /**\n * Custom class for the container\n */\n class?: string\n\n /**\n * Custom class for the ghost text\n */\n ghostClass?: string\n\n /**\n * Accept hint text (e.g., \"Tab to accept\")\n */\n hintText?: string\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n}\n\n/**\n * GhostText Component\n * Overlays ghost text on an input field to show completion suggestions\n */\nexport const GhostText: Component<GhostTextProps> = (props) => {\n const shouldShow = createMemo(() =>\n props.visible !== false && props.ghostText && props.ghostText.length > 0\n )\n\n return (\n <div\n class={`mcp-ui-root mcp-ghost-text-container ${props.class || ''}`}\n style={{\n position: 'relative',\n display: 'inline-block',\n width: '100%'\n }}\n >\n {/* Ghost text overlay */}\n <Show when={shouldShow()}>\n <div\n class=\"mcp-ghost-text-overlay\"\n style={{\n position: 'absolute',\n top: '0',\n left: '0',\n right: '0',\n bottom: '0',\n 'pointer-events': 'none',\n overflow: 'hidden',\n 'white-space': 'pre',\n padding: 'inherit',\n font: 'inherit',\n 'line-height': 'inherit',\n 'letter-spacing': 'inherit'\n }}\n aria-hidden=\"true\"\n >\n {/* Invisible placeholder for input text */}\n <span style={{ visibility: 'hidden' }}>{props.inputValue}</span>\n {/* Visible ghost text */}\n <span\n class={`mcp-ghost-text ${props.ghostClass || ''}`}\n style={{\n color: 'var(--mcp-ui-fg-subtle, #9ca3af)',\n opacity: '0.7'\n }}\n >\n {props.ghostText}\n </span>\n </div>\n </Show>\n\n {/* Hint text */}\n <Show when={shouldShow() && props.hintText}>\n <div\n class=\"mcp-ghost-text-hint\"\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)',\n 'font-size': '0.75rem',\n color: 'var(--mcp-ui-fg-muted, #6b7280)',\n 'background-color': 'var(--mcp-ui-surface, rgba(255, 255, 255, 0.9))',\n padding: '2px 6px',\n 'border-radius': '4px',\n 'pointer-events': 'none'\n }}\n >\n {props.hintText}\n </div>\n </Show>\n\n {/* Loading indicator */}\n <Show when={props.isLoading}>\n <div\n class=\"mcp-ghost-text-loading\"\n style={{\n position: 'absolute',\n right: '8px',\n top: '50%',\n transform: 'translateY(-50%)'\n }}\n >\n <span\n style={{\n display: 'inline-block',\n width: '12px',\n height: '12px',\n border: '2px solid var(--mcp-ui-border, #e5e7eb)',\n 'border-top-color': 'var(--mcp-ui-accent, #3b82f6)',\n 'border-radius': '50%',\n animation: 'mcp-spin 0.6s linear infinite'\n }}\n />\n </div>\n </Show>\n </div>\n )\n}\n\n/**\n * Input wrapper that includes ghost text functionality\n */\nexport interface GhostTextInputProps {\n /**\n * Current input value\n */\n value: string\n\n /**\n * Ghost text to show\n */\n ghostText: string\n\n /**\n * onChange handler\n */\n onInput?: (value: string) => void\n\n /**\n * onKeyDown handler\n */\n onKeyDown?: (e: KeyboardEvent) => void\n\n /**\n * Placeholder text\n */\n placeholder?: string\n\n /**\n * Input type\n */\n type?: 'text' | 'email' | 'search'\n\n /**\n * Whether input is disabled\n */\n disabled?: boolean\n\n /**\n * Input name\n */\n name?: string\n\n /**\n * Input ID\n */\n id?: string\n\n /**\n * Custom class for input\n */\n class?: string\n\n /**\n * Accept hint\n */\n hintText?: string\n\n /**\n * Whether loading\n */\n isLoading?: boolean\n\n /**\n * Whether ghost text is visible\n */\n showGhost?: boolean\n\n /**\n * Additional input attributes\n */\n inputProps?: JSX.InputHTMLAttributes<HTMLInputElement>\n}\n\n/**\n * GhostTextInput Component\n * Input field with integrated ghost text overlay\n */\nexport const GhostTextInput: Component<GhostTextInputProps> = (props) => {\n return (\n <div class=\"mcp-ui-root mcp-ghost-text-input-wrapper\" style={{ position: 'relative' }}>\n <GhostText\n inputValue={props.value}\n ghostText={props.ghostText}\n visible={props.showGhost}\n hintText={props.hintText}\n isLoading={props.isLoading}\n />\n <input\n type={props.type || 'text'}\n id={props.id}\n name={props.name}\n value={props.value}\n placeholder={props.placeholder}\n disabled={props.disabled}\n class={`mcp-ghost-text-input ${props.class || ''}`}\n style={{\n position: 'relative',\n 'background-color': 'transparent',\n 'caret-color': 'inherit'\n }}\n onInput={(e) => props.onInput?.(e.currentTarget.value)}\n onKeyDown={(e) => props.onKeyDown?.(e)}\n {...(props.inputProps || {})}\n />\n </div>\n )\n}\n\nexport default GhostText\n"],"names":["GhostText","props","shouldShow","createMemo","visible","ghostText","length","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$0","_el$1","_co$2","_el$10","_el$11","_co$3","_$insert","_$createComponent","Show","when","children","_el$2","_tmpl$","_el$3","_el$4","inputValue","_$effect","_$className","ghostClass","_$memo","hintText","_el$5","_tmpl$2","isLoading","_el$6","_tmpl$3","class","GhostTextInput","_el$12","_tmpl$5","_el$14","_el$15","_co$4","_el$13","value","showGhost","$$keydown","e","onKeyDown","$$input","onInput","currentTarget","_$spread","_$mergeProps","type","id","name","placeholder","disabled","inputProps","_$runHydrationEvents","_$delegateEvents"],"mappings":"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"}