@burdenoff/microfe-vibecontrols 2026.601.21 → 2026.601.23

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 (44) hide show
  1. package/dist/components/actions/ActionCard.js +77 -66
  2. package/dist/components/actions/ActionCard.js.map +1 -1
  3. package/dist/components/ai/AIContextsTab.js +186 -173
  4. package/dist/components/ai/AIContextsTab.js.map +1 -1
  5. package/dist/components/ai/AITemplatesTab.js +135 -125
  6. package/dist/components/ai/AITemplatesTab.js.map +1 -1
  7. package/dist/components/ai/InstructionFilesManager.js +151 -137
  8. package/dist/components/ai/InstructionFilesManager.js.map +1 -1
  9. package/dist/components/docs/DocsEditPanel.js +17 -16
  10. package/dist/components/docs/DocsEditPanel.js.map +1 -1
  11. package/dist/components/docs/DocsPreviewPanel.js +25 -24
  12. package/dist/components/docs/DocsPreviewPanel.js.map +1 -1
  13. package/dist/components/docs/DocsTabPanel.js +110 -94
  14. package/dist/components/docs/DocsTabPanel.js.map +1 -1
  15. package/dist/components/notes/NotesTabPanel.js +8 -8
  16. package/dist/components/scorecard/ScorecardPanel.js +271 -257
  17. package/dist/components/scorecard/ScorecardPanel.js.map +1 -1
  18. package/dist/components/sharing/EntityShareButton.js +58 -0
  19. package/dist/components/sharing/EntityShareButton.js.map +1 -0
  20. package/dist/components/sharing/entityShareOps.js +603 -0
  21. package/dist/components/sharing/entityShareOps.js.map +1 -0
  22. package/dist/components/sharing/index.js +3 -0
  23. package/dist/components/sharing/shareRegistry.js +37 -12
  24. package/dist/components/sharing/shareRegistry.js.map +1 -1
  25. package/dist/components/sharing/useEntityShareController.js +88 -0
  26. package/dist/components/sharing/useEntityShareController.js.map +1 -0
  27. package/dist/constants/permissions.js +11 -0
  28. package/dist/constants/permissions.js.map +1 -1
  29. package/dist/pages/ActionsPage.js +162 -162
  30. package/dist/pages/ActionsPage.js.map +1 -1
  31. package/dist/pages/CatalogDetailPage.js +264 -250
  32. package/dist/pages/CatalogDetailPage.js.map +1 -1
  33. package/dist/pages/ComponentDetailPage.js +124 -113
  34. package/dist/pages/ComponentDetailPage.js.map +1 -1
  35. package/dist/pages/TargetDetailsPage.js +139 -126
  36. package/dist/pages/TargetDetailsPage.js.map +1 -1
  37. package/dist/pages/TemplateDetailPage.js +78 -67
  38. package/dist/pages/TemplateDetailPage.js.map +1 -1
  39. package/dist/pages/VibeDeckPage.js +1 -1
  40. package/dist/pages/VibeDetailsPage.js +484 -484
  41. package/dist/pages/VibeDetailsPage.js.map +1 -1
  42. package/dist/pages/tunnels/TunnelDetailsPage.js +91 -77
  43. package/dist/pages/tunnels/TunnelDetailsPage.js.map +1 -1
  44. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AITemplatesTab.js","names":[],"sources":["../../../src/components/ai/AITemplatesTab.tsx"],"sourcesContent":["import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { Plus, Search, Pencil, Trash2, Eye, Code, X } from 'lucide-react';\nimport {\n Card,\n LoadingState,\n ErrorState,\n EmptyState,\n ConfirmDialog,\n SelectionCheckbox,\n} from '@/components/shared';\nimport type { AITemplate } from '@/services/aiApi';\nimport {\n fetchTemplates,\n createTemplate,\n updateTemplate,\n deleteTemplate,\n renderTemplate,\n} from '@/services/aiApi';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface AITemplatesTabProps {\n agentId: string;\n}\n\ninterface TemplateFormData {\n name: string;\n content: string;\n description: string;\n variables: Record<string, unknown>;\n tags: string[];\n}\n\nconst emptyForm: TemplateFormData = {\n name: '',\n content: '',\n description: '',\n variables: {},\n tags: [],\n};\n\nexport function AITemplatesTab({ agentId }: AITemplatesTabProps) {\n const tr = useTr();\n const [templates, setTemplates] = useState<AITemplate[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [search, setSearch] = useState('');\n const [showForm, setShowForm] = useState(false);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [formData, setFormData] = useState<TemplateFormData>(emptyForm);\n const [variablesMode, setVariablesMode] = useState<'form' | 'json'>('form');\n const [variablesJson, setVariablesJson] = useState('{}');\n const [saving, setSaving] = useState(false);\n const [deleteIds, setDeleteIds] = useState<string[]>([]);\n const [deleting, setDeleting] = useState(false);\n const [selectedTemplateIds, setSelectedTemplateIds] = useState<Set<string>>(new Set());\n const [previewId, setPreviewId] = useState<string | null>(null);\n const [previewVars, setPreviewVars] = useState<Record<string, string>>({});\n const [previewResult, setPreviewResult] = useState<string | null>(null);\n const [previewing, setPreviewing] = useState(false);\n\n const loadTemplates = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await fetchTemplates(agentId);\n setTemplates(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load templates');\n } finally {\n setLoading(false);\n }\n }, [agentId]);\n\n useEffect(() => {\n loadTemplates();\n }, [loadTemplates]);\n\n const filtered = templates.filter((t) => {\n if (!search) return true;\n const q = search.toLowerCase();\n return (\n t.name.toLowerCase().includes(q) ||\n t.description?.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q))\n );\n });\n\n const selectedTemplates = useMemo(\n () => templates.filter((template) => selectedTemplateIds.has(template.id)),\n [templates, selectedTemplateIds]\n );\n const allVisibleSelected =\n filtered.length > 0 && filtered.every((template) => selectedTemplateIds.has(template.id));\n const partiallySelected =\n filtered.some((template) => selectedTemplateIds.has(template.id)) && !allVisibleSelected;\n\n const openCreate = () => {\n setEditingId(null);\n setFormData(emptyForm);\n setVariablesJson('{}');\n setShowForm(true);\n };\n\n const openEdit = (t: AITemplate) => {\n setEditingId(t.id);\n setFormData({\n name: t.name,\n content: t.content,\n description: t.description ?? '',\n variables: t.variables ?? {},\n tags: t.tags ?? [],\n });\n setVariablesJson(JSON.stringify(t.variables ?? {}, null, 2));\n setShowForm(true);\n };\n\n const handleSave = async () => {\n setSaving(true);\n try {\n const vars = variablesMode === 'json' ? JSON.parse(variablesJson) : formData.variables;\n const payload = { ...formData, variables: vars };\n if (editingId) {\n await updateTemplate(agentId, editingId, payload);\n } else {\n await createTemplate(agentId, payload);\n }\n setShowForm(false);\n await loadTemplates();\n } catch (err) {\n console.error('Failed to save template:', err);\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async () => {\n if (deleteIds.length === 0) return;\n setDeleting(true);\n try {\n await Promise.allSettled(deleteIds.map((deleteId) => deleteTemplate(agentId, deleteId)));\n setSelectedTemplateIds((prev) => {\n const next = new Set(prev);\n deleteIds.forEach((deleteId) => next.delete(deleteId));\n return next;\n });\n setDeleteIds([]);\n await loadTemplates();\n } catch (err) {\n console.error('Failed to delete template:', err);\n } finally {\n setDeleting(false);\n }\n };\n\n const handlePreview = async () => {\n if (!previewId) return;\n setPreviewing(true);\n try {\n const result = await renderTemplate(agentId, previewId, previewVars);\n setPreviewResult(result.rendered);\n } catch (err) {\n setPreviewResult(\n `Error: ${err instanceof Error ? err.message : 'Failed to render template'}`\n );\n } finally {\n setPreviewing(false);\n }\n };\n\n const openPreview = (t: AITemplate) => {\n setPreviewId(t.id);\n const vars: Record<string, string> = {};\n if (t.variables) {\n for (const key of Object.keys(t.variables)) {\n vars[key] = '';\n }\n }\n setPreviewVars(vars);\n setPreviewResult(null);\n };\n\n // Variable form helpers\n const addVariable = () => {\n setFormData((prev) => ({\n ...prev,\n variables: { ...prev.variables, '': '' },\n }));\n };\n\n const updateVariableKey = (oldKey: string, newKey: string) => {\n const entries = Object.entries(formData.variables);\n const updated: Record<string, unknown> = {};\n for (const [k, v] of entries) {\n updated[k === oldKey ? newKey : k] = v;\n }\n setFormData((prev) => ({ ...prev, variables: updated }));\n };\n\n const updateVariableValue = (key: string, value: string) => {\n setFormData((prev) => ({\n ...prev,\n variables: { ...prev.variables, [key]: value },\n }));\n };\n\n const removeVariable = (key: string) => {\n const rest = { ...formData.variables };\n delete rest[key];\n setFormData((prev) => ({ ...prev, variables: rest }));\n };\n\n const toggleTemplateSelection = (templateId: string, checked: boolean) => {\n setSelectedTemplateIds((prev) => {\n const next = new Set(prev);\n if (checked) {\n next.add(templateId);\n } else {\n next.delete(templateId);\n }\n return next;\n });\n };\n\n const toggleAllVisibleTemplates = (checked: boolean) => {\n setSelectedTemplateIds((prev) => {\n const next = new Set(prev);\n filtered.forEach((template) => {\n if (checked) {\n next.add(template.id);\n } else {\n next.delete(template.id);\n }\n });\n return next;\n });\n };\n\n const clearSelection = () => setSelectedTemplateIds(new Set());\n\n if (loading)\n return (\n <LoadingState message={tr('vibecontrols.ai.templates.loading', 'Loading templates...')} />\n );\n if (error)\n return (\n <ErrorState\n title={tr('vibecontrols.ai.templates.loadFailed', 'Failed to load templates')}\n message={error}\n onRetry={loadTemplates}\n />\n );\n\n return (\n <div className=\"space-y-4\">\n {/* Toolbar */}\n <div className=\"flex flex-col sm:flex-row items-stretch sm:items-center gap-2\">\n <div className=\"relative flex-1 sm:max-w-xs\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 size-4 text-text-secondary\" />\n <input\n aria-label=\"control\"\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={tr('vibecontrols.ai.templates.searchPlaceholder', 'Search templates...')}\n className=\"w-full pl-9 pr-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm placeholder:text-text-placeholder focus:outline-none focus:border-border-strong\"\n />\n </div>\n <button\n type=\"button\"\n onClick={openCreate}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors text-sm\"\n >\n <Plus className=\"size-4\" />\n {tr('vibecontrols.ai.templates.newTemplate', 'New Template')}\n </button>\n </div>\n\n {filtered.length > 0 && (\n <div className=\"rounded-lg border border-border-default bg-bg-surface p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"flex items-center gap-2\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllVisibleTemplates}\n ariaLabel=\"Select all visible templates\"\n />\n <span className=\"text-sm font-medium text-text-primary\">Select all visible</span>\n </div>\n {selectedTemplateIds.size > 0 && (\n <button\n type=\"button\"\n onClick={clearSelection}\n className=\"text-sm text-text-secondary hover:text-text-primary\"\n >\n Clear selection\n </button>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded-full bg-bg-sunken px-3 py-1 text-sm font-medium text-text-secondary\">\n {selectedTemplateIds.size} selected\n </span>\n <button\n type=\"button\"\n onClick={() => setDeleteIds(selectedTemplates.map((template) => template.id))}\n disabled={selectedTemplates.length === 0}\n className=\"rounded-md border border-status-error-border px-3 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg disabled:cursor-not-allowed disabled:opacity-50\"\n >\n Delete Selected\n {selectedTemplates.length > 0 ? ` (${selectedTemplates.length})` : ''}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Template List */}\n {filtered.length === 0 ? (\n <EmptyState\n icon={<Code className=\"size-8 text-text-secondary\" />}\n title={\n search\n ? tr('vibecontrols.ai.templates.noMatch', 'No templates match your search')\n : tr('vibecontrols.ai.templates.emptyTitle', 'No templates yet')\n }\n description={\n search\n ? tr('vibecontrols.ai.templates.adjustSearch', 'Try adjusting your search query')\n : tr(\n 'vibecontrols.ai.templates.emptyDescription',\n 'Create your first prompt template to get started'\n )\n }\n action={\n !search ? (\n <button\n type=\"button\"\n onClick={openCreate}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"size-4\" />\n New Template\n </button>\n ) : undefined\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {filtered.map((t) => (\n <Card\n key={t.id}\n className={`p-4 ${selectedTemplateIds.has(t.id) ? 'border-action-primary-bg ring-1 ring-action-primary-bg/25' : ''}`}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-start gap-3 min-w-0 flex-1\">\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selectedTemplateIds.has(t.id)}\n onChange={(checked) => toggleTemplateSelection(t.id, checked)}\n ariaLabel={`Select template ${t.name}`}\n />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h4 className=\"font-semibold text-text-primary truncate\">{t.name}</h4>\n {t.description && (\n <p className=\"text-xs text-text-secondary mt-0.5 line-clamp-2\">\n {t.description}\n </p>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-1 flex-shrink-0\">\n <button\n type=\"button\"\n onClick={() => openPreview(t)}\n className=\"p-1.5 hover:bg-bg-sunken rounded-md transition-colors\"\n title=\"Preview\"\n >\n <Eye className=\"size-3.5 text-text-secondary\" />\n </button>\n <button\n type=\"button\"\n onClick={() => openEdit(t)}\n className=\"p-1.5 hover:bg-bg-sunken rounded-md transition-colors\"\n title=\"Edit\"\n >\n <Pencil className=\"size-3.5 text-text-secondary\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setDeleteIds([t.id])}\n className=\"p-1.5 hover:bg-status-error-bg rounded-md transition-colors\"\n title=\"Delete\"\n >\n <Trash2 className=\"size-3.5 text-status-error-text\" />\n </button>\n </div>\n </div>\n <pre className=\"mt-2 text-xs text-text-secondary bg-bg-sunken rounded p-2 max-h-24 overflow-auto whitespace-pre-wrap\">\n {t.content}\n </pre>\n {t.tags && t.tags.length > 0 && (\n <div className=\"mt-2 flex flex-wrap gap-1\">\n {t.tags.map((tag) => (\n <span\n key={tag}\n className=\"px-1.5 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </Card>\n ))}\n </div>\n )}\n\n {/* Create/Edit Dialog */}\n {showForm && (\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => setShowForm(false))();\n }\n }}\n className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-50 p-4\"\n onClick={() => setShowForm(false)}\n >\n <div\n className=\"bg-bg-surface border border-border-default rounded-lg shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto p-6\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {editingId\n ? tr('vibecontrols.ai.templates.editTemplate', 'Edit Template')\n : tr('vibecontrols.ai.templates.newTemplate', 'New Template')}\n </h3>\n <button\n type=\"button\"\n onClick={() => setShowForm(false)}\n className=\"p-1 hover:bg-bg-sunken rounded-md\"\n >\n <X className=\"size-4 text-text-secondary\" />\n </button>\n </div>\n\n <div className=\"space-y-4\">\n <div>\n <label\n htmlFor=\"aitemplatestab-11\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Name\n </label>\n <input\n id=\"aitemplatestab-11\"\n aria-label=\"Template name\"\n type=\"text\"\n value={formData.name}\n onChange={(e) => setFormData({ ...formData, name: e.target.value })}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm focus:outline-none focus:border-border-strong\"\n placeholder=\"Template name\"\n />\n </div>\n <div>\n <label\n htmlFor=\"aitemplatestab-10\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Description\n </label>\n <input\n id=\"aitemplatestab-10\"\n aria-label=\"Brief description\"\n type=\"text\"\n value={formData.description}\n onChange={(e) => setFormData({ ...formData, description: e.target.value })}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm focus:outline-none focus:border-border-strong\"\n placeholder=\"Brief description\"\n />\n </div>\n <div>\n <label\n htmlFor=\"aitemplatestab-9\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Content\n </label>\n <textarea\n id=\"aitemplatestab-9\"\n aria-label=\"Use {{variable}} for template variables\"\n value={formData.content}\n onChange={(e) => setFormData({ ...formData, content: e.target.value })}\n rows={6}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm font-mono focus:outline-none focus:border-border-strong\"\n placeholder=\"Use {{variable}} for template variables\"\n />\n </div>\n\n {/* Variables Editor */}\n <div>\n <div className=\"flex items-center justify-between mb-1\">\n <label\n htmlFor=\"aitemplatestab-8\"\n className=\"text-sm font-medium text-text-primary\"\n >\n Variables\n </label>\n <div className=\"flex items-center gap-1 bg-bg-sunken rounded-md p-0.5\">\n <button\n type=\"button\"\n onClick={() => {\n setVariablesMode('form');\n try {\n setFormData((prev) => ({\n ...prev,\n variables: JSON.parse(variablesJson),\n }));\n } catch {\n /* ignore parse errors */\n }\n }}\n className={`px-2 py-1 text-xs rounded ${variablesMode === 'form' ? 'bg-bg-surface shadow-sm' : ''}`}\n >\n Form\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setVariablesMode('json');\n setVariablesJson(JSON.stringify(formData.variables, null, 2));\n }}\n className={`px-2 py-1 text-xs rounded ${variablesMode === 'json' ? 'bg-bg-surface shadow-sm' : ''}`}\n >\n JSON\n </button>\n </div>\n </div>\n {variablesMode === 'form' ? (\n <div className=\"space-y-2\">\n {Object.entries(formData.variables).map(([key, val], idx) => (\n <div key={idx} className=\"flex items-center gap-2\">\n <input\n id=\"aitemplatestab-8\"\n aria-label=\"Key\"\n type=\"text\"\n value={key}\n onChange={(e) => updateVariableKey(key, e.target.value)}\n className=\"flex-1 px-2 py-1.5 bg-bg-sunken border border-border-default rounded text-sm text-text-primary focus:outline-none focus:border-border-strong\"\n placeholder=\"Key\"\n />\n <input\n aria-label=\"Default value\"\n type=\"text\"\n value={String(val ?? '')}\n onChange={(e) => updateVariableValue(key, e.target.value)}\n className=\"flex-1 px-2 py-1.5 bg-bg-sunken border border-border-default rounded text-sm text-text-primary focus:outline-none focus:border-border-strong\"\n placeholder=\"Default value\"\n />\n <button\n type=\"button\"\n onClick={() => removeVariable(key)}\n className=\"p-1 hover:bg-status-error-bg rounded\"\n >\n <X className=\"size-3.5 text-status-error-text\" />\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={addVariable}\n className=\"text-xs text-action-primary-bg hover:underline\"\n >\n + Add variable\n </button>\n </div>\n ) : (\n <textarea\n aria-label=\"control\"\n value={variablesJson}\n onChange={(e) => setVariablesJson(e.target.value)}\n rows={4}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm font-mono focus:outline-none focus:border-border-strong\"\n />\n )}\n </div>\n </div>\n\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n type=\"button\"\n onClick={() => setShowForm(false)}\n className=\"px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={saving || !formData.name || !formData.content}\n className=\"px-4 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {saving ? 'Saving...' : editingId ? 'Update' : 'Create'}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Preview Dialog */}\n {previewId && (\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => setPreviewId(null))();\n }\n }}\n className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-50 p-4\"\n onClick={() => setPreviewId(null)}\n >\n <div\n className=\"bg-bg-surface border border-border-default rounded-lg shadow-xl w-full max-w-md max-h-[80vh] overflow-y-auto p-6\"\n onClick={(e) => e.stopPropagation()}\n >\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n {tr('vibecontrols.ai.templates.previewTemplate', 'Preview Template')}\n </h3>\n <div className=\"space-y-3\">\n {Object.keys(previewVars).map((key) => (\n <div key={key}>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n {key}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={previewVars[key]}\n onChange={(e) => setPreviewVars((prev) => ({ ...prev, [key]: e.target.value }))}\n className=\"w-full px-3 py-1.5 bg-bg-sunken border border-border-default rounded text-sm text-text-primary focus:outline-none focus:border-border-strong\"\n />\n </div>\n ))}\n <button\n type=\"button\"\n onClick={handlePreview}\n disabled={previewing}\n className=\"w-full px-4 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {previewing\n ? tr('vibecontrols.ai.templates.rendering', 'Rendering...')\n : tr('vibecontrols.ai.templates.render', 'Render')}\n </button>\n {previewResult !== null && (\n <pre className=\"mt-2 text-sm text-text-primary bg-bg-sunken rounded p-3 whitespace-pre-wrap max-h-48 overflow-auto\">\n {previewResult}\n </pre>\n )}\n </div>\n <div className=\"flex justify-end mt-4\">\n <button\n type=\"button\"\n onClick={() => setPreviewId(null)}\n className=\"px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Delete Confirmation */}\n <ConfirmDialog\n isOpen={deleteIds.length > 0}\n title={deleteIds.length > 1 ? 'Delete Templates' : 'Delete Template'}\n message={\n deleteIds.length > 1\n ? `Are you sure you want to delete ${deleteIds.length} selected templates? This action cannot be undone.`\n : 'Are you sure you want to delete this template? This action cannot be undone.'\n }\n confirmLabel={deleting ? 'Deleting...' : 'Delete'}\n variant=\"danger\"\n onConfirm={handleDelete}\n onClose={() => setDeleteIds([])}\n />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AITemplatesTab.js","names":[],"sources":["../../../src/components/ai/AITemplatesTab.tsx"],"sourcesContent":["import { useState, useEffect, useCallback, useMemo } from 'react';\nimport { Plus, Search, Pencil, Trash2, Eye, Code, X } from 'lucide-react';\nimport {\n Card,\n LoadingState,\n ErrorState,\n EmptyState,\n ConfirmDialog,\n SelectionCheckbox,\n} from '@/components/shared';\nimport { EntityShareButton } from '@/components/sharing';\nimport type { AITemplate } from '@/services/aiApi';\nimport {\n fetchTemplates,\n createTemplate,\n updateTemplate,\n deleteTemplate,\n renderTemplate,\n} from '@/services/aiApi';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface AITemplatesTabProps {\n agentId: string;\n}\n\ninterface TemplateFormData {\n name: string;\n content: string;\n description: string;\n variables: Record<string, unknown>;\n tags: string[];\n}\n\nconst emptyForm: TemplateFormData = {\n name: '',\n content: '',\n description: '',\n variables: {},\n tags: [],\n};\n\nexport function AITemplatesTab({ agentId }: AITemplatesTabProps) {\n const tr = useTr();\n const [templates, setTemplates] = useState<AITemplate[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [search, setSearch] = useState('');\n const [showForm, setShowForm] = useState(false);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [formData, setFormData] = useState<TemplateFormData>(emptyForm);\n const [variablesMode, setVariablesMode] = useState<'form' | 'json'>('form');\n const [variablesJson, setVariablesJson] = useState('{}');\n const [saving, setSaving] = useState(false);\n const [deleteIds, setDeleteIds] = useState<string[]>([]);\n const [deleting, setDeleting] = useState(false);\n const [selectedTemplateIds, setSelectedTemplateIds] = useState<Set<string>>(new Set());\n const [previewId, setPreviewId] = useState<string | null>(null);\n const [previewVars, setPreviewVars] = useState<Record<string, string>>({});\n const [previewResult, setPreviewResult] = useState<string | null>(null);\n const [previewing, setPreviewing] = useState(false);\n\n const loadTemplates = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await fetchTemplates(agentId);\n setTemplates(result);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load templates');\n } finally {\n setLoading(false);\n }\n }, [agentId]);\n\n useEffect(() => {\n loadTemplates();\n }, [loadTemplates]);\n\n const filtered = templates.filter((t) => {\n if (!search) return true;\n const q = search.toLowerCase();\n return (\n t.name.toLowerCase().includes(q) ||\n t.description?.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q))\n );\n });\n\n const selectedTemplates = useMemo(\n () => templates.filter((template) => selectedTemplateIds.has(template.id)),\n [templates, selectedTemplateIds]\n );\n const allVisibleSelected =\n filtered.length > 0 && filtered.every((template) => selectedTemplateIds.has(template.id));\n const partiallySelected =\n filtered.some((template) => selectedTemplateIds.has(template.id)) && !allVisibleSelected;\n\n const openCreate = () => {\n setEditingId(null);\n setFormData(emptyForm);\n setVariablesJson('{}');\n setShowForm(true);\n };\n\n const openEdit = (t: AITemplate) => {\n setEditingId(t.id);\n setFormData({\n name: t.name,\n content: t.content,\n description: t.description ?? '',\n variables: t.variables ?? {},\n tags: t.tags ?? [],\n });\n setVariablesJson(JSON.stringify(t.variables ?? {}, null, 2));\n setShowForm(true);\n };\n\n const handleSave = async () => {\n setSaving(true);\n try {\n const vars = variablesMode === 'json' ? JSON.parse(variablesJson) : formData.variables;\n const payload = { ...formData, variables: vars };\n if (editingId) {\n await updateTemplate(agentId, editingId, payload);\n } else {\n await createTemplate(agentId, payload);\n }\n setShowForm(false);\n await loadTemplates();\n } catch (err) {\n console.error('Failed to save template:', err);\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async () => {\n if (deleteIds.length === 0) return;\n setDeleting(true);\n try {\n await Promise.allSettled(deleteIds.map((deleteId) => deleteTemplate(agentId, deleteId)));\n setSelectedTemplateIds((prev) => {\n const next = new Set(prev);\n deleteIds.forEach((deleteId) => next.delete(deleteId));\n return next;\n });\n setDeleteIds([]);\n await loadTemplates();\n } catch (err) {\n console.error('Failed to delete template:', err);\n } finally {\n setDeleting(false);\n }\n };\n\n const handlePreview = async () => {\n if (!previewId) return;\n setPreviewing(true);\n try {\n const result = await renderTemplate(agentId, previewId, previewVars);\n setPreviewResult(result.rendered);\n } catch (err) {\n setPreviewResult(\n `Error: ${err instanceof Error ? err.message : 'Failed to render template'}`\n );\n } finally {\n setPreviewing(false);\n }\n };\n\n const openPreview = (t: AITemplate) => {\n setPreviewId(t.id);\n const vars: Record<string, string> = {};\n if (t.variables) {\n for (const key of Object.keys(t.variables)) {\n vars[key] = '';\n }\n }\n setPreviewVars(vars);\n setPreviewResult(null);\n };\n\n // Variable form helpers\n const addVariable = () => {\n setFormData((prev) => ({\n ...prev,\n variables: { ...prev.variables, '': '' },\n }));\n };\n\n const updateVariableKey = (oldKey: string, newKey: string) => {\n const entries = Object.entries(formData.variables);\n const updated: Record<string, unknown> = {};\n for (const [k, v] of entries) {\n updated[k === oldKey ? newKey : k] = v;\n }\n setFormData((prev) => ({ ...prev, variables: updated }));\n };\n\n const updateVariableValue = (key: string, value: string) => {\n setFormData((prev) => ({\n ...prev,\n variables: { ...prev.variables, [key]: value },\n }));\n };\n\n const removeVariable = (key: string) => {\n const rest = { ...formData.variables };\n delete rest[key];\n setFormData((prev) => ({ ...prev, variables: rest }));\n };\n\n const toggleTemplateSelection = (templateId: string, checked: boolean) => {\n setSelectedTemplateIds((prev) => {\n const next = new Set(prev);\n if (checked) {\n next.add(templateId);\n } else {\n next.delete(templateId);\n }\n return next;\n });\n };\n\n const toggleAllVisibleTemplates = (checked: boolean) => {\n setSelectedTemplateIds((prev) => {\n const next = new Set(prev);\n filtered.forEach((template) => {\n if (checked) {\n next.add(template.id);\n } else {\n next.delete(template.id);\n }\n });\n return next;\n });\n };\n\n const clearSelection = () => setSelectedTemplateIds(new Set());\n\n if (loading)\n return (\n <LoadingState message={tr('vibecontrols.ai.templates.loading', 'Loading templates...')} />\n );\n if (error)\n return (\n <ErrorState\n title={tr('vibecontrols.ai.templates.loadFailed', 'Failed to load templates')}\n message={error}\n onRetry={loadTemplates}\n />\n );\n\n return (\n <div className=\"space-y-4\">\n {/* Toolbar */}\n <div className=\"flex flex-col sm:flex-row items-stretch sm:items-center gap-2\">\n <div className=\"relative flex-1 sm:max-w-xs\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 size-4 text-text-secondary\" />\n <input\n aria-label=\"control\"\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n placeholder={tr('vibecontrols.ai.templates.searchPlaceholder', 'Search templates...')}\n className=\"w-full pl-9 pr-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm placeholder:text-text-placeholder focus:outline-none focus:border-border-strong\"\n />\n </div>\n <button\n type=\"button\"\n onClick={openCreate}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors text-sm\"\n >\n <Plus className=\"size-4\" />\n {tr('vibecontrols.ai.templates.newTemplate', 'New Template')}\n </button>\n </div>\n\n {filtered.length > 0 && (\n <div className=\"rounded-lg border border-border-default bg-bg-surface p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"flex items-center gap-2\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllVisibleTemplates}\n ariaLabel=\"Select all visible templates\"\n />\n <span className=\"text-sm font-medium text-text-primary\">Select all visible</span>\n </div>\n {selectedTemplateIds.size > 0 && (\n <button\n type=\"button\"\n onClick={clearSelection}\n className=\"text-sm text-text-secondary hover:text-text-primary\"\n >\n Clear selection\n </button>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded-full bg-bg-sunken px-3 py-1 text-sm font-medium text-text-secondary\">\n {selectedTemplateIds.size} selected\n </span>\n <button\n type=\"button\"\n onClick={() => setDeleteIds(selectedTemplates.map((template) => template.id))}\n disabled={selectedTemplates.length === 0}\n className=\"rounded-md border border-status-error-border px-3 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg disabled:cursor-not-allowed disabled:opacity-50\"\n >\n Delete Selected\n {selectedTemplates.length > 0 ? ` (${selectedTemplates.length})` : ''}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Template List */}\n {filtered.length === 0 ? (\n <EmptyState\n icon={<Code className=\"size-8 text-text-secondary\" />}\n title={\n search\n ? tr('vibecontrols.ai.templates.noMatch', 'No templates match your search')\n : tr('vibecontrols.ai.templates.emptyTitle', 'No templates yet')\n }\n description={\n search\n ? tr('vibecontrols.ai.templates.adjustSearch', 'Try adjusting your search query')\n : tr(\n 'vibecontrols.ai.templates.emptyDescription',\n 'Create your first prompt template to get started'\n )\n }\n action={\n !search ? (\n <button\n type=\"button\"\n onClick={openCreate}\n className=\"flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Plus className=\"size-4\" />\n New Template\n </button>\n ) : undefined\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {filtered.map((t) => (\n <Card\n key={t.id}\n className={`p-4 ${selectedTemplateIds.has(t.id) ? 'border-action-primary-bg ring-1 ring-action-primary-bg/25' : ''}`}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-start gap-3 min-w-0 flex-1\">\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selectedTemplateIds.has(t.id)}\n onChange={(checked) => toggleTemplateSelection(t.id, checked)}\n ariaLabel={`Select template ${t.name}`}\n />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h4 className=\"font-semibold text-text-primary truncate\">{t.name}</h4>\n {t.description && (\n <p className=\"text-xs text-text-secondary mt-0.5 line-clamp-2\">\n {t.description}\n </p>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-1 flex-shrink-0\">\n <button\n type=\"button\"\n onClick={() => openPreview(t)}\n className=\"p-1.5 hover:bg-bg-sunken rounded-md transition-colors\"\n title=\"Preview\"\n >\n <Eye className=\"size-3.5 text-text-secondary\" />\n </button>\n <button\n type=\"button\"\n onClick={() => openEdit(t)}\n className=\"p-1.5 hover:bg-bg-sunken rounded-md transition-colors\"\n title=\"Edit\"\n >\n <Pencil className=\"size-3.5 text-text-secondary\" />\n </button>\n <EntityShareButton\n entity=\"aiprompt\"\n resource={{ id: t.id, name: t.name }}\n label={tr('vibecontrols.ai.templates.share', 'Share')}\n />\n <button\n type=\"button\"\n onClick={() => setDeleteIds([t.id])}\n className=\"p-1.5 hover:bg-status-error-bg rounded-md transition-colors\"\n title=\"Delete\"\n >\n <Trash2 className=\"size-3.5 text-status-error-text\" />\n </button>\n </div>\n </div>\n <pre className=\"mt-2 text-xs text-text-secondary bg-bg-sunken rounded p-2 max-h-24 overflow-auto whitespace-pre-wrap\">\n {t.content}\n </pre>\n {t.tags && t.tags.length > 0 && (\n <div className=\"mt-2 flex flex-wrap gap-1\">\n {t.tags.map((tag) => (\n <span\n key={tag}\n className=\"px-1.5 py-0.5 text-xs bg-bg-sunken text-text-secondary rounded\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n </Card>\n ))}\n </div>\n )}\n\n {/* Create/Edit Dialog */}\n {showForm && (\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => setShowForm(false))();\n }\n }}\n className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-50 p-4\"\n onClick={() => setShowForm(false)}\n >\n <div\n className=\"bg-bg-surface border border-border-default rounded-lg shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto p-6\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {editingId\n ? tr('vibecontrols.ai.templates.editTemplate', 'Edit Template')\n : tr('vibecontrols.ai.templates.newTemplate', 'New Template')}\n </h3>\n <button\n type=\"button\"\n onClick={() => setShowForm(false)}\n className=\"p-1 hover:bg-bg-sunken rounded-md\"\n >\n <X className=\"size-4 text-text-secondary\" />\n </button>\n </div>\n\n <div className=\"space-y-4\">\n <div>\n <label\n htmlFor=\"aitemplatestab-11\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Name\n </label>\n <input\n id=\"aitemplatestab-11\"\n aria-label=\"Template name\"\n type=\"text\"\n value={formData.name}\n onChange={(e) => setFormData({ ...formData, name: e.target.value })}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm focus:outline-none focus:border-border-strong\"\n placeholder=\"Template name\"\n />\n </div>\n <div>\n <label\n htmlFor=\"aitemplatestab-10\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Description\n </label>\n <input\n id=\"aitemplatestab-10\"\n aria-label=\"Brief description\"\n type=\"text\"\n value={formData.description}\n onChange={(e) => setFormData({ ...formData, description: e.target.value })}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm focus:outline-none focus:border-border-strong\"\n placeholder=\"Brief description\"\n />\n </div>\n <div>\n <label\n htmlFor=\"aitemplatestab-9\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Content\n </label>\n <textarea\n id=\"aitemplatestab-9\"\n aria-label=\"Use {{variable}} for template variables\"\n value={formData.content}\n onChange={(e) => setFormData({ ...formData, content: e.target.value })}\n rows={6}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm font-mono focus:outline-none focus:border-border-strong\"\n placeholder=\"Use {{variable}} for template variables\"\n />\n </div>\n\n {/* Variables Editor */}\n <div>\n <div className=\"flex items-center justify-between mb-1\">\n <label\n htmlFor=\"aitemplatestab-8\"\n className=\"text-sm font-medium text-text-primary\"\n >\n Variables\n </label>\n <div className=\"flex items-center gap-1 bg-bg-sunken rounded-md p-0.5\">\n <button\n type=\"button\"\n onClick={() => {\n setVariablesMode('form');\n try {\n setFormData((prev) => ({\n ...prev,\n variables: JSON.parse(variablesJson),\n }));\n } catch {\n /* ignore parse errors */\n }\n }}\n className={`px-2 py-1 text-xs rounded ${variablesMode === 'form' ? 'bg-bg-surface shadow-sm' : ''}`}\n >\n Form\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setVariablesMode('json');\n setVariablesJson(JSON.stringify(formData.variables, null, 2));\n }}\n className={`px-2 py-1 text-xs rounded ${variablesMode === 'json' ? 'bg-bg-surface shadow-sm' : ''}`}\n >\n JSON\n </button>\n </div>\n </div>\n {variablesMode === 'form' ? (\n <div className=\"space-y-2\">\n {Object.entries(formData.variables).map(([key, val], idx) => (\n <div key={idx} className=\"flex items-center gap-2\">\n <input\n id=\"aitemplatestab-8\"\n aria-label=\"Key\"\n type=\"text\"\n value={key}\n onChange={(e) => updateVariableKey(key, e.target.value)}\n className=\"flex-1 px-2 py-1.5 bg-bg-sunken border border-border-default rounded text-sm text-text-primary focus:outline-none focus:border-border-strong\"\n placeholder=\"Key\"\n />\n <input\n aria-label=\"Default value\"\n type=\"text\"\n value={String(val ?? '')}\n onChange={(e) => updateVariableValue(key, e.target.value)}\n className=\"flex-1 px-2 py-1.5 bg-bg-sunken border border-border-default rounded text-sm text-text-primary focus:outline-none focus:border-border-strong\"\n placeholder=\"Default value\"\n />\n <button\n type=\"button\"\n onClick={() => removeVariable(key)}\n className=\"p-1 hover:bg-status-error-bg rounded\"\n >\n <X className=\"size-3.5 text-status-error-text\" />\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={addVariable}\n className=\"text-xs text-action-primary-bg hover:underline\"\n >\n + Add variable\n </button>\n </div>\n ) : (\n <textarea\n aria-label=\"control\"\n value={variablesJson}\n onChange={(e) => setVariablesJson(e.target.value)}\n rows={4}\n className=\"w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-md text-text-primary text-sm font-mono focus:outline-none focus:border-border-strong\"\n />\n )}\n </div>\n </div>\n\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n type=\"button\"\n onClick={() => setShowForm(false)}\n className=\"px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={saving || !formData.name || !formData.content}\n className=\"px-4 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {saving ? 'Saving...' : editingId ? 'Update' : 'Create'}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Preview Dialog */}\n {previewId && (\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (() => setPreviewId(null))();\n }\n }}\n className=\"fixed inset-0 bg-bg-overlay flex items-center justify-center z-50 p-4\"\n onClick={() => setPreviewId(null)}\n >\n <div\n className=\"bg-bg-surface border border-border-default rounded-lg shadow-xl w-full max-w-md max-h-[80vh] overflow-y-auto p-6\"\n onClick={(e) => e.stopPropagation()}\n >\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n {tr('vibecontrols.ai.templates.previewTemplate', 'Preview Template')}\n </h3>\n <div className=\"space-y-3\">\n {Object.keys(previewVars).map((key) => (\n <div key={key}>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n {key}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={previewVars[key]}\n onChange={(e) => setPreviewVars((prev) => ({ ...prev, [key]: e.target.value }))}\n className=\"w-full px-3 py-1.5 bg-bg-sunken border border-border-default rounded text-sm text-text-primary focus:outline-none focus:border-border-strong\"\n />\n </div>\n ))}\n <button\n type=\"button\"\n onClick={handlePreview}\n disabled={previewing}\n className=\"w-full px-4 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {previewing\n ? tr('vibecontrols.ai.templates.rendering', 'Rendering...')\n : tr('vibecontrols.ai.templates.render', 'Render')}\n </button>\n {previewResult !== null && (\n <pre className=\"mt-2 text-sm text-text-primary bg-bg-sunken rounded p-3 whitespace-pre-wrap max-h-48 overflow-auto\">\n {previewResult}\n </pre>\n )}\n </div>\n <div className=\"flex justify-end mt-4\">\n <button\n type=\"button\"\n onClick={() => setPreviewId(null)}\n className=\"px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-md transition-colors\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n )}\n\n {/* Delete Confirmation */}\n <ConfirmDialog\n isOpen={deleteIds.length > 0}\n title={deleteIds.length > 1 ? 'Delete Templates' : 'Delete Template'}\n message={\n deleteIds.length > 1\n ? `Are you sure you want to delete ${deleteIds.length} selected templates? This action cannot be undone.`\n : 'Are you sure you want to delete this template? This action cannot be undone.'\n }\n confirmLabel={deleting ? 'Deleting...' : 'Delete'}\n variant=\"danger\"\n onConfirm={handleDelete}\n onClose={() => setDeleteIds([])}\n />\n </div>\n );\n}\n"],"mappings":"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"}