@templatical/core 0.0.1 → 0.0.2
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/cloud/index.cjs +106 -24
- package/dist/cloud/index.cjs.map +1 -1
- package/dist/cloud/index.d.cts +17 -2
- package/dist/cloud/index.d.ts +17 -2
- package/dist/cloud/index.js +105 -24
- package/dist/cloud/index.js.map +1 -1
- package/dist/editor-K644r-hl.d.cts +39 -0
- package/dist/editor-K644r-hl.d.ts +39 -0
- package/dist/index.cjs +40 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -76
- package/dist/index.d.ts +13 -76
- package/dist/index.js +38 -3
- package/dist/index.js.map +1 -1
- package/package.json +17 -7
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { TemplateContent, ViewportSize, UiTheme, TemplateDefaults, Block, TemplateSettings } from '@templatical/types';
|
|
2
|
+
import { Ref, DeepReadonly } from '@vue/reactivity';
|
|
3
|
+
|
|
4
|
+
interface EditorState {
|
|
5
|
+
content: TemplateContent;
|
|
6
|
+
selectedBlockId: string | null;
|
|
7
|
+
viewport: ViewportSize;
|
|
8
|
+
darkMode: boolean;
|
|
9
|
+
previewMode: boolean;
|
|
10
|
+
isDirty: boolean;
|
|
11
|
+
uiTheme: UiTheme;
|
|
12
|
+
}
|
|
13
|
+
interface UseEditorOptions {
|
|
14
|
+
content: TemplateContent;
|
|
15
|
+
defaultFontFamily?: string;
|
|
16
|
+
templateDefaults?: TemplateDefaults;
|
|
17
|
+
lockedBlocks?: Ref<Map<string, unknown>>;
|
|
18
|
+
}
|
|
19
|
+
interface UseEditorReturn {
|
|
20
|
+
state: DeepReadonly<EditorState>;
|
|
21
|
+
content: Ref<TemplateContent>;
|
|
22
|
+
selectedBlock: Ref<Block | null>;
|
|
23
|
+
setContent: (content: TemplateContent, markDirty?: boolean) => void;
|
|
24
|
+
selectBlock: (blockId: string | null) => void;
|
|
25
|
+
setViewport: (viewport: ViewportSize) => void;
|
|
26
|
+
setDarkMode: (darkMode: boolean) => void;
|
|
27
|
+
setPreviewMode: (previewMode: boolean) => void;
|
|
28
|
+
setUiTheme: (theme: UiTheme) => void;
|
|
29
|
+
updateBlock: (blockId: string, updates: Partial<Block>) => void;
|
|
30
|
+
updateSettings: (updates: Partial<TemplateSettings>) => void;
|
|
31
|
+
addBlock: (block: Block, targetSectionId?: string, columnIndex?: number, index?: number) => void;
|
|
32
|
+
removeBlock: (blockId: string) => void;
|
|
33
|
+
moveBlock: (blockId: string, newIndex: number, targetSectionId?: string, columnIndex?: number) => void;
|
|
34
|
+
isBlockLocked: (blockId: string) => boolean;
|
|
35
|
+
markDirty: () => void;
|
|
36
|
+
}
|
|
37
|
+
declare function useEditor(options: UseEditorOptions): UseEditorReturn;
|
|
38
|
+
|
|
39
|
+
export { type EditorState as E, type UseEditorReturn as U, type UseEditorOptions as a, useEditor as u };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { TemplateContent, ViewportSize, UiTheme, TemplateDefaults, Block, TemplateSettings } from '@templatical/types';
|
|
2
|
+
import { Ref, DeepReadonly } from '@vue/reactivity';
|
|
3
|
+
|
|
4
|
+
interface EditorState {
|
|
5
|
+
content: TemplateContent;
|
|
6
|
+
selectedBlockId: string | null;
|
|
7
|
+
viewport: ViewportSize;
|
|
8
|
+
darkMode: boolean;
|
|
9
|
+
previewMode: boolean;
|
|
10
|
+
isDirty: boolean;
|
|
11
|
+
uiTheme: UiTheme;
|
|
12
|
+
}
|
|
13
|
+
interface UseEditorOptions {
|
|
14
|
+
content: TemplateContent;
|
|
15
|
+
defaultFontFamily?: string;
|
|
16
|
+
templateDefaults?: TemplateDefaults;
|
|
17
|
+
lockedBlocks?: Ref<Map<string, unknown>>;
|
|
18
|
+
}
|
|
19
|
+
interface UseEditorReturn {
|
|
20
|
+
state: DeepReadonly<EditorState>;
|
|
21
|
+
content: Ref<TemplateContent>;
|
|
22
|
+
selectedBlock: Ref<Block | null>;
|
|
23
|
+
setContent: (content: TemplateContent, markDirty?: boolean) => void;
|
|
24
|
+
selectBlock: (blockId: string | null) => void;
|
|
25
|
+
setViewport: (viewport: ViewportSize) => void;
|
|
26
|
+
setDarkMode: (darkMode: boolean) => void;
|
|
27
|
+
setPreviewMode: (previewMode: boolean) => void;
|
|
28
|
+
setUiTheme: (theme: UiTheme) => void;
|
|
29
|
+
updateBlock: (blockId: string, updates: Partial<Block>) => void;
|
|
30
|
+
updateSettings: (updates: Partial<TemplateSettings>) => void;
|
|
31
|
+
addBlock: (block: Block, targetSectionId?: string, columnIndex?: number, index?: number) => void;
|
|
32
|
+
removeBlock: (blockId: string) => void;
|
|
33
|
+
moveBlock: (blockId: string, newIndex: number, targetSectionId?: string, columnIndex?: number) => void;
|
|
34
|
+
isBlockLocked: (blockId: string) => boolean;
|
|
35
|
+
markDirty: () => void;
|
|
36
|
+
}
|
|
37
|
+
declare function useEditor(options: UseEditorOptions): UseEditorReturn;
|
|
38
|
+
|
|
39
|
+
export { type EditorState as E, type UseEditorReturn as U, type UseEditorOptions as a, useEditor as u };
|
package/dist/index.cjs
CHANGED
|
@@ -25,7 +25,8 @@ __export(index_exports, {
|
|
|
25
25
|
useConditionPreview: () => useConditionPreview,
|
|
26
26
|
useDataSourceFetch: () => useDataSourceFetch,
|
|
27
27
|
useEditor: () => useEditor,
|
|
28
|
-
useHistory: () => useHistory
|
|
28
|
+
useHistory: () => useHistory,
|
|
29
|
+
useHistoryInterceptor: () => useHistoryInterceptor
|
|
29
30
|
});
|
|
30
31
|
module.exports = __toCommonJS(index_exports);
|
|
31
32
|
|
|
@@ -42,7 +43,8 @@ function useEditor(options) {
|
|
|
42
43
|
viewport: "desktop",
|
|
43
44
|
darkMode: false,
|
|
44
45
|
previewMode: false,
|
|
45
|
-
isDirty: false
|
|
46
|
+
isDirty: false,
|
|
47
|
+
uiTheme: "auto"
|
|
46
48
|
});
|
|
47
49
|
const content = (0, import_reactivity.computed)({
|
|
48
50
|
get: () => state.content,
|
|
@@ -105,6 +107,9 @@ function useEditor(options) {
|
|
|
105
107
|
function setDarkMode(darkMode) {
|
|
106
108
|
state.darkMode = darkMode;
|
|
107
109
|
}
|
|
110
|
+
function setUiTheme(theme) {
|
|
111
|
+
state.uiTheme = theme;
|
|
112
|
+
}
|
|
108
113
|
function setPreviewMode(previewMode) {
|
|
109
114
|
state.previewMode = previewMode;
|
|
110
115
|
if (previewMode) {
|
|
@@ -191,6 +196,7 @@ function useEditor(options) {
|
|
|
191
196
|
selectBlock,
|
|
192
197
|
setViewport,
|
|
193
198
|
setDarkMode,
|
|
199
|
+
setUiTheme,
|
|
194
200
|
setPreviewMode,
|
|
195
201
|
updateBlock,
|
|
196
202
|
updateSettings,
|
|
@@ -475,7 +481,7 @@ function useDataSourceFetch(options) {
|
|
|
475
481
|
fieldValues: { ...options.block.value.fieldValues },
|
|
476
482
|
blockId: options.block.value.id
|
|
477
483
|
});
|
|
478
|
-
if (result
|
|
484
|
+
if (result == null) {
|
|
479
485
|
return;
|
|
480
486
|
}
|
|
481
487
|
const merged = { ...options.block.value.fieldValues };
|
|
@@ -500,6 +506,35 @@ function useDataSourceFetch(options) {
|
|
|
500
506
|
needsFetch
|
|
501
507
|
};
|
|
502
508
|
}
|
|
509
|
+
|
|
510
|
+
// src/history-interceptor.ts
|
|
511
|
+
function useHistoryInterceptor(editor, history) {
|
|
512
|
+
const originalAddBlock = editor.addBlock;
|
|
513
|
+
const originalRemoveBlock = editor.removeBlock;
|
|
514
|
+
const originalMoveBlock = editor.moveBlock;
|
|
515
|
+
const originalUpdateBlock = editor.updateBlock;
|
|
516
|
+
const originalUpdateSettings = editor.updateSettings;
|
|
517
|
+
editor.addBlock = (block, targetSectionId, columnIndex, index) => {
|
|
518
|
+
history.record();
|
|
519
|
+
originalAddBlock(block, targetSectionId, columnIndex, index);
|
|
520
|
+
};
|
|
521
|
+
editor.removeBlock = (blockId) => {
|
|
522
|
+
history.record();
|
|
523
|
+
originalRemoveBlock(blockId);
|
|
524
|
+
};
|
|
525
|
+
editor.moveBlock = (blockId, newIndex, targetSectionId, columnIndex) => {
|
|
526
|
+
history.record();
|
|
527
|
+
originalMoveBlock(blockId, newIndex, targetSectionId, columnIndex);
|
|
528
|
+
};
|
|
529
|
+
editor.updateBlock = (blockId, updates) => {
|
|
530
|
+
history.recordDebounced(blockId);
|
|
531
|
+
originalUpdateBlock(blockId, updates);
|
|
532
|
+
};
|
|
533
|
+
editor.updateSettings = (updates) => {
|
|
534
|
+
history.record();
|
|
535
|
+
originalUpdateSettings(updates);
|
|
536
|
+
};
|
|
537
|
+
}
|
|
503
538
|
// Annotate the CommonJS export names for ESM import in node:
|
|
504
539
|
0 && (module.exports = {
|
|
505
540
|
useAutoSave,
|
|
@@ -507,6 +542,7 @@ function useDataSourceFetch(options) {
|
|
|
507
542
|
useConditionPreview,
|
|
508
543
|
useDataSourceFetch,
|
|
509
544
|
useEditor,
|
|
510
|
-
useHistory
|
|
545
|
+
useHistory,
|
|
546
|
+
useHistoryInterceptor
|
|
511
547
|
});
|
|
512
548
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/editor.ts","../src/history.ts","../src/block-actions.ts","../src/auto-save.ts","../src/condition-preview.ts","../src/data-source-fetch.ts"],"sourcesContent":["// Editor state\nexport { useEditor } from \"./editor\";\nexport type { EditorState, UseEditorOptions, UseEditorReturn } from \"./editor\";\n\n// History (undo/redo)\nexport { useHistory } from \"./history\";\nexport type { UseHistoryOptions, UseHistoryReturn } from \"./history\";\n\n// Block actions\nexport { useBlockActions } from \"./block-actions\";\nexport type {\n UseBlockActionsOptions,\n UseBlockActionsReturn,\n} from \"./block-actions\";\n\n// Auto-save\nexport { useAutoSave } from \"./auto-save\";\nexport type { UseAutoSaveOptions, UseAutoSaveReturn } from \"./auto-save\";\n\n// Display condition preview\nexport { useConditionPreview } from \"./condition-preview\";\nexport type { UseConditionPreviewReturn } from \"./condition-preview\";\n\n// Custom block data source fetching\nexport { useDataSourceFetch } from \"./data-source-fetch\";\n\n// Plugin system\nexport type {\n BlockContextAction,\n EditorPlugin,\n EditorPluginContext,\n SidebarPanel,\n ToolbarAction,\n} from \"./plugins\";\n","import type {\n Block,\n TemplateContent,\n TemplateDefaults,\n TemplateSettings,\n ViewportSize,\n} from \"@templatical/types\";\nimport { createDefaultTemplateContent } from \"@templatical/types\";\nimport {\n computed,\n reactive,\n readonly,\n type DeepReadonly,\n type Ref,\n} from \"@vue/reactivity\";\n\nexport interface EditorState {\n content: TemplateContent;\n selectedBlockId: string | null;\n viewport: ViewportSize;\n darkMode: boolean;\n previewMode: boolean;\n isDirty: boolean;\n}\n\nexport interface UseEditorOptions {\n content: TemplateContent;\n defaultFontFamily?: string;\n templateDefaults?: TemplateDefaults;\n lockedBlocks?: Ref<Map<string, unknown>>;\n}\n\nexport interface UseEditorReturn {\n state: DeepReadonly<EditorState>;\n content: Ref<TemplateContent>;\n selectedBlock: Ref<Block | null>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n selectBlock: (blockId: string | null) => void;\n setViewport: (viewport: ViewportSize) => void;\n setDarkMode: (darkMode: boolean) => void;\n setPreviewMode: (previewMode: boolean) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n updateSettings: (updates: Partial<TemplateSettings>) => void;\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n index?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n moveBlock: (\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n isBlockLocked: (blockId: string) => boolean;\n markDirty: () => void;\n}\n\nexport function useEditor(options: UseEditorOptions): UseEditorReturn {\n const state = reactive<EditorState>({\n content:\n options.content ??\n createDefaultTemplateContent(\n options.defaultFontFamily,\n options.templateDefaults,\n ),\n selectedBlockId: null,\n viewport: \"desktop\",\n darkMode: false,\n previewMode: false,\n isDirty: false,\n });\n\n const content = computed({\n get: () => state.content,\n set: (value: TemplateContent) => {\n state.content = value;\n state.isDirty = true;\n },\n });\n\n const selectedBlock = computed(() => {\n if (!state.selectedBlockId) return null;\n return findBlockById(state.content.blocks, state.selectedBlockId);\n });\n\n function findBlockById(blocks: Block[], id: string): Block | null {\n for (const block of blocks) {\n if (block.id === id) return block;\n if (block.type === \"section\") {\n for (const column of block.children) {\n const found = findBlockById(column, id);\n if (found) return found;\n }\n }\n }\n return null;\n }\n\n function findBlockParent(\n blocks: Block[],\n id: string,\n parent: {\n blocks: Block[];\n sectionId?: string;\n columnIndex?: number;\n } = { blocks },\n ): { blocks: Block[]; sectionId?: string; columnIndex?: number } | null {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (block.id === id) return parent;\n if (block.type === \"section\") {\n for (let colIdx = 0; colIdx < block.children.length; colIdx++) {\n const result = findBlockParent(block.children[colIdx], id, {\n blocks: block.children[colIdx],\n sectionId: block.id,\n columnIndex: colIdx,\n });\n if (result) return result;\n }\n }\n }\n return null;\n }\n\n function isBlockLocked(blockId: string): boolean {\n return options.lockedBlocks?.value.has(blockId) ?? false;\n }\n\n function setContent(newContent: TemplateContent, markDirty = true): void {\n state.content = newContent;\n if (markDirty) {\n state.isDirty = true;\n }\n }\n\n function selectBlock(blockId: string | null): void {\n if (blockId && isBlockLocked(blockId)) {\n return;\n }\n state.selectedBlockId = blockId;\n }\n\n function setViewport(viewport: ViewportSize): void {\n state.viewport = viewport;\n }\n\n function setDarkMode(darkMode: boolean): void {\n state.darkMode = darkMode;\n }\n\n function setPreviewMode(previewMode: boolean): void {\n state.previewMode = previewMode;\n if (previewMode) {\n state.selectedBlockId = null;\n }\n }\n\n function updateBlock(blockId: string, updates: Partial<Block>): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const block = findBlockById(state.content.blocks, blockId);\n if (block) {\n Object.assign(block, updates);\n state.isDirty = true;\n }\n }\n\n function updateSettings(updates: Partial<TemplateSettings>): void {\n state.content.settings = { ...state.content.settings, ...updates };\n state.isDirty = true;\n }\n\n function addBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex = 0,\n index?: number,\n ): void {\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n const targetArray = section.children[columnIndex];\n if (index !== undefined && index < targetArray.length) {\n targetArray.splice(index, 0, block);\n } else {\n targetArray.push(block);\n }\n }\n } else {\n if (index !== undefined && index < state.content.blocks.length) {\n state.content.blocks.splice(index, 0, block);\n } else {\n state.content.blocks.push(block);\n }\n }\n state.isDirty = true;\n }\n\n function removeBlock(blockId: string): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const parent = findBlockParent(state.content.blocks, blockId);\n if (parent) {\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index !== -1) {\n parent.blocks.splice(index, 1);\n if (state.selectedBlockId === blockId) {\n state.selectedBlockId = null;\n }\n state.isDirty = true;\n }\n }\n }\n\n function moveBlock(\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex = 0,\n ): void {\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return;\n\n const oldIndex = parent.blocks.findIndex((b) => b.id === blockId);\n if (oldIndex === -1) return;\n\n const [block] = parent.blocks.splice(oldIndex, 1);\n\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n section.children[columnIndex].splice(newIndex, 0, block);\n }\n } else {\n state.content.blocks.splice(newIndex, 0, block);\n }\n\n state.isDirty = true;\n }\n\n function markDirty(): void {\n state.isDirty = true;\n }\n\n return {\n state: readonly(state),\n content,\n selectedBlock,\n isBlockLocked,\n setContent,\n selectBlock,\n setViewport,\n setDarkMode,\n setPreviewMode,\n updateBlock,\n updateSettings,\n addBlock,\n removeBlock,\n moveBlock,\n markDirty,\n };\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport { computed, ref, type ComputedRef, type Ref } from \"@vue/reactivity\";\n\nexport interface UseHistoryOptions {\n content: Ref<TemplateContent>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n isRemoteOperation?: () => boolean;\n maxSize?: number;\n}\n\nexport interface UseHistoryReturn {\n canUndo: ComputedRef<boolean>;\n canRedo: ComputedRef<boolean>;\n isNavigating: Ref<boolean>;\n undo: () => void;\n redo: () => void;\n record: () => void;\n recordDebounced: (blockId: string) => void;\n clear: () => void;\n destroy: () => void;\n}\n\ninterface DebouncedSnapshot {\n blockId: string;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\nconst MAX_STACK_SIZE = 50;\nconst DEBOUNCE_MS = 300;\nconst NAVIGATE_IDLE_MS = 1500;\n\nexport function useHistory(options: UseHistoryOptions): UseHistoryReturn {\n const {\n content,\n setContent,\n isRemoteOperation,\n maxSize = MAX_STACK_SIZE,\n } = options;\n\n const undoStack = ref<TemplateContent[]>([]);\n const redoStack = ref<TemplateContent[]>([]);\n const isNavigating = ref(false);\n let navigatingTimeoutId: ReturnType<typeof setTimeout> | null = null;\n let pendingDebounce: DebouncedSnapshot | null = null;\n\n const canUndo = computed(() => undoStack.value.length > 0);\n const canRedo = computed(() => redoStack.value.length > 0);\n\n function cloneContent(): TemplateContent {\n return JSON.parse(JSON.stringify(content.value)) as TemplateContent;\n }\n\n function pushToUndoStack(snapshot: TemplateContent): void {\n undoStack.value.push(snapshot);\n if (undoStack.value.length > maxSize) {\n undoStack.value.splice(0, undoStack.value.length - maxSize);\n }\n }\n\n function flushPendingDebounce(): void {\n if (pendingDebounce) {\n clearTimeout(pendingDebounce.timeoutId);\n pendingDebounce = null;\n }\n }\n\n function record(): void {\n if (isRemoteOperation?.()) {\n return;\n }\n\n flushPendingDebounce();\n pushToUndoStack(cloneContent());\n redoStack.value = [];\n }\n\n function recordDebounced(blockId: string): void {\n if (isRemoteOperation?.()) {\n return;\n }\n\n if (pendingDebounce && pendingDebounce.blockId === blockId) {\n clearTimeout(pendingDebounce.timeoutId);\n pendingDebounce.timeoutId = setTimeout(() => {\n pendingDebounce = null;\n }, DEBOUNCE_MS);\n return;\n }\n\n flushPendingDebounce();\n\n pushToUndoStack(cloneContent());\n redoStack.value = [];\n\n pendingDebounce = {\n blockId,\n timeoutId: setTimeout(() => {\n pendingDebounce = null;\n }, DEBOUNCE_MS),\n };\n }\n\n function setNavigating(): void {\n isNavigating.value = true;\n if (navigatingTimeoutId) {\n clearTimeout(navigatingTimeoutId);\n }\n navigatingTimeoutId = setTimeout(() => {\n isNavigating.value = false;\n navigatingTimeoutId = null;\n }, NAVIGATE_IDLE_MS);\n }\n\n function undo(): void {\n if (undoStack.value.length === 0) {\n return;\n }\n\n flushPendingDebounce();\n\n const snapshot = undoStack.value.pop()!;\n redoStack.value.push(cloneContent());\n setContent(snapshot, true);\n setNavigating();\n }\n\n function redo(): void {\n if (redoStack.value.length === 0) {\n return;\n }\n\n flushPendingDebounce();\n\n const snapshot = redoStack.value.pop()!;\n undoStack.value.push(cloneContent());\n setContent(snapshot, true);\n setNavigating();\n }\n\n function clear(): void {\n undoStack.value = [];\n redoStack.value = [];\n flushPendingDebounce();\n }\n\n function destroy(): void {\n clear();\n if (navigatingTimeoutId) {\n clearTimeout(navigatingTimeoutId);\n navigatingTimeoutId = null;\n }\n }\n\n return {\n canUndo,\n canRedo,\n isNavigating,\n undo,\n redo,\n record,\n recordDebounced,\n clear,\n destroy,\n };\n}\n","import type { Block, BlockDefaults, BlockType } from \"@templatical/types\";\nimport { createBlock, generateId } from \"@templatical/types\";\n\nexport interface UseBlockActionsOptions {\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n selectBlock: (blockId: string | null) => void;\n blockDefaults?: BlockDefaults;\n}\n\nexport interface UseBlockActionsReturn {\n createAndAddBlock: (\n type: BlockType,\n targetSectionId?: string,\n columnIndex?: number,\n ) => Block;\n duplicateBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ) => Block;\n deleteBlock: (blockId: string) => void;\n updateBlockProperty: <K extends keyof Block>(\n blockId: string,\n key: K,\n value: Block[K],\n ) => void;\n}\n\nexport function useBlockActions(\n options: UseBlockActionsOptions,\n): UseBlockActionsReturn {\n const { addBlock, removeBlock, updateBlock, selectBlock } = options;\n\n function createAndAddBlock(\n type: BlockType,\n targetSectionId?: string,\n columnIndex?: number,\n ): Block {\n const block = createBlock(type, options.blockDefaults);\n addBlock(block, targetSectionId, columnIndex);\n selectBlock(block.id);\n return block;\n }\n\n function duplicateBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ): Block {\n const cloned = JSON.parse(JSON.stringify(block)) as Block;\n cloned.id = generateId();\n\n if (cloned.type === \"section\") {\n cloned.children = cloned.children.map((column) =>\n column.map((child) => {\n const clonedChild = JSON.parse(JSON.stringify(child)) as Block;\n clonedChild.id = generateId();\n return clonedChild;\n }),\n );\n }\n\n addBlock(cloned, targetSectionId, columnIndex);\n selectBlock(cloned.id);\n return cloned;\n }\n\n function deleteBlock(blockId: string): void {\n removeBlock(blockId);\n }\n\n function updateBlockProperty<K extends keyof Block>(\n blockId: string,\n key: K,\n value: Block[K],\n ): void {\n updateBlock(blockId, { [key]: value } as Partial<Block>);\n }\n\n return {\n createAndAddBlock,\n duplicateBlock,\n deleteBlock,\n updateBlockProperty,\n };\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport { watch, type Ref } from \"@vue/reactivity\";\n\nexport interface UseAutoSaveOptions {\n content: Ref<TemplateContent>;\n isDirty: () => boolean;\n onChange: (content: TemplateContent) => void;\n debounce?: number;\n enabled?: boolean | (() => boolean);\n}\n\nexport interface UseAutoSaveReturn {\n flush: () => void;\n cancel: () => void;\n pause: () => void;\n resume: () => void;\n destroy: () => void;\n}\n\nexport function useAutoSave(options: UseAutoSaveOptions): UseAutoSaveReturn {\n const {\n content,\n isDirty,\n onChange,\n debounce = 1000,\n enabled = true,\n } = options;\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let paused = false;\n\n function isEnabled(): boolean {\n return typeof enabled === \"function\" ? enabled() : enabled;\n }\n\n function pause(): void {\n paused = true;\n cancel();\n }\n\n function resume(): void {\n paused = false;\n }\n\n function cancel(): void {\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function flush(): void {\n cancel();\n if (isDirty()) {\n onChange(JSON.parse(JSON.stringify(content.value)));\n }\n }\n\n function scheduleOnChange(): void {\n if (!isEnabled() || paused) return;\n\n cancel();\n timeoutId = setTimeout(() => {\n timeoutId = null;\n if (isDirty()) {\n onChange(JSON.parse(JSON.stringify(content.value)));\n }\n }, debounce);\n }\n\n const stopWatch = watch(\n content,\n () => {\n if (isEnabled() && !paused && isDirty()) {\n scheduleOnChange();\n }\n },\n { deep: true },\n );\n\n function destroy(): void {\n stopWatch();\n cancel();\n }\n\n return {\n flush,\n cancel,\n pause,\n resume,\n destroy,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport { computed, reactive, type ComputedRef } from \"@vue/reactivity\";\n\nexport interface UseConditionPreviewReturn {\n isHidden: (blockId: string) => boolean;\n toggleBlock: (blockId: string) => void;\n reset: () => void;\n hasHiddenBlocks: ComputedRef<boolean>;\n}\n\nexport function useConditionPreview(\n editor: UseEditorReturn,\n): UseConditionPreviewReturn {\n const hiddenBlockIds = reactive(new Set<string>());\n\n const hasHiddenBlocks = computed(() => hiddenBlockIds.size > 0);\n\n function isHidden(blockId: string): boolean {\n return hiddenBlockIds.has(blockId);\n }\n\n function toggleBlock(blockId: string): void {\n if (hiddenBlockIds.has(blockId)) {\n hiddenBlockIds.delete(blockId);\n } else {\n hiddenBlockIds.add(blockId);\n\n if (editor.state.selectedBlockId === blockId) {\n editor.selectBlock(null);\n }\n }\n }\n\n function reset(): void {\n hiddenBlockIds.clear();\n }\n\n return {\n isHidden,\n toggleBlock,\n reset,\n hasHiddenBlocks,\n };\n}\n","import type { CustomBlock, CustomBlockDefinition } from \"@templatical/types\";\nimport type { ComputedRef, Ref } from \"@vue/reactivity\";\nimport { computed, ref } from \"@vue/reactivity\";\n\nexport function useDataSourceFetch(options: {\n definition: ComputedRef<CustomBlockDefinition | undefined>;\n block: ComputedRef<CustomBlock>;\n onUpdate: (fieldValues: Record<string, unknown>, fetched: boolean) => void;\n}): {\n isFetching: Ref<boolean>;\n fetchError: Ref<boolean>;\n fetch: () => Promise<void>;\n hasDataSource: ComputedRef<boolean>;\n needsFetch: ComputedRef<boolean>;\n} {\n const isFetching = ref(false);\n const fetchError = ref(false);\n\n const hasDataSource = computed(() => !!options.definition.value?.dataSource);\n\n const needsFetch = computed(\n () => hasDataSource.value && !options.block.value.dataSourceFetched,\n );\n\n async function fetch(): Promise<void> {\n const def = options.definition.value;\n if (!def?.dataSource) {\n return;\n }\n\n isFetching.value = true;\n fetchError.value = false;\n\n try {\n const result = await def.dataSource.onFetch({\n fieldValues: { ...options.block.value.fieldValues },\n blockId: options.block.value.id,\n });\n\n if (result === null || result === undefined) {\n return;\n }\n\n const merged = { ...options.block.value.fieldValues };\n for (const key of Object.keys(merged)) {\n if (key in result) {\n merged[key] = result[key];\n }\n }\n\n options.onUpdate(merged, true);\n } catch (error) {\n console.warn(\"[Templatical] Data source fetch error:\", error);\n fetchError.value = true;\n } finally {\n isFetching.value = false;\n }\n }\n\n return {\n isFetching,\n fetchError,\n fetch,\n hasDataSource,\n needsFetch,\n };\n}\n"],"mappings":"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","names":["markDirty","import_reactivity","import_types","import_reactivity","import_reactivity","import_reactivity"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/editor.ts","../src/history.ts","../src/block-actions.ts","../src/auto-save.ts","../src/condition-preview.ts","../src/data-source-fetch.ts","../src/history-interceptor.ts"],"sourcesContent":["// Editor state\nexport { useEditor } from \"./editor\";\nexport type { EditorState, UseEditorOptions, UseEditorReturn } from \"./editor\";\n\n// History (undo/redo)\nexport { useHistory } from \"./history\";\nexport type { UseHistoryOptions, UseHistoryReturn } from \"./history\";\n\n// Block actions\nexport { useBlockActions } from \"./block-actions\";\nexport type {\n UseBlockActionsOptions,\n UseBlockActionsReturn,\n} from \"./block-actions\";\n\n// Auto-save\nexport { useAutoSave } from \"./auto-save\";\nexport type { UseAutoSaveOptions, UseAutoSaveReturn } from \"./auto-save\";\n\n// Display condition preview\nexport { useConditionPreview } from \"./condition-preview\";\nexport type { UseConditionPreviewReturn } from \"./condition-preview\";\n\n// Custom block data source fetching\nexport { useDataSourceFetch } from \"./data-source-fetch\";\n\n// History interceptor\nexport { useHistoryInterceptor } from \"./history-interceptor\";\n","import type {\n Block,\n TemplateContent,\n TemplateDefaults,\n TemplateSettings,\n UiTheme,\n ViewportSize,\n} from \"@templatical/types\";\nimport { createDefaultTemplateContent } from \"@templatical/types\";\nimport {\n computed,\n reactive,\n readonly,\n type DeepReadonly,\n type Ref,\n} from \"@vue/reactivity\";\n\nexport interface EditorState {\n content: TemplateContent;\n selectedBlockId: string | null;\n viewport: ViewportSize;\n darkMode: boolean;\n previewMode: boolean;\n isDirty: boolean;\n uiTheme: UiTheme;\n}\n\nexport interface UseEditorOptions {\n content: TemplateContent;\n defaultFontFamily?: string;\n templateDefaults?: TemplateDefaults;\n lockedBlocks?: Ref<Map<string, unknown>>;\n}\n\nexport interface UseEditorReturn {\n state: DeepReadonly<EditorState>;\n content: Ref<TemplateContent>;\n selectedBlock: Ref<Block | null>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n selectBlock: (blockId: string | null) => void;\n setViewport: (viewport: ViewportSize) => void;\n setDarkMode: (darkMode: boolean) => void;\n setPreviewMode: (previewMode: boolean) => void;\n setUiTheme: (theme: UiTheme) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n updateSettings: (updates: Partial<TemplateSettings>) => void;\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n index?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n moveBlock: (\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n isBlockLocked: (blockId: string) => boolean;\n markDirty: () => void;\n}\n\nexport function useEditor(options: UseEditorOptions): UseEditorReturn {\n const state = reactive<EditorState>({\n content:\n options.content ??\n createDefaultTemplateContent(\n options.defaultFontFamily,\n options.templateDefaults,\n ),\n selectedBlockId: null,\n viewport: \"desktop\",\n darkMode: false,\n previewMode: false,\n isDirty: false,\n uiTheme: \"auto\",\n });\n\n const content = computed({\n get: () => state.content,\n set: (value: TemplateContent) => {\n state.content = value;\n state.isDirty = true;\n },\n });\n\n const selectedBlock = computed(() => {\n if (!state.selectedBlockId) return null;\n return findBlockById(state.content.blocks, state.selectedBlockId);\n });\n\n function findBlockById(blocks: Block[], id: string): Block | null {\n for (const block of blocks) {\n if (block.id === id) return block;\n if (block.type === \"section\") {\n for (const column of block.children) {\n const found = findBlockById(column, id);\n if (found) return found;\n }\n }\n }\n return null;\n }\n\n function findBlockParent(\n blocks: Block[],\n id: string,\n parent: {\n blocks: Block[];\n sectionId?: string;\n columnIndex?: number;\n } = { blocks },\n ): { blocks: Block[]; sectionId?: string; columnIndex?: number } | null {\n for (let i = 0; i < blocks.length; i++) {\n const block = blocks[i];\n if (block.id === id) return parent;\n if (block.type === \"section\") {\n for (let colIdx = 0; colIdx < block.children.length; colIdx++) {\n const result = findBlockParent(block.children[colIdx], id, {\n blocks: block.children[colIdx],\n sectionId: block.id,\n columnIndex: colIdx,\n });\n if (result) return result;\n }\n }\n }\n return null;\n }\n\n function isBlockLocked(blockId: string): boolean {\n return options.lockedBlocks?.value.has(blockId) ?? false;\n }\n\n function setContent(newContent: TemplateContent, markDirty = true): void {\n state.content = newContent;\n if (markDirty) {\n state.isDirty = true;\n }\n }\n\n function selectBlock(blockId: string | null): void {\n if (blockId && isBlockLocked(blockId)) {\n return;\n }\n state.selectedBlockId = blockId;\n }\n\n function setViewport(viewport: ViewportSize): void {\n state.viewport = viewport;\n }\n\n function setDarkMode(darkMode: boolean): void {\n state.darkMode = darkMode;\n }\n\n function setUiTheme(theme: UiTheme): void {\n state.uiTheme = theme;\n }\n\n function setPreviewMode(previewMode: boolean): void {\n state.previewMode = previewMode;\n if (previewMode) {\n state.selectedBlockId = null;\n }\n }\n\n function updateBlock(blockId: string, updates: Partial<Block>): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const block = findBlockById(state.content.blocks, blockId);\n if (block) {\n Object.assign(block, updates);\n state.isDirty = true;\n }\n }\n\n function updateSettings(updates: Partial<TemplateSettings>): void {\n state.content.settings = { ...state.content.settings, ...updates };\n state.isDirty = true;\n }\n\n function addBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex = 0,\n index?: number,\n ): void {\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n const targetArray = section.children[columnIndex];\n if (index !== undefined && index < targetArray.length) {\n targetArray.splice(index, 0, block);\n } else {\n targetArray.push(block);\n }\n }\n } else {\n if (index !== undefined && index < state.content.blocks.length) {\n state.content.blocks.splice(index, 0, block);\n } else {\n state.content.blocks.push(block);\n }\n }\n state.isDirty = true;\n }\n\n function removeBlock(blockId: string): void {\n if (isBlockLocked(blockId)) {\n return;\n }\n const parent = findBlockParent(state.content.blocks, blockId);\n if (parent) {\n const index = parent.blocks.findIndex((b) => b.id === blockId);\n if (index !== -1) {\n parent.blocks.splice(index, 1);\n if (state.selectedBlockId === blockId) {\n state.selectedBlockId = null;\n }\n state.isDirty = true;\n }\n }\n }\n\n function moveBlock(\n blockId: string,\n newIndex: number,\n targetSectionId?: string,\n columnIndex = 0,\n ): void {\n const parent = findBlockParent(state.content.blocks, blockId);\n if (!parent) return;\n\n const oldIndex = parent.blocks.findIndex((b) => b.id === blockId);\n if (oldIndex === -1) return;\n\n const [block] = parent.blocks.splice(oldIndex, 1);\n\n if (targetSectionId) {\n const section = findBlockById(state.content.blocks, targetSectionId);\n if (section && section.type === \"section\") {\n section.children[columnIndex] = section.children[columnIndex] || [];\n section.children[columnIndex].splice(newIndex, 0, block);\n }\n } else {\n state.content.blocks.splice(newIndex, 0, block);\n }\n\n state.isDirty = true;\n }\n\n function markDirty(): void {\n state.isDirty = true;\n }\n\n return {\n state: readonly(state),\n content,\n selectedBlock,\n isBlockLocked,\n setContent,\n selectBlock,\n setViewport,\n setDarkMode,\n setUiTheme,\n setPreviewMode,\n updateBlock,\n updateSettings,\n addBlock,\n removeBlock,\n moveBlock,\n markDirty,\n };\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport { computed, ref, type ComputedRef, type Ref } from \"@vue/reactivity\";\n\nexport interface UseHistoryOptions {\n content: Ref<TemplateContent>;\n setContent: (content: TemplateContent, markDirty?: boolean) => void;\n isRemoteOperation?: () => boolean;\n maxSize?: number;\n}\n\nexport interface UseHistoryReturn {\n canUndo: ComputedRef<boolean>;\n canRedo: ComputedRef<boolean>;\n isNavigating: Ref<boolean>;\n undo: () => void;\n redo: () => void;\n record: () => void;\n recordDebounced: (blockId: string) => void;\n clear: () => void;\n destroy: () => void;\n}\n\ninterface DebouncedSnapshot {\n blockId: string;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\nconst MAX_STACK_SIZE = 50;\nconst DEBOUNCE_MS = 300;\nconst NAVIGATE_IDLE_MS = 1500;\n\nexport function useHistory(options: UseHistoryOptions): UseHistoryReturn {\n const {\n content,\n setContent,\n isRemoteOperation,\n maxSize = MAX_STACK_SIZE,\n } = options;\n\n const undoStack = ref<TemplateContent[]>([]);\n const redoStack = ref<TemplateContent[]>([]);\n const isNavigating = ref(false);\n let navigatingTimeoutId: ReturnType<typeof setTimeout> | null = null;\n let pendingDebounce: DebouncedSnapshot | null = null;\n\n const canUndo = computed(() => undoStack.value.length > 0);\n const canRedo = computed(() => redoStack.value.length > 0);\n\n function cloneContent(): TemplateContent {\n return JSON.parse(JSON.stringify(content.value)) as TemplateContent;\n }\n\n function pushToUndoStack(snapshot: TemplateContent): void {\n undoStack.value.push(snapshot);\n if (undoStack.value.length > maxSize) {\n undoStack.value.splice(0, undoStack.value.length - maxSize);\n }\n }\n\n function flushPendingDebounce(): void {\n if (pendingDebounce) {\n clearTimeout(pendingDebounce.timeoutId);\n pendingDebounce = null;\n }\n }\n\n function record(): void {\n if (isRemoteOperation?.()) {\n return;\n }\n\n flushPendingDebounce();\n pushToUndoStack(cloneContent());\n redoStack.value = [];\n }\n\n function recordDebounced(blockId: string): void {\n if (isRemoteOperation?.()) {\n return;\n }\n\n if (pendingDebounce && pendingDebounce.blockId === blockId) {\n clearTimeout(pendingDebounce.timeoutId);\n pendingDebounce.timeoutId = setTimeout(() => {\n pendingDebounce = null;\n }, DEBOUNCE_MS);\n return;\n }\n\n flushPendingDebounce();\n\n pushToUndoStack(cloneContent());\n redoStack.value = [];\n\n pendingDebounce = {\n blockId,\n timeoutId: setTimeout(() => {\n pendingDebounce = null;\n }, DEBOUNCE_MS),\n };\n }\n\n function setNavigating(): void {\n isNavigating.value = true;\n if (navigatingTimeoutId) {\n clearTimeout(navigatingTimeoutId);\n }\n navigatingTimeoutId = setTimeout(() => {\n isNavigating.value = false;\n navigatingTimeoutId = null;\n }, NAVIGATE_IDLE_MS);\n }\n\n function undo(): void {\n if (undoStack.value.length === 0) {\n return;\n }\n\n flushPendingDebounce();\n\n const snapshot = undoStack.value.pop()!;\n redoStack.value.push(cloneContent());\n setContent(snapshot, true);\n setNavigating();\n }\n\n function redo(): void {\n if (redoStack.value.length === 0) {\n return;\n }\n\n flushPendingDebounce();\n\n const snapshot = redoStack.value.pop()!;\n undoStack.value.push(cloneContent());\n setContent(snapshot, true);\n setNavigating();\n }\n\n function clear(): void {\n undoStack.value = [];\n redoStack.value = [];\n flushPendingDebounce();\n }\n\n function destroy(): void {\n clear();\n if (navigatingTimeoutId) {\n clearTimeout(navigatingTimeoutId);\n navigatingTimeoutId = null;\n }\n }\n\n return {\n canUndo,\n canRedo,\n isNavigating,\n undo,\n redo,\n record,\n recordDebounced,\n clear,\n destroy,\n };\n}\n","import type { Block, BlockDefaults, BlockType } from \"@templatical/types\";\nimport { createBlock, generateId } from \"@templatical/types\";\n\nexport interface UseBlockActionsOptions {\n addBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ) => void;\n removeBlock: (blockId: string) => void;\n updateBlock: (blockId: string, updates: Partial<Block>) => void;\n selectBlock: (blockId: string | null) => void;\n blockDefaults?: BlockDefaults;\n}\n\nexport interface UseBlockActionsReturn {\n createAndAddBlock: (\n type: BlockType,\n targetSectionId?: string,\n columnIndex?: number,\n ) => Block;\n duplicateBlock: (\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ) => Block;\n deleteBlock: (blockId: string) => void;\n updateBlockProperty: <K extends keyof Block>(\n blockId: string,\n key: K,\n value: Block[K],\n ) => void;\n}\n\nexport function useBlockActions(\n options: UseBlockActionsOptions,\n): UseBlockActionsReturn {\n const { addBlock, removeBlock, updateBlock, selectBlock } = options;\n\n function createAndAddBlock(\n type: BlockType,\n targetSectionId?: string,\n columnIndex?: number,\n ): Block {\n const block = createBlock(type, options.blockDefaults);\n addBlock(block, targetSectionId, columnIndex);\n selectBlock(block.id);\n return block;\n }\n\n function duplicateBlock(\n block: Block,\n targetSectionId?: string,\n columnIndex?: number,\n ): Block {\n const cloned = JSON.parse(JSON.stringify(block)) as Block;\n cloned.id = generateId();\n\n if (cloned.type === \"section\") {\n cloned.children = cloned.children.map((column) =>\n column.map((child) => {\n const clonedChild = JSON.parse(JSON.stringify(child)) as Block;\n clonedChild.id = generateId();\n return clonedChild;\n }),\n );\n }\n\n addBlock(cloned, targetSectionId, columnIndex);\n selectBlock(cloned.id);\n return cloned;\n }\n\n function deleteBlock(blockId: string): void {\n removeBlock(blockId);\n }\n\n function updateBlockProperty<K extends keyof Block>(\n blockId: string,\n key: K,\n value: Block[K],\n ): void {\n updateBlock(blockId, { [key]: value } as Partial<Block>);\n }\n\n return {\n createAndAddBlock,\n duplicateBlock,\n deleteBlock,\n updateBlockProperty,\n };\n}\n","import type { TemplateContent } from \"@templatical/types\";\nimport { watch, type Ref } from \"@vue/reactivity\";\n\nexport interface UseAutoSaveOptions {\n content: Ref<TemplateContent>;\n isDirty: () => boolean;\n onChange: (content: TemplateContent) => void;\n debounce?: number;\n enabled?: boolean | (() => boolean);\n}\n\nexport interface UseAutoSaveReturn {\n flush: () => void;\n cancel: () => void;\n pause: () => void;\n resume: () => void;\n destroy: () => void;\n}\n\nexport function useAutoSave(options: UseAutoSaveOptions): UseAutoSaveReturn {\n const {\n content,\n isDirty,\n onChange,\n debounce = 1000,\n enabled = true,\n } = options;\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let paused = false;\n\n function isEnabled(): boolean {\n return typeof enabled === \"function\" ? enabled() : enabled;\n }\n\n function pause(): void {\n paused = true;\n cancel();\n }\n\n function resume(): void {\n paused = false;\n }\n\n function cancel(): void {\n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n }\n\n function flush(): void {\n cancel();\n if (isDirty()) {\n onChange(JSON.parse(JSON.stringify(content.value)));\n }\n }\n\n function scheduleOnChange(): void {\n if (!isEnabled() || paused) return;\n\n cancel();\n timeoutId = setTimeout(() => {\n timeoutId = null;\n if (isDirty()) {\n onChange(JSON.parse(JSON.stringify(content.value)));\n }\n }, debounce);\n }\n\n const stopWatch = watch(\n content,\n () => {\n if (isEnabled() && !paused && isDirty()) {\n scheduleOnChange();\n }\n },\n { deep: true },\n );\n\n function destroy(): void {\n stopWatch();\n cancel();\n }\n\n return {\n flush,\n cancel,\n pause,\n resume,\n destroy,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport { computed, reactive, type ComputedRef } from \"@vue/reactivity\";\n\nexport interface UseConditionPreviewReturn {\n isHidden: (blockId: string) => boolean;\n toggleBlock: (blockId: string) => void;\n reset: () => void;\n hasHiddenBlocks: ComputedRef<boolean>;\n}\n\nexport function useConditionPreview(\n editor: UseEditorReturn,\n): UseConditionPreviewReturn {\n const hiddenBlockIds = reactive(new Set<string>());\n\n const hasHiddenBlocks = computed(() => hiddenBlockIds.size > 0);\n\n function isHidden(blockId: string): boolean {\n return hiddenBlockIds.has(blockId);\n }\n\n function toggleBlock(blockId: string): void {\n if (hiddenBlockIds.has(blockId)) {\n hiddenBlockIds.delete(blockId);\n } else {\n hiddenBlockIds.add(blockId);\n\n if (editor.state.selectedBlockId === blockId) {\n editor.selectBlock(null);\n }\n }\n }\n\n function reset(): void {\n hiddenBlockIds.clear();\n }\n\n return {\n isHidden,\n toggleBlock,\n reset,\n hasHiddenBlocks,\n };\n}\n","import type { CustomBlock, CustomBlockDefinition } from \"@templatical/types\";\nimport type { ComputedRef, Ref } from \"@vue/reactivity\";\nimport { computed, ref } from \"@vue/reactivity\";\n\nexport function useDataSourceFetch(options: {\n definition: ComputedRef<CustomBlockDefinition | undefined>;\n block: ComputedRef<CustomBlock>;\n onUpdate: (fieldValues: Record<string, unknown>, fetched: boolean) => void;\n}): {\n isFetching: Ref<boolean>;\n fetchError: Ref<boolean>;\n fetch: () => Promise<void>;\n hasDataSource: ComputedRef<boolean>;\n needsFetch: ComputedRef<boolean>;\n} {\n const isFetching = ref(false);\n const fetchError = ref(false);\n\n const hasDataSource = computed(() => !!options.definition.value?.dataSource);\n\n const needsFetch = computed(\n () => hasDataSource.value && !options.block.value.dataSourceFetched,\n );\n\n async function fetch(): Promise<void> {\n const def = options.definition.value;\n if (!def?.dataSource) {\n return;\n }\n\n isFetching.value = true;\n fetchError.value = false;\n\n try {\n const result = await def.dataSource.onFetch({\n fieldValues: { ...options.block.value.fieldValues },\n blockId: options.block.value.id,\n });\n\n if (result == null) {\n return;\n }\n\n const merged = { ...options.block.value.fieldValues };\n for (const key of Object.keys(merged)) {\n if (key in result) {\n merged[key] = result[key];\n }\n }\n\n options.onUpdate(merged, true);\n } catch (error) {\n console.warn(\"[Templatical] Data source fetch error:\", error);\n fetchError.value = true;\n } finally {\n isFetching.value = false;\n }\n }\n\n return {\n isFetching,\n fetchError,\n fetch,\n hasDataSource,\n needsFetch,\n };\n}\n","import type { UseEditorReturn } from \"./editor\";\nimport type { UseHistoryReturn } from \"./history\";\n\n/**\n * Wraps editor mutation methods to record history snapshots before each\n * operation. Mutates the editor object in place.\n *\n * Must be applied **after** any collaboration broadcast wrapping so the\n * call chain is: history.record() → broadcast → original mutation.\n */\nexport function useHistoryInterceptor(\n editor: UseEditorReturn,\n history: UseHistoryReturn,\n): void {\n const originalAddBlock = editor.addBlock;\n const originalRemoveBlock = editor.removeBlock;\n const originalMoveBlock = editor.moveBlock;\n const originalUpdateBlock = editor.updateBlock;\n const originalUpdateSettings = editor.updateSettings;\n\n editor.addBlock = (block, targetSectionId?, columnIndex?, index?) => {\n history.record();\n originalAddBlock(block, targetSectionId, columnIndex, index);\n };\n\n editor.removeBlock = (blockId) => {\n history.record();\n originalRemoveBlock(blockId);\n };\n\n editor.moveBlock = (blockId, newIndex, targetSectionId?, columnIndex?) => {\n history.record();\n originalMoveBlock(blockId, newIndex, targetSectionId, columnIndex);\n };\n\n editor.updateBlock = (blockId, updates) => {\n history.recordDebounced(blockId);\n originalUpdateBlock(blockId, updates);\n };\n\n editor.updateSettings = (updates) => {\n history.record();\n originalUpdateSettings(updates);\n };\n}\n"],"mappings":"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","names":["markDirty","import_reactivity","import_types","import_reactivity","import_reactivity","import_reactivity"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,38 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
content: TemplateContent;
|
|
6
|
-
selectedBlockId: string | null;
|
|
7
|
-
viewport: ViewportSize;
|
|
8
|
-
darkMode: boolean;
|
|
9
|
-
previewMode: boolean;
|
|
10
|
-
isDirty: boolean;
|
|
11
|
-
}
|
|
12
|
-
interface UseEditorOptions {
|
|
13
|
-
content: TemplateContent;
|
|
14
|
-
defaultFontFamily?: string;
|
|
15
|
-
templateDefaults?: TemplateDefaults;
|
|
16
|
-
lockedBlocks?: Ref<Map<string, unknown>>;
|
|
17
|
-
}
|
|
18
|
-
interface UseEditorReturn {
|
|
19
|
-
state: DeepReadonly<EditorState>;
|
|
20
|
-
content: Ref<TemplateContent>;
|
|
21
|
-
selectedBlock: Ref<Block | null>;
|
|
22
|
-
setContent: (content: TemplateContent, markDirty?: boolean) => void;
|
|
23
|
-
selectBlock: (blockId: string | null) => void;
|
|
24
|
-
setViewport: (viewport: ViewportSize) => void;
|
|
25
|
-
setDarkMode: (darkMode: boolean) => void;
|
|
26
|
-
setPreviewMode: (previewMode: boolean) => void;
|
|
27
|
-
updateBlock: (blockId: string, updates: Partial<Block>) => void;
|
|
28
|
-
updateSettings: (updates: Partial<TemplateSettings>) => void;
|
|
29
|
-
addBlock: (block: Block, targetSectionId?: string, columnIndex?: number, index?: number) => void;
|
|
30
|
-
removeBlock: (blockId: string) => void;
|
|
31
|
-
moveBlock: (blockId: string, newIndex: number, targetSectionId?: string, columnIndex?: number) => void;
|
|
32
|
-
isBlockLocked: (blockId: string) => boolean;
|
|
33
|
-
markDirty: () => void;
|
|
34
|
-
}
|
|
35
|
-
declare function useEditor(options: UseEditorOptions): UseEditorReturn;
|
|
1
|
+
import { U as UseEditorReturn } from './editor-K644r-hl.cjs';
|
|
2
|
+
export { E as EditorState, a as UseEditorOptions, u as useEditor } from './editor-K644r-hl.cjs';
|
|
3
|
+
import { TemplateContent, Block, BlockDefaults, BlockType, CustomBlockDefinition, CustomBlock } from '@templatical/types';
|
|
4
|
+
import { Ref, ComputedRef } from '@vue/reactivity';
|
|
36
5
|
|
|
37
6
|
interface UseHistoryOptions {
|
|
38
7
|
content: Ref<TemplateContent>;
|
|
@@ -104,45 +73,13 @@ declare function useDataSourceFetch(options: {
|
|
|
104
73
|
needsFetch: ComputedRef<boolean>;
|
|
105
74
|
};
|
|
106
75
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
readonly selectedBlockId: DeepReadonly<EditorState>["selectedBlockId"];
|
|
116
|
-
readonly viewport: DeepReadonly<EditorState>["viewport"];
|
|
117
|
-
addBlock(block: Block, targetSectionId?: string, columnIndex?: number, index?: number): void;
|
|
118
|
-
updateBlock(blockId: string, updates: Partial<Block>): void;
|
|
119
|
-
removeBlock(blockId: string): void;
|
|
120
|
-
moveBlock(blockId: string, newIndex: number, targetSectionId?: string, columnIndex?: number): void;
|
|
121
|
-
updateSettings(updates: Partial<TemplateSettings>): void;
|
|
122
|
-
selectBlock(blockId: string | null): void;
|
|
123
|
-
registerToolbarAction(action: ToolbarAction): void;
|
|
124
|
-
registerSidebarPanel(panel: SidebarPanel): void;
|
|
125
|
-
registerBlockAction(action: BlockContextAction): void;
|
|
126
|
-
}
|
|
127
|
-
interface ToolbarAction {
|
|
128
|
-
id: string;
|
|
129
|
-
icon: string;
|
|
130
|
-
label: string;
|
|
131
|
-
onClick: () => void;
|
|
132
|
-
position?: "left" | "right";
|
|
133
|
-
}
|
|
134
|
-
interface SidebarPanel {
|
|
135
|
-
id: string;
|
|
136
|
-
icon: string;
|
|
137
|
-
label: string;
|
|
138
|
-
component: unknown;
|
|
139
|
-
position?: "left" | "right";
|
|
140
|
-
}
|
|
141
|
-
interface BlockContextAction {
|
|
142
|
-
id: string;
|
|
143
|
-
icon: string;
|
|
144
|
-
label: string;
|
|
145
|
-
onClick: (blockId: string) => void;
|
|
146
|
-
}
|
|
76
|
+
/**
|
|
77
|
+
* Wraps editor mutation methods to record history snapshots before each
|
|
78
|
+
* operation. Mutates the editor object in place.
|
|
79
|
+
*
|
|
80
|
+
* Must be applied **after** any collaboration broadcast wrapping so the
|
|
81
|
+
* call chain is: history.record() → broadcast → original mutation.
|
|
82
|
+
*/
|
|
83
|
+
declare function useHistoryInterceptor(editor: UseEditorReturn, history: UseHistoryReturn): void;
|
|
147
84
|
|
|
148
|
-
export { type
|
|
85
|
+
export { type UseAutoSaveOptions, type UseAutoSaveReturn, type UseBlockActionsOptions, type UseBlockActionsReturn, type UseConditionPreviewReturn, UseEditorReturn, type UseHistoryOptions, type UseHistoryReturn, useAutoSave, useBlockActions, useConditionPreview, useDataSourceFetch, useHistory, useHistoryInterceptor };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,38 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
content: TemplateContent;
|
|
6
|
-
selectedBlockId: string | null;
|
|
7
|
-
viewport: ViewportSize;
|
|
8
|
-
darkMode: boolean;
|
|
9
|
-
previewMode: boolean;
|
|
10
|
-
isDirty: boolean;
|
|
11
|
-
}
|
|
12
|
-
interface UseEditorOptions {
|
|
13
|
-
content: TemplateContent;
|
|
14
|
-
defaultFontFamily?: string;
|
|
15
|
-
templateDefaults?: TemplateDefaults;
|
|
16
|
-
lockedBlocks?: Ref<Map<string, unknown>>;
|
|
17
|
-
}
|
|
18
|
-
interface UseEditorReturn {
|
|
19
|
-
state: DeepReadonly<EditorState>;
|
|
20
|
-
content: Ref<TemplateContent>;
|
|
21
|
-
selectedBlock: Ref<Block | null>;
|
|
22
|
-
setContent: (content: TemplateContent, markDirty?: boolean) => void;
|
|
23
|
-
selectBlock: (blockId: string | null) => void;
|
|
24
|
-
setViewport: (viewport: ViewportSize) => void;
|
|
25
|
-
setDarkMode: (darkMode: boolean) => void;
|
|
26
|
-
setPreviewMode: (previewMode: boolean) => void;
|
|
27
|
-
updateBlock: (blockId: string, updates: Partial<Block>) => void;
|
|
28
|
-
updateSettings: (updates: Partial<TemplateSettings>) => void;
|
|
29
|
-
addBlock: (block: Block, targetSectionId?: string, columnIndex?: number, index?: number) => void;
|
|
30
|
-
removeBlock: (blockId: string) => void;
|
|
31
|
-
moveBlock: (blockId: string, newIndex: number, targetSectionId?: string, columnIndex?: number) => void;
|
|
32
|
-
isBlockLocked: (blockId: string) => boolean;
|
|
33
|
-
markDirty: () => void;
|
|
34
|
-
}
|
|
35
|
-
declare function useEditor(options: UseEditorOptions): UseEditorReturn;
|
|
1
|
+
import { U as UseEditorReturn } from './editor-K644r-hl.js';
|
|
2
|
+
export { E as EditorState, a as UseEditorOptions, u as useEditor } from './editor-K644r-hl.js';
|
|
3
|
+
import { TemplateContent, Block, BlockDefaults, BlockType, CustomBlockDefinition, CustomBlock } from '@templatical/types';
|
|
4
|
+
import { Ref, ComputedRef } from '@vue/reactivity';
|
|
36
5
|
|
|
37
6
|
interface UseHistoryOptions {
|
|
38
7
|
content: Ref<TemplateContent>;
|
|
@@ -104,45 +73,13 @@ declare function useDataSourceFetch(options: {
|
|
|
104
73
|
needsFetch: ComputedRef<boolean>;
|
|
105
74
|
};
|
|
106
75
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
readonly selectedBlockId: DeepReadonly<EditorState>["selectedBlockId"];
|
|
116
|
-
readonly viewport: DeepReadonly<EditorState>["viewport"];
|
|
117
|
-
addBlock(block: Block, targetSectionId?: string, columnIndex?: number, index?: number): void;
|
|
118
|
-
updateBlock(blockId: string, updates: Partial<Block>): void;
|
|
119
|
-
removeBlock(blockId: string): void;
|
|
120
|
-
moveBlock(blockId: string, newIndex: number, targetSectionId?: string, columnIndex?: number): void;
|
|
121
|
-
updateSettings(updates: Partial<TemplateSettings>): void;
|
|
122
|
-
selectBlock(blockId: string | null): void;
|
|
123
|
-
registerToolbarAction(action: ToolbarAction): void;
|
|
124
|
-
registerSidebarPanel(panel: SidebarPanel): void;
|
|
125
|
-
registerBlockAction(action: BlockContextAction): void;
|
|
126
|
-
}
|
|
127
|
-
interface ToolbarAction {
|
|
128
|
-
id: string;
|
|
129
|
-
icon: string;
|
|
130
|
-
label: string;
|
|
131
|
-
onClick: () => void;
|
|
132
|
-
position?: "left" | "right";
|
|
133
|
-
}
|
|
134
|
-
interface SidebarPanel {
|
|
135
|
-
id: string;
|
|
136
|
-
icon: string;
|
|
137
|
-
label: string;
|
|
138
|
-
component: unknown;
|
|
139
|
-
position?: "left" | "right";
|
|
140
|
-
}
|
|
141
|
-
interface BlockContextAction {
|
|
142
|
-
id: string;
|
|
143
|
-
icon: string;
|
|
144
|
-
label: string;
|
|
145
|
-
onClick: (blockId: string) => void;
|
|
146
|
-
}
|
|
76
|
+
/**
|
|
77
|
+
* Wraps editor mutation methods to record history snapshots before each
|
|
78
|
+
* operation. Mutates the editor object in place.
|
|
79
|
+
*
|
|
80
|
+
* Must be applied **after** any collaboration broadcast wrapping so the
|
|
81
|
+
* call chain is: history.record() → broadcast → original mutation.
|
|
82
|
+
*/
|
|
83
|
+
declare function useHistoryInterceptor(editor: UseEditorReturn, history: UseHistoryReturn): void;
|
|
147
84
|
|
|
148
|
-
export { type
|
|
85
|
+
export { type UseAutoSaveOptions, type UseAutoSaveReturn, type UseBlockActionsOptions, type UseBlockActionsReturn, type UseConditionPreviewReturn, UseEditorReturn, type UseHistoryOptions, type UseHistoryReturn, useAutoSave, useBlockActions, useConditionPreview, useDataSourceFetch, useHistory, useHistoryInterceptor };
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,8 @@ function useEditor(options) {
|
|
|
15
15
|
viewport: "desktop",
|
|
16
16
|
darkMode: false,
|
|
17
17
|
previewMode: false,
|
|
18
|
-
isDirty: false
|
|
18
|
+
isDirty: false,
|
|
19
|
+
uiTheme: "auto"
|
|
19
20
|
});
|
|
20
21
|
const content = computed({
|
|
21
22
|
get: () => state.content,
|
|
@@ -78,6 +79,9 @@ function useEditor(options) {
|
|
|
78
79
|
function setDarkMode(darkMode) {
|
|
79
80
|
state.darkMode = darkMode;
|
|
80
81
|
}
|
|
82
|
+
function setUiTheme(theme) {
|
|
83
|
+
state.uiTheme = theme;
|
|
84
|
+
}
|
|
81
85
|
function setPreviewMode(previewMode) {
|
|
82
86
|
state.previewMode = previewMode;
|
|
83
87
|
if (previewMode) {
|
|
@@ -164,6 +168,7 @@ function useEditor(options) {
|
|
|
164
168
|
selectBlock,
|
|
165
169
|
setViewport,
|
|
166
170
|
setDarkMode,
|
|
171
|
+
setUiTheme,
|
|
167
172
|
setPreviewMode,
|
|
168
173
|
updateBlock,
|
|
169
174
|
updateSettings,
|
|
@@ -448,7 +453,7 @@ function useDataSourceFetch(options) {
|
|
|
448
453
|
fieldValues: { ...options.block.value.fieldValues },
|
|
449
454
|
blockId: options.block.value.id
|
|
450
455
|
});
|
|
451
|
-
if (result
|
|
456
|
+
if (result == null) {
|
|
452
457
|
return;
|
|
453
458
|
}
|
|
454
459
|
const merged = { ...options.block.value.fieldValues };
|
|
@@ -473,12 +478,42 @@ function useDataSourceFetch(options) {
|
|
|
473
478
|
needsFetch
|
|
474
479
|
};
|
|
475
480
|
}
|
|
481
|
+
|
|
482
|
+
// src/history-interceptor.ts
|
|
483
|
+
function useHistoryInterceptor(editor, history) {
|
|
484
|
+
const originalAddBlock = editor.addBlock;
|
|
485
|
+
const originalRemoveBlock = editor.removeBlock;
|
|
486
|
+
const originalMoveBlock = editor.moveBlock;
|
|
487
|
+
const originalUpdateBlock = editor.updateBlock;
|
|
488
|
+
const originalUpdateSettings = editor.updateSettings;
|
|
489
|
+
editor.addBlock = (block, targetSectionId, columnIndex, index) => {
|
|
490
|
+
history.record();
|
|
491
|
+
originalAddBlock(block, targetSectionId, columnIndex, index);
|
|
492
|
+
};
|
|
493
|
+
editor.removeBlock = (blockId) => {
|
|
494
|
+
history.record();
|
|
495
|
+
originalRemoveBlock(blockId);
|
|
496
|
+
};
|
|
497
|
+
editor.moveBlock = (blockId, newIndex, targetSectionId, columnIndex) => {
|
|
498
|
+
history.record();
|
|
499
|
+
originalMoveBlock(blockId, newIndex, targetSectionId, columnIndex);
|
|
500
|
+
};
|
|
501
|
+
editor.updateBlock = (blockId, updates) => {
|
|
502
|
+
history.recordDebounced(blockId);
|
|
503
|
+
originalUpdateBlock(blockId, updates);
|
|
504
|
+
};
|
|
505
|
+
editor.updateSettings = (updates) => {
|
|
506
|
+
history.record();
|
|
507
|
+
originalUpdateSettings(updates);
|
|
508
|
+
};
|
|
509
|
+
}
|
|
476
510
|
export {
|
|
477
511
|
useAutoSave,
|
|
478
512
|
useBlockActions,
|
|
479
513
|
useConditionPreview,
|
|
480
514
|
useDataSourceFetch,
|
|
481
515
|
useEditor,
|
|
482
|
-
useHistory
|
|
516
|
+
useHistory,
|
|
517
|
+
useHistoryInterceptor
|
|
483
518
|
};
|
|
484
519
|
//# sourceMappingURL=index.js.map
|