@json-to-office/jto 7.0.0 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/dist/client/assets/{HomePage-CAQsE0sn.js → HomePage-Lgf6tdDd.js} +4 -4
- package/dist/client/assets/{HomePage-CAQsE0sn.js.map → HomePage-Lgf6tdDd.js.map} +1 -1
- package/dist/client/assets/{JsonEditorPage-Cqz2zDan.js → JsonEditorPage-CvR_nPhi.js} +3 -3
- package/dist/client/assets/{JsonEditorPage-Cqz2zDan.js.map → JsonEditorPage-CvR_nPhi.js.map} +1 -1
- package/dist/client/assets/{MonacoPluginProvider-FJHgHgFQ.js → MonacoPluginProvider-B9ylIvJ1.js} +5 -5
- package/dist/client/assets/{MonacoPluginProvider-FJHgHgFQ.js.map → MonacoPluginProvider-B9ylIvJ1.js.map} +1 -1
- package/dist/client/assets/{_virtual_jto-plugin-type-libs-DroopP3q.js → _virtual_jto-plugin-type-libs-0VdrjFY7.js} +158 -5
- package/dist/client/assets/{_virtual_jto-plugin-type-libs-DroopP3q.js.map → _virtual_jto-plugin-type-libs-0VdrjFY7.js.map} +1 -1
- package/dist/client/assets/{_virtual_jto-sandbox-runtime-v4kQF3ee.js → _virtual_jto-sandbox-runtime-D-AIkzB-.js} +2 -2
- package/dist/client/assets/_virtual_jto-sandbox-runtime-D-AIkzB-.js.map +1 -0
- package/dist/client/assets/{editor-1mTGQjga.js → editor-RriNJVGd.js} +2 -2
- package/dist/client/assets/{editor-1mTGQjga.js.map → editor-RriNJVGd.js.map} +1 -1
- package/dist/client/assets/{editor-monaco-json-B19wOO_b.js → editor-monaco-json-DB7frltk.js} +2 -2
- package/dist/client/assets/{editor-monaco-json-B19wOO_b.js.map → editor-monaco-json-DB7frltk.js.map} +1 -1
- package/dist/client/assets/{index-Da5mi8tP.js → index-4AXBK6QA.js} +2 -2
- package/dist/client/assets/{index-Da5mi8tP.js.map → index-4AXBK6QA.js.map} +1 -1
- package/dist/client/assets/{index-DsuZTLjf.js → index-CPNiZvgQ.js} +8 -8
- package/dist/client/assets/index-CPNiZvgQ.js.map +1 -0
- package/dist/client/assets/{preview-T1T-uQbx.js → preview-CchFIss2.js} +2 -2
- package/dist/client/assets/{preview-T1T-uQbx.js.map → preview-CchFIss2.js.map} +1 -1
- package/dist/client/assets/{useQualityAnalysis-CnLgG345.js → useQualityAnalysis-DgWJorkg.js} +2 -2
- package/dist/client/assets/{useQualityAnalysis-CnLgG345.js.map → useQualityAnalysis-DgWJorkg.js.map} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/client/templates/client-report-blocks.docx.json +2 -10
- package/package.json +4 -4
- package/dist/client/assets/_virtual_jto-sandbox-runtime-v4kQF3ee.js.map +0 -1
- package/dist/client/assets/index-DsuZTLjf.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor-1mTGQjga.js","sources":["../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/utils/validators.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/utils/definedErrors.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/utils/deepClone.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/utils/enums.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/constrainedModel.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/constrainedEditor.js","../../../src/client/components/json-editor/editor-monaco-theme.tsx","../../../src/client/lib/theme-editor/schema-form.ts","../../../src/client/lib/theme-json-schema.ts","../../../src/client/components/ui/popover.tsx","../../../src/client/lib/theme-editor/color.ts","../../../src/client/components/theme-editor/color-picker.tsx","../../../src/client/components/theme-editor/theme-colors-section.tsx","../../../src/client/components/theme-editor/font-combobox.tsx","../../../src/client/components/theme-editor/theme-typography-section.tsx","../../../src/client/components/theme-editor/theme-page-section.tsx","../../../src/client/components/theme-editor/theme-styles-section.tsx","../../../src/client/components/theme-editor/theme-schema-section.tsx","../../../src/client/components/theme-editor/theme-visual-editor.tsx","../../../src/client/components/theme-editor/theme-editor-host.tsx","../../../src/client/components/plugin-editor/plugin-editor-strip.tsx","../../../src/client/components/plugin-editor/editor-monaco-plugin.tsx","../../../src/client/components/playground/editor-tabs-content.tsx","../../../src/client/utils/retry.ts","../../../src/client/lib/theme-editor/specimen.ts","../../../src/client/components/playground/editor.tsx"],"sourcesContent":["const validators = {\n initWith: function (monaco) {\n const dummyDiv = document.createElement('div');\n const dummyEditorInstance = monaco.editor.create(dummyDiv);\n const editorInstanceConstructorName = dummyEditorInstance.constructor.name;\n const editorModelConstructorName = dummyEditorInstance.getModel().constructor.name;\n const instanceCheck = function (valueToValidate) {\n return valueToValidate.constructor.name === editorInstanceConstructorName;\n }\n const modelCheck = function (valueToValidate) {\n return valueToValidate.constructor.name === editorModelConstructorName;\n }\n const rangesCheck = function (ranges) {\n if (Array.isArray(ranges)) {\n return ranges.every(function (rangeObj) {\n if (typeof rangeObj === 'object' && rangeObj.constructor.name === 'Object') {\n if (!rangeObj.hasOwnProperty('range')) return false;\n if (!Array.isArray(rangeObj.range)) return false;\n if (rangeObj.range.length !== 4) return false;\n if (!(rangeObj.range.every(num => num > 0 && parseInt(num) === num))) return false;\n if (rangeObj.hasOwnProperty('allowMultiline')) {\n if (typeof rangeObj.allowMultiline !== 'boolean') return false;\n }\n if (rangeObj.hasOwnProperty('label')) {\n if (typeof rangeObj.label !== 'string') return false;\n }\n if (rangeObj.hasOwnProperty('validate')) {\n if (typeof rangeObj.validate !== 'function') return false;\n }\n return true;\n }\n return false;\n });\n }\n return false;\n }\n return {\n isInstanceValid: instanceCheck,\n isModelValid: modelCheck,\n isRangesValid: rangesCheck\n }\n }\n}\nexport default validators;","export const TypeMustBe = function (type, key, additional) {\n return 'The value for the ' + key + ' should be of type ' + (Array.isArray(type) ? type.join(' | ') : type) + '. ' + (additional || '')\n}\nconst definedErrors = {\n TypeMustBe : TypeMustBe\n};\nexport default definedErrors;","export const deepClone = (function () {\n const byPassPrimitives = function (value, callback) {\n if (typeof value !== 'object' || value === null) {\n return this.freeze ? Object.freeze(value) : value;\n }\n if (value instanceof Date) {\n return this.freeze ? Object.freeze(new Date(value)) : new Date(value);\n }\n return callback.call(this, value);\n }\n const cloneArray = function (array, callback) {\n const keys = Object.keys(array);\n const arrayClone = new Array(keys.length)\n for (let i = 0; i < keys.length; i++) {\n arrayClone[keys[i]] = byPassPrimitives.call(this, array[keys[i]], callback);\n }\n return arrayClone;\n }\n const cloner = function (object) {\n return byPassPrimitives.call(this, object, function (object) {\n if (Array.isArray(object)) {\n return cloneArray.call(this, object, cloner)\n }\n const clone = {};\n for (let key in object) {\n if (!this.withProto && Object.hasOwnProperty.call(object, key) === false) {\n continue;\n }\n clone[key] = byPassPrimitives.call(this, object[key], cloner);\n }\n return clone;\n })\n }\n const config = (function () {\n const constructOptionForCode = function (value) {\n const options = [\n 'withProto',\n 'freeze'\n ]\n this[value] = options.reduce(function (acc, option) {\n if (acc[option] = (value >= this[option])) {\n value -= this[option]\n }\n return acc;\n }.bind(this), {})\n }\n const codes = Object.create(Object.defineProperties({}, {\n withProto: { value: 1 },\n freeze: { value: 2 }\n }));\n for (let i = 0; i <= 3; i++) {\n constructOptionForCode.call(codes, i);\n }\n return codes;\n }());\n const methods = {\n withProto: cloner.bind(config[1]),\n andFreeze: cloner.bind(config[2]),\n withProtoAndFreeze: cloner.bind(config[3])\n }\n const API = cloner.bind(config[0]);\n for (let methodName in methods) {\n Object.defineProperty(API, methodName, {\n enumerable: false,\n writable: false,\n configurable: false,\n value: methods[methodName]\n })\n }\n return API;\n}());\n\nexport default deepClone;","export const enums = {\n SINGLE_LINE_HIGHLIGHT_CLASS: 'editableArea--single-line',\n MULTI_LINE_HIGHLIGHT_CLASS: 'editableArea--multi-line'\n}\nexport default enums;","import deepClone from './utils/deepClone.js';\nimport enums from './utils/enums.js';\nexport const constrainedModel = function (model, ranges, monaco) {\n const rangeConstructor = monaco.Range;\n const sortRangesInAscendingOrder = function (rangeObject1, rangeObject2) {\n const rangeA = rangeObject1.range;\n const rangeB = rangeObject2.range;\n if (\n rangeA[0] < rangeB[0] ||\n (rangeA[0] === rangeB[0] && rangeA[3] < rangeB[1])\n ) {\n return -1;\n }\n }\n const normalizeRange = function (range, content) {\n const lines = content.split('\\n');\n const noOfLines = lines.length;\n const normalizedRange = [];\n range.forEach(function (value, index) {\n if (value === 0) {\n throw new Error('Range values cannot be zero');//No I18n\n }\n switch (index) {\n case 0: {\n if (value < 0) {\n throw new Error('Start Line of Range cannot be negative');//No I18n\n } else if (value > noOfLines) {\n throw new Error('Provided Start Line(' + value + ') is out of bounds. Max Lines in content is ' + noOfLines);//No I18n\n }\n normalizedRange[index] = value;\n }\n break;\n case 1: {\n let actualStartCol = value;\n const startLineNo = normalizedRange[0];\n const maxCols = lines[startLineNo - 1].length\n if (actualStartCol < 0) {\n actualStartCol = maxCols - Math.abs(actualStartCol);\n if (actualStartCol < 0) {\n throw new Error('Provided Start Column(' + value + ') is out of bounds. Max Column in line ' + startLineNo + ' is ' + maxCols);//No I18n\n }\n } else if (actualStartCol > (maxCols + 1)) {\n throw new Error('Provided Start Column(' + value + ') is out of bounds. Max Column in line ' + startLineNo + ' is ' + maxCols);//No I18n\n }\n normalizedRange[index] = actualStartCol;\n }\n break;\n case 2: {\n let actualEndLine = value;\n if (actualEndLine < 0) {\n actualEndLine = noOfLines - Math.abs(value);\n if (actualEndLine < 0) {\n throw new Error('Provided End Line(' + value + ') is out of bounds. Max Lines in content is ' + noOfLines);//No I18n\n }\n if (actualEndLine < normalizedRange[0]) {\n console.warn('Provided End Line(' + value + ') is less than the start Line, the Restriction may not behave as expected');//No I18n\n }\n } else if (value > noOfLines) {\n throw new Error('Provided End Line(' + value + ') is out of bounds. Max Lines in content is ' + noOfLines);//No I18n\n }\n normalizedRange[index] = actualEndLine;\n }\n break;\n case 3: {\n let actualEndCol = value;\n const endLineNo = normalizedRange[2];\n const maxCols = lines[endLineNo - 1].length\n if (actualEndCol < 0) {\n actualEndCol = maxCols - Math.abs(actualEndCol);\n if (actualEndCol < 0) {\n throw new Error('Provided End Column(' + value + ') is out of bounds. Max Column in line ' + endLineNo + ' is ' + maxCols);//No I18n\n }\n } else if (actualEndCol > (maxCols + 1)) {\n throw new Error('Provided Start Column(' + value + ') is out of bounds. Max Column in line ' + endLineNo + ' is ' + maxCols);//No I18n\n }\n normalizedRange[index] = actualEndCol;\n }\n break;\n }\n })\n return normalizedRange;\n }\n let restrictions = deepClone(ranges).sort(sortRangesInAscendingOrder);\n const prepareRestrictions = function (restrictions) {\n const content = model.getValue();\n restrictions.forEach(function (restriction, index) {\n const range = normalizeRange(restriction.range, content);\n const startLine = range[0];\n const startCol = range[1];\n const endLine = range[2];\n const endCol = range[3];\n restriction._originalRange = range.slice();\n restriction.range = new rangeConstructor(startLine, startCol, endLine, endCol);\n restriction.index = index;\n if (!restriction.allowMultiline) {\n restriction.allowMultiline = rangeConstructor.spansMultipleLines(restriction.range)\n }\n if (!restriction.label) {\n restriction.label = `[${startLine},${startCol} -> ${endLine}${endCol}]`;\n }\n });\n }\n const getCurrentEditableRanges = function () {\n return restrictions.reduce(function (acc, restriction) {\n acc[restriction.label] = {\n allowMultiline: restriction.allowMultiline || false,\n index: restriction.index,\n range: Object.assign({}, restriction.range),\n originalRange: restriction._originalRange.slice()\n };\n return acc;\n }, {});\n }\n const getValueInEditableRanges = function () {\n return restrictions.reduce(function (acc, restriction) {\n acc[restriction.label] = model.getValueInRange(restriction.range);\n return acc;\n }, {});\n }\n const updateValueInEditableRanges = function (object, forceMoveMarkers) {\n if (typeof object === 'object' && !Array.isArray(object)) {\n forceMoveMarkers = typeof forceMoveMarkers === 'boolean' ? forceMoveMarkers : false;\n const restrictionsMap = restrictions.reduce(function (acc, restriction) {\n if (restriction.label) {\n acc[restriction.label] = restriction;\n }\n return acc;\n }, {});\n for (let label in object) {\n const restriction = restrictionsMap[label];\n if (restriction) {\n const value = object[label];\n if (doesChangeHasMultilineConflict(restriction, value)) {\n throw new Error('Multiline change is not allowed for ' + label);\n }\n const newRange = deepClone(restriction.range);\n newRange.endLine = newRange.startLine + value.split('\\n').length - 1;\n newRange.endColumn = value.split('\\n').pop().length;\n if (isChangeInvalidAsPerUser(restriction, value, newRange)) {\n throw new Error('Change is invalidated by validate function of ' + label);\n }\n model.applyEdits([{\n forceMoveMarkers: !!forceMoveMarkers,\n range: restriction.range,\n text: value\n }]);\n } else {\n console.error('No restriction found for ' + label);\n }\n }\n } else {\n throw new Error('Value must be an object');//No I18n\n }\n }\n const disposeRestrictions = function () {\n model._restrictionChangeListener.dispose();\n window.removeEventListener(\"error\", handleUnhandledPromiseRejection);\n delete model.editInRestrictedArea;\n delete model.disposeRestrictions;\n delete model.getValueInEditableRanges;\n delete model.updateValueInEditableRanges;\n delete model.updateRestrictions;\n delete model.getCurrentEditableRanges;\n delete model.toggleHighlightOfEditableAreas;\n delete model._hasHighlight;\n delete model._isRestrictedModel;\n delete model._isCursorAtCheckPoint;\n delete model._currentCursorPositions;\n delete model._editableRangeChangeListener;\n delete model._restrictionChangeListener;\n delete model._oldDecorations;\n delete model._oldDecorationsSource;\n return model;\n }\n const isCursorAtCheckPoint = function (positions) {\n positions.some(function (position) {\n const posLineNumber = position.lineNumber;\n const posCol = position.column;\n const length = restrictions.length;\n for (let i = 0; i < length; i++) {\n const range = restrictions[i].range;\n if (\n (range.startLineNumber === posLineNumber && range.startColumn === posCol) ||\n (range.endLineNumber === posLineNumber && range.endColumn === posCol)\n ) {\n model.pushStackElement();\n return true;\n }\n }\n });\n };\n const addEditableRangeListener = function (callback) {\n if (typeof callback === 'function') {\n model._editableRangeChangeListener.push(callback);\n }\n };\n const triggerChangeListenersWith = function (currentChanges, allChanges) {\n const currentRanges = getCurrentEditableRanges();\n model._editableRangeChangeListener.forEach(function (callback) {\n callback.call(model, currentChanges, allChanges, currentRanges);\n });\n };\n const doUndo = function () {\n return Promise.resolve().then(function () {\n model.editInRestrictedArea = true;\n model.undo();\n model.editInRestrictedArea = false;\n if (model._hasHighlight && model._oldDecorationsSource) {\n // id present in the decorations info will be omitted by monaco\n // So we don't need to remove the old decorations id\n model.deltaDecorations(model._oldDecorations, model._oldDecorationsSource);\n model._oldDecorationsSource.forEach(function (object) {\n object.range = model.getDecorationRange(object.id);\n });\n }\n });\n };\n const updateRange = function (restriction, range, finalLine, finalColumn, changes, changeIndex) {\n let oldRangeEndLineNumber = range.endLineNumber;\n let oldRangeEndColumn = range.endColumn;\n restriction.prevRange = range;\n restriction.range = range.setEndPosition(finalLine, finalColumn);\n const length = restrictions.length;\n let changesLength = changes.length;\n const diffInCol = finalColumn - oldRangeEndColumn;\n const diffInRow = finalLine - oldRangeEndLineNumber;\n\n const cursorPositions = model._currentCursorPositions || [];\n const noOfCursorPositions = cursorPositions.length;\n // if (noOfCursorPositions > 0) {\n if (changesLength !== noOfCursorPositions) {\n changes = changes.filter(function (change) {\n const range = change.range;\n for (let i = 0; i < noOfCursorPositions; i++) {\n const cursorPosition = cursorPositions[i];\n if (\n (range.startLineNumber === cursorPosition.startLineNumber) &&\n (range.endLineNumber === cursorPosition.endLineNumber) &&\n (range.startColumn === cursorPosition.startColumn) &&\n (range.endColumn === cursorPosition.endColumn)\n ) {\n return true;\n }\n }\n return false;\n });\n changesLength = changes.length;\n }\n if (diffInRow !== 0) {\n for (let i = restriction.index + 1; i < length; i++) {\n const nextRestriction = restrictions[i];\n const nextRange = nextRestriction.range;\n if (oldRangeEndLineNumber === nextRange.startLineNumber) {\n nextRange.startColumn += diffInCol;\n }\n if (oldRangeEndLineNumber === nextRange.endLineNumber) {\n nextRange.endColumn += diffInCol;\n }\n nextRange.startLineNumber += diffInRow;\n nextRange.endLineNumber += diffInRow;\n nextRestriction.range = nextRange;\n }\n for (let i = changeIndex + 1; i < changesLength; i++) {\n const nextChange = changes[i];\n const rangeInChange = nextChange.range;\n const rangeAsString = rangeInChange.toString();\n const rangeMapValue = rangeMap[rangeAsString];\n delete rangeMap[rangeAsString];\n if (oldRangeEndLineNumber === rangeInChange.startLineNumber) {\n rangeInChange.startColumn += diffInCol;\n }\n if (oldRangeEndLineNumber === rangeInChange.endLineNumber) {\n rangeInChange.endColumn += diffInCol;\n }\n rangeInChange.startLineNumber += diffInRow;\n rangeInChange.endLineNumber += diffInRow;\n nextChange.range = rangeInChange;\n rangeMap[rangeInChange.toString()] = rangeMapValue;\n }\n } else {\n // Only Column might have changed\n for (let i = restriction.index + 1; i < length; i++) {\n const nextRestriction = restrictions[i];\n const nextRange = nextRestriction.range;\n if (nextRange.startLineNumber > oldRangeEndLineNumber) {\n break;\n } else {\n nextRange.startColumn += diffInCol;\n nextRange.endColumn += diffInCol;\n nextRestriction.range = nextRange;\n }\n }\n for (let i = changeIndex + 1; i < changesLength; i++) {\n // rangeMap\n const nextChange = changes[i];\n const rangeInChange = nextChange.range;\n const rangeAsString = rangeInChange.toString();\n const rangeMapValue = rangeMap[rangeAsString];\n delete rangeMap[rangeAsString];\n if (rangeInChange.startLineNumber > oldRangeEndLineNumber) {\n rangeMap[rangeInChange.toString()] = rangeMapValue;\n break;\n } else {\n rangeInChange.startColumn += diffInCol;\n rangeInChange.endColumn += diffInCol;\n nextChange.range = rangeInChange;\n rangeMap[rangeInChange.toString()] = rangeMapValue;\n }\n }\n }\n // }\n };\n const getInfoFrom = function (change, editableRange) {\n const info = {};\n const range = change.range;\n // Get State\n if (change.text === '') {\n info.isDeletion = true;\n } else if (\n (range.startLineNumber === range.endLineNumber) &&\n (range.startColumn === range.endColumn)\n ) {\n info.isAddition = true;\n } else {\n info.isReplacement = true;\n }\n // Get Position Of Range\n info.startLineOfRange = range.startLineNumber === editableRange.startLineNumber;\n info.startColumnOfRange = range.startColumn === editableRange.startColumn;\n\n info.endLineOfRange = range.endLineNumber === editableRange.endLineNumber;\n info.endColumnOfRange = range.endColumn === editableRange.endColumn;\n\n info.middleLineOfRange = !info.startLineOfRange && !info.endLineOfRange;\n\n // Editable Range Span\n if (editableRange.startLineNumber === editableRange.endLineNumber) {\n info.rangeIsSingleLine = true;\n } else {\n info.rangeIsMultiLine = true;\n }\n return info;\n };\n const updateRestrictions = function (ranges) {\n restrictions = deepClone(ranges).sort(sortRangesInAscendingOrder);\n prepareRestrictions(restrictions);\n };\n const toggleHighlightOfEditableAreas = function (cssClasses) {\n if (!model._hasHighlight) {\n const cssClassForSingleLine = cssClasses.cssClassForSingleLine ||enums.SINGLE_LINE_HIGHLIGHT_CLASS\n const cssClassForMultiLine = cssClasses.cssClassForMultiLine ||enums.MULTI_LINE_HIGHLIGHT_CLASS\n const decorations = restrictions.map(function (restriction) {\n const decoration = {\n range: restriction.range,\n options: {\n className: restriction.allowMultiline ?\n cssClassForMultiLine :\n cssClassForSingleLine\n }\n }\n if (restriction.label) {\n decoration.hoverMessage = restriction.label;\n }\n return decoration;\n });\n model._oldDecorations = model.deltaDecorations([], decorations);\n model._oldDecorationsSource = decorations.map(function (decoration, index) {\n return Object.assign({}, decoration, { id: model._oldDecorations[index] });\n });\n model._hasHighlight = true;\n } else {\n model.deltaDecorations(model._oldDecorations, []);\n delete model._oldDecorations;\n delete model._oldDecorationsSource;\n model._hasHighlight = false;\n }\n }\n const handleUnhandledPromiseRejection = function () {\n console.debug('handler for unhandled promise rejection');\n };\n const setAllRangesToPrev = function (rangeMap) {\n for (let key in rangeMap) {\n const restriction = rangeMap[key];\n restriction.range = restriction.prevRange;\n }\n };\n const doesChangeHasMultilineConflict = function (restriction, text) {\n return !restriction.allowMultiline && text.includes('\\n');\n };\n const isChangeInvalidAsPerUser = function (restriction, value, range) {\n return restriction.validate && !restriction.validate(value, range, restriction.lastInfo);\n }\n\n const manipulatorApi = {\n _isRestrictedModel: true,\n _isRestrictedValueValid: true,\n _editableRangeChangeListener: [],\n _isCursorAtCheckPoint: isCursorAtCheckPoint,\n _currentCursorPositions: []\n }\n\n prepareRestrictions(restrictions);\n model._hasHighlight = false;\n manipulatorApi._restrictionChangeListener = model.onDidChangeContent(function (contentChangedEvent) {\n const isUndoing = contentChangedEvent.isUndoing;\n model._isRestrictedValueValid = true;\n if (!(isUndoing && model.editInRestrictedArea)) {\n const changes = contentChangedEvent.changes.sort(sortRangesInAscendingOrder);\n const rangeMap = {};\n const length = restrictions.length;\n const isAllChangesValid = changes.every(function (change) {\n const editedRange = change.range;\n const rangeAsString = editedRange.toString();\n rangeMap[rangeAsString] = null;\n for (let i = 0; i < length; i++) {\n const restriction = restrictions[i];\n const range = restriction.range;\n if (range.containsRange(editedRange)) {\n if (doesChangeHasMultilineConflict(restriction, change.text)) {\n return false;\n }\n rangeMap[rangeAsString] = restriction;\n return true;\n }\n }\n return false;\n })\n if (isAllChangesValid) {\n changes.forEach(function (change, changeIndex) {\n const changedRange = change.range;\n const restriction = rangeMap[changedRange.toString()];\n const editableRange = restriction.range;\n const text = change.text || '';\n /**\n * Things to check before implementing the change\n * - A | D | R => Addition | Deletion | Replacement\n * - MC | SC => MultiLineChange | SingleLineChange\n * - SOR | MOR | EOR => Change Occured in - Start Of Range | Middle Of Range | End Of Range\n * - SSL | SML => Editable Range - Spans Single Line | Spans Multiple Line\n */\n const noOfLinesAdded = (text.match(/\\n/g) || []).length;\n const noOfColsAddedAtLastLine = text.split(/\\n/g).pop().length;\n\n const lineDiffInRange = changedRange.endLineNumber - changedRange.startLineNumber;\n const colDiffInRange = changedRange.endColumn - changedRange.startColumn;\n\n let finalLine = editableRange.endLineNumber;\n let finalColumn = editableRange.endColumn;\n\n let columnsCarriedToEnd = 0;\n if (\n (editableRange.endLineNumber === changedRange.startLineNumber) ||\n (editableRange.endLineNumber === changedRange.endLineNumber)\n ) {\n columnsCarriedToEnd += (editableRange.endColumn - changedRange.startColumn) + 1;\n }\n\n const info = getInfoFrom(change, editableRange);\n restriction.lastInfo = info;\n if (info.isAddition || info.isReplacement) {\n if (info.rangeIsSingleLine) {\n /**\n * Only Column Change has occurred , so regardless of the position of the change\n * Addition of noOfCols is enough\n */\n if (noOfLinesAdded === 0) {\n finalColumn += noOfColsAddedAtLastLine;\n } else {\n finalLine += noOfLinesAdded;\n if (info.startColumnOfRange) {\n finalColumn += noOfColsAddedAtLastLine\n } else if (info.endColumnOfRange) {\n finalColumn = (noOfColsAddedAtLastLine + 1)\n } else {\n finalColumn = (noOfColsAddedAtLastLine + columnsCarriedToEnd)\n }\n }\n }\n if (info.rangeIsMultiLine) {\n // Handling for Start Of Range is not required\n finalLine += noOfLinesAdded;\n if (info.endLineOfRange) {\n if (noOfLinesAdded === 0) {\n finalColumn += noOfColsAddedAtLastLine;\n } else {\n finalColumn = (columnsCarriedToEnd + noOfColsAddedAtLastLine);\n }\n }\n }\n }\n if (info.isDeletion || info.isReplacement) {\n if (info.rangeIsSingleLine) {\n finalColumn -= colDiffInRange;\n }\n if (info.rangeIsMultiLine) {\n if (info.endLineOfRange) {\n finalLine -= lineDiffInRange;\n finalColumn -= colDiffInRange;\n } else {\n finalLine -= lineDiffInRange;\n }\n }\n }\n updateRange(restriction, editableRange, finalLine, finalColumn, changes, changeIndex);\n });\n const values = model.getValueInEditableRanges();\n const currentlyEditedRanges = {};\n for (let key in rangeMap) {\n const restriction = rangeMap[key];\n const range = restriction.range;\n const rangeString = restriction.label || range.toString();\n const value = values[rangeString];\n if (isChangeInvalidAsPerUser(restriction, value, range)) {\n setAllRangesToPrev(rangeMap);\n doUndo();\n return; // Breaks the loop and prevents the triggerChangeListener\n }\n currentlyEditedRanges[rangeString] = value;\n }\n if (model._hasHighlight) {\n model._oldDecorationsSource.forEach(function (object) {\n object.range = model.getDecorationRange(object.id);\n });\n }\n triggerChangeListenersWith(currentlyEditedRanges, values);\n } else {\n doUndo();\n }\n } else if (model.editInRestrictedArea) {\n model._isRestrictedValueValid = false;\n }\n });\n window.onerror = handleUnhandledPromiseRejection;\n const exposedApi = {\n editInRestrictedArea: false,\n getCurrentEditableRanges: getCurrentEditableRanges,\n getValueInEditableRanges: getValueInEditableRanges,\n disposeRestrictions: disposeRestrictions,\n onDidChangeContentInEditableRange: addEditableRangeListener,\n updateRestrictions: updateRestrictions,\n updateValueInEditableRanges: updateValueInEditableRanges,\n toggleHighlightOfEditableAreas: toggleHighlightOfEditableAreas\n }\n for (let funcName in manipulatorApi) {\n Object.defineProperty(model, funcName, {\n enumerable: false,\n configurable: true,\n writable: true,\n value: manipulatorApi[funcName]\n })\n }\n for (let apiName in exposedApi) {\n Object.defineProperty(model, apiName, {\n enumerable: false,\n configurable: true,\n writable: true,\n value: exposedApi[apiName]\n })\n }\n return model;\n}\nexport default constrainedModel;","import validators from './utils/validators.js';\nimport { TypeMustBe } from './utils/definedErrors.js';\nimport constrainedModel from './constrainedModel.js';\n\nexport function constrainedEditor(monaco) {\n /**\n * Injected Dependencies\n */\n if (monaco === undefined) {\n throw new Error([\n \"Please pass the monaco global variable into function as\",\n \"(eg:)constrainedEditor({ range : monaco.range });\",\n ].join('\\n'));\n }\n /**\n *\n * @param {Object} editorInstance This should be the monaco editor instance.\n * @description This is the listener function to check whether the cursor is at checkpoints\n * (i.e) the point where editable and non editable portions meet\n */\n const listenerFn = function (editorInstance) {\n const model = editorInstance.getModel();\n if (model._isCursorAtCheckPoint) {\n const selections = editorInstance.getSelections();\n const positions = selections.map(function (selection) {\n return {\n lineNumber: selection.positionLineNumber,\n column: selection.positionColumn\n }\n });\n model._isCursorAtCheckPoint(positions);\n model._currentCursorPositions = selections;\n }\n }\n const _uriRestrictionMap = {};\n const { isInstanceValid, isModelValid, isRangesValid } = validators.initWith(monaco);\n /**\n *\n * @param {Object} editorInstance This should be the monaco editor instance\n * @returns {Boolean}\n */\n const initInEditorInstance = function (editorInstance) {\n if (isInstanceValid(editorInstance)) {\n let domNode = editorInstance.getDomNode();\n manipulator._listener = listenerFn.bind(API, editorInstance);\n manipulator._editorInstance = editorInstance;\n manipulator._editorInstance._isInDevMode = false;\n domNode.addEventListener('keydown', manipulator._listener, true);\n manipulator._onChangeModelDisposable = editorInstance.onDidChangeModel(function () {\n // domNode - refers old dom node\n domNode && domNode.removeEventListener('keydown', manipulator._listener, true)\n const newDomNode = editorInstance.getDomNode(); // Gets Current dom node\n newDomNode && newDomNode.addEventListener('keydown', manipulator._listener, true);\n domNode = newDomNode;\n })\n return true;\n } else {\n throw new Error(\n TypeMustBe(\n 'ICodeEditor',\n 'editorInstance',\n 'This type interface can be found in monaco editor documentation'\n )\n )\n }\n }\n /**\n *\n * @param {Object} model This should be the monaco editor model instance. Refer https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.itextmodel.html\n * @param {*} ranges This should be the array of range objects. Refer constrained editor plugin documentation\n * @returns model\n */\n const addRestrictionsTo = function (model, ranges) {\n if (isModelValid(model)) {\n if (isRangesValid(ranges)) {\n const modelToConstrain = constrainedModel(model, ranges, monaco, manipulator._editorInstance);\n _uriRestrictionMap[modelToConstrain.uri.toString()] = modelToConstrain;\n return modelToConstrain;\n } else {\n throw new Error(\n TypeMustBe(\n 'Array<RangeRestrictionObject>',\n 'ranges',\n 'Please refer constrained editor documentation for proper structure'\n )\n )\n }\n } else {\n throw new Error(\n TypeMustBe(\n 'ICodeEditor',\n 'editorInstance',\n 'This type interface can be found in monaco editor documentation'\n )\n )\n }\n }\n /**\n *\n * @param {Object} model This should be the monaco editor model instance. Refer https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.itextmodel.html\n * @returns {Boolean} True if the restrictions are removed\n */\n const removeRestrictionsIn = function (model) {\n if (isModelValid(model)) {\n const uri = model.uri.toString();\n const restrictedModel = _uriRestrictionMap[uri];\n if (restrictedModel) {\n return restrictedModel.disposeRestrictions();\n } else {\n console.warn('Current Model is not a restricted Model');\n return false;\n }\n } else {\n throw new Error(\n TypeMustBe(\n 'ICodeEditor',\n 'editorInstance',\n 'This type interface can be found in monaco editor documentation'\n )\n )\n }\n }\n /**\n *\n * @returns {Boolean} True if the constrainer is disposed\n */\n const disposeConstrainer = function () {\n if (manipulator._editorInstance) {\n const instance = manipulator._editorInstance;\n const domNode = instance.getDomNode();\n domNode && domNode.removeEventListener('keydown', manipulator._listener);\n manipulator._onChangeModelDisposable && manipulator._onChangeModelDisposable.dispose();\n delete manipulator._listener;\n delete manipulator._editorInstance._isInDevMode;\n delete manipulator._editorInstance._devModeAction;\n delete manipulator._editorInstance;\n delete manipulator._onChangeModelDisposable;\n for (let key in _uriRestrictionMap) {\n delete _uriRestrictionMap[key];\n }\n return true;\n }\n return false;\n }\n /**\n * @description This function used to make the developer to find the ranges of selected portions\n */\n const toggleDevMode = function () {\n if (manipulator._editorInstance._isInDevMode) {\n manipulator._editorInstance._isInDevMode = false;\n manipulator._editorInstance._devModeAction.dispose();\n delete manipulator._editorInstance._devModeAction;\n } else {\n manipulator._editorInstance._isInDevMode = true;\n manipulator._editorInstance._devModeAction = manipulator._editorInstance.addAction({\n id: 'showRange',\n label: 'Show Range in console',\n contextMenuGroupId: 'navigation',\n contextMenuOrder: 1.5,\n run: function (editor) {\n const selections = editor.getSelections();\n const ranges = selections.reduce(function (acc, { startLineNumber, endLineNumber, startColumn, endColumn }) {\n acc.push('range : ' + JSON.stringify([\n startLineNumber,\n startColumn,\n endLineNumber,\n endColumn\n ]));\n return acc;\n }, []).join('\\n');\n console.log(`Selected Ranges : \\n` + JSON.stringify(ranges, null, 2));\n }\n });\n }\n }\n\n /**\n * Main Function starts here\n */\n // @internal\n const manipulator = {\n /**\n * These variables should not be modified by external code\n * This has to be used for debugging and testing\n */\n _listener: null,\n _editorInstance: null,\n _uriRestrictionMap: _uriRestrictionMap,\n _injectedResources: monaco\n }\n const API = Object.create(manipulator);\n const exposedMethods = {\n /**\n * These functions are exposed to the user\n * These functions should be protected from editing\n */\n initializeIn: initInEditorInstance,\n addRestrictionsTo: addRestrictionsTo,\n removeRestrictionsIn: removeRestrictionsIn,\n disposeConstrainer: disposeConstrainer,\n toggleDevMode: toggleDevMode\n }\n for (let methodName in exposedMethods) {\n Object.defineProperty(API, methodName, {\n enumerable: false,\n writable: false,\n configurable: false,\n value: exposedMethods[methodName]\n })\n }\n return Object.freeze(API);\n}\n\nexport default constrainedEditor;\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { useTheme } from '../theme-provider';\nimport { constrainedEditor } from 'constrained-editor-plugin';\nimport MonacoEditor, { Monaco, DiffEditor } from '@monaco-editor/react';\nimport type { editor as MonacoEditorType } from 'monaco-editor';\nimport type { TextFile } from '../../lib/types';\nimport { type JsonEditorError } from '../../lib/json-types';\nimport { FORMAT } from '../../lib/env';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { Button } from '../ui/button';\nimport { useEditorRefsStore } from '../../store/editor-refs-store';\nimport {\n getSelectionContext,\n createContextSnippet,\n} from '../../lib/monaco-selection-utils';\nimport { ValidationPanel, ValidationStatusBar } from './validation-panel';\nimport { monacoThemeFor, registerMonacoThemes } from '../../lib/monaco-theme';\n\n/** Ensure defaultPath matches the schema fileMatch pattern (*.FORMAT.theme.json) */\nfunction resolveThemeDefaultPath(name: string): string {\n const ext = `.${FORMAT}.theme.json`;\n if (name.endsWith(ext)) return name;\n const base = name\n .replace(/\\.\\w+\\.theme\\.json$/, '')\n .replace(/\\.theme\\.json$/, '')\n .replace(/\\.json$/, '');\n return base + ext;\n}\n\n/**\n * EditorMonacoTheme component for editing JSON theme files with schema validation\n */\nfunction EditorMonacoTheme({\n document,\n readOnly = false,\n onChange,\n}: {\n document: TextFile;\n readOnly?: boolean;\n onChange?: (value: string) => void;\n}) {\n const editorRef = useRef<MonacoEditorType.IStandaloneCodeEditor | null>(null);\n const monacoRef = useRef<Monaco | null>(null);\n const modelRef = useRef<MonacoEditorType.ITextModel | null>(null);\n const { theme } = useTheme();\n const [validationErrors, setValidationErrors] = useState<JsonEditorError[]>(\n []\n );\n const [showValidationPanel, setShowValidationPanel] = useState(true);\n const [isValidationPanelMinimized, setIsValidationPanelMinimized] =\n useState(false);\n const userDismissedRef = useRef(false);\n const pendingDiff = useDocumentsStore((s) => s.pendingDiffs[document.name]);\n const clearPendingDiff = useDocumentsStore((s) => s.clearPendingDiff);\n const saveDocument = useDocumentsStore((s) => s.saveDocument);\n const { registerEditor, unregisterEditor, setActiveEditor } =\n useEditorRefsStore();\n\n // Get resolved theme - convert 'system' to actual theme\n const resolvedTheme =\n theme === 'system'\n ? window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n : theme;\n\n // Initialize Monaco editor\n const handleEditorWillMount = useCallback((monaco: Monaco) => {\n monacoRef.current = monaco;\n // Idempotent; guards the case where an editor mounts before the global\n // configureMonaco() promise has resolved.\n registerMonacoThemes(monaco);\n // Don't call setDiagnosticsOptions here — it would clobber the global\n // config. The theme schema is already registered by configureMonacoInstance\n // and matched via defaultPath → fileMatch.\n }, []);\n\n // Handle editor mount\n const handleEditorMount = useCallback(\n (editor: MonacoEditorType.IStandaloneCodeEditor, monaco: Monaco) => {\n editorRef.current = editor;\n modelRef.current = editor.getModel();\n\n // Register editor in the refs store\n registerEditor(document.name, editor, monaco);\n setActiveEditor(document.name);\n\n // Enable constrained editing\n const constrainedInstance = constrainedEditor(monaco);\n const model = editor.getModel();\n if (model) {\n constrainedInstance.initializeIn(editor);\n }\n\n // Configure editor options\n editor.updateOptions({\n formatOnType: true,\n formatOnPaste: true,\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: true,\n wordWrap: 'on',\n folding: true,\n foldingStrategy: 'indentation',\n suggest: {\n showColors: true,\n showConstants: true,\n showEnums: true,\n showFields: true,\n showFunctions: true,\n showKeywords: true,\n showModules: true,\n showProperties: true,\n showSnippets: true,\n showStructs: true,\n showTypeParameters: true,\n showUnits: true,\n showValues: true,\n showVariables: true,\n },\n });\n\n // Add keyboard shortcuts\n // Cmd+K => send selection to AI assistant\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK, () => {\n const selection = getSelectionContext(editor, monaco);\n if (selection) {\n const snippet = createContextSnippet(selection);\n window.dispatchEvent(\n new CustomEvent('monaco-selection-to-ai', {\n detail: {\n documentName: document.name,\n selection,\n snippet,\n isTheme: true,\n },\n })\n );\n }\n });\n\n // Cmd+S => save command\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {\n // Save command - parent component handles this\n console.log('Save command triggered in theme editor');\n });\n\n // Add context menu action for AI assistant\n editor.addAction({\n id: 'send-theme-to-ai-assistant',\n label: 'Send to AI Assistant (⌘K)',\n contextMenuGroupId: 'navigation',\n contextMenuOrder: 1.5,\n keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK],\n run: function () {\n // Use the editor reference from closure instead of the parameter\n const selection = getSelectionContext(editor, monaco);\n if (selection) {\n const snippet = createContextSnippet(selection);\n // Dispatch event for the chat panel to capture\n window.dispatchEvent(\n new CustomEvent('monaco-selection-to-ai', {\n detail: {\n documentName: document.name,\n selection,\n snippet,\n isTheme: true,\n },\n })\n );\n }\n },\n });\n\n // Format document on mount\n setTimeout(() => {\n editor.getAction('editor.action.formatDocument')?.run();\n }, 100);\n\n console.log('Monaco theme editor mounted');\n },\n [document.name, registerEditor, setActiveEditor]\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n unregisterEditor(document.name);\n };\n }, [document.name, unregisterEditor]);\n\n // Handle content changes\n const handleChange = useCallback(\n (\n value: string | undefined,\n _event: MonacoEditorType.IModelContentChangedEvent\n ) => {\n if (value !== undefined && onChange) {\n onChange(value);\n }\n },\n [onChange]\n );\n\n // Handle Monaco's built-in schema validation markers\n const handleEditorValidation = useCallback(\n (markers: MonacoEditorType.IMarker[]) => {\n const errors: JsonEditorError[] = markers.map((marker) => ({\n path: '',\n message: marker.message,\n code:\n typeof marker.code === 'string'\n ? marker.code\n : marker.code?.value || 'validation_error',\n startLineNumber: marker.startLineNumber,\n startColumn: marker.startColumn,\n endLineNumber: marker.endLineNumber,\n endColumn: marker.endColumn,\n severity:\n marker.severity >= 8\n ? 'error'\n : marker.severity >= 4\n ? 'warning'\n : 'info',\n }));\n\n setValidationErrors(errors);\n\n if (errors.length > 0 && !userDismissedRef.current) {\n setShowValidationPanel(true);\n setIsValidationPanelMinimized(false);\n }\n if (errors.length === 0) {\n userDismissedRef.current = false;\n }\n },\n []\n );\n\n const handleErrorClick = useCallback((error: JsonEditorError) => {\n if (editorRef.current && error.startLineNumber && error.startColumn) {\n editorRef.current.setPosition({\n lineNumber: error.startLineNumber,\n column: error.startColumn,\n });\n editorRef.current.revealLineInCenter(error.startLineNumber);\n editorRef.current.focus();\n }\n }, []);\n\n // Update theme\n useEffect(() => {\n if (editorRef.current) {\n editorRef.current.updateOptions({ theme: monacoThemeFor(resolvedTheme) });\n }\n }, [resolvedTheme]);\n\n return (\n <div className=\"relative h-full\">\n {pendingDiff ? (\n <>\n <div className=\"flex items-center justify-between px-2 py-1 border-b bg-muted/40 text-xs\">\n <div>\n Review changes for{' '}\n <span className=\"font-medium\">{document.name}</span>\n </div>\n <div className=\"flex gap-2\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => clearPendingDiff(document.name)}\n >\n Discard\n </Button>\n <Button\n size=\"sm\"\n onClick={() => {\n saveDocument(document.name, pendingDiff.modified);\n clearPendingDiff(document.name, true);\n }}\n >\n Apply Changes\n </Button>\n </div>\n </div>\n <DiffEditor\n height=\"calc(100% - 32px)\"\n original={pendingDiff.original}\n modified={pendingDiff.modified}\n language=\"json\"\n theme={monacoThemeFor(resolvedTheme)}\n options={{\n readOnly: true,\n renderSideBySide: true,\n originalEditable: false,\n automaticLayout: true,\n minimap: { enabled: false },\n }}\n beforeMount={handleEditorWillMount}\n />\n </>\n ) : (\n <MonacoEditor\n height=\"100%\"\n language=\"json\"\n defaultPath={resolveThemeDefaultPath(document.name)}\n value={document.text}\n theme={monacoThemeFor(resolvedTheme)}\n onChange={handleChange}\n beforeMount={handleEditorWillMount}\n onMount={handleEditorMount}\n onValidate={handleEditorValidation}\n options={{\n readOnly,\n lineNumbers: 'on',\n glyphMargin: true,\n folding: true,\n lineDecorationsWidth: 5,\n lineNumbersMinChars: 3,\n renderValidationDecorations: 'on',\n quickSuggestions: {\n other: true,\n comments: false,\n strings: true,\n },\n acceptSuggestionOnCommitCharacter: true,\n acceptSuggestionOnEnter: 'on',\n accessibilitySupport: 'auto',\n autoIndent: 'advanced',\n formatOnType: true,\n formatOnPaste: true,\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: true,\n wordWrap: 'on',\n }}\n />\n )}\n\n {/* Validation Status Bar */}\n <div className=\"absolute top-0 right-0\">\n <ValidationStatusBar\n errors={validationErrors}\n onClick={() => {\n setShowValidationPanel(true);\n setIsValidationPanelMinimized(false);\n }}\n />\n </div>\n\n {/* Validation Panel */}\n {showValidationPanel && validationErrors.length > 0 && (\n <ValidationPanel\n errors={validationErrors}\n isMinimized={isValidationPanelMinimized}\n onToggleMinimize={() =>\n setIsValidationPanelMinimized(!isValidationPanelMinimized)\n }\n onErrorClick={handleErrorClick}\n onClose={() => {\n setShowValidationPanel(false);\n userDismissedRef.current = true;\n }}\n className=\"z-40\"\n />\n )}\n </div>\n );\n}\n\nexport const EditorMonacoThemeMemoized = React.memo(EditorMonacoTheme);\n","/**\n * A form derived from the theme's JSON Schema, for the keys the hand-built\n * sections do not cover — palette, type roles and scale, spacing, chrome\n * recipes, motif, component defaults.\n *\n * The schema already says everything a field needs: the key, its type, its\n * bounds, its enum, whether a string is a colour, and a description to show\n * as the hint. Deriving the form from it means a new theme key becomes\n * editable the day the schema learns it, and the editor never invents a\n * meaning the runtime does not share. What the schema cannot express as one\n * control — a value that is either a number or an object, an array of\n * objects, a free-form map — is shown as such and handed to the JSON view.\n *\n * Pure: schema and value in, field tree out. The React section renders it.\n */\nimport type { Path, ThemeJson } from './model';\nimport { isHexColor, resolveColor } from './model';\n\ntype JsonSchema = Record<string, any>;\n\nexport type SchemaFieldKind =\n | 'text'\n | 'number'\n | 'boolean'\n | 'enum'\n | 'color'\n | 'list'\n | 'group'\n | 'json';\n\nexport interface SchemaField {\n kind: SchemaFieldKind;\n key: string;\n path: Path;\n label: string;\n /** The schema's description, when it has one. */\n hint?: string;\n required?: boolean;\n /** `enum`: the accepted values. */\n options?: string[];\n /** `number`: bounds and integrality. */\n min?: number;\n max?: number;\n integer?: boolean;\n /** `list`: what one entry is. */\n item?: SchemaField;\n /** `group`: the nested fields, in schema order. */\n children?: SchemaField[];\n}\n\n/** `basePt` → \"Base pt\", `runningHead` → \"Running head\", `a4` → \"A4\". */\nexport function humanize(key: string): string {\n if (/^[a-z]\\d+$/.test(key)) return key.toUpperCase();\n const spaced = key\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .toLowerCase();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nconst COLOR_PATTERN = /\\[0-9A-Fa-f\\]\\{6\\}/;\n\nfunction enumOptions(schema: JsonSchema): string[] | undefined {\n if (Array.isArray(schema.enum))\n return schema.enum.every((v: unknown) => typeof v === 'string')\n ? schema.enum\n : undefined;\n const branches = schema.anyOf ?? schema.oneOf;\n if (\n Array.isArray(branches) &&\n branches.length > 0 &&\n branches.every(\n (b: JsonSchema) =>\n b && typeof b === 'object' && typeof b.const === 'string'\n )\n )\n return branches.map((b: JsonSchema) => b.const);\n return undefined;\n}\n\nfunction scalarKind(\n schema: JsonSchema\n): Exclude<SchemaFieldKind, 'list' | 'group' | 'json'> | undefined {\n const options = enumOptions(schema);\n if (options) return 'enum';\n switch (schema.type) {\n case 'string':\n return typeof schema.pattern === 'string' &&\n COLOR_PATTERN.test(schema.pattern)\n ? 'color'\n : 'text';\n case 'number':\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n default:\n return undefined;\n }\n}\n\n/** One field for one property schema; `json` when no single control fits. */\nexport function schemaField(\n key: string,\n schema: JsonSchema,\n path: Path,\n required = false\n): SchemaField {\n const base: SchemaField = {\n kind: 'json',\n key,\n path,\n label: humanize(key),\n ...(typeof schema?.description === 'string' && {\n hint: schema.description,\n }),\n ...(required && { required }),\n };\n if (!schema || typeof schema !== 'object') return base;\n const scalar = scalarKind(schema);\n if (scalar) {\n const field: SchemaField = { ...base, kind: scalar };\n if (scalar === 'enum') field.options = enumOptions(schema);\n if (scalar === 'number') {\n const integer = schema.type === 'integer';\n const step = integer ? 1 : 0.5;\n const min =\n schema.minimum ??\n (typeof schema.exclusiveMinimum === 'number'\n ? schema.exclusiveMinimum + step\n : undefined);\n const max =\n schema.maximum ??\n (typeof schema.exclusiveMaximum === 'number'\n ? schema.exclusiveMaximum - step\n : undefined);\n if (min !== undefined) field.min = min;\n if (max !== undefined) field.max = max;\n if (integer) field.integer = true;\n }\n return field;\n }\n if (schema.type === 'object' && schema.properties) {\n const requiredKeys = new Set<string>(schema.required ?? []);\n return {\n ...base,\n kind: 'group',\n children: Object.entries(schema.properties as Record<string, JsonSchema>)\n .filter(([child]) => child !== '$schema')\n .map(([child, sub]) =>\n schemaField(child, sub, [...path, child], requiredKeys.has(child))\n ),\n };\n }\n if (\n schema.type === 'array' &&\n schema.items &&\n typeof schema.items === 'object' &&\n !Array.isArray(schema.items) &&\n scalarKind(schema.items)\n ) {\n return {\n ...base,\n kind: 'list',\n item: schemaField('item', schema.items, [...path, 0]),\n ...(typeof schema.maxItems === 'number' && { max: schema.maxItems }),\n ...(typeof schema.minItems === 'number' && { min: schema.minItems }),\n };\n }\n return base;\n}\n\nexport interface SchemaSection {\n key: string;\n title: string;\n hint?: string;\n fields: SchemaField[];\n}\n\n/**\n * Titles for the keys the design system names, where the humanized key\n * would collide with a hand-built section (\"Typography\" is the fonts) or\n * say less than the rail should.\n */\nconst SECTION_TITLES: Record<string, string> = {\n palette: 'Palette',\n typography: 'Type roles & scale',\n spacing: 'Spacing',\n chrome: 'Chrome recipes',\n motif: 'Motif',\n componentDefaults: 'Component defaults',\n};\n\n/**\n * The top-level keys the schema declares as objects with named properties\n * and no hand-built section claims — one form section each, in schema\n * order. Keys the schema types otherwise (a font registry array, a word\n * list) stay in the Advanced list with the JSON view.\n */\nexport function extendedSections(\n schema: JsonSchema | null,\n handledKeys: readonly string[]\n): SchemaSection[] {\n if (!schema?.properties) return [];\n const handled = new Set(handledKeys);\n return Object.entries(schema.properties as Record<string, JsonSchema>)\n .filter(\n ([key, sub]) =>\n !handled.has(key) &&\n key !== '$schema' &&\n sub &&\n typeof sub === 'object' &&\n sub.type === 'object' &&\n sub.properties\n )\n .map(([key, sub]) => {\n const field = schemaField(key, sub, [key]);\n return {\n key,\n title: SECTION_TITLES[key] ?? humanize(key),\n ...(field.hint && { hint: field.hint }),\n fields: field.children ?? [],\n };\n });\n}\n\n/** The keys the schema declares at the top level, `$schema` aside. */\nexport function schemaTopLevelKeys(schema: JsonSchema | null): string[] {\n return Object.keys(schema?.properties ?? {}).filter(\n (key) => key !== '$schema'\n );\n}\n\n/** Case-insensitive substring match of a query against any of the terms. */\nexport function matchesQuery(\n query: string,\n ...terms: (string | undefined)[]\n): boolean {\n const needle = query.trim().toLowerCase();\n if (!needle) return true;\n return terms.some((term) => term?.toLowerCase().includes(needle));\n}\n\n/**\n * The fields a search keeps: a field matches on its key, label, hint or\n * path; a group is kept whole when its own name matches, else pruned to the\n * children that match. An empty query keeps everything.\n */\nexport function filterFields(\n fields: readonly SchemaField[],\n query: string\n): SchemaField[] {\n if (!query.trim()) return [...fields];\n const out: SchemaField[] = [];\n for (const field of fields) {\n const own = matchesQuery(\n query,\n field.key,\n field.label,\n field.hint,\n field.path.join('.')\n );\n if (field.kind === 'group' && field.children) {\n if (own) out.push(field);\n else {\n const children = filterFields(field.children, query);\n if (children.length) out.push({ ...field, children });\n }\n } else if (own) out.push(field);\n }\n return out;\n}\n\n/**\n * Why a JSON value cannot be edited by its field's control, or null when it\n * can. A value of the wrong shape is left alone and pointed at the JSON\n * view rather than silently replaced.\n */\nexport function fieldValueError(\n field: SchemaField,\n value: unknown\n): string | null {\n if (value === undefined) return null;\n switch (field.kind) {\n case 'text':\n case 'color':\n case 'enum':\n return typeof value === 'string' ? null : 'Not a string';\n case 'number':\n return typeof value === 'number' ? null : 'Not a number';\n case 'boolean':\n return typeof value === 'boolean' ? null : 'Not a boolean';\n case 'list':\n return Array.isArray(value) ? null : 'Not a list';\n case 'group':\n return value && typeof value === 'object' && !Array.isArray(value)\n ? null\n : 'Not an object';\n default:\n return null;\n }\n}\n\n/**\n * Resolve a colour the way the design system reads it: a hex, a theme\n * colour token, or a palette token that itself names either. One hop\n * through the palette is enough — the palette's own values resolve through\n * the theme colours — and a cycle ends in null, not a loop.\n */\nexport function resolveThemeColor(\n theme: ThemeJson,\n value: unknown\n): string | null {\n const direct = resolveColor(theme, value);\n if (direct) return direct;\n if (typeof value !== 'string') return null;\n const palette = theme.palette as Record<string, unknown> | undefined;\n const entry = palette?.[value];\n if (typeof entry !== 'string' || entry === value) return null;\n return isHexColor(entry) ? entry : resolveColor(theme, entry);\n}\n\n/** A short reading of a value the form shows but does not edit. */\nexport function summarizeValue(value: unknown): string {\n if (value === undefined) return 'Not set';\n if (Array.isArray(value))\n return `${value.length} item${value.length === 1 ? '' : 's'}`;\n if (value && typeof value === 'object') {\n const keys = Object.keys(value as object);\n return keys.length === 0\n ? 'Empty'\n : keys.slice(0, 4).join(', ') + (keys.length > 4 ? ', …' : '');\n }\n const text = String(value);\n return text.length > 40 ? `${text.slice(0, 40)}…` : text;\n}\n","/**\n * Theme JSON Schema — fetched from the server (format-aware)\n */\n\nlet _cachedSchema: any | null = null;\n\n/**\n * Fetch the theme JSON schema from the server.\n * Result is cached for the lifetime of the session.\n */\nexport async function fetchThemeJsonSchema(): Promise<any> {\n if (_cachedSchema) return _cachedSchema;\n\n const res = await fetch('/api/discovery/schemas/theme');\n const json = await res.json();\n if (!json.success)\n throw new Error(json.error ?? 'Failed to fetch theme schema');\n\n _cachedSchema = json.data;\n return _cachedSchema;\n}\n","import * as React from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { cn } from '@/lib/utils';\n\nconst Popover = PopoverPrimitive.Root;\nconst PopoverTrigger = PopoverPrimitive.Trigger;\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'start', sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-lg border p-3 shadow-lg outline-none',\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };\n","/**\n * Hex ↔ HSV, for the picker only.\n *\n * The theme stores 6-digit hex and nothing else, so HSV exists purely as the\n * shape a saturation square and a hue rail can be dragged in. Round trips are\n * lossy at the edges (every grey is hue 0 after a trip through hex), which is\n * why the picker keeps its own HSV while it is open rather than re-deriving\n * it from the value on every drag.\n */\n\nexport interface Hsv {\n /** 0–360 */\n h: number;\n /** 0–1 */\n s: number;\n /** 0–1 */\n v: number;\n}\n\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\nexport function hexToRgb(hex: string): Rgb | null {\n const match = hex.match(/^#?([0-9A-Fa-f]{6})$/);\n if (!match) return null;\n const int = parseInt(match[1], 16);\n return { r: (int >> 16) & 255, g: (int >> 8) & 255, b: int & 255 };\n}\n\nexport function rgbToHex({ r, g, b }: Rgb): string {\n const channel = (value: number) =>\n Math.max(0, Math.min(255, Math.round(value)))\n .toString(16)\n .padStart(2, '0')\n .toUpperCase();\n return `#${channel(r)}${channel(g)}${channel(b)}`;\n}\n\nexport function rgbToHsv({ r, g, b }: Rgb): Hsv {\n const red = r / 255;\n const green = g / 255;\n const blue = b / 255;\n const max = Math.max(red, green, blue);\n const min = Math.min(red, green, blue);\n const span = max - min;\n let h = 0;\n if (span !== 0) {\n if (max === red) h = ((green - blue) / span) % 6;\n else if (max === green) h = (blue - red) / span + 2;\n else h = (red - green) / span + 4;\n h *= 60;\n if (h < 0) h += 360;\n }\n return { h, s: max === 0 ? 0 : span / max, v: max };\n}\n\nexport function hsvToRgb({ h, s, v }: Hsv): Rgb {\n const hue = ((h % 360) + 360) % 360;\n const c = v * s;\n const x = c * (1 - Math.abs(((hue / 60) % 2) - 1));\n const m = v - c;\n const [r, g, b] =\n hue < 60\n ? [c, x, 0]\n : hue < 120\n ? [x, c, 0]\n : hue < 180\n ? [0, c, x]\n : hue < 240\n ? [0, x, c]\n : hue < 300\n ? [x, 0, c]\n : [c, 0, x];\n return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };\n}\n\nexport function hexToHsv(hex: string): Hsv | null {\n const rgb = hexToRgb(hex);\n return rgb ? rgbToHsv(rgb) : null;\n}\n\nexport function hsvToHex(hsv: Hsv): string {\n return rgbToHex(hsvToRgb(hsv));\n}\n\n/** Black or white, whichever reads on `hex`. For text drawn over a swatch. */\nexport function readableInk(hex: string): string {\n const rgb = hexToRgb(hex);\n if (!rgb) return '#000000';\n // Perceived brightness (ITU-R BT.601), the cheap version that is right\n // often enough for a 20px chip.\n const brightness = (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;\n return brightness > 140 ? '#000000' : '#FFFFFF';\n}\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Check, Pipette, X } from 'lucide-react';\nimport { Input } from '../ui/input';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';\nimport {\n hexToHsv,\n hsvToHex,\n readableInk,\n type Hsv,\n} from '../../lib/theme-editor/color';\nimport {\n normalizeHex,\n resolveColor,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport { cn } from '../../lib/utils';\nimport { INPUT_CLASS, useDraft } from './theme-editor-shared';\n\n/**\n * The colour control: a swatch that opens a picker, and a field beside it\n * that still takes a typed hex — or the name of another token, because both\n * schemas let one colour reference another.\n *\n * The picker holds its own HSV for as long as it is open. Hex is a lossy\n * home for it (every grey comes back as hue 0, black loses saturation), so\n * re-deriving HSV from the committed value on each drag would make the hue\n * rail jump under the pointer at the edges of the square.\n *\n * Dragging writes through on an animation frame rather than on every pointer\n * move: one theme edit is a re-parse and a re-serialise of the whole file, and\n * a 120Hz trackpad would otherwise ask for a hundred of them a second.\n */\n\nconst TOKEN_NAME = /^[a-zA-Z][a-zA-Z0-9]*$/;\nconst PLACEHOLDER_HEX = '#D4D4D8';\n\nexport interface ColorToken {\n key: string;\n hex: string;\n}\n\n/** Commit at most once per frame while a pointer drag is in flight. */\nfunction useFrameCommit(commit: (hex: string) => void) {\n const pending = useRef<string | null>(null);\n const frame = useRef<number | null>(null);\n const latest = useRef(commit);\n latest.current = commit;\n\n const flush = useCallback(() => {\n frame.current = null;\n const value = pending.current;\n pending.current = null;\n if (value !== null) latest.current(value);\n }, []);\n\n const schedule = useCallback(\n (hex: string) => {\n pending.current = hex;\n if (frame.current === null) {\n frame.current = requestAnimationFrame(flush);\n }\n },\n [flush]\n );\n\n // A drag that ends between frames must not lose its last position.\n const finish = useCallback(() => {\n if (frame.current !== null) {\n cancelAnimationFrame(frame.current);\n flush();\n }\n }, [flush]);\n\n useEffect(\n () => () => {\n if (frame.current !== null) cancelAnimationFrame(frame.current);\n },\n []\n );\n\n return { schedule, finish };\n}\n\n/** Pointer drag over a box, reported as 0–1 on each axis. */\nfunction useDragArea(\n onMove: (x: number, y: number) => void,\n onEnd: () => void\n) {\n const ref = useRef<HTMLDivElement | null>(null);\n const report = useCallback(\n (event: React.PointerEvent) => {\n const box = ref.current?.getBoundingClientRect();\n if (!box || box.width === 0 || box.height === 0) return;\n const x = (event.clientX - box.left) / box.width;\n const y = (event.clientY - box.top) / box.height;\n onMove(Math.min(1, Math.max(0, x)), Math.min(1, Math.max(0, y)));\n },\n [onMove]\n );\n const onPointerDown = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n report(event);\n },\n [report]\n );\n const onPointerMove = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (!event.currentTarget.hasPointerCapture(event.pointerId)) return;\n report(event);\n },\n [report]\n );\n const onPointerUp = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n onEnd();\n },\n [onEnd]\n );\n return { ref, onPointerDown, onPointerMove, onPointerUp };\n}\n\nfunction SaturationArea({\n hsv,\n onChange,\n onEnd,\n}: {\n hsv: Hsv;\n onChange: (next: Hsv) => void;\n onEnd: () => void;\n}) {\n const move = useCallback(\n (x: number, y: number) => onChange({ ...hsv, s: x, v: 1 - y }),\n [hsv, onChange]\n );\n const drag = useDragArea(move, onEnd);\n const step = useCallback(\n (event: React.KeyboardEvent) => {\n const delta = event.shiftKey ? 0.1 : 0.02;\n const map: Record<string, Partial<Hsv>> = {\n ArrowLeft: { s: Math.max(0, hsv.s - delta) },\n ArrowRight: { s: Math.min(1, hsv.s + delta) },\n ArrowUp: { v: Math.min(1, hsv.v + delta) },\n ArrowDown: { v: Math.max(0, hsv.v - delta) },\n };\n const next = map[event.key];\n if (!next) return;\n event.preventDefault();\n onChange({ ...hsv, ...next });\n onEnd();\n },\n [hsv, onChange, onEnd]\n );\n return (\n <div\n ref={drag.ref}\n role=\"application\"\n aria-label=\"Saturation and brightness\"\n tabIndex={0}\n onPointerDown={drag.onPointerDown}\n onPointerMove={drag.onPointerMove}\n onPointerUp={drag.onPointerUp}\n onKeyDown={step}\n className={cn(\n 'relative h-32 w-full cursor-crosshair touch-none overflow-hidden rounded-sm border',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n style={{ backgroundColor: hsvToHex({ h: hsv.h, s: 1, v: 1 }) }}\n >\n <div className=\"absolute inset-0 bg-[linear-gradient(to_right,#fff,transparent)]\" />\n <div className=\"absolute inset-0 bg-[linear-gradient(to_top,#000,transparent)]\" />\n <span\n aria-hidden\n className=\"absolute size-3 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0_0_0_1px_rgba(0,0,0,0.45)]\"\n style={{\n left: `${hsv.s * 100}%`,\n top: `${(1 - hsv.v) * 100}%`,\n backgroundColor: hsvToHex(hsv),\n }}\n />\n </div>\n );\n}\n\nconst HUE_GRADIENT =\n 'linear-gradient(to right,#FF0000,#FFFF00,#00FF00,#00FFFF,#0000FF,#FF00FF,#FF0000)';\n\nfunction HueRail({\n hsv,\n onChange,\n onEnd,\n}: {\n hsv: Hsv;\n onChange: (next: Hsv) => void;\n onEnd: () => void;\n}) {\n const move = useCallback(\n (x: number) => onChange({ ...hsv, h: x * 360 }),\n [hsv, onChange]\n );\n const drag = useDragArea(move, onEnd);\n return (\n <div\n ref={drag.ref}\n role=\"slider\"\n aria-label=\"Hue\"\n aria-valuemin={0}\n aria-valuemax={360}\n aria-valuenow={Math.round(hsv.h)}\n tabIndex={0}\n onPointerDown={drag.onPointerDown}\n onPointerMove={drag.onPointerMove}\n onPointerUp={drag.onPointerUp}\n onKeyDown={(event) => {\n const delta =\n event.key === 'ArrowLeft' ? -1 : event.key === 'ArrowRight' ? 1 : 0;\n if (!delta) return;\n event.preventDefault();\n onChange({\n ...hsv,\n h: (hsv.h + delta * (event.shiftKey ? 10 : 2) + 360) % 360,\n });\n onEnd();\n }}\n className={cn(\n 'relative h-3 w-full cursor-ew-resize touch-none rounded-full border',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n style={{ background: HUE_GRADIENT }}\n >\n <span\n aria-hidden\n className=\"absolute top-1/2 size-3.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0_0_0_1px_rgba(0,0,0,0.45)]\"\n style={{\n left: `${(hsv.h / 360) * 100}%`,\n backgroundColor: hsvToHex({ h: hsv.h, s: 1, v: 1 }),\n }}\n />\n </div>\n );\n}\n\nfunction TokenChips({\n tokens,\n active,\n onPick,\n}: {\n tokens: readonly ColorToken[];\n active: string | null;\n onPick: (key: string) => void;\n}) {\n return (\n <div className=\"flex flex-wrap gap-1\">\n {tokens.map((token) => {\n const selected = token.key === active;\n return (\n <Tooltip key={token.key}>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => onPick(token.key)}\n aria-label={`Use token ${token.key}`}\n aria-pressed={selected}\n className={cn(\n 'flex size-6 cursor-pointer items-center justify-center rounded-sm border',\n 'transition-shadow focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n selected\n ? 'ring-1 ring-ring ring-offset-1 ring-offset-popover'\n : 'border-border/70'\n )}\n style={{ backgroundColor: token.hex }}\n >\n {selected && (\n <Check\n className=\"size-3\"\n style={{ color: readableInk(token.hex) }}\n aria-hidden\n />\n )}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p className=\"font-mono text-xs\">\n {token.key} {token.hex}\n </p>\n </TooltipContent>\n </Tooltip>\n );\n })}\n </div>\n );\n}\n\n/**\n * Swatch + field. The swatch opens the picker; the field takes a hex, or a\n * token name when `allowReference`.\n */\nexport function ColorControl({\n id,\n label,\n value,\n resolved,\n onCommit,\n allowReference = true,\n tokens,\n className,\n}: {\n id?: string;\n label: string;\n /** Raw JSON value: a hex, a token name, or nothing. */\n value: string | undefined;\n /** What the value resolves to after following references. */\n resolved: string | null;\n onCommit: (next: string | null) => void;\n allowReference?: boolean;\n /** Theme colours offered as one-click references inside the picker. */\n tokens?: readonly ColorToken[];\n className?: string;\n}) {\n const [open, setOpen] = useState(false);\n const commitText = useCallback(\n (draft: string) => {\n const trimmed = draft.trim();\n if (trimmed === '') {\n onCommit(null);\n return;\n }\n const hex = normalizeHex(trimmed);\n if (/^#[0-9A-F]{6}$/.test(hex)) {\n onCommit(hex);\n return;\n }\n if (allowReference && TOKEN_NAME.test(trimmed)) onCommit(trimmed);\n // Anything else reverts: the input drops its draft on blur regardless.\n },\n [allowReference, onCommit]\n );\n const { props: draft } = useDraft(value ?? '', commitText);\n const swatch = resolved ?? PLACEHOLDER_HEX;\n const reference = value && !value.startsWith('#') ? value : null;\n\n return (\n <div className={cn('flex min-w-0 items-center gap-1.5', className)}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={`${label} picker`}\n className={cn(\n 'relative size-6 shrink-0 cursor-pointer overflow-hidden rounded-sm border',\n 'transition-shadow focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n resolved\n ? 'border-border hover:ring-1 hover:ring-ring/50'\n : 'border-dashed border-muted-foreground/40 opacity-60'\n )}\n style={{ backgroundColor: swatch }}\n />\n </PopoverTrigger>\n {/* Focus lands on the saturation square, which takes arrow keys, so\n the picker is usable without a pointer from the moment it opens. */}\n <PopoverContent className=\"w-64\">\n <ColorPickerBody\n label={label}\n value={value}\n resolved={resolved}\n tokens={allowReference ? tokens : undefined}\n onCommit={onCommit}\n onDone={() => setOpen(false)}\n />\n </PopoverContent>\n </Popover>\n <Input\n id={id}\n type=\"text\"\n aria-label={label}\n autoComplete=\"off\"\n spellCheck={false}\n placeholder=\"#RRGGBB\"\n title={reference && resolved ? `${reference} → ${resolved}` : undefined}\n className={cn(\n INPUT_CLASS,\n 'w-full min-w-0 font-mono',\n reference ? 'lowercase' : 'uppercase'\n )}\n {...draft}\n />\n </div>\n );\n}\n\nfunction ColorPickerBody({\n label,\n value,\n resolved,\n tokens,\n onCommit,\n onDone,\n}: {\n label: string;\n value: string | undefined;\n resolved: string | null;\n tokens?: readonly ColorToken[];\n onCommit: (next: string | null) => void;\n onDone: () => void;\n}) {\n // Seeded once per opening — this body only exists while the popover is up —\n // so HSV is the truth for as long as it lasts and hex is derived from it: a\n // drag through grey or black keeps the hue it came in with.\n const [hsv, setHsv] = useState<Hsv>(\n () => hexToHsv(resolved ?? PLACEHOLDER_HEX) ?? { h: 0, s: 0, v: 0.8 }\n );\n const seeded = useRef(resolved);\n if (resolved !== seeded.current) {\n // A token chip or a typed hex changed the value from outside the square.\n seeded.current = resolved;\n const next = hexToHsv(resolved ?? PLACEHOLDER_HEX);\n if (next) setHsv(next);\n }\n\n const commitHex = useCallback((hex: string) => onCommit(hex), [onCommit]);\n const { schedule, finish } = useFrameCommit(commitHex);\n const onChange = useCallback(\n (next: Hsv) => {\n setHsv(next);\n const hex = hsvToHex(next);\n seeded.current = hex;\n schedule(hex);\n },\n [schedule]\n );\n\n const hex = hsvToHex(hsv);\n const eyedropper =\n typeof window !== 'undefined' && 'EyeDropper' in window\n ? async () => {\n try {\n const EyeDropperCtor = (\n window as unknown as {\n EyeDropper: new () => {\n open: () => Promise<{ sRGBHex: string }>;\n };\n }\n ).EyeDropper;\n const picked = await new EyeDropperCtor().open();\n const normalized = normalizeHex(picked.sRGBHex);\n if (/^#[0-9A-F]{6}$/.test(normalized)) onCommit(normalized);\n } catch {\n // Dismissed, or denied. Nothing to say about either.\n }\n }\n : null;\n\n return (\n <div className=\"flex flex-col gap-2.5\">\n <SaturationArea hsv={hsv} onChange={onChange} onEnd={finish} />\n <HueRail hsv={hsv} onChange={onChange} onEnd={finish} />\n <div className=\"flex items-center gap-1.5\">\n <span\n aria-hidden\n className=\"size-6 shrink-0 rounded-sm border\"\n style={{ backgroundColor: resolved ?? PLACEHOLDER_HEX }}\n />\n <PickerHexInput hex={hex} onCommit={onCommit} label={label} />\n {eyedropper && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={eyedropper}\n aria-label=\"Pick a colour from the screen\"\n className={cn(\n 'flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-sm',\n 'text-muted-foreground transition-colors hover:bg-accent hover:text-foreground',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <Pipette className=\"size-3.5\" aria-hidden />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>Pick from the screen</p>\n </TooltipContent>\n </Tooltip>\n )}\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => {\n onCommit(null);\n onDone();\n }}\n aria-label={`Clear ${label}`}\n disabled={value === undefined}\n className={cn(\n 'flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-sm',\n 'text-muted-foreground transition-colors hover:bg-accent hover:text-foreground',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n 'disabled:pointer-events-none disabled:opacity-40'\n )}\n >\n <X className=\"size-3.5\" aria-hidden />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>Clear</p>\n </TooltipContent>\n </Tooltip>\n </div>\n {tokens && tokens.length > 0 && (\n <div className=\"flex flex-col gap-1.5 border-t pt-2\">\n <span className=\"text-[10px] font-medium tracking-[0.08em] text-muted-foreground uppercase\">\n Theme colours\n </span>\n <TokenChips\n tokens={tokens}\n active={value && !value.startsWith('#') ? value : null}\n onPick={(key) => onCommit(key)}\n />\n <p className=\"text-[11px] leading-snug text-muted-foreground\">\n A token follows the theme when that colour changes; a hex does not.\n </p>\n </div>\n )}\n </div>\n );\n}\n\n/** The hex inside the popover: shows the square's live value, commits on blur. */\nfunction PickerHexInput({\n hex,\n label,\n onCommit,\n}: {\n hex: string;\n label: string;\n onCommit: (next: string | null) => void;\n}) {\n const commit = useCallback(\n (draft: string) => {\n const normalized = normalizeHex(draft);\n if (/^#[0-9A-F]{6}$/.test(normalized)) onCommit(normalized);\n },\n [onCommit]\n );\n const { props: draft } = useDraft(hex, commit);\n return (\n <Input\n type=\"text\"\n aria-label={`${label} hex`}\n autoComplete=\"off\"\n spellCheck={false}\n // Flat on the popover, like every other input in the app is flat on\n // the surface behind it; `bg-background` here would read as a filled\n // field only because the popover is a lighter white.\n className={cn(\n INPUT_CLASS,\n 'h-7 min-w-0 flex-1 bg-transparent font-mono uppercase'\n )}\n {...draft}\n />\n );\n}\n\n/**\n * Theme colours as picker chips, memoised on the colours themselves.\n *\n * Every edit anywhere in a theme produces a new parse, so a list derived from\n * the theme object would be a new array each time and would re-render every\n * memoised row that holds one. Keyed on the serialised colours, the identity\n * only moves when the palette actually does.\n */\nexport function useThemeColorTokens(theme: ThemeJson): ColorToken[] {\n const json = JSON.stringify(theme.colors ?? null);\n return useMemo(() => {\n const colors = JSON.parse(json) as Record<string, unknown> | null;\n // `themeColorTokens` reads nothing but `colors`, so this stands in for\n // the whole theme.\n return colors ? themeColorTokens({ colors }) : [];\n }, [json]);\n}\n\n/** Theme colours as picker chips, in the order the theme declares them. */\nexport function themeColorTokens(theme: ThemeJson): ColorToken[] {\n const colors = theme.colors;\n if (!colors || typeof colors !== 'object') return [];\n const out: ColorToken[] = [];\n for (const [key, value] of Object.entries(\n colors as Record<string, unknown>\n )) {\n const hex = resolveColor(theme, value);\n if (hex) out.push({ key, hex });\n }\n return out;\n}\n","import React, { useCallback, useMemo } from 'react';\nimport { CornerDownRight } from 'lucide-react';\nimport { FORMAT } from '../../lib/env';\nimport {\n colorTokens,\n contrastRatio,\n isHexColor,\n resolveColor,\n type ColorTokenDescriptor,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport { cn } from '../../lib/utils';\nimport {\n ClearButton,\n ContrastBadge,\n EditorSection,\n GroupLabel,\n HINT_CLASS,\n useThemeEditor,\n} from './theme-editor-shared';\nimport {\n ColorControl,\n useThemeColorTokens,\n type ColorToken,\n} from './color-picker';\nimport { matchesQuery } from '../../lib/theme-editor/schema-form';\n\n/**\n * One row per token the schema declares, in the schema's groups. A token may\n * hold a hex or the name of another token; the row shows the resolved swatch\n * either way and says where a reference points, so `accent5: \"primary\"`\n * never looks like a colour of its own.\n */\n\nconst TOKENS = colorTokens(FORMAT);\nconst GROUPS = Array.from(new Set(TOKENS.map((t) => t.group)));\n\ninterface RowState {\n raw: string | undefined;\n resolved: string | null;\n /** The token a reference points at; null for a hex or nothing. */\n reference: string | null;\n error: string | null;\n}\n\nfunction rowState(theme: ThemeJson, token: ColorTokenDescriptor): RowState {\n const colors = theme.colors as Record<string, unknown> | undefined;\n const value = colors?.[token.key];\n const raw = typeof value === 'string' ? value : undefined;\n const resolved = resolveColor(theme, raw);\n const reference =\n raw !== undefined && !isHexColor(raw) && resolved ? raw : null;\n let error: string | null = null;\n if (raw === undefined && value !== undefined) error = 'Must be a string';\n else if (raw === undefined && token.required) error = 'Required';\n else if (raw !== undefined && !resolved) {\n error = /^[a-zA-Z][a-zA-Z0-9]*$/.test(raw)\n ? `No token named \"${raw}\"`\n : 'Not a hex colour';\n }\n return { raw, resolved, reference, error };\n}\n\nconst ColorRow = React.memo(function ColorRow({\n token,\n raw,\n resolved,\n reference,\n error,\n tokens,\n}: { token: ColorTokenDescriptor; tokens: readonly ColorToken[] } & RowState) {\n const { set, remove } = useThemeEditor();\n const commit = useCallback(\n (next: string | null) => {\n if (next === null) remove(['colors', token.key]);\n else set(['colors', token.key], next);\n },\n [remove, set, token.key]\n );\n const clear = useCallback(\n () => remove(['colors', token.key]),\n [remove, token.key]\n );\n const inputId = `theme-color-${token.key}`;\n return (\n <div className=\"flex min-h-8 items-center gap-2\">\n <ColorControl\n id={inputId}\n label={token.label}\n value={raw}\n resolved={resolved}\n onCommit={commit}\n tokens={tokens}\n // Narrow panes give the width back to the token name and its\n // hint; a hex needs 96px and no more.\n className=\"w-[8.5rem] shrink-0 @[30rem]:w-[10.5rem]\"\n />\n <div className=\"flex min-w-0 flex-1 flex-col justify-center\">\n <div className=\"flex min-w-0 items-center gap-1.5\">\n <label htmlFor={inputId} className=\"truncate text-sm\">\n {token.label}\n </label>\n <code className=\"truncate text-[10px] text-muted-foreground\">\n {token.key}\n </code>\n {token.required && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1 text-[10px] tracking-wide text-muted-foreground uppercase\">\n required\n </span>\n )}\n </div>\n <p className={cn(HINT_CLASS, 'truncate')}>\n {error ? (\n <span className=\"text-destructive\">{error}</span>\n ) : reference ? (\n <span className=\"inline-flex items-center gap-1\">\n <CornerDownRight className=\"size-3\" aria-hidden />\n <code>{reference}</code>\n <span>{resolved}</span>\n </span>\n ) : (\n token.hint\n )}\n </p>\n </div>\n {raw !== undefined && !token.required ? (\n <ClearButton label={`Clear ${token.label}`} onClick={clear} />\n ) : (\n <span className=\"size-6 shrink-0\" aria-hidden />\n )}\n </div>\n );\n});\n\nexport function ThemeColorsSection({\n theme,\n query = '',\n}: {\n theme: ThemeJson;\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const rows = useMemo(\n () =>\n TOKENS.filter(\n (token) =>\n matchesQuery(query, 'colours', 'colors') ||\n matchesQuery(query, token.key, token.label, token.group, token.hint)\n ).map((token) => ({ token, ...rowState(theme, token) })),\n [query, theme]\n );\n\n const contrast = useMemo(() => {\n const colors = theme.colors as Record<string, unknown> | undefined;\n const background = resolveColor(theme, colors?.background);\n const text = resolveColor(theme, colors?.text);\n const primary = resolveColor(theme, colors?.primary);\n return {\n text: background && text ? contrastRatio(text, background) : null,\n primary:\n background && primary ? contrastRatio(primary, background) : null,\n };\n }, [theme]);\n\n // Chips inside each picker: every colour this theme already resolves, so a\n // token can be reused without leaving the row it is being set on.\n const tokens = useThemeColorTokens(theme);\n const defined = rows.filter((r) => r.raw !== undefined).length;\n if (searching && rows.length === 0) return null;\n\n return (\n <EditorSection\n title=\"Colours\"\n hint=\"Hex values, or the name of another token to reuse it. Required tokens are what the compiler reads directly; the rest are optional slots.\"\n forceOpen={searching ? true : undefined}\n actions={\n <span className=\"text-[11px] tabular-nums text-muted-foreground\">\n {defined}/{TOKENS.length}\n </span>\n }\n >\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1\">\n <ContrastBadge label=\"Text on background\" ratio={contrast.text} />\n <ContrastBadge label=\"Primary on background\" ratio={contrast.primary} />\n </div>\n {GROUPS.filter((group) =>\n rows.some((row) => row.token.group === group)\n ).map((group) => (\n <div key={group} className=\"flex flex-col gap-1\">\n <GroupLabel>{group}</GroupLabel>\n {rows\n .filter((row) => row.token.group === group)\n .map((row) => (\n <ColorRow\n key={row.token.key}\n token={row.token}\n raw={row.raw}\n resolved={row.resolved}\n reference={row.reference}\n error={row.error}\n tokens={tokens}\n />\n ))}\n </div>\n ))}\n </EditorSection>\n );\n}\n","import React, { useCallback, useMemo, useRef, useState } from 'react';\nimport { Check, ChevronsUpDown, Search, Type } from 'lucide-react';\nimport { Input } from '../ui/input';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { useFontPickerStore } from '../../store/font-picker-store';\nimport type { Path } from '../../lib/theme-editor/model';\nimport { cn } from '../../lib/utils';\nimport {\n HINT_CLASS,\n QuietButton,\n useFontCatalog,\n type FontCatalog,\n} from './theme-editor-shared';\n\n/**\n * A font family as a combobox: the catalog filtered as you type, with the\n * typed text itself always on offer — a theme may legitimately name a face\n * this browser has never heard of, and refusing it would make the form less\n * capable than the JSON it edits.\n *\n * Only a slice of the matches is rendered. The Google list is ~1500 families,\n * and a combobox that has to lay out 1500 rows before it can show the first\n * one stops feeling like a text field.\n */\n\nconst MAX_ROWS = 40;\n\ninterface Option {\n family: string;\n /** \"Safe\" for the OS list, else the Google category. */\n tag: string;\n safe: boolean;\n}\n\nfunction buildOptions(catalog: FontCatalog): Option[] {\n return [\n ...catalog.safe.map((family) => ({ family, tag: 'safe', safe: true })),\n ...catalog.google.map((font) => ({\n family: font.family,\n tag: font.category,\n safe: false,\n })),\n ];\n}\n\nfunction score(family: string, query: string): number {\n const lower = family.toLowerCase();\n if (lower === query) return 0;\n if (lower.startsWith(query)) return 1;\n const index = lower.indexOf(query);\n return index === -1 ? -1 : 2 + index;\n}\n\n/**\n * With a query, the best `MAX_ROWS` matches. Without one, the current family\n * first and the catalog after it.\n *\n * Pinning the current value is what makes the unfiltered list honest: the\n * catalog runs to hundreds of families and only a window of it is rendered,\n * so a theme naming the four-hundredth would otherwise open a list its own\n * value is not in — with the first row highlighted, one Return away from\n * replacing it.\n */\nfunction filterOptions(\n options: Option[],\n query: string,\n current: string | undefined\n): Option[] {\n const trimmed = query.trim().toLowerCase();\n if (!trimmed) {\n if (!current) return options.slice(0, MAX_ROWS);\n const known = options.find((option) => option.family === current);\n const rest = options.filter((option) => option.family !== current);\n return [\n known ?? { family: current, tag: 'current', safe: false },\n ...rest,\n ].slice(0, MAX_ROWS);\n }\n const scored: { option: Option; rank: number }[] = [];\n for (const option of options) {\n const rank = score(option.family, trimmed);\n if (rank !== -1) scored.push({ option, rank });\n }\n scored.sort(\n (a, b) => a.rank - b.rank || Number(b.option.safe) - Number(a.option.safe)\n );\n return scored.slice(0, MAX_ROWS).map((entry) => entry.option);\n}\n\nexport function FamilyCombobox({\n id,\n label,\n value,\n onCommit,\n pickerPath,\n className,\n}: {\n id?: string;\n label: string;\n value: string | undefined;\n onCommit: (next: string | null) => void;\n /** Where the full font dialog writes when \"Browse all\" is used. */\n pickerPath: Path;\n className?: string;\n}) {\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [active, setActive] = useState(0);\n const listRef = useRef<HTMLDivElement | null>(null);\n const catalog = useFontCatalog();\n const options = useMemo(() => buildOptions(catalog), [catalog]);\n const matches = useMemo(\n () => filterOptions(options, query, value),\n [options, query, value]\n );\n\n const typed = query.trim();\n const exact = matches.some(\n (option) => option.family.toLowerCase() === typed.toLowerCase()\n );\n const custom = typed && !exact ? typed : null;\n const rows = custom\n ? [custom, ...matches.map((m) => m.family)]\n : matches.map((m) => m.family);\n\n const choose = useCallback(\n (family: string) => {\n onCommit(family);\n setOpen(false);\n setQuery('');\n },\n [onCommit]\n );\n\n const browse = useCallback(() => {\n setOpen(false);\n useFontPickerStore\n .getState()\n .openFor({ jsonPath: pickerPath, currentValue: value });\n }, [pickerPath, value]);\n\n const onKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n setActive((index) => {\n const next =\n index < 0\n ? event.key === 'ArrowDown'\n ? 0\n : rows.length - 1\n : index + (event.key === 'ArrowDown' ? 1 : -1);\n const last = rows.length - 1;\n const clamped = next < 0 ? last : next > last ? 0 : next;\n listRef.current\n ?.querySelector(`[data-row=\"${clamped}\"]`)\n ?.scrollIntoView({ block: 'nearest' });\n return clamped;\n });\n } else if (event.key === 'Enter') {\n event.preventDefault();\n const family = rows[active];\n if (family) choose(family);\n } else if (event.key === 'Escape') {\n setOpen(false);\n }\n },\n [active, choose, rows]\n );\n\n return (\n <div className={cn('flex min-w-0 items-center gap-1', className)}>\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n // Open on the family that is set, not on row zero: Return is then\n // a no-op on a list the author only meant to look at. A family the\n // catalog does not have and no query has offered leaves nothing\n // highlighted rather than arming a different one.\n if (next) {\n setQuery('');\n setActive(value ? 0 : -1);\n }\n }}\n >\n <PopoverTrigger asChild>\n <button\n id={id}\n type=\"button\"\n role=\"combobox\"\n aria-expanded={open}\n aria-label={label}\n className={cn(\n 'flex h-7 min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded-sm border',\n 'border-input bg-background px-2 text-xs shadow-none transition-colors',\n 'hover:bg-accent/40 focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <Type className=\"size-3 shrink-0 opacity-50\" aria-hidden />\n <span\n className={cn(\n 'min-w-0 flex-1 truncate text-left',\n !value && 'text-muted-foreground'\n )}\n style={\n value\n ? { fontFamily: `\"${value.replace(/\"/g, '')}\", system-ui` }\n : undefined\n }\n >\n {value || 'Inherit'}\n </span>\n <ChevronsUpDown\n className=\"size-3 shrink-0 opacity-50\"\n aria-hidden\n />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"w-72 p-0\" onKeyDown={onKeyDown}>\n <div className=\"flex items-center gap-1.5 border-b px-2\">\n <Search className=\"size-3.5 shrink-0 opacity-50\" aria-hidden />\n <Input\n autoFocus\n value={query}\n onChange={(event) => {\n setQuery(event.target.value);\n setActive(0);\n }}\n placeholder=\"Search fonts…\"\n aria-label={`Search fonts for ${label}`}\n autoComplete=\"off\"\n spellCheck={false}\n // Transparent, not `bg-background`: the popover is its own\n // surface, and the input's default fill would paint a lighter\n // block from the icon to the right edge of the row.\n className=\"h-8 border-0 bg-transparent px-0 text-xs shadow-none focus-visible:ring-0\"\n />\n </div>\n <div\n ref={listRef}\n role=\"listbox\"\n aria-label={`${label} options`}\n className=\"max-h-64 overflow-y-auto p-1\"\n >\n {custom && (\n <Row\n index={0}\n active={active === 0}\n family={custom}\n tag=\"use as typed\"\n selected={value === custom}\n onPick={choose}\n onHover={setActive}\n />\n )}\n {matches.map((option, index) => {\n const row = custom ? index + 1 : index;\n return (\n <Row\n key={`${option.safe ? 's' : 'g'}:${option.family}`}\n index={row}\n active={active === row}\n family={option.family}\n tag={option.tag}\n selected={value === option.family}\n onPick={choose}\n onHover={setActive}\n />\n );\n })}\n {rows.length === 0 && (\n <p className={cn(HINT_CLASS, 'px-2 py-3 text-center')}>\n {catalog.safe.length + catalog.google.length === 0\n ? 'The font catalog is unavailable — type a family name.'\n : 'No family matches.'}\n </p>\n )}\n </div>\n <div className=\"flex items-center justify-between border-t px-1.5 py-1\">\n <QuietButton onClick={browse}>Browse all fonts…</QuietButton>\n {value && (\n <QuietButton\n onClick={() => {\n onCommit(null);\n setOpen(false);\n }}\n >\n Clear\n </QuietButton>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n\nconst Row = React.memo(function Row({\n index,\n active,\n family,\n tag,\n selected,\n onPick,\n onHover,\n}: {\n index: number;\n active: boolean;\n family: string;\n tag: string;\n selected: boolean;\n onPick: (family: string) => void;\n onHover: (index: number) => void;\n}) {\n return (\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={selected}\n data-row={index}\n onMouseMove={() => onHover(index)}\n onClick={() => onPick(family)}\n className={cn(\n 'flex h-7 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs',\n active && 'bg-accent text-accent-foreground'\n )}\n >\n <Check\n className={cn(\n 'size-3 shrink-0',\n selected ? 'opacity-100' : 'opacity-0'\n )}\n aria-hidden\n />\n <span className=\"min-w-0 flex-1 truncate\">{family}</span>\n <span className=\"shrink-0 text-[10px] text-muted-foreground\">{tag}</span>\n </button>\n );\n});\n","import React, { useCallback, useMemo } from 'react';\nimport { FORMAT } from '../../lib/env';\nimport {\n DOCX_FONT_ROLES,\n FONT_ROLE_HINTS,\n PPTX_FONT_ROLES,\n getAt,\n resolveColor,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport {\n DraftNumberInput,\n EditorSection,\n FIELD_LABEL_CLASS,\n GroupLabel,\n HINT_CLASS,\n useThemeEditor,\n} from './theme-editor-shared';\nimport { ColorControl, useThemeColorTokens } from './color-picker';\nimport { FamilyCombobox } from './font-combobox';\nimport { matchesQuery } from '../../lib/theme-editor/schema-form';\n\n/**\n * docx fonts are roles — heading, body, mono, light — each a family and a\n * size the styles inherit. pptx fonts are two family strings, and the\n * sizes live in `defaults`, so the section takes a different shape per\n * format rather than pretending the two agree.\n */\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' ? value : undefined;\n}\n\nconst DocxRoleCard = React.memo(function DocxRoleCard({\n role,\n family,\n size,\n}: {\n role: string;\n family: string | undefined;\n size: number | undefined;\n}) {\n const { set, remove } = useThemeEditor();\n const commitFamily = useCallback(\n (next: string | null) =>\n next === null\n ? remove(['fonts', role, 'family'])\n : set(['fonts', role, 'family'], next),\n [remove, role, set]\n );\n const commitSize = useCallback(\n (next: number | null) =>\n next === null\n ? remove(['fonts', role, 'size'])\n : set(['fonts', role, 'size'], next),\n [remove, role, set]\n );\n const familyId = `theme-font-${role}-family`;\n const sizeId = `theme-font-${role}-size`;\n return (\n <div className=\"grid grid-cols-[minmax(0,1fr)_6.5rem] gap-x-2 gap-y-1 rounded-sm border border-border/70 p-2\">\n <div className=\"col-span-2 flex items-baseline gap-2\">\n <span className=\"text-sm capitalize\">{role}</span>\n <span className={HINT_CLASS}>{FONT_ROLE_HINTS[role]}</span>\n </div>\n <label htmlFor={familyId} className={FIELD_LABEL_CLASS}>\n Family\n </label>\n <label htmlFor={sizeId} className={FIELD_LABEL_CLASS}>\n Size\n </label>\n <FamilyCombobox\n id={familyId}\n label={`${role} family`}\n value={family}\n onCommit={commitFamily}\n pickerPath={['fonts', role, 'family']}\n />\n <DraftNumberInput\n id={sizeId}\n aria-label={`${role} size`}\n value={size}\n onCommit={commitSize}\n unit=\"pt\"\n min={8}\n max={120}\n step={0.5}\n />\n </div>\n );\n});\n\nconst PptxFamilyRow = React.memo(function PptxFamilyRow({\n role,\n family,\n}: {\n role: string;\n family: string | undefined;\n}) {\n const { set, remove } = useThemeEditor();\n const commit = useCallback(\n (next: string | null) =>\n next === null ? remove(['fonts', role]) : set(['fonts', role], next),\n [remove, role, set]\n );\n const id = `theme-font-${role}`;\n return (\n <div className=\"grid grid-cols-[6rem_minmax(0,1fr)] items-center gap-2\">\n <label htmlFor={id} className=\"flex flex-col\">\n <span className=\"text-sm capitalize\">{role}</span>\n <span className={HINT_CLASS}>{FONT_ROLE_HINTS[role]}</span>\n </label>\n <FamilyCombobox\n id={id}\n label={`${role} family`}\n value={family}\n onCommit={commit}\n pickerPath={['fonts', role]}\n />\n </div>\n );\n});\n\nfunction PptxDefaults({ theme }: { theme: ThemeJson }) {\n const { set, remove } = useThemeEditor();\n const fontSize = asNumber(getAt(theme, ['defaults', 'fontSize']));\n const fontColor = asString(getAt(theme, ['defaults', 'fontColor']));\n const resolved = useMemo(\n () => resolveColor(theme, fontColor),\n [theme, fontColor]\n );\n const tokens = useThemeColorTokens(theme);\n const commitSize = useCallback(\n (next: number | null) =>\n next === null\n ? remove(['defaults', 'fontSize'])\n : set(['defaults', 'fontSize'], next),\n [remove, set]\n );\n const commitColor = useCallback(\n (next: string | null) =>\n next === null\n ? remove(['defaults', 'fontColor'])\n : set(['defaults', 'fontColor'], next),\n [remove, set]\n );\n return (\n <div className=\"flex flex-col gap-2\">\n <GroupLabel>Defaults</GroupLabel>\n <p className={HINT_CLASS}>\n What text falls back to when no style says otherwise.\n </p>\n <div className=\"grid grid-cols-[6rem_minmax(0,1fr)] items-center gap-2\">\n <label htmlFor=\"theme-defaults-size\" className=\"text-sm\">\n Font size\n </label>\n <DraftNumberInput\n id=\"theme-defaults-size\"\n value={fontSize}\n onCommit={commitSize}\n unit=\"pt\"\n min={1}\n max={200}\n step={1}\n className=\"max-w-[7rem]\"\n />\n <label htmlFor=\"theme-defaults-color\" className=\"text-sm\">\n Font colour\n </label>\n <ColorControl\n id=\"theme-defaults-color\"\n label=\"Default font colour\"\n value={fontColor}\n resolved={resolved}\n onCommit={commitColor}\n allowReference={false}\n tokens={tokens}\n className=\"max-w-[12rem]\"\n />\n </div>\n </div>\n );\n}\n\nexport function ThemeTypographySection({\n theme,\n query = '',\n}: {\n theme: ThemeJson;\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const whole = matchesQuery(query, 'typography', 'fonts', 'font');\n const roleMatches = (role: string) =>\n whole || matchesQuery(query, role, FONT_ROLE_HINTS[role]);\n const forceOpen = searching ? true : undefined;\n if (FORMAT === 'docx') {\n const roles = DOCX_FONT_ROLES.filter(roleMatches);\n if (searching && roles.length === 0) return null;\n return (\n <EditorSection\n title=\"Typography\"\n hint=\"Four roles the styles point at. A family beyond the safe list needs a fontRegistry entry on the document to embed; the specimen shows what the browser has.\"\n forceOpen={forceOpen}\n >\n <div className=\"grid grid-cols-1 gap-2 @[34rem]:grid-cols-2\">\n {roles.map((role) => {\n const font = getAt(theme, ['fonts', role]);\n const record =\n font && typeof font === 'object'\n ? (font as Record<string, unknown>)\n : undefined;\n return (\n <DocxRoleCard\n key={role}\n role={role}\n family={asString(record?.family)}\n size={asNumber(record?.size)}\n />\n );\n })}\n </div>\n </EditorSection>\n );\n }\n const roles = PPTX_FONT_ROLES.filter(roleMatches);\n const showDefaults =\n whole || matchesQuery(query, 'defaults', 'font size', 'font colour');\n if (searching && roles.length === 0 && !showDefaults) return null;\n return (\n <EditorSection\n title=\"Typography\"\n hint=\"Two families; every style uses one or names its own face.\"\n forceOpen={forceOpen}\n >\n {roles.length > 0 && (\n <div className=\"flex flex-col gap-2\">\n {roles.map((role) => (\n <PptxFamilyRow\n key={role}\n role={role}\n family={asString(getAt(theme, ['fonts', role]))}\n />\n ))}\n </div>\n )}\n {showDefaults && <PptxDefaults theme={theme} />}\n </EditorSection>\n );\n}\n","import React, { useCallback, useState } from 'react';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../ui/select';\nimport {\n MARGIN_KEYS,\n PAGE_SIZES,\n getAt,\n twipsToUnit,\n unitToTwips,\n type LengthUnit,\n type Path,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport {\n DraftNumberInput,\n EditorSection,\n FIELD_LABEL_CLASS,\n SELECT_TRIGGER_CLASS,\n useThemeEditor,\n} from './theme-editor-shared';\nimport { matchesQuery } from '../../lib/theme-editor/schema-form';\n\n/**\n * docx only. The JSON stores twips because Word does; nobody thinks in\n * twips, so the fields show the author's unit and convert on the way in\n * and out. The unit is a view setting, never written to the theme.\n */\n\nconst CUSTOM = '__custom__';\nconst UNITS: readonly { value: LengthUnit; label: string }[] = [\n { value: 'in', label: 'in' },\n { value: 'cm', label: 'cm' },\n { value: 'pt', label: 'pt' },\n { value: 'twips', label: 'twips' },\n];\nconst STEP: Record<LengthUnit, number> = {\n in: 0.05,\n cm: 0.1,\n pt: 1,\n twips: 10,\n};\n\n/** Module-level paths so the memoised fields see the same array each render. */\nconst MARGIN_PATHS: Record<string, Path> = Object.fromEntries(\n MARGIN_KEYS.map((key) => [key, ['page', 'margins', key]])\n);\nconst WIDTH_PATH: Path = ['page', 'size', 'width'];\nconst HEIGHT_PATH: Path = ['page', 'size', 'height'];\n\nfunction twips(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value)\n ? value\n : undefined;\n}\n\n/** A length in twips at `path`, edited in `unit`. */\nconst LengthField = React.memo(function LengthField({\n id,\n label,\n path,\n value,\n unit,\n}: {\n id: string;\n label: string;\n path: Path;\n value: number | undefined;\n unit: LengthUnit;\n}) {\n const { set, remove } = useThemeEditor();\n const commit = useCallback(\n (next: number | null) =>\n next === null ? remove(path) : set(path, unitToTwips(next, unit)),\n [path, remove, set, unit]\n );\n return (\n <div className=\"flex flex-col gap-1\">\n <label htmlFor={id} className={FIELD_LABEL_CLASS}>\n {label}\n </label>\n <DraftNumberInput\n id={id}\n value={value === undefined ? undefined : twipsToUnit(value, unit)}\n onCommit={commit}\n unit={unit}\n min={0}\n step={STEP[unit]}\n />\n </div>\n );\n});\n\nexport function ThemePageSection({\n theme,\n query = '',\n}: {\n theme: ThemeJson;\n query?: string;\n}) {\n const searching = query.trim() !== '';\n if (\n searching &&\n !matchesQuery(\n query,\n 'page',\n 'size',\n 'margins',\n 'width',\n 'height',\n ...MARGIN_KEYS,\n ...PAGE_SIZES\n )\n )\n return null;\n const { set } = useThemeEditor();\n const [unit, setUnit] = useState<LengthUnit>('in');\n\n const size = getAt(theme, ['page', 'size']);\n const isCustom = !!size && typeof size === 'object';\n const sizeValue =\n typeof size === 'string' && (PAGE_SIZES as readonly string[]).includes(size)\n ? size\n : isCustom\n ? CUSTOM\n : '';\n\n const onSizeChange = useCallback(\n (next: string) => {\n if (next === CUSTOM) {\n // Start the custom box from A4 so the fields are never blank.\n set(['page', 'size'], { width: 11906, height: 16838 });\n } else {\n set(['page', 'size'], next);\n }\n },\n [set]\n );\n\n return (\n <EditorSection\n title=\"Page\"\n hint=\"Paper and margins. Stored in twips (1/1440 in); shown in the unit you pick here.\"\n forceOpen={searching ? true : undefined}\n actions={\n <Select value={unit} onValueChange={(v) => setUnit(v as LengthUnit)}>\n <SelectTrigger\n aria-label=\"Length unit\"\n className=\"h-6 min-h-0 w-auto gap-1 border-transparent bg-transparent px-1.5 text-[11px] shadow-none hover:bg-accent\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {UNITS.map((u) => (\n <SelectItem key={u.value} value={u.value} className=\"text-xs\">\n {u.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n }\n >\n <div className=\"grid grid-cols-[6rem_minmax(0,12rem)] items-center gap-2\">\n <label htmlFor=\"theme-page-size\" className=\"text-sm\">\n Size\n </label>\n <Select value={sizeValue} onValueChange={onSizeChange}>\n <SelectTrigger id=\"theme-page-size\" className={SELECT_TRIGGER_CLASS}>\n <SelectValue placeholder=\"Choose a size\" />\n </SelectTrigger>\n <SelectContent>\n {PAGE_SIZES.map((name) => (\n <SelectItem key={name} value={name} className=\"text-xs\">\n {name}\n </SelectItem>\n ))}\n <SelectItem value={CUSTOM} className=\"text-xs\">\n Custom\n </SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {isCustom && (\n <div className=\"grid grid-cols-2 gap-2 @[34rem]:max-w-[24rem]\">\n <LengthField\n id=\"theme-page-width\"\n label=\"Width\"\n path={WIDTH_PATH}\n value={twips(getAt(theme, WIDTH_PATH))}\n unit={unit}\n />\n <LengthField\n id=\"theme-page-height\"\n label=\"Height\"\n path={HEIGHT_PATH}\n value={twips(getAt(theme, HEIGHT_PATH))}\n unit={unit}\n />\n </div>\n )}\n\n <div className=\"grid grid-cols-2 gap-2 @[30rem]:grid-cols-4\">\n {MARGIN_KEYS.map((key) => (\n <LengthField\n key={key}\n id={`theme-margin-${key}`}\n label={key.charAt(0).toUpperCase() + key.slice(1)}\n path={MARGIN_PATHS[key]}\n value={twips(getAt(theme, MARGIN_PATHS[key]))}\n unit={unit}\n />\n ))}\n </div>\n </EditorSection>\n );\n}\n","import React, { useCallback, useMemo, useState } from 'react';\nimport { ChevronRight, Plus, Trash2 } from 'lucide-react';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../ui/select';\nimport { Input } from '../ui/input';\nimport { FORMAT } from '../../lib/env';\nimport {\n DOCX_FONT_ROLES,\n customStyleNames,\n getAt,\n resolveColor,\n styleFields,\n styleLabel,\n styleNames,\n type Path,\n type StyleFieldDescriptor,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport { cn } from '../../lib/utils';\nimport {\n ClearButton,\n DraftNumberInput,\n DraftTextInput,\n EditorSection,\n FIELD_LABEL_CLASS,\n HINT_CLASS,\n INPUT_CLASS,\n QuietButton,\n SELECT_TRIGGER_CLASS,\n Segmented,\n useThemeEditor,\n} from './theme-editor-shared';\nimport {\n ColorControl,\n useThemeColorTokens,\n type ColorToken,\n} from './color-picker';\nimport { FamilyCombobox } from './font-combobox';\nimport { matchesQuery } from '../../lib/theme-editor/schema-form';\n\n/**\n * The named styles: the schema's slots first, then whatever else the theme\n * defines. Each row is a one-line summary until opened, because fifteen\n * open grids would bury the two the author came to change.\n *\n * Rows are memoised on the style's JSON, not its object: the tab re-parses\n * the whole theme on every write, so identities are new each time and only\n * the text says whether anything in this style moved.\n */\n\nconst NAMES = styleNames(FORMAT);\nconst FIELDS = styleFields(FORMAT);\nconst BASIC = FIELDS.filter((f) => !f.advanced);\nconst ADVANCED = FIELDS.filter((f) => f.advanced);\nconst STYLE_DEPTH = 2; // ['styles', name]\n\nconst BOOLEAN_OPTIONS = [\n { value: 'unset' as const, label: 'Unset' },\n { value: 'off' as const, label: 'Off' },\n { value: 'on' as const, label: 'On' },\n];\n\ntype StyleJson = Record<string, unknown>;\n\nfunction fieldKey(field: StyleFieldDescriptor): string {\n return field.path.join('.');\n}\n\nfunction summarize(style: StyleJson): string {\n const parts: string[] = [];\n const push = (value: unknown) => {\n if (typeof value === 'string' && value) parts.push(value);\n };\n if (FORMAT === 'docx') {\n push(style.font);\n if (typeof style.size === 'number') parts.push(`${style.size}pt`);\n } else {\n push(style.fontFace);\n if (typeof style.fontSize === 'number') parts.push(`${style.fontSize}pt`);\n }\n if (style.bold === true) parts.push('bold');\n if (typeof style.fontWeight === 'number') parts.push(`w${style.fontWeight}`);\n if (style.italic === true) parts.push('italic');\n if (style.underline === true) parts.push('underline');\n push(FORMAT === 'docx' ? style.color : style.fontColor);\n push(FORMAT === 'docx' ? style.alignment : style.align);\n if (parts.length === 0) {\n const keys = Object.keys(style);\n return keys.length === 0 ? 'Defined, nothing set' : keys.join(' · ');\n }\n return parts.join(' · ');\n}\n\n// ---------------------------------------------------------------------------\n// Fields\n// ---------------------------------------------------------------------------\n\ninterface FieldProps {\n styleName: string;\n field: StyleFieldDescriptor;\n value: unknown;\n tokens: readonly ColorToken[];\n resolved: string | null;\n}\n\n/**\n * One control for both ways a style names a colour. The picker offers the\n * theme's own tokens as chips and a hex everywhere else, so the source is a\n * choice inside the control rather than a mode switch beside it.\n */\nfunction ColorField({\n styleName,\n field,\n value,\n tokens,\n resolved,\n onCommit,\n}: FieldProps & { onCommit: (next: string | null) => void }) {\n return (\n <ColorControl\n id={`theme-style-${styleName}-${fieldKey(field)}`}\n label={field.label}\n value={typeof value === 'string' ? value : undefined}\n resolved={resolved}\n onCommit={onCommit}\n tokens={tokens}\n className=\"min-w-0\"\n />\n );\n}\n\nconst StyleField = React.memo(function StyleField(props: FieldProps) {\n const { styleName, field, value } = props;\n const { set, remove } = useThemeEditor();\n const path = useMemo<Path>(\n () => ['styles', styleName, ...field.path],\n [field.path, styleName]\n );\n const clear = useCallback(\n () => remove(path, { keepDepth: STYLE_DEPTH }),\n [path, remove]\n );\n const commitString = useCallback(\n (next: string | null) => (next === null ? clear() : set(path, next)),\n [clear, path, set]\n );\n const commitNumber = useCallback(\n (next: number | null) => (next === null ? clear() : set(path, next)),\n [clear, path, set]\n );\n const id = `theme-style-${styleName}-${fieldKey(field)}`;\n const isSet = value !== undefined;\n\n let control: React.ReactNode;\n switch (field.kind) {\n case 'text':\n control = (\n <DraftTextInput\n id={id}\n value={typeof value === 'string' ? value : undefined}\n onCommit={commitString}\n />\n );\n break;\n case 'number':\n control = (\n <DraftNumberInput\n id={id}\n value={typeof value === 'number' ? value : undefined}\n onCommit={commitNumber}\n unit={field.unit}\n min={field.min}\n max={field.max}\n step={field.step}\n />\n );\n break;\n case 'boolean':\n // Three states, not two. A switch can only be on or off, and a style\n // that says nothing about `bold` is not the same as one that says\n // `false` — the first inherits, the second overrides.\n control = (\n <Segmented<'unset' | 'off' | 'on'>\n label={field.label}\n value={value === undefined ? 'unset' : value === true ? 'on' : 'off'}\n options={BOOLEAN_OPTIONS}\n onChange={(next) =>\n next === 'unset' ? clear() : set(path, next === 'on')\n }\n className=\"h-7\"\n />\n );\n break;\n case 'select':\n control = (\n <Select\n value={typeof value === 'string' ? value : ''}\n onValueChange={(next) => set(path, next)}\n >\n <SelectTrigger id={id} className={SELECT_TRIGGER_CLASS}>\n <SelectValue placeholder=\"Unset\" />\n </SelectTrigger>\n <SelectContent>\n {(field.options ?? []).map((option) => (\n <SelectItem key={option} value={option} className=\"text-xs\">\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n break;\n case 'fontRole':\n control = (\n <Select\n value={typeof value === 'string' ? value : ''}\n onValueChange={(next) => set(path, next)}\n >\n <SelectTrigger id={id} className={SELECT_TRIGGER_CLASS}>\n <SelectValue placeholder=\"Unset\" />\n </SelectTrigger>\n <SelectContent>\n {DOCX_FONT_ROLES.map((role) => (\n <SelectItem key={role} value={role} className=\"text-xs\">\n {role}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n break;\n case 'fontFamily':\n control = (\n <FamilyCombobox\n id={id}\n label={field.label}\n value={typeof value === 'string' ? value : undefined}\n onCommit={commitString}\n pickerPath={path}\n />\n );\n break;\n case 'color':\n control = <ColorField {...props} onCommit={commitString} />;\n break;\n }\n\n return (\n <div className=\"flex min-w-0 flex-col gap-1\">\n <div className=\"flex h-4 items-center justify-between gap-1\">\n <label\n htmlFor={field.kind === 'boolean' ? undefined : id}\n className={cn(FIELD_LABEL_CLASS, isSet && 'text-foreground')}\n title={field.hint}\n >\n {field.label}\n </label>\n {isSet && field.kind !== 'boolean' && (\n <ClearButton\n label={`Clear ${field.label}`}\n onClick={clear}\n className=\"size-5\"\n />\n )}\n </div>\n {control}\n {field.hint && <p className={HINT_CLASS}>{field.hint}</p>}\n </div>\n );\n});\n\n// ---------------------------------------------------------------------------\n// Rows\n// ---------------------------------------------------------------------------\n\ninterface StyleRowProps {\n name: string;\n custom: boolean;\n /** `undefined` when the style is not defined at all. */\n styleJson: string | undefined;\n /** The theme's colour tokens, JSON, so the memo compare stays a `===`. */\n tokensJson: string;\n /** Resolved hex per colour field key, JSON. */\n resolvedJson: string;\n}\n\nconst StyleRow = React.memo(function StyleRow({\n name,\n custom,\n styleJson,\n tokensJson,\n resolvedJson,\n}: StyleRowProps) {\n const { set, remove } = useThemeEditor();\n const [open, setOpen] = useState(false);\n const [more, setMore] = useState(false);\n const style = useMemo<StyleJson | undefined>(\n () => (styleJson === undefined ? undefined : JSON.parse(styleJson)),\n [styleJson]\n );\n const tokens = useMemo(\n () => JSON.parse(tokensJson) as ColorToken[],\n [tokensJson]\n );\n const resolved = useMemo<Record<string, string | null>>(\n () => JSON.parse(resolvedJson),\n [resolvedJson]\n );\n const define = useCallback(() => set(['styles', name], {}), [name, set]);\n const removeStyle = useCallback(\n () => remove(['styles', name]),\n [name, remove]\n );\n const label = styleLabel(name);\n const setCount = style ? Object.keys(style).length : 0;\n\n const renderField = (field: StyleFieldDescriptor) => (\n <StyleField\n key={fieldKey(field)}\n styleName={name}\n field={field}\n value={style ? getAt(style, field.path) : undefined}\n tokens={tokens}\n resolved={resolved[fieldKey(field)] ?? null}\n />\n );\n\n return (\n <div className=\"rounded-sm border border-border/70\">\n <div className=\"flex h-8 items-center gap-1 pr-1\">\n <button\n type=\"button\"\n onClick={() => setOpen((o) => !o)}\n aria-expanded={open}\n className={cn(\n 'flex h-8 min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded-sm px-2 text-left',\n 'transition-colors hover:bg-accent',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <ChevronRight\n aria-hidden\n className={cn(\n 'size-3 shrink-0 text-muted-foreground transition-transform duration-150 ease-out',\n open && 'rotate-90'\n )}\n />\n <span className=\"shrink-0 text-sm\">{label}</span>\n {custom && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1 text-[10px] tracking-wide text-muted-foreground uppercase\">\n custom\n </span>\n )}\n <span className={cn(HINT_CLASS, 'min-w-0 flex-1 truncate')}>\n {style ? summarize(style) : 'Not defined — inherits defaults'}\n </span>\n </button>\n {custom && (\n <button\n type=\"button\"\n onClick={removeStyle}\n aria-label={`Remove style ${name}`}\n title=\"Remove style\"\n className={cn(\n 'flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-sm',\n 'text-muted-foreground/70 transition-colors hover:bg-accent hover:text-destructive',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <Trash2 className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </div>\n\n {open && (\n <div className=\"flex flex-col gap-3 border-t border-border/60 px-2 pt-2 pb-3\">\n {!style ? (\n <div className=\"flex items-center gap-3\">\n <span className={HINT_CLASS}>\n Not defined — inherits defaults.\n </span>\n <QuietButton onClick={define}>\n <Plus className=\"size-3\" aria-hidden />\n Define\n </QuietButton>\n </div>\n ) : (\n <>\n <div className=\"grid grid-cols-1 gap-x-4 gap-y-3 @[30rem]:grid-cols-2\">\n {BASIC.map(renderField)}\n </div>\n {ADVANCED.length > 0 && (\n <>\n <div className=\"flex items-center gap-2\">\n <QuietButton\n onClick={() => setMore((m) => !m)}\n aria-expanded={more}\n >\n <ChevronRight\n aria-hidden\n className={cn(\n 'size-3 transition-transform duration-150 ease-out',\n more && 'rotate-90'\n )}\n />\n More\n </QuietButton>\n <span className={HINT_CLASS}>\n {ADVANCED.length} more fields\n {setCount > 0 &&\n ` · ${setCount} key${setCount === 1 ? '' : 's'} set`}\n </span>\n </div>\n {more && (\n <div className=\"grid grid-cols-1 gap-x-4 gap-y-3 @[30rem]:grid-cols-2\">\n {ADVANCED.map(renderField)}\n </div>\n )}\n </>\n )}\n </>\n )}\n </div>\n )}\n </div>\n );\n});\n\n// ---------------------------------------------------------------------------\n// Add custom style (docx)\n// ---------------------------------------------------------------------------\n\nfunction AddCustomStyle({ existing }: { existing: Set<string> }) {\n const { set } = useThemeEditor();\n const [open, setOpen] = useState(false);\n const [name, setName] = useState('');\n const trimmed = name.trim();\n const problem = !trimmed\n ? null\n : existing.has(trimmed)\n ? 'A style with this name exists'\n : /\\s/.test(trimmed)\n ? 'No spaces — this is the style id a document names'\n : null;\n const submit = () => {\n if (!trimmed || problem) return;\n set(['styles', trimmed], {});\n setName('');\n setOpen(false);\n };\n if (!open) {\n return (\n <QuietButton onClick={() => setOpen(true)}>\n <Plus className=\"size-3\" aria-hidden />\n Add custom style\n </QuietButton>\n );\n }\n return (\n <form\n className=\"flex flex-wrap items-center gap-2\"\n onSubmit={(e) => {\n e.preventDefault();\n submit();\n }}\n >\n <label htmlFor=\"theme-new-style\" className=\"text-xs\">\n New style\n </label>\n {/* Plain controlled input: the name is local state until \"Add\", so\n the draft-on-blur behaviour of the field inputs would only get in\n the way of the validation message updating as you type. */}\n <Input\n id=\"theme-new-style\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. callout\"\n autoComplete=\"off\"\n spellCheck={false}\n autoFocus\n className={cn(INPUT_CLASS, 'w-40')}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setOpen(false);\n }}\n />\n <QuietButton type=\"submit\" disabled={!trimmed || !!problem}>\n Add\n </QuietButton>\n <QuietButton onClick={() => setOpen(false)}>Cancel</QuietButton>\n {problem && (\n <span className=\"text-[11px] text-destructive\">{problem}</span>\n )}\n </form>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Section\n// ---------------------------------------------------------------------------\n\nexport function ThemeStylesSection({\n theme,\n query = '',\n}: {\n theme: ThemeJson;\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const tokens = useThemeColorTokens(theme);\n const tokensJson = useMemo(() => JSON.stringify(tokens), [tokens]);\n const custom = useMemo(() => customStyleNames(theme, FORMAT), [theme]);\n const rows = useMemo(() => {\n const styles = theme.styles;\n const table =\n styles && typeof styles === 'object' && !Array.isArray(styles)\n ? (styles as Record<string, unknown>)\n : {};\n const colorFields = FIELDS.filter((f) => f.kind === 'color');\n const row = (name: string, isCustom: boolean): StyleRowProps => {\n const style = table[name];\n const defined = !!style && typeof style === 'object';\n const resolved: Record<string, string | null> = {};\n for (const field of colorFields) {\n resolved[fieldKey(field)] = defined\n ? resolveColor(theme, getAt(style, field.path))\n : null;\n }\n return {\n name,\n custom: isCustom,\n styleJson: defined ? JSON.stringify(style) : undefined,\n tokensJson,\n resolvedJson: JSON.stringify(resolved),\n };\n };\n const all = [\n ...NAMES.map((name) => row(name, false)),\n ...custom.map((name) => row(name, true)),\n ];\n return matchesQuery(query, 'styles', 'style')\n ? all\n : all.filter((entry) =>\n matchesQuery(query, entry.name, styleLabel(entry.name))\n );\n }, [theme, tokensJson, custom, query]);\n\n const existing = useMemo(() => new Set([...NAMES, ...custom]), [custom]);\n const definedCount = rows.filter((r) => r.styleJson !== undefined).length;\n if (searching && rows.length === 0) return null;\n\n return (\n <EditorSection\n title=\"Styles\"\n hint={\n FORMAT === 'docx'\n ? 'Paragraph styles a document names with themeStyle. A colour may be a token or a hex; sizes are points.'\n : 'Text presets a slide names by style. Sizes are points; a colour may be a token or a hex.'\n }\n forceOpen={searching ? true : undefined}\n actions={\n <span className=\"text-[11px] tabular-nums text-muted-foreground\">\n {definedCount}/{rows.length}\n </span>\n }\n >\n <div className=\"flex flex-col gap-1\">\n {rows.map((row) => (\n <StyleRow key={row.name} {...row} />\n ))}\n </div>\n {FORMAT === 'docx' && <AddCustomStyle existing={existing} />}\n </EditorSection>\n );\n}\n","import React, { useCallback, useMemo } from 'react';\nimport { Braces, Plus } from 'lucide-react';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../ui/select';\nimport { getAt, type Path, type ThemeJson } from '../../lib/theme-editor/model';\nimport {\n fieldValueError,\n filterFields,\n matchesQuery,\n resolveThemeColor,\n summarizeValue,\n type SchemaField,\n type SchemaSection,\n} from '../../lib/theme-editor/schema-form';\nimport { cn } from '../../lib/utils';\nimport {\n ClearButton,\n DraftNumberInput,\n DraftTextInput,\n EditorSection,\n GroupLabel,\n HINT_CLASS,\n QuietButton,\n SELECT_TRIGGER_CLASS,\n Segmented,\n useThemeEditor,\n} from './theme-editor-shared';\nimport {\n ColorControl,\n useThemeColorTokens,\n type ColorToken,\n} from './color-picker';\n\n/**\n * A section for one extended theme key, rendered from its schema: every\n * property the schema names is a row with the control its type wants, its\n * description as the hint, and a clear that removes the key (pruning the\n * empty parents it leaves behind, so a theme never carries `\"motif\": {}`).\n * What the schema cannot express as one control is shown with its value\n * and a way to the JSON view.\n */\n\nconst UNSET = '__unset__';\nconst BOOLEAN_OPTIONS = [\n { value: 'unset' as const, label: 'Unset' },\n { value: 'off' as const, label: 'Off' },\n { value: 'on' as const, label: 'On' },\n];\n\nfunction fieldId(path: Path): string {\n return `theme-schema-${path.join('-')}`;\n}\n\n/** The depth below which a cleared key's empty parents are pruned. */\nconst SECTION_DEPTH = 1;\n\nconst ScalarControl = React.memo(function ScalarControl({\n field,\n value,\n theme,\n tokens,\n onOpenJson,\n}: {\n field: SchemaField;\n value: unknown;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n}) {\n const { set, remove } = useThemeEditor();\n const path = field.path;\n const clear = useCallback(\n () => remove(path, { keepDepth: SECTION_DEPTH }),\n [path, remove]\n );\n const commitString = useCallback(\n (next: string | null) => (next === null ? clear() : set(path, next)),\n [clear, path, set]\n );\n const commitNumber = useCallback(\n (next: number | null) => (next === null ? clear() : set(path, next)),\n [clear, path, set]\n );\n const id = fieldId(path);\n const error = fieldValueError(field, value);\n if (error) {\n return (\n <JsonOnly\n summary={`${error}: ${summarizeValue(value)}`}\n onOpenJson={onOpenJson}\n onClear={clear}\n />\n );\n }\n switch (field.kind) {\n case 'text':\n return (\n <DraftTextInput\n id={id}\n value={typeof value === 'string' ? value : undefined}\n onCommit={commitString}\n />\n );\n case 'number':\n return (\n <DraftNumberInput\n id={id}\n value={typeof value === 'number' ? value : undefined}\n onCommit={commitNumber}\n min={field.min}\n max={field.max}\n step={field.integer ? 1 : 0.5}\n />\n );\n case 'boolean':\n return (\n <Segmented<'unset' | 'off' | 'on'>\n label={field.label}\n value={value === undefined ? 'unset' : value === true ? 'on' : 'off'}\n options={BOOLEAN_OPTIONS}\n onChange={(next) =>\n next === 'unset' ? clear() : set(path, next === 'on')\n }\n className=\"h-7\"\n />\n );\n case 'enum':\n return (\n <Select\n value={typeof value === 'string' ? value : UNSET}\n onValueChange={(next) => (next === UNSET ? clear() : set(path, next))}\n >\n <SelectTrigger\n id={id}\n aria-label={field.label}\n className={SELECT_TRIGGER_CLASS}\n >\n <SelectValue placeholder=\"Unset\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={UNSET}>Unset</SelectItem>\n {(field.options ?? []).map((option) => (\n <SelectItem key={option} value={option}>\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n case 'color':\n return (\n <ColorControl\n id={id}\n label={field.label}\n value={typeof value === 'string' ? value : undefined}\n resolved={resolveThemeColor(theme, value)}\n onCommit={commitString}\n tokens={tokens}\n className=\"min-w-0\"\n />\n );\n default:\n return (\n <JsonOnly\n summary={summarizeValue(value)}\n onOpenJson={onOpenJson}\n onClear={value === undefined ? undefined : clear}\n />\n );\n }\n});\n\n/** A value the form shows but leaves to the JSON view. */\nfunction JsonOnly({\n summary,\n onOpenJson,\n onClear,\n}: {\n summary: string;\n onOpenJson: () => void;\n onClear?: () => void;\n}) {\n return (\n <div className=\"flex h-7 min-w-0 items-center gap-1\">\n <span className=\"min-w-0 flex-1 truncate text-xs text-muted-foreground\">\n {summary}\n </span>\n <QuietButton onClick={onOpenJson}>\n <Braces className=\"size-3\" aria-hidden />\n JSON\n </QuietButton>\n {onClear && <ClearButton label=\"Clear\" onClick={onClear} />}\n </div>\n );\n}\n\n/** An array of scalars: one row per entry, add at the end, clear per entry. */\nconst ListControl = React.memo(function ListControl({\n field,\n value,\n theme,\n tokens,\n onOpenJson,\n}: {\n field: SchemaField;\n value: unknown;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n}) {\n const { set, remove } = useThemeEditor();\n const entries = Array.isArray(value) ? value : [];\n const item = field.item!;\n const add = useCallback(() => {\n const seed =\n item.kind === 'number'\n ? item.min ?? 0\n : item.kind === 'boolean'\n ? true\n : '';\n set(field.path, [...entries, seed]);\n }, [entries, field.path, item.kind, item.min, set]);\n const full = field.max !== undefined && entries.length >= field.max;\n if (value !== undefined && !Array.isArray(value)) {\n return (\n <JsonOnly\n summary={`Not a list: ${summarizeValue(value)}`}\n onOpenJson={onOpenJson}\n onClear={() => remove(field.path, { keepDepth: SECTION_DEPTH })}\n />\n );\n }\n return (\n <div className=\"flex flex-col gap-1\">\n {entries.map((entry, index) => {\n const entryField: SchemaField = {\n ...item,\n key: String(index),\n label: `${field.label} ${index + 1}`,\n path: [...field.path, index],\n };\n return (\n <div key={index} className=\"flex items-center gap-1\">\n <div className=\"min-w-0 flex-1\">\n <ListEntry\n field={entryField}\n value={entry}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n onRemove={() => {\n const next = entries.filter((_, i) => i !== index);\n if (next.length === 0)\n remove(field.path, { keepDepth: SECTION_DEPTH });\n else set(field.path, next);\n }}\n />\n </div>\n </div>\n );\n })}\n {!full && (\n <QuietButton onClick={add} className=\"self-start\">\n <Plus className=\"size-3\" aria-hidden />\n Add\n </QuietButton>\n )}\n </div>\n );\n});\n\n/**\n * One list entry. Clearing an entry removes it from the list rather than\n * leaving a hole, which is what a clear on an array member has to mean.\n */\nfunction ListEntry({\n field,\n value,\n theme,\n tokens,\n onOpenJson,\n onRemove,\n}: {\n field: SchemaField;\n value: unknown;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n onRemove: () => void;\n}) {\n const { set } = useThemeEditor();\n const commitString = useCallback(\n (next: string | null) =>\n next === null ? onRemove() : set(field.path, next),\n [field.path, onRemove, set]\n );\n const commitNumber = useCallback(\n (next: number | null) =>\n next === null ? onRemove() : set(field.path, next),\n [field.path, onRemove, set]\n );\n const id = fieldId(field.path);\n let control: React.ReactNode;\n switch (field.kind) {\n case 'color':\n control = (\n <ColorControl\n id={id}\n label={field.label}\n value={typeof value === 'string' ? value : undefined}\n resolved={resolveThemeColor(theme, value)}\n onCommit={commitString}\n tokens={tokens}\n className=\"min-w-0\"\n />\n );\n break;\n case 'number':\n control = (\n <DraftNumberInput\n id={id}\n value={typeof value === 'number' ? value : undefined}\n onCommit={commitNumber}\n min={field.min}\n max={field.max}\n step={field.integer ? 1 : 0.5}\n />\n );\n break;\n case 'enum':\n control = (\n <Select\n value={typeof value === 'string' ? value : UNSET}\n onValueChange={(next) =>\n next === UNSET ? onRemove() : set(field.path, next)\n }\n >\n <SelectTrigger\n id={id}\n aria-label={field.label}\n className={SELECT_TRIGGER_CLASS}\n >\n <SelectValue placeholder=\"Unset\" />\n </SelectTrigger>\n <SelectContent>\n {(field.options ?? []).map((option) => (\n <SelectItem key={option} value={option}>\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n break;\n case 'text':\n control = (\n <DraftTextInput\n id={id}\n value={typeof value === 'string' ? value : undefined}\n onCommit={commitString}\n />\n );\n break;\n default:\n control = (\n <JsonOnly summary={summarizeValue(value)} onOpenJson={onOpenJson} />\n );\n }\n return (\n <div className=\"flex items-center gap-1\">\n <div className=\"min-w-0 flex-1\">{control}</div>\n <ClearButton label={`Remove ${field.label}`} onClick={onRemove} />\n </div>\n );\n}\n\nconst FieldRow = React.memo(function FieldRow({\n field,\n value,\n theme,\n tokens,\n onOpenJson,\n}: {\n field: SchemaField;\n value: unknown;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n}) {\n const { remove } = useThemeEditor();\n const isSet = value !== undefined;\n const id = fieldId(field.path);\n const clear = useCallback(\n () => remove(field.path, { keepDepth: SECTION_DEPTH }),\n [field.path, remove]\n );\n const clearable =\n isSet &&\n field.kind !== 'list' &&\n field.kind !== 'json' &&\n !fieldValueError(field, value);\n return (\n <div className=\"grid grid-cols-[minmax(0,1fr)_minmax(0,12rem)_1.5rem] items-start gap-x-2 gap-y-0.5 @[30rem]:grid-cols-[minmax(0,1fr)_minmax(0,16rem)_1.5rem]\">\n <label htmlFor={id} className=\"flex min-w-0 flex-col pt-1.5\">\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <span\n className={cn(\n 'truncate text-sm',\n !isSet && 'text-muted-foreground'\n )}\n >\n {field.label}\n </span>\n <code className=\"truncate text-[10px] text-muted-foreground\">\n {field.key}\n </code>\n {field.required && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1 text-[10px] tracking-wide text-muted-foreground uppercase\">\n required\n </span>\n )}\n </span>\n {field.hint && (\n <span className={cn(HINT_CLASS, 'line-clamp-2')}>{field.hint}</span>\n )}\n </label>\n <div className=\"min-w-0 pt-0.5\">\n {field.kind === 'list' ? (\n <ListControl\n field={field}\n value={value}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n />\n ) : (\n <ScalarControl\n field={field}\n value={value}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n />\n )}\n </div>\n <div className=\"pt-0.5\">\n {clearable && (\n <ClearButton label={`Clear ${field.label}`} onClick={clear} />\n )}\n </div>\n </div>\n );\n});\n\n/** A group: its label, then its children one level in. */\nfunction GroupRows({\n field,\n theme,\n tokens,\n onOpenJson,\n depth,\n}: {\n field: SchemaField;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n depth: number;\n}) {\n const value = getAt(theme, field.path);\n const error = fieldValueError(field, value);\n const { remove } = useThemeEditor();\n return (\n <div\n className={cn(\n 'flex flex-col gap-2',\n depth > 0 && 'border-l border-border/60 pl-3'\n )}\n data-crumb={field.label}\n >\n <div className=\"flex items-baseline gap-2\">\n <GroupLabel>{field.label}</GroupLabel>\n <code className=\"text-[10px] text-muted-foreground\">{field.key}</code>\n {value === undefined && (\n <span className={HINT_CLASS}>Not defined — inherits defaults</span>\n )}\n </div>\n {field.hint && <p className={cn(HINT_CLASS, '-mt-1')}>{field.hint}</p>}\n {error ? (\n <JsonOnly\n summary={`${error}: ${summarizeValue(value)}`}\n onOpenJson={onOpenJson}\n onClear={() => remove(field.path, { keepDepth: SECTION_DEPTH })}\n />\n ) : (\n <Rows\n fields={field.children ?? []}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n depth={depth + 1}\n />\n )}\n </div>\n );\n}\n\nfunction Rows({\n fields,\n theme,\n tokens,\n onOpenJson,\n depth,\n}: {\n fields: readonly SchemaField[];\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n depth: number;\n}) {\n return (\n <div className=\"flex flex-col gap-2\">\n {fields.map((field) =>\n field.kind === 'group' ? (\n <GroupRows\n key={field.key}\n field={field}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n depth={depth}\n />\n ) : (\n <FieldRow\n key={field.key}\n field={field}\n value={getAt(theme, field.path)}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n />\n )\n )}\n </div>\n );\n}\n\nexport function ThemeSchemaSection({\n section,\n theme,\n query,\n onOpenJson,\n}: {\n section: SchemaSection;\n theme: ThemeJson;\n query: string;\n onOpenJson: () => void;\n}) {\n const tokens = useThemeColorTokens(theme);\n const defined = theme[section.key] !== undefined;\n const fields = useMemo(\n () =>\n matchesQuery(query, section.key, section.title, section.hint)\n ? section.fields\n : filterFields(section.fields, query),\n [query, section]\n );\n if (query.trim() && fields.length === 0) return null;\n return (\n <EditorSection\n title={section.title}\n hint={section.hint}\n defaultOpen={defined}\n forceOpen={query.trim() ? true : undefined}\n actions={\n <QuietButton onClick={onOpenJson}>\n <Braces className=\"size-3\" aria-hidden />\n JSON\n </QuietButton>\n }\n >\n {!defined && (\n <p className={HINT_CLASS}>\n Not defined — inherits defaults. Set a field to define it.\n </p>\n )}\n <Rows\n fields={fields}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n depth={0}\n />\n </EditorSection>\n );\n}\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Braces, Search, X } from 'lucide-react';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { ScrollArea } from '../ui/scroll-area';\nimport { FORMAT } from '../../lib/env';\nimport {\n advancedKeys,\n deleteAt,\n ensureContainers,\n formKeys,\n getAt,\n parseTheme,\n serializeTheme,\n setAt,\n type Path,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport {\n extendedSections,\n matchesQuery,\n type SchemaSection,\n} from '../../lib/theme-editor/schema-form';\nimport { fetchThemeJsonSchema } from '../../lib/theme-json-schema';\nimport {\n DraftTextInput,\n EditorSection,\n HINT_CLASS,\n INPUT_CLASS,\n QuietButton,\n ThemeEditorProvider,\n useThemeEditor,\n type ThemeEditorActions,\n} from './theme-editor-shared';\nimport { cn } from '../../lib/utils';\nimport { ThemeColorsSection } from './theme-colors-section';\nimport { ThemeTypographySection } from './theme-typography-section';\nimport { ThemePageSection } from './theme-page-section';\nimport { ThemeStylesSection } from './theme-styles-section';\nimport { ThemeSchemaSection } from './theme-schema-section';\n\n/**\n * The sections the theme schema adds beyond the hand-built ones — palette,\n * type roles and scale, spacing, chrome, motif, component defaults — derived\n * once the schema arrives from the server. Until then those keys sit in the\n * Advanced list exactly as before.\n */\nfunction useExtendedSections(): SchemaSection[] {\n const [sections, setSections] = useState<SchemaSection[]>([]);\n useEffect(() => {\n let cancelled = false;\n fetchThemeJsonSchema()\n .then((schema) => {\n if (!cancelled) setSections(extendedSections(schema, formKeys(FORMAT)));\n })\n .catch((error) => {\n console.warn('[theme editor] schema unavailable:', error);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n return sections;\n}\n\n/**\n * The theme as a form.\n *\n * The tab owns the text; this component owns nothing. Every render parses\n * `text` and derives the form from it, and every edit is a pure change to\n * that parse written back through `onChange`. That is what keeps the two\n * views of a theme (this one and Monaco) from ever holding different files.\n *\n * `set` and `remove` are stable for the life of the editor and read the\n * latest parse from a ref, so memoised rows keep their identity across\n * writes and only the row whose value changed re-renders.\n */\n\nexport function ThemeVisualEditor({\n docName,\n text,\n onChange,\n onOpenJson,\n usedBy = [],\n nameClash = [],\n}: {\n docName: string;\n text: string;\n onChange: (text: string) => void;\n onOpenJson: () => void;\n /** Open documents whose `props.theme` names this theme. */\n usedBy?: readonly string[];\n /** Other open theme files that declare the same name. */\n nameClash?: readonly string[];\n}) {\n const parsed = useMemo(() => parseTheme(text), [text]);\n\n const latest = useRef<{\n theme: ThemeJson | null;\n onChange: (text: string) => void;\n }>({ theme: null, onChange });\n latest.current.theme = parsed.ok ? parsed.theme : null;\n latest.current.onChange = onChange;\n\n const update = useCallback((fn: (theme: ThemeJson) => ThemeJson) => {\n const current = latest.current.theme;\n // Never write over text the author is mid-way through fixing in JSON.\n if (!current) return;\n const next = fn(current);\n if (next === current) return;\n // Two edits in one tick (a picker firing twice, a switch and a clear)\n // must compose rather than the second clobbering the first, so the ref\n // moves ahead of the render that will confirm it.\n latest.current.theme = next;\n latest.current.onChange(serializeTheme(next));\n }, []);\n\n const set = useCallback(\n (path: Path, value: unknown) =>\n update((theme) => {\n const head = path[0];\n const container = typeof head === 'string' ? theme[head] : undefined;\n const base =\n path.length > 1 && (!container || typeof container !== 'object')\n ? ensureContainers(theme, FORMAT)\n : theme;\n return setAt(base, path, value);\n }),\n [update]\n );\n\n const remove = useCallback(\n (path: Path, prune?: { keepDepth: number }) =>\n update((theme) => {\n let next = deleteAt(theme, path);\n if (!prune) return next;\n let parent = path.slice(0, -1);\n while (parent.length > prune.keepDepth) {\n const value = getAt(next, parent);\n const emptyObject =\n !!value &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n Object.keys(value as object).length === 0;\n if (!emptyObject) break;\n next = deleteAt(next, parent);\n parent = parent.slice(0, -1);\n }\n return next;\n }),\n [update]\n );\n\n const actions = useMemo<ThemeEditorActions>(\n () => ({ set, remove }),\n [set, remove]\n );\n\n if (!parsed.ok) {\n return (\n <div className=\"flex h-full flex-col items-start gap-3 p-4\">\n <p className=\"text-sm text-muted-foreground\">\n The theme JSON has an error:{' '}\n <span className=\"text-destructive\">{parsed.error}</span>\n </p>\n <p className={HINT_CLASS}>\n The form stays read-only until the file parses, so nothing you typed\n in JSON is overwritten.\n </p>\n <Button variant=\"outline\" size=\"sm\" onClick={onOpenJson}>\n <Braces aria-hidden />\n Open JSON\n </Button>\n </div>\n );\n }\n\n const theme = parsed.theme;\n\n return (\n <ThemeEditorProvider value={actions}>\n <ThemeForm\n docName={docName}\n theme={theme}\n usedBy={usedBy}\n nameClash={nameClash}\n onOpenJson={onOpenJson}\n />\n </ThemeEditorProvider>\n );\n}\n\n/**\n * Where the reader is: the section, and the groups inside it, that the\n * sticky bar is currently cutting through. Every section and schema group\n * carries a `data-crumb`; the ones whose box spans the bar's bottom edge are\n * the nesting chain, outermost first. Recomputed on scroll and on any change\n * to the form's height (a section opening, a search narrowing the rows).\n */\nfunction useScrollCrumb(barRef: React.RefObject<HTMLDivElement | null>) {\n const [crumb, setCrumb] = useState<string[]>([]);\n useEffect(() => {\n const bar = barRef.current;\n const viewport = bar?.closest<HTMLElement>(\n '[data-radix-scroll-area-viewport]'\n );\n if (!bar || !viewport) return;\n let frame: number | null = null;\n const measure = () => {\n frame = null;\n const line = bar.getBoundingClientRect().bottom + 1;\n const chain: string[] = [];\n for (const element of viewport.querySelectorAll<HTMLElement>(\n '[data-crumb]'\n )) {\n const box = element.getBoundingClientRect();\n if (box.top <= line && box.bottom > line)\n chain.push(element.dataset.crumb ?? '');\n }\n setCrumb((previous) =>\n previous.length === chain.length &&\n previous.every((entry, index) => entry === chain[index])\n ? previous\n : chain\n );\n };\n const schedule = () => {\n if (frame === null) frame = requestAnimationFrame(measure);\n };\n measure();\n viewport.addEventListener('scroll', schedule, { passive: true });\n const observer = new ResizeObserver(schedule);\n observer.observe(viewport);\n for (const child of viewport.children) observer.observe(child);\n return () => {\n if (frame !== null) cancelAnimationFrame(frame);\n viewport.removeEventListener('scroll', schedule);\n observer.disconnect();\n };\n }, [barRef]);\n return crumb;\n}\n\n/**\n * The sections, behind a search box. The query filters every section's rows\n * by key, label and hint and holds the survivors open; a section with\n * nothing left steps aside. Cleared, everything is back where it was. The\n * bar also names the section being scrolled through, so a long form never\n * loses the reader.\n */\nfunction ThemeForm({\n docName,\n theme,\n usedBy,\n nameClash,\n onOpenJson,\n}: {\n docName: string;\n theme: ThemeJson;\n usedBy: readonly string[];\n nameClash: readonly string[];\n onOpenJson: () => void;\n}) {\n const [query, setQuery] = useState('');\n const extended = useExtendedSections();\n const extendedKeys = useMemo(\n () => extended.map((section) => section.key),\n [extended]\n );\n const barRef = useRef<HTMLDivElement>(null);\n const crumb = useScrollCrumb(barRef);\n return (\n <ScrollArea className=\"h-full\">\n {/* Keyed by document so section disclosure resets per file. */}\n <div\n key={docName}\n className=\"@container mx-auto flex w-full max-w-[760px] flex-col gap-2 px-4 pt-1 pb-8\"\n >\n <div\n ref={barRef}\n className=\"sticky top-0 z-10 -mx-1 bg-background/95 px-1 py-1.5 backdrop-blur\"\n >\n {/* The section under the bar, so a long form says where you are. */}\n <div\n aria-live=\"polite\"\n className={cn(\n 'flex h-4 items-center gap-1 truncate px-1 text-[10px] tracking-[0.08em] text-muted-foreground uppercase',\n crumb.length === 0 && 'invisible'\n )}\n >\n {crumb.map((entry, index) => (\n <React.Fragment key={`${index}-${entry}`}>\n {index > 0 && (\n <span aria-hidden className=\"text-muted-foreground/50\">\n ›\n </span>\n )}\n <span\n className={cn(\n index === crumb.length - 1 && 'text-foreground/80'\n )}\n >\n {entry}\n </span>\n </React.Fragment>\n ))}\n </div>\n <div className=\"relative\">\n <Search\n aria-hidden\n className=\"pointer-events-none absolute top-1/2 left-2 size-3.5 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setQuery('');\n }}\n placeholder=\"Find a setting… (motif, tracking, safe area)\"\n aria-label=\"Find a theme setting\"\n autoComplete=\"off\"\n spellCheck={false}\n className={cn(INPUT_CLASS, 'h-8 pr-7 pl-7')}\n />\n {query && (\n <button\n type=\"button\"\n onClick={() => setQuery('')}\n aria-label=\"Clear search\"\n className=\"absolute top-1/2 right-1 flex size-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-sm text-muted-foreground hover:text-foreground\"\n >\n <X className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </div>\n </div>\n <IdentitySection\n theme={theme}\n usedBy={usedBy}\n nameClash={nameClash}\n query={query}\n />\n <ThemeColorsSection theme={theme} query={query} />\n <ThemeTypographySection theme={theme} query={query} />\n {FORMAT === 'docx' && <ThemePageSection theme={theme} query={query} />}\n <ThemeStylesSection theme={theme} query={query} />\n {extended.map((section) => (\n <ThemeSchemaSection\n key={section.key}\n section={section}\n theme={theme}\n query={query}\n onOpenJson={onOpenJson}\n />\n ))}\n <AdvancedSection\n theme={theme}\n onOpenJson={onOpenJson}\n alsoHandled={extendedKeys}\n query={query}\n />\n </div>\n </ScrollArea>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Identity\n// ---------------------------------------------------------------------------\n\nconst IDENTITY_FIELDS: Record<\n string,\n readonly { key: string; label: string; hint?: string }[]\n> = {\n docx: [\n { key: 'name', label: 'Name', hint: 'What a document puts in \"theme\"' },\n { key: 'displayName', label: 'Display name' },\n { key: 'description', label: 'Description' },\n { key: 'version', label: 'Version' },\n ],\n pptx: [\n { key: 'name', label: 'Name', hint: 'What a document puts in \"theme\"' },\n { key: 'displayName', label: 'Display name' },\n { key: 'description', label: 'Description' },\n { key: 'version', label: 'Version' },\n ],\n};\n\nfunction IdentityField({\n fieldKey,\n label,\n hint,\n value,\n}: {\n fieldKey: string;\n label: string;\n hint?: string;\n value: string | undefined;\n}) {\n const { set, remove } = useThemeEditor();\n const commit = useCallback(\n (next: string | null) =>\n next === null ? remove([fieldKey]) : set([fieldKey], next),\n [fieldKey, remove, set]\n );\n const id = `theme-identity-${fieldKey}`;\n return (\n <>\n <label htmlFor={id} className=\"flex flex-col pt-1.5 text-sm\">\n {label}\n {hint && <span className={HINT_CLASS}>{hint}</span>}\n </label>\n <DraftTextInput\n id={id}\n value={value}\n onCommit={commit}\n className={fieldKey === 'name' ? 'font-mono' : undefined}\n />\n </>\n );\n}\n\nfunction IdentitySection({\n theme,\n usedBy,\n nameClash,\n query = '',\n}: {\n theme: ThemeJson;\n usedBy: readonly string[];\n nameClash: readonly string[];\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const fields = matchesQuery(query, 'identity', 'name')\n ? IDENTITY_FIELDS[FORMAT]\n : IDENTITY_FIELDS[FORMAT].filter((field) =>\n matchesQuery(query, field.key, field.label, field.hint)\n );\n if (searching && fields.length === 0) return null;\n return (\n <EditorSection\n title=\"Identity\"\n hint=\"A document picks this theme by its name; the rest is what the library shows.\"\n forceOpen={searching ? true : undefined}\n >\n <div className=\"grid grid-cols-[7rem_minmax(0,1fr)] items-start gap-x-3 gap-y-2\">\n {fields.map((field) => {\n const value = theme[field.key];\n return (\n <IdentityField\n key={field.key}\n fieldKey={field.key}\n label={field.label}\n hint={field.hint}\n value={typeof value === 'string' ? value : undefined}\n />\n );\n })}\n </div>\n {/* Renaming a theme orphans every document that names it; say who\n that is before the field is touched, not after. */}\n <p className={cn(HINT_CLASS, 'mt-2')}>\n {usedBy.length > 0 ? (\n <>\n Used by{' '}\n {usedBy.map((name, index) => (\n <React.Fragment key={name}>\n {index > 0 && ', '}\n <code className=\"rounded-sm bg-muted px-1 py-0.5 text-[11px]\">\n {name}\n </code>\n </React.Fragment>\n ))}\n . Renaming the theme breaks that reference until the document is\n updated.\n </>\n ) : (\n 'Not used by any open document yet — Run sample shows it anyway.'\n )}\n </p>\n {nameClash.length > 0 && (\n <p className=\"mt-1 text-xs text-warning\">\n {nameClash.join(', ')} also declare{nameClash.length === 1 ? 's' : ''}{' '}\n this name; only one of them can win when a document asks for it.\n </p>\n )}\n </EditorSection>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Advanced\n// ---------------------------------------------------------------------------\n\nfunction AdvancedSection({\n theme,\n onOpenJson,\n alsoHandled,\n query = '',\n}: {\n theme: ThemeJson;\n onOpenJson: () => void;\n alsoHandled: readonly string[];\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const keys = useMemo(\n () =>\n advancedKeys(theme, FORMAT, alsoHandled).filter(\n (entry) =>\n matchesQuery(query, 'advanced') ||\n matchesQuery(query, entry.key, entry.summary)\n ),\n [alsoHandled, query, theme]\n );\n if (searching && keys.length === 0) return null;\n return (\n <EditorSection\n title=\"Advanced\"\n hint=\"Keys the form has no field for. They travel untouched through every edit here.\"\n forceOpen={searching ? true : undefined}\n actions={\n keys.length > 0 ? (\n <QuietButton onClick={onOpenJson}>\n <Braces className=\"size-3\" aria-hidden />\n Edit in JSON\n </QuietButton>\n ) : undefined\n }\n >\n {keys.length === 0 ? (\n <p className={HINT_CLASS}>Nothing beyond the fields above.</p>\n ) : (\n <ul className=\"flex flex-col gap-1\">\n {keys.map((entry) => (\n <li\n key={entry.key}\n className=\"flex min-w-0 items-baseline gap-2 text-xs\"\n >\n <code className=\"shrink-0 rounded-sm bg-muted px-1 py-0.5 text-[11px]\">\n {entry.key}\n </code>\n <span className=\"truncate text-muted-foreground\">\n {entry.summary}\n </span>\n </li>\n ))}\n </ul>\n )}\n </EditorSection>\n );\n}\n\nexport const ThemeVisualEditorMemoized = React.memo(ThemeVisualEditor);\n","import React, { useCallback, useMemo } from 'react';\nimport { EditorMonacoThemeMemoized } from '../json-editor/editor-monaco-theme';\nimport { ThemeVisualEditor } from './theme-visual-editor';\nimport { useSettingsStore } from '../../store/settings-store-provider';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { getThemeName } from '../../lib/theme-validation';\nimport { themeView } from '../../lib/theme-editor/view';\nimport type { TextFile } from '../../lib/types';\n\n/**\n * A theme tab: the same file seen either as a form or as JSON source.\n *\n * The switch between the two sits in the app header, beside Run, rather than\n * on a strip of its own — a tab this narrow cannot spare 36px to say what it\n * already is. The header owns the preference; this reads the same rule so the\n * two never disagree about which view a forced JSON is showing.\n */\nexport function ThemeEditorHost({\n document,\n onChange,\n}: {\n document: TextFile;\n onChange: (text: string) => void;\n}) {\n const preferred = useSettingsStore((s) => s.themeEditorView);\n const setSettings = useSettingsStore((s) => s.setSettings);\n const hasPendingDiff = useDocumentsStore(\n (s) => s.pendingDiffs[document.name] !== undefined\n );\n\n const parsed = useMemo(() => {\n try {\n const value = JSON.parse(document.text);\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n }, [document.text]);\n const themeName = parsed ? getThemeName(parsed) : null;\n\n // Which open documents name this theme, and which other open theme files\n // claim the same name — the two things the Identity section has to say.\n const usedBy = useDocumentsStore((s) => {\n if (!themeName) return EMPTY;\n const names = s.documents\n .filter(\n (d) =>\n (s.documentTypes[d.name] ?? 'application/json+report') ===\n 'application/json+report' && documentThemeName(d.text) === themeName\n )\n .map((d) => d.name);\n return names.length === 0 ? EMPTY : names.join('\\n');\n });\n const nameClash = useDocumentsStore((s) => {\n if (!themeName) return EMPTY;\n const names = s.documents\n .filter(\n (d) =>\n d.name !== document.name &&\n s.documentTypes[d.name] === 'application/json+theme' &&\n themeFileName(d.text) === themeName\n )\n .map((d) => d.name);\n return names.length === 0 ? EMPTY : names.join('\\n');\n });\n\n const { view } = themeView({\n preferred,\n parses: parsed !== null,\n hasPendingDiff,\n });\n\n const openJson = useCallback(\n () => setSettings({ themeEditorView: 'json' }),\n [setSettings]\n );\n\n return (\n <div className=\"h-full\">\n {view === 'visual' ? (\n <ThemeVisualEditor\n docName={document.name}\n text={document.text}\n onChange={onChange}\n onOpenJson={openJson}\n usedBy={usedBy === EMPTY ? NONE : usedBy.split('\\n')}\n nameClash={nameClash === EMPTY ? NONE : nameClash.split('\\n')}\n />\n ) : (\n <EditorMonacoThemeMemoized document={document} onChange={onChange} />\n )}\n </div>\n );\n}\n\nconst EMPTY = '';\nconst NONE: string[] = [];\n\n/** `props.theme` of a document, or null when it has none or does not parse. */\nfunction documentThemeName(text: string): string | null {\n try {\n const theme = JSON.parse(text)?.props?.theme;\n return typeof theme === 'string' ? theme : null;\n } catch {\n return null;\n }\n}\n\n/** The `name` inside a theme file, or null. */\nfunction themeFileName(text: string): string | null {\n try {\n return getThemeName(JSON.parse(text));\n } catch {\n return null;\n }\n}\n\nexport const ThemeEditorHostMemoized = React.memo(ThemeEditorHost);\n","import React, { useCallback, useEffect, useState } from 'react';\nimport {\n BookOpen,\n Check,\n Copy,\n Download as DownloadIcon,\n Globe,\n Info,\n Puzzle,\n} from 'lucide-react';\nimport { Badge } from '../ui/badge';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { Spinner } from '../ui/spinner';\nimport { Switch } from '../ui/switch';\nimport { Textarea } from '../ui/textarea';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';\nimport { useToast } from '../ui/use-toast';\nimport { useBrowserPluginsStore } from '../../store/browser-plugins-store';\nimport { pluginHost } from '../../lib/plugins/host';\nimport { compileQueue } from '../../lib/plugins/compile-queue';\nimport { parseNetworkOrigins } from '../../lib/plugins/network-policy';\nimport {\n onPluginTypeScriptReady,\n pluginTypeScriptReady,\n} from '../../lib/plugins/type-libs';\nimport { download } from '../../lib/download';\nimport { cn } from '../../lib/utils';\nimport { BROWSER_PLUGINS_CHANGED_EVENT } from '../../hooks/useBrowserPluginsSync';\nimport { PLUGIN_FILE_SUFFIX } from '../../store/documents-store';\n\n/** True once the plugin API declarations are in Monaco's TypeScript. */\nfunction usePluginTypesReady(): boolean {\n const [ready, setReady] = useState(pluginTypeScriptReady);\n useEffect(() => onPluginTypeScriptReady(() => setReady(true)), []);\n return ready;\n}\n\n/**\n * The bar above a plugin's source: what it is called, whether it compiled,\n * and the two switches that decide how it takes part — enabled at all, and\n * allowed to reach the network from its sandbox.\n */\nexport function PluginEditorStrip({\n docName,\n text,\n}: {\n docName: string;\n text: string;\n}) {\n const record = useBrowserPluginsStore((s) => s.records[docName]);\n const setEnabled = useBrowserPluginsStore((s) => s.setEnabled);\n const setAllowNetwork = useBrowserPluginsStore((s) => s.setAllowNetwork);\n const setNetworkOrigins = useBrowserPluginsStore((s) => s.setNetworkOrigins);\n const { toast } = useToast();\n const [copiedIndex, setCopiedIndex] = useState<number | null>(null);\n const typesReady = usePluginTypesReady();\n\n const metadata = record?.metadata;\n const status = record?.status ?? 'idle';\n const errorCount = (record?.diagnostics ?? []).filter(\n (d) => d.severity === 'error'\n ).length;\n const displayName =\n metadata?.name ??\n docName.replace(new RegExp(`${PLUGIN_FILE_SUFFIX}$`, 'i'), '');\n const examples = metadata?.examples ?? [];\n\n const announce = useCallback(() => {\n window.dispatchEvent(\n new CustomEvent(BROWSER_PLUGINS_CHANGED_EVENT, { detail: { docName } })\n );\n }, [docName]);\n\n const toggleEnabled = useCallback(\n (enabled: boolean) => {\n setEnabled(docName, enabled);\n announce();\n },\n [announce, docName, setEnabled]\n );\n\n // The sandbox is hardened once, when it loads, and its CSP is fixed when\n // the frame is written: a new setting needs a new frame. Compile again as\n // well — a plugin that failed to load because it reached for the network is\n // only known to work, or not, once it has loaded under the new setting.\n const recompileUnderNewPolicy = useCallback(() => {\n pluginHost.dispose(docName);\n useBrowserPluginsStore.getState().upsert(docName, { status: 'idle' });\n void compileQueue.run(docName);\n }, [docName]);\n\n const toggleNetwork = useCallback(\n (allowNetwork: boolean) => {\n setAllowNetwork(docName, allowNetwork);\n recompileUnderNewPolicy();\n },\n [docName, recompileUnderNewPolicy, setAllowNetwork]\n );\n\n const commitOrigins = useCallback(\n (origins: string[]) => {\n setNetworkOrigins(docName, origins);\n recompileUnderNewPolicy();\n },\n [docName, recompileUnderNewPolicy, setNetworkOrigins]\n );\n\n const copyExample = useCallback(\n async (index: number) => {\n const example = examples[index];\n if (!example || !metadata) return;\n const usage = JSON.stringify(\n { name: metadata.name, props: example.props },\n null,\n 2\n );\n try {\n await navigator.clipboard.writeText(usage);\n setCopiedIndex(index);\n setTimeout(() => setCopiedIndex(null), 1500);\n } catch {\n toast({\n title: 'Clipboard unavailable',\n description: 'Could not copy the example to the clipboard.',\n variant: 'destructive',\n });\n }\n },\n [examples, metadata, toast]\n );\n\n const statusChip = (() => {\n if (!typesReady && status !== 'ready' && status !== 'error') {\n return (\n <span className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <Spinner size=\"sm\" />\n Loading types…\n </span>\n );\n }\n switch (status) {\n case 'compiling':\n return (\n <span className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <Spinner size=\"sm\" />\n Compiling…\n </span>\n );\n case 'ready':\n return (\n <span className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <span aria-hidden className=\"size-1.5 rounded-full bg-success\" />\n Ready\n </span>\n );\n case 'error':\n return (\n <span className=\"flex items-center gap-1.5 text-xs text-destructive\">\n <span\n aria-hidden\n className=\"size-1.5 rounded-full bg-destructive\"\n />\n {errorCount > 0\n ? `${errorCount} error${errorCount === 1 ? '' : 's'}`\n : 'Failed'}\n </span>\n );\n default:\n return (\n <span className=\"text-xs text-muted-foreground\">Not compiled</span>\n );\n }\n })();\n\n return (\n <div className=\"flex h-9 shrink-0 items-center gap-2 border-b bg-sidebar px-3\">\n <Puzzle className=\"size-3.5 shrink-0 text-sidebar-foreground/60\" />\n <span className=\"truncate text-[13px] font-medium\">{displayName}</span>\n {metadata?.latest && (\n <Badge variant=\"outline\" className=\"h-4 px-1.5 font-mono text-[10px]\">\n v{metadata.latest}\n </Badge>\n )}\n <span className=\"mx-1 h-4 w-px bg-border/60\" />\n {statusChip}\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"How plugins run\"\n className=\"inline-flex size-6 cursor-help items-center justify-center rounded-sm hover:bg-muted/60\"\n >\n <Info className=\"size-3.5 text-muted-foreground\" />\n </button>\n </TooltipTrigger>\n <TooltipContent className=\"max-w-sm\">\n <p className=\"text-sm\">\n Compiled in your browser and run in a worker inside a sandboxed\n frame with its own origin: no page, no cookies, no storage, and\n nothing on the network it has not been given. The server only ever\n receives the standard components it produces.\n </p>\n <p className=\"mt-2 text-sm\">\n Network is per host. A plugin allowed to call a host can also load\n code from it and send it anything it renders, so list only hosts you\n would trust with the document.\n </p>\n </TooltipContent>\n </Tooltip>\n\n <span className=\"flex-1\" />\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 gap-1.5 px-2 text-xs\"\n disabled={examples.length === 0}\n title={\n examples.length === 0\n ? 'Add a JSDoc @example with a JSON block to list usage examples here'\n : undefined\n }\n >\n <BookOpen className=\"size-3.5\" />\n Examples\n {examples.length > 0 && (\n <Badge variant=\"secondary\" className=\"h-4 px-1 text-[10px]\">\n {examples.length}\n </Badge>\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\">\n <DropdownMenuLabel className=\"text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Copy as component JSON\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n {examples.map((example, index) => (\n <DropdownMenuItem\n key={index}\n onClick={(event) => {\n event.preventDefault();\n void copyExample(index);\n }}\n className=\"gap-2\"\n >\n {copiedIndex === index ? (\n <Check className=\"size-3.5 text-success\" />\n ) : (\n <Copy className=\"size-3.5 text-muted-foreground\" />\n )}\n <span className=\"truncate\">\n {example.title ?? `Example ${index + 1}`}\n </span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n <label\n htmlFor={`plugin-enabled-${docName}`}\n className={cn(\n 'flex h-7 cursor-pointer items-center gap-1.5 rounded-sm px-1.5 text-xs',\n record?.enabled ? 'text-foreground' : 'text-muted-foreground'\n )}\n title=\"On: the component is offered in completions and expanded in every build. Off: a document that still names it fails to build with a message pointing here.\"\n >\n Enabled\n <Switch\n id={`plugin-enabled-${docName}`}\n checked={record?.enabled ?? true}\n onCheckedChange={toggleEnabled}\n aria-label=\"Enable plugin\"\n />\n </label>\n <NetworkControl\n docName={docName}\n allowNetwork={record?.allowNetwork ?? false}\n origins={record?.networkOrigins ?? []}\n onToggle={toggleNetwork}\n onCommitOrigins={commitOrigins}\n />\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-7\"\n aria-label=\"Download plugin source\"\n onClick={() =>\n download(docName, new Blob([text], { type: 'text/typescript' }))\n }\n >\n <DownloadIcon className=\"size-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n <p>\n Download <code>{docName}</code> to use it on disk with the CLI\n </p>\n </TooltipContent>\n </Tooltip>\n </div>\n );\n}\n\nexport const PluginEditorStripMemoized = React.memo(PluginEditorStrip);\n\n/**\n * The Network control: a switch, and the hosts the switch grants.\n *\n * The switch alone reaches nothing. That is the point — \"on\" used to mean the\n * whole internet, which made it a grant nobody could reason about: a plugin\n * that may call anywhere may also fetch code and run it, so reading its source\n * stops telling you what it does. Naming the hosts keeps the decision one an\n * author can actually make.\n */\nfunction NetworkControl({\n docName,\n allowNetwork,\n origins,\n onToggle,\n onCommitOrigins,\n}: {\n docName: string;\n allowNetwork: boolean;\n origins: string[];\n onToggle: (allowNetwork: boolean) => void;\n onCommitOrigins: (origins: string[]) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [draft, setDraft] = useState(() => origins.join('\\n'));\n\n // The field trails the record while it is closed; opening re-seeds it so a\n // rename or an edit from elsewhere is not overwritten by a stale draft.\n useEffect(() => {\n if (!open) setDraft(origins.join('\\n'));\n }, [open, origins]);\n\n const parsed = parseNetworkOrigins(draft);\n const granted = allowNetwork && origins.length > 0;\n const label = !allowNetwork\n ? 'Network off'\n : origins.length === 0\n ? 'Network on, no hosts listed'\n : `Network: ${origins.join(', ')}`;\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n className={cn(\n 'flex h-7 cursor-pointer items-center gap-1.5 rounded-sm px-1.5 text-xs',\n 'transition-colors hover:bg-muted/60',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n granted ? 'text-foreground' : 'text-muted-foreground'\n )}\n >\n <Globe className=\"size-3.5\" aria-hidden=\"true\" />\n <span className=\"hidden sm:inline\">Network</span>\n {granted && (\n <Badge\n variant=\"outline\"\n className=\"h-4 px-1 font-mono text-[10px] tabular-nums\"\n >\n {origins.length}\n </Badge>\n )}\n {allowNetwork && origins.length === 0 && (\n <span className=\"text-[10px] text-amber-600 dark:text-amber-500\">\n no hosts\n </span>\n )}\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-80 space-y-3\">\n <label\n htmlFor={`plugin-network-${docName}`}\n className=\"flex cursor-pointer items-center justify-between gap-2\"\n >\n <span className=\"text-sm font-medium\">Allow network</span>\n <Switch\n id={`plugin-network-${docName}`}\n checked={allowNetwork}\n onCheckedChange={onToggle}\n aria-label=\"Allow network access\"\n />\n </label>\n <p className=\"text-xs text-muted-foreground\">\n Off: <code>fetch</code>, <code>XMLHttpRequest</code>,{' '}\n <code>WebSocket</code> and <code>EventSource</code> throw inside the\n sandbox. On: only the hosts below are reachable — everything else is\n refused by the browser, not by the plugin.\n </p>\n {allowNetwork && (\n <>\n <Textarea\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onBlur={() => onCommitOrigins(parsed.origins)}\n spellCheck={false}\n rows={3}\n aria-label=\"Hosts this plugin may call\"\n placeholder={'api.open-meteo.com\\ngeocoding-api.open-meteo.com'}\n className=\"font-mono text-xs\"\n />\n <p className=\"text-xs text-muted-foreground\">\n One host per line. <code>https</code> is assumed;{' '}\n <code>*.example.com</code> matches subdomains.\n </p>\n {parsed.errors.length > 0 && (\n <ul className=\"space-y-0.5 text-xs text-destructive\">\n {parsed.errors.map((error) => (\n <li key={error}>{error}</li>\n ))}\n </ul>\n )}\n {parsed.errors.length === 0 && parsed.origins.length === 0 && (\n <p className=\"text-xs text-amber-600 dark:text-amber-500\">\n Nothing listed, so nothing is reachable.\n </p>\n )}\n </>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport Editor, { type Monaco } from '@monaco-editor/react';\nimport type { editor as MonacoEditorType } from 'monaco-editor';\nimport debounce from 'lodash.debounce';\nimport { useTheme } from '../theme-provider';\nimport { monacoThemeFor, registerMonacoThemes } from '../../lib/monaco-theme';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { useEditorRefsStore } from '../../store/editor-refs-store';\nimport { useBrowserPluginsStore } from '../../store/browser-plugins-store';\nimport { pluginModelPath } from '../../lib/plugins/compiler';\nimport { ensurePluginTypeScript } from '../../lib/plugins/type-libs';\nimport type { JsonEditorError } from '../../lib/json-types';\nimport {\n ValidationPanel,\n ValidationStatusBar,\n} from '../json-editor/validation-panel';\nimport { PluginEditorStripMemoized } from './plugin-editor-strip';\n\n/**\n * A plugin file open in a tab: Monaco in TypeScript mode over the same model\n * the compiler uses, so completions, hovers and the diagnostics below come\n * from one program. Saving is the document store's job, debounced like the\n * JSON editors; compiling is the sync hook's, which watches the store.\n */\nfunction EditorMonacoPlugin({\n name,\n value,\n saveDocumentDebounceWait,\n}: {\n name: string;\n value: string;\n saveDocumentDebounceWait: number;\n}) {\n const editorRef = useRef<MonacoEditorType.IStandaloneCodeEditor | null>(null);\n const { resolvedTheme } = useTheme();\n const saveDocument = useDocumentsStore((s) => s.saveDocument);\n const closeDocument = useDocumentsStore((s) => s.closeDocument);\n const { registerEditor, unregisterEditor, setActiveEditor } =\n useEditorRefsStore();\n const diagnostics = useBrowserPluginsStore(\n (s) => s.records[name]?.diagnostics\n );\n\n // Our own save echoes must not be written back into the editor: with the\n // debounce the store trails the model, and the wrapper would otherwise\n // replace newer keystrokes with the older saved text.\n const lastSavedRef = useRef<string | null>(null);\n const [editorValue, setEditorValue] = useState(value);\n const debouncedSaveRef = useRef(\n debounce((text: string) => {\n lastSavedRef.current = text;\n saveDocument(name, text);\n }, saveDocumentDebounceWait)\n );\n\n const [showPanel, setShowPanel] = useState(true);\n const [panelMinimized, setPanelMinimized] = useState(false);\n const userDismissedRef = useRef(false);\n\n const errors = useMemo<JsonEditorError[]>(\n () =>\n (diagnostics ?? []).map((d) => ({\n path: d.source === 'typescript' ? '' : d.source,\n message: d.message,\n code: d.source,\n severity: d.severity,\n ...(d.line !== undefined\n ? {\n startLineNumber: d.line,\n startColumn: d.column,\n endLineNumber: d.endLine,\n endColumn: d.endColumn,\n }\n : {}),\n })),\n [diagnostics]\n );\n\n useEffect(() => {\n if (errors.length > 0 && !userDismissedRef.current) {\n setShowPanel(true);\n setPanelMinimized(false);\n }\n if (errors.length === 0) userDismissedRef.current = false;\n }, [errors.length]);\n\n const handleWillMount = useCallback((monaco: Monaco) => {\n registerMonacoThemes(monaco);\n // Types load asynchronously; diagnostics settle once they have.\n void ensurePluginTypeScript(monaco);\n }, []);\n\n const flushPendingSave = useCallback(() => {\n debouncedSaveRef.current.flush();\n }, []);\n\n const handleMount = useCallback(\n (editor: MonacoEditorType.IStandaloneCodeEditor, monaco: Monaco) => {\n editorRef.current = editor;\n registerEditor(\n name,\n editor,\n monaco,\n undefined,\n undefined,\n flushPendingSave\n );\n setActiveEditor(name);\n\n const saveNow = () => {\n const text = editor.getValue();\n debouncedSaveRef.current.cancel();\n lastSavedRef.current = text;\n saveDocument(name, text);\n };\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, saveNow);\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyW, () => {\n saveNow();\n closeDocument(name);\n });\n editor.addCommand(\n monaco.KeyMod.Shift | monaco.KeyMod.Alt | monaco.KeyCode.KeyF,\n () => {\n editor.getAction('editor.action.formatDocument')?.run();\n }\n );\n },\n [\n closeDocument,\n flushPendingSave,\n name,\n registerEditor,\n saveDocument,\n setActiveEditor,\n ]\n );\n\n useEffect(() => {\n const debouncedSave = debouncedSaveRef.current;\n return () => {\n debouncedSave.flush();\n unregisterEditor(name);\n };\n }, [name, unregisterEditor]);\n\n // A genuine external change (rename, AI apply, another view): replace the\n // model text. Our own echoes are recognised by `lastSavedRef`.\n useEffect(() => {\n if (value === lastSavedRef.current) return;\n const model = editorRef.current?.getModel();\n if (model && model.getValue() !== value) model.setValue(value);\n setEditorValue(value);\n }, [value]);\n\n const handleErrorClick = useCallback((error: JsonEditorError) => {\n const editor = editorRef.current;\n if (!editor || !error.startLineNumber) return;\n editor.setPosition({\n lineNumber: error.startLineNumber,\n column: error.startColumn ?? 1,\n });\n editor.revealLineInCenter(error.startLineNumber);\n editor.focus();\n }, []);\n\n return (\n <div className=\"flex h-full flex-col\">\n <PluginEditorStripMemoized docName={name} text={value} />\n <div className=\"relative min-h-0 flex-1\">\n <Editor\n height=\"100%\"\n defaultLanguage=\"typescript\"\n path={pluginModelPath(name)}\n value={editorValue}\n theme={monacoThemeFor(resolvedTheme)}\n beforeMount={handleWillMount}\n onMount={handleMount}\n keepCurrentModel\n onChange={(text) => {\n if (text !== undefined) debouncedSaveRef.current(text);\n }}\n options={{\n lineNumbers: 'on',\n glyphMargin: true,\n folding: true,\n lineDecorationsWidth: 5,\n lineNumbersMinChars: 3,\n renderValidationDecorations: 'on',\n quickSuggestions: { other: true, comments: false, strings: true },\n acceptSuggestionOnCommitCharacter: true,\n acceptSuggestionOnEnter: 'on',\n autoIndent: 'advanced',\n formatOnType: true,\n formatOnPaste: true,\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: true,\n tabSize: 2,\n wordWrap: 'off',\n }}\n />\n <div className=\"absolute top-0 right-0\">\n <ValidationStatusBar\n errors={errors}\n onClick={() => {\n setShowPanel(true);\n setPanelMinimized(false);\n }}\n />\n </div>\n {showPanel && errors.length > 0 && (\n <ValidationPanel\n errors={errors}\n isMinimized={panelMinimized}\n onToggleMinimize={() => setPanelMinimized((v) => !v)}\n onErrorClick={handleErrorClick}\n onClose={() => {\n setShowPanel(false);\n userDismissedRef.current = true;\n }}\n className=\"z-40\"\n />\n )}\n </div>\n </div>\n );\n}\n\nexport const EditorMonacoPluginMemoized = React.memo(EditorMonacoPlugin);\n","import React from 'react';\nimport { EditorMonacoJsonMemoized } from '../json-editor/editor-monaco-json';\nimport { ThemeEditorHostMemoized } from '../theme-editor/theme-editor-host';\nimport { EditorMonacoPluginMemoized } from '../plugin-editor/editor-monaco-plugin';\nimport { TabsContent } from '../ui/tabs';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { useThemesStore } from '../../store/themes-store-provider';\nimport type { TextFile } from '../../lib/types';\nimport type { DocumentType } from '../../store/documents-store';\nimport debounce from 'lodash.debounce';\n\nfunction TabContent({\n name,\n text,\n buildError: _buildError,\n saveDocumentDebounceWait,\n documentType,\n}: {\n name: string;\n text: string;\n buildError?: string;\n saveDocumentDebounceWait: number;\n documentType: DocumentType;\n}) {\n const { saveDocument } = useDocumentsStore((state) => state);\n const { updateTheme } = useThemesStore((state) => state);\n\n // Create a debounced version of updateTheme\n const debouncedUpdateTheme = React.useMemo(\n () => debounce(updateTheme, saveDocumentDebounceWait),\n [updateTheme, saveDocumentDebounceWait]\n );\n\n // Flush pending theme updates on unmount so the themes store is always\n // up-to-date when the user switches away from a theme tab.\n React.useEffect(() => {\n return () => {\n debouncedUpdateTheme.flush();\n };\n }, [debouncedUpdateTheme]);\n\n const handleChange = React.useCallback(\n (value: string) => {\n saveDocument(name, value);\n\n // If this is a theme document, update the themes store with debouncing\n if (documentType === 'application/json+theme') {\n console.log(\n 'TabContent: Theme document change detected, debouncing update',\n {\n documentName: name,\n debounceWait: saveDocumentDebounceWait,\n }\n );\n debouncedUpdateTheme(name, value);\n }\n },\n [\n name,\n saveDocument,\n debouncedUpdateTheme,\n documentType,\n saveDocumentDebounceWait,\n ]\n );\n\n // Create a fake document object for the theme editor\n const document: TextFile = React.useMemo(\n () => ({\n name,\n type: 'application/json',\n text,\n mtime: new Date(),\n ctime: new Date(),\n atime: new Date(),\n }),\n [name, text]\n );\n\n return (\n <TabsContent\n value={name}\n className=\"mt-0 h-full p-0\"\n tabIndex={-1} // to prevent focus on Tab trigger (fix for accessibility size issue)\n >\n {documentType === 'application/json+theme' ? (\n <ThemeEditorHostMemoized document={document} onChange={handleChange} />\n ) : documentType === 'application/typescript+plugin' ? (\n <EditorMonacoPluginMemoized\n name={name}\n value={text}\n saveDocumentDebounceWait={saveDocumentDebounceWait}\n />\n ) : (\n <EditorMonacoJsonMemoized\n name={name}\n value={text}\n saveDocumentDebounceWait={saveDocumentDebounceWait}\n />\n )}\n </TabsContent>\n );\n}\n\nconst TabContentMemoized = React.memo(TabContent);\n\nfunction EditorTabsContent({\n openTabs,\n documents,\n buildErrors,\n saveDocumentDebounceWait,\n}: {\n openTabs: string[];\n documents: TextFile[];\n buildErrors: Record<string, string>;\n saveDocumentDebounceWait: number;\n}) {\n const { documentTypes } = useDocumentsStore((state) => state);\n\n return openTabs\n .map((name) => documents.find((d) => d.name === name))\n .filter((doc): doc is TextFile => doc !== undefined)\n .map((doc) => {\n const documentType = documentTypes[doc.name] || 'application/json+report';\n\n return (\n <TabContentMemoized\n key={doc.name}\n name={doc.name}\n text={doc.text}\n buildError={buildErrors[doc.name]}\n saveDocumentDebounceWait={saveDocumentDebounceWait}\n documentType={documentType}\n />\n );\n });\n}\n\nexport const EditorTabsContentMemoized = React.memo(EditorTabsContent);\n","export interface RetryOptions {\n maxRetries?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffFactor?: number;\n onRetry?: (error: Error, attempt: number) => void;\n shouldRetry?: (error: Error) => boolean;\n signal?: AbortSignal;\n}\n\nexport class RetryError extends Error {\n constructor(\n message: string,\n public readonly lastError: Error,\n public readonly attempts: number\n ) {\n super(message);\n this.name = 'RetryError';\n }\n}\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<T> {\n const {\n maxRetries = 3,\n initialDelay = 1000,\n maxDelay = 30000,\n backoffFactor = 2,\n onRetry,\n shouldRetry = () => true,\n signal,\n } = options;\n\n let lastError: Error;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n // Check if operation was cancelled\n if (signal?.aborted) {\n throw new Error('Operation cancelled');\n }\n\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry if it's the last attempt\n if (attempt === maxRetries) {\n break;\n }\n\n // Check if we should retry this error\n if (!shouldRetry(lastError)) {\n throw lastError;\n }\n\n // Calculate delay with exponential backoff\n const delay = Math.min(\n initialDelay * Math.pow(backoffFactor, attempt),\n maxDelay\n );\n\n // Add some jitter to prevent thundering herd\n const jitteredDelay = delay * (0.5 + Math.random() * 0.5);\n\n // Call retry callback if provided\n if (onRetry) {\n onRetry(lastError, attempt + 1);\n }\n\n // Wait before retrying\n await new Promise((resolve) => {\n const timeoutId = setTimeout(resolve, jitteredDelay);\n\n // Clean up timeout if cancelled\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeoutId);\n resolve(undefined);\n },\n { once: true }\n );\n }\n });\n }\n }\n\n throw new RetryError(\n `Failed after ${maxRetries + 1} attempts`,\n lastError!,\n maxRetries + 1\n );\n}\n\n/**\n * Retry decorator for class methods\n */\nexport function Retryable(options: RetryOptions = {}) {\n return function (\n _target: any,\n _propertyKey: string,\n descriptor: PropertyDescriptor\n ) {\n const originalMethod = descriptor.value;\n\n descriptor.value = async function (...args: any[]) {\n return retry(() => originalMethod.apply(this, args), options);\n };\n\n return descriptor;\n };\n}\n\n/**\n * Common retry strategies\n */\nexport const RetryStrategies = {\n // Retry on network errors\n networkErrors: (error: Error) => {\n const networkErrorPatterns = [\n 'NetworkError',\n 'Failed to fetch',\n 'ERR_NETWORK',\n 'ECONNREFUSED',\n 'ETIMEDOUT',\n 'ENOTFOUND',\n 'fetch failed',\n ];\n\n return networkErrorPatterns.some(\n (pattern) =>\n error.message.includes(pattern) || error.name.includes(pattern)\n );\n },\n\n // Retry on specific HTTP status codes\n httpStatusCodes: (statusCodes: number[]) => (error: any) => {\n if (error.response?.status) {\n return statusCodes.includes(error.response.status);\n }\n return false;\n },\n\n // Retry on temporary errors\n temporaryErrors: (error: Error) => {\n const temporaryPatterns = [\n 'EBUSY',\n 'EAGAIN',\n 'temporarily unavailable',\n 'too many requests',\n 'rate limit',\n ];\n\n return temporaryPatterns.some((pattern) =>\n error.message.toLowerCase().includes(pattern.toLowerCase())\n );\n },\n\n // Combine multiple strategies\n combine:\n (...strategies: ((error: Error) => boolean)[]) =>\n (error: Error) => {\n return strategies.some((strategy) => strategy(error));\n },\n};\n","import type { FormatName } from '../env';\nimport { definedColorKeys, type ThemeJson } from './model';\n\n/**\n * A document that shows a theme.\n *\n * \"Preview specimen\" renders this through the ordinary generate + preview\n * path, so what the author sees is the real output of the real pipeline in\n * the theme they are editing: every named style, the colour tokens as\n * swatches, a table, and (PPTX) a native chart drawn from the palette.\n *\n * Only tokens the theme defines are referenced. A DOCX theme that leaves\n * `accent4` unset throws on a component that names it, and the specimen must\n * never be the thing that fails.\n */\n\nconst BODY_TEXT =\n 'Body text in the normal style, with **bold**, *italic* and `mono` runs beside plain words so weight and the mono role read next to each other. A second sentence gives the line spacing and paragraph spacing room to show.';\n\nconst TOKEN_ROLES: Record<string, string> = {\n primary: 'Headings and the strongest brand colour',\n secondary: 'Supporting brand colour',\n accent: 'Highlights and emphasis',\n text: 'Body text',\n textPrimary: 'Primary text',\n textSecondary: 'Secondary text',\n textMuted: 'Captions and muted text',\n text2: 'Secondary text and captions',\n background: 'Page background',\n backgroundPrimary: 'Primary surface',\n backgroundSecondary: 'Alternate surface',\n background2: 'Alternate surface and rules',\n border: 'Rules and borders',\n borderPrimary: 'Primary rules',\n borderSecondary: 'Subtle rules',\n accent4: 'Chart series 4',\n accent5: 'Chart series 5',\n accent6: 'Chart series 6',\n};\n\n/** The colour keys worth a swatch: hex values only, references included. */\nfunction swatchTokens(theme: ThemeJson | undefined): string[] {\n if (!theme) return [];\n return definedColorKeys(theme);\n}\n\nfunction hasStyle(theme: ThemeJson | undefined, name: string): boolean {\n const styles = theme?.styles;\n return !!styles && typeof styles === 'object' && name in (styles as object);\n}\n\nfunction docxSpecimen(\n themeName: string,\n theme: ThemeJson | undefined\n): unknown {\n const tokens = swatchTokens(theme);\n const children: unknown[] = [];\n\n children.push(\n hasStyle(theme, 'title')\n ? {\n name: 'paragraph',\n props: { text: 'Theme specimen', themeStyle: 'title' },\n }\n : { name: 'heading', props: { text: 'Theme specimen', level: 1 } }\n );\n if (hasStyle(theme, 'subtitle')) {\n children.push({\n name: 'paragraph',\n props: {\n text: `Every named style, colour and font of \"${themeName}\", on one page.`,\n themeStyle: 'subtitle',\n },\n });\n } else {\n children.push({\n name: 'paragraph',\n props: {\n text: `Every named style, colour and font of \"${themeName}\", on one page.`,\n },\n });\n }\n\n children.push(\n { name: 'heading', props: { text: 'Heading 1 — Typography', level: 1 } },\n { name: 'paragraph', props: { text: BODY_TEXT } },\n { name: 'heading', props: { text: 'Heading 2 — Structure', level: 2 } },\n {\n name: 'paragraph',\n props: {\n text: 'A second paragraph under a second-level heading, so the spacing before and after headings can be judged against running text.',\n },\n },\n { name: 'heading', props: { text: 'Heading 3 — Detail', level: 3 } },\n {\n name: 'list',\n props: {\n items: [\n 'Primary carries the headings',\n 'Secondary supports it',\n 'Accent marks emphasis',\n ],\n },\n },\n { name: 'divider', props: {} },\n { name: 'heading', props: { text: 'Figures', level: 2 } },\n {\n name: 'statistic',\n props: {\n number: '42%',\n description:\n 'A statistic: the number in the heading font, the caption below it',\n },\n }\n );\n\n if (tokens.length > 0) {\n children.push(\n { name: 'heading', props: { text: 'Colours', level: 2 } },\n {\n name: 'table',\n props: {\n columns: [\n {\n header: { content: 'Token' },\n cells: tokens.map((token) => ({ content: token })),\n },\n {\n header: { content: 'Swatch' },\n cells: tokens.map((token) => ({\n content: ' ',\n backgroundColor: token,\n })),\n },\n {\n header: { content: 'Role' },\n cells: tokens.map((token) => ({\n content: TOKEN_ROLES[token] ?? '',\n })),\n },\n ],\n },\n }\n );\n }\n\n return {\n name: 'docx',\n props: {\n theme: themeName,\n metadata: {\n title: `${themeName} sample`,\n author: 'json-to-office playground',\n description: `Sample rendered in the \"${themeName}\" theme`,\n },\n },\n children: [{ name: 'section', props: {}, children }],\n };\n}\n\nfunction pptxSpecimen(\n themeName: string,\n theme: ThemeJson | undefined\n): unknown {\n const tokens = swatchTokens(theme);\n const text = (\n content: string,\n style: string,\n x: number,\n y: number,\n w: number,\n h: number\n ) => ({ name: 'text', props: { text: content, style, x, y, w, h } });\n\n const slides: unknown[] = [\n {\n name: 'slide',\n props: { meta: { title: 'Title' } },\n children: [\n text('Theme specimen', 'title', 0.5, 1.6, 9, 1.2),\n text(\n `Named styles, colours and fonts of \"${themeName}\"`,\n 'subtitle',\n 0.5,\n 2.9,\n 9,\n 0.8\n ),\n ],\n },\n {\n name: 'slide',\n props: { meta: { title: 'Typography' } },\n children: [\n text('Typography', 'heading1', 0.5, 0.4, 9, 0.8),\n text('Heading 2 — the section style', 'heading2', 0.5, 1.3, 9, 0.6),\n text('Heading 3 — the detail style', 'heading3', 0.5, 1.95, 9, 0.5),\n text(\n 'Body text in the body style. It runs long enough to wrap onto a second line, so the line spacing and the body size can be judged against the headings above it.',\n 'body',\n 0.5,\n 2.55,\n 9,\n 1.4\n ),\n text(\n 'Caption — the smallest voice on the slide',\n 'caption',\n 0.5,\n 4.1,\n 9,\n 0.4\n ),\n ],\n },\n ];\n\n if (tokens.length > 0) {\n const perRow = 6;\n const swatches: unknown[] = [];\n tokens.forEach((token, index) => {\n const column = index % perRow;\n const row = Math.floor(index / perRow);\n const x = 0.5 + column * 1.5;\n const y = 1.3 + row * 1.6;\n swatches.push(\n {\n name: 'shape',\n props: { type: 'rect', x, y, w: 1.3, h: 0.9, fill: { color: token } },\n },\n text(token, 'caption', x, y + 0.95, 1.3, 0.4)\n );\n });\n slides.push({\n name: 'slide',\n props: { meta: { title: 'Colours' } },\n children: [text('Colours', 'heading1', 0.5, 0.4, 9, 0.8), ...swatches],\n });\n }\n\n slides.push({\n name: 'slide',\n props: { meta: { title: 'Chart and table' } },\n children: [\n text('Chart and table', 'heading1', 0.5, 0.4, 9, 0.8),\n {\n name: 'chart',\n props: {\n type: 'bar',\n x: 0.5,\n y: 1.3,\n w: 4.6,\n h: 3.6,\n showLegend: true,\n data: [\n {\n name: 'Revenue',\n labels: ['Q1', 'Q2', 'Q3', 'Q4'],\n values: [120, 132, 145, 160],\n },\n {\n name: 'Cost',\n labels: ['Q1', 'Q2', 'Q3', 'Q4'],\n values: [80, 84, 91, 95],\n },\n {\n name: 'Margin',\n labels: ['Q1', 'Q2', 'Q3', 'Q4'],\n values: [40, 48, 54, 65],\n },\n ],\n },\n },\n {\n name: 'table',\n props: {\n x: 5.4,\n y: 1.3,\n w: 4.1,\n headerRow: true,\n rows: [\n [{ text: 'Metric' }, { text: 'Value' }],\n [{ text: 'Revenue' }, { text: '$4.2M' }],\n [{ text: 'Users' }, { text: '12,847' }],\n [{ text: 'Retention' }, { text: '94%' }],\n ],\n },\n },\n ],\n });\n\n return {\n name: 'pptx',\n props: { title: `${themeName} sample`, theme: themeName },\n children: slides,\n };\n}\n\n/** The output name a theme's sample builds under, so the header says what it is. */\nexport function sampleOutputName(themeName: string): string {\n return `Sample · ${themeName}`;\n}\n\nexport function isSampleOutputName(name: string): boolean {\n return name.startsWith('Sample · ');\n}\n\n/**\n * The specimen for `themeName`. `theme` is the parsed theme when the caller\n * has it; it decides which tokens and styles the specimen dares to name.\n */\nexport function buildThemeSpecimen(\n format: FormatName,\n themeName: string,\n theme?: ThemeJson\n): unknown {\n return format === 'docx'\n ? docxSpecimen(themeName, theme)\n : pptxSpecimen(themeName, theme);\n}\n","import {\n useEffect,\n useCallback,\n useRef,\n useMemo,\n memo,\n useContext,\n} from 'react';\nimport { EditorTabsContentMemoized } from './editor-tabs-content';\nimport { Tabs } from '../ui/tabs';\nimport {\n useDocumentsStore,\n DocumentsStoreContext,\n} from '../../store/documents-store-provider';\nimport {\n useOutputStore,\n OutputStoreContext,\n} from '../../store/output-store-provider';\nimport { useSettingsStore } from '../../store/settings-store-provider';\nimport { useEditorRefsStore } from '../../store/editor-refs-store';\nimport {\n useThemesStore,\n ThemesStoreContext,\n} from '../../store/themes-store-provider';\nimport {\n QualityGateFailedError,\n usePresentationGenerator,\n} from '../../hooks/usePresentationGenerator';\nimport { useQualityAnalysis } from '../../hooks/useQualityAnalysis';\nimport { FORMAT } from '../../lib/env';\nimport {\n buildQualityOptions,\n storedProfileId,\n} from '../../lib/quality-profiles';\nimport {\n isStaleQualityTicket,\n nextQualityTicket,\n} from '../../lib/quality-sequence';\nimport {\n countBySeverity,\n findingsFromAnalysis,\n splitQualityWarnings,\n type GenerationWarningLike,\n} from '../../lib/quality-findings';\nimport type { GenerationWarning, QualityState } from '../../store/output-store';\nimport { retry, RetryStrategies } from '../../utils/retry';\nimport { themeChangeEmitter } from '../../utils/theme-change-emitter';\nimport { expandForServer } from '../../lib/plugins/expand-for-server';\nimport { compileQueue } from '../../lib/plugins/compile-queue';\nimport { BROWSER_PLUGINS_CHANGED_EVENT } from '../../hooks/useBrowserPluginsSync';\nimport {\n buildThemeSpecimen,\n isSampleOutputName,\n sampleOutputName,\n} from '../../lib/theme-editor/specimen';\nimport { getThemeName } from '../../lib/theme-validation';\nimport { useShallow } from 'zustand/react/shallow';\n\ninterface BuildRequest {\n id: string;\n docName: string;\n doc: any;\n signal: AbortSignal;\n timestamp: number;\n /** Ordering ticket for the quality slice; see lib/quality-sequence.ts. */\n qualityTicket: number;\n}\n\nfunction EditorComponent() {\n const setOutput = useOutputStore((state) => state.setOutput);\n const outputStore = useContext(OutputStoreContext)!;\n const documentsStore = useContext(DocumentsStoreContext)!;\n const themesStore = useContext(ThemesStoreContext)!;\n const saveDocumentDebounceWait = useSettingsStore(\n (state) => state.saveDocumentDebounceWait\n );\n const {\n openTabs,\n activeTab,\n setActiveTab,\n documents,\n buildErrors,\n setBuildError,\n documentTypes,\n } = useDocumentsStore(\n useShallow((state) => ({\n openTabs: state.openTabs,\n activeTab: state.activeTab,\n setActiveTab: state.setActiveTab,\n documents: state.documents,\n buildErrors: state.buildErrors,\n setBuildError: state.setBuildError,\n documentTypes: state.documentTypes,\n }))\n );\n const { customThemes } = useThemesStore(\n useShallow((state) => ({ customThemes: state.customThemes }))\n );\n const { generatePresentation, cancelGeneration } = usePresentationGenerator();\n const qualityProfileIds = useSettingsStore(\n (state) => state.qualityProfileIds\n );\n const qualityProfileId = storedProfileId(qualityProfileIds);\n const qualityGate = useSettingsStore((state) => state.qualityGate);\n const qualityPolicyText = useSettingsStore(\n (state) => state.qualityPolicies?.[FORMAT]\n );\n const qualityOptions = useMemo(\n () => buildQualityOptions(qualityProfileId, qualityGate, qualityPolicyText),\n [qualityProfileId, qualityGate, qualityPolicyText]\n );\n const { analyze: analyzeQuality, cancel: cancelQualityAnalysis } =\n useQualityAnalysis();\n\n // Refs to track ongoing operations and prevent race conditions\n const buildAbortControllersRef = useRef<Map<string, AbortController>>(\n new Map()\n );\n const buildTimeoutsRef = useRef<Map<string, NodeJS.Timeout>>(new Map());\n // Debounce timer for Run-button builds (150ms to coalesce rapid clicks).\n const flushBuildTimerRef = useRef<NodeJS.Timeout | null>(null);\n const lastBuildRequestIdRef = useRef<string>('');\n const documentVersionsRef = useRef<Map<string, number>>(new Map());\n\n // User-initiated cancel from the loading UI: invalidate the current request\n // id first (so both build paths take their quiet \"cancelled\" exit instead of\n // surfacing a global error), then abort the controllers and the in-flight\n // fetch.\n const cancelActiveBuild = useCallback(() => {\n lastBuildRequestIdRef.current = `cancelled-${Date.now()}`;\n // Also drop queued debounced builds — without this, a pending auto-build\n // timer could start a new generation right after the user cancelled.\n for (const timeout of buildTimeoutsRef.current.values()) {\n clearTimeout(timeout);\n }\n buildTimeoutsRef.current.clear();\n if (flushBuildTimerRef.current) {\n clearTimeout(flushBuildTimerRef.current);\n flushBuildTimerRef.current = null;\n }\n for (const controller of buildAbortControllersRef.current.values()) {\n controller.abort();\n }\n buildAbortControllersRef.current.clear();\n cancelGeneration();\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n }, [cancelGeneration, setOutput]);\n\n useEffect(() => {\n setOutput({ cancelGeneration: cancelActiveBuild });\n }, [cancelActiveBuild, setOutput]);\n\n // Get or create a document version number\n const getDocumentVersion = useCallback((docName: string) => {\n const currentVersion = documentVersionsRef.current.get(docName) || 0;\n const newVersion = currentVersion + 1;\n documentVersionsRef.current.set(docName, newVersion);\n return newVersion;\n }, []);\n\n // Prepare valid custom themes with deep comparison\n const customThemesContentHash = useMemo(() => {\n // Create a content hash of all themes to detect deep changes\n const themeData = Object.entries(customThemes).map(([key, theme]) => {\n // Handle lastModified that might be a string (from localStorage) or Date\n let lastModifiedTime = 0;\n if (theme.lastModified) {\n if (theme.lastModified instanceof Date) {\n lastModifiedTime = theme.lastModified.getTime();\n } else if (typeof theme.lastModified === 'string') {\n lastModifiedTime = new Date(theme.lastModified).getTime();\n }\n }\n\n return {\n key,\n name: theme.name,\n content: theme.content,\n valid: theme.valid,\n lastModified: lastModifiedTime,\n };\n });\n return JSON.stringify(themeData);\n }, [customThemes]);\n\n const validCustomThemes = useMemo(() => {\n const themes: { [key: string]: any } = {};\n Object.values(customThemes).forEach((theme) => {\n if (theme.valid && theme.parsed) {\n themes[theme.name] = theme.parsed;\n }\n });\n return themes;\n }, [customThemesContentHash]);\n\n // Helper function to get fresh theme data (bypasses memo)\n const getFreshThemeData = useCallback(() => {\n const freshThemes: { [key: string]: any } = {};\n const { customThemes } = themesStore.getState();\n Object.values(customThemes).forEach((theme) => {\n if (theme.valid && theme.parsed) {\n freshThemes[theme.name] = theme.parsed;\n }\n });\n return freshThemes;\n }, [themesStore]);\n\n // Helper function to build a document with proper cancellation and retry\n const buildDocument = useCallback(\n async (\n doc: any,\n signal?: AbortSignal,\n options?: { bypassCache?: boolean }\n ) => {\n if (!doc || !generatePresentation) {\n return;\n }\n\n // Cancel any existing build operation for this document\n const existingController = buildAbortControllersRef.current.get(doc.name);\n if (existingController) {\n existingController.abort();\n buildAbortControllersRef.current.delete(doc.name);\n }\n\n // Create new abort controller if not provided\n const abortController = signal ? null : new AbortController();\n const finalSignal = signal || abortController!.signal;\n if (abortController) {\n buildAbortControllersRef.current.set(doc.name, abortController);\n }\n\n // Create build request\n const requestId = `${doc.name}-${Date.now()}-${Math.random()}`;\n const version = getDocumentVersion(doc.name);\n lastBuildRequestIdRef.current = requestId;\n\n const buildRequest: BuildRequest = {\n id: requestId,\n docName: doc.name,\n doc,\n signal: finalSignal,\n timestamp: Date.now(),\n // Claimed now, not on completion: a long build must not overwrite the\n // live analysis of an edit made while it was running.\n qualityTicket: nextQualityTicket(),\n };\n\n await processBuildRequestRef.current(buildRequest, version, options);\n },\n [generatePresentation, setOutput, getDocumentVersion]\n );\n\n // Process a build request from the queue\n const processBuildRequest = useCallback(\n async (\n request: BuildRequest,\n version: number,\n options?: { bypassCache?: boolean }\n ) => {\n const { doc, signal, id, qualityTicket } = request;\n // A build's findings describe the text it was handed. Anything newer in\n // the store was computed against text the editor actually holds now.\n const qualityIfCurrent = (next: QualityState) =>\n isStaleQualityTicket(outputStore.getState().quality, qualityTicket)\n ? {}\n : { quality: next };\n\n // Check if this is still the latest request\n if (lastBuildRequestIdRef.current !== id) {\n console.log('Skipping outdated build request for:', doc.name);\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n return;\n }\n\n setOutput({\n globalError: undefined,\n isGenerating: true,\n generationStartedAt: Date.now(),\n generationProgress: {\n stage: 'parsing',\n message: 'Validating JSON structure...',\n },\n });\n\n const onProgress = (\n stage: 'parsing' | 'building' | 'rendering' | 'finalizing',\n message?: string\n ) => {\n if (signal.aborted || lastBuildRequestIdRef.current !== id) return;\n\n // Check document version to ensure we're still building the latest\n const currentVersion = documentVersionsRef.current.get(doc.name) || 0;\n if (currentVersion !== version) {\n console.log('Document version changed, aborting build');\n signal.dispatchEvent(new Event('abort'));\n return;\n }\n\n setOutput({\n isGenerating: true,\n generationProgress: { stage, message },\n });\n };\n\n try {\n // Always get fresh theme data to ensure latest changes are applied\n const freshThemeData = getFreshThemeData();\n\n console.log('Editor: Using themes for document build', {\n docName: doc.name,\n freshThemeCount: Object.keys(freshThemeData).length,\n freshThemeNames: Object.keys(freshThemeData),\n memoizedCount: Object.keys(validCustomThemes).length,\n requestId: id,\n });\n\n // Browser plugins are expanded here, before the document leaves the\n // page: the server only ever sees standard components. Outside the\n // retry below, because a plugin that throws will throw again.\n onProgress('parsing', 'Expanding plugins...');\n const expansion = await expandForServer(doc.text, {\n customThemes: freshThemeData,\n signal,\n });\n // A document build supersedes a theme sample as the thing Run refreshes.\n if (!isSampleOutputName(doc.name)) lastSampleRef.current = null;\n if (signal.aborted || lastBuildRequestIdRef.current !== id) {\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n return;\n }\n\n // Retry logic for temporary failures\n const result = await retry(\n async () => {\n if (signal.aborted) throw new Error('Build cancelled');\n return await generatePresentation(\n doc.name,\n expansion.text,\n freshThemeData,\n onProgress,\n {\n ...options,\n ...(qualityOptions ? { quality: qualityOptions } : {}),\n }\n );\n },\n {\n maxRetries: 2,\n initialDelay: 500,\n shouldRetry: (error) => {\n // Don't retry on cancellation or syntax errors\n if (\n error.message.includes('cancelled') ||\n error.message.includes('JSON') ||\n error.message.includes('parse') ||\n error.message.includes('syntax')\n ) {\n return false;\n }\n // Retry on worker errors\n return RetryStrategies.combine(\n RetryStrategies.temporaryErrors,\n (e) =>\n e.message.includes('Worker') || e.message.includes('Proxy')\n )(error);\n },\n onRetry: (error, attempt) => {\n console.log(\n `Retrying presentation generation (attempt ${attempt}):`,\n error.message\n );\n setOutput({\n isGenerating: true,\n generationProgress: {\n stage: 'parsing',\n message: `Retrying generation (attempt ${attempt})...`,\n },\n });\n },\n signal,\n }\n );\n\n if (signal.aborted || lastBuildRequestIdRef.current !== id) {\n console.log('Build cancelled for:', doc.name);\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n return;\n }\n\n if (\n result &&\n typeof result === 'object' &&\n 'name' in result &&\n 'text' in result &&\n 'blob' in result\n ) {\n console.log('Editor: Build completed', {\n docName: result.name,\n blobSize: (result.blob as Blob)?.size,\n timestamp: Date.now(),\n requestId: id,\n version,\n });\n\n // Quality findings arrive flattened into the same warnings array\n // as component warnings. Left there they are counted as warnings\n // whatever their real severity, which is how a stock deck's two\n // hundred advisory infos became a warning-coloured bar.\n const { findings, others } = splitQualityWarnings(\n (result as any).warnings as\n | GenerationWarningLike[]\n | null\n | undefined\n );\n\n setOutput({\n name: result.name as string,\n text: result.text as string,\n blob: result.blob as Blob,\n renderer: result.renderer as string | undefined,\n globalError: undefined,\n isGenerating: false,\n isPreviewStale: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n lastBuiltSequence: outputStore.getState().editSequence,\n cacheStatus: (result as any).cacheStatus as\n | 'HIT'\n | 'MISS'\n | 'UNKNOWN'\n | undefined,\n cacheHitRate: (result as any).cacheHitRate as string | undefined,\n // Plugin warnings first: they were raised by the author's own code\n // and read above whatever the renderer then had to say.\n warnings: [...expansion.warnings, ...others] as GenerationWarning[],\n ...qualityIfCurrent({\n findings,\n counts: countBySeverity(findings),\n // The generate response does not name the profile it ran, so\n // only an explicit choice is reported; a blank label is honest\n // about the server having picked the format's default.\n ...(qualityProfileId ? { profileId: qualityProfileId } : {}),\n documentName: doc.name,\n seq: qualityTicket,\n source: 'generate',\n analyzedAt: Date.now(),\n }),\n });\n setBuildError(result.name as string, undefined);\n }\n } catch (error) {\n if (signal.aborted || lastBuildRequestIdRef.current !== id) {\n console.log('Build cancelled with error for:', doc.name);\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n return;\n }\n\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n // A gate rejection is the only failure that says something about the\n // document rather than about the request, and it ships the findings\n // that caused it — so the panel names them instead of leaving the\n // author with \"blocked\" and nothing to act on.\n const gateFindings =\n error instanceof QualityGateFailedError\n ? findingsFromAnalysis(error.quality)\n : null;\n\n setOutput({\n globalError: errorMessage,\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n ...(gateFindings\n ? qualityIfCurrent({\n findings: gateFindings,\n counts: countBySeverity(gateFindings),\n ...(qualityProfileId ? { profileId: qualityProfileId } : {}),\n documentName: doc.name,\n seq: qualityTicket,\n blocked: true,\n source: 'generate' as const,\n analyzedAt: Date.now(),\n gateError: errorMessage,\n })\n : {}),\n });\n\n setBuildError(doc.name, errorMessage);\n } finally {\n buildAbortControllersRef.current.delete(doc.name);\n }\n },\n [\n generatePresentation,\n getFreshThemeData,\n qualityOptions,\n qualityProfileId,\n setOutput,\n setBuildError,\n outputStore,\n ]\n );\n const processBuildRequestRef = useRef(processBuildRequest);\n useEffect(() => {\n processBuildRequestRef.current = processBuildRequest;\n });\n\n // Track the last viewed document for theme updates\n const lastViewedDocumentRef = useRef<string | null>(null);\n // The theme whose sample is on screen, if a sample is what was last built.\n const lastSampleRef = useRef<{ themeDocName: string } | null>(null);\n\n // re-build on active tab change or any document change\n useEffect(() => {\n console.log('Editor: Document rebuild effect triggered', {\n activeTab,\n });\n\n const activeFile = documents.find((doc) => doc.name === activeTab);\n const docType = documentTypes[activeTab] || 'application/json+report';\n\n // Track last viewed document\n if (docType === 'application/json+report' && activeFile) {\n lastViewedDocumentRef.current = activeTab;\n }\n\n // Clear any pending build timeout for this document\n const existingTimeout = buildTimeoutsRef.current.get(activeTab);\n if (existingTimeout) {\n clearTimeout(existingTimeout);\n buildTimeoutsRef.current.delete(activeTab);\n }\n\n if (activeFile && docType === 'application/json+report') {\n // Editing marks the preview stale rather than rebuilding: a build costs\n // a LibreOffice conversion, so it waits for Run. Do not clobber a build\n // already in flight (e.g. one the Run button started).\n if (!outputStore.getState().isGenerating) {\n setOutput({ isPreviewStale: true });\n }\n } else if (activeFile && docType !== 'application/json+report') {\n // Theme or plugin tab active — no document preview to build.\n // Don't clear blob: preserve the last document preview in the background.\n cancelGeneration();\n }\n\n // Cleanup function to cancel pending operations\n return () => {\n const timeout = buildTimeoutsRef.current.get(activeTab);\n if (timeout) {\n clearTimeout(timeout);\n buildTimeoutsRef.current.delete(activeTab);\n }\n };\n }, [\n documents,\n activeTab,\n setOutput,\n documentTypes,\n buildDocument,\n cancelGeneration,\n ]);\n\n // Refresh the quality findings as the document settles, so the panel tracks\n // the editor instead of only the last build. `analyze` debounces and aborts\n // its own in-flight request, so a stale analysis can never land on top of a\n // newer one; returning `cancel` drops the pending work on unmount and on a\n // document switch.\n useEffect(() => {\n const activeFile = documents.find((doc) => doc.name === activeTab);\n const docType = documentTypes[activeTab] || 'application/json+report';\n if (!activeFile || docType !== 'application/json+report') {\n // A theme has no document findings of its own, and an analysis started\n // for the previous tab would report them under this one. Clearing rather\n // than only cancelling matters because nothing else ever will: without\n // it the previous document's findings stay on screen, and actionable,\n // for as long as a theme tab is open.\n cancelQualityAnalysis();\n setOutput({ quality: null });\n return;\n }\n analyzeQuality(activeTab, activeFile.text);\n return cancelQualityAnalysis;\n }, [\n activeTab,\n analyzeQuality,\n cancelQualityAnalysis,\n documents,\n documentTypes,\n setOutput,\n ]);\n\n // Track which documents use which themes (only parse the active doc to avoid O(n) JSON.parse)\n const documentThemeDependencies = useMemo(() => {\n const deps = new Map<string, string>();\n const activeDoc = documents.find((d) => d.name === activeTab);\n if (\n activeDoc &&\n documentTypes[activeDoc.name] === 'application/json+report'\n ) {\n try {\n const parsed = JSON.parse(activeDoc.text);\n const themeName = parsed.props?.theme;\n if (typeof themeName === 'string') {\n const themeExists = Object.values(customThemes).some(\n (t) => t.name === themeName && t.valid\n );\n if (themeExists) {\n deps.set(activeDoc.name, themeName);\n }\n }\n } catch {\n // Ignore parse errors\n }\n }\n return deps;\n }, [activeTab, documents, documentTypes, customThemes]);\n\n // Listen for theme change events and force immediate rebuild\n useEffect(() => {\n console.log('Editor: Setting up theme change listener', {\n documentCount: documents.length,\n dependencyCount: documentThemeDependencies.size,\n dependencies: Array.from(documentThemeDependencies.entries()),\n customThemes: Object.entries(customThemes).map(([key, theme]) => ({\n key,\n name: theme.name,\n valid: theme.valid,\n })),\n });\n\n const unsubscribe = themeChangeEmitter.onThemeChange((event) => {\n console.log('Editor: Theme change detected', {\n event,\n dependencies: Array.from(documentThemeDependencies.entries()),\n activeTab,\n customThemes: Object.entries(customThemes).map(([key, theme]) => ({\n key,\n name: theme.name,\n valid: theme.valid,\n })),\n });\n\n // Find all documents that use this theme\n const documentsUsingTheme: any[] = [];\n\n documentThemeDependencies.forEach((themeName, docName) => {\n if (themeName === event.themeName) {\n const doc = documents.find((d) => d.name === docName);\n if (doc) {\n documentsUsingTheme.push(doc);\n }\n }\n });\n\n console.log('Editor: Documents using changed theme', {\n themeName: event.themeName,\n documentCount: documentsUsingTheme.length,\n documentNames: documentsUsingTheme.map((d) => d.name),\n });\n\n if (documentsUsingTheme.length === 0) {\n console.log('Editor: No documents use this theme, skipping rebuild');\n return;\n }\n\n // A theme change invalidates the preview of every document using it;\n // rebuilding is the author’s call, as it is for a document edit.\n if (!outputStore.getState().isGenerating) {\n setOutput({ isPreviewStale: true });\n }\n });\n\n return unsubscribe;\n }, [\n documentThemeDependencies,\n documents,\n buildDocument,\n getDocumentVersion,\n activeTab,\n setOutput,\n ]);\n\n // Flush debounces and immediately build — triggered by Run button via custom event\n // Debounced at 150ms to coalesce rapid clicks\n // Stable refs so the event handler never goes stale and doesn't need\n // reactive deps that would cause cleanup to cancel the pending timeout\n const buildDocumentRef = useRef(buildDocument);\n useEffect(() => {\n buildDocumentRef.current = buildDocument;\n });\n const getDocumentVersionRef = useRef(getDocumentVersion);\n useEffect(() => {\n getDocumentVersionRef.current = getDocumentVersion;\n });\n\n useEffect(() => {\n const handler = () => {\n // Mark generating early so the rebuild effect (triggered by saveDocument\n // below) doesn't clobber this build with isPreviewStale\n setOutput({ isGenerating: true });\n\n // 1. Flush Monaco debounce: read live text, save to store immediately\n let themeDirty = false;\n const editorRef = useEditorRefsStore.getState().getActiveEditor();\n if (editorRef) {\n // Don't flush if a pending diff is active — editor may be disposed\n const hasPendingDiff =\n documentsStore.getState().pendingDiffs[editorRef.documentName];\n if (!hasPendingDiff) {\n const liveText = editorRef.toStorageValue(\n editorRef.editor.getValue()\n );\n documentsStore\n .getState()\n .saveDocument(editorRef.documentName, liveText);\n }\n }\n\n // Flush all open theme editors whose live text differs from the\n // themes store so the build always uses up-to-date theme data.\n const { documents: allDocs, documentTypes: allDtypes } =\n documentsStore.getState();\n for (const doc of allDocs) {\n if (allDtypes[doc.name] === 'application/json+theme') {\n const ref = useEditorRefsStore.getState().getEditor(doc.name);\n if (ref) {\n const liveText = ref.toStorageValue(ref.editor.getValue());\n const existing = themesStore.getState().customThemes[doc.name];\n if (!existing || existing.content !== liveText) {\n themesStore.getState().updateTheme(doc.name, liveText);\n themeDirty = true;\n }\n }\n } else if (allDtypes[doc.name] === 'application/typescript+plugin') {\n // A plugin edited a moment ago is still behind its save debounce\n // and its compile debounce; the build must see what is on screen.\n const ref = useEditorRefsStore.getState().getEditor(doc.name);\n if (ref) {\n ref.flushPendingSave?.();\n const liveText = ref.toStorageValue(ref.editor.getValue());\n if (liveText !== doc.text) {\n documentsStore.getState().saveDocument(doc.name, liveText);\n }\n }\n }\n }\n // Whatever compile the edits above queued starts now rather than after\n // its debounce; the build below waits for the queue to drain.\n compileQueue.flush();\n\n // 2. Cancel any pending build timeout for active doc\n const currentTab = documentsStore.getState().activeTab;\n const timeout = buildTimeoutsRef.current.get(currentTab);\n if (timeout) {\n clearTimeout(timeout);\n buildTimeoutsRef.current.delete(currentTab);\n }\n\n // 3. Debounce the actual build to coalesce rapid Run clicks\n if (flushBuildTimerRef.current) {\n clearTimeout(flushBuildTimerRef.current);\n }\n flushBuildTimerRef.current = setTimeout(async () => {\n flushBuildTimerRef.current = null;\n // Plugins that were just edited are compiling; a build that ran now\n // would expand with the previous compiled code.\n await compileQueue.whenIdle();\n const {\n documents: docs,\n activeTab: tab,\n documentTypes: dtypes,\n } = documentsStore.getState();\n\n // Determine target: if active tab is a theme or a plugin, build the\n // last-viewed document instead — unless what is on screen is this\n // theme's sample, in which case Run refreshes the sample.\n let targetName = tab;\n const tabType = dtypes[tab] || 'application/json+report';\n if (tabType !== 'application/json+report') {\n const sample = lastSampleRef.current;\n if (\n sample &&\n tabType === 'application/json+theme' &&\n sample.themeDocName === tab\n ) {\n buildSampleRef.current(tab);\n return;\n }\n if (lastViewedDocumentRef.current) {\n targetName = lastViewedDocumentRef.current;\n } else {\n // No document was viewed yet — nothing to build\n setOutput({ isGenerating: false });\n return;\n }\n }\n\n const freshDoc = docs.find((d) => d.name === targetName);\n if (freshDoc) {\n // If a pending diff exists (AI suggestion), preview the modified version\n const pending = documentsStore.getState().pendingDiffs[targetName];\n const ref = useEditorRefsStore.getState().getEditor(targetName);\n const doc = pending\n ? { ...freshDoc, text: pending.modified }\n : ref\n ? { ...freshDoc, text: ref.toStorageValue(ref.editor.getValue()) }\n : freshDoc;\n getDocumentVersionRef.current(doc.name);\n // Bypass cache only when a theme was updated during this flush\n buildDocumentRef.current(\n doc,\n undefined,\n themeDirty ? { bypassCache: true } : undefined\n );\n } else {\n setOutput({ isGenerating: false });\n }\n }, 150);\n };\n\n window.addEventListener('preview:flushAndBuild', handler);\n return () => {\n window.removeEventListener('preview:flushAndBuild', handler);\n if (flushBuildTimerRef.current) {\n clearTimeout(flushBuildTimerRef.current);\n }\n };\n }, [setOutput, documentsStore, themesStore]);\n\n // A theme's sample: a document the theme editor builds on demand rather\n // than a file in the workspace. Same build path as Run, cache bypassed since\n // the theme it names was just edited. The sample is remembered per theme\n // file so a later Run on that tab refreshes it instead of swapping the\n // preview back to the last document.\n const buildSample = useCallback(\n (themeDocName: string) => {\n const { documents: docs } = documentsStore.getState();\n const themeDoc = docs.find((d) => d.name === themeDocName);\n if (!themeDoc) {\n setOutput({ isGenerating: false });\n return;\n }\n let parsed: Record<string, unknown> | undefined;\n let themeName: string | null = null;\n let parseError: string | null = null;\n try {\n parsed = JSON.parse(themeDoc.text);\n themeName = getThemeName(parsed);\n } catch (error) {\n // A syntax error and a missing name are different repairs; saying\n // \"no name\" against broken JSON sends the author to the wrong line.\n parseError = error instanceof Error ? error.message : 'Invalid JSON';\n }\n if (!themeName) {\n setOutput({\n isGenerating: false,\n globalError: parseError\n ? `The theme is not valid JSON: ${parseError}`\n : 'The theme has no name',\n });\n return;\n }\n const name = sampleOutputName(themeName);\n const text = JSON.stringify(\n buildThemeSpecimen(FORMAT, themeName, parsed),\n null,\n 2\n );\n lastSampleRef.current = { themeDocName };\n setOutput({ isGenerating: true });\n getDocumentVersionRef.current(name);\n buildDocumentRef.current({ name, text }, undefined, {\n bypassCache: true,\n });\n },\n [documentsStore, setOutput]\n );\n const buildSampleRef = useRef(buildSample);\n useEffect(() => {\n buildSampleRef.current = buildSample;\n });\n\n useEffect(() => {\n const handler = (event: Event) => {\n const detail = (event as CustomEvent<{ themeDocName?: string }>).detail;\n if (!detail?.themeDocName) return;\n buildSampleRef.current(detail.themeDocName);\n };\n window.addEventListener('preview:buildSpecimen', handler);\n return () => window.removeEventListener('preview:buildSpecimen', handler);\n }, []);\n\n // A plugin that recompiled may change what the previewed document renders\n // to; like a theme edit, that is the author's cue to Run again.\n useEffect(() => {\n const handler = () => {\n if (!outputStore.getState().isGenerating) {\n setOutput({ isPreviewStale: true });\n }\n };\n window.addEventListener(BROWSER_PLUGINS_CHANGED_EVENT, handler);\n return () =>\n window.removeEventListener(BROWSER_PLUGINS_CHANGED_EVENT, handler);\n }, [outputStore, setOutput]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n // Cancel all pending builds\n buildAbortControllersRef.current.forEach((controller) =>\n controller.abort()\n );\n buildAbortControllersRef.current.clear();\n\n // Clear all timeouts\n buildTimeoutsRef.current.forEach((timeout) => clearTimeout(timeout));\n buildTimeoutsRef.current.clear();\n\n // Cancel any ongoing generation\n cancelGeneration();\n };\n }, [cancelGeneration]);\n\n if (!openTabs.length) {\n return (\n <div className=\"flex flex-col text-muted-foreground h-full items-center justify-center\">\n {!documents?.length ? 'Create a new document...' : 'Open a document...'}\n </div>\n );\n }\n\n return (\n <Tabs value={activeTab} onValueChange={setActiveTab} className=\"h-full\">\n {/* Tabs header removed to gain vertical space */}\n <EditorTabsContentMemoized\n openTabs={openTabs}\n documents={documents}\n buildErrors={buildErrors}\n saveDocumentDebounceWait={saveDocumentDebounceWait}\n />\n </Tabs>\n );\n}\n\n// Export memoized version of Editor component\nexport const Editor = memo(EditorComponent);\n"],"names":["validators","monaco","dummyDiv","dummyEditorInstance","editorInstanceConstructorName","editorModelConstructorName","valueToValidate","ranges","rangeObj","num","TypeMustBe","type","key","additional","deepClone","byPassPrimitives","value","callback","cloneArray","array","keys","arrayClone","i","cloner","object","clone","config","constructOptionForCode","options","acc","option","codes","methods","API","methodName","enums","constrainedModel","model","rangeConstructor","sortRangesInAscendingOrder","rangeObject1","rangeObject2","rangeA","rangeB","normalizeRange","range","content","lines","noOfLines","normalizedRange","index","actualStartCol","startLineNo","maxCols","actualEndLine","actualEndCol","endLineNo","restrictions","prepareRestrictions","restriction","startLine","startCol","endLine","endCol","getCurrentEditableRanges","getValueInEditableRanges","updateValueInEditableRanges","forceMoveMarkers","restrictionsMap","label","doesChangeHasMultilineConflict","newRange","isChangeInvalidAsPerUser","disposeRestrictions","handleUnhandledPromiseRejection","isCursorAtCheckPoint","positions","position","posLineNumber","posCol","length","addEditableRangeListener","triggerChangeListenersWith","currentChanges","allChanges","currentRanges","doUndo","updateRange","finalLine","finalColumn","changes","changeIndex","oldRangeEndLineNumber","oldRangeEndColumn","changesLength","diffInCol","diffInRow","cursorPositions","noOfCursorPositions","change","cursorPosition","nextRestriction","nextRange","nextChange","rangeInChange","rangeAsString","rangeMapValue","getInfoFrom","editableRange","info","updateRestrictions","toggleHighlightOfEditableAreas","cssClasses","cssClassForSingleLine","cssClassForMultiLine","decorations","decoration","setAllRangesToPrev","rangeMap","text","manipulatorApi","contentChangedEvent","isUndoing","editedRange","changedRange","noOfLinesAdded","noOfColsAddedAtLastLine","lineDiffInRange","colDiffInRange","columnsCarriedToEnd","values","currentlyEditedRanges","rangeString","exposedApi","funcName","apiName","constrainedEditor","listenerFn","editorInstance","selections","selection","_uriRestrictionMap","isInstanceValid","isModelValid","isRangesValid","initInEditorInstance","domNode","manipulator","newDomNode","addRestrictionsTo","modelToConstrain","removeRestrictionsIn","uri","restrictedModel","disposeConstrainer","toggleDevMode","editor","startLineNumber","endLineNumber","startColumn","endColumn","exposedMethods","resolveThemeDefaultPath","name","ext","FORMAT","EditorMonacoTheme","document","readOnly","onChange","editorRef","useRef","monacoRef","modelRef","theme","useTheme","validationErrors","setValidationErrors","useState","showValidationPanel","setShowValidationPanel","isValidationPanelMinimized","setIsValidationPanelMinimized","userDismissedRef","pendingDiff","useDocumentsStore","s","clearPendingDiff","saveDocument","registerEditor","unregisterEditor","setActiveEditor","useEditorRefsStore","resolvedTheme","handleEditorWillMount","useCallback","registerMonacoThemes","handleEditorMount","constrainedInstance","getSelectionContext","snippet","createContextSnippet","_a","useEffect","handleChange","_event","handleEditorValidation","markers","errors","marker","handleErrorClick","error","monacoThemeFor","jsxs","Fragment","jsx","Button","DiffEditor","MonacoEditor","ValidationStatusBar","ValidationPanel","EditorMonacoThemeMemoized","React","humanize","spaced","COLOR_PATTERN","enumOptions","schema","v","branches","b","scalarKind","schemaField","path","required","base","scalar","field","integer","step","min","max","requiredKeys","child","sub","SECTION_TITLES","extendedSections","handledKeys","handled","matchesQuery","query","terms","needle","term","filterFields","fields","out","own","children","fieldValueError","resolveThemeColor","direct","resolveColor","palette","entry","isHexColor","summarizeValue","_cachedSchema","fetchThemeJsonSchema","json","Popover","PopoverPrimitive.Root","PopoverTrigger","PopoverPrimitive.Trigger","PopoverContent","React.forwardRef","className","align","sideOffset","props","ref","PopoverPrimitive.Portal","PopoverPrimitive.Content","cn","hexToRgb","hex","match","int","rgbToHex","r","g","channel","rgbToHsv","red","green","blue","span","h","hsvToRgb","hue","c","x","m","hexToHsv","rgb","hsvToHex","hsv","readableInk","TOKEN_NAME","PLACEHOLDER_HEX","useFrameCommit","commit","pending","frame","latest","flush","schedule","finish","useDragArea","onMove","onEnd","report","event","box","y","onPointerDown","onPointerMove","onPointerUp","SaturationArea","move","drag","delta","next","HUE_GRADIENT","HueRail","TokenChips","tokens","active","onPick","token","selected","Tooltip","TooltipTrigger","Check","TooltipContent","ColorControl","id","resolved","onCommit","allowReference","open","setOpen","commitText","draft","trimmed","normalizeHex","useDraft","swatch","reference","ColorPickerBody","Input","INPUT_CLASS","onDone","setHsv","seeded","commitHex","eyedropper","EyeDropperCtor","picked","normalized","PickerHexInput","Pipette","X","useThemeColorTokens","useMemo","colors","themeColorTokens","TOKENS","colorTokens","GROUPS","t","rowState","raw","ColorRow","set","remove","useThemeEditor","clear","inputId","HINT_CLASS","CornerDownRight","ClearButton","ThemeColorsSection","searching","rows","contrast","background","primary","contrastRatio","defined","EditorSection","ContrastBadge","group","row","GroupLabel","MAX_ROWS","buildOptions","catalog","family","font","score","lower","filterOptions","current","known","rest","scored","rank","a","FamilyCombobox","pickerPath","setQuery","setActive","listRef","useFontCatalog","matches","typed","exact","custom","choose","browse","useFontPickerStore","onKeyDown","last","clamped","_b","Type","ChevronsUpDown","Search","Row","QuietButton","tag","onHover","asString","asNumber","DocxRoleCard","role","size","commitFamily","commitSize","familyId","sizeId","FONT_ROLE_HINTS","FIELD_LABEL_CLASS","DraftNumberInput","PptxFamilyRow","PptxDefaults","fontSize","getAt","fontColor","commitColor","ThemeTypographySection","whole","roleMatches","forceOpen","roles","DOCX_FONT_ROLES","record","PPTX_FONT_ROLES","showDefaults","CUSTOM","UNITS","STEP","MARGIN_PATHS","MARGIN_KEYS","WIDTH_PATH","HEIGHT_PATH","twips","LengthField","unit","unitToTwips","twipsToUnit","ThemePageSection","PAGE_SIZES","setUnit","isCustom","sizeValue","onSizeChange","Select","SelectTrigger","SelectValue","SelectContent","u","SelectItem","SELECT_TRIGGER_CLASS","NAMES","styleNames","FIELDS","styleFields","BASIC","f","ADVANCED","STYLE_DEPTH","BOOLEAN_OPTIONS","fieldKey","summarize","style","parts","push","ColorField","styleName","StyleField","commitString","commitNumber","isSet","control","DraftTextInput","Segmented","StyleRow","styleJson","tokensJson","resolvedJson","more","setMore","define","removeStyle","styleLabel","setCount","renderField","o","ChevronRight","Trash2","Plus","AddCustomStyle","existing","setName","problem","submit","e","ThemeStylesSection","customStyleNames","styles","table","colorFields","all","definedCount","UNSET","fieldId","SECTION_DEPTH","ScalarControl","onOpenJson","JsonOnly","summary","onClear","Braces","ListControl","entries","item","add","seed","full","entryField","ListEntry","_","onRemove","FieldRow","clearable","GroupRows","depth","Rows","ThemeSchemaSection","section","useExtendedSections","sections","setSections","cancelled","formKeys","ThemeVisualEditor","docName","usedBy","nameClash","parsed","parseTheme","update","fn","serializeTheme","head","container","ensureContainers","setAt","prune","deleteAt","parent","actions","ThemeEditorProvider","ThemeForm","useScrollCrumb","barRef","crumb","setCrumb","bar","viewport","measure","line","chain","element","previous","observer","extended","extendedKeys","ScrollArea","IdentitySection","AdvancedSection","IDENTITY_FIELDS","IdentityField","hint","alsoHandled","advancedKeys","ThemeEditorHost","preferred","useSettingsStore","setSettings","hasPendingDiff","themeName","getThemeName","EMPTY","names","d","documentThemeName","themeFileName","view","themeView","openJson","NONE","ThemeEditorHostMemoized","usePluginTypesReady","ready","setReady","pluginTypeScriptReady","onPluginTypeScriptReady","PluginEditorStrip","useBrowserPluginsStore","setEnabled","setAllowNetwork","setNetworkOrigins","toast","useToast","copiedIndex","setCopiedIndex","typesReady","metadata","status","errorCount","displayName","PLUGIN_FILE_SUFFIX","examples","announce","BROWSER_PLUGINS_CHANGED_EVENT","toggleEnabled","enabled","recompileUnderNewPolicy","pluginHost","compileQueue","toggleNetwork","allowNetwork","commitOrigins","origins","copyExample","example","usage","statusChip","Spinner","Puzzle","Badge","Info","DropdownMenu","DropdownMenuTrigger","BookOpen","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuItem","Copy","Switch","NetworkControl","download","DownloadIcon","PluginEditorStripMemoized","onToggle","onCommitOrigins","setDraft","parseNetworkOrigins","granted","Globe","Textarea","EditorMonacoPlugin","saveDocumentDebounceWait","closeDocument","diagnostics","lastSavedRef","editorValue","setEditorValue","debouncedSaveRef","debounce","showPanel","setShowPanel","panelMinimized","setPanelMinimized","handleWillMount","ensurePluginTypeScript","flushPendingSave","handleMount","saveNow","debouncedSave","Editor","pluginModelPath","EditorMonacoPluginMemoized","TabContent","_buildError","documentType","state","updateTheme","useThemesStore","debouncedUpdateTheme","TabsContent","EditorMonacoJsonMemoized","TabContentMemoized","EditorTabsContent","openTabs","documents","buildErrors","documentTypes","doc","EditorTabsContentMemoized","RetryError","message","lastError","attempts","retry","maxRetries","initialDelay","maxDelay","backoffFactor","onRetry","shouldRetry","signal","attempt","jitteredDelay","resolve","timeoutId","RetryStrategies","pattern","statusCodes","strategies","strategy","BODY_TEXT","TOKEN_ROLES","swatchTokens","definedColorKeys","hasStyle","docxSpecimen","pptxSpecimen","w","slides","swatches","column","sampleOutputName","isSampleOutputName","buildThemeSpecimen","format","EditorComponent","setOutput","useOutputStore","outputStore","useContext","OutputStoreContext","documentsStore","DocumentsStoreContext","themesStore","ThemesStoreContext","activeTab","setActiveTab","setBuildError","useShallow","customThemes","generatePresentation","cancelGeneration","usePresentationGenerator","qualityProfileIds","qualityProfileId","storedProfileId","qualityGate","qualityPolicyText","qualityOptions","buildQualityOptions","analyzeQuality","cancelQualityAnalysis","useQualityAnalysis","buildAbortControllersRef","buildTimeoutsRef","flushBuildTimerRef","lastBuildRequestIdRef","documentVersionsRef","cancelActiveBuild","timeout","controller","getDocumentVersion","newVersion","customThemesContentHash","themeData","lastModifiedTime","validCustomThemes","themes","getFreshThemeData","freshThemes","buildDocument","existingController","abortController","finalSignal","requestId","version","buildRequest","nextQualityTicket","processBuildRequestRef","processBuildRequest","request","qualityTicket","qualityIfCurrent","isStaleQualityTicket","onProgress","stage","freshThemeData","expansion","expandForServer","result","findings","others","splitQualityWarnings","countBySeverity","errorMessage","gateFindings","QualityGateFailedError","findingsFromAnalysis","lastViewedDocumentRef","lastSampleRef","activeFile","docType","existingTimeout","documentThemeDependencies","deps","activeDoc","themeChangeEmitter","documentsUsingTheme","buildDocumentRef","getDocumentVersionRef","handler","themeDirty","liveText","allDocs","allDtypes","currentTab","docs","tab","dtypes","targetName","tabType","sample","buildSampleRef","freshDoc","buildSample","themeDocName","themeDoc","parseError","detail","Tabs","memo"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5]}
|
|
1
|
+
{"version":3,"file":"editor-RriNJVGd.js","sources":["../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/utils/validators.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/utils/definedErrors.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/utils/deepClone.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/utils/enums.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/constrainedModel.js","../../../../../node_modules/.pnpm/constrained-editor-plugin@1.4.0/node_modules/constrained-editor-plugin/dist/esm/constrainedEditor.js","../../../src/client/components/json-editor/editor-monaco-theme.tsx","../../../src/client/lib/theme-editor/schema-form.ts","../../../src/client/lib/theme-json-schema.ts","../../../src/client/components/ui/popover.tsx","../../../src/client/lib/theme-editor/color.ts","../../../src/client/components/theme-editor/color-picker.tsx","../../../src/client/components/theme-editor/theme-colors-section.tsx","../../../src/client/components/theme-editor/font-combobox.tsx","../../../src/client/components/theme-editor/theme-typography-section.tsx","../../../src/client/components/theme-editor/theme-page-section.tsx","../../../src/client/components/theme-editor/theme-styles-section.tsx","../../../src/client/components/theme-editor/theme-schema-section.tsx","../../../src/client/components/theme-editor/theme-visual-editor.tsx","../../../src/client/components/theme-editor/theme-editor-host.tsx","../../../src/client/components/plugin-editor/plugin-editor-strip.tsx","../../../src/client/components/plugin-editor/editor-monaco-plugin.tsx","../../../src/client/components/playground/editor-tabs-content.tsx","../../../src/client/utils/retry.ts","../../../src/client/lib/theme-editor/specimen.ts","../../../src/client/components/playground/editor.tsx"],"sourcesContent":["const validators = {\n initWith: function (monaco) {\n const dummyDiv = document.createElement('div');\n const dummyEditorInstance = monaco.editor.create(dummyDiv);\n const editorInstanceConstructorName = dummyEditorInstance.constructor.name;\n const editorModelConstructorName = dummyEditorInstance.getModel().constructor.name;\n const instanceCheck = function (valueToValidate) {\n return valueToValidate.constructor.name === editorInstanceConstructorName;\n }\n const modelCheck = function (valueToValidate) {\n return valueToValidate.constructor.name === editorModelConstructorName;\n }\n const rangesCheck = function (ranges) {\n if (Array.isArray(ranges)) {\n return ranges.every(function (rangeObj) {\n if (typeof rangeObj === 'object' && rangeObj.constructor.name === 'Object') {\n if (!rangeObj.hasOwnProperty('range')) return false;\n if (!Array.isArray(rangeObj.range)) return false;\n if (rangeObj.range.length !== 4) return false;\n if (!(rangeObj.range.every(num => num > 0 && parseInt(num) === num))) return false;\n if (rangeObj.hasOwnProperty('allowMultiline')) {\n if (typeof rangeObj.allowMultiline !== 'boolean') return false;\n }\n if (rangeObj.hasOwnProperty('label')) {\n if (typeof rangeObj.label !== 'string') return false;\n }\n if (rangeObj.hasOwnProperty('validate')) {\n if (typeof rangeObj.validate !== 'function') return false;\n }\n return true;\n }\n return false;\n });\n }\n return false;\n }\n return {\n isInstanceValid: instanceCheck,\n isModelValid: modelCheck,\n isRangesValid: rangesCheck\n }\n }\n}\nexport default validators;","export const TypeMustBe = function (type, key, additional) {\n return 'The value for the ' + key + ' should be of type ' + (Array.isArray(type) ? type.join(' | ') : type) + '. ' + (additional || '')\n}\nconst definedErrors = {\n TypeMustBe : TypeMustBe\n};\nexport default definedErrors;","export const deepClone = (function () {\n const byPassPrimitives = function (value, callback) {\n if (typeof value !== 'object' || value === null) {\n return this.freeze ? Object.freeze(value) : value;\n }\n if (value instanceof Date) {\n return this.freeze ? Object.freeze(new Date(value)) : new Date(value);\n }\n return callback.call(this, value);\n }\n const cloneArray = function (array, callback) {\n const keys = Object.keys(array);\n const arrayClone = new Array(keys.length)\n for (let i = 0; i < keys.length; i++) {\n arrayClone[keys[i]] = byPassPrimitives.call(this, array[keys[i]], callback);\n }\n return arrayClone;\n }\n const cloner = function (object) {\n return byPassPrimitives.call(this, object, function (object) {\n if (Array.isArray(object)) {\n return cloneArray.call(this, object, cloner)\n }\n const clone = {};\n for (let key in object) {\n if (!this.withProto && Object.hasOwnProperty.call(object, key) === false) {\n continue;\n }\n clone[key] = byPassPrimitives.call(this, object[key], cloner);\n }\n return clone;\n })\n }\n const config = (function () {\n const constructOptionForCode = function (value) {\n const options = [\n 'withProto',\n 'freeze'\n ]\n this[value] = options.reduce(function (acc, option) {\n if (acc[option] = (value >= this[option])) {\n value -= this[option]\n }\n return acc;\n }.bind(this), {})\n }\n const codes = Object.create(Object.defineProperties({}, {\n withProto: { value: 1 },\n freeze: { value: 2 }\n }));\n for (let i = 0; i <= 3; i++) {\n constructOptionForCode.call(codes, i);\n }\n return codes;\n }());\n const methods = {\n withProto: cloner.bind(config[1]),\n andFreeze: cloner.bind(config[2]),\n withProtoAndFreeze: cloner.bind(config[3])\n }\n const API = cloner.bind(config[0]);\n for (let methodName in methods) {\n Object.defineProperty(API, methodName, {\n enumerable: false,\n writable: false,\n configurable: false,\n value: methods[methodName]\n })\n }\n return API;\n}());\n\nexport default deepClone;","export const enums = {\n SINGLE_LINE_HIGHLIGHT_CLASS: 'editableArea--single-line',\n MULTI_LINE_HIGHLIGHT_CLASS: 'editableArea--multi-line'\n}\nexport default enums;","import deepClone from './utils/deepClone.js';\nimport enums from './utils/enums.js';\nexport const constrainedModel = function (model, ranges, monaco) {\n const rangeConstructor = monaco.Range;\n const sortRangesInAscendingOrder = function (rangeObject1, rangeObject2) {\n const rangeA = rangeObject1.range;\n const rangeB = rangeObject2.range;\n if (\n rangeA[0] < rangeB[0] ||\n (rangeA[0] === rangeB[0] && rangeA[3] < rangeB[1])\n ) {\n return -1;\n }\n }\n const normalizeRange = function (range, content) {\n const lines = content.split('\\n');\n const noOfLines = lines.length;\n const normalizedRange = [];\n range.forEach(function (value, index) {\n if (value === 0) {\n throw new Error('Range values cannot be zero');//No I18n\n }\n switch (index) {\n case 0: {\n if (value < 0) {\n throw new Error('Start Line of Range cannot be negative');//No I18n\n } else if (value > noOfLines) {\n throw new Error('Provided Start Line(' + value + ') is out of bounds. Max Lines in content is ' + noOfLines);//No I18n\n }\n normalizedRange[index] = value;\n }\n break;\n case 1: {\n let actualStartCol = value;\n const startLineNo = normalizedRange[0];\n const maxCols = lines[startLineNo - 1].length\n if (actualStartCol < 0) {\n actualStartCol = maxCols - Math.abs(actualStartCol);\n if (actualStartCol < 0) {\n throw new Error('Provided Start Column(' + value + ') is out of bounds. Max Column in line ' + startLineNo + ' is ' + maxCols);//No I18n\n }\n } else if (actualStartCol > (maxCols + 1)) {\n throw new Error('Provided Start Column(' + value + ') is out of bounds. Max Column in line ' + startLineNo + ' is ' + maxCols);//No I18n\n }\n normalizedRange[index] = actualStartCol;\n }\n break;\n case 2: {\n let actualEndLine = value;\n if (actualEndLine < 0) {\n actualEndLine = noOfLines - Math.abs(value);\n if (actualEndLine < 0) {\n throw new Error('Provided End Line(' + value + ') is out of bounds. Max Lines in content is ' + noOfLines);//No I18n\n }\n if (actualEndLine < normalizedRange[0]) {\n console.warn('Provided End Line(' + value + ') is less than the start Line, the Restriction may not behave as expected');//No I18n\n }\n } else if (value > noOfLines) {\n throw new Error('Provided End Line(' + value + ') is out of bounds. Max Lines in content is ' + noOfLines);//No I18n\n }\n normalizedRange[index] = actualEndLine;\n }\n break;\n case 3: {\n let actualEndCol = value;\n const endLineNo = normalizedRange[2];\n const maxCols = lines[endLineNo - 1].length\n if (actualEndCol < 0) {\n actualEndCol = maxCols - Math.abs(actualEndCol);\n if (actualEndCol < 0) {\n throw new Error('Provided End Column(' + value + ') is out of bounds. Max Column in line ' + endLineNo + ' is ' + maxCols);//No I18n\n }\n } else if (actualEndCol > (maxCols + 1)) {\n throw new Error('Provided Start Column(' + value + ') is out of bounds. Max Column in line ' + endLineNo + ' is ' + maxCols);//No I18n\n }\n normalizedRange[index] = actualEndCol;\n }\n break;\n }\n })\n return normalizedRange;\n }\n let restrictions = deepClone(ranges).sort(sortRangesInAscendingOrder);\n const prepareRestrictions = function (restrictions) {\n const content = model.getValue();\n restrictions.forEach(function (restriction, index) {\n const range = normalizeRange(restriction.range, content);\n const startLine = range[0];\n const startCol = range[1];\n const endLine = range[2];\n const endCol = range[3];\n restriction._originalRange = range.slice();\n restriction.range = new rangeConstructor(startLine, startCol, endLine, endCol);\n restriction.index = index;\n if (!restriction.allowMultiline) {\n restriction.allowMultiline = rangeConstructor.spansMultipleLines(restriction.range)\n }\n if (!restriction.label) {\n restriction.label = `[${startLine},${startCol} -> ${endLine}${endCol}]`;\n }\n });\n }\n const getCurrentEditableRanges = function () {\n return restrictions.reduce(function (acc, restriction) {\n acc[restriction.label] = {\n allowMultiline: restriction.allowMultiline || false,\n index: restriction.index,\n range: Object.assign({}, restriction.range),\n originalRange: restriction._originalRange.slice()\n };\n return acc;\n }, {});\n }\n const getValueInEditableRanges = function () {\n return restrictions.reduce(function (acc, restriction) {\n acc[restriction.label] = model.getValueInRange(restriction.range);\n return acc;\n }, {});\n }\n const updateValueInEditableRanges = function (object, forceMoveMarkers) {\n if (typeof object === 'object' && !Array.isArray(object)) {\n forceMoveMarkers = typeof forceMoveMarkers === 'boolean' ? forceMoveMarkers : false;\n const restrictionsMap = restrictions.reduce(function (acc, restriction) {\n if (restriction.label) {\n acc[restriction.label] = restriction;\n }\n return acc;\n }, {});\n for (let label in object) {\n const restriction = restrictionsMap[label];\n if (restriction) {\n const value = object[label];\n if (doesChangeHasMultilineConflict(restriction, value)) {\n throw new Error('Multiline change is not allowed for ' + label);\n }\n const newRange = deepClone(restriction.range);\n newRange.endLine = newRange.startLine + value.split('\\n').length - 1;\n newRange.endColumn = value.split('\\n').pop().length;\n if (isChangeInvalidAsPerUser(restriction, value, newRange)) {\n throw new Error('Change is invalidated by validate function of ' + label);\n }\n model.applyEdits([{\n forceMoveMarkers: !!forceMoveMarkers,\n range: restriction.range,\n text: value\n }]);\n } else {\n console.error('No restriction found for ' + label);\n }\n }\n } else {\n throw new Error('Value must be an object');//No I18n\n }\n }\n const disposeRestrictions = function () {\n model._restrictionChangeListener.dispose();\n window.removeEventListener(\"error\", handleUnhandledPromiseRejection);\n delete model.editInRestrictedArea;\n delete model.disposeRestrictions;\n delete model.getValueInEditableRanges;\n delete model.updateValueInEditableRanges;\n delete model.updateRestrictions;\n delete model.getCurrentEditableRanges;\n delete model.toggleHighlightOfEditableAreas;\n delete model._hasHighlight;\n delete model._isRestrictedModel;\n delete model._isCursorAtCheckPoint;\n delete model._currentCursorPositions;\n delete model._editableRangeChangeListener;\n delete model._restrictionChangeListener;\n delete model._oldDecorations;\n delete model._oldDecorationsSource;\n return model;\n }\n const isCursorAtCheckPoint = function (positions) {\n positions.some(function (position) {\n const posLineNumber = position.lineNumber;\n const posCol = position.column;\n const length = restrictions.length;\n for (let i = 0; i < length; i++) {\n const range = restrictions[i].range;\n if (\n (range.startLineNumber === posLineNumber && range.startColumn === posCol) ||\n (range.endLineNumber === posLineNumber && range.endColumn === posCol)\n ) {\n model.pushStackElement();\n return true;\n }\n }\n });\n };\n const addEditableRangeListener = function (callback) {\n if (typeof callback === 'function') {\n model._editableRangeChangeListener.push(callback);\n }\n };\n const triggerChangeListenersWith = function (currentChanges, allChanges) {\n const currentRanges = getCurrentEditableRanges();\n model._editableRangeChangeListener.forEach(function (callback) {\n callback.call(model, currentChanges, allChanges, currentRanges);\n });\n };\n const doUndo = function () {\n return Promise.resolve().then(function () {\n model.editInRestrictedArea = true;\n model.undo();\n model.editInRestrictedArea = false;\n if (model._hasHighlight && model._oldDecorationsSource) {\n // id present in the decorations info will be omitted by monaco\n // So we don't need to remove the old decorations id\n model.deltaDecorations(model._oldDecorations, model._oldDecorationsSource);\n model._oldDecorationsSource.forEach(function (object) {\n object.range = model.getDecorationRange(object.id);\n });\n }\n });\n };\n const updateRange = function (restriction, range, finalLine, finalColumn, changes, changeIndex) {\n let oldRangeEndLineNumber = range.endLineNumber;\n let oldRangeEndColumn = range.endColumn;\n restriction.prevRange = range;\n restriction.range = range.setEndPosition(finalLine, finalColumn);\n const length = restrictions.length;\n let changesLength = changes.length;\n const diffInCol = finalColumn - oldRangeEndColumn;\n const diffInRow = finalLine - oldRangeEndLineNumber;\n\n const cursorPositions = model._currentCursorPositions || [];\n const noOfCursorPositions = cursorPositions.length;\n // if (noOfCursorPositions > 0) {\n if (changesLength !== noOfCursorPositions) {\n changes = changes.filter(function (change) {\n const range = change.range;\n for (let i = 0; i < noOfCursorPositions; i++) {\n const cursorPosition = cursorPositions[i];\n if (\n (range.startLineNumber === cursorPosition.startLineNumber) &&\n (range.endLineNumber === cursorPosition.endLineNumber) &&\n (range.startColumn === cursorPosition.startColumn) &&\n (range.endColumn === cursorPosition.endColumn)\n ) {\n return true;\n }\n }\n return false;\n });\n changesLength = changes.length;\n }\n if (diffInRow !== 0) {\n for (let i = restriction.index + 1; i < length; i++) {\n const nextRestriction = restrictions[i];\n const nextRange = nextRestriction.range;\n if (oldRangeEndLineNumber === nextRange.startLineNumber) {\n nextRange.startColumn += diffInCol;\n }\n if (oldRangeEndLineNumber === nextRange.endLineNumber) {\n nextRange.endColumn += diffInCol;\n }\n nextRange.startLineNumber += diffInRow;\n nextRange.endLineNumber += diffInRow;\n nextRestriction.range = nextRange;\n }\n for (let i = changeIndex + 1; i < changesLength; i++) {\n const nextChange = changes[i];\n const rangeInChange = nextChange.range;\n const rangeAsString = rangeInChange.toString();\n const rangeMapValue = rangeMap[rangeAsString];\n delete rangeMap[rangeAsString];\n if (oldRangeEndLineNumber === rangeInChange.startLineNumber) {\n rangeInChange.startColumn += diffInCol;\n }\n if (oldRangeEndLineNumber === rangeInChange.endLineNumber) {\n rangeInChange.endColumn += diffInCol;\n }\n rangeInChange.startLineNumber += diffInRow;\n rangeInChange.endLineNumber += diffInRow;\n nextChange.range = rangeInChange;\n rangeMap[rangeInChange.toString()] = rangeMapValue;\n }\n } else {\n // Only Column might have changed\n for (let i = restriction.index + 1; i < length; i++) {\n const nextRestriction = restrictions[i];\n const nextRange = nextRestriction.range;\n if (nextRange.startLineNumber > oldRangeEndLineNumber) {\n break;\n } else {\n nextRange.startColumn += diffInCol;\n nextRange.endColumn += diffInCol;\n nextRestriction.range = nextRange;\n }\n }\n for (let i = changeIndex + 1; i < changesLength; i++) {\n // rangeMap\n const nextChange = changes[i];\n const rangeInChange = nextChange.range;\n const rangeAsString = rangeInChange.toString();\n const rangeMapValue = rangeMap[rangeAsString];\n delete rangeMap[rangeAsString];\n if (rangeInChange.startLineNumber > oldRangeEndLineNumber) {\n rangeMap[rangeInChange.toString()] = rangeMapValue;\n break;\n } else {\n rangeInChange.startColumn += diffInCol;\n rangeInChange.endColumn += diffInCol;\n nextChange.range = rangeInChange;\n rangeMap[rangeInChange.toString()] = rangeMapValue;\n }\n }\n }\n // }\n };\n const getInfoFrom = function (change, editableRange) {\n const info = {};\n const range = change.range;\n // Get State\n if (change.text === '') {\n info.isDeletion = true;\n } else if (\n (range.startLineNumber === range.endLineNumber) &&\n (range.startColumn === range.endColumn)\n ) {\n info.isAddition = true;\n } else {\n info.isReplacement = true;\n }\n // Get Position Of Range\n info.startLineOfRange = range.startLineNumber === editableRange.startLineNumber;\n info.startColumnOfRange = range.startColumn === editableRange.startColumn;\n\n info.endLineOfRange = range.endLineNumber === editableRange.endLineNumber;\n info.endColumnOfRange = range.endColumn === editableRange.endColumn;\n\n info.middleLineOfRange = !info.startLineOfRange && !info.endLineOfRange;\n\n // Editable Range Span\n if (editableRange.startLineNumber === editableRange.endLineNumber) {\n info.rangeIsSingleLine = true;\n } else {\n info.rangeIsMultiLine = true;\n }\n return info;\n };\n const updateRestrictions = function (ranges) {\n restrictions = deepClone(ranges).sort(sortRangesInAscendingOrder);\n prepareRestrictions(restrictions);\n };\n const toggleHighlightOfEditableAreas = function (cssClasses) {\n if (!model._hasHighlight) {\n const cssClassForSingleLine = cssClasses.cssClassForSingleLine ||enums.SINGLE_LINE_HIGHLIGHT_CLASS\n const cssClassForMultiLine = cssClasses.cssClassForMultiLine ||enums.MULTI_LINE_HIGHLIGHT_CLASS\n const decorations = restrictions.map(function (restriction) {\n const decoration = {\n range: restriction.range,\n options: {\n className: restriction.allowMultiline ?\n cssClassForMultiLine :\n cssClassForSingleLine\n }\n }\n if (restriction.label) {\n decoration.hoverMessage = restriction.label;\n }\n return decoration;\n });\n model._oldDecorations = model.deltaDecorations([], decorations);\n model._oldDecorationsSource = decorations.map(function (decoration, index) {\n return Object.assign({}, decoration, { id: model._oldDecorations[index] });\n });\n model._hasHighlight = true;\n } else {\n model.deltaDecorations(model._oldDecorations, []);\n delete model._oldDecorations;\n delete model._oldDecorationsSource;\n model._hasHighlight = false;\n }\n }\n const handleUnhandledPromiseRejection = function () {\n console.debug('handler for unhandled promise rejection');\n };\n const setAllRangesToPrev = function (rangeMap) {\n for (let key in rangeMap) {\n const restriction = rangeMap[key];\n restriction.range = restriction.prevRange;\n }\n };\n const doesChangeHasMultilineConflict = function (restriction, text) {\n return !restriction.allowMultiline && text.includes('\\n');\n };\n const isChangeInvalidAsPerUser = function (restriction, value, range) {\n return restriction.validate && !restriction.validate(value, range, restriction.lastInfo);\n }\n\n const manipulatorApi = {\n _isRestrictedModel: true,\n _isRestrictedValueValid: true,\n _editableRangeChangeListener: [],\n _isCursorAtCheckPoint: isCursorAtCheckPoint,\n _currentCursorPositions: []\n }\n\n prepareRestrictions(restrictions);\n model._hasHighlight = false;\n manipulatorApi._restrictionChangeListener = model.onDidChangeContent(function (contentChangedEvent) {\n const isUndoing = contentChangedEvent.isUndoing;\n model._isRestrictedValueValid = true;\n if (!(isUndoing && model.editInRestrictedArea)) {\n const changes = contentChangedEvent.changes.sort(sortRangesInAscendingOrder);\n const rangeMap = {};\n const length = restrictions.length;\n const isAllChangesValid = changes.every(function (change) {\n const editedRange = change.range;\n const rangeAsString = editedRange.toString();\n rangeMap[rangeAsString] = null;\n for (let i = 0; i < length; i++) {\n const restriction = restrictions[i];\n const range = restriction.range;\n if (range.containsRange(editedRange)) {\n if (doesChangeHasMultilineConflict(restriction, change.text)) {\n return false;\n }\n rangeMap[rangeAsString] = restriction;\n return true;\n }\n }\n return false;\n })\n if (isAllChangesValid) {\n changes.forEach(function (change, changeIndex) {\n const changedRange = change.range;\n const restriction = rangeMap[changedRange.toString()];\n const editableRange = restriction.range;\n const text = change.text || '';\n /**\n * Things to check before implementing the change\n * - A | D | R => Addition | Deletion | Replacement\n * - MC | SC => MultiLineChange | SingleLineChange\n * - SOR | MOR | EOR => Change Occured in - Start Of Range | Middle Of Range | End Of Range\n * - SSL | SML => Editable Range - Spans Single Line | Spans Multiple Line\n */\n const noOfLinesAdded = (text.match(/\\n/g) || []).length;\n const noOfColsAddedAtLastLine = text.split(/\\n/g).pop().length;\n\n const lineDiffInRange = changedRange.endLineNumber - changedRange.startLineNumber;\n const colDiffInRange = changedRange.endColumn - changedRange.startColumn;\n\n let finalLine = editableRange.endLineNumber;\n let finalColumn = editableRange.endColumn;\n\n let columnsCarriedToEnd = 0;\n if (\n (editableRange.endLineNumber === changedRange.startLineNumber) ||\n (editableRange.endLineNumber === changedRange.endLineNumber)\n ) {\n columnsCarriedToEnd += (editableRange.endColumn - changedRange.startColumn) + 1;\n }\n\n const info = getInfoFrom(change, editableRange);\n restriction.lastInfo = info;\n if (info.isAddition || info.isReplacement) {\n if (info.rangeIsSingleLine) {\n /**\n * Only Column Change has occurred , so regardless of the position of the change\n * Addition of noOfCols is enough\n */\n if (noOfLinesAdded === 0) {\n finalColumn += noOfColsAddedAtLastLine;\n } else {\n finalLine += noOfLinesAdded;\n if (info.startColumnOfRange) {\n finalColumn += noOfColsAddedAtLastLine\n } else if (info.endColumnOfRange) {\n finalColumn = (noOfColsAddedAtLastLine + 1)\n } else {\n finalColumn = (noOfColsAddedAtLastLine + columnsCarriedToEnd)\n }\n }\n }\n if (info.rangeIsMultiLine) {\n // Handling for Start Of Range is not required\n finalLine += noOfLinesAdded;\n if (info.endLineOfRange) {\n if (noOfLinesAdded === 0) {\n finalColumn += noOfColsAddedAtLastLine;\n } else {\n finalColumn = (columnsCarriedToEnd + noOfColsAddedAtLastLine);\n }\n }\n }\n }\n if (info.isDeletion || info.isReplacement) {\n if (info.rangeIsSingleLine) {\n finalColumn -= colDiffInRange;\n }\n if (info.rangeIsMultiLine) {\n if (info.endLineOfRange) {\n finalLine -= lineDiffInRange;\n finalColumn -= colDiffInRange;\n } else {\n finalLine -= lineDiffInRange;\n }\n }\n }\n updateRange(restriction, editableRange, finalLine, finalColumn, changes, changeIndex);\n });\n const values = model.getValueInEditableRanges();\n const currentlyEditedRanges = {};\n for (let key in rangeMap) {\n const restriction = rangeMap[key];\n const range = restriction.range;\n const rangeString = restriction.label || range.toString();\n const value = values[rangeString];\n if (isChangeInvalidAsPerUser(restriction, value, range)) {\n setAllRangesToPrev(rangeMap);\n doUndo();\n return; // Breaks the loop and prevents the triggerChangeListener\n }\n currentlyEditedRanges[rangeString] = value;\n }\n if (model._hasHighlight) {\n model._oldDecorationsSource.forEach(function (object) {\n object.range = model.getDecorationRange(object.id);\n });\n }\n triggerChangeListenersWith(currentlyEditedRanges, values);\n } else {\n doUndo();\n }\n } else if (model.editInRestrictedArea) {\n model._isRestrictedValueValid = false;\n }\n });\n window.onerror = handleUnhandledPromiseRejection;\n const exposedApi = {\n editInRestrictedArea: false,\n getCurrentEditableRanges: getCurrentEditableRanges,\n getValueInEditableRanges: getValueInEditableRanges,\n disposeRestrictions: disposeRestrictions,\n onDidChangeContentInEditableRange: addEditableRangeListener,\n updateRestrictions: updateRestrictions,\n updateValueInEditableRanges: updateValueInEditableRanges,\n toggleHighlightOfEditableAreas: toggleHighlightOfEditableAreas\n }\n for (let funcName in manipulatorApi) {\n Object.defineProperty(model, funcName, {\n enumerable: false,\n configurable: true,\n writable: true,\n value: manipulatorApi[funcName]\n })\n }\n for (let apiName in exposedApi) {\n Object.defineProperty(model, apiName, {\n enumerable: false,\n configurable: true,\n writable: true,\n value: exposedApi[apiName]\n })\n }\n return model;\n}\nexport default constrainedModel;","import validators from './utils/validators.js';\nimport { TypeMustBe } from './utils/definedErrors.js';\nimport constrainedModel from './constrainedModel.js';\n\nexport function constrainedEditor(monaco) {\n /**\n * Injected Dependencies\n */\n if (monaco === undefined) {\n throw new Error([\n \"Please pass the monaco global variable into function as\",\n \"(eg:)constrainedEditor({ range : monaco.range });\",\n ].join('\\n'));\n }\n /**\n *\n * @param {Object} editorInstance This should be the monaco editor instance.\n * @description This is the listener function to check whether the cursor is at checkpoints\n * (i.e) the point where editable and non editable portions meet\n */\n const listenerFn = function (editorInstance) {\n const model = editorInstance.getModel();\n if (model._isCursorAtCheckPoint) {\n const selections = editorInstance.getSelections();\n const positions = selections.map(function (selection) {\n return {\n lineNumber: selection.positionLineNumber,\n column: selection.positionColumn\n }\n });\n model._isCursorAtCheckPoint(positions);\n model._currentCursorPositions = selections;\n }\n }\n const _uriRestrictionMap = {};\n const { isInstanceValid, isModelValid, isRangesValid } = validators.initWith(monaco);\n /**\n *\n * @param {Object} editorInstance This should be the monaco editor instance\n * @returns {Boolean}\n */\n const initInEditorInstance = function (editorInstance) {\n if (isInstanceValid(editorInstance)) {\n let domNode = editorInstance.getDomNode();\n manipulator._listener = listenerFn.bind(API, editorInstance);\n manipulator._editorInstance = editorInstance;\n manipulator._editorInstance._isInDevMode = false;\n domNode.addEventListener('keydown', manipulator._listener, true);\n manipulator._onChangeModelDisposable = editorInstance.onDidChangeModel(function () {\n // domNode - refers old dom node\n domNode && domNode.removeEventListener('keydown', manipulator._listener, true)\n const newDomNode = editorInstance.getDomNode(); // Gets Current dom node\n newDomNode && newDomNode.addEventListener('keydown', manipulator._listener, true);\n domNode = newDomNode;\n })\n return true;\n } else {\n throw new Error(\n TypeMustBe(\n 'ICodeEditor',\n 'editorInstance',\n 'This type interface can be found in monaco editor documentation'\n )\n )\n }\n }\n /**\n *\n * @param {Object} model This should be the monaco editor model instance. Refer https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.itextmodel.html\n * @param {*} ranges This should be the array of range objects. Refer constrained editor plugin documentation\n * @returns model\n */\n const addRestrictionsTo = function (model, ranges) {\n if (isModelValid(model)) {\n if (isRangesValid(ranges)) {\n const modelToConstrain = constrainedModel(model, ranges, monaco, manipulator._editorInstance);\n _uriRestrictionMap[modelToConstrain.uri.toString()] = modelToConstrain;\n return modelToConstrain;\n } else {\n throw new Error(\n TypeMustBe(\n 'Array<RangeRestrictionObject>',\n 'ranges',\n 'Please refer constrained editor documentation for proper structure'\n )\n )\n }\n } else {\n throw new Error(\n TypeMustBe(\n 'ICodeEditor',\n 'editorInstance',\n 'This type interface can be found in monaco editor documentation'\n )\n )\n }\n }\n /**\n *\n * @param {Object} model This should be the monaco editor model instance. Refer https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.itextmodel.html\n * @returns {Boolean} True if the restrictions are removed\n */\n const removeRestrictionsIn = function (model) {\n if (isModelValid(model)) {\n const uri = model.uri.toString();\n const restrictedModel = _uriRestrictionMap[uri];\n if (restrictedModel) {\n return restrictedModel.disposeRestrictions();\n } else {\n console.warn('Current Model is not a restricted Model');\n return false;\n }\n } else {\n throw new Error(\n TypeMustBe(\n 'ICodeEditor',\n 'editorInstance',\n 'This type interface can be found in monaco editor documentation'\n )\n )\n }\n }\n /**\n *\n * @returns {Boolean} True if the constrainer is disposed\n */\n const disposeConstrainer = function () {\n if (manipulator._editorInstance) {\n const instance = manipulator._editorInstance;\n const domNode = instance.getDomNode();\n domNode && domNode.removeEventListener('keydown', manipulator._listener);\n manipulator._onChangeModelDisposable && manipulator._onChangeModelDisposable.dispose();\n delete manipulator._listener;\n delete manipulator._editorInstance._isInDevMode;\n delete manipulator._editorInstance._devModeAction;\n delete manipulator._editorInstance;\n delete manipulator._onChangeModelDisposable;\n for (let key in _uriRestrictionMap) {\n delete _uriRestrictionMap[key];\n }\n return true;\n }\n return false;\n }\n /**\n * @description This function used to make the developer to find the ranges of selected portions\n */\n const toggleDevMode = function () {\n if (manipulator._editorInstance._isInDevMode) {\n manipulator._editorInstance._isInDevMode = false;\n manipulator._editorInstance._devModeAction.dispose();\n delete manipulator._editorInstance._devModeAction;\n } else {\n manipulator._editorInstance._isInDevMode = true;\n manipulator._editorInstance._devModeAction = manipulator._editorInstance.addAction({\n id: 'showRange',\n label: 'Show Range in console',\n contextMenuGroupId: 'navigation',\n contextMenuOrder: 1.5,\n run: function (editor) {\n const selections = editor.getSelections();\n const ranges = selections.reduce(function (acc, { startLineNumber, endLineNumber, startColumn, endColumn }) {\n acc.push('range : ' + JSON.stringify([\n startLineNumber,\n startColumn,\n endLineNumber,\n endColumn\n ]));\n return acc;\n }, []).join('\\n');\n console.log(`Selected Ranges : \\n` + JSON.stringify(ranges, null, 2));\n }\n });\n }\n }\n\n /**\n * Main Function starts here\n */\n // @internal\n const manipulator = {\n /**\n * These variables should not be modified by external code\n * This has to be used for debugging and testing\n */\n _listener: null,\n _editorInstance: null,\n _uriRestrictionMap: _uriRestrictionMap,\n _injectedResources: monaco\n }\n const API = Object.create(manipulator);\n const exposedMethods = {\n /**\n * These functions are exposed to the user\n * These functions should be protected from editing\n */\n initializeIn: initInEditorInstance,\n addRestrictionsTo: addRestrictionsTo,\n removeRestrictionsIn: removeRestrictionsIn,\n disposeConstrainer: disposeConstrainer,\n toggleDevMode: toggleDevMode\n }\n for (let methodName in exposedMethods) {\n Object.defineProperty(API, methodName, {\n enumerable: false,\n writable: false,\n configurable: false,\n value: exposedMethods[methodName]\n })\n }\n return Object.freeze(API);\n}\n\nexport default constrainedEditor;\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { useTheme } from '../theme-provider';\nimport { constrainedEditor } from 'constrained-editor-plugin';\nimport MonacoEditor, { Monaco, DiffEditor } from '@monaco-editor/react';\nimport type { editor as MonacoEditorType } from 'monaco-editor';\nimport type { TextFile } from '../../lib/types';\nimport { type JsonEditorError } from '../../lib/json-types';\nimport { FORMAT } from '../../lib/env';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { Button } from '../ui/button';\nimport { useEditorRefsStore } from '../../store/editor-refs-store';\nimport {\n getSelectionContext,\n createContextSnippet,\n} from '../../lib/monaco-selection-utils';\nimport { ValidationPanel, ValidationStatusBar } from './validation-panel';\nimport { monacoThemeFor, registerMonacoThemes } from '../../lib/monaco-theme';\n\n/** Ensure defaultPath matches the schema fileMatch pattern (*.FORMAT.theme.json) */\nfunction resolveThemeDefaultPath(name: string): string {\n const ext = `.${FORMAT}.theme.json`;\n if (name.endsWith(ext)) return name;\n const base = name\n .replace(/\\.\\w+\\.theme\\.json$/, '')\n .replace(/\\.theme\\.json$/, '')\n .replace(/\\.json$/, '');\n return base + ext;\n}\n\n/**\n * EditorMonacoTheme component for editing JSON theme files with schema validation\n */\nfunction EditorMonacoTheme({\n document,\n readOnly = false,\n onChange,\n}: {\n document: TextFile;\n readOnly?: boolean;\n onChange?: (value: string) => void;\n}) {\n const editorRef = useRef<MonacoEditorType.IStandaloneCodeEditor | null>(null);\n const monacoRef = useRef<Monaco | null>(null);\n const modelRef = useRef<MonacoEditorType.ITextModel | null>(null);\n const { theme } = useTheme();\n const [validationErrors, setValidationErrors] = useState<JsonEditorError[]>(\n []\n );\n const [showValidationPanel, setShowValidationPanel] = useState(true);\n const [isValidationPanelMinimized, setIsValidationPanelMinimized] =\n useState(false);\n const userDismissedRef = useRef(false);\n const pendingDiff = useDocumentsStore((s) => s.pendingDiffs[document.name]);\n const clearPendingDiff = useDocumentsStore((s) => s.clearPendingDiff);\n const saveDocument = useDocumentsStore((s) => s.saveDocument);\n const { registerEditor, unregisterEditor, setActiveEditor } =\n useEditorRefsStore();\n\n // Get resolved theme - convert 'system' to actual theme\n const resolvedTheme =\n theme === 'system'\n ? window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n : theme;\n\n // Initialize Monaco editor\n const handleEditorWillMount = useCallback((monaco: Monaco) => {\n monacoRef.current = monaco;\n // Idempotent; guards the case where an editor mounts before the global\n // configureMonaco() promise has resolved.\n registerMonacoThemes(monaco);\n // Don't call setDiagnosticsOptions here — it would clobber the global\n // config. The theme schema is already registered by configureMonacoInstance\n // and matched via defaultPath → fileMatch.\n }, []);\n\n // Handle editor mount\n const handleEditorMount = useCallback(\n (editor: MonacoEditorType.IStandaloneCodeEditor, monaco: Monaco) => {\n editorRef.current = editor;\n modelRef.current = editor.getModel();\n\n // Register editor in the refs store\n registerEditor(document.name, editor, monaco);\n setActiveEditor(document.name);\n\n // Enable constrained editing\n const constrainedInstance = constrainedEditor(monaco);\n const model = editor.getModel();\n if (model) {\n constrainedInstance.initializeIn(editor);\n }\n\n // Configure editor options\n editor.updateOptions({\n formatOnType: true,\n formatOnPaste: true,\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: true,\n wordWrap: 'on',\n folding: true,\n foldingStrategy: 'indentation',\n suggest: {\n showColors: true,\n showConstants: true,\n showEnums: true,\n showFields: true,\n showFunctions: true,\n showKeywords: true,\n showModules: true,\n showProperties: true,\n showSnippets: true,\n showStructs: true,\n showTypeParameters: true,\n showUnits: true,\n showValues: true,\n showVariables: true,\n },\n });\n\n // Add keyboard shortcuts\n // Cmd+K => send selection to AI assistant\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK, () => {\n const selection = getSelectionContext(editor, monaco);\n if (selection) {\n const snippet = createContextSnippet(selection);\n window.dispatchEvent(\n new CustomEvent('monaco-selection-to-ai', {\n detail: {\n documentName: document.name,\n selection,\n snippet,\n isTheme: true,\n },\n })\n );\n }\n });\n\n // Cmd+S => save command\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {\n // Save command - parent component handles this\n console.log('Save command triggered in theme editor');\n });\n\n // Add context menu action for AI assistant\n editor.addAction({\n id: 'send-theme-to-ai-assistant',\n label: 'Send to AI Assistant (⌘K)',\n contextMenuGroupId: 'navigation',\n contextMenuOrder: 1.5,\n keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK],\n run: function () {\n // Use the editor reference from closure instead of the parameter\n const selection = getSelectionContext(editor, monaco);\n if (selection) {\n const snippet = createContextSnippet(selection);\n // Dispatch event for the chat panel to capture\n window.dispatchEvent(\n new CustomEvent('monaco-selection-to-ai', {\n detail: {\n documentName: document.name,\n selection,\n snippet,\n isTheme: true,\n },\n })\n );\n }\n },\n });\n\n // Format document on mount\n setTimeout(() => {\n editor.getAction('editor.action.formatDocument')?.run();\n }, 100);\n\n console.log('Monaco theme editor mounted');\n },\n [document.name, registerEditor, setActiveEditor]\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n unregisterEditor(document.name);\n };\n }, [document.name, unregisterEditor]);\n\n // Handle content changes\n const handleChange = useCallback(\n (\n value: string | undefined,\n _event: MonacoEditorType.IModelContentChangedEvent\n ) => {\n if (value !== undefined && onChange) {\n onChange(value);\n }\n },\n [onChange]\n );\n\n // Handle Monaco's built-in schema validation markers\n const handleEditorValidation = useCallback(\n (markers: MonacoEditorType.IMarker[]) => {\n const errors: JsonEditorError[] = markers.map((marker) => ({\n path: '',\n message: marker.message,\n code:\n typeof marker.code === 'string'\n ? marker.code\n : marker.code?.value || 'validation_error',\n startLineNumber: marker.startLineNumber,\n startColumn: marker.startColumn,\n endLineNumber: marker.endLineNumber,\n endColumn: marker.endColumn,\n severity:\n marker.severity >= 8\n ? 'error'\n : marker.severity >= 4\n ? 'warning'\n : 'info',\n }));\n\n setValidationErrors(errors);\n\n if (errors.length > 0 && !userDismissedRef.current) {\n setShowValidationPanel(true);\n setIsValidationPanelMinimized(false);\n }\n if (errors.length === 0) {\n userDismissedRef.current = false;\n }\n },\n []\n );\n\n const handleErrorClick = useCallback((error: JsonEditorError) => {\n if (editorRef.current && error.startLineNumber && error.startColumn) {\n editorRef.current.setPosition({\n lineNumber: error.startLineNumber,\n column: error.startColumn,\n });\n editorRef.current.revealLineInCenter(error.startLineNumber);\n editorRef.current.focus();\n }\n }, []);\n\n // Update theme\n useEffect(() => {\n if (editorRef.current) {\n editorRef.current.updateOptions({ theme: monacoThemeFor(resolvedTheme) });\n }\n }, [resolvedTheme]);\n\n return (\n <div className=\"relative h-full\">\n {pendingDiff ? (\n <>\n <div className=\"flex items-center justify-between px-2 py-1 border-b bg-muted/40 text-xs\">\n <div>\n Review changes for{' '}\n <span className=\"font-medium\">{document.name}</span>\n </div>\n <div className=\"flex gap-2\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => clearPendingDiff(document.name)}\n >\n Discard\n </Button>\n <Button\n size=\"sm\"\n onClick={() => {\n saveDocument(document.name, pendingDiff.modified);\n clearPendingDiff(document.name, true);\n }}\n >\n Apply Changes\n </Button>\n </div>\n </div>\n <DiffEditor\n height=\"calc(100% - 32px)\"\n original={pendingDiff.original}\n modified={pendingDiff.modified}\n language=\"json\"\n theme={monacoThemeFor(resolvedTheme)}\n options={{\n readOnly: true,\n renderSideBySide: true,\n originalEditable: false,\n automaticLayout: true,\n minimap: { enabled: false },\n }}\n beforeMount={handleEditorWillMount}\n />\n </>\n ) : (\n <MonacoEditor\n height=\"100%\"\n language=\"json\"\n defaultPath={resolveThemeDefaultPath(document.name)}\n value={document.text}\n theme={monacoThemeFor(resolvedTheme)}\n onChange={handleChange}\n beforeMount={handleEditorWillMount}\n onMount={handleEditorMount}\n onValidate={handleEditorValidation}\n options={{\n readOnly,\n lineNumbers: 'on',\n glyphMargin: true,\n folding: true,\n lineDecorationsWidth: 5,\n lineNumbersMinChars: 3,\n renderValidationDecorations: 'on',\n quickSuggestions: {\n other: true,\n comments: false,\n strings: true,\n },\n acceptSuggestionOnCommitCharacter: true,\n acceptSuggestionOnEnter: 'on',\n accessibilitySupport: 'auto',\n autoIndent: 'advanced',\n formatOnType: true,\n formatOnPaste: true,\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: true,\n wordWrap: 'on',\n }}\n />\n )}\n\n {/* Validation Status Bar */}\n <div className=\"absolute top-0 right-0\">\n <ValidationStatusBar\n errors={validationErrors}\n onClick={() => {\n setShowValidationPanel(true);\n setIsValidationPanelMinimized(false);\n }}\n />\n </div>\n\n {/* Validation Panel */}\n {showValidationPanel && validationErrors.length > 0 && (\n <ValidationPanel\n errors={validationErrors}\n isMinimized={isValidationPanelMinimized}\n onToggleMinimize={() =>\n setIsValidationPanelMinimized(!isValidationPanelMinimized)\n }\n onErrorClick={handleErrorClick}\n onClose={() => {\n setShowValidationPanel(false);\n userDismissedRef.current = true;\n }}\n className=\"z-40\"\n />\n )}\n </div>\n );\n}\n\nexport const EditorMonacoThemeMemoized = React.memo(EditorMonacoTheme);\n","/**\n * A form derived from the theme's JSON Schema, for the keys the hand-built\n * sections do not cover — palette, type roles and scale, spacing, chrome\n * recipes, motif, component defaults.\n *\n * The schema already says everything a field needs: the key, its type, its\n * bounds, its enum, whether a string is a colour, and a description to show\n * as the hint. Deriving the form from it means a new theme key becomes\n * editable the day the schema learns it, and the editor never invents a\n * meaning the runtime does not share. What the schema cannot express as one\n * control — a value that is either a number or an object, an array of\n * objects, a free-form map — is shown as such and handed to the JSON view.\n *\n * Pure: schema and value in, field tree out. The React section renders it.\n */\nimport type { Path, ThemeJson } from './model';\nimport { isHexColor, resolveColor } from './model';\n\ntype JsonSchema = Record<string, any>;\n\nexport type SchemaFieldKind =\n | 'text'\n | 'number'\n | 'boolean'\n | 'enum'\n | 'color'\n | 'list'\n | 'group'\n | 'json';\n\nexport interface SchemaField {\n kind: SchemaFieldKind;\n key: string;\n path: Path;\n label: string;\n /** The schema's description, when it has one. */\n hint?: string;\n required?: boolean;\n /** `enum`: the accepted values. */\n options?: string[];\n /** `number`: bounds and integrality. */\n min?: number;\n max?: number;\n integer?: boolean;\n /** `list`: what one entry is. */\n item?: SchemaField;\n /** `group`: the nested fields, in schema order. */\n children?: SchemaField[];\n}\n\n/** `basePt` → \"Base pt\", `runningHead` → \"Running head\", `a4` → \"A4\". */\nexport function humanize(key: string): string {\n if (/^[a-z]\\d+$/.test(key)) return key.toUpperCase();\n const spaced = key\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .toLowerCase();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nconst COLOR_PATTERN = /\\[0-9A-Fa-f\\]\\{6\\}/;\n\nfunction enumOptions(schema: JsonSchema): string[] | undefined {\n if (Array.isArray(schema.enum))\n return schema.enum.every((v: unknown) => typeof v === 'string')\n ? schema.enum\n : undefined;\n const branches = schema.anyOf ?? schema.oneOf;\n if (\n Array.isArray(branches) &&\n branches.length > 0 &&\n branches.every(\n (b: JsonSchema) =>\n b && typeof b === 'object' && typeof b.const === 'string'\n )\n )\n return branches.map((b: JsonSchema) => b.const);\n return undefined;\n}\n\nfunction scalarKind(\n schema: JsonSchema\n): Exclude<SchemaFieldKind, 'list' | 'group' | 'json'> | undefined {\n const options = enumOptions(schema);\n if (options) return 'enum';\n switch (schema.type) {\n case 'string':\n return typeof schema.pattern === 'string' &&\n COLOR_PATTERN.test(schema.pattern)\n ? 'color'\n : 'text';\n case 'number':\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n default:\n return undefined;\n }\n}\n\n/** One field for one property schema; `json` when no single control fits. */\nexport function schemaField(\n key: string,\n schema: JsonSchema,\n path: Path,\n required = false\n): SchemaField {\n const base: SchemaField = {\n kind: 'json',\n key,\n path,\n label: humanize(key),\n ...(typeof schema?.description === 'string' && {\n hint: schema.description,\n }),\n ...(required && { required }),\n };\n if (!schema || typeof schema !== 'object') return base;\n const scalar = scalarKind(schema);\n if (scalar) {\n const field: SchemaField = { ...base, kind: scalar };\n if (scalar === 'enum') field.options = enumOptions(schema);\n if (scalar === 'number') {\n const integer = schema.type === 'integer';\n const step = integer ? 1 : 0.5;\n const min =\n schema.minimum ??\n (typeof schema.exclusiveMinimum === 'number'\n ? schema.exclusiveMinimum + step\n : undefined);\n const max =\n schema.maximum ??\n (typeof schema.exclusiveMaximum === 'number'\n ? schema.exclusiveMaximum - step\n : undefined);\n if (min !== undefined) field.min = min;\n if (max !== undefined) field.max = max;\n if (integer) field.integer = true;\n }\n return field;\n }\n if (schema.type === 'object' && schema.properties) {\n const requiredKeys = new Set<string>(schema.required ?? []);\n return {\n ...base,\n kind: 'group',\n children: Object.entries(schema.properties as Record<string, JsonSchema>)\n .filter(([child]) => child !== '$schema')\n .map(([child, sub]) =>\n schemaField(child, sub, [...path, child], requiredKeys.has(child))\n ),\n };\n }\n if (\n schema.type === 'array' &&\n schema.items &&\n typeof schema.items === 'object' &&\n !Array.isArray(schema.items) &&\n scalarKind(schema.items)\n ) {\n return {\n ...base,\n kind: 'list',\n item: schemaField('item', schema.items, [...path, 0]),\n ...(typeof schema.maxItems === 'number' && { max: schema.maxItems }),\n ...(typeof schema.minItems === 'number' && { min: schema.minItems }),\n };\n }\n return base;\n}\n\nexport interface SchemaSection {\n key: string;\n title: string;\n hint?: string;\n fields: SchemaField[];\n}\n\n/**\n * Titles for the keys the design system names, where the humanized key\n * would collide with a hand-built section (\"Typography\" is the fonts) or\n * say less than the rail should.\n */\nconst SECTION_TITLES: Record<string, string> = {\n palette: 'Palette',\n typography: 'Type roles & scale',\n spacing: 'Spacing',\n chrome: 'Chrome recipes',\n motif: 'Motif',\n componentDefaults: 'Component defaults',\n};\n\n/**\n * The top-level keys the schema declares as objects with named properties\n * and no hand-built section claims — one form section each, in schema\n * order. Keys the schema types otherwise (a font registry array, a word\n * list) stay in the Advanced list with the JSON view.\n */\nexport function extendedSections(\n schema: JsonSchema | null,\n handledKeys: readonly string[]\n): SchemaSection[] {\n if (!schema?.properties) return [];\n const handled = new Set(handledKeys);\n return Object.entries(schema.properties as Record<string, JsonSchema>)\n .filter(\n ([key, sub]) =>\n !handled.has(key) &&\n key !== '$schema' &&\n sub &&\n typeof sub === 'object' &&\n sub.type === 'object' &&\n sub.properties\n )\n .map(([key, sub]) => {\n const field = schemaField(key, sub, [key]);\n return {\n key,\n title: SECTION_TITLES[key] ?? humanize(key),\n ...(field.hint && { hint: field.hint }),\n fields: field.children ?? [],\n };\n });\n}\n\n/** The keys the schema declares at the top level, `$schema` aside. */\nexport function schemaTopLevelKeys(schema: JsonSchema | null): string[] {\n return Object.keys(schema?.properties ?? {}).filter(\n (key) => key !== '$schema'\n );\n}\n\n/** Case-insensitive substring match of a query against any of the terms. */\nexport function matchesQuery(\n query: string,\n ...terms: (string | undefined)[]\n): boolean {\n const needle = query.trim().toLowerCase();\n if (!needle) return true;\n return terms.some((term) => term?.toLowerCase().includes(needle));\n}\n\n/**\n * The fields a search keeps: a field matches on its key, label, hint or\n * path; a group is kept whole when its own name matches, else pruned to the\n * children that match. An empty query keeps everything.\n */\nexport function filterFields(\n fields: readonly SchemaField[],\n query: string\n): SchemaField[] {\n if (!query.trim()) return [...fields];\n const out: SchemaField[] = [];\n for (const field of fields) {\n const own = matchesQuery(\n query,\n field.key,\n field.label,\n field.hint,\n field.path.join('.')\n );\n if (field.kind === 'group' && field.children) {\n if (own) out.push(field);\n else {\n const children = filterFields(field.children, query);\n if (children.length) out.push({ ...field, children });\n }\n } else if (own) out.push(field);\n }\n return out;\n}\n\n/**\n * Why a JSON value cannot be edited by its field's control, or null when it\n * can. A value of the wrong shape is left alone and pointed at the JSON\n * view rather than silently replaced.\n */\nexport function fieldValueError(\n field: SchemaField,\n value: unknown\n): string | null {\n if (value === undefined) return null;\n switch (field.kind) {\n case 'text':\n case 'color':\n case 'enum':\n return typeof value === 'string' ? null : 'Not a string';\n case 'number':\n return typeof value === 'number' ? null : 'Not a number';\n case 'boolean':\n return typeof value === 'boolean' ? null : 'Not a boolean';\n case 'list':\n return Array.isArray(value) ? null : 'Not a list';\n case 'group':\n return value && typeof value === 'object' && !Array.isArray(value)\n ? null\n : 'Not an object';\n default:\n return null;\n }\n}\n\n/**\n * Resolve a colour the way the design system reads it: a hex, a theme\n * colour token, or a palette token that itself names either. One hop\n * through the palette is enough — the palette's own values resolve through\n * the theme colours — and a cycle ends in null, not a loop.\n */\nexport function resolveThemeColor(\n theme: ThemeJson,\n value: unknown\n): string | null {\n const direct = resolveColor(theme, value);\n if (direct) return direct;\n if (typeof value !== 'string') return null;\n const palette = theme.palette as Record<string, unknown> | undefined;\n const entry = palette?.[value];\n if (typeof entry !== 'string' || entry === value) return null;\n return isHexColor(entry) ? entry : resolveColor(theme, entry);\n}\n\n/** A short reading of a value the form shows but does not edit. */\nexport function summarizeValue(value: unknown): string {\n if (value === undefined) return 'Not set';\n if (Array.isArray(value))\n return `${value.length} item${value.length === 1 ? '' : 's'}`;\n if (value && typeof value === 'object') {\n const keys = Object.keys(value as object);\n return keys.length === 0\n ? 'Empty'\n : keys.slice(0, 4).join(', ') + (keys.length > 4 ? ', …' : '');\n }\n const text = String(value);\n return text.length > 40 ? `${text.slice(0, 40)}…` : text;\n}\n","/**\n * Theme JSON Schema — fetched from the server (format-aware)\n */\n\nlet _cachedSchema: any | null = null;\n\n/**\n * Fetch the theme JSON schema from the server.\n * Result is cached for the lifetime of the session.\n */\nexport async function fetchThemeJsonSchema(): Promise<any> {\n if (_cachedSchema) return _cachedSchema;\n\n const res = await fetch('/api/discovery/schemas/theme');\n const json = await res.json();\n if (!json.success)\n throw new Error(json.error ?? 'Failed to fetch theme schema');\n\n _cachedSchema = json.data;\n return _cachedSchema;\n}\n","import * as React from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { cn } from '@/lib/utils';\n\nconst Popover = PopoverPrimitive.Root;\nconst PopoverTrigger = PopoverPrimitive.Trigger;\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'start', sideOffset = 4, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-lg border p-3 shadow-lg outline-none',\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverTrigger, PopoverAnchor, PopoverContent };\n","/**\n * Hex ↔ HSV, for the picker only.\n *\n * The theme stores 6-digit hex and nothing else, so HSV exists purely as the\n * shape a saturation square and a hue rail can be dragged in. Round trips are\n * lossy at the edges (every grey is hue 0 after a trip through hex), which is\n * why the picker keeps its own HSV while it is open rather than re-deriving\n * it from the value on every drag.\n */\n\nexport interface Hsv {\n /** 0–360 */\n h: number;\n /** 0–1 */\n s: number;\n /** 0–1 */\n v: number;\n}\n\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\nexport function hexToRgb(hex: string): Rgb | null {\n const match = hex.match(/^#?([0-9A-Fa-f]{6})$/);\n if (!match) return null;\n const int = parseInt(match[1], 16);\n return { r: (int >> 16) & 255, g: (int >> 8) & 255, b: int & 255 };\n}\n\nexport function rgbToHex({ r, g, b }: Rgb): string {\n const channel = (value: number) =>\n Math.max(0, Math.min(255, Math.round(value)))\n .toString(16)\n .padStart(2, '0')\n .toUpperCase();\n return `#${channel(r)}${channel(g)}${channel(b)}`;\n}\n\nexport function rgbToHsv({ r, g, b }: Rgb): Hsv {\n const red = r / 255;\n const green = g / 255;\n const blue = b / 255;\n const max = Math.max(red, green, blue);\n const min = Math.min(red, green, blue);\n const span = max - min;\n let h = 0;\n if (span !== 0) {\n if (max === red) h = ((green - blue) / span) % 6;\n else if (max === green) h = (blue - red) / span + 2;\n else h = (red - green) / span + 4;\n h *= 60;\n if (h < 0) h += 360;\n }\n return { h, s: max === 0 ? 0 : span / max, v: max };\n}\n\nexport function hsvToRgb({ h, s, v }: Hsv): Rgb {\n const hue = ((h % 360) + 360) % 360;\n const c = v * s;\n const x = c * (1 - Math.abs(((hue / 60) % 2) - 1));\n const m = v - c;\n const [r, g, b] =\n hue < 60\n ? [c, x, 0]\n : hue < 120\n ? [x, c, 0]\n : hue < 180\n ? [0, c, x]\n : hue < 240\n ? [0, x, c]\n : hue < 300\n ? [x, 0, c]\n : [c, 0, x];\n return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };\n}\n\nexport function hexToHsv(hex: string): Hsv | null {\n const rgb = hexToRgb(hex);\n return rgb ? rgbToHsv(rgb) : null;\n}\n\nexport function hsvToHex(hsv: Hsv): string {\n return rgbToHex(hsvToRgb(hsv));\n}\n\n/** Black or white, whichever reads on `hex`. For text drawn over a swatch. */\nexport function readableInk(hex: string): string {\n const rgb = hexToRgb(hex);\n if (!rgb) return '#000000';\n // Perceived brightness (ITU-R BT.601), the cheap version that is right\n // often enough for a 20px chip.\n const brightness = (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;\n return brightness > 140 ? '#000000' : '#FFFFFF';\n}\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Check, Pipette, X } from 'lucide-react';\nimport { Input } from '../ui/input';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';\nimport {\n hexToHsv,\n hsvToHex,\n readableInk,\n type Hsv,\n} from '../../lib/theme-editor/color';\nimport {\n normalizeHex,\n resolveColor,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport { cn } from '../../lib/utils';\nimport { INPUT_CLASS, useDraft } from './theme-editor-shared';\n\n/**\n * The colour control: a swatch that opens a picker, and a field beside it\n * that still takes a typed hex — or the name of another token, because both\n * schemas let one colour reference another.\n *\n * The picker holds its own HSV for as long as it is open. Hex is a lossy\n * home for it (every grey comes back as hue 0, black loses saturation), so\n * re-deriving HSV from the committed value on each drag would make the hue\n * rail jump under the pointer at the edges of the square.\n *\n * Dragging writes through on an animation frame rather than on every pointer\n * move: one theme edit is a re-parse and a re-serialise of the whole file, and\n * a 120Hz trackpad would otherwise ask for a hundred of them a second.\n */\n\nconst TOKEN_NAME = /^[a-zA-Z][a-zA-Z0-9]*$/;\nconst PLACEHOLDER_HEX = '#D4D4D8';\n\nexport interface ColorToken {\n key: string;\n hex: string;\n}\n\n/** Commit at most once per frame while a pointer drag is in flight. */\nfunction useFrameCommit(commit: (hex: string) => void) {\n const pending = useRef<string | null>(null);\n const frame = useRef<number | null>(null);\n const latest = useRef(commit);\n latest.current = commit;\n\n const flush = useCallback(() => {\n frame.current = null;\n const value = pending.current;\n pending.current = null;\n if (value !== null) latest.current(value);\n }, []);\n\n const schedule = useCallback(\n (hex: string) => {\n pending.current = hex;\n if (frame.current === null) {\n frame.current = requestAnimationFrame(flush);\n }\n },\n [flush]\n );\n\n // A drag that ends between frames must not lose its last position.\n const finish = useCallback(() => {\n if (frame.current !== null) {\n cancelAnimationFrame(frame.current);\n flush();\n }\n }, [flush]);\n\n useEffect(\n () => () => {\n if (frame.current !== null) cancelAnimationFrame(frame.current);\n },\n []\n );\n\n return { schedule, finish };\n}\n\n/** Pointer drag over a box, reported as 0–1 on each axis. */\nfunction useDragArea(\n onMove: (x: number, y: number) => void,\n onEnd: () => void\n) {\n const ref = useRef<HTMLDivElement | null>(null);\n const report = useCallback(\n (event: React.PointerEvent) => {\n const box = ref.current?.getBoundingClientRect();\n if (!box || box.width === 0 || box.height === 0) return;\n const x = (event.clientX - box.left) / box.width;\n const y = (event.clientY - box.top) / box.height;\n onMove(Math.min(1, Math.max(0, x)), Math.min(1, Math.max(0, y)));\n },\n [onMove]\n );\n const onPointerDown = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n report(event);\n },\n [report]\n );\n const onPointerMove = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (!event.currentTarget.hasPointerCapture(event.pointerId)) return;\n report(event);\n },\n [report]\n );\n const onPointerUp = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n onEnd();\n },\n [onEnd]\n );\n return { ref, onPointerDown, onPointerMove, onPointerUp };\n}\n\nfunction SaturationArea({\n hsv,\n onChange,\n onEnd,\n}: {\n hsv: Hsv;\n onChange: (next: Hsv) => void;\n onEnd: () => void;\n}) {\n const move = useCallback(\n (x: number, y: number) => onChange({ ...hsv, s: x, v: 1 - y }),\n [hsv, onChange]\n );\n const drag = useDragArea(move, onEnd);\n const step = useCallback(\n (event: React.KeyboardEvent) => {\n const delta = event.shiftKey ? 0.1 : 0.02;\n const map: Record<string, Partial<Hsv>> = {\n ArrowLeft: { s: Math.max(0, hsv.s - delta) },\n ArrowRight: { s: Math.min(1, hsv.s + delta) },\n ArrowUp: { v: Math.min(1, hsv.v + delta) },\n ArrowDown: { v: Math.max(0, hsv.v - delta) },\n };\n const next = map[event.key];\n if (!next) return;\n event.preventDefault();\n onChange({ ...hsv, ...next });\n onEnd();\n },\n [hsv, onChange, onEnd]\n );\n return (\n <div\n ref={drag.ref}\n role=\"application\"\n aria-label=\"Saturation and brightness\"\n tabIndex={0}\n onPointerDown={drag.onPointerDown}\n onPointerMove={drag.onPointerMove}\n onPointerUp={drag.onPointerUp}\n onKeyDown={step}\n className={cn(\n 'relative h-32 w-full cursor-crosshair touch-none overflow-hidden rounded-sm border',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n style={{ backgroundColor: hsvToHex({ h: hsv.h, s: 1, v: 1 }) }}\n >\n <div className=\"absolute inset-0 bg-[linear-gradient(to_right,#fff,transparent)]\" />\n <div className=\"absolute inset-0 bg-[linear-gradient(to_top,#000,transparent)]\" />\n <span\n aria-hidden\n className=\"absolute size-3 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0_0_0_1px_rgba(0,0,0,0.45)]\"\n style={{\n left: `${hsv.s * 100}%`,\n top: `${(1 - hsv.v) * 100}%`,\n backgroundColor: hsvToHex(hsv),\n }}\n />\n </div>\n );\n}\n\nconst HUE_GRADIENT =\n 'linear-gradient(to right,#FF0000,#FFFF00,#00FF00,#00FFFF,#0000FF,#FF00FF,#FF0000)';\n\nfunction HueRail({\n hsv,\n onChange,\n onEnd,\n}: {\n hsv: Hsv;\n onChange: (next: Hsv) => void;\n onEnd: () => void;\n}) {\n const move = useCallback(\n (x: number) => onChange({ ...hsv, h: x * 360 }),\n [hsv, onChange]\n );\n const drag = useDragArea(move, onEnd);\n return (\n <div\n ref={drag.ref}\n role=\"slider\"\n aria-label=\"Hue\"\n aria-valuemin={0}\n aria-valuemax={360}\n aria-valuenow={Math.round(hsv.h)}\n tabIndex={0}\n onPointerDown={drag.onPointerDown}\n onPointerMove={drag.onPointerMove}\n onPointerUp={drag.onPointerUp}\n onKeyDown={(event) => {\n const delta =\n event.key === 'ArrowLeft' ? -1 : event.key === 'ArrowRight' ? 1 : 0;\n if (!delta) return;\n event.preventDefault();\n onChange({\n ...hsv,\n h: (hsv.h + delta * (event.shiftKey ? 10 : 2) + 360) % 360,\n });\n onEnd();\n }}\n className={cn(\n 'relative h-3 w-full cursor-ew-resize touch-none rounded-full border',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n style={{ background: HUE_GRADIENT }}\n >\n <span\n aria-hidden\n className=\"absolute top-1/2 size-3.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white shadow-[0_0_0_1px_rgba(0,0,0,0.45)]\"\n style={{\n left: `${(hsv.h / 360) * 100}%`,\n backgroundColor: hsvToHex({ h: hsv.h, s: 1, v: 1 }),\n }}\n />\n </div>\n );\n}\n\nfunction TokenChips({\n tokens,\n active,\n onPick,\n}: {\n tokens: readonly ColorToken[];\n active: string | null;\n onPick: (key: string) => void;\n}) {\n return (\n <div className=\"flex flex-wrap gap-1\">\n {tokens.map((token) => {\n const selected = token.key === active;\n return (\n <Tooltip key={token.key}>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => onPick(token.key)}\n aria-label={`Use token ${token.key}`}\n aria-pressed={selected}\n className={cn(\n 'flex size-6 cursor-pointer items-center justify-center rounded-sm border',\n 'transition-shadow focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n selected\n ? 'ring-1 ring-ring ring-offset-1 ring-offset-popover'\n : 'border-border/70'\n )}\n style={{ backgroundColor: token.hex }}\n >\n {selected && (\n <Check\n className=\"size-3\"\n style={{ color: readableInk(token.hex) }}\n aria-hidden\n />\n )}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p className=\"font-mono text-xs\">\n {token.key} {token.hex}\n </p>\n </TooltipContent>\n </Tooltip>\n );\n })}\n </div>\n );\n}\n\n/**\n * Swatch + field. The swatch opens the picker; the field takes a hex, or a\n * token name when `allowReference`.\n */\nexport function ColorControl({\n id,\n label,\n value,\n resolved,\n onCommit,\n allowReference = true,\n tokens,\n className,\n}: {\n id?: string;\n label: string;\n /** Raw JSON value: a hex, a token name, or nothing. */\n value: string | undefined;\n /** What the value resolves to after following references. */\n resolved: string | null;\n onCommit: (next: string | null) => void;\n allowReference?: boolean;\n /** Theme colours offered as one-click references inside the picker. */\n tokens?: readonly ColorToken[];\n className?: string;\n}) {\n const [open, setOpen] = useState(false);\n const commitText = useCallback(\n (draft: string) => {\n const trimmed = draft.trim();\n if (trimmed === '') {\n onCommit(null);\n return;\n }\n const hex = normalizeHex(trimmed);\n if (/^#[0-9A-F]{6}$/.test(hex)) {\n onCommit(hex);\n return;\n }\n if (allowReference && TOKEN_NAME.test(trimmed)) onCommit(trimmed);\n // Anything else reverts: the input drops its draft on blur regardless.\n },\n [allowReference, onCommit]\n );\n const { props: draft } = useDraft(value ?? '', commitText);\n const swatch = resolved ?? PLACEHOLDER_HEX;\n const reference = value && !value.startsWith('#') ? value : null;\n\n return (\n <div className={cn('flex min-w-0 items-center gap-1.5', className)}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={`${label} picker`}\n className={cn(\n 'relative size-6 shrink-0 cursor-pointer overflow-hidden rounded-sm border',\n 'transition-shadow focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n resolved\n ? 'border-border hover:ring-1 hover:ring-ring/50'\n : 'border-dashed border-muted-foreground/40 opacity-60'\n )}\n style={{ backgroundColor: swatch }}\n />\n </PopoverTrigger>\n {/* Focus lands on the saturation square, which takes arrow keys, so\n the picker is usable without a pointer from the moment it opens. */}\n <PopoverContent className=\"w-64\">\n <ColorPickerBody\n label={label}\n value={value}\n resolved={resolved}\n tokens={allowReference ? tokens : undefined}\n onCommit={onCommit}\n onDone={() => setOpen(false)}\n />\n </PopoverContent>\n </Popover>\n <Input\n id={id}\n type=\"text\"\n aria-label={label}\n autoComplete=\"off\"\n spellCheck={false}\n placeholder=\"#RRGGBB\"\n title={reference && resolved ? `${reference} → ${resolved}` : undefined}\n className={cn(\n INPUT_CLASS,\n 'w-full min-w-0 font-mono',\n reference ? 'lowercase' : 'uppercase'\n )}\n {...draft}\n />\n </div>\n );\n}\n\nfunction ColorPickerBody({\n label,\n value,\n resolved,\n tokens,\n onCommit,\n onDone,\n}: {\n label: string;\n value: string | undefined;\n resolved: string | null;\n tokens?: readonly ColorToken[];\n onCommit: (next: string | null) => void;\n onDone: () => void;\n}) {\n // Seeded once per opening — this body only exists while the popover is up —\n // so HSV is the truth for as long as it lasts and hex is derived from it: a\n // drag through grey or black keeps the hue it came in with.\n const [hsv, setHsv] = useState<Hsv>(\n () => hexToHsv(resolved ?? PLACEHOLDER_HEX) ?? { h: 0, s: 0, v: 0.8 }\n );\n const seeded = useRef(resolved);\n if (resolved !== seeded.current) {\n // A token chip or a typed hex changed the value from outside the square.\n seeded.current = resolved;\n const next = hexToHsv(resolved ?? PLACEHOLDER_HEX);\n if (next) setHsv(next);\n }\n\n const commitHex = useCallback((hex: string) => onCommit(hex), [onCommit]);\n const { schedule, finish } = useFrameCommit(commitHex);\n const onChange = useCallback(\n (next: Hsv) => {\n setHsv(next);\n const hex = hsvToHex(next);\n seeded.current = hex;\n schedule(hex);\n },\n [schedule]\n );\n\n const hex = hsvToHex(hsv);\n const eyedropper =\n typeof window !== 'undefined' && 'EyeDropper' in window\n ? async () => {\n try {\n const EyeDropperCtor = (\n window as unknown as {\n EyeDropper: new () => {\n open: () => Promise<{ sRGBHex: string }>;\n };\n }\n ).EyeDropper;\n const picked = await new EyeDropperCtor().open();\n const normalized = normalizeHex(picked.sRGBHex);\n if (/^#[0-9A-F]{6}$/.test(normalized)) onCommit(normalized);\n } catch {\n // Dismissed, or denied. Nothing to say about either.\n }\n }\n : null;\n\n return (\n <div className=\"flex flex-col gap-2.5\">\n <SaturationArea hsv={hsv} onChange={onChange} onEnd={finish} />\n <HueRail hsv={hsv} onChange={onChange} onEnd={finish} />\n <div className=\"flex items-center gap-1.5\">\n <span\n aria-hidden\n className=\"size-6 shrink-0 rounded-sm border\"\n style={{ backgroundColor: resolved ?? PLACEHOLDER_HEX }}\n />\n <PickerHexInput hex={hex} onCommit={onCommit} label={label} />\n {eyedropper && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={eyedropper}\n aria-label=\"Pick a colour from the screen\"\n className={cn(\n 'flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-sm',\n 'text-muted-foreground transition-colors hover:bg-accent hover:text-foreground',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <Pipette className=\"size-3.5\" aria-hidden />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>Pick from the screen</p>\n </TooltipContent>\n </Tooltip>\n )}\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => {\n onCommit(null);\n onDone();\n }}\n aria-label={`Clear ${label}`}\n disabled={value === undefined}\n className={cn(\n 'flex size-7 shrink-0 cursor-pointer items-center justify-center rounded-sm',\n 'text-muted-foreground transition-colors hover:bg-accent hover:text-foreground',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n 'disabled:pointer-events-none disabled:opacity-40'\n )}\n >\n <X className=\"size-3.5\" aria-hidden />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>Clear</p>\n </TooltipContent>\n </Tooltip>\n </div>\n {tokens && tokens.length > 0 && (\n <div className=\"flex flex-col gap-1.5 border-t pt-2\">\n <span className=\"text-[10px] font-medium tracking-[0.08em] text-muted-foreground uppercase\">\n Theme colours\n </span>\n <TokenChips\n tokens={tokens}\n active={value && !value.startsWith('#') ? value : null}\n onPick={(key) => onCommit(key)}\n />\n <p className=\"text-[11px] leading-snug text-muted-foreground\">\n A token follows the theme when that colour changes; a hex does not.\n </p>\n </div>\n )}\n </div>\n );\n}\n\n/** The hex inside the popover: shows the square's live value, commits on blur. */\nfunction PickerHexInput({\n hex,\n label,\n onCommit,\n}: {\n hex: string;\n label: string;\n onCommit: (next: string | null) => void;\n}) {\n const commit = useCallback(\n (draft: string) => {\n const normalized = normalizeHex(draft);\n if (/^#[0-9A-F]{6}$/.test(normalized)) onCommit(normalized);\n },\n [onCommit]\n );\n const { props: draft } = useDraft(hex, commit);\n return (\n <Input\n type=\"text\"\n aria-label={`${label} hex`}\n autoComplete=\"off\"\n spellCheck={false}\n // Flat on the popover, like every other input in the app is flat on\n // the surface behind it; `bg-background` here would read as a filled\n // field only because the popover is a lighter white.\n className={cn(\n INPUT_CLASS,\n 'h-7 min-w-0 flex-1 bg-transparent font-mono uppercase'\n )}\n {...draft}\n />\n );\n}\n\n/**\n * Theme colours as picker chips, memoised on the colours themselves.\n *\n * Every edit anywhere in a theme produces a new parse, so a list derived from\n * the theme object would be a new array each time and would re-render every\n * memoised row that holds one. Keyed on the serialised colours, the identity\n * only moves when the palette actually does.\n */\nexport function useThemeColorTokens(theme: ThemeJson): ColorToken[] {\n const json = JSON.stringify(theme.colors ?? null);\n return useMemo(() => {\n const colors = JSON.parse(json) as Record<string, unknown> | null;\n // `themeColorTokens` reads nothing but `colors`, so this stands in for\n // the whole theme.\n return colors ? themeColorTokens({ colors }) : [];\n }, [json]);\n}\n\n/** Theme colours as picker chips, in the order the theme declares them. */\nexport function themeColorTokens(theme: ThemeJson): ColorToken[] {\n const colors = theme.colors;\n if (!colors || typeof colors !== 'object') return [];\n const out: ColorToken[] = [];\n for (const [key, value] of Object.entries(\n colors as Record<string, unknown>\n )) {\n const hex = resolveColor(theme, value);\n if (hex) out.push({ key, hex });\n }\n return out;\n}\n","import React, { useCallback, useMemo } from 'react';\nimport { CornerDownRight } from 'lucide-react';\nimport { FORMAT } from '../../lib/env';\nimport {\n colorTokens,\n contrastRatio,\n isHexColor,\n resolveColor,\n type ColorTokenDescriptor,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport { cn } from '../../lib/utils';\nimport {\n ClearButton,\n ContrastBadge,\n EditorSection,\n GroupLabel,\n HINT_CLASS,\n useThemeEditor,\n} from './theme-editor-shared';\nimport {\n ColorControl,\n useThemeColorTokens,\n type ColorToken,\n} from './color-picker';\nimport { matchesQuery } from '../../lib/theme-editor/schema-form';\n\n/**\n * One row per token the schema declares, in the schema's groups. A token may\n * hold a hex or the name of another token; the row shows the resolved swatch\n * either way and says where a reference points, so `accent5: \"primary\"`\n * never looks like a colour of its own.\n */\n\nconst TOKENS = colorTokens(FORMAT);\nconst GROUPS = Array.from(new Set(TOKENS.map((t) => t.group)));\n\ninterface RowState {\n raw: string | undefined;\n resolved: string | null;\n /** The token a reference points at; null for a hex or nothing. */\n reference: string | null;\n error: string | null;\n}\n\nfunction rowState(theme: ThemeJson, token: ColorTokenDescriptor): RowState {\n const colors = theme.colors as Record<string, unknown> | undefined;\n const value = colors?.[token.key];\n const raw = typeof value === 'string' ? value : undefined;\n const resolved = resolveColor(theme, raw);\n const reference =\n raw !== undefined && !isHexColor(raw) && resolved ? raw : null;\n let error: string | null = null;\n if (raw === undefined && value !== undefined) error = 'Must be a string';\n else if (raw === undefined && token.required) error = 'Required';\n else if (raw !== undefined && !resolved) {\n error = /^[a-zA-Z][a-zA-Z0-9]*$/.test(raw)\n ? `No token named \"${raw}\"`\n : 'Not a hex colour';\n }\n return { raw, resolved, reference, error };\n}\n\nconst ColorRow = React.memo(function ColorRow({\n token,\n raw,\n resolved,\n reference,\n error,\n tokens,\n}: { token: ColorTokenDescriptor; tokens: readonly ColorToken[] } & RowState) {\n const { set, remove } = useThemeEditor();\n const commit = useCallback(\n (next: string | null) => {\n if (next === null) remove(['colors', token.key]);\n else set(['colors', token.key], next);\n },\n [remove, set, token.key]\n );\n const clear = useCallback(\n () => remove(['colors', token.key]),\n [remove, token.key]\n );\n const inputId = `theme-color-${token.key}`;\n return (\n <div className=\"flex min-h-8 items-center gap-2\">\n <ColorControl\n id={inputId}\n label={token.label}\n value={raw}\n resolved={resolved}\n onCommit={commit}\n tokens={tokens}\n // Narrow panes give the width back to the token name and its\n // hint; a hex needs 96px and no more.\n className=\"w-[8.5rem] shrink-0 @[30rem]:w-[10.5rem]\"\n />\n <div className=\"flex min-w-0 flex-1 flex-col justify-center\">\n <div className=\"flex min-w-0 items-center gap-1.5\">\n <label htmlFor={inputId} className=\"truncate text-sm\">\n {token.label}\n </label>\n <code className=\"truncate text-[10px] text-muted-foreground\">\n {token.key}\n </code>\n {token.required && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1 text-[10px] tracking-wide text-muted-foreground uppercase\">\n required\n </span>\n )}\n </div>\n <p className={cn(HINT_CLASS, 'truncate')}>\n {error ? (\n <span className=\"text-destructive\">{error}</span>\n ) : reference ? (\n <span className=\"inline-flex items-center gap-1\">\n <CornerDownRight className=\"size-3\" aria-hidden />\n <code>{reference}</code>\n <span>{resolved}</span>\n </span>\n ) : (\n token.hint\n )}\n </p>\n </div>\n {raw !== undefined && !token.required ? (\n <ClearButton label={`Clear ${token.label}`} onClick={clear} />\n ) : (\n <span className=\"size-6 shrink-0\" aria-hidden />\n )}\n </div>\n );\n});\n\nexport function ThemeColorsSection({\n theme,\n query = '',\n}: {\n theme: ThemeJson;\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const rows = useMemo(\n () =>\n TOKENS.filter(\n (token) =>\n matchesQuery(query, 'colours', 'colors') ||\n matchesQuery(query, token.key, token.label, token.group, token.hint)\n ).map((token) => ({ token, ...rowState(theme, token) })),\n [query, theme]\n );\n\n const contrast = useMemo(() => {\n const colors = theme.colors as Record<string, unknown> | undefined;\n const background = resolveColor(theme, colors?.background);\n const text = resolveColor(theme, colors?.text);\n const primary = resolveColor(theme, colors?.primary);\n return {\n text: background && text ? contrastRatio(text, background) : null,\n primary:\n background && primary ? contrastRatio(primary, background) : null,\n };\n }, [theme]);\n\n // Chips inside each picker: every colour this theme already resolves, so a\n // token can be reused without leaving the row it is being set on.\n const tokens = useThemeColorTokens(theme);\n const defined = rows.filter((r) => r.raw !== undefined).length;\n if (searching && rows.length === 0) return null;\n\n return (\n <EditorSection\n title=\"Colours\"\n hint=\"Hex values, or the name of another token to reuse it. Required tokens are what the compiler reads directly; the rest are optional slots.\"\n forceOpen={searching ? true : undefined}\n actions={\n <span className=\"text-[11px] tabular-nums text-muted-foreground\">\n {defined}/{TOKENS.length}\n </span>\n }\n >\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1\">\n <ContrastBadge label=\"Text on background\" ratio={contrast.text} />\n <ContrastBadge label=\"Primary on background\" ratio={contrast.primary} />\n </div>\n {GROUPS.filter((group) =>\n rows.some((row) => row.token.group === group)\n ).map((group) => (\n <div key={group} className=\"flex flex-col gap-1\">\n <GroupLabel>{group}</GroupLabel>\n {rows\n .filter((row) => row.token.group === group)\n .map((row) => (\n <ColorRow\n key={row.token.key}\n token={row.token}\n raw={row.raw}\n resolved={row.resolved}\n reference={row.reference}\n error={row.error}\n tokens={tokens}\n />\n ))}\n </div>\n ))}\n </EditorSection>\n );\n}\n","import React, { useCallback, useMemo, useRef, useState } from 'react';\nimport { Check, ChevronsUpDown, Search, Type } from 'lucide-react';\nimport { Input } from '../ui/input';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { useFontPickerStore } from '../../store/font-picker-store';\nimport type { Path } from '../../lib/theme-editor/model';\nimport { cn } from '../../lib/utils';\nimport {\n HINT_CLASS,\n QuietButton,\n useFontCatalog,\n type FontCatalog,\n} from './theme-editor-shared';\n\n/**\n * A font family as a combobox: the catalog filtered as you type, with the\n * typed text itself always on offer — a theme may legitimately name a face\n * this browser has never heard of, and refusing it would make the form less\n * capable than the JSON it edits.\n *\n * Only a slice of the matches is rendered. The Google list is ~1500 families,\n * and a combobox that has to lay out 1500 rows before it can show the first\n * one stops feeling like a text field.\n */\n\nconst MAX_ROWS = 40;\n\ninterface Option {\n family: string;\n /** \"Safe\" for the OS list, else the Google category. */\n tag: string;\n safe: boolean;\n}\n\nfunction buildOptions(catalog: FontCatalog): Option[] {\n return [\n ...catalog.safe.map((family) => ({ family, tag: 'safe', safe: true })),\n ...catalog.google.map((font) => ({\n family: font.family,\n tag: font.category,\n safe: false,\n })),\n ];\n}\n\nfunction score(family: string, query: string): number {\n const lower = family.toLowerCase();\n if (lower === query) return 0;\n if (lower.startsWith(query)) return 1;\n const index = lower.indexOf(query);\n return index === -1 ? -1 : 2 + index;\n}\n\n/**\n * With a query, the best `MAX_ROWS` matches. Without one, the current family\n * first and the catalog after it.\n *\n * Pinning the current value is what makes the unfiltered list honest: the\n * catalog runs to hundreds of families and only a window of it is rendered,\n * so a theme naming the four-hundredth would otherwise open a list its own\n * value is not in — with the first row highlighted, one Return away from\n * replacing it.\n */\nfunction filterOptions(\n options: Option[],\n query: string,\n current: string | undefined\n): Option[] {\n const trimmed = query.trim().toLowerCase();\n if (!trimmed) {\n if (!current) return options.slice(0, MAX_ROWS);\n const known = options.find((option) => option.family === current);\n const rest = options.filter((option) => option.family !== current);\n return [\n known ?? { family: current, tag: 'current', safe: false },\n ...rest,\n ].slice(0, MAX_ROWS);\n }\n const scored: { option: Option; rank: number }[] = [];\n for (const option of options) {\n const rank = score(option.family, trimmed);\n if (rank !== -1) scored.push({ option, rank });\n }\n scored.sort(\n (a, b) => a.rank - b.rank || Number(b.option.safe) - Number(a.option.safe)\n );\n return scored.slice(0, MAX_ROWS).map((entry) => entry.option);\n}\n\nexport function FamilyCombobox({\n id,\n label,\n value,\n onCommit,\n pickerPath,\n className,\n}: {\n id?: string;\n label: string;\n value: string | undefined;\n onCommit: (next: string | null) => void;\n /** Where the full font dialog writes when \"Browse all\" is used. */\n pickerPath: Path;\n className?: string;\n}) {\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [active, setActive] = useState(0);\n const listRef = useRef<HTMLDivElement | null>(null);\n const catalog = useFontCatalog();\n const options = useMemo(() => buildOptions(catalog), [catalog]);\n const matches = useMemo(\n () => filterOptions(options, query, value),\n [options, query, value]\n );\n\n const typed = query.trim();\n const exact = matches.some(\n (option) => option.family.toLowerCase() === typed.toLowerCase()\n );\n const custom = typed && !exact ? typed : null;\n const rows = custom\n ? [custom, ...matches.map((m) => m.family)]\n : matches.map((m) => m.family);\n\n const choose = useCallback(\n (family: string) => {\n onCommit(family);\n setOpen(false);\n setQuery('');\n },\n [onCommit]\n );\n\n const browse = useCallback(() => {\n setOpen(false);\n useFontPickerStore\n .getState()\n .openFor({ jsonPath: pickerPath, currentValue: value });\n }, [pickerPath, value]);\n\n const onKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n setActive((index) => {\n const next =\n index < 0\n ? event.key === 'ArrowDown'\n ? 0\n : rows.length - 1\n : index + (event.key === 'ArrowDown' ? 1 : -1);\n const last = rows.length - 1;\n const clamped = next < 0 ? last : next > last ? 0 : next;\n listRef.current\n ?.querySelector(`[data-row=\"${clamped}\"]`)\n ?.scrollIntoView({ block: 'nearest' });\n return clamped;\n });\n } else if (event.key === 'Enter') {\n event.preventDefault();\n const family = rows[active];\n if (family) choose(family);\n } else if (event.key === 'Escape') {\n setOpen(false);\n }\n },\n [active, choose, rows]\n );\n\n return (\n <div className={cn('flex min-w-0 items-center gap-1', className)}>\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n // Open on the family that is set, not on row zero: Return is then\n // a no-op on a list the author only meant to look at. A family the\n // catalog does not have and no query has offered leaves nothing\n // highlighted rather than arming a different one.\n if (next) {\n setQuery('');\n setActive(value ? 0 : -1);\n }\n }}\n >\n <PopoverTrigger asChild>\n <button\n id={id}\n type=\"button\"\n role=\"combobox\"\n aria-expanded={open}\n aria-label={label}\n className={cn(\n 'flex h-7 min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded-sm border',\n 'border-input bg-background px-2 text-xs shadow-none transition-colors',\n 'hover:bg-accent/40 focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <Type className=\"size-3 shrink-0 opacity-50\" aria-hidden />\n <span\n className={cn(\n 'min-w-0 flex-1 truncate text-left',\n !value && 'text-muted-foreground'\n )}\n style={\n value\n ? { fontFamily: `\"${value.replace(/\"/g, '')}\", system-ui` }\n : undefined\n }\n >\n {value || 'Inherit'}\n </span>\n <ChevronsUpDown\n className=\"size-3 shrink-0 opacity-50\"\n aria-hidden\n />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"w-72 p-0\" onKeyDown={onKeyDown}>\n <div className=\"flex items-center gap-1.5 border-b px-2\">\n <Search className=\"size-3.5 shrink-0 opacity-50\" aria-hidden />\n <Input\n autoFocus\n value={query}\n onChange={(event) => {\n setQuery(event.target.value);\n setActive(0);\n }}\n placeholder=\"Search fonts…\"\n aria-label={`Search fonts for ${label}`}\n autoComplete=\"off\"\n spellCheck={false}\n // Transparent, not `bg-background`: the popover is its own\n // surface, and the input's default fill would paint a lighter\n // block from the icon to the right edge of the row.\n className=\"h-8 border-0 bg-transparent px-0 text-xs shadow-none focus-visible:ring-0\"\n />\n </div>\n <div\n ref={listRef}\n role=\"listbox\"\n aria-label={`${label} options`}\n className=\"max-h-64 overflow-y-auto p-1\"\n >\n {custom && (\n <Row\n index={0}\n active={active === 0}\n family={custom}\n tag=\"use as typed\"\n selected={value === custom}\n onPick={choose}\n onHover={setActive}\n />\n )}\n {matches.map((option, index) => {\n const row = custom ? index + 1 : index;\n return (\n <Row\n key={`${option.safe ? 's' : 'g'}:${option.family}`}\n index={row}\n active={active === row}\n family={option.family}\n tag={option.tag}\n selected={value === option.family}\n onPick={choose}\n onHover={setActive}\n />\n );\n })}\n {rows.length === 0 && (\n <p className={cn(HINT_CLASS, 'px-2 py-3 text-center')}>\n {catalog.safe.length + catalog.google.length === 0\n ? 'The font catalog is unavailable — type a family name.'\n : 'No family matches.'}\n </p>\n )}\n </div>\n <div className=\"flex items-center justify-between border-t px-1.5 py-1\">\n <QuietButton onClick={browse}>Browse all fonts…</QuietButton>\n {value && (\n <QuietButton\n onClick={() => {\n onCommit(null);\n setOpen(false);\n }}\n >\n Clear\n </QuietButton>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n\nconst Row = React.memo(function Row({\n index,\n active,\n family,\n tag,\n selected,\n onPick,\n onHover,\n}: {\n index: number;\n active: boolean;\n family: string;\n tag: string;\n selected: boolean;\n onPick: (family: string) => void;\n onHover: (index: number) => void;\n}) {\n return (\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={selected}\n data-row={index}\n onMouseMove={() => onHover(index)}\n onClick={() => onPick(family)}\n className={cn(\n 'flex h-7 w-full cursor-pointer items-center gap-2 rounded-sm px-2 text-left text-xs',\n active && 'bg-accent text-accent-foreground'\n )}\n >\n <Check\n className={cn(\n 'size-3 shrink-0',\n selected ? 'opacity-100' : 'opacity-0'\n )}\n aria-hidden\n />\n <span className=\"min-w-0 flex-1 truncate\">{family}</span>\n <span className=\"shrink-0 text-[10px] text-muted-foreground\">{tag}</span>\n </button>\n );\n});\n","import React, { useCallback, useMemo } from 'react';\nimport { FORMAT } from '../../lib/env';\nimport {\n DOCX_FONT_ROLES,\n FONT_ROLE_HINTS,\n PPTX_FONT_ROLES,\n getAt,\n resolveColor,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport {\n DraftNumberInput,\n EditorSection,\n FIELD_LABEL_CLASS,\n GroupLabel,\n HINT_CLASS,\n useThemeEditor,\n} from './theme-editor-shared';\nimport { ColorControl, useThemeColorTokens } from './color-picker';\nimport { FamilyCombobox } from './font-combobox';\nimport { matchesQuery } from '../../lib/theme-editor/schema-form';\n\n/**\n * docx fonts are roles — heading, body, mono, light — each a family and a\n * size the styles inherit. pptx fonts are two family strings, and the\n * sizes live in `defaults`, so the section takes a different shape per\n * format rather than pretending the two agree.\n */\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n return typeof value === 'number' ? value : undefined;\n}\n\nconst DocxRoleCard = React.memo(function DocxRoleCard({\n role,\n family,\n size,\n}: {\n role: string;\n family: string | undefined;\n size: number | undefined;\n}) {\n const { set, remove } = useThemeEditor();\n const commitFamily = useCallback(\n (next: string | null) =>\n next === null\n ? remove(['fonts', role, 'family'])\n : set(['fonts', role, 'family'], next),\n [remove, role, set]\n );\n const commitSize = useCallback(\n (next: number | null) =>\n next === null\n ? remove(['fonts', role, 'size'])\n : set(['fonts', role, 'size'], next),\n [remove, role, set]\n );\n const familyId = `theme-font-${role}-family`;\n const sizeId = `theme-font-${role}-size`;\n return (\n <div className=\"grid grid-cols-[minmax(0,1fr)_6.5rem] gap-x-2 gap-y-1 rounded-sm border border-border/70 p-2\">\n <div className=\"col-span-2 flex items-baseline gap-2\">\n <span className=\"text-sm capitalize\">{role}</span>\n <span className={HINT_CLASS}>{FONT_ROLE_HINTS[role]}</span>\n </div>\n <label htmlFor={familyId} className={FIELD_LABEL_CLASS}>\n Family\n </label>\n <label htmlFor={sizeId} className={FIELD_LABEL_CLASS}>\n Size\n </label>\n <FamilyCombobox\n id={familyId}\n label={`${role} family`}\n value={family}\n onCommit={commitFamily}\n pickerPath={['fonts', role, 'family']}\n />\n <DraftNumberInput\n id={sizeId}\n aria-label={`${role} size`}\n value={size}\n onCommit={commitSize}\n unit=\"pt\"\n min={8}\n max={120}\n step={0.5}\n />\n </div>\n );\n});\n\nconst PptxFamilyRow = React.memo(function PptxFamilyRow({\n role,\n family,\n}: {\n role: string;\n family: string | undefined;\n}) {\n const { set, remove } = useThemeEditor();\n const commit = useCallback(\n (next: string | null) =>\n next === null ? remove(['fonts', role]) : set(['fonts', role], next),\n [remove, role, set]\n );\n const id = `theme-font-${role}`;\n return (\n <div className=\"grid grid-cols-[6rem_minmax(0,1fr)] items-center gap-2\">\n <label htmlFor={id} className=\"flex flex-col\">\n <span className=\"text-sm capitalize\">{role}</span>\n <span className={HINT_CLASS}>{FONT_ROLE_HINTS[role]}</span>\n </label>\n <FamilyCombobox\n id={id}\n label={`${role} family`}\n value={family}\n onCommit={commit}\n pickerPath={['fonts', role]}\n />\n </div>\n );\n});\n\nfunction PptxDefaults({ theme }: { theme: ThemeJson }) {\n const { set, remove } = useThemeEditor();\n const fontSize = asNumber(getAt(theme, ['defaults', 'fontSize']));\n const fontColor = asString(getAt(theme, ['defaults', 'fontColor']));\n const resolved = useMemo(\n () => resolveColor(theme, fontColor),\n [theme, fontColor]\n );\n const tokens = useThemeColorTokens(theme);\n const commitSize = useCallback(\n (next: number | null) =>\n next === null\n ? remove(['defaults', 'fontSize'])\n : set(['defaults', 'fontSize'], next),\n [remove, set]\n );\n const commitColor = useCallback(\n (next: string | null) =>\n next === null\n ? remove(['defaults', 'fontColor'])\n : set(['defaults', 'fontColor'], next),\n [remove, set]\n );\n return (\n <div className=\"flex flex-col gap-2\">\n <GroupLabel>Defaults</GroupLabel>\n <p className={HINT_CLASS}>\n What text falls back to when no style says otherwise.\n </p>\n <div className=\"grid grid-cols-[6rem_minmax(0,1fr)] items-center gap-2\">\n <label htmlFor=\"theme-defaults-size\" className=\"text-sm\">\n Font size\n </label>\n <DraftNumberInput\n id=\"theme-defaults-size\"\n value={fontSize}\n onCommit={commitSize}\n unit=\"pt\"\n min={1}\n max={200}\n step={1}\n className=\"max-w-[7rem]\"\n />\n <label htmlFor=\"theme-defaults-color\" className=\"text-sm\">\n Font colour\n </label>\n <ColorControl\n id=\"theme-defaults-color\"\n label=\"Default font colour\"\n value={fontColor}\n resolved={resolved}\n onCommit={commitColor}\n allowReference={false}\n tokens={tokens}\n className=\"max-w-[12rem]\"\n />\n </div>\n </div>\n );\n}\n\nexport function ThemeTypographySection({\n theme,\n query = '',\n}: {\n theme: ThemeJson;\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const whole = matchesQuery(query, 'typography', 'fonts', 'font');\n const roleMatches = (role: string) =>\n whole || matchesQuery(query, role, FONT_ROLE_HINTS[role]);\n const forceOpen = searching ? true : undefined;\n if (FORMAT === 'docx') {\n const roles = DOCX_FONT_ROLES.filter(roleMatches);\n if (searching && roles.length === 0) return null;\n return (\n <EditorSection\n title=\"Typography\"\n hint=\"Four roles the styles point at. A family beyond the safe list needs a fontRegistry entry on the document to embed; the specimen shows what the browser has.\"\n forceOpen={forceOpen}\n >\n <div className=\"grid grid-cols-1 gap-2 @[34rem]:grid-cols-2\">\n {roles.map((role) => {\n const font = getAt(theme, ['fonts', role]);\n const record =\n font && typeof font === 'object'\n ? (font as Record<string, unknown>)\n : undefined;\n return (\n <DocxRoleCard\n key={role}\n role={role}\n family={asString(record?.family)}\n size={asNumber(record?.size)}\n />\n );\n })}\n </div>\n </EditorSection>\n );\n }\n const roles = PPTX_FONT_ROLES.filter(roleMatches);\n const showDefaults =\n whole || matchesQuery(query, 'defaults', 'font size', 'font colour');\n if (searching && roles.length === 0 && !showDefaults) return null;\n return (\n <EditorSection\n title=\"Typography\"\n hint=\"Two families; every style uses one or names its own face.\"\n forceOpen={forceOpen}\n >\n {roles.length > 0 && (\n <div className=\"flex flex-col gap-2\">\n {roles.map((role) => (\n <PptxFamilyRow\n key={role}\n role={role}\n family={asString(getAt(theme, ['fonts', role]))}\n />\n ))}\n </div>\n )}\n {showDefaults && <PptxDefaults theme={theme} />}\n </EditorSection>\n );\n}\n","import React, { useCallback, useState } from 'react';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../ui/select';\nimport {\n MARGIN_KEYS,\n PAGE_SIZES,\n getAt,\n twipsToUnit,\n unitToTwips,\n type LengthUnit,\n type Path,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport {\n DraftNumberInput,\n EditorSection,\n FIELD_LABEL_CLASS,\n SELECT_TRIGGER_CLASS,\n useThemeEditor,\n} from './theme-editor-shared';\nimport { matchesQuery } from '../../lib/theme-editor/schema-form';\n\n/**\n * docx only. The JSON stores twips because Word does; nobody thinks in\n * twips, so the fields show the author's unit and convert on the way in\n * and out. The unit is a view setting, never written to the theme.\n */\n\nconst CUSTOM = '__custom__';\nconst UNITS: readonly { value: LengthUnit; label: string }[] = [\n { value: 'in', label: 'in' },\n { value: 'cm', label: 'cm' },\n { value: 'pt', label: 'pt' },\n { value: 'twips', label: 'twips' },\n];\nconst STEP: Record<LengthUnit, number> = {\n in: 0.05,\n cm: 0.1,\n pt: 1,\n twips: 10,\n};\n\n/** Module-level paths so the memoised fields see the same array each render. */\nconst MARGIN_PATHS: Record<string, Path> = Object.fromEntries(\n MARGIN_KEYS.map((key) => [key, ['page', 'margins', key]])\n);\nconst WIDTH_PATH: Path = ['page', 'size', 'width'];\nconst HEIGHT_PATH: Path = ['page', 'size', 'height'];\n\nfunction twips(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value)\n ? value\n : undefined;\n}\n\n/** A length in twips at `path`, edited in `unit`. */\nconst LengthField = React.memo(function LengthField({\n id,\n label,\n path,\n value,\n unit,\n}: {\n id: string;\n label: string;\n path: Path;\n value: number | undefined;\n unit: LengthUnit;\n}) {\n const { set, remove } = useThemeEditor();\n const commit = useCallback(\n (next: number | null) =>\n next === null ? remove(path) : set(path, unitToTwips(next, unit)),\n [path, remove, set, unit]\n );\n return (\n <div className=\"flex flex-col gap-1\">\n <label htmlFor={id} className={FIELD_LABEL_CLASS}>\n {label}\n </label>\n <DraftNumberInput\n id={id}\n value={value === undefined ? undefined : twipsToUnit(value, unit)}\n onCommit={commit}\n unit={unit}\n min={0}\n step={STEP[unit]}\n />\n </div>\n );\n});\n\nexport function ThemePageSection({\n theme,\n query = '',\n}: {\n theme: ThemeJson;\n query?: string;\n}) {\n const searching = query.trim() !== '';\n if (\n searching &&\n !matchesQuery(\n query,\n 'page',\n 'size',\n 'margins',\n 'width',\n 'height',\n ...MARGIN_KEYS,\n ...PAGE_SIZES\n )\n )\n return null;\n const { set } = useThemeEditor();\n const [unit, setUnit] = useState<LengthUnit>('in');\n\n const size = getAt(theme, ['page', 'size']);\n const isCustom = !!size && typeof size === 'object';\n const sizeValue =\n typeof size === 'string' && (PAGE_SIZES as readonly string[]).includes(size)\n ? size\n : isCustom\n ? CUSTOM\n : '';\n\n const onSizeChange = useCallback(\n (next: string) => {\n if (next === CUSTOM) {\n // Start the custom box from A4 so the fields are never blank.\n set(['page', 'size'], { width: 11906, height: 16838 });\n } else {\n set(['page', 'size'], next);\n }\n },\n [set]\n );\n\n return (\n <EditorSection\n title=\"Page\"\n hint=\"Paper and margins. Stored in twips (1/1440 in); shown in the unit you pick here.\"\n forceOpen={searching ? true : undefined}\n actions={\n <Select value={unit} onValueChange={(v) => setUnit(v as LengthUnit)}>\n <SelectTrigger\n aria-label=\"Length unit\"\n className=\"h-6 min-h-0 w-auto gap-1 border-transparent bg-transparent px-1.5 text-[11px] shadow-none hover:bg-accent\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {UNITS.map((u) => (\n <SelectItem key={u.value} value={u.value} className=\"text-xs\">\n {u.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n }\n >\n <div className=\"grid grid-cols-[6rem_minmax(0,12rem)] items-center gap-2\">\n <label htmlFor=\"theme-page-size\" className=\"text-sm\">\n Size\n </label>\n <Select value={sizeValue} onValueChange={onSizeChange}>\n <SelectTrigger id=\"theme-page-size\" className={SELECT_TRIGGER_CLASS}>\n <SelectValue placeholder=\"Choose a size\" />\n </SelectTrigger>\n <SelectContent>\n {PAGE_SIZES.map((name) => (\n <SelectItem key={name} value={name} className=\"text-xs\">\n {name}\n </SelectItem>\n ))}\n <SelectItem value={CUSTOM} className=\"text-xs\">\n Custom\n </SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {isCustom && (\n <div className=\"grid grid-cols-2 gap-2 @[34rem]:max-w-[24rem]\">\n <LengthField\n id=\"theme-page-width\"\n label=\"Width\"\n path={WIDTH_PATH}\n value={twips(getAt(theme, WIDTH_PATH))}\n unit={unit}\n />\n <LengthField\n id=\"theme-page-height\"\n label=\"Height\"\n path={HEIGHT_PATH}\n value={twips(getAt(theme, HEIGHT_PATH))}\n unit={unit}\n />\n </div>\n )}\n\n <div className=\"grid grid-cols-2 gap-2 @[30rem]:grid-cols-4\">\n {MARGIN_KEYS.map((key) => (\n <LengthField\n key={key}\n id={`theme-margin-${key}`}\n label={key.charAt(0).toUpperCase() + key.slice(1)}\n path={MARGIN_PATHS[key]}\n value={twips(getAt(theme, MARGIN_PATHS[key]))}\n unit={unit}\n />\n ))}\n </div>\n </EditorSection>\n );\n}\n","import React, { useCallback, useMemo, useState } from 'react';\nimport { ChevronRight, Plus, Trash2 } from 'lucide-react';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../ui/select';\nimport { Input } from '../ui/input';\nimport { FORMAT } from '../../lib/env';\nimport {\n DOCX_FONT_ROLES,\n customStyleNames,\n getAt,\n resolveColor,\n styleFields,\n styleLabel,\n styleNames,\n type Path,\n type StyleFieldDescriptor,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport { cn } from '../../lib/utils';\nimport {\n ClearButton,\n DraftNumberInput,\n DraftTextInput,\n EditorSection,\n FIELD_LABEL_CLASS,\n HINT_CLASS,\n INPUT_CLASS,\n QuietButton,\n SELECT_TRIGGER_CLASS,\n Segmented,\n useThemeEditor,\n} from './theme-editor-shared';\nimport {\n ColorControl,\n useThemeColorTokens,\n type ColorToken,\n} from './color-picker';\nimport { FamilyCombobox } from './font-combobox';\nimport { matchesQuery } from '../../lib/theme-editor/schema-form';\n\n/**\n * The named styles: the schema's slots first, then whatever else the theme\n * defines. Each row is a one-line summary until opened, because fifteen\n * open grids would bury the two the author came to change.\n *\n * Rows are memoised on the style's JSON, not its object: the tab re-parses\n * the whole theme on every write, so identities are new each time and only\n * the text says whether anything in this style moved.\n */\n\nconst NAMES = styleNames(FORMAT);\nconst FIELDS = styleFields(FORMAT);\nconst BASIC = FIELDS.filter((f) => !f.advanced);\nconst ADVANCED = FIELDS.filter((f) => f.advanced);\nconst STYLE_DEPTH = 2; // ['styles', name]\n\nconst BOOLEAN_OPTIONS = [\n { value: 'unset' as const, label: 'Unset' },\n { value: 'off' as const, label: 'Off' },\n { value: 'on' as const, label: 'On' },\n];\n\ntype StyleJson = Record<string, unknown>;\n\nfunction fieldKey(field: StyleFieldDescriptor): string {\n return field.path.join('.');\n}\n\nfunction summarize(style: StyleJson): string {\n const parts: string[] = [];\n const push = (value: unknown) => {\n if (typeof value === 'string' && value) parts.push(value);\n };\n if (FORMAT === 'docx') {\n push(style.font);\n if (typeof style.size === 'number') parts.push(`${style.size}pt`);\n } else {\n push(style.fontFace);\n if (typeof style.fontSize === 'number') parts.push(`${style.fontSize}pt`);\n }\n if (style.bold === true) parts.push('bold');\n if (typeof style.fontWeight === 'number') parts.push(`w${style.fontWeight}`);\n if (style.italic === true) parts.push('italic');\n if (style.underline === true) parts.push('underline');\n push(FORMAT === 'docx' ? style.color : style.fontColor);\n push(FORMAT === 'docx' ? style.alignment : style.align);\n if (parts.length === 0) {\n const keys = Object.keys(style);\n return keys.length === 0 ? 'Defined, nothing set' : keys.join(' · ');\n }\n return parts.join(' · ');\n}\n\n// ---------------------------------------------------------------------------\n// Fields\n// ---------------------------------------------------------------------------\n\ninterface FieldProps {\n styleName: string;\n field: StyleFieldDescriptor;\n value: unknown;\n tokens: readonly ColorToken[];\n resolved: string | null;\n}\n\n/**\n * One control for both ways a style names a colour. The picker offers the\n * theme's own tokens as chips and a hex everywhere else, so the source is a\n * choice inside the control rather than a mode switch beside it.\n */\nfunction ColorField({\n styleName,\n field,\n value,\n tokens,\n resolved,\n onCommit,\n}: FieldProps & { onCommit: (next: string | null) => void }) {\n return (\n <ColorControl\n id={`theme-style-${styleName}-${fieldKey(field)}`}\n label={field.label}\n value={typeof value === 'string' ? value : undefined}\n resolved={resolved}\n onCommit={onCommit}\n tokens={tokens}\n className=\"min-w-0\"\n />\n );\n}\n\nconst StyleField = React.memo(function StyleField(props: FieldProps) {\n const { styleName, field, value } = props;\n const { set, remove } = useThemeEditor();\n const path = useMemo<Path>(\n () => ['styles', styleName, ...field.path],\n [field.path, styleName]\n );\n const clear = useCallback(\n () => remove(path, { keepDepth: STYLE_DEPTH }),\n [path, remove]\n );\n const commitString = useCallback(\n (next: string | null) => (next === null ? clear() : set(path, next)),\n [clear, path, set]\n );\n const commitNumber = useCallback(\n (next: number | null) => (next === null ? clear() : set(path, next)),\n [clear, path, set]\n );\n const id = `theme-style-${styleName}-${fieldKey(field)}`;\n const isSet = value !== undefined;\n\n let control: React.ReactNode;\n switch (field.kind) {\n case 'text':\n control = (\n <DraftTextInput\n id={id}\n value={typeof value === 'string' ? value : undefined}\n onCommit={commitString}\n />\n );\n break;\n case 'number':\n control = (\n <DraftNumberInput\n id={id}\n value={typeof value === 'number' ? value : undefined}\n onCommit={commitNumber}\n unit={field.unit}\n min={field.min}\n max={field.max}\n step={field.step}\n />\n );\n break;\n case 'boolean':\n // Three states, not two. A switch can only be on or off, and a style\n // that says nothing about `bold` is not the same as one that says\n // `false` — the first inherits, the second overrides.\n control = (\n <Segmented<'unset' | 'off' | 'on'>\n label={field.label}\n value={value === undefined ? 'unset' : value === true ? 'on' : 'off'}\n options={BOOLEAN_OPTIONS}\n onChange={(next) =>\n next === 'unset' ? clear() : set(path, next === 'on')\n }\n className=\"h-7\"\n />\n );\n break;\n case 'select':\n control = (\n <Select\n value={typeof value === 'string' ? value : ''}\n onValueChange={(next) => set(path, next)}\n >\n <SelectTrigger id={id} className={SELECT_TRIGGER_CLASS}>\n <SelectValue placeholder=\"Unset\" />\n </SelectTrigger>\n <SelectContent>\n {(field.options ?? []).map((option) => (\n <SelectItem key={option} value={option} className=\"text-xs\">\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n break;\n case 'fontRole':\n control = (\n <Select\n value={typeof value === 'string' ? value : ''}\n onValueChange={(next) => set(path, next)}\n >\n <SelectTrigger id={id} className={SELECT_TRIGGER_CLASS}>\n <SelectValue placeholder=\"Unset\" />\n </SelectTrigger>\n <SelectContent>\n {DOCX_FONT_ROLES.map((role) => (\n <SelectItem key={role} value={role} className=\"text-xs\">\n {role}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n break;\n case 'fontFamily':\n control = (\n <FamilyCombobox\n id={id}\n label={field.label}\n value={typeof value === 'string' ? value : undefined}\n onCommit={commitString}\n pickerPath={path}\n />\n );\n break;\n case 'color':\n control = <ColorField {...props} onCommit={commitString} />;\n break;\n }\n\n return (\n <div className=\"flex min-w-0 flex-col gap-1\">\n <div className=\"flex h-4 items-center justify-between gap-1\">\n <label\n htmlFor={field.kind === 'boolean' ? undefined : id}\n className={cn(FIELD_LABEL_CLASS, isSet && 'text-foreground')}\n title={field.hint}\n >\n {field.label}\n </label>\n {isSet && field.kind !== 'boolean' && (\n <ClearButton\n label={`Clear ${field.label}`}\n onClick={clear}\n className=\"size-5\"\n />\n )}\n </div>\n {control}\n {field.hint && <p className={HINT_CLASS}>{field.hint}</p>}\n </div>\n );\n});\n\n// ---------------------------------------------------------------------------\n// Rows\n// ---------------------------------------------------------------------------\n\ninterface StyleRowProps {\n name: string;\n custom: boolean;\n /** `undefined` when the style is not defined at all. */\n styleJson: string | undefined;\n /** The theme's colour tokens, JSON, so the memo compare stays a `===`. */\n tokensJson: string;\n /** Resolved hex per colour field key, JSON. */\n resolvedJson: string;\n}\n\nconst StyleRow = React.memo(function StyleRow({\n name,\n custom,\n styleJson,\n tokensJson,\n resolvedJson,\n}: StyleRowProps) {\n const { set, remove } = useThemeEditor();\n const [open, setOpen] = useState(false);\n const [more, setMore] = useState(false);\n const style = useMemo<StyleJson | undefined>(\n () => (styleJson === undefined ? undefined : JSON.parse(styleJson)),\n [styleJson]\n );\n const tokens = useMemo(\n () => JSON.parse(tokensJson) as ColorToken[],\n [tokensJson]\n );\n const resolved = useMemo<Record<string, string | null>>(\n () => JSON.parse(resolvedJson),\n [resolvedJson]\n );\n const define = useCallback(() => set(['styles', name], {}), [name, set]);\n const removeStyle = useCallback(\n () => remove(['styles', name]),\n [name, remove]\n );\n const label = styleLabel(name);\n const setCount = style ? Object.keys(style).length : 0;\n\n const renderField = (field: StyleFieldDescriptor) => (\n <StyleField\n key={fieldKey(field)}\n styleName={name}\n field={field}\n value={style ? getAt(style, field.path) : undefined}\n tokens={tokens}\n resolved={resolved[fieldKey(field)] ?? null}\n />\n );\n\n return (\n <div className=\"rounded-sm border border-border/70\">\n <div className=\"flex h-8 items-center gap-1 pr-1\">\n <button\n type=\"button\"\n onClick={() => setOpen((o) => !o)}\n aria-expanded={open}\n className={cn(\n 'flex h-8 min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded-sm px-2 text-left',\n 'transition-colors hover:bg-accent',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <ChevronRight\n aria-hidden\n className={cn(\n 'size-3 shrink-0 text-muted-foreground transition-transform duration-150 ease-out',\n open && 'rotate-90'\n )}\n />\n <span className=\"shrink-0 text-sm\">{label}</span>\n {custom && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1 text-[10px] tracking-wide text-muted-foreground uppercase\">\n custom\n </span>\n )}\n <span className={cn(HINT_CLASS, 'min-w-0 flex-1 truncate')}>\n {style ? summarize(style) : 'Not defined — inherits defaults'}\n </span>\n </button>\n {custom && (\n <button\n type=\"button\"\n onClick={removeStyle}\n aria-label={`Remove style ${name}`}\n title=\"Remove style\"\n className={cn(\n 'flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-sm',\n 'text-muted-foreground/70 transition-colors hover:bg-accent hover:text-destructive',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none'\n )}\n >\n <Trash2 className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </div>\n\n {open && (\n <div className=\"flex flex-col gap-3 border-t border-border/60 px-2 pt-2 pb-3\">\n {!style ? (\n <div className=\"flex items-center gap-3\">\n <span className={HINT_CLASS}>\n Not defined — inherits defaults.\n </span>\n <QuietButton onClick={define}>\n <Plus className=\"size-3\" aria-hidden />\n Define\n </QuietButton>\n </div>\n ) : (\n <>\n <div className=\"grid grid-cols-1 gap-x-4 gap-y-3 @[30rem]:grid-cols-2\">\n {BASIC.map(renderField)}\n </div>\n {ADVANCED.length > 0 && (\n <>\n <div className=\"flex items-center gap-2\">\n <QuietButton\n onClick={() => setMore((m) => !m)}\n aria-expanded={more}\n >\n <ChevronRight\n aria-hidden\n className={cn(\n 'size-3 transition-transform duration-150 ease-out',\n more && 'rotate-90'\n )}\n />\n More\n </QuietButton>\n <span className={HINT_CLASS}>\n {ADVANCED.length} more fields\n {setCount > 0 &&\n ` · ${setCount} key${setCount === 1 ? '' : 's'} set`}\n </span>\n </div>\n {more && (\n <div className=\"grid grid-cols-1 gap-x-4 gap-y-3 @[30rem]:grid-cols-2\">\n {ADVANCED.map(renderField)}\n </div>\n )}\n </>\n )}\n </>\n )}\n </div>\n )}\n </div>\n );\n});\n\n// ---------------------------------------------------------------------------\n// Add custom style (docx)\n// ---------------------------------------------------------------------------\n\nfunction AddCustomStyle({ existing }: { existing: Set<string> }) {\n const { set } = useThemeEditor();\n const [open, setOpen] = useState(false);\n const [name, setName] = useState('');\n const trimmed = name.trim();\n const problem = !trimmed\n ? null\n : existing.has(trimmed)\n ? 'A style with this name exists'\n : /\\s/.test(trimmed)\n ? 'No spaces — this is the style id a document names'\n : null;\n const submit = () => {\n if (!trimmed || problem) return;\n set(['styles', trimmed], {});\n setName('');\n setOpen(false);\n };\n if (!open) {\n return (\n <QuietButton onClick={() => setOpen(true)}>\n <Plus className=\"size-3\" aria-hidden />\n Add custom style\n </QuietButton>\n );\n }\n return (\n <form\n className=\"flex flex-wrap items-center gap-2\"\n onSubmit={(e) => {\n e.preventDefault();\n submit();\n }}\n >\n <label htmlFor=\"theme-new-style\" className=\"text-xs\">\n New style\n </label>\n {/* Plain controlled input: the name is local state until \"Add\", so\n the draft-on-blur behaviour of the field inputs would only get in\n the way of the validation message updating as you type. */}\n <Input\n id=\"theme-new-style\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. callout\"\n autoComplete=\"off\"\n spellCheck={false}\n autoFocus\n className={cn(INPUT_CLASS, 'w-40')}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setOpen(false);\n }}\n />\n <QuietButton type=\"submit\" disabled={!trimmed || !!problem}>\n Add\n </QuietButton>\n <QuietButton onClick={() => setOpen(false)}>Cancel</QuietButton>\n {problem && (\n <span className=\"text-[11px] text-destructive\">{problem}</span>\n )}\n </form>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Section\n// ---------------------------------------------------------------------------\n\nexport function ThemeStylesSection({\n theme,\n query = '',\n}: {\n theme: ThemeJson;\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const tokens = useThemeColorTokens(theme);\n const tokensJson = useMemo(() => JSON.stringify(tokens), [tokens]);\n const custom = useMemo(() => customStyleNames(theme, FORMAT), [theme]);\n const rows = useMemo(() => {\n const styles = theme.styles;\n const table =\n styles && typeof styles === 'object' && !Array.isArray(styles)\n ? (styles as Record<string, unknown>)\n : {};\n const colorFields = FIELDS.filter((f) => f.kind === 'color');\n const row = (name: string, isCustom: boolean): StyleRowProps => {\n const style = table[name];\n const defined = !!style && typeof style === 'object';\n const resolved: Record<string, string | null> = {};\n for (const field of colorFields) {\n resolved[fieldKey(field)] = defined\n ? resolveColor(theme, getAt(style, field.path))\n : null;\n }\n return {\n name,\n custom: isCustom,\n styleJson: defined ? JSON.stringify(style) : undefined,\n tokensJson,\n resolvedJson: JSON.stringify(resolved),\n };\n };\n const all = [\n ...NAMES.map((name) => row(name, false)),\n ...custom.map((name) => row(name, true)),\n ];\n return matchesQuery(query, 'styles', 'style')\n ? all\n : all.filter((entry) =>\n matchesQuery(query, entry.name, styleLabel(entry.name))\n );\n }, [theme, tokensJson, custom, query]);\n\n const existing = useMemo(() => new Set([...NAMES, ...custom]), [custom]);\n const definedCount = rows.filter((r) => r.styleJson !== undefined).length;\n if (searching && rows.length === 0) return null;\n\n return (\n <EditorSection\n title=\"Styles\"\n hint={\n FORMAT === 'docx'\n ? 'Paragraph styles a document names with themeStyle. A colour may be a token or a hex; sizes are points.'\n : 'Text presets a slide names by style. Sizes are points; a colour may be a token or a hex.'\n }\n forceOpen={searching ? true : undefined}\n actions={\n <span className=\"text-[11px] tabular-nums text-muted-foreground\">\n {definedCount}/{rows.length}\n </span>\n }\n >\n <div className=\"flex flex-col gap-1\">\n {rows.map((row) => (\n <StyleRow key={row.name} {...row} />\n ))}\n </div>\n {FORMAT === 'docx' && <AddCustomStyle existing={existing} />}\n </EditorSection>\n );\n}\n","import React, { useCallback, useMemo } from 'react';\nimport { Braces, Plus } from 'lucide-react';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '../ui/select';\nimport { getAt, type Path, type ThemeJson } from '../../lib/theme-editor/model';\nimport {\n fieldValueError,\n filterFields,\n matchesQuery,\n resolveThemeColor,\n summarizeValue,\n type SchemaField,\n type SchemaSection,\n} from '../../lib/theme-editor/schema-form';\nimport { cn } from '../../lib/utils';\nimport {\n ClearButton,\n DraftNumberInput,\n DraftTextInput,\n EditorSection,\n GroupLabel,\n HINT_CLASS,\n QuietButton,\n SELECT_TRIGGER_CLASS,\n Segmented,\n useThemeEditor,\n} from './theme-editor-shared';\nimport {\n ColorControl,\n useThemeColorTokens,\n type ColorToken,\n} from './color-picker';\n\n/**\n * A section for one extended theme key, rendered from its schema: every\n * property the schema names is a row with the control its type wants, its\n * description as the hint, and a clear that removes the key (pruning the\n * empty parents it leaves behind, so a theme never carries `\"motif\": {}`).\n * What the schema cannot express as one control is shown with its value\n * and a way to the JSON view.\n */\n\nconst UNSET = '__unset__';\nconst BOOLEAN_OPTIONS = [\n { value: 'unset' as const, label: 'Unset' },\n { value: 'off' as const, label: 'Off' },\n { value: 'on' as const, label: 'On' },\n];\n\nfunction fieldId(path: Path): string {\n return `theme-schema-${path.join('-')}`;\n}\n\n/** The depth below which a cleared key's empty parents are pruned. */\nconst SECTION_DEPTH = 1;\n\nconst ScalarControl = React.memo(function ScalarControl({\n field,\n value,\n theme,\n tokens,\n onOpenJson,\n}: {\n field: SchemaField;\n value: unknown;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n}) {\n const { set, remove } = useThemeEditor();\n const path = field.path;\n const clear = useCallback(\n () => remove(path, { keepDepth: SECTION_DEPTH }),\n [path, remove]\n );\n const commitString = useCallback(\n (next: string | null) => (next === null ? clear() : set(path, next)),\n [clear, path, set]\n );\n const commitNumber = useCallback(\n (next: number | null) => (next === null ? clear() : set(path, next)),\n [clear, path, set]\n );\n const id = fieldId(path);\n const error = fieldValueError(field, value);\n if (error) {\n return (\n <JsonOnly\n summary={`${error}: ${summarizeValue(value)}`}\n onOpenJson={onOpenJson}\n onClear={clear}\n />\n );\n }\n switch (field.kind) {\n case 'text':\n return (\n <DraftTextInput\n id={id}\n value={typeof value === 'string' ? value : undefined}\n onCommit={commitString}\n />\n );\n case 'number':\n return (\n <DraftNumberInput\n id={id}\n value={typeof value === 'number' ? value : undefined}\n onCommit={commitNumber}\n min={field.min}\n max={field.max}\n step={field.integer ? 1 : 0.5}\n />\n );\n case 'boolean':\n return (\n <Segmented<'unset' | 'off' | 'on'>\n label={field.label}\n value={value === undefined ? 'unset' : value === true ? 'on' : 'off'}\n options={BOOLEAN_OPTIONS}\n onChange={(next) =>\n next === 'unset' ? clear() : set(path, next === 'on')\n }\n className=\"h-7\"\n />\n );\n case 'enum':\n return (\n <Select\n value={typeof value === 'string' ? value : UNSET}\n onValueChange={(next) => (next === UNSET ? clear() : set(path, next))}\n >\n <SelectTrigger\n id={id}\n aria-label={field.label}\n className={SELECT_TRIGGER_CLASS}\n >\n <SelectValue placeholder=\"Unset\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={UNSET}>Unset</SelectItem>\n {(field.options ?? []).map((option) => (\n <SelectItem key={option} value={option}>\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n case 'color':\n return (\n <ColorControl\n id={id}\n label={field.label}\n value={typeof value === 'string' ? value : undefined}\n resolved={resolveThemeColor(theme, value)}\n onCommit={commitString}\n tokens={tokens}\n className=\"min-w-0\"\n />\n );\n default:\n return (\n <JsonOnly\n summary={summarizeValue(value)}\n onOpenJson={onOpenJson}\n onClear={value === undefined ? undefined : clear}\n />\n );\n }\n});\n\n/** A value the form shows but leaves to the JSON view. */\nfunction JsonOnly({\n summary,\n onOpenJson,\n onClear,\n}: {\n summary: string;\n onOpenJson: () => void;\n onClear?: () => void;\n}) {\n return (\n <div className=\"flex h-7 min-w-0 items-center gap-1\">\n <span className=\"min-w-0 flex-1 truncate text-xs text-muted-foreground\">\n {summary}\n </span>\n <QuietButton onClick={onOpenJson}>\n <Braces className=\"size-3\" aria-hidden />\n JSON\n </QuietButton>\n {onClear && <ClearButton label=\"Clear\" onClick={onClear} />}\n </div>\n );\n}\n\n/** An array of scalars: one row per entry, add at the end, clear per entry. */\nconst ListControl = React.memo(function ListControl({\n field,\n value,\n theme,\n tokens,\n onOpenJson,\n}: {\n field: SchemaField;\n value: unknown;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n}) {\n const { set, remove } = useThemeEditor();\n const entries = Array.isArray(value) ? value : [];\n const item = field.item!;\n const add = useCallback(() => {\n const seed =\n item.kind === 'number'\n ? item.min ?? 0\n : item.kind === 'boolean'\n ? true\n : '';\n set(field.path, [...entries, seed]);\n }, [entries, field.path, item.kind, item.min, set]);\n const full = field.max !== undefined && entries.length >= field.max;\n if (value !== undefined && !Array.isArray(value)) {\n return (\n <JsonOnly\n summary={`Not a list: ${summarizeValue(value)}`}\n onOpenJson={onOpenJson}\n onClear={() => remove(field.path, { keepDepth: SECTION_DEPTH })}\n />\n );\n }\n return (\n <div className=\"flex flex-col gap-1\">\n {entries.map((entry, index) => {\n const entryField: SchemaField = {\n ...item,\n key: String(index),\n label: `${field.label} ${index + 1}`,\n path: [...field.path, index],\n };\n return (\n <div key={index} className=\"flex items-center gap-1\">\n <div className=\"min-w-0 flex-1\">\n <ListEntry\n field={entryField}\n value={entry}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n onRemove={() => {\n const next = entries.filter((_, i) => i !== index);\n if (next.length === 0)\n remove(field.path, { keepDepth: SECTION_DEPTH });\n else set(field.path, next);\n }}\n />\n </div>\n </div>\n );\n })}\n {!full && (\n <QuietButton onClick={add} className=\"self-start\">\n <Plus className=\"size-3\" aria-hidden />\n Add\n </QuietButton>\n )}\n </div>\n );\n});\n\n/**\n * One list entry. Clearing an entry removes it from the list rather than\n * leaving a hole, which is what a clear on an array member has to mean.\n */\nfunction ListEntry({\n field,\n value,\n theme,\n tokens,\n onOpenJson,\n onRemove,\n}: {\n field: SchemaField;\n value: unknown;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n onRemove: () => void;\n}) {\n const { set } = useThemeEditor();\n const commitString = useCallback(\n (next: string | null) =>\n next === null ? onRemove() : set(field.path, next),\n [field.path, onRemove, set]\n );\n const commitNumber = useCallback(\n (next: number | null) =>\n next === null ? onRemove() : set(field.path, next),\n [field.path, onRemove, set]\n );\n const id = fieldId(field.path);\n let control: React.ReactNode;\n switch (field.kind) {\n case 'color':\n control = (\n <ColorControl\n id={id}\n label={field.label}\n value={typeof value === 'string' ? value : undefined}\n resolved={resolveThemeColor(theme, value)}\n onCommit={commitString}\n tokens={tokens}\n className=\"min-w-0\"\n />\n );\n break;\n case 'number':\n control = (\n <DraftNumberInput\n id={id}\n value={typeof value === 'number' ? value : undefined}\n onCommit={commitNumber}\n min={field.min}\n max={field.max}\n step={field.integer ? 1 : 0.5}\n />\n );\n break;\n case 'enum':\n control = (\n <Select\n value={typeof value === 'string' ? value : UNSET}\n onValueChange={(next) =>\n next === UNSET ? onRemove() : set(field.path, next)\n }\n >\n <SelectTrigger\n id={id}\n aria-label={field.label}\n className={SELECT_TRIGGER_CLASS}\n >\n <SelectValue placeholder=\"Unset\" />\n </SelectTrigger>\n <SelectContent>\n {(field.options ?? []).map((option) => (\n <SelectItem key={option} value={option}>\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n break;\n case 'text':\n control = (\n <DraftTextInput\n id={id}\n value={typeof value === 'string' ? value : undefined}\n onCommit={commitString}\n />\n );\n break;\n default:\n control = (\n <JsonOnly summary={summarizeValue(value)} onOpenJson={onOpenJson} />\n );\n }\n return (\n <div className=\"flex items-center gap-1\">\n <div className=\"min-w-0 flex-1\">{control}</div>\n <ClearButton label={`Remove ${field.label}`} onClick={onRemove} />\n </div>\n );\n}\n\nconst FieldRow = React.memo(function FieldRow({\n field,\n value,\n theme,\n tokens,\n onOpenJson,\n}: {\n field: SchemaField;\n value: unknown;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n}) {\n const { remove } = useThemeEditor();\n const isSet = value !== undefined;\n const id = fieldId(field.path);\n const clear = useCallback(\n () => remove(field.path, { keepDepth: SECTION_DEPTH }),\n [field.path, remove]\n );\n const clearable =\n isSet &&\n field.kind !== 'list' &&\n field.kind !== 'json' &&\n !fieldValueError(field, value);\n return (\n <div className=\"grid grid-cols-[minmax(0,1fr)_minmax(0,12rem)_1.5rem] items-start gap-x-2 gap-y-0.5 @[30rem]:grid-cols-[minmax(0,1fr)_minmax(0,16rem)_1.5rem]\">\n <label htmlFor={id} className=\"flex min-w-0 flex-col pt-1.5\">\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <span\n className={cn(\n 'truncate text-sm',\n !isSet && 'text-muted-foreground'\n )}\n >\n {field.label}\n </span>\n <code className=\"truncate text-[10px] text-muted-foreground\">\n {field.key}\n </code>\n {field.required && (\n <span className=\"shrink-0 rounded-sm bg-muted px-1 text-[10px] tracking-wide text-muted-foreground uppercase\">\n required\n </span>\n )}\n </span>\n {field.hint && (\n <span className={cn(HINT_CLASS, 'line-clamp-2')}>{field.hint}</span>\n )}\n </label>\n <div className=\"min-w-0 pt-0.5\">\n {field.kind === 'list' ? (\n <ListControl\n field={field}\n value={value}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n />\n ) : (\n <ScalarControl\n field={field}\n value={value}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n />\n )}\n </div>\n <div className=\"pt-0.5\">\n {clearable && (\n <ClearButton label={`Clear ${field.label}`} onClick={clear} />\n )}\n </div>\n </div>\n );\n});\n\n/** A group: its label, then its children one level in. */\nfunction GroupRows({\n field,\n theme,\n tokens,\n onOpenJson,\n depth,\n}: {\n field: SchemaField;\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n depth: number;\n}) {\n const value = getAt(theme, field.path);\n const error = fieldValueError(field, value);\n const { remove } = useThemeEditor();\n return (\n <div\n className={cn(\n 'flex flex-col gap-2',\n depth > 0 && 'border-l border-border/60 pl-3'\n )}\n data-crumb={field.label}\n >\n <div className=\"flex items-baseline gap-2\">\n <GroupLabel>{field.label}</GroupLabel>\n <code className=\"text-[10px] text-muted-foreground\">{field.key}</code>\n {value === undefined && (\n <span className={HINT_CLASS}>Not defined — inherits defaults</span>\n )}\n </div>\n {field.hint && <p className={cn(HINT_CLASS, '-mt-1')}>{field.hint}</p>}\n {error ? (\n <JsonOnly\n summary={`${error}: ${summarizeValue(value)}`}\n onOpenJson={onOpenJson}\n onClear={() => remove(field.path, { keepDepth: SECTION_DEPTH })}\n />\n ) : (\n <Rows\n fields={field.children ?? []}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n depth={depth + 1}\n />\n )}\n </div>\n );\n}\n\nfunction Rows({\n fields,\n theme,\n tokens,\n onOpenJson,\n depth,\n}: {\n fields: readonly SchemaField[];\n theme: ThemeJson;\n tokens: readonly ColorToken[];\n onOpenJson: () => void;\n depth: number;\n}) {\n return (\n <div className=\"flex flex-col gap-2\">\n {fields.map((field) =>\n field.kind === 'group' ? (\n <GroupRows\n key={field.key}\n field={field}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n depth={depth}\n />\n ) : (\n <FieldRow\n key={field.key}\n field={field}\n value={getAt(theme, field.path)}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n />\n )\n )}\n </div>\n );\n}\n\nexport function ThemeSchemaSection({\n section,\n theme,\n query,\n onOpenJson,\n}: {\n section: SchemaSection;\n theme: ThemeJson;\n query: string;\n onOpenJson: () => void;\n}) {\n const tokens = useThemeColorTokens(theme);\n const defined = theme[section.key] !== undefined;\n const fields = useMemo(\n () =>\n matchesQuery(query, section.key, section.title, section.hint)\n ? section.fields\n : filterFields(section.fields, query),\n [query, section]\n );\n if (query.trim() && fields.length === 0) return null;\n return (\n <EditorSection\n title={section.title}\n hint={section.hint}\n defaultOpen={defined}\n forceOpen={query.trim() ? true : undefined}\n actions={\n <QuietButton onClick={onOpenJson}>\n <Braces className=\"size-3\" aria-hidden />\n JSON\n </QuietButton>\n }\n >\n {!defined && (\n <p className={HINT_CLASS}>\n Not defined — inherits defaults. Set a field to define it.\n </p>\n )}\n <Rows\n fields={fields}\n theme={theme}\n tokens={tokens}\n onOpenJson={onOpenJson}\n depth={0}\n />\n </EditorSection>\n );\n}\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Braces, Search, X } from 'lucide-react';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { ScrollArea } from '../ui/scroll-area';\nimport { FORMAT } from '../../lib/env';\nimport {\n advancedKeys,\n deleteAt,\n ensureContainers,\n formKeys,\n getAt,\n parseTheme,\n serializeTheme,\n setAt,\n type Path,\n type ThemeJson,\n} from '../../lib/theme-editor/model';\nimport {\n extendedSections,\n matchesQuery,\n type SchemaSection,\n} from '../../lib/theme-editor/schema-form';\nimport { fetchThemeJsonSchema } from '../../lib/theme-json-schema';\nimport {\n DraftTextInput,\n EditorSection,\n HINT_CLASS,\n INPUT_CLASS,\n QuietButton,\n ThemeEditorProvider,\n useThemeEditor,\n type ThemeEditorActions,\n} from './theme-editor-shared';\nimport { cn } from '../../lib/utils';\nimport { ThemeColorsSection } from './theme-colors-section';\nimport { ThemeTypographySection } from './theme-typography-section';\nimport { ThemePageSection } from './theme-page-section';\nimport { ThemeStylesSection } from './theme-styles-section';\nimport { ThemeSchemaSection } from './theme-schema-section';\n\n/**\n * The sections the theme schema adds beyond the hand-built ones — palette,\n * type roles and scale, spacing, chrome, motif, component defaults — derived\n * once the schema arrives from the server. Until then those keys sit in the\n * Advanced list exactly as before.\n */\nfunction useExtendedSections(): SchemaSection[] {\n const [sections, setSections] = useState<SchemaSection[]>([]);\n useEffect(() => {\n let cancelled = false;\n fetchThemeJsonSchema()\n .then((schema) => {\n if (!cancelled) setSections(extendedSections(schema, formKeys(FORMAT)));\n })\n .catch((error) => {\n console.warn('[theme editor] schema unavailable:', error);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n return sections;\n}\n\n/**\n * The theme as a form.\n *\n * The tab owns the text; this component owns nothing. Every render parses\n * `text` and derives the form from it, and every edit is a pure change to\n * that parse written back through `onChange`. That is what keeps the two\n * views of a theme (this one and Monaco) from ever holding different files.\n *\n * `set` and `remove` are stable for the life of the editor and read the\n * latest parse from a ref, so memoised rows keep their identity across\n * writes and only the row whose value changed re-renders.\n */\n\nexport function ThemeVisualEditor({\n docName,\n text,\n onChange,\n onOpenJson,\n usedBy = [],\n nameClash = [],\n}: {\n docName: string;\n text: string;\n onChange: (text: string) => void;\n onOpenJson: () => void;\n /** Open documents whose `props.theme` names this theme. */\n usedBy?: readonly string[];\n /** Other open theme files that declare the same name. */\n nameClash?: readonly string[];\n}) {\n const parsed = useMemo(() => parseTheme(text), [text]);\n\n const latest = useRef<{\n theme: ThemeJson | null;\n onChange: (text: string) => void;\n }>({ theme: null, onChange });\n latest.current.theme = parsed.ok ? parsed.theme : null;\n latest.current.onChange = onChange;\n\n const update = useCallback((fn: (theme: ThemeJson) => ThemeJson) => {\n const current = latest.current.theme;\n // Never write over text the author is mid-way through fixing in JSON.\n if (!current) return;\n const next = fn(current);\n if (next === current) return;\n // Two edits in one tick (a picker firing twice, a switch and a clear)\n // must compose rather than the second clobbering the first, so the ref\n // moves ahead of the render that will confirm it.\n latest.current.theme = next;\n latest.current.onChange(serializeTheme(next));\n }, []);\n\n const set = useCallback(\n (path: Path, value: unknown) =>\n update((theme) => {\n const head = path[0];\n const container = typeof head === 'string' ? theme[head] : undefined;\n const base =\n path.length > 1 && (!container || typeof container !== 'object')\n ? ensureContainers(theme, FORMAT)\n : theme;\n return setAt(base, path, value);\n }),\n [update]\n );\n\n const remove = useCallback(\n (path: Path, prune?: { keepDepth: number }) =>\n update((theme) => {\n let next = deleteAt(theme, path);\n if (!prune) return next;\n let parent = path.slice(0, -1);\n while (parent.length > prune.keepDepth) {\n const value = getAt(next, parent);\n const emptyObject =\n !!value &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n Object.keys(value as object).length === 0;\n if (!emptyObject) break;\n next = deleteAt(next, parent);\n parent = parent.slice(0, -1);\n }\n return next;\n }),\n [update]\n );\n\n const actions = useMemo<ThemeEditorActions>(\n () => ({ set, remove }),\n [set, remove]\n );\n\n if (!parsed.ok) {\n return (\n <div className=\"flex h-full flex-col items-start gap-3 p-4\">\n <p className=\"text-sm text-muted-foreground\">\n The theme JSON has an error:{' '}\n <span className=\"text-destructive\">{parsed.error}</span>\n </p>\n <p className={HINT_CLASS}>\n The form stays read-only until the file parses, so nothing you typed\n in JSON is overwritten.\n </p>\n <Button variant=\"outline\" size=\"sm\" onClick={onOpenJson}>\n <Braces aria-hidden />\n Open JSON\n </Button>\n </div>\n );\n }\n\n const theme = parsed.theme;\n\n return (\n <ThemeEditorProvider value={actions}>\n <ThemeForm\n docName={docName}\n theme={theme}\n usedBy={usedBy}\n nameClash={nameClash}\n onOpenJson={onOpenJson}\n />\n </ThemeEditorProvider>\n );\n}\n\n/**\n * Where the reader is: the section, and the groups inside it, that the\n * sticky bar is currently cutting through. Every section and schema group\n * carries a `data-crumb`; the ones whose box spans the bar's bottom edge are\n * the nesting chain, outermost first. Recomputed on scroll and on any change\n * to the form's height (a section opening, a search narrowing the rows).\n */\nfunction useScrollCrumb(barRef: React.RefObject<HTMLDivElement | null>) {\n const [crumb, setCrumb] = useState<string[]>([]);\n useEffect(() => {\n const bar = barRef.current;\n const viewport = bar?.closest<HTMLElement>(\n '[data-radix-scroll-area-viewport]'\n );\n if (!bar || !viewport) return;\n let frame: number | null = null;\n const measure = () => {\n frame = null;\n const line = bar.getBoundingClientRect().bottom + 1;\n const chain: string[] = [];\n for (const element of viewport.querySelectorAll<HTMLElement>(\n '[data-crumb]'\n )) {\n const box = element.getBoundingClientRect();\n if (box.top <= line && box.bottom > line)\n chain.push(element.dataset.crumb ?? '');\n }\n setCrumb((previous) =>\n previous.length === chain.length &&\n previous.every((entry, index) => entry === chain[index])\n ? previous\n : chain\n );\n };\n const schedule = () => {\n if (frame === null) frame = requestAnimationFrame(measure);\n };\n measure();\n viewport.addEventListener('scroll', schedule, { passive: true });\n const observer = new ResizeObserver(schedule);\n observer.observe(viewport);\n for (const child of viewport.children) observer.observe(child);\n return () => {\n if (frame !== null) cancelAnimationFrame(frame);\n viewport.removeEventListener('scroll', schedule);\n observer.disconnect();\n };\n }, [barRef]);\n return crumb;\n}\n\n/**\n * The sections, behind a search box. The query filters every section's rows\n * by key, label and hint and holds the survivors open; a section with\n * nothing left steps aside. Cleared, everything is back where it was. The\n * bar also names the section being scrolled through, so a long form never\n * loses the reader.\n */\nfunction ThemeForm({\n docName,\n theme,\n usedBy,\n nameClash,\n onOpenJson,\n}: {\n docName: string;\n theme: ThemeJson;\n usedBy: readonly string[];\n nameClash: readonly string[];\n onOpenJson: () => void;\n}) {\n const [query, setQuery] = useState('');\n const extended = useExtendedSections();\n const extendedKeys = useMemo(\n () => extended.map((section) => section.key),\n [extended]\n );\n const barRef = useRef<HTMLDivElement>(null);\n const crumb = useScrollCrumb(barRef);\n return (\n <ScrollArea className=\"h-full\">\n {/* Keyed by document so section disclosure resets per file. */}\n <div\n key={docName}\n className=\"@container mx-auto flex w-full max-w-[760px] flex-col gap-2 px-4 pt-1 pb-8\"\n >\n <div\n ref={barRef}\n className=\"sticky top-0 z-10 -mx-1 bg-background/95 px-1 py-1.5 backdrop-blur\"\n >\n {/* The section under the bar, so a long form says where you are. */}\n <div\n aria-live=\"polite\"\n className={cn(\n 'flex h-4 items-center gap-1 truncate px-1 text-[10px] tracking-[0.08em] text-muted-foreground uppercase',\n crumb.length === 0 && 'invisible'\n )}\n >\n {crumb.map((entry, index) => (\n <React.Fragment key={`${index}-${entry}`}>\n {index > 0 && (\n <span aria-hidden className=\"text-muted-foreground/50\">\n ›\n </span>\n )}\n <span\n className={cn(\n index === crumb.length - 1 && 'text-foreground/80'\n )}\n >\n {entry}\n </span>\n </React.Fragment>\n ))}\n </div>\n <div className=\"relative\">\n <Search\n aria-hidden\n className=\"pointer-events-none absolute top-1/2 left-2 size-3.5 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Escape') setQuery('');\n }}\n placeholder=\"Find a setting… (motif, tracking, safe area)\"\n aria-label=\"Find a theme setting\"\n autoComplete=\"off\"\n spellCheck={false}\n className={cn(INPUT_CLASS, 'h-8 pr-7 pl-7')}\n />\n {query && (\n <button\n type=\"button\"\n onClick={() => setQuery('')}\n aria-label=\"Clear search\"\n className=\"absolute top-1/2 right-1 flex size-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-sm text-muted-foreground hover:text-foreground\"\n >\n <X className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </div>\n </div>\n <IdentitySection\n theme={theme}\n usedBy={usedBy}\n nameClash={nameClash}\n query={query}\n />\n <ThemeColorsSection theme={theme} query={query} />\n <ThemeTypographySection theme={theme} query={query} />\n {FORMAT === 'docx' && <ThemePageSection theme={theme} query={query} />}\n <ThemeStylesSection theme={theme} query={query} />\n {extended.map((section) => (\n <ThemeSchemaSection\n key={section.key}\n section={section}\n theme={theme}\n query={query}\n onOpenJson={onOpenJson}\n />\n ))}\n <AdvancedSection\n theme={theme}\n onOpenJson={onOpenJson}\n alsoHandled={extendedKeys}\n query={query}\n />\n </div>\n </ScrollArea>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Identity\n// ---------------------------------------------------------------------------\n\nconst IDENTITY_FIELDS: Record<\n string,\n readonly { key: string; label: string; hint?: string }[]\n> = {\n docx: [\n { key: 'name', label: 'Name', hint: 'What a document puts in \"theme\"' },\n { key: 'displayName', label: 'Display name' },\n { key: 'description', label: 'Description' },\n { key: 'version', label: 'Version' },\n ],\n pptx: [\n { key: 'name', label: 'Name', hint: 'What a document puts in \"theme\"' },\n { key: 'displayName', label: 'Display name' },\n { key: 'description', label: 'Description' },\n { key: 'version', label: 'Version' },\n ],\n};\n\nfunction IdentityField({\n fieldKey,\n label,\n hint,\n value,\n}: {\n fieldKey: string;\n label: string;\n hint?: string;\n value: string | undefined;\n}) {\n const { set, remove } = useThemeEditor();\n const commit = useCallback(\n (next: string | null) =>\n next === null ? remove([fieldKey]) : set([fieldKey], next),\n [fieldKey, remove, set]\n );\n const id = `theme-identity-${fieldKey}`;\n return (\n <>\n <label htmlFor={id} className=\"flex flex-col pt-1.5 text-sm\">\n {label}\n {hint && <span className={HINT_CLASS}>{hint}</span>}\n </label>\n <DraftTextInput\n id={id}\n value={value}\n onCommit={commit}\n className={fieldKey === 'name' ? 'font-mono' : undefined}\n />\n </>\n );\n}\n\nfunction IdentitySection({\n theme,\n usedBy,\n nameClash,\n query = '',\n}: {\n theme: ThemeJson;\n usedBy: readonly string[];\n nameClash: readonly string[];\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const fields = matchesQuery(query, 'identity', 'name')\n ? IDENTITY_FIELDS[FORMAT]\n : IDENTITY_FIELDS[FORMAT].filter((field) =>\n matchesQuery(query, field.key, field.label, field.hint)\n );\n if (searching && fields.length === 0) return null;\n return (\n <EditorSection\n title=\"Identity\"\n hint=\"A document picks this theme by its name; the rest is what the library shows.\"\n forceOpen={searching ? true : undefined}\n >\n <div className=\"grid grid-cols-[7rem_minmax(0,1fr)] items-start gap-x-3 gap-y-2\">\n {fields.map((field) => {\n const value = theme[field.key];\n return (\n <IdentityField\n key={field.key}\n fieldKey={field.key}\n label={field.label}\n hint={field.hint}\n value={typeof value === 'string' ? value : undefined}\n />\n );\n })}\n </div>\n {/* Renaming a theme orphans every document that names it; say who\n that is before the field is touched, not after. */}\n <p className={cn(HINT_CLASS, 'mt-2')}>\n {usedBy.length > 0 ? (\n <>\n Used by{' '}\n {usedBy.map((name, index) => (\n <React.Fragment key={name}>\n {index > 0 && ', '}\n <code className=\"rounded-sm bg-muted px-1 py-0.5 text-[11px]\">\n {name}\n </code>\n </React.Fragment>\n ))}\n . Renaming the theme breaks that reference until the document is\n updated.\n </>\n ) : (\n 'Not used by any open document yet — Run sample shows it anyway.'\n )}\n </p>\n {nameClash.length > 0 && (\n <p className=\"mt-1 text-xs text-warning\">\n {nameClash.join(', ')} also declare{nameClash.length === 1 ? 's' : ''}{' '}\n this name; only one of them can win when a document asks for it.\n </p>\n )}\n </EditorSection>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Advanced\n// ---------------------------------------------------------------------------\n\nfunction AdvancedSection({\n theme,\n onOpenJson,\n alsoHandled,\n query = '',\n}: {\n theme: ThemeJson;\n onOpenJson: () => void;\n alsoHandled: readonly string[];\n query?: string;\n}) {\n const searching = query.trim() !== '';\n const keys = useMemo(\n () =>\n advancedKeys(theme, FORMAT, alsoHandled).filter(\n (entry) =>\n matchesQuery(query, 'advanced') ||\n matchesQuery(query, entry.key, entry.summary)\n ),\n [alsoHandled, query, theme]\n );\n if (searching && keys.length === 0) return null;\n return (\n <EditorSection\n title=\"Advanced\"\n hint=\"Keys the form has no field for. They travel untouched through every edit here.\"\n forceOpen={searching ? true : undefined}\n actions={\n keys.length > 0 ? (\n <QuietButton onClick={onOpenJson}>\n <Braces className=\"size-3\" aria-hidden />\n Edit in JSON\n </QuietButton>\n ) : undefined\n }\n >\n {keys.length === 0 ? (\n <p className={HINT_CLASS}>Nothing beyond the fields above.</p>\n ) : (\n <ul className=\"flex flex-col gap-1\">\n {keys.map((entry) => (\n <li\n key={entry.key}\n className=\"flex min-w-0 items-baseline gap-2 text-xs\"\n >\n <code className=\"shrink-0 rounded-sm bg-muted px-1 py-0.5 text-[11px]\">\n {entry.key}\n </code>\n <span className=\"truncate text-muted-foreground\">\n {entry.summary}\n </span>\n </li>\n ))}\n </ul>\n )}\n </EditorSection>\n );\n}\n\nexport const ThemeVisualEditorMemoized = React.memo(ThemeVisualEditor);\n","import React, { useCallback, useMemo } from 'react';\nimport { EditorMonacoThemeMemoized } from '../json-editor/editor-monaco-theme';\nimport { ThemeVisualEditor } from './theme-visual-editor';\nimport { useSettingsStore } from '../../store/settings-store-provider';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { getThemeName } from '../../lib/theme-validation';\nimport { themeView } from '../../lib/theme-editor/view';\nimport type { TextFile } from '../../lib/types';\n\n/**\n * A theme tab: the same file seen either as a form or as JSON source.\n *\n * The switch between the two sits in the app header, beside Run, rather than\n * on a strip of its own — a tab this narrow cannot spare 36px to say what it\n * already is. The header owns the preference; this reads the same rule so the\n * two never disagree about which view a forced JSON is showing.\n */\nexport function ThemeEditorHost({\n document,\n onChange,\n}: {\n document: TextFile;\n onChange: (text: string) => void;\n}) {\n const preferred = useSettingsStore((s) => s.themeEditorView);\n const setSettings = useSettingsStore((s) => s.setSettings);\n const hasPendingDiff = useDocumentsStore(\n (s) => s.pendingDiffs[document.name] !== undefined\n );\n\n const parsed = useMemo(() => {\n try {\n const value = JSON.parse(document.text);\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n }, [document.text]);\n const themeName = parsed ? getThemeName(parsed) : null;\n\n // Which open documents name this theme, and which other open theme files\n // claim the same name — the two things the Identity section has to say.\n const usedBy = useDocumentsStore((s) => {\n if (!themeName) return EMPTY;\n const names = s.documents\n .filter(\n (d) =>\n (s.documentTypes[d.name] ?? 'application/json+report') ===\n 'application/json+report' && documentThemeName(d.text) === themeName\n )\n .map((d) => d.name);\n return names.length === 0 ? EMPTY : names.join('\\n');\n });\n const nameClash = useDocumentsStore((s) => {\n if (!themeName) return EMPTY;\n const names = s.documents\n .filter(\n (d) =>\n d.name !== document.name &&\n s.documentTypes[d.name] === 'application/json+theme' &&\n themeFileName(d.text) === themeName\n )\n .map((d) => d.name);\n return names.length === 0 ? EMPTY : names.join('\\n');\n });\n\n const { view } = themeView({\n preferred,\n parses: parsed !== null,\n hasPendingDiff,\n });\n\n const openJson = useCallback(\n () => setSettings({ themeEditorView: 'json' }),\n [setSettings]\n );\n\n return (\n <div className=\"h-full\">\n {view === 'visual' ? (\n <ThemeVisualEditor\n docName={document.name}\n text={document.text}\n onChange={onChange}\n onOpenJson={openJson}\n usedBy={usedBy === EMPTY ? NONE : usedBy.split('\\n')}\n nameClash={nameClash === EMPTY ? NONE : nameClash.split('\\n')}\n />\n ) : (\n <EditorMonacoThemeMemoized document={document} onChange={onChange} />\n )}\n </div>\n );\n}\n\nconst EMPTY = '';\nconst NONE: string[] = [];\n\n/** `props.theme` of a document, or null when it has none or does not parse. */\nfunction documentThemeName(text: string): string | null {\n try {\n const theme = JSON.parse(text)?.props?.theme;\n return typeof theme === 'string' ? theme : null;\n } catch {\n return null;\n }\n}\n\n/** The `name` inside a theme file, or null. */\nfunction themeFileName(text: string): string | null {\n try {\n return getThemeName(JSON.parse(text));\n } catch {\n return null;\n }\n}\n\nexport const ThemeEditorHostMemoized = React.memo(ThemeEditorHost);\n","import React, { useCallback, useEffect, useState } from 'react';\nimport {\n BookOpen,\n Check,\n Copy,\n Download as DownloadIcon,\n Globe,\n Info,\n Puzzle,\n} from 'lucide-react';\nimport { Badge } from '../ui/badge';\nimport { Button } from '../ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { Spinner } from '../ui/spinner';\nimport { Switch } from '../ui/switch';\nimport { Textarea } from '../ui/textarea';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';\nimport { useToast } from '../ui/use-toast';\nimport { useBrowserPluginsStore } from '../../store/browser-plugins-store';\nimport { pluginHost } from '../../lib/plugins/host';\nimport { compileQueue } from '../../lib/plugins/compile-queue';\nimport { parseNetworkOrigins } from '../../lib/plugins/network-policy';\nimport {\n onPluginTypeScriptReady,\n pluginTypeScriptReady,\n} from '../../lib/plugins/type-libs';\nimport { download } from '../../lib/download';\nimport { cn } from '../../lib/utils';\nimport { BROWSER_PLUGINS_CHANGED_EVENT } from '../../hooks/useBrowserPluginsSync';\nimport { PLUGIN_FILE_SUFFIX } from '../../store/documents-store';\n\n/** True once the plugin API declarations are in Monaco's TypeScript. */\nfunction usePluginTypesReady(): boolean {\n const [ready, setReady] = useState(pluginTypeScriptReady);\n useEffect(() => onPluginTypeScriptReady(() => setReady(true)), []);\n return ready;\n}\n\n/**\n * The bar above a plugin's source: what it is called, whether it compiled,\n * and the two switches that decide how it takes part — enabled at all, and\n * allowed to reach the network from its sandbox.\n */\nexport function PluginEditorStrip({\n docName,\n text,\n}: {\n docName: string;\n text: string;\n}) {\n const record = useBrowserPluginsStore((s) => s.records[docName]);\n const setEnabled = useBrowserPluginsStore((s) => s.setEnabled);\n const setAllowNetwork = useBrowserPluginsStore((s) => s.setAllowNetwork);\n const setNetworkOrigins = useBrowserPluginsStore((s) => s.setNetworkOrigins);\n const { toast } = useToast();\n const [copiedIndex, setCopiedIndex] = useState<number | null>(null);\n const typesReady = usePluginTypesReady();\n\n const metadata = record?.metadata;\n const status = record?.status ?? 'idle';\n const errorCount = (record?.diagnostics ?? []).filter(\n (d) => d.severity === 'error'\n ).length;\n const displayName =\n metadata?.name ??\n docName.replace(new RegExp(`${PLUGIN_FILE_SUFFIX}$`, 'i'), '');\n const examples = metadata?.examples ?? [];\n\n const announce = useCallback(() => {\n window.dispatchEvent(\n new CustomEvent(BROWSER_PLUGINS_CHANGED_EVENT, { detail: { docName } })\n );\n }, [docName]);\n\n const toggleEnabled = useCallback(\n (enabled: boolean) => {\n setEnabled(docName, enabled);\n announce();\n },\n [announce, docName, setEnabled]\n );\n\n // The sandbox is hardened once, when it loads, and its CSP is fixed when\n // the frame is written: a new setting needs a new frame. Compile again as\n // well — a plugin that failed to load because it reached for the network is\n // only known to work, or not, once it has loaded under the new setting.\n const recompileUnderNewPolicy = useCallback(() => {\n pluginHost.dispose(docName);\n useBrowserPluginsStore.getState().upsert(docName, { status: 'idle' });\n void compileQueue.run(docName);\n }, [docName]);\n\n const toggleNetwork = useCallback(\n (allowNetwork: boolean) => {\n setAllowNetwork(docName, allowNetwork);\n recompileUnderNewPolicy();\n },\n [docName, recompileUnderNewPolicy, setAllowNetwork]\n );\n\n const commitOrigins = useCallback(\n (origins: string[]) => {\n setNetworkOrigins(docName, origins);\n recompileUnderNewPolicy();\n },\n [docName, recompileUnderNewPolicy, setNetworkOrigins]\n );\n\n const copyExample = useCallback(\n async (index: number) => {\n const example = examples[index];\n if (!example || !metadata) return;\n const usage = JSON.stringify(\n { name: metadata.name, props: example.props },\n null,\n 2\n );\n try {\n await navigator.clipboard.writeText(usage);\n setCopiedIndex(index);\n setTimeout(() => setCopiedIndex(null), 1500);\n } catch {\n toast({\n title: 'Clipboard unavailable',\n description: 'Could not copy the example to the clipboard.',\n variant: 'destructive',\n });\n }\n },\n [examples, metadata, toast]\n );\n\n const statusChip = (() => {\n if (!typesReady && status !== 'ready' && status !== 'error') {\n return (\n <span className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <Spinner size=\"sm\" />\n Loading types…\n </span>\n );\n }\n switch (status) {\n case 'compiling':\n return (\n <span className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <Spinner size=\"sm\" />\n Compiling…\n </span>\n );\n case 'ready':\n return (\n <span className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <span aria-hidden className=\"size-1.5 rounded-full bg-success\" />\n Ready\n </span>\n );\n case 'error':\n return (\n <span className=\"flex items-center gap-1.5 text-xs text-destructive\">\n <span\n aria-hidden\n className=\"size-1.5 rounded-full bg-destructive\"\n />\n {errorCount > 0\n ? `${errorCount} error${errorCount === 1 ? '' : 's'}`\n : 'Failed'}\n </span>\n );\n default:\n return (\n <span className=\"text-xs text-muted-foreground\">Not compiled</span>\n );\n }\n })();\n\n return (\n <div className=\"flex h-9 shrink-0 items-center gap-2 border-b bg-sidebar px-3\">\n <Puzzle className=\"size-3.5 shrink-0 text-sidebar-foreground/60\" />\n <span className=\"truncate text-[13px] font-medium\">{displayName}</span>\n {metadata?.latest && (\n <Badge variant=\"outline\" className=\"h-4 px-1.5 font-mono text-[10px]\">\n v{metadata.latest}\n </Badge>\n )}\n <span className=\"mx-1 h-4 w-px bg-border/60\" />\n {statusChip}\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"How plugins run\"\n className=\"inline-flex size-6 cursor-help items-center justify-center rounded-sm hover:bg-muted/60\"\n >\n <Info className=\"size-3.5 text-muted-foreground\" />\n </button>\n </TooltipTrigger>\n <TooltipContent className=\"max-w-sm\">\n <p className=\"text-sm\">\n Compiled in your browser and run in a worker inside a sandboxed\n frame with its own origin: no page, no cookies, no storage, and\n nothing on the network it has not been given. The server only ever\n receives the standard components it produces.\n </p>\n <p className=\"mt-2 text-sm\">\n Network is per host. A plugin allowed to call a host can also load\n code from it and send it anything it renders, so list only hosts you\n would trust with the document.\n </p>\n </TooltipContent>\n </Tooltip>\n\n <span className=\"flex-1\" />\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 gap-1.5 px-2 text-xs\"\n disabled={examples.length === 0}\n title={\n examples.length === 0\n ? 'Add a JSDoc @example with a JSON block to list usage examples here'\n : undefined\n }\n >\n <BookOpen className=\"size-3.5\" />\n Examples\n {examples.length > 0 && (\n <Badge variant=\"secondary\" className=\"h-4 px-1 text-[10px]\">\n {examples.length}\n </Badge>\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-64\">\n <DropdownMenuLabel className=\"text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n Copy as component JSON\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n {examples.map((example, index) => (\n <DropdownMenuItem\n key={index}\n onClick={(event) => {\n event.preventDefault();\n void copyExample(index);\n }}\n className=\"gap-2\"\n >\n {copiedIndex === index ? (\n <Check className=\"size-3.5 text-success\" />\n ) : (\n <Copy className=\"size-3.5 text-muted-foreground\" />\n )}\n <span className=\"truncate\">\n {example.title ?? `Example ${index + 1}`}\n </span>\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n <label\n htmlFor={`plugin-enabled-${docName}`}\n className={cn(\n 'flex h-7 cursor-pointer items-center gap-1.5 rounded-sm px-1.5 text-xs',\n record?.enabled ? 'text-foreground' : 'text-muted-foreground'\n )}\n title=\"On: the component is offered in completions and expanded in every build. Off: a document that still names it fails to build with a message pointing here.\"\n >\n Enabled\n <Switch\n id={`plugin-enabled-${docName}`}\n checked={record?.enabled ?? true}\n onCheckedChange={toggleEnabled}\n aria-label=\"Enable plugin\"\n />\n </label>\n <NetworkControl\n docName={docName}\n allowNetwork={record?.allowNetwork ?? false}\n origins={record?.networkOrigins ?? []}\n onToggle={toggleNetwork}\n onCommitOrigins={commitOrigins}\n />\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-7\"\n aria-label=\"Download plugin source\"\n onClick={() =>\n download(docName, new Blob([text], { type: 'text/typescript' }))\n }\n >\n <DownloadIcon className=\"size-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n <p>\n Download <code>{docName}</code> to use it on disk with the CLI\n </p>\n </TooltipContent>\n </Tooltip>\n </div>\n );\n}\n\nexport const PluginEditorStripMemoized = React.memo(PluginEditorStrip);\n\n/**\n * The Network control: a switch, and the hosts the switch grants.\n *\n * The switch alone reaches nothing. That is the point — \"on\" used to mean the\n * whole internet, which made it a grant nobody could reason about: a plugin\n * that may call anywhere may also fetch code and run it, so reading its source\n * stops telling you what it does. Naming the hosts keeps the decision one an\n * author can actually make.\n */\nfunction NetworkControl({\n docName,\n allowNetwork,\n origins,\n onToggle,\n onCommitOrigins,\n}: {\n docName: string;\n allowNetwork: boolean;\n origins: string[];\n onToggle: (allowNetwork: boolean) => void;\n onCommitOrigins: (origins: string[]) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [draft, setDraft] = useState(() => origins.join('\\n'));\n\n // The field trails the record while it is closed; opening re-seeds it so a\n // rename or an edit from elsewhere is not overwritten by a stale draft.\n useEffect(() => {\n if (!open) setDraft(origins.join('\\n'));\n }, [open, origins]);\n\n const parsed = parseNetworkOrigins(draft);\n const granted = allowNetwork && origins.length > 0;\n const label = !allowNetwork\n ? 'Network off'\n : origins.length === 0\n ? 'Network on, no hosts listed'\n : `Network: ${origins.join(', ')}`;\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n className={cn(\n 'flex h-7 cursor-pointer items-center gap-1.5 rounded-sm px-1.5 text-xs',\n 'transition-colors hover:bg-muted/60',\n 'focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none',\n granted ? 'text-foreground' : 'text-muted-foreground'\n )}\n >\n <Globe className=\"size-3.5\" aria-hidden=\"true\" />\n <span className=\"hidden sm:inline\">Network</span>\n {granted && (\n <Badge\n variant=\"outline\"\n className=\"h-4 px-1 font-mono text-[10px] tabular-nums\"\n >\n {origins.length}\n </Badge>\n )}\n {allowNetwork && origins.length === 0 && (\n <span className=\"text-[10px] text-amber-600 dark:text-amber-500\">\n no hosts\n </span>\n )}\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-80 space-y-3\">\n <label\n htmlFor={`plugin-network-${docName}`}\n className=\"flex cursor-pointer items-center justify-between gap-2\"\n >\n <span className=\"text-sm font-medium\">Allow network</span>\n <Switch\n id={`plugin-network-${docName}`}\n checked={allowNetwork}\n onCheckedChange={onToggle}\n aria-label=\"Allow network access\"\n />\n </label>\n <p className=\"text-xs text-muted-foreground\">\n Off: <code>fetch</code>, <code>XMLHttpRequest</code>,{' '}\n <code>WebSocket</code> and <code>EventSource</code> throw inside the\n sandbox. On: only the hosts below are reachable — everything else is\n refused by the browser, not by the plugin.\n </p>\n {allowNetwork && (\n <>\n <Textarea\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onBlur={() => onCommitOrigins(parsed.origins)}\n spellCheck={false}\n rows={3}\n aria-label=\"Hosts this plugin may call\"\n placeholder={'api.open-meteo.com\\ngeocoding-api.open-meteo.com'}\n className=\"font-mono text-xs\"\n />\n <p className=\"text-xs text-muted-foreground\">\n One host per line. <code>https</code> is assumed;{' '}\n <code>*.example.com</code> matches subdomains.\n </p>\n {parsed.errors.length > 0 && (\n <ul className=\"space-y-0.5 text-xs text-destructive\">\n {parsed.errors.map((error) => (\n <li key={error}>{error}</li>\n ))}\n </ul>\n )}\n {parsed.errors.length === 0 && parsed.origins.length === 0 && (\n <p className=\"text-xs text-amber-600 dark:text-amber-500\">\n Nothing listed, so nothing is reachable.\n </p>\n )}\n </>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport Editor, { type Monaco } from '@monaco-editor/react';\nimport type { editor as MonacoEditorType } from 'monaco-editor';\nimport debounce from 'lodash.debounce';\nimport { useTheme } from '../theme-provider';\nimport { monacoThemeFor, registerMonacoThemes } from '../../lib/monaco-theme';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { useEditorRefsStore } from '../../store/editor-refs-store';\nimport { useBrowserPluginsStore } from '../../store/browser-plugins-store';\nimport { pluginModelPath } from '../../lib/plugins/compiler';\nimport { ensurePluginTypeScript } from '../../lib/plugins/type-libs';\nimport type { JsonEditorError } from '../../lib/json-types';\nimport {\n ValidationPanel,\n ValidationStatusBar,\n} from '../json-editor/validation-panel';\nimport { PluginEditorStripMemoized } from './plugin-editor-strip';\n\n/**\n * A plugin file open in a tab: Monaco in TypeScript mode over the same model\n * the compiler uses, so completions, hovers and the diagnostics below come\n * from one program. Saving is the document store's job, debounced like the\n * JSON editors; compiling is the sync hook's, which watches the store.\n */\nfunction EditorMonacoPlugin({\n name,\n value,\n saveDocumentDebounceWait,\n}: {\n name: string;\n value: string;\n saveDocumentDebounceWait: number;\n}) {\n const editorRef = useRef<MonacoEditorType.IStandaloneCodeEditor | null>(null);\n const { resolvedTheme } = useTheme();\n const saveDocument = useDocumentsStore((s) => s.saveDocument);\n const closeDocument = useDocumentsStore((s) => s.closeDocument);\n const { registerEditor, unregisterEditor, setActiveEditor } =\n useEditorRefsStore();\n const diagnostics = useBrowserPluginsStore(\n (s) => s.records[name]?.diagnostics\n );\n\n // Our own save echoes must not be written back into the editor: with the\n // debounce the store trails the model, and the wrapper would otherwise\n // replace newer keystrokes with the older saved text.\n const lastSavedRef = useRef<string | null>(null);\n const [editorValue, setEditorValue] = useState(value);\n const debouncedSaveRef = useRef(\n debounce((text: string) => {\n lastSavedRef.current = text;\n saveDocument(name, text);\n }, saveDocumentDebounceWait)\n );\n\n const [showPanel, setShowPanel] = useState(true);\n const [panelMinimized, setPanelMinimized] = useState(false);\n const userDismissedRef = useRef(false);\n\n const errors = useMemo<JsonEditorError[]>(\n () =>\n (diagnostics ?? []).map((d) => ({\n path: d.source === 'typescript' ? '' : d.source,\n message: d.message,\n code: d.source,\n severity: d.severity,\n ...(d.line !== undefined\n ? {\n startLineNumber: d.line,\n startColumn: d.column,\n endLineNumber: d.endLine,\n endColumn: d.endColumn,\n }\n : {}),\n })),\n [diagnostics]\n );\n\n useEffect(() => {\n if (errors.length > 0 && !userDismissedRef.current) {\n setShowPanel(true);\n setPanelMinimized(false);\n }\n if (errors.length === 0) userDismissedRef.current = false;\n }, [errors.length]);\n\n const handleWillMount = useCallback((monaco: Monaco) => {\n registerMonacoThemes(monaco);\n // Types load asynchronously; diagnostics settle once they have.\n void ensurePluginTypeScript(monaco);\n }, []);\n\n const flushPendingSave = useCallback(() => {\n debouncedSaveRef.current.flush();\n }, []);\n\n const handleMount = useCallback(\n (editor: MonacoEditorType.IStandaloneCodeEditor, monaco: Monaco) => {\n editorRef.current = editor;\n registerEditor(\n name,\n editor,\n monaco,\n undefined,\n undefined,\n flushPendingSave\n );\n setActiveEditor(name);\n\n const saveNow = () => {\n const text = editor.getValue();\n debouncedSaveRef.current.cancel();\n lastSavedRef.current = text;\n saveDocument(name, text);\n };\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, saveNow);\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyW, () => {\n saveNow();\n closeDocument(name);\n });\n editor.addCommand(\n monaco.KeyMod.Shift | monaco.KeyMod.Alt | monaco.KeyCode.KeyF,\n () => {\n editor.getAction('editor.action.formatDocument')?.run();\n }\n );\n },\n [\n closeDocument,\n flushPendingSave,\n name,\n registerEditor,\n saveDocument,\n setActiveEditor,\n ]\n );\n\n useEffect(() => {\n const debouncedSave = debouncedSaveRef.current;\n return () => {\n debouncedSave.flush();\n unregisterEditor(name);\n };\n }, [name, unregisterEditor]);\n\n // A genuine external change (rename, AI apply, another view): replace the\n // model text. Our own echoes are recognised by `lastSavedRef`.\n useEffect(() => {\n if (value === lastSavedRef.current) return;\n const model = editorRef.current?.getModel();\n if (model && model.getValue() !== value) model.setValue(value);\n setEditorValue(value);\n }, [value]);\n\n const handleErrorClick = useCallback((error: JsonEditorError) => {\n const editor = editorRef.current;\n if (!editor || !error.startLineNumber) return;\n editor.setPosition({\n lineNumber: error.startLineNumber,\n column: error.startColumn ?? 1,\n });\n editor.revealLineInCenter(error.startLineNumber);\n editor.focus();\n }, []);\n\n return (\n <div className=\"flex h-full flex-col\">\n <PluginEditorStripMemoized docName={name} text={value} />\n <div className=\"relative min-h-0 flex-1\">\n <Editor\n height=\"100%\"\n defaultLanguage=\"typescript\"\n path={pluginModelPath(name)}\n value={editorValue}\n theme={monacoThemeFor(resolvedTheme)}\n beforeMount={handleWillMount}\n onMount={handleMount}\n keepCurrentModel\n onChange={(text) => {\n if (text !== undefined) debouncedSaveRef.current(text);\n }}\n options={{\n lineNumbers: 'on',\n glyphMargin: true,\n folding: true,\n lineDecorationsWidth: 5,\n lineNumbersMinChars: 3,\n renderValidationDecorations: 'on',\n quickSuggestions: { other: true, comments: false, strings: true },\n acceptSuggestionOnCommitCharacter: true,\n acceptSuggestionOnEnter: 'on',\n autoIndent: 'advanced',\n formatOnType: true,\n formatOnPaste: true,\n automaticLayout: true,\n minimap: { enabled: false },\n scrollBeyondLastLine: true,\n tabSize: 2,\n wordWrap: 'off',\n }}\n />\n <div className=\"absolute top-0 right-0\">\n <ValidationStatusBar\n errors={errors}\n onClick={() => {\n setShowPanel(true);\n setPanelMinimized(false);\n }}\n />\n </div>\n {showPanel && errors.length > 0 && (\n <ValidationPanel\n errors={errors}\n isMinimized={panelMinimized}\n onToggleMinimize={() => setPanelMinimized((v) => !v)}\n onErrorClick={handleErrorClick}\n onClose={() => {\n setShowPanel(false);\n userDismissedRef.current = true;\n }}\n className=\"z-40\"\n />\n )}\n </div>\n </div>\n );\n}\n\nexport const EditorMonacoPluginMemoized = React.memo(EditorMonacoPlugin);\n","import React from 'react';\nimport { EditorMonacoJsonMemoized } from '../json-editor/editor-monaco-json';\nimport { ThemeEditorHostMemoized } from '../theme-editor/theme-editor-host';\nimport { EditorMonacoPluginMemoized } from '../plugin-editor/editor-monaco-plugin';\nimport { TabsContent } from '../ui/tabs';\nimport { useDocumentsStore } from '../../store/documents-store-provider';\nimport { useThemesStore } from '../../store/themes-store-provider';\nimport type { TextFile } from '../../lib/types';\nimport type { DocumentType } from '../../store/documents-store';\nimport debounce from 'lodash.debounce';\n\nfunction TabContent({\n name,\n text,\n buildError: _buildError,\n saveDocumentDebounceWait,\n documentType,\n}: {\n name: string;\n text: string;\n buildError?: string;\n saveDocumentDebounceWait: number;\n documentType: DocumentType;\n}) {\n const { saveDocument } = useDocumentsStore((state) => state);\n const { updateTheme } = useThemesStore((state) => state);\n\n // Create a debounced version of updateTheme\n const debouncedUpdateTheme = React.useMemo(\n () => debounce(updateTheme, saveDocumentDebounceWait),\n [updateTheme, saveDocumentDebounceWait]\n );\n\n // Flush pending theme updates on unmount so the themes store is always\n // up-to-date when the user switches away from a theme tab.\n React.useEffect(() => {\n return () => {\n debouncedUpdateTheme.flush();\n };\n }, [debouncedUpdateTheme]);\n\n const handleChange = React.useCallback(\n (value: string) => {\n saveDocument(name, value);\n\n // If this is a theme document, update the themes store with debouncing\n if (documentType === 'application/json+theme') {\n console.log(\n 'TabContent: Theme document change detected, debouncing update',\n {\n documentName: name,\n debounceWait: saveDocumentDebounceWait,\n }\n );\n debouncedUpdateTheme(name, value);\n }\n },\n [\n name,\n saveDocument,\n debouncedUpdateTheme,\n documentType,\n saveDocumentDebounceWait,\n ]\n );\n\n // Create a fake document object for the theme editor\n const document: TextFile = React.useMemo(\n () => ({\n name,\n type: 'application/json',\n text,\n mtime: new Date(),\n ctime: new Date(),\n atime: new Date(),\n }),\n [name, text]\n );\n\n return (\n <TabsContent\n value={name}\n className=\"mt-0 h-full p-0\"\n tabIndex={-1} // to prevent focus on Tab trigger (fix for accessibility size issue)\n >\n {documentType === 'application/json+theme' ? (\n <ThemeEditorHostMemoized document={document} onChange={handleChange} />\n ) : documentType === 'application/typescript+plugin' ? (\n <EditorMonacoPluginMemoized\n name={name}\n value={text}\n saveDocumentDebounceWait={saveDocumentDebounceWait}\n />\n ) : (\n <EditorMonacoJsonMemoized\n name={name}\n value={text}\n saveDocumentDebounceWait={saveDocumentDebounceWait}\n />\n )}\n </TabsContent>\n );\n}\n\nconst TabContentMemoized = React.memo(TabContent);\n\nfunction EditorTabsContent({\n openTabs,\n documents,\n buildErrors,\n saveDocumentDebounceWait,\n}: {\n openTabs: string[];\n documents: TextFile[];\n buildErrors: Record<string, string>;\n saveDocumentDebounceWait: number;\n}) {\n const { documentTypes } = useDocumentsStore((state) => state);\n\n return openTabs\n .map((name) => documents.find((d) => d.name === name))\n .filter((doc): doc is TextFile => doc !== undefined)\n .map((doc) => {\n const documentType = documentTypes[doc.name] || 'application/json+report';\n\n return (\n <TabContentMemoized\n key={doc.name}\n name={doc.name}\n text={doc.text}\n buildError={buildErrors[doc.name]}\n saveDocumentDebounceWait={saveDocumentDebounceWait}\n documentType={documentType}\n />\n );\n });\n}\n\nexport const EditorTabsContentMemoized = React.memo(EditorTabsContent);\n","export interface RetryOptions {\n maxRetries?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffFactor?: number;\n onRetry?: (error: Error, attempt: number) => void;\n shouldRetry?: (error: Error) => boolean;\n signal?: AbortSignal;\n}\n\nexport class RetryError extends Error {\n constructor(\n message: string,\n public readonly lastError: Error,\n public readonly attempts: number\n ) {\n super(message);\n this.name = 'RetryError';\n }\n}\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<T> {\n const {\n maxRetries = 3,\n initialDelay = 1000,\n maxDelay = 30000,\n backoffFactor = 2,\n onRetry,\n shouldRetry = () => true,\n signal,\n } = options;\n\n let lastError: Error;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n // Check if operation was cancelled\n if (signal?.aborted) {\n throw new Error('Operation cancelled');\n }\n\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry if it's the last attempt\n if (attempt === maxRetries) {\n break;\n }\n\n // Check if we should retry this error\n if (!shouldRetry(lastError)) {\n throw lastError;\n }\n\n // Calculate delay with exponential backoff\n const delay = Math.min(\n initialDelay * Math.pow(backoffFactor, attempt),\n maxDelay\n );\n\n // Add some jitter to prevent thundering herd\n const jitteredDelay = delay * (0.5 + Math.random() * 0.5);\n\n // Call retry callback if provided\n if (onRetry) {\n onRetry(lastError, attempt + 1);\n }\n\n // Wait before retrying\n await new Promise((resolve) => {\n const timeoutId = setTimeout(resolve, jitteredDelay);\n\n // Clean up timeout if cancelled\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeoutId);\n resolve(undefined);\n },\n { once: true }\n );\n }\n });\n }\n }\n\n throw new RetryError(\n `Failed after ${maxRetries + 1} attempts`,\n lastError!,\n maxRetries + 1\n );\n}\n\n/**\n * Retry decorator for class methods\n */\nexport function Retryable(options: RetryOptions = {}) {\n return function (\n _target: any,\n _propertyKey: string,\n descriptor: PropertyDescriptor\n ) {\n const originalMethod = descriptor.value;\n\n descriptor.value = async function (...args: any[]) {\n return retry(() => originalMethod.apply(this, args), options);\n };\n\n return descriptor;\n };\n}\n\n/**\n * Common retry strategies\n */\nexport const RetryStrategies = {\n // Retry on network errors\n networkErrors: (error: Error) => {\n const networkErrorPatterns = [\n 'NetworkError',\n 'Failed to fetch',\n 'ERR_NETWORK',\n 'ECONNREFUSED',\n 'ETIMEDOUT',\n 'ENOTFOUND',\n 'fetch failed',\n ];\n\n return networkErrorPatterns.some(\n (pattern) =>\n error.message.includes(pattern) || error.name.includes(pattern)\n );\n },\n\n // Retry on specific HTTP status codes\n httpStatusCodes: (statusCodes: number[]) => (error: any) => {\n if (error.response?.status) {\n return statusCodes.includes(error.response.status);\n }\n return false;\n },\n\n // Retry on temporary errors\n temporaryErrors: (error: Error) => {\n const temporaryPatterns = [\n 'EBUSY',\n 'EAGAIN',\n 'temporarily unavailable',\n 'too many requests',\n 'rate limit',\n ];\n\n return temporaryPatterns.some((pattern) =>\n error.message.toLowerCase().includes(pattern.toLowerCase())\n );\n },\n\n // Combine multiple strategies\n combine:\n (...strategies: ((error: Error) => boolean)[]) =>\n (error: Error) => {\n return strategies.some((strategy) => strategy(error));\n },\n};\n","import type { FormatName } from '../env';\nimport { definedColorKeys, type ThemeJson } from './model';\n\n/**\n * A document that shows a theme.\n *\n * \"Preview specimen\" renders this through the ordinary generate + preview\n * path, so what the author sees is the real output of the real pipeline in\n * the theme they are editing: every named style, the colour tokens as\n * swatches, a table, and (PPTX) a native chart drawn from the palette.\n *\n * Only tokens the theme defines are referenced. A DOCX theme that leaves\n * `accent4` unset throws on a component that names it, and the specimen must\n * never be the thing that fails.\n */\n\nconst BODY_TEXT =\n 'Body text in the normal style, with **bold**, *italic* and `mono` runs beside plain words so weight and the mono role read next to each other. A second sentence gives the line spacing and paragraph spacing room to show.';\n\nconst TOKEN_ROLES: Record<string, string> = {\n primary: 'Headings and the strongest brand colour',\n secondary: 'Supporting brand colour',\n accent: 'Highlights and emphasis',\n text: 'Body text',\n textPrimary: 'Primary text',\n textSecondary: 'Secondary text',\n textMuted: 'Captions and muted text',\n text2: 'Secondary text and captions',\n background: 'Page background',\n backgroundPrimary: 'Primary surface',\n backgroundSecondary: 'Alternate surface',\n background2: 'Alternate surface and rules',\n border: 'Rules and borders',\n borderPrimary: 'Primary rules',\n borderSecondary: 'Subtle rules',\n accent4: 'Chart series 4',\n accent5: 'Chart series 5',\n accent6: 'Chart series 6',\n};\n\n/** The colour keys worth a swatch: hex values only, references included. */\nfunction swatchTokens(theme: ThemeJson | undefined): string[] {\n if (!theme) return [];\n return definedColorKeys(theme);\n}\n\nfunction hasStyle(theme: ThemeJson | undefined, name: string): boolean {\n const styles = theme?.styles;\n return !!styles && typeof styles === 'object' && name in (styles as object);\n}\n\nfunction docxSpecimen(\n themeName: string,\n theme: ThemeJson | undefined\n): unknown {\n const tokens = swatchTokens(theme);\n const children: unknown[] = [];\n\n children.push(\n hasStyle(theme, 'title')\n ? {\n name: 'paragraph',\n props: { text: 'Theme specimen', themeStyle: 'title' },\n }\n : { name: 'heading', props: { text: 'Theme specimen', level: 1 } }\n );\n if (hasStyle(theme, 'subtitle')) {\n children.push({\n name: 'paragraph',\n props: {\n text: `Every named style, colour and font of \"${themeName}\", on one page.`,\n themeStyle: 'subtitle',\n },\n });\n } else {\n children.push({\n name: 'paragraph',\n props: {\n text: `Every named style, colour and font of \"${themeName}\", on one page.`,\n },\n });\n }\n\n children.push(\n { name: 'heading', props: { text: 'Heading 1 — Typography', level: 1 } },\n { name: 'paragraph', props: { text: BODY_TEXT } },\n { name: 'heading', props: { text: 'Heading 2 — Structure', level: 2 } },\n {\n name: 'paragraph',\n props: {\n text: 'A second paragraph under a second-level heading, so the spacing before and after headings can be judged against running text.',\n },\n },\n { name: 'heading', props: { text: 'Heading 3 — Detail', level: 3 } },\n {\n name: 'list',\n props: {\n items: [\n 'Primary carries the headings',\n 'Secondary supports it',\n 'Accent marks emphasis',\n ],\n },\n },\n { name: 'divider', props: {} },\n { name: 'heading', props: { text: 'Figures', level: 2 } },\n {\n name: 'statistic',\n props: {\n number: '42%',\n description:\n 'A statistic: the number in the heading font, the caption below it',\n },\n }\n );\n\n if (tokens.length > 0) {\n children.push(\n { name: 'heading', props: { text: 'Colours', level: 2 } },\n {\n name: 'table',\n props: {\n columns: [\n {\n header: { content: 'Token' },\n cells: tokens.map((token) => ({ content: token })),\n },\n {\n header: { content: 'Swatch' },\n cells: tokens.map((token) => ({\n content: ' ',\n backgroundColor: token,\n })),\n },\n {\n header: { content: 'Role' },\n cells: tokens.map((token) => ({\n content: TOKEN_ROLES[token] ?? '',\n })),\n },\n ],\n },\n }\n );\n }\n\n return {\n name: 'docx',\n props: {\n theme: themeName,\n metadata: {\n title: `${themeName} sample`,\n author: 'json-to-office playground',\n description: `Sample rendered in the \"${themeName}\" theme`,\n },\n },\n children: [{ name: 'section', props: {}, children }],\n };\n}\n\nfunction pptxSpecimen(\n themeName: string,\n theme: ThemeJson | undefined\n): unknown {\n const tokens = swatchTokens(theme);\n const text = (\n content: string,\n style: string,\n x: number,\n y: number,\n w: number,\n h: number\n ) => ({ name: 'text', props: { text: content, style, x, y, w, h } });\n\n const slides: unknown[] = [\n {\n name: 'slide',\n props: { meta: { title: 'Title' } },\n children: [\n text('Theme specimen', 'title', 0.5, 1.6, 9, 1.2),\n text(\n `Named styles, colours and fonts of \"${themeName}\"`,\n 'subtitle',\n 0.5,\n 2.9,\n 9,\n 0.8\n ),\n ],\n },\n {\n name: 'slide',\n props: { meta: { title: 'Typography' } },\n children: [\n text('Typography', 'heading1', 0.5, 0.4, 9, 0.8),\n text('Heading 2 — the section style', 'heading2', 0.5, 1.3, 9, 0.6),\n text('Heading 3 — the detail style', 'heading3', 0.5, 1.95, 9, 0.5),\n text(\n 'Body text in the body style. It runs long enough to wrap onto a second line, so the line spacing and the body size can be judged against the headings above it.',\n 'body',\n 0.5,\n 2.55,\n 9,\n 1.4\n ),\n text(\n 'Caption — the smallest voice on the slide',\n 'caption',\n 0.5,\n 4.1,\n 9,\n 0.4\n ),\n ],\n },\n ];\n\n if (tokens.length > 0) {\n const perRow = 6;\n const swatches: unknown[] = [];\n tokens.forEach((token, index) => {\n const column = index % perRow;\n const row = Math.floor(index / perRow);\n const x = 0.5 + column * 1.5;\n const y = 1.3 + row * 1.6;\n swatches.push(\n {\n name: 'shape',\n props: { type: 'rect', x, y, w: 1.3, h: 0.9, fill: { color: token } },\n },\n text(token, 'caption', x, y + 0.95, 1.3, 0.4)\n );\n });\n slides.push({\n name: 'slide',\n props: { meta: { title: 'Colours' } },\n children: [text('Colours', 'heading1', 0.5, 0.4, 9, 0.8), ...swatches],\n });\n }\n\n slides.push({\n name: 'slide',\n props: { meta: { title: 'Chart and table' } },\n children: [\n text('Chart and table', 'heading1', 0.5, 0.4, 9, 0.8),\n {\n name: 'chart',\n props: {\n type: 'bar',\n x: 0.5,\n y: 1.3,\n w: 4.6,\n h: 3.6,\n showLegend: true,\n data: [\n {\n name: 'Revenue',\n labels: ['Q1', 'Q2', 'Q3', 'Q4'],\n values: [120, 132, 145, 160],\n },\n {\n name: 'Cost',\n labels: ['Q1', 'Q2', 'Q3', 'Q4'],\n values: [80, 84, 91, 95],\n },\n {\n name: 'Margin',\n labels: ['Q1', 'Q2', 'Q3', 'Q4'],\n values: [40, 48, 54, 65],\n },\n ],\n },\n },\n {\n name: 'table',\n props: {\n x: 5.4,\n y: 1.3,\n w: 4.1,\n headerRow: true,\n rows: [\n [{ text: 'Metric' }, { text: 'Value' }],\n [{ text: 'Revenue' }, { text: '$4.2M' }],\n [{ text: 'Users' }, { text: '12,847' }],\n [{ text: 'Retention' }, { text: '94%' }],\n ],\n },\n },\n ],\n });\n\n return {\n name: 'pptx',\n props: { title: `${themeName} sample`, theme: themeName },\n children: slides,\n };\n}\n\n/** The output name a theme's sample builds under, so the header says what it is. */\nexport function sampleOutputName(themeName: string): string {\n return `Sample · ${themeName}`;\n}\n\nexport function isSampleOutputName(name: string): boolean {\n return name.startsWith('Sample · ');\n}\n\n/**\n * The specimen for `themeName`. `theme` is the parsed theme when the caller\n * has it; it decides which tokens and styles the specimen dares to name.\n */\nexport function buildThemeSpecimen(\n format: FormatName,\n themeName: string,\n theme?: ThemeJson\n): unknown {\n return format === 'docx'\n ? docxSpecimen(themeName, theme)\n : pptxSpecimen(themeName, theme);\n}\n","import {\n useEffect,\n useCallback,\n useRef,\n useMemo,\n memo,\n useContext,\n} from 'react';\nimport { EditorTabsContentMemoized } from './editor-tabs-content';\nimport { Tabs } from '../ui/tabs';\nimport {\n useDocumentsStore,\n DocumentsStoreContext,\n} from '../../store/documents-store-provider';\nimport {\n useOutputStore,\n OutputStoreContext,\n} from '../../store/output-store-provider';\nimport { useSettingsStore } from '../../store/settings-store-provider';\nimport { useEditorRefsStore } from '../../store/editor-refs-store';\nimport {\n useThemesStore,\n ThemesStoreContext,\n} from '../../store/themes-store-provider';\nimport {\n QualityGateFailedError,\n usePresentationGenerator,\n} from '../../hooks/usePresentationGenerator';\nimport { useQualityAnalysis } from '../../hooks/useQualityAnalysis';\nimport { FORMAT } from '../../lib/env';\nimport {\n buildQualityOptions,\n storedProfileId,\n} from '../../lib/quality-profiles';\nimport {\n isStaleQualityTicket,\n nextQualityTicket,\n} from '../../lib/quality-sequence';\nimport {\n countBySeverity,\n findingsFromAnalysis,\n splitQualityWarnings,\n type GenerationWarningLike,\n} from '../../lib/quality-findings';\nimport type { GenerationWarning, QualityState } from '../../store/output-store';\nimport { retry, RetryStrategies } from '../../utils/retry';\nimport { themeChangeEmitter } from '../../utils/theme-change-emitter';\nimport { expandForServer } from '../../lib/plugins/expand-for-server';\nimport { compileQueue } from '../../lib/plugins/compile-queue';\nimport { BROWSER_PLUGINS_CHANGED_EVENT } from '../../hooks/useBrowserPluginsSync';\nimport {\n buildThemeSpecimen,\n isSampleOutputName,\n sampleOutputName,\n} from '../../lib/theme-editor/specimen';\nimport { getThemeName } from '../../lib/theme-validation';\nimport { useShallow } from 'zustand/react/shallow';\n\ninterface BuildRequest {\n id: string;\n docName: string;\n doc: any;\n signal: AbortSignal;\n timestamp: number;\n /** Ordering ticket for the quality slice; see lib/quality-sequence.ts. */\n qualityTicket: number;\n}\n\nfunction EditorComponent() {\n const setOutput = useOutputStore((state) => state.setOutput);\n const outputStore = useContext(OutputStoreContext)!;\n const documentsStore = useContext(DocumentsStoreContext)!;\n const themesStore = useContext(ThemesStoreContext)!;\n const saveDocumentDebounceWait = useSettingsStore(\n (state) => state.saveDocumentDebounceWait\n );\n const {\n openTabs,\n activeTab,\n setActiveTab,\n documents,\n buildErrors,\n setBuildError,\n documentTypes,\n } = useDocumentsStore(\n useShallow((state) => ({\n openTabs: state.openTabs,\n activeTab: state.activeTab,\n setActiveTab: state.setActiveTab,\n documents: state.documents,\n buildErrors: state.buildErrors,\n setBuildError: state.setBuildError,\n documentTypes: state.documentTypes,\n }))\n );\n const { customThemes } = useThemesStore(\n useShallow((state) => ({ customThemes: state.customThemes }))\n );\n const { generatePresentation, cancelGeneration } = usePresentationGenerator();\n const qualityProfileIds = useSettingsStore(\n (state) => state.qualityProfileIds\n );\n const qualityProfileId = storedProfileId(qualityProfileIds);\n const qualityGate = useSettingsStore((state) => state.qualityGate);\n const qualityPolicyText = useSettingsStore(\n (state) => state.qualityPolicies?.[FORMAT]\n );\n const qualityOptions = useMemo(\n () => buildQualityOptions(qualityProfileId, qualityGate, qualityPolicyText),\n [qualityProfileId, qualityGate, qualityPolicyText]\n );\n const { analyze: analyzeQuality, cancel: cancelQualityAnalysis } =\n useQualityAnalysis();\n\n // Refs to track ongoing operations and prevent race conditions\n const buildAbortControllersRef = useRef<Map<string, AbortController>>(\n new Map()\n );\n const buildTimeoutsRef = useRef<Map<string, NodeJS.Timeout>>(new Map());\n // Debounce timer for Run-button builds (150ms to coalesce rapid clicks).\n const flushBuildTimerRef = useRef<NodeJS.Timeout | null>(null);\n const lastBuildRequestIdRef = useRef<string>('');\n const documentVersionsRef = useRef<Map<string, number>>(new Map());\n\n // User-initiated cancel from the loading UI: invalidate the current request\n // id first (so both build paths take their quiet \"cancelled\" exit instead of\n // surfacing a global error), then abort the controllers and the in-flight\n // fetch.\n const cancelActiveBuild = useCallback(() => {\n lastBuildRequestIdRef.current = `cancelled-${Date.now()}`;\n // Also drop queued debounced builds — without this, a pending auto-build\n // timer could start a new generation right after the user cancelled.\n for (const timeout of buildTimeoutsRef.current.values()) {\n clearTimeout(timeout);\n }\n buildTimeoutsRef.current.clear();\n if (flushBuildTimerRef.current) {\n clearTimeout(flushBuildTimerRef.current);\n flushBuildTimerRef.current = null;\n }\n for (const controller of buildAbortControllersRef.current.values()) {\n controller.abort();\n }\n buildAbortControllersRef.current.clear();\n cancelGeneration();\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n }, [cancelGeneration, setOutput]);\n\n useEffect(() => {\n setOutput({ cancelGeneration: cancelActiveBuild });\n }, [cancelActiveBuild, setOutput]);\n\n // Get or create a document version number\n const getDocumentVersion = useCallback((docName: string) => {\n const currentVersion = documentVersionsRef.current.get(docName) || 0;\n const newVersion = currentVersion + 1;\n documentVersionsRef.current.set(docName, newVersion);\n return newVersion;\n }, []);\n\n // Prepare valid custom themes with deep comparison\n const customThemesContentHash = useMemo(() => {\n // Create a content hash of all themes to detect deep changes\n const themeData = Object.entries(customThemes).map(([key, theme]) => {\n // Handle lastModified that might be a string (from localStorage) or Date\n let lastModifiedTime = 0;\n if (theme.lastModified) {\n if (theme.lastModified instanceof Date) {\n lastModifiedTime = theme.lastModified.getTime();\n } else if (typeof theme.lastModified === 'string') {\n lastModifiedTime = new Date(theme.lastModified).getTime();\n }\n }\n\n return {\n key,\n name: theme.name,\n content: theme.content,\n valid: theme.valid,\n lastModified: lastModifiedTime,\n };\n });\n return JSON.stringify(themeData);\n }, [customThemes]);\n\n const validCustomThemes = useMemo(() => {\n const themes: { [key: string]: any } = {};\n Object.values(customThemes).forEach((theme) => {\n if (theme.valid && theme.parsed) {\n themes[theme.name] = theme.parsed;\n }\n });\n return themes;\n }, [customThemesContentHash]);\n\n // Helper function to get fresh theme data (bypasses memo)\n const getFreshThemeData = useCallback(() => {\n const freshThemes: { [key: string]: any } = {};\n const { customThemes } = themesStore.getState();\n Object.values(customThemes).forEach((theme) => {\n if (theme.valid && theme.parsed) {\n freshThemes[theme.name] = theme.parsed;\n }\n });\n return freshThemes;\n }, [themesStore]);\n\n // Helper function to build a document with proper cancellation and retry\n const buildDocument = useCallback(\n async (\n doc: any,\n signal?: AbortSignal,\n options?: { bypassCache?: boolean }\n ) => {\n if (!doc || !generatePresentation) {\n return;\n }\n\n // Cancel any existing build operation for this document\n const existingController = buildAbortControllersRef.current.get(doc.name);\n if (existingController) {\n existingController.abort();\n buildAbortControllersRef.current.delete(doc.name);\n }\n\n // Create new abort controller if not provided\n const abortController = signal ? null : new AbortController();\n const finalSignal = signal || abortController!.signal;\n if (abortController) {\n buildAbortControllersRef.current.set(doc.name, abortController);\n }\n\n // Create build request\n const requestId = `${doc.name}-${Date.now()}-${Math.random()}`;\n const version = getDocumentVersion(doc.name);\n lastBuildRequestIdRef.current = requestId;\n\n const buildRequest: BuildRequest = {\n id: requestId,\n docName: doc.name,\n doc,\n signal: finalSignal,\n timestamp: Date.now(),\n // Claimed now, not on completion: a long build must not overwrite the\n // live analysis of an edit made while it was running.\n qualityTicket: nextQualityTicket(),\n };\n\n await processBuildRequestRef.current(buildRequest, version, options);\n },\n [generatePresentation, setOutput, getDocumentVersion]\n );\n\n // Process a build request from the queue\n const processBuildRequest = useCallback(\n async (\n request: BuildRequest,\n version: number,\n options?: { bypassCache?: boolean }\n ) => {\n const { doc, signal, id, qualityTicket } = request;\n // A build's findings describe the text it was handed. Anything newer in\n // the store was computed against text the editor actually holds now.\n const qualityIfCurrent = (next: QualityState) =>\n isStaleQualityTicket(outputStore.getState().quality, qualityTicket)\n ? {}\n : { quality: next };\n\n // Check if this is still the latest request\n if (lastBuildRequestIdRef.current !== id) {\n console.log('Skipping outdated build request for:', doc.name);\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n return;\n }\n\n setOutput({\n globalError: undefined,\n isGenerating: true,\n generationStartedAt: Date.now(),\n generationProgress: {\n stage: 'parsing',\n message: 'Validating JSON structure...',\n },\n });\n\n const onProgress = (\n stage: 'parsing' | 'building' | 'rendering' | 'finalizing',\n message?: string\n ) => {\n if (signal.aborted || lastBuildRequestIdRef.current !== id) return;\n\n // Check document version to ensure we're still building the latest\n const currentVersion = documentVersionsRef.current.get(doc.name) || 0;\n if (currentVersion !== version) {\n console.log('Document version changed, aborting build');\n signal.dispatchEvent(new Event('abort'));\n return;\n }\n\n setOutput({\n isGenerating: true,\n generationProgress: { stage, message },\n });\n };\n\n try {\n // Always get fresh theme data to ensure latest changes are applied\n const freshThemeData = getFreshThemeData();\n\n console.log('Editor: Using themes for document build', {\n docName: doc.name,\n freshThemeCount: Object.keys(freshThemeData).length,\n freshThemeNames: Object.keys(freshThemeData),\n memoizedCount: Object.keys(validCustomThemes).length,\n requestId: id,\n });\n\n // Browser plugins are expanded here, before the document leaves the\n // page: the server only ever sees standard components. Outside the\n // retry below, because a plugin that throws will throw again.\n onProgress('parsing', 'Expanding plugins...');\n const expansion = await expandForServer(doc.text, {\n customThemes: freshThemeData,\n signal,\n });\n // A document build supersedes a theme sample as the thing Run refreshes.\n if (!isSampleOutputName(doc.name)) lastSampleRef.current = null;\n if (signal.aborted || lastBuildRequestIdRef.current !== id) {\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n return;\n }\n\n // Retry logic for temporary failures\n const result = await retry(\n async () => {\n if (signal.aborted) throw new Error('Build cancelled');\n return await generatePresentation(\n doc.name,\n expansion.text,\n freshThemeData,\n onProgress,\n {\n ...options,\n ...(qualityOptions ? { quality: qualityOptions } : {}),\n }\n );\n },\n {\n maxRetries: 2,\n initialDelay: 500,\n shouldRetry: (error) => {\n // Don't retry on cancellation or syntax errors\n if (\n error.message.includes('cancelled') ||\n error.message.includes('JSON') ||\n error.message.includes('parse') ||\n error.message.includes('syntax')\n ) {\n return false;\n }\n // Retry on worker errors\n return RetryStrategies.combine(\n RetryStrategies.temporaryErrors,\n (e) =>\n e.message.includes('Worker') || e.message.includes('Proxy')\n )(error);\n },\n onRetry: (error, attempt) => {\n console.log(\n `Retrying presentation generation (attempt ${attempt}):`,\n error.message\n );\n setOutput({\n isGenerating: true,\n generationProgress: {\n stage: 'parsing',\n message: `Retrying generation (attempt ${attempt})...`,\n },\n });\n },\n signal,\n }\n );\n\n if (signal.aborted || lastBuildRequestIdRef.current !== id) {\n console.log('Build cancelled for:', doc.name);\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n return;\n }\n\n if (\n result &&\n typeof result === 'object' &&\n 'name' in result &&\n 'text' in result &&\n 'blob' in result\n ) {\n console.log('Editor: Build completed', {\n docName: result.name,\n blobSize: (result.blob as Blob)?.size,\n timestamp: Date.now(),\n requestId: id,\n version,\n });\n\n // Quality findings arrive flattened into the same warnings array\n // as component warnings. Left there they are counted as warnings\n // whatever their real severity, which is how a stock deck's two\n // hundred advisory infos became a warning-coloured bar.\n const { findings, others } = splitQualityWarnings(\n (result as any).warnings as\n | GenerationWarningLike[]\n | null\n | undefined\n );\n\n setOutput({\n name: result.name as string,\n text: result.text as string,\n blob: result.blob as Blob,\n renderer: result.renderer as string | undefined,\n globalError: undefined,\n isGenerating: false,\n isPreviewStale: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n lastBuiltSequence: outputStore.getState().editSequence,\n cacheStatus: (result as any).cacheStatus as\n | 'HIT'\n | 'MISS'\n | 'UNKNOWN'\n | undefined,\n cacheHitRate: (result as any).cacheHitRate as string | undefined,\n // Plugin warnings first: they were raised by the author's own code\n // and read above whatever the renderer then had to say.\n warnings: [...expansion.warnings, ...others] as GenerationWarning[],\n ...qualityIfCurrent({\n findings,\n counts: countBySeverity(findings),\n // The generate response does not name the profile it ran, so\n // only an explicit choice is reported; a blank label is honest\n // about the server having picked the format's default.\n ...(qualityProfileId ? { profileId: qualityProfileId } : {}),\n documentName: doc.name,\n seq: qualityTicket,\n source: 'generate',\n analyzedAt: Date.now(),\n }),\n });\n setBuildError(result.name as string, undefined);\n }\n } catch (error) {\n if (signal.aborted || lastBuildRequestIdRef.current !== id) {\n console.log('Build cancelled with error for:', doc.name);\n setOutput({\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n });\n return;\n }\n\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n // A gate rejection is the only failure that says something about the\n // document rather than about the request, and it ships the findings\n // that caused it — so the panel names them instead of leaving the\n // author with \"blocked\" and nothing to act on.\n const gateFindings =\n error instanceof QualityGateFailedError\n ? findingsFromAnalysis(error.quality)\n : null;\n\n setOutput({\n globalError: errorMessage,\n isGenerating: false,\n generationProgress: undefined,\n generationStartedAt: undefined,\n ...(gateFindings\n ? qualityIfCurrent({\n findings: gateFindings,\n counts: countBySeverity(gateFindings),\n ...(qualityProfileId ? { profileId: qualityProfileId } : {}),\n documentName: doc.name,\n seq: qualityTicket,\n blocked: true,\n source: 'generate' as const,\n analyzedAt: Date.now(),\n gateError: errorMessage,\n })\n : {}),\n });\n\n setBuildError(doc.name, errorMessage);\n } finally {\n buildAbortControllersRef.current.delete(doc.name);\n }\n },\n [\n generatePresentation,\n getFreshThemeData,\n qualityOptions,\n qualityProfileId,\n setOutput,\n setBuildError,\n outputStore,\n ]\n );\n const processBuildRequestRef = useRef(processBuildRequest);\n useEffect(() => {\n processBuildRequestRef.current = processBuildRequest;\n });\n\n // Track the last viewed document for theme updates\n const lastViewedDocumentRef = useRef<string | null>(null);\n // The theme whose sample is on screen, if a sample is what was last built.\n const lastSampleRef = useRef<{ themeDocName: string } | null>(null);\n\n // re-build on active tab change or any document change\n useEffect(() => {\n console.log('Editor: Document rebuild effect triggered', {\n activeTab,\n });\n\n const activeFile = documents.find((doc) => doc.name === activeTab);\n const docType = documentTypes[activeTab] || 'application/json+report';\n\n // Track last viewed document\n if (docType === 'application/json+report' && activeFile) {\n lastViewedDocumentRef.current = activeTab;\n }\n\n // Clear any pending build timeout for this document\n const existingTimeout = buildTimeoutsRef.current.get(activeTab);\n if (existingTimeout) {\n clearTimeout(existingTimeout);\n buildTimeoutsRef.current.delete(activeTab);\n }\n\n if (activeFile && docType === 'application/json+report') {\n // Editing marks the preview stale rather than rebuilding: a build costs\n // a LibreOffice conversion, so it waits for Run. Do not clobber a build\n // already in flight (e.g. one the Run button started).\n if (!outputStore.getState().isGenerating) {\n setOutput({ isPreviewStale: true });\n }\n } else if (activeFile && docType !== 'application/json+report') {\n // Theme or plugin tab active — no document preview to build.\n // Don't clear blob: preserve the last document preview in the background.\n cancelGeneration();\n }\n\n // Cleanup function to cancel pending operations\n return () => {\n const timeout = buildTimeoutsRef.current.get(activeTab);\n if (timeout) {\n clearTimeout(timeout);\n buildTimeoutsRef.current.delete(activeTab);\n }\n };\n }, [\n documents,\n activeTab,\n setOutput,\n documentTypes,\n buildDocument,\n cancelGeneration,\n ]);\n\n // Refresh the quality findings as the document settles, so the panel tracks\n // the editor instead of only the last build. `analyze` debounces and aborts\n // its own in-flight request, so a stale analysis can never land on top of a\n // newer one; returning `cancel` drops the pending work on unmount and on a\n // document switch.\n useEffect(() => {\n const activeFile = documents.find((doc) => doc.name === activeTab);\n const docType = documentTypes[activeTab] || 'application/json+report';\n if (!activeFile || docType !== 'application/json+report') {\n // A theme has no document findings of its own, and an analysis started\n // for the previous tab would report them under this one. Clearing rather\n // than only cancelling matters because nothing else ever will: without\n // it the previous document's findings stay on screen, and actionable,\n // for as long as a theme tab is open.\n cancelQualityAnalysis();\n setOutput({ quality: null });\n return;\n }\n analyzeQuality(activeTab, activeFile.text);\n return cancelQualityAnalysis;\n }, [\n activeTab,\n analyzeQuality,\n cancelQualityAnalysis,\n documents,\n documentTypes,\n setOutput,\n ]);\n\n // Track which documents use which themes (only parse the active doc to avoid O(n) JSON.parse)\n const documentThemeDependencies = useMemo(() => {\n const deps = new Map<string, string>();\n const activeDoc = documents.find((d) => d.name === activeTab);\n if (\n activeDoc &&\n documentTypes[activeDoc.name] === 'application/json+report'\n ) {\n try {\n const parsed = JSON.parse(activeDoc.text);\n const themeName = parsed.props?.theme;\n if (typeof themeName === 'string') {\n const themeExists = Object.values(customThemes).some(\n (t) => t.name === themeName && t.valid\n );\n if (themeExists) {\n deps.set(activeDoc.name, themeName);\n }\n }\n } catch {\n // Ignore parse errors\n }\n }\n return deps;\n }, [activeTab, documents, documentTypes, customThemes]);\n\n // Listen for theme change events and force immediate rebuild\n useEffect(() => {\n console.log('Editor: Setting up theme change listener', {\n documentCount: documents.length,\n dependencyCount: documentThemeDependencies.size,\n dependencies: Array.from(documentThemeDependencies.entries()),\n customThemes: Object.entries(customThemes).map(([key, theme]) => ({\n key,\n name: theme.name,\n valid: theme.valid,\n })),\n });\n\n const unsubscribe = themeChangeEmitter.onThemeChange((event) => {\n console.log('Editor: Theme change detected', {\n event,\n dependencies: Array.from(documentThemeDependencies.entries()),\n activeTab,\n customThemes: Object.entries(customThemes).map(([key, theme]) => ({\n key,\n name: theme.name,\n valid: theme.valid,\n })),\n });\n\n // Find all documents that use this theme\n const documentsUsingTheme: any[] = [];\n\n documentThemeDependencies.forEach((themeName, docName) => {\n if (themeName === event.themeName) {\n const doc = documents.find((d) => d.name === docName);\n if (doc) {\n documentsUsingTheme.push(doc);\n }\n }\n });\n\n console.log('Editor: Documents using changed theme', {\n themeName: event.themeName,\n documentCount: documentsUsingTheme.length,\n documentNames: documentsUsingTheme.map((d) => d.name),\n });\n\n if (documentsUsingTheme.length === 0) {\n console.log('Editor: No documents use this theme, skipping rebuild');\n return;\n }\n\n // A theme change invalidates the preview of every document using it;\n // rebuilding is the author’s call, as it is for a document edit.\n if (!outputStore.getState().isGenerating) {\n setOutput({ isPreviewStale: true });\n }\n });\n\n return unsubscribe;\n }, [\n documentThemeDependencies,\n documents,\n buildDocument,\n getDocumentVersion,\n activeTab,\n setOutput,\n ]);\n\n // Flush debounces and immediately build — triggered by Run button via custom event\n // Debounced at 150ms to coalesce rapid clicks\n // Stable refs so the event handler never goes stale and doesn't need\n // reactive deps that would cause cleanup to cancel the pending timeout\n const buildDocumentRef = useRef(buildDocument);\n useEffect(() => {\n buildDocumentRef.current = buildDocument;\n });\n const getDocumentVersionRef = useRef(getDocumentVersion);\n useEffect(() => {\n getDocumentVersionRef.current = getDocumentVersion;\n });\n\n useEffect(() => {\n const handler = () => {\n // Mark generating early so the rebuild effect (triggered by saveDocument\n // below) doesn't clobber this build with isPreviewStale\n setOutput({ isGenerating: true });\n\n // 1. Flush Monaco debounce: read live text, save to store immediately\n let themeDirty = false;\n const editorRef = useEditorRefsStore.getState().getActiveEditor();\n if (editorRef) {\n // Don't flush if a pending diff is active — editor may be disposed\n const hasPendingDiff =\n documentsStore.getState().pendingDiffs[editorRef.documentName];\n if (!hasPendingDiff) {\n const liveText = editorRef.toStorageValue(\n editorRef.editor.getValue()\n );\n documentsStore\n .getState()\n .saveDocument(editorRef.documentName, liveText);\n }\n }\n\n // Flush all open theme editors whose live text differs from the\n // themes store so the build always uses up-to-date theme data.\n const { documents: allDocs, documentTypes: allDtypes } =\n documentsStore.getState();\n for (const doc of allDocs) {\n if (allDtypes[doc.name] === 'application/json+theme') {\n const ref = useEditorRefsStore.getState().getEditor(doc.name);\n if (ref) {\n const liveText = ref.toStorageValue(ref.editor.getValue());\n const existing = themesStore.getState().customThemes[doc.name];\n if (!existing || existing.content !== liveText) {\n themesStore.getState().updateTheme(doc.name, liveText);\n themeDirty = true;\n }\n }\n } else if (allDtypes[doc.name] === 'application/typescript+plugin') {\n // A plugin edited a moment ago is still behind its save debounce\n // and its compile debounce; the build must see what is on screen.\n const ref = useEditorRefsStore.getState().getEditor(doc.name);\n if (ref) {\n ref.flushPendingSave?.();\n const liveText = ref.toStorageValue(ref.editor.getValue());\n if (liveText !== doc.text) {\n documentsStore.getState().saveDocument(doc.name, liveText);\n }\n }\n }\n }\n // Whatever compile the edits above queued starts now rather than after\n // its debounce; the build below waits for the queue to drain.\n compileQueue.flush();\n\n // 2. Cancel any pending build timeout for active doc\n const currentTab = documentsStore.getState().activeTab;\n const timeout = buildTimeoutsRef.current.get(currentTab);\n if (timeout) {\n clearTimeout(timeout);\n buildTimeoutsRef.current.delete(currentTab);\n }\n\n // 3. Debounce the actual build to coalesce rapid Run clicks\n if (flushBuildTimerRef.current) {\n clearTimeout(flushBuildTimerRef.current);\n }\n flushBuildTimerRef.current = setTimeout(async () => {\n flushBuildTimerRef.current = null;\n // Plugins that were just edited are compiling; a build that ran now\n // would expand with the previous compiled code.\n await compileQueue.whenIdle();\n const {\n documents: docs,\n activeTab: tab,\n documentTypes: dtypes,\n } = documentsStore.getState();\n\n // Determine target: if active tab is a theme or a plugin, build the\n // last-viewed document instead — unless what is on screen is this\n // theme's sample, in which case Run refreshes the sample.\n let targetName = tab;\n const tabType = dtypes[tab] || 'application/json+report';\n if (tabType !== 'application/json+report') {\n const sample = lastSampleRef.current;\n if (\n sample &&\n tabType === 'application/json+theme' &&\n sample.themeDocName === tab\n ) {\n buildSampleRef.current(tab);\n return;\n }\n if (lastViewedDocumentRef.current) {\n targetName = lastViewedDocumentRef.current;\n } else {\n // No document was viewed yet — nothing to build\n setOutput({ isGenerating: false });\n return;\n }\n }\n\n const freshDoc = docs.find((d) => d.name === targetName);\n if (freshDoc) {\n // If a pending diff exists (AI suggestion), preview the modified version\n const pending = documentsStore.getState().pendingDiffs[targetName];\n const ref = useEditorRefsStore.getState().getEditor(targetName);\n const doc = pending\n ? { ...freshDoc, text: pending.modified }\n : ref\n ? { ...freshDoc, text: ref.toStorageValue(ref.editor.getValue()) }\n : freshDoc;\n getDocumentVersionRef.current(doc.name);\n // Bypass cache only when a theme was updated during this flush\n buildDocumentRef.current(\n doc,\n undefined,\n themeDirty ? { bypassCache: true } : undefined\n );\n } else {\n setOutput({ isGenerating: false });\n }\n }, 150);\n };\n\n window.addEventListener('preview:flushAndBuild', handler);\n return () => {\n window.removeEventListener('preview:flushAndBuild', handler);\n if (flushBuildTimerRef.current) {\n clearTimeout(flushBuildTimerRef.current);\n }\n };\n }, [setOutput, documentsStore, themesStore]);\n\n // A theme's sample: a document the theme editor builds on demand rather\n // than a file in the workspace. Same build path as Run, cache bypassed since\n // the theme it names was just edited. The sample is remembered per theme\n // file so a later Run on that tab refreshes it instead of swapping the\n // preview back to the last document.\n const buildSample = useCallback(\n (themeDocName: string) => {\n const { documents: docs } = documentsStore.getState();\n const themeDoc = docs.find((d) => d.name === themeDocName);\n if (!themeDoc) {\n setOutput({ isGenerating: false });\n return;\n }\n let parsed: Record<string, unknown> | undefined;\n let themeName: string | null = null;\n let parseError: string | null = null;\n try {\n parsed = JSON.parse(themeDoc.text);\n themeName = getThemeName(parsed);\n } catch (error) {\n // A syntax error and a missing name are different repairs; saying\n // \"no name\" against broken JSON sends the author to the wrong line.\n parseError = error instanceof Error ? error.message : 'Invalid JSON';\n }\n if (!themeName) {\n setOutput({\n isGenerating: false,\n globalError: parseError\n ? `The theme is not valid JSON: ${parseError}`\n : 'The theme has no name',\n });\n return;\n }\n const name = sampleOutputName(themeName);\n const text = JSON.stringify(\n buildThemeSpecimen(FORMAT, themeName, parsed),\n null,\n 2\n );\n lastSampleRef.current = { themeDocName };\n setOutput({ isGenerating: true });\n getDocumentVersionRef.current(name);\n buildDocumentRef.current({ name, text }, undefined, {\n bypassCache: true,\n });\n },\n [documentsStore, setOutput]\n );\n const buildSampleRef = useRef(buildSample);\n useEffect(() => {\n buildSampleRef.current = buildSample;\n });\n\n useEffect(() => {\n const handler = (event: Event) => {\n const detail = (event as CustomEvent<{ themeDocName?: string }>).detail;\n if (!detail?.themeDocName) return;\n buildSampleRef.current(detail.themeDocName);\n };\n window.addEventListener('preview:buildSpecimen', handler);\n return () => window.removeEventListener('preview:buildSpecimen', handler);\n }, []);\n\n // A plugin that recompiled may change what the previewed document renders\n // to; like a theme edit, that is the author's cue to Run again.\n useEffect(() => {\n const handler = () => {\n if (!outputStore.getState().isGenerating) {\n setOutput({ isPreviewStale: true });\n }\n };\n window.addEventListener(BROWSER_PLUGINS_CHANGED_EVENT, handler);\n return () =>\n window.removeEventListener(BROWSER_PLUGINS_CHANGED_EVENT, handler);\n }, [outputStore, setOutput]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n // Cancel all pending builds\n buildAbortControllersRef.current.forEach((controller) =>\n controller.abort()\n );\n buildAbortControllersRef.current.clear();\n\n // Clear all timeouts\n buildTimeoutsRef.current.forEach((timeout) => clearTimeout(timeout));\n buildTimeoutsRef.current.clear();\n\n // Cancel any ongoing generation\n cancelGeneration();\n };\n }, [cancelGeneration]);\n\n if (!openTabs.length) {\n return (\n <div className=\"flex flex-col text-muted-foreground h-full items-center justify-center\">\n {!documents?.length ? 'Create a new document...' : 'Open a document...'}\n </div>\n );\n }\n\n return (\n <Tabs value={activeTab} onValueChange={setActiveTab} className=\"h-full\">\n {/* Tabs header removed to gain vertical space */}\n <EditorTabsContentMemoized\n openTabs={openTabs}\n documents={documents}\n buildErrors={buildErrors}\n saveDocumentDebounceWait={saveDocumentDebounceWait}\n />\n </Tabs>\n );\n}\n\n// Export memoized version of Editor component\nexport const Editor = memo(EditorComponent);\n"],"names":["validators","monaco","dummyDiv","dummyEditorInstance","editorInstanceConstructorName","editorModelConstructorName","valueToValidate","ranges","rangeObj","num","TypeMustBe","type","key","additional","deepClone","byPassPrimitives","value","callback","cloneArray","array","keys","arrayClone","i","cloner","object","clone","config","constructOptionForCode","options","acc","option","codes","methods","API","methodName","enums","constrainedModel","model","rangeConstructor","sortRangesInAscendingOrder","rangeObject1","rangeObject2","rangeA","rangeB","normalizeRange","range","content","lines","noOfLines","normalizedRange","index","actualStartCol","startLineNo","maxCols","actualEndLine","actualEndCol","endLineNo","restrictions","prepareRestrictions","restriction","startLine","startCol","endLine","endCol","getCurrentEditableRanges","getValueInEditableRanges","updateValueInEditableRanges","forceMoveMarkers","restrictionsMap","label","doesChangeHasMultilineConflict","newRange","isChangeInvalidAsPerUser","disposeRestrictions","handleUnhandledPromiseRejection","isCursorAtCheckPoint","positions","position","posLineNumber","posCol","length","addEditableRangeListener","triggerChangeListenersWith","currentChanges","allChanges","currentRanges","doUndo","updateRange","finalLine","finalColumn","changes","changeIndex","oldRangeEndLineNumber","oldRangeEndColumn","changesLength","diffInCol","diffInRow","cursorPositions","noOfCursorPositions","change","cursorPosition","nextRestriction","nextRange","nextChange","rangeInChange","rangeAsString","rangeMapValue","getInfoFrom","editableRange","info","updateRestrictions","toggleHighlightOfEditableAreas","cssClasses","cssClassForSingleLine","cssClassForMultiLine","decorations","decoration","setAllRangesToPrev","rangeMap","text","manipulatorApi","contentChangedEvent","isUndoing","editedRange","changedRange","noOfLinesAdded","noOfColsAddedAtLastLine","lineDiffInRange","colDiffInRange","columnsCarriedToEnd","values","currentlyEditedRanges","rangeString","exposedApi","funcName","apiName","constrainedEditor","listenerFn","editorInstance","selections","selection","_uriRestrictionMap","isInstanceValid","isModelValid","isRangesValid","initInEditorInstance","domNode","manipulator","newDomNode","addRestrictionsTo","modelToConstrain","removeRestrictionsIn","uri","restrictedModel","disposeConstrainer","toggleDevMode","editor","startLineNumber","endLineNumber","startColumn","endColumn","exposedMethods","resolveThemeDefaultPath","name","ext","FORMAT","EditorMonacoTheme","document","readOnly","onChange","editorRef","useRef","monacoRef","modelRef","theme","useTheme","validationErrors","setValidationErrors","useState","showValidationPanel","setShowValidationPanel","isValidationPanelMinimized","setIsValidationPanelMinimized","userDismissedRef","pendingDiff","useDocumentsStore","s","clearPendingDiff","saveDocument","registerEditor","unregisterEditor","setActiveEditor","useEditorRefsStore","resolvedTheme","handleEditorWillMount","useCallback","registerMonacoThemes","handleEditorMount","constrainedInstance","getSelectionContext","snippet","createContextSnippet","_a","useEffect","handleChange","_event","handleEditorValidation","markers","errors","marker","handleErrorClick","error","monacoThemeFor","jsxs","Fragment","jsx","Button","DiffEditor","MonacoEditor","ValidationStatusBar","ValidationPanel","EditorMonacoThemeMemoized","React","humanize","spaced","COLOR_PATTERN","enumOptions","schema","v","branches","b","scalarKind","schemaField","path","required","base","scalar","field","integer","step","min","max","requiredKeys","child","sub","SECTION_TITLES","extendedSections","handledKeys","handled","matchesQuery","query","terms","needle","term","filterFields","fields","out","own","children","fieldValueError","resolveThemeColor","direct","resolveColor","palette","entry","isHexColor","summarizeValue","_cachedSchema","fetchThemeJsonSchema","json","Popover","PopoverPrimitive.Root","PopoverTrigger","PopoverPrimitive.Trigger","PopoverContent","React.forwardRef","className","align","sideOffset","props","ref","PopoverPrimitive.Portal","PopoverPrimitive.Content","cn","hexToRgb","hex","match","int","rgbToHex","r","g","channel","rgbToHsv","red","green","blue","span","h","hsvToRgb","hue","c","x","m","hexToHsv","rgb","hsvToHex","hsv","readableInk","TOKEN_NAME","PLACEHOLDER_HEX","useFrameCommit","commit","pending","frame","latest","flush","schedule","finish","useDragArea","onMove","onEnd","report","event","box","y","onPointerDown","onPointerMove","onPointerUp","SaturationArea","move","drag","delta","next","HUE_GRADIENT","HueRail","TokenChips","tokens","active","onPick","token","selected","Tooltip","TooltipTrigger","Check","TooltipContent","ColorControl","id","resolved","onCommit","allowReference","open","setOpen","commitText","draft","trimmed","normalizeHex","useDraft","swatch","reference","ColorPickerBody","Input","INPUT_CLASS","onDone","setHsv","seeded","commitHex","eyedropper","EyeDropperCtor","picked","normalized","PickerHexInput","Pipette","X","useThemeColorTokens","useMemo","colors","themeColorTokens","TOKENS","colorTokens","GROUPS","t","rowState","raw","ColorRow","set","remove","useThemeEditor","clear","inputId","HINT_CLASS","CornerDownRight","ClearButton","ThemeColorsSection","searching","rows","contrast","background","primary","contrastRatio","defined","EditorSection","ContrastBadge","group","row","GroupLabel","MAX_ROWS","buildOptions","catalog","family","font","score","lower","filterOptions","current","known","rest","scored","rank","a","FamilyCombobox","pickerPath","setQuery","setActive","listRef","useFontCatalog","matches","typed","exact","custom","choose","browse","useFontPickerStore","onKeyDown","last","clamped","_b","Type","ChevronsUpDown","Search","Row","QuietButton","tag","onHover","asString","asNumber","DocxRoleCard","role","size","commitFamily","commitSize","familyId","sizeId","FONT_ROLE_HINTS","FIELD_LABEL_CLASS","DraftNumberInput","PptxFamilyRow","PptxDefaults","fontSize","getAt","fontColor","commitColor","ThemeTypographySection","whole","roleMatches","forceOpen","roles","DOCX_FONT_ROLES","record","PPTX_FONT_ROLES","showDefaults","CUSTOM","UNITS","STEP","MARGIN_PATHS","MARGIN_KEYS","WIDTH_PATH","HEIGHT_PATH","twips","LengthField","unit","unitToTwips","twipsToUnit","ThemePageSection","PAGE_SIZES","setUnit","isCustom","sizeValue","onSizeChange","Select","SelectTrigger","SelectValue","SelectContent","u","SelectItem","SELECT_TRIGGER_CLASS","NAMES","styleNames","FIELDS","styleFields","BASIC","f","ADVANCED","STYLE_DEPTH","BOOLEAN_OPTIONS","fieldKey","summarize","style","parts","push","ColorField","styleName","StyleField","commitString","commitNumber","isSet","control","DraftTextInput","Segmented","StyleRow","styleJson","tokensJson","resolvedJson","more","setMore","define","removeStyle","styleLabel","setCount","renderField","o","ChevronRight","Trash2","Plus","AddCustomStyle","existing","setName","problem","submit","e","ThemeStylesSection","customStyleNames","styles","table","colorFields","all","definedCount","UNSET","fieldId","SECTION_DEPTH","ScalarControl","onOpenJson","JsonOnly","summary","onClear","Braces","ListControl","entries","item","add","seed","full","entryField","ListEntry","_","onRemove","FieldRow","clearable","GroupRows","depth","Rows","ThemeSchemaSection","section","useExtendedSections","sections","setSections","cancelled","formKeys","ThemeVisualEditor","docName","usedBy","nameClash","parsed","parseTheme","update","fn","serializeTheme","head","container","ensureContainers","setAt","prune","deleteAt","parent","actions","ThemeEditorProvider","ThemeForm","useScrollCrumb","barRef","crumb","setCrumb","bar","viewport","measure","line","chain","element","previous","observer","extended","extendedKeys","ScrollArea","IdentitySection","AdvancedSection","IDENTITY_FIELDS","IdentityField","hint","alsoHandled","advancedKeys","ThemeEditorHost","preferred","useSettingsStore","setSettings","hasPendingDiff","themeName","getThemeName","EMPTY","names","d","documentThemeName","themeFileName","view","themeView","openJson","NONE","ThemeEditorHostMemoized","usePluginTypesReady","ready","setReady","pluginTypeScriptReady","onPluginTypeScriptReady","PluginEditorStrip","useBrowserPluginsStore","setEnabled","setAllowNetwork","setNetworkOrigins","toast","useToast","copiedIndex","setCopiedIndex","typesReady","metadata","status","errorCount","displayName","PLUGIN_FILE_SUFFIX","examples","announce","BROWSER_PLUGINS_CHANGED_EVENT","toggleEnabled","enabled","recompileUnderNewPolicy","pluginHost","compileQueue","toggleNetwork","allowNetwork","commitOrigins","origins","copyExample","example","usage","statusChip","Spinner","Puzzle","Badge","Info","DropdownMenu","DropdownMenuTrigger","BookOpen","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuItem","Copy","Switch","NetworkControl","download","DownloadIcon","PluginEditorStripMemoized","onToggle","onCommitOrigins","setDraft","parseNetworkOrigins","granted","Globe","Textarea","EditorMonacoPlugin","saveDocumentDebounceWait","closeDocument","diagnostics","lastSavedRef","editorValue","setEditorValue","debouncedSaveRef","debounce","showPanel","setShowPanel","panelMinimized","setPanelMinimized","handleWillMount","ensurePluginTypeScript","flushPendingSave","handleMount","saveNow","debouncedSave","Editor","pluginModelPath","EditorMonacoPluginMemoized","TabContent","_buildError","documentType","state","updateTheme","useThemesStore","debouncedUpdateTheme","TabsContent","EditorMonacoJsonMemoized","TabContentMemoized","EditorTabsContent","openTabs","documents","buildErrors","documentTypes","doc","EditorTabsContentMemoized","RetryError","message","lastError","attempts","retry","maxRetries","initialDelay","maxDelay","backoffFactor","onRetry","shouldRetry","signal","attempt","jitteredDelay","resolve","timeoutId","RetryStrategies","pattern","statusCodes","strategies","strategy","BODY_TEXT","TOKEN_ROLES","swatchTokens","definedColorKeys","hasStyle","docxSpecimen","pptxSpecimen","w","slides","swatches","column","sampleOutputName","isSampleOutputName","buildThemeSpecimen","format","EditorComponent","setOutput","useOutputStore","outputStore","useContext","OutputStoreContext","documentsStore","DocumentsStoreContext","themesStore","ThemesStoreContext","activeTab","setActiveTab","setBuildError","useShallow","customThemes","generatePresentation","cancelGeneration","usePresentationGenerator","qualityProfileIds","qualityProfileId","storedProfileId","qualityGate","qualityPolicyText","qualityOptions","buildQualityOptions","analyzeQuality","cancelQualityAnalysis","useQualityAnalysis","buildAbortControllersRef","buildTimeoutsRef","flushBuildTimerRef","lastBuildRequestIdRef","documentVersionsRef","cancelActiveBuild","timeout","controller","getDocumentVersion","newVersion","customThemesContentHash","themeData","lastModifiedTime","validCustomThemes","themes","getFreshThemeData","freshThemes","buildDocument","existingController","abortController","finalSignal","requestId","version","buildRequest","nextQualityTicket","processBuildRequestRef","processBuildRequest","request","qualityTicket","qualityIfCurrent","isStaleQualityTicket","onProgress","stage","freshThemeData","expansion","expandForServer","result","findings","others","splitQualityWarnings","countBySeverity","errorMessage","gateFindings","QualityGateFailedError","findingsFromAnalysis","lastViewedDocumentRef","lastSampleRef","activeFile","docType","existingTimeout","documentThemeDependencies","deps","activeDoc","themeChangeEmitter","documentsUsingTheme","buildDocumentRef","getDocumentVersionRef","handler","themeDirty","liveText","allDocs","allDtypes","currentTab","docs","tab","dtypes","targetName","tabType","sample","buildSampleRef","freshDoc","buildSample","themeDocName","themeDoc","parseError","detail","Tabs","memo"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5]}
|